authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-06-29 20:56:52+03:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2022-06-30 21:47:25+03:00
log4f200eda9f055425ad3163d9be7ee43a057f7f2f
tree7762ffefe32f72f1582082170bfbb338d04f2364
parent90ae37cc00b08394c9e20c1699066cf9b08a13e7

stage2 llvm: ensure `@tagName` functions are unique


2 files changed, 38 insertions(+), 18 deletions(-)

src/codegen/llvm.zig+17-18
...@@ -7620,33 +7620,31 @@ pub const FuncGen = struct {...@@ -7620,33 +7620,31 @@ pub const FuncGen = struct {
7620 fn airTagName(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {7620 fn airTagName(self: *FuncGen, inst: Air.Inst.Index) !?*const llvm.Value {
7621 if (self.liveness.isUnused(inst)) return null;7621 if (self.liveness.isUnused(inst)) return null;
76227622
7623 var arena_allocator = std.heap.ArenaAllocator.init(self.gpa);
7624 defer arena_allocator.deinit();
7625 const arena = arena_allocator.allocator();
7626
7627 const un_op = self.air.instructions.items(.data)[inst].un_op;7623 const un_op = self.air.instructions.items(.data)[inst].un_op;
7628 const operand = try self.resolveInst(un_op);7624 const operand = try self.resolveInst(un_op);
7629 const enum_ty = self.air.typeOf(un_op);7625 const enum_ty = self.air.typeOf(un_op);
76307626
7631 const mod = self.dg.module;7627 const llvm_fn = try self.getEnumTagNameFunction(enum_ty);
7632 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{
7633 try mod.declPtr(enum_ty.getOwnerDecl()).getFullyQualifiedName(mod),
7634 });
7635
7636 const llvm_fn = try self.getEnumTagNameFunction(enum_ty, llvm_fn_name);
7637 const params = [_]*const llvm.Value{operand};7628 const params = [_]*const llvm.Value{operand};
7638 return self.builder.buildCall(llvm_fn, &params, params.len, .Fast, .Auto, "");7629 return self.builder.buildCall(llvm_fn, &params, params.len, .Fast, .Auto, "");
7639 }7630 }
76407631
7641 fn getEnumTagNameFunction(7632 fn getEnumTagNameFunction(self: *FuncGen, enum_ty: Type) !*const llvm.Value {
7642 self: *FuncGen,7633 const enum_decl = enum_ty.getOwnerDecl();
7643 enum_ty: Type,7634
7644 llvm_fn_name: [:0]const u8,
7645 ) !*const llvm.Value {
7646 // TODO: detect when the type changes and re-emit this function.7635 // TODO: detect when the type changes and re-emit this function.
7647 if (self.dg.object.llvm_module.getNamedFunction(llvm_fn_name)) |llvm_fn| {7636 const gop = try self.dg.object.decl_map.getOrPut(self.dg.gpa, enum_decl);
7648 return llvm_fn;7637 if (gop.found_existing) return gop.value_ptr.*;
7649 }7638 errdefer assert(self.dg.object.decl_map.remove(enum_decl));
7639
7640 var arena_allocator = std.heap.ArenaAllocator.init(self.gpa);
7641 defer arena_allocator.deinit();
7642 const arena = arena_allocator.allocator();
7643
7644 const mod = self.dg.module;
7645 const llvm_fn_name = try std.fmt.allocPrintZ(arena, "__zig_tag_name_{s}", .{
7646 try mod.declPtr(enum_decl).getFullyQualifiedName(mod),
7647 });
76507648
7651 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);7649 const slice_ty = Type.initTag(.const_slice_u8_sentinel_0);
7652 const llvm_ret_ty = try self.dg.lowerType(slice_ty);7650 const llvm_ret_ty = try self.dg.lowerType(slice_ty);
...@@ -7663,6 +7661,7 @@ pub const FuncGen = struct {...@@ -7663,6 +7661,7 @@ pub const FuncGen = struct {
7663 fn_val.setLinkage(.Internal);7661 fn_val.setLinkage(.Internal);
7664 fn_val.setFunctionCallConv(.Fast);7662 fn_val.setFunctionCallConv(.Fast);
7665 self.dg.addCommonFnAttributes(fn_val);7663 self.dg.addCommonFnAttributes(fn_val);
7664 gop.value_ptr.* = fn_val;
76667665
7667 const prev_block = self.builder.getInsertBlock();7666 const prev_block = self.builder.getInsertBlock();
7668 const prev_debug_location = self.builder.getCurrentDebugLocation2();7667 const prev_debug_location = self.builder.getCurrentDebugLocation2();
test/behavior/enum.zig+21
...@@ -1107,3 +1107,24 @@ test "enum literal in array literal" {...@@ -1107,3 +1107,24 @@ test "enum literal in array literal" {
1107 try expect(array[0] == .one);1107 try expect(array[0] == .one);
1108 try expect(array[1] == .two);1108 try expect(array[1] == .two);
1109}1109}
1110
1111test "tag name functions are unique" {
1112 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
1113 if (builtin.zig_backend == .stage2_wasm) return error.SkipZigTest; // TODO
1114 if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
1115 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
1116 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest;
1117
1118 {
1119 const E = enum { a, b };
1120 var b = E.a;
1121 var a = @tagName(b);
1122 _ = a;
1123 }
1124 {
1125 const E = enum { a, b, c, d, e, f };
1126 var b = E.a;
1127 var a = @tagName(b);
1128 _ = a;
1129 }
1130}