| author | |
| committer | |
| log | d448c3d38af9f8f70daaa2817a5834e30da4b8ca |
| tree | 647e1885ea02bbe9557338d0edb818f17abaae21 |
| parent | 59bc1d272120bd860cc3cd1f894a2a4e08fc1f3f |
5 files changed, 105 insertions(+), 1 deletions(-)
lib/std/build.zig+6| ... | @@ -1149,6 +1149,7 @@ pub const LibExeObjStep = struct { | ... | @@ -1149,6 +1149,7 @@ pub const LibExeObjStep = struct { |
| 1149 | name_prefix: []const u8, | 1149 | name_prefix: []const u8, |
| 1150 | filter: ?[]const u8, | 1150 | filter: ?[]const u8, |
| 1151 | single_threaded: bool, | 1151 | single_threaded: bool, |
| 1152 | code_model: builtin.CodeModel = .default, | ||
| 1152 | 1153 | ||
| 1153 | root_src: ?FileSource, | 1154 | root_src: ?FileSource, |
| 1154 | out_h_filename: []const u8, | 1155 | out_h_filename: []const u8, |
| ... | @@ -1970,6 +1971,11 @@ pub const LibExeObjStep = struct { | ... | @@ -1970,6 +1971,11 @@ pub const LibExeObjStep = struct { |
| 1970 | try zig_args.append("-fno-sanitize-c"); | 1971 | try zig_args.append("-fno-sanitize-c"); |
| 1971 | } | 1972 | } |
| 1972 | 1973 | ||
| 1974 | if (self.code_model != .default) { | ||
| 1975 | try zig_args.append("-code-model"); | ||
| 1976 | try zig_args.append(@tagName(self.code_model)); | ||
| 1977 | } | ||
| 1978 | |||
| 1973 | switch (self.target) { | 1979 | switch (self.target) { |
| 1974 | .Native => {}, | 1980 | .Native => {}, |
| 1975 | .Cross => |cross| { | 1981 | .Cross => |cross| { |
lib/std/builtin.zig+15| ... | @@ -91,6 +91,21 @@ pub const AtomicRmwOp = enum { | ... | @@ -91,6 +91,21 @@ pub const AtomicRmwOp = enum { |
| 91 | Min, | 91 | Min, |
| 92 | }; | 92 | }; |
| 93 | 93 | ||
| 94 | /// The code model puts constraints on the location of symbols and the size of code and data. | ||
| 95 | /// 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. | ||
| 96 | /// 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. | ||
| 97 | /// | ||
| 98 | /// This data structure is used by the Zig language code generation and | ||
| 99 | /// therefore must be kept in sync with the compiler implementation. | ||
| 100 | pub const CodeModel = enum { | ||
| 101 | default, | ||
| 102 | tiny, | ||
| 103 | small, | ||
| 104 | kernel, | ||
| 105 | medium, | ||
| 106 | large, | ||
| 107 | }; | ||
| 108 | |||
| 94 | /// This data structure is used by the Zig language code generation and | 109 | /// This data structure is used by the Zig language code generation and |
| 95 | /// therefore must be kept in sync with the compiler implementation. | 110 | /// therefore must be kept in sync with the compiler implementation. |
| 96 | pub const Mode = enum { | 111 | pub const Mode = enum { |
src/all_types.hpp+10| ... | @@ -1947,6 +1947,15 @@ enum BuildMode { | ... | @@ -1947,6 +1947,15 @@ enum BuildMode { |
| 1947 | BuildModeSmallRelease, | 1947 | BuildModeSmallRelease, |
| 1948 | }; | 1948 | }; |
| 1949 | 1949 | ||
| 1950 | enum CodeModel { | ||
| 1951 | CodeModelDefault, | ||
| 1952 | CodeModelTiny, | ||
| 1953 | CodeModelSmall, | ||
| 1954 | CodeModelKernel, | ||
| 1955 | CodeModelMedium, | ||
| 1956 | CodeModelLarge, | ||
| 1957 | }; | ||
| 1958 | |||
| 1950 | enum EmitFileType { | 1959 | enum EmitFileType { |
| 1951 | EmitFileTypeBinary, | 1960 | EmitFileTypeBinary, |
| 1952 | EmitFileTypeAssembly, | 1961 | EmitFileTypeAssembly, |
| ... | @@ -2235,6 +2244,7 @@ struct CodeGen { | ... | @@ -2235,6 +2244,7 @@ struct CodeGen { |
| 2235 | bool enable_dump_analysis; | 2244 | bool enable_dump_analysis; |
| 2236 | bool enable_doc_generation; | 2245 | bool enable_doc_generation; |
| 2237 | bool disable_bin_generation; | 2246 | bool disable_bin_generation; |
| 2247 | CodeModel code_model; | ||
| 2238 | 2248 | ||
| 2239 | Buf *mmacosx_version_min; | 2249 | Buf *mmacosx_version_min; |
| 2240 | Buf *mios_version_min; | 2250 | Buf *mios_version_min; |
src/codegen.cpp+52-1| ... | @@ -8365,6 +8365,25 @@ static bool detect_err_ret_tracing(CodeGen *g) { | ... | @@ -8365,6 +8365,25 @@ static bool detect_err_ret_tracing(CodeGen *g) { |
| 8365 | g->build_mode != BuildModeSmallRelease; | 8365 | g->build_mode != BuildModeSmallRelease; |
| 8366 | } | 8366 | } |
| 8367 | 8367 | ||
| 8368 | static LLVMCodeModel to_llvm_code_model(CodeGen *g) { | ||
| 8369 | switch (g->code_model) { | ||
| 8370 | case CodeModelDefault: | ||
| 8371 | return LLVMCodeModelDefault; | ||
| 8372 | case CodeModelTiny: | ||
| 8373 | return LLVMCodeModelTiny; | ||
| 8374 | case CodeModelSmall: | ||
| 8375 | return LLVMCodeModelSmall; | ||
| 8376 | case CodeModelKernel: | ||
| 8377 | return LLVMCodeModelKernel; | ||
| 8378 | case CodeModelMedium: | ||
| 8379 | return LLVMCodeModelMedium; | ||
| 8380 | case CodeModelLarge: | ||
| 8381 | return LLVMCodeModelLarge; | ||
| 8382 | } | ||
| 8383 | |||
| 8384 | zig_unreachable(); | ||
| 8385 | } | ||
| 8386 | |||
| 8368 | Buf *codegen_generate_builtin_source(CodeGen *g) { | 8387 | Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 8369 | g->have_dynamic_link = detect_dynamic_link(g); | 8388 | g->have_dynamic_link = detect_dynamic_link(g); |
| 8370 | g->have_pic = detect_pic(g); | 8389 | g->have_pic = detect_pic(g); |
| ... | @@ -8544,6 +8563,34 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { | ... | @@ -8544,6 +8563,34 @@ Buf *codegen_generate_builtin_source(CodeGen *g) { |
| 8544 | buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic)); | 8563 | buf_appendf(contents, "pub const position_independent_code = %s;\n", bool_to_str(g->have_pic)); |
| 8545 | buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols)); | 8564 | buf_appendf(contents, "pub const strip_debug_info = %s;\n", bool_to_str(g->strip_debug_symbols)); |
| 8546 | 8565 | ||
| 8566 | { | ||
| 8567 | const char *code_model; | ||
| 8568 | switch (g->code_model) { | ||
| 8569 | case CodeModelDefault: | ||
| 8570 | code_model = "default"; | ||
| 8571 | break; | ||
| 8572 | case CodeModelTiny: | ||
| 8573 | code_model = "tiny"; | ||
| 8574 | break; | ||
| 8575 | case CodeModelSmall: | ||
| 8576 | code_model = "small"; | ||
| 8577 | break; | ||
| 8578 | case CodeModelKernel: | ||
| 8579 | code_model = "kernel"; | ||
| 8580 | break; | ||
| 8581 | case CodeModelMedium: | ||
| 8582 | code_model = "medium"; | ||
| 8583 | break; | ||
| 8584 | case CodeModelLarge: | ||
| 8585 | code_model = "large"; | ||
| 8586 | break; | ||
| 8587 | default: | ||
| 8588 | zig_unreachable(); | ||
| 8589 | } | ||
| 8590 | |||
| 8591 | buf_appendf(contents, "pub const code_model = CodeModel.%s;\n", code_model); | ||
| 8592 | } | ||
| 8593 | |||
| 8547 | { | 8594 | { |
| 8548 | TargetSubsystem detected_subsystem = detect_subsystem(g); | 8595 | TargetSubsystem detected_subsystem = detect_subsystem(g); |
| 8549 | if (detected_subsystem != TargetSubsystemAuto) { | 8596 | if (detected_subsystem != TargetSubsystemAuto) { |
| ... | @@ -8588,6 +8635,7 @@ static Error define_builtin_compile_vars(CodeGen *g) { | ... | @@ -8588,6 +8635,7 @@ static Error define_builtin_compile_vars(CodeGen *g) { |
| 8588 | cache_bool(&cache_hash, g->is_dynamic); | 8635 | cache_bool(&cache_hash, g->is_dynamic); |
| 8589 | cache_bool(&cache_hash, g->is_test_build); | 8636 | cache_bool(&cache_hash, g->is_test_build); |
| 8590 | cache_bool(&cache_hash, g->is_single_threaded); | 8637 | cache_bool(&cache_hash, g->is_single_threaded); |
| 8638 | cache_int(&cache_hash, g->code_model); | ||
| 8591 | cache_int(&cache_hash, g->zig_target->is_native); | 8639 | cache_int(&cache_hash, g->zig_target->is_native); |
| 8592 | cache_int(&cache_hash, g->zig_target->arch); | 8640 | cache_int(&cache_hash, g->zig_target->arch); |
| 8593 | cache_int(&cache_hash, g->zig_target->sub_arch); | 8641 | cache_int(&cache_hash, g->zig_target->sub_arch); |
| ... | @@ -8745,7 +8793,7 @@ static void init(CodeGen *g) { | ... | @@ -8745,7 +8793,7 @@ static void init(CodeGen *g) { |
| 8745 | 8793 | ||
| 8746 | g->target_machine = ZigLLVMCreateTargetMachine(target_ref, buf_ptr(&g->llvm_triple_str), | 8794 | g->target_machine = ZigLLVMCreateTargetMachine(target_ref, buf_ptr(&g->llvm_triple_str), |
| 8747 | target_specific_cpu_args, target_specific_features, opt_level, reloc_mode, | 8795 | target_specific_cpu_args, target_specific_features, opt_level, reloc_mode, |
| 8748 | LLVMCodeModelDefault, g->function_sections); | 8796 | to_llvm_code_model(g), g->function_sections); |
| 8749 | 8797 | ||
| 8750 | g->target_data_ref = LLVMCreateTargetDataLayout(g->target_machine); | 8798 | g->target_data_ref = LLVMCreateTargetDataLayout(g->target_machine); |
| 8751 | 8799 | ||
| ... | @@ -9527,6 +9575,8 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose | ... | @@ -9527,6 +9575,8 @@ Error create_c_object_cache(CodeGen *g, CacheHash **out_cache_hash, bool verbose |
| 9527 | cache_bool(cache_hash, g->have_sanitize_c); | 9575 | cache_bool(cache_hash, g->have_sanitize_c); |
| 9528 | cache_bool(cache_hash, want_valgrind_support(g)); | 9576 | cache_bool(cache_hash, want_valgrind_support(g)); |
| 9529 | cache_bool(cache_hash, g->function_sections); | 9577 | cache_bool(cache_hash, g->function_sections); |
| 9578 | cache_int(cache_hash, g->code_model); | ||
| 9579 | |||
| 9530 | for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) { | 9580 | for (size_t arg_i = 0; arg_i < g->clang_argv_len; arg_i += 1) { |
| 9531 | cache_str(cache_hash, g->clang_argv[arg_i]); | 9581 | cache_str(cache_hash, g->clang_argv[arg_i]); |
| 9532 | } | 9582 | } |
| ... | @@ -10696,6 +10746,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget | ... | @@ -10696,6 +10746,7 @@ CodeGen *codegen_create(Buf *main_pkg_path, Buf *root_src_path, const ZigTarget |
| 10696 | g->one_possible_values.init(32); | 10746 | g->one_possible_values.init(32); |
| 10697 | g->is_test_build = is_test_build; | 10747 | g->is_test_build = is_test_build; |
| 10698 | g->is_single_threaded = false; | 10748 | g->is_single_threaded = false; |
| 10749 | g->code_model = CodeModelDefault; | ||
| 10699 | buf_resize(&g->global_asm, 0); | 10750 | buf_resize(&g->global_asm, 0); |
| 10700 | 10751 | ||
| 10701 | for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) { | 10752 | for (size_t i = 0; i < array_length(symbols_that_llvm_depends_on); i += 1) { |
src/main.cpp+22| ... | @@ -103,6 +103,9 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { | ... | @@ -103,6 +103,9 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) { |
| 103 | " -D[macro]=[value] define C [macro] to [value] (1 if [value] omitted)\n" | 103 | " -D[macro]=[value] define C [macro] to [value] (1 if [value] omitted)\n" |
| 104 | " -target-cpu [cpu] target one specific CPU by name\n" | 104 | " -target-cpu [cpu] target one specific CPU by name\n" |
| 105 | " -target-feature [features] specify the set of CPU features to target\n" | 105 | " -target-feature [features] specify the set of CPU features to target\n" |
| 106 | " -code-model [default|tiny| set target code model\n" | ||
| 107 | " small|kernel|\n" | ||
| 108 | " medium|large]\n" | ||
| 106 | "\n" | 109 | "\n" |
| 107 | "Link Options:\n" | 110 | "Link Options:\n" |
| 108 | " --bundle-compiler-rt for static libraries, include compiler-rt symbols\n" | 111 | " --bundle-compiler-rt for static libraries, include compiler-rt symbols\n" |
| ... | @@ -452,6 +455,7 @@ int main(int argc, char **argv) { | ... | @@ -452,6 +455,7 @@ int main(int argc, char **argv) { |
| 452 | bool function_sections = false; | 455 | bool function_sections = false; |
| 453 | const char *cpu = nullptr; | 456 | const char *cpu = nullptr; |
| 454 | const char *features = nullptr; | 457 | const char *features = nullptr; |
| 458 | CodeModel code_model = CodeModelDefault; | ||
| 455 | 459 | ||
| 456 | ZigList<const char *> llvm_argv = {0}; | 460 | ZigList<const char *> llvm_argv = {0}; |
| 457 | llvm_argv.append("zig (LLVM option parsing)"); | 461 | llvm_argv.append("zig (LLVM option parsing)"); |
| ... | @@ -768,6 +772,23 @@ int main(int argc, char **argv) { | ... | @@ -768,6 +772,23 @@ int main(int argc, char **argv) { |
| 768 | clang_argv.append(argv[i]); | 772 | clang_argv.append(argv[i]); |
| 769 | 773 | ||
| 770 | llvm_argv.append(argv[i]); | 774 | llvm_argv.append(argv[i]); |
| 775 | } else if (strcmp(arg, "-code-model") == 0) { | ||
| 776 | if (strcmp(argv[i], "default") == 0) { | ||
| 777 | code_model = CodeModelDefault; | ||
| 778 | } else if (strcmp(argv[i], "tiny") == 0) { | ||
| 779 | code_model = CodeModelTiny; | ||
| 780 | } else if (strcmp(argv[i], "small") == 0) { | ||
| 781 | code_model = CodeModelSmall; | ||
| 782 | } else if (strcmp(argv[i], "kernel") == 0) { | ||
| 783 | code_model = CodeModelKernel; | ||
| 784 | } else if (strcmp(argv[i], "medium") == 0) { | ||
| 785 | code_model = CodeModelMedium; | ||
| 786 | } else if (strcmp(argv[i], "large") == 0) { | ||
| 787 | code_model = CodeModelLarge; | ||
| 788 | } else { | ||
| 789 | fprintf(stderr, "-code-model options are 'default', 'tiny', 'small', 'kernel', 'medium', or 'large'\n"); | ||
| 790 | return print_error_usage(arg0); | ||
| 791 | } | ||
| 771 | } else if (strcmp(arg, "--override-lib-dir") == 0) { | 792 | } else if (strcmp(arg, "--override-lib-dir") == 0) { |
| 772 | override_lib_dir = buf_create_from_str(argv[i]); | 793 | override_lib_dir = buf_create_from_str(argv[i]); |
| 773 | } else if (strcmp(arg, "--main-pkg-path") == 0) { | 794 | } else if (strcmp(arg, "--main-pkg-path") == 0) { |
| ... | @@ -1170,6 +1191,7 @@ int main(int argc, char **argv) { | ... | @@ -1170,6 +1191,7 @@ int main(int argc, char **argv) { |
| 1170 | codegen_set_errmsg_color(g, color); | 1191 | codegen_set_errmsg_color(g, color); |
| 1171 | g->system_linker_hack = system_linker_hack; | 1192 | g->system_linker_hack = system_linker_hack; |
| 1172 | g->function_sections = function_sections; | 1193 | g->function_sections = function_sections; |
| 1194 | g->code_model = code_model; | ||
| 1173 | 1195 | ||
| 1174 | 1196 | ||
| 1175 | for (size_t i = 0; i < lib_dirs.length; i += 1) { | 1197 | for (size_t i = 0; i < lib_dirs.length; i += 1) { |