authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-04 14:40:59-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-04 14:40:59-07:00
log7a27f0d80c5ce9d596b2b43699e131ab387e1317
tree8b0d7bb597244f9b8bdc03a87be62154a9706ad8
parent1f0fd643025d4508f84a236453168173290a01a0

Sema: restore the extern lib name functionality


3 files changed, 90 insertions(+), 133 deletions(-)

BRANCH_TODO-128
...@@ -55,132 +55,4 @@...@@ -55,132 +55,4 @@
55 natural alignment for fields and do not have any comptime fields. this55 natural alignment for fields and do not have any comptime fields. this
56 will save 16 bytes per struct field in the compilation.56 will save 16 bytes per struct field in the compilation.
5757
58pub fn analyzeNamespace(
59 mod: *Module,
60 namespace: *Scope.Namespace,
61 decls: []const ast.Node.Index,
62) InnerError!void {
63 for (decls) |decl_node| switch (node_tags[decl_node]) {
64 .@"comptime" => {
65 const name_index = mod.getNextAnonNameIndex();
66 const name = try std.fmt.allocPrint(mod.gpa, "__comptime_{d}", .{name_index});
67 defer mod.gpa.free(name);
68
69 const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));
70
71 const new_decl = try mod.createNewDecl(namespace, name, decl_node, name_hash, contents_hash);
72 namespace.decls.putAssumeCapacity(new_decl, {});
73 mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
74 },
75
76 // Container fields are handled in AstGen.
77 .container_field_init,
78 .container_field_align,
79 .container_field,
80 => continue,
81
82 .test_decl => {
83 if (mod.comp.bin_file.options.is_test) {
84 log.err("TODO: analyze test decl", .{});
85 }
86 },
87 .@"usingnamespace" => {
88 const name_index = mod.getNextAnonNameIndex();
89 const name = try std.fmt.allocPrint(mod.gpa, "__usingnamespace_{d}", .{name_index});
90 defer mod.gpa.free(name);
91
92 const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));
93
94 const new_decl = try mod.createNewDecl(namespace, name, decl_node, name_hash, contents_hash);
95 namespace.decls.putAssumeCapacity(new_decl, {});
96
97 mod.ensureDeclAnalyzed(new_decl) catch |err| switch (err) {
98 error.OutOfMemory => return error.OutOfMemory,
99 error.AnalysisFail => continue,
100 };
101 },
102 else => unreachable,
103 };
104}
105
106/// Trailing:
107/// 0. `EmitH` if `module.emit_h != null`.
108/// 1. A per-Decl link object. Represents the position of the code in the output file.
109/// This is populated regardless of semantic analysis and code generation.
110/// Depending on the target, will be one of:
111/// * Elf.TextBlock
112/// * Coff.TextBlock
113/// * MachO.TextBlock
114/// * C.DeclBlock
115/// * Wasm.DeclBlock
116/// * void
117/// 2. If it is a function, a per-Decl link function object. Represents the
118/// function in the linked output file, if the `Decl` is a function.
119/// This is stored here and not in `Fn` because `Decl` survives across updates but
120/// `Fn` does not. Depending on the target, will be one of:
121/// * Elf.SrcFn
122/// * Coff.SrcFn
123/// * MachO.SrcFn
124/// * C.FnBlock
125/// * Wasm.FnData
126/// * SpirV.FnData
127
128
129 extra_index += @boolToInt(has_align);
130 extra_index += @boolToInt(has_section);
131
132 /// Contains un-analyzed ZIR instructions generated from Zig source AST.
133 /// Even after we finish analysis, the ZIR is kept in memory, so that
134 /// comptime and inline function calls can happen.
135 /// Parameter names are stored here so that they may be referenced for debug info,
136 /// without having source code bytes loaded into memory.
137 /// The number of parameters is determined by referring to the type.
138 /// The first N elements of `extra` are indexes into `string_bytes` to
139 /// a null-terminated string.
140 /// This memory is managed with gpa, must be freed when the function is freed.
141 zir: Zir,
142
143
144 if (fn_proto.lib_name) |lib_name_token| blk: {
145 log.debug("extern fn symbol expected in lib '{s}'", .{lib_name_str});
146 mod.comp.stage1AddLinkLib(lib_name_str) catch |err| {
147 return mod.failTok(
148 &fn_type_scope.base,
149 lib_name_token,
150 "unable to add link lib '{s}': {s}",
151 .{ lib_name_str, @errorName(err) },
152 );
153 };
154 const target = mod.comp.getTarget();
155 if (target_util.is_libc_lib_name(target, lib_name_str)) {
156 if (!mod.comp.bin_file.options.link_libc) {
157 return mod.failTok(
158 &fn_type_scope.base,
159 lib_name_token,
160 "dependency on libc must be explicitly specified in the build command",
161 .{},
162 );
163 }
164 break :blk;
165 }
166 if (target_util.is_libcpp_lib_name(target, lib_name_str)) {
167 if (!mod.comp.bin_file.options.link_libcpp) {
168 return mod.failTok(
169 &fn_type_scope.base,
170 lib_name_token,
171 "dependency on libc++ must be explicitly specified in the build command",
172 .{},
173 );
174 }
175 break :blk;
176 }
177 if (!target.isWasm() and !mod.comp.bin_file.options.pic) {
178 return mod.failTok(
179 &fn_type_scope.base,
180 lib_name_token,
181 "dependency on dynamic library '{s}' requires enabling Position Independent Code. Fixed by `-l{s}` or `-fPIC`.",
182 .{ lib_name_str, lib_name_str },
183 );
184 }
185 }
18658
src/Module.zig+36
...@@ -1603,6 +1603,34 @@ pub const SrcLoc = struct {...@@ -1603,6 +1603,34 @@ pub const SrcLoc = struct {
1603 const token_starts = tree.tokens.items(.start);1603 const token_starts = tree.tokens.items(.start);
1604 return token_starts[tok_index];1604 return token_starts[tok_index];
1605 },1605 },
1606
1607 .node_offset_lib_name => |node_off| {
1608 const tree = try src_loc.file_scope.getTree(gpa);
1609 const node_datas = tree.nodes.items(.data);
1610 const node_tags = tree.nodes.items(.tag);
1611 const parent_node = src_loc.declRelativeToNodeIndex(node_off);
1612 var params: [1]ast.Node.Index = undefined;
1613 const full = switch (node_tags[parent_node]) {
1614 .fn_proto_simple => tree.fnProtoSimple(&params, parent_node),
1615 .fn_proto_multi => tree.fnProtoMulti(parent_node),
1616 .fn_proto_one => tree.fnProtoOne(&params, parent_node),
1617 .fn_proto => tree.fnProto(parent_node),
1618 .fn_decl => blk: {
1619 const fn_proto = node_datas[parent_node].lhs;
1620 break :blk switch (node_tags[fn_proto]) {
1621 .fn_proto_simple => tree.fnProtoSimple(&params, fn_proto),
1622 .fn_proto_multi => tree.fnProtoMulti(fn_proto),
1623 .fn_proto_one => tree.fnProtoOne(&params, fn_proto),
1624 .fn_proto => tree.fnProto(fn_proto),
1625 else => unreachable,
1626 };
1627 },
1628 else => unreachable,
1629 };
1630 const tok_index = full.lib_name.?;
1631 const token_starts = tree.tokens.items(.start);
1632 return token_starts[tok_index];
1633 },
1606 }1634 }
1607 }1635 }
1608};1636};
...@@ -1768,6 +1796,12 @@ pub const LazySrcLoc = union(enum) {...@@ -1768,6 +1796,12 @@ pub const LazySrcLoc = union(enum) {
1768 /// to the type expression.1796 /// to the type expression.
1769 /// The Decl is determined contextually.1797 /// The Decl is determined contextually.
1770 node_offset_anyframe_type: i32,1798 node_offset_anyframe_type: i32,
1799 /// The source location points to the string literal of `extern "foo"`, found
1800 /// by taking this AST node index offset from the containing
1801 /// Decl AST node, which points to a function prototype or variable declaration
1802 /// expression AST node. Next, navigate to the string literal of the `extern "foo"`.
1803 /// The Decl is determined contextually.
1804 node_offset_lib_name: i32,
17711805
1772 /// Upgrade to a `SrcLoc` based on the `Decl` or file in the provided scope.1806 /// Upgrade to a `SrcLoc` based on the `Decl` or file in the provided scope.
1773 pub fn toSrcLoc(lazy: LazySrcLoc, scope: *Scope) SrcLoc {1807 pub fn toSrcLoc(lazy: LazySrcLoc, scope: *Scope) SrcLoc {
...@@ -1808,6 +1842,7 @@ pub const LazySrcLoc = union(enum) {...@@ -1808,6 +1842,7 @@ pub const LazySrcLoc = union(enum) {
1808 .node_offset_fn_type_cc,1842 .node_offset_fn_type_cc,
1809 .node_offset_fn_type_ret_ty,1843 .node_offset_fn_type_ret_ty,
1810 .node_offset_anyframe_type,1844 .node_offset_anyframe_type,
1845 .node_offset_lib_name,
1811 => .{1846 => .{
1812 .file_scope = scope.getFileScope(),1847 .file_scope = scope.getFileScope(),
1813 .parent_decl_node = scope.srcDecl().?.src_node,1848 .parent_decl_node = scope.srcDecl().?.src_node,
...@@ -1855,6 +1890,7 @@ pub const LazySrcLoc = union(enum) {...@@ -1855,6 +1890,7 @@ pub const LazySrcLoc = union(enum) {
1855 .node_offset_fn_type_cc,1890 .node_offset_fn_type_cc,
1856 .node_offset_fn_type_ret_ty,1891 .node_offset_fn_type_ret_ty,
1857 .node_offset_anyframe_type,1892 .node_offset_anyframe_type,
1893 .node_offset_lib_name,
1858 => .{1894 => .{
1859 .file_scope = decl.getFileScope(),1895 .file_scope = decl.getFileScope(),
1860 .parent_decl_node = decl.src_node,1896 .parent_decl_node = decl.src_node,
src/Sema.zig+54-5
...@@ -63,6 +63,7 @@ const InnerError = Module.InnerError;...@@ -63,6 +63,7 @@ const InnerError = Module.InnerError;
63const Decl = Module.Decl;63const Decl = Module.Decl;
64const LazySrcLoc = Module.LazySrcLoc;64const LazySrcLoc = Module.LazySrcLoc;
65const RangeSet = @import("RangeSet.zig");65const RangeSet = @import("RangeSet.zig");
66const target_util = @import("target.zig");
6667
67pub fn analyzeFnBody(68pub fn analyzeFnBody(
68 sema: *Sema,69 sema: *Sema,
...@@ -2739,6 +2740,7 @@ fn zirFunc(...@@ -2739,6 +2740,7 @@ fn zirFunc(
2739 false,2740 false,
2740 inferred_error_set,2741 inferred_error_set,
2741 src_locs,2742 src_locs,
2743 null,
2742 );2744 );
2743}2745}
27442746
...@@ -2754,11 +2756,14 @@ fn funcCommon(...@@ -2754,11 +2756,14 @@ fn funcCommon(
2754 var_args: bool,2756 var_args: bool,
2755 inferred_error_set: bool,2757 inferred_error_set: bool,
2756 src_locs: Zir.Inst.Func.SrcLocs,2758 src_locs: Zir.Inst.Func.SrcLocs,
2759 opt_lib_name: ?[]const u8,
2757) InnerError!*Inst {2760) InnerError!*Inst {
2758 const src: LazySrcLoc = .{ .node_offset = src_node_offset };2761 const src: LazySrcLoc = .{ .node_offset = src_node_offset };
2759 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };2762 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
2760 const return_type = try sema.resolveType(block, ret_ty_src, zir_return_type);2763 const return_type = try sema.resolveType(block, ret_ty_src, zir_return_type);
27612764
2765 const mod = sema.mod;
2766
2762 const fn_ty: Type = fn_ty: {2767 const fn_ty: Type = fn_ty: {
2763 // Hot path for some common function types.2768 // Hot path for some common function types.
2764 if (zir_param_types.len == 0 and !var_args and align_val.tag() == .null_value) {2769 if (zir_param_types.len == 0 and !var_args and align_val.tag() == .null_value) {
...@@ -2789,7 +2794,7 @@ fn funcCommon(...@@ -2789,7 +2794,7 @@ fn funcCommon(
2789 }2794 }
27902795
2791 if (align_val.tag() != .null_value) {2796 if (align_val.tag() != .null_value) {
2792 return sema.mod.fail(&block.base, src, "TODO implement support for function prototypes to have alignment specified", .{});2797 return mod.fail(&block.base, src, "TODO implement support for function prototypes to have alignment specified", .{});
2793 }2798 }
27942799
2795 break :fn_ty try Type.Tag.function.create(sema.arena, .{2800 break :fn_ty try Type.Tag.function.create(sema.arena, .{
...@@ -2801,7 +2806,48 @@ fn funcCommon(...@@ -2801,7 +2806,48 @@ fn funcCommon(
2801 };2806 };
28022807
2803 if (body_inst == 0) {2808 if (body_inst == 0) {
2804 return sema.mod.constType(sema.arena, src, fn_ty);2809 return mod.constType(sema.arena, src, fn_ty);
2810 }
2811
2812 if (opt_lib_name) |lib_name| blk: {
2813 const lib_name_src: LazySrcLoc = .{ .node_offset_lib_name = src_node_offset };
2814 log.debug("extern fn symbol expected in lib '{s}'", .{lib_name});
2815 mod.comp.stage1AddLinkLib(lib_name) catch |err| {
2816 return mod.fail(&block.base, lib_name_src, "unable to add link lib '{s}': {s}", .{
2817 lib_name, @errorName(err),
2818 });
2819 };
2820 const target = mod.getTarget();
2821 if (target_util.is_libc_lib_name(target, lib_name)) {
2822 if (!mod.comp.bin_file.options.link_libc) {
2823 return mod.fail(
2824 &block.base,
2825 lib_name_src,
2826 "dependency on libc must be explicitly specified in the build command",
2827 .{},
2828 );
2829 }
2830 break :blk;
2831 }
2832 if (target_util.is_libcpp_lib_name(target, lib_name)) {
2833 if (!mod.comp.bin_file.options.link_libcpp) {
2834 return mod.fail(
2835 &block.base,
2836 lib_name_src,
2837 "dependency on libc++ must be explicitly specified in the build command",
2838 .{},
2839 );
2840 }
2841 break :blk;
2842 }
2843 if (!target.isWasm() and !mod.comp.bin_file.options.pic) {
2844 return mod.fail(
2845 &block.base,
2846 lib_name_src,
2847 "dependency on dynamic library '{s}' requires enabling Position Independent Code. Fixed by `-l{s}` or `-fPIC`.",
2848 .{ lib_name, lib_name },
2849 );
2850 }
2805 }2851 }
28062852
2807 const is_inline = fn_ty.fnCallingConvention() == .Inline;2853 const is_inline = fn_ty.fnCallingConvention() == .Inline;
...@@ -5599,11 +5645,13 @@ fn zirFuncExtended(...@@ -5599,11 +5645,13 @@ fn zirFuncExtended(
5599 const small = @bitCast(Zir.Inst.ExtendedFunc.Small, extended.small);5645 const small = @bitCast(Zir.Inst.ExtendedFunc.Small, extended.small);
56005646
5601 var extra_index: usize = extra.end;5647 var extra_index: usize = extra.end;
5602 if (small.has_lib_name) {5648
5649 const lib_name: ?[]const u8 = if (small.has_lib_name) blk: {
5603 const lib_name = sema.code.nullTerminatedString(sema.code.extra[extra_index]);5650 const lib_name = sema.code.nullTerminatedString(sema.code.extra[extra_index]);
5604 extra_index += 1;5651 extra_index += 1;
5605 return sema.mod.fail(&block.base, src, "TODO: implement Sema func lib name", .{});5652 break :blk lib_name;
5606 }5653 } else null;
5654
5607 const cc: std.builtin.CallingConvention = if (small.has_cc) blk: {5655 const cc: std.builtin.CallingConvention = if (small.has_cc) blk: {
5608 const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);5656 const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
5609 extra_index += 1;5657 extra_index += 1;
...@@ -5640,6 +5688,7 @@ fn zirFuncExtended(...@@ -5640,6 +5688,7 @@ fn zirFuncExtended(
5640 small.is_var_args,5688 small.is_var_args,
5641 small.is_inferred_error,5689 small.is_inferred_error,
5642 src_locs,5690 src_locs,
5691 lib_name,
5643 );5692 );
5644}5693}
56455694