zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 35c7e376b89f41d8260b70e770e03ef6af68849d (tree)
parent 0333ff4476d0132a2397122dcab964de7fc0f2d3
Author: Veikka Tuominen <git@vexu.eu>
Date:   Sat, 11 Jun 2022 11:33:09 +0300

stage2: improve anon name strategy for local variables

Diffstat:
Mlib/std/fmt.zig | 64++++++++++++++++++++++++++++++++++++++++++++++------------------
Msrc/AstGen.zig | 7+++++++
Msrc/Sema.zig | 49++++++++++++++++++++++++++++++++++++++-----------
Msrc/Zir.zig | 2++
Mtest/behavior/typename.zig | 61+++++++++++++++++++++++++------------------------------------
5 files changed, 118 insertions(+), 65 deletions(-)

diff --git a/lib/std/fmt.zig b/lib/std/fmt.zig @@ -2190,18 +2190,22 @@ test "enum" { } test "non-exhaustive enum" { + if (builtin.zig_backend == .stage1) { + // stage1 fails to return fully qualified namespaces. + return error.SkipZigTest; + } const Enum = enum(u16) { One = 0x000f, Two = 0xbeef, _, }; - try expectFmt("enum: Enum.One\n", "enum: {}\n", .{Enum.One}); - try expectFmt("enum: Enum.Two\n", "enum: {}\n", .{Enum.Two}); - try expectFmt("enum: Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)}); - try expectFmt("enum: Enum.One\n", "enum: {x}\n", .{Enum.One}); - try expectFmt("enum: Enum.Two\n", "enum: {x}\n", .{Enum.Two}); - try expectFmt("enum: Enum.Two\n", "enum: {X}\n", .{Enum.Two}); - try expectFmt("enum: Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)}); + try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.One\n", "enum: {}\n", .{Enum.One}); + try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {}\n", .{Enum.Two}); + try expectFmt("enum: fmt.test.non-exhaustive enum.Enum(4660)\n", "enum: {}\n", .{@intToEnum(Enum, 0x1234)}); + try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.One\n", "enum: {x}\n", .{Enum.One}); + try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {x}\n", .{Enum.Two}); + try expectFmt("enum: fmt.test.non-exhaustive enum.Enum.Two\n", "enum: {X}\n", .{Enum.Two}); + try expectFmt("enum: fmt.test.non-exhaustive enum.Enum(1234)\n", "enum: {x}\n", .{@intToEnum(Enum, 0x1234)}); } test "float.scientific" { @@ -2357,6 +2361,10 @@ test "custom" { } test "struct" { + if (builtin.zig_backend == .stage1) { + // stage1 fails to return fully qualified namespaces. + return error.SkipZigTest; + } const S = struct { a: u32, b: anyerror, @@ -2367,7 +2375,7 @@ test "struct" { .b = error.Unused, }; - try expectFmt("S{ .a = 456, .b = error.Unused }", "{}", .{inst}); + try expectFmt("fmt.test.struct.S{ .a = 456, .b = error.Unused }", "{}", .{inst}); // Tuples try expectFmt("{ }", "{}", .{.{}}); try expectFmt("{ -1 }", "{}", .{.{-1}}); @@ -2375,6 +2383,10 @@ test "struct" { } test "union" { + if (builtin.zig_backend == .stage1) { + // stage1 fails to return fully qualified namespaces. + return error.SkipZigTest; + } const TU = union(enum) { float: f32, int: u32, @@ -2394,17 +2406,21 @@ test "union" { const uu_inst = UU{ .int = 456 }; const eu_inst = EU{ .float = 321.123 }; - try expectFmt("TU{ .int = 123 }", "{}", .{tu_inst}); + try expectFmt("fmt.test.union.TU{ .int = 123 }", "{}", .{tu_inst}); var buf: [100]u8 = undefined; const uu_result = try bufPrint(buf[0..], "{}", .{uu_inst}); - try std.testing.expect(mem.eql(u8, uu_result[0..3], "UU@")); + try std.testing.expect(mem.eql(u8, uu_result[0..18], "fmt.test.union.UU@")); const eu_result = try bufPrint(buf[0..], "{}", .{eu_inst}); - try std.testing.expect(mem.eql(u8, eu_result[0..3], "EU@")); + try std.testing.expect(mem.eql(u8, eu_result[0..18], "fmt.test.union.EU@")); } test "enum" { + if (builtin.zig_backend == .stage1) { + // stage1 fails to return fully qualified namespaces. + return error.SkipZigTest; + } const E = enum { One, Two, @@ -2413,10 +2429,14 @@ test "enum" { const inst = E.Two; - try expectFmt("E.Two", "{}", .{inst}); + try expectFmt("fmt.test.enum.E.Two", "{}", .{inst}); } test "struct.self-referential" { + if (builtin.zig_backend == .stage1) { + // stage1 fails to return fully qualified namespaces. + return error.SkipZigTest; + } const S = struct { const SelfType = @This(); a: ?*SelfType, @@ -2427,10 +2447,14 @@ test "struct.self-referential" { }; inst.a = &inst; - try expectFmt("S{ .a = S{ .a = S{ .a = S{ ... } } } }", "{}", .{inst}); + try expectFmt("fmt.test.struct.self-referential.S{ .a = fmt.test.struct.self-referential.S{ .a = fmt.test.struct.self-referential.S{ .a = fmt.test.struct.self-referential.S{ ... } } } }", "{}", .{inst}); } test "struct.zero-size" { + if (builtin.zig_backend == .stage1) { + // stage1 fails to return fully qualified namespaces. + return error.SkipZigTest; + } const A = struct { fn foo() void {} }; @@ -2442,7 +2466,7 @@ test "struct.zero-size" { const a = A{}; const b = B{ .a = a, .c = 0 }; - try expectFmt("B{ .a = A{ }, .c = 0 }", "{}", .{b}); + try expectFmt("fmt.test.struct.zero-size.B{ .a = fmt.test.struct.zero-size.A{ }, .c = 0 }", "{}", .{b}); } test "bytes.hex" { @@ -2508,6 +2532,10 @@ test "formatFloatValue with comptime_float" { } test "formatType max_depth" { + if (builtin.zig_backend == .stage1) { + // stage1 fails to return fully qualified namespaces. + return error.SkipZigTest; + } const Vec2 = struct { const SelfType = @This(); x: f32, @@ -2558,19 +2586,19 @@ test "formatType max_depth" { var buf: [1000]u8 = undefined; var fbs = std.io.fixedBufferStream(&buf); try formatType(inst, "", FormatOptions{}, fbs.writer(), 0); - try std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ ... }")); + try std.testing.expect(mem.eql(u8, fbs.getWritten(), "fmt.test.formatType max_depth.S{ ... }")); fbs.reset(); try formatType(inst, "", FormatOptions{}, fbs.writer(), 1); - try std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }")); + try std.testing.expect(mem.eql(u8, fbs.getWritten(), "fmt.test.formatType max_depth.S{ .a = fmt.test.formatType max_depth.S{ ... }, .tu = fmt.test.formatType max_depth.TU{ ... }, .e = fmt.test.formatType max_depth.E.Two, .vec = (10.200,2.220) }")); fbs.reset(); try formatType(inst, "", FormatOptions{}, fbs.writer(), 2); - try std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }")); + try std.testing.expect(mem.eql(u8, fbs.getWritten(), "fmt.test.formatType max_depth.S{ .a = fmt.test.formatType max_depth.S{ .a = fmt.test.formatType max_depth.S{ ... }, .tu = fmt.test.formatType max_depth.TU{ ... }, .e = fmt.test.formatType max_depth.E.Two, .vec = (10.200,2.220) }, .tu = fmt.test.formatType max_depth.TU{ .ptr = fmt.test.formatType max_depth.TU{ ... } }, .e = fmt.test.formatType max_depth.E.Two, .vec = (10.200,2.220) }")); fbs.reset(); try formatType(inst, "", FormatOptions{}, fbs.writer(), 3); - try std.testing.expect(mem.eql(u8, fbs.getWritten(), "S{ .a = S{ .a = S{ .a = S{ ... }, .tu = TU{ ... }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ ... } }, .e = E.Two, .vec = (10.200,2.220) }, .tu = TU{ .ptr = TU{ .ptr = TU{ ... } } }, .e = E.Two, .vec = (10.200,2.220) }")); + try std.testing.expect(mem.eql(u8, fbs.getWritten(), "fmt.test.formatType max_depth.S{ .a = fmt.test.formatType max_depth.S{ .a = fmt.test.formatType max_depth.S{ .a = fmt.test.formatType max_depth.S{ ... }, .tu = fmt.test.formatType max_depth.TU{ ... }, .e = fmt.test.formatType max_depth.E.Two, .vec = (10.200,2.220) }, .tu = fmt.test.formatType max_depth.TU{ .ptr = fmt.test.formatType max_depth.TU{ ... } }, .e = fmt.test.formatType max_depth.E.Two, .vec = (10.200,2.220) }, .tu = fmt.test.formatType max_depth.TU{ .ptr = fmt.test.formatType max_depth.TU{ .ptr = fmt.test.formatType max_depth.TU{ ... } } }, .e = fmt.test.formatType max_depth.E.Two, .vec = (10.200,2.220) }")); } test "positional" { diff --git a/src/AstGen.zig b/src/AstGen.zig @@ -2753,7 +2753,10 @@ fn varDecl( const result_loc: ResultLoc = if (type_node != 0) .{ .ty = try typeExpr(gz, scope, type_node), } else .none; + const prev_anon_name_strategy = gz.anon_name_strategy; + gz.anon_name_strategy = .dbg_var; const init_inst = try reachableExpr(gz, scope, result_loc, var_decl.ast.init_node, node); + gz.anon_name_strategy = prev_anon_name_strategy; try gz.addDbgVar(.dbg_var_val, ident_name, init_inst); @@ -2777,6 +2780,7 @@ fn varDecl( var init_scope = gz.makeSubBlock(scope); // we may add more instructions to gz before stacking init_scope init_scope.instructions_top = GenZir.unstacked_top; + init_scope.anon_name_strategy = .dbg_var; defer init_scope.unstack(); var resolve_inferred_alloc: Zir.Inst.Ref = .none; @@ -2956,7 +2960,10 @@ fn varDecl( resolve_inferred_alloc = alloc; break :a .{ .alloc = alloc, .result_loc = .{ .inferred_ptr = alloc } }; }; + const prev_anon_name_strategy = gz.anon_name_strategy; + gz.anon_name_strategy = .dbg_var; _ = try reachableExprComptime(gz, scope, var_data.result_loc, var_decl.ast.init_node, node, is_comptime); + gz.anon_name_strategy = prev_anon_name_strategy; if (resolve_inferred_alloc != .none) { _ = try gz.addUnNode(.resolve_inferred_alloc, resolve_inferred_alloc, node); } diff --git a/src/Sema.zig b/src/Sema.zig @@ -914,9 +914,9 @@ fn analyzeBodyInner( // zig fmt: off .variable => try sema.zirVarExtended( block, extended), .struct_decl => try sema.zirStructDecl( block, extended, inst), - .enum_decl => try sema.zirEnumDecl( block, extended), + .enum_decl => try sema.zirEnumDecl( block, extended, inst), .union_decl => try sema.zirUnionDecl( block, extended, inst), - .opaque_decl => try sema.zirOpaqueDecl( block, extended), + .opaque_decl => try sema.zirOpaqueDecl( block, extended, inst), .this => try sema.zirThis( block, extended), .ret_addr => try sema.zirRetAddr( block, extended), .builtin_src => try sema.zirBuiltinSrc( block, extended), @@ -2101,7 +2101,7 @@ fn zirStructDecl( const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ .ty = Type.type, .val = struct_val, - }, small.name_strategy, "struct"); + }, small.name_strategy, "struct", inst); const new_decl = mod.declPtr(new_decl_index); new_decl.owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -2133,6 +2133,7 @@ fn createAnonymousDeclTypeNamed( typed_value: TypedValue, name_strategy: Zir.Inst.NameStrategy, anon_prefix: []const u8, + inst: ?Zir.Inst.Index, ) !Decl.Index { const mod = sema.mod; const namespace = block.namespace; @@ -2152,11 +2153,13 @@ fn createAnonymousDeclTypeNamed( const name = try std.fmt.allocPrintZ(sema.gpa, "{s}__{s}_{d}", .{ src_decl.name, anon_prefix, @enumToInt(new_decl_index), }); + errdefer sema.gpa.free(name); try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); return new_decl_index; }, .parent => { const name = try sema.gpa.dupeZ(u8, mem.sliceTo(sema.mod.declPtr(block.src_decl).name, 0)); + errdefer sema.gpa.free(name); try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); return new_decl_index; }, @@ -2188,9 +2191,31 @@ fn createAnonymousDeclTypeNamed( try buf.appendSlice(")"); const name = try buf.toOwnedSliceSentinel(0); + errdefer sema.gpa.free(name); try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); return new_decl_index; }, + .dbg_var => { + const ref = Zir.indexToRef(inst.?); + const zir_tags = sema.code.instructions.items(.tag); + const zir_data = sema.code.instructions.items(.data); + var i = inst.?; + while (i < zir_tags.len) : (i += 1) switch (zir_tags[i]) { + .dbg_var_ptr, .dbg_var_val => { + if (zir_data[i].str_op.operand != ref) continue; + + const name = try std.fmt.allocPrintZ(sema.gpa, "{s}.{s}", .{ + src_decl.name, zir_data[i].str_op.getStr(sema.code), + }); + errdefer sema.gpa.free(name); + + try mod.initNewAnonDecl(new_decl_index, src_decl.src_line, namespace, typed_value, name); + return new_decl_index; + }, + else => {}, + }; + return sema.createAnonymousDeclTypeNamed(block, typed_value, .anon, anon_prefix, null); + }, } } @@ -2198,6 +2223,7 @@ fn zirEnumDecl( sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, + inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -2252,7 +2278,7 @@ fn zirEnumDecl( const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ .ty = Type.type, .val = enum_val, - }, small.name_strategy, "enum"); + }, small.name_strategy, "enum", inst); const new_decl = mod.declPtr(new_decl_index); new_decl.owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -2472,7 +2498,7 @@ fn zirUnionDecl( const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ .ty = Type.type, .val = union_val, - }, small.name_strategy, "union"); + }, small.name_strategy, "union", inst); const new_decl = mod.declPtr(new_decl_index); new_decl.owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -2504,6 +2530,7 @@ fn zirOpaqueDecl( sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData, + inst: Zir.Inst.Index, ) CompileError!Air.Inst.Ref { const tracy = trace(@src()); defer tracy.end(); @@ -2540,7 +2567,7 @@ fn zirOpaqueDecl( const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ .ty = Type.type, .val = opaque_val, - }, small.name_strategy, "opaque"); + }, small.name_strategy, "opaque", inst); const new_decl = mod.declPtr(new_decl_index); new_decl.owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -2589,7 +2616,7 @@ fn zirErrorSetDecl( const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ .ty = Type.type, .val = error_set_val, - }, name_strategy, "error"); + }, name_strategy, "error", inst); const new_decl = mod.declPtr(new_decl_index); new_decl.owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -14632,7 +14659,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ .ty = Type.type, .val = enum_val, - }, .anon, "enum"); + }, .anon, "enum", null); const new_decl = mod.declPtr(new_decl_index); new_decl.owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -14722,7 +14749,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ .ty = Type.type, .val = opaque_val, - }, .anon, "opaque"); + }, .anon, "opaque", null); const new_decl = mod.declPtr(new_decl_index); new_decl.owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -14773,7 +14800,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ .ty = Type.type, .val = new_union_val, - }, .anon, "union"); + }, .anon, "union", null); const new_decl = mod.declPtr(new_decl_index); new_decl.owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); @@ -14941,7 +14968,7 @@ fn reifyStruct( const new_decl_index = try sema.createAnonymousDeclTypeNamed(block, .{ .ty = Type.type, .val = new_struct_val, - }, .anon, "struct"); + }, .anon, "struct", null); const new_decl = mod.declPtr(new_decl_index); new_decl.owns_tv = true; errdefer mod.abortAnonDecl(new_decl_index); diff --git a/src/Zir.zig b/src/Zir.zig @@ -3156,6 +3156,8 @@ pub const Inst = struct { /// Create an anonymous name for this declaration. /// Like this: "ParentDeclName_struct_69" anon, + /// Use the name specified in the next `dbg_var_{val,ptr}` instruction. + dbg_var, }; /// Trailing: diff --git a/test/behavior/typename.zig b/test/behavior/typename.zig @@ -137,43 +137,8 @@ const A_Enum = enum { fn regular() void {} -test "fn body decl" { - if (builtin.zig_backend == .stage1) { - // stage1 fails to return fully qualified namespaces. - return error.SkipZigTest; - } - - if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO - if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO - - try B.doTest(); -} - const B = struct { - fn doTest() !void { - const B_Struct = struct {}; - const B_Union = union { - unused: u8, - }; - const B_Enum = enum { - unused, - }; - - try expectEqualStringsIgnoreDigits( - "behavior.typename.B.doTest__struct_0", - @typeName(B_Struct), - ); - try expectEqualStringsIgnoreDigits( - "behavior.typename.B.doTest__union_0", - @typeName(B_Union), - ); - try expectEqualStringsIgnoreDigits( - "behavior.typename.B.doTest__enum_0", - @typeName(B_Enum), - ); - } + fn doTest() !void {} }; test "fn param" { @@ -246,3 +211,27 @@ pub fn expectEqualStringsIgnoreDigits(expected: []const u8, actual: []const u8) } return expectEqualStrings(expected, actual_buf[0..actual_i]); } + +test "local variable" { + if (builtin.zig_backend == .stage1) { + // stage1 fails to return fully qualified namespaces. + return error.SkipZigTest; + } + + if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO + if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO + + const Foo = struct { a: u32 }; + const Bar = union { a: u32 }; + const Baz = enum { a, b }; + const Qux = enum { a, b }; + const Quux = enum { a, b }; + + try expectEqualStrings("behavior.typename.test.local variable.Foo", @typeName(Foo)); + try expectEqualStrings("behavior.typename.test.local variable.Bar", @typeName(Bar)); + try expectEqualStrings("behavior.typename.test.local variable.Baz", @typeName(Baz)); + try expectEqualStrings("behavior.typename.test.local variable.Qux", @typeName(Qux)); + try expectEqualStrings("behavior.typename.test.local variable.Quux", @typeName(Quux)); +}