Commit d448c3d38a

Valentin Anger <syrupthinker@gryphno.de>
2020-01-29 13:22:11
Add support for code model selection
1 parent 59bc1d2
lib/std/build.zig
@@ -1149,6 +1149,7 @@ pub const LibExeObjStep = struct {
     name_prefix: []const u8,
     filter: ?[]const u8,
     single_threaded: bool,
+    code_model: builtin.CodeModel = .default,
 
     root_src: ?FileSource,
     out_h_filename: []const u8,
@@ -1970,6 +1971,11 @@ pub const LibExeObjStep = struct {
             try zig_args.append("-fno-sanitize-c");
         }
 
+        if (self.code_model != .default) {
+            try zig_args.append("-code-model");
+            try zig_args.append(@tagName(self.code_model));
+        }
+
         switch (self.target) {
             .Native => {},
             .Cross => |cross| {
lib/std/builtin.zig
@@ -91,6 +91,21 @@ pub const AtomicRmwOp = enum {
     Min,
 };
 
+/// The code model puts constraints on the location of symbols and the size of code and data.
+/// The selection of a code model is a trade off on speed and restrictions that needs to be selected on a per application basis to meet its requirements.
+/// A slightly more detailed explanation can be found in (for example) the [System V Application Binary Interface (x86_64)](https://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-1.0.pdf) 3.5.1.
+///
+/// This data structure is used by the Zig language code generation and
+/// therefore must be kept in sync with the compiler implementation.
+pub const CodeModel = enum {
+    default,
+    tiny,
+    small,
+    kernel,
+    medium,
+    large,
+};
+
 /// This data structure is used by the Zig language code generation and
 /// therefore must be kept in sync with the compiler implementation.
 pub const Mode = enum {
src/all_types.hpp
@@ -1947,6 +1947,15 @@ enum BuildMode {
     BuildModeSmallRelease,
 };
 
+enum CodeModel {
+    CodeModelDefault,
+    CodeModelTiny,
+    CodeModelSmall,
+    CodeModelKernel,
+    CodeModelMedium,
+    CodeModelLarge,
+};
+
 enum EmitFileType {
     EmitFileTypeBinary,
     EmitFileTypeAssembly,
@@ -2235,6 +2244,7 @@ struct CodeGen {
     bool enable_dump_analysis;
     bool enable_doc_generation;
     bool disable_bin_generation;
+    CodeModel code_model;
 
     Buf *mmacosx_version_min;
     Buf *mios_version_min;
src/codegen.cpp
@@ -8365,6 +8365,25 @@ static bool detect_err_ret_tracing(CodeGen *g) {
         g->build_mode != BuildModeSmallRelease;
 }
 
+static LLVMCodeModel to_llvm_code_model(CodeGen *g) {
+        switch (g->code_model) {
+            case CodeModelDefault:
+                return LLVMCodeModelDefault;
+            case CodeModelTiny:
+                return LLVMCodeModelTiny;
+            case CodeModelSmall:
+                return LLVMCodeModelSmall;
+            case CodeModelKernel:
+                return LLVMCodeModelKernel;
+            case CodeModelMedium:
+                return LLVMCodeModelMedium;
+            case CodeModelLarge:
+                return LLVMCodeModelLarge;
+        }
+
+        zig_unreachable();
+}
+
 Buf *codegen_generate_builtin_source(CodeGen *g) {
     g->have_dynamic_link = detect_dynamic_link(g);
     g->have_pic = detect_pic(g);
@@ -8544,6 +8563,34 @@ Buf *codegen_generate_builtin_source(CodeGen *g) {
     buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic));
     buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols));
 
+    {
+        const char *code_model;
+        switch (g->code_model) {
+        case CodeModelDefault:
+            code_model = "default";
+            break;
+        case CodeModelTiny:
+            code_model = "tiny";
+            break;
+        case CodeModelSmall:
+            code_model = "small";
+            break;
+        case CodeModelKernel:
+            code_model = "kernel";
+            break;
+        case CodeModelMedium:
+            code_model = "medium";
+            break;
+        case CodeModelLarge:
+            code_model = "large";
+            break;
+        default:
+            zig_unreachable();
+        }
+
+        buf_appendf(contents, "pub const code_model = CodeModel.%s;\n", code_model);
+    }
+
     {
         TargetSubsystem detected_subsystem = detect_subsystem(g);
         if (detected_subsystem != TargetSubsystemAuto) {
@@ -8588,6 +8635,7 @@ static Error define_builtin_compile_vars(CodeGen *g) {
     cache_bool(&cache_hash, g->is_dynamic);
     cache_bool(&cache_hash, g->is_test_build);
     cache_bool(&cache_hash, g->is_single_threaded);
+    cache_int(&cache_hash, g->code_model);
     cache_int(&cache_hash, g->zig_target->is_native);
     cache_int(&cache_hash, g->zig_target->arch);
     cache_int(&cache_hash, g->zig_target->sub_arch);
@@ -8745,7 +8793,7 @@ static void init(CodeGen *g) {
     
     g->target_machine = ZigLLVMCreateTargetMachine(target_ref, buf_ptr(&g->llvm_triple_str),
             target_specific_cpu_args, target_specific_features, opt_level, reloc_mode,
-            LLVMCodeModelDefault, g->function_sections);
+            to_llvm_code_model(g), g->function_sections);
 
     g->target_data_ref = LLVMCreateTargetDataLayout(g->target_machine);
 
@@ -9527,6 +9575,8 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose
     cache_bool(cache_hash, g->have_sanitize_c);
     cache_bool(cache_hash, want_valgrind_support(g));
     cache_bool(cache_hash, g->function_sections);
+    cache_int(cache_hash, g->code_model);
+
     for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) {
         cache_str(cache_hash, g->clang_argv[arg_i]);
     }
@@ -10696,6 +10746,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget
     g->one_possible_values.init(32);
     g->is_test_build = is_test_build;
     g->is_single_threaded = false;
+    g->code_model = CodeModelDefault;
     buf_resize(&g->global_asm, 0);
 
     for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) {
src/main.cpp
@@ -103,6 +103,9 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
         "  -D[macro]=[value]            define C [macro] to [value] (1 if [value] omitted)\n"
         "  -target-cpu [cpu]            target one specific CPU by name\n"
         "  -target-feature [features]   specify the set of CPU features to target\n"
+        "  -code-model [default|tiny|   set target code model\n"
+        "               small|kernel|\n"
+        "               medium|large]\n"
         "\n"
         "Link Options:\n"
         "  --bundle-compiler-rt         for static libraries, include compiler-rt symbols\n"
@@ -452,6 +455,7 @@ int main(int argc, char **argv) {
     bool function_sections = false;
     const char *cpu = nullptr;
     const char *features = nullptr;
+    CodeModel code_model = CodeModelDefault;
 
     ZigList<const char *> llvm_argv = {0};
     llvm_argv.append("zig (LLVM option parsing)");
@@ -768,6 +772,23 @@ int main(int argc, char **argv) {
                     clang_argv.append(argv[i]);
 
                     llvm_argv.append(argv[i]);
+                } else if (strcmp(arg, "-code-model") == 0) {
+                    if (strcmp(argv[i], "default") == 0) {
+                        code_model = CodeModelDefault;
+                    } else if (strcmp(argv[i], "tiny") == 0) {
+                        code_model = CodeModelTiny;
+                    } else if (strcmp(argv[i], "small") == 0) {
+                        code_model = CodeModelSmall;
+                    } else if (strcmp(argv[i], "kernel") == 0) {
+                        code_model = CodeModelKernel;
+                    } else if (strcmp(argv[i], "medium") == 0) {
+                        code_model = CodeModelMedium;
+                    } else if (strcmp(argv[i], "large") == 0) {
+                        code_model = CodeModelLarge;
+                    } else {
+                        fprintf(stderr, "-code-model options are 'default', 'tiny', 'small', 'kernel', 'medium', or 'large'\n");
+                        return print_error_usage(arg0);
+                    }
                 } else if (strcmp(arg, "--override-lib-dir") == 0) {
                     override_lib_dir = buf_create_from_str(argv[i]);
                 } else if (strcmp(arg, "--main-pkg-path") == 0) {
@@ -1170,6 +1191,7 @@ int main(int argc, char **argv) {
             codegen_set_errmsg_color(g, color);
             g->system_linker_hack = system_linker_hack;
             g->function_sections = function_sections;
+            g->code_model = code_model;
 
 
             for (size_t i = 0; i < lib_dirs.length; i += 1) {