aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-02-10 13:01:23 +0100
committerJakub Konka <kubkon@jakubkonka.com>2022-02-11 10:52:13 +0100
commit08e2f5d08390d41b58c92707693385e5e2968fc8 (patch)
tree54547ecfb53ce4817174e6db467cc17ce4d10efe /src
parentf0400ad93eac984332c938b39e9c1627062d6b6a (diff)
downloadzig-08e2f5d08390d41b58c92707693385e5e2968fc8.tar.gz
zig-08e2f5d08390d41b58c92707693385e5e2968fc8.zip
codegen: handle lowering of const slice pointers
Diffstat (limited to 'src')
-rw-r--r--src/arch/x86_64/CodeGen.zig87
-rw-r--r--src/codegen.zig1
2 files changed, 71 insertions, 17 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig
index 09cd09b12d..c0bb233499 100644
--- a/src/arch/x86_64/CodeGen.zig
+++ b/src/arch/x86_64/CodeGen.zig
@@ -3514,8 +3514,14 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
else => return self.fail("TODO implement args on stack for {} with abi size > 8", .{mcv}),
}
},
+ .embedded_in_code => {
+ if (abi_size <= 8) {
+ const reg = try self.copyToTmpRegister(ty, mcv);
+ return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
+ }
+ return self.fail("TODO implement args on stack for {} with abi size > 8", .{mcv});
+ },
.memory,
- .embedded_in_code,
.direct_load,
.got_load,
=> {
@@ -3523,7 +3529,58 @@ fn genSetStackArg(self: *Self, ty: Type, stack_offset: i32, mcv: MCValue) InnerE
const reg = try self.copyToTmpRegister(ty, mcv);
return self.genSetStackArg(ty, stack_offset, MCValue{ .register = reg });
}
- return self.fail("TODO implement memcpy for setting args on stack from {}", .{mcv});
+
+ self.register_manager.freezeRegs(&.{ .rax, .rcx });
+ defer self.register_manager.unfreezeRegs(&.{ .rax, .rcx });
+
+ const addr_reg: Register = blk: {
+ switch (mcv) {
+ .got_load,
+ .direct_load,
+ => |sym_index| {
+ const flags: u2 = switch (mcv) {
+ .got_load => 0b00,
+ .direct_load => 0b01,
+ else => unreachable,
+ };
+ const addr_reg = try self.register_manager.allocReg(null);
+ _ = try self.addInst(.{
+ .tag = .lea_pie,
+ .ops = (Mir.Ops{
+ .reg1 = addr_reg.to64(),
+ .flags = flags,
+ }).encode(),
+ .data = .{ .linker_sym_index = sym_index },
+ });
+ break :blk addr_reg;
+ },
+ .memory => |addr| {
+ const addr_reg = try self.copyToTmpRegister(Type.usize, .{ .immediate = addr });
+ break :blk addr_reg;
+ },
+ else => unreachable,
+ }
+ };
+
+ self.register_manager.freezeRegs(&.{addr_reg});
+ defer self.register_manager.unfreezeRegs(&.{addr_reg});
+
+ const regs = try self.register_manager.allocRegs(2, .{ null, null });
+ const count_reg = regs[0];
+ const tmp_reg = regs[1];
+
+ try self.register_manager.getReg(.rax, null);
+ try self.register_manager.getReg(.rcx, null);
+
+ // TODO allow for abi_size to be u64
+ try self.genSetReg(Type.u32, count_reg, .{ .immediate = @intCast(u32, abi_size) });
+ try self.genInlineMemcpy(
+ -(stack_offset + @intCast(i32, abi_size)),
+ .rsp,
+ addr_reg.to64(),
+ count_reg.to64(),
+ tmp_reg.to8(),
+ );
},
.register => |reg| {
_ = try self.addInst(.{
@@ -4488,6 +4545,7 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl: *Module.Decl) InnerError!MCVa
}
fn lowerUnnamedConst(self: *Self, tv: TypedValue) InnerError!MCValue {
+ log.debug("lowerUnnamedConst: ty = {}, val = {}", .{ tv.ty, tv.val });
const local_sym_index = self.bin_file.lowerUnnamedConst(tv, self.mod_fn.owner_decl) catch |err| {
return self.fail("lowering unnamed constant failed: {s}", .{@errorName(err)});
};
@@ -4520,23 +4578,20 @@ fn genTypedValue(self: *Self, typed_value: TypedValue) InnerError!MCValue {
switch (typed_value.ty.zigTypeTag()) {
.Pointer => switch (typed_value.ty.ptrSize()) {
.Slice => {
- var buf: Type.SlicePtrFieldTypeBuffer = undefined;
- const ptr_type = typed_value.ty.slicePtrFieldType(&buf);
- const ptr_mcv = try self.genTypedValue(.{ .ty = ptr_type, .val = typed_value.val });
- const slice_len = typed_value.val.sliceLen();
- // Codegen can't handle some kinds of indirection. If the wrong union field is accessed here it may mean
- // the Sema code needs to use anonymous Decls or alloca instructions to store data.
- const ptr_imm = ptr_mcv.memory;
- _ = slice_len;
- _ = ptr_imm;
- // We need more general support for const data being stored in memory to make this work.
- return self.fail("TODO codegen for const slices", .{});
+ return self.lowerUnnamedConst(typed_value);
},
else => {
- if (typed_value.val.tag() == .int_u64) {
- return MCValue{ .immediate = typed_value.val.toUnsignedInt() };
+ switch (typed_value.val.tag()) {
+ .int_u64 => {
+ return MCValue{ .immediate = typed_value.val.toUnsignedInt() };
+ },
+ .slice => {
+ return self.lowerUnnamedConst(typed_value);
+ },
+ else => {
+ return self.fail("TODO codegen more kinds of const pointers: {}", .{typed_value.val.tag()});
+ },
}
- return self.fail("TODO codegen more kinds of const pointers: {}", .{typed_value.val.tag()});
},
},
.Int => {
diff --git a/src/codegen.zig b/src/codegen.zig
index d1c249d99d..389f38a020 100644
--- a/src/codegen.zig
+++ b/src/codegen.zig
@@ -230,7 +230,6 @@ pub fn generateSymbol(
return lowerDeclRef(bin_file, src_loc, typed_value, decl, code, debug_output);
},
.slice => {
- // TODO populate .debug_info for the slice
const slice = typed_value.val.castTag(.slice).?.data;
// generate ptr