| author | |
| committer | |
| log | 4b2719b51d7ec9a38bad57ca02040231b6e8df26 |
| tree | 7f3af852912303da208a806274f95c335ba9cb8a |
| parent | a2abdb185f9e47b663edce1bdfa3fa525502f321 |
| parent | 8c77c5705f41e55a5f2d80db20270d0c644338ed |
| signature |
30 files changed, 701 insertions(+), 183 deletions(-)
CMakeLists.txt+11-5| ... | ... | @@ -600,7 +600,6 @@ set(ZIG_STD_FILES |
| 600 | 600 | "sort.zig" |
| 601 | 601 | "special/bootstrap.zig" |
| 602 | 602 | "special/bootstrap_lib.zig" |
| 603 | "special/build_file_template.zig" | |
| 604 | 603 | "special/build_runner.zig" |
| 605 | 604 | "special/builtin.zig" |
| 606 | 605 | "special/compiler_rt/aulldiv.zig" |
| ... | ... | @@ -618,22 +617,26 @@ set(ZIG_STD_FILES |
| 618 | 617 | "special/compiler_rt/fixunstfdi.zig" |
| 619 | 618 | "special/compiler_rt/fixunstfsi.zig" |
| 620 | 619 | "special/compiler_rt/fixunstfti.zig" |
| 620 | "special/compiler_rt/floattidf.zig" | |
| 621 | "special/compiler_rt/floattisf.zig" | |
| 622 | "special/compiler_rt/floattitf.zig" | |
| 621 | 623 | "special/compiler_rt/floatunditf.zig" |
| 622 | 624 | "special/compiler_rt/floatunsitf.zig" |
| 623 | 625 | "special/compiler_rt/floatuntidf.zig" |
| 624 | 626 | "special/compiler_rt/floatuntisf.zig" |
| 625 | 627 | "special/compiler_rt/floatuntitf.zig" |
| 626 | "special/compiler_rt/floattidf.zig" | |
| 627 | "special/compiler_rt/floattisf.zig" | |
| 628 | "special/compiler_rt/floattitf.zig" | |
| 629 | "special/compiler_rt/muloti4.zig" | |
| 630 | 628 | "special/compiler_rt/index.zig" |
| 629 | "special/compiler_rt/muloti4.zig" | |
| 631 | 630 | "special/compiler_rt/truncXfYf2.zig" |
| 632 | 631 | "special/compiler_rt/udivmod.zig" |
| 633 | 632 | "special/compiler_rt/udivmoddi4.zig" |
| 634 | 633 | "special/compiler_rt/udivmodti4.zig" |
| 635 | 634 | "special/compiler_rt/udivti3.zig" |
| 636 | 635 | "special/compiler_rt/umodti3.zig" |
| 636 | "special/init-exe/build.zig" | |
| 637 | "special/init-exe/src/main.zig" | |
| 638 | "special/init-lib/build.zig" | |
| 639 | "special/init-lib/src/main.zig" | |
| 637 | 640 | "special/panic.zig" |
| 638 | 641 | "special/test_runner.zig" |
| 639 | 642 | "unicode.zig" |
| ... | ... | @@ -796,6 +799,9 @@ if(MSVC) |
| 796 | 799 | set(EXE_CFLAGS "${EXE_CFLAGS}") |
| 797 | 800 | else() |
| 798 | 801 | set(EXE_CFLAGS "${EXE_CFLAGS} -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -D_GNU_SOURCE -fno-exceptions -fno-rtti -Werror=strict-prototypes -Werror=old-style-definition -Werror=type-limits -Wno-missing-braces") |
| 802 | if(MINGW) | |
| 803 | set(EXE_CFLAGS "${EXE_CFLAGS} -D__USE_MINGW_ANSI_STDIO -Wno-pedantic-ms-format") | |
| 804 | endif() | |
| 799 | 805 | endif() |
| 800 | 806 | |
| 801 | 807 | set(BLAKE_CFLAGS "-std=c99") |
build.zig+1| ... | ... | @@ -112,6 +112,7 @@ pub fn build(b: *Builder) !void { |
| 112 | 112 | |
| 113 | 113 | test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes)); |
| 114 | 114 | test_step.dependOn(tests.addBuildExampleTests(b, test_filter, modes)); |
| 115 | test_step.dependOn(tests.addCliTests(b, test_filter, modes)); | |
| 115 | 116 | test_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes)); |
| 116 | 117 | test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes)); |
| 117 | 118 | test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes)); |
doc/langref.html.in+1-1| ... | ... | @@ -5877,7 +5877,7 @@ fn add(a: i32, b: i32) i32 { |
| 5877 | 5877 | {#header_open|@OpaqueType#} |
| 5878 | 5878 | <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre> |
| 5879 | 5879 | <p> |
| 5880 | Creates a new type with an unknown size and alignment. | |
| 5880 | Creates a new type with an unknown (but non-zero) size and alignment. | |
| 5881 | 5881 | </p> |
| 5882 | 5882 | <p> |
| 5883 | 5883 | This is typically used for type safety when interacting with C code that does not expose struct details. |
example/hello_world/hello_windows.zig+2| ... | ... | @@ -1,5 +1,7 @@ |
| 1 | 1 | use @import("std").os.windows; |
| 2 | 2 | |
| 3 | extern "user32" stdcallcc fn MessageBoxA(hWnd: ?HANDLE, lpText: ?LPCTSTR, lpCaption: ?LPCTSTR, uType: UINT) c_int; | |
| 4 | ||
| 3 | 5 | export fn WinMain(hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: PWSTR, nCmdShow: INT) INT { |
| 4 | 6 | _ = MessageBoxA(null, c"hello", c"title", 0); |
| 5 | 7 | return 0; |
src/analyze.cpp+6-4| ... | ... | @@ -1470,7 +1470,8 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) { |
| 1470 | 1470 | case ZigTypeIdArray: |
| 1471 | 1471 | return type_allowed_in_extern(g, type_entry->data.array.child_type); |
| 1472 | 1472 | case ZigTypeIdFn: |
| 1473 | return type_entry->data.fn.fn_type_id.cc == CallingConventionC; | |
| 1473 | return type_entry->data.fn.fn_type_id.cc == CallingConventionC || | |
| 1474 | type_entry->data.fn.fn_type_id.cc == CallingConventionStdcall; | |
| 1474 | 1475 | case ZigTypeIdPointer: |
| 1475 | 1476 | if (type_size(g, type_entry) == 0) |
| 1476 | 1477 | return false; |
| ... | ... | @@ -3992,9 +3993,10 @@ uint32_t get_ptr_align(CodeGen *g, ZigType *type) { |
| 3992 | 3993 | return (ptr_type->data.pointer.explicit_alignment == 0) ? |
| 3993 | 3994 | get_abi_alignment(g, ptr_type->data.pointer.child_type) : ptr_type->data.pointer.explicit_alignment; |
| 3994 | 3995 | } else if (ptr_type->id == ZigTypeIdFn) { |
| 3995 | return (ptr_type->data.fn.fn_type_id.alignment == 0) ? | |
| 3996 | LLVMABIAlignmentOfType(g->target_data_ref, ptr_type->data.fn.raw_type_ref) : | |
| 3997 | ptr_type->data.fn.fn_type_id.alignment; | |
| 3996 | // I tried making this use LLVMABIAlignmentOfType but it trips this assertion in LLVM: | |
| 3997 | // "Cannot getTypeInfo() on a type that is unsized!" | |
| 3998 | // when getting the alignment of `?extern fn() void`. | |
| 3999 | return (ptr_type->data.fn.fn_type_id.alignment == 0) ? 1 : ptr_type->data.fn.fn_type_id.alignment; | |
| 3998 | 4000 | } else if (ptr_type->id == ZigTypeIdPromise) { |
| 3999 | 4001 | return get_coro_frame_align_bytes(g); |
| 4000 | 4002 | } else { |
src/codegen.cpp+16| ... | ... | @@ -1662,6 +1662,22 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z |
| 1662 | 1662 | if (actual_type->id == ZigTypeIdFloat) { |
| 1663 | 1663 | return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, ""); |
| 1664 | 1664 | } else if (actual_type->id == ZigTypeIdInt) { |
| 1665 | if (wanted_bits == 0) { | |
| 1666 | if (!want_runtime_safety) | |
| 1667 | return nullptr; | |
| 1668 | ||
| 1669 | LLVMValueRef zero = LLVMConstNull(actual_type->type_ref); | |
| 1670 | LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, expr_val, zero, ""); | |
| 1671 | LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenOk"); | |
| 1672 | LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "CastShortenFail"); | |
| 1673 | LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); | |
| 1674 | ||
| 1675 | LLVMPositionBuilderAtEnd(g->builder, fail_block); | |
| 1676 | gen_safety_crash(g, PanicMsgIdCastTruncatedData); | |
| 1677 | ||
| 1678 | LLVMPositionBuilderAtEnd(g->builder, ok_block); | |
| 1679 | return nullptr; | |
| 1680 | } | |
| 1665 | 1681 | LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, ""); |
| 1666 | 1682 | if (!want_runtime_safety) { |
| 1667 | 1683 | return trunc_val; |
src/compiler.cpp+101| ... | ... | @@ -5,6 +5,9 @@ |
| 5 | 5 | static Buf saved_compiler_id = BUF_INIT; |
| 6 | 6 | static Buf saved_app_data_dir = BUF_INIT; |
| 7 | 7 | static Buf saved_stage1_path = BUF_INIT; |
| 8 | static Buf saved_lib_dir = BUF_INIT; | |
| 9 | static Buf saved_special_dir = BUF_INIT; | |
| 10 | static Buf saved_std_dir = BUF_INIT; | |
| 8 | 11 | |
| 9 | 12 | Buf *get_stage1_cache_path() { |
| 10 | 13 | if (saved_stage1_path.list.length != 0) { |
| ... | ... | @@ -64,3 +67,101 @@ Error get_compiler_id(Buf **result) { |
| 64 | 67 | return ErrorNone; |
| 65 | 68 | } |
| 66 | 69 | |
| 70 | ||
| 71 | static bool test_zig_install_prefix(Buf *test_path, Buf *out_zig_lib_dir) { | |
| 72 | Buf lib_buf = BUF_INIT; | |
| 73 | buf_init_from_str(&lib_buf, "lib"); | |
| 74 | ||
| 75 | Buf zig_buf = BUF_INIT; | |
| 76 | buf_init_from_str(&zig_buf, "zig"); | |
| 77 | ||
| 78 | Buf std_buf = BUF_INIT; | |
| 79 | buf_init_from_str(&std_buf, "std"); | |
| 80 | ||
| 81 | Buf index_zig_buf = BUF_INIT; | |
| 82 | buf_init_from_str(&index_zig_buf, "index.zig"); | |
| 83 | ||
| 84 | Buf test_lib_dir = BUF_INIT; | |
| 85 | Buf test_zig_dir = BUF_INIT; | |
| 86 | Buf test_std_dir = BUF_INIT; | |
| 87 | Buf test_index_file = BUF_INIT; | |
| 88 | ||
| 89 | os_path_join(test_path, &lib_buf, &test_lib_dir); | |
| 90 | os_path_join(&test_lib_dir, &zig_buf, &test_zig_dir); | |
| 91 | os_path_join(&test_zig_dir, &std_buf, &test_std_dir); | |
| 92 | os_path_join(&test_std_dir, &index_zig_buf, &test_index_file); | |
| 93 | ||
| 94 | int err; | |
| 95 | bool exists; | |
| 96 | if ((err = os_file_exists(&test_index_file, &exists))) { | |
| 97 | exists = false; | |
| 98 | } | |
| 99 | if (exists) { | |
| 100 | buf_init_from_buf(out_zig_lib_dir, &test_zig_dir); | |
| 101 | return true; | |
| 102 | } | |
| 103 | return false; | |
| 104 | } | |
| 105 | ||
| 106 | static int find_zig_lib_dir(Buf *out_path) { | |
| 107 | int err; | |
| 108 | ||
| 109 | Buf self_exe_path = BUF_INIT; | |
| 110 | buf_resize(&self_exe_path, 0); | |
| 111 | if (!(err = os_self_exe_path(&self_exe_path))) { | |
| 112 | Buf *cur_path = &self_exe_path; | |
| 113 | ||
| 114 | for (;;) { | |
| 115 | Buf *test_dir = buf_alloc(); | |
| 116 | os_path_dirname(cur_path, test_dir); | |
| 117 | ||
| 118 | if (buf_eql_buf(test_dir, cur_path)) { | |
| 119 | break; | |
| 120 | } | |
| 121 | ||
| 122 | if (test_zig_install_prefix(test_dir, out_path)) { | |
| 123 | return 0; | |
| 124 | } | |
| 125 | ||
| 126 | cur_path = test_dir; | |
| 127 | } | |
| 128 | } | |
| 129 | ||
| 130 | return ErrorFileNotFound; | |
| 131 | } | |
| 132 | ||
| 133 | Buf *get_zig_lib_dir(void) { | |
| 134 | if (saved_lib_dir.list.length != 0) { | |
| 135 | return &saved_lib_dir; | |
| 136 | } | |
| 137 | buf_resize(&saved_lib_dir, 0); | |
| 138 | ||
| 139 | int err; | |
| 140 | if ((err = find_zig_lib_dir(&saved_lib_dir))) { | |
| 141 | fprintf(stderr, "Unable to find zig lib directory\n"); | |
| 142 | exit(EXIT_FAILURE); | |
| 143 | } | |
| 144 | return &saved_lib_dir; | |
| 145 | } | |
| 146 | ||
| 147 | Buf *get_zig_std_dir() { | |
| 148 | if (saved_std_dir.list.length != 0) { | |
| 149 | return &saved_std_dir; | |
| 150 | } | |
| 151 | buf_resize(&saved_std_dir, 0); | |
| 152 | ||
| 153 | os_path_join(get_zig_lib_dir(), buf_create_from_str("std"), &saved_std_dir); | |
| 154 | ||
| 155 | return &saved_std_dir; | |
| 156 | } | |
| 157 | ||
| 158 | Buf *get_zig_special_dir() { | |
| 159 | if (saved_special_dir.list.length != 0) { | |
| 160 | return &saved_special_dir; | |
| 161 | } | |
| 162 | buf_resize(&saved_special_dir, 0); | |
| 163 | ||
| 164 | os_path_join(get_zig_std_dir(), buf_sprintf("special"), &saved_special_dir); | |
| 165 | ||
| 166 | return &saved_special_dir; | |
| 167 | } |
src/compiler.hpp+4| ... | ... | @@ -14,4 +14,8 @@ |
| 14 | 14 | Buf *get_stage1_cache_path(); |
| 15 | 15 | Error get_compiler_id(Buf **result); |
| 16 | 16 | |
| 17 | Buf *get_zig_lib_dir(); | |
| 18 | Buf *get_zig_special_dir(); | |
| 19 | Buf *get_zig_std_dir(); | |
| 20 | ||
| 17 | 21 | #endif |
src/ir.cpp+64-23| ... | ... | @@ -10015,21 +10015,25 @@ static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_ |
| 10015 | 10015 | |
| 10016 | 10016 | if (value->id == IrInstructionIdLoadPtr) { |
| 10017 | 10017 | IrInstructionLoadPtr *load_ptr_inst = (IrInstructionLoadPtr *)value; |
| 10018 | return load_ptr_inst->ptr; | |
| 10019 | } else { | |
| 10020 | IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instr->scope, | |
| 10021 | source_instr->source_node, value, true, false); | |
| 10022 | new_instruction->value.type = wanted_type; | |
| 10018 | ConstCastOnly const_cast_result = types_match_const_cast_only(ira, wanted_type, | |
| 10019 | load_ptr_inst->ptr->value.type, source_instr->source_node, false); | |
| 10020 | if (const_cast_result.id == ConstCastResultIdInvalid) | |
| 10021 | return ira->codegen->invalid_instruction; | |
| 10022 | if (const_cast_result.id == ConstCastResultIdOk) | |
| 10023 | return load_ptr_inst->ptr; | |
| 10024 | } | |
| 10025 | IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instr->scope, | |
| 10026 | source_instr->source_node, value, true, false); | |
| 10027 | new_instruction->value.type = wanted_type; | |
| 10023 | 10028 | |
| 10024 | ZigType *child_type = wanted_type->data.pointer.child_type; | |
| 10025 | if (type_has_bits(child_type)) { | |
| 10026 | ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); | |
| 10027 | assert(fn_entry); | |
| 10028 | fn_entry->alloca_list.append(new_instruction); | |
| 10029 | } | |
| 10030 | ir_add_alloca(ira, new_instruction, child_type); | |
| 10031 | return new_instruction; | |
| 10029 | ZigType *child_type = wanted_type->data.pointer.child_type; | |
| 10030 | if (type_has_bits(child_type)) { | |
| 10031 | ZigFn *fn_entry = exec_fn_entry(ira->new_irb.exec); | |
| 10032 | assert(fn_entry); | |
| 10033 | fn_entry->alloca_list.append(new_instruction); | |
| 10032 | 10034 | } |
| 10035 | ir_add_alloca(ira, new_instruction, child_type); | |
| 10036 | return new_instruction; | |
| 10033 | 10037 | } |
| 10034 | 10038 | |
| 10035 | 10039 | static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *source_instr, IrInstruction *value, ZigType *wanted_type) { |
| ... | ... | @@ -11057,7 +11061,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 11057 | 11061 | } |
| 11058 | 11062 | } |
| 11059 | 11063 | |
| 11060 | // enum to &const union which has the enum as the tag type | |
| 11064 | // enum to *const union which has the enum as the tag type | |
| 11061 | 11065 | if (actual_type->id == ZigTypeIdEnum && wanted_type->id == ZigTypeIdPointer) { |
| 11062 | 11066 | ZigType *union_type = wanted_type->data.pointer.child_type; |
| 11063 | 11067 | if (union_type->data.unionation.decl_node->data.container_decl.auto_enum || |
| ... | ... | @@ -11187,6 +11191,13 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 11187 | 11191 | } |
| 11188 | 11192 | } |
| 11189 | 11193 | } |
| 11194 | // dereferencing a *u0 is comptime known to be 0 | |
| 11195 | if (child_type->id == ZigTypeIdInt && child_type->data.integral.bit_count == 0) { | |
| 11196 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope, | |
| 11197 | source_instruction->source_node, child_type); | |
| 11198 | init_const_unsigned_negative(&result->value, child_type, 0, false); | |
| 11199 | return result; | |
| 11200 | } | |
| 11190 | 11201 | // TODO if the instruction is a const ref instruction we can skip it |
| 11191 | 11202 | IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope, |
| 11192 | 11203 | source_instruction->source_node, ptr); |
| ... | ... | @@ -11521,7 +11532,13 @@ static bool optional_value_is_null(ConstExprValue *val) { |
| 11521 | 11532 | static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) { |
| 11522 | 11533 | Error err; |
| 11523 | 11534 | IrInstruction *op1 = bin_op_instruction->op1->other; |
| 11535 | if (type_is_invalid(op1->value.type)) | |
| 11536 | return ira->codegen->builtin_types.entry_invalid; | |
| 11537 | ||
| 11524 | 11538 | IrInstruction *op2 = bin_op_instruction->op2->other; |
| 11539 | if (type_is_invalid(op2->value.type)) | |
| 11540 | return ira->codegen->builtin_types.entry_invalid; | |
| 11541 | ||
| 11525 | 11542 | AstNode *source_node = bin_op_instruction->base.source_node; |
| 11526 | 11543 | |
| 11527 | 11544 | IrBinOp op_id = bin_op_instruction->op_id; |
| ... | ... | @@ -11564,6 +11581,9 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op |
| 11564 | 11581 | ir_link_new_instruction(is_non_null, &bin_op_instruction->base); |
| 11565 | 11582 | } |
| 11566 | 11583 | return ira->codegen->builtin_types.entry_bool; |
| 11584 | } else if (op1->value.type->id == ZigTypeIdNull || op2->value.type->id == ZigTypeIdNull) { | |
| 11585 | ir_add_error_node(ira, source_node, buf_sprintf("comparison against null can only be done with optionals")); | |
| 11586 | return ira->codegen->builtin_types.entry_invalid; | |
| 11567 | 11587 | } |
| 11568 | 11588 | |
| 11569 | 11589 | if (op1->value.type->id == ZigTypeIdErrorSet && op2->value.type->id == ZigTypeIdErrorSet) { |
| ... | ... | @@ -12063,6 +12083,12 @@ static ZigType *ir_analyze_bit_shift(IrAnalyze *ira, IrInstructionBinOp *bin_op_ |
| 12063 | 12083 | ir_add_error(ira, &bin_op_instruction->base, |
| 12064 | 12084 | buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known")); |
| 12065 | 12085 | return ira->codegen->builtin_types.entry_invalid; |
| 12086 | } else if (instr_is_comptime(casted_op2) && bigint_cmp_zero(&casted_op2->value.data.x_bigint) == CmpEQ) { | |
| 12087 | IrInstruction *result = ir_build_cast(&ira->new_irb, bin_op_instruction->base.scope, | |
| 12088 | bin_op_instruction->base.source_node, op1->value.type, op1, CastOpNoop); | |
| 12089 | result->value.type = op1->value.type; | |
| 12090 | ir_link_new_instruction(result, &bin_op_instruction->base); | |
| 12091 | return result->value.type; | |
| 12066 | 12092 | } |
| 12067 | 12093 | |
| 12068 | 12094 | ir_build_bin_op_from(&ira->new_irb, &bin_op_instruction->base, op_id, |
| ... | ... | @@ -18165,17 +18191,18 @@ static ZigType *ir_analyze_instruction_embed_file(IrAnalyze *ira, IrInstructionE |
| 18165 | 18191 | &source_dir_path, |
| 18166 | 18192 | rel_file_path, |
| 18167 | 18193 | }; |
| 18168 | Buf file_path = os_path_resolve(resolve_paths, 2); | |
| 18194 | Buf *file_path = buf_alloc(); | |
| 18195 | *file_path = os_path_resolve(resolve_paths, 2); | |
| 18169 | 18196 | |
| 18170 | 18197 | // load from file system into const expr |
| 18171 | 18198 | Buf *file_contents = buf_alloc(); |
| 18172 | 18199 | int err; |
| 18173 | if ((err = file_fetch(ira->codegen, &file_path, file_contents))) { | |
| 18200 | if ((err = file_fetch(ira->codegen, file_path, file_contents))) { | |
| 18174 | 18201 | if (err == ErrorFileNotFound) { |
| 18175 | ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(&file_path))); | |
| 18202 | ir_add_error(ira, instruction->name, buf_sprintf("unable to find '%s'", buf_ptr(file_path))); | |
| 18176 | 18203 | return ira->codegen->builtin_types.entry_invalid; |
| 18177 | 18204 | } else { |
| 18178 | ir_add_error(ira, instruction->name, buf_sprintf("unable to open '%s': %s", buf_ptr(&file_path), err_str(err))); | |
| 18205 | ir_add_error(ira, instruction->name, buf_sprintf("unable to open '%s': %s", buf_ptr(file_path), err_str(err))); | |
| 18179 | 18206 | return ira->codegen->builtin_types.entry_invalid; |
| 18180 | 18207 | } |
| 18181 | 18208 | } |
| ... | ... | @@ -18494,6 +18521,9 @@ static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionF |
| 18494 | 18521 | src_ptr_align = get_abi_alignment(ira->codegen, target->value.type); |
| 18495 | 18522 | } |
| 18496 | 18523 | |
| 18524 | if ((err = type_resolve(ira->codegen, dest_child_type, ResolveStatusSizeKnown))) | |
| 18525 | return ira->codegen->builtin_types.entry_invalid; | |
| 18526 | ||
| 18497 | 18527 | ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_child_type, |
| 18498 | 18528 | src_ptr_const, src_ptr_volatile, PtrLenUnknown, |
| 18499 | 18529 | src_ptr_align, 0, 0); |
| ... | ... | @@ -20174,11 +20204,19 @@ static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtr |
| 20174 | 20204 | instruction->base.source_node, nullptr, ptr); |
| 20175 | 20205 | casted_ptr->value.type = dest_type; |
| 20176 | 20206 | |
| 20177 | // Keep the bigger alignment, it can only help- | |
| 20178 | // unless the target is zero bits. | |
| 20179 | if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown))) | |
| 20207 | if (type_has_bits(dest_type) && !type_has_bits(src_type)) { | |
| 20208 | ErrorMsg *msg = ir_add_error(ira, &instruction->base, | |
| 20209 | buf_sprintf("'%s' and '%s' do not have the same in-memory representation", | |
| 20210 | buf_ptr(&src_type->name), buf_ptr(&dest_type->name))); | |
| 20211 | add_error_note(ira->codegen, msg, ptr->source_node, | |
| 20212 | buf_sprintf("'%s' has no in-memory bits", buf_ptr(&src_type->name))); | |
| 20213 | add_error_note(ira->codegen, msg, dest_type_value->source_node, | |
| 20214 | buf_sprintf("'%s' has in-memory bits", buf_ptr(&dest_type->name))); | |
| 20180 | 20215 | return ira->codegen->builtin_types.entry_invalid; |
| 20216 | } | |
| 20181 | 20217 | |
| 20218 | // Keep the bigger alignment, it can only help- | |
| 20219 | // unless the target is zero bits. | |
| 20182 | 20220 | IrInstruction *result; |
| 20183 | 20221 | if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) { |
| 20184 | 20222 | result = ir_align_cast(ira, casted_ptr, src_align_bytes, false); |
| ... | ... | @@ -20216,6 +20254,11 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 20216 | 20254 | bigint_write_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count, |
| 20217 | 20255 | codegen->is_big_endian); |
| 20218 | 20256 | return; |
| 20257 | case ZigTypeIdEnum: | |
| 20258 | bigint_write_twos_complement(&val->data.x_enum_tag, buf, | |
| 20259 | val->type->data.enumeration.tag_int_type->data.integral.bit_count, | |
| 20260 | codegen->is_big_endian); | |
| 20261 | return; | |
| 20219 | 20262 | case ZigTypeIdFloat: |
| 20220 | 20263 | float_write_ieee597(val, buf, codegen->is_big_endian); |
| 20221 | 20264 | return; |
| ... | ... | @@ -20247,8 +20290,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 20247 | 20290 | zig_panic("TODO buf_write_value_bytes error union"); |
| 20248 | 20291 | case ZigTypeIdErrorSet: |
| 20249 | 20292 | zig_panic("TODO buf_write_value_bytes pure error type"); |
| 20250 | case ZigTypeIdEnum: | |
| 20251 | zig_panic("TODO buf_write_value_bytes enum type"); | |
| 20252 | 20293 | case ZigTypeIdFn: |
| 20253 | 20294 | zig_panic("TODO buf_write_value_bytes fn type"); |
| 20254 | 20295 | case ZigTypeIdUnion: |
src/main.cpp+112-118| ... | ... | @@ -25,6 +25,8 @@ static int usage(const char *arg0) { |
| 25 | 25 | " build-obj [source] create object from source or assembly\n" |
| 26 | 26 | " builtin show the source code of that @import(\"builtin\")\n" |
| 27 | 27 | " id print the base64-encoded compiler id\n" |
| 28 | " init-exe initialize a `zig build` application in the cwd\n" | |
| 29 | " init-lib initialize a `zig build` library in the cwd\n" | |
| 28 | 30 | " run [source] create executable and run immediately\n" |
| 29 | 31 | " translate-c [source] convert c code to zig code\n" |
| 30 | 32 | " targets list available compilation targets\n" |
| ... | ... | @@ -34,7 +36,7 @@ static int usage(const char *arg0) { |
| 34 | 36 | "Compile Options:\n" |
| 35 | 37 | " --assembly [source] add assembly file to build\n" |
| 36 | 38 | " --cache-dir [path] override the cache directory\n" |
| 37 | " --cache [auto|off|on] build to the global cache and print output path to stdout\n" | |
| 39 | " --cache [auto|off|on] build in global cache, print out paths to stdout\n" | |
| 38 | 40 | " --color [auto|off|on] enable or disable colored error messages\n" |
| 39 | 41 | " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n" |
| 40 | 42 | " -ftime-report print timing diagnostics\n" |
| ... | ... | @@ -42,7 +44,7 @@ static int usage(const char *arg0) { |
| 42 | 44 | " --name [name] override output name\n" |
| 43 | 45 | " --output [file] override destination path\n" |
| 44 | 46 | " --output-h [file] override generated header file path\n" |
| 45 | " --pkg-begin [name] [path] make package available to import and push current pkg\n" | |
| 47 | " --pkg-begin [name] [path] make pkg available to import and push current pkg\n" | |
| 46 | 48 | " --pkg-end pop current pkg\n" |
| 47 | 49 | " --release-fast build with optimizations on and safety off\n" |
| 48 | 50 | " --release-safe build with optimizations on and safety on\n" |
| ... | ... | @@ -52,17 +54,16 @@ static int usage(const char *arg0) { |
| 52 | 54 | " --target-arch [name] specify target architecture\n" |
| 53 | 55 | " --target-environ [name] specify target environment\n" |
| 54 | 56 | " --target-os [name] specify target operating system\n" |
| 55 | " --verbose-tokenize turn on compiler debug output for tokenization\n" | |
| 56 | " --verbose-ast turn on compiler debug output for parsing into an AST\n" | |
| 57 | " --verbose-link turn on compiler debug output for linking\n" | |
| 58 | " --verbose-ir turn on compiler debug output for Zig IR\n" | |
| 59 | " --verbose-llvm-ir turn on compiler debug output for LLVM IR\n" | |
| 60 | " --verbose-cimport turn on compiler debug output for C imports\n" | |
| 57 | " --verbose-tokenize enable compiler debug output for tokenization\n" | |
| 58 | " --verbose-ast enable compiler debug output for AST parsing\n" | |
| 59 | " --verbose-link enable compiler debug output for linking\n" | |
| 60 | " --verbose-ir enable compiler debug output for Zig IR\n" | |
| 61 | " --verbose-llvm-ir enable compiler debug output for LLVM IR\n" | |
| 62 | " --verbose-cimport enable compiler debug output for C imports\n" | |
| 61 | 63 | " -dirafter [dir] same as -isystem but do it last\n" |
| 62 | 64 | " -isystem [dir] add additional search path for other .h files\n" |
| 63 | " -mllvm [arg] additional arguments to forward to LLVM's option processing\n" | |
| 65 | " -mllvm [arg] forward an arg to LLVM's option processing\n" | |
| 64 | 66 | "Link Options:\n" |
| 65 | " --ar-path [path] set the path to ar\n" | |
| 66 | 67 | " --dynamic-linker [path] set the path to ld.so\n" |
| 67 | 68 | " --each-lib-rpath add rpath for each used dynamic library\n" |
| 68 | 69 | " --libc-lib-dir [path] directory where libc crt1.o resides\n" |
| ... | ... | @@ -142,78 +143,6 @@ static int print_target_list(FILE *f) { |
| 142 | 143 | return EXIT_SUCCESS; |
| 143 | 144 | } |
| 144 | 145 | |
| 145 | static bool test_zig_install_prefix(Buf *test_path, Buf *out_zig_lib_dir) { | |
| 146 | Buf lib_buf = BUF_INIT; | |
| 147 | buf_init_from_str(&lib_buf, "lib"); | |
| 148 | ||
| 149 | Buf zig_buf = BUF_INIT; | |
| 150 | buf_init_from_str(&zig_buf, "zig"); | |
| 151 | ||
| 152 | Buf std_buf = BUF_INIT; | |
| 153 | buf_init_from_str(&std_buf, "std"); | |
| 154 | ||
| 155 | Buf index_zig_buf = BUF_INIT; | |
| 156 | buf_init_from_str(&index_zig_buf, "index.zig"); | |
| 157 | ||
| 158 | Buf test_lib_dir = BUF_INIT; | |
| 159 | Buf test_zig_dir = BUF_INIT; | |
| 160 | Buf test_std_dir = BUF_INIT; | |
| 161 | Buf test_index_file = BUF_INIT; | |
| 162 | ||
| 163 | os_path_join(test_path, &lib_buf, &test_lib_dir); | |
| 164 | os_path_join(&test_lib_dir, &zig_buf, &test_zig_dir); | |
| 165 | os_path_join(&test_zig_dir, &std_buf, &test_std_dir); | |
| 166 | os_path_join(&test_std_dir, &index_zig_buf, &test_index_file); | |
| 167 | ||
| 168 | int err; | |
| 169 | bool exists; | |
| 170 | if ((err = os_file_exists(&test_index_file, &exists))) { | |
| 171 | exists = false; | |
| 172 | } | |
| 173 | if (exists) { | |
| 174 | buf_init_from_buf(out_zig_lib_dir, &test_zig_dir); | |
| 175 | return true; | |
| 176 | } | |
| 177 | return false; | |
| 178 | } | |
| 179 | ||
| 180 | static int find_zig_lib_dir(Buf *out_path) { | |
| 181 | int err; | |
| 182 | ||
| 183 | Buf self_exe_path = BUF_INIT; | |
| 184 | buf_resize(&self_exe_path, 0); | |
| 185 | if (!(err = os_self_exe_path(&self_exe_path))) { | |
| 186 | Buf *cur_path = &self_exe_path; | |
| 187 | ||
| 188 | for (;;) { | |
| 189 | Buf *test_dir = buf_alloc(); | |
| 190 | os_path_dirname(cur_path, test_dir); | |
| 191 | ||
| 192 | if (buf_eql_buf(test_dir, cur_path)) { | |
| 193 | break; | |
| 194 | } | |
| 195 | ||
| 196 | if (test_zig_install_prefix(test_dir, out_path)) { | |
| 197 | return 0; | |
| 198 | } | |
| 199 | ||
| 200 | cur_path = test_dir; | |
| 201 | } | |
| 202 | } | |
| 203 | ||
| 204 | return ErrorFileNotFound; | |
| 205 | } | |
| 206 | ||
| 207 | static Buf *resolve_zig_lib_dir(void) { | |
| 208 | int err; | |
| 209 | Buf *result = buf_alloc(); | |
| 210 | if ((err = find_zig_lib_dir(result))) { | |
| 211 | fprintf(stderr, "Unable to find zig lib directory\n"); | |
| 212 | exit(EXIT_FAILURE); | |
| 213 | } | |
| 214 | return result; | |
| 215 | } | |
| 216 | ||
| 217 | 146 | enum Cmd { |
| 218 | 147 | CmdInvalid, |
| 219 | 148 | CmdBuild, |
| ... | ... | @@ -277,6 +206,9 @@ static bool get_cache_opt(CacheOpt opt, bool default_value) { |
| 277 | 206 | } |
| 278 | 207 | |
| 279 | 208 | int main(int argc, char **argv) { |
| 209 | char *arg0 = argv[0]; | |
| 210 | Error err; | |
| 211 | ||
| 280 | 212 | if (argc == 2 && strcmp(argv[1], "BUILD_INFO") == 0) { |
| 281 | 213 | printf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", |
| 282 | 214 | ZIG_CMAKE_BINARY_DIR, |
| ... | ... | @@ -290,8 +222,10 @@ int main(int argc, char **argv) { |
| 290 | 222 | return 0; |
| 291 | 223 | } |
| 292 | 224 | |
| 225 | // Must be before all os.hpp function calls. | |
| 226 | os_init(); | |
| 227 | ||
| 293 | 228 | if (argc == 2 && strcmp(argv[1], "id") == 0) { |
| 294 | Error err; | |
| 295 | 229 | Buf *compiler_id; |
| 296 | 230 | if ((err = get_compiler_id(&compiler_id))) { |
| 297 | 231 | fprintf(stderr, "Unable to determine compiler id: %s\n", err_str(err)); |
| ... | ... | @@ -301,9 +235,97 @@ int main(int argc, char **argv) { |
| 301 | 235 | return EXIT_SUCCESS; |
| 302 | 236 | } |
| 303 | 237 | |
| 304 | os_init(); | |
| 238 | enum InitKind { | |
| 239 | InitKindNone, | |
| 240 | InitKindExe, | |
| 241 | InitKindLib, | |
| 242 | }; | |
| 243 | InitKind init_kind = InitKindNone; | |
| 244 | if (argc >= 2) { | |
| 245 | const char *init_cmd = argv[1]; | |
| 246 | if (strcmp(init_cmd, "init-exe") == 0) { | |
| 247 | init_kind = InitKindExe; | |
| 248 | } else if (strcmp(init_cmd, "init-lib") == 0) { | |
| 249 | init_kind = InitKindLib; | |
| 250 | } | |
| 251 | if (init_kind != InitKindNone) { | |
| 252 | if (argc >= 3) { | |
| 253 | fprintf(stderr, "Unexpected extra argument: %s\n", argv[2]); | |
| 254 | return usage(arg0); | |
| 255 | } | |
| 256 | Buf *cmd_template_path = buf_alloc(); | |
| 257 | os_path_join(get_zig_special_dir(), buf_create_from_str(init_cmd), cmd_template_path); | |
| 258 | Buf *build_zig_path = buf_alloc(); | |
| 259 | os_path_join(cmd_template_path, buf_create_from_str("build.zig"), build_zig_path); | |
| 260 | Buf *src_dir_path = buf_alloc(); | |
| 261 | os_path_join(cmd_template_path, buf_create_from_str("src"), src_dir_path); | |
| 262 | Buf *main_zig_path = buf_alloc(); | |
| 263 | os_path_join(src_dir_path, buf_create_from_str("main.zig"), main_zig_path); | |
| 264 | ||
| 265 | Buf *cwd = buf_alloc(); | |
| 266 | if ((err = os_get_cwd(cwd))) { | |
| 267 | fprintf(stderr, "Unable to get cwd: %s\n", err_str(err)); | |
| 268 | return EXIT_FAILURE; | |
| 269 | } | |
| 270 | Buf *cwd_basename = buf_alloc(); | |
| 271 | os_path_split(cwd, nullptr, cwd_basename); | |
| 272 | ||
| 273 | Buf *build_zig_contents = buf_alloc(); | |
| 274 | if ((err = os_fetch_file_path(build_zig_path, build_zig_contents, false))) { | |
| 275 | fprintf(stderr, "Unable to read %s: %s\n", buf_ptr(build_zig_path), err_str(err)); | |
| 276 | return EXIT_FAILURE; | |
| 277 | } | |
| 278 | Buf *modified_build_zig_contents = buf_alloc(); | |
| 279 | for (size_t i = 0; i < buf_len(build_zig_contents); i += 1) { | |
| 280 | char c = buf_ptr(build_zig_contents)[i]; | |
| 281 | if (c == '$') { | |
| 282 | buf_append_buf(modified_build_zig_contents, cwd_basename); | |
| 283 | } else { | |
| 284 | buf_append_char(modified_build_zig_contents, c); | |
| 285 | } | |
| 286 | } | |
| 287 | ||
| 288 | Buf *main_zig_contents = buf_alloc(); | |
| 289 | if ((err = os_fetch_file_path(main_zig_path, main_zig_contents, false))) { | |
| 290 | fprintf(stderr, "Unable to read %s: %s\n", buf_ptr(main_zig_path), err_str(err)); | |
| 291 | return EXIT_FAILURE; | |
| 292 | } | |
| 293 | ||
| 294 | Buf *out_build_zig_path = buf_create_from_str("build.zig"); | |
| 295 | Buf *out_src_dir_path = buf_create_from_str("src"); | |
| 296 | Buf *out_main_zig_path = buf_alloc(); | |
| 297 | os_path_join(out_src_dir_path, buf_create_from_str("main.zig"), out_main_zig_path); | |
| 298 | ||
| 299 | bool already_exists; | |
| 300 | if ((err = os_file_exists(out_build_zig_path, &already_exists))) { | |
| 301 | fprintf(stderr, "Unable test existence of %s: %s\n", buf_ptr(out_build_zig_path), err_str(err)); | |
| 302 | return EXIT_FAILURE; | |
| 303 | } | |
| 304 | if (already_exists) { | |
| 305 | fprintf(stderr, "This file would be overwritten: %s\n", buf_ptr(out_build_zig_path)); | |
| 306 | return EXIT_FAILURE; | |
| 307 | } | |
| 308 | ||
| 309 | if ((err = os_make_dir(out_src_dir_path))) { | |
| 310 | fprintf(stderr, "Unable to make directory: %s: %s\n", buf_ptr(out_src_dir_path), err_str(err)); | |
| 311 | return EXIT_FAILURE; | |
| 312 | } | |
| 313 | os_write_file(out_build_zig_path, modified_build_zig_contents); | |
| 314 | os_write_file(out_main_zig_path, main_zig_contents); | |
| 315 | fprintf(stderr, "Created %s\n", buf_ptr(out_build_zig_path)); | |
| 316 | fprintf(stderr, "Created %s\n", buf_ptr(out_main_zig_path)); | |
| 317 | if (init_kind == InitKindExe) { | |
| 318 | fprintf(stderr, "\nNext, try `zig build --help` or `zig build run`\n"); | |
| 319 | } else if (init_kind == InitKindLib) { | |
| 320 | fprintf(stderr, "\nNext, try `zig build --help` or `zig build test`\n"); | |
| 321 | } else { | |
| 322 | zig_unreachable(); | |
| 323 | } | |
| 324 | ||
| 325 | return EXIT_SUCCESS; | |
| 326 | } | |
| 327 | } | |
| 305 | 328 | |
| 306 | char *arg0 = argv[0]; | |
| 307 | 329 | Cmd cmd = CmdInvalid; |
| 308 | 330 | EmitFileType emit_file_type = EmitFileTypeBinary; |
| 309 | 331 | const char *in_file = nullptr; |
| ... | ... | @@ -333,7 +355,6 @@ int main(int argc, char **argv) { |
| 333 | 355 | ZigList<const char *> link_libs = {0}; |
| 334 | 356 | ZigList<const char *> forbidden_link_libs = {0}; |
| 335 | 357 | ZigList<const char *> frameworks = {0}; |
| 336 | int err; | |
| 337 | 358 | const char *target_arch = nullptr; |
| 338 | 359 | const char *target_os = nullptr; |
| 339 | 360 | const char *target_environ = nullptr; |
| ... | ... | @@ -364,7 +385,6 @@ int main(int argc, char **argv) { |
| 364 | 385 | const char *zig_exe_path = arg0; |
| 365 | 386 | const char *build_file = "build.zig"; |
| 366 | 387 | bool asked_for_help = false; |
| 367 | bool asked_to_init = false; | |
| 368 | 388 | |
| 369 | 389 | init_all_targets(); |
| 370 | 390 | |
| ... | ... | @@ -376,9 +396,6 @@ int main(int argc, char **argv) { |
| 376 | 396 | if (strcmp(argv[i], "--help") == 0) { |
| 377 | 397 | asked_for_help = true; |
| 378 | 398 | args.append(argv[i]); |
| 379 | } else if (strcmp(argv[i], "--init") == 0) { | |
| 380 | asked_to_init = true; | |
| 381 | args.append(argv[i]); | |
| 382 | 399 | } else if (i + 1 < argc && strcmp(argv[i], "--build-file") == 0) { |
| 383 | 400 | build_file = argv[i + 1]; |
| 384 | 401 | i += 1; |
| ... | ... | @@ -390,18 +407,10 @@ int main(int argc, char **argv) { |
| 390 | 407 | } |
| 391 | 408 | } |
| 392 | 409 | |
| 393 | Buf *zig_lib_dir_buf = resolve_zig_lib_dir(); | |
| 394 | ||
| 395 | Buf *zig_std_dir = buf_alloc(); | |
| 396 | os_path_join(zig_lib_dir_buf, buf_create_from_str("std"), zig_std_dir); | |
| 397 | ||
| 398 | Buf *special_dir = buf_alloc(); | |
| 399 | os_path_join(zig_std_dir, buf_sprintf("special"), special_dir); | |
| 400 | ||
| 401 | 410 | Buf *build_runner_path = buf_alloc(); |
| 402 | os_path_join(special_dir, buf_create_from_str("build_runner.zig"), build_runner_path); | |
| 411 | os_path_join(get_zig_special_dir(), buf_create_from_str("build_runner.zig"), build_runner_path); | |
| 403 | 412 | |
| 404 | CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, zig_lib_dir_buf); | |
| 413 | CodeGen *g = codegen_create(build_runner_path, nullptr, OutTypeExe, BuildModeDebug, get_zig_lib_dir()); | |
| 405 | 414 | g->enable_time_report = timing_info; |
| 406 | 415 | buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name); |
| 407 | 416 | codegen_set_out_name(g, buf_create_from_str("build")); |
| ... | ... | @@ -437,7 +446,6 @@ int main(int argc, char **argv) { |
| 437 | 446 | "\n" |
| 438 | 447 | "General Options:\n" |
| 439 | 448 | " --help Print this help and exit\n" |
| 440 | " --init Generate a build.zig template\n" | |
| 441 | 449 | " --build-file [file] Override path to build.zig\n" |
| 442 | 450 | " --cache-dir [path] Override path to cache directory\n" |
| 443 | 451 | " --verbose Print commands before executing them\n" |
| ... | ... | @@ -463,22 +471,11 @@ int main(int argc, char **argv) { |
| 463 | 471 | "\n" |
| 464 | 472 | , zig_exe_path); |
| 465 | 473 | return EXIT_SUCCESS; |
| 466 | } else if (asked_to_init) { | |
| 467 | Buf *build_template_path = buf_alloc(); | |
| 468 | os_path_join(special_dir, buf_create_from_str("build_file_template.zig"), build_template_path); | |
| 469 | ||
| 470 | if ((err = os_copy_file(build_template_path, &build_file_abs))) { | |
| 471 | fprintf(stderr, "Unable to write build.zig template: %s\n", err_str(err)); | |
| 472 | return EXIT_FAILURE; | |
| 473 | } else { | |
| 474 | fprintf(stderr, "Wrote build.zig template\n"); | |
| 475 | return EXIT_SUCCESS; | |
| 476 | } | |
| 477 | 474 | } |
| 478 | 475 | |
| 479 | 476 | fprintf(stderr, |
| 480 | 477 | "No 'build.zig' file found.\n" |
| 481 | "Initialize a 'build.zig' template file with `zig build --init`,\n" | |
| 478 | "Initialize a 'build.zig' template file with `zig init-lib` or `zig init-exe`,\n" | |
| 482 | 479 | "or build an executable directly with `zig build-exe $FILENAME.zig`.\n" |
| 483 | 480 | "See: `zig build --help` or `zig help` for more options.\n" |
| 484 | 481 | ); |
| ... | ... | @@ -773,8 +770,7 @@ int main(int argc, char **argv) { |
| 773 | 770 | |
| 774 | 771 | switch (cmd) { |
| 775 | 772 | case CmdBuiltin: { |
| 776 | Buf *zig_lib_dir_buf = resolve_zig_lib_dir(); | |
| 777 | CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, zig_lib_dir_buf); | |
| 773 | CodeGen *g = codegen_create(nullptr, target, out_type, build_mode, get_zig_lib_dir()); | |
| 778 | 774 | Buf *builtin_source = codegen_generate_builtin_source(g); |
| 779 | 775 | if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) { |
| 780 | 776 | fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout))); |
| ... | ... | @@ -832,9 +828,7 @@ int main(int argc, char **argv) { |
| 832 | 828 | if (cmd == CmdRun && buf_out_name == nullptr) { |
| 833 | 829 | buf_out_name = buf_create_from_str("run"); |
| 834 | 830 | } |
| 835 | Buf *zig_lib_dir_buf = resolve_zig_lib_dir(); | |
| 836 | ||
| 837 | CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, zig_lib_dir_buf); | |
| 831 | CodeGen *g = codegen_create(zig_root_source_file, target, out_type, build_mode, get_zig_lib_dir()); | |
| 838 | 832 | g->enable_time_report = timing_info; |
| 839 | 833 | buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name); |
| 840 | 834 | codegen_set_out_name(g, buf_out_name); |
src/os.cpp+17-9| ... | ... | @@ -23,6 +23,14 @@ |
| 23 | 23 | #define WIN32_LEAN_AND_MEAN |
| 24 | 24 | #endif |
| 25 | 25 | |
| 26 | #if !defined(_WIN32_WINNT) | |
| 27 | #define _WIN32_WINNT 0x600 | |
| 28 | #endif | |
| 29 | ||
| 30 | #if !defined(NTDDI_VERSION) | |
| 31 | #define NTDDI_VERSION 0x06000000 | |
| 32 | #endif | |
| 33 | ||
| 26 | 34 | #include <windows.h> |
| 27 | 35 | #include <shlobj.h> |
| 28 | 36 | #include <io.h> |
| ... | ... | @@ -1091,14 +1099,14 @@ Error os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) { |
| 1091 | 1099 | return result; |
| 1092 | 1100 | } |
| 1093 | 1101 | |
| 1094 | int os_get_cwd(Buf *out_cwd) { | |
| 1102 | Error os_get_cwd(Buf *out_cwd) { | |
| 1095 | 1103 | #if defined(ZIG_OS_WINDOWS) |
| 1096 | 1104 | char buf[4096]; |
| 1097 | 1105 | if (GetCurrentDirectory(4096, buf) == 0) { |
| 1098 | 1106 | zig_panic("GetCurrentDirectory failed"); |
| 1099 | 1107 | } |
| 1100 | 1108 | buf_init_from_str(out_cwd, buf); |
| 1101 | return 0; | |
| 1109 | return ErrorNone; | |
| 1102 | 1110 | #elif defined(ZIG_OS_POSIX) |
| 1103 | 1111 | char buf[PATH_MAX]; |
| 1104 | 1112 | char *res = getcwd(buf, PATH_MAX); |
| ... | ... | @@ -1106,7 +1114,7 @@ int os_get_cwd(Buf *out_cwd) { |
| 1106 | 1114 | zig_panic("unable to get cwd: %s", strerror(errno)); |
| 1107 | 1115 | } |
| 1108 | 1116 | buf_init_from_str(out_cwd, res); |
| 1109 | return 0; | |
| 1117 | return ErrorNone; | |
| 1110 | 1118 | #else |
| 1111 | 1119 | #error "missing os_get_cwd implementation" |
| 1112 | 1120 | #endif |
| ... | ... | @@ -1634,16 +1642,16 @@ static Optional<uint32_t> Utf16LeIterator_nextCodepoint(Utf16LeIterator *it) { |
| 1634 | 1642 | if (it->bytes[it->i] == 0 && it->bytes[it->i + 1] == 0) |
| 1635 | 1643 | return {}; |
| 1636 | 1644 | uint32_t c0 = ((uint32_t)it->bytes[it->i]) | (((uint32_t)it->bytes[it->i + 1]) << 8); |
| 1637 | if (c0 & ~((uint32_t)0x03ff) == 0xd800) { | |
| 1645 | if ((c0 & ~((uint32_t)0x03ff)) == 0xd800) { | |
| 1638 | 1646 | // surrogate pair |
| 1639 | 1647 | it->i += 2; |
| 1640 | 1648 | assert(it->bytes[it->i] != 0 || it->bytes[it->i + 1] != 0); |
| 1641 | 1649 | uint32_t c1 = ((uint32_t)it->bytes[it->i]) | (((uint32_t)it->bytes[it->i + 1]) << 8); |
| 1642 | assert(c1 & ~((uint32_t)0x03ff) == 0xdc00); | |
| 1650 | assert((c1 & ~((uint32_t)0x03ff)) == 0xdc00); | |
| 1643 | 1651 | it->i += 2; |
| 1644 | 1652 | return Optional<uint32_t>::some(0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff))); |
| 1645 | 1653 | } else { |
| 1646 | assert(c0 & ~((uint32_t)0x03ff) != 0xdc00); | |
| 1654 | assert((c0 & ~((uint32_t)0x03ff)) != 0xdc00); | |
| 1647 | 1655 | it->i += 2; |
| 1648 | 1656 | return Optional<uint32_t>::some(c0); |
| 1649 | 1657 | } |
| ... | ... | @@ -1714,7 +1722,6 @@ static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le) { |
| 1714 | 1722 | // Ported from std.os.getAppDataDir |
| 1715 | 1723 | Error os_get_app_data_dir(Buf *out_path, const char *appname) { |
| 1716 | 1724 | #if defined(ZIG_OS_WINDOWS) |
| 1717 | Error err; | |
| 1718 | 1725 | WCHAR *dir_path_ptr; |
| 1719 | 1726 | switch (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &dir_path_ptr)) { |
| 1720 | 1727 | case S_OK: |
| ... | ... | @@ -1928,7 +1935,7 @@ Error os_file_mtime(OsFile file, OsTimeStamp *mtime) { |
| 1928 | 1935 | FILETIME last_write_time; |
| 1929 | 1936 | if (!GetFileTime(file, nullptr, nullptr, &last_write_time)) |
| 1930 | 1937 | return ErrorUnexpected; |
| 1931 | mtime->sec = last_write_time.dwLowDateTime | (last_write_time.dwHighDateTime << 32); | |
| 1938 | mtime->sec = (((ULONGLONG) last_write_time.dwHighDateTime) << 32) + last_write_time.dwLowDateTime; | |
| 1932 | 1939 | mtime->nsec = 0; |
| 1933 | 1940 | return ErrorNone; |
| 1934 | 1941 | #elif defined(ZIG_OS_LINUX) |
| ... | ... | @@ -2011,7 +2018,8 @@ Error os_file_overwrite(OsFile file, Buf *contents) { |
| 2011 | 2018 | return ErrorFileSystem; |
| 2012 | 2019 | if (!SetEndOfFile(file)) |
| 2013 | 2020 | return ErrorFileSystem; |
| 2014 | if (!WriteFile(file, buf_ptr(contents), buf_len(contents), nullptr, nullptr)) | |
| 2021 | DWORD bytes_written; | |
| 2022 | if (!WriteFile(file, buf_ptr(contents), buf_len(contents), &bytes_written, nullptr)) | |
| 2015 | 2023 | return ErrorFileSystem; |
| 2016 | 2024 | return ErrorNone; |
| 2017 | 2025 | #else |
src/os.hpp+1-1| ... | ... | @@ -114,7 +114,7 @@ int os_copy_file(Buf *src_path, Buf *dest_path); |
| 114 | 114 | Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents, bool skip_shebang); |
| 115 | 115 | Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang); |
| 116 | 116 | |
| 117 | int os_get_cwd(Buf *out_cwd); | |
| 117 | Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd); | |
| 118 | 118 | |
| 119 | 119 | bool os_stderr_tty(void); |
| 120 | 120 | void os_stderr_set_color(TermColor color); |
src/windows_com.hpp+3| ... | ... | @@ -28,6 +28,9 @@ |
| 28 | 28 | #include <io.h> |
| 29 | 29 | #include <shellapi.h> |
| 30 | 30 | |
| 31 | // Standard headers | |
| 32 | #include <stdio.h> | |
| 33 | ||
| 31 | 34 | // COM support header files |
| 32 | 35 | #include <comdef.h> |
| 33 | 36 |
std/os/windows/advapi32.zig-12| ... | ... | @@ -11,18 +11,6 @@ pub const HKEY__ = extern struct { |
| 11 | 11 | }; |
| 12 | 12 | pub const LSTATUS = LONG; |
| 13 | 13 | |
| 14 | pub extern "advapi32" stdcallcc fn CryptAcquireContextA( | |
| 15 | phProv: *HCRYPTPROV, | |
| 16 | pszContainer: ?LPCSTR, | |
| 17 | pszProvider: ?LPCSTR, | |
| 18 | dwProvType: DWORD, | |
| 19 | dwFlags: DWORD, | |
| 20 | ) BOOL; | |
| 21 | ||
| 22 | pub extern "advapi32" stdcallcc fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) BOOL; | |
| 23 | ||
| 24 | pub extern "advapi32" stdcallcc fn CryptGenRandom(hProv: HCRYPTPROV, dwLen: DWORD, pbBuffer: [*]BYTE) BOOL; | |
| 25 | ||
| 26 | 14 | pub extern "advapi32" stdcallcc fn RegOpenKeyExW( |
| 27 | 15 | hKey: HKEY, |
| 28 | 16 | lpSubKey: LPCWSTR, |
std/special/build_file_template.zig deleted-10| ... | ... | @@ -1,10 +0,0 @@ |
| 1 | const Builder = @import("std").build.Builder; | |
| 2 | ||
| 3 | pub fn build(b: *Builder) void { | |
| 4 | const mode = b.standardReleaseOptions(); | |
| 5 | const exe = b.addExecutable("YOUR_NAME_HERE", "src/main.zig"); | |
| 6 | exe.setBuildMode(mode); | |
| 7 | ||
| 8 | b.default_step.dependOn(&exe.step); | |
| 9 | b.installArtifact(exe); | |
| 10 | } |
std/special/init-exe/build.zig created+15| ... | ... | @@ -0,0 +1,15 @@ |
| 1 | const Builder = @import("std").build.Builder; | |
| 2 | ||
| 3 | pub fn build(b: *Builder) void { | |
| 4 | const mode = b.standardReleaseOptions(); | |
| 5 | const exe = b.addExecutable("$", "src/main.zig"); | |
| 6 | exe.setBuildMode(mode); | |
| 7 | ||
| 8 | const run_step = b.step("run", "Run the app"); | |
| 9 | const run_cmd = b.addCommand(".", b.env_map, [][]const u8{exe.getOutputPath()}); | |
| 10 | run_step.dependOn(&run_cmd.step); | |
| 11 | run_cmd.step.dependOn(&exe.step); | |
| 12 | ||
| 13 | b.default_step.dependOn(&exe.step); | |
| 14 | b.installArtifact(exe); | |
| 15 | } |
std/special/init-exe/src/main.zig created+5| ... | ... | @@ -0,0 +1,5 @@ |
| 1 | const std = @import("std"); | |
| 2 | ||
| 3 | pub fn main() error!void { | |
| 4 | std.debug.warn("All your base are belong to us.\n"); | |
| 5 | } |
std/special/init-lib/build.zig created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | const Builder = @import("std").build.Builder; | |
| 2 | ||
| 3 | pub fn build(b: *Builder) void { | |
| 4 | const mode = b.standardReleaseOptions(); | |
| 5 | const lib = b.addStaticLibrary("$", "src/main.zig"); | |
| 6 | lib.setBuildMode(mode); | |
| 7 | ||
| 8 | var main_tests = b.addTest("src/main.zig"); | |
| 9 | main_tests.setBuildMode(mode); | |
| 10 | ||
| 11 | const test_step = b.step("test", "Run library tests"); | |
| 12 | test_step.dependOn(&main_tests.step); | |
| 13 | ||
| 14 | b.default_step.dependOn(&lib.step); | |
| 15 | b.installArtifact(lib); | |
| 16 | } |
std/special/init-lib/src/main.zig created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assertOrPanic = std.debug.assertOrPanic; | |
| 3 | ||
| 4 | export fn add(a: i32, b: i32) i32 { | |
| 5 | return a + b; | |
| 6 | } | |
| 7 | ||
| 8 | test "basic add functionality" { | |
| 9 | assertOrPanic(add(3, 7) == 10); | |
| 10 | } |
test/behavior.zig+1| ... | ... | @@ -71,4 +71,5 @@ comptime { |
| 71 | 71 | _ = @import("cases/void.zig"); |
| 72 | 72 | _ = @import("cases/while.zig"); |
| 73 | 73 | _ = @import("cases/widening.zig"); |
| 74 | _ = @import("cases/bit_shifting.zig"); | |
| 74 | 75 | } |
test/cases/align.zig+9| ... | ... | @@ -219,3 +219,12 @@ test "alignment of structs" { |
| 219 | 219 | b: *i32, |
| 220 | 220 | }) == @alignOf(usize)); |
| 221 | 221 | } |
| 222 | ||
| 223 | test "alignment of extern() void" { | |
| 224 | var runtime_nothing = nothing; | |
| 225 | const casted1 = @ptrCast(*const u8, runtime_nothing); | |
| 226 | const casted2 = @ptrCast(extern fn () void, casted1); | |
| 227 | casted2(); | |
| 228 | } | |
| 229 | ||
| 230 | extern fn nothing() void {} |
test/cases/bit_shifting.zig created+88| ... | ... | @@ -0,0 +1,88 @@ |
| 1 | const std = @import("std"); | |
| 2 | const assert = std.debug.assert; | |
| 3 | ||
| 4 | fn ShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime V: type) type { | |
| 5 | assert(Key == @IntType(false, Key.bit_count)); | |
| 6 | assert(Key.bit_count >= mask_bit_count); | |
| 7 | const ShardKey = @IntType(false, mask_bit_count); | |
| 8 | const shift_amount = Key.bit_count - ShardKey.bit_count; | |
| 9 | return struct { | |
| 10 | const Self = @This(); | |
| 11 | shards: [1 << ShardKey.bit_count]?*Node, | |
| 12 | ||
| 13 | pub fn create() Self { | |
| 14 | return Self{ .shards = []?*Node{null} ** (1 << ShardKey.bit_count) }; | |
| 15 | } | |
| 16 | ||
| 17 | fn getShardKey(key: Key) ShardKey { | |
| 18 | // https://github.com/ziglang/zig/issues/1544 | |
| 19 | // this special case is needed because you can't u32 >> 32. | |
| 20 | if (ShardKey == u0) return 0; | |
| 21 | ||
| 22 | // this can be u1 >> u0 | |
| 23 | const shard_key = key >> shift_amount; | |
| 24 | ||
| 25 | // TODO: https://github.com/ziglang/zig/issues/1544 | |
| 26 | // This cast could be implicit if we teach the compiler that | |
| 27 | // u32 >> 30 -> u2 | |
| 28 | return @intCast(ShardKey, shard_key); | |
| 29 | } | |
| 30 | ||
| 31 | pub fn put(self: *Self, node: *Node) void { | |
| 32 | const shard_key = Self.getShardKey(node.key); | |
| 33 | node.next = self.shards[shard_key]; | |
| 34 | self.shards[shard_key] = node; | |
| 35 | } | |
| 36 | ||
| 37 | pub fn get(self: *Self, key: Key) ?*Node { | |
| 38 | const shard_key = Self.getShardKey(key); | |
| 39 | var maybe_node = self.shards[shard_key]; | |
| 40 | while (maybe_node) |node| : (maybe_node = node.next) { | |
| 41 | if (node.key == key) return node; | |
| 42 | } | |
| 43 | return null; | |
| 44 | } | |
| 45 | ||
| 46 | pub const Node = struct { | |
| 47 | key: Key, | |
| 48 | value: V, | |
| 49 | next: ?*Node, | |
| 50 | ||
| 51 | pub fn init(self: *Node, key: Key, value: V) void { | |
| 52 | self.key = key; | |
| 53 | self.value = value; | |
| 54 | self.next = null; | |
| 55 | } | |
| 56 | }; | |
| 57 | }; | |
| 58 | } | |
| 59 | ||
| 60 | test "sharded table" { | |
| 61 | // realistic 16-way sharding | |
| 62 | testShardedTable(u32, 4, 8); | |
| 63 | ||
| 64 | testShardedTable(u5, 0, 32); // ShardKey == u0 | |
| 65 | testShardedTable(u5, 2, 32); | |
| 66 | testShardedTable(u5, 5, 32); | |
| 67 | ||
| 68 | testShardedTable(u1, 0, 2); | |
| 69 | testShardedTable(u1, 1, 2); // this does u1 >> u0 | |
| 70 | ||
| 71 | testShardedTable(u0, 0, 1); | |
| 72 | } | |
| 73 | fn testShardedTable(comptime Key: type, comptime mask_bit_count: comptime_int, comptime node_count: comptime_int) void { | |
| 74 | const Table = ShardedTable(Key, mask_bit_count, void); | |
| 75 | ||
| 76 | var table = Table.create(); | |
| 77 | var node_buffer: [node_count]Table.Node = undefined; | |
| 78 | for (node_buffer) |*node, i| { | |
| 79 | const key = @intCast(Key, i); | |
| 80 | assert(table.get(key) == null); | |
| 81 | node.init(key, {}); | |
| 82 | table.put(node); | |
| 83 | } | |
| 84 | ||
| 85 | for (node_buffer) |*node, i| { | |
| 86 | assert(table.get(@intCast(Key, i)) == node); | |
| 87 | } | |
| 88 | } |
test/cases/bitcast.zig+17| ... | ... | @@ -16,3 +16,20 @@ fn conv(x: i32) u32 { |
| 16 | 16 | fn conv2(x: u32) i32 { |
| 17 | 17 | return @bitCast(i32, x); |
| 18 | 18 | } |
| 19 | ||
| 20 | test "@bitCast extern enum to its integer type" { | |
| 21 | const SOCK = extern enum { | |
| 22 | A, | |
| 23 | B, | |
| 24 | ||
| 25 | fn testBitCastExternEnum() void { | |
| 26 | var SOCK_DGRAM = @This().B; | |
| 27 | var sock_dgram = @bitCast(c_int, SOCK_DGRAM); | |
| 28 | assert(sock_dgram == 1); | |
| 29 | } | |
| 30 | }; | |
| 31 | ||
| 32 | SOCK.testBitCastExternEnum(); | |
| 33 | comptime SOCK.testBitCastExternEnum(); | |
| 34 | } | |
| 35 |
test/cases/eval.zig+28| ... | ... | @@ -682,3 +682,31 @@ test "refer to the type of a generic function" { |
| 682 | 682 | } |
| 683 | 683 | |
| 684 | 684 | fn doNothingWithType(comptime T: type) void {} |
| 685 | ||
| 686 | test "zero extend from u0 to u1" { | |
| 687 | var zero_u0: u0 = 0; | |
| 688 | var zero_u1: u1 = zero_u0; | |
| 689 | assert(zero_u1 == 0); | |
| 690 | } | |
| 691 | ||
| 692 | test "bit shift a u1" { | |
| 693 | var x: u1 = 1; | |
| 694 | var y = x << 0; | |
| 695 | assert(y == 1); | |
| 696 | } | |
| 697 | ||
| 698 | test "@intCast to a u0" { | |
| 699 | var x: u8 = 0; | |
| 700 | var y: u0 = @intCast(u0, x); | |
| 701 | assert(y == 0); | |
| 702 | } | |
| 703 | ||
| 704 | test "@bytesToslice on a packed struct" { | |
| 705 | const F = packed struct { | |
| 706 | a: u8, | |
| 707 | }; | |
| 708 | ||
| 709 | var b = [1]u8{9}; | |
| 710 | var f = @bytesToSlice(F, b); | |
| 711 | assert(f[0].a == 9); | |
| 712 | } |
test/cases/fn.zig+14| ... | ... | @@ -191,3 +191,17 @@ test "return inner function which references comptime variable of outer function |
| 191 | 191 | var func = outer(10); |
| 192 | 192 | assert(func(3) == 7); |
| 193 | 193 | } |
| 194 | ||
| 195 | test "extern struct with stdcallcc fn pointer" { | |
| 196 | const S = extern struct { | |
| 197 | ptr: stdcallcc fn () i32, | |
| 198 | ||
| 199 | stdcallcc fn foo() i32 { | |
| 200 | return 1234; | |
| 201 | } | |
| 202 | }; | |
| 203 | ||
| 204 | var s: S = undefined; | |
| 205 | s.ptr = S.foo; | |
| 206 | assert(s.ptr() == 1234); | |
| 207 | } |
test/cases/struct.zig+16| ... | ... | @@ -437,3 +437,19 @@ test "call method with mutable reference to struct with no fields" { |
| 437 | 437 | assert(S.do(&s)); |
| 438 | 438 | assert(s.do()); |
| 439 | 439 | } |
| 440 | ||
| 441 | test "implicit cast packed struct field to const ptr" { | |
| 442 | const LevelUpMove = packed struct { | |
| 443 | move_id: u9, | |
| 444 | level: u7, | |
| 445 | ||
| 446 | fn toInt(value: *const u7) u7 { | |
| 447 | return value.*; | |
| 448 | } | |
| 449 | }; | |
| 450 | ||
| 451 | var lup: LevelUpMove = undefined; | |
| 452 | lup.level = 12; | |
| 453 | const res = LevelUpMove.toInt(lup.level); | |
| 454 | assert(res == 12); | |
| 455 | } |
test/cli.zig created+92| ... | ... | @@ -0,0 +1,92 @@ |
| 1 | const std = @import("std"); | |
| 2 | const os = std.os; | |
| 3 | const assertOrPanic = std.debug.assertOrPanic; | |
| 4 | ||
| 5 | var a: *std.mem.Allocator = undefined; | |
| 6 | ||
| 7 | pub fn main() !void { | |
| 8 | var direct_allocator = std.heap.DirectAllocator.init(); | |
| 9 | defer direct_allocator.deinit(); | |
| 10 | ||
| 11 | var arena = std.heap.ArenaAllocator.init(&direct_allocator.allocator); | |
| 12 | defer arena.deinit(); | |
| 13 | ||
| 14 | var arg_it = os.args(); | |
| 15 | ||
| 16 | // skip my own exe name | |
| 17 | _ = arg_it.skip(); | |
| 18 | ||
| 19 | a = &arena.allocator; | |
| 20 | ||
| 21 | const zig_exe_rel = try (arg_it.next(a) orelse { | |
| 22 | std.debug.warn("Expected first argument to be path to zig compiler\n"); | |
| 23 | return error.InvalidArgs; | |
| 24 | }); | |
| 25 | const cache_root = try (arg_it.next(a) orelse { | |
| 26 | std.debug.warn("Expected second argument to be cache root directory path\n"); | |
| 27 | return error.InvalidArgs; | |
| 28 | }); | |
| 29 | const zig_exe = try os.path.resolve(a, zig_exe_rel); | |
| 30 | ||
| 31 | try testZigInitLib(zig_exe, cache_root); | |
| 32 | try testZigInitExe(zig_exe, cache_root); | |
| 33 | } | |
| 34 | ||
| 35 | fn unwrapArg(arg: UnwrapArgError![]u8) UnwrapArgError![]u8 { | |
| 36 | return arg catch |err| { | |
| 37 | warn("Unable to parse command line: {}\n", err); | |
| 38 | return err; | |
| 39 | }; | |
| 40 | } | |
| 41 | ||
| 42 | fn printCmd(cwd: []const u8, argv: []const []const u8) void { | |
| 43 | std.debug.warn("cd {} && ", cwd); | |
| 44 | for (argv) |arg| { | |
| 45 | std.debug.warn("{} ", arg); | |
| 46 | } | |
| 47 | std.debug.warn("\n"); | |
| 48 | } | |
| 49 | ||
| 50 | fn exec(cwd: []const u8, argv: []const []const u8) !os.ChildProcess.ExecResult { | |
| 51 | const max_output_size = 100 * 1024; | |
| 52 | const result = os.ChildProcess.exec(a, argv, cwd, null, max_output_size) catch |err| { | |
| 53 | std.debug.warn("The following command failed:\n"); | |
| 54 | printCmd(cwd, argv); | |
| 55 | return err; | |
| 56 | }; | |
| 57 | switch (result.term) { | |
| 58 | os.ChildProcess.Term.Exited => |code| { | |
| 59 | if (code != 0) { | |
| 60 | std.debug.warn("The following command exited with error code {}:\n", code); | |
| 61 | printCmd(cwd, argv); | |
| 62 | std.debug.warn("stderr:\n{}\n", result.stderr); | |
| 63 | return error.CommandFailed; | |
| 64 | } | |
| 65 | }, | |
| 66 | else => { | |
| 67 | std.debug.warn("The following command terminated unexpectedly:\n"); | |
| 68 | printCmd(cwd, argv); | |
| 69 | std.debug.warn("stderr:\n{}\n", result.stderr); | |
| 70 | return error.CommandFailed; | |
| 71 | }, | |
| 72 | } | |
| 73 | return result; | |
| 74 | } | |
| 75 | ||
| 76 | fn testZigInitLib(zig_exe: []const u8, cache_root: []const u8) !void { | |
| 77 | const dir_path = try os.path.join(a, cache_root, "clitest"); | |
| 78 | try os.deleteTree(a, dir_path); | |
| 79 | try os.makeDir(dir_path); | |
| 80 | _ = try exec(dir_path, [][]const u8{ zig_exe, "init-lib" }); | |
| 81 | const test_result = try exec(dir_path, [][]const u8{ zig_exe, "build", "test" }); | |
| 82 | assertOrPanic(std.mem.endsWith(u8, test_result.stderr, "All tests passed.\n")); | |
| 83 | } | |
| 84 | ||
| 85 | fn testZigInitExe(zig_exe: []const u8, cache_root: []const u8) !void { | |
| 86 | const dir_path = try os.path.join(a, cache_root, "clitest"); | |
| 87 | try os.deleteTree(a, dir_path); | |
| 88 | try os.makeDir(dir_path); | |
| 89 | _ = try exec(dir_path, [][]const u8{ zig_exe, "init-exe" }); | |
| 90 | const run_result = try exec(dir_path, [][]const u8{ zig_exe, "build", "run" }); | |
| 91 | assertOrPanic(std.mem.eql(u8, run_result.stderr, "All your base are belong to us.\n")); | |
| 92 | } |
test/compile_errors.zig+23| ... | ... | @@ -1,6 +1,29 @@ |
| 1 | 1 | const tests = @import("tests.zig"); |
| 2 | 2 | |
| 3 | 3 | pub fn addCases(cases: *tests.CompileErrorContext) void { |
| 4 | cases.add( | |
| 5 | "@ptrCast a 0 bit type to a non- 0 bit type", | |
| 6 | \\export fn entry() bool { | |
| 7 | \\ var x: u0 = 0; | |
| 8 | \\ const p = @ptrCast(?*u0, &x); | |
| 9 | \\ return p == null; | |
| 10 | \\} | |
| 11 | , | |
| 12 | ".tmp_source.zig:3:15: error: '*u0' and '?*u0' do not have the same in-memory representation", | |
| 13 | ".tmp_source.zig:3:31: note: '*u0' has no in-memory bits", | |
| 14 | ".tmp_source.zig:3:24: note: '?*u0' has in-memory bits", | |
| 15 | ); | |
| 16 | ||
| 17 | cases.add( | |
| 18 | "comparing a non-optional pointer against null", | |
| 19 | \\export fn entry() void { | |
| 20 | \\ var x: i32 = 1; | |
| 21 | \\ _ = &x == null; | |
| 22 | \\} | |
| 23 | , | |
| 24 | ".tmp_source.zig:3:12: error: comparison against null can only be done with optionals", | |
| 25 | ); | |
| 26 | ||
| 4 | 27 | cases.add( |
| 5 | 28 | "non error sets used in merge error sets operator", |
| 6 | 29 | \\export fn foo() void { |
test/runtime_safety.zig+13| ... | ... | @@ -249,6 +249,19 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { |
| 249 | 249 | \\} |
| 250 | 250 | ); |
| 251 | 251 | |
| 252 | cases.addRuntimeSafety("value does not fit in shortening cast - u0", | |
| 253 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { | |
| 254 | \\ @import("std").os.exit(126); | |
| 255 | \\} | |
| 256 | \\pub fn main() !void { | |
| 257 | \\ const x = shorten_cast(1); | |
| 258 | \\ if (x == 0) return error.Whatever; | |
| 259 | \\} | |
| 260 | \\fn shorten_cast(x: u8) u0 { | |
| 261 | \\ return @intCast(u0, x); | |
| 262 | \\} | |
| 263 | ); | |
| 264 | ||
| 252 | 265 | cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer", |
| 253 | 266 | \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { |
| 254 | 267 | \\ @import("std").os.exit(126); |
test/tests.zig+15| ... | ... | @@ -103,6 +103,21 @@ pub fn addBuildExampleTests(b: *build.Builder, test_filter: ?[]const u8, modes: |
| 103 | 103 | return cases.step; |
| 104 | 104 | } |
| 105 | 105 | |
| 106 | pub fn addCliTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { | |
| 107 | const step = b.step("test-cli", "Test the command line interface"); | |
| 108 | ||
| 109 | const exe = b.addExecutable("test-cli", "test/cli.zig"); | |
| 110 | const run_cmd = b.addCommand(null, b.env_map, [][]const u8{ | |
| 111 | b.pathFromRoot(exe.getOutputPath()), | |
| 112 | os.path.realAlloc(b.allocator, b.zig_exe) catch unreachable, | |
| 113 | b.pathFromRoot(b.cache_root), | |
| 114 | }); | |
| 115 | run_cmd.step.dependOn(&exe.step); | |
| 116 | ||
| 117 | step.dependOn(&run_cmd.step); | |
| 118 | return step; | |
| 119 | } | |
| 120 | ||
| 106 | 121 | pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { |
| 107 | 122 | const cases = b.allocator.create(CompareOutputContext{ |
| 108 | 123 | .b = b, |