authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-01-25 23:17:13+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-01-26 14:29:14+01:00
log041bc71bc8ff45dc2d4df11d48023e457b8b021e
treedd89ac48c1159c11612bbc70867da377cd53a9b1
parent4d804c1b239e45a0a28f4caf1f9748dac44ddce2

self-hosted: clean up calling logic for x86_64 and aarch64 across linkers


2 files changed, 93 insertions(+), 195 deletions(-)

src/arch/aarch64/CodeGen.zig+41-82
......@@ -4302,32 +4302,19 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43024302 // on linking.
43034303 const mod = self.bin_file.options.module.?;
43044304 if (self.air.value(callee)) |func_value| {
4305 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
4306 if (func_value.castTag(.function)) |func_payload| {
4307 const func = func_payload.data;
4305 if (func_value.castTag(.function)) |func_payload| {
4306 const func = func_payload.data;
4307 const fn_owner_decl = mod.declPtr(func.owner_decl);
4308
4309 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
43084310 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
43094311 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
4310 const fn_owner_decl = mod.declPtr(func.owner_decl);
43114312 const got_addr = blk: {
43124313 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
43134314 break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes);
43144315 };
4315
43164316 try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = got_addr });
4317
4318 _ = try self.addInst(.{
4319 .tag = .blr,
4320 .data = .{ .reg = .x30 },
4321 });
4322 } else if (func_value.castTag(.extern_fn)) |_| {
4323 return self.fail("TODO implement calling extern functions", .{});
4324 } else {
4325 return self.fail("TODO implement calling bitcasted functions", .{});
4326 }
4327 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
4328 if (func_value.castTag(.function)) |func_payload| {
4329 const func = func_payload.data;
4330 const fn_owner_decl = mod.declPtr(func.owner_decl);
4317 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
43314318 try fn_owner_decl.link.macho.ensureInitialized(macho_file);
43324319 try self.genSetReg(Type.initTag(.u64), .x30, .{
43334320 .linker_load = .{
......@@ -4335,22 +4322,39 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43354322 .sym_index = fn_owner_decl.link.macho.getSymbolIndex().?,
43364323 },
43374324 });
4338 // blr x30
4339 _ = try self.addInst(.{
4340 .tag = .blr,
4341 .data = .{ .reg = .x30 },
4325 } else if (self.bin_file.cast(link.File.Coff)) |_| {
4326 try self.genSetReg(Type.initTag(.u64), .x30, .{
4327 .linker_load = .{
4328 .type = .got,
4329 .sym_index = fn_owner_decl.link.coff.sym_index,
4330 },
43424331 });
4343 } else if (func_value.castTag(.extern_fn)) |func_payload| {
4344 const extern_fn = func_payload.data;
4345 const decl_name = mod.declPtr(extern_fn.owner_decl).name;
4346 if (extern_fn.lib_name) |lib_name| {
4347 log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{
4348 decl_name,
4349 lib_name,
4350 });
4351 }
4352 const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
4332 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
4333 try p9.seeDecl(func.owner_decl);
4334 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
4335 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
4336 const got_addr = p9.bases.data;
4337 const got_index = fn_owner_decl.link.plan9.got_index.?;
4338 const fn_got_addr = got_addr + got_index * ptr_bytes;
4339 try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = fn_got_addr });
4340 } else unreachable;
4341
4342 _ = try self.addInst(.{
4343 .tag = .blr,
4344 .data = .{ .reg = .x30 },
4345 });
4346 } else if (func_value.castTag(.extern_fn)) |func_payload| {
4347 const extern_fn = func_payload.data;
4348 const decl_name = mod.declPtr(extern_fn.owner_decl).name;
4349 if (extern_fn.lib_name) |lib_name| {
4350 log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{
4351 decl_name,
4352 lib_name,
4353 });
4354 }
43534355
4356 if (self.bin_file.cast(link.File.MachO)) |macho_file| {
4357 const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
43544358 _ = try self.addInst(.{
43554359 .tag = .call_extern,
43564360 .data = .{
......@@ -4360,33 +4364,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43604364 },
43614365 },
43624366 });
4363 } else {
4364 return self.fail("TODO implement calling bitcasted functions", .{});
4365 }
4366 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
4367 if (func_value.castTag(.function)) |func_payload| {
4368 const func = func_payload.data;
4369 const fn_owner_decl = mod.declPtr(func.owner_decl);
4370 try self.genSetReg(Type.initTag(.u64), .x30, .{
4371 .linker_load = .{
4372 .type = .got,
4373 .sym_index = fn_owner_decl.link.coff.sym_index,
4374 },
4375 });
4376 // blr x30
4377 _ = try self.addInst(.{
4378 .tag = .blr,
4379 .data = .{ .reg = .x30 },
4380 });
4381 } else if (func_value.castTag(.extern_fn)) |func_payload| {
4382 const extern_fn = func_payload.data;
4383 const decl_name = mod.declPtr(extern_fn.owner_decl).name;
4384 if (extern_fn.lib_name) |lib_name| {
4385 log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{
4386 decl_name,
4387 lib_name,
4388 });
4389 }
4367 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
43904368 const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
43914369 try self.genSetReg(Type.initTag(.u64), .x30, .{
43924370 .linker_load = .{
......@@ -4394,35 +4372,16 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43944372 .sym_index = sym_index,
43954373 },
43964374 });
4397 // blr x30
43984375 _ = try self.addInst(.{
43994376 .tag = .blr,
44004377 .data = .{ .reg = .x30 },
44014378 });
44024379 } else {
4403 return self.fail("TODO implement calling bitcasted functions", .{});
4404 }
4405 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
4406 if (func_value.castTag(.function)) |func_payload| {
4407 try p9.seeDecl(func_payload.data.owner_decl);
4408 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
4409 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
4410 const got_addr = p9.bases.data;
4411 const got_index = mod.declPtr(func_payload.data.owner_decl).link.plan9.got_index.?;
4412 const fn_got_addr = got_addr + got_index * ptr_bytes;
4413
4414 try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = fn_got_addr });
4415
4416 _ = try self.addInst(.{
4417 .tag = .blr,
4418 .data = .{ .reg = .x30 },
4419 });
4420 } else if (func_value.castTag(.extern_fn)) |_| {
44214380 return self.fail("TODO implement calling extern functions", .{});
4422 } else {
4423 return self.fail("TODO implement calling bitcasted functions", .{});
44244381 }
4425 } else unreachable;
4382 } else {
4383 return self.fail("TODO implement calling bitcasted functions", .{});
4384 }
44264385 } else {
44274386 assert(ty.zigTypeTag() == .Pointer);
44284387 const mcv = try self.resolveInst(callee);
src/arch/x86_64/CodeGen.zig+52-113
......@@ -3992,13 +3992,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
39923992 // Due to incremental compilation, how function calls are generated depends
39933993 // on linking.
39943994 const mod = self.bin_file.options.module.?;
3995 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
3996 if (self.air.value(callee)) |func_value| {
3997 if (func_value.castTag(.function)) |func_payload| {
3998 const func = func_payload.data;
3995 if (self.air.value(callee)) |func_value| {
3996 if (func_value.castTag(.function)) |func_payload| {
3997 const func = func_payload.data;
3998 const fn_owner_decl = mod.declPtr(func.owner_decl);
3999
4000 if (self.bin_file.cast(link.File.Elf)) |elf_file| {
39994001 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
40004002 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
4001 const fn_owner_decl = mod.declPtr(func.owner_decl);
40024003 const got_addr = blk: {
40034004 const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
40044005 break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes);
......@@ -4008,29 +4009,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
40084009 .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }),
40094010 .data = .{ .imm = @truncate(u32, got_addr) },
40104011 });
4011 } else if (func_value.castTag(.extern_fn)) |_| {
4012 return self.fail("TODO implement calling extern functions", .{});
4013 } else {
4014 return self.fail("TODO implement calling bitcasted functions", .{});
4015 }
4016 } else {
4017 assert(ty.zigTypeTag() == .Pointer);
4018 const mcv = try self.resolveInst(callee);
4019 try self.genSetReg(Type.initTag(.usize), .rax, mcv);
4020 _ = try self.addInst(.{
4021 .tag = .call,
4022 .ops = Mir.Inst.Ops.encode(.{
4023 .reg1 = .rax,
4024 .flags = 0b01,
4025 }),
4026 .data = undefined,
4027 });
4028 }
4029 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
4030 if (self.air.value(callee)) |func_value| {
4031 if (func_value.castTag(.function)) |func_payload| {
4032 const func = func_payload.data;
4033 const fn_owner_decl = mod.declPtr(func.owner_decl);
4012 } else if (self.bin_file.cast(link.File.Coff)) |_| {
40344013 try self.genSetReg(Type.initTag(.usize), .rax, .{
40354014 .linker_load = .{
40364015 .type = .got,
......@@ -4045,19 +4024,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
40454024 }),
40464025 .data = undefined,
40474026 });
4048 } else if (func_value.castTag(.extern_fn)) |func_payload| {
4049 const extern_fn = func_payload.data;
4050 const decl_name = mod.declPtr(extern_fn.owner_decl).name;
4051 if (extern_fn.lib_name) |lib_name| {
4052 log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{
4053 decl_name,
4054 lib_name,
4055 });
4056 }
4057 const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
4027 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
4028 try fn_owner_decl.link.macho.ensureInitialized(macho_file);
4029 const sym_index = fn_owner_decl.link.macho.getSymbolIndex().?;
40584030 try self.genSetReg(Type.initTag(.usize), .rax, .{
40594031 .linker_load = .{
4060 .type = .import,
4032 .type = .got,
40614033 .sym_index = sym_index,
40624034 },
40634035 });
......@@ -4069,36 +4041,37 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
40694041 }),
40704042 .data = undefined,
40714043 });
4072 } else {
4073 return self.fail("TODO implement calling bitcasted functions", .{});
4044 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
4045 try p9.seeDecl(func.owner_decl);
4046 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
4047 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
4048 const got_addr = p9.bases.data;
4049 const got_index = fn_owner_decl.link.plan9.got_index.?;
4050 const fn_got_addr = got_addr + got_index * ptr_bytes;
4051 _ = try self.addInst(.{
4052 .tag = .call,
4053 .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }),
4054 .data = .{ .imm = @intCast(u32, fn_got_addr) },
4055 });
4056 } else unreachable;
4057 } else if (func_value.castTag(.extern_fn)) |func_payload| {
4058 const extern_fn = func_payload.data;
4059 const decl_name = mod.declPtr(extern_fn.owner_decl).name;
4060 if (extern_fn.lib_name) |lib_name| {
4061 log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{
4062 decl_name,
4063 lib_name,
4064 });
40744065 }
4075 } else {
4076 assert(ty.zigTypeTag() == .Pointer);
4077 const mcv = try self.resolveInst(callee);
4078 try self.genSetReg(Type.initTag(.usize), .rax, mcv);
4079 _ = try self.addInst(.{
4080 .tag = .call,
4081 .ops = Mir.Inst.Ops.encode(.{
4082 .reg1 = .rax,
4083 .flags = 0b01,
4084 }),
4085 .data = undefined,
4086 });
4087 }
4088 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
4089 if (self.air.value(callee)) |func_value| {
4090 if (func_value.castTag(.function)) |func_payload| {
4091 const func = func_payload.data;
4092 const fn_owner_decl = mod.declPtr(func.owner_decl);
4093 try fn_owner_decl.link.macho.ensureInitialized(macho_file);
4094 const sym_index = fn_owner_decl.link.macho.getSymbolIndex().?;
4066
4067 if (self.bin_file.cast(link.File.Coff)) |coff_file| {
4068 const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
40954069 try self.genSetReg(Type.initTag(.usize), .rax, .{
40964070 .linker_load = .{
4097 .type = .got,
4071 .type = .import,
40984072 .sym_index = sym_index,
40994073 },
41004074 });
4101 // callq *%rax
41024075 _ = try self.addInst(.{
41034076 .tag = .call,
41044077 .ops = Mir.Inst.Ops.encode(.{
......@@ -4107,15 +4080,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
41074080 }),
41084081 .data = undefined,
41094082 });
4110 } else if (func_value.castTag(.extern_fn)) |func_payload| {
4111 const extern_fn = func_payload.data;
4112 const decl_name = mod.declPtr(extern_fn.owner_decl).name;
4113 if (extern_fn.lib_name) |lib_name| {
4114 log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{
4115 decl_name,
4116 lib_name,
4117 });
4118 }
4083 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
41194084 const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
41204085 _ = try self.addInst(.{
41214086 .tag = .call_extern,
......@@ -4128,50 +4093,24 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
41284093 },
41294094 });
41304095 } else {
4131 return self.fail("TODO implement calling bitcasted functions", .{});
4096 return self.fail("TODO implement calling extern functions", .{});
41324097 }
41334098 } else {
4134 assert(ty.zigTypeTag() == .Pointer);
4135 const mcv = try self.resolveInst(callee);
4136 try self.genSetReg(Type.initTag(.usize), .rax, mcv);
4137 _ = try self.addInst(.{
4138 .tag = .call,
4139 .ops = Mir.Inst.Ops.encode(.{
4140 .reg1 = .rax,
4141 .flags = 0b01,
4142 }),
4143 .data = undefined,
4144 });
4145 }
4146 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
4147 if (self.air.value(callee)) |func_value| {
4148 if (func_value.castTag(.function)) |func_payload| {
4149 try p9.seeDecl(func_payload.data.owner_decl);
4150 const ptr_bits = self.target.cpu.arch.ptrBitWidth();
4151 const ptr_bytes: u64 = @divExact(ptr_bits, 8);
4152 const got_addr = p9.bases.data;
4153 const got_index = mod.declPtr(func_payload.data.owner_decl).link.plan9.got_index.?;
4154 const fn_got_addr = got_addr + got_index * ptr_bytes;
4155 _ = try self.addInst(.{
4156 .tag = .call,
4157 .ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }),
4158 .data = .{ .imm = @intCast(u32, fn_got_addr) },
4159 });
4160 } else return self.fail("TODO implement calling extern fn on plan9", .{});
4161 } else {
4162 assert(ty.zigTypeTag() == .Pointer);
4163 const mcv = try self.resolveInst(callee);
4164 try self.genSetReg(Type.initTag(.usize), .rax, mcv);
4165 _ = try self.addInst(.{
4166 .tag = .call,
4167 .ops = Mir.Inst.Ops.encode(.{
4168 .reg1 = .rax,
4169 .flags = 0b01,
4170 }),
4171 .data = undefined,
4172 });
4099 return self.fail("TODO implement calling bitcasted functions", .{});
41734100 }
4174 } else unreachable;
4101 } else {
4102 assert(ty.zigTypeTag() == .Pointer);
4103 const mcv = try self.resolveInst(callee);
4104 try self.genSetReg(Type.initTag(.usize), .rax, mcv);
4105 _ = try self.addInst(.{
4106 .tag = .call,
4107 .ops = Mir.Inst.Ops.encode(.{
4108 .reg1 = .rax,
4109 .flags = 0b01,
4110 }),
4111 .data = undefined,
4112 });
4113 }
41754114
41764115 if (info.stack_byte_count > 0) {
41774116 // Readjust the stack