| ... | @@ -760,7 +760,7 @@ fn resolveInst(cg: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue { | ... | @@ -760,7 +760,7 @@ fn resolveInst(cg: *CodeGen, ref: Air.Inst.Ref) InnerError!WValue { |
| 760 | // | 760 | // |
| 761 | // In the other cases, we will simply lower the constant to a value that fits | 761 | // In the other cases, we will simply lower the constant to a value that fits |
| 762 | // into a single local (such as a pointer, integer, bool, etc). | 762 | // into a single local (such as a pointer, integer, bool, etc). |
| 763 | const result: WValue = if (isByRef(ty, pt, cg.target)) | 763 | const result: WValue = if (isByRef(ty, zcu, cg.target)) |
| 764 | .{ .uav_ref = .{ .ip_index = val.toIntern() } } | 764 | .{ .uav_ref = .{ .ip_index = val.toIntern() } } |
| 765 | else | 765 | else |
| 766 | try cg.lowerConstant(val, ty); | 766 | try cg.lowerConstant(val, ty); |
| ... | @@ -953,9 +953,8 @@ fn addExtraAssumeCapacity(cg: *CodeGen, extra: anytype) error{OutOfMemory}!u32 { | ... | @@ -953,9 +953,8 @@ fn addExtraAssumeCapacity(cg: *CodeGen, extra: anytype) error{OutOfMemory}!u32 { |
| 953 | return result; | 953 | return result; |
| 954 | } | 954 | } |
| 955 | | 955 | |
| 956 | /// Using a given `Type`, returns the corresponding valtype for .auto callconv | 956 | /// For `std.builtin.CallingConvention.auto`. |
| 957 | fn typeToValtype(ty: Type, pt: Zcu.PerThread, target: *const std.Target) std.wasm.Valtype { | 957 | pub fn typeToValtype(ty: Type, zcu: *const Zcu, target: *const std.Target) std.wasm.Valtype { |
| 958 | const zcu = pt.zcu; | | |
| 959 | const ip = &zcu.intern_pool; | 958 | const ip = &zcu.intern_pool; |
| 960 | return switch (ty.zigTypeTag(zcu)) { | 959 | return switch (ty.zigTypeTag(zcu)) { |
| 961 | .float => switch (ty.floatBits(target.*)) { | 960 | .float => switch (ty.floatBits(target.*)) { |
| ... | @@ -973,19 +972,20 @@ fn typeToValtype(ty: Type, pt: Zcu.PerThread, target: *const std.Target) std.was | ... | @@ -973,19 +972,20 @@ fn typeToValtype(ty: Type, pt: Zcu.PerThread, target: *const std.Target) std.was |
| 973 | .@"struct" => blk: { | 972 | .@"struct" => blk: { |
| 974 | if (zcu.typeToPackedStruct(ty)) |packed_struct| { | 973 | if (zcu.typeToPackedStruct(ty)) |packed_struct| { |
| 975 | const backing_int_ty = Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)); | 974 | const backing_int_ty = Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)); |
| 976 | break :blk typeToValtype(backing_int_ty, pt, target); | 975 | break :blk typeToValtype(backing_int_ty, zcu, target); |
| 977 | } else { | 976 | } else { |
| 978 | break :blk .i32; | 977 | break :blk .i32; |
| 979 | } | 978 | } |
| 980 | }, | 979 | }, |
| 981 | .vector => switch (determineSimdStoreStrategy(ty, zcu, target)) { | 980 | .vector => switch (CodeGen.determineSimdStoreStrategy(ty, zcu, target)) { |
| 982 | .direct => .v128, | 981 | .direct => .v128, |
| 983 | .unrolled => .i32, | 982 | .unrolled => .i32, |
| 984 | }, | 983 | }, |
| 985 | .@"union" => switch (ty.containerLayout(zcu)) { | 984 | .@"union" => switch (ty.containerLayout(zcu)) { |
| 986 | .@"packed" => blk: { | 985 | .@"packed" => switch (ty.bitSize(zcu)) { |
| 987 | const int_ty = pt.intType(.unsigned, @as(u16, @intCast(ty.bitSize(zcu)))) catch @panic("out of memory"); | 986 | 0...32 => .i32, |
| 988 | break :blk typeToValtype(int_ty, pt, target); | 987 | 33...64 => .i64, |
| | 988 | else => .i32, |
| 989 | }, | 989 | }, |
| 990 | else => .i32, | 990 | else => .i32, |
| 991 | }, | 991 | }, |
| ... | @@ -994,17 +994,17 @@ fn typeToValtype(ty: Type, pt: Zcu.PerThread, target: *const std.Target) std.was | ... | @@ -994,17 +994,17 @@ fn typeToValtype(ty: Type, pt: Zcu.PerThread, target: *const std.Target) std.was |
| 994 | } | 994 | } |
| 995 | | 995 | |
| 996 | /// Using a given `Type`, returns the byte representation of its wasm value type | 996 | /// Using a given `Type`, returns the byte representation of its wasm value type |
| 997 | fn genValtype(ty: Type, pt: Zcu.PerThread, target: *const std.Target) u8 { | 997 | fn genValtype(ty: Type, zcu: *const Zcu, target: *const std.Target) u8 { |
| 998 | return @intFromEnum(typeToValtype(ty, pt, target)); | 998 | return @intFromEnum(typeToValtype(ty, zcu, target)); |
| 999 | } | 999 | } |
| 1000 | | 1000 | |
| 1001 | /// Using a given `Type`, returns the corresponding wasm value type | 1001 | /// Using a given `Type`, returns the corresponding wasm value type |
| 1002 | /// Differently from `genValtype` this also allows `void` to create a block | 1002 | /// Differently from `genValtype` this also allows `void` to create a block |
| 1003 | /// with no return type | 1003 | /// with no return type |
| 1004 | fn genBlockType(ty: Type, pt: Zcu.PerThread, target: *const std.Target) u8 { | 1004 | fn genBlockType(ty: Type, zcu: *const Zcu, target: *const std.Target) u8 { |
| 1005 | return switch (ty.ip_index) { | 1005 | return switch (ty.ip_index) { |
| 1006 | .void_type, .noreturn_type => std.wasm.block_empty, | 1006 | .void_type, .noreturn_type => std.wasm.block_empty, |
| 1007 | else => genValtype(ty, pt, target), | 1007 | else => genValtype(ty, zcu, target), |
| 1008 | }; | 1008 | }; |
| 1009 | } | 1009 | } |
| 1010 | | 1010 | |
| ... | @@ -1086,8 +1086,8 @@ fn getResolvedInst(cg: *CodeGen, ref: Air.Inst.Ref) *WValue { | ... | @@ -1086,8 +1086,8 @@ fn getResolvedInst(cg: *CodeGen, ref: Air.Inst.Ref) *WValue { |
| 1086 | /// Creates one locals for a given `Type`. | 1086 | /// Creates one locals for a given `Type`. |
| 1087 | /// Returns a corresponding `Wvalue` with `local` as active tag | 1087 | /// Returns a corresponding `Wvalue` with `local` as active tag |
| 1088 | fn allocLocal(cg: *CodeGen, ty: Type) InnerError!WValue { | 1088 | fn allocLocal(cg: *CodeGen, ty: Type) InnerError!WValue { |
| 1089 | const pt = cg.pt; | 1089 | const zcu = cg.pt.zcu; |
| 1090 | const valtype = typeToValtype(ty, pt, cg.target); | 1090 | const valtype = typeToValtype(ty, zcu, cg.target); |
| 1091 | const index_or_null = switch (valtype) { | 1091 | const index_or_null = switch (valtype) { |
| 1092 | .i32 => cg.free_locals_i32.popOrNull(), | 1092 | .i32 => cg.free_locals_i32.popOrNull(), |
| 1093 | .i64 => cg.free_locals_i64.popOrNull(), | 1093 | .i64 => cg.free_locals_i64.popOrNull(), |
| ... | @@ -1106,74 +1106,13 @@ fn allocLocal(cg: *CodeGen, ty: Type) InnerError!WValue { | ... | @@ -1106,74 +1106,13 @@ fn allocLocal(cg: *CodeGen, ty: Type) InnerError!WValue { |
| 1106 | /// Ensures a new local will be created. This is useful when it's useful | 1106 | /// Ensures a new local will be created. This is useful when it's useful |
| 1107 | /// to use a zero-initialized local. | 1107 | /// to use a zero-initialized local. |
| 1108 | fn ensureAllocLocal(cg: *CodeGen, ty: Type) InnerError!WValue { | 1108 | fn ensureAllocLocal(cg: *CodeGen, ty: Type) InnerError!WValue { |
| 1109 | const pt = cg.pt; | 1109 | const zcu = cg.pt.zcu; |
| 1110 | try cg.locals.append(cg.gpa, genValtype(ty, pt, cg.target)); | 1110 | try cg.locals.append(cg.gpa, genValtype(ty, zcu, cg.target)); |
| 1111 | const initial_index = cg.local_index; | 1111 | const initial_index = cg.local_index; |
| 1112 | cg.local_index += 1; | 1112 | cg.local_index += 1; |
| 1113 | return .{ .local = .{ .value = initial_index, .references = 1 } }; | 1113 | return .{ .local = .{ .value = initial_index, .references = 1 } }; |
| 1114 | } | 1114 | } |
| 1115 | | 1115 | |
| 1116 | fn genFunctype( | | |
| 1117 | wasm: *link.File.Wasm, | | |
| 1118 | cc: std.builtin.CallingConvention, | | |
| 1119 | params: []const InternPool.Index, | | |
| 1120 | return_type: Type, | | |
| 1121 | pt: Zcu.PerThread, | | |
| 1122 | target: *const std.Target, | | |
| 1123 | ) !link.File.Wasm.FunctionType.Index { | | |
| 1124 | const zcu = pt.zcu; | | |
| 1125 | const gpa = zcu.gpa; | | |
| 1126 | var temp_params: std.ArrayListUnmanaged(std.wasm.Valtype) = .empty; | | |
| 1127 | defer temp_params.deinit(gpa); | | |
| 1128 | var returns: std.ArrayListUnmanaged(std.wasm.Valtype) = .empty; | | |
| 1129 | defer returns.deinit(gpa); | | |
| 1130 | | | |
| 1131 | if (firstParamSRet(cc, return_type, pt, target)) { | | |
| 1132 | try temp_params.append(gpa, .i32); // memory address is always a 32-bit handle | | |
| 1133 | } else if (return_type.hasRuntimeBitsIgnoreComptime(zcu)) { | | |
| 1134 | if (cc == .wasm_watc) { | | |
| 1135 | const res_classes = abi.classifyType(return_type, zcu); | | |
| 1136 | assert(res_classes[0] == .direct and res_classes[1] == .none); | | |
| 1137 | const scalar_type = abi.scalarType(return_type, zcu); | | |
| 1138 | try returns.append(gpa, typeToValtype(scalar_type, pt, target)); | | |
| 1139 | } else { | | |
| 1140 | try returns.append(gpa, typeToValtype(return_type, pt, target)); | | |
| 1141 | } | | |
| 1142 | } else if (return_type.isError(zcu)) { | | |
| 1143 | try returns.append(gpa, .i32); | | |
| 1144 | } | | |
| 1145 | | | |
| 1146 | // param types | | |
| 1147 | for (params) |param_type_ip| { | | |
| 1148 | const param_type = Type.fromInterned(param_type_ip); | | |
| 1149 | if (!param_type.hasRuntimeBitsIgnoreComptime(zcu)) continue; | | |
| 1150 | | | |
| 1151 | switch (cc) { | | |
| 1152 | .wasm_watc => { | | |
| 1153 | const param_classes = abi.classifyType(param_type, zcu); | | |
| 1154 | if (param_classes[1] == .none) { | | |
| 1155 | if (param_classes[0] == .direct) { | | |
| 1156 | const scalar_type = abi.scalarType(param_type, zcu); | | |
| 1157 | try temp_params.append(gpa, typeToValtype(scalar_type, pt, target)); | | |
| 1158 | } else { | | |
| 1159 | try temp_params.append(gpa, typeToValtype(param_type, pt, target)); | | |
| 1160 | } | | |
| 1161 | } else { | | |
| 1162 | // i128/f128 | | |
| 1163 | try temp_params.append(gpa, .i64); | | |
| 1164 | try temp_params.append(gpa, .i64); | | |
| 1165 | } | | |
| 1166 | }, | | |
| 1167 | else => try temp_params.append(gpa, typeToValtype(param_type, pt, target)), | | |
| 1168 | } | | |
| 1169 | } | | |
| 1170 | | | |
| 1171 | return wasm.addFuncType(.{ | | |
| 1172 | .params = try wasm.internValtypeList(temp_params.items), | | |
| 1173 | .returns = try wasm.internValtypeList(returns.items), | | |
| 1174 | }); | | |
| 1175 | } | | |
| 1176 | | | |
| 1177 | pub const Function = extern struct { | 1116 | pub const Function = extern struct { |
| 1178 | /// Index into `Wasm.mir_instructions`. | 1117 | /// Index into `Wasm.mir_instructions`. |
| 1179 | mir_off: u32, | 1118 | mir_off: u32, |
| ... | @@ -1291,7 +1230,7 @@ pub fn function( | ... | @@ -1291,7 +1230,7 @@ pub fn function( |
| 1291 | const fn_ty = zcu.navValue(cg.owner_nav).typeOf(zcu); | 1230 | const fn_ty = zcu.navValue(cg.owner_nav).typeOf(zcu); |
| 1292 | const fn_info = zcu.typeToFunc(fn_ty).?; | 1231 | const fn_info = zcu.typeToFunc(fn_ty).?; |
| 1293 | const ip = &zcu.intern_pool; | 1232 | const ip = &zcu.intern_pool; |
| 1294 | const fn_ty_index = try genFunctype(wasm, fn_info.cc, fn_info.param_types.get(ip), Type.fromInterned(fn_info.return_type), pt, target); | 1233 | const fn_ty_index = try wasm.internFunctionType(fn_info.cc, fn_info.param_types.get(ip), .fromInterned(fn_info.return_type), target); |
| 1295 | const returns = fn_ty_index.ptr(wasm).returns.slice(wasm); | 1234 | const returns = fn_ty_index.ptr(wasm).returns.slice(wasm); |
| 1296 | const any_returns = returns.len != 0; | 1235 | const any_returns = returns.len != 0; |
| 1297 | | 1236 | |
| ... | @@ -1409,7 +1348,7 @@ fn resolveCallingConventionValues( | ... | @@ -1409,7 +1348,7 @@ fn resolveCallingConventionValues( |
| 1409 | | 1348 | |
| 1410 | // Check if we store the result as a pointer to the stack rather than | 1349 | // Check if we store the result as a pointer to the stack rather than |
| 1411 | // by value | 1350 | // by value |
| 1412 | if (firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), pt, target)) { | 1351 | if (firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), zcu, target)) { |
| 1413 | // the sret arg will be passed as first argument, therefore we | 1352 | // the sret arg will be passed as first argument, therefore we |
| 1414 | // set the `return_value` before allocating locals for regular args. | 1353 | // set the `return_value` before allocating locals for regular args. |
| 1415 | result.return_value = .{ .local = .{ .value = result.local_index, .references = 1 } }; | 1354 | result.return_value = .{ .local = .{ .value = result.local_index, .references = 1 } }; |
| ... | @@ -1443,17 +1382,17 @@ fn resolveCallingConventionValues( | ... | @@ -1443,17 +1382,17 @@ fn resolveCallingConventionValues( |
| 1443 | return result; | 1382 | return result; |
| 1444 | } | 1383 | } |
| 1445 | | 1384 | |
| 1446 | fn firstParamSRet( | 1385 | pub fn firstParamSRet( |
| 1447 | cc: std.builtin.CallingConvention, | 1386 | cc: std.builtin.CallingConvention, |
| 1448 | return_type: Type, | 1387 | return_type: Type, |
| 1449 | pt: Zcu.PerThread, | 1388 | zcu: *const Zcu, |
| 1450 | target: *const std.Target, | 1389 | target: *const std.Target, |
| 1451 | ) bool { | 1390 | ) bool { |
| 1452 | switch (cc) { | 1391 | switch (cc) { |
| 1453 | .@"inline" => unreachable, | 1392 | .@"inline" => unreachable, |
| 1454 | .auto => return isByRef(return_type, pt, target), | 1393 | .auto => return isByRef(return_type, zcu, target), |
| 1455 | .wasm_watc => { | 1394 | .wasm_watc => { |
| 1456 | const ty_classes = abi.classifyType(return_type, pt.zcu); | 1395 | const ty_classes = abi.classifyType(return_type, zcu); |
| 1457 | if (ty_classes[0] == .indirect) return true; | 1396 | if (ty_classes[0] == .indirect) return true; |
| 1458 | if (ty_classes[0] == .direct and ty_classes[1] == .direct) return true; | 1397 | if (ty_classes[0] == .direct and ty_classes[1] == .direct) return true; |
| 1459 | return false; | 1398 | return false; |
| ... | @@ -1744,8 +1683,7 @@ fn ptrSize(cg: *const CodeGen) u16 { | ... | @@ -1744,8 +1683,7 @@ fn ptrSize(cg: *const CodeGen) u16 { |
| 1744 | | 1683 | |
| 1745 | /// For a given `Type`, will return true when the type will be passed | 1684 | /// For a given `Type`, will return true when the type will be passed |
| 1746 | /// by reference, rather than by value | 1685 | /// by reference, rather than by value |
| 1747 | fn isByRef(ty: Type, pt: Zcu.PerThread, target: *const std.Target) bool { | 1686 | fn isByRef(ty: Type, zcu: *const Zcu, target: *const std.Target) bool { |
| 1748 | const zcu = pt.zcu; | | |
| 1749 | const ip = &zcu.intern_pool; | 1687 | const ip = &zcu.intern_pool; |
| 1750 | switch (ty.zigTypeTag(zcu)) { | 1688 | switch (ty.zigTypeTag(zcu)) { |
| 1751 | .type, | 1689 | .type, |
| ... | @@ -1778,7 +1716,7 @@ fn isByRef(ty: Type, pt: Zcu.PerThread, target: *const std.Target) bool { | ... | @@ -1778,7 +1716,7 @@ fn isByRef(ty: Type, pt: Zcu.PerThread, target: *const std.Target) bool { |
| 1778 | }, | 1716 | }, |
| 1779 | .@"struct" => { | 1717 | .@"struct" => { |
| 1780 | if (zcu.typeToPackedStruct(ty)) |packed_struct| { | 1718 | if (zcu.typeToPackedStruct(ty)) |packed_struct| { |
| 1781 | return isByRef(Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)), pt, target); | 1719 | return isByRef(Type.fromInterned(packed_struct.backingIntTypeUnordered(ip)), zcu, target); |
| 1782 | } | 1720 | } |
| 1783 | return ty.hasRuntimeBitsIgnoreComptime(zcu); | 1721 | return ty.hasRuntimeBitsIgnoreComptime(zcu); |
| 1784 | }, | 1722 | }, |
| ... | @@ -1816,7 +1754,7 @@ const SimdStoreStrategy = enum { | ... | @@ -1816,7 +1754,7 @@ const SimdStoreStrategy = enum { |
| 1816 | /// This means when a given type is 128 bits and either the simd128 or relaxed-simd | 1754 | /// This means when a given type is 128 bits and either the simd128 or relaxed-simd |
| 1817 | /// features are enabled, the function will return `.direct`. This would allow to store | 1755 | /// features are enabled, the function will return `.direct`. This would allow to store |
| 1818 | /// it using a instruction, rather than an unrolled version. | 1756 | /// it using a instruction, rather than an unrolled version. |
| 1819 | fn determineSimdStoreStrategy(ty: Type, zcu: *Zcu, target: *const std.Target) SimdStoreStrategy { | 1757 | pub fn determineSimdStoreStrategy(ty: Type, zcu: *const Zcu, target: *const std.Target) SimdStoreStrategy { |
| 1820 | assert(ty.zigTypeTag(zcu) == .vector); | 1758 | assert(ty.zigTypeTag(zcu) == .vector); |
| 1821 | if (ty.bitSize(zcu) != 128) return .unrolled; | 1759 | if (ty.bitSize(zcu) != 128) return .unrolled; |
| 1822 | const hasFeature = std.Target.wasm.featureSetHas; | 1760 | const hasFeature = std.Target.wasm.featureSetHas; |
| ... | @@ -2144,7 +2082,7 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2144,7 +2082,7 @@ fn airRet(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2144 | .op = .load, | 2082 | .op = .load, |
| 2145 | .width = @as(u8, @intCast(scalar_type.abiSize(zcu) * 8)), | 2083 | .width = @as(u8, @intCast(scalar_type.abiSize(zcu) * 8)), |
| 2146 | .signedness = if (scalar_type.isSignedInt(zcu)) .signed else .unsigned, | 2084 | .signedness = if (scalar_type.isSignedInt(zcu)) .signed else .unsigned, |
| 2147 | .valtype1 = typeToValtype(scalar_type, pt, cg.target), | 2085 | .valtype1 = typeToValtype(scalar_type, zcu, cg.target), |
| 2148 | }); | 2086 | }); |
| 2149 | try cg.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{ | 2087 | try cg.addMemArg(Mir.Inst.Tag.fromOpcode(opcode), .{ |
| 2150 | .offset = operand.offset(), | 2088 | .offset = operand.offset(), |
| ... | @@ -2177,7 +2115,7 @@ fn airRetPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2177,7 +2115,7 @@ fn airRetPtr(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2177 | } | 2115 | } |
| 2178 | | 2116 | |
| 2179 | const fn_info = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?; | 2117 | const fn_info = zcu.typeToFunc(zcu.navValue(cg.owner_nav).typeOf(zcu)).?; |
| 2180 | if (firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), pt, cg.target)) { | 2118 | if (firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), zcu, cg.target)) { |
| 2181 | break :result cg.return_value; | 2119 | break :result cg.return_value; |
| 2182 | } | 2120 | } |
| 2183 | | 2121 | |
| ... | @@ -2199,7 +2137,7 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2199,7 +2137,7 @@ fn airRetLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2199 | if (ret_ty.isError(zcu)) { | 2137 | if (ret_ty.isError(zcu)) { |
| 2200 | try cg.addImm32(0); | 2138 | try cg.addImm32(0); |
| 2201 | } | 2139 | } |
| 2202 | } else if (!firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), pt, cg.target)) { | 2140 | } else if (!firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), zcu, cg.target)) { |
| 2203 | // leave on the stack | 2141 | // leave on the stack |
| 2204 | _ = try cg.load(operand, ret_ty, 0); | 2142 | _ = try cg.load(operand, ret_ty, 0); |
| 2205 | } | 2143 | } |
| ... | @@ -2227,7 +2165,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie | ... | @@ -2227,7 +2165,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie |
| 2227 | }; | 2165 | }; |
| 2228 | const ret_ty = fn_ty.fnReturnType(zcu); | 2166 | const ret_ty = fn_ty.fnReturnType(zcu); |
| 2229 | const fn_info = zcu.typeToFunc(fn_ty).?; | 2167 | const fn_info = zcu.typeToFunc(fn_ty).?; |
| 2230 | const first_param_sret = firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), pt, cg.target); | 2168 | const first_param_sret = firstParamSRet(fn_info.cc, Type.fromInterned(fn_info.return_type), zcu, cg.target); |
| 2231 | | 2169 | |
| 2232 | const callee: ?InternPool.Nav.Index = blk: { | 2170 | const callee: ?InternPool.Nav.Index = blk: { |
| 2233 | const func_val = (try cg.air.value(pl_op.operand, pt)) orelse break :blk null; | 2171 | const func_val = (try cg.air.value(pl_op.operand, pt)) orelse break :blk null; |
| ... | @@ -2267,7 +2205,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie | ... | @@ -2267,7 +2205,7 @@ fn airCall(cg: *CodeGen, inst: Air.Inst.Index, modifier: std.builtin.CallModifie |
| 2267 | const operand = try cg.resolveInst(pl_op.operand); | 2205 | const operand = try cg.resolveInst(pl_op.operand); |
| 2268 | try cg.emitWValue(operand); | 2206 | try cg.emitWValue(operand); |
| 2269 | | 2207 | |
| 2270 | const fn_type_index = try genFunctype(wasm, fn_info.cc, fn_info.param_types.get(ip), Type.fromInterned(fn_info.return_type), pt, cg.target); | 2208 | const fn_type_index = try wasm.internFunctionType(fn_info.cc, fn_info.param_types.get(ip), .fromInterned(fn_info.return_type), cg.target); |
| 2271 | try cg.addLabel(.call_indirect, @intFromEnum(fn_type_index)); | 2209 | try cg.addLabel(.call_indirect, @intFromEnum(fn_type_index)); |
| 2272 | } | 2210 | } |
| 2273 | | 2211 | |
| ... | @@ -2328,7 +2266,7 @@ fn airStore(cg: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void { | ... | @@ -2328,7 +2266,7 @@ fn airStore(cg: *CodeGen, inst: Air.Inst.Index, safety: bool) InnerError!void { |
| 2328 | // load the value, and then shift+or the rhs into the result location. | 2266 | // load the value, and then shift+or the rhs into the result location. |
| 2329 | const int_elem_ty = try pt.intType(.unsigned, ptr_info.packed_offset.host_size * 8); | 2267 | const int_elem_ty = try pt.intType(.unsigned, ptr_info.packed_offset.host_size * 8); |
| 2330 | | 2268 | |
| 2331 | if (isByRef(int_elem_ty, pt, cg.target)) { | 2269 | if (isByRef(int_elem_ty, zcu, cg.target)) { |
| 2332 | return cg.fail("TODO: airStore for pointers to bitfields with backing type larger than 64bits", .{}); | 2270 | return cg.fail("TODO: airStore for pointers to bitfields with backing type larger than 64bits", .{}); |
| 2333 | } | 2271 | } |
| 2334 | | 2272 | |
| ... | @@ -2394,7 +2332,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr | ... | @@ -2394,7 +2332,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr |
| 2394 | const len = @as(u32, @intCast(abi_size)); | 2332 | const len = @as(u32, @intCast(abi_size)); |
| 2395 | return cg.memcpy(lhs, rhs, .{ .imm32 = len }); | 2333 | return cg.memcpy(lhs, rhs, .{ .imm32 = len }); |
| 2396 | }, | 2334 | }, |
| 2397 | .@"struct", .array, .@"union" => if (isByRef(ty, pt, cg.target)) { | 2335 | .@"struct", .array, .@"union" => if (isByRef(ty, zcu, cg.target)) { |
| 2398 | const len = @as(u32, @intCast(abi_size)); | 2336 | const len = @as(u32, @intCast(abi_size)); |
| 2399 | return cg.memcpy(lhs, rhs, .{ .imm32 = len }); | 2337 | return cg.memcpy(lhs, rhs, .{ .imm32 = len }); |
| 2400 | }, | 2338 | }, |
| ... | @@ -2456,7 +2394,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr | ... | @@ -2456,7 +2394,7 @@ fn store(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErr |
| 2456 | // into lhs, so we calculate that and emit that instead | 2394 | // into lhs, so we calculate that and emit that instead |
| 2457 | try cg.lowerToStack(rhs); | 2395 | try cg.lowerToStack(rhs); |
| 2458 | | 2396 | |
| 2459 | const valtype = typeToValtype(ty, pt, cg.target); | 2397 | const valtype = typeToValtype(ty, zcu, cg.target); |
| 2460 | const opcode = buildOpcode(.{ | 2398 | const opcode = buildOpcode(.{ |
| 2461 | .valtype1 = valtype, | 2399 | .valtype1 = valtype, |
| 2462 | .width = @as(u8, @intCast(abi_size * 8)), | 2400 | .width = @as(u8, @intCast(abi_size * 8)), |
| ... | @@ -2485,7 +2423,7 @@ fn airLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -2485,7 +2423,7 @@ fn airLoad(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 2485 | if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) return cg.finishAir(inst, .none, &.{ty_op.operand}); | 2423 | if (!ty.hasRuntimeBitsIgnoreComptime(zcu)) return cg.finishAir(inst, .none, &.{ty_op.operand}); |
| 2486 | | 2424 | |
| 2487 | const result = result: { | 2425 | const result = result: { |
| 2488 | if (isByRef(ty, pt, cg.target)) { | 2426 | if (isByRef(ty, zcu, cg.target)) { |
| 2489 | const new_local = try cg.allocStack(ty); | 2427 | const new_local = try cg.allocStack(ty); |
| 2490 | try cg.store(new_local, operand, ty, 0); | 2428 | try cg.store(new_local, operand, ty, 0); |
| 2491 | break :result new_local; | 2429 | break :result new_local; |
| ... | @@ -2535,7 +2473,7 @@ fn load(cg: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValue | ... | @@ -2535,7 +2473,7 @@ fn load(cg: *CodeGen, operand: WValue, ty: Type, offset: u32) InnerError!WValue |
| 2535 | | 2473 | |
| 2536 | const abi_size: u8 = @intCast(ty.abiSize(zcu)); | 2474 | const abi_size: u8 = @intCast(ty.abiSize(zcu)); |
| 2537 | const opcode = buildOpcode(.{ | 2475 | const opcode = buildOpcode(.{ |
| 2538 | .valtype1 = typeToValtype(ty, pt, cg.target), | 2476 | .valtype1 = typeToValtype(ty, zcu, cg.target), |
| 2539 | .width = abi_size * 8, | 2477 | .width = abi_size * 8, |
| 2540 | .op = .load, | 2478 | .op = .load, |
| 2541 | .signedness = if (ty.isSignedInt(zcu)) .signed else .unsigned, | 2479 | .signedness = if (ty.isSignedInt(zcu)) .signed else .unsigned, |
| ... | @@ -2632,7 +2570,7 @@ fn binOp(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WV | ... | @@ -2632,7 +2570,7 @@ fn binOp(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WV |
| 2632 | return cg.floatOp(float_op, ty, &.{ lhs, rhs }); | 2570 | return cg.floatOp(float_op, ty, &.{ lhs, rhs }); |
| 2633 | } | 2571 | } |
| 2634 | | 2572 | |
| 2635 | if (isByRef(ty, pt, cg.target)) { | 2573 | if (isByRef(ty, zcu, cg.target)) { |
| 2636 | if (ty.zigTypeTag(zcu) == .int) { | 2574 | if (ty.zigTypeTag(zcu) == .int) { |
| 2637 | return cg.binOpBigInt(lhs, rhs, ty, op); | 2575 | return cg.binOpBigInt(lhs, rhs, ty, op); |
| 2638 | } else { | 2576 | } else { |
| ... | @@ -2645,7 +2583,7 @@ fn binOp(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WV | ... | @@ -2645,7 +2583,7 @@ fn binOp(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: Op) InnerError!WV |
| 2645 | | 2583 | |
| 2646 | const opcode: std.wasm.Opcode = buildOpcode(.{ | 2584 | const opcode: std.wasm.Opcode = buildOpcode(.{ |
| 2647 | .op = op, | 2585 | .op = op, |
| 2648 | .valtype1 = typeToValtype(ty, pt, cg.target), | 2586 | .valtype1 = typeToValtype(ty, zcu, cg.target), |
| 2649 | .signedness = if (ty.isSignedInt(zcu)) .signed else .unsigned, | 2587 | .signedness = if (ty.isSignedInt(zcu)) .signed else .unsigned, |
| 2650 | }); | 2588 | }); |
| 2651 | try cg.emitWValue(lhs); | 2589 | try cg.emitWValue(lhs); |
| ... | @@ -2949,7 +2887,7 @@ fn floatOp(cg: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) Inne | ... | @@ -2949,7 +2887,7 @@ fn floatOp(cg: *CodeGen, float_op: FloatOp, ty: Type, args: []const WValue) Inne |
| 2949 | for (args) |operand| { | 2887 | for (args) |operand| { |
| 2950 | try cg.emitWValue(operand); | 2888 | try cg.emitWValue(operand); |
| 2951 | } | 2889 | } |
| 2952 | const opcode = buildOpcode(.{ .op = op, .valtype1 = typeToValtype(ty, pt, cg.target) }); | 2890 | const opcode = buildOpcode(.{ .op = op, .valtype1 = typeToValtype(ty, zcu, cg.target) }); |
| 2953 | try cg.addTag(Mir.Inst.Tag.fromOpcode(opcode)); | 2891 | try cg.addTag(Mir.Inst.Tag.fromOpcode(opcode)); |
| 2954 | return .stack; | 2892 | return .stack; |
| 2955 | } | 2893 | } |
| ... | @@ -3174,7 +3112,7 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro | ... | @@ -3174,7 +3112,7 @@ fn lowerPtr(cg: *CodeGen, ptr_val: InternPool.Index, prev_offset: u64) InnerErro |
| 3174 | fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { | 3112 | fn lowerConstant(cg: *CodeGen, val: Value, ty: Type) InnerError!WValue { |
| 3175 | const pt = cg.pt; | 3113 | const pt = cg.pt; |
| 3176 | const zcu = pt.zcu; | 3114 | const zcu = pt.zcu; |
| 3177 | assert(!isByRef(ty, pt, cg.target)); | 3115 | assert(!isByRef(ty, zcu, cg.target)); |
| 3178 | const ip = &zcu.intern_pool; | 3116 | const ip = &zcu.intern_pool; |
| 3179 | if (val.isUndefDeep(zcu)) return cg.emitUndefined(ty); | 3117 | if (val.isUndefDeep(zcu)) return cg.emitUndefined(ty); |
| 3180 | | 3118 | |
| ... | @@ -3415,11 +3353,12 @@ fn airBlock(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3415,11 +3353,12 @@ fn airBlock(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3415 | | 3353 | |
| 3416 | fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, block_ty: Type, body: []const Air.Inst.Index) InnerError!void { | 3354 | fn lowerBlock(cg: *CodeGen, inst: Air.Inst.Index, block_ty: Type, body: []const Air.Inst.Index) InnerError!void { |
| 3417 | const pt = cg.pt; | 3355 | const pt = cg.pt; |
| 3418 | const wasm_block_ty = genBlockType(block_ty, pt, cg.target); | 3356 | const zcu = pt.zcu; |
| | 3357 | const wasm_block_ty = genBlockType(block_ty, zcu, cg.target); |
| 3419 | | 3358 | |
| 3420 | // if wasm_block_ty is non-empty, we create a register to store the temporary value | 3359 | // if wasm_block_ty is non-empty, we create a register to store the temporary value |
| 3421 | const block_result: WValue = if (wasm_block_ty != std.wasm.block_empty) blk: { | 3360 | const block_result: WValue = if (wasm_block_ty != std.wasm.block_empty) blk: { |
| 3422 | const ty: Type = if (isByRef(block_ty, pt, cg.target)) Type.u32 else block_ty; | 3361 | const ty: Type = if (isByRef(block_ty, zcu, cg.target)) Type.u32 else block_ty; |
| 3423 | break :blk try cg.ensureAllocLocal(ty); // make sure it's a clean local as it may never get overwritten | 3362 | break :blk try cg.ensureAllocLocal(ty); // make sure it's a clean local as it may never get overwritten |
| 3424 | } else .none; | 3363 | } else .none; |
| 3425 | | 3364 | |
| ... | @@ -3544,7 +3483,7 @@ fn cmp(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareOpe | ... | @@ -3544,7 +3483,7 @@ fn cmp(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareOpe |
| 3544 | } | 3483 | } |
| 3545 | } else if (ty.isAnyFloat()) { | 3484 | } else if (ty.isAnyFloat()) { |
| 3546 | return cg.cmpFloat(ty, lhs, rhs, op); | 3485 | return cg.cmpFloat(ty, lhs, rhs, op); |
| 3547 | } else if (isByRef(ty, pt, cg.target)) { | 3486 | } else if (isByRef(ty, zcu, cg.target)) { |
| 3548 | return cg.cmpBigInt(lhs, rhs, ty, op); | 3487 | return cg.cmpBigInt(lhs, rhs, ty, op); |
| 3549 | } | 3488 | } |
| 3550 | | 3489 | |
| ... | @@ -3562,7 +3501,7 @@ fn cmp(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareOpe | ... | @@ -3562,7 +3501,7 @@ fn cmp(cg: *CodeGen, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareOpe |
| 3562 | try cg.lowerToStack(rhs); | 3501 | try cg.lowerToStack(rhs); |
| 3563 | | 3502 | |
| 3564 | const opcode: std.wasm.Opcode = buildOpcode(.{ | 3503 | const opcode: std.wasm.Opcode = buildOpcode(.{ |
| 3565 | .valtype1 = typeToValtype(ty, pt, cg.target), | 3504 | .valtype1 = typeToValtype(ty, zcu, cg.target), |
| 3566 | .op = switch (op) { | 3505 | .op = switch (op) { |
| 3567 | .lt => .lt, | 3506 | .lt => .lt, |
| 3568 | .lte => .le, | 3507 | .lte => .le, |
| ... | @@ -3769,7 +3708,7 @@ fn airBitcast(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3769,7 +3708,7 @@ fn airBitcast(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3769 | break :result try cg.bitcast(wanted_ty, given_ty, operand); | 3708 | break :result try cg.bitcast(wanted_ty, given_ty, operand); |
| 3770 | } | 3709 | } |
| 3771 | | 3710 | |
| 3772 | if (isByRef(given_ty, pt, cg.target) and !isByRef(wanted_ty, pt, cg.target)) { | 3711 | if (isByRef(given_ty, zcu, cg.target) and !isByRef(wanted_ty, zcu, cg.target)) { |
| 3773 | const loaded_memory = try cg.load(operand, wanted_ty, 0); | 3712 | const loaded_memory = try cg.load(operand, wanted_ty, 0); |
| 3774 | if (needs_wrapping) { | 3713 | if (needs_wrapping) { |
| 3775 | break :result try cg.wrapOperand(loaded_memory, wanted_ty); | 3714 | break :result try cg.wrapOperand(loaded_memory, wanted_ty); |
| ... | @@ -3777,7 +3716,7 @@ fn airBitcast(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3777,7 +3716,7 @@ fn airBitcast(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3777 | break :result loaded_memory; | 3716 | break :result loaded_memory; |
| 3778 | } | 3717 | } |
| 3779 | } | 3718 | } |
| 3780 | if (!isByRef(given_ty, pt, cg.target) and isByRef(wanted_ty, pt, cg.target)) { | 3719 | if (!isByRef(given_ty, zcu, cg.target) and isByRef(wanted_ty, zcu, cg.target)) { |
| 3781 | const stack_memory = try cg.allocStack(wanted_ty); | 3720 | const stack_memory = try cg.allocStack(wanted_ty); |
| 3782 | try cg.store(stack_memory, operand, given_ty, 0); | 3721 | try cg.store(stack_memory, operand, given_ty, 0); |
| 3783 | if (needs_wrapping) { | 3722 | if (needs_wrapping) { |
| ... | @@ -3807,8 +3746,8 @@ fn bitcast(cg: *CodeGen, wanted_ty: Type, given_ty: Type, operand: WValue) Inner | ... | @@ -3807,8 +3746,8 @@ fn bitcast(cg: *CodeGen, wanted_ty: Type, given_ty: Type, operand: WValue) Inner |
| 3807 | | 3746 | |
| 3808 | const opcode = buildOpcode(.{ | 3747 | const opcode = buildOpcode(.{ |
| 3809 | .op = .reinterpret, | 3748 | .op = .reinterpret, |
| 3810 | .valtype1 = typeToValtype(wanted_ty, pt, cg.target), | 3749 | .valtype1 = typeToValtype(wanted_ty, zcu, cg.target), |
| 3811 | .valtype2 = typeToValtype(given_ty, pt, cg.target), | 3750 | .valtype2 = typeToValtype(given_ty, zcu, cg.target), |
| 3812 | }); | 3751 | }); |
| 3813 | try cg.emitWValue(operand); | 3752 | try cg.emitWValue(operand); |
| 3814 | try cg.addTag(Mir.Inst.Tag.fromOpcode(opcode)); | 3753 | try cg.addTag(Mir.Inst.Tag.fromOpcode(opcode)); |
| ... | @@ -3930,8 +3869,8 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3930,8 +3869,8 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3930 | break :result try cg.trunc(shifted_value, field_ty, backing_ty); | 3869 | break :result try cg.trunc(shifted_value, field_ty, backing_ty); |
| 3931 | }, | 3870 | }, |
| 3932 | .@"union" => result: { | 3871 | .@"union" => result: { |
| 3933 | if (isByRef(struct_ty, pt, cg.target)) { | 3872 | if (isByRef(struct_ty, zcu, cg.target)) { |
| 3934 | if (!isByRef(field_ty, pt, cg.target)) { | 3873 | if (!isByRef(field_ty, zcu, cg.target)) { |
| 3935 | break :result try cg.load(operand, field_ty, 0); | 3874 | break :result try cg.load(operand, field_ty, 0); |
| 3936 | } else { | 3875 | } else { |
| 3937 | const new_stack_val = try cg.allocStack(field_ty); | 3876 | const new_stack_val = try cg.allocStack(field_ty); |
| ... | @@ -3957,7 +3896,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -3957,7 +3896,7 @@ fn airStructFieldVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 3957 | const offset = std.math.cast(u32, struct_ty.structFieldOffset(field_index, zcu)) orelse { | 3896 | const offset = std.math.cast(u32, struct_ty.structFieldOffset(field_index, zcu)) orelse { |
| 3958 | return cg.fail("Field type '{}' too big to fit into stack frame", .{field_ty.fmt(pt)}); | 3897 | return cg.fail("Field type '{}' too big to fit into stack frame", .{field_ty.fmt(pt)}); |
| 3959 | }; | 3898 | }; |
| 3960 | if (isByRef(field_ty, pt, cg.target)) { | 3899 | if (isByRef(field_ty, zcu, cg.target)) { |
| 3961 | switch (operand) { | 3900 | switch (operand) { |
| 3962 | .stack_offset => |stack_offset| { | 3901 | .stack_offset => |stack_offset| { |
| 3963 | break :result .{ .stack_offset = .{ .value = stack_offset.value + offset, .references = 1 } }; | 3902 | break :result .{ .stack_offset = .{ .value = stack_offset.value + offset, .references = 1 } }; |
| ... | @@ -4220,7 +4159,7 @@ fn airUnwrapErrUnionPayload(cg: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) | ... | @@ -4220,7 +4159,7 @@ fn airUnwrapErrUnionPayload(cg: *CodeGen, inst: Air.Inst.Index, op_is_ptr: bool) |
| 4220 | } | 4159 | } |
| 4221 | | 4160 | |
| 4222 | const pl_offset = @as(u32, @intCast(errUnionPayloadOffset(payload_ty, zcu))); | 4161 | const pl_offset = @as(u32, @intCast(errUnionPayloadOffset(payload_ty, zcu))); |
| 4223 | if (op_is_ptr or isByRef(payload_ty, pt, cg.target)) { | 4162 | if (op_is_ptr or isByRef(payload_ty, zcu, cg.target)) { |
| 4224 | break :result try cg.buildPointerOffset(operand, pl_offset, .new); | 4163 | break :result try cg.buildPointerOffset(operand, pl_offset, .new); |
| 4225 | } | 4164 | } |
| 4226 | | 4165 | |
| ... | @@ -4446,7 +4385,7 @@ fn airOptionalPayload(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4446,7 +4385,7 @@ fn airOptionalPayload(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4446 | const operand = try cg.resolveInst(ty_op.operand); | 4385 | const operand = try cg.resolveInst(ty_op.operand); |
| 4447 | if (opt_ty.optionalReprIsPayload(zcu)) break :result cg.reuseOperand(ty_op.operand, operand); | 4386 | if (opt_ty.optionalReprIsPayload(zcu)) break :result cg.reuseOperand(ty_op.operand, operand); |
| 4448 | | 4387 | |
| 4449 | if (isByRef(payload_ty, pt, cg.target)) { | 4388 | if (isByRef(payload_ty, zcu, cg.target)) { |
| 4450 | break :result try cg.buildPointerOffset(operand, 0, .new); | 4389 | break :result try cg.buildPointerOffset(operand, 0, .new); |
| 4451 | } | 4390 | } |
| 4452 | | 4391 | |
| ... | @@ -4580,7 +4519,7 @@ fn airSliceElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4580,7 +4519,7 @@ fn airSliceElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4580 | try cg.addTag(.i32_mul); | 4519 | try cg.addTag(.i32_mul); |
| 4581 | try cg.addTag(.i32_add); | 4520 | try cg.addTag(.i32_add); |
| 4582 | | 4521 | |
| 4583 | const elem_result = if (isByRef(elem_ty, pt, cg.target)) | 4522 | const elem_result = if (isByRef(elem_ty, zcu, cg.target)) |
| 4584 | .stack | 4523 | .stack |
| 4585 | else | 4524 | else |
| 4586 | try cg.load(.stack, elem_ty, 0); | 4525 | try cg.load(.stack, elem_ty, 0); |
| ... | @@ -4739,7 +4678,7 @@ fn airPtrElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4739,7 +4678,7 @@ fn airPtrElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4739 | try cg.addTag(.i32_mul); | 4678 | try cg.addTag(.i32_mul); |
| 4740 | try cg.addTag(.i32_add); | 4679 | try cg.addTag(.i32_add); |
| 4741 | | 4680 | |
| 4742 | const elem_result = if (isByRef(elem_ty, pt, cg.target)) | 4681 | const elem_result = if (isByRef(elem_ty, zcu, cg.target)) |
| 4743 | .stack | 4682 | .stack |
| 4744 | else | 4683 | else |
| 4745 | try cg.load(.stack, elem_ty, 0); | 4684 | try cg.load(.stack, elem_ty, 0); |
| ... | @@ -4790,7 +4729,7 @@ fn airPtrBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { | ... | @@ -4790,7 +4729,7 @@ fn airPtrBinOp(cg: *CodeGen, inst: Air.Inst.Index, op: Op) InnerError!void { |
| 4790 | else => ptr_ty.childType(zcu), | 4729 | else => ptr_ty.childType(zcu), |
| 4791 | }; | 4730 | }; |
| 4792 | | 4731 | |
| 4793 | const valtype = typeToValtype(Type.usize, pt, cg.target); | 4732 | const valtype = typeToValtype(Type.usize, zcu, cg.target); |
| 4794 | const mul_opcode = buildOpcode(.{ .valtype1 = valtype, .op = .mul }); | 4733 | const mul_opcode = buildOpcode(.{ .valtype1 = valtype, .op = .mul }); |
| 4795 | const bin_opcode = buildOpcode(.{ .valtype1 = valtype, .op = op }); | 4734 | const bin_opcode = buildOpcode(.{ .valtype1 = valtype, .op = op }); |
| 4796 | | 4735 | |
| ... | @@ -4933,7 +4872,7 @@ fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4933,7 +4872,7 @@ fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4933 | const elem_ty = array_ty.childType(zcu); | 4872 | const elem_ty = array_ty.childType(zcu); |
| 4934 | const elem_size = elem_ty.abiSize(zcu); | 4873 | const elem_size = elem_ty.abiSize(zcu); |
| 4935 | | 4874 | |
| 4936 | if (isByRef(array_ty, pt, cg.target)) { | 4875 | if (isByRef(array_ty, zcu, cg.target)) { |
| 4937 | try cg.lowerToStack(array); | 4876 | try cg.lowerToStack(array); |
| 4938 | try cg.emitWValue(index); | 4877 | try cg.emitWValue(index); |
| 4939 | try cg.addImm32(@intCast(elem_size)); | 4878 | try cg.addImm32(@intCast(elem_size)); |
| ... | @@ -4976,7 +4915,7 @@ fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -4976,7 +4915,7 @@ fn airArrayElemVal(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 4976 | } | 4915 | } |
| 4977 | } | 4916 | } |
| 4978 | | 4917 | |
| 4979 | const elem_result = if (isByRef(elem_ty, pt, cg.target)) | 4918 | const elem_result = if (isByRef(elem_ty, zcu, cg.target)) |
| 4980 | .stack | 4919 | .stack |
| 4981 | else | 4920 | else |
| 4982 | try cg.load(.stack, elem_ty, 0); | 4921 | try cg.load(.stack, elem_ty, 0); |
| ... | @@ -5027,8 +4966,8 @@ fn airIntFromFloat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5027,8 +4966,8 @@ fn airIntFromFloat(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5027 | try cg.emitWValue(operand); | 4966 | try cg.emitWValue(operand); |
| 5028 | const op = buildOpcode(.{ | 4967 | const op = buildOpcode(.{ |
| 5029 | .op = .trunc, | 4968 | .op = .trunc, |
| 5030 | .valtype1 = typeToValtype(dest_ty, pt, cg.target), | 4969 | .valtype1 = typeToValtype(dest_ty, zcu, cg.target), |
| 5031 | .valtype2 = typeToValtype(op_ty, pt, cg.target), | 4970 | .valtype2 = typeToValtype(op_ty, zcu, cg.target), |
| 5032 | .signedness = dest_info.signedness, | 4971 | .signedness = dest_info.signedness, |
| 5033 | }); | 4972 | }); |
| 5034 | try cg.addTag(Mir.Inst.Tag.fromOpcode(op)); | 4973 | try cg.addTag(Mir.Inst.Tag.fromOpcode(op)); |
| ... | @@ -5080,8 +5019,8 @@ fn airFloatFromInt(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5080,8 +5019,8 @@ fn airFloatFromInt(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5080 | try cg.emitWValue(operand); | 5019 | try cg.emitWValue(operand); |
| 5081 | const op = buildOpcode(.{ | 5020 | const op = buildOpcode(.{ |
| 5082 | .op = .convert, | 5021 | .op = .convert, |
| 5083 | .valtype1 = typeToValtype(dest_ty, pt, cg.target), | 5022 | .valtype1 = typeToValtype(dest_ty, zcu, cg.target), |
| 5084 | .valtype2 = typeToValtype(op_ty, pt, cg.target), | 5023 | .valtype2 = typeToValtype(op_ty, zcu, cg.target), |
| 5085 | .signedness = op_info.signedness, | 5024 | .signedness = op_info.signedness, |
| 5086 | }); | 5025 | }); |
| 5087 | try cg.addTag(Mir.Inst.Tag.fromOpcode(op)); | 5026 | try cg.addTag(Mir.Inst.Tag.fromOpcode(op)); |
| ... | @@ -5180,7 +5119,7 @@ fn airShuffle(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5180,7 +5119,7 @@ fn airShuffle(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5180 | const elem_size = child_ty.abiSize(zcu); | 5119 | const elem_size = child_ty.abiSize(zcu); |
| 5181 | | 5120 | |
| 5182 | // TODO: One of them could be by ref; handle in loop | 5121 | // TODO: One of them could be by ref; handle in loop |
| 5183 | if (isByRef(cg.typeOf(extra.a), pt, cg.target) or isByRef(inst_ty, pt, cg.target)) { | 5122 | if (isByRef(cg.typeOf(extra.a), zcu, cg.target) or isByRef(inst_ty, zcu, cg.target)) { |
| 5184 | const result = try cg.allocStack(inst_ty); | 5123 | const result = try cg.allocStack(inst_ty); |
| 5185 | | 5124 | |
| 5186 | for (0..mask_len) |index| { | 5125 | for (0..mask_len) |index| { |
| ... | @@ -5256,7 +5195,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5256,7 +5195,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5256 | // When the element type is by reference, we must copy the entire | 5195 | // When the element type is by reference, we must copy the entire |
| 5257 | // value. It is therefore safer to move the offset pointer and store | 5196 | // value. It is therefore safer to move the offset pointer and store |
| 5258 | // each value individually, instead of using store offsets. | 5197 | // each value individually, instead of using store offsets. |
| 5259 | if (isByRef(elem_ty, pt, cg.target)) { | 5198 | if (isByRef(elem_ty, zcu, cg.target)) { |
| 5260 | // copy stack pointer into a temporary local, which is | 5199 | // copy stack pointer into a temporary local, which is |
| 5261 | // moved for each element to store each value in the right position. | 5200 | // moved for each element to store each value in the right position. |
| 5262 | const offset = try cg.buildPointerOffset(result, 0, .new); | 5201 | const offset = try cg.buildPointerOffset(result, 0, .new); |
| ... | @@ -5286,7 +5225,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5286,7 +5225,7 @@ fn airAggregateInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5286 | }, | 5225 | }, |
| 5287 | .@"struct" => switch (result_ty.containerLayout(zcu)) { | 5226 | .@"struct" => switch (result_ty.containerLayout(zcu)) { |
| 5288 | .@"packed" => { | 5227 | .@"packed" => { |
| 5289 | if (isByRef(result_ty, pt, cg.target)) { | 5228 | if (isByRef(result_ty, zcu, cg.target)) { |
| 5290 | return cg.fail("TODO: airAggregateInit for packed structs larger than 64 bits", .{}); | 5229 | return cg.fail("TODO: airAggregateInit for packed structs larger than 64 bits", .{}); |
| 5291 | } | 5230 | } |
| 5292 | const packed_struct = zcu.typeToPackedStruct(result_ty).?; | 5231 | const packed_struct = zcu.typeToPackedStruct(result_ty).?; |
| ... | @@ -5389,15 +5328,15 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -5389,15 +5328,15 @@ fn airUnionInit(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 5389 | if (layout.tag_size == 0) { | 5328 | if (layout.tag_size == 0) { |
| 5390 | break :result .none; | 5329 | break :result .none; |
| 5391 | } | 5330 | } |
| 5392 | assert(!isByRef(union_ty, pt, cg.target)); | 5331 | assert(!isByRef(union_ty, zcu, cg.target)); |
| 5393 | break :result tag_int; | 5332 | break :result tag_int; |
| 5394 | } | 5333 | } |
| 5395 | | 5334 | |
| 5396 | if (isByRef(union_ty, pt, cg.target)) { | 5335 | if (isByRef(union_ty, zcu, cg.target)) { |
| 5397 | const result_ptr = try cg.allocStack(union_ty); | 5336 | const result_ptr = try cg.allocStack(union_ty); |
| 5398 | const payload = try cg.resolveInst(extra.init); | 5337 | const payload = try cg.resolveInst(extra.init); |
| 5399 | if (layout.tag_align.compare(.gte, layout.payload_align)) { | 5338 | if (layout.tag_align.compare(.gte, layout.payload_align)) { |
| 5400 | if (isByRef(field_ty, pt, cg.target)) { | 5339 | if (isByRef(field_ty, zcu, cg.target)) { |
| 5401 | const payload_ptr = try cg.buildPointerOffset(result_ptr, layout.tag_size, .new); | 5340 | const payload_ptr = try cg.buildPointerOffset(result_ptr, layout.tag_size, .new); |
| 5402 | try cg.store(payload_ptr, payload, field_ty, 0); | 5341 | try cg.store(payload_ptr, payload, field_ty, 0); |
| 5403 | } else { | 5342 | } else { |
| ... | @@ -5478,7 +5417,7 @@ fn cmpOptionals(cg: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: st | ... | @@ -5478,7 +5417,7 @@ fn cmpOptionals(cg: *CodeGen, lhs: WValue, rhs: WValue, operand_ty: Type, op: st |
| 5478 | | 5417 | |
| 5479 | _ = try cg.load(lhs, payload_ty, 0); | 5418 | _ = try cg.load(lhs, payload_ty, 0); |
| 5480 | _ = try cg.load(rhs, payload_ty, 0); | 5419 | _ = try cg.load(rhs, payload_ty, 0); |
| 5481 | const opcode = buildOpcode(.{ .op = .ne, .valtype1 = typeToValtype(payload_ty, pt, cg.target) }); | 5420 | const opcode = buildOpcode(.{ .op = .ne, .valtype1 = typeToValtype(payload_ty, zcu, cg.target) }); |
| 5482 | try cg.addTag(Mir.Inst.Tag.fromOpcode(opcode)); | 5421 | try cg.addTag(Mir.Inst.Tag.fromOpcode(opcode)); |
| 5483 | try cg.addLabel(.br_if, 0); | 5422 | try cg.addLabel(.br_if, 0); |
| 5484 | | 5423 | |
| ... | @@ -6521,7 +6460,7 @@ fn lowerTry( | ... | @@ -6521,7 +6460,7 @@ fn lowerTry( |
| 6521 | } | 6460 | } |
| 6522 | | 6461 | |
| 6523 | const pl_offset: u32 = @intCast(errUnionPayloadOffset(pl_ty, zcu)); | 6462 | const pl_offset: u32 = @intCast(errUnionPayloadOffset(pl_ty, zcu)); |
| 6524 | if (isByRef(pl_ty, pt, cg.target)) { | 6463 | if (isByRef(pl_ty, zcu, cg.target)) { |
| 6525 | return buildPointerOffset(cg, err_union, pl_offset, .new); | 6464 | return buildPointerOffset(cg, err_union, pl_offset, .new); |
| 6526 | } | 6465 | } |
| 6527 | const payload = try cg.load(err_union, pl_ty, pl_offset); | 6466 | const payload = try cg.load(err_union, pl_ty, pl_offset); |
| ... | @@ -7100,7 +7039,7 @@ fn callIntrinsic( | ... | @@ -7100,7 +7039,7 @@ fn callIntrinsic( |
| 7100 | | 7039 | |
| 7101 | // Always pass over C-ABI | 7040 | // Always pass over C-ABI |
| 7102 | | 7041 | |
| 7103 | const want_sret_param = firstParamSRet(.{ .wasm_watc = .{} }, return_type, pt, cg.target); | 7042 | const want_sret_param = firstParamSRet(.{ .wasm_watc = .{} }, return_type, zcu, cg.target); |
| 7104 | // if we want return as first param, we allocate a pointer to stack, | 7043 | // if we want return as first param, we allocate a pointer to stack, |
| 7105 | // and emit it as our first argument | 7044 | // and emit it as our first argument |
| 7106 | const sret = if (want_sret_param) blk: { | 7045 | const sret = if (want_sret_param) blk: { |
| ... | @@ -7282,7 +7221,7 @@ fn airCmpxchg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { | ... | @@ -7282,7 +7221,7 @@ fn airCmpxchg(cg: *CodeGen, inst: Air.Inst.Index) InnerError!void { |
| 7282 | break :val ptr_val; | 7221 | break :val ptr_val; |
| 7283 | }; | 7222 | }; |
| 7284 | | 7223 | |
| 7285 | const result = if (isByRef(result_ty, pt, cg.target)) val: { | 7224 | const result = if (isByRef(result_ty, zcu, cg.target)) val: { |
| 7286 | try cg.emitWValue(cmp_result); | 7225 | try cg.emitWValue(cmp_result); |
| 7287 | try cg.addImm32(~@as(u32, 0)); | 7226 | try cg.addImm32(~@as(u32, 0)); |
| 7288 | try cg.addTag(.i32_xor); | 7227 | try cg.addTag(.i32_xor); |