authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-01 21:57:52-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-05-01 21:57:52-07:00
logeadcefc124b4ee61c99c8ed97434ed26e24c5f83
treee76e08b8c4411a8ef609efdef020e9731e43de4b
parent6248e2a5609cb9e30588f8bcd0000f5d5aa5fdee

stage2: dbg_stmt ZIR instructions have line/col

instead of node indexes. * AstGen: dbg_stmt instructions now have line and column indexes, relative to the parent declaration. This allows codegen to emit debug info without having the source bytes, tokens, or AST nodes loaded in memory. * ZIR: each decl has the absolute line number. This allows computing line numbers from offsets without consulting source code bytes. Memory management: creating a function definition does not prematurely set the Decl arena. Instead the function is allocated with the general purpose allocator. Codegen no longer looks at source code bytes for any reason. They can remain unloaded from disk.

8 files changed, 253 insertions(+), 130 deletions(-)

BRANCH_TODO-1
...@@ -1,4 +1,3 @@...@@ -1,4 +1,3 @@
1 * modify dbg_stmt ZIR instructions to have line/column rather than node indexes
2 * decouple AstGen from Module, Compilation1 * decouple AstGen from Module, Compilation
3 * AstGen threadlocal2 * AstGen threadlocal
4 * extern "foo" for vars and for functions3 * extern "foo" for vars and for functions
src/AstGen.zig+61-12
...@@ -94,6 +94,7 @@ pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir {...@@ -94,6 +94,7 @@ pub fn generate(gpa: *Allocator, file: *Scope.File) InnerError!Zir {
94 .force_comptime = true,94 .force_comptime = true,
95 .parent = &file.base,95 .parent = &file.base,
96 .decl_node_index = 0,96 .decl_node_index = 0,
97 .decl_line = 0,
97 .astgen = &astgen,98 .astgen = &astgen,
98 };99 };
99 defer gen_scope.instructions.deinit(gpa);100 defer gen_scope.instructions.deinit(gpa);
...@@ -2056,7 +2057,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner...@@ -2056,7 +2057,7 @@ fn unusedResultExpr(gz: *GenZir, scope: *Scope, statement: ast.Node.Index) Inner
2056 // ZIR instructions that are always either `noreturn` or `void`.2057 // ZIR instructions that are always either `noreturn` or `void`.
2057 .breakpoint,2058 .breakpoint,
2058 .fence,2059 .fence,
2059 .dbg_stmt_node,2060 .dbg_stmt,
2060 .ensure_result_used,2061 .ensure_result_used,
2061 .ensure_result_non_error,2062 .ensure_result_non_error,
2062 .@"export",2063 .@"export",
...@@ -2395,9 +2396,25 @@ fn varDecl(...@@ -2395,9 +2396,25 @@ fn varDecl(
2395}2396}
23962397
2397fn emitDbgNode(gz: *GenZir, node: ast.Node.Index) !void {2398fn emitDbgNode(gz: *GenZir, node: ast.Node.Index) !void {
2398 if (!gz.force_comptime) {2399 // The instruction emitted here is for debugging runtime code.
2399 _ = try gz.addNode(.dbg_stmt_node, node);2400 // If the current block will be evaluated only during semantic analysis
2400 }2401 // then no dbg_stmt ZIR instruction is needed.
2402 if (gz.force_comptime) return;
2403
2404 const astgen = gz.astgen;
2405 const tree = &astgen.file.tree;
2406 const node_tags = tree.nodes.items(.tag);
2407 const token_starts = tree.tokens.items(.start);
2408 const decl_start = token_starts[tree.firstToken(gz.decl_node_index)];
2409 const node_start = token_starts[tree.firstToken(node)];
2410 const source = tree.source[decl_start..node_start];
2411 const loc = std.zig.findLineColumn(source, source.len);
2412 _ = try gz.add(.{ .tag = .dbg_stmt, .data = .{
2413 .dbg_stmt = .{
2414 .line = @intCast(u32, loc.line),
2415 .column = @intCast(u32, loc.column),
2416 },
2417 } });
2401}2418}
24022419
2403fn assign(gz: *GenZir, scope: *Scope, infix_node: ast.Node.Index) InnerError!void {2420fn assign(gz: *GenZir, scope: *Scope, infix_node: ast.Node.Index) InnerError!void {
...@@ -2689,6 +2706,7 @@ fn fnDecl(...@@ -2689,6 +2706,7 @@ fn fnDecl(
2689 var decl_gz: GenZir = .{2706 var decl_gz: GenZir = .{
2690 .force_comptime = true,2707 .force_comptime = true,
2691 .decl_node_index = fn_proto.ast.proto_node,2708 .decl_node_index = fn_proto.ast.proto_node,
2709 .decl_line = gz.calcLine(decl_node),
2692 .parent = &gz.base,2710 .parent = &gz.base,
2693 .astgen = astgen,2711 .astgen = astgen,
2694 };2712 };
...@@ -2791,7 +2809,7 @@ fn fnDecl(...@@ -2791,7 +2809,7 @@ fn fnDecl(
2791 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});2809 return astgen.failTok(maybe_bang, "function prototype may not have inferred error set", .{});
2792 }2810 }
2793 break :func try decl_gz.addFunc(.{2811 break :func try decl_gz.addFunc(.{
2794 .src_node = fn_proto.ast.proto_node,2812 .src_node = decl_node,
2795 .ret_ty = return_type_inst,2813 .ret_ty = return_type_inst,
2796 .param_types = param_types,2814 .param_types = param_types,
2797 .body = &[0]Zir.Inst.Index{},2815 .body = &[0]Zir.Inst.Index{},
...@@ -2810,6 +2828,7 @@ fn fnDecl(...@@ -2810,6 +2828,7 @@ fn fnDecl(
2810 var fn_gz: GenZir = .{2828 var fn_gz: GenZir = .{
2811 .force_comptime = false,2829 .force_comptime = false,
2812 .decl_node_index = fn_proto.ast.proto_node,2830 .decl_node_index = fn_proto.ast.proto_node,
2831 .decl_line = decl_gz.decl_line,
2813 .parent = &decl_gz.base,2832 .parent = &decl_gz.base,
2814 .astgen = astgen,2833 .astgen = astgen,
2815 };2834 };
...@@ -2866,7 +2885,7 @@ fn fnDecl(...@@ -2866,7 +2885,7 @@ fn fnDecl(
2866 astgen.fn_block = prev_fn_block;2885 astgen.fn_block = prev_fn_block;
28672886
2868 break :func try decl_gz.addFunc(.{2887 break :func try decl_gz.addFunc(.{
2869 .src_node = fn_proto.ast.proto_node,2888 .src_node = decl_node,
2870 .ret_ty = return_type_inst,2889 .ret_ty = return_type_inst,
2871 .param_types = param_types,2890 .param_types = param_types,
2872 .body = fn_gz.instructions.items,2891 .body = fn_gz.instructions.items,
...@@ -2889,12 +2908,16 @@ fn fnDecl(...@@ -2889,12 +2908,16 @@ fn fnDecl(
2889 _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst);2908 _ = try decl_gz.addBreak(.break_inline, block_inst, func_inst);
2890 try decl_gz.setBlockBody(block_inst);2909 try decl_gz.setBlockBody(block_inst);
28912910
2892 try wip_decls.payload.ensureUnusedCapacity(gpa, 8);2911 try wip_decls.payload.ensureUnusedCapacity(gpa, 9);
2893 {2912 {
2894 const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));2913 const contents_hash = std.zig.hashSrc(tree.getNodeSource(decl_node));
2895 const casted = @bitCast([4]u32, contents_hash);2914 const casted = @bitCast([4]u32, contents_hash);
2896 wip_decls.payload.appendSliceAssumeCapacity(&casted);2915 wip_decls.payload.appendSliceAssumeCapacity(&casted);
2897 }2916 }
2917 {
2918 const line_delta = decl_gz.decl_line - gz.decl_line;
2919 wip_decls.payload.appendAssumeCapacity(line_delta);
2920 }
2898 wip_decls.payload.appendAssumeCapacity(fn_name_str_index);2921 wip_decls.payload.appendAssumeCapacity(fn_name_str_index);
2899 wip_decls.payload.appendAssumeCapacity(block_inst);2922 wip_decls.payload.appendAssumeCapacity(block_inst);
2900 if (align_inst != .none) {2923 if (align_inst != .none) {
...@@ -2925,6 +2948,7 @@ fn globalVarDecl(...@@ -2925,6 +2948,7 @@ fn globalVarDecl(
2925 var block_scope: GenZir = .{2948 var block_scope: GenZir = .{
2926 .parent = scope,2949 .parent = scope,
2927 .decl_node_index = node,2950 .decl_node_index = node,
2951 .decl_line = gz.calcLine(node),
2928 .astgen = astgen,2952 .astgen = astgen,
2929 .force_comptime = true,2953 .force_comptime = true,
2930 };2954 };
...@@ -3024,12 +3048,16 @@ fn globalVarDecl(...@@ -3024,12 +3048,16 @@ fn globalVarDecl(
3024 const name_token = var_decl.ast.mut_token + 1;3048 const name_token = var_decl.ast.mut_token + 1;
3025 const name_str_index = try astgen.identAsString(name_token);3049 const name_str_index = try astgen.identAsString(name_token);
30263050
3027 try wip_decls.payload.ensureUnusedCapacity(gpa, 8);3051 try wip_decls.payload.ensureUnusedCapacity(gpa, 9);
3028 {3052 {
3029 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));3053 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
3030 const casted = @bitCast([4]u32, contents_hash);3054 const casted = @bitCast([4]u32, contents_hash);
3031 wip_decls.payload.appendSliceAssumeCapacity(&casted);3055 wip_decls.payload.appendSliceAssumeCapacity(&casted);
3032 }3056 }
3057 {
3058 const line_delta = block_scope.decl_line - gz.decl_line;
3059 wip_decls.payload.appendAssumeCapacity(line_delta);
3060 }
3033 wip_decls.payload.appendAssumeCapacity(name_str_index);3061 wip_decls.payload.appendAssumeCapacity(name_str_index);
3034 wip_decls.payload.appendAssumeCapacity(block_inst);3062 wip_decls.payload.appendAssumeCapacity(block_inst);
3035 if (align_inst != .none) {3063 if (align_inst != .none) {
...@@ -3060,6 +3088,7 @@ fn comptimeDecl(...@@ -3060,6 +3088,7 @@ fn comptimeDecl(
3060 var decl_block: GenZir = .{3088 var decl_block: GenZir = .{
3061 .force_comptime = true,3089 .force_comptime = true,
3062 .decl_node_index = node,3090 .decl_node_index = node,
3091 .decl_line = gz.calcLine(node),
3063 .parent = scope,3092 .parent = scope,
3064 .astgen = astgen,3093 .astgen = astgen,
3065 };3094 };
...@@ -3071,12 +3100,16 @@ fn comptimeDecl(...@@ -3071,12 +3100,16 @@ fn comptimeDecl(
3071 }3100 }
3072 try decl_block.setBlockBody(block_inst);3101 try decl_block.setBlockBody(block_inst);
30733102
3074 try wip_decls.payload.ensureUnusedCapacity(gpa, 6);3103 try wip_decls.payload.ensureUnusedCapacity(gpa, 7);
3075 {3104 {
3076 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));3105 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
3077 const casted = @bitCast([4]u32, contents_hash);3106 const casted = @bitCast([4]u32, contents_hash);
3078 wip_decls.payload.appendSliceAssumeCapacity(&casted);3107 wip_decls.payload.appendSliceAssumeCapacity(&casted);
3079 }3108 }
3109 {
3110 const line_delta = decl_block.decl_line - gz.decl_line;
3111 wip_decls.payload.appendAssumeCapacity(line_delta);
3112 }
3080 wip_decls.payload.appendAssumeCapacity(0);3113 wip_decls.payload.appendAssumeCapacity(0);
3081 wip_decls.payload.appendAssumeCapacity(block_inst);3114 wip_decls.payload.appendAssumeCapacity(block_inst);
3082}3115}
...@@ -3107,6 +3140,7 @@ fn usingnamespaceDecl(...@@ -3107,6 +3140,7 @@ fn usingnamespaceDecl(
3107 var decl_block: GenZir = .{3140 var decl_block: GenZir = .{
3108 .force_comptime = true,3141 .force_comptime = true,
3109 .decl_node_index = node,3142 .decl_node_index = node,
3143 .decl_line = gz.calcLine(node),
3110 .parent = scope,3144 .parent = scope,
3111 .astgen = astgen,3145 .astgen = astgen,
3112 };3146 };
...@@ -3116,12 +3150,16 @@ fn usingnamespaceDecl(...@@ -3116,12 +3150,16 @@ fn usingnamespaceDecl(
3116 _ = try decl_block.addBreak(.break_inline, block_inst, namespace_inst);3150 _ = try decl_block.addBreak(.break_inline, block_inst, namespace_inst);
3117 try decl_block.setBlockBody(block_inst);3151 try decl_block.setBlockBody(block_inst);
31183152
3119 try wip_decls.payload.ensureUnusedCapacity(gpa, 6);3153 try wip_decls.payload.ensureUnusedCapacity(gpa, 7);
3120 {3154 {
3121 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));3155 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
3122 const casted = @bitCast([4]u32, contents_hash);3156 const casted = @bitCast([4]u32, contents_hash);
3123 wip_decls.payload.appendSliceAssumeCapacity(&casted);3157 wip_decls.payload.appendSliceAssumeCapacity(&casted);
3124 }3158 }
3159 {
3160 const line_delta = decl_block.decl_line - gz.decl_line;
3161 wip_decls.payload.appendAssumeCapacity(line_delta);
3162 }
3125 wip_decls.payload.appendAssumeCapacity(0);3163 wip_decls.payload.appendAssumeCapacity(0);
3126 wip_decls.payload.appendAssumeCapacity(block_inst);3164 wip_decls.payload.appendAssumeCapacity(block_inst);
3127}3165}
...@@ -3147,6 +3185,7 @@ fn testDecl(...@@ -3147,6 +3185,7 @@ fn testDecl(
3147 var decl_block: GenZir = .{3185 var decl_block: GenZir = .{
3148 .force_comptime = true,3186 .force_comptime = true,
3149 .decl_node_index = node,3187 .decl_node_index = node,
3188 .decl_line = gz.calcLine(node),
3150 .parent = scope,3189 .parent = scope,
3151 .astgen = astgen,3190 .astgen = astgen,
3152 };3191 };
...@@ -3167,6 +3206,7 @@ fn testDecl(...@@ -3167,6 +3206,7 @@ fn testDecl(
3167 var fn_block: GenZir = .{3206 var fn_block: GenZir = .{
3168 .force_comptime = false,3207 .force_comptime = false,
3169 .decl_node_index = node,3208 .decl_node_index = node,
3209 .decl_line = decl_block.decl_line,
3170 .parent = &decl_block.base,3210 .parent = &decl_block.base,
3171 .astgen = astgen,3211 .astgen = astgen,
3172 };3212 };
...@@ -3200,12 +3240,16 @@ fn testDecl(...@@ -3200,12 +3240,16 @@ fn testDecl(
3200 _ = try decl_block.addBreak(.break_inline, block_inst, func_inst);3240 _ = try decl_block.addBreak(.break_inline, block_inst, func_inst);
3201 try decl_block.setBlockBody(block_inst);3241 try decl_block.setBlockBody(block_inst);
32023242
3203 try wip_decls.payload.ensureUnusedCapacity(gpa, 6);3243 try wip_decls.payload.ensureUnusedCapacity(gpa, 7);
3204 {3244 {
3205 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));3245 const contents_hash = std.zig.hashSrc(tree.getNodeSource(node));
3206 const casted = @bitCast([4]u32, contents_hash);3246 const casted = @bitCast([4]u32, contents_hash);
3207 wip_decls.payload.appendSliceAssumeCapacity(&casted);3247 wip_decls.payload.appendSliceAssumeCapacity(&casted);
3208 }3248 }
3249 {
3250 const line_delta = decl_block.decl_line - gz.decl_line;
3251 wip_decls.payload.appendAssumeCapacity(line_delta);
3252 }
3209 wip_decls.payload.appendAssumeCapacity(test_name);3253 wip_decls.payload.appendAssumeCapacity(test_name);
3210 wip_decls.payload.appendAssumeCapacity(block_inst);3254 wip_decls.payload.appendAssumeCapacity(block_inst);
3211}3255}
...@@ -3237,6 +3281,7 @@ fn structDeclInner(...@@ -3237,6 +3281,7 @@ fn structDeclInner(
3237 var block_scope: GenZir = .{3281 var block_scope: GenZir = .{
3238 .parent = scope,3282 .parent = scope,
3239 .decl_node_index = node,3283 .decl_node_index = node,
3284 .decl_line = gz.calcLine(node),
3240 .astgen = astgen,3285 .astgen = astgen,
3241 .force_comptime = true,3286 .force_comptime = true,
3242 .ref_start_index = gz.ref_start_index,3287 .ref_start_index = gz.ref_start_index,
...@@ -3448,6 +3493,7 @@ fn unionDeclInner(...@@ -3448,6 +3493,7 @@ fn unionDeclInner(
3448 var block_scope: GenZir = .{3493 var block_scope: GenZir = .{
3449 .parent = scope,3494 .parent = scope,
3450 .decl_node_index = node,3495 .decl_node_index = node,
3496 .decl_line = gz.calcLine(node),
3451 .astgen = astgen,3497 .astgen = astgen,
3452 .force_comptime = true,3498 .force_comptime = true,
3453 .ref_start_index = gz.ref_start_index,3499 .ref_start_index = gz.ref_start_index,
...@@ -3797,6 +3843,7 @@ fn containerDecl(...@@ -3797,6 +3843,7 @@ fn containerDecl(
3797 var block_scope: GenZir = .{3843 var block_scope: GenZir = .{
3798 .parent = scope,3844 .parent = scope,
3799 .decl_node_index = node,3845 .decl_node_index = node,
3846 .decl_line = gz.calcLine(node),
3800 .astgen = astgen,3847 .astgen = astgen,
3801 .force_comptime = true,3848 .force_comptime = true,
3802 .ref_start_index = gz.ref_start_index,3849 .ref_start_index = gz.ref_start_index,
...@@ -4464,7 +4511,9 @@ fn boolBinOp(...@@ -4464,7 +4511,9 @@ fn boolBinOp(
4464 node: ast.Node.Index,4511 node: ast.Node.Index,
4465 zir_tag: Zir.Inst.Tag,4512 zir_tag: Zir.Inst.Tag,
4466) InnerError!Zir.Inst.Ref {4513) InnerError!Zir.Inst.Ref {
4467 const node_datas = gz.tree().nodes.items(.data);4514 const astgen = gz.astgen;
4515 const tree = &astgen.file.tree;
4516 const node_datas = tree.nodes.items(.data);
44684517
4469 const lhs = try expr(gz, scope, bool_rl, node_datas[node].lhs);4518 const lhs = try expr(gz, scope, bool_rl, node_datas[node].lhs);
4470 const bool_br = try gz.addBoolBr(zir_tag, lhs);4519 const bool_br = try gz.addBoolBr(zir_tag, lhs);
src/Module.zig+79-16
...@@ -182,9 +182,12 @@ pub const Decl = struct {...@@ -182,9 +182,12 @@ pub const Decl = struct {
182 /// The AST node index of this declaration.182 /// The AST node index of this declaration.
183 /// Must be recomputed when the corresponding source file is modified.183 /// Must be recomputed when the corresponding source file is modified.
184 src_node: ast.Node.Index,184 src_node: ast.Node.Index,
185 /// Line number corresponding to `src_node`. Stored separately so that source files
186 /// do not need to be loaded into memory in order to compute debug line numbers.
187 src_line: u32,
185 /// Index to ZIR `extra` array to the entry in the parent's decl structure188 /// Index to ZIR `extra` array to the entry in the parent's decl structure
186 /// (the part that says "for every decls_len"). The first item at this index is189 /// (the part that says "for every decls_len"). The first item at this index is
187 /// the contents hash, followed by the name.190 /// the contents hash, followed by line, name, etc.
188 zir_decl_index: Zir.Inst.Index,191 zir_decl_index: Zir.Inst.Index,
189192
190 /// Represents the "shallow" analysis status. For example, for decls that are functions,193 /// Represents the "shallow" analysis status. For example, for decls that are functions,
...@@ -282,6 +285,7 @@ pub const Decl = struct {...@@ -282,6 +285,7 @@ pub const Decl = struct {
282 if (decl.val.castTag(.function)) |payload| {285 if (decl.val.castTag(.function)) |payload| {
283 const func = payload.data;286 const func = payload.data;
284 func.deinit(gpa);287 func.deinit(gpa);
288 gpa.destroy(func);
285 } else if (decl.val.getTypeNamespace()) |namespace| {289 } else if (decl.val.getTypeNamespace()) |namespace| {
286 if (namespace.getDecl() == decl) {290 if (namespace.getDecl() == decl) {
287 namespace.clearDecls(module);291 namespace.clearDecls(module);
...@@ -323,7 +327,7 @@ pub const Decl = struct {...@@ -323,7 +327,7 @@ pub const Decl = struct {
323 }327 }
324328
325 pub fn getNameZir(decl: Decl, zir: Zir) ?[:0]const u8 {329 pub fn getNameZir(decl: Decl, zir: Zir) ?[:0]const u8 {
326 const name_index = zir.extra[decl.zir_decl_index + 4];330 const name_index = zir.extra[decl.zir_decl_index + 5];
327 if (name_index <= 1) return null;331 if (name_index <= 1) return null;
328 return zir.nullTerminatedString(name_index);332 return zir.nullTerminatedString(name_index);
329 }333 }
...@@ -341,7 +345,7 @@ pub const Decl = struct {...@@ -341,7 +345,7 @@ pub const Decl = struct {
341345
342 pub fn zirBlockIndex(decl: Decl) Zir.Inst.Index {346 pub fn zirBlockIndex(decl: Decl) Zir.Inst.Index {
343 const zir = decl.namespace.file_scope.zir;347 const zir = decl.namespace.file_scope.zir;
344 return zir.extra[decl.zir_decl_index + 5];348 return zir.extra[decl.zir_decl_index + 6];
345 }349 }
346350
347 pub fn zirAlignRef(decl: Decl) Zir.Inst.Ref {351 pub fn zirAlignRef(decl: Decl) Zir.Inst.Ref {
...@@ -357,6 +361,10 @@ pub const Decl = struct {...@@ -357,6 +361,10 @@ pub const Decl = struct {
357 return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);361 return @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
358 }362 }
359363
364 pub fn relativeToLine(decl: Decl, offset: u32) u32 {
365 return decl.src_line + offset;
366 }
367
360 pub fn relativeToNodeIndex(decl: Decl, offset: i32) ast.Node.Index {368 pub fn relativeToNodeIndex(decl: Decl, offset: i32) ast.Node.Index {
361 return @bitCast(ast.Node.Index, offset + @bitCast(i32, decl.src_node));369 return @bitCast(ast.Node.Index, offset + @bitCast(i32, decl.src_node));
362 }370 }
...@@ -565,13 +573,21 @@ pub const EnumFull = struct {...@@ -565,13 +573,21 @@ pub const EnumFull = struct {
565/// the `Decl` only, with a `Value` tag of `extern_fn`.573/// the `Decl` only, with a `Value` tag of `extern_fn`.
566pub const Fn = struct {574pub const Fn = struct {
567 owner_decl: *Decl,575 owner_decl: *Decl,
576 /// undefined unless analysis state is `success`.
577 body: ir.Body,
568 /// The ZIR instruction that is a function instruction. Use this to find578 /// The ZIR instruction that is a function instruction. Use this to find
569 /// the body. We store this rather than the body directly so that when ZIR579 /// the body. We store this rather than the body directly so that when ZIR
570 /// is regenerated on update(), we can map this to the new corresponding580 /// is regenerated on update(), we can map this to the new corresponding
571 /// ZIR instruction.581 /// ZIR instruction.
572 zir_body_inst: Zir.Inst.Index,582 zir_body_inst: Zir.Inst.Index,
573 /// undefined unless analysis state is `success`.583
574 body: ir.Body,584 /// Relative to owner Decl.
585 lbrace_line: u32,
586 /// Relative to owner Decl.
587 rbrace_line: u32,
588 lbrace_column: u16,
589 rbrace_column: u16,
590
575 state: Analysis,591 state: Analysis,
576592
577 pub const Analysis = enum {593 pub const Analysis = enum {
...@@ -1130,7 +1146,7 @@ pub const Scope = struct {...@@ -1130,7 +1146,7 @@ pub const Scope = struct {
1130 return &inst.base;1146 return &inst.base;
1131 }1147 }
11321148
1133 pub fn addDbgStmt(block: *Scope.Block, src: LazySrcLoc, abs_byte_off: u32) !*ir.Inst {1149 pub fn addDbgStmt(block: *Scope.Block, src: LazySrcLoc, line: u32, column: u32) !*ir.Inst {
1134 const inst = try block.sema.arena.create(ir.Inst.DbgStmt);1150 const inst = try block.sema.arena.create(ir.Inst.DbgStmt);
1135 inst.* = .{1151 inst.* = .{
1136 .base = .{1152 .base = .{
...@@ -1138,7 +1154,8 @@ pub const Scope = struct {...@@ -1138,7 +1154,8 @@ pub const Scope = struct {
1138 .ty = Type.initTag(.void),1154 .ty = Type.initTag(.void),
1139 .src = src,1155 .src = src,
1140 },1156 },
1141 .byte_offset = abs_byte_off,1157 .line = line,
1158 .column = column,
1142 };1159 };
1143 try block.instructions.append(block.sema.gpa, &inst.base);1160 try block.instructions.append(block.sema.gpa, &inst.base);
1144 return &inst.base;1161 return &inst.base;
...@@ -1177,6 +1194,8 @@ pub const Scope = struct {...@@ -1177,6 +1194,8 @@ pub const Scope = struct {
1177 ref_start_index: u32 = Zir.Inst.Ref.typed_value_map.len,1194 ref_start_index: u32 = Zir.Inst.Ref.typed_value_map.len,
1178 /// The containing decl AST node.1195 /// The containing decl AST node.
1179 decl_node_index: ast.Node.Index,1196 decl_node_index: ast.Node.Index,
1197 /// The containing decl line index, absolute.
1198 decl_line: u32,
1180 /// Parents can be: `GenZir`, `File`1199 /// Parents can be: `GenZir`, `File`
1181 parent: *Scope,1200 parent: *Scope,
1182 /// All `GenZir` scopes for the same ZIR share this.1201 /// All `GenZir` scopes for the same ZIR share this.
...@@ -1218,6 +1237,7 @@ pub const Scope = struct {...@@ -1218,6 +1237,7 @@ pub const Scope = struct {
1218 .force_comptime = gz.force_comptime,1237 .force_comptime = gz.force_comptime,
1219 .ref_start_index = gz.ref_start_index,1238 .ref_start_index = gz.ref_start_index,
1220 .decl_node_index = gz.decl_node_index,1239 .decl_node_index = gz.decl_node_index,
1240 .decl_line = gz.decl_line,
1221 .parent = scope,1241 .parent = scope,
1222 .astgen = gz.astgen,1242 .astgen = gz.astgen,
1223 .suspend_node = gz.suspend_node,1243 .suspend_node = gz.suspend_node,
...@@ -1239,6 +1259,18 @@ pub const Scope = struct {...@@ -1239,6 +1259,18 @@ pub const Scope = struct {
1239 return false;1259 return false;
1240 }1260 }
12411261
1262 pub fn calcLine(gz: GenZir, node: ast.Node.Index) u32 {
1263 const astgen = gz.astgen;
1264 const tree = &astgen.file.tree;
1265 const node_tags = tree.nodes.items(.tag);
1266 const token_starts = tree.tokens.items(.start);
1267 const decl_start = token_starts[tree.firstToken(gz.decl_node_index)];
1268 const node_start = token_starts[tree.firstToken(node)];
1269 const source = tree.source[decl_start..node_start];
1270 const loc = std.zig.findLineColumn(source, source.len);
1271 return @intCast(u32, gz.decl_line + loc.line);
1272 }
1273
1242 pub fn tokSrcLoc(gz: GenZir, token_index: ast.TokenIndex) LazySrcLoc {1274 pub fn tokSrcLoc(gz: GenZir, token_index: ast.TokenIndex) LazySrcLoc {
1243 return .{ .token_offset = token_index - gz.srcToken() };1275 return .{ .token_offset = token_index - gz.srcToken() };
1244 }1276 }
...@@ -1259,10 +1291,6 @@ pub const Scope = struct {...@@ -1259,10 +1291,6 @@ pub const Scope = struct {
1259 return gz.astgen.file.tree.firstToken(gz.decl_node_index);1291 return gz.astgen.file.tree.firstToken(gz.decl_node_index);
1260 }1292 }
12611293
1262 pub fn tree(gz: *const GenZir) *const ast.Tree {
1263 return &gz.astgen.file.tree;
1264 }
1265
1266 pub fn indexToRef(gz: GenZir, inst: Zir.Inst.Index) Zir.Inst.Ref {1294 pub fn indexToRef(gz: GenZir, inst: Zir.Inst.Index) Zir.Inst.Ref {
1267 return @intToEnum(Zir.Inst.Ref, gz.ref_start_index + inst);1295 return @intToEnum(Zir.Inst.Ref, gz.ref_start_index + inst);
1268 }1296 }
...@@ -1376,13 +1404,40 @@ pub const Scope = struct {...@@ -1376,13 +1404,40 @@ pub const Scope = struct {
1376 try gz.instructions.ensureUnusedCapacity(gpa, 1);1404 try gz.instructions.ensureUnusedCapacity(gpa, 1);
1377 try astgen.instructions.ensureUnusedCapacity(gpa, 1);1405 try astgen.instructions.ensureUnusedCapacity(gpa, 1);
13781406
1407 var src_locs_buffer: [3]u32 = undefined;
1408 var src_locs: []u32 = src_locs_buffer[0..0];
1409 if (args.body.len != 0) {
1410 const tree = &astgen.file.tree;
1411 const node_tags = tree.nodes.items(.tag);
1412 const node_datas = tree.nodes.items(.data);
1413 const token_starts = tree.tokens.items(.start);
1414 const decl_start = token_starts[tree.firstToken(gz.decl_node_index)];
1415 const fn_decl = args.src_node;
1416 assert(node_tags[fn_decl] == .fn_decl or node_tags[fn_decl] == .test_decl);
1417 const block = node_datas[fn_decl].rhs;
1418 const lbrace_start = token_starts[tree.firstToken(block)];
1419 const rbrace_start = token_starts[tree.lastToken(block)];
1420 const lbrace_source = tree.source[decl_start..lbrace_start];
1421 const lbrace_loc = std.zig.findLineColumn(lbrace_source, lbrace_source.len);
1422 const rbrace_source = tree.source[lbrace_start..rbrace_start];
1423 const rbrace_loc = std.zig.findLineColumn(rbrace_source, rbrace_source.len);
1424 const lbrace_line = @intCast(u32, lbrace_loc.line);
1425 const rbrace_line = lbrace_line + @intCast(u32, rbrace_loc.line);
1426 const columns = @intCast(u32, lbrace_loc.column) |
1427 (@intCast(u32, rbrace_loc.column) << 16);
1428 src_locs_buffer[0] = lbrace_line;
1429 src_locs_buffer[1] = rbrace_line;
1430 src_locs_buffer[2] = columns;
1431 src_locs = &src_locs_buffer;
1432 }
1433
1379 if (args.cc != .none or args.lib_name != 0 or1434 if (args.cc != .none or args.lib_name != 0 or
1380 args.is_var_args or args.is_test or args.align_inst != .none)1435 args.is_var_args or args.is_test or args.align_inst != .none)
1381 {1436 {
1382 try astgen.extra.ensureUnusedCapacity(1437 try astgen.extra.ensureUnusedCapacity(
1383 gpa,1438 gpa,
1384 @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len +1439 @typeInfo(Zir.Inst.ExtendedFunc).Struct.fields.len +
1385 args.param_types.len + args.body.len +1440 args.param_types.len + args.body.len + src_locs.len +
1386 @boolToInt(args.lib_name != 0) +1441 @boolToInt(args.lib_name != 0) +
1387 @boolToInt(args.align_inst != .none) +1442 @boolToInt(args.align_inst != .none) +
1388 @boolToInt(args.cc != .none),1443 @boolToInt(args.cc != .none),
...@@ -1404,6 +1459,7 @@ pub const Scope = struct {...@@ -1404,6 +1459,7 @@ pub const Scope = struct {
1404 }1459 }
1405 astgen.appendRefsAssumeCapacity(args.param_types);1460 astgen.appendRefsAssumeCapacity(args.param_types);
1406 astgen.extra.appendSliceAssumeCapacity(args.body);1461 astgen.extra.appendSliceAssumeCapacity(args.body);
1462 astgen.extra.appendSliceAssumeCapacity(src_locs);
14071463
1408 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);1464 const new_index = @intCast(Zir.Inst.Index, astgen.instructions.len);
1409 astgen.instructions.appendAssumeCapacity(.{1465 astgen.instructions.appendAssumeCapacity(.{
...@@ -1427,7 +1483,7 @@ pub const Scope = struct {...@@ -1427,7 +1483,7 @@ pub const Scope = struct {
1427 try gz.astgen.extra.ensureUnusedCapacity(1483 try gz.astgen.extra.ensureUnusedCapacity(
1428 gpa,1484 gpa,
1429 @typeInfo(Zir.Inst.Func).Struct.fields.len +1485 @typeInfo(Zir.Inst.Func).Struct.fields.len +
1430 args.param_types.len + args.body.len,1486 args.param_types.len + args.body.len + src_locs.len,
1431 );1487 );
14321488
1433 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Func{1489 const payload_index = gz.astgen.addExtraAssumeCapacity(Zir.Inst.Func{
...@@ -1437,6 +1493,7 @@ pub const Scope = struct {...@@ -1437,6 +1493,7 @@ pub const Scope = struct {
1437 });1493 });
1438 gz.astgen.appendRefsAssumeCapacity(args.param_types);1494 gz.astgen.appendRefsAssumeCapacity(args.param_types);
1439 gz.astgen.extra.appendSliceAssumeCapacity(args.body);1495 gz.astgen.extra.appendSliceAssumeCapacity(args.body);
1496 gz.astgen.extra.appendSliceAssumeCapacity(src_locs);
14401497
1441 const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func;1498 const tag: Zir.Inst.Tag = if (args.is_inferred_error) .func_inferred else .func;
1442 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);1499 const new_index = @intCast(Zir.Inst.Index, gz.astgen.instructions.len);
...@@ -3297,6 +3354,7 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {...@@ -3297,6 +3354,7 @@ pub fn semaFile(mod: *Module, file: *Scope.File) InnerError!void {
3297 file.namespace = &struct_obj.namespace;3354 file.namespace = &struct_obj.namespace;
3298 const new_decl = try mod.allocateNewDecl(&struct_obj.namespace, 0);3355 const new_decl = try mod.allocateNewDecl(&struct_obj.namespace, 0);
3299 struct_obj.owner_decl = new_decl;3356 struct_obj.owner_decl = new_decl;
3357 new_decl.src_line = 0;
3300 new_decl.name = try file.fullyQualifiedNameZ(gpa);3358 new_decl.name = try file.fullyQualifiedNameZ(gpa);
3301 new_decl.is_pub = true;3359 new_decl.is_pub = true;
3302 new_decl.is_exported = false;3360 new_decl.is_exported = false;
...@@ -3694,7 +3752,7 @@ pub fn scanNamespace(...@@ -3694,7 +3752,7 @@ pub fn scanNamespace(
3694 cur_bit_bag >>= 4;3752 cur_bit_bag >>= 4;
36953753
3696 const decl_sub_index = extra_index;3754 const decl_sub_index = extra_index;
3697 extra_index += 6;3755 extra_index += 7; // src_hash(4) + line(1) + name(1) + value(1)
3698 extra_index += @truncate(u1, flags >> 2);3756 extra_index += @truncate(u1, flags >> 2);
3699 extra_index += @truncate(u1, flags >> 3);3757 extra_index += @truncate(u1, flags >> 3);
37003758
...@@ -3752,8 +3810,9 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo...@@ -3752,8 +3810,9 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo
3752 const has_linksection = (flags & 0b1000) != 0;3810 const has_linksection = (flags & 0b1000) != 0;
3753 // zig fmt: on3811 // zig fmt: on
37543812
3755 const decl_name_index = zir.extra[decl_sub_index + 4];3813 const line = iter.parent_decl.relativeToLine(zir.extra[decl_sub_index + 4]);
3756 const decl_index = zir.extra[decl_sub_index + 5];3814 const decl_name_index = zir.extra[decl_sub_index + 5];
3815 const decl_index = zir.extra[decl_sub_index + 6];
3757 const decl_block_inst_data = zir.instructions.items(.data)[decl_index].pl_node;3816 const decl_block_inst_data = zir.instructions.items(.data)[decl_index].pl_node;
3758 const decl_node = iter.parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node);3817 const decl_node = iter.parent_decl.relativeToNodeIndex(decl_block_inst_data.src_node);
37593818
...@@ -3783,6 +3842,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo...@@ -3783,6 +3842,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo
3783 const gop = try namespace.decls.getOrPut(gpa, decl_name);3842 const gop = try namespace.decls.getOrPut(gpa, decl_name);
3784 if (!gop.found_existing) {3843 if (!gop.found_existing) {
3785 const new_decl = try mod.allocateNewDecl(namespace, decl_node);3844 const new_decl = try mod.allocateNewDecl(namespace, decl_node);
3845 new_decl.src_line = line;
3786 new_decl.name = decl_name;3846 new_decl.name = decl_name;
3787 gop.entry.value = new_decl;3847 gop.entry.value = new_decl;
3788 // Exported decls, comptime decls, usingnamespace decls, and3848 // Exported decls, comptime decls, usingnamespace decls, and
...@@ -3807,6 +3867,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo...@@ -3807,6 +3867,7 @@ fn scanDecl(iter: *ScanDeclIter, decl_sub_index: usize, flags: u4) InnerError!vo
3807 // have been re-ordered.3867 // have been re-ordered.
3808 const prev_src_node = decl.src_node;3868 const prev_src_node = decl.src_node;
3809 decl.src_node = decl_node;3869 decl.src_node = decl_node;
3870 decl.src_line = line;
38103871
3811 decl.is_pub = is_pub;3872 decl.is_pub = is_pub;
3812 decl.is_exported = is_exported;3873 decl.is_exported = is_exported;
...@@ -4056,6 +4117,7 @@ fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: ast.Node...@@ -4056,6 +4117,7 @@ fn allocateNewDecl(mod: *Module, namespace: *Scope.Namespace, src_node: ast.Node
4056 .name = "",4117 .name = "",
4057 .namespace = namespace,4118 .namespace = namespace,
4058 .src_node = src_node,4119 .src_node = src_node,
4120 .src_line = undefined,
4059 .has_tv = false,4121 .has_tv = false,
4060 .ty = undefined,4122 .ty = undefined,
4061 .val = undefined,4123 .val = undefined,
...@@ -4292,6 +4354,7 @@ pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue)...@@ -4292,6 +4354,7 @@ pub fn createAnonymousDecl(mod: *Module, scope: *Scope, typed_value: TypedValue)
4292 const new_decl = try mod.allocateNewDecl(namespace, scope_decl.src_node);4354 const new_decl = try mod.allocateNewDecl(namespace, scope_decl.src_node);
4293 namespace.decls.putAssumeCapacityNoClobber(name, new_decl);4355 namespace.decls.putAssumeCapacityNoClobber(name, new_decl);
42944356
4357 new_decl.src_line = scope_decl.src_line;
4295 new_decl.name = name;4358 new_decl.name = name;
4296 new_decl.ty = typed_value.ty;4359 new_decl.ty = typed_value.ty;
4297 new_decl.val = typed_value.val;4360 new_decl.val = typed_value.val;
src/Sema.zig+29-21
...@@ -397,8 +397,8 @@ pub fn analyzeBody(...@@ -397,8 +397,8 @@ pub fn analyzeBody(
397 try sema.zirFence(block, inst);397 try sema.zirFence(block, inst);
398 continue;398 continue;
399 },399 },
400 .dbg_stmt_node => {400 .dbg_stmt => {
401 try sema.zirDbgStmtNode(block, inst);401 try sema.zirDbgStmt(block, inst);
402 continue;402 continue;
403 },403 },
404 .ensure_err_payload_void => {404 .ensure_err_payload_void => {
...@@ -1920,7 +1920,7 @@ fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: Zir.Inst.Index) InnerE...@@ -1920,7 +1920,7 @@ fn zirBreak(sema: *Sema, start_block: *Scope.Block, inst: Zir.Inst.Index) InnerE
1920 }1920 }
1921}1921}
19221922
1923fn zirDbgStmtNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {1923fn zirDbgStmt(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!void {
1924 const tracy = trace(@src());1924 const tracy = trace(@src());
1925 defer tracy.end();1925 defer tracy.end();
19261926
...@@ -1930,14 +1930,8 @@ fn zirDbgStmtNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerE...@@ -1930,14 +1930,8 @@ fn zirDbgStmtNode(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerE
1930 // instructions.1930 // instructions.
1931 if (block.is_comptime) return;1931 if (block.is_comptime) return;
19321932
1933 const src_node = sema.code.instructions.items(.data)[inst].node;1933 const inst_data = sema.code.instructions.items(.data)[inst].dbg_stmt;
1934 const src: LazySrcLoc = .{ .node_offset = src_node };1934 _ = try block.addDbgStmt(.unneeded, inst_data.line, inst_data.column);
1935
1936 const src_loc = src.toSrcLoc(&block.base);
1937 const abs_byte_off = src_loc.byteOffset(sema.gpa) catch |err| {
1938 return sema.mod.fail(&block.base, src, "TODO modify dbg_stmt ZIR instructions to have line/column rather than node indexes. {s}", .{@errorName(err)});
1939 };
1940 _ = try block.addDbgStmt(src, abs_byte_off);
1941}1935}
19421936
1943fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {1937fn zirDeclRef(sema: *Sema, block: *Scope.Block, inst: Zir.Inst.Index) InnerError!*Inst {
...@@ -2793,7 +2787,14 @@ fn zirFunc(...@@ -2793,7 +2787,14 @@ fn zirFunc(
2793 const src = inst_data.src();2787 const src = inst_data.src();
2794 const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);2788 const extra = sema.code.extraData(Zir.Inst.Func, inst_data.payload_index);
2795 const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len);2789 const param_types = sema.code.refSlice(extra.end, extra.data.param_types_len);
2796 const body_inst = if (extra.data.body_len != 0) inst else 0;2790
2791 var body_inst: Zir.Inst.Index = 0;
2792 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
2793 if (extra.data.body_len != 0) {
2794 body_inst = inst;
2795 const extra_index = extra.end + extra.data.param_types_len + extra.data.body_len;
2796 src_locs = sema.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
2797 }
27972798
2798 return sema.funcCommon(2799 return sema.funcCommon(
2799 block,2800 block,
...@@ -2805,6 +2806,7 @@ fn zirFunc(...@@ -2805,6 +2806,7 @@ fn zirFunc(
2805 Value.initTag(.null_value),2806 Value.initTag(.null_value),
2806 false,2807 false,
2807 inferred_error_set,2808 inferred_error_set,
2809 src_locs,
2808 );2810 );
2809}2811}
28102812
...@@ -2819,6 +2821,7 @@ fn funcCommon(...@@ -2819,6 +2821,7 @@ fn funcCommon(
2819 align_val: Value,2821 align_val: Value,
2820 var_args: bool,2822 var_args: bool,
2821 inferred_error_set: bool,2823 inferred_error_set: bool,
2824 src_locs: Zir.Inst.Func.SrcLocs,
2822) InnerError!*Inst {2825) InnerError!*Inst {
2823 const src: LazySrcLoc = .{ .node_offset = src_node_offset };2826 const src: LazySrcLoc = .{ .node_offset = src_node_offset };
2824 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };2827 const ret_ty_src: LazySrcLoc = .{ .node_offset_fn_type_ret_ty = src_node_offset };
...@@ -2872,18 +2875,17 @@ fn funcCommon(...@@ -2872,18 +2875,17 @@ fn funcCommon(
2872 const is_inline = fn_ty.fnCallingConvention() == .Inline;2875 const is_inline = fn_ty.fnCallingConvention() == .Inline;
2873 const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .queued;2876 const anal_state: Module.Fn.Analysis = if (is_inline) .inline_only else .queued;
28742877
2875 // Use the Decl's arena for function memory.2878 const fn_payload = try sema.arena.create(Value.Payload.Function);
2876 var fn_arena = std.heap.ArenaAllocator.init(sema.gpa);2879 const new_func = try sema.gpa.create(Module.Fn);
2877 errdefer fn_arena.deinit();
2878
2879 const new_func = try fn_arena.allocator.create(Module.Fn);
2880 const fn_payload = try fn_arena.allocator.create(Value.Payload.Function);
2881
2882 new_func.* = .{2880 new_func.* = .{
2883 .state = anal_state,2881 .state = anal_state,
2884 .zir_body_inst = body_inst,2882 .zir_body_inst = body_inst,
2885 .owner_decl = sema.owner_decl,2883 .owner_decl = sema.owner_decl,
2886 .body = undefined,2884 .body = undefined,
2885 .lbrace_line = src_locs.lbrace_line,
2886 .rbrace_line = src_locs.rbrace_line,
2887 .lbrace_column = @truncate(u16, src_locs.columns),
2888 .rbrace_column = @truncate(u16, src_locs.columns >> 16),
2887 };2889 };
2888 fn_payload.* = .{2890 fn_payload.* = .{
2889 .base = .{ .tag = .function },2891 .base = .{ .tag = .function },
...@@ -2893,7 +2895,6 @@ fn funcCommon(...@@ -2893,7 +2895,6 @@ fn funcCommon(
2893 .ty = fn_ty,2895 .ty = fn_ty,
2894 .val = Value.initPayload(&fn_payload.base),2896 .val = Value.initPayload(&fn_payload.base),
2895 });2897 });
2896 try sema.owner_decl.finalizeNewArena(&fn_arena);
2897 return result;2898 return result;
2898}2899}
28992900
...@@ -5577,7 +5578,13 @@ fn zirFuncExtended(...@@ -5577,7 +5578,13 @@ fn zirFuncExtended(
5577 const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len);5578 const param_types = sema.code.refSlice(extra_index, extra.data.param_types_len);
5578 extra_index += param_types.len;5579 extra_index += param_types.len;
55795580
5580 const body_inst = if (extra.data.body_len != 0) inst else 0;5581 var body_inst: Zir.Inst.Index = 0;
5582 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
5583 if (extra.data.body_len != 0) {
5584 body_inst = inst;
5585 extra_index += extra.data.body_len;
5586 src_locs = sema.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
5587 }
55815588
5582 return sema.funcCommon(5589 return sema.funcCommon(
5583 block,5590 block,
...@@ -5589,6 +5596,7 @@ fn zirFuncExtended(...@@ -5589,6 +5596,7 @@ fn zirFuncExtended(
5589 align_val,5596 align_val,
5590 small.is_var_args,5597 small.is_var_args,
5591 small.is_inferred_error,5598 small.is_inferred_error,
5599 src_locs,
5592 );5600 );
5593}5601}
55945602
src/Zir.zig+56-7
...@@ -321,8 +321,9 @@ pub const Inst = struct {...@@ -321,8 +321,9 @@ pub const Inst = struct {
321 /// Uses the `pl_node` union field. Payload is `ErrorSetDecl`.321 /// Uses the `pl_node` union field. Payload is `ErrorSetDecl`.
322 error_set_decl,322 error_set_decl,
323 /// Declares the beginning of a statement. Used for debug info.323 /// Declares the beginning of a statement. Used for debug info.
324 /// Uses the `node` union field.324 /// Uses the `dbg_stmt` union field. The line and column are offset
325 dbg_stmt_node,325 /// from the parent declaration.
326 dbg_stmt,
326 /// Uses a name to identify a Decl and takes a pointer to it.327 /// Uses a name to identify a Decl and takes a pointer to it.
327 /// Uses the `str_tok` union field.328 /// Uses the `str_tok` union field.
328 decl_ref,329 decl_ref,
...@@ -1016,7 +1017,7 @@ pub const Inst = struct {...@@ -1016,7 +1017,7 @@ pub const Inst = struct {
1016 .enum_decl_nonexhaustive,1017 .enum_decl_nonexhaustive,
1017 .opaque_decl,1018 .opaque_decl,
1018 .error_set_decl,1019 .error_set_decl,
1019 .dbg_stmt_node,1020 .dbg_stmt,
1020 .decl_ref,1021 .decl_ref,
1021 .decl_val,1022 .decl_val,
1022 .load,1023 .load,
...@@ -1276,7 +1277,7 @@ pub const Inst = struct {...@@ -1276,7 +1277,7 @@ pub const Inst = struct {
1276 .enum_decl_nonexhaustive = .pl_node,1277 .enum_decl_nonexhaustive = .pl_node,
1277 .opaque_decl = .pl_node,1278 .opaque_decl = .pl_node,
1278 .error_set_decl = .pl_node,1279 .error_set_decl = .pl_node,
1279 .dbg_stmt_node = .node,1280 .dbg_stmt = .dbg_stmt,
1280 .decl_ref = .str_tok,1281 .decl_ref = .str_tok,
1281 .decl_val = .str_tok,1282 .decl_val = .str_tok,
1282 .load = .un_node,1283 .load = .un_node,
...@@ -2118,6 +2119,10 @@ pub const Inst = struct {...@@ -2118,6 +2119,10 @@ pub const Inst = struct {
2118 switch_inst: Index,2119 switch_inst: Index,
2119 prong_index: u32,2120 prong_index: u32,
2120 },2121 },
2122 dbg_stmt: struct {
2123 line: u32,
2124 column: u32,
2125 },
21212126
2122 // Make sure we don't accidentally add a field to make this union2127 // Make sure we don't accidentally add a field to make this union
2123 // bigger than expected. Note that in Debug builds, Zig is allowed2128 // bigger than expected. Note that in Debug builds, Zig is allowed
...@@ -2153,6 +2158,7 @@ pub const Inst = struct {...@@ -2153,6 +2158,7 @@ pub const Inst = struct {
2153 @"unreachable",2158 @"unreachable",
2154 @"break",2159 @"break",
2155 switch_capture,2160 switch_capture,
2161 dbg_stmt,
2156 };2162 };
2157 };2163 };
21582164
...@@ -2193,6 +2199,7 @@ pub const Inst = struct {...@@ -2193,6 +2199,7 @@ pub const Inst = struct {
2193 /// 2. align: Ref, // if has_align is set2199 /// 2. align: Ref, // if has_align is set
2194 /// 3. param_type: Ref // for each param_types_len2200 /// 3. param_type: Ref // for each param_types_len
2195 /// 4. body: Index // for each body_len2201 /// 4. body: Index // for each body_len
2202 /// 5. src_locs: Func.SrcLocs // if body_len != 0
2196 pub const ExtendedFunc = struct {2203 pub const ExtendedFunc = struct {
2197 src_node: i32,2204 src_node: i32,
2198 return_type: Ref,2205 return_type: Ref,
...@@ -2231,10 +2238,21 @@ pub const Inst = struct {...@@ -2231,10 +2238,21 @@ pub const Inst = struct {
2231 /// 0. param_type: Ref // for each param_types_len2238 /// 0. param_type: Ref // for each param_types_len
2232 /// - `none` indicates that the param type is `anytype`.2239 /// - `none` indicates that the param type is `anytype`.
2233 /// 1. body: Index // for each body_len2240 /// 1. body: Index // for each body_len
2241 /// 2. src_locs: SrcLocs // if body_len != 0
2234 pub const Func = struct {2242 pub const Func = struct {
2235 return_type: Ref,2243 return_type: Ref,
2236 param_types_len: u32,2244 param_types_len: u32,
2237 body_len: u32,2245 body_len: u32,
2246
2247 pub const SrcLocs = struct {
2248 /// Absolute line number in the source file.
2249 lbrace_line: u32,
2250 /// Absolute line number in the source file.
2251 rbrace_line: u32,
2252 /// lbrace_column is least significant bits u16
2253 /// rbrace_column is most significant bits u16
2254 columns: u32,
2255 };
2238 };2256 };
22392257
2240 /// This data is stored inside extra, with trailing operands according to `operands_len`.2258 /// This data is stored inside extra, with trailing operands according to `operands_len`.
...@@ -2398,6 +2416,7 @@ pub const Inst = struct {...@@ -2398,6 +2416,7 @@ pub const Inst = struct {
2398 /// 0bX000: whether corresponding decl has a linksection expression2416 /// 0bX000: whether corresponding decl has a linksection expression
2399 /// 1. decl: { // for every decls_len2417 /// 1. decl: { // for every decls_len
2400 /// src_hash: [4]u32, // hash of source bytes2418 /// src_hash: [4]u32, // hash of source bytes
2419 /// line: u32, // line number of decl, relative to parent
2401 /// name: u32, // null terminated string index2420 /// name: u32, // null terminated string index
2402 /// - 0 means comptime or usingnamespace decl.2421 /// - 0 means comptime or usingnamespace decl.
2403 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace2422 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
...@@ -2435,6 +2454,7 @@ pub const Inst = struct {...@@ -2435,6 +2454,7 @@ pub const Inst = struct {
2435 /// 0bX000: whether corresponding decl has a linksection expression2454 /// 0bX000: whether corresponding decl has a linksection expression
2436 /// 1. decl: { // for every decls_len2455 /// 1. decl: { // for every decls_len
2437 /// src_hash: [4]u32, // hash of source bytes2456 /// src_hash: [4]u32, // hash of source bytes
2457 /// line: u32, // line number of decl, relative to parent
2438 /// name: u32, // null terminated string index2458 /// name: u32, // null terminated string index
2439 /// - 0 means comptime or usingnamespace decl.2459 /// - 0 means comptime or usingnamespace decl.
2440 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace2460 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
...@@ -2467,6 +2487,7 @@ pub const Inst = struct {...@@ -2467,6 +2487,7 @@ pub const Inst = struct {
2467 /// 0bX000: whether corresponding decl has a linksection expression2487 /// 0bX000: whether corresponding decl has a linksection expression
2468 /// 1. decl: { // for every decls_len2488 /// 1. decl: { // for every decls_len
2469 /// src_hash: [4]u32, // hash of source bytes2489 /// src_hash: [4]u32, // hash of source bytes
2490 /// line: u32, // line number of decl, relative to parent
2470 /// name: u32, // null terminated string index2491 /// name: u32, // null terminated string index
2471 /// - 0 means comptime or usingnamespace decl.2492 /// - 0 means comptime or usingnamespace decl.
2472 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace2493 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
...@@ -2509,6 +2530,7 @@ pub const Inst = struct {...@@ -2509,6 +2530,7 @@ pub const Inst = struct {
2509 /// 0bX000: whether corresponding decl has a linksection expression2530 /// 0bX000: whether corresponding decl has a linksection expression
2510 /// 1. decl: { // for every decls_len2531 /// 1. decl: { // for every decls_len
2511 /// src_hash: [4]u32, // hash of source bytes2532 /// src_hash: [4]u32, // hash of source bytes
2533 /// line: u32, // line number of decl, relative to parent
2512 /// name: u32, // null terminated string index2534 /// name: u32, // null terminated string index
2513 /// - 0 means comptime or usingnamespace decl.2535 /// - 0 means comptime or usingnamespace decl.
2514 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace2536 /// - if name == 0 `is_exported` determines which one: 0=comptime,1=usingnamespace
...@@ -2978,7 +3000,6 @@ const Writer = struct {...@@ -2978,7 +3000,6 @@ const Writer = struct {
29783000
2979 .breakpoint,3001 .breakpoint,
2980 .fence,3002 .fence,
2981 .dbg_stmt_node,
2982 .repeat,3003 .repeat,
2983 .repeat_inline,3004 .repeat_inline,
2984 .alloc_inferred,3005 .alloc_inferred,
...@@ -3007,6 +3028,8 @@ const Writer = struct {...@@ -3007,6 +3028,8 @@ const Writer = struct {
3007 .switch_capture_else_ref,3028 .switch_capture_else_ref,
3008 => try self.writeSwitchCapture(stream, inst),3029 => try self.writeSwitchCapture(stream, inst),
30093030
3031 .dbg_stmt => try self.writeDbgStmt(stream, inst),
3032
3010 .extended => try self.writeExtended(stream, inst),3033 .extended => try self.writeExtended(stream, inst),
3011 }3034 }
3012 }3035 }
...@@ -3606,6 +3629,8 @@ const Writer = struct {...@@ -3606,6 +3629,8 @@ const Writer = struct {
36063629
3607 const hash_u32s = self.code.extra[extra_index..][0..4];3630 const hash_u32s = self.code.extra[extra_index..][0..4];
3608 extra_index += 4;3631 extra_index += 4;
3632 const line = self.code.extra[extra_index];
3633 extra_index += 1;
3609 const decl_name_index = self.code.extra[extra_index];3634 const decl_name_index = self.code.extra[extra_index];
3610 const decl_name = self.code.nullTerminatedString(decl_name_index);3635 const decl_name = self.code.nullTerminatedString(decl_name_index);
3611 extra_index += 1;3636 extra_index += 1;
...@@ -3646,8 +3671,8 @@ const Writer = struct {...@@ -3646,8 +3671,8 @@ const Writer = struct {
3646 }3671 }
3647 }3672 }
3648 const tag = self.code.instructions.items(.tag)[decl_index];3673 const tag = self.code.instructions.items(.tag)[decl_index];
3649 try stream.print(" hash({}): %{d} = {s}(", .{3674 try stream.print(" line({d}) hash({}): %{d} = {s}(", .{
3650 std.fmt.fmtSliceHexLower(&hash_bytes), decl_index, @tagName(tag),3675 line, std.fmt.fmtSliceHexLower(&hash_bytes), decl_index, @tagName(tag),
3651 });3676 });
36523677
3653 const decl_block_inst_data = self.code.instructions.items(.data)[decl_index].pl_node;3678 const decl_block_inst_data = self.code.instructions.items(.data)[decl_index].pl_node;
...@@ -3979,6 +4004,11 @@ const Writer = struct {...@@ -3979,6 +4004,11 @@ const Writer = struct {
3979 const extra = self.code.extraData(Inst.Func, inst_data.payload_index);4004 const extra = self.code.extraData(Inst.Func, inst_data.payload_index);
3980 const param_types = self.code.refSlice(extra.end, extra.data.param_types_len);4005 const param_types = self.code.refSlice(extra.end, extra.data.param_types_len);
3981 const body = self.code.extra[extra.end + param_types.len ..][0..extra.data.body_len];4006 const body = self.code.extra[extra.end + param_types.len ..][0..extra.data.body_len];
4007 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
4008 if (body.len != 0) {
4009 const extra_index = extra.end + param_types.len + body.len;
4010 src_locs = self.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
4011 }
3982 return self.writeFuncCommon(4012 return self.writeFuncCommon(
3983 stream,4013 stream,
3984 param_types,4014 param_types,
...@@ -3989,6 +4019,7 @@ const Writer = struct {...@@ -3989,6 +4019,7 @@ const Writer = struct {
3989 .none,4019 .none,
3990 body,4020 body,
3991 src,4021 src,
4022 src_locs,
3992 );4023 );
3993 }4024 }
39944025
...@@ -4019,7 +4050,12 @@ const Writer = struct {...@@ -4019,7 +4050,12 @@ const Writer = struct {
4019 extra_index += param_types.len;4050 extra_index += param_types.len;
40204051
4021 const body = self.code.extra[extra_index..][0..extra.data.body_len];4052 const body = self.code.extra[extra_index..][0..extra.data.body_len];
4053 extra_index += body.len;
40224054
4055 var src_locs: Zir.Inst.Func.SrcLocs = undefined;
4056 if (body.len != 0) {
4057 src_locs = self.code.extraData(Zir.Inst.Func.SrcLocs, extra_index).data;
4058 }
4023 return self.writeFuncCommon(4059 return self.writeFuncCommon(
4024 stream,4060 stream,
4025 param_types,4061 param_types,
...@@ -4030,6 +4066,7 @@ const Writer = struct {...@@ -4030,6 +4066,7 @@ const Writer = struct {
4030 align_inst,4066 align_inst,
4031 body,4067 body,
4032 src,4068 src,
4069 src_locs,
4033 );4070 );
4034 }4071 }
40354072
...@@ -4111,6 +4148,7 @@ const Writer = struct {...@@ -4111,6 +4148,7 @@ const Writer = struct {
4111 align_inst: Inst.Ref,4148 align_inst: Inst.Ref,
4112 body: []const Inst.Index,4149 body: []const Inst.Index,
4113 src: LazySrcLoc,4150 src: LazySrcLoc,
4151 src_locs: Zir.Inst.Func.SrcLocs,
4114 ) !void {4152 ) !void {
4115 try stream.writeAll("[");4153 try stream.writeAll("[");
4116 for (param_types) |param_type, i| {4154 for (param_types) |param_type, i| {
...@@ -4134,6 +4172,12 @@ const Writer = struct {...@@ -4134,6 +4172,12 @@ const Writer = struct {
4134 try stream.writeByteNTimes(' ', self.indent);4172 try stream.writeByteNTimes(' ', self.indent);
4135 try stream.writeAll("}) ");4173 try stream.writeAll("}) ");
4136 }4174 }
4175 if (body.len != 0) {
4176 try stream.print("(lbrace={d}:{d},rbrace={d}:{d}) ", .{
4177 src_locs.lbrace_line, @truncate(u16, src_locs.columns),
4178 src_locs.rbrace_line, @truncate(u16, src_locs.columns >> 16),
4179 });
4180 }
4137 try self.writeSrc(stream, src);4181 try self.writeSrc(stream, src);
4138 }4182 }
41394183
...@@ -4143,6 +4187,11 @@ const Writer = struct {...@@ -4143,6 +4187,11 @@ const Writer = struct {
4143 try stream.print(", {d})", .{inst_data.prong_index});4187 try stream.print(", {d})", .{inst_data.prong_index});
4144 }4188 }
41454189
4190 fn writeDbgStmt(self: *Writer, stream: anytype, inst: Inst.Index) !void {
4191 const inst_data = self.code.instructions.items(.data)[inst].dbg_stmt;
4192 try stream.print("{d}, {d})", .{ inst_data.line, inst_data.column });
4193 }
4194
4146 fn writeInstRef(self: *Writer, stream: anytype, ref: Inst.Ref) !void {4195 fn writeInstRef(self: *Writer, stream: anytype, ref: Inst.Ref) !void {
4147 var i: usize = @enumToInt(ref);4196 var i: usize = @enumToInt(ref);
41484197
src/codegen.zig+22-44
...@@ -264,14 +264,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -264,14 +264,13 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
264 src_loc: Module.SrcLoc,264 src_loc: Module.SrcLoc,
265 stack_align: u32,265 stack_align: u32,
266266
267 /// Byte offset within the source file.267 prev_di_line: u32,
268 prev_di_src: usize,268 prev_di_column: u32,
269 /// Byte offset within the source file of the ending curly.
270 end_di_line: u32,
271 end_di_column: u32,
269 /// Relative to the beginning of `code`.272 /// Relative to the beginning of `code`.
270 prev_di_pc: usize,273 prev_di_pc: usize,
271 /// Used to find newlines and count line deltas.
272 source: []const u8,
273 /// Byte offset within the source file of the ending curly.
274 rbrace_src: usize,
275274
276 /// The value is an offset into the `Function` `code` from the beginning.275 /// The value is an offset into the `Function` `code` from the beginning.
277 /// To perform the reloc, write 32-bit signed little-endian integer276 /// To perform the reloc, write 32-bit signed little-endian integer
...@@ -411,25 +410,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -411,25 +410,6 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
411 }410 }
412 try branch_stack.append(.{});411 try branch_stack.append(.{});
413412
414 const src_data: struct { lbrace_src: usize, rbrace_src: usize, source: []const u8 } = blk: {
415 const namespace = module_fn.owner_decl.namespace;
416 const tree = namespace.file_scope.tree;
417 const node_tags = tree.nodes.items(.tag);
418 const node_datas = tree.nodes.items(.data);
419 const token_starts = tree.tokens.items(.start);
420
421 const fn_decl = module_fn.owner_decl.src_node;
422 assert(node_tags[fn_decl] == .fn_decl);
423 const block = node_datas[fn_decl].rhs;
424 const lbrace_src = token_starts[tree.firstToken(block)];
425 const rbrace_src = token_starts[tree.lastToken(block)];
426 break :blk .{
427 .lbrace_src = lbrace_src,
428 .rbrace_src = rbrace_src,
429 .source = tree.source,
430 };
431 };
432
433 var function = Self{413 var function = Self{
434 .gpa = bin_file.allocator,414 .gpa = bin_file.allocator,
435 .target = &bin_file.options.target,415 .target = &bin_file.options.target,
...@@ -446,9 +426,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -446,9 +426,10 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
446 .src_loc = src_loc,426 .src_loc = src_loc,
447 .stack_align = undefined,427 .stack_align = undefined,
448 .prev_di_pc = 0,428 .prev_di_pc = 0,
449 .prev_di_src = src_data.lbrace_src,429 .prev_di_line = module_fn.lbrace_line,
450 .rbrace_src = src_data.rbrace_src,430 .prev_di_column = module_fn.lbrace_column,
451 .source = src_data.source,431 .end_di_line = module_fn.rbrace_line,
432 .end_di_column = module_fn.rbrace_column,
452 };433 };
453 defer function.stack.deinit(bin_file.allocator);434 defer function.stack.deinit(bin_file.allocator);
454 defer function.exitlude_jump_relocs.deinit(bin_file.allocator);435 defer function.exitlude_jump_relocs.deinit(bin_file.allocator);
...@@ -701,7 +682,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -701,7 +682,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
701 },682 },
702 }683 }
703 // Drop them off at the rbrace.684 // Drop them off at the rbrace.
704 try self.dbgAdvancePCAndLine(self.rbrace_src);685 try self.dbgAdvancePCAndLine(self.end_di_line, self.end_di_column);
705 }686 }
706687
707 fn genBody(self: *Self, body: ir.Body) InnerError!void {688 fn genBody(self: *Self, body: ir.Body) InnerError!void {
...@@ -727,7 +708,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -727,7 +708,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
727 switch (self.debug_output) {708 switch (self.debug_output) {
728 .dwarf => |dbg_out| {709 .dwarf => |dbg_out| {
729 try dbg_out.dbg_line.append(DW.LNS_set_prologue_end);710 try dbg_out.dbg_line.append(DW.LNS_set_prologue_end);
730 try self.dbgAdvancePCAndLine(self.prev_di_src);711 try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
731 },712 },
732 .none => {},713 .none => {},
733 }714 }
...@@ -737,27 +718,21 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -737,27 +718,21 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
737 switch (self.debug_output) {718 switch (self.debug_output) {
738 .dwarf => |dbg_out| {719 .dwarf => |dbg_out| {
739 try dbg_out.dbg_line.append(DW.LNS_set_epilogue_begin);720 try dbg_out.dbg_line.append(DW.LNS_set_epilogue_begin);
740 try self.dbgAdvancePCAndLine(self.prev_di_src);721 try self.dbgAdvancePCAndLine(self.prev_di_line, self.prev_di_column);
741 },722 },
742 .none => {},723 .none => {},
743 }724 }
744 }725 }
745726
746 fn dbgAdvancePCAndLine(self: *Self, abs_byte_off: usize) InnerError!void {727 fn dbgAdvancePCAndLine(self: *Self, line: u32, column: u32) InnerError!void {
747 self.prev_di_src = abs_byte_off;
748 self.prev_di_pc = self.code.items.len;
749 switch (self.debug_output) {728 switch (self.debug_output) {
750 .dwarf => |dbg_out| {729 .dwarf => |dbg_out| {
751 // TODO Look into improving the performance here by adding a token-index-to-line730 const delta_line = @intCast(i32, line) - @intCast(i32, self.prev_di_line);
752 // lookup table, and changing ir.Inst from storing byte offset to token. Currently
753 // this involves scanning over the source code for newlines
754 // (but only from the previous byte offset to the new one).
755 const delta_line = std.zig.lineDelta(self.source, self.prev_di_src, abs_byte_off);
756 const delta_pc = self.code.items.len - self.prev_di_pc;731 const delta_pc = self.code.items.len - self.prev_di_pc;
757 // TODO Look into using the DWARF special opcodes to compress this data. It lets you emit732 // TODO Look into using the DWARF special opcodes to compress this data.
758 // single-byte opcodes that add different numbers to both the PC and the line number733 // It lets you emit single-byte opcodes that add different numbers to
759 // at the same time.734 // both the PC and the line number at the same time.
760 try dbg_out.dbg_line.ensureCapacity(dbg_out.dbg_line.items.len + 11);735 try dbg_out.dbg_line.ensureUnusedCapacity(11);
761 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS_advance_pc);736 dbg_out.dbg_line.appendAssumeCapacity(DW.LNS_advance_pc);
762 leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable;737 leb128.writeULEB128(dbg_out.dbg_line.writer(), delta_pc) catch unreachable;
763 if (delta_line != 0) {738 if (delta_line != 0) {
...@@ -768,6 +743,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -768,6 +743,9 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
768 },743 },
769 .none => {},744 .none => {},
770 }745 }
746 self.prev_di_line = line;
747 self.prev_di_column = column;
748 self.prev_di_pc = self.code.items.len;
771 }749 }
772750
773 /// Asserts there is already capacity to insert into top branch inst_table.751 /// Asserts there is already capacity to insert into top branch inst_table.
...@@ -2317,7 +2295,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {...@@ -2317,7 +2295,7 @@ fn Function(comptime arch: std.Target.Cpu.Arch) type {
2317 // well to be more efficient, as well as support inlined function calls correctly.2295 // well to be more efficient, as well as support inlined function calls correctly.
2318 // For now we convert LazySrcLoc to absolute byte offset, to match what the2296 // For now we convert LazySrcLoc to absolute byte offset, to match what the
2319 // existing codegen code expects.2297 // existing codegen code expects.
2320 try self.dbgAdvancePCAndLine(inst.byte_offset);2298 try self.dbgAdvancePCAndLine(inst.line, inst.column);
2321 assert(inst.base.isUnused());2299 assert(inst.base.isUnused());
2322 return MCValue.dead;2300 return MCValue.dead;
2323 }2301 }
src/ir.zig+2-1
...@@ -622,7 +622,8 @@ pub const Inst = struct {...@@ -622,7 +622,8 @@ pub const Inst = struct {
622 pub const base_tag = Tag.dbg_stmt;622 pub const base_tag = Tag.dbg_stmt;
623623
624 base: Inst,624 base: Inst,
625 byte_offset: u32,625 line: u32,
626 column: u32,
626627
627 pub fn operandCount(self: *const DbgStmt) usize {628 pub fn operandCount(self: *const DbgStmt) usize {
628 return 0;629 return 0;
src/link/Elf.zig+4-28
...@@ -2221,21 +2221,8 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {...@@ -2221,21 +2221,8 @@ pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void {
2221 // For functions we need to add a prologue to the debug line program.2221 // For functions we need to add a prologue to the debug line program.
2222 try dbg_line_buffer.ensureCapacity(26);2222 try dbg_line_buffer.ensureCapacity(26);
22232223
2224 const line_off: u28 = blk: {2224 const func = decl.val.castTag(.function).?.data;
2225 const tree = decl.namespace.file_scope.tree;2225 const line_off = @intCast(u28, decl.src_line + func.lbrace_line);
2226 const node_tags = tree.nodes.items(.tag);
2227 const node_datas = tree.nodes.items(.data);
2228 const token_starts = tree.tokens.items(.start);
2229
2230 // TODO Look into improving the performance here by adding a token-index-to-line
2231 // lookup table. Currently this involves scanning over the source code for newlines.
2232 const fn_decl = decl.src_node;
2233 assert(node_tags[fn_decl] == .fn_decl);
2234 const block = node_datas[fn_decl].rhs;
2235 const lbrace = tree.firstToken(block);
2236 const line_delta = std.zig.lineDelta(tree.source, 0, token_starts[lbrace]);
2237 break :blk @intCast(u28, line_delta);
2238 };
22392226
2240 const ptr_width_bytes = self.ptrWidthBytes();2227 const ptr_width_bytes = self.ptrWidthBytes();
2241 dbg_line_buffer.appendSliceAssumeCapacity(&[_]u8{2228 dbg_line_buffer.appendSliceAssumeCapacity(&[_]u8{
...@@ -2750,19 +2737,8 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec...@@ -2750,19 +2737,8 @@ pub fn updateDeclLineNumber(self: *Elf, module: *Module, decl: *const Module.Dec
27502737
2751 if (self.llvm_object) |_| return;2738 if (self.llvm_object) |_| return;
27522739
2753 const tree = decl.namespace.file_scope.tree;2740 const func = decl.val.castTag(.function).?.data;
2754 const node_tags = tree.nodes.items(.tag);2741 const casted_line_off = @intCast(u28, decl.src_line + func.lbrace_line);
2755 const node_datas = tree.nodes.items(.data);
2756 const token_starts = tree.tokens.items(.start);
2757
2758 // TODO Look into improving the performance here by adding a token-index-to-line
2759 // lookup table. Currently this involves scanning over the source code for newlines.
2760 const fn_decl = decl.src_node;
2761 assert(node_tags[fn_decl] == .fn_decl);
2762 const block = node_datas[fn_decl].rhs;
2763 const lbrace = tree.firstToken(block);
2764 const line_delta = std.zig.lineDelta(tree.source, 0, token_starts[lbrace]);
2765 const casted_line_off = @intCast(u28, line_delta);
27662742
2767 const shdr = &self.sections.items[self.debug_line_section_index.?];2743 const shdr = &self.sections.items[self.debug_line_section_index.?];
2768 const file_pos = shdr.sh_offset + decl.fn_link.elf.off + self.getRelocDbgLineOff();2744 const file_pos = shdr.sh_offset + decl.fn_link.elf.off + self.getRelocDbgLineOff();