aboutsummaryrefslogtreecommitdiff
path: root/src/Module.zig
diff options
context:
space:
mode:
Diffstat (limited to 'src/Module.zig')
-rw-r--r--src/Module.zig107
1 files changed, 94 insertions, 13 deletions
diff --git a/src/Module.zig b/src/Module.zig
index 4ac2775515..6122b417e4 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -2161,6 +2161,10 @@ pub const SrcLoc = struct {
.local_var_decl => tree.localVarDecl(node),
.simple_var_decl => tree.simpleVarDecl(node),
.aligned_var_decl => tree.alignedVarDecl(node),
+ .@"usingnamespace" => {
+ const node_data = tree.nodes.items(.data);
+ return nodeToSpan(tree, node_data[node].lhs);
+ },
else => unreachable,
};
if (full.ast.type_node != 0) {
@@ -2171,6 +2175,58 @@ pub const SrcLoc = struct {
const end = start + @intCast(u32, tree.tokenSlice(tok_index).len);
return Span{ .start = start, .end = end, .main = start };
},
+ .node_offset_var_decl_align => |node_off| {
+ const tree = try src_loc.file_scope.getTree(gpa);
+ const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node_tags = tree.nodes.items(.tag);
+ const full: Ast.full.VarDecl = switch (node_tags[node]) {
+ .global_var_decl => tree.globalVarDecl(node),
+ .local_var_decl => tree.localVarDecl(node),
+ .simple_var_decl => tree.simpleVarDecl(node),
+ .aligned_var_decl => tree.alignedVarDecl(node),
+ else => unreachable,
+ };
+ return nodeToSpan(tree, full.ast.align_node);
+ },
+ .node_offset_var_decl_section => |node_off| {
+ const tree = try src_loc.file_scope.getTree(gpa);
+ const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node_tags = tree.nodes.items(.tag);
+ const full: Ast.full.VarDecl = switch (node_tags[node]) {
+ .global_var_decl => tree.globalVarDecl(node),
+ .local_var_decl => tree.localVarDecl(node),
+ .simple_var_decl => tree.simpleVarDecl(node),
+ .aligned_var_decl => tree.alignedVarDecl(node),
+ else => unreachable,
+ };
+ return nodeToSpan(tree, full.ast.section_node);
+ },
+ .node_offset_var_decl_addrspace => |node_off| {
+ const tree = try src_loc.file_scope.getTree(gpa);
+ const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node_tags = tree.nodes.items(.tag);
+ const full: Ast.full.VarDecl = switch (node_tags[node]) {
+ .global_var_decl => tree.globalVarDecl(node),
+ .local_var_decl => tree.localVarDecl(node),
+ .simple_var_decl => tree.simpleVarDecl(node),
+ .aligned_var_decl => tree.alignedVarDecl(node),
+ else => unreachable,
+ };
+ return nodeToSpan(tree, full.ast.addrspace_node);
+ },
+ .node_offset_var_decl_init => |node_off| {
+ const tree = try src_loc.file_scope.getTree(gpa);
+ const node = src_loc.declRelativeToNodeIndex(node_off);
+ const node_tags = tree.nodes.items(.tag);
+ const full: Ast.full.VarDecl = switch (node_tags[node]) {
+ .global_var_decl => tree.globalVarDecl(node),
+ .local_var_decl => tree.localVarDecl(node),
+ .simple_var_decl => tree.simpleVarDecl(node),
+ .aligned_var_decl => tree.alignedVarDecl(node),
+ else => unreachable,
+ };
+ return nodeToSpan(tree, full.ast.init_node);
+ },
.node_offset_builtin_call_arg0 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 0),
.node_offset_builtin_call_arg1 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 1),
.node_offset_builtin_call_arg2 => |n| return src_loc.byteOffsetBuiltinCallArg(gpa, n, 2),
@@ -2857,6 +2913,18 @@ pub const LazySrcLoc = union(enum) {
/// to the type expression.
/// The Decl is determined contextually.
node_offset_var_decl_ty: i32,
+ /// The source location points to the alignment expression of a var decl.
+ /// The Decl is determined contextually.
+ node_offset_var_decl_align: i32,
+ /// The source location points to the linksection expression of a var decl.
+ /// The Decl is determined contextually.
+ node_offset_var_decl_section: i32,
+ /// The source location points to the addrspace expression of a var decl.
+ /// The Decl is determined contextually.
+ node_offset_var_decl_addrspace: i32,
+ /// The source location points to the initializer of a var decl.
+ /// The Decl is determined contextually.
+ node_offset_var_decl_init: i32,
/// The source location points to a for loop condition expression,
/// found by taking this AST node index offset from the containing
/// Decl AST node, which points to a for loop AST node. Next, navigate
@@ -3098,6 +3166,10 @@ pub const LazySrcLoc = union(enum) {
.node_offset,
.node_offset_initializer,
.node_offset_var_decl_ty,
+ .node_offset_var_decl_align,
+ .node_offset_var_decl_section,
+ .node_offset_var_decl_addrspace,
+ .node_offset_var_decl_init,
.node_offset_for_cond,
.node_offset_builtin_call_arg0,
.node_offset_builtin_call_arg1,
@@ -4414,17 +4486,26 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
const body = zir.extra[extra.end..][0..extra.data.body_len];
const result_ref = (try sema.analyzeBodyBreak(&block_scope, body)).?.operand;
try wip_captures.finalize();
- const src = LazySrcLoc.nodeOffset(0);
- const decl_tv = try sema.resolveInstValue(&block_scope, .unneeded, result_ref, undefined);
+ const align_src: LazySrcLoc = .{ .node_offset_var_decl_align = 0 };
+ const section_src: LazySrcLoc = .{ .node_offset_var_decl_section = 0 };
+ const address_space_src: LazySrcLoc = .{ .node_offset_var_decl_addrspace = 0 };
+ const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = 0 };
+ const init_src: LazySrcLoc = .{ .node_offset_var_decl_init = 0 };
+ const decl_tv = try sema.resolveInstValue(&block_scope, init_src, result_ref, undefined);
const decl_align: u32 = blk: {
const align_ref = decl.zirAlignRef();
if (align_ref == .none) break :blk 0;
- break :blk try sema.resolveAlign(&block_scope, src, align_ref);
+ break :blk try sema.resolveAlign(&block_scope, align_src, align_ref);
};
const decl_linksection: ?[*:0]const u8 = blk: {
const linksection_ref = decl.zirLinksectionRef();
if (linksection_ref == .none) break :blk null;
- const bytes = try sema.resolveConstString(&block_scope, src, linksection_ref, "linksection must be comptime known");
+ const bytes = try sema.resolveConstString(&block_scope, section_src, linksection_ref, "linksection must be comptime known");
+ if (mem.indexOfScalar(u8, bytes, 0) != null) {
+ return sema.fail(&block_scope, section_src, "linksection cannot contain null bytes", .{});
+ } else if (bytes.len == 0) {
+ return sema.fail(&block_scope, section_src, "linksection cannot be empty", .{});
+ }
break :blk (try decl_arena_allocator.dupeZ(u8, bytes)).ptr;
};
const target = sema.mod.getTarget();
@@ -4442,27 +4523,27 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
.constant => target_util.defaultAddressSpace(target, .global_constant),
else => unreachable,
},
- else => |addrspace_ref| try sema.analyzeAddrspace(&block_scope, src, addrspace_ref, addrspace_ctx),
+ else => |addrspace_ref| try sema.analyzeAddrspace(&block_scope, address_space_src, addrspace_ref, addrspace_ctx),
};
};
// Note this resolves the type of the Decl, not the value; if this Decl
// is a struct, for example, this resolves `type` (which needs no resolution),
// not the struct itself.
- try sema.resolveTypeLayout(&block_scope, src, decl_tv.ty);
+ try sema.resolveTypeLayout(&block_scope, ty_src, decl_tv.ty);
const decl_arena_state = try decl_arena_allocator.create(std.heap.ArenaAllocator.State);
if (decl.is_usingnamespace) {
if (!decl_tv.ty.eql(Type.type, mod)) {
- return sema.fail(&block_scope, src, "expected type, found {}", .{
+ return sema.fail(&block_scope, ty_src, "expected type, found {}", .{
decl_tv.ty.fmt(mod),
});
}
var buffer: Value.ToTypeBuffer = undefined;
const ty = try decl_tv.val.toType(&buffer).copy(decl_arena_allocator);
if (ty.getNamespace() == null) {
- return sema.fail(&block_scope, src, "type {} has no namespace", .{ty.fmt(mod)});
+ return sema.fail(&block_scope, ty_src, "type {} has no namespace", .{ty.fmt(mod)});
}
decl.ty = Type.type;
@@ -4508,7 +4589,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
decl.analysis = .complete;
decl.generation = mod.generation;
- const has_runtime_bits = try sema.fnHasRuntimeBits(&block_scope, src, decl.ty);
+ const has_runtime_bits = try sema.fnHasRuntimeBits(&block_scope, ty_src, decl.ty);
if (has_runtime_bits) {
// We don't fully codegen the decl until later, but we do need to reserve a global
@@ -4525,7 +4606,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
const is_inline = decl.ty.fnCallingConvention() == .Inline;
if (decl.is_exported) {
- const export_src = src; // TODO make this point at `export` token
+ const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) };
if (is_inline) {
return sema.fail(&block_scope, export_src, "export of inline function", .{});
}
@@ -4588,14 +4669,14 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
decl.generation = mod.generation;
const has_runtime_bits = is_extern or
- (queue_linker_work and try sema.typeHasRuntimeBits(&block_scope, src, decl.ty));
+ (queue_linker_work and try sema.typeHasRuntimeBits(&block_scope, ty_src, decl.ty));
if (has_runtime_bits) {
log.debug("queue linker work for {*} ({s})", .{ decl, decl.name });
// Needed for codegen_decl which will call updateDecl and then the
// codegen backend wants full access to the Decl Type.
- try sema.resolveTypeFully(&block_scope, src, decl.ty);
+ try sema.resolveTypeFully(&block_scope, ty_src, decl.ty);
try mod.comp.bin_file.allocateDeclIndexes(decl_index);
try mod.comp.work_queue.writeItem(.{ .codegen_decl = decl_index });
@@ -4606,7 +4687,7 @@ fn semaDecl(mod: *Module, decl_index: Decl.Index) !bool {
}
if (decl.is_exported) {
- const export_src = src; // TODO point to the export token
+ const export_src: LazySrcLoc = .{ .token_offset = @boolToInt(decl.is_pub) };
// The scope needs to have the decl in it.
const options: std.builtin.ExportOptions = .{ .name = mem.sliceTo(decl.name, 0) };
try sema.analyzeExport(&block_scope, export_src, options, decl_index);