Commit 6524a64bda

Andrew Kelley <andrew@ziglang.org>
2020-06-02 23:43:51
stage2: fix referencing decls which appear later in the file
1 parent 14d235d
Changed files (3)
src-self-hosted
test
stage2
src-self-hosted/Module.zig
@@ -743,7 +743,7 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {
                             self.allocator,
                             decl.src,
                             "unable to load source file '{}': {}",
-                            .{decl.scope.sub_file_path, @errorName(err)},
+                            .{ decl.scope.sub_file_path, @errorName(err) },
                         ));
                         decl.analysis = .codegen_failure_retryable;
                         continue;
@@ -756,7 +756,7 @@ pub fn performAllTheWork(self: *Module) error{OutOfMemory}!void {
                     error.OutOfMemory => return error.OutOfMemory,
                     error.AnalysisFail => continue,
                 };
-            }
+            },
         },
     };
 }
@@ -945,7 +945,7 @@ fn deleteDeclExports(self: *Module, decl: *Decl) void {
             var new_len = list.len;
             while (i < new_len) {
                 if (list[i].owner_decl == decl) {
-                    mem.copyBackwards(*Export, list[i..], list[i + 1..new_len]);
+                    mem.copyBackwards(*Export, list[i..], list[i + 1 .. new_len]);
                     new_len -= 1;
                 } else {
                     i += 1;
@@ -1494,13 +1494,11 @@ fn analyzeInstDeclRef(self: *Module, scope: *Scope, inst: *zir.Inst.DeclRef) Inn
     const decl_name = try self.resolveConstString(scope, inst.positionals.name);
     // This will need to get more fleshed out when there are proper structs & namespaces.
     const zir_module = scope.namespace();
-    for (zir_module.contents.module.decls) |src_decl| {
-        if (mem.eql(u8, src_decl.name, decl_name)) {
-            const decl = try self.resolveCompleteDecl(scope, src_decl);
-            return self.analyzeDeclRef(scope, inst.base.src, decl);
-        }
-    }
-    return self.fail(scope, inst.positionals.name.src, "use of undeclared identifier '{}'", .{decl_name});
+    const src_decl = zir_module.contents.module.findDecl(decl_name) orelse
+        return self.fail(scope, inst.positionals.name.src, "use of undeclared identifier '{}'", .{decl_name});
+
+    const decl = try self.resolveCompleteDecl(scope, src_decl);
+    return self.analyzeDeclRef(scope, inst.base.src, decl);
 }
 
 fn analyzeDeclRef(self: *Module, scope: *Scope, src: usize, decl: *Decl) InnerError!*Inst {
src-self-hosted/zir.zig
@@ -964,8 +964,8 @@ const Parser = struct {
                 self.i = src;
                 return self.fail("unrecognized identifier: {}", .{bad_name});
             } else {
-                const name = try self.arena.allocator.create(Inst.Str);
-                name.* = .{
+                const name_array = try self.arena.allocator.create(Inst.Str);
+                name_array.* = .{
                     .base = .{
                         .name = try self.generateName(),
                         .src = src,
@@ -974,6 +974,16 @@ const Parser = struct {
                     .positionals = .{ .bytes = ident },
                     .kw_args = .{},
                 };
+                const name = try self.arena.allocator.create(Inst.Ref);
+                name.* = .{
+                    .base = .{
+                        .name = try self.generateName(),
+                        .src = src,
+                        .tag = Inst.Ref.base_tag,
+                    },
+                    .positionals = .{ .operand = &name_array.base },
+                    .kw_args = .{},
+                };
                 const declref = try self.arena.allocator.create(Inst.DeclRef);
                 declref.* = .{
                     .base = .{
@@ -984,7 +994,17 @@ const Parser = struct {
                     .positionals = .{ .name = &name.base },
                     .kw_args = .{},
                 };
-                return &declref.base;
+                const deref = try self.arena.allocator.create(Inst.Deref);
+                deref.* = .{
+                    .base = .{
+                        .name = try self.generateName(),
+                        .src = src,
+                        .tag = Inst.Deref.base_tag,
+                    },
+                    .positionals = .{ .ptr = &declref.base },
+                    .kw_args = .{},
+                };
+                return &deref.base;
             }
         };
         if (local_ref) {
test/stage2/zir.zig
@@ -9,6 +9,28 @@ const linux_x64 = std.zig.CrossTarget{
 };
 
 pub fn addCases(ctx: *TestContext) void {
+    ctx.addZIRTransform("referencing decls which appear later in the file", linux_x64,
+        \\@void = primitive(void)
+        \\@fnty = fntype([], @void, cc=C)
+        \\
+        \\@9 = str("entry")
+        \\@10 = ref(@9)
+        \\@11 = export(@10, @entry)
+        \\
+        \\@entry = fn(@fnty, {
+        \\  %11 = return()
+        \\})
+    ,
+        \\@0 = primitive(void)
+        \\@1 = fntype([], @0, cc=C)
+        \\@2 = fn(@1, {
+        \\  %0 = return()
+        \\})
+        \\@3 = str("entry")
+        \\@4 = ref(@3)
+        \\@5 = export(@4, @2)
+        \\
+    );
     ctx.addZIRTransform("elemptr, add, cmp, condbr, return, breakpoint", linux_x64,
         \\@void = primitive(void)
         \\@usize = primitive(usize)