Commit 041bc71bc8

Jakub Konka <kubkon@jakubkonka.com>
2023-01-25 23:17:13
self-hosted: clean up calling logic for x86_64 and aarch64 across linkers
1 parent 4d804c1
Changed files (2)
src
arch
aarch64
x86_64
src/arch/aarch64/CodeGen.zig
@@ -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);
src/arch/x86_64/CodeGen.zig
@@ -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,19 +4024,12 @@ 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,
-                    });
-                }
-                const sym_index = try coff_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
+            } 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 = .import,
+                        .type = .got,
                         .sym_index = sym_index,
                     },
                 });
@@ -4069,36 +4041,37 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
                     }),
                     .data = undefined,
                 });
-            } else {
-                return self.fail("TODO implement calling bitcasted functions", .{});
+            } 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,
+                });
             }
-        } 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().?;
+
+            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 = .{
-                        .type = .got,
+                        .type = .import,
                         .sym_index = sym_index,
                     },
                 });
-                // callq *%rax
                 _ = try self.addInst(.{
                     .tag = .call,
                     .ops = Mir.Inst.Ops.encode(.{
@@ -4107,15 +4080,7 @@ 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| {
                 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,
-            });
-        }
-    } 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,
-            });
+            return self.fail("TODO implement calling bitcasted functions", .{});
         }
-    } 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