| ... | @@ -37,10 +37,20 @@ const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev; | ... | @@ -37,10 +37,20 @@ const compilerRtIntAbbrev = target_util.compilerRtIntAbbrev; |
| 37 | | 37 | |
| 38 | const Error = error{ OutOfMemory, CodegenFail }; | 38 | const Error = error{ OutOfMemory, CodegenFail }; |
| 39 | | 39 | |
| | 40 | fn subArchName(features: std.Target.Cpu.Feature.Set, arch: anytype, mappings: anytype) ?[]const u8 { |
| | 41 | inline for (mappings) |mapping| { |
| | 42 | if (arch.featureSetHas(features, mapping[0])) return mapping[1]; |
| | 43 | } |
| | 44 | |
| | 45 | return null; |
| | 46 | } |
| | 47 | |
| 40 | pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 { | 48 | pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 { |
| 41 | var llvm_triple = std.ArrayList(u8).init(allocator); | 49 | var llvm_triple = std.ArrayList(u8).init(allocator); |
| 42 | defer llvm_triple.deinit(); | 50 | defer llvm_triple.deinit(); |
| 43 | | 51 | |
| | 52 | const features = target.cpu.features; |
| | 53 | |
| 44 | const llvm_arch = switch (target.cpu.arch) { | 54 | const llvm_arch = switch (target.cpu.arch) { |
| 45 | .arm => "arm", | 55 | .arm => "arm", |
| 46 | .armeb => "armeb", | 56 | .armeb => "armeb", |
| ... | @@ -55,10 +65,11 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 { | ... | @@ -55,10 +65,11 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 { |
| 55 | .loongarch32 => "loongarch32", | 65 | .loongarch32 => "loongarch32", |
| 56 | .loongarch64 => "loongarch64", | 66 | .loongarch64 => "loongarch64", |
| 57 | .m68k => "m68k", | 67 | .m68k => "m68k", |
| 58 | .mips => "mips", | 68 | // MIPS sub-architectures are a bit irregular, so we handle them manually here. |
| 59 | .mipsel => "mipsel", | 69 | .mips => if (std.Target.mips.featureSetHas(features, .mips32r6)) "mipsisa32r6" else "mips", |
| 60 | .mips64 => "mips64", | 70 | .mipsel => if (std.Target.mips.featureSetHas(features, .mips32r6)) "mipsisa32r6el" else "mipsel", |
| 61 | .mips64el => "mips64el", | 71 | .mips64 => if (std.Target.mips.featureSetHas(features, .mips64r6)) "mipsisa64r6" else "mips64", |
| | 72 | .mips64el => if (std.Target.mips.featureSetHas(features, .mips64r6)) "mipsisa64r6el" else "mips64el", |
| 62 | .msp430 => "msp430", | 73 | .msp430 => "msp430", |
| 63 | .powerpc => "powerpc", | 74 | .powerpc => "powerpc", |
| 64 | .powerpcle => "powerpcle", | 75 | .powerpcle => "powerpcle", |
| ... | @@ -93,8 +104,67 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 { | ... | @@ -93,8 +104,67 @@ pub fn targetTriple(allocator: Allocator, target: std.Target) ![]const u8 { |
| 93 | => unreachable, // Gated by hasLlvmSupport(). | 104 | => unreachable, // Gated by hasLlvmSupport(). |
| 94 | | 105 | |
| 95 | }; | 106 | }; |
| | 107 | |
| 96 | try llvm_triple.appendSlice(llvm_arch); | 108 | try llvm_triple.appendSlice(llvm_arch); |
| 97 | | 109 | |
| | 110 | const llvm_sub_arch: ?[]const u8 = switch (target.cpu.arch) { |
| | 111 | .arm, .armeb, .thumb, .thumbeb => subArchName(features, std.Target.arm, .{ |
| | 112 | .{ .v4t, "v4t" }, |
| | 113 | .{ .v5t, "v5t" }, |
| | 114 | .{ .v5te, "v5te" }, |
| | 115 | .{ .v5tej, "v5tej" }, |
| | 116 | .{ .v6, "v6" }, |
| | 117 | .{ .v6k, "v6k" }, |
| | 118 | .{ .v6kz, "v6kz" }, |
| | 119 | .{ .v6m, "v6m" }, |
| | 120 | .{ .v6t2, "v6t2" }, |
| | 121 | // v7k and v7s imply v7a so they have to be tested first. |
| | 122 | .{ .v7k, "v7k" }, |
| | 123 | .{ .v7s, "v7s" }, |
| | 124 | .{ .v7a, "v7a" }, |
| | 125 | .{ .v7em, "v7em" }, |
| | 126 | .{ .v7m, "v7m" }, |
| | 127 | .{ .v7r, "v7r" }, |
| | 128 | .{ .v7ve, "v7ve" }, |
| | 129 | .{ .v8a, "v8a" }, |
| | 130 | .{ .v8_1a, "v8.1a" }, |
| | 131 | .{ .v8_2a, "v8.2a" }, |
| | 132 | .{ .v8_3a, "v8.3a" }, |
| | 133 | .{ .v8_4a, "v8.4a" }, |
| | 134 | .{ .v8_5a, "v8.5a" }, |
| | 135 | .{ .v8_6a, "v8.6a" }, |
| | 136 | .{ .v8_7a, "v8.7a" }, |
| | 137 | .{ .v8_8a, "v8.8a" }, |
| | 138 | .{ .v8_9a, "v8.9a" }, |
| | 139 | .{ .v8m, "v8m.base" }, |
| | 140 | .{ .v8m_main, "v8m.main" }, |
| | 141 | .{ .v8_1m_main, "v8.1m.main" }, |
| | 142 | .{ .v8r, "v8r" }, |
| | 143 | .{ .v9a, "v9a" }, |
| | 144 | .{ .v9_1a, "v9.1a" }, |
| | 145 | .{ .v9_2a, "v9.2a" }, |
| | 146 | .{ .v9_3a, "v9.3a" }, |
| | 147 | .{ .v9_4a, "v9.4a" }, |
| | 148 | .{ .v9_5a, "v9.5a" }, |
| | 149 | }), |
| | 150 | .powerpc => subArchName(features, std.Target.powerpc, .{ |
| | 151 | .{ .spe, "spe" }, |
| | 152 | }), |
| | 153 | .spirv => subArchName(features, std.Target.spirv, .{ |
| | 154 | .{ .v1_5, "1.5" }, |
| | 155 | }), |
| | 156 | .spirv32, .spirv64 => subArchName(features, std.Target.spirv, .{ |
| | 157 | .{ .v1_5, "1.5" }, |
| | 158 | .{ .v1_4, "1.4" }, |
| | 159 | .{ .v1_3, "1.3" }, |
| | 160 | .{ .v1_2, "1.2" }, |
| | 161 | .{ .v1_1, "1.1" }, |
| | 162 | }), |
| | 163 | else => null, |
| | 164 | }; |
| | 165 | |
| | 166 | if (llvm_sub_arch) |sub| try llvm_triple.appendSlice(sub); |
| | 167 | |
| 98 | // Unlike CPU backends, GPU backends actually care about the vendor tag. | 168 | // Unlike CPU backends, GPU backends actually care about the vendor tag. |
| 99 | try llvm_triple.appendSlice(switch (target.cpu.arch) { | 169 | try llvm_triple.appendSlice(switch (target.cpu.arch) { |
| 100 | .amdgcn => if (target.os.tag == .mesa3d) "-mesa-" else "-amd-", | 170 | .amdgcn => if (target.os.tag == .mesa3d) "-mesa-" else "-amd-", |