Commit cc5c25d48b

Robin Voetter <robin@voetter.nl>
2022-01-08 04:29:49
stage2: implement @src
1 parent 4931b8d
src/AstGen.zig
@@ -6918,12 +6918,25 @@ fn builtinCall(
             return rvalue(gz, rl, result, node);
         },
 
+        .src => {
+            const token_starts = tree.tokens.items(.start);
+            const node_start = token_starts[tree.firstToken(node)];
+
+            astgen.advanceSourceCursor(tree.source, node_start);
+
+            const result = try gz.addExtendedPayload(.builtin_src, Zir.Inst.LineColumn{
+                .line = @intCast(u32, astgen.source_line),
+                .column = @intCast(u32, astgen.source_column),
+            });
+
+            return rvalue(gz, rl, result, node);
+        },
+
         .breakpoint => return simpleNoOpVoid(gz, rl, node, .breakpoint),
 
         // zig fmt: off
         .This               => return rvalue(gz, rl, try gz.addNodeExtended(.this,               node), node),
         .return_address     => return rvalue(gz, rl, try gz.addNodeExtended(.ret_addr,           node), node),
-        .src                => return rvalue(gz, rl, try gz.addNodeExtended(.builtin_src,        node), node),
         .error_return_trace => return rvalue(gz, rl, try gz.addNodeExtended(.error_return_trace, node), node),
         .frame              => return rvalue(gz, rl, try gz.addNodeExtended(.frame,              node), node),
         .frame_address      => return rvalue(gz, rl, try gz.addNodeExtended(.frame_address,      node), node),
src/Module.zig
@@ -1663,6 +1663,11 @@ pub const File = struct {
         return file.pkg.root_src_directory.join(ally, &[_][]const u8{file.sub_file_path});
     }
 
+    /// Returns the full path to this file relative to its package.
+    pub fn fullPathZ(file: File, ally: Allocator) ![:0]u8 {
+        return file.pkg.root_src_directory.joinZ(ally, &[_][]const u8{file.sub_file_path});
+    }
+
     pub fn dumpSrc(file: *File, src: LazySrcLoc) void {
         const loc = std.zig.findLineColumn(file.source.bytes, src);
         std.debug.print("{s}:{d}:{d}\n", .{ file.sub_file_path, loc.line + 1, loc.column + 1 });
src/Sema.zig
@@ -9182,8 +9182,50 @@ fn zirBuiltinSrc(
     block: *Block,
     extended: Zir.Inst.Extended.InstData,
 ) CompileError!Air.Inst.Ref {
+    const tracy = trace(@src());
+    defer tracy.end();
+
     const src: LazySrcLoc = .{ .node_offset = @bitCast(i32, extended.operand) };
-    return sema.fail(block, src, "TODO: implement Sema.zirBuiltinSrc", .{});
+    const extra = sema.code.extraData(Zir.Inst.LineColumn, extended.operand).data;
+    const func = sema.func orelse return sema.fail(block, src, "@src outside function", .{});
+
+    const func_name_val = blk: {
+        var anon_decl = try block.startAnonDecl();
+        defer anon_decl.deinit();
+        const name = std.mem.span(func.owner_decl.name);
+        const bytes = try anon_decl.arena().dupe(u8, name[0 .. name.len + 1]);
+        const new_decl = try anon_decl.finish(
+            try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len - 1),
+            try Value.Tag.bytes.create(anon_decl.arena(), bytes),
+        );
+        break :blk try Value.Tag.decl_ref.create(sema.arena, new_decl);
+    };
+
+    const file_name_val = blk: {
+        var anon_decl = try block.startAnonDecl();
+        defer anon_decl.deinit();
+        const name = try func.owner_decl.getFileScope().fullPathZ(anon_decl.arena());
+        const new_decl = try anon_decl.finish(
+            try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), name.len),
+            try Value.Tag.bytes.create(anon_decl.arena(), name[0 .. name.len + 1]),
+        );
+        break :blk try Value.Tag.decl_ref.create(sema.arena, new_decl);
+    };
+
+    const field_values = try sema.arena.alloc(Value, 4);
+    // file: [:0]const u8,
+    field_values[0] = file_name_val;
+    // fn_name: [:0]const u8,
+    field_values[1] = func_name_val;
+    // line: u32
+    field_values[2] = try Value.Tag.int_u64.create(sema.arena, extra.line + 1);
+    // column: u32,
+    field_values[3] = try Value.Tag.int_u64.create(sema.arena, extra.column + 1);
+
+    return sema.addConstant(
+        try sema.getBuiltinType(block, src, "SourceLocation"),
+        try Value.Tag.@"struct".create(sema.arena, field_values),
+    );
 }
 
 fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
src/Zir.zig
@@ -1510,7 +1510,7 @@ pub const Inst = struct {
         /// `operand` is `src_node: i32`.
         ret_addr,
         /// Implements the `@src` builtin.
-        /// `operand` is `src_node: i32`.
+        /// `operand` is payload index to `ColumnLine`.
         builtin_src,
         /// Implements the `@errorReturnTrace` builtin.
         /// `operand` is `src_node: i32`.
@@ -2160,10 +2160,7 @@ pub const Inst = struct {
             switch_inst: Index,
             prong_index: u32,
         },
-        dbg_stmt: struct {
-            line: u32,
-            column: u32,
-        },
+        dbg_stmt: LineColumn,
         /// Used for unary operators which reference an inst,
         /// with an AST node source location.
         inst_node: struct {
@@ -2964,6 +2961,11 @@ pub const Inst = struct {
             token: Ast.TokenIndex,
         };
     };
+
+    pub const LineColumn = struct {
+        line: u32,
+        column: u32,
+    };
 };
 
 pub const SpecialProng = enum { none, @"else", under };
test/behavior.zig
@@ -65,6 +65,7 @@ test {
             _ = @import("behavior/translate_c_macros.zig");
             _ = @import("behavior/try.zig");
             _ = @import("behavior/undefined.zig");
+            _ = @import("behavior/src.zig");
 
             if (builtin.zig_backend != .stage2_c) {
                 // Tests that pass for stage1 and the llvm backend.
@@ -204,7 +205,6 @@ test {
                         _ = @import("behavior/wasm.zig");
                     }
                     _ = @import("behavior/while_stage1.zig");
-                    _ = @import("behavior/src.zig");
                     _ = @import("behavior/translate_c_macros_stage1.zig");
                 }
             }