aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-04-15 20:34:21 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-04-15 20:34:21 -0700
commit8387307807434cf151d72a7dfb5b7da4863b2192 (patch)
tree9795185b63245e1a820b1614858726f5ce494e56 /src
parent7818586a2bc24252468977f8304d3c5b870a932a (diff)
downloadzig-8387307807434cf151d72a7dfb5b7da4863b2192.tar.gz
zig-8387307807434cf151d72a7dfb5b7da4863b2192.zip
AstGen: implement global variable decls
Diffstat (limited to 'src')
-rw-r--r--src/AstGen.zig111
-rw-r--r--src/Module.zig7
2 files changed, 102 insertions, 16 deletions
diff --git a/src/AstGen.zig b/src/AstGen.zig
index 3118d1fe94..cb1a28deda 100644
--- a/src/AstGen.zig
+++ b/src/AstGen.zig
@@ -1491,7 +1491,7 @@ fn varDecl(
}
if (var_decl.ast.init_node == 0) {
- return astgen.failTok(name_token, "variables must be initialized", .{});
+ return astgen.failNode(node, "variables must be initialized", .{});
}
switch (token_tags[var_decl.ast.mut_token]) {
@@ -1851,10 +1851,12 @@ fn fnDecl(
const is_pub = fn_proto.visib_token != null;
const is_export = blk: {
- if (fn_proto.extern_export_token) |maybe_export_token| {
- break :blk token_tags[maybe_export_token] == .keyword_export;
- }
- break :blk false;
+ const maybe_export_token = fn_proto.extern_export_token orelse break :blk false;
+ break :blk token_tags[maybe_export_token] == .keyword_export;
+ };
+ const is_extern = blk: {
+ const maybe_extern_token = fn_proto.extern_export_token orelse break :blk false;
+ break :blk token_tags[maybe_extern_token] == .keyword_extern;
};
if (wip_decls.decl_index % 16 == 0 and wip_decls.decl_index != 0) {
try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag);
@@ -1937,11 +1939,6 @@ fn fnDecl(
fn_proto.ast.return_type,
);
- const is_extern = if (fn_proto.extern_export_token) |maybe_export_token|
- token_tags[maybe_export_token] == .keyword_extern
- else
- false;
-
const cc: Zir.Inst.Ref = if (fn_proto.ast.callconv_expr != 0)
// TODO instead of enum literal type, this needs to be the
// std.builtin.CallingConvention enum. We need to implement importing other files
@@ -2070,10 +2067,94 @@ fn fnDecl(
fn globalVarDecl(
astgen: *AstGen,
gz: *GenZir,
+ scope: *Scope,
wip_decls: *WipDecls,
+ node: ast.Node.Index,
var_decl: ast.full.VarDecl,
) InnerError!void {
- @panic("TODO astgen globalVarDecl");
+ const gpa = astgen.gpa;
+ const tree = &astgen.file.tree;
+ const token_tags = tree.tokens.items(.tag);
+
+ const is_pub = var_decl.visib_token != null;
+ const is_export = blk: {
+ const maybe_export_token = var_decl.extern_export_token orelse break :blk false;
+ break :blk token_tags[maybe_export_token] == .keyword_export;
+ };
+ const is_extern = blk: {
+ const maybe_extern_token = var_decl.extern_export_token orelse break :blk false;
+ break :blk token_tags[maybe_extern_token] == .keyword_extern;
+ };
+ if (wip_decls.decl_index % 16 == 0 and wip_decls.decl_index != 0) {
+ try wip_decls.bit_bag.append(gpa, wip_decls.cur_bit_bag);
+ wip_decls.cur_bit_bag = 0;
+ }
+ wip_decls.cur_bit_bag = (wip_decls.cur_bit_bag >> 2) |
+ (@as(u32, @boolToInt(is_pub)) << 30) |
+ (@as(u32, @boolToInt(is_export)) << 31);
+ wip_decls.decl_index += 1;
+
+ const is_mutable = token_tags[var_decl.ast.mut_token] == .keyword_var;
+ const is_threadlocal = if (var_decl.threadlocal_token) |tok| blk: {
+ if (!is_mutable) {
+ return astgen.failTok(tok, "threadlocal variable cannot be constant", .{});
+ }
+ break :blk true;
+ } else false;
+
+ const lib_name: u32 = if (var_decl.lib_name) |lib_name_token| blk: {
+ const lib_name_str = try gz.strLitAsString(lib_name_token);
+ break :blk lib_name_str.index;
+ } else 0;
+
+ assert(var_decl.comptime_token == null); // handled by parser
+ if (var_decl.ast.align_node != 0) {
+ return astgen.failNode(var_decl.ast.align_node, "TODO implement alignment on globals", .{});
+ }
+ if (var_decl.ast.section_node != 0) {
+ return astgen.failNode(var_decl.ast.section_node, "TODO linksection on globals", .{});
+ }
+
+ const var_inst: Zir.Inst.Ref = if (var_decl.ast.init_node != 0) vi: {
+ if (is_extern) {
+ return astgen.failNode(
+ var_decl.ast.init_node,
+ "extern variables have no initializers",
+ .{},
+ );
+ }
+
+ const init_result_loc: AstGen.ResultLoc = if (var_decl.ast.type_node != 0) .{
+ .ty = try expr(gz, scope, .{ .ty = .type_type }, var_decl.ast.type_node),
+ } else .none;
+
+ const init_inst = try expr(gz, scope, init_result_loc, var_decl.ast.init_node);
+
+ if (!is_mutable) {
+ // const globals are just their instruction. mutable globals have
+ // a special ZIR form.
+ break :vi init_inst;
+ }
+
+ @panic("TODO astgen global variable");
+ } else if (!is_extern) {
+ return astgen.failNode(node, "variables must be initialized", .{});
+ } else if (var_decl.ast.type_node != 0) {
+ // Extern variable which has an explicit type.
+
+ const type_inst = try typeExpr(gz, scope, var_decl.ast.type_node);
+
+ @panic("TODO AstGen extern global variable");
+ } else {
+ return astgen.failNode(node, "unable to infer variable type", .{});
+ };
+
+ const name_token = var_decl.ast.mut_token + 1;
+ const name_str_index = try gz.identAsString(name_token);
+
+ try wip_decls.name_and_value.ensureCapacity(gpa, wip_decls.name_and_value.items.len + 2);
+ wip_decls.name_and_value.appendAssumeCapacity(name_str_index);
+ wip_decls.name_and_value.appendAssumeCapacity(@enumToInt(var_inst));
}
fn comptimeDecl(
@@ -2191,19 +2272,19 @@ fn structDeclInner(
},
.global_var_decl => {
- try astgen.globalVarDecl(gz, &wip_decls, tree.globalVarDecl(member_node));
+ try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.globalVarDecl(member_node));
continue;
},
.local_var_decl => {
- try astgen.globalVarDecl(gz, &wip_decls, tree.localVarDecl(member_node));
+ try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.localVarDecl(member_node));
continue;
},
.simple_var_decl => {
- try astgen.globalVarDecl(gz, &wip_decls, tree.simpleVarDecl(member_node));
+ try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.simpleVarDecl(member_node));
continue;
},
.aligned_var_decl => {
- try astgen.globalVarDecl(gz, &wip_decls, tree.alignedVarDecl(member_node));
+ try astgen.globalVarDecl(gz, scope, &wip_decls, member_node, tree.alignedVarDecl(member_node));
continue;
},
diff --git a/src/Module.zig b/src/Module.zig
index bcb4b8dc99..2baa064255 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -2457,6 +2457,9 @@ fn freeExportList(gpa: *Allocator, export_list: []*Export) void {
}
pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node) !void {
+ const tracy = trace(@src());
+ defer tracy.end();
+
const comp = mod.comp;
const gpa = mod.gpa;
@@ -2468,7 +2471,9 @@ pub fn astGenFile(mod: *Module, file: *Scope.File, prog_node: *std.Progress.Node
// Determine whether we need to reload the file from disk and redo parsing and AstGen.
switch (file.status) {
- .never_loaded, .retryable_failure => {},
+ .never_loaded, .retryable_failure => {
+ log.debug("first-time AstGen: {s}", .{file.sub_file_path});
+ },
.parse_failure, .astgen_failure, .success => {
const unchanged_metadata =
stat.size == file.stat_size and