Commit 7a27f0d80c
Changed files (3)
src/Module.zig
@@ -1603,6 +1603,34 @@ pub const SrcLoc = struct {
const token_starts = tree.tokens.items(.start);
return token_starts[tok_index];
},
+
+ .node_offset_lib_name => |node_off| {
+ const tree = try src_loc.file_scope.getTree(gpa);
+ const node_datas = tree.nodes.items(.data);
+ const node_tags = tree.nodes.items(.tag);
+ const parent_node = src_loc.declRelativeToNodeIndex(node_off);
+ var params: [1]ast.Node.Index = undefined;
+ const full = switch (node_tags[parent_node]) {
+ .fn_proto_simple => tree.fnProtoSimple(¶ms, parent_node),
+ .fn_proto_multi => tree.fnProtoMulti(parent_node),
+ .fn_proto_one => tree.fnProtoOne(¶ms, parent_node),
+ .fn_proto => tree.fnProto(parent_node),
+ .fn_decl => blk: {
+ const fn_proto = node_datas[parent_node].lhs;
+ break :blk switch (node_tags[fn_proto]) {
+ .fn_proto_simple => tree.fnProtoSimple(¶ms, fn_proto),
+ .fn_proto_multi => tree.fnProtoMulti(fn_proto),
+ .fn_proto_one => tree.fnProtoOne(¶ms, fn_proto),
+ .fn_proto => tree.fnProto(fn_proto),
+ else => unreachable,
+ };
+ },
+ else => unreachable,
+ };
+ const tok_index = full.lib_name.?;
+ const token_starts = tree.tokens.items(.start);
+ return token_starts[tok_index];
+ },
}
}
};
@@ -1768,6 +1796,12 @@ pub const LazySrcLoc = union(enum) {
/// to the type expression.
/// The Decl is determined contextually.
node_offset_anyframe_type: i32,
+ /// The source location points to the string literal of `extern "foo"`, found
+ /// by taking this AST node index offset from the containing
+ /// Decl AST node, which points to a function prototype or variable declaration
+ /// expression AST node. Next, navigate to the string literal of the `extern "foo"`.
+ /// The Decl is determined contextually.
+ node_offset_lib_name: i32,
/// Upgrade to a `SrcLoc` based on the `Decl` or file in the provided scope.
pub fn toSrcLoc(lazy: LazySrcLoc, scope: *Scope) SrcLoc {
@@ -1808,6 +1842,7 @@ pub const LazySrcLoc = union(enum) {
.node_offset_fn_type_cc,
.node_offset_fn_type_ret_ty,
.node_offset_anyframe_type,
+ .node_offset_lib_name,
=> .{
.file_scope = scope.getFileScope(),
.parent_decl_node = scope.srcDecl().?.src_node,
@@ -1855,6 +1890,7 @@ pub const LazySrcLoc = union(enum) {
.node_offset_fn_type_cc,
.node_offset_fn_type_ret_ty,
.node_offset_anyframe_type,
+ .node_offset_lib_name,
=> .{
.file_scope = decl.getFileScope(),
.parent_decl_node = decl.src_node,
src/Sema.zig
@@ -63,6 +63,7 @@ const InnerError = Module.InnerError;
const Decl = Module.Decl;
const LazySrcLoc = Module.LazySrcLoc;
const RangeSet = @import("RangeSet.zig");
+const target_util = @import("target.zig");
pub fn analyzeFnBody(
sema: *Sema,
@@ -2739,6 +2740,7 @@ fn zirFunc(
false,
inferred_error_set,
src_locs,
+ null,
);
}
@@ -2754,11 +2756,14 @@ fn funcCommon(
var_args: bool,
inferred_error_set: bool,
src_locs: Zir.Inst.Func.SrcLocs,
+ opt_lib_name: ?[]const u8,
) InnerError!*Inst {
const src: LazySrcLoc = .{ .node_offset = src_node_offset };
const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
const return_type = try sema.resolveType(block, ret_ty_src, zir_return_type);
+ const mod = sema.mod;
+
const fn_ty: Type = fn_ty: {
// Hot path for some common function types.
if (zir_param_types.len == 0 and !var_args and align_val.tag() == .null_value) {
@@ -2789,7 +2794,7 @@ fn funcCommon(
}
if (align_val.tag() != .null_value) {
- return sema.mod.fail(&block.base, src, "TODO implement support for function prototypes to have alignment specified", .{});
+ return mod.fail(&block.base, src, "TODO implement support for function prototypes to have alignment specified", .{});
}
break :fn_ty try Type.Tag.function.create(sema.arena, .{
@@ -2801,7 +2806,48 @@ fn funcCommon(
};
if (body_inst == 0) {
- return sema.mod.constType(sema.arena, src, fn_ty);
+ return mod.constType(sema.arena, src, fn_ty);
+ }
+
+ if (opt_lib_name) |lib_name| blk: {
+ const lib_name_src: LazySrcLoc = .{ .node_offset_lib_name = src_node_offset };
+ log.debug("extern fn symbol expected in lib '{s}'", .{lib_name});
+ mod.comp.stage1AddLinkLib(lib_name) catch |err| {
+ return mod.fail(&block.base, lib_name_src, "unable to add link lib '{s}': {s}", .{
+ lib_name, @errorName(err),
+ });
+ };
+ const target = mod.getTarget();
+ if (target_util.is_libc_lib_name(target, lib_name)) {
+ if (!mod.comp.bin_file.options.link_libc) {
+ return mod.fail(
+ &block.base,
+ lib_name_src,
+ "dependency on libc must be explicitly specified in the build command",
+ .{},
+ );
+ }
+ break :blk;
+ }
+ if (target_util.is_libcpp_lib_name(target, lib_name)) {
+ if (!mod.comp.bin_file.options.link_libcpp) {
+ return mod.fail(
+ &block.base,
+ lib_name_src,
+ "dependency on libc++ must be explicitly specified in the build command",
+ .{},
+ );
+ }
+ break :blk;
+ }
+ if (!target.isWasm() and !mod.comp.bin_file.options.pic) {
+ return mod.fail(
+ &block.base,
+ lib_name_src,
+ "dependency on dynamic library '{s}' requires enabling Position Independent Code. Fixed by `-l{s}` or `-fPIC`.",
+ .{ lib_name, lib_name },
+ );
+ }
}
const is_inline = fn_ty.fnCallingConvention() == .Inline;
@@ -5599,11 +5645,13 @@ fn zirFuncExtended(
const small = @bitCast(Zir.Inst.ExtendedFunc.Small, extended.small);
var extra_index: usize = extra.end;
- if (small.has_lib_name) {
+
+ const lib_name: ?[]const u8 = if (small.has_lib_name) blk: {
const lib_name = sema.code.nullTerminatedString(sema.code.extra[extra_index]);
extra_index += 1;
- return sema.mod.fail(&block.base, src, "TODO: implement Sema func lib name", .{});
- }
+ break :blk lib_name;
+ } else null;
+
const cc: std.builtin.CallingConvention = if (small.has_cc) blk: {
const cc_ref = @intToEnum(Zir.Inst.Ref, sema.code.extra[extra_index]);
extra_index += 1;
@@ -5640,6 +5688,7 @@ fn zirFuncExtended(
small.is_var_args,
small.is_inferred_error,
src_locs,
+ lib_name,
);
}
BRANCH_TODO
@@ -55,132 +55,4 @@
natural alignment for fields and do not have any comptime fields. this
will save 16 bytes per struct field in the compilation.
-pub fn analyzeNamespace(
- mod: *Module,
- namespace: *Scope.Namespace,
- decls: []const ast.Node.Index,
-) InnerError!void {
- for (decls) |decl_node| switch (node_tags[decl_node]) {
- .@"comptime" => {
- const name_index = mod.getNextAnonNameIndex();
- const name = try std.fmt.allocPrint(mod.gpa, "__comptime_{d}", .{name_index});
- defer mod.gpa.free(name);
-
- const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));
-
- const new_decl = try mod.createNewDecl(namespace, name, decl_node, name_hash, contents_hash);
- namespace.decls.putAssumeCapacity(new_decl, {});
- mod.comp.work_queue.writeItemAssumeCapacity(.{ .analyze_decl = new_decl });
- },
-
- // Container fields are handled in AstGen.
- .container_field_init,
- .container_field_align,
- .container_field,
- => continue,
-
- .test_decl => {
- if (mod.comp.bin_file.options.is_test) {
- log.err("TODO: analyze test decl", .{});
- }
- },
- .@"usingnamespace" => {
- const name_index = mod.getNextAnonNameIndex();
- const name = try std.fmt.allocPrint(mod.gpa, "__usingnamespace_{d}", .{name_index});
- defer mod.gpa.free(name);
-
- const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));
-
- const new_decl = try mod.createNewDecl(namespace, name, decl_node, name_hash, contents_hash);
- namespace.decls.putAssumeCapacity(new_decl, {});
-
- mod.ensureDeclAnalyzed(new_decl) catch |err| switch (err) {
- error.OutOfMemory => return error.OutOfMemory,
- error.AnalysisFail => continue,
- };
- },
- else => unreachable,
- };
-}
-
-/// Trailing:
-/// 0. `EmitH` if `module.emit_h != null`.
-/// 1. A per-Decl link object. Represents the position of the code in the output file.
-/// This is populated regardless of semantic analysis and code generation.
-/// Depending on the target, will be one of:
-/// * Elf.TextBlock
-/// * Coff.TextBlock
-/// * MachO.TextBlock
-/// * C.DeclBlock
-/// * Wasm.DeclBlock
-/// * void
-/// 2. If it is a function, a per-Decl link function object. Represents the
-/// function in the linked output file, if the `Decl` is a function.
-/// This is stored here and not in `Fn` because `Decl` survives across updates but
-/// `Fn` does not. Depending on the target, will be one of:
-/// * Elf.SrcFn
-/// * Coff.SrcFn
-/// * MachO.SrcFn
-/// * C.FnBlock
-/// * Wasm.FnData
-/// * SpirV.FnData
-
-
- extra_index += @boolToInt(has_align);
- extra_index += @boolToInt(has_section);
-
- /// Contains un-analyzed ZIR instructions generated from Zig source AST.
- /// Even after we finish analysis, the ZIR is kept in memory, so that
- /// comptime and inline function calls can happen.
- /// Parameter names are stored here so that they may be referenced for debug info,
- /// without having source code bytes loaded into memory.
- /// The number of parameters is determined by referring to the type.
- /// The first N elements of `extra` are indexes into `string_bytes` to
- /// a null-terminated string.
- /// This memory is managed with gpa, must be freed when the function is freed.
- zir: Zir,
-
-
- if (fn_proto.lib_name) |lib_name_token| blk: {
- log.debug("extern fn symbol expected in lib '{s}'", .{lib_name_str});
- mod.comp.stage1AddLinkLib(lib_name_str) catch |err| {
- return mod.failTok(
- &fn_type_scope.base,
- lib_name_token,
- "unable to add link lib '{s}': {s}",
- .{ lib_name_str, @errorName(err) },
- );
- };
- const target = mod.comp.getTarget();
- if (target_util.is_libc_lib_name(target, lib_name_str)) {
- if (!mod.comp.bin_file.options.link_libc) {
- return mod.failTok(
- &fn_type_scope.base,
- lib_name_token,
- "dependency on libc must be explicitly specified in the build command",
- .{},
- );
- }
- break :blk;
- }
- if (target_util.is_libcpp_lib_name(target, lib_name_str)) {
- if (!mod.comp.bin_file.options.link_libcpp) {
- return mod.failTok(
- &fn_type_scope.base,
- lib_name_token,
- "dependency on libc++ must be explicitly specified in the build command",
- .{},
- );
- }
- break :blk;
- }
- if (!target.isWasm() and !mod.comp.bin_file.options.pic) {
- return mod.failTok(
- &fn_type_scope.base,
- lib_name_token,
- "dependency on dynamic library '{s}' requires enabling Position Independent Code. Fixed by `-l{s}` or `-fPIC`.",
- .{ lib_name_str, lib_name_str },
- );
- }
- }