Commit 94f7c56001

Andrew Kelley <andrew@ziglang.org>
2020-03-23 02:47:19
riscv: add -mrelax arg for C to work around upstream issue
See #4485
1 parent e5e5196
Changed files (5)
src/analyze.hpp
@@ -257,7 +257,13 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose
 LLVMTypeRef get_llvm_type(CodeGen *g, ZigType *type);
 ZigLLVMDIType *get_llvm_di_type(CodeGen *g, ZigType *type);
 
-void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_path, bool translate_c);
+enum CSourceKind {
+    CSourceKindAsm,
+    CSourceKindC,
+};
+
+void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_path, bool translate_c,
+        CSourceKind source_kind);
 
 void src_assert(bool ok, AstNode *source_node);
 bool is_container(ZigType *type_entry);
src/codegen.cpp
@@ -9155,13 +9155,15 @@ static void detect_libc(CodeGen *g) {
 }
 
 // does not add the "cc" arg
-void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_path, bool translate_c) {
+void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_path,
+        bool translate_c, CSourceKind source_kind)
+{
     if (translate_c) {
         args.append("-x");
         args.append("c");
     }
 
-    if (out_dep_path != nullptr) {
+    if (source_kind != CSourceKindAsm && out_dep_path != nullptr) {
         args.append("-MD");
         args.append("-MV");
         args.append("-MF");
@@ -9176,10 +9178,12 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
     }
 
     if (translate_c) {
-        // this gives us access to preprocessing entities, presumably at
-        // the cost of performance
-        args.append("-Xclang");
-        args.append("-detailed-preprocessing-record");
+        if (source_kind == CSourceKindC) {
+            // this gives us access to preprocessing entities, presumably at
+            // the cost of performance
+            args.append("-Xclang");
+            args.append("-detailed-preprocessing-record");
+        }
     } else {
         switch (g->err_color) {
             case ErrColorAuto:
@@ -9212,26 +9216,29 @@ void add_cc_args(CodeGen *g, ZigList<const char *> &args, const char *out_dep_pa
         args.append(include_dir);
     }
 
-    if (g->zig_target->is_native) {
-        if (target_supports_clang_march_native(g->zig_target)) {
-            args.append("-march=native");
-        }
-    } else {
-        args.append("-target");
-        args.append(buf_ptr(&g->llvm_triple_str));
+    args.append("-target");
+    args.append(buf_ptr(&g->llvm_triple_str));
 
-        if (g->zig_target->llvm_cpu_name != nullptr) {
-            args.append("-Xclang");
-            args.append("-target-cpu");
-            args.append("-Xclang");
-            args.append(g->zig_target->llvm_cpu_name);
-        }
-        if (g->zig_target->llvm_cpu_features != nullptr) {
-            args.append("-Xclang");
-            args.append("-target-feature");
-            args.append("-Xclang");
-            args.append(g->zig_target->llvm_cpu_features);
-        }
+    switch (source_kind) {
+        case CSourceKindC:
+            if (g->zig_target->llvm_cpu_name != nullptr) {
+                args.append("-Xclang");
+                args.append("-target-cpu");
+                args.append("-Xclang");
+                args.append(g->zig_target->llvm_cpu_name);
+            }
+            if (g->zig_target->llvm_cpu_features != nullptr) {
+                args.append("-Xclang");
+                args.append("-target-feature");
+                args.append("-Xclang");
+                args.append(g->zig_target->llvm_cpu_features);
+            }
+            break;
+        case CSourceKindAsm:
+            break;
+    }
+    for (size_t i = 0; i < g->zig_target->llvm_cpu_features_asm_len; i += 1) {
+        args.append(g->zig_target->llvm_cpu_features_asm_ptr[i]);
     }
 
     if (g->zig_target->os == OsFreestanding) {
@@ -9377,7 +9384,7 @@ void codegen_translate_c(CodeGen *g, Buf *full_path) {
     }
 
     ZigList<const char *> clang_argv = {0};
-    add_cc_args(g, clang_argv, out_dep_path_cstr, true);
+    add_cc_args(g, clang_argv, out_dep_path_cstr, true, CSourceKindC);
 
     clang_argv.append(buf_ptr(full_path));
 
@@ -9714,6 +9721,15 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
     Buf *c_source_basename = buf_alloc();
     os_path_split(c_source_file, nullptr, c_source_basename);
 
+    CSourceKind c_source_kind;
+    if (buf_ends_with_str(c_source_basename, ".s") ||
+        buf_ends_with_str(c_source_basename, ".S"))
+    {
+        c_source_kind = CSourceKindAsm;
+    } else {
+        c_source_kind = CSourceKindC;
+    }
+
     Stage2ProgressNode *child_prog_node = stage2_progress_start(g->sub_progress_node, buf_ptr(c_source_basename),
             buf_len(c_source_basename), 0);
 
@@ -9786,7 +9802,7 @@ static void gen_c_object(CodeGen *g, Buf *self_exe_path, CFile *c_file) {
         }
 
         Buf *out_dep_path = buf_sprintf("%s.d", buf_ptr(out_obj_path));
-        add_cc_args(g, args, buf_ptr(out_dep_path), false);
+        add_cc_args(g, args, buf_ptr(out_dep_path), false, c_source_kind);
 
         args.append("-o");
         args.append(buf_ptr(out_obj_path));
src/ir.cpp
@@ -25126,7 +25126,7 @@ static IrInstGen *ir_analyze_instruction_c_import(IrAnalyze *ira, IrInstSrcCImpo
 
         ZigList<const char *> clang_argv = {0};
 
-        add_cc_args(ira->codegen, clang_argv, buf_ptr(tmp_dep_file), true);
+        add_cc_args(ira->codegen, clang_argv, buf_ptr(tmp_dep_file), true, CSourceKindC);
 
         clang_argv.append(buf_ptr(&tmp_c_file_path));
 
src/stage2.h
@@ -293,6 +293,9 @@ struct ZigTarget {
     const char *os_builtin_str;
     const char *dynamic_linker;
     const char *standard_dynamic_linker_path;
+
+    const char **llvm_cpu_features_asm_ptr;
+    size_t llvm_cpu_features_asm_len;
 };
 
 // ABI warning
src-self-hosted/stage2.zig
@@ -912,6 +912,9 @@ const Stage2Target = extern struct {
     dynamic_linker: ?[*:0]const u8,
     standard_dynamic_linker_path: ?[*:0]const u8,
 
+    llvm_cpu_features_asm_ptr: [*]const [*:0]const u8,
+    llvm_cpu_features_asm_len: usize,
+
     fn fromTarget(self: *Stage2Target, cross_target: CrossTarget) !void {
         const allocator = std.heap.c_allocator;
 
@@ -943,6 +946,12 @@ const Stage2Target = extern struct {
         var llvm_features_buffer = try std.Buffer.initSize(allocator, 0);
         defer llvm_features_buffer.deinit();
 
+        // Unfortunately we have to do the work twice, because Clang does not support
+        // the same command line parameters for CPU features when assembling code as it does
+        // when compiling C code.
+        var asm_features_list = std.ArrayList([*:0]const u8).init(allocator);
+        defer asm_features_list.deinit();
+
         for (target.cpu.arch.allFeaturesList()) |feature, index_usize| {
             const index = @intCast(Target.Cpu.Feature.Set.Index, index_usize);
             const is_enabled = target.cpu.features.isEnabled(index);
@@ -963,6 +972,21 @@ const Stage2Target = extern struct {
             }
         }
 
+        switch (target.cpu.arch) {
+            .riscv32, .riscv64 => {
+                if (std.Target.riscv.featureSetHas(target.cpu.features, .relax)) {
+                    try asm_features_list.append("-mrelax");
+                } else {
+                    try asm_features_list.append("-mno-relax");
+                }
+            },
+            else => {
+                // TODO
+                // Argh, why doesn't the assembler accept the list of CPU features?!
+                // I don't see a way to do this other than hard coding everything.
+            },
+        }
+
         try cpu_builtin_str_buffer.append(
             \\    }),
             \\};
@@ -1128,6 +1152,7 @@ const Stage2Target = extern struct {
             null;
 
         const cache_hash_slice = cache_hash.toOwnedSlice();
+        const asm_features = asm_features_list.toOwnedSlice();
         self.* = .{
             .arch = @enumToInt(target.cpu.arch) + 1, // skip over ZigLLVM_UnknownArch
             .vendor = 0,
@@ -1135,6 +1160,8 @@ const Stage2Target = extern struct {
             .abi = @enumToInt(target.abi),
             .llvm_cpu_name = if (target.cpu.model.llvm_name) |s| s.ptr else null,
             .llvm_cpu_features = llvm_features_buffer.toOwnedSlice().ptr,
+            .llvm_cpu_features_asm_ptr = asm_features.ptr,
+            .llvm_cpu_features_asm_len = asm_features.len,
             .cpu_builtin_str = cpu_builtin_str_buffer.toOwnedSlice().ptr,
             .os_builtin_str = os_builtin_str_buffer.toOwnedSlice().ptr,
             .cache_hash = cache_hash_slice.ptr,