From 1f7babbc80211e12c9a38ff2196d6ff8c5a19302 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Tue, 21 Jan 2020 03:01:20 -0500 Subject: [PATCH] properly forward baseline target cpu features to llvm --- src-self-hosted/stage1.zig | 84 ++++++++++++++++++++++++-------------- src/codegen.cpp | 2 + src/main.cpp | 2 +- src/userland.cpp | 2 +- src/userland.h | 3 +- 5 files changed, 59 insertions(+), 34 deletions(-) diff --git a/src-self-hosted/stage1.zig b/src-self-hosted/stage1.zig index eed5804c0..9cbbf75d8 100644 --- a/src-self-hosted/stage1.zig +++ b/src-self-hosted/stage1.zig @@ -627,7 +627,7 @@ const Stage2CpuFeatures = struct { const Self = @This(); - fn createBaseline(allocator: *mem.Allocator) !*Self { + fn createBaseline(allocator: *mem.Allocator, arch: Target.Arch) !*Self { const self = try allocator.create(Self); errdefer allocator.destroy(self); @@ -641,10 +641,11 @@ const Stage2CpuFeatures = struct { .allocator = allocator, .cpu_features = .baseline, .llvm_cpu_name = null, - .llvm_features_str = null, + .llvm_features_str = try initLLVMFeatures(allocator, arch, arch.baselineFeatures()), .builtin_str = builtin_str, .cache_hash = cache_hash, }; + return self; } @@ -658,7 +659,7 @@ const Stage2CpuFeatures = struct { const arch = target.Cross.arch; const cpu_features = try cpuFeaturesFromLLVM(arch, llvm_cpu_name_z, llvm_cpu_features); switch (cpu_features) { - .baseline => return createBaseline(allocator), + .baseline => return createBaseline(allocator, arch), .cpu => |cpu| return createFromCpu(allocator, arch, cpu), .features => |features| return createFromCpuFeatures(allocator, arch, features), } @@ -688,6 +689,39 @@ const Stage2CpuFeatures = struct { return self; } + fn initLLVMFeatures( + allocator: *mem.Allocator, + arch: Target.Arch, + feature_set: Target.Cpu.Feature.Set, + ) ![*:0]const u8 { + var llvm_features_buffer = try std.Buffer.initSize(allocator, 0); + defer llvm_features_buffer.deinit(); + // First, disable all features. + // This way, we only get the ones the user requests. + const all_features = arch.allFeaturesList(); + for (all_features) |feature| { + if (feature.llvm_name) |llvm_name| { + try llvm_features_buffer.append("-"); + try llvm_features_buffer.append(llvm_name); + try llvm_features_buffer.append(","); + } + } + for (all_features) |feature, index| { + if (!feature_set.isEnabled(@intCast(u8, index))) continue; + + if (feature.llvm_name) |llvm_name| { + try llvm_features_buffer.append("+"); + try llvm_features_buffer.append(llvm_name); + try llvm_features_buffer.append(","); + } + } + + if (mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ",")) { + llvm_features_buffer.shrink(llvm_features_buffer.len() - 1); + } + return llvm_features_buffer.toOwnedSlice().ptr; + } + fn createFromCpuFeatures( allocator: *mem.Allocator, arch: Target.Arch, @@ -710,38 +744,14 @@ const Stage2CpuFeatures = struct { ); defer builtin_str_buffer.deinit(); - var llvm_features_buffer = try std.Buffer.initSize(allocator, 0); - defer llvm_features_buffer.deinit(); - - // First, disable all features. - // This way, we only get the ones the user requests. - const all_features = arch.allFeaturesList(); - for (all_features) |feature| { - if (feature.llvm_name) |llvm_name| { - try llvm_features_buffer.append("-"); - try llvm_features_buffer.append(llvm_name); - try llvm_features_buffer.append(","); - } - } - - for (all_features) |feature, index| { + for (arch.allFeaturesList()) |feature, index| { if (!feature_set.isEnabled(@intCast(u8, index))) continue; - if (feature.llvm_name) |llvm_name| { - try llvm_features_buffer.append("+"); - try llvm_features_buffer.append(llvm_name); - try llvm_features_buffer.append(","); - } - try builtin_str_buffer.append(" ."); try builtin_str_buffer.append(feature.name); try builtin_str_buffer.append(",\n"); } - if (mem.endsWith(u8, llvm_features_buffer.toSliceConst(), ",")) { - llvm_features_buffer.shrink(llvm_features_buffer.len() - 1); - } - try builtin_str_buffer.append( \\ }), \\}; @@ -752,7 +762,7 @@ const Stage2CpuFeatures = struct { .allocator = allocator, .cpu_features = .{ .features = feature_set }, .llvm_cpu_name = null, - .llvm_features_str = llvm_features_buffer.toOwnedSlice().ptr, + .llvm_features_str = try initLLVMFeatures(allocator, arch, feature_set), .builtin_str = builtin_str_buffer.toOwnedSlice(), .cache_hash = cache_hash, }; @@ -843,13 +853,25 @@ fn parseFeatures(zig_triple: [*:0]const u8, features_text: [*:0]const u8) !*Stag } // ABI warning -export fn stage2_cpu_features_baseline(result: **Stage2CpuFeatures) Error { - result.* = Stage2CpuFeatures.createBaseline(std.heap.c_allocator) catch |err| switch (err) { +export fn stage2_cpu_features_baseline(result: **Stage2CpuFeatures, zig_triple: [*:0]const u8) Error { + result.* = cpuFeaturesBaseline(zig_triple) catch |err| switch (err) { error.OutOfMemory => return .OutOfMemory, + error.UnknownArchitecture => return .UnknownArchitecture, + error.UnknownSubArchitecture => return .UnknownSubArchitecture, + error.UnknownOperatingSystem => return .UnknownOperatingSystem, + error.UnknownApplicationBinaryInterface => return .UnknownApplicationBinaryInterface, + error.MissingOperatingSystem => return .MissingOperatingSystem, + error.MissingArchitecture => return .MissingArchitecture, }; return .None; } +fn cpuFeaturesBaseline(zig_triple: [*:0]const u8) !*Stage2CpuFeatures { + const target = try Target.parse(mem.toSliceConst(u8, zig_triple)); + const arch = target.Cross.arch; + return Stage2CpuFeatures.createBaseline(std.heap.c_allocator, arch); +} + // ABI warning export fn stage2_cpu_features_llvm( result: **Stage2CpuFeatures, diff --git a/src/codegen.cpp b/src/codegen.cpp index 9cbd5fc6a..ffdf0e5bb 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -8802,6 +8802,8 @@ static void init(CodeGen *g) { target_specific_cpu_args = stage2_cpu_features_get_llvm_cpu(g->zig_target->cpu_features); target_specific_features = stage2_cpu_features_get_llvm_features(g->zig_target->cpu_features); } + //fprintf(stderr, "name=%s target_specific_cpu_args=%s\n", buf_ptr(g->root_out_name), target_specific_cpu_args); + //fprintf(stderr, "name=%s target_specific_features=%s\n", buf_ptr(g->root_out_name), target_specific_features); g->target_machine = ZigLLVMCreateTargetMachine(target_ref, buf_ptr(&g->llvm_triple_str), target_specific_cpu_args, target_specific_features, opt_level, reloc_mode, diff --git a/src/main.cpp b/src/main.cpp index 813eada26..d12ae850f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1005,7 +1005,7 @@ int main(int argc, char **argv) { return main_exit(root_progress_node, EXIT_FAILURE); } } else { - if ((err = stage2_cpu_features_baseline(&target.cpu_features))) { + if ((err = stage2_cpu_features_baseline(&target.cpu_features, buf_ptr(&zig_triple_buf)))) { fprintf(stderr, "unable to determine baseline CPU features: %s\n", err_str(err)); return main_exit(root_progress_node, EXIT_FAILURE); } diff --git a/src/userland.cpp b/src/userland.cpp index 9a923e1b8..64849b65e 100644 --- a/src/userland.cpp +++ b/src/userland.cpp @@ -104,7 +104,7 @@ Error stage2_cpu_features_parse_features(Stage2CpuFeatures **out, const char *zi const char *msg = "stage0 called stage2_cpu_features_parse_features"; stage2_panic(msg, strlen(msg)); } -Error stage2_cpu_features_baseline(Stage2CpuFeatures **out) { +Error stage2_cpu_features_baseline(Stage2CpuFeatures **out, const char *zig_triple) { Stage2CpuFeatures *result = allocate(1, "Stage2CpuFeatures"); result->builtin_str = ".baseline;\n"; result->cache_hash = "\n\n"; diff --git a/src/userland.h b/src/userland.h index 1a07b605e..01faf0b53 100644 --- a/src/userland.h +++ b/src/userland.h @@ -192,7 +192,8 @@ ZIG_EXTERN_C Error stage2_cpu_features_parse_features(struct Stage2CpuFeatures * const char *zig_triple, const char *features); // ABI warning -ZIG_EXTERN_C Error stage2_cpu_features_baseline(struct Stage2CpuFeatures **result); +ZIG_EXTERN_C Error stage2_cpu_features_baseline(struct Stage2CpuFeatures **result, + const char *zig_triple); // ABI warning ZIG_EXTERN_C Error stage2_cpu_features_llvm(struct Stage2CpuFeatures **result,