Commit fd17a9962b

Layne Gustafson <lgustaf1@binghamton.edu>
2020-01-09 04:29:12
Add defaut feature support
1 parent 03dd376
Changed files (5)
src/codegen.cpp
@@ -8781,8 +8781,9 @@ static void init(CodeGen *g) {
         reloc_mode = LLVMRelocStatic;
     }
 
-    const char *target_specific_cpu_args;
-    const char *target_specific_features;
+    const char *target_specific_cpu_args = "";
+    const char *target_specific_features = "";
+
     if (g->zig_target->is_native) {
         // LLVM creates invalid binaries on Windows sometimes.
         // See https://github.com/ziglang/zig/issues/508
@@ -8794,22 +8795,6 @@ static void init(CodeGen *g) {
             target_specific_cpu_args = ZigLLVMGetHostCPUName();
             target_specific_features = ZigLLVMGetNativeFeatures();
         }
-    } else if (target_is_riscv(g->zig_target)) {
-        // TODO https://github.com/ziglang/zig/issues/2883
-        // Be aware of https://github.com/ziglang/zig/issues/3275
-        target_specific_cpu_args = "";
-        target_specific_features = riscv_default_features;
-    } else if (g->zig_target->arch == ZigLLVM_x86) {
-        // This is because we're really targeting i686 rather than i386.
-        // It's pretty much impossible to use many of the language features
-        // such as fp16 if you stick use the x87 only. This is also what clang
-        // uses as base cpu.
-        // TODO https://github.com/ziglang/zig/issues/2883
-        target_specific_cpu_args = "pentium4";
-        target_specific_features = (g->zig_target->os == OsFreestanding) ? "-sse": "";
-    } else {
-        target_specific_cpu_args = "";
-        target_specific_features = "";
     }
 
     // Override CPU and features if defined by user.
src/main.cpp
@@ -1090,6 +1090,12 @@ int main(int argc, char **argv) {
             fprintf(stderr, "invalid --features value\n");
             return main_exit(root_progress_node, EXIT_FAILURE);
         }
+    } else {
+        // If no details are specified and we are not native, load
+        // cross-compilation default features.
+        if (!target.is_native) {
+            target_details = stage2_target_details_get_default(target_arch_name(target.arch), target_os_name(target.os));
+        }
     }
 
     if (output_dir != nullptr && enable_cache == CacheOptOn) {
src/userland.cpp
@@ -109,3 +109,6 @@ const char *stage2_target_details_get_llvm_features(const Stage2TargetDetails *t
 const char *stage2_target_details_get_builtin_str(const Stage2TargetDetails *target_details) {
     return "";
 }
+Stage2TargetDetails *stage2_target_details_get_default(const char *arch, const char *os) {
+    return nullptr;
+}
src/userland.h
@@ -201,4 +201,7 @@ ZIG_EXTERN_C const char *stage2_target_details_get_llvm_features(const Stage2Tar
 // ABI warning
 ZIG_EXTERN_C const char *stage2_target_details_get_builtin_str(const Stage2TargetDetails *target_details);
 
+// ABI warning
+ZIG_EXTERN_C Stage2TargetDetails *stage2_target_details_get_default(const char *arch, const char *os);
+
 #endif
src-self-hosted/stage1.zig
@@ -625,6 +625,63 @@ const Stage2TargetDetails = struct {
     llvm_features_str: [:0]const u8,
 
     builtin_str: [:0]const u8,
+
+    const Self = @This();
+
+    fn initCpu(allocator: *std.mem.Allocator, arch: @TagType(std.Target.Arch), cpu: *const std.target.Cpu) !Self {
+        var builtin_str_buffer = try std.Buffer.init(
+            allocator,
+            "@import(\"std\").target.TargetDetails{.cpu=&@import(\"std\").target.");
+        defer builtin_str_buffer.deinit();
+
+        try builtin_str_buffer.append(@tagName(arch));
+        try builtin_str_buffer.append(".cpu_");
+        try builtin_str_buffer.append(cpu.name);
+        try builtin_str_buffer.append("};");
+        return Self{
+            .allocator = allocator,
+            .target_details = .{
+                .cpu = cpu,
+            },
+            .llvm_cpu_str = cpu.name,
+            .llvm_features_str = "",
+            .builtin_str = builtin_str_buffer.toOwnedSlice(),
+        };
+    }
+
+    fn initFeatures(allocator: *std.mem.Allocator, arch: @TagType(std.Target.Arch), features: []*const std.target.Feature) !Self {
+        var builtin_str_buffer = try std.Buffer.init(
+            allocator, 
+            "@import(\"std\").target.TargetDetails{.features=&[_]*const @import(\"std\").target.Feature{\n");
+        defer builtin_str_buffer.deinit();
+
+        var llvm_features_buffer = try std.Buffer.initSize(allocator, 0);
+        defer llvm_features_buffer.deinit();
+
+        for (features) |feature| {
+            try llvm_features_buffer.append("+");
+            try llvm_features_buffer.append(feature.llvm_name);
+            try llvm_features_buffer.append(",");
+            
+            try builtin_str_buffer.append("&@import(\"std\").target.");
+            try builtin_str_buffer.append(@tagName(arch));
+            try builtin_str_buffer.append(".feature_");
+            try builtin_str_buffer.append(feature.name);
+            try builtin_str_buffer.append(",");
+        }
+
+        try builtin_str_buffer.append("}};");
+
+        return Self{
+            .allocator = allocator,
+            .target_details = std.target.TargetDetails{
+                .features = features,
+            },
+            .llvm_cpu_str = "",
+            .llvm_features_str = llvm_features_buffer.toOwnedSlice(),
+            .builtin_str = builtin_str_buffer.toOwnedSlice(),
+        };
+    }
 };
 
 // ABI warning
@@ -658,32 +715,14 @@ export fn stage2_target_details_parse_features(arch_str: ?[*:0]const u8, feature
 }
 
 fn parseCpu(arch: @TagType(std.Target.Arch), str: []const u8) !*Stage2TargetDetails {
+    const allocator = std.heap.c_allocator;
+
     const cpus = std.target.getCpusForArch(arch);
 
     for (cpus) |cpu| {
         if (std.mem.eql(u8, str, cpu.name)) {
-            const allocator = std.heap.c_allocator;
-
-            var builtin_str_buffer = try std.Buffer.init(
-                allocator,
-                "@import(\"std\").target.TargetDetails{.cpu=&@import(\"std\").target.");
-            defer builtin_str_buffer.deinit();
-
-            try builtin_str_buffer.append(@tagName(arch));
-            try builtin_str_buffer.append(".cpu_");
-            try builtin_str_buffer.append(cpu.name);
-            try builtin_str_buffer.append("};");
-
             const ptr = try allocator.create(Stage2TargetDetails);
-            ptr.* = .{
-                .allocator = allocator,
-                .target_details = .{
-                    .cpu = cpu,
-                },
-                .llvm_cpu_str = cpu.name,
-                .llvm_features_str = "",
-                .builtin_str = builtin_str_buffer.toOwnedSlice(),
-            };
+            ptr.* = try Stage2TargetDetails.initCpu(std.heap.c_allocator, arch, cpu);
 
             return ptr;
         }
@@ -700,11 +739,6 @@ fn parseFeatures(arch: @TagType(std.Target.Arch), str: []const u8) !*Stage2Targe
     var features = std.ArrayList(*const std.target.Feature).init(allocator);
     defer features.deinit();
 
-    var builtin_str_buffer = try std.Buffer.init(
-        allocator, 
-        "@import(\"std\").target.TargetDetails{.features=&[_]*const @import(\"std\").target.Feature{\n");
-    defer builtin_str_buffer.deinit();
-
     var start: usize = 0;
     while (start < str.len) {
         const next_comma_pos = std.mem.indexOfScalar(u8, str[start..], ',') orelse str.len - start;
@@ -725,39 +759,15 @@ fn parseFeatures(arch: @TagType(std.Target.Arch), str: []const u8) !*Stage2Targe
         if (feature) |f| {
             features.append(f) catch @panic("out of memory");
 
-            try builtin_str_buffer.append("&@import(\"std\").target.");
-            try builtin_str_buffer.append(@tagName(arch));
-            try builtin_str_buffer.append(".feature_");
-            try builtin_str_buffer.append(f.name);
-            try builtin_str_buffer.append(",");
         } else {
             return error.InvalidFeature;
         }
     }
 
-    try builtin_str_buffer.append("}};");
-    
     const features_slice = features.toOwnedSlice();
 
-    var llvm_features_buffer = try std.Buffer.initSize(allocator, 0);
-    defer llvm_features_buffer.deinit();
-
-    for (features_slice) |feature| {
-        try llvm_features_buffer.append("+");
-        try llvm_features_buffer.append(feature.llvm_name);
-        try llvm_features_buffer.append(",");
-    }
-
     const ptr = try allocator.create(Stage2TargetDetails);
-    ptr.* = Stage2TargetDetails{
-        .allocator = allocator,
-        .target_details = std.target.TargetDetails{
-            .features = features_slice,
-        },
-        .llvm_cpu_str = "",
-        .llvm_features_str = llvm_features_buffer.toOwnedSlice(),
-        .builtin_str = builtin_str_buffer.toOwnedSlice(),
-    };
+    ptr.* = try Stage2TargetDetails.initFeatures(allocator, arch, features_slice);
 
     return ptr;
 }
@@ -800,3 +810,68 @@ export fn stage2_target_details_get_builtin_str(target_details: ?*const Stage2Ta
 
     return @as([*:0]const u8, "");
 }
+
+const riscv_default_features: []*const std.target.Feature = &[_]*const std.target.Feature {
+    &std.target.riscv.feature_a,
+    &std.target.riscv.feature_c,
+    &std.target.riscv.feature_d,
+    &std.target.riscv.feature_f,
+    &std.target.riscv.feature_m,
+    &std.target.riscv.feature_relax,
+};
+
+const i386_default_features: []*const std.target.Feature = &[_]*const std.target.Feature {
+    &std.target.x86.feature_cmov,
+    &std.target.x86.feature_cx8,
+    &std.target.x86.feature_fxsr,
+    &std.target.x86.feature_mmx,
+    &std.target.x86.feature_nopl,
+    &std.target.x86.feature_sse,
+    &std.target.x86.feature_sse2,
+    &std.target.x86.feature_slowUnalignedMem16,
+    &std.target.x86.feature_x87,
+};
+
+// Same as above but without sse.
+const i386_default_features_freestanding: []*const std.target.Feature = &[_]*const std.target.Feature {
+    &std.target.x86.feature_cmov,
+    &std.target.x86.feature_cx8,
+    &std.target.x86.feature_fxsr,
+    &std.target.x86.feature_mmx,
+    &std.target.x86.feature_nopl,
+    &std.target.x86.feature_slowUnalignedMem16,
+    &std.target.x86.feature_x87,
+};
+
+// ABI warning
+export fn stage2_target_details_get_default(arch_str: ?[*:0]const u8, os_str: ?[*:0]const u8) ?*Stage2TargetDetails {
+    if (arch_str == null) return null;
+    if (os_str == null) return null;
+    
+    const arch = Target.parseArchTag(std.mem.toSliceConst(u8, arch_str.?)) catch return null;
+    const os = Target.parseOs(std.mem.toSliceConst(u8, os_str.?)) catch return null;
+
+    return createDefaultTargetDetails(arch, os) catch return null;
+}
+
+fn createDefaultTargetDetails(arch: @TagType(std.Target.Arch), os: std.Target.Os) !?*Stage2TargetDetails {
+    const allocator = std.heap.c_allocator;
+
+    return switch (arch) {
+        .riscv32, .riscv64 => blk: {
+            const ptr = try allocator.create(Stage2TargetDetails);
+            ptr.* = try Stage2TargetDetails.initFeatures(allocator, arch, riscv_default_features);
+            break :blk ptr;
+        },
+        .i386 => blk: {
+            const ptr = try allocator.create(Stage2TargetDetails);
+            const features = switch (os) {
+                .freestanding => i386_default_features_freestanding,
+                else => i386_default_features,
+            };
+            ptr.* = try Stage2TargetDetails.initFeatures(allocator, arch, features);
+            break :blk ptr;
+        },
+        else => null,
+    };
+}