authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-18 15:05:47-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-18 15:05:47-04:00
log4b2719b51d7ec9a38bad57ca02040231b6e8df26
tree7f3af852912303da208a806274f95c335ba9cb8a
parenta2abdb185f9e47b663edce1bdfa3fa525502f321
parent8c77c5705f41e55a5f2d80db20270d0c644338ed
signaturelock-open Commit is signed but in an unrecognized format.

Merge remote-tracking branch 'origin/master' into llvm7


30 files changed, 701 insertions(+), 183 deletions(-)

CMakeLists.txt+11-5
......@@ -600,7 +600,6 @@ set(ZIG_STD_FILES
600600 "sort.zig"
601601 "special/bootstrap.zig"
602602 "special/bootstrap_lib.zig"
603 "special/build_file_template.zig"
604603 "special/build_runner.zig"
605604 "special/builtin.zig"
606605 "special/compiler_rt/aulldiv.zig"
......@@ -618,22 +617,26 @@ set(ZIG_STD_FILES
618617 "special/compiler_rt/fixunstfdi.zig"
619618 "special/compiler_rt/fixunstfsi.zig"
620619 "special/compiler_rt/fixunstfti.zig"
620 "special/compiler_rt/floattidf.zig"
621 "special/compiler_rt/floattisf.zig"
622 "special/compiler_rt/floattitf.zig"
621623 "special/compiler_rt/floatunditf.zig"
622624 "special/compiler_rt/floatunsitf.zig"
623625 "special/compiler_rt/floatuntidf.zig"
624626 "special/compiler_rt/floatuntisf.zig"
625627 "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"
630628 "special/compiler_rt/index.zig"
629 "special/compiler_rt/muloti4.zig"
631630 "special/compiler_rt/truncXfYf2.zig"
632631 "special/compiler_rt/udivmod.zig"
633632 "special/compiler_rt/udivmoddi4.zig"
634633 "special/compiler_rt/udivmodti4.zig"
635634 "special/compiler_rt/udivti3.zig"
636635 "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"
637640 "special/panic.zig"
638641 "special/test_runner.zig"
639642 "unicode.zig"
......@@ -796,6 +799,9 @@ if(MSVC)
796799 set(EXE_CFLAGS "${EXE_CFLAGS}")
797800else()
798801 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()
799805endif()
800806
801807set(BLAKE_CFLAGS "-std=c99")
build.zig+1
......@@ -112,6 +112,7 @@ pub fn build(b: *Builder) !void {
112112
113113 test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes));
114114 test_step.dependOn(tests.addBuildExampleTests(b, test_filter, modes));
115 test_step.dependOn(tests.addCliTests(b, test_filter, modes));
115116 test_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes));
116117 test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes));
117118 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 {
58775877 {#header_open|@OpaqueType#}
58785878 <pre>{#syntax#}@OpaqueType() type{#endsyntax#}</pre>
58795879 <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.
58815881 </p>
58825882 <p>
58835883 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 @@
11use @import("std").os.windows;
22
3extern "user32" stdcallcc fn MessageBoxA(hWnd: ?HANDLE, lpText: ?LPCTSTR, lpCaption: ?LPCTSTR, uType: UINT) c_int;
4
35export fn WinMain(hInstance: HINSTANCE, hPrevInstance: HINSTANCE, lpCmdLine: PWSTR, nCmdShow: INT) INT {
46 _ = MessageBoxA(null, c"hello", c"title", 0);
57 return 0;
src/analyze.cpp+6-4
......@@ -1470,7 +1470,8 @@ static bool type_allowed_in_extern(CodeGen *g, ZigType *type_entry) {
14701470 case ZigTypeIdArray:
14711471 return type_allowed_in_extern(g, type_entry->data.array.child_type);
14721472 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;
14741475 case ZigTypeIdPointer:
14751476 if (type_size(g, type_entry) == 0)
14761477 return false;
......@@ -3992,9 +3993,10 @@ uint32_t get_ptr_align(CodeGen *g, ZigType *type) {
39923993 return (ptr_type->data.pointer.explicit_alignment == 0) ?
39933994 get_abi_alignment(g, ptr_type->data.pointer.child_type) : ptr_type->data.pointer.explicit_alignment;
39943995 } 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;
39984000 } else if (ptr_type->id == ZigTypeIdPromise) {
39994001 return get_coro_frame_align_bytes(g);
40004002 } else {
src/codegen.cpp+16
......@@ -1662,6 +1662,22 @@ static LLVMValueRef gen_widen_or_shorten(CodeGen *g, bool want_runtime_safety, Z
16621662 if (actual_type->id == ZigTypeIdFloat) {
16631663 return LLVMBuildFPTrunc(g->builder, expr_val, wanted_type->type_ref, "");
16641664 } 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 }
16651681 LLVMValueRef trunc_val = LLVMBuildTrunc(g->builder, expr_val, wanted_type->type_ref, "");
16661682 if (!want_runtime_safety) {
16671683 return trunc_val;
src/compiler.cpp+101
......@@ -5,6 +5,9 @@
55static Buf saved_compiler_id = BUF_INIT;
66static Buf saved_app_data_dir = BUF_INIT;
77static Buf saved_stage1_path = BUF_INIT;
8static Buf saved_lib_dir = BUF_INIT;
9static Buf saved_special_dir = BUF_INIT;
10static Buf saved_std_dir = BUF_INIT;
811
912Buf *get_stage1_cache_path() {
1013 if (saved_stage1_path.list.length != 0) {
......@@ -64,3 +67,101 @@ Error get_compiler_id(Buf **result) {
6467 return ErrorNone;
6568}
6669
70
71static 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
106static 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
133Buf *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
147Buf *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
158Buf *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 @@
1414Buf *get_stage1_cache_path();
1515Error get_compiler_id(Buf **result);
1616
17Buf *get_zig_lib_dir();
18Buf *get_zig_special_dir();
19Buf *get_zig_std_dir();
20
1721#endif
src/ir.cpp+64-23
......@@ -10015,21 +10015,25 @@ static IrInstruction *ir_analyze_cast_ref(IrAnalyze *ira, IrInstruction *source_
1001510015
1001610016 if (value->id == IrInstructionIdLoadPtr) {
1001710017 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;
1002310028
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);
1003210034 }
10035 ir_add_alloca(ira, new_instruction, child_type);
10036 return new_instruction;
1003310037}
1003410038
1003510039static 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
1105711061 }
1105811062 }
1105911063
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
1106111065 if (actual_type->id == ZigTypeIdEnum && wanted_type->id == ZigTypeIdPointer) {
1106211066 ZigType *union_type = wanted_type->data.pointer.child_type;
1106311067 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
1118711191 }
1118811192 }
1118911193 }
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 }
1119011201 // TODO if the instruction is a const ref instruction we can skip it
1119111202 IrInstruction *load_ptr_instruction = ir_build_load_ptr(&ira->new_irb, source_instruction->scope,
1119211203 source_instruction->source_node, ptr);
......@@ -11521,7 +11532,13 @@ static bool optional_value_is_null(ConstExprValue *val) {
1152111532static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op_instruction) {
1152211533 Error err;
1152311534 IrInstruction *op1 = bin_op_instruction->op1->other;
11535 if (type_is_invalid(op1->value.type))
11536 return ira->codegen->builtin_types.entry_invalid;
11537
1152411538 IrInstruction *op2 = bin_op_instruction->op2->other;
11539 if (type_is_invalid(op2->value.type))
11540 return ira->codegen->builtin_types.entry_invalid;
11541
1152511542 AstNode *source_node = bin_op_instruction->base.source_node;
1152611543
1152711544 IrBinOp op_id = bin_op_instruction->op_id;
......@@ -11564,6 +11581,9 @@ static ZigType *ir_analyze_bin_op_cmp(IrAnalyze *ira, IrInstructionBinOp *bin_op
1156411581 ir_link_new_instruction(is_non_null, &bin_op_instruction->base);
1156511582 }
1156611583 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;
1156711587 }
1156811588
1156911589 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_
1206312083 ir_add_error(ira, &bin_op_instruction->base,
1206412084 buf_sprintf("LHS of shift must be an integer type, or RHS must be compile-time known"));
1206512085 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;
1206612092 }
1206712093
1206812094 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
1816518191 &source_dir_path,
1816618192 rel_file_path,
1816718193 };
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);
1816918196
1817018197 // load from file system into const expr
1817118198 Buf *file_contents = buf_alloc();
1817218199 int err;
18173 if ((err = file_fetch(ira->codegen, &file_path, file_contents))) {
18200 if ((err = file_fetch(ira->codegen, file_path, file_contents))) {
1817418201 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)));
1817618203 return ira->codegen->builtin_types.entry_invalid;
1817718204 } 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)));
1817918206 return ira->codegen->builtin_types.entry_invalid;
1818018207 }
1818118208 }
......@@ -18494,6 +18521,9 @@ static ZigType *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionF
1849418521 src_ptr_align = get_abi_alignment(ira->codegen, target->value.type);
1849518522 }
1849618523
18524 if ((err = type_resolve(ira->codegen, dest_child_type, ResolveStatusSizeKnown)))
18525 return ira->codegen->builtin_types.entry_invalid;
18526
1849718527 ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_child_type,
1849818528 src_ptr_const, src_ptr_volatile, PtrLenUnknown,
1849918529 src_ptr_align, 0, 0);
......@@ -20174,11 +20204,19 @@ static ZigType *ir_analyze_instruction_ptr_cast(IrAnalyze *ira, IrInstructionPtr
2017420204 instruction->base.source_node, nullptr, ptr);
2017520205 casted_ptr->value.type = dest_type;
2017620206
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)));
2018020215 return ira->codegen->builtin_types.entry_invalid;
20216 }
2018120217
20218 // Keep the bigger alignment, it can only help-
20219 // unless the target is zero bits.
2018220220 IrInstruction *result;
2018320221 if (src_align_bytes > dest_align_bytes && type_has_bits(dest_type)) {
2018420222 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
2021620254 bigint_write_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count,
2021720255 codegen->is_big_endian);
2021820256 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;
2021920262 case ZigTypeIdFloat:
2022020263 float_write_ieee597(val, buf, codegen->is_big_endian);
2022120264 return;
......@@ -20247,8 +20290,6 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue
2024720290 zig_panic("TODO buf_write_value_bytes error union");
2024820291 case ZigTypeIdErrorSet:
2024920292 zig_panic("TODO buf_write_value_bytes pure error type");
20250 case ZigTypeIdEnum:
20251 zig_panic("TODO buf_write_value_bytes enum type");
2025220293 case ZigTypeIdFn:
2025320294 zig_panic("TODO buf_write_value_bytes fn type");
2025420295 case ZigTypeIdUnion:
src/main.cpp+112-118
......@@ -25,6 +25,8 @@ static int usage(const char *arg0) {
2525 " build-obj [source] create object from source or assembly\n"
2626 " builtin show the source code of that @import(\"builtin\")\n"
2727 " 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"
2830 " run [source] create executable and run immediately\n"
2931 " translate-c [source] convert c code to zig code\n"
3032 " targets list available compilation targets\n"
......@@ -34,7 +36,7 @@ static int usage(const char *arg0) {
3436 "Compile Options:\n"
3537 " --assembly [source] add assembly file to build\n"
3638 " --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"
3840 " --color [auto|off|on] enable or disable colored error messages\n"
3941 " --emit [asm|bin|llvm-ir] emit a specific file format as compilation output\n"
4042 " -ftime-report print timing diagnostics\n"
......@@ -42,7 +44,7 @@ static int usage(const char *arg0) {
4244 " --name [name] override output name\n"
4345 " --output [file] override destination path\n"
4446 " --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"
4648 " --pkg-end pop current pkg\n"
4749 " --release-fast build with optimizations on and safety off\n"
4850 " --release-safe build with optimizations on and safety on\n"
......@@ -52,17 +54,16 @@ static int usage(const char *arg0) {
5254 " --target-arch [name] specify target architecture\n"
5355 " --target-environ [name] specify target environment\n"
5456 " --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"
6163 " -dirafter [dir] same as -isystem but do it last\n"
6264 " -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"
6466 "Link Options:\n"
65 " --ar-path [path] set the path to ar\n"
6667 " --dynamic-linker [path] set the path to ld.so\n"
6768 " --each-lib-rpath add rpath for each used dynamic library\n"
6869 " --libc-lib-dir [path] directory where libc crt1.o resides\n"
......@@ -142,78 +143,6 @@ static int print_target_list(FILE *f) {
142143 return EXIT_SUCCESS;
143144}
144145
145static 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
180static 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
207static 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
217146enum Cmd {
218147 CmdInvalid,
219148 CmdBuild,
......@@ -277,6 +206,9 @@ static bool get_cache_opt(CacheOpt opt, bool default_value) {
277206}
278207
279208int main(int argc, char **argv) {
209 char *arg0 = argv[0];
210 Error err;
211
280212 if (argc == 2 && strcmp(argv[1], "BUILD_INFO") == 0) {
281213 printf("%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
282214 ZIG_CMAKE_BINARY_DIR,
......@@ -290,8 +222,10 @@ int main(int argc, char **argv) {
290222 return 0;
291223 }
292224
225 // Must be before all os.hpp function calls.
226 os_init();
227
293228 if (argc == 2 && strcmp(argv[1], "id") == 0) {
294 Error err;
295229 Buf *compiler_id;
296230 if ((err = get_compiler_id(&compiler_id))) {
297231 fprintf(stderr, "Unable to determine compiler id: %s\n", err_str(err));
......@@ -301,9 +235,97 @@ int main(int argc, char **argv) {
301235 return EXIT_SUCCESS;
302236 }
303237
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 }
305328
306 char *arg0 = argv[0];
307329 Cmd cmd = CmdInvalid;
308330 EmitFileType emit_file_type = EmitFileTypeBinary;
309331 const char *in_file = nullptr;
......@@ -333,7 +355,6 @@ int main(int argc, char **argv) {
333355 ZigList<const char *> link_libs = {0};
334356 ZigList<const char *> forbidden_link_libs = {0};
335357 ZigList<const char *> frameworks = {0};
336 int err;
337358 const char *target_arch = nullptr;
338359 const char *target_os = nullptr;
339360 const char *target_environ = nullptr;
......@@ -364,7 +385,6 @@ int main(int argc, char **argv) {
364385 const char *zig_exe_path = arg0;
365386 const char *build_file = "build.zig";
366387 bool asked_for_help = false;
367 bool asked_to_init = false;
368388
369389 init_all_targets();
370390
......@@ -376,9 +396,6 @@ int main(int argc, char **argv) {
376396 if (strcmp(argv[i], "--help") == 0) {
377397 asked_for_help = true;
378398 args.append(argv[i]);
379 } else if (strcmp(argv[i], "--init") == 0) {
380 asked_to_init = true;
381 args.append(argv[i]);
382399 } else if (i + 1 < argc && strcmp(argv[i], "--build-file") == 0) {
383400 build_file = argv[i + 1];
384401 i += 1;
......@@ -390,18 +407,10 @@ int main(int argc, char **argv) {
390407 }
391408 }
392409
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
401410 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);
403412
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());
405414 g->enable_time_report = timing_info;
406415 buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
407416 codegen_set_out_name(g, buf_create_from_str("build"));
......@@ -437,7 +446,6 @@ int main(int argc, char **argv) {
437446 "\n"
438447 "General Options:\n"
439448 " --help Print this help and exit\n"
440 " --init Generate a build.zig template\n"
441449 " --build-file [file] Override path to build.zig\n"
442450 " --cache-dir [path] Override path to cache directory\n"
443451 " --verbose Print commands before executing them\n"
......@@ -463,22 +471,11 @@ int main(int argc, char **argv) {
463471 "\n"
464472 , zig_exe_path);
465473 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 }
477474 }
478475
479476 fprintf(stderr,
480477 "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"
482479 "or build an executable directly with `zig build-exe $FILENAME.zig`.\n"
483480 "See: `zig build --help` or `zig help` for more options.\n"
484481 );
......@@ -773,8 +770,7 @@ int main(int argc, char **argv) {
773770
774771 switch (cmd) {
775772 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());
778774 Buf *builtin_source = codegen_generate_builtin_source(g);
779775 if (fwrite(buf_ptr(builtin_source), 1, buf_len(builtin_source), stdout) != buf_len(builtin_source)) {
780776 fprintf(stderr, "unable to write to stdout: %s\n", strerror(ferror(stdout)));
......@@ -832,9 +828,7 @@ int main(int argc, char **argv) {
832828 if (cmd == CmdRun && buf_out_name == nullptr) {
833829 buf_out_name = buf_create_from_str("run");
834830 }
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());
838832 g->enable_time_report = timing_info;
839833 buf_init_from_str(&g->cache_dir, cache_dir ? cache_dir : default_zig_cache_name);
840834 codegen_set_out_name(g, buf_out_name);
src/os.cpp+17-9
......@@ -23,6 +23,14 @@
2323#define WIN32_LEAN_AND_MEAN
2424#endif
2525
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
2634#include <windows.h>
2735#include <shlobj.h>
2836#include <io.h>
......@@ -1091,14 +1099,14 @@ Error os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang) {
10911099 return result;
10921100}
10931101
1094int os_get_cwd(Buf *out_cwd) {
1102Error os_get_cwd(Buf *out_cwd) {
10951103#if defined(ZIG_OS_WINDOWS)
10961104 char buf[4096];
10971105 if (GetCurrentDirectory(4096, buf) == 0) {
10981106 zig_panic("GetCurrentDirectory failed");
10991107 }
11001108 buf_init_from_str(out_cwd, buf);
1101 return 0;
1109 return ErrorNone;
11021110#elif defined(ZIG_OS_POSIX)
11031111 char buf[PATH_MAX];
11041112 char *res = getcwd(buf, PATH_MAX);
......@@ -1106,7 +1114,7 @@ int os_get_cwd(Buf *out_cwd) {
11061114 zig_panic("unable to get cwd: %s", strerror(errno));
11071115 }
11081116 buf_init_from_str(out_cwd, res);
1109 return 0;
1117 return ErrorNone;
11101118#else
11111119#error "missing os_get_cwd implementation"
11121120#endif
......@@ -1634,16 +1642,16 @@ static Optional<uint32_t> Utf16LeIterator_nextCodepoint(Utf16LeIterator *it) {
16341642 if (it->bytes[it->i] == 0 && it->bytes[it->i + 1] == 0)
16351643 return {};
16361644 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) {
16381646 // surrogate pair
16391647 it->i += 2;
16401648 assert(it->bytes[it->i] != 0 || it->bytes[it->i + 1] != 0);
16411649 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);
16431651 it->i += 2;
16441652 return Optional<uint32_t>::some(0x10000 + (((c0 & 0x03ff) << 10) | (c1 & 0x03ff)));
16451653 } else {
1646 assert(c0 & ~((uint32_t)0x03ff) != 0xdc00);
1654 assert((c0 & ~((uint32_t)0x03ff)) != 0xdc00);
16471655 it->i += 2;
16481656 return Optional<uint32_t>::some(c0);
16491657 }
......@@ -1714,7 +1722,6 @@ static void utf16le_ptr_to_utf8(Buf *out, WCHAR *utf16le) {
17141722// Ported from std.os.getAppDataDir
17151723Error os_get_app_data_dir(Buf *out_path, const char *appname) {
17161724#if defined(ZIG_OS_WINDOWS)
1717 Error err;
17181725 WCHAR *dir_path_ptr;
17191726 switch (SHGetKnownFolderPath(FOLDERID_LocalAppData, KF_FLAG_CREATE, nullptr, &dir_path_ptr)) {
17201727 case S_OK:
......@@ -1928,7 +1935,7 @@ Error os_file_mtime(OsFile file, OsTimeStamp *mtime) {
19281935 FILETIME last_write_time;
19291936 if (!GetFileTime(file, nullptr, nullptr, &last_write_time))
19301937 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;
19321939 mtime->nsec = 0;
19331940 return ErrorNone;
19341941#elif defined(ZIG_OS_LINUX)
......@@ -2011,7 +2018,8 @@ Error os_file_overwrite(OsFile file, Buf *contents) {
20112018 return ErrorFileSystem;
20122019 if (!SetEndOfFile(file))
20132020 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))
20152023 return ErrorFileSystem;
20162024 return ErrorNone;
20172025#else
src/os.hpp+1-1
......@@ -114,7 +114,7 @@ int os_copy_file(Buf *src_path, Buf *dest_path);
114114Error ATTRIBUTE_MUST_USE os_fetch_file(FILE *file, Buf *out_contents, bool skip_shebang);
115115Error ATTRIBUTE_MUST_USE os_fetch_file_path(Buf *full_path, Buf *out_contents, bool skip_shebang);
116116
117int os_get_cwd(Buf *out_cwd);
117Error ATTRIBUTE_MUST_USE os_get_cwd(Buf *out_cwd);
118118
119119bool os_stderr_tty(void);
120120void os_stderr_set_color(TermColor color);
src/windows_com.hpp+3
......@@ -28,6 +28,9 @@
2828#include <io.h>
2929#include <shellapi.h>
3030
31// Standard headers
32#include <stdio.h>
33
3134// COM support header files
3235#include <comdef.h>
3336
std/os/windows/advapi32.zig-12
......@@ -11,18 +11,6 @@ pub const HKEY__ = extern struct {
1111};
1212pub const LSTATUS = LONG;
1313
14pub extern "advapi32" stdcallcc fn CryptAcquireContextA(
15 phProv: *HCRYPTPROV,
16 pszContainer: ?LPCSTR,
17 pszProvider: ?LPCSTR,
18 dwProvType: DWORD,
19 dwFlags: DWORD,
20) BOOL;
21
22pub extern "advapi32" stdcallcc fn CryptReleaseContext(hProv: HCRYPTPROV, dwFlags: DWORD) BOOL;
23
24pub extern "advapi32" stdcallcc fn CryptGenRandom(hProv: HCRYPTPROV, dwLen: DWORD, pbBuffer: [*]BYTE) BOOL;
25
2614pub extern "advapi32" stdcallcc fn RegOpenKeyExW(
2715 hKey: HKEY,
2816 lpSubKey: LPCWSTR,
std/special/build_file_template.zig deleted-10
......@@ -1,10 +0,0 @@
1const Builder = @import("std").build.Builder;
2
3pub 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 @@
1const Builder = @import("std").build.Builder;
2
3pub 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 @@
1const std = @import("std");
2
3pub 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 @@
1const Builder = @import("std").build.Builder;
2
3pub 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 @@
1const std = @import("std");
2const assertOrPanic = std.debug.assertOrPanic;
3
4export fn add(a: i32, b: i32) i32 {
5 return a + b;
6}
7
8test "basic add functionality" {
9 assertOrPanic(add(3, 7) == 10);
10}
test/behavior.zig+1
......@@ -71,4 +71,5 @@ comptime {
7171 _ = @import("cases/void.zig");
7272 _ = @import("cases/while.zig");
7373 _ = @import("cases/widening.zig");
74 _ = @import("cases/bit_shifting.zig");
7475}
test/cases/align.zig+9
......@@ -219,3 +219,12 @@ test "alignment of structs" {
219219 b: *i32,
220220 }) == @alignOf(usize));
221221}
222
223test "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
230extern fn nothing() void {}
test/cases/bit_shifting.zig created+88
......@@ -0,0 +1,88 @@
1const std = @import("std");
2const assert = std.debug.assert;
3
4fn 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
60test "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}
73fn 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 {
1616fn conv2(x: u32) i32 {
1717 return @bitCast(i32, x);
1818}
19
20test "@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" {
682682}
683683
684684fn doNothingWithType(comptime T: type) void {}
685
686test "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
692test "bit shift a u1" {
693 var x: u1 = 1;
694 var y = x << 0;
695 assert(y == 1);
696}
697
698test "@intCast to a u0" {
699 var x: u8 = 0;
700 var y: u0 = @intCast(u0, x);
701 assert(y == 0);
702}
703
704test "@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
191191 var func = outer(10);
192192 assert(func(3) == 7);
193193}
194
195test "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" {
437437 assert(S.do(&s));
438438 assert(s.do());
439439}
440
441test "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 @@
1const std = @import("std");
2const os = std.os;
3const assertOrPanic = std.debug.assertOrPanic;
4
5var a: *std.mem.Allocator = undefined;
6
7pub 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
35fn 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
42fn 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
50fn 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
76fn 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
85fn 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 @@
11const tests = @import("tests.zig");
22
33pub 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
427 cases.add(
528 "non error sets used in merge error sets operator",
629 \\export fn foo() void {
test/runtime_safety.zig+13
......@@ -249,6 +249,19 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
249249 \\}
250250 );
251251
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
252265 cases.addRuntimeSafety("signed integer not fitting in cast to unsigned integer",
253266 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
254267 \\ @import("std").os.exit(126);
test/tests.zig+15
......@@ -103,6 +103,21 @@ pub fn addBuildExampleTests(b: *build.Builder, test_filter: ?[]const u8, modes:
103103 return cases.step;
104104}
105105
106pub 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
106121pub fn addAssembleAndLinkTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
107122 const cases = b.allocator.create(CompareOutputContext{
108123 .b = b,