| ... | ... | @@ -3514,8 +3514,14 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 3514 | 3514 | else => return self.fail("TODO implement args on stack for {} with abi size > 8", .{mcv}), |
| 3515 | 3515 | } |
| 3516 | 3516 | }, |
| 3517 | .embedded_in_code => { |
| 3518 | if (abi_size <= 8) { |
| 3519 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 3520 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); |
| 3521 | } |
| 3522 | return self.fail("TODO implement args on stack for {} with abi size > 8", .{mcv}); |
| 3523 | }, |
| 3517 | 3524 | .memory, |
| 3518 | | .embedded_in_code, |
| 3519 | 3525 | .direct_load, |
| 3520 | 3526 | .got_load, |
| 3521 | 3527 | => { |
| ... | ... | @@ -3523,7 +3529,58 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE |
| 3523 | 3529 | const reg = try self.copyToTmpRegister(ty, mcv); |
| 3524 | 3530 | return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg }); |
| 3525 | 3531 | } |
| 3526 | | return self.fail("TODO implement memcpy for setting args on stack from {}", .{mcv}); |
| 3532 | |
| 3533 | self.register_manager.freezeRegs(&.{ .rax, .rcx }); |
| 3534 | defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx }); |
| 3535 | |
| 3536 | const addr_reg: Register = blk: { |
| 3537 | switch (mcv) { |
| 3538 | .got_load, |
| 3539 | .direct_load, |
| 3540 | => |sym_index| { |
| 3541 | const flags: u2 = switch (mcv) { |
| 3542 | .got_load => 0b00, |
| 3543 | .direct_load => 0b01, |
| 3544 | else => unreachable, |
| 3545 | }; |
| 3546 | const addr_reg = try self.register_manager.allocReg(null); |
| 3547 | _ = try self.addInst(.{ |
| 3548 | .tag = .lea_pie, |
| 3549 | .ops = (Mir.Ops{ |
| 3550 | .reg1 = addr_reg.to64(), |
| 3551 | .flags = flags, |
| 3552 | }).encode(), |
| 3553 | .data = .{ .linker_sym_index = sym_index }, |
| 3554 | }); |
| 3555 | break :blk addr_reg; |
| 3556 | }, |
| 3557 | .memory => |addr| { |
| 3558 | const addr_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = addr }); |
| 3559 | break :blk addr_reg; |
| 3560 | }, |
| 3561 | else => unreachable, |
| 3562 | } |
| 3563 | }; |
| 3564 | |
| 3565 | self.register_manager.freezeRegs(&.{addr_reg}); |
| 3566 | defer self.register_manager.unfreezeRegs(&.{addr_reg}); |
| 3567 | |
| 3568 | const regs = try self.register_manager.allocRegs(2, .{ null, null }); |
| 3569 | const count_reg = regs[0]; |
| 3570 | const tmp_reg = regs[1]; |
| 3571 | |
| 3572 | try self.register_manager.getReg(.rax, null); |
| 3573 | try self.register_manager.getReg(.rcx, null); |
| 3574 | |
| 3575 | // TODO allow for abi_size to be u64 |
| 3576 | try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) }); |
| 3577 | try self.genInlineMemcpy( |
| 3578 | -(stack_offset + @intCast(i32, abi_size)), |
| 3579 | .rsp, |
| 3580 | addr_reg.to64(), |
| 3581 | count_reg.to64(), |
| 3582 | tmp_reg.to8(), |
| 3583 | ); |
| 3527 | 3584 | }, |
| 3528 | 3585 | .register => |reg| { |
| 3529 | 3586 | _ = try self.addInst(.{ |
| ... | ... | @@ -4488,6 +4545,7 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa |
| 4488 | 4545 | } |
| 4489 | 4546 | |
| 4490 | 4547 | fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue { |
| 4548 | log.debug("lowerUnnamedConst: ty = {}, val = {}", .{ tv.ty, tv.val }); |
| 4491 | 4549 | const local_sym_index = self.bin_file.lowerUnnamedConst(tv, self.mod_fn.owner_decl) catch |err| { |
| 4492 | 4550 | return self.fail("lowering unnamed constant failed: {s}", .{@errorName(err)}); |
| 4493 | 4551 | }; |
| ... | ... | @@ -4520,23 +4578,20 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue { |
| 4520 | 4578 | switch (typed_value.ty.zigTypeTag()) { |
| 4521 | 4579 | .Pointer => switch (typed_value.ty.ptrSize()) { |
| 4522 | 4580 | .Slice => { |
| 4523 | | var buf: Type.SlicePtrFieldTypeBuffer = undefined; |
| 4524 | | const ptr_type = typed_value.ty.slicePtrFieldType(&buf); |
| 4525 | | const ptr_mcv = try self.genTypedValue(.{ .ty = ptr_type, .val = typed_value.val }); |
| 4526 | | const slice_len = typed_value.val.sliceLen(); |
| 4527 | | // Codegen can't handle some kinds of indirection. If the wrong union field is accessed here it may mean |
| 4528 | | // the Sema code needs to use anonymous Decls or alloca instructions to store data. |
| 4529 | | const ptr_imm = ptr_mcv.memory; |
| 4530 | | _ = slice_len; |
| 4531 | | _ = ptr_imm; |
| 4532 | | // We need more general support for const data being stored in memory to make this work. |
| 4533 | | return self.fail("TODO codegen for const slices", .{}); |
| 4581 | return self.lowerUnnamedConst(typed_value); |
| 4534 | 4582 | }, |
| 4535 | 4583 | else => { |
| 4536 | | if (typed_value.val.tag() == .int_u64) { |
| 4537 | | return MCValue{ .immediate = typed_value.val.toUnsignedInt() }; |
| 4584 | switch (typed_value.val.tag()) { |
| 4585 | .int_u64 => { |
| 4586 | return MCValue{ .immediate = typed_value.val.toUnsignedInt() }; |
| 4587 | }, |
| 4588 | .slice => { |
| 4589 | return self.lowerUnnamedConst(typed_value); |
| 4590 | }, |
| 4591 | else => { |
| 4592 | return self.fail("TODO codegen more kinds of const pointers: {}", .{typed_value.val.tag()}); |
| 4593 | }, |
| 4538 | 4594 | } |
| 4539 | | return self.fail("TODO codegen more kinds of const pointers: {}", .{typed_value.val.tag()}); |
| 4540 | 4595 | }, |
| 4541 | 4596 | }, |
| 4542 | 4597 | .Int => { |