authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-01-08 23:16:50+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-01-13 14:51:23-08:00
log5487dd13ea23ad7e547995b9a088ba37bfe17737
treed1bc46aed5d4db149d32cb4fca0406f86f1f1790
parenta021c7b1b2428ecda85e79e281d43fa1c92f8c94

stage2: lay the groundwork in prep for extern fn

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,6 +22,7 @@ const ast = std.zig.ast;
22const trace = @import("tracy.zig").trace;22const trace = @import("tracy.zig").trace;
23const astgen = @import("astgen.zig");23const astgen = @import("astgen.zig");
24const zir_sema = @import("zir_sema.zig");24const zir_sema = @import("zir_sema.zig");
25const target_util = @import("target.zig");
2526
26const default_eval_branch_quota = 1000;27const default_eval_branch_quota = 1000;
2728
...@@ -1109,8 +1110,48 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {...@@ -1109,8 +1110,48 @@ fn astGenAndAnalyzeDecl(self: *Module, decl: *Decl) !bool {
1109 if (fn_proto.getVarArgsToken()) |var_args_token| {1110 if (fn_proto.getVarArgsToken()) |var_args_token| {
1110 return self.failTok(&fn_type_scope.base, var_args_token, "TODO implement var args", .{});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 if (fn_proto.getLibName()) |lib_name| blk: {
1113 return self.failNode(&fn_type_scope.base, lib_name, "TODO implement function library name", .{});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 if (fn_proto.getAlignExpr()) |align_expr| {1156 if (fn_proto.getAlignExpr()) |align_expr| {
1116 return self.failNode(&fn_type_scope.base, align_expr, "TODO implement function align expression", .{});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,6 +1602,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1602 try self.code.ensureCapacity(self.code.items.len + 7);1602 try self.code.ensureCapacity(self.code.items.len + 7);
1603 self.code.appendSliceAssumeCapacity(&[3]u8{ 0xff, 0x14, 0x25 });1603 self.code.appendSliceAssumeCapacity(&[3]u8{ 0xff, 0x14, 0x25 });
1604 mem.writeIntLittle(u32, self.code.addManyAsArrayAssumeCapacity(4), got_addr);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 } else {1607 } else {
1606 return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{});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,6 +1630,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
16281630
1629 try self.genSetReg(inst.base.src, .ra, .{ .memory = got_addr });1631 try self.genSetReg(inst.base.src, .ra, .{ .memory = got_addr });
1630 mem.writeIntLittle(u32, try self.code.addManyAsArray(4), Instruction.jalr(.ra, 0, .ra).toU32());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 } else {1635 } else {
1632 return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{});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,6 +1676,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1672 else => return self.fail(inst.base.src, "TODO implement fn call with non-void return value", .{}),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 } else {1681 } else {
1676 return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{});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,6 +1739,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1733 writeInt(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, .lr, Instruction.Operand.reg(.pc, Instruction.Operand.Shift.none)).toU32());1739 writeInt(u32, try self.code.addManyAsArray(4), Instruction.mov(.al, .lr, Instruction.Operand.reg(.pc, Instruction.Operand.Shift.none)).toU32());
1734 writeInt(u32, try self.code.addManyAsArray(4), Instruction.bx(.al, .lr).toU32());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 } else {1744 } else {
1737 return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{});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,6 +1795,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1787 try self.genSetReg(inst.base.src, .x30, .{ .memory = got_addr });1795 try self.genSetReg(inst.base.src, .x30, .{ .memory = got_addr });
17881796
1789 writeInt(u32, try self.code.addManyAsArray(4), Instruction.blr(.x30).toU32());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 } else {1800 } else {
1791 return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{});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,6 +1859,8 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
1849 },1859 },
1850 else => unreachable, // unsupported architecture on MachO1860 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 } else {1864 } else {
1853 return self.fail(inst.base.src, "TODO implement calling bitcasted functions", .{});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,10 +662,14 @@ pub fn updateDecl(self: *Coff, module: *Module, decl: *Module.Decl) !void {
662 if (build_options.have_llvm)662 if (build_options.have_llvm)
663 if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.updateDecl(module, decl);663 if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.updateDecl(module, decl);
664664
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 var code_buffer = std.ArrayList(u8).init(self.base.allocator);670 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
666 defer code_buffer.deinit();671 defer code_buffer.deinit();
667672
668 const typed_value = decl.typed_value.most_recent.typed_value;
669 const res = try codegen.generateSymbol(&self.base, decl.src(), typed_value, &code_buffer, .none);673 const res = try codegen.generateSymbol(&self.base, decl.src(), typed_value, &code_buffer, .none);
670 const code = switch (res) {674 const code = switch (res) {
671 .externally_managed => |x| x,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,6 +2157,11 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
2157 if (build_options.have_llvm)2157 if (build_options.have_llvm)
2158 if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.updateDecl(module, decl);2158 if (self.llvm_ir_module) |llvm_ir_module| return try llvm_ir_module.updateDecl(module, decl);
21592159
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 var code_buffer = std.ArrayList(u8).init(self.base.allocator);2165 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
2161 defer code_buffer.deinit();2166 defer code_buffer.deinit();
21622167
...@@ -2175,7 +2180,6 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {...@@ -2175,7 +2180,6 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
2175 dbg_info_type_relocs.deinit(self.base.allocator);2180 dbg_info_type_relocs.deinit(self.base.allocator);
2176 }2181 }
21772182
2178 const typed_value = decl.typed_value.most_recent.typed_value;
2179 const is_fn: bool = switch (typed_value.ty.zigTypeTag()) {2183 const is_fn: bool = switch (typed_value.ty.zigTypeTag()) {
2180 .Fn => true,2184 .Fn => true,
2181 else => false,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,6 +1118,11 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1118 const tracy = trace(@src());1118 const tracy = trace(@src());
1119 defer tracy.end();1119 defer tracy.end();
11201120
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 var code_buffer = std.ArrayList(u8).init(self.base.allocator);1126 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
1122 defer code_buffer.deinit();1127 defer code_buffer.deinit();
11231128
...@@ -1134,7 +1139,6 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {...@@ -1134,7 +1139,6 @@ pub fn updateDecl(self: *MachO, module: *Module, decl: *Module.Decl) !void {
1134 }1139 }
1135 }1140 }
11361141
1137 const typed_value = decl.typed_value.most_recent.typed_value;
1138 const res = if (debug_buffers) |*dbg|1142 const res = if (debug_buffers) |*dbg|
1139 try codegen.generateSymbol(&self.base, decl.src(), typed_value, &code_buffer, .{1143 try codegen.generateSymbol(&self.base, decl.src(), typed_value, &code_buffer, .{
1140 .dwarf = .{1144 .dwarf = .{
src/link/Wasm.zig+4-1
...@@ -100,8 +100,11 @@ pub fn deinit(self: *Wasm) void {...@@ -100,8 +100,11 @@ pub fn deinit(self: *Wasm) void {
100// Generate code for the Decl, storing it in memory to be later written to100// Generate code for the Decl, storing it in memory to be later written to
101// the file on flush().101// the file on flush().
102pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {102pub 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 return error.TODOImplementNonFnDeclsForWasm;105 return error.TODOImplementNonFnDeclsForWasm;
106 if (typed_value.val.tag() == .extern_fn)
107 return error.TODOImplementExternFnDeclsForWasm;
105108
106 if (decl.fn_link.wasm) |*fn_data| {109 if (decl.fn_link.wasm) |*fn_data| {
107 fn_data.functype.items.len = 0;110 fn_data.functype.items.len = 0;