diff options
| author | Jacob Young <jacobly0@users.noreply.github.com> | 2023-07-18 03:08:15 -0400 |
|---|---|---|
| committer | Jacob Young <jacobly0@users.noreply.github.com> | 2023-07-19 23:38:40 -0400 |
| commit | 9dd7a9eb0265f8be0fbfa4ea65b2b52f8bf29b0f (patch) | |
| tree | 326d0b94db0c2e5a6fb0017181294ac923702fca /src/codegen/llvm.zig | |
| parent | 9c4d5e64b45001cd82c0db53d1a489f433024223 (diff) | |
| download | zig-9dd7a9eb0265f8be0fbfa4ea65b2b52f8bf29b0f.tar.gz zig-9dd7a9eb0265f8be0fbfa4ea65b2b52f8bf29b0f.zip | |
llvm: fix various crashes
Diffstat (limited to 'src/codegen/llvm.zig')
| -rw-r--r-- | src/codegen/llvm.zig | 300 |
1 files changed, 227 insertions, 73 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 8c5660f8c5..d4bdb04507 100644 --- a/src/codegen/llvm.zig +++ b/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 }, |
