Commit 0576086395

Andrew Kelley <andrew@ziglang.org>
2022-03-20 08:35:09
stage2: remove Value.Tag.abi_align_default
and make Decl alignment & linksection, and struct & union field alignment be scalar values, not Value values. YAGNI
1 parent 3ef34fe
Changed files (5)
src/arch/x86_64/abi.zig
@@ -179,9 +179,8 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class {
             var byte_i: usize = 0; // out of 8
             const fields = ty.structFields();
             for (fields.values()) |field| {
-                if (field.abi_align.tag() != .abi_align_default) {
-                    const field_alignment = field.abi_align.toUnsignedInt();
-                    if (field_alignment < field.ty.abiAlignment(target)) {
+                if (field.abi_align != 0) {
+                    if (field.abi_align < field.ty.abiAlignment(target)) {
                         return memory_class;
                     }
                 }
@@ -288,9 +287,8 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class {
 
             const fields = ty.unionFields();
             for (fields.values()) |field| {
-                if (field.abi_align.tag() != .abi_align_default) {
-                    const field_alignment = field.abi_align.toUnsignedInt();
-                    if (field_alignment < field.ty.abiAlignment(target)) {
+                if (field.abi_align != 0) {
+                    if (field.abi_align < field.ty.abiAlignment(target)) {
                         return memory_class;
                     }
                 }
src/codegen/c.zig
@@ -245,7 +245,7 @@ pub const Function = struct {
                     ty,
                     decl_c_value,
                     .Const,
-                    Value.initTag(.abi_align_default),
+                    0,
                 );
                 try writer.writeAll(" = ");
                 try f.object.dg.renderValue(writer, ty, val);
@@ -267,10 +267,10 @@ pub const Function = struct {
     }
 
     fn allocLocal(f: *Function, ty: Type, mutability: Mutability) !CValue {
-        return f.allocAlignedLocal(ty, mutability, Value.initTag(.abi_align_default));
+        return f.allocAlignedLocal(ty, mutability, 0);
     }
 
-    fn allocAlignedLocal(f: *Function, ty: Type, mutability: Mutability, alignment: Value) !CValue {
+    fn allocAlignedLocal(f: *Function, ty: Type, mutability: Mutability, alignment: u32) !CValue {
         const local_value = f.allocLocalValue();
         try f.object.dg.renderTypeAndName(
             f.object.writer(),
@@ -854,8 +854,7 @@ pub const DeclGen = struct {
                 try w.writeAll(", ");
             }
             const name = CValue{ .arg = index };
-            const alignment = Value.initTag(.abi_align_default);
-            try dg.renderTypeAndName(w, dg.decl.ty.fnParamType(index), name, .Mut, alignment);
+            try dg.renderTypeAndName(w, dg.decl.ty.fnParamType(index), name, .Mut, 0);
             params_written += 1;
         }
 
@@ -928,8 +927,7 @@ pub const DeclGen = struct {
         var ptr_type_buf: Type.SlicePtrFieldTypeBuffer = undefined;
         const ptr_type = t.slicePtrFieldType(&ptr_type_buf);
         const ptr_name = CValue{ .bytes = "ptr" };
-        const ptr_alignment = Value.initTag(.abi_align_default);
-        try dg.renderTypeAndName(bw, ptr_type, ptr_name, .Mut, ptr_alignment);
+        try dg.renderTypeAndName(bw, ptr_type, ptr_name, .Mut, 0);
 
         const ptr_sentinel = ptr_type.ptrInfo().data.sentinel;
         const child_type = t.childType();
@@ -1018,7 +1016,7 @@ pub const DeclGen = struct {
                 try name.writer().print("field_{d}", .{i});
 
                 try buffer.append(' ');
-                try dg.renderTypeAndName(writer, field_ty, .{ .bytes = name.items }, .Mut, Value.initTag(.abi_align_default));
+                try dg.renderTypeAndName(writer, field_ty, .{ .bytes = name.items }, .Mut, 0);
                 try buffer.appendSlice(";\n");
             }
         }
@@ -1056,7 +1054,7 @@ pub const DeclGen = struct {
             const name: CValue = .{ .bytes = "tag" };
             try buffer.appendSlice("struct {\n ");
             if (layout.tag_size != 0) {
-                try dg.renderTypeAndName(buffer.writer(), tag_ty, name, .Mut, Value.initTag(.abi_align_default));
+                try dg.renderTypeAndName(buffer.writer(), tag_ty, name, .Mut, 0);
                 try buffer.appendSlice(";\n");
             }
         }
@@ -1106,8 +1104,7 @@ pub const DeclGen = struct {
 
         try bw.writeAll("typedef struct { ");
         const payload_name = CValue{ .bytes = "payload" };
-        const alignment = Value.initTag(.abi_align_default);
-        try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, alignment);
+        try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, 0);
         try bw.writeAll("; uint16_t error; } ");
         const name_index = buffer.items.len;
         if (err_set_type.castTag(.error_set_inferred)) |inf_err_set_payload| {
@@ -1172,8 +1169,7 @@ pub const DeclGen = struct {
 
         try bw.writeAll("typedef struct { ");
         const payload_name = CValue{ .bytes = "payload" };
-        const alignment = Value.initTag(.abi_align_default);
-        try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, alignment);
+        try dg.renderTypeAndName(bw, child_type, payload_name, .Mut, 0);
         try bw.writeAll("; bool is_null; } ");
         const name_index = buffer.items.len;
         try bw.print("zig_Q_{s};\n", .{typeToCIdentifier(child_type)});
@@ -1375,12 +1371,9 @@ pub const DeclGen = struct {
         dg: *DeclGen,
         w: anytype,
         ty: Type,
-        //mutability: Mutability,
-        //alignment: Value,
     ) error{ OutOfMemory, AnalysisFail }!void {
         const name = CValue{ .bytes = "" };
-        const alignment = Value.initTag(.abi_align_default);
-        return renderTypeAndName(dg, w, ty, name, .Mut, alignment);
+        return renderTypeAndName(dg, w, ty, name, .Mut, 0);
     }
 
     /// Renders a type and name in field declaration/definition format.
@@ -1398,7 +1391,7 @@ pub const DeclGen = struct {
         ty: Type,
         name: CValue,
         mutability: Mutability,
-        alignment: Value,
+        alignment: u32,
     ) error{ OutOfMemory, AnalysisFail }!void {
         var suffix = std.ArrayList(u8).init(dg.gpa);
         defer suffix.deinit();
@@ -1413,8 +1406,8 @@ pub const DeclGen = struct {
             render_ty = render_ty.elemType();
         }
 
-        if (alignment.tag() != .abi_align_default and alignment.tag() != .null_value)
-            try w.print("ZIG_ALIGN({}) ", .{alignment.toUnsignedInt()});
+        if (alignment != 0)
+            try w.print("ZIG_ALIGN({}) ", .{alignment});
         try dg.renderType(w, render_ty);
 
         const const_prefix = switch (mutability) {
@@ -1570,7 +1563,7 @@ pub fn genDecl(o: *Object) !void {
 
         const decl_c_value: CValue = if (is_global) .{ .bytes = mem.span(o.dg.decl.name) } else .{ .decl = o.dg.decl };
 
-        try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.align_val);
+        try o.dg.renderTypeAndName(fwd_decl_writer, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align");
         try fwd_decl_writer.writeAll(";\n");
 
         if (variable.init.isUndefDeep()) {
@@ -1579,7 +1572,7 @@ pub fn genDecl(o: *Object) !void {
 
         try o.indent_writer.insertNewline();
         const w = o.writer();
-        try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.align_val);
+        try o.dg.renderTypeAndName(w, o.dg.decl.ty, decl_c_value, .Mut, o.dg.decl.@"align");
         try w.writeAll(" = ");
         if (variable.init.tag() != .unreachable_value) {
             try o.dg.renderValue(w, tv.ty, variable.init);
@@ -1594,7 +1587,7 @@ pub fn genDecl(o: *Object) !void {
         // https://github.com/ziglang/zig/issues/7582
 
         const decl_c_value: CValue = .{ .decl = o.dg.decl };
-        try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.align_val);
+        try o.dg.renderTypeAndName(writer, tv.ty, decl_c_value, .Mut, o.dg.decl.@"align");
 
         try writer.writeAll(" = ");
         try o.dg.renderValue(writer, tv.ty, tv.val);
@@ -1993,15 +1986,8 @@ fn airAlloc(f: *Function, inst: Air.Inst.Index) !CValue {
     }
 
     const target = f.object.dg.module.getTarget();
-    const alignment = inst_ty.ptrAlignment(target);
-    var payload = Value.Payload.U64{
-        .base = .{ .tag = .int_u64 },
-        .data = alignment,
-    };
-    const alignment_value = Value.initPayload(&payload.base);
-
     // First line: the variable used as data storage.
-    const local = try f.allocAlignedLocal(elem_type, mutability, alignment_value);
+    const local = try f.allocAlignedLocal(elem_type, mutability, inst_ty.ptrAlignment(target));
     try writer.writeAll(";\n");
 
     return CValue{ .local_ref = local.local };
src/Module.zig
@@ -349,12 +349,13 @@ pub const Decl = struct {
     /// Populated when `has_tv`.
     val: Value,
     /// Populated when `has_tv`.
-    align_val: Value,
+    /// Points to memory inside value_arena.
+    @"linksection": ?[*:0]const u8,
     /// Populated when `has_tv`.
-    linksection_val: Value,
+    @"align": u32,
     /// Populated when `has_tv`.
     @"addrspace": std.builtin.AddressSpace,
-    /// The memory for ty, val, align_val, linksection_val, and captures.
+    /// The memory for ty, val, align, linksection, and captures.
     /// If this is `null` then there is no memory management needed.
     value_arena: ?*std.heap.ArenaAllocator.State = null,
     /// The direct parent namespace of the Decl.
@@ -423,7 +424,7 @@ pub const Decl = struct {
         /// to require re-analysis.
         outdated,
     },
-    /// Whether `typed_value`, `align_val`, `linksection_val` and `addrspace` are populated.
+    /// Whether `typed_value`, `align`, `linksection` and `addrspace` are populated.
     has_tv: bool,
     /// If `true` it means the `Decl` is the resource owner of the type/value associated
     /// with it. That means when `Decl` is destroyed, the cleanup code should additionally
@@ -794,9 +795,9 @@ pub const Decl = struct {
 
     pub fn getAlignment(decl: Decl, target: Target) u32 {
         assert(decl.has_tv);
-        if (decl.align_val.tag() != .null_value) {
+        if (decl.@"align" != 0) {
             // Explicit alignment.
-            return @intCast(u32, decl.align_val.toUnsignedInt());
+            return decl.@"align";
         } else {
             // Natural alignment.
             return decl.ty.abiAlignment(target);
@@ -893,9 +894,10 @@ pub const Struct = struct {
         /// Uses `noreturn` to indicate `anytype`.
         /// undefined until `status` is `have_field_types` or `have_layout`.
         ty: Type,
-        abi_align: Value,
         /// Uses `unreachable_value` to indicate no default.
         default_val: Value,
+        /// Zero means to use the ABI alignment of the type.
+        abi_align: u32,
         /// undefined until `status` is `have_layout`.
         offset: u32,
         /// If true then `default_val` is the comptime field value.
@@ -903,10 +905,10 @@ pub const Struct = struct {
 
         /// Returns the field alignment, assuming the struct is not packed.
         pub fn normalAlignment(field: Field, target: Target) u32 {
-            if (field.abi_align.tag() == .abi_align_default) {
+            if (field.abi_align == 0) {
                 return field.ty.abiAlignment(target);
             } else {
-                return @intCast(u32, field.abi_align.toUnsignedInt());
+                return field.abi_align;
             }
         }
     };
@@ -1139,16 +1141,17 @@ pub const Union = struct {
     pub const Field = struct {
         /// undefined until `status` is `have_field_types` or `have_layout`.
         ty: Type,
-        abi_align: Value,
+        /// 0 means the ABI alignment of the type.
+        abi_align: u32,
 
         /// Returns the field alignment, assuming the union is not packed.
         /// Keep implementation in sync with `Sema.unionFieldAlignment`.
         /// Prefer to call that function instead of this one during Sema.
         pub fn normalAlignment(field: Field, target: Target) u32 {
-            if (field.abi_align.tag() == .abi_align_default) {
+            if (field.abi_align == 0) {
                 return field.ty.abiAlignment(target);
             } else {
-                return @intCast(u32, field.abi_align.toUnsignedInt());
+                return field.abi_align;
             }
         }
     };
@@ -1224,7 +1227,7 @@ pub const Union = struct {
             if (!field.ty.hasRuntimeBits()) continue;
 
             const field_align = a: {
-                if (field.abi_align.tag() == .abi_align_default) {
+                if (field.abi_align == 0) {
                     break :a field.ty.abiAlignment(target);
                 } else {
                     break :a @intCast(u32, field.abi_align.toUnsignedInt());
@@ -1246,10 +1249,10 @@ pub const Union = struct {
             if (!field.ty.hasRuntimeBits()) continue;
 
             const field_align = a: {
-                if (field.abi_align.tag() == .abi_align_default) {
+                if (field.abi_align == 0) {
                     break :a field.ty.abiAlignment(target);
                 } else {
-                    break :a @intCast(u32, field.abi_align.toUnsignedInt());
+                    break :a field.abi_align;
                 }
             };
             max_align = @maximum(max_align, field_align);
@@ -1300,10 +1303,10 @@ pub const Union = struct {
             if (!field.ty.hasRuntimeBitsIgnoreComptime()) continue;
 
             const field_align = a: {
-                if (field.abi_align.tag() == .abi_align_default) {
+                if (field.abi_align == 0) {
                     break :a field.ty.abiAlignment(target);
                 } else {
-                    break :a @intCast(u32, field.abi_align.toUnsignedInt());
+                    break :a field.abi_align;
                 }
             };
             const field_size = field.ty.abiSize(target);
@@ -3863,15 +3866,16 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
     try wip_captures.finalize();
     const src: LazySrcLoc = .{ .node_offset = 0 };
     const decl_tv = try sema.resolveInstValue(&block_scope, src, result_ref);
-    const align_val = blk: {
+    const decl_align: u16 = blk: {
         const align_ref = decl.zirAlignRef();
-        if (align_ref == .none) break :blk Value.initTag(.null_value);
-        break :blk (try sema.resolveInstConst(&block_scope, src, align_ref)).val;
+        if (align_ref == .none) break :blk 0;
+        break :blk try sema.resolveAlign(&block_scope, src, align_ref);
     };
-    const linksection_val = blk: {
+    const decl_linksection: ?[*:0]const u8 = blk: {
         const linksection_ref = decl.zirLinksectionRef();
-        if (linksection_ref == .none) break :blk Value.initTag(.null_value);
-        break :blk (try sema.resolveInstConst(&block_scope, src, linksection_ref)).val;
+        if (linksection_ref == .none) break :blk null;
+        const bytes = try sema.resolveConstString(&block_scope, src, linksection_ref);
+        break :blk (try decl_arena_allocator.dupeZ(u8, bytes)).ptr;
     };
     const address_space = blk: {
         const addrspace_ctx: Sema.AddressSpaceContext = switch (decl_tv.val.tag()) {
@@ -3911,8 +3915,8 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
 
         decl.ty = ty_ty;
         decl.val = try Value.Tag.ty.create(decl_arena_allocator, ty);
-        decl.align_val = Value.initTag(.null_value);
-        decl.linksection_val = Value.initTag(.null_value);
+        decl.@"align" = 0;
+        decl.@"linksection" = null;
         decl.has_tv = true;
         decl.owns_tv = false;
         decl_arena_state.* = decl_arena.state;
@@ -3942,8 +3946,8 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
 
             decl.ty = try decl_tv.ty.copy(decl_arena_allocator);
             decl.val = try decl_tv.val.copy(decl_arena_allocator);
-            decl.align_val = try align_val.copy(decl_arena_allocator);
-            decl.linksection_val = try linksection_val.copy(decl_arena_allocator);
+            decl.@"align" = decl_align;
+            decl.@"linksection" = decl_linksection;
             decl.@"addrspace" = address_space;
             decl.has_tv = true;
             decl.owns_tv = owns_tv;
@@ -4022,8 +4026,8 @@ fn semaDecl(mod: *Module, decl: *Decl) !bool {
 
     decl.ty = try decl_tv.ty.copy(decl_arena_allocator);
     decl.val = try decl_tv.val.copy(decl_arena_allocator);
-    decl.align_val = try align_val.copy(decl_arena_allocator);
-    decl.linksection_val = try linksection_val.copy(decl_arena_allocator);
+    decl.@"align" = decl_align;
+    decl.@"linksection" = decl_linksection;
     decl.@"addrspace" = address_space;
     decl.has_tv = true;
     decl_arena_state.* = decl_arena.state;
@@ -4889,8 +4893,8 @@ pub fn allocateNewDecl(
         .owns_tv = false,
         .ty = undefined,
         .val = undefined,
-        .align_val = undefined,
-        .linksection_val = undefined,
+        .@"align" = undefined,
+        .@"linksection" = undefined,
         .@"addrspace" = .generic,
         .analysis = .unreferenced,
         .deletion_flag = false,
@@ -4995,8 +4999,8 @@ pub fn createAnonymousDeclFromDeclNamed(
     new_decl.src_line = src_decl.src_line;
     new_decl.ty = typed_value.ty;
     new_decl.val = typed_value.val;
-    new_decl.align_val = Value.@"null";
-    new_decl.linksection_val = Value.@"null";
+    new_decl.@"align" = 0;
+    new_decl.@"linksection" = null;
     new_decl.has_tv = true;
     new_decl.analysis = .complete;
     new_decl.generation = mod.generation;
src/Sema.zig
@@ -486,19 +486,17 @@ pub const Block = struct {
             wad.* = undefined;
         }
 
+        /// `alignment` value of 0 means to use ABI alignment.
         pub fn finish(wad: *WipAnonDecl, ty: Type, val: Value, alignment: u32) !*Decl {
             const sema = wad.block.sema;
             // Do this ahead of time because `createAnonymousDecl` depends on calling
             // `type.hasRuntimeBits()`.
             _ = try sema.typeHasRuntimeBits(wad.block, wad.src, ty);
-            const align_val = if (alignment != 0) blk: {
-                break :blk try Value.Tag.int_u64.create(wad.arena(), alignment);
-            } else Value.@"null";
             const new_decl = try sema.mod.createAnonymousDecl(wad.block, .{
                 .ty = ty,
                 .val = val,
             });
-            new_decl.align_val = align_val;
+            new_decl.@"align" = alignment;
             errdefer sema.mod.abortAnonDecl(new_decl);
             try new_decl.finalizeNewArena(&wad.new_decl_arena);
             wad.finished = true;
@@ -1281,7 +1279,7 @@ fn resolveConstBool(
     return val.toBool();
 }
 
-fn resolveConstString(
+pub fn resolveConstString(
     sema: *Sema,
     block: *Block,
     src: LazySrcLoc,
@@ -1539,7 +1537,7 @@ fn failWithOwnedErrorMsg(sema: *Sema, block: *Block, err_msg: *Module.ErrorMsg)
     return error.AnalysisFail;
 }
 
-fn resolveAlign(
+pub fn resolveAlign(
     sema: *Sema,
     block: *Block,
     src: LazySrcLoc,
@@ -13061,7 +13059,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
                     var buffer: Value.ToTypeBuffer = undefined;
                     gop.value_ptr.* = .{
                         .ty = try field_type_val.toType(&buffer).copy(new_decl_arena_allocator),
-                        .abi_align = try alignment_val.copy(new_decl_arena_allocator),
+                        .abi_align = @intCast(u32, alignment_val.toUnsignedInt()),
                     };
                 }
             }
@@ -13230,7 +13228,7 @@ fn reifyStruct(
         var buffer: Value.ToTypeBuffer = undefined;
         gop.value_ptr.* = .{
             .ty = try field_type_val.toType(&buffer).copy(new_decl_arena_allocator),
-            .abi_align = try alignment_val.copy(new_decl_arena_allocator),
+            .abi_align = @intCast(u32, alignment_val.toUnsignedInt()),
             .default_val = default_val,
             .is_comptime = is_comptime_val.toBool(),
             .offset = undefined,
@@ -14949,9 +14947,9 @@ fn zirFieldParentPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
     };
 
     if (struct_obj.layout == .Packed) {
-        // TODO handle packed structs
-    } else if (field.abi_align.tag() != .abi_align_default) {
-        ptr_ty_data.@"align" = @intCast(u32, field.abi_align.toUnsignedInt());
+        return sema.fail(block, src, "TODO handle packed structs with @fieldParentPtr", .{});
+    } else {
+        ptr_ty_data.@"align" = field.abi_align;
     }
 
     const target = sema.mod.getTarget();
@@ -15552,8 +15550,8 @@ fn zirBuiltinExtern(
     new_decl.src_line = sema.owner_decl.src_line;
     new_decl.ty = try ty.copy(new_decl_arena_allocator);
     new_decl.val = try Value.Tag.variable.create(new_decl_arena_allocator, new_var);
-    new_decl.align_val = Value.@"null";
-    new_decl.linksection_val = Value.@"null";
+    new_decl.@"align" = 0;
+    new_decl.@"linksection" = null;
     new_decl.has_tv = true;
     new_decl.analysis = .complete;
     new_decl.generation = sema.mod.generation;
@@ -16543,9 +16541,7 @@ fn structFieldPtrByIndex(
             ptr_ty_data.bit_offset += struct_ptr_ty_info.bit_offset;
         }
     } else {
-        if (field.abi_align.tag() != .abi_align_default) {
-            ptr_ty_data.@"align" = @intCast(u32, field.abi_align.toUnsignedInt());
-        }
+        ptr_ty_data.@"align" = field.abi_align;
     }
 
     const target = sema.mod.getTarget();
@@ -19168,15 +19164,11 @@ fn analyzeDeclRef(sema: *Sema, decl: *Decl) CompileError!Air.Inst.Ref {
     const decl_tv = try decl.typedValue();
     if (decl_tv.val.castTag(.variable)) |payload| {
         const variable = payload.data;
-        const alignment: u32 = if (decl.align_val.tag() == .null_value)
-            0
-        else
-            @intCast(u32, decl.align_val.toUnsignedInt());
         const ty = try Type.ptr(sema.arena, target, .{
             .pointee_type = decl_tv.ty,
             .mutable = variable.is_mutable,
             .@"addrspace" = decl.@"addrspace",
-            .@"align" = alignment,
+            .@"align" = decl.@"align",
         });
         return sema.addConstant(ty, try Value.Tag.decl_ref.create(sema.arena, decl));
     }
@@ -20848,7 +20840,7 @@ fn semaStructFields(
         assert(!gop.found_existing);
         gop.value_ptr.* = .{
             .ty = try field_ty.copy(decl_arena_allocator),
-            .abi_align = Value.initTag(.abi_align_default),
+            .abi_align = 0,
             .default_val = Value.initTag(.unreachable_value),
             .is_comptime = is_comptime,
             .offset = undefined,
@@ -20860,8 +20852,7 @@ fn semaStructFields(
             // TODO: if we need to report an error here, use a source location
             // that points to this alignment expression rather than the struct.
             // But only resolve the source location if we need to emit a compile error.
-            const abi_align_val = (try sema.resolveInstConst(&block_scope, src, align_ref)).val;
-            gop.value_ptr.abi_align = try abi_align_val.copy(decl_arena_allocator);
+            gop.value_ptr.abi_align = try sema.resolveAlign(&block_scope, src, align_ref);
         }
         if (has_default) {
             const default_ref = @intToEnum(Zir.Inst.Ref, zir.extra[extra_index]);
@@ -21088,17 +21079,16 @@ fn semaUnionFields(mod: *Module, union_obj: *Module.Union) CompileError!void {
         assert(!gop.found_existing);
         gop.value_ptr.* = .{
             .ty = try field_ty.copy(decl_arena_allocator),
-            .abi_align = Value.initTag(.abi_align_default),
+            .abi_align = 0,
         };
 
         if (align_ref != .none) {
             // TODO: if we need to report an error here, use a source location
             // that points to this alignment expression rather than the struct.
             // But only resolve the source location if we need to emit a compile error.
-            const abi_align_val = (try sema.resolveInstConst(&block_scope, src, align_ref)).val;
-            gop.value_ptr.abi_align = try abi_align_val.copy(decl_arena_allocator);
+            gop.value_ptr.abi_align = try sema.resolveAlign(&block_scope, src, align_ref);
         } else {
-            gop.value_ptr.abi_align = Value.initTag(.abi_align_default);
+            gop.value_ptr.abi_align = 0;
         }
     }
 }
@@ -21638,11 +21628,6 @@ fn analyzeComptimeAlloc(
     var anon_decl = try block.startAnonDecl(src);
     defer anon_decl.deinit();
 
-    const align_val = if (alignment == 0)
-        Value.@"null"
-    else
-        try Value.Tag.int_u64.create(anon_decl.arena(), alignment);
-
     const decl = try anon_decl.finish(
         try var_type.copy(anon_decl.arena()),
         // There will be stores before the first load, but they may be to sub-elements or
@@ -21651,7 +21636,7 @@ fn analyzeComptimeAlloc(
         Value.undef,
         alignment,
     );
-    decl.align_val = align_val;
+    decl.@"align" = alignment;
 
     try sema.mod.declareDeclDependency(sema.owner_decl, decl);
     return sema.addConstant(ptr_type, try Value.Tag.decl_ref_mut.create(sema.arena, .{
@@ -22066,10 +22051,10 @@ fn unionFieldAlignment(
     src: LazySrcLoc,
     field: Module.Union.Field,
 ) !u32 {
-    if (field.abi_align.tag() == .abi_align_default) {
+    if (field.abi_align == 0) {
         return sema.typeAbiAlignment(block, src, field.ty);
     } else {
-        return @intCast(u32, field.abi_align.toUnsignedInt());
+        return field.abi_align;
     }
 }
 
src/value.zig
@@ -98,7 +98,6 @@ pub const Value = extern union {
         bool_false,
         generic_poison,
 
-        abi_align_default,
         empty_struct_value,
         empty_array, // See last_no_payload_tag below.
         // After this, the tag requires a payload.
@@ -241,7 +240,6 @@ pub const Value = extern union {
                 .null_value,
                 .bool_true,
                 .bool_false,
-                .abi_align_default,
                 .manyptr_u8_type,
                 .manyptr_const_u8_type,
                 .manyptr_const_u8_sentinel_0_type,
@@ -437,7 +435,6 @@ pub const Value = extern union {
             .bool_true,
             .bool_false,
             .empty_struct_value,
-            .abi_align_default,
             .manyptr_u8_type,
             .manyptr_const_u8_type,
             .manyptr_const_u8_sentinel_0_type,
@@ -677,7 +674,6 @@ pub const Value = extern union {
             .export_options_type => return out_stream.writeAll("std.builtin.ExportOptions"),
             .extern_options_type => return out_stream.writeAll("std.builtin.ExternOptions"),
             .type_info_type => return out_stream.writeAll("std.builtin.Type"),
-            .abi_align_default => return out_stream.writeAll("(default ABI alignment)"),
 
             .empty_struct_value => return out_stream.writeAll("struct {}{}"),
             .aggregate => {