| author | |
| committer | |
| log | 5487dd13ea23ad7e547995b9a088ba37bfe17737 |
| tree | d1bc46aed5d4db149d32cb4fca0406f86f1f1790 |
| parent | a021c7b1b2428ecda85e79e281d43fa1c92f8c94 |
This commit lays the groundwork in preparation for implementing
handling of extern functions in various backends.6 files changed, 74 insertions(+), 6 deletions(-)
src/Module.zig+43-2| ... | ... | @@ -22,6 +22,7 @@ const ast = std.zig.ast; |
| 22 | 22 | const trace = @import("tracy.zig").trace; |
| 23 | 23 | const astgen = @import("astgen.zig"); |
| 24 | 24 | const zir_sema = @import("zir_sema.zig"); |
| 25 | const target_util = @import("target.zig"); | |
| 25 | 26 | |
| 26 | 27 | const default_eval_branch_quota = 1000; |
| 27 | 28 | |
| ... | ... | @@ -1109,8 +1110,48 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool { |
| 1109 | 1110 | if (fn_proto.getVarArgsToken()) |var_args_token| { |
| 1110 | 1111 | return self.failTok(&fn_type_scope.base, var_args_token, "TODO implement var args", .{}); |
| 1111 | 1112 | } |
| 1112 | if (fn_proto.getLibName()) |lib_name| { | |
| 1113 | return self.failNode(&fn_type_scope.base, lib_name, "TODO implement function library name", .{}); | |
| 1113 | if (fn_proto.getLibName()) |lib_name| blk: { | |
| 1114 | const lib_name_str = mem.trim(u8, tree.tokenSlice(lib_name.firstToken()), "\""); // TODO: call identifierTokenString | |
| 1115 | log.debug("extern fn symbol expected in lib '{s}'", .{lib_name_str}); | |
| 1116 | const target = self.comp.getTarget(); | |
| 1117 | if (target_util.is_libc_lib_name(target, lib_name_str)) { | |
| 1118 | if (!self.comp.bin_file.options.link_libc) { | |
| 1119 | return self.failNode( | |
| 1120 | &fn_type_scope.base, | |
| 1121 | lib_name, | |
| 1122 | "dependency on libc must be explicitly specified in the build command", | |
| 1123 | .{}, | |
| 1124 | ); | |
| 1125 | } | |
| 1126 | break :blk; | |
| 1127 | } | |
| 1128 | if (target_util.is_libcpp_lib_name(target, lib_name_str)) { | |
| 1129 | if (!self.comp.bin_file.options.link_libcpp) { | |
| 1130 | return self.failNode( | |
| 1131 | &fn_type_scope.base, | |
| 1132 | lib_name, | |
| 1133 | "dependency on libc++ must be explicitly specified in the build command", | |
| 1134 | .{}, | |
| 1135 | ); | |
| 1136 | } | |
| 1137 | break :blk; | |
| 1138 | } | |
| 1139 | if (!target.isWasm() and !self.comp.bin_file.options.pic) { | |
| 1140 | return self.failNode( | |
| 1141 | &fn_type_scope.base, | |
| 1142 | lib_name, | |
| 1143 | "dependency on dynamic library '{s}' requires enabling Position Independent Code. Fixed by `-l{s}` or `-fPIC`.", | |
| 1144 | .{ lib_name, lib_name }, | |
| 1145 | ); | |
| 1146 | } | |
| 1147 | self.comp.stage1AddLinkLib(lib_name_str) catch |err| { | |
| 1148 | return self.failNode( | |
| 1149 | &fn_type_scope.base, | |
| 1150 | lib_name, | |
| 1151 | "unable to add link lib '{s}': {s}", | |
| 1152 | .{ lib_name, @errorName(err) }, | |
| 1153 | ); | |
| 1154 | }; | |
| 1114 | 1155 | } |
| 1115 | 1156 | if (fn_proto.getAlignExpr()) |align_expr| { |
| 1116 | 1157 | return self.failNode(&fn_type_scope.base, align_expr, "TODO implement function align expression", .{}); |
src/codegen.zig+12| ... | ... | @@ -1602,6 +1602,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1602 | 1602 | try self.code.ensureCapacity(self.code.items.len + 7); |
| 1603 | 1603 | self.code.appendSliceAssumeCapacity(&[3]u8{ 0xff, 0x14, 0x25 }); |
| 1604 | 1604 | mem.writeIntLittle(u32, self.code.addManyAsArrayAssumeCapacity(4), got_addr); |
| 1605 | } else if (func_value.castTag(.extern_fn)) |_| { | |
| 1606 | return self.fail(inst.base.src, "TODO implement calling extern functions", .{}); | |
| 1605 | 1607 | } else { |
| 1606 | 1608 | return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{}); |
| 1607 | 1609 | } |
| ... | ... | @@ -1628,6 +1630,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1628 | 1630 | |
| 1629 | 1631 | try self.genSetReg(inst.base.src, .ra, .{ .memory = got_addr }); |
| 1630 | 1632 | mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.jalr(.ra, 0, .ra).toU32()); |
| 1633 | } else if (func_value.castTag(.extern_fn)) |_| { | |
| 1634 | return self.fail(inst.base.src, "TODO implement calling extern functions", .{}); | |
| 1631 | 1635 | } else { |
| 1632 | 1636 | return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{}); |
| 1633 | 1637 | } |
| ... | ... | @@ -1672,6 +1676,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1672 | 1676 | else => return self.fail(inst.base.src, "TODO implement fn call with non-void return value", .{}), |
| 1673 | 1677 | } |
| 1674 | 1678 | } |
| 1679 | } else if (func_value.castTag(.extern_fn)) |_| { | |
| 1680 | return self.fail(inst.base.src, "TODO implement calling extern functions", .{}); | |
| 1675 | 1681 | } else { |
| 1676 | 1682 | return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{}); |
| 1677 | 1683 | } |
| ... | ... | @@ -1733,6 +1739,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1733 | 1739 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, .lr, Instruction.Operand.reg(.pc, Instruction.Operand.Shift.none)).toU32()); |
| 1734 | 1740 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.bx(.al, .lr).toU32()); |
| 1735 | 1741 | } |
| 1742 | } else if (func_value.castTag(.extern_fn)) |_| { | |
| 1743 | return self.fail(inst.base.src, "TODO implement calling extern functions", .{}); | |
| 1736 | 1744 | } else { |
| 1737 | 1745 | return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{}); |
| 1738 | 1746 | } |
| ... | ... | @@ -1787,6 +1795,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1787 | 1795 | try self.genSetReg(inst.base.src, .x30, .{ .memory = got_addr }); |
| 1788 | 1796 | |
| 1789 | 1797 | writeInt(u32, try self.code.addManyAsArray(4), Instruction.blr(.x30).toU32()); |
| 1798 | } else if (func_value.castTag(.extern_fn)) |_| { | |
| 1799 | return self.fail(inst.base.src, "TODO implement calling extern functions", .{}); | |
| 1790 | 1800 | } else { |
| 1791 | 1801 | return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{}); |
| 1792 | 1802 | } |
| ... | ... | @@ -1849,6 +1859,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type { |
| 1849 | 1859 | }, |
| 1850 | 1860 | else => unreachable, // unsupported architecture on MachO |
| 1851 | 1861 | } |
| 1862 | } else if (func_value.castTag(.extern_fn)) |_| { | |
| 1863 | return self.fail(inst.base.src, "TODO implement calling extern functions", .{}); | |
| 1852 | 1864 | } else { |
| 1853 | 1865 | return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{}); |
| 1854 | 1866 | } |
src/link/Coff.zig+5-1| ... | ... | @@ -662,10 +662,14 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void { |
| 662 | 662 | if (build_options.have_llvm) |
| 663 | 663 | if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.updateDecl(module, decl); |
| 664 | 664 | |
| 665 | const typed_value = decl.typed_value.most_recent.typed_value; | |
| 666 | if (typed_value.val.tag() == .extern_fn) { | |
| 667 | return; // TODO Should we do more when front-end analyzed extern decl? | |
| 668 | } | |
| 669 | ||
| 665 | 670 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 666 | 671 | defer code_buffer.deinit(); |
| 667 | 672 | |
| 668 | const typed_value = decl.typed_value.most_recent.typed_value; | |
| 669 | 673 | const res = try codegen.generateSymbol(&self.base, decl.src(), typed_value, &code_buffer, .none); |
| 670 | 674 | const code = switch (res) { |
| 671 | 675 | .externally_managed => |x| x, |
src/link/Elf.zig+5-1| ... | ... | @@ -2157,6 +2157,11 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { |
| 2157 | 2157 | if (build_options.have_llvm) |
| 2158 | 2158 | if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.updateDecl(module, decl); |
| 2159 | 2159 | |
| 2160 | const typed_value = decl.typed_value.most_recent.typed_value; | |
| 2161 | if (typed_value.val.tag() == .extern_fn) { | |
| 2162 | return; // TODO Should we do more when front-end analyzed extern decl? | |
| 2163 | } | |
| 2164 | ||
| 2160 | 2165 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 2161 | 2166 | defer code_buffer.deinit(); |
| 2162 | 2167 | |
| ... | ... | @@ -2175,7 +2180,6 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { |
| 2175 | 2180 | dbg_info_type_relocs.deinit(self.base.allocator); |
| 2176 | 2181 | } |
| 2177 | 2182 | |
| 2178 | const typed_value = decl.typed_value.most_recent.typed_value; | |
| 2179 | 2183 | const is_fn: bool = switch (typed_value.ty.zigTypeTag()) { |
| 2180 | 2184 | .Fn => true, |
| 2181 | 2185 | else => false, |
src/link/MachO.zig+5-1| ... | ... | @@ -1118,6 +1118,11 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 1118 | 1118 | const tracy = trace(@src()); |
| 1119 | 1119 | defer tracy.end(); |
| 1120 | 1120 | |
| 1121 | const typed_value = decl.typed_value.most_recent.typed_value; | |
| 1122 | if (typed_value.val.tag() == .extern_fn) { | |
| 1123 | return; // TODO Should we do more when front-end analyzed extern decl? | |
| 1124 | } | |
| 1125 | ||
| 1121 | 1126 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 1122 | 1127 | defer code_buffer.deinit(); |
| 1123 | 1128 | |
| ... | ... | @@ -1134,7 +1139,6 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void { |
| 1134 | 1139 | } |
| 1135 | 1140 | } |
| 1136 | 1141 | |
| 1137 | const typed_value = decl.typed_value.most_recent.typed_value; | |
| 1138 | 1142 | const res = if (debug_buffers) |*dbg| |
| 1139 | 1143 | try codegen.generateSymbol(&self.base, decl.src(), typed_value, &code_buffer, .{ |
| 1140 | 1144 | .dwarf = .{ |
src/link/Wasm.zig+4-1| ... | ... | @@ -100,8 +100,11 @@ pub fn deinit(self: *Wasm) void { |
| 100 | 100 | // Generate code for the Decl, storing it in memory to be later written to |
| 101 | 101 | // the file on flush(). |
| 102 | 102 | pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void { |
| 103 | if (decl.typed_value.most_recent.typed_value.ty.zigTypeTag() != .Fn) | |
| 103 | const typed_value = decl.typed_value.most_recent.typed_value; | |
| 104 | if (typed_value.ty.zigTypeTag() != .Fn) | |
| 104 | 105 | return error.TODOImplementNonFnDeclsForWasm; |
| 106 | if (typed_value.val.tag() == .extern_fn) | |
| 107 | return error.TODOImplementExternFnDeclsForWasm; | |
| 105 | 108 | |
| 106 | 109 | if (decl.fn_link.wasm) |*fn_data| { |
| 107 | 110 | fn_data.functype.items.len = 0; |