authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-05-02 17:34:21-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-05-02 17:34:21-04:00
log24a9a42966dc9c0654314ad99866699208776025
tree338bbf5f3aa39700e08eda107194b3ce93958059
parent7c236f6dd8194500f459b48621e2eb1997563caf

add safe release build mode

closes #288

11 files changed, 151 insertions(+), 89 deletions(-)

src/all_types.hpp+7-1
...@@ -1297,6 +1297,12 @@ struct TimeEvent {...@@ -1297,6 +1297,12 @@ struct TimeEvent {
1297 const char *name;1297 const char *name;
1298};1298};
12991299
1300enum BuildMode {
1301 BuildModeDebug,
1302 BuildModeFastRelease,
1303 BuildModeSafeRelease,
1304};
1305
1300struct CodeGen {1306struct CodeGen {
1301 LLVMModuleRef module;1307 LLVMModuleRef module;
1302 ZigList<ErrorMsg*> errors;1308 ZigList<ErrorMsg*> errors;
...@@ -1392,7 +1398,7 @@ struct CodeGen {...@@ -1392,7 +1398,7 @@ struct CodeGen {
1392 Buf *dynamic_linker;1398 Buf *dynamic_linker;
1393 Buf *ar_path;1399 Buf *ar_path;
1394 Buf triple_str;1400 Buf triple_str;
1395 bool is_release_build;1401 BuildMode build_mode;
1396 bool is_test_build;1402 bool is_test_build;
1397 uint32_t target_os_index;1403 uint32_t target_os_index;
1398 uint32_t target_arch_index;1404 uint32_t target_arch_index;
src/codegen.cpp+29-17
...@@ -55,11 +55,12 @@ static PackageTableEntry *new_package(const char *root_src_dir, const char *root...@@ -55,11 +55,12 @@ static PackageTableEntry *new_package(const char *root_src_dir, const char *root
55 return entry;55 return entry;
56}56}
5757
58CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type) {58CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode) {
59 CodeGen *g = allocate<CodeGen>(1);59 CodeGen *g = allocate<CodeGen>(1);
6060
61 codegen_add_time_event(g, "Initialize");61 codegen_add_time_event(g, "Initialize");
6262
63 g->build_mode = build_mode;
63 g->out_type = out_type;64 g->out_type = out_type;
64 g->import_table.init(32);65 g->import_table.init(32);
65 g->builtin_fn_table.init(32);66 g->builtin_fn_table.init(32);
...@@ -72,7 +73,6 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out...@@ -72,7 +73,6 @@ CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out
72 g->memoized_fn_eval_table.init(16);73 g->memoized_fn_eval_table.init(16);
73 g->exported_symbol_names.init(8);74 g->exported_symbol_names.init(8);
74 g->external_prototypes.init(8);75 g->external_prototypes.init(8);
75 g->is_release_build = false;
76 g->is_test_build = false;76 g->is_test_build = false;
77 g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib);77 g->want_h_file = (out_type == OutTypeObj || out_type == OutTypeLib);
7878
...@@ -154,10 +154,6 @@ void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) {...@@ -154,10 +154,6 @@ void codegen_set_clang_argv(CodeGen *g, const char **args, size_t len) {
154 g->clang_argv_len = len;154 g->clang_argv_len = len;
155}155}
156156
157void codegen_set_is_release(CodeGen *g, bool is_release_build) {
158 g->is_release_build = is_release_build;
159}
160
161void codegen_set_omit_zigrt(CodeGen *g, bool omit_zigrt) {157void codegen_set_omit_zigrt(CodeGen *g, bool omit_zigrt) {
162 g->omit_zigrt = omit_zigrt;158 g->omit_zigrt = omit_zigrt;
163}159}
...@@ -393,7 +389,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {...@@ -393,7 +389,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
393 }389 }
394390
395 if (fn_table_entry->body_node != nullptr) {391 if (fn_table_entry->body_node != nullptr) {
396 bool want_fn_safety = !g->is_release_build && !fn_table_entry->def_scope->safety_off;392 bool want_fn_safety = g->build_mode != BuildModeFastRelease && !fn_table_entry->def_scope->safety_off;
397 if (want_fn_safety) {393 if (want_fn_safety) {
398 if (g->link_libc) {394 if (g->link_libc) {
399 addLLVMFnAttr(fn_table_entry->llvm_value, "sspstrong");395 addLLVMFnAttr(fn_table_entry->llvm_value, "sspstrong");
...@@ -407,7 +403,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {...@@ -407,7 +403,7 @@ static LLVMValueRef fn_llvm_value(CodeGen *g, FnTableEntry *fn_table_entry) {
407 ZigLLVMAddFunctionAttrCold(fn_table_entry->llvm_value);403 ZigLLVMAddFunctionAttrCold(fn_table_entry->llvm_value);
408 }404 }
409 addLLVMFnAttr(fn_table_entry->llvm_value, "nounwind");405 addLLVMFnAttr(fn_table_entry->llvm_value, "nounwind");
410 if (!g->is_release_build && fn_table_entry->fn_inline != FnInlineAlways) {406 if (g->build_mode == BuildModeDebug && fn_table_entry->fn_inline != FnInlineAlways) {
411 ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim", "true");407 ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim", "true");
412 ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim-non-leaf", nullptr);408 ZigLLVMAddFunctionAttr(fn_table_entry->llvm_value, "no-frame-pointer-elim-non-leaf", nullptr);
413 }409 }
...@@ -440,7 +436,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {...@@ -440,7 +436,7 @@ static ZigLLVMDIScope *get_di_scope(CodeGen *g, Scope *scope) {
440 unsigned scope_line = line_number;436 unsigned scope_line = line_number;
441 bool is_definition = fn_table_entry->body_node != nullptr;437 bool is_definition = fn_table_entry->body_node != nullptr;
442 unsigned flags = 0;438 unsigned flags = 0;
443 bool is_optimized = g->is_release_build;439 bool is_optimized = g->build_mode != BuildModeDebug;
444 bool is_internal_linkage = (fn_table_entry->linkage == GlobalLinkageIdInternal);440 bool is_internal_linkage = (fn_table_entry->linkage == GlobalLinkageIdInternal);
445 ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder,441 ZigLLVMDISubprogram *subprogram = ZigLLVMCreateFunction(g->dbuilder,
446 get_di_scope(g, scope->parent), buf_ptr(&fn_table_entry->symbol_name), "",442 get_di_scope(g, scope->parent), buf_ptr(&fn_table_entry->symbol_name), "",
...@@ -555,7 +551,7 @@ static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, TypeTableEntr...@@ -555,7 +551,7 @@ static LLVMValueRef get_handle_value(CodeGen *g, LLVMValueRef ptr, TypeTableEntr
555}551}
556552
557static bool ir_want_debug_safety(CodeGen *g, IrInstruction *instruction) {553static bool ir_want_debug_safety(CodeGen *g, IrInstruction *instruction) {
558 if (g->is_release_build)554 if (g->build_mode == BuildModeFastRelease)
559 return false;555 return false;
560556
561 // TODO memoize557 // TODO memoize
...@@ -725,7 +721,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {...@@ -725,7 +721,7 @@ static LLVMValueRef get_safety_crash_err_fn(CodeGen *g) {
725 LLVMSetLinkage(fn_val, LLVMInternalLinkage);721 LLVMSetLinkage(fn_val, LLVMInternalLinkage);
726 LLVMSetFunctionCallConv(fn_val, LLVMFastCallConv);722 LLVMSetFunctionCallConv(fn_val, LLVMFastCallConv);
727 addLLVMFnAttr(fn_val, "nounwind");723 addLLVMFnAttr(fn_val, "nounwind");
728 if (!g->is_release_build) {724 if (g->build_mode == BuildModeDebug) {
729 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");725 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim", "true");
730 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim-non-leaf", nullptr);726 ZigLLVMAddFunctionAttr(fn_val, "no-frame-pointer-elim-non-leaf", nullptr);
731 }727 }
...@@ -1697,7 +1693,7 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,...@@ -1697,7 +1693,7 @@ static LLVMValueRef ir_render_decl_var(CodeGen *g, IrExecutable *executable,
1697 if (!type_has_bits(var->value->type))1693 if (!type_has_bits(var->value->type))
1698 return nullptr;1694 return nullptr;
16991695
1700 if (var->ref_count == 0 && g->is_release_build)1696 if (var->ref_count == 0 && g->build_mode != BuildModeDebug)
1701 return nullptr;1697 return nullptr;
17021698
1703 IrInstruction *init_value = decl_var_instruction->init_value;1699 IrInstruction *init_value = decl_var_instruction->init_value;
...@@ -3926,7 +3922,7 @@ static void do_code_gen(CodeGen *g) {...@@ -3926,7 +3922,7 @@ static void do_code_gen(CodeGen *g) {
3926 os_path_join(g->cache_dir, o_basename, output_path);3922 os_path_join(g->cache_dir, o_basename, output_path);
3927 ensure_cache_dir(g);3923 ensure_cache_dir(g);
3928 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),3924 if (ZigLLVMTargetMachineEmitToFile(g->target_machine, g->module, buf_ptr(output_path),
3929 LLVMObjectFile, &err_msg, !g->is_release_build))3925 LLVMObjectFile, &err_msg, g->build_mode == BuildModeDebug))
3930 {3926 {
3931 zig_panic("unable to write object file: %s", err_msg);3927 zig_panic("unable to write object file: %s", err_msg);
3932 }3928 }
...@@ -4320,6 +4316,15 @@ static const char *bool_to_str(bool b) {...@@ -4320,6 +4316,15 @@ static const char *bool_to_str(bool b) {
4320 return b ? "true" : "false";4316 return b ? "true" : "false";
4321}4317}
43224318
4319static const char *build_mode_to_str(BuildMode build_mode) {
4320 switch (build_mode) {
4321 case BuildModeDebug: return "Mode.Debug";
4322 case BuildModeSafeRelease: return "Mode.ReleaseSafe";
4323 case BuildModeFastRelease: return "Mode.ReleaseFast";
4324 }
4325 zig_unreachable();
4326}
4327
4323static void define_builtin_compile_vars(CodeGen *g) {4328static void define_builtin_compile_vars(CodeGen *g) {
4324 if (g->std_package == nullptr)4329 if (g->std_package == nullptr)
4325 return;4330 return;
...@@ -4428,13 +4433,21 @@ static void define_builtin_compile_vars(CodeGen *g) {...@@ -4428,13 +4433,21 @@ static void define_builtin_compile_vars(CodeGen *g) {
4428 " SeqCst,\n"4433 " SeqCst,\n"
4429 "};\n\n");4434 "};\n\n");
4430 }4435 }
4436 {
4437 buf_appendf(contents,
4438 "pub const Mode = enum {\n"
4439 " Debug,\n"
4440 " ReleaseSafe,\n"
4441 " ReleaseFast,\n"
4442 "};\n\n");
4443 }
4431 buf_appendf(contents, "pub const is_big_endian = %s;\n", bool_to_str(g->is_big_endian));4444 buf_appendf(contents, "pub const is_big_endian = %s;\n", bool_to_str(g->is_big_endian));
4432 buf_appendf(contents, "pub const is_release = %s;\n", bool_to_str(g->is_release_build));
4433 buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build));4445 buf_appendf(contents, "pub const is_test = %s;\n", bool_to_str(g->is_test_build));
4434 buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);4446 buf_appendf(contents, "pub const os = Os.%s;\n", cur_os);
4435 buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);4447 buf_appendf(contents, "pub const arch = Arch.%s;\n", cur_arch);
4436 buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ);4448 buf_appendf(contents, "pub const environ = Environ.%s;\n", cur_environ);
4437 buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt);4449 buf_appendf(contents, "pub const object_format = ObjectFormat.%s;\n", cur_obj_fmt);
4450 buf_appendf(contents, "pub const mode = %s;\n", build_mode_to_str(g->build_mode));
44384451
4439 {4452 {
4440 buf_appendf(contents, "pub const link_libs = [][]const u8 {\n");4453 buf_appendf(contents, "pub const link_libs = [][]const u8 {\n");
...@@ -4484,8 +4497,8 @@ static void init(CodeGen *g) {...@@ -4484,8 +4497,8 @@ static void init(CodeGen *g) {
4484 zig_panic("unable to create target based on: %s", buf_ptr(&g->triple_str));4497 zig_panic("unable to create target based on: %s", buf_ptr(&g->triple_str));
4485 }4498 }
44864499
44874500 bool is_optimized = g->build_mode != BuildModeDebug;
4488 LLVMCodeGenOptLevel opt_level = g->is_release_build ? LLVMCodeGenLevelAggressive : LLVMCodeGenLevelNone;4501 LLVMCodeGenOptLevel opt_level = is_optimized ? LLVMCodeGenLevelAggressive : LLVMCodeGenLevelNone;
44894502
4490 LLVMRelocMode reloc_mode = g->is_static ? LLVMRelocStatic : LLVMRelocPIC;4503 LLVMRelocMode reloc_mode = g->is_static ? LLVMRelocStatic : LLVMRelocPIC;
44914504
...@@ -4518,7 +4531,6 @@ static void init(CodeGen *g) {...@@ -4518,7 +4531,6 @@ static void init(CodeGen *g) {
45184531
45194532
4520 Buf *producer = buf_sprintf("zig %s", ZIG_VERSION_STRING);4533 Buf *producer = buf_sprintf("zig %s", ZIG_VERSION_STRING);
4521 bool is_optimized = g->is_release_build;
4522 const char *flags = "";4534 const char *flags = "";
4523 unsigned runtime_version = 0;4535 unsigned runtime_version = 0;
4524 ZigLLVMDIFile *compile_unit_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(g->root_out_name),4536 ZigLLVMDIFile *compile_unit_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(g->root_out_name),
src/codegen.hpp+1-2
...@@ -14,10 +14,9 @@...@@ -14,10 +14,9 @@
1414
15#include <stdio.h>15#include <stdio.h>
1616
17CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type);17CodeGen *codegen_create(Buf *root_src_path, const ZigTarget *target, OutType out_type, BuildMode build_mode);
1818
19void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);19void codegen_set_clang_argv(CodeGen *codegen, const char **args, size_t len);
20void codegen_set_is_release(CodeGen *codegen, bool is_release);
21void codegen_set_is_test(CodeGen *codegen, bool is_test);20void codegen_set_is_test(CodeGen *codegen, bool is_test);
22void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath);21void codegen_set_each_lib_rpath(CodeGen *codegen, bool each_lib_rpath);
2322
src/ir.cpp-1
...@@ -4649,7 +4649,6 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod...@@ -4649,7 +4649,6 @@ static IrInstruction *ir_gen_var_decl(IrBuilder *irb, Scope *scope, AstNode *nod
4649 if (init_value == irb->codegen->invalid_instruction)4649 if (init_value == irb->codegen->invalid_instruction)
4650 return init_value;4650 return init_value;
46514651
4652
4653 IrInstruction *result = ir_build_var_decl(irb, scope, node, var, type_instruction, init_value);4652 IrInstruction *result = ir_build_var_decl(irb, scope, node, var, type_instruction, init_value);
4654 var->decl_instruction = result;4653 var->decl_instruction = result;
4655 return result;4654 return result;
src/link.cpp+1-3
...@@ -37,7 +37,7 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) {...@@ -37,7 +37,7 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) {
37 os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path);37 os_path_join(parent_gen->zig_std_special_dir, source_basename, full_path);
3838
39 ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target;39 ZigTarget *child_target = parent_gen->is_native_target ? nullptr : &parent_gen->zig_target;
40 CodeGen *child_gen = codegen_create(full_path, child_target, OutTypeObj);40 CodeGen *child_gen = codegen_create(full_path, child_target, OutTypeObj, parent_gen->build_mode);
41 child_gen->link_libc = parent_gen->link_libc;41 child_gen->link_libc = parent_gen->link_libc;
4242
43 child_gen->link_libs.resize(parent_gen->link_libs.length);43 child_gen->link_libs.resize(parent_gen->link_libs.length);
...@@ -50,8 +50,6 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) {...@@ -50,8 +50,6 @@ static Buf *build_o(CodeGen *parent_gen, const char *oname) {
5050
51 codegen_set_cache_dir(child_gen, parent_gen->cache_dir);51 codegen_set_cache_dir(child_gen, parent_gen->cache_dir);
5252
53 codegen_set_is_release(child_gen, parent_gen->is_release_build);
54
55 codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);53 codegen_set_strip(child_gen, parent_gen->strip_debug_symbols);
56 codegen_set_is_static(child_gen, parent_gen->is_static);54 codegen_set_is_static(child_gen, parent_gen->is_static);
5755
src/main.cpp+9-7
...@@ -38,7 +38,8 @@ static int usage(const char *arg0) {...@@ -38,7 +38,8 @@ static int usage(const char *arg0) {
38 " --output-h [file] override generated header file path\n"38 " --output-h [file] override generated header file path\n"
39 " --pkg-begin [name] [path] make package available to import and push current pkg\n"39 " --pkg-begin [name] [path] make package available to import and push current pkg\n"
40 " --pkg-end pop current pkg\n"40 " --pkg-end pop current pkg\n"
41 " --release build with optimizations on and debug protection off\n"41 " --release-fast build with optimizations on and safety off\n"
42 " --release-safe build with optimizations on and safety on\n"
42 " --static output will be statically linked\n"43 " --static output will be statically linked\n"
43 " --strip exclude debug symbols\n"44 " --strip exclude debug symbols\n"
44 " --target-arch [name] specify target architecture\n"45 " --target-arch [name] specify target architecture\n"
...@@ -161,7 +162,6 @@ int main(int argc, char **argv) {...@@ -161,7 +162,6 @@ int main(int argc, char **argv) {
161 const char *in_file = nullptr;162 const char *in_file = nullptr;
162 const char *out_file = nullptr;163 const char *out_file = nullptr;
163 const char *out_file_h = nullptr;164 const char *out_file_h = nullptr;
164 bool is_release_build = false;
165 bool strip = false;165 bool strip = false;
166 bool is_static = false;166 bool is_static = false;
167 OutType out_type = OutTypeUnknown;167 OutType out_type = OutTypeUnknown;
...@@ -201,6 +201,7 @@ int main(int argc, char **argv) {...@@ -201,6 +201,7 @@ int main(int argc, char **argv) {
201 bool timing_info = false;201 bool timing_info = false;
202 const char *cache_dir = nullptr;202 const char *cache_dir = nullptr;
203 CliPkg *cur_pkg = allocate<CliPkg>(1);203 CliPkg *cur_pkg = allocate<CliPkg>(1);
204 BuildMode build_mode = BuildModeDebug;
204205
205 if (argc >= 2 && strcmp(argv[1], "build") == 0) {206 if (argc >= 2 && strcmp(argv[1], "build") == 0) {
206 const char *zig_exe_path = arg0;207 const char *zig_exe_path = arg0;
...@@ -237,7 +238,7 @@ int main(int argc, char **argv) {...@@ -237,7 +238,7 @@ int main(int argc, char **argv) {
237 }238 }
238 }239 }
239240
240 CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe);241 CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug);
241 codegen_set_out_name(g, buf_create_from_str("build"));242 codegen_set_out_name(g, buf_create_from_str("build"));
242 codegen_set_verbose(g, verbose);243 codegen_set_verbose(g, verbose);
243244
...@@ -319,8 +320,10 @@ int main(int argc, char **argv) {...@@ -319,8 +320,10 @@ int main(int argc, char **argv) {
319 char *arg = argv[i];320 char *arg = argv[i];
320321
321 if (arg[0] == '-') {322 if (arg[0] == '-') {
322 if (strcmp(arg, "--release") == 0) {323 if (strcmp(arg, "--release-fast") == 0) {
323 is_release_build = true;324 build_mode = BuildModeFastRelease;
325 } else if (strcmp(arg, "--release-safe") == 0) {
326 build_mode = BuildModeSafeRelease;
324 } else if (strcmp(arg, "--strip") == 0) {327 } else if (strcmp(arg, "--strip") == 0) {
325 strip = true;328 strip = true;
326 } else if (strcmp(arg, "--static") == 0) {329 } else if (strcmp(arg, "--static") == 0) {
...@@ -569,10 +572,9 @@ int main(int argc, char **argv) {...@@ -569,10 +572,9 @@ int main(int argc, char **argv) {
569 buf_create_from_str((cache_dir == nullptr) ? default_zig_cache_name : cache_dir),572 buf_create_from_str((cache_dir == nullptr) ? default_zig_cache_name : cache_dir),
570 full_cache_dir);573 full_cache_dir);
571574
572 CodeGen *g = codegen_create(zig_root_source_file, target, out_type);575 CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode);
573 codegen_set_out_name(g, buf_out_name);576 codegen_set_out_name(g, buf_out_name);
574 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);577 codegen_set_lib_version(g, ver_major, ver_minor, ver_patch);
575 codegen_set_is_release(g, is_release_build);
576 codegen_set_is_test(g, cmd == CmdTest);578 codegen_set_is_test(g, cmd == CmdTest);
577 codegen_set_linker_script(g, linker_script);579 codegen_set_linker_script(g, linker_script);
578 codegen_set_cache_dir(g, full_cache_dir);580 codegen_set_cache_dir(g, full_cache_dir);
std/build.zig+69-35
...@@ -405,6 +405,23 @@ pub const Builder = struct {...@@ -405,6 +405,23 @@ pub const Builder = struct {
405 return &step_info.step;405 return &step_info.step;
406 }406 }
407407
408 pub fn standardReleaseOptions(self: &Builder) -> builtin.Mode {
409 const release_safe = self.option(bool, "release-safe", "optimizations on and safety on") ?? false;
410 const release_fast = self.option(bool, "release-fast", "optimizations on and safety off") ?? false;
411
412 if (release_safe and !release_fast) {
413 return builtin.Mode.ReleaseSafe;
414 } else if (release_fast and !release_safe) {
415 return builtin.Mode.ReleaseFast;
416 } else if (!release_fast and !release_safe) {
417 return builtin.Mode.Debug;
418 } else {
419 %%io.stderr.printf("Both -Drelease-safe and -Drelease-fast specified");
420 self.markInvalidUserInput();
421 return builtin.Mode.Debug;
422 }
423 }
424
408 pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) -> bool {425 pub fn addUserInputOption(self: &Builder, name: []const u8, value: []const u8) -> bool {
409 test (%%self.user_input_options.put(name, UserInputOption {426 test (%%self.user_input_options.put(name, UserInputOption {
410 .name = name,427 .name = name,
...@@ -667,7 +684,7 @@ pub const LibExeObjStep = struct {...@@ -667,7 +684,7 @@ pub const LibExeObjStep = struct {
667 linker_script: ?[]const u8,684 linker_script: ?[]const u8,
668 link_libs: BufSet,685 link_libs: BufSet,
669 verbose: bool,686 verbose: bool,
670 release: bool,687 build_mode: builtin.Mode,
671 static: bool,688 static: bool,
672 output_path: ?[]const u8,689 output_path: ?[]const u8,
673 output_h_path: ?[]const u8,690 output_h_path: ?[]const u8,
...@@ -724,7 +741,7 @@ pub const LibExeObjStep = struct {...@@ -724,7 +741,7 @@ pub const LibExeObjStep = struct {
724 var self = LibExeObjStep {741 var self = LibExeObjStep {
725 .builder = builder,742 .builder = builder,
726 .verbose = false,743 .verbose = false,
727 .release = false,744 .build_mode = builtin.Mode.Debug,
728 .static = static,745 .static = static,
729 .kind = kind,746 .kind = kind,
730 .root_src = root_src,747 .root_src = root_src,
...@@ -794,8 +811,8 @@ pub const LibExeObjStep = struct {...@@ -794,8 +811,8 @@ pub const LibExeObjStep = struct {
794 self.verbose = value;811 self.verbose = value;
795 }812 }
796813
797 pub fn setRelease(self: &LibExeObjStep, value: bool) {814 pub fn setBuildMode(self: &LibExeObjStep, mode: builtin.Mode) {
798 self.release = value;815 self.build_mode = mode;
799 }816 }
800817
801 pub fn setOutputPath(self: &LibExeObjStep, value: []const u8) {818 pub fn setOutputPath(self: &LibExeObjStep, value: []const u8) {
...@@ -886,8 +903,10 @@ pub const LibExeObjStep = struct {...@@ -886,8 +903,10 @@ pub const LibExeObjStep = struct {
886 %%zig_args.append("--verbose");903 %%zig_args.append("--verbose");
887 }904 }
888905
889 if (self.release) {906 switch (self.build_mode) {
890 %%zig_args.append("--release");907 builtin.Mode.Debug => {},
908 builtin.Mode.ReleaseSafe => %%zig_args.append("--release-safe"),
909 builtin.Mode.ReleaseFast => %%zig_args.append("--release-fast"),
891 }910 }
892911
893 %%zig_args.append("--cache-dir");912 %%zig_args.append("--cache-dir");
...@@ -980,7 +999,7 @@ pub const TestStep = struct {...@@ -980,7 +999,7 @@ pub const TestStep = struct {
980 step: Step,999 step: Step,
981 builder: &Builder,1000 builder: &Builder,
982 root_src: []const u8,1001 root_src: []const u8,
983 release: bool,1002 build_mode: builtin.Mode,
984 verbose: bool,1003 verbose: bool,
985 link_libs: BufSet,1004 link_libs: BufSet,
986 name_prefix: []const u8,1005 name_prefix: []const u8,
...@@ -992,7 +1011,7 @@ pub const TestStep = struct {...@@ -992,7 +1011,7 @@ pub const TestStep = struct {
992 .step = Step.init(step_name, builder.allocator, make),1011 .step = Step.init(step_name, builder.allocator, make),
993 .builder = builder,1012 .builder = builder,
994 .root_src = root_src,1013 .root_src = root_src,
995 .release = false,1014 .build_mode = builtin.Mode.Debug,
996 .verbose = false,1015 .verbose = false,
997 .name_prefix = "",1016 .name_prefix = "",
998 .filter = null,1017 .filter = null,
...@@ -1004,8 +1023,8 @@ pub const TestStep = struct {...@@ -1004,8 +1023,8 @@ pub const TestStep = struct {
1004 self.verbose = value;1023 self.verbose = value;
1005 }1024 }
10061025
1007 pub fn setRelease(self: &TestStep, value: bool) {1026 pub fn setBuildMode(self: &TestStep, mode: builtin.Mode) {
1008 self.release = value;1027 self.build_mode = mode;
1009 }1028 }
10101029
1011 pub fn linkSystemLibrary(self: &TestStep, name: []const u8) {1030 pub fn linkSystemLibrary(self: &TestStep, name: []const u8) {
...@@ -1034,8 +1053,10 @@ pub const TestStep = struct {...@@ -1034,8 +1053,10 @@ pub const TestStep = struct {
1034 %%zig_args.append("--verbose");1053 %%zig_args.append("--verbose");
1035 }1054 }
10361055
1037 if (self.release) {1056 switch (self.build_mode) {
1038 %%zig_args.append("--release");1057 builtin.Mode.Debug => {},
1058 builtin.Mode.ReleaseSafe => %%zig_args.append("--release-safe"),
1059 builtin.Mode.ReleaseFast => %%zig_args.append("--release-fast"),
1039 }1060 }
10401061
1041 test (self.filter) |filter| {1062 test (self.filter) |filter| {
...@@ -1095,6 +1116,8 @@ pub const CLibExeObjStep = struct {...@@ -1095,6 +1116,8 @@ pub const CLibExeObjStep = struct {
1095 name_only_filename: []const u8,1116 name_only_filename: []const u8,
1096 object_src: []const u8,1117 object_src: []const u8,
1097 kind: Kind,1118 kind: Kind,
1119 build_mode: builtin.Mode,
1120 strip: bool,
10981121
1099 const Kind = enum {1122 const Kind = enum {
1100 Exe,1123 Exe,
...@@ -1147,6 +1170,8 @@ pub const CLibExeObjStep = struct {...@@ -1147,6 +1170,8 @@ pub const CLibExeObjStep = struct {
1147 .major_only_filename = undefined,1170 .major_only_filename = undefined,
1148 .name_only_filename = undefined,1171 .name_only_filename = undefined,
1149 .object_src = undefined,1172 .object_src = undefined,
1173 .build_mode = builtin.Mode.Debug,
1174 .strip = false,
1150 };1175 };
1151 clib.computeOutFileNames();1176 clib.computeOutFileNames();
1152 return clib;1177 return clib;
...@@ -1233,13 +1258,8 @@ pub const CLibExeObjStep = struct {...@@ -1233,13 +1258,8 @@ pub const CLibExeObjStep = struct {
1233 %%self.include_dirs.append(path);1258 %%self.include_dirs.append(path);
1234 }1259 }
12351260
1236 pub fn addCompileFlagsForRelease(self: &CLibExeObjStep, release: bool) {1261 pub fn setBuildMode(self: &CLibExeObjStep, build_mode: builtin.Mode) {
1237 if (release) {1262 self.build_mode = build_mode;
1238 %%self.cflags.append("-g");
1239 %%self.cflags.append("-O2");
1240 } else {
1241 %%self.cflags.append("-g");
1242 }
1243 }1263 }
12441264
1245 pub fn addCompileFlags(self: &CLibExeObjStep, flags: []const []const u8) {1265 pub fn addCompileFlags(self: &CLibExeObjStep, flags: []const []const u8) {
...@@ -1248,6 +1268,34 @@ pub const CLibExeObjStep = struct {...@@ -1248,6 +1268,34 @@ pub const CLibExeObjStep = struct {
1248 }1268 }
1249 }1269 }
12501270
1271 fn appendCompileFlags(self: &CLibExeObjStep, args: &List([]const u8)) {
1272 if (!self.strip) {
1273 %%args.append("-g");
1274 }
1275 switch (self.build_mode) {
1276 builtin.Mode.Debug => {},
1277 builtin.Mode.ReleaseSafe => {
1278 %%args.append("-O2");
1279 %%args.append("-D_FORTIFY_SOURCE=2");
1280 %%args.append("-fstack-protector-strong");
1281 %%args.append("--param");
1282 %%args.append("ssp-buffer-size=4");
1283 },
1284 builtin.Mode.ReleaseFast => {
1285 %%args.append("-O2");
1286 },
1287 }
1288
1289 for (self.include_dirs.toSliceConst()) |dir| {
1290 %%args.append("-I");
1291 %%args.append(self.builder.pathFromRoot(dir));
1292 }
1293
1294 for (self.cflags.toSliceConst()) |cflag| {
1295 %%args.append(cflag);
1296 }
1297 }
1298
1251 fn make(step: &Step) -> %void {1299 fn make(step: &Step) -> %void {
1252 const self = @fieldParentPtr(CLibExeObjStep, "step", step);1300 const self = @fieldParentPtr(CLibExeObjStep, "step", step);
1253 const cc = os.getEnv("CC") ?? "cc";1301 const cc = os.getEnv("CC") ?? "cc";
...@@ -1265,14 +1313,7 @@ pub const CLibExeObjStep = struct {...@@ -1265,14 +1313,7 @@ pub const CLibExeObjStep = struct {
1265 %%cc_args.append("-o");1313 %%cc_args.append("-o");
1266 %%cc_args.append(output_path);1314 %%cc_args.append(output_path);
12671315
1268 for (self.cflags.toSliceConst()) |cflag| {1316 self.appendCompileFlags(&cc_args);
1269 %%cc_args.append(cflag);
1270 }
1271
1272 for (self.include_dirs.toSliceConst()) |dir| {
1273 %%cc_args.append("-I");
1274 %%cc_args.append(builder.pathFromRoot(dir));
1275 }
12761317
1277 %return builder.spawnChild(cc, cc_args.toSliceConst());1318 %return builder.spawnChild(cc, cc_args.toSliceConst());
1278 },1319 },
...@@ -1295,14 +1336,7 @@ pub const CLibExeObjStep = struct {...@@ -1295,14 +1336,7 @@ pub const CLibExeObjStep = struct {
1295 %%cc_args.append("-o");1336 %%cc_args.append("-o");
1296 %%cc_args.append(cache_o_file);1337 %%cc_args.append(cache_o_file);
12971338
1298 for (self.cflags.toSliceConst()) |cflag| {1339 self.appendCompileFlags(&cc_args);
1299 %%cc_args.append(cflag);
1300 }
1301
1302 for (self.include_dirs.toSliceConst()) |dir| {
1303 %%cc_args.append("-I");
1304 %%cc_args.append(builder.pathFromRoot(dir));
1305 }
13061340
1307 %return builder.spawnChild(cc, cc_args.toSliceConst());1341 %return builder.spawnChild(cc, cc_args.toSliceConst());
13081342
std/hash_map.zig+1-1
...@@ -5,7 +5,7 @@ const mem = @import("mem.zig");...@@ -5,7 +5,7 @@ const mem = @import("mem.zig");
5const Allocator = mem.Allocator;5const Allocator = mem.Allocator;
6const builtin = @import("builtin");6const builtin = @import("builtin");
77
8const want_modification_safety = !builtin.is_release;8const want_modification_safety = builtin.mode != builtin.Mode.ReleaseFast;
9const debug_u32 = if (want_modification_safety) u32 else void;9const debug_u32 = if (want_modification_safety) u32 else void;
1010
11pub fn HashMap(comptime K: type, comptime V: type,11pub fn HashMap(comptime K: type, comptime V: type,
std/special/build_file_template.zig+12-2
...@@ -1,10 +1,20 @@...@@ -1,10 +1,20 @@
1const Builder = @import("std").build.Builder;1const Builder = @import("std").build.Builder;
2const Mode = @import("builtin").Mode;
23
3pub fn build(b: &Builder) {4pub fn build(b: &Builder) {
4 const release = b.option(bool, "release", "optimizations on and safety off") ?? false;5 const release_safe = b.option(bool, "--release-safe", "optimizations on and safety on") ?? false;
6 const release_fast = b.option(bool, "--release-fast", "optimizations on and safety off") ?? false;
7
8 const build_mode = if (release_safe) {
9 Mode.ReleaseSafe
10 } else if (release_fast) {
11 Mode.ReleaseFast
12 } else {
13 Mode.Debug
14 };
515
6 const exe = b.addExecutable("YOUR_NAME_HERE", "src/main.zig");16 const exe = b.addExecutable("YOUR_NAME_HERE", "src/main.zig");
7 exe.setRelease(release);17 exe.setBuildMode(build_mode);
818
9 b.default_step.dependOn(&exe.step);19 b.default_step.dependOn(&exe.step);
10}20}
std/special/builtin.zig+1-1
...@@ -32,7 +32,7 @@ export fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) {...@@ -32,7 +32,7 @@ export fn memcpy(noalias dest: ?&u8, noalias src: ?&const u8, n: usize) {
32}32}
3333
34export fn __stack_chk_fail() {34export fn __stack_chk_fail() {
35 if (builtin.is_release) {35 if (builtin.mode == builtin.Mode.ReleaseFast) {
36 @setGlobalLinkage(__stack_chk_fail, builtin.GlobalLinkage.Internal);36 @setGlobalLinkage(__stack_chk_fail, builtin.GlobalLinkage.Internal);
37 unreachable;37 unreachable;
38 }38 }
test/tests.zig+21-19
...@@ -9,6 +9,7 @@ const io = std.io;...@@ -9,6 +9,7 @@ const io = std.io;
9const mem = std.mem;9const mem = std.mem;
10const fmt = std.fmt;10const fmt = std.fmt;
11const List = std.list.List;11const List = std.list.List;
12const Mode = @import("builtin").Mode;
1213
13const compare_output = @import("compare_output.zig");14const compare_output = @import("compare_output.zig");
14const build_examples = @import("build_examples.zig");15const build_examples = @import("build_examples.zig");
...@@ -107,14 +108,13 @@ pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []cons...@@ -107,14 +108,13 @@ pub fn addPkgTests(b: &build.Builder, test_filter: ?[]const u8, root_src: []cons
107 name:[] const u8, desc: []const u8) -> &build.Step108 name:[] const u8, desc: []const u8) -> &build.Step
108{109{
109 const step = b.step(b.fmt("test-{}", name), desc);110 const step = b.step(b.fmt("test-{}", name), desc);
110 for ([]bool{false, true}) |release| {111 for ([]Mode{Mode.Debug, Mode.ReleaseFast}) |mode| {
111 for ([]bool{false, true}) |link_libc| {112 for ([]bool{false, true}) |link_libc| {
112 const these_tests = b.addTest(root_src);113 const these_tests = b.addTest(root_src);
113 these_tests.setNamePrefix(b.fmt("{}-{}-{} ", name,114 these_tests.setNamePrefix(b.fmt("{}-{}-{} ", name, @enumTagName(mode),
114 if (release) "release" else "debug",
115 if (link_libc) "c" else "bare"));115 if (link_libc) "c" else "bare"));
116 these_tests.setFilter(test_filter);116 these_tests.setFilter(test_filter);
117 these_tests.setRelease(release);117 these_tests.setBuildMode(mode);
118 if (link_libc) {118 if (link_libc) {
119 these_tests.linkSystemLibrary("c");119 these_tests.linkSystemLibrary("c");
120 }120 }
...@@ -372,9 +372,9 @@ pub const CompareOutputContext = struct {...@@ -372,9 +372,9 @@ pub const CompareOutputContext = struct {
372 self.step.dependOn(&run_and_cmp_output.step);372 self.step.dependOn(&run_and_cmp_output.step);
373 },373 },
374 Special.None => {374 Special.None => {
375 for ([]bool{false, true}) |release| {375 for ([]Mode{Mode.Debug, Mode.ReleaseFast}) |mode| {
376 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "{} {} ({})",376 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "{} {} ({})",
377 "compare-output", case.name, if (release) "release" else "debug");377 "compare-output", case.name, @enumTagName(mode));
378 test (self.test_filter) |filter| {378 test (self.test_filter) |filter| {
379 if (mem.indexOf(u8, annotated_case_name, filter) == null)379 if (mem.indexOf(u8, annotated_case_name, filter) == null)
380 continue;380 continue;
...@@ -382,7 +382,7 @@ pub const CompareOutputContext = struct {...@@ -382,7 +382,7 @@ pub const CompareOutputContext = struct {
382382
383 const exe = b.addExecutable("test", root_src);383 const exe = b.addExecutable("test", root_src);
384 exe.setOutputPath(exe_path);384 exe.setOutputPath(exe_path);
385 exe.setRelease(release);385 exe.setBuildMode(mode);
386 if (case.link_libc) {386 if (case.link_libc) {
387 exe.linkSystemLibrary("c");387 exe.linkSystemLibrary("c");
388 }388 }
...@@ -465,10 +465,10 @@ pub const CompileErrorContext = struct {...@@ -465,10 +465,10 @@ pub const CompileErrorContext = struct {
465 name: []const u8,465 name: []const u8,
466 test_index: usize,466 test_index: usize,
467 case: &const TestCase,467 case: &const TestCase,
468 release: bool,468 build_mode: Mode,
469469
470 pub fn create(context: &CompileErrorContext, name: []const u8,470 pub fn create(context: &CompileErrorContext, name: []const u8,
471 case: &const TestCase, release: bool) -> &CompileCmpOutputStep471 case: &const TestCase, build_mode: Mode) -> &CompileCmpOutputStep
472 {472 {
473 const allocator = context.b.allocator;473 const allocator = context.b.allocator;
474 const ptr = %%allocator.create(CompileCmpOutputStep);474 const ptr = %%allocator.create(CompileCmpOutputStep);
...@@ -478,7 +478,7 @@ pub const CompileErrorContext = struct {...@@ -478,7 +478,7 @@ pub const CompileErrorContext = struct {
478 .name = name,478 .name = name,
479 .test_index = context.test_index,479 .test_index = context.test_index,
480 .case = case,480 .case = case,
481 .release = release,481 .build_mode = build_mode,
482 };482 };
483 context.test_index += 1;483 context.test_index += 1;
484 return ptr;484 return ptr;
...@@ -501,8 +501,10 @@ pub const CompileErrorContext = struct {...@@ -501,8 +501,10 @@ pub const CompileErrorContext = struct {
501 %%zig_args.append("--output");501 %%zig_args.append("--output");
502 %%zig_args.append(b.pathFromRoot(obj_path));502 %%zig_args.append(b.pathFromRoot(obj_path));
503503
504 if (self.release) {504 switch (self.build_mode) {
505 %%zig_args.append("--release");505 Mode.Debug => {},
506 Mode.ReleaseSafe => %%zig_args.append("--release-safe"),
507 Mode.ReleaseFast => %%zig_args.append("--release-fast"),
506 }508 }
507509
508 %%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);510 %%io.stderr.printf("Test {}/{} {}...", self.test_index+1, self.context.test_index, self.name);
...@@ -620,15 +622,15 @@ pub const CompileErrorContext = struct {...@@ -620,15 +622,15 @@ pub const CompileErrorContext = struct {
620 pub fn addCase(self: &CompileErrorContext, case: &const TestCase) {622 pub fn addCase(self: &CompileErrorContext, case: &const TestCase) {
621 const b = self.b;623 const b = self.b;
622624
623 for ([]bool{false, true}) |release| {625 for ([]Mode{Mode.Debug, Mode.ReleaseFast}) |mode| {
624 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "compile-error {} ({})",626 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "compile-error {} ({})",
625 case.name, if (release) "release" else "debug");627 case.name, @enumTagName(mode));
626 test (self.test_filter) |filter| {628 test (self.test_filter) |filter| {
627 if (mem.indexOf(u8, annotated_case_name, filter) == null)629 if (mem.indexOf(u8, annotated_case_name, filter) == null)
628 continue;630 continue;
629 }631 }
630632
631 const compile_and_cmp_errors = CompileCmpOutputStep.create(self, annotated_case_name, case, release);633 const compile_and_cmp_errors = CompileCmpOutputStep.create(self, annotated_case_name, case, mode);
632 self.step.dependOn(&compile_and_cmp_errors.step);634 self.step.dependOn(&compile_and_cmp_errors.step);
633635
634 for (case.sources.toSliceConst()) |src_file| {636 for (case.sources.toSliceConst()) |src_file| {
...@@ -657,7 +659,7 @@ pub const BuildExamplesContext = struct {...@@ -657,7 +659,7 @@ pub const BuildExamplesContext = struct {
657 pub fn addBuildFile(self: &BuildExamplesContext, build_file: []const u8) {659 pub fn addBuildFile(self: &BuildExamplesContext, build_file: []const u8) {
658 const b = self.b;660 const b = self.b;
659661
660 const annotated_case_name = b.fmt("build {} (debug)", build_file);662 const annotated_case_name = b.fmt("build {} (Debug)", build_file);
661 test (self.test_filter) |filter| {663 test (self.test_filter) |filter| {
662 if (mem.indexOf(u8, annotated_case_name, filter) == null)664 if (mem.indexOf(u8, annotated_case_name, filter) == null)
663 return;665 return;
...@@ -686,16 +688,16 @@ pub const BuildExamplesContext = struct {...@@ -686,16 +688,16 @@ pub const BuildExamplesContext = struct {
686 pub fn addAllArgs(self: &BuildExamplesContext, root_src: []const u8, link_libc: bool) {688 pub fn addAllArgs(self: &BuildExamplesContext, root_src: []const u8, link_libc: bool) {
687 const b = self.b;689 const b = self.b;
688690
689 for ([]bool{false, true}) |release| {691 for ([]Mode{Mode.Debug, Mode.ReleaseFast}) |mode| {
690 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "build {} ({})",692 const annotated_case_name = %%fmt.allocPrint(self.b.allocator, "build {} ({})",
691 root_src, if (release) "release" else "debug");693 root_src, @enumTagName(mode));
692 test (self.test_filter) |filter| {694 test (self.test_filter) |filter| {
693 if (mem.indexOf(u8, annotated_case_name, filter) == null)695 if (mem.indexOf(u8, annotated_case_name, filter) == null)
694 continue;696 continue;
695 }697 }
696698
697 const exe = b.addExecutable("test", root_src);699 const exe = b.addExecutable("test", root_src);
698 exe.setRelease(release);700 exe.setBuildMode(mode);
699 if (link_libc) {701 if (link_libc) {
700 exe.linkSystemLibrary("c");702 exe.linkSystemLibrary("c");
701 }703 }