| ... | ... | @@ -794,7 +794,7 @@ fn genFunctype(gpa: Allocator, fn_info: Type.Payload.Function.Data, target: std. |
| 794 | 794 | defer returns.deinit(); |
| 795 | 795 | |
| 796 | 796 | if (firstParamSRet(fn_info, target)) { |
| 797 | | try params.append(typeToValtype(fn_info.return_type, target)); |
| 797 | try params.append(.i32); // memory address is always a 32-bit handle |
| 798 | 798 | } else if (fn_info.return_type.hasRuntimeBitsIgnoreComptime()) { |
| 799 | 799 | if (fn_info.cc == .C) { |
| 800 | 800 | const res_classes = abi.classifyType(fn_info.return_type, target); |
| ... | ... | @@ -824,7 +824,10 @@ fn genFunctype(gpa: Allocator, fn_info: Type.Payload.Function.Data, target: std. |
| 824 | 824 | } |
| 825 | 825 | } |
| 826 | 826 | }, |
| 827 | | else => try params.append(typeToValtype(param_type, target)), |
| 827 | else => if (isByRef(param_type, target)) |
| 828 | try params.append(.i32) |
| 829 | else |
| 830 | try params.append(typeToValtype(param_type, target)), |
| 828 | 831 | } |
| 829 | 832 | } |
| 830 | 833 | } |
| ... | ... | @@ -844,7 +847,6 @@ pub fn generate( |
| 844 | 847 | code: *std.ArrayList(u8), |
| 845 | 848 | debug_output: codegen.DebugInfoOutput, |
| 846 | 849 | ) codegen.GenerateSymbolError!codegen.FnResult { |
| 847 | | _ = debug_output; // TODO |
| 848 | 850 | _ = src_loc; |
| 849 | 851 | var code_gen: Self = .{ |
| 850 | 852 | .gpa = bin_file.allocator, |
| ... | ... | @@ -1088,9 +1090,9 @@ fn lowerArg(self: *Self, cc: std.builtin.CallingConvention, ty: Type, value: WVa |
| 1088 | 1090 | assert(ty.abiSize(self.target) == 16); |
| 1089 | 1091 | // in this case we have an integer or float that must be lowered as 2 i64's. |
| 1090 | 1092 | try self.emitWValue(value); |
| 1091 | | try self.addMemArg(.i64_load, .{ .offset = value.offset(), .alignment = 16 }); |
| 1093 | try self.addMemArg(.i64_load, .{ .offset = value.offset(), .alignment = 8 }); |
| 1092 | 1094 | try self.emitWValue(value); |
| 1093 | | try self.addMemArg(.i64_load, .{ .offset = value.offset() + 8, .alignment = 16 }); |
| 1095 | try self.addMemArg(.i64_load, .{ .offset = value.offset() + 8, .alignment = 8 }); |
| 1094 | 1096 | }, |
| 1095 | 1097 | else => return self.lowerToStack(value), |
| 1096 | 1098 | } |
| ... | ... | @@ -1221,14 +1223,8 @@ fn memcpy(self: *Self, dst: WValue, src: WValue, len: WValue) !void { |
| 1221 | 1223 | // When bulk_memory is enabled, we lower it to wasm's memcpy instruction. |
| 1222 | 1224 | // If not, we lower it ourselves manually |
| 1223 | 1225 | if (std.Target.wasm.featureSetHas(self.target.cpu.features, .bulk_memory)) { |
| 1224 | | switch (dst) { |
| 1225 | | .stack_offset => try self.emitWValue(try self.buildPointerOffset(dst, 0, .new)), |
| 1226 | | else => try self.emitWValue(dst), |
| 1227 | | } |
| 1228 | | switch (src) { |
| 1229 | | .stack_offset => try self.emitWValue(try self.buildPointerOffset(src, 0, .new)), |
| 1230 | | else => try self.emitWValue(src), |
| 1231 | | } |
| 1226 | try self.lowerToStack(dst); |
| 1227 | try self.lowerToStack(src); |
| 1232 | 1228 | try self.emitWValue(len); |
| 1233 | 1229 | try self.addExtended(.memory_copy); |
| 1234 | 1230 | return; |
| ... | ... | @@ -1792,7 +1788,7 @@ fn airStore(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 1792 | 1788 | const ty = self.air.typeOf(bin_op.lhs).childType(); |
| 1793 | 1789 | |
| 1794 | 1790 | try self.store(lhs, rhs, ty, 0); |
| 1795 | | return .none; |
| 1791 | return WValue{ .none = {} }; |
| 1796 | 1792 | } |
| 1797 | 1793 | |
| 1798 | 1794 | fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerError!void { |
| ... | ... | @@ -1848,11 +1844,8 @@ fn store(self: *Self, lhs: WValue, rhs: WValue, ty: Type, offset: u32) InnerErro |
| 1848 | 1844 | try self.emitWValue(lhs); |
| 1849 | 1845 | // In this case we're actually interested in storing the stack position |
| 1850 | 1846 | // into lhs, so we calculate that and emit that instead |
| 1851 | | if (rhs == .stack_offset) { |
| 1852 | | try self.emitWValue(try self.buildPointerOffset(rhs, 0, .new)); |
| 1853 | | } else { |
| 1854 | | try self.emitWValue(rhs); |
| 1855 | | } |
| 1847 | try self.lowerToStack(rhs); |
| 1848 | |
| 1856 | 1849 | const valtype = typeToValtype(ty, self.target); |
| 1857 | 1850 | const abi_size = @intCast(u8, ty.abiSize(self.target)); |
| 1858 | 1851 | |
| ... | ... | @@ -1912,14 +1905,29 @@ fn airArg(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 1912 | 1905 | const arg_index = self.arg_index; |
| 1913 | 1906 | const arg = self.args[arg_index]; |
| 1914 | 1907 | const cc = self.decl.ty.fnInfo().cc; |
| 1908 | const arg_ty = self.air.typeOfIndex(inst); |
| 1915 | 1909 | if (cc == .C) { |
| 1916 | | const ty = self.air.typeOfIndex(inst); |
| 1917 | | const arg_classes = abi.classifyType(ty, self.target); |
| 1910 | const arg_classes = abi.classifyType(arg_ty, self.target); |
| 1918 | 1911 | for (arg_classes) |class| { |
| 1919 | 1912 | if (class != .none) { |
| 1920 | 1913 | self.arg_index += 1; |
| 1921 | 1914 | } |
| 1922 | 1915 | } |
| 1916 | |
| 1917 | // When we have an argument that's passed using more than a single parameter, |
| 1918 | // we combine them into a single stack value |
| 1919 | if (arg_classes[0] == .direct and arg_classes[1] == .direct) { |
| 1920 | if (arg_ty.zigTypeTag() != .Int) { |
| 1921 | return self.fail( |
| 1922 | "TODO: Implement C-ABI argument for type '{}'", |
| 1923 | .{arg_ty.fmt(self.bin_file.base.options.module.?)}, |
| 1924 | ); |
| 1925 | } |
| 1926 | const result = try self.allocStack(arg_ty); |
| 1927 | try self.store(result, arg, Type.u64, 0); |
| 1928 | try self.store(result, self.args[arg_index + 1], Type.u64, 8); |
| 1929 | return result; |
| 1930 | } |
| 1923 | 1931 | } else { |
| 1924 | 1932 | self.arg_index += 1; |
| 1925 | 1933 | } |
| ... | ... | @@ -1943,7 +1951,7 @@ fn airArg(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 1943 | 1951 | std.dwarf.OP.WASM_local, |
| 1944 | 1952 | }); |
| 1945 | 1953 | leb.writeULEB128(dbg_info.writer(), arg.local) catch unreachable; |
| 1946 | | try self.addDbgInfoTypeReloc(self.air.typeOfIndex(inst)); |
| 1954 | try self.addDbgInfoTypeReloc(arg_ty); |
| 1947 | 1955 | dbg_info.appendSliceAssumeCapacity(name); |
| 1948 | 1956 | dbg_info.appendAssumeCapacity(0); |
| 1949 | 1957 | }, |
| ... | ... | @@ -2503,14 +2511,8 @@ fn cmp(self: *Self, lhs: WValue, rhs: WValue, ty: Type, op: std.math.CompareOper |
| 2503 | 2511 | |
| 2504 | 2512 | // ensure that when we compare pointers, we emit |
| 2505 | 2513 | // the true pointer of a stack value, rather than the stack pointer. |
| 2506 | | switch (lhs) { |
| 2507 | | .stack_offset => try self.emitWValue(try self.buildPointerOffset(lhs, 0, .new)), |
| 2508 | | else => try self.emitWValue(lhs), |
| 2509 | | } |
| 2510 | | switch (rhs) { |
| 2511 | | .stack_offset => try self.emitWValue(try self.buildPointerOffset(rhs, 0, .new)), |
| 2512 | | else => try self.emitWValue(rhs), |
| 2513 | | } |
| 2514 | try self.lowerToStack(lhs); |
| 2515 | try self.lowerToStack(rhs); |
| 2514 | 2516 | |
| 2515 | 2517 | const signedness: std.builtin.Signedness = blk: { |
| 2516 | 2518 | // by default we tell the operand type is unsigned (i.e. bools and enum values) |
| ... | ... | @@ -2560,11 +2562,7 @@ fn airBr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 2560 | 2562 | // if operand has codegen bits we should break with a value |
| 2561 | 2563 | if (self.air.typeOf(br.operand).hasRuntimeBitsIgnoreComptime()) { |
| 2562 | 2564 | const operand = try self.resolveInst(br.operand); |
| 2563 | | const op = switch (operand) { |
| 2564 | | .stack_offset => try self.buildPointerOffset(operand, 0, .new), |
| 2565 | | else => operand, |
| 2566 | | }; |
| 2567 | | try self.emitWValue(op); |
| 2565 | try self.lowerToStack(operand); |
| 2568 | 2566 | |
| 2569 | 2567 | if (block.value != .none) { |
| 2570 | 2568 | try self.addLabel(.local_set, block.value.local); |
| ... | ... | @@ -3295,11 +3293,7 @@ fn airPtrElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3295 | 3293 | const ptr_local = try self.load(ptr, Type.usize, 0); |
| 3296 | 3294 | try self.addLabel(.local_get, ptr_local.local); |
| 3297 | 3295 | } else { |
| 3298 | | const pointer = switch (ptr) { |
| 3299 | | .stack_offset => try self.buildPointerOffset(ptr, 0, .new), |
| 3300 | | else => ptr, |
| 3301 | | }; |
| 3302 | | try self.emitWValue(pointer); |
| 3296 | try self.lowerToStack(ptr); |
| 3303 | 3297 | } |
| 3304 | 3298 | |
| 3305 | 3299 | // calculate index into slice |
| ... | ... | @@ -3332,11 +3326,7 @@ fn airPtrElemPtr(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3332 | 3326 | const ptr_local = try self.load(ptr, Type.usize, 0); |
| 3333 | 3327 | try self.addLabel(.local_get, ptr_local.local); |
| 3334 | 3328 | } else { |
| 3335 | | const pointer = switch (ptr) { |
| 3336 | | .stack_offset => try self.buildPointerOffset(ptr, 0, .new), |
| 3337 | | else => ptr, |
| 3338 | | }; |
| 3339 | | try self.emitWValue(pointer); |
| 3329 | try self.lowerToStack(ptr); |
| 3340 | 3330 | } |
| 3341 | 3331 | |
| 3342 | 3332 | // calculate index into ptr |
| ... | ... | @@ -3365,11 +3355,7 @@ fn airPtrBinOp(self: *Self, inst: Air.Inst.Index, op: Op) InnerError!WValue { |
| 3365 | 3355 | const mul_opcode = buildOpcode(.{ .valtype1 = valtype, .op = .mul }); |
| 3366 | 3356 | const bin_opcode = buildOpcode(.{ .valtype1 = valtype, .op = op }); |
| 3367 | 3357 | |
| 3368 | | const pointer = switch (ptr) { |
| 3369 | | .stack_offset => try self.buildPointerOffset(ptr, 0, .new), |
| 3370 | | else => ptr, |
| 3371 | | }; |
| 3372 | | try self.emitWValue(pointer); |
| 3358 | try self.lowerToStack(ptr); |
| 3373 | 3359 | try self.emitWValue(offset); |
| 3374 | 3360 | try self.addImm32(@bitCast(i32, @intCast(u32, pointee_ty.abiSize(self.target)))); |
| 3375 | 3361 | try self.addTag(Mir.Inst.Tag.fromOpcode(mul_opcode)); |
| ... | ... | @@ -3400,10 +3386,7 @@ fn memset(self: *Self, ptr: WValue, len: WValue, value: WValue) InnerError!void |
| 3400 | 3386 | // When bulk_memory is enabled, we lower it to wasm's memset instruction. |
| 3401 | 3387 | // If not, we lower it ourselves |
| 3402 | 3388 | if (std.Target.wasm.featureSetHas(self.target.cpu.features, .bulk_memory)) { |
| 3403 | | switch (ptr) { |
| 3404 | | .stack_offset => try self.emitWValue(try self.buildPointerOffset(ptr, 0, .new)), |
| 3405 | | else => try self.emitWValue(ptr), |
| 3406 | | } |
| 3389 | try self.lowerToStack(ptr); |
| 3407 | 3390 | try self.emitWValue(value); |
| 3408 | 3391 | try self.emitWValue(len); |
| 3409 | 3392 | try self.addExtended(.memory_fill); |
| ... | ... | @@ -3490,12 +3473,7 @@ fn airArrayElemVal(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3490 | 3473 | const elem_ty = array_ty.childType(); |
| 3491 | 3474 | const elem_size = elem_ty.abiSize(self.target); |
| 3492 | 3475 | |
| 3493 | | const array_ptr = switch (array) { |
| 3494 | | .stack_offset => try self.buildPointerOffset(array, 0, .new), |
| 3495 | | else => array, |
| 3496 | | }; |
| 3497 | | |
| 3498 | | try self.emitWValue(array_ptr); |
| 3476 | try self.lowerToStack(array); |
| 3499 | 3477 | try self.emitWValue(index); |
| 3500 | 3478 | try self.addImm32(@bitCast(i32, @intCast(u32, elem_size))); |
| 3501 | 3479 | try self.addTag(.i32_mul); |
| ... | ... | @@ -3518,6 +3496,10 @@ fn airFloatToInt(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3518 | 3496 | const dest_ty = self.air.typeOfIndex(inst); |
| 3519 | 3497 | const op_ty = self.air.typeOf(ty_op.operand); |
| 3520 | 3498 | |
| 3499 | if (op_ty.abiSize(self.target) > 8) { |
| 3500 | return self.fail("TODO: floatToInt for integers/floats with bitsize larger than 64 bits", .{}); |
| 3501 | } |
| 3502 | |
| 3521 | 3503 | try self.emitWValue(operand); |
| 3522 | 3504 | const op = buildOpcode(.{ |
| 3523 | 3505 | .op = .trunc, |
| ... | ... | @@ -3541,6 +3523,10 @@ fn airIntToFloat(self: *Self, inst: Air.Inst.Index) InnerError!WValue { |
| 3541 | 3523 | const dest_ty = self.air.typeOfIndex(inst); |
| 3542 | 3524 | const op_ty = self.air.typeOf(ty_op.operand); |
| 3543 | 3525 | |
| 3526 | if (op_ty.abiSize(self.target) > 8) { |
| 3527 | return self.fail("TODO: intToFloat for integers/floats with bitsize larger than 64 bits", .{}); |
| 3528 | } |
| 3529 | |
| 3544 | 3530 | try self.emitWValue(operand); |
| 3545 | 3531 | const op = buildOpcode(.{ |
| 3546 | 3532 | .op = .convert, |