Commit 9dd7a9eb02

Jacob Young <jacobly0@users.noreply.github.com>
2023-07-18 09:08:15
llvm: fix various crashes
1 parent 9c4d5e6
Changed files (3)
lib
src
codegen
lib/std/target.zig
@@ -1910,12 +1910,37 @@ pub const Target = struct {
 
     pub fn stackAlignment(target: Target) u16 {
         return switch (target.cpu.arch) {
+            .amdgcn => 4,
             .x86 => switch (target.os.tag) {
                 .windows => 4,
                 else => 16,
             },
-            .arm, .armeb, .mips, .mipsel => 8,
-            .aarch64, .aarch64_be, .powerpc64, .powerpc64le, .riscv64, .x86_64, .wasm32, .wasm64 => 16,
+            .arm,
+            .armeb,
+            .thumb,
+            .thumbeb,
+            .mips,
+            .mipsel,
+            .sparc,
+            .sparcel,
+            => 8,
+            .aarch64,
+            .aarch64_be,
+            .aarch64_32,
+            .bpfeb,
+            .bpfel,
+            .mips64,
+            .mips64el,
+            .powerpc64,
+            .powerpc64le,
+            .riscv32,
+            .riscv64,
+            .sparc64,
+            .x86_64,
+            .ve,
+            .wasm32,
+            .wasm64,
+            => 16,
             else => @divExact(target.ptrBitWidth(), 8),
         };
     }
src/codegen/llvm/Builder.zig
@@ -2789,10 +2789,6 @@ pub const WipFunction = struct {
         name: []const u8,
     ) Allocator.Error!Value {
         assert(ptr.typeOfWip(self).isPointer(self.builder));
-        const final_scope = switch (ordering) {
-            .none => .system,
-            else => scope,
-        };
         try self.ensureUnusedExtraCapacity(1, Instruction.Load, 0);
         const instruction = try self.addInst(name, .{
             .tag = switch (ordering) {
@@ -2808,7 +2804,10 @@ pub const WipFunction = struct {
             .data = self.addExtraAssumeCapacity(Instruction.Load{
                 .type = ty,
                 .ptr = ptr,
-                .info = .{ .scope = final_scope, .ordering = ordering, .alignment = alignment },
+                .info = .{ .scope = switch (ordering) {
+                    .none => .system,
+                    else => scope,
+                }, .ordering = ordering, .alignment = alignment },
             }),
         });
         if (self.builder.useLibLlvm()) {
@@ -2817,7 +2816,6 @@ pub const WipFunction = struct {
                 ptr.toLlvm(self),
                 instruction.llvmName(self),
             );
-            if (final_scope == .singlethread) llvm_instruction.setAtomicSingleThread(.True);
             if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering)));
             if (alignment.toByteUnits()) |a| llvm_instruction.setAlignment(@intCast(a));
             self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
@@ -2845,10 +2843,6 @@ pub const WipFunction = struct {
         alignment: Alignment,
     ) Allocator.Error!Instruction.Index {
         assert(ptr.typeOfWip(self).isPointer(self.builder));
-        const final_scope = switch (ordering) {
-            .none => .system,
-            else => scope,
-        };
         try self.ensureUnusedExtraCapacity(1, Instruction.Store, 0);
         const instruction = try self.addInst(null, .{
             .tag = switch (ordering) {
@@ -2864,7 +2858,10 @@ pub const WipFunction = struct {
             .data = self.addExtraAssumeCapacity(Instruction.Store{
                 .val = val,
                 .ptr = ptr,
-                .info = .{ .scope = final_scope, .ordering = ordering, .alignment = alignment },
+                .info = .{ .scope = switch (ordering) {
+                    .none => .system,
+                    else => scope,
+                }, .ordering = ordering, .alignment = alignment },
             }),
         });
         if (self.builder.useLibLlvm()) {
@@ -2873,7 +2870,6 @@ pub const WipFunction = struct {
                 .normal => {},
                 .@"volatile" => llvm_instruction.setVolatile(.True),
             }
-            if (final_scope == .singlethread) llvm_instruction.setAtomicSingleThread(.True);
             if (ordering != .none) llvm_instruction.setOrdering(@enumFromInt(@intFromEnum(ordering)));
             if (alignment.toByteUnits()) |a| llvm_instruction.setAlignment(@intCast(a));
             self.llvm.instructions.appendAssumeCapacity(llvm_instruction);
src/codegen/llvm.zig
@@ -341,34 +341,40 @@ const DataLayoutBuilder = struct {
         writer: anytype,
     ) @TypeOf(writer).Error!void {
         const is_aarch64_windows = self.target.cpu.arch == .aarch64 and self.target.os.tag == .windows;
-        try writer.print("{c}-m:{c}", .{
-            @as(u8, switch (self.target.cpu.arch.endian()) {
-                .Little => 'e',
-                .Big => 'E',
-            }),
-            @as(u8, if (self.target.cpu.arch.isMIPS())
-                'm' // Mips mangling: Private symbols get a $ prefix.
-            else switch (self.target.ofmt) {
-                .elf => 'e', // ELF mangling: Private symbols get a `.L` prefix.
-                //.goff => 'l', // GOFF mangling: Private symbols get a `@` prefix.
-                .macho => 'o', // Mach-O mangling: Private symbols get `L` prefix.
-                // Other symbols get a `_` prefix.
-                .coff => switch (self.target.os.tag) {
-                    .windows => switch (self.target.cpu.arch) {
-                        .x86 => 'x', // Windows x86 COFF mangling: Private symbols get the usual prefix.
-                        // Regular C symbols get a `_` prefix. Functions with `__stdcall`, `__fastcall`,
-                        // and `__vectorcall` have custom mangling that appends `@N` where N is the
-                        // number of bytes used to pass parameters. C++ symbols starting with `?` are
-                        // not mangled in any way.
-                        else => 'w', // Windows COFF mangling: Similar to x, except that normal C
-                        // symbols do not receive a `_` prefix.
+        try writer.writeByte(switch (self.target.cpu.arch.endian()) {
+            .Little => 'e',
+            .Big => 'E',
+        });
+        switch (self.target.cpu.arch) {
+            .amdgcn,
+            .nvptx,
+            .nvptx64,
+            => {},
+            .avr => try writer.writeAll("-P1"),
+            else => try writer.print("-m:{c}", .{@as(u8, switch (self.target.cpu.arch) {
+                .mips, .mipsel => 'm', // Mips mangling: Private symbols get a $ prefix.
+                else => switch (self.target.ofmt) {
+                    .elf => 'e', // ELF mangling: Private symbols get a `.L` prefix.
+                    //.goff => 'l', // GOFF mangling: Private symbols get a `@` prefix.
+                    .macho => 'o', // Mach-O mangling: Private symbols get `L` prefix.
+                    // Other symbols get a `_` prefix.
+                    .coff => switch (self.target.os.tag) {
+                        .windows => switch (self.target.cpu.arch) {
+                            .x86 => 'x', // Windows x86 COFF mangling: Private symbols get the usual
+                            // prefix. Regular C symbols get a `_` prefix. Functions with `__stdcall`,
+                            //`__fastcall`, and `__vectorcall` have custom mangling that appends `@N`
+                            // where N is the number of bytes used to pass parameters. C++ symbols
+                            // starting with `?` are not mangled in any way.
+                            else => 'w', // Windows COFF mangling: Similar to x, except that normal C
+                            // symbols do not receive a `_` prefix.
+                        },
+                        else => 'e',
                     },
+                    //.xcoff => 'a', // XCOFF mangling: Private symbols get a `L..` prefix.
                     else => 'e',
                 },
-                //.xcoff => 'a', // XCOFF mangling: Private symbols get a `L..` prefix.
-                else => 'e',
-            }),
-        });
+            })}),
+        }
         var any_non_integral = false;
         const ptr_bit_width = self.target.ptrBitWidth();
         var default_info = struct { size: u16, abi: u16, pref: u16, idx: u16 }{
@@ -399,66 +405,134 @@ const DataLayoutBuilder = struct {
                 .pref = pref,
                 .idx = idx,
             };
+            if (self.target.cpu.arch == .aarch64_32) continue;
             if (!info.force_in_data_layout and matches_default and
-                self.target.cpu.arch != .riscv64 and !is_aarch64_windows) continue;
+                self.target.cpu.arch != .riscv64 and !is_aarch64_windows and
+                self.target.cpu.arch != .bpfeb and self.target.cpu.arch != .bpfel) continue;
             try writer.writeAll("-p");
             if (info.llvm != .default) try writer.print("{d}", .{@intFromEnum(info.llvm)});
             try writer.print(":{d}:{d}", .{ size, abi });
-            if (pref != abi or idx != size) {
+            if (pref != abi or idx != size or self.target.cpu.arch == .hexagon) {
                 try writer.print(":{d}", .{pref});
                 if (idx != size) try writer.print(":{d}", .{idx});
             }
         }
         if (self.target.cpu.arch.isARM() or self.target.cpu.arch.isThumb())
             try writer.writeAll("-Fi8"); // for thumb interwork
-        try self.typeAlignment(.integer, 8, 8, 8, false, writer);
-        try self.typeAlignment(.integer, 16, 16, 16, false, writer);
-        try self.typeAlignment(.integer, 32, if (is_aarch64_windows) 0 else 32, 32, false, writer);
-        try self.typeAlignment(.integer, 64, 32, 64, false, writer);
-        try self.typeAlignment(.integer, 128, 32, 64, false, writer);
-        if (backendSupportsF16(self.target)) try self.typeAlignment(.float, 16, 16, 16, false, writer);
-        try self.typeAlignment(.float, 32, 32, 32, false, writer);
-        try self.typeAlignment(.float, 64, 64, 64, false, writer);
-        if (backendSupportsF80(self.target)) try self.typeAlignment(.float, 80, 0, 0, false, writer);
-        try self.typeAlignment(.float, 128, 128, 128, false, writer);
-        try self.typeAlignment(.vector, 64, 64, 64, false, writer);
-        try self.typeAlignment(.vector, 128, 128, 128, false, writer);
-        if (self.target.os.tag != .windows) try self.typeAlignment(.aggregate, 0, 0, 64, false, writer);
+        if (self.target.cpu.arch != .hexagon) {
+            if (self.target.cpu.arch == .s390x) try self.typeAlignment(.integer, 1, 8, 8, false, writer);
+            try self.typeAlignment(.integer, 8, 8, 8, false, writer);
+            try self.typeAlignment(.integer, 16, 16, 16, false, writer);
+            try self.typeAlignment(.integer, 32, if (is_aarch64_windows) 0 else 32, 32, false, writer);
+            try self.typeAlignment(.integer, 64, 32, 64, false, writer);
+            try self.typeAlignment(.integer, 128, 32, 64, false, writer);
+            if (backendSupportsF16(self.target)) try self.typeAlignment(.float, 16, 16, 16, false, writer);
+            try self.typeAlignment(.float, 32, 32, 32, false, writer);
+            try self.typeAlignment(.float, 64, 64, 64, false, writer);
+            if (backendSupportsF80(self.target)) try self.typeAlignment(.float, 80, 0, 0, false, writer);
+            try self.typeAlignment(.float, 128, 128, 128, false, writer);
+        }
+        switch (self.target.cpu.arch) {
+            .amdgcn => {
+                try self.typeAlignment(.vector, 16, 16, 16, false, writer);
+                try self.typeAlignment(.vector, 24, 32, 32, false, writer);
+                try self.typeAlignment(.vector, 32, 32, 32, false, writer);
+                try self.typeAlignment(.vector, 48, 64, 64, false, writer);
+                try self.typeAlignment(.vector, 96, 128, 128, false, writer);
+                try self.typeAlignment(.vector, 192, 256, 256, false, writer);
+                try self.typeAlignment(.vector, 256, 256, 256, false, writer);
+                try self.typeAlignment(.vector, 512, 512, 512, false, writer);
+                try self.typeAlignment(.vector, 1024, 1024, 1024, false, writer);
+                try self.typeAlignment(.vector, 2048, 2048, 2048, false, writer);
+            },
+            .ve => {},
+            else => {
+                try self.typeAlignment(.vector, 16, 32, 32, false, writer);
+                try self.typeAlignment(.vector, 32, 32, 32, false, writer);
+                try self.typeAlignment(.vector, 64, 64, 64, false, writer);
+                try self.typeAlignment(.vector, 128, 128, 128, true, writer);
+            },
+        }
+        if (self.target.os.tag != .windows and self.target.cpu.arch != .avr)
+            try self.typeAlignment(.aggregate, 0, 0, 64, false, writer);
         for (@as([]const u24, switch (self.target.cpu.arch) {
-            .aarch64_32,
+            .avr => &.{8},
+            .msp430 => &.{ 8, 16 },
             .arm,
             .armeb,
             .mips,
             .mipsel,
             .powerpc,
             .powerpcle,
+            .riscv32,
+            .sparc,
+            .sparcel,
             .thumb,
             .thumbeb,
-            .riscv32,
             => &.{32},
             .aarch64,
             .aarch64_be,
+            .aarch64_32,
+            .amdgcn,
+            .bpfeb,
+            .bpfel,
             .mips64,
             .mips64el,
             .powerpc64,
             .powerpc64le,
             .riscv64,
+            .s390x,
+            .sparc64,
+            .ve,
             .wasm32,
             .wasm64,
             => &.{ 32, 64 },
+            .hexagon => &.{ 16, 32 },
             .x86 => &.{ 8, 16, 32 },
+            .nvptx,
+            .nvptx64,
+            => &.{ 16, 32, 64 },
             .x86_64 => &.{ 8, 16, 32, 64 },
             else => &.{},
         }), 0..) |natural, index| switch (index) {
             0 => try writer.print("-n{d}", .{natural}),
             else => try writer.print(":{d}", .{natural}),
         };
-        if (self.target.os.tag == .windows) try self.typeAlignment(.aggregate, 0, 0, 64, false, writer);
+        if (self.target.cpu.arch == .hexagon) {
+            try self.typeAlignment(.integer, 64, 64, 64, true, writer);
+            try self.typeAlignment(.integer, 32, 32, 32, true, writer);
+            try self.typeAlignment(.integer, 16, 16, 16, true, writer);
+            try self.typeAlignment(.integer, 1, 8, 8, true, writer);
+            try self.typeAlignment(.float, 32, 32, 32, true, writer);
+            try self.typeAlignment(.float, 64, 64, 64, true, writer);
+        }
+        if (self.target.os.tag == .windows or self.target.cpu.arch == .avr)
+            try self.typeAlignment(.aggregate, 0, 0, 64, false, writer);
         const stack_abi = self.target.stackAlignment() * 8;
-        if (self.target.os.tag == .windows or stack_abi != ptr_bit_width)
+        if (self.target.os.tag == .windows or self.target.cpu.arch == .msp430 or
+            stack_abi != ptr_bit_width)
             try writer.print("-S{d}", .{stack_abi});
-        try self.typeAlignment(.vector, 256, 128, 128, true, writer);
-        try self.typeAlignment(.vector, 512, 128, 128, true, writer);
+        switch (self.target.cpu.arch) {
+            .hexagon, .ve => {
+                try self.typeAlignment(.vector, 32, 128, 128, true, writer);
+                try self.typeAlignment(.vector, 64, 128, 128, true, writer);
+                try self.typeAlignment(.vector, 128, 128, 128, true, writer);
+            },
+            else => {},
+        }
+        if (self.target.cpu.arch != .amdgcn) {
+            try self.typeAlignment(.vector, 256, 128, 128, true, writer);
+            try self.typeAlignment(.vector, 512, 128, 128, true, writer);
+            try self.typeAlignment(.vector, 1024, 128, 128, true, writer);
+            try self.typeAlignment(.vector, 2048, 128, 128, true, writer);
+            try self.typeAlignment(.vector, 4096, 128, 128, true, writer);
+            try self.typeAlignment(.vector, 8192, 128, 128, true, writer);
+            try self.typeAlignment(.vector, 16384, 128, 128, true, writer);
+        }
+        const alloca_addr_space = llvmAllocaAddressSpace(self.target);
+        if (alloca_addr_space != .default) try writer.print("-A{d}", .{@intFromEnum(alloca_addr_space)});
+        const global_addr_space = llvmDefaultGlobalAddressSpace(self.target);
+        if (global_addr_space != .default) try writer.print("-G{d}", .{@intFromEnum(global_addr_space)});
         if (any_non_integral) {
             try writer.writeAll("-ni");
             for (addr_space_info) |info| if (info.non_integral)
@@ -472,11 +546,13 @@ const DataLayoutBuilder = struct {
         size: u24,
         default_abi: u24,
         default_pref: u24,
-        force_pref: bool,
+        default_force_pref: bool,
         writer: anytype,
     ) @TypeOf(writer).Error!void {
         var abi = default_abi;
         var pref = default_pref;
+        var force_abi = false;
+        var force_pref = default_force_pref;
         if (kind == .float and size == 80) {
             abi = 128;
             pref = 128;
@@ -493,21 +569,45 @@ const DataLayoutBuilder = struct {
         }
         switch (kind) {
             .integer => {
+                if (self.target.ptrBitWidth() <= 16 and size >= 128) return;
                 abi = @min(abi, self.target.maxIntAlignment() * 8);
                 switch (self.target.os.tag) {
                     .linux => switch (self.target.cpu.arch) {
-                        .aarch64, .aarch64_be, .mips, .mipsel => pref = @max(pref, 32),
+                        .aarch64,
+                        .aarch64_be,
+                        .aarch64_32,
+                        .mips,
+                        .mipsel,
+                        => pref = @max(pref, 32),
                         else => {},
                     },
                     else => {},
                 }
                 switch (self.target.cpu.arch) {
-                    .aarch64, .aarch64_be, .riscv64 => switch (size) {
-                        128 => {
-                            abi = size;
-                            pref = size;
-                        },
-                        else => {},
+                    .aarch64,
+                    .aarch64_be,
+                    .aarch64_32,
+                    .bpfeb,
+                    .bpfel,
+                    .nvptx,
+                    .nvptx64,
+                    .riscv64,
+                    => if (size == 128) {
+                        abi = size;
+                        pref = size;
+                    },
+                    .hexagon => force_abi = true,
+                    .mips64,
+                    .mips64el,
+                    => if (size <= 32) {
+                        pref = 32;
+                    },
+                    .s390x => if (size <= 16) {
+                        pref = 16;
+                    },
+                    .ve => if (size == 64) {
+                        abi = size;
+                        pref = size;
                     },
                     else => {},
                 }
@@ -517,18 +617,66 @@ const DataLayoutBuilder = struct {
                     128 => abi = 64,
                     else => {},
                 }
-            } else if (self.target.cpu.arch.isPPC64()) {
+            } else if ((self.target.cpu.arch.isPPC64() and (size == 256 or size == 512)) or
+                (self.target.cpu.arch.isNvptx() and (size == 16 or size == 32)))
+            {
+                force_abi = true;
+                abi = size;
+                pref = size;
+            } else if (self.target.cpu.arch == .amdgcn and size <= 2048) {
+                force_abi = true;
+            } else if (self.target.cpu.arch == .hexagon and
+                ((size >= 32 and size <= 64) or (size >= 512 and size <= 2048)))
+            {
                 abi = size;
                 pref = size;
+                force_pref = true;
+            } else if (self.target.cpu.arch == .s390x and size == 128) {
+                abi = 64;
+                pref = 64;
+                force_pref = false;
+            } else if (self.target.cpu.arch == .ve and (size >= 64 and size <= 16384)) {
+                abi = 64;
+                pref = 64;
+                force_abi = true;
+                force_pref = true;
+            },
+            .float => switch (self.target.cpu.arch) {
+                .avr, .msp430, .sparc64 => if (size != 32 and size != 64) return,
+                .hexagon => if (size == 32 or size == 64) {
+                    force_abi = true;
+                },
+                .aarch64_32 => if (size == 128) {
+                    abi = size;
+                    pref = size;
+                },
+                .ve => if (size == 64) {
+                    abi = size;
+                    pref = size;
+                },
+                else => {},
             },
-            .float => {},
             .aggregate => if (self.target.os.tag == .windows or
                 self.target.cpu.arch.isARM() or self.target.cpu.arch.isThumb())
             {
                 pref = @min(pref, self.target.ptrBitWidth());
+            } else if (self.target.cpu.arch == .hexagon) {
+                abi = 0;
+                pref = 0;
+            } else if (self.target.cpu.arch == .s390x) {
+                abi = 8;
+                pref = 16;
+            } else if (self.target.cpu.arch == .msp430) {
+                abi = 8;
+                pref = 8;
             },
         }
-        if (abi == default_abi and pref == default_pref) return;
+        if (kind != .vector and self.target.cpu.arch == .avr) {
+            force_abi = true;
+            abi = 8;
+            pref = 8;
+        }
+        if (!force_abi and abi == default_abi and pref == default_pref) return;
         try writer.print("-{c}", .{@tagName(kind)[0]});
         if (size != 0) try writer.print("{d}", .{size});
         try writer.print(":{d}", .{abi});
@@ -5096,12 +5244,15 @@ pub const FuncGen = struct {
             // In this case the function return type is honoring the calling convention by having
             // a different LLVM type than the usual one. We solve this here at the callsite
             // by using our canonical type, then loading it if necessary.
-            const rp = try self.buildAlloca(llvm_ret_ty, .default);
-            _ = try self.wip.store(.normal, call, rp, .default);
+            const alignment = Builder.Alignment.fromByteUnits(
+                o.target_data.abiAlignmentOfType(abi_ret_ty.toLlvm(&o.builder)),
+            );
+            const rp = try self.buildAlloca(llvm_ret_ty, alignment);
+            _ = try self.wip.store(.normal, call, rp, alignment);
             return if (isByRef(return_type, mod))
                 rp
             else
-                try self.wip.load(.normal, llvm_ret_ty, rp, .default, "");
+                try self.wip.load(.normal, llvm_ret_ty, rp, alignment, "");
         }
 
         if (isByRef(return_type, mod)) {
@@ -10923,23 +11074,26 @@ fn llvmAddrSpaceInfo(target: std.Target) []const AddrSpaceInfo {
             .{ .zig = .local, .llvm = Builder.AddrSpace.nvptx.local },
         },
         .amdgcn => &.{
-            .{ .zig = .generic, .llvm = Builder.AddrSpace.amdgpu.flat },
-            .{ .zig = .global, .llvm = Builder.AddrSpace.amdgpu.global },
-            .{ .zig = .constant, .llvm = Builder.AddrSpace.amdgpu.constant },
-            .{ .zig = .shared, .llvm = Builder.AddrSpace.amdgpu.local },
-            .{ .zig = .local, .llvm = Builder.AddrSpace.amdgpu.private },
+            .{ .zig = .generic, .llvm = Builder.AddrSpace.amdgpu.flat, .force_in_data_layout = true },
+            .{ .zig = .global, .llvm = Builder.AddrSpace.amdgpu.global, .force_in_data_layout = true },
+            .{ .zig = null, .llvm = Builder.AddrSpace.amdgpu.region, .size = 32, .abi = 32 },
+            .{ .zig = .shared, .llvm = Builder.AddrSpace.amdgpu.local, .size = 32, .abi = 32 },
+            .{ .zig = .constant, .llvm = Builder.AddrSpace.amdgpu.constant, .force_in_data_layout = true },
+            .{ .zig = .local, .llvm = Builder.AddrSpace.amdgpu.private, .size = 32, .abi = 32 },
+            .{ .zig = null, .llvm = Builder.AddrSpace.amdgpu.constant_32bit, .size = 32, .abi = 32 },
+            .{ .zig = null, .llvm = Builder.AddrSpace.amdgpu.buffer_fat_pointer, .non_integral = true },
         },
         .avr => &.{
-            .{ .zig = .generic, .llvm = .default },
-            .{ .zig = .flash, .llvm = Builder.AddrSpace.avr.flash },
-            .{ .zig = .flash1, .llvm = Builder.AddrSpace.avr.flash1 },
-            .{ .zig = .flash2, .llvm = Builder.AddrSpace.avr.flash2 },
-            .{ .zig = .flash3, .llvm = Builder.AddrSpace.avr.flash3 },
-            .{ .zig = .flash4, .llvm = Builder.AddrSpace.avr.flash4 },
-            .{ .zig = .flash5, .llvm = Builder.AddrSpace.avr.flash5 },
+            .{ .zig = .generic, .llvm = .default, .abi = 8 },
+            .{ .zig = .flash, .llvm = Builder.AddrSpace.avr.flash, .abi = 8 },
+            .{ .zig = .flash1, .llvm = Builder.AddrSpace.avr.flash1, .abi = 8 },
+            .{ .zig = .flash2, .llvm = Builder.AddrSpace.avr.flash2, .abi = 8 },
+            .{ .zig = .flash3, .llvm = Builder.AddrSpace.avr.flash3, .abi = 8 },
+            .{ .zig = .flash4, .llvm = Builder.AddrSpace.avr.flash4, .abi = 8 },
+            .{ .zig = .flash5, .llvm = Builder.AddrSpace.avr.flash5, .abi = 8 },
         },
         .wasm32, .wasm64 => &.{
-            .{ .zig = .generic, .llvm = .default },
+            .{ .zig = .generic, .llvm = .default, .force_in_data_layout = true },
             .{ .zig = null, .llvm = Builder.AddrSpace.wasm.variable, .non_integral = true },
             .{ .zig = null, .llvm = Builder.AddrSpace.wasm.externref, .non_integral = true, .size = 8, .abi = 8 },
             .{ .zig = null, .llvm = Builder.AddrSpace.wasm.funcref, .non_integral = true, .size = 8, .abi = 8 },