| author | |
| committer | |
| log | 6db520a4cd1ce2391c79d0d55b2b2d5297e133a3 |
| tree | 279f46702877d50bdfaa04a23c4923758e264c1c |
| parent | 47c5f556c08c1b15c74dbaca743d17a3297bcdef |
- make ubsan to be linkable by linker
- currently ignore bool vectors tests for `.stage2_wasm`, let defer handling it properly after supporting simd128 in backend (mainly tiny fixes + enabling it for matrix)
- I needed to refactor `wasm/abi.zig`, still bad9 files changed, 202 insertions(+), 64 deletions(-)
src/codegen/llvm/FuncGen.zig+2-2| ... | ... | @@ -7156,7 +7156,7 @@ const ParamTypeIterator = struct { |
| 7156 | 7156 | }, |
| 7157 | 7157 | } |
| 7158 | 7158 | }, |
| 7159 | .wasm_mvp => switch (wasm_c_abi.classifyType(ty, zcu)) { | |
| 7159 | .wasm_mvp => switch (wasm_c_abi.classifyTypeForLlvm(ty, zcu)) { | |
| 7160 | 7160 | .direct => |scalar_ty| { |
| 7161 | 7161 | if (isScalar(zcu, ty)) { |
| 7162 | 7162 | it.zig_index += 1; |
| ... | ... | @@ -7508,7 +7508,7 @@ pub fn fnReturnStrat(o: *Object, cc: std.lang.CallingConvention, ret_ty: Type) A |
| 7508 | 7508 | .simple_aggregate => unreachable, |
| 7509 | 7509 | .pointer => .sret, |
| 7510 | 7510 | }, |
| 7511 | .wasm_mvp => switch (wasm_c_abi.classifyType(ret_ty, zcu)) { | |
| 7511 | .wasm_mvp => switch (wasm_c_abi.classifyTypeForLlvm(ret_ty, zcu)) { | |
| 7512 | 7512 | .direct => |scalar_ty| if (scalar_ty.toIntern() == ret_ty.toIntern()) { |
| 7513 | 7513 | assert(!isByRef(ret_ty, zcu)); |
| 7514 | 7514 | return .by_val; |
src/codegen/wasm/CodeGen.zig+81-32| ... | ... | @@ -927,21 +927,26 @@ fn resolveCallingConventionValues( |
| 927 | 927 | }, |
| 928 | 928 | .wasm_mvp => { |
| 929 | 929 | for (fn_info.param_types.get(ip)) |ty| { |
| 930 | if (!Type.fromInterned(ty).hasRuntimeBits(zcu)) { | |
| 930 | const param_ty: Type = .fromInterned(ty); | |
| 931 | if (!param_ty.hasRuntimeBits(zcu)) { | |
| 931 | 932 | continue; |
| 932 | 933 | } |
| 933 | switch (abi.classifyType(.fromInterned(ty), zcu)) { | |
| 934 | .direct => |scalar_ty| if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) { | |
| 934 | ||
| 935 | switch (abi.classifyType(param_ty, zcu, target)) { | |
| 936 | .direct, .indirect => { | |
| 935 | 937 | try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } }); |
| 936 | 938 | result.local_index += 1; |
| 937 | } else { | |
| 939 | }, | |
| 940 | .double_i64 => { | |
| 938 | 941 | try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } }); |
| 939 | 942 | try args.append(.{ .local = .{ .value = result.local_index + 1, .references = 1 } }); |
| 940 | 943 | result.local_index += 2; |
| 941 | 944 | }, |
| 942 | .indirect => { | |
| 943 | try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } }); | |
| 944 | result.local_index += 1; | |
| 945 | .unrolled => |vector| { | |
| 946 | for (0..vector.len) |_| { | |
| 947 | try args.append(.{ .local = .{ .value = result.local_index, .references = 1 } }); | |
| 948 | result.local_index += 1; | |
| 949 | } | |
| 945 | 950 | }, |
| 946 | 951 | } |
| 947 | 952 | } |
| ... | ... | @@ -968,9 +973,10 @@ pub fn firstParamSRet( |
| 968 | 973 | switch (cc) { |
| 969 | 974 | .@"inline" => unreachable, |
| 970 | 975 | .auto => return isByRef(return_type, zcu, target), |
| 971 | .wasm_mvp => switch (abi.classifyType(return_type, zcu)) { | |
| 972 | .direct => |scalar_ty| return abi.lowerAsDoubleI64(scalar_ty, zcu), | |
| 973 | .indirect => return true, | |
| 976 | .wasm_mvp => switch (abi.classifyType(return_type, zcu, target)) { | |
| 977 | .direct => return false, | |
| 978 | .double_i64, .indirect => return true, | |
| 979 | .unrolled => |vector| return vector.len > 1, | |
| 974 | 980 | }, |
| 975 | 981 | else => return false, |
| 976 | 982 | } |
| ... | ... | @@ -985,18 +991,15 @@ fn lowerArg(cg: *CodeGen, cc: std.lang.CallingConvention, ty: Type, value: WValu |
| 985 | 991 | |
| 986 | 992 | const zcu = cg.pt.zcu; |
| 987 | 993 | |
| 988 | switch (abi.classifyType(ty, zcu)) { | |
| 989 | .direct => |scalar_type| if (!abi.lowerAsDoubleI64(scalar_type, zcu)) { | |
| 994 | switch (abi.classifyType(ty, zcu, cg.target)) { | |
| 995 | .direct => |scalar_ty| { | |
| 990 | 996 | if (!isByRef(ty, zcu, cg.target)) { |
| 991 | 997 | return cg.lowerToStack(value); |
| 992 | 998 | } else { |
| 993 | switch (value) { | |
| 994 | .nav_ref, .stack_offset => _ = try cg.load(value, scalar_type, 0), | |
| 995 | .dead => unreachable, | |
| 996 | else => try cg.emitWValue(value), | |
| 997 | } | |
| 999 | _ = try cg.load(value, scalar_ty, 0); | |
| 998 | 1000 | } |
| 999 | } else { | |
| 1001 | }, | |
| 1002 | .double_i64 => { | |
| 1000 | 1003 | assert(ty.abiSize(zcu) == 16); |
| 1001 | 1004 | // in this case we have an integer or float that must be lowered as 2 i64's. |
| 1002 | 1005 | try cg.emitWValue(value); |
| ... | ... | @@ -1004,7 +1007,17 @@ fn lowerArg(cg: *CodeGen, cc: std.lang.CallingConvention, ty: Type, value: WValu |
| 1004 | 1007 | try cg.emitWValue(value); |
| 1005 | 1008 | try cg.addMemArg(.i64_load, .{ .offset = value.offset() + 8, .alignment = 8 }); |
| 1006 | 1009 | }, |
| 1007 | .indirect => return cg.lowerToStack(value), | |
| 1010 | .indirect => { | |
| 1011 | const stack_copy = try cg.allocStack(ty); | |
| 1012 | try cg.store(stack_copy, value, ty, 0); | |
| 1013 | return cg.lowerToStack(stack_copy); | |
| 1014 | }, | |
| 1015 | .unrolled => |vector| { | |
| 1016 | const elem_size: u32 = @intCast(vector.elem_type.abiSize(zcu)); | |
| 1017 | for (0..vector.len) |index| { | |
| 1018 | _ = try cg.load(value, vector.elem_type, @intCast(index * elem_size)); | |
| 1019 | } | |
| 1020 | }, | |
| 1008 | 1021 | } |
| 1009 | 1022 | } |
| 1010 | 1023 | |
| ... | ... | @@ -1947,16 +1960,19 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 1947 | 1960 | if (cg.return_value != .none) { |
| 1948 | 1961 | try cg.store(cg.return_value, operand, ret_ty, 0); |
| 1949 | 1962 | } else if (fn_info.cc == .wasm_mvp and ret_ty.hasRuntimeBits(zcu)) { |
| 1950 | switch (abi.classifyType(ret_ty, zcu)) { | |
| 1963 | switch (abi.classifyType(ret_ty, zcu, cg.target)) { | |
| 1951 | 1964 | .direct => |scalar_type| { |
| 1952 | assert(!abi.lowerAsDoubleI64(scalar_type, zcu)); | |
| 1953 | 1965 | if (!isByRef(ret_ty, zcu, cg.target)) { |
| 1954 | 1966 | try cg.emitWValue(operand); |
| 1955 | 1967 | } else { |
| 1956 | 1968 | _ = try cg.load(operand, scalar_type, 0); |
| 1957 | 1969 | } |
| 1958 | 1970 | }, |
| 1959 | .indirect => unreachable, | |
| 1971 | .double_i64, .indirect => unreachable, | |
| 1972 | .unrolled => |vector| { | |
| 1973 | assert(vector.len == 1); | |
| 1974 | _ = try cg.load(operand, vector.elem_type, 0); | |
| 1975 | }, | |
| 1960 | 1976 | } |
| 1961 | 1977 | } else { |
| 1962 | 1978 | if (!ret_ty.hasRuntimeBits(zcu) and ret_ty.isError(zcu)) { |
| ... | ... | @@ -2003,8 +2019,18 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2003 | 2019 | try cg.addImm32(0); |
| 2004 | 2020 | } |
| 2005 | 2021 | } else if (!firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), zcu, cg.target)) { |
| 2006 | // leave on the stack | |
| 2007 | _ = try cg.load(operand, ret_ty, 0); | |
| 2022 | if (fn_info.cc == .wasm_mvp) { | |
| 2023 | switch (abi.classifyType(ret_ty, zcu, cg.target)) { | |
| 2024 | .direct => |scalar_type| _ = try cg.load(operand, scalar_type, 0), | |
| 2025 | .double_i64, .indirect => unreachable, | |
| 2026 | .unrolled => |vector| { | |
| 2027 | assert(vector.len == 1); | |
| 2028 | _ = try cg.load(operand, vector.elem_type, 0); | |
| 2029 | }, | |
| 2030 | } | |
| 2031 | } else { | |
| 2032 | _ = try cg.load(operand, ret_ty, 0); | |
| 2033 | } | |
| 2008 | 2034 | } |
| 2009 | 2035 | |
| 2010 | 2036 | try cg.restoreStackPointer(); |
| ... | ... | @@ -2132,22 +2158,30 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.lang.CallModifier) |
| 2132 | 2158 | } else if (first_param_sret) { |
| 2133 | 2159 | break :result_value sret; |
| 2134 | 2160 | } else if (zcu.typeToFunc(fn_ty).?.cc == .wasm_mvp) { |
| 2135 | switch (abi.classifyType(ret_ty, zcu)) { | |
| 2161 | switch (abi.classifyType(ret_ty, zcu, cg.target)) { | |
| 2136 | 2162 | .direct => |scalar_type| { |
| 2137 | assert(!abi.lowerAsDoubleI64(scalar_type, zcu)); | |
| 2138 | 2163 | if (!isByRef(ret_ty, zcu, cg.target)) { |
| 2139 | 2164 | const result_local = try cg.allocLocal(ret_ty); |
| 2140 | 2165 | try cg.addLocal(.local_set, result_local.local.value); |
| 2141 | 2166 | break :result_value result_local; |
| 2142 | 2167 | } else { |
| 2143 | const result_local = try cg.allocLocal(ret_ty); | |
| 2168 | const result_local = try cg.allocLocal(scalar_type); | |
| 2144 | 2169 | try cg.addLocal(.local_set, result_local.local.value); |
| 2145 | 2170 | const result = try cg.allocStack(ret_ty); |
| 2146 | 2171 | try cg.store(result, result_local, scalar_type, 0); |
| 2147 | 2172 | break :result_value result; |
| 2148 | 2173 | } |
| 2149 | 2174 | }, |
| 2150 | .indirect => unreachable, | |
| 2175 | .double_i64, .indirect => unreachable, | |
| 2176 | .unrolled => |vector| { | |
| 2177 | assert(vector.len == 1); | |
| 2178 | const result_local = try cg.allocLocal(vector.elem_type); | |
| 2179 | // save call result from operand stack | |
| 2180 | try cg.addLocal(.local_set, result_local.local.value); | |
| 2181 | const result = try cg.allocStack(ret_ty); | |
| 2182 | try cg.store(result, result_local, vector.elem_type, 0); | |
| 2183 | break :result_value result; | |
| 2184 | }, | |
| 2151 | 2185 | } |
| 2152 | 2186 | } else { |
| 2153 | 2187 | const result_local = try cg.allocLocal(ret_ty); |
| ... | ... | @@ -2450,17 +2484,32 @@ fn airArg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2450 | 2484 | const cc = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?.cc; |
| 2451 | 2485 | const arg_ty = cg.typeOfIndex(inst); |
| 2452 | 2486 | if (cc == .wasm_mvp) { |
| 2453 | switch (abi.classifyType(arg_ty, zcu)) { | |
| 2454 | .direct => |scalar_ty| if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) { | |
| 2487 | switch (abi.classifyType(arg_ty, zcu, cg.target)) { | |
| 2488 | .direct => |scalar_type| { | |
| 2455 | 2489 | cg.arg_index += 1; |
| 2456 | } else { | |
| 2490 | if (isByRef(arg_ty, zcu, cg.target)) { | |
| 2491 | const result = try cg.allocStack(arg_ty); | |
| 2492 | try cg.store(result, arg, scalar_type, 0); | |
| 2493 | return cg.finishAir(inst, result, &.{}); | |
| 2494 | } | |
| 2495 | }, | |
| 2496 | .indirect => cg.arg_index += 1, | |
| 2497 | .double_i64 => { | |
| 2457 | 2498 | cg.arg_index += 2; |
| 2458 | 2499 | const result = try cg.allocStack(arg_ty); |
| 2459 | 2500 | try cg.store(result, arg, Type.u64, 0); |
| 2460 | 2501 | try cg.store(result, cg.args[arg_index + 1], Type.u64, 8); |
| 2461 | 2502 | return cg.finishAir(inst, result, &.{}); |
| 2462 | 2503 | }, |
| 2463 | .indirect => cg.arg_index += 1, | |
| 2504 | .unrolled => |vector| { | |
| 2505 | const result = try cg.allocStack(arg_ty); | |
| 2506 | const elem_size: u32 = @intCast(vector.elem_type.abiSize(zcu)); | |
| 2507 | for (0..vector.len) |index| { | |
| 2508 | try cg.store(result, cg.args[cg.arg_index], vector.elem_type, @intCast(index * elem_size)); | |
| 2509 | cg.arg_index += 1; | |
| 2510 | } | |
| 2511 | return cg.finishAir(inst, result, &.{}); | |
| 2512 | }, | |
| 2464 | 2513 | } |
| 2465 | 2514 | } else { |
| 2466 | 2515 | cg.arg_index += 1; |
src/codegen/wasm/abi.zig+35-11| ... | ... | @@ -11,16 +11,44 @@ const assert = std.debug.assert; |
| 11 | 11 | const Type = @import("../../Type.zig"); |
| 12 | 12 | const Zcu = @import("../../Zcu.zig"); |
| 13 | 13 | |
| 14 | /// Defines how to pass a type as part of a function signature, | |
| 15 | /// both for parameters as well as return values. | |
| 14 | /// Describes how the Wasm backend represents a C ABI value. | |
| 16 | 15 | pub const Class = union(enum) { |
| 17 | 16 | direct: Type, |
| 17 | double_i64, | |
| 18 | 18 | indirect, |
| 19 | unrolled: struct { | |
| 20 | elem_type: Type, | |
| 21 | len: u32, | |
| 22 | }, | |
| 19 | 23 | }; |
| 20 | 24 | |
| 21 | /// Classifies a given Zig type to determine how they must be passed | |
| 22 | /// or returned as value within a wasm function. | |
| 23 | pub fn classifyType(ty: Type, zcu: *const Zcu) Class { | |
| 25 | pub const LlvmClass = union(enum) { | |
| 26 | direct: Type, | |
| 27 | indirect, | |
| 28 | }; | |
| 29 | ||
| 30 | pub fn classifyType(ty: Type, zcu: *const Zcu, target: *const Target) Class { | |
| 31 | if (ty.zigTypeTag(zcu) == .vector) { | |
| 32 | if (!(ty.bitSize(zcu) == 128 and target.cpu.has(.wasm, .simd128))) { | |
| 33 | const elem_type = ty.childType(zcu); | |
| 34 | return .{ .unrolled = .{ | |
| 35 | .elem_type = elem_type, | |
| 36 | .len = ty.vectorLen(zcu), | |
| 37 | } }; | |
| 38 | } | |
| 39 | return .{ .direct = ty }; | |
| 40 | } | |
| 41 | ||
| 42 | return switch (classifyTypeForLlvm(ty, zcu)) { | |
| 43 | .direct => |scalar_ty| if (scalar_ty.bitSize(zcu) > 64) | |
| 44 | .double_i64 | |
| 45 | else | |
| 46 | .{ .direct = scalar_ty }, | |
| 47 | .indirect => .indirect, | |
| 48 | }; | |
| 49 | } | |
| 50 | ||
| 51 | pub fn classifyTypeForLlvm(ty: Type, zcu: *const Zcu) LlvmClass { | |
| 24 | 52 | const ip = &zcu.intern_pool; |
| 25 | 53 | assert(ty.hasRuntimeBits(zcu)); |
| 26 | 54 | switch (ty.zigTypeTag(zcu)) { |
| ... | ... | @@ -56,7 +84,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class { |
| 56 | 84 | if (explicit_align.compareStrict(.gt, field_ty.abiAlignment(zcu))) |
| 57 | 85 | return .indirect; |
| 58 | 86 | } |
| 59 | return classifyType(field_ty, zcu); | |
| 87 | return classifyTypeForLlvm(field_ty, zcu); | |
| 60 | 88 | }, |
| 61 | 89 | .@"union" => { |
| 62 | 90 | const union_obj = zcu.typeToUnion(ty).?; |
| ... | ... | @@ -67,7 +95,7 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class { |
| 67 | 95 | assert(layout.tag_size == 0); |
| 68 | 96 | if (union_obj.field_types.len > 1) return .indirect; |
| 69 | 97 | const first_field_ty = Type.fromInterned(union_obj.field_types.get(ip)[0]); |
| 70 | return classifyType(first_field_ty, zcu); | |
| 98 | return classifyTypeForLlvm(first_field_ty, zcu); | |
| 71 | 99 | }, |
| 72 | 100 | .error_union, |
| 73 | 101 | .frame, |
| ... | ... | @@ -86,7 +114,3 @@ pub fn classifyType(ty: Type, zcu: *const Zcu) Class { |
| 86 | 114 | => unreachable, |
| 87 | 115 | } |
| 88 | 116 | } |
| 89 | ||
| 90 | pub fn lowerAsDoubleI64(scalar_ty: Type, zcu: *const Zcu) bool { | |
| 91 | return scalar_ty.bitSize(zcu) > 64; | |
| 92 | } |
src/link/Wasm.zig+22-13| ... | ... | @@ -4938,12 +4938,15 @@ fn convertZcuFnType( |
| 4938 | 4938 | try params_buffer.append(gpa, .i32); // memory address is always a 32-bit handle |
| 4939 | 4939 | } else if (return_type.hasRuntimeBits(zcu)) { |
| 4940 | 4940 | if (cc == .wasm_mvp) { |
| 4941 | switch (abi.classifyType(return_type, zcu)) { | |
| 4942 | .direct => |scalar_ty| { | |
| 4943 | assert(!abi.lowerAsDoubleI64(scalar_ty, zcu)); | |
| 4944 | try returns_buffer.append(gpa, CodeGen.typeToValtype(scalar_ty, zcu, target)); | |
| 4941 | switch (abi.classifyType(return_type, zcu, target)) { | |
| 4942 | .direct => |scalar_type| { | |
| 4943 | try returns_buffer.append(gpa, CodeGen.typeToValtype(scalar_type, zcu, target)); | |
| 4944 | }, | |
| 4945 | .double_i64, .indirect => unreachable, | |
| 4946 | .unrolled => |vector| { | |
| 4947 | assert(vector.len == 1); | |
| 4948 | try returns_buffer.append(gpa, CodeGen.typeToValtype(vector.elem_type, zcu, target)); | |
| 4945 | 4949 | }, |
| 4946 | .indirect => unreachable, | |
| 4947 | 4950 | } |
| 4948 | 4951 | } else { |
| 4949 | 4952 | try returns_buffer.append(gpa, CodeGen.typeToValtype(return_type, zcu, target)); |
| ... | ... | @@ -4959,16 +4962,22 @@ fn convertZcuFnType( |
| 4959 | 4962 | |
| 4960 | 4963 | switch (cc) { |
| 4961 | 4964 | .wasm_mvp => { |
| 4962 | switch (abi.classifyType(param_type, zcu)) { | |
| 4963 | .direct => |scalar_ty| { | |
| 4964 | if (!abi.lowerAsDoubleI64(scalar_ty, zcu)) { | |
| 4965 | try params_buffer.append(gpa, CodeGen.typeToValtype(scalar_ty, zcu, target)); | |
| 4966 | } else { | |
| 4967 | try params_buffer.append(gpa, .i64); | |
| 4968 | try params_buffer.append(gpa, .i64); | |
| 4965 | switch (abi.classifyType(param_type, zcu, target)) { | |
| 4966 | .direct => |scalar_type| { | |
| 4967 | try params_buffer.append(gpa, CodeGen.typeToValtype(scalar_type, zcu, target)); | |
| 4968 | }, | |
| 4969 | .double_i64 => { | |
| 4970 | try params_buffer.append(gpa, .i64); | |
| 4971 | try params_buffer.append(gpa, .i64); | |
| 4972 | }, | |
| 4973 | .indirect => { | |
| 4974 | try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target)); | |
| 4975 | }, | |
| 4976 | .unrolled => |vector| { | |
| 4977 | for (0..vector.len) |_| { | |
| 4978 | try params_buffer.append(gpa, CodeGen.typeToValtype(vector.elem_type, zcu, target)); | |
| 4969 | 4979 | } |
| 4970 | 4980 | }, |
| 4971 | .indirect => try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target)), | |
| 4972 | 4981 | } |
| 4973 | 4982 | }, |
| 4974 | 4983 | else => try params_buffer.append(gpa, CodeGen.typeToValtype(param_type, zcu, target)), |
src/link/Wasm/Flush.zig+33-4| ... | ... | @@ -248,6 +248,9 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 248 | 248 | |
| 249 | 249 | if (comp.zcu) |zcu| { |
| 250 | 250 | const ip: *const InternPool = &zcu.intern_pool; // No mutations allowed! |
| 251 | const function_imports_start = wasm.function_imports.entries.len; | |
| 252 | const global_imports_start = wasm.global_imports.entries.len; | |
| 253 | const data_imports_start = wasm.data_imports.entries.len; | |
| 251 | 254 | |
| 252 | 255 | log.debug("total MIR instructions: {d}", .{wasm.mir_instructions.len}); |
| 253 | 256 | |
| ... | ... | @@ -464,6 +467,35 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 464 | 467 | else => continue, |
| 465 | 468 | }; |
| 466 | 469 | |
| 470 | // marking above may discover additional imports | |
| 471 | try f.function_imports.ensureUnusedCapacity(gpa, wasm.function_imports.entries.len - function_imports_start); | |
| 472 | for ( | |
| 473 | wasm.function_imports.keys()[function_imports_start..], | |
| 474 | wasm.function_imports.values()[function_imports_start..], | |
| 475 | ) |name, id| { | |
| 476 | if (!f.function_imports.contains(name) and Wasm.FunctionIndex.fromSymbolName(wasm, name) == null) { | |
| 477 | f.function_imports.putAssumeCapacity(name, id); | |
| 478 | } | |
| 479 | } | |
| 480 | ||
| 481 | try f.global_imports.ensureUnusedCapacity(gpa, wasm.global_imports.entries.len - global_imports_start); | |
| 482 | for ( | |
| 483 | wasm.global_imports.keys()[global_imports_start..], | |
| 484 | wasm.global_imports.values()[global_imports_start..], | |
| 485 | ) |name, id| { | |
| 486 | if (!f.global_imports.contains(name)) f.global_imports.putAssumeCapacity(name, id); | |
| 487 | } | |
| 488 | ||
| 489 | try f.data_imports.ensureUnusedCapacity(gpa, wasm.data_imports.entries.len - data_imports_start); | |
| 490 | for ( | |
| 491 | wasm.data_imports.keys()[data_imports_start..], | |
| 492 | wasm.data_imports.values()[data_imports_start..], | |
| 493 | ) |name, id| { | |
| 494 | if (!f.data_imports.contains(name) and !f.data_exports.contains(name)) { | |
| 495 | f.data_imports.putAssumeCapacity(name, id); | |
| 496 | } | |
| 497 | } | |
| 498 | ||
| 467 | 499 | for (f.missing_exports.keys()) |exp_name| { |
| 468 | 500 | diags.addError("manually specified export name '{s}' undefined", .{exp_name.slice(wasm)}); |
| 469 | 501 | } |
| ... | ... | @@ -1075,13 +1107,10 @@ pub fn finish(f: *Flush, wasm: *Wasm) !void { |
| 1075 | 1107 | if (wasm.functions.getIndex(.__wasm_init_memory)) |func_index| { |
| 1076 | 1108 | try emitStartSection(gpa, binary_bytes, .fromFunctionIndex(wasm, @fromBackingInt(@intCast(func_index)))); |
| 1077 | 1109 | section_index += 1; |
| 1078 | } else if (Wasm.OutputFunctionIndex.fromResolution(wasm, wasm.entry_resolution)) |func_index| { | |
| 1079 | try emitStartSection(gpa, binary_bytes, func_index); | |
| 1080 | section_index += 1; | |
| 1081 | 1110 | } |
| 1082 | 1111 | |
| 1083 | 1112 | // element section |
| 1084 | if (f.indirect_function_table.entries.len > 0) { | |
| 1113 | if (!is_obj and f.indirect_function_table.entries.len > 0) { | |
| 1085 | 1114 | const header_offset = try reserveVecSectionHeader(gpa, binary_bytes); |
| 1086 | 1115 | |
| 1087 | 1116 | // indirect function table elements |
src/link/Wasm/Object.zig+1-1| ... | ... | @@ -856,7 +856,7 @@ pub fn parse( |
| 856 | 856 | start_function = @fromBackingInt(@intCast(functions_start + index)); |
| 857 | 857 | }, |
| 858 | 858 | .element => { |
| 859 | log.warn("unimplemented: element section in {f} {?s}", .{ path, archive_member_name }); | |
| 859 | // element section is not needed for linking, validating it serves no purpose | |
| 860 | 860 | pos = section_end; |
| 861 | 861 | }, |
| 862 | 862 | .code => { |
src/target.zig+1-1| ... | ... | @@ -450,7 +450,7 @@ pub fn canBuildLibUbsanRt(target: *const std.Target) enum { no, yes, llvm_only, |
| 450 | 450 | else => {}, |
| 451 | 451 | } |
| 452 | 452 | return switch (zigBackend(target, false)) { |
| 453 | .stage2_wasm => .llvm_lld_only, | |
| 453 | .stage2_wasm => .yes, | |
| 454 | 454 | .stage2_x86_64 => .yes, |
| 455 | 455 | else => .llvm_only, |
| 456 | 456 | }; |
test/c_abi/main.zig+18| ... | ... | @@ -451,6 +451,7 @@ test "long double" { |
| 451 | 451 | |
| 452 | 452 | comptime { |
| 453 | 453 | skip: { |
| 454 | if (builtin.zig_backend == .stage2_wasm) break :skip; | |
| 454 | 455 | if (builtin.cpu.arch == .hexagon) break :skip; |
| 455 | 456 | if (builtin.cpu.arch == .loongarch64) break :skip; |
| 456 | 457 | if (builtin.cpu.arch.isMIPS()) break :skip; |
| ... | ... | @@ -477,6 +478,7 @@ extern fn c_vector_2_bool(@Vector(2, bool)) void; |
| 477 | 478 | extern fn c_test_vector_2_bool() void; |
| 478 | 479 | |
| 479 | 480 | test "@Vector(2, bool)" { |
| 481 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | |
| 480 | 482 | if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; |
| 481 | 483 | if (builtin.cpu.arch.isArm()) return error.SkipZigTest; |
| 482 | 484 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| ... | ... | @@ -497,6 +499,7 @@ test "@Vector(2, bool)" { |
| 497 | 499 | |
| 498 | 500 | comptime { |
| 499 | 501 | skip: { |
| 502 | if (builtin.zig_backend == .stage2_wasm) break :skip; | |
| 500 | 503 | if (builtin.cpu.arch == .hexagon) break :skip; |
| 501 | 504 | if (builtin.cpu.arch == .loongarch64) break :skip; |
| 502 | 505 | if (builtin.cpu.arch.isMIPS()) break :skip; |
| ... | ... | @@ -527,6 +530,7 @@ extern fn c_vector_4_bool(@Vector(4, bool)) void; |
| 527 | 530 | extern fn c_test_vector_4_bool() void; |
| 528 | 531 | |
| 529 | 532 | test "@Vector(4, bool)" { |
| 533 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | |
| 530 | 534 | if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; |
| 531 | 535 | if (builtin.cpu.arch.isArm()) return error.SkipZigTest; |
| 532 | 536 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| ... | ... | @@ -551,6 +555,7 @@ test "@Vector(4, bool)" { |
| 551 | 555 | |
| 552 | 556 | comptime { |
| 553 | 557 | skip: { |
| 558 | if (builtin.zig_backend == .stage2_wasm) break :skip; | |
| 554 | 559 | if (builtin.cpu.arch == .hexagon) break :skip; |
| 555 | 560 | if (builtin.cpu.arch == .loongarch64) break :skip; |
| 556 | 561 | if (builtin.cpu.arch.isMIPS()) break :skip; |
| ... | ... | @@ -589,6 +594,7 @@ extern fn c_vector_8_bool(@Vector(8, bool)) void; |
| 589 | 594 | extern fn c_test_vector_8_bool() void; |
| 590 | 595 | |
| 591 | 596 | test "@Vector(8, bool)" { |
| 597 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | |
| 592 | 598 | if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; |
| 593 | 599 | if (builtin.cpu.arch.isArm()) return error.SkipZigTest; |
| 594 | 600 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| ... | ... | @@ -621,6 +627,7 @@ test "@Vector(8, bool)" { |
| 621 | 627 | |
| 622 | 628 | comptime { |
| 623 | 629 | skip: { |
| 630 | if (builtin.zig_backend == .stage2_wasm) break :skip; | |
| 624 | 631 | if (builtin.cpu.arch == .hexagon) break :skip; |
| 625 | 632 | if (builtin.cpu.arch == .loongarch64) break :skip; |
| 626 | 633 | if (builtin.cpu.arch.isMIPS()) break :skip; |
| ... | ... | @@ -675,6 +682,7 @@ extern fn c_vector_16_bool(@Vector(16, bool)) void; |
| 675 | 682 | extern fn c_test_vector_16_bool() void; |
| 676 | 683 | |
| 677 | 684 | test "@Vector(16, bool)" { |
| 685 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | |
| 678 | 686 | if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; |
| 679 | 687 | if (builtin.cpu.arch.isArm()) return error.SkipZigTest; |
| 680 | 688 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| ... | ... | @@ -723,6 +731,7 @@ test "@Vector(16, bool)" { |
| 723 | 731 | |
| 724 | 732 | comptime { |
| 725 | 733 | skip: { |
| 734 | if (builtin.zig_backend == .stage2_wasm) break :skip; | |
| 726 | 735 | if (builtin.cpu.arch == .hexagon) break :skip; |
| 727 | 736 | if (builtin.cpu.arch == .loongarch64) break :skip; |
| 728 | 737 | if (builtin.cpu.arch.isMIPS()) break :skip; |
| ... | ... | @@ -809,6 +818,7 @@ extern fn c_vector_32_bool(@Vector(32, bool)) void; |
| 809 | 818 | extern fn c_test_vector_32_bool() void; |
| 810 | 819 | |
| 811 | 820 | test "@Vector(32, bool)" { |
| 821 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | |
| 812 | 822 | if (builtin.cpu.arch.isAARCH64()) return error.SkipZigTest; |
| 813 | 823 | if (builtin.cpu.arch.isArm()) return error.SkipZigTest; |
| 814 | 824 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| ... | ... | @@ -889,6 +899,7 @@ test "@Vector(32, bool)" { |
| 889 | 899 | |
| 890 | 900 | comptime { |
| 891 | 901 | skip: { |
| 902 | if (builtin.zig_backend == .stage2_wasm) break :skip; | |
| 892 | 903 | if (builtin.cpu.arch == .hexagon) break :skip; |
| 893 | 904 | if (builtin.cpu.arch == .loongarch64) break :skip; |
| 894 | 905 | if (builtin.cpu.arch.isMIPS()) break :skip; |
| ... | ... | @@ -1039,6 +1050,7 @@ extern fn c_vector_64_bool(@Vector(64, bool)) void; |
| 1039 | 1050 | extern fn c_test_vector_64_bool() void; |
| 1040 | 1051 | |
| 1041 | 1052 | test "@Vector(64, bool)" { |
| 1053 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | |
| 1042 | 1054 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 1043 | 1055 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 1044 | 1056 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| ... | ... | @@ -1181,6 +1193,7 @@ test "@Vector(64, bool)" { |
| 1181 | 1193 | |
| 1182 | 1194 | comptime { |
| 1183 | 1195 | skip: { |
| 1196 | if (builtin.zig_backend == .stage2_wasm) break :skip; | |
| 1184 | 1197 | if (builtin.cpu.arch == .hexagon) break :skip; |
| 1185 | 1198 | if (builtin.cpu.arch == .loongarch64) break :skip; |
| 1186 | 1199 | if (builtin.cpu.arch.isMIPS()) break :skip; |
| ... | ... | @@ -1459,6 +1472,7 @@ extern fn c_vector_128_bool(@Vector(128, bool)) void; |
| 1459 | 1472 | extern fn c_test_vector_128_bool() void; |
| 1460 | 1473 | |
| 1461 | 1474 | test "@Vector(128, bool)" { |
| 1475 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | |
| 1462 | 1476 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 1463 | 1477 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 1464 | 1478 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| ... | ... | @@ -1729,6 +1743,7 @@ test "@Vector(128, bool)" { |
| 1729 | 1743 | |
| 1730 | 1744 | comptime { |
| 1731 | 1745 | skip: { |
| 1746 | if (builtin.zig_backend == .stage2_wasm) break :skip; | |
| 1732 | 1747 | if (builtin.cpu.arch == .hexagon) break :skip; |
| 1733 | 1748 | if (builtin.cpu.arch == .loongarch64) break :skip; |
| 1734 | 1749 | if (builtin.cpu.arch.isMIPS()) break :skip; |
| ... | ... | @@ -2263,6 +2278,7 @@ extern fn c_vector_256_bool(@Vector(256, bool)) void; |
| 2263 | 2278 | extern fn c_test_vector_256_bool() void; |
| 2264 | 2279 | |
| 2265 | 2280 | test "@Vector(256, bool)" { |
| 2281 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | |
| 2266 | 2282 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 2267 | 2283 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 2268 | 2284 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
| ... | ... | @@ -2789,6 +2805,7 @@ test "@Vector(256, bool)" { |
| 2789 | 2805 | |
| 2790 | 2806 | comptime { |
| 2791 | 2807 | skip: { |
| 2808 | if (builtin.zig_backend == .stage2_wasm) break :skip; | |
| 2792 | 2809 | if (builtin.cpu.arch == .hexagon) break :skip; |
| 2793 | 2810 | if (builtin.cpu.arch == .loongarch64) break :skip; |
| 2794 | 2811 | if (builtin.cpu.arch.isMIPS()) break :skip; |
| ... | ... | @@ -3835,6 +3852,7 @@ extern fn c_vector_512_bool(@Vector(512, bool)) void; |
| 3835 | 3852 | extern fn c_test_vector_512_bool() void; |
| 3836 | 3853 | |
| 3837 | 3854 | test "@Vector(512, bool)" { |
| 3855 | if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; | |
| 3838 | 3856 | if (builtin.cpu.arch == .hexagon) return error.SkipZigTest; |
| 3839 | 3857 | if (builtin.cpu.arch == .loongarch64) return error.SkipZigTest; |
| 3840 | 3858 | if (builtin.cpu.arch.isMIPS()) return error.SkipZigTest; |
test/tests.zig+9| ... | ... | @@ -2060,6 +2060,15 @@ const c_abi_targets = blk: { |
| 2060 | 2060 | .abi = .musl, |
| 2061 | 2061 | }, |
| 2062 | 2062 | }, |
| 2063 | .{ | |
| 2064 | .target = .{ | |
| 2065 | .cpu_arch = .wasm32, | |
| 2066 | .os_tag = .wasi, | |
| 2067 | .abi = .musl, | |
| 2068 | }, | |
| 2069 | .use_llvm = false, | |
| 2070 | .use_lld = false, | |
| 2071 | }, | |
| 2063 | 2072 | |
| 2064 | 2073 | // Windows Targets |
| 2065 | 2074 |