mirror of
https://github.com/ziglang/zig.git
synced 2025-12-25 15:43:06 +00:00
self-hosted: clean up calling logic for x86_64 and aarch64 across linkers
This commit is contained in:
parent
4d804c1b23
commit
041bc71bc8
@ -4302,32 +4302,19 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||
// on linking.
|
||||
const mod = self.bin_file.options.module.?;
|
||||
if (self.air.value(callee)) |func_value| {
|
||||
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
|
||||
if (func_value.castTag(.function)) |func_payload| {
|
||||
const func = func_payload.data;
|
||||
if (func_value.castTag(.function)) |func_payload| {
|
||||
const func = func_payload.data;
|
||||
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
||||
|
||||
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
|
||||
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
|
||||
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
|
||||
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
||||
const got_addr = blk: {
|
||||
const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
|
||||
break :blk @intCast(u32, got.p_vaddr + fn_owner_decl.link.elf.offset_table_index * ptr_bytes);
|
||||
};
|
||||
|
||||
try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = got_addr });
|
||||
|
||||
_ = try self.addInst(.{
|
||||
.tag = .blr,
|
||||
.data = .{ .reg = .x30 },
|
||||
});
|
||||
} else if (func_value.castTag(.extern_fn)) |_| {
|
||||
return self.fail("TODO implement calling extern functions", .{});
|
||||
} else {
|
||||
return self.fail("TODO implement calling bitcasted functions", .{});
|
||||
}
|
||||
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
if (func_value.castTag(.function)) |func_payload| {
|
||||
const func = func_payload.data;
|
||||
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
||||
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
try fn_owner_decl.link.macho.ensureInitialized(macho_file);
|
||||
try self.genSetReg(Type.initTag(.u64), .x30, .{
|
||||
.linker_load = .{
|
||||
@ -4335,22 +4322,39 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||
.sym_index = fn_owner_decl.link.macho.getSymbolIndex().?,
|
||||
},
|
||||
});
|
||||
// blr x30
|
||||
_ = try self.addInst(.{
|
||||
.tag = .blr,
|
||||
.data = .{ .reg = .x30 },
|
||||
} else if (self.bin_file.cast(link.File.Coff)) |_| {
|
||||
try self.genSetReg(Type.initTag(.u64), .x30, .{
|
||||
.linker_load = .{
|
||||
.type = .got,
|
||||
.sym_index = fn_owner_decl.link.coff.sym_index,
|
||||
},
|
||||
});
|
||||
} else if (func_value.castTag(.extern_fn)) |func_payload| {
|
||||
const extern_fn = func_payload.data;
|
||||
const decl_name = mod.declPtr(extern_fn.owner_decl).name;
|
||||
if (extern_fn.lib_name) |lib_name| {
|
||||
log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{
|
||||
decl_name,
|
||||
lib_name,
|
||||
});
|
||||
}
|
||||
const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
|
||||
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
|
||||
try p9.seeDecl(func.owner_decl);
|
||||
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
|
||||
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
|
||||
const got_addr = p9.bases.data;
|
||||
const got_index = fn_owner_decl.link.plan9.got_index.?;
|
||||
const fn_got_addr = got_addr + got_index * ptr_bytes;
|
||||
try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = fn_got_addr });
|
||||
} else unreachable;
|
||||
|
||||
_ = try self.addInst(.{
|
||||
.tag = .blr,
|
||||
.data = .{ .reg = .x30 },
|
||||
});
|
||||
} else if (func_value.castTag(.extern_fn)) |func_payload| {
|
||||
const extern_fn = func_payload.data;
|
||||
const decl_name = mod.declPtr(extern_fn.owner_decl).name;
|
||||
if (extern_fn.lib_name) |lib_name| {
|
||||
log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{
|
||||
decl_name,
|
||||
lib_name,
|
||||
});
|
||||
}
|
||||
|
||||
if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
|
||||
_ = try self.addInst(.{
|
||||
.tag = .call_extern,
|
||||
.data = .{
|
||||
@ -4360,33 +4364,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||
},
|
||||
},
|
||||
});
|
||||
} else {
|
||||
return self.fail("TODO implement calling bitcasted functions", .{});
|
||||
}
|
||||
} else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
|
||||
if (func_value.castTag(.function)) |func_payload| {
|
||||
const func = func_payload.data;
|
||||
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
||||
try self.genSetReg(Type.initTag(.u64), .x30, .{
|
||||
.linker_load = .{
|
||||
.type = .got,
|
||||
.sym_index = fn_owner_decl.link.coff.sym_index,
|
||||
},
|
||||
});
|
||||
// blr x30
|
||||
_ = try self.addInst(.{
|
||||
.tag = .blr,
|
||||
.data = .{ .reg = .x30 },
|
||||
});
|
||||
} else if (func_value.castTag(.extern_fn)) |func_payload| {
|
||||
const extern_fn = func_payload.data;
|
||||
const decl_name = mod.declPtr(extern_fn.owner_decl).name;
|
||||
if (extern_fn.lib_name) |lib_name| {
|
||||
log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{
|
||||
decl_name,
|
||||
lib_name,
|
||||
});
|
||||
}
|
||||
} else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
|
||||
const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
|
||||
try self.genSetReg(Type.initTag(.u64), .x30, .{
|
||||
.linker_load = .{
|
||||
@ -4394,35 +4372,16 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||
.sym_index = sym_index,
|
||||
},
|
||||
});
|
||||
// blr x30
|
||||
_ = try self.addInst(.{
|
||||
.tag = .blr,
|
||||
.data = .{ .reg = .x30 },
|
||||
});
|
||||
} else {
|
||||
return self.fail("TODO implement calling bitcasted functions", .{});
|
||||
}
|
||||
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
|
||||
if (func_value.castTag(.function)) |func_payload| {
|
||||
try p9.seeDecl(func_payload.data.owner_decl);
|
||||
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
|
||||
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
|
||||
const got_addr = p9.bases.data;
|
||||
const got_index = mod.declPtr(func_payload.data.owner_decl).link.plan9.got_index.?;
|
||||
const fn_got_addr = got_addr + got_index * ptr_bytes;
|
||||
|
||||
try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = fn_got_addr });
|
||||
|
||||
_ = try self.addInst(.{
|
||||
.tag = .blr,
|
||||
.data = .{ .reg = .x30 },
|
||||
});
|
||||
} else if (func_value.castTag(.extern_fn)) |_| {
|
||||
return self.fail("TODO implement calling extern functions", .{});
|
||||
} else {
|
||||
return self.fail("TODO implement calling bitcasted functions", .{});
|
||||
}
|
||||
} else unreachable;
|
||||
} else {
|
||||
return self.fail("TODO implement calling bitcasted functions", .{});
|
||||
}
|
||||
} else {
|
||||
assert(ty.zigTypeTag() == .Pointer);
|
||||
const mcv = try self.resolveInst(callee);
|
||||
|
||||
@ -3992,13 +3992,14 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||
// Due to incremental compilation, how function calls are generated depends
|
||||
// on linking.
|
||||
const mod = self.bin_file.options.module.?;
|
||||
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
|
||||
if (self.air.value(callee)) |func_value| {
|
||||
if (func_value.castTag(.function)) |func_payload| {
|
||||
const func = func_payload.data;
|
||||
if (self.air.value(callee)) |func_value| {
|
||||
if (func_value.castTag(.function)) |func_payload| {
|
||||
const func = func_payload.data;
|
||||
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
||||
|
||||
if (self.bin_file.cast(link.File.Elf)) |elf_file| {
|
||||
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
|
||||
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
|
||||
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
||||
const got_addr = blk: {
|
||||
const got = &elf_file.program_headers.items[elf_file.phdr_got_index.?];
|
||||
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
|
||||
.ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }),
|
||||
.data = .{ .imm = @truncate(u32, got_addr) },
|
||||
});
|
||||
} else if (func_value.castTag(.extern_fn)) |_| {
|
||||
return self.fail("TODO implement calling extern functions", .{});
|
||||
} else {
|
||||
return self.fail("TODO implement calling bitcasted functions", .{});
|
||||
}
|
||||
} else {
|
||||
assert(ty.zigTypeTag() == .Pointer);
|
||||
const mcv = try self.resolveInst(callee);
|
||||
try self.genSetReg(Type.initTag(.usize), .rax, mcv);
|
||||
_ = try self.addInst(.{
|
||||
.tag = .call,
|
||||
.ops = Mir.Inst.Ops.encode(.{
|
||||
.reg1 = .rax,
|
||||
.flags = 0b01,
|
||||
}),
|
||||
.data = undefined,
|
||||
});
|
||||
}
|
||||
} else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
|
||||
if (self.air.value(callee)) |func_value| {
|
||||
if (func_value.castTag(.function)) |func_payload| {
|
||||
const func = func_payload.data;
|
||||
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
||||
} else if (self.bin_file.cast(link.File.Coff)) |_| {
|
||||
try self.genSetReg(Type.initTag(.usize), .rax, .{
|
||||
.linker_load = .{
|
||||
.type = .got,
|
||||
@ -4045,15 +4024,47 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||
}),
|
||||
.data = undefined,
|
||||
});
|
||||
} else if (func_value.castTag(.extern_fn)) |func_payload| {
|
||||
const extern_fn = func_payload.data;
|
||||
const decl_name = mod.declPtr(extern_fn.owner_decl).name;
|
||||
if (extern_fn.lib_name) |lib_name| {
|
||||
log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{
|
||||
decl_name,
|
||||
lib_name,
|
||||
});
|
||||
}
|
||||
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
try fn_owner_decl.link.macho.ensureInitialized(macho_file);
|
||||
const sym_index = fn_owner_decl.link.macho.getSymbolIndex().?;
|
||||
try self.genSetReg(Type.initTag(.usize), .rax, .{
|
||||
.linker_load = .{
|
||||
.type = .got,
|
||||
.sym_index = sym_index,
|
||||
},
|
||||
});
|
||||
_ = try self.addInst(.{
|
||||
.tag = .call,
|
||||
.ops = Mir.Inst.Ops.encode(.{
|
||||
.reg1 = .rax,
|
||||
.flags = 0b01,
|
||||
}),
|
||||
.data = undefined,
|
||||
});
|
||||
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
|
||||
try p9.seeDecl(func.owner_decl);
|
||||
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
|
||||
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
|
||||
const got_addr = p9.bases.data;
|
||||
const got_index = fn_owner_decl.link.plan9.got_index.?;
|
||||
const fn_got_addr = got_addr + got_index * ptr_bytes;
|
||||
_ = try self.addInst(.{
|
||||
.tag = .call,
|
||||
.ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }),
|
||||
.data = .{ .imm = @intCast(u32, fn_got_addr) },
|
||||
});
|
||||
} else unreachable;
|
||||
} else if (func_value.castTag(.extern_fn)) |func_payload| {
|
||||
const extern_fn = func_payload.data;
|
||||
const decl_name = mod.declPtr(extern_fn.owner_decl).name;
|
||||
if (extern_fn.lib_name) |lib_name| {
|
||||
log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{
|
||||
decl_name,
|
||||
lib_name,
|
||||
});
|
||||
}
|
||||
|
||||
if (self.bin_file.cast(link.File.Coff)) |coff_file| {
|
||||
const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
|
||||
try self.genSetReg(Type.initTag(.usize), .rax, .{
|
||||
.linker_load = .{
|
||||
@ -4069,53 +4080,7 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||
}),
|
||||
.data = undefined,
|
||||
});
|
||||
} else {
|
||||
return self.fail("TODO implement calling bitcasted functions", .{});
|
||||
}
|
||||
} else {
|
||||
assert(ty.zigTypeTag() == .Pointer);
|
||||
const mcv = try self.resolveInst(callee);
|
||||
try self.genSetReg(Type.initTag(.usize), .rax, mcv);
|
||||
_ = try self.addInst(.{
|
||||
.tag = .call,
|
||||
.ops = Mir.Inst.Ops.encode(.{
|
||||
.reg1 = .rax,
|
||||
.flags = 0b01,
|
||||
}),
|
||||
.data = undefined,
|
||||
});
|
||||
}
|
||||
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
if (self.air.value(callee)) |func_value| {
|
||||
if (func_value.castTag(.function)) |func_payload| {
|
||||
const func = func_payload.data;
|
||||
const fn_owner_decl = mod.declPtr(func.owner_decl);
|
||||
try fn_owner_decl.link.macho.ensureInitialized(macho_file);
|
||||
const sym_index = fn_owner_decl.link.macho.getSymbolIndex().?;
|
||||
try self.genSetReg(Type.initTag(.usize), .rax, .{
|
||||
.linker_load = .{
|
||||
.type = .got,
|
||||
.sym_index = sym_index,
|
||||
},
|
||||
});
|
||||
// callq *%rax
|
||||
_ = try self.addInst(.{
|
||||
.tag = .call,
|
||||
.ops = Mir.Inst.Ops.encode(.{
|
||||
.reg1 = .rax,
|
||||
.flags = 0b01,
|
||||
}),
|
||||
.data = undefined,
|
||||
});
|
||||
} else if (func_value.castTag(.extern_fn)) |func_payload| {
|
||||
const extern_fn = func_payload.data;
|
||||
const decl_name = mod.declPtr(extern_fn.owner_decl).name;
|
||||
if (extern_fn.lib_name) |lib_name| {
|
||||
log.debug("TODO enforce that '{s}' is expected in '{s}' library", .{
|
||||
decl_name,
|
||||
lib_name,
|
||||
});
|
||||
}
|
||||
} else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
|
||||
const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
|
||||
_ = try self.addInst(.{
|
||||
.tag = .call_extern,
|
||||
@ -4128,50 +4093,24 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
|
||||
},
|
||||
});
|
||||
} else {
|
||||
return self.fail("TODO implement calling bitcasted functions", .{});
|
||||
return self.fail("TODO implement calling extern functions", .{});
|
||||
}
|
||||
} else {
|
||||
assert(ty.zigTypeTag() == .Pointer);
|
||||
const mcv = try self.resolveInst(callee);
|
||||
try self.genSetReg(Type.initTag(.usize), .rax, mcv);
|
||||
_ = try self.addInst(.{
|
||||
.tag = .call,
|
||||
.ops = Mir.Inst.Ops.encode(.{
|
||||
.reg1 = .rax,
|
||||
.flags = 0b01,
|
||||
}),
|
||||
.data = undefined,
|
||||
});
|
||||
return self.fail("TODO implement calling bitcasted functions", .{});
|
||||
}
|
||||
} else if (self.bin_file.cast(link.File.Plan9)) |p9| {
|
||||
if (self.air.value(callee)) |func_value| {
|
||||
if (func_value.castTag(.function)) |func_payload| {
|
||||
try p9.seeDecl(func_payload.data.owner_decl);
|
||||
const ptr_bits = self.target.cpu.arch.ptrBitWidth();
|
||||
const ptr_bytes: u64 = @divExact(ptr_bits, 8);
|
||||
const got_addr = p9.bases.data;
|
||||
const got_index = mod.declPtr(func_payload.data.owner_decl).link.plan9.got_index.?;
|
||||
const fn_got_addr = got_addr + got_index * ptr_bytes;
|
||||
_ = try self.addInst(.{
|
||||
.tag = .call,
|
||||
.ops = Mir.Inst.Ops.encode(.{ .flags = 0b01 }),
|
||||
.data = .{ .imm = @intCast(u32, fn_got_addr) },
|
||||
});
|
||||
} else return self.fail("TODO implement calling extern fn on plan9", .{});
|
||||
} else {
|
||||
assert(ty.zigTypeTag() == .Pointer);
|
||||
const mcv = try self.resolveInst(callee);
|
||||
try self.genSetReg(Type.initTag(.usize), .rax, mcv);
|
||||
_ = try self.addInst(.{
|
||||
.tag = .call,
|
||||
.ops = Mir.Inst.Ops.encode(.{
|
||||
.reg1 = .rax,
|
||||
.flags = 0b01,
|
||||
}),
|
||||
.data = undefined,
|
||||
});
|
||||
}
|
||||
} else unreachable;
|
||||
} else {
|
||||
assert(ty.zigTypeTag() == .Pointer);
|
||||
const mcv = try self.resolveInst(callee);
|
||||
try self.genSetReg(Type.initTag(.usize), .rax, mcv);
|
||||
_ = try self.addInst(.{
|
||||
.tag = .call,
|
||||
.ops = Mir.Inst.Ops.encode(.{
|
||||
.reg1 = .rax,
|
||||
.flags = 0b01,
|
||||
}),
|
||||
.data = undefined,
|
||||
});
|
||||
}
|
||||
|
||||
if (info.stack_byte_count > 0) {
|
||||
// Readjust the stack
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user