Skip to content

Commit e54ed9f

Browse files
authored
Merge pull request #5628 from Vexu/src
Implement @src
2 parents 9781342 + 14acc65 commit e54ed9f

File tree

8 files changed

+125
-0
lines changed

8 files changed

+125
-0
lines changed

lib/std/builtin.zig

+9
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,15 @@ pub const CallingConvention = enum {
131131
AAPCSVFP,
132132
};
133133

134+
/// This data structure is used by the Zig language code generation and
135+
/// therefore must be kept in sync with the compiler implementation.
136+
pub const SourceLocation = struct {
137+
file: []const u8,
138+
fn_name: []const u8,
139+
line: u32,
140+
column: u32,
141+
};
142+
134143
pub const TypeId = @TagType(TypeInfo);
135144

136145
/// This data structure is used by the Zig language code generation and

src/all_types.hpp

+6
Original file line numberDiff line numberDiff line change
@@ -1827,6 +1827,7 @@ enum BuiltinFnId {
18271827
BuiltinFnIdBitSizeof,
18281828
BuiltinFnIdWasmMemorySize,
18291829
BuiltinFnIdWasmMemoryGrow,
1830+
BuiltinFnIdSrc,
18301831
};
18311832

18321833
struct BuiltinFnEntry {
@@ -2754,6 +2755,7 @@ enum IrInstSrcId {
27542755
IrInstSrcIdSpillEnd,
27552756
IrInstSrcIdWasmMemorySize,
27562757
IrInstSrcIdWasmMemoryGrow,
2758+
IrInstSrcIdSrc,
27572759
};
27582760

27592761
// ir_render_* functions in codegen.cpp consume Gen instructions and produce LLVM IR.
@@ -3761,6 +3763,10 @@ struct IrInstGenWasmMemoryGrow {
37613763
IrInstGen *delta;
37623764
};
37633765

3766+
struct IrInstSrcSrc {
3767+
IrInstSrc base;
3768+
};
3769+
37643770
struct IrInstSrcSlice {
37653771
IrInstSrc base;
37663772

src/codegen.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -8714,6 +8714,7 @@ static void define_builtin_fns(CodeGen *g) {
87148714
create_builtin_fn(g, BuiltinFnIdBitSizeof, "bitSizeOf", 1);
87158715
create_builtin_fn(g, BuiltinFnIdWasmMemorySize, "wasmMemorySize", 1);
87168716
create_builtin_fn(g, BuiltinFnIdWasmMemoryGrow, "wasmMemoryGrow", 2);
8717+
create_builtin_fn(g, BuiltinFnIdSrc, "src", 0);
87178718
}
87188719

87198720
static const char *bool_to_str(bool b) {

src/ir.cpp

+76
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,8 @@ static void destroy_instruction_src(IrInstSrc *inst) {
561561
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcWasmMemorySize *>(inst));
562562
case IrInstSrcIdWasmMemoryGrow:
563563
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcWasmMemoryGrow *>(inst));
564+
case IrInstSrcIdSrc:
565+
return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcSrc *>(inst));
564566
}
565567
zig_unreachable();
566568
}
@@ -1627,6 +1629,9 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcWasmMemoryGrow *) {
16271629
return IrInstSrcIdWasmMemoryGrow;
16281630
}
16291631

1632+
static constexpr IrInstSrcId ir_inst_id(IrInstSrcSrc *) {
1633+
return IrInstSrcIdSrc;
1634+
}
16301635

