diff options
| author | Veikka Tuominen <git@vexu.eu> | 2022-08-30 16:01:28 +0300 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-08-30 12:22:07 -0700 |
| commit | c558de6655e2e9b72c5733b2d477ff18520d1c6b (patch) | |
| tree | 279830f956fc27ba8f18e8959efc8a657c4fc0c8 /src | |
| parent | d3b4b2edf140c002da4c9c1396c26e0f66835eb0 (diff) | |
| download | zig-c558de6655e2e9b72c5733b2d477ff18520d1c6b.tar.gz zig-c558de6655e2e9b72c5733b2d477ff18520d1c6b.zip | |
stage2 llvm: use tag value instead of field index in airUnionInit
Closes #12656
Diffstat (limited to 'src')
| -rw-r--r-- | src/Sema.zig | 12 | ||||
| -rw-r--r-- | src/codegen/llvm.zig | 19 |
2 files changed, 22 insertions, 9 deletions
diff --git a/src/Sema.zig b/src/Sema.zig index 1b35f52437..74f19e5b93 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -21933,6 +21933,7 @@ fn unionFieldPtr( .mutable = union_ptr_ty.ptrIsMutable(), .@"addrspace" = union_ptr_ty.ptrAddressSpace(), }); + const enum_field_index = @intCast(u32, union_obj.tag_ty.enumFieldIndex(field_name).?); if (initializing and field.ty.zigTypeTag() == .NoReturn) { const msg = msg: { @@ -21954,11 +21955,10 @@ fn unionFieldPtr( if (union_val.isUndef()) { return sema.failWithUseOfUndef(block, src); } - const enum_field_index = union_obj.tag_ty.enumFieldIndex(field_name).?; const tag_and_val = union_val.castTag(.@"union").?.data; var field_tag_buf: Value.Payload.U32 = .{ .base = .{ .tag = .enum_field_index }, - .data = @intCast(u32, enum_field_index), + .data = enum_field_index, }; const field_tag = Value.initPayload(&field_tag_buf.base); const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, sema.mod); @@ -21990,7 +21990,7 @@ fn unionFieldPtr( if (!initializing and union_obj.layout == .Auto and block.wantSafety() and union_ty.unionTagTypeSafety() != null and union_obj.fields.count() > 1) { - const wanted_tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index); + const wanted_tag_val = try Value.Tag.enum_field_index.create(sema.arena, enum_field_index); const wanted_tag = try sema.addConstant(union_obj.tag_ty, wanted_tag_val); // TODO would it be better if get_union_tag supported pointers to unions? const union_val = try block.addTyOp(.load, union_ty, union_ptr); @@ -22020,15 +22020,15 @@ fn unionFieldVal( const union_obj = union_ty.cast(Type.Payload.Union).?.data; const field_index = try sema.unionFieldIndex(block, union_ty, field_name, field_name_src); const field = union_obj.fields.values()[field_index]; + const enum_field_index = @intCast(u32, union_obj.tag_ty.enumFieldIndex(field_name).?); if (try sema.resolveMaybeUndefVal(block, src, union_byval)) |union_val| { if (union_val.isUndef()) return sema.addConstUndef(field.ty); const tag_and_val = union_val.castTag(.@"union").?.data; - const enum_field_index = union_obj.tag_ty.enumFieldIndex(field_name).?; var field_tag_buf: Value.Payload.U32 = .{ .base = .{ .tag = .enum_field_index }, - .data = @intCast(u32, enum_field_index), + .data = enum_field_index, }; const field_tag = Value.initPayload(&field_tag_buf.base); const tag_matches = tag_and_val.tag.eql(field_tag, union_obj.tag_ty, sema.mod); @@ -22064,7 +22064,7 @@ fn unionFieldVal( if (union_obj.layout == .Auto and block.wantSafety() and union_ty.unionTagTypeSafety() != null and union_obj.fields.count() > 1) { - const wanted_tag_val = try Value.Tag.enum_field_index.create(sema.arena, field_index); + const wanted_tag_val = try Value.Tag.enum_field_index.create(sema.arena, enum_field_index); const wanted_tag = try sema.addConstant(union_obj.tag_ty, wanted_tag_val); const active_tag = try block.addTyOp(.get_union_tag, union_obj.tag_ty, union_byval); const ok = try block.addBinOp(.cmp_eq, active_tag, wanted_tag); diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index a431c14d5a..93d2eaa9df 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -8527,12 +8527,26 @@ pub const FuncGen = struct { const union_llvm_ty = try self.dg.lowerType(union_ty); const target = self.dg.module.getTarget(); const layout = union_ty.unionGetLayout(target); + const union_obj = union_ty.cast(Type.Payload.Union).?.data; + const tag_int = blk: { + const tag_ty = union_ty.unionTagTypeHypothetical(); + const union_field_name = union_obj.fields.keys()[extra.field_index]; + const enum_field_index = tag_ty.enumFieldIndex(union_field_name).?; + var tag_val_payload: Value.Payload.U32 = .{ + .base = .{ .tag = .enum_field_index }, + .data = @intCast(u32, enum_field_index), + }; + const tag_val = Value.initPayload(&tag_val_payload.base); + var int_payload: Value.Payload.U64 = undefined; + const tag_int_val = tag_val.enumToInt(tag_ty, &int_payload); + break :blk tag_int_val.toUnsignedInt(target); + }; if (layout.payload_size == 0) { if (layout.tag_size == 0) { return null; } assert(!isByRef(union_ty)); - return union_llvm_ty.constInt(extra.field_index, .False); + return union_llvm_ty.constInt(tag_int, .False); } assert(isByRef(union_ty)); // The llvm type of the alloca will the the named LLVM union type, which will not @@ -8541,7 +8555,6 @@ pub const FuncGen = struct { // then set the fields appropriately. const result_ptr = self.buildAlloca(union_llvm_ty); const llvm_payload = try self.resolveInst(extra.init); - const union_obj = union_ty.cast(Type.Payload.Union).?.data; assert(union_obj.haveFieldTypes()); const field = union_obj.fields.values()[extra.field_index]; const field_llvm_ty = try self.dg.lowerType(field.ty); @@ -8625,7 +8638,7 @@ pub const FuncGen = struct { }; const field_ptr = self.builder.buildInBoundsGEP(casted_ptr, &indices, indices.len, ""); const tag_llvm_ty = try self.dg.lowerType(union_obj.tag_ty); - const llvm_tag = tag_llvm_ty.constInt(extra.field_index, .False); + const llvm_tag = tag_llvm_ty.constInt(tag_int, .False); const store_inst = self.builder.buildStore(llvm_tag, field_ptr); store_inst.setAlignment(union_obj.tag_ty.abiAlignment(target)); } |