16311636
static constexpr IrInstGenId ir_inst_id(IrInstGenDeclVar *) {
16321637
return IrInstGenIdDeclVar;
@@ -5030,6 +5035,11 @@ static IrInstGen *ir_build_wasm_memory_grow_gen(IrAnalyze *ira, IrInst *source_i
50305035
return &instruction->base;
50315036
}
50325037

5038+
static IrInstSrc *ir_build_src(IrBuilderSrc *irb, Scope *scope, AstNode *source_node) {
5039+
IrInstSrcSrc *instruction = ir_build_instruction<IrInstSrcSrc>(irb, scope, source_node);
5040+
5041+
return &instruction->base;
5042+
}
50335043

50345044
static void ir_count_defers(IrBuilderSrc *irb, Scope *inner_scope, Scope *outer_scope, size_t *results) {
50355045
results[ReturnKindUnconditional] = 0;
@@ -7450,6 +7460,11 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod
74507460
return ir_gen_union_init_expr(irb, scope, node, union_type_inst, name_inst, init_node,
74517461
lval, result_loc);
74527462
}
7463+
case BuiltinFnIdSrc:
7464+
{
7465+
IrInstSrc *src_inst = ir_build_src(irb, scope, node);
7466+
return ir_lval_wrap(irb, scope, src_inst, lval, result_loc);
7467+
}
74537468
}
74547469
zig_unreachable();
74557470
}
@@ -30859,6 +30874,64 @@ static IrInstGen *ir_analyze_instruction_spill_end(IrAnalyze *ira, IrInstSrcSpil
3085930874
return ir_build_spill_end_gen(ira, &instruction->base.base, begin, operand->value->type);
3086030875
}
3086130876

30877+
static IrInstGen *ir_analyze_instruction_src(IrAnalyze *ira, IrInstSrcSrc *instruction) {
30878+
ZigFn *fn_entry = scope_fn_entry(instruction->base.base.scope);
30879+
if (fn_entry == nullptr) {
30880+
ir_add_error(ira, &instruction->base.base, buf_sprintf("@src outside function"));
30881+
return ira->codegen->invalid_inst_gen;
30882+
}
30883+
30884+
ZigType *u8_ptr = get_pointer_to_type_extra(
30885+
ira->codegen, ira->codegen->builtin_types.entry_u8,
30886+
true, false, PtrLenUnknown,
30887+
0, 0, 0, false);
30888+
ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
30889+
30890+
ZigType *source_location_type = get_builtin_type(ira->codegen, "SourceLocation");
30891+
if (type_resolve(ira->codegen, source_location_type, ResolveStatusSizeKnown)) {
30892+
zig_unreachable();
30893+
}
30894+
30895+
ZigValue *result = ira->codegen->pass1_arena->create<ZigValue>();
30896+
result->special = ConstValSpecialStatic;
30897+
result->type = source_location_type;
30898+
30899+
ZigValue **fields = alloc_const_vals_ptrs(ira->codegen, 4);
30900+
result->data.x_struct.fields = fields;
30901+
30902+
// file: []const u8
30903+
ensure_field_index(source_location_type, "file", 0);
30904+
fields[0]->special = ConstValSpecialStatic;
30905+
fields[0]->type = u8_slice;
30906+
30907+
ZigType *import = instruction->base.base.source_node->owner;
30908+
Buf *path = import->data.structure.root_struct->path;
30909+
ZigValue *file_name = create_const_str_lit(ira->codegen, path)->data.x_ptr.data.ref.pointee;
30910+
init_const_slice(ira->codegen, fields[0], file_name, 0, buf_len(path), true);
30911+
30912+
// fn_name: []const u8
30913+
ensure_field_index(source_location_type, "fn_name", 1);
30914+
fields[1]->special = ConstValSpecialStatic;
30915+
fields[1]->type = u8_slice;
30916+
30917+
ZigValue *fn_name = create_const_str_lit(ira->codegen, &fn_entry->symbol_name)->data.x_ptr.data.ref.pointee;
30918+
init_const_slice(ira->codegen, fields[1], fn_name, 0, buf_len(&fn_entry->symbol_name), true);
30919+
30920+
// line: u32
30921+
ensure_field_index(source_location_type, "line", 2);
30922+
fields[2]->special = ConstValSpecialStatic;
30923+
fields[2]->type = ira->codegen->builtin_types.entry_u32;
30924+
bigint_init_unsigned(&fields[2]->data.x_bigint, instruction->base.base.source_node->line + 1);
30925+
30926+
// column: u32
30927+
ensure_field_index(source_location_type, "column", 3);
30928+
fields[3]->special = ConstValSpecialStatic;
30929+
fields[3]->type = ira->codegen->builtin_types.entry_u32;
30930+
bigint_init_unsigned(&fields[3]->data.x_bigint, instruction->base.base.source_node->column + 1);
30931+
30932+
return ir_const_move(ira, &instruction->base.base, result);
30933+
}
30934+
3086230935
static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruction) {
3086330936
switch (instruction->id) {
3086430937
case IrInstSrcIdInvalid:
@@ -31130,6 +31203,8 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc
3113031203
return ir_analyze_instruction_wasm_memory_size(ira, (IrInstSrcWasmMemorySize *)instruction);
3113131204
case IrInstSrcIdWasmMemoryGrow:
3113231205
return ir_analyze_instruction_wasm_memory_grow(ira, (IrInstSrcWasmMemoryGrow *)instruction);
31206+
case IrInstSrcIdSrc:
31207+
return ir_analyze_instruction_src(ira, (IrInstSrcSrc *)instruction);
3113331208
}
3113431209
zig_unreachable();
3113531210
}
@@ -31525,6 +31600,7 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) {
3152531600
case IrInstSrcIdAlloca:
3152631601
case IrInstSrcIdSpillEnd:
3152731602
case IrInstSrcIdWasmMemorySize:
31603+
case IrInstSrcIdSrc:
3152831604
return false;
3152931605

3153031606
case IrInstSrcIdAsm:

src/ir_print.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,8 @@ const char* ir_inst_src_type_str(IrInstSrcId id) {
325325
return "SrcWasmMemorySize";
326326
case IrInstSrcIdWasmMemoryGrow:
327327
return "SrcWasmMemoryGrow";
328+
case IrInstSrcIdSrc:
329+
return "SrcSrc";
328330
}
329331
zig_unreachable();
330332
}
@@ -1744,6 +1746,10 @@ static void ir_print_wasm_memory_grow(IrPrintGen *irp, IrInstGenWasmMemoryGrow *
17441746
fprintf(irp->f, ")");
17451747
}
17461748

1749+
static void ir_print_builtin_src(IrPrintSrc *irp, IrInstSrcSrc *instruction) {
1750+
fprintf(irp->f, "@src()");
1751+
}
1752+
17471753
static void ir_print_memset(IrPrintSrc *irp, IrInstSrcMemset *instruction) {
17481754
fprintf(irp->f, "@memset(");
17491755
ir_print_other_inst_src(irp, instruction->dest_ptr);
@@ -2994,6 +3000,9 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai
29943000
case IrInstSrcIdWasmMemoryGrow:
29953001
ir_print_wasm_memory_grow(irp, (IrInstSrcWasmMemoryGrow *)instruction);
29963002
break;
3003+
case IrInstSrcIdSrc:
3004+
ir_print_builtin_src(irp, (IrInstSrcSrc *)instruction);
3005+
break;
29973006
}
29983007
fprintf(irp->f, "\n");
29993008
}

test/compile_errors.zig

+8
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@ const tests = @import("tests.zig");
22
const std = @import("std");
33

44
pub fn addCases(cases: *tests.CompileErrorContext) void {
5+
cases.add("@src outside function",
6+
\\comptime {
7+
\\ @src();
8+
\\}
9+
, &[_][]const u8{
10+
"tmp.zig:2:5: error: @src outside function",
11+
});
12+
513
cases.add("call assigned to constant",
614
\\const Foo = struct {
715
\\ x: i32,

test/stage1/behavior.zig

+1
Original file line numberDiff line numberDiff line change
@@ -131,4 +131,5 @@ comptime {
131131
}
132132
_ = @import("behavior/while.zig");
133133
_ = @import("behavior/widening.zig");
134+
_ = @import("behavior/src.zig");
134135
}

test/stage1/behavior/src.zig

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
const std = @import("std");
2+
const expect = std.testing.expect;
3+
4+
test "@src" {
5+
doTheTest();
6+
}
7+
8+
fn doTheTest() void {
9+
const src = @src();
10+
11+
expect(src.line == 9);
12+
expect(src.column == 17);
13+
expect(std.mem.endsWith(u8, src.fn_name, "doTheTest"));
14+
expect(std.mem.endsWith(u8, src.file, "src.zig"));
15+
}

0 commit comments

Comments
 (0)