authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2019-09-04 15:55:54+02:00
committergravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2019-09-04 15:55:54+02:00
log5308eb7045b7b6a48356c6e814baf2a45a094d80
tree88b2bd51d15a72b1aa27c51fdc54a2c51d8c827a
parentd62f7c6b605a672f032aff8870496d2ae2366017
parent77a5f888be664f9ef09e2c93f52338448e992e00

Merge remote-tracking branch 'upstream/master' into arm-support-improvement


36 files changed, 964 insertions(+), 124 deletions(-)

CMakeLists.txt+10-6
...@@ -23,14 +23,18 @@ find_program(GIT_EXE NAMES git)...@@ -23,14 +23,18 @@ find_program(GIT_EXE NAMES git)
23if(GIT_EXE)23if(GIT_EXE)
24 execute_process(24 execute_process(
25 COMMAND ${GIT_EXE} -C ${CMAKE_SOURCE_DIR} name-rev HEAD --tags --name-only --no-undefined --always25 COMMAND ${GIT_EXE} -C ${CMAKE_SOURCE_DIR} name-rev HEAD --tags --name-only --no-undefined --always
26 RESULT_VARIABLE EXIT_STATUS
26 OUTPUT_VARIABLE ZIG_GIT_REV27 OUTPUT_VARIABLE ZIG_GIT_REV
27 OUTPUT_STRIP_TRAILING_WHITESPACE)28 OUTPUT_STRIP_TRAILING_WHITESPACE
28 if(ZIG_GIT_REV MATCHES "\\^0$")29 ERROR_QUIET)
29 if(NOT("${ZIG_GIT_REV}" STREQUAL "${ZIG_VERSION}^0"))30 if(EXIT_STATUS EQUAL "0")
30 message("WARNING: Tag does not match configured Zig version")31 if(ZIG_GIT_REV MATCHES "\\^0$")
32 if(NOT("${ZIG_GIT_REV}" STREQUAL "${ZIG_VERSION}^0"))
33 message("WARNING: Tag does not match configured Zig version")
34 endif()
35 else()
36 set(ZIG_VERSION "${ZIG_VERSION}+${ZIG_GIT_REV}")
31 endif()37 endif()
32 else()
33 set(ZIG_VERSION "${ZIG_VERSION}+${ZIG_GIT_REV}")
34 endif()38 endif()
35endif()39endif()
36message("Configuring zig version ${ZIG_VERSION}")40message("Configuring zig version ${ZIG_VERSION}")
build.zig+2-1
...@@ -138,12 +138,13 @@ pub fn build(b: *Builder) !void {...@@ -138,12 +138,13 @@ pub fn build(b: *Builder) !void {
138138
139 test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes));139 test_step.dependOn(tests.addCompareOutputTests(b, test_filter, modes));
140 test_step.dependOn(tests.addStandaloneTests(b, test_filter, modes));140 test_step.dependOn(tests.addStandaloneTests(b, test_filter, modes));
141 test_step.dependOn(tests.addStackTraceTests(b, test_filter, modes));
141 test_step.dependOn(tests.addCliTests(b, test_filter, modes));142 test_step.dependOn(tests.addCliTests(b, test_filter, modes));
142 test_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes));
143 test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes));143 test_step.dependOn(tests.addAssembleAndLinkTests(b, test_filter, modes));
144 test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes));144 test_step.dependOn(tests.addRuntimeSafetyTests(b, test_filter, modes));
145 test_step.dependOn(tests.addTranslateCTests(b, test_filter));145 test_step.dependOn(tests.addTranslateCTests(b, test_filter));
146 test_step.dependOn(tests.addGenHTests(b, test_filter));146 test_step.dependOn(tests.addGenHTests(b, test_filter));
147 test_step.dependOn(tests.addCompileErrorTests(b, test_filter, modes));
147 test_step.dependOn(docs_step);148 test_step.dependOn(docs_step);
148}149}
149150
doc/docgen.zig+2-2
...@@ -307,7 +307,7 @@ const Node = union(enum) {...@@ -307,7 +307,7 @@ const Node = union(enum) {
307const Toc = struct {307const Toc = struct {
308 nodes: []Node,308 nodes: []Node,
309 toc: []u8,309 toc: []u8,
310 urls: std.HashMap([]const u8, Token, mem.hash_slice_u8, mem.eql_slice_u8),310 urls: std.StringHashMap(Token),
311};311};
312312
313const Action = enum {313const Action = enum {
...@@ -316,7 +316,7 @@ const Action = enum {...@@ -316,7 +316,7 @@ const Action = enum {
316};316};
317317
318fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {318fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc {
319 var urls = std.HashMap([]const u8, Token, mem.hash_slice_u8, mem.eql_slice_u8).init(allocator);319 var urls = std.StringHashMap(Token).init(allocator);
320 errdefer urls.deinit();320 errdefer urls.deinit();
321321
322 var header_stack_size: usize = 0;322 var header_stack_size: usize = 0;
src-self-hosted/arg.zig+2-2
...@@ -5,7 +5,7 @@ const mem = std.mem;...@@ -5,7 +5,7 @@ const mem = std.mem;
55
6const Allocator = mem.Allocator;6const Allocator = mem.Allocator;
7const ArrayList = std.ArrayList;7const ArrayList = std.ArrayList;
8const HashMap = std.HashMap;8const StringHashMap = std.StringHashMap;
99
10fn trimStart(slice: []const u8, ch: u8) []const u8 {10fn trimStart(slice: []const u8, ch: u8) []const u8 {
11 var i: usize = 0;11 var i: usize = 0;
...@@ -73,7 +73,7 @@ fn readFlagArguments(allocator: *Allocator, args: []const []const u8, required:...@@ -73,7 +73,7 @@ fn readFlagArguments(allocator: *Allocator, args: []const []const u8, required:
73 }73 }
74}74}
7575
76const HashMapFlags = HashMap([]const u8, FlagArg, std.hash.Fnv1a_32.hash, mem.eql_slice_u8);76const HashMapFlags = StringHashMap(FlagArg);
7777
78// A store for querying found flags and positional arguments.78// A store for querying found flags and positional arguments.
79pub const Args = struct {79pub const Args = struct {
src-self-hosted/compilation.zig+1-1
...@@ -249,7 +249,7 @@ pub const Compilation = struct {...@@ -249,7 +249,7 @@ pub const Compilation = struct {
249 const ArrayTypeTable = std.HashMap(*const Type.Array.Key, *Type.Array, Type.Array.Key.hash, Type.Array.Key.eql);249 const ArrayTypeTable = std.HashMap(*const Type.Array.Key, *Type.Array, Type.Array.Key.hash, Type.Array.Key.eql);
250 const PtrTypeTable = std.HashMap(*const Type.Pointer.Key, *Type.Pointer, Type.Pointer.Key.hash, Type.Pointer.Key.eql);250 const PtrTypeTable = std.HashMap(*const Type.Pointer.Key, *Type.Pointer, Type.Pointer.Key.hash, Type.Pointer.Key.eql);
251 const FnTypeTable = std.HashMap(*const Type.Fn.Key, *Type.Fn, Type.Fn.Key.hash, Type.Fn.Key.eql);251 const FnTypeTable = std.HashMap(*const Type.Fn.Key, *Type.Fn, Type.Fn.Key.hash, Type.Fn.Key.eql);
252 const TypeTable = std.HashMap([]const u8, *Type, mem.hash_slice_u8, mem.eql_slice_u8);252 const TypeTable = std.StringHashMap(*Type);
253253
254 const CompileErrList = std.ArrayList(*Msg);254 const CompileErrList = std.ArrayList(*Msg);
255255
src-self-hosted/decl.zig+1-1
...@@ -20,7 +20,7 @@ pub const Decl = struct {...@@ -20,7 +20,7 @@ pub const Decl = struct {
20 // TODO when we destroy the decl, deref the tree scope20 // TODO when we destroy the decl, deref the tree scope
21 tree_scope: *Scope.AstTree,21 tree_scope: *Scope.AstTree,
2222
23 pub const Table = std.HashMap([]const u8, *Decl, mem.hash_slice_u8, mem.eql_slice_u8);23 pub const Table = std.StringHashMap(*Decl);
2424
25 pub fn cast(base: *Decl, comptime T: type) ?*T {25 pub fn cast(base: *Decl, comptime T: type) ?*T {
26 if (base.id != @field(Id, @typeName(T))) return null;26 if (base.id != @field(Id, @typeName(T))) return null;
src-self-hosted/main.zig+1-1
...@@ -541,7 +541,7 @@ const Fmt = struct {...@@ -541,7 +541,7 @@ const Fmt = struct {
541 color: errmsg.Color,541 color: errmsg.Color,
542 loop: *event.Loop,542 loop: *event.Loop,
543543
544 const SeenMap = std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8);544 const SeenMap = std.StringHashMap(void);
545};545};
546546
547fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_file: []const u8) void {547fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_file: []const u8) void {
src-self-hosted/package.zig+1-1
...@@ -10,7 +10,7 @@ pub const Package = struct {...@@ -10,7 +10,7 @@ pub const Package = struct {
10 /// relative to root_src_dir10 /// relative to root_src_dir
11 table: Table,11 table: Table,
1212
13 pub const Table = std.HashMap([]const u8, *Package, mem.hash_slice_u8, mem.eql_slice_u8);13 pub const Table = std.StringHashMap(*Package);
1414
15 /// makes internal copies of root_src_dir and root_src_path15 /// makes internal copies of root_src_dir and root_src_path
16 /// allocator should be an arena allocator because Package never frees anything16 /// allocator should be an arena allocator because Package never frees anything
src-self-hosted/stage1.zig+2-2
...@@ -343,7 +343,7 @@ const Fmt = struct {...@@ -343,7 +343,7 @@ const Fmt = struct {
343 color: errmsg.Color,343 color: errmsg.Color,
344 allocator: *mem.Allocator,344 allocator: *mem.Allocator,
345345
346 const SeenMap = std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8);346 const SeenMap = std.StringHashMap(void);
347};347};
348348
349fn printErrMsgToFile(349fn printErrMsgToFile(
...@@ -376,7 +376,7 @@ fn printErrMsgToFile(...@@ -376,7 +376,7 @@ fn printErrMsgToFile(
376 const text = text_buf.toOwnedSlice();376 const text = text_buf.toOwnedSlice();
377377
378 const stream = &file.outStream().stream;378 const stream = &file.outStream().stream;
379 try stream.print( "{}:{}:{}: error: {}\n", path, start_loc.line + 1, start_loc.column + 1, text);379 try stream.print("{}:{}:{}: error: {}\n", path, start_loc.line + 1, start_loc.column + 1, text);
380380
381 if (!color_on) return;381 if (!color_on) return;
382382
src/all_types.hpp+2
...@@ -1989,6 +1989,7 @@ struct CodeGen {...@@ -1989,6 +1989,7 @@ struct CodeGen {
1989 bool system_linker_hack;1989 bool system_linker_hack;
1990 bool reported_bad_link_libc_error;1990 bool reported_bad_link_libc_error;
1991 bool is_dynamic; // shared library rather than static library. dynamic musl rather than static musl.1991 bool is_dynamic; // shared library rather than static library. dynamic musl rather than static musl.
1992 bool need_frame_size_prefix_data;
19921993
1993 //////////////////////////// Participates in Input Parameter Cache Hash1994 //////////////////////////// Participates in Input Parameter Cache Hash
1994 /////// Note: there is a separate cache hash for builtin.zig, when adding fields,1995 /////// Note: there is a separate cache hash for builtin.zig, when adding fields,
...@@ -2003,6 +2004,7 @@ struct CodeGen {...@@ -2003,6 +2004,7 @@ struct CodeGen {
2003 ZigList<Buf *> assembly_files;2004 ZigList<Buf *> assembly_files;
2004 ZigList<CFile *> c_source_files;2005 ZigList<CFile *> c_source_files;
2005 ZigList<const char *> lib_dirs;2006 ZigList<const char *> lib_dirs;
2007 ZigList<const char *> framework_dirs;
20062008
2007 ZigLibCInstallation *libc;2009 ZigLibCInstallation *libc;
20082010
src/analyze.cpp+12-3
...@@ -2671,6 +2671,10 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {...@@ -2671,6 +2671,10 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) {
2671 }2671 }
2672 }2672 }
26732673
2674 if (!type_has_bits(struct_type)) {
2675 assert(struct_type->abi_align == 0);
2676 }
2677
2674 struct_type->data.structure.resolve_loop_flag_other = false;2678 struct_type->data.structure.resolve_loop_flag_other = false;
26752679
2676 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) {2680 if (struct_type->data.structure.resolve_status == ResolveStatusInvalid) {
...@@ -4191,7 +4195,7 @@ bool fn_is_async(ZigFn *fn) {...@@ -4191,7 +4195,7 @@ bool fn_is_async(ZigFn *fn) {
4191 return fn->inferred_async_node != inferred_async_none;4195 return fn->inferred_async_node != inferred_async_none;
4192}4196}
41934197
4194static void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) {4198void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) {
4195 assert(fn->inferred_async_node != nullptr);4199 assert(fn->inferred_async_node != nullptr);
4196 assert(fn->inferred_async_node != inferred_async_checking);4200 assert(fn->inferred_async_node != inferred_async_checking);
4197 assert(fn->inferred_async_node != inferred_async_none);4201 assert(fn->inferred_async_node != inferred_async_none);
...@@ -7687,8 +7691,13 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta...@@ -7687,8 +7691,13 @@ static void resolve_llvm_types_union(CodeGen *g, ZigType *union_type, ResolveSta
7687 ZigType *tag_type = union_type->data.unionation.tag_type;7691 ZigType *tag_type = union_type->data.unionation.tag_type;
7688 uint32_t gen_field_count = union_type->data.unionation.gen_field_count;7692 uint32_t gen_field_count = union_type->data.unionation.gen_field_count;
7689 if (gen_field_count == 0) {7693 if (gen_field_count == 0) {
7690 union_type->llvm_type = get_llvm_type(g, tag_type);7694 if (tag_type == nullptr) {
7691 union_type->llvm_di_type = get_llvm_di_type(g, tag_type);7695 union_type->llvm_type = g->builtin_types.entry_void->llvm_type;
7696 union_type->llvm_di_type = g->builtin_types.entry_void->llvm_di_type;
7697 } else {
7698 union_type->llvm_type = get_llvm_type(g, tag_type);
7699 union_type->llvm_di_type = get_llvm_di_type(g, tag_type);
7700 }
7692 union_type->data.unionation.resolve_status = ResolveStatusLLVMFull;7701 union_type->data.unionation.resolve_status = ResolveStatusLLVMFull;
7693 return;7702 return;
7694 }7703 }
src/analyze.hpp+2
...@@ -256,4 +256,6 @@ Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, ZigType *...@@ -256,4 +256,6 @@ Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, ZigType *
256ZigType *resolve_union_field_type(CodeGen *g, TypeUnionField *union_field);256ZigType *resolve_union_field_type(CodeGen *g, TypeUnionField *union_field);
257ZigType *resolve_struct_field_type(CodeGen *g, TypeStructField *struct_field);257ZigType *resolve_struct_field_type(CodeGen *g, TypeStructField *struct_field);
258258
259void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn);
260
259#endif261#endif
src/codegen.cpp+45-2
...@@ -3522,6 +3522,15 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir...@@ -3522,6 +3522,15 @@ static LLVMValueRef ir_render_store_ptr(CodeGen *g, IrExecutable *executable, Ir
3522 assert(ptr_type->id == ZigTypeIdPointer);3522 assert(ptr_type->id == ZigTypeIdPointer);
3523 if (!type_has_bits(ptr_type))3523 if (!type_has_bits(ptr_type))
3524 return nullptr;3524 return nullptr;
3525 if (instruction->ptr->ref_count == 0) {
3526 // In this case, this StorePtr instruction should be elided. Something happened like this:
3527 // var t = true;
3528 // const x = if (t) Num.Two else unreachable;
3529 // The if condition is a runtime value, so the StorePtr for `x = Num.Two` got generated
3530 // (this instruction being rendered) but because of `else unreachable` the result ended
3531 // up being a comptime const value.
3532 return nullptr;
3533 }
35253534
3526 bool have_init_expr = !value_is_all_undef(&instruction->value->value);3535 bool have_init_expr = !value_is_all_undef(&instruction->value->value);
3527 if (have_init_expr) {3536 if (have_init_expr) {
...@@ -3766,6 +3775,7 @@ static void render_async_var_decls(CodeGen *g, Scope *scope) {...@@ -3766,6 +3775,7 @@ static void render_async_var_decls(CodeGen *g, Scope *scope) {
3766}3775}
37673776
3768static LLVMValueRef gen_frame_size(CodeGen *g, LLVMValueRef fn_val) {3777static LLVMValueRef gen_frame_size(CodeGen *g, LLVMValueRef fn_val) {
3778 assert(g->need_frame_size_prefix_data);
3769 LLVMTypeRef usize_llvm_type = g->builtin_types.entry_usize->llvm_type;3779 LLVMTypeRef usize_llvm_type = g->builtin_types.entry_usize->llvm_type;
3770 LLVMTypeRef ptr_usize_llvm_type = LLVMPointerType(usize_llvm_type, 0);3780 LLVMTypeRef ptr_usize_llvm_type = LLVMPointerType(usize_llvm_type, 0);
3771 LLVMValueRef casted_fn_val = LLVMBuildBitCast(g->builder, fn_val, ptr_usize_llvm_type, "");3781 LLVMValueRef casted_fn_val = LLVMBuildBitCast(g->builder, fn_val, ptr_usize_llvm_type, "");
...@@ -4103,6 +4113,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr...@@ -4103,6 +4113,8 @@ static LLVMValueRef ir_render_call(CodeGen *g, IrExecutable *executable, IrInstr
4103static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executable,4113static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executable,
4104 IrInstructionStructFieldPtr *instruction)4114 IrInstructionStructFieldPtr *instruction)
4105{4115{
4116 Error err;
4117
4106 if (instruction->base.value.special != ConstValSpecialRuntime)4118 if (instruction->base.value.special != ConstValSpecialRuntime)
4107 return nullptr;4119 return nullptr;
41084120
...@@ -4120,6 +4132,11 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa...@@ -4120,6 +4132,11 @@ static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executa
4120 return struct_ptr;4132 return struct_ptr;
4121 }4133 }
41224134
4135 ZigType *struct_type = (struct_ptr_type->id == ZigTypeIdPointer) ?
4136 struct_ptr_type->data.pointer.child_type : struct_ptr_type;
4137 if ((err = type_resolve(g, struct_type, ResolveStatusLLVMFull)))
4138 report_errors_and_exit(g);
4139
4123 assert(field->gen_index != SIZE_MAX);4140 assert(field->gen_index != SIZE_MAX);
4124 return LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, "");4141 return LLVMBuildStructGEP(g->builder, struct_ptr, (unsigned)field->gen_index, "");
4125}4142}
...@@ -7199,7 +7216,9 @@ static void do_code_gen(CodeGen *g) {...@@ -7199,7 +7216,9 @@ static void do_code_gen(CodeGen *g) {
71997216
7200 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;7217 LLVMTypeRef usize_type_ref = g->builtin_types.entry_usize->llvm_type;
7201 LLVMValueRef size_val = LLVMConstInt(usize_type_ref, fn_table_entry->frame_type->abi_size, false);7218 LLVMValueRef size_val = LLVMConstInt(usize_type_ref, fn_table_entry->frame_type->abi_size, false);
7202 ZigLLVMFunctionSetPrefixData(fn_table_entry->llvm_value, size_val);7219 if (g->need_frame_size_prefix_data) {
7220 ZigLLVMFunctionSetPrefixData(fn_table_entry->llvm_value, size_val);
7221 }
72037222
7204 if (!g->strip_debug_symbols) {7223 if (!g->strip_debug_symbols) {
7205 AstNode *source_node = fn_table_entry->proto_node;7224 AstNode *source_node = fn_table_entry->proto_node;
...@@ -8445,8 +8464,21 @@ static void init(CodeGen *g) {...@@ -8445,8 +8464,21 @@ static void init(CodeGen *g) {
8445 Buf *producer = buf_sprintf("zig %d.%d.%d", ZIG_VERSION_MAJOR, ZIG_VERSION_MINOR, ZIG_VERSION_PATCH);8464 Buf *producer = buf_sprintf("zig %d.%d.%d", ZIG_VERSION_MAJOR, ZIG_VERSION_MINOR, ZIG_VERSION_PATCH);
8446 const char *flags = "";8465 const char *flags = "";
8447 unsigned runtime_version = 0;8466 unsigned runtime_version = 0;
8467
8468 // For macOS stack traces, we want to avoid having to parse the compilation unit debug
8469 // info. As long as each debug info file has a path independent of the compilation unit
8470 // directory (DW_AT_comp_dir), then we never have to look at the compilation unit debug
8471 // info. If we provide an absolute path to LLVM here for the compilation unit debug info,
8472 // LLVM will emit DWARF info that depends on DW_AT_comp_dir. To avoid this, we pass "."
8473 // for the compilation unit directory. This forces each debug file to have a directory
8474 // rather than be relative to DW_AT_comp_dir. According to DWARF 5, debug files will
8475 // no longer reference DW_AT_comp_dir, for the purpose of being able to support the
8476 // common practice of stripping all but the line number sections from an executable.
8477 const char *compile_unit_dir = target_os_is_darwin(g->zig_target->os) ? "." :
8478 buf_ptr(&g->root_package->root_src_dir);
8479
8448 ZigLLVMDIFile *compile_unit_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(g->root_out_name),8480 ZigLLVMDIFile *compile_unit_file = ZigLLVMCreateFile(g->dbuilder, buf_ptr(g->root_out_name),
8449 buf_ptr(&g->root_package->root_src_dir));8481 compile_unit_dir);
8450 g->compile_unit = ZigLLVMCreateCompileUnit(g->dbuilder, ZigLLVMLang_DW_LANG_C99(),8482 g->compile_unit = ZigLLVMCreateCompileUnit(g->dbuilder, ZigLLVMLang_DW_LANG_C99(),
8451 compile_unit_file, buf_ptr(producer), is_optimized, flags, runtime_version,8483 compile_unit_file, buf_ptr(producer), is_optimized, flags, runtime_version,
8452 "", 0, !g->strip_debug_symbols);8484 "", 0, !g->strip_debug_symbols);
...@@ -8873,6 +8905,15 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {...@@ -8873,6 +8905,15 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
8873 for (size_t i = 0; i < g->test_fns.length; i += 1) {8905 for (size_t i = 0; i < g->test_fns.length; i += 1) {
8874 ZigFn *test_fn_entry = g->test_fns.at(i);8906 ZigFn *test_fn_entry = g->test_fns.at(i);
88758907
8908 if (fn_is_async(test_fn_entry)) {
8909 ErrorMsg *msg = add_node_error(g, test_fn_entry->proto_node,
8910 buf_create_from_str("test functions cannot be async"));
8911 add_error_note(g, msg, test_fn_entry->proto_node,
8912 buf_sprintf("this restriction may be lifted in the future. See https://github.com/ziglang/zig/issues/3117 for more details"));
8913 add_async_error_notes(g, msg, test_fn_entry);
8914 continue;
8915 }
8916
8876 ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i];8917 ConstExprValue *this_val = &test_fn_array->data.x_array.data.s_none.elements[i];
8877 this_val->special = ConstValSpecialStatic;8918 this_val->special = ConstValSpecialStatic;
8878 this_val->type = struct_type;8919 this_val->type = struct_type;
...@@ -8892,6 +8933,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {...@@ -8892,6 +8933,7 @@ static void create_test_compile_var_and_add_test_runner(CodeGen *g) {
8892 fn_field->data.x_ptr.mut = ConstPtrMutComptimeConst;8933 fn_field->data.x_ptr.mut = ConstPtrMutComptimeConst;
8893 fn_field->data.x_ptr.data.fn.fn_entry = test_fn_entry;8934 fn_field->data.x_ptr.data.fn.fn_entry = test_fn_entry;
8894 }8935 }
8936 report_errors_and_maybe_exit(g);
88958937
8896 ConstExprValue *test_fn_slice = create_const_slice(g, test_fn_array, 0, g->test_fns.length, true);8938 ConstExprValue *test_fn_slice = create_const_slice(g, test_fn_array, 0, g->test_fns.length, true);
88978939
...@@ -9803,6 +9845,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {...@@ -9803,6 +9845,7 @@ static Error check_cache(CodeGen *g, Buf *manifest_dir, Buf *digest) {
9803 cache_list_of_str(ch, g->llvm_argv, g->llvm_argv_len);9845 cache_list_of_str(ch, g->llvm_argv, g->llvm_argv_len);
9804 cache_list_of_str(ch, g->clang_argv, g->clang_argv_len);9846 cache_list_of_str(ch, g->clang_argv, g->clang_argv_len);
9805 cache_list_of_str(ch, g->lib_dirs.items, g->lib_dirs.length);9847 cache_list_of_str(ch, g->lib_dirs.items, g->lib_dirs.length);
9848 cache_list_of_str(ch, g->framework_dirs.items, g->framework_dirs.length);
9806 if (g->libc) {9849 if (g->libc) {
9807 cache_buf(ch, &g->libc->include_dir);9850 cache_buf(ch, &g->libc->include_dir);
9808 cache_buf(ch, &g->libc->sys_include_dir);9851 cache_buf(ch, &g->libc->sys_include_dir);
src/ir.cpp+61-37
...@@ -330,6 +330,8 @@ static bool ir_should_inline(IrExecutable *exec, Scope *scope) {...@@ -330,6 +330,8 @@ static bool ir_should_inline(IrExecutable *exec, Scope *scope) {
330 while (scope != nullptr) {330 while (scope != nullptr) {
331 if (scope->id == ScopeIdCompTime)331 if (scope->id == ScopeIdCompTime)
332 return true;332 return true;
333 if (scope->id == ScopeIdTypeOf)
334 return false;
333 if (scope->id == ScopeIdFnDef)335 if (scope->id == ScopeIdFnDef)
334 break;336 break;
335 scope = scope->parent;337 scope = scope->parent;
...@@ -14837,6 +14839,12 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in...@@ -14837,6 +14839,12 @@ static IrInstruction *ir_analyze_alloca(IrAnalyze *ira, IrInstruction *source_in
14837 if (align != 0) {14839 if (align != 0) {
14838 if ((err = type_resolve(ira->codegen, var_type, ResolveStatusAlignmentKnown)))14840 if ((err = type_resolve(ira->codegen, var_type, ResolveStatusAlignmentKnown)))
14839 return ira->codegen->invalid_instruction;14841 return ira->codegen->invalid_instruction;
14842 if (!type_has_bits(var_type)) {
14843 ir_add_error(ira, source_inst,
14844 buf_sprintf("variable '%s' of zero-bit type '%s' has no in-memory representation, it cannot be aligned",
14845 name_hint, buf_ptr(&var_type->name)));
14846 return ira->codegen->invalid_instruction;
14847 }
14840 }14848 }
14841 assert(result->base.value.data.x_ptr.special != ConstPtrSpecialInvalid);14849 assert(result->base.value.data.x_ptr.special != ConstPtrSpecialInvalid);
1484214850
...@@ -15648,6 +15656,32 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -15648,6 +15656,32 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
15648 return &store_ptr->base;15656 return &store_ptr->base;
15649}15657}
1565015658
15659static IrInstruction *analyze_casted_new_stack(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,
15660 ZigFn *fn_entry)
15661{
15662 if (call_instruction->new_stack == nullptr)
15663 return nullptr;
15664
15665 IrInstruction *new_stack = call_instruction->new_stack->child;
15666 if (type_is_invalid(new_stack->value.type))
15667 return ira->codegen->invalid_instruction;
15668
15669 if (call_instruction->is_async_call_builtin &&
15670 fn_entry != nullptr && new_stack->value.type->id == ZigTypeIdPointer &&
15671 new_stack->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame)
15672 {
15673 ZigType *needed_frame_type = get_pointer_to_type(ira->codegen,
15674 get_fn_frame_type(ira->codegen, fn_entry), false);
15675 return ir_implicit_cast(ira, new_stack, needed_frame_type);
15676 } else {
15677 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
15678 false, false, PtrLenUnknown, target_fn_align(ira->codegen->zig_target), 0, 0, false);
15679 ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
15680 ira->codegen->need_frame_size_prefix_data = true;
15681 return ir_implicit_cast(ira, new_stack, u8_slice);
15682 }
15683}
15684
15651static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,15685static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction,
15652 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,15686 ZigFn *fn_entry, ZigType *fn_type, IrInstruction *fn_ref,
15653 IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)15687 IrInstruction *first_arg_ptr, bool comptime_fn_call, FnInline fn_inline)
...@@ -15826,31 +15860,6 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -15826,31 +15860,6 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
15826 return ir_finish_anal(ira, new_instruction);15860 return ir_finish_anal(ira, new_instruction);
15827 }15861 }
1582815862
15829 IrInstruction *casted_new_stack = nullptr;
15830 if (call_instruction->new_stack != nullptr) {
15831 IrInstruction *new_stack = call_instruction->new_stack->child;
15832 if (type_is_invalid(new_stack->value.type))
15833 return ira->codegen->invalid_instruction;
15834
15835 if (call_instruction->is_async_call_builtin &&
15836 fn_entry != nullptr && new_stack->value.type->id == ZigTypeIdPointer &&
15837 new_stack->value.type->data.pointer.child_type->id == ZigTypeIdFnFrame)
15838 {
15839 ZigType *needed_frame_type = get_pointer_to_type(ira->codegen,
15840 get_fn_frame_type(ira->codegen, fn_entry), false);
15841 casted_new_stack = ir_implicit_cast(ira, new_stack, needed_frame_type);
15842 if (type_is_invalid(casted_new_stack->value.type))
15843 return ira->codegen->invalid_instruction;
15844 } else {
15845 ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
15846 false, false, PtrLenUnknown, target_fn_align(ira->codegen->zig_target), 0, 0, false);
15847 ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr);
15848 casted_new_stack = ir_implicit_cast(ira, new_stack, u8_slice);
15849 if (type_is_invalid(casted_new_stack->value.type))
15850 return ira->codegen->invalid_instruction;
15851 }
15852 }
15853
15854 if (fn_type->data.fn.is_generic) {15863 if (fn_type->data.fn.is_generic) {
15855 if (!fn_entry) {15864 if (!fn_entry) {
15856 ir_add_error(ira, call_instruction->fn_ref,15865 ir_add_error(ira, call_instruction->fn_ref,
...@@ -16063,6 +16072,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -16063,6 +16072,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
16063 parent_fn_entry->calls_or_awaits_errorable_fn = true;16072 parent_fn_entry->calls_or_awaits_errorable_fn = true;
16064 }16073 }
1606516074
16075 IrInstruction *casted_new_stack = analyze_casted_new_stack(ira, call_instruction, impl_fn);
16076 if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value.type))
16077 return ira->codegen->invalid_instruction;
16078
16066 size_t impl_param_count = impl_fn_type_id->param_count;16079 size_t impl_param_count = impl_fn_type_id->param_count;
16067 if (call_instruction->is_async) {16080 if (call_instruction->is_async) {
16068 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,16081 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, impl_fn, impl_fn->type_entry,
...@@ -16071,11 +16084,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -16071,11 +16084,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
16071 }16084 }
1607216085
16073 IrInstruction *result_loc;16086 IrInstruction *result_loc;
16074 if (call_instruction->is_async_call_builtin) {16087 if (handle_is_ptr(impl_fn_type_id->return_type)) {
16075 result_loc = get_async_call_result_loc(ira, call_instruction, impl_fn_type_id->return_type);
16076 if (result_loc != nullptr && type_is_invalid(result_loc->value.type))
16077 return ira->codegen->invalid_instruction;
16078 } else if (handle_is_ptr(impl_fn_type_id->return_type)) {
16079 result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,16088 result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
16080 impl_fn_type_id->return_type, nullptr, true, true, false);16089 impl_fn_type_id->return_type, nullptr, true, true, false);
16081 if (result_loc != nullptr) {16090 if (result_loc != nullptr) {
...@@ -16087,6 +16096,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -16087,6 +16096,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
16087 result_loc = nullptr;16096 result_loc = nullptr;
16088 }16097 }
16089 }16098 }
16099 } else if (call_instruction->is_async_call_builtin) {
16100 result_loc = get_async_call_result_loc(ira, call_instruction, impl_fn_type_id->return_type);
16101 if (result_loc != nullptr && type_is_invalid(result_loc->value.type))
16102 return ira->codegen->invalid_instruction;
16090 } else {16103 } else {
16091 result_loc = nullptr;16104 result_loc = nullptr;
16092 }16105 }
...@@ -16211,6 +16224,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -16211,6 +16224,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
16211 return ira->codegen->invalid_instruction;16224 return ira->codegen->invalid_instruction;
16212 }16225 }
1621316226
16227 IrInstruction *casted_new_stack = analyze_casted_new_stack(ira, call_instruction, fn_entry);
16228 if (casted_new_stack != nullptr && type_is_invalid(casted_new_stack->value.type))
16229 return ira->codegen->invalid_instruction;
16230
16214 if (call_instruction->is_async) {16231 if (call_instruction->is_async) {
16215 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref,16232 IrInstruction *result = ir_analyze_async_call(ira, call_instruction, fn_entry, fn_type, fn_ref,
16216 casted_args, call_param_count, casted_new_stack);16233 casted_args, call_param_count, casted_new_stack);
...@@ -16223,11 +16240,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -16223,11 +16240,7 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
16223 }16240 }
1622416241
16225 IrInstruction *result_loc;16242 IrInstruction *result_loc;
16226 if (call_instruction->is_async_call_builtin) {16243 if (handle_is_ptr(return_type)) {
16227 result_loc = get_async_call_result_loc(ira, call_instruction, return_type);
16228 if (result_loc != nullptr && type_is_invalid(result_loc->value.type))
16229 return ira->codegen->invalid_instruction;
16230 } else if (handle_is_ptr(return_type)) {
16231 result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,16244 result_loc = ir_resolve_result(ira, &call_instruction->base, call_instruction->result_loc,
16232 return_type, nullptr, true, true, false);16245 return_type, nullptr, true, true, false);
16233 if (result_loc != nullptr) {16246 if (result_loc != nullptr) {
...@@ -16239,6 +16252,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c...@@ -16239,6 +16252,10 @@ static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *c
16239 result_loc = nullptr;16252 result_loc = nullptr;
16240 }16253 }
16241 }16254 }
16255 } else if (call_instruction->is_async_call_builtin) {
16256 result_loc = get_async_call_result_loc(ira, call_instruction, return_type);
16257 if (result_loc != nullptr && type_is_invalid(result_loc->value.type))
16258 return ira->codegen->invalid_instruction;
16242 } else {16259 } else {
16243 result_loc = nullptr;16260 result_loc = nullptr;
16244 }16261 }
...@@ -17453,7 +17470,12 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_...@@ -17453,7 +17470,12 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
17453 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,17470 return ir_analyze_container_member_access_inner(ira, bare_type, field_name,
17454 source_instr, container_ptr, container_type);17471 source_instr, container_ptr, container_type);
17455 }17472 }
17456 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field->type_entry,17473
17474 ZigType *field_type = resolve_union_field_type(ira->codegen, field);
17475 if (field_type == nullptr)
17476 return ira->codegen->invalid_instruction;
17477
17478 ZigType *ptr_type = get_pointer_to_type_extra(ira->codegen, field_type,
17457 is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);17479 is_const, is_volatile, PtrLenSingle, 0, 0, 0, false);
17458 if (instr_is_comptime(container_ptr)) {17480 if (instr_is_comptime(container_ptr)) {
17459 ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);17481 ConstExprValue *ptr_val = ir_resolve_const(ira, container_ptr, UndefBad);
...@@ -17470,7 +17492,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_...@@ -17470,7 +17492,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
17470 if (initializing) {17492 if (initializing) {
17471 ConstExprValue *payload_val = create_const_vals(1);17493 ConstExprValue *payload_val = create_const_vals(1);
17472 payload_val->special = ConstValSpecialUndef;17494 payload_val->special = ConstValSpecialUndef;
17473 payload_val->type = field->type_entry;17495 payload_val->type = field_type;
17474 payload_val->parent.id = ConstParentIdUnion;17496 payload_val->parent.id = ConstParentIdUnion;
17475 payload_val->parent.data.p_union.union_val = union_val;17497 payload_val->parent.data.p_union.union_val = union_val;
1747617498
...@@ -22523,6 +22545,8 @@ static IrInstruction *ir_analyze_instruction_frame_size(IrAnalyze *ira, IrInstru...@@ -22523,6 +22545,8 @@ static IrInstruction *ir_analyze_instruction_frame_size(IrAnalyze *ira, IrInstru
22523 return ira->codegen->invalid_instruction;22545 return ira->codegen->invalid_instruction;
22524 }22546 }
2252522547
22548 ira->codegen->need_frame_size_prefix_data = true;
22549
22526 IrInstruction *result = ir_build_frame_size_gen(&ira->new_irb, instruction->base.scope,22550 IrInstruction *result = ir_build_frame_size_gen(&ira->new_irb, instruction->base.scope,
22527 instruction->base.source_node, fn);22551 instruction->base.source_node, fn);
22528 result->value.type = ira->codegen->builtin_types.entry_usize;22552 result->value.type = ira->codegen->builtin_types.entry_usize;
src/link.cpp+6
...@@ -2510,6 +2510,12 @@ static void construct_linker_job_macho(LinkJob *lj) {...@@ -2510,6 +2510,12 @@ static void construct_linker_job_macho(LinkJob *lj) {
2510 lj->args.append("dynamic_lookup");2510 lj->args.append("dynamic_lookup");
2511 }2511 }
25122512
2513 for (size_t i = 0; i < g->framework_dirs.length; i += 1) {
2514 const char *framework_dir = g->framework_dirs.at(i);
2515 lj->args.append("-F");
2516 lj->args.append(framework_dir);
2517 }
2518
2513 for (size_t i = 0; i < g->darwin_frameworks.length; i += 1) {2519 for (size_t i = 0; i < g->darwin_frameworks.length; i += 1) {
2514 lj->args.append("-framework");2520 lj->args.append("-framework");
2515 lj->args.append(buf_ptr(g->darwin_frameworks.at(i)));2521 lj->args.append(buf_ptr(g->darwin_frameworks.at(i)));
src/main.cpp+9
...@@ -104,6 +104,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {...@@ -104,6 +104,7 @@ static int print_full_usage(const char *arg0, FILE *file, int return_code) {
104 " -rdynamic add all symbols to the dynamic symbol table\n"104 " -rdynamic add all symbols to the dynamic symbol table\n"
105 " -rpath [path] add directory to the runtime library search path\n"105 " -rpath [path] add directory to the runtime library search path\n"
106 " --subsystem [subsystem] (windows) /SUBSYSTEM:<subsystem> to the linker\n"106 " --subsystem [subsystem] (windows) /SUBSYSTEM:<subsystem> to the linker\n"
107 " -F[dir] (darwin) add search path for frameworks\n"
107 " -framework [name] (darwin) link against framework\n"108 " -framework [name] (darwin) link against framework\n"
108 " -mios-version-min [ver] (darwin) set iOS deployment target\n"109 " -mios-version-min [ver] (darwin) set iOS deployment target\n"
109 " -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target\n"110 " -mmacosx-version-min [ver] (darwin) set Mac OS X deployment target\n"
...@@ -454,6 +455,7 @@ int main(int argc, char **argv) {...@@ -454,6 +455,7 @@ int main(int argc, char **argv) {
454 ZigList<const char *> lib_dirs = {0};455 ZigList<const char *> lib_dirs = {0};
455 ZigList<const char *> link_libs = {0};456 ZigList<const char *> link_libs = {0};
456 ZigList<const char *> forbidden_link_libs = {0};457 ZigList<const char *> forbidden_link_libs = {0};
458 ZigList<const char *> framework_dirs = {0};
457 ZigList<const char *> frameworks = {0};459 ZigList<const char *> frameworks = {0};
458 bool have_libc = false;460 bool have_libc = false;
459 const char *target_string = nullptr;461 const char *target_string = nullptr;
...@@ -686,6 +688,8 @@ int main(int argc, char **argv) {...@@ -686,6 +688,8 @@ int main(int argc, char **argv) {
686 } else if (arg[1] == 'L' && arg[2] != 0) {688 } else if (arg[1] == 'L' && arg[2] != 0) {
687 // alias for --library-path689 // alias for --library-path
688 lib_dirs.append(&arg[2]);690 lib_dirs.append(&arg[2]);
691 } else if (arg[1] == 'F' && arg[2] != 0) {
692 framework_dirs.append(&arg[2]);
689 } else if (strcmp(arg, "--pkg-begin") == 0) {693 } else if (strcmp(arg, "--pkg-begin") == 0) {
690 if (i + 2 >= argc) {694 if (i + 2 >= argc) {
691 fprintf(stderr, "Expected 2 arguments after --pkg-begin\n");695 fprintf(stderr, "Expected 2 arguments after --pkg-begin\n");
...@@ -772,6 +776,8 @@ int main(int argc, char **argv) {...@@ -772,6 +776,8 @@ int main(int argc, char **argv) {
772 main_pkg_path = buf_create_from_str(argv[i]);776 main_pkg_path = buf_create_from_str(argv[i]);
773 } else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) {777 } else if (strcmp(arg, "--library-path") == 0 || strcmp(arg, "-L") == 0) {
774 lib_dirs.append(argv[i]);778 lib_dirs.append(argv[i]);
779 } else if (strcmp(arg, "-F") == 0) {
780 framework_dirs.append(argv[i]);
775 } else if (strcmp(arg, "--library") == 0) {781 } else if (strcmp(arg, "--library") == 0) {
776 if (strcmp(argv[i], "c") == 0)782 if (strcmp(argv[i], "c") == 0)
777 have_libc = true;783 have_libc = true;
...@@ -1153,6 +1159,9 @@ int main(int argc, char **argv) {...@@ -1153,6 +1159,9 @@ int main(int argc, char **argv) {
1153 for (size_t i = 0; i < lib_dirs.length; i += 1) {1159 for (size_t i = 0; i < lib_dirs.length; i += 1) {
1154 codegen_add_lib_dir(g, lib_dirs.at(i));1160 codegen_add_lib_dir(g, lib_dirs.at(i));
1155 }1161 }
1162 for (size_t i = 0; i < framework_dirs.length; i += 1) {
1163 g->framework_dirs.append(framework_dirs.at(i));
1164 }
1156 for (size_t i = 0; i < link_libs.length; i += 1) {1165 for (size_t i = 0; i < link_libs.length; i += 1) {
1157 LinkLib *link_lib = codegen_add_link_lib(g, buf_create_from_str(link_libs.at(i)));1166 LinkLib *link_lib = codegen_add_link_lib(g, buf_create_from_str(link_libs.at(i)));
1158 link_lib->provided_explicitly = true;1167 link_lib->provided_explicitly = true;
src/zig_llvm.cpp+1
...@@ -842,6 +842,7 @@ const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch) {...@@ -842,6 +842,7 @@ const char *ZigLLVMGetSubArchTypeName(ZigLLVM_SubArchType sub_arch) {
842842
843void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module) {843void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module) {
844 unwrap(module)->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION);844 unwrap(module)->addModuleFlag(Module::Warning, "Debug Info Version", DEBUG_METADATA_VERSION);
845 unwrap(module)->addModuleFlag(Module::Warning, "Dwarf Version", 4);
845}846}
846847
847void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module) {848void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module) {
std/buf_map.zig+2-2
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("std.zig");1const std = @import("std.zig");
2const HashMap = std.HashMap;2const StringHashMap = std.StringHashMap;
3const mem = std.mem;3const mem = std.mem;
4const Allocator = mem.Allocator;4const Allocator = mem.Allocator;
5const testing = std.testing;5const testing = std.testing;
...@@ -9,7 +9,7 @@ const testing = std.testing;...@@ -9,7 +9,7 @@ const testing = std.testing;
9pub const BufMap = struct {9pub const BufMap = struct {
10 hash_map: BufMapHashMap,10 hash_map: BufMapHashMap,
1111
12 const BufMapHashMap = HashMap([]const u8, []const u8, mem.hash_slice_u8, mem.eql_slice_u8);12 const BufMapHashMap = StringHashMap([]const u8);
1313
14 pub fn init(allocator: *Allocator) BufMap {14 pub fn init(allocator: *Allocator) BufMap {
15 var self = BufMap{ .hash_map = BufMapHashMap.init(allocator) };15 var self = BufMap{ .hash_map = BufMapHashMap.init(allocator) };
std/buf_set.zig+2-2
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1const std = @import("std.zig");1const std = @import("std.zig");
2const HashMap = @import("hash_map.zig").HashMap;2const StringHashMap = std.StringHashMap;
3const mem = @import("mem.zig");3const mem = @import("mem.zig");
4const Allocator = mem.Allocator;4const Allocator = mem.Allocator;
5const testing = std.testing;5const testing = std.testing;
...@@ -7,7 +7,7 @@ const testing = std.testing;...@@ -7,7 +7,7 @@ const testing = std.testing;
7pub const BufSet = struct {7pub const BufSet = struct {
8 hash_map: BufSetHashMap,8 hash_map: BufSetHashMap,
99
10 const BufSetHashMap = HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8);10 const BufSetHashMap = StringHashMap(void);
1111
12 pub fn init(a: *Allocator) BufSet {12 pub fn init(a: *Allocator) BufSet {
13 var self = BufSet{ .hash_map = BufSetHashMap.init(a) };13 var self = BufSet{ .hash_map = BufSetHashMap.init(a) };
std/build.zig+34-19
...@@ -4,10 +4,11 @@ const io = std.io;...@@ -4,10 +4,11 @@ const io = std.io;
4const fs = std.fs;4const fs = std.fs;
5const mem = std.mem;5const mem = std.mem;
6const debug = std.debug;6const debug = std.debug;
7const panic = std.debug.panic;
7const assert = debug.assert;8const assert = debug.assert;
8const warn = std.debug.warn;9const warn = std.debug.warn;
9const ArrayList = std.ArrayList;10const ArrayList = std.ArrayList;
10const HashMap = std.HashMap;11const StringHashMap = std.StringHashMap;
11const Allocator = mem.Allocator;12const Allocator = mem.Allocator;
12const process = std.process;13const process = std.process;
13const BufSet = std.BufSet;14const BufSet = std.BufSet;
...@@ -42,8 +43,8 @@ pub const Builder = struct {...@@ -42,8 +43,8 @@ pub const Builder = struct {
42 top_level_steps: ArrayList(*TopLevelStep),43 top_level_steps: ArrayList(*TopLevelStep),
43 install_prefix: ?[]const u8,44 install_prefix: ?[]const u8,
44 dest_dir: ?[]const u8,45 dest_dir: ?[]const u8,
45 lib_dir: ?[]const u8,46 lib_dir: []const u8,
46 exe_dir: ?[]const u8,47 exe_dir: []const u8,
47 install_path: []const u8,48 install_path: []const u8,
48 search_prefixes: ArrayList([]const u8),49 search_prefixes: ArrayList([]const u8),
49 installed_files: ArrayList(InstalledFile),50 installed_files: ArrayList(InstalledFile),
...@@ -60,8 +61,8 @@ pub const Builder = struct {...@@ -60,8 +61,8 @@ pub const Builder = struct {
60 C11,61 C11,
61 };62 };
6263
63 const UserInputOptionsMap = HashMap([]const u8, UserInputOption, mem.hash_slice_u8, mem.eql_slice_u8);64 const UserInputOptionsMap = StringHashMap(UserInputOption);
64 const AvailableOptionsMap = HashMap([]const u8, AvailableOption, mem.hash_slice_u8, mem.eql_slice_u8);65 const AvailableOptionsMap = StringHashMap(AvailableOption);
6566
66 const AvailableOption = struct {67 const AvailableOption = struct {
67 name: []const u8,68 name: []const u8,
...@@ -129,8 +130,8 @@ pub const Builder = struct {...@@ -129,8 +130,8 @@ pub const Builder = struct {
129 .env_map = env_map,130 .env_map = env_map,
130 .search_prefixes = ArrayList([]const u8).init(allocator),131 .search_prefixes = ArrayList([]const u8).init(allocator),
131 .install_prefix = null,132 .install_prefix = null,
132 .lib_dir = null,133 .lib_dir = undefined,
133 .exe_dir = null,134 .exe_dir = undefined,
134 .dest_dir = env_map.get("DESTDIR"),135 .dest_dir = env_map.get("DESTDIR"),
135 .installed_files = ArrayList(InstalledFile).init(allocator),136 .installed_files = ArrayList(InstalledFile).init(allocator),
136 .install_tls = TopLevelStep{137 .install_tls = TopLevelStep{
...@@ -163,11 +164,13 @@ pub const Builder = struct {...@@ -163,11 +164,13 @@ pub const Builder = struct {
163 self.allocator.destroy(self);164 self.allocator.destroy(self);
164 }165 }
165166
167 /// This function is intended to be called by std/special/build_runner.zig, not a build.zig file.
166 pub fn setInstallPrefix(self: *Builder, optional_prefix: ?[]const u8) void {168 pub fn setInstallPrefix(self: *Builder, optional_prefix: ?[]const u8) void {
167 self.install_prefix = optional_prefix;169 self.install_prefix = optional_prefix;
168 }170 }
169171
170 fn resolveInstallPrefix(self: *Builder) void {172 /// This function is intended to be called by std/special/build_runner.zig, not a build.zig file.
173 pub fn resolveInstallPrefix(self: *Builder) void {
171 if (self.dest_dir) |dest_dir| {174 if (self.dest_dir) |dest_dir| {
172 const install_prefix = self.install_prefix orelse "/usr";175 const install_prefix = self.install_prefix orelse "/usr";
173 self.install_path = fs.path.join(self.allocator, [_][]const u8{ dest_dir, install_prefix }) catch unreachable;176 self.install_path = fs.path.join(self.allocator, [_][]const u8{ dest_dir, install_prefix }) catch unreachable;
...@@ -437,7 +440,7 @@ pub const Builder = struct {...@@ -437,7 +440,7 @@ pub const Builder = struct {
437 .description = description,440 .description = description,
438 };441 };
439 if ((self.available_options_map.put(name, available_option) catch unreachable) != null) {442 if ((self.available_options_map.put(name, available_option) catch unreachable) != null) {
440 debug.panic("Option '{}' declared twice", name);443 panic("Option '{}' declared twice", name);
441 }444 }
442 self.available_options_list.append(available_option) catch unreachable;445 self.available_options_list.append(available_option) catch unreachable;
443446
...@@ -463,8 +466,8 @@ pub const Builder = struct {...@@ -463,8 +466,8 @@ pub const Builder = struct {
463 return null;466 return null;
464 },467 },
465 },468 },
466 TypeId.Int => debug.panic("TODO integer options to build script"),469 TypeId.Int => panic("TODO integer options to build script"),
467 TypeId.Float => debug.panic("TODO float options to build script"),470 TypeId.Float => panic("TODO float options to build script"),
468 TypeId.String => switch (entry.value.value) {471 TypeId.String => switch (entry.value.value) {
469 UserValue.Flag => {472 UserValue.Flag => {
470 warn("Expected -D{} to be a string, but received a boolean.\n", name);473 warn("Expected -D{} to be a string, but received a boolean.\n", name);
...@@ -478,7 +481,7 @@ pub const Builder = struct {...@@ -478,7 +481,7 @@ pub const Builder = struct {
478 },481 },
479 UserValue.Scalar => |s| return s,482 UserValue.Scalar => |s| return s,
480 },483 },
481 TypeId.List => debug.panic("TODO list options to build script"),484 TypeId.List => panic("TODO list options to build script"),
482 }485 }
483 }486 }
484487
...@@ -644,8 +647,6 @@ pub const Builder = struct {...@@ -644,8 +647,6 @@ pub const Builder = struct {
644 }647 }
645648
646 pub fn validateUserInputDidItFail(self: *Builder) bool {649 pub fn validateUserInputDidItFail(self: *Builder) bool {
647 self.resolveInstallPrefix();
648
649 // make sure all args are used650 // make sure all args are used
650 var it = self.user_input_options.iterator();651 var it = self.user_input_options.iterator();
651 while (true) {652 while (true) {
...@@ -855,7 +856,7 @@ pub const Builder = struct {...@@ -855,7 +856,7 @@ pub const Builder = struct {
855 var stdout_file_in_stream = child.stdout.?.inStream();856 var stdout_file_in_stream = child.stdout.?.inStream();
856 try stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size);857 try stdout_file_in_stream.stream.readAllBuffer(&stdout, max_output_size);
857858
858 const term = child.wait() catch |err| std.debug.panic("unable to spawn {}: {}", argv[0], err);859 const term = child.wait() catch |err| panic("unable to spawn {}: {}", argv[0], err);
859 switch (term) {860 switch (term) {
860 .Exited => |code| {861 .Exited => |code| {
861 if (code != 0) {862 if (code != 0) {
...@@ -882,8 +883,8 @@ pub const Builder = struct {...@@ -882,8 +883,8 @@ pub const Builder = struct {
882 fn getInstallPath(self: *Builder, dir: InstallDir, dest_rel_path: []const u8) []const u8 {883 fn getInstallPath(self: *Builder, dir: InstallDir, dest_rel_path: []const u8) []const u8 {
883 const base_dir = switch (dir) {884 const base_dir = switch (dir) {
884 .Prefix => self.install_path,885 .Prefix => self.install_path,
885 .Bin => self.exe_dir.?,886 .Bin => self.exe_dir,
886 .Lib => self.lib_dir.?,887 .Lib => self.lib_dir,
887 };888 };
888 return fs.path.resolve(889 return fs.path.resolve(
889 self.allocator,890 self.allocator,
...@@ -1228,6 +1229,7 @@ pub const LibExeObjStep = struct {...@@ -1228,6 +1229,7 @@ pub const LibExeObjStep = struct {
1228 name_only_filename: []const u8,1229 name_only_filename: []const u8,
1229 strip: bool,1230 strip: bool,
1230 lib_paths: ArrayList([]const u8),1231 lib_paths: ArrayList([]const u8),
1232 framework_dirs: ArrayList([]const u8),
1231 frameworks: BufSet,1233 frameworks: BufSet,
1232 verbose_link: bool,1234 verbose_link: bool,
1233 verbose_cc: bool,1235 verbose_cc: bool,
...@@ -1317,6 +1319,9 @@ pub const LibExeObjStep = struct {...@@ -1317,6 +1319,9 @@ pub const LibExeObjStep = struct {
1317 }1319 }
13181320
1319 fn initExtraArgs(builder: *Builder, name: []const u8, root_src: ?[]const u8, kind: Kind, is_dynamic: bool, ver: Version) LibExeObjStep {1321 fn initExtraArgs(builder: *Builder, name: []const u8, root_src: ?[]const u8, kind: Kind, is_dynamic: bool, ver: Version) LibExeObjStep {
1322 if (mem.indexOf(u8, name, "/") != null or mem.indexOf(u8, name, "\\") != null) {
1323 panic("invalid name: '{}'. It looks like a file path, but it is supposed to be the library or application name.", name);
1324 }
1320 var self = LibExeObjStep{1325 var self = LibExeObjStep{
1321 .strip = false,1326 .strip = false,
1322 .builder = builder,1327 .builder = builder,
...@@ -1341,6 +1346,7 @@ pub const LibExeObjStep = struct {...@@ -1341,6 +1346,7 @@ pub const LibExeObjStep = struct {
1341 .include_dirs = ArrayList(IncludeDir).init(builder.allocator),1346 .include_dirs = ArrayList(IncludeDir).init(builder.allocator),
1342 .link_objects = ArrayList(LinkObject).init(builder.allocator),1347 .link_objects = ArrayList(LinkObject).init(builder.allocator),
1343 .lib_paths = ArrayList([]const u8).init(builder.allocator),1348 .lib_paths = ArrayList([]const u8).init(builder.allocator),
1349 .framework_dirs = ArrayList([]const u8).init(builder.allocator),
1344 .object_src = undefined,1350 .object_src = undefined,
1345 .build_options_contents = std.Buffer.initSize(builder.allocator, 0) catch unreachable,1351 .build_options_contents = std.Buffer.initSize(builder.allocator, 0) catch unreachable,
1346 .c_std = Builder.CStd.C99,1352 .c_std = Builder.CStd.C99,
...@@ -1614,6 +1620,10 @@ pub const LibExeObjStep = struct {...@@ -1614,6 +1620,10 @@ pub const LibExeObjStep = struct {
1614 self.lib_paths.append(path) catch unreachable;1620 self.lib_paths.append(path) catch unreachable;
1615 }1621 }
16161622
1623 pub fn addFrameworkDir(self: *LibExeObjStep, dir_path: []const u8) void {
1624 self.framework_dirs.append(dir_path) catch unreachable;
1625 }
1626
1617 pub fn addPackagePath(self: *LibExeObjStep, name: []const u8, pkg_index_path: []const u8) void {1627 pub fn addPackagePath(self: *LibExeObjStep, name: []const u8, pkg_index_path: []const u8) void {
1618 self.packages.append(Pkg{1628 self.packages.append(Pkg{
1619 .name = name,1629 .name = name,
...@@ -1860,8 +1870,8 @@ pub const LibExeObjStep = struct {...@@ -1860,8 +1870,8 @@ pub const LibExeObjStep = struct {
1860 }1870 }
18611871
1862 for (self.lib_paths.toSliceConst()) |lib_path| {1872 for (self.lib_paths.toSliceConst()) |lib_path| {
1863 zig_args.append("--library-path") catch unreachable;1873 try zig_args.append("-L");
1864 zig_args.append(lib_path) catch unreachable;1874 try zig_args.append(lib_path);
1865 }1875 }
18661876
1867 if (self.need_system_paths and self.target == Target.Native) {1877 if (self.need_system_paths and self.target == Target.Native) {
...@@ -1882,6 +1892,11 @@ pub const LibExeObjStep = struct {...@@ -1882,6 +1892,11 @@ pub const LibExeObjStep = struct {
1882 }1892 }
18831893
1884 if (self.target.isDarwin()) {1894 if (self.target.isDarwin()) {
1895 for (self.framework_dirs.toSliceConst()) |dir| {
1896 try zig_args.append("-F");
1897 try zig_args.append(dir);
1898 }
1899
1885 var it = self.frameworks.iterator();1900 var it = self.frameworks.iterator();
1886 while (it.next()) |entry| {1901 while (it.next()) |entry| {
1887 zig_args.append("-framework") catch unreachable;1902 zig_args.append("-framework") catch unreachable;
std/fmt/parse_float.zig+11-3
...@@ -110,9 +110,7 @@ fn convertRepr(comptime T: type, n: FloatRepr) T {...@@ -110,9 +110,7 @@ fn convertRepr(comptime T: type, n: FloatRepr) T {
110 q.shiftLeft1(s); // q = p << 1110 q.shiftLeft1(s); // q = p << 1
111 r.shiftLeft1(q); // r = p << 2111 r.shiftLeft1(q); // r = p << 2
112 s.shiftLeft1(r); // p = p << 3112 s.shiftLeft1(r); // p = p << 3
113 q.add(s); // p = (p << 3) + (p << 1)113 s.add(q); // p = (p << 3) + (p << 1)
114
115 exp -= 1;
116114
117 while (s.d2 & mask28 != 0) {115 while (s.d2 & mask28 != 0) {
118 q.shiftRight1(s);116 q.shiftRight1(s);
...@@ -402,6 +400,13 @@ test "fmt.parseFloat" {...@@ -402,6 +400,13 @@ test "fmt.parseFloat" {
402 expectEqual((try parseFloat(T, "+0")), 0.0);400 expectEqual((try parseFloat(T, "+0")), 0.0);
403 expectEqual((try parseFloat(T, "-0")), 0.0);401 expectEqual((try parseFloat(T, "-0")), 0.0);
404402
403 expectEqual((try parseFloat(T, "0e0")), 0);
404 expectEqual((try parseFloat(T, "2e3")), 2000.0);
405 expectEqual((try parseFloat(T, "1e0")), 1.0);
406 expectEqual((try parseFloat(T, "-2e3")), -2000.0);
407 expectEqual((try parseFloat(T, "-1e0")), -1.0);
408 expectEqual((try parseFloat(T, "1.234e3")), 1234);
409
405 expect(approxEq(T, try parseFloat(T, "3.141"), 3.141, epsilon));410 expect(approxEq(T, try parseFloat(T, "3.141"), 3.141, epsilon));
406 expect(approxEq(T, try parseFloat(T, "-3.141"), -3.141, epsilon));411 expect(approxEq(T, try parseFloat(T, "-3.141"), -3.141, epsilon));
407412
...@@ -413,6 +418,9 @@ test "fmt.parseFloat" {...@@ -413,6 +418,9 @@ test "fmt.parseFloat" {
413 expectEqual((try parseFloat(T, "-INF")), -std.math.inf(T));418 expectEqual((try parseFloat(T, "-INF")), -std.math.inf(T));
414419
415 if (T != f16) {420 if (T != f16) {
421 expect(approxEq(T, try parseFloat(T, "1e-2"), 0.01, epsilon));
422 expect(approxEq(T, try parseFloat(T, "1234e-2"), 12.34, epsilon));
423
416 expect(approxEq(T, try parseFloat(T, "123142.1"), 123142.1, epsilon));424 expect(approxEq(T, try parseFloat(T, "123142.1"), 123142.1, epsilon));
417 expect(approxEq(T, try parseFloat(T, "-123142.1124"), T(-123142.1124), epsilon));425 expect(approxEq(T, try parseFloat(T, "-123142.1124"), T(-123142.1124), epsilon));
418 expect(approxEq(T, try parseFloat(T, "0.7062146892655368"), T(0.7062146892655368), epsilon));426 expect(approxEq(T, try parseFloat(T, "0.7062146892655368"), T(0.7062146892655368), epsilon));
std/hash_map.zig+1-3
...@@ -23,9 +23,7 @@ pub fn StringHashMap(comptime V: type) type {...@@ -23,9 +23,7 @@ pub fn StringHashMap(comptime V: type) type {
23}23}
2424
25pub fn eqlString(a: []const u8, b: []const u8) bool {25pub fn eqlString(a: []const u8, b: []const u8) bool {
26 if (a.len != b.len) return false;26 return mem.eql(u8, a, b);
27 if (a.ptr == b.ptr) return true;
28 return mem.compare(u8, a, b) == .Equal;
29}27}
3028
31pub fn hashString(s: []const u8) u32 {29pub fn hashString(s: []const u8) u32 {
std/json.zig+2-2
...@@ -989,7 +989,7 @@ test "json.validate" {...@@ -989,7 +989,7 @@ test "json.validate" {
989const Allocator = std.mem.Allocator;989const Allocator = std.mem.Allocator;
990const ArenaAllocator = std.heap.ArenaAllocator;990const ArenaAllocator = std.heap.ArenaAllocator;
991const ArrayList = std.ArrayList;991const ArrayList = std.ArrayList;
992const HashMap = std.HashMap;992const StringHashMap = std.StringHashMap;
993993
994pub const ValueTree = struct {994pub const ValueTree = struct {
995 arena: ArenaAllocator,995 arena: ArenaAllocator,
...@@ -1000,7 +1000,7 @@ pub const ValueTree = struct {...@@ -1000,7 +1000,7 @@ pub const ValueTree = struct {
1000 }1000 }
1001};1001};
10021002
1003pub const ObjectMap = HashMap([]const u8, Value, mem.hash_slice_u8, mem.eql_slice_u8);1003pub const ObjectMap = StringHashMap(Value);
10041004
1005pub const Value = union(enum) {1005pub const Value = union(enum) {
1006 Null,1006 Null,
std/mem.zig+13-25
...@@ -339,6 +339,7 @@ test "mem.lessThan" {...@@ -339,6 +339,7 @@ test "mem.lessThan" {
339/// Compares two slices and returns whether they are equal.339/// Compares two slices and returns whether they are equal.
340pub fn eql(comptime T: type, a: []const T, b: []const T) bool {340pub fn eql(comptime T: type, a: []const T, b: []const T) bool {
341 if (a.len != b.len) return false;341 if (a.len != b.len) return false;
342 if (a.ptr == b.ptr) return true;
342 for (a) |item, index| {343 for (a) |item, index| {
343 if (b[index] != item) return false;344 if (b[index] != item) return false;
344 }345 }
...@@ -738,47 +739,34 @@ test "writeIntBig and writeIntLittle" {...@@ -738,47 +739,34 @@ test "writeIntBig and writeIntLittle" {
738 var buf9: [9]u8 = undefined;739 var buf9: [9]u8 = undefined;
739740
740 writeIntBig(u0, &buf0, 0x0);741 writeIntBig(u0, &buf0, 0x0);
741 testing.expect(eql_slice_u8(buf0[0..], [_]u8{}));742 testing.expect(eql(u8, buf0[0..], [_]u8{}));
742 writeIntLittle(u0, &buf0, 0x0);743 writeIntLittle(u0, &buf0, 0x0);
743 testing.expect(eql_slice_u8(buf0[0..], [_]u8{}));744 testing.expect(eql(u8, buf0[0..], [_]u8{}));
744745
745 writeIntBig(u8, &buf1, 0x12);746 writeIntBig(u8, &buf1, 0x12);
746 testing.expect(eql_slice_u8(buf1[0..], [_]u8{0x12}));747 testing.expect(eql(u8, buf1[0..], [_]u8{0x12}));
747 writeIntLittle(u8, &buf1, 0x34);748 writeIntLittle(u8, &buf1, 0x34);
748 testing.expect(eql_slice_u8(buf1[0..], [_]u8{0x34}));749 testing.expect(eql(u8, buf1[0..], [_]u8{0x34}));
749750
750 writeIntBig(u16, &buf2, 0x1234);751 writeIntBig(u16, &buf2, 0x1234);
751 testing.expect(eql_slice_u8(buf2[0..], [_]u8{ 0x12, 0x34 }));752 testing.expect(eql(u8, buf2[0..], [_]u8{ 0x12, 0x34 }));
752 writeIntLittle(u16, &buf2, 0x5678);753 writeIntLittle(u16, &buf2, 0x5678);
753 testing.expect(eql_slice_u8(buf2[0..], [_]u8{ 0x78, 0x56 }));754 testing.expect(eql(u8, buf2[0..], [_]u8{ 0x78, 0x56 }));
754755
755 writeIntBig(u72, &buf9, 0x123456789abcdef024);756 writeIntBig(u72, &buf9, 0x123456789abcdef024);
756 testing.expect(eql_slice_u8(buf9[0..], [_]u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }));757 testing.expect(eql(u8, buf9[0..], [_]u8{ 0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc, 0xde, 0xf0, 0x24 }));
757 writeIntLittle(u72, &buf9, 0xfedcba9876543210ec);758 writeIntLittle(u72, &buf9, 0xfedcba9876543210ec);
758 testing.expect(eql_slice_u8(buf9[0..], [_]u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }));759 testing.expect(eql(u8, buf9[0..], [_]u8{ 0xec, 0x10, 0x32, 0x54, 0x76, 0x98, 0xba, 0xdc, 0xfe }));
759760
760 writeIntBig(i8, &buf1, -1);761 writeIntBig(i8, &buf1, -1);
761 testing.expect(eql_slice_u8(buf1[0..], [_]u8{0xff}));762 testing.expect(eql(u8, buf1[0..], [_]u8{0xff}));
762 writeIntLittle(i8, &buf1, -2);763 writeIntLittle(i8, &buf1, -2);
763 testing.expect(eql_slice_u8(buf1[0..], [_]u8{0xfe}));764 testing.expect(eql(u8, buf1[0..], [_]u8{0xfe}));
764765
765 writeIntBig(i16, &buf2, -3);766 writeIntBig(i16, &buf2, -3);
766 testing.expect(eql_slice_u8(buf2[0..], [_]u8{ 0xff, 0xfd }));767 testing.expect(eql(u8, buf2[0..], [_]u8{ 0xff, 0xfd }));
767 writeIntLittle(i16, &buf2, -4);768 writeIntLittle(i16, &buf2, -4);
768 testing.expect(eql_slice_u8(buf2[0..], [_]u8{ 0xfc, 0xff }));769 testing.expect(eql(u8, buf2[0..], [_]u8{ 0xfc, 0xff }));
769}
770
771pub fn hash_slice_u8(k: []const u8) u32 {
772 // FNV 32-bit hash
773 var h: u32 = 2166136261;
774 for (k) |b| {
775 h = (h ^ b) *% 16777619;
776 }
777 return h;
778}
779
780pub fn eql_slice_u8(a: []const u8, b: []const u8) bool {
781 return eql(u8, a, b);
782}770}
783771
784/// Returns an iterator that iterates over the slices of `buffer` that are not772/// Returns an iterator that iterates over the slices of `buffer` that are not
std/special/build_runner.zig+2
...@@ -123,6 +123,7 @@ pub fn main() !void {...@@ -123,6 +123,7 @@ pub fn main() !void {
123 }123 }
124 }124 }
125125
126 builder.resolveInstallPrefix();
126 try runBuild(builder);127 try runBuild(builder);
127128
128 if (builder.validateUserInputDidItFail())129 if (builder.validateUserInputDidItFail())
...@@ -151,6 +152,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {...@@ -151,6 +152,7 @@ fn usage(builder: *Builder, already_ran_build: bool, out_stream: var) !void {
151 // run the build script to collect the options152 // run the build script to collect the options
152 if (!already_ran_build) {153 if (!already_ran_build) {
153 builder.setInstallPrefix(null);154 builder.setInstallPrefix(null);
155 builder.resolveInstallPrefix();
154 try runBuild(builder);156 try runBuild(builder);
155 }157 }
156158
std/zig/parser_test.zig+88
...@@ -2419,6 +2419,94 @@ test "zig fmt: comment after empty comment" {...@@ -2419,6 +2419,94 @@ test "zig fmt: comment after empty comment" {
2419 );2419 );
2420}2420}
24212421
2422test "zig fmt: line comment in array" {
2423 try testTransform(
2424 \\test "a" {
2425 \\ var arr = [_]u32{
2426 \\ 0
2427 \\ // 1,
2428 \\ // 2,
2429 \\ };
2430 \\}
2431 \\
2432 ,
2433 \\test "a" {
2434 \\ var arr = [_]u32{
2435 \\ 0, // 1,
2436 \\ // 2,
2437 \\ };
2438 \\}
2439 \\
2440 );
2441 try testCanonical(
2442 \\test "a" {
2443 \\ var arr = [_]u32{
2444 \\ 0,
2445 \\ // 1,
2446 \\ // 2,
2447 \\ };
2448 \\}
2449 \\
2450 );
2451}
2452
2453test "zig fmt: comment after params" {
2454 try testTransform(
2455 \\fn a(
2456 \\ b: u32
2457 \\ // c: u32,
2458 \\ // d: u32,
2459 \\) void {}
2460 \\
2461 ,
2462 \\fn a(
2463 \\ b: u32, // c: u32,
2464 \\ // d: u32,
2465 \\) void {}
2466 \\
2467 );
2468 try testCanonical(
2469 \\fn a(
2470 \\ b: u32,
2471 \\ // c: u32,
2472 \\ // d: u32,
2473 \\) void {}
2474 \\
2475 );
2476}
2477
2478test "zig fmt: comment in array initializer/access" {
2479 try testCanonical(
2480 \\test "a" {
2481 \\ var a = x{ //aa
2482 \\ //bb
2483 \\ };
2484 \\ var a = []x{ //aa
2485 \\ //bb
2486 \\ };
2487 \\ var b = [ //aa
2488 \\ _
2489 \\ ]x{ //aa
2490 \\ //bb
2491 \\ 9,
2492 \\ };
2493 \\ var c = b[ //aa
2494 \\ 0
2495 \\ ];
2496 \\ var d = [_
2497 \\ //aa
2498 \\ ]x{ //aa
2499 \\ //bb
2500 \\ 9,
2501 \\ };
2502 \\ var e = d[0
2503 \\ //aa
2504 \\ ];
2505 \\}
2506 \\
2507 );
2508}
2509
2422test "zig fmt: comments at several places in struct init" {2510test "zig fmt: comments at several places in struct init" {
2423 try testTransform(2511 try testTransform(
2424 \\var bar = Bar{2512 \\var bar = Bar{
std/zig/render.zig+34-9
...@@ -483,9 +483,23 @@ fn renderExpression(...@@ -483,9 +483,23 @@ fn renderExpression(
483 },483 },
484484
485 ast.Node.PrefixOp.Op.ArrayType => |array_index| {485 ast.Node.PrefixOp.Op.ArrayType => |array_index| {
486 try renderToken(tree, stream, prefix_op_node.op_token, indent, start_col, Space.None); // [486 const lbracket = prefix_op_node.op_token;
487 try renderExpression(allocator, stream, tree, indent, start_col, array_index, Space.None);487 const rbracket = tree.nextToken(array_index.lastToken());
488 try renderToken(tree, stream, tree.nextToken(array_index.lastToken()), indent, start_col, Space.None); // ]488
489 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
490
491 const starts_with_comment = tree.tokens.at(lbracket + 1).id == .LineComment;
492 const ends_with_comment = tree.tokens.at(rbracket - 1).id == .LineComment;
493 const new_indent = if (ends_with_comment) indent + indent_delta else indent;
494 const new_space = if (ends_with_comment) Space.Newline else Space.None;
495 try renderExpression(allocator, stream, tree, new_indent, start_col, array_index, new_space);
496 if (starts_with_comment) {
497 try stream.writeByte('\n');
498 }
499 if (ends_with_comment or starts_with_comment) {
500 try stream.writeByteNTimes(' ', indent);
501 }
502 try renderToken(tree, stream, rbracket, indent, start_col, Space.None); // ]
489 },503 },
490 ast.Node.PrefixOp.Op.BitNot,504 ast.Node.PrefixOp.Op.BitNot,
491 ast.Node.PrefixOp.Op.BoolNot,505 ast.Node.PrefixOp.Op.BoolNot,
...@@ -580,7 +594,18 @@ fn renderExpression(...@@ -580,7 +594,18 @@ fn renderExpression(
580594
581 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);595 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
582 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [596 try renderToken(tree, stream, lbracket, indent, start_col, Space.None); // [
583 try renderExpression(allocator, stream, tree, indent, start_col, index_expr, Space.None);597
598 const starts_with_comment = tree.tokens.at(lbracket + 1).id == .LineComment;
599 const ends_with_comment = tree.tokens.at(rbracket - 1).id == .LineComment;
600 const new_indent = if (ends_with_comment) indent + indent_delta else indent;
601 const new_space = if (ends_with_comment) Space.Newline else Space.None;
602 try renderExpression(allocator, stream, tree, new_indent, start_col, index_expr, new_space);
603 if (starts_with_comment) {
604 try stream.writeByte('\n');
605 }
606 if (ends_with_comment or starts_with_comment) {
607 try stream.writeByteNTimes(' ', indent);
608 }
584 return renderToken(tree, stream, rbracket, indent, start_col, space); // ]609 return renderToken(tree, stream, rbracket, indent, start_col, space); // ]
585 },610 },
586611
...@@ -615,7 +640,7 @@ fn renderExpression(...@@ -615,7 +640,7 @@ fn renderExpression(
615640
616 if (field_inits.len == 0) {641 if (field_inits.len == 0) {
617 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);642 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
618 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);643 try renderToken(tree, stream, lbrace, indent + indent_delta, start_col, Space.None);
619 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);644 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
620 }645 }
621646
...@@ -714,7 +739,7 @@ fn renderExpression(...@@ -714,7 +739,7 @@ fn renderExpression(
714 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);739 try renderToken(tree, stream, lbrace, indent, start_col, Space.None);
715 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);740 return renderToken(tree, stream, suffix_op.rtoken, indent, start_col, space);
716 }741 }
717 if (exprs.len == 1) {742 if (exprs.len == 1 and tree.tokens.at(exprs.at(0).*.lastToken() + 1).id == .RBrace) {
718 const expr = exprs.at(0).*;743 const expr = exprs.at(0).*;
719744
720 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);745 try renderExpression(allocator, stream, tree, indent, start_col, suffix_op.lhs, Space.None);
...@@ -775,7 +800,7 @@ fn renderExpression(...@@ -775,7 +800,7 @@ fn renderExpression(
775 while (it.next()) |expr| : (i += 1) {800 while (it.next()) |expr| : (i += 1) {
776 counting_stream.bytes_written = 0;801 counting_stream.bytes_written = 0;
777 var dummy_col: usize = 0;802 var dummy_col: usize = 0;
778 try renderExpression(allocator, &counting_stream.stream, tree, 0, &dummy_col, expr.*, Space.None);803 try renderExpression(allocator, &counting_stream.stream, tree, indent, &dummy_col, expr.*, Space.None);
779 const width = @intCast(usize, counting_stream.bytes_written);804 const width = @intCast(usize, counting_stream.bytes_written);
780 const col = i % row_size;805 const col = i % row_size;
781 column_widths[col] = std.math.max(column_widths[col], width);806 column_widths[col] = std.math.max(column_widths[col], width);
...@@ -1191,8 +1216,8 @@ fn renderExpression(...@@ -1191,8 +1216,8 @@ fn renderExpression(
1191 });1216 });
11921217
1193 const src_params_trailing_comma = blk: {1218 const src_params_trailing_comma = blk: {
1194 const maybe_comma = tree.prevToken(rparen);1219 const maybe_comma = tree.tokens.at(rparen - 1).id;
1195 break :blk tree.tokens.at(maybe_comma).id == Token.Id.Comma;1220 break :blk maybe_comma == .Comma or maybe_comma == .LineComment;
1196 };1221 };
11971222
1198 if (!src_params_trailing_comma) {1223 if (!src_params_trailing_comma) {
test/compile_errors.zig+9
...@@ -6462,4 +6462,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -6462,4 +6462,13 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
6462 "tmp.zig:5:30: error: expression value is ignored",6462 "tmp.zig:5:30: error: expression value is ignored",
6463 "tmp.zig:9:30: error: expression value is ignored",6463 "tmp.zig:9:30: error: expression value is ignored",
6464 );6464 );
6465
6466 cases.add(
6467 "aligned variable of zero-bit type",
6468 \\export fn f() void {
6469 \\ var s: struct {} align(4) = undefined;
6470 \\}
6471 ,
6472 "tmp.zig:2:5: error: variable 's' of zero-bit type 'struct:2:12' has no in-memory representation, it cannot be aligned",
6473 );
6465}6474}
test/stack_traces.zig created+274
...@@ -0,0 +1,274 @@
1const builtin = @import("builtin");
2const std = @import("std");
3const os = std.os;
4const tests = @import("tests.zig");
5
6pub fn addCases(cases: *tests.StackTracesContext) void {
7 const source_return =
8 \\const std = @import("std");
9 \\
10 \\pub fn main() !void {
11 \\ return error.TheSkyIsFalling;
12 \\}
13 ;
14 const source_try_return =
15 \\const std = @import("std");
16 \\
17 \\fn foo() !void {
18 \\ return error.TheSkyIsFalling;
19 \\}
20 \\
21 \\pub fn main() !void {
22 \\ try foo();
23 \\}
24 ;
25 const source_try_try_return_return =
26 \\const std = @import("std");
27 \\
28 \\fn foo() !void {
29 \\ try bar();
30 \\}
31 \\
32 \\fn bar() !void {
33 \\ return make_error();
34 \\}
35 \\
36 \\fn make_error() !void {
37 \\ return error.TheSkyIsFalling;
38 \\}
39 \\
40 \\pub fn main() !void {
41 \\ try foo();
42 \\}
43 ;
44 switch (builtin.os) {
45 .linux => {
46 cases.addCase(
47 "return",
48 source_return,
49 [_][]const u8{
50 // debug
51 \\error: TheSkyIsFalling
52 \\source.zig:4:5: [address] in main (test)
53 \\
54 ,
55 // release-safe
56 \\error: TheSkyIsFalling
57 \\source.zig:4:5: [address] in std.special.posixCallMainAndExit (test)
58 \\
59 ,
60 // release-fast
61 \\error: TheSkyIsFalling
62 \\
63 ,
64 // release-small
65 \\error: TheSkyIsFalling
66 \\
67 },
68 );
69 cases.addCase(
70 "try return",
71 source_try_return,
72 [_][]const u8{
73 // debug
74 \\error: TheSkyIsFalling
75 \\source.zig:4:5: [address] in foo (test)
76 \\source.zig:8:5: [address] in main (test)
77 \\
78 ,
79 // release-safe
80 \\error: TheSkyIsFalling
81 \\source.zig:4:5: [address] in std.special.posixCallMainAndExit (test)
82 \\source.zig:8:5: [address] in std.special.posixCallMainAndExit (test)
83 \\
84 ,
85 // release-fast
86 \\error: TheSkyIsFalling
87 \\
88 ,
89 // release-small
90 \\error: TheSkyIsFalling
91 \\
92 },
93 );
94 cases.addCase(
95 "try try return return",
96 source_try_try_return_return,
97 [_][]const u8{
98 // debug
99 \\error: TheSkyIsFalling
100 \\source.zig:12:5: [address] in make_error (test)
101 \\source.zig:8:5: [address] in bar (test)
102 \\source.zig:4:5: [address] in foo (test)
103 \\source.zig:16:5: [address] in main (test)
104 \\
105 ,
106 // release-safe
107 \\error: TheSkyIsFalling
108 \\source.zig:12:5: [address] in std.special.posixCallMainAndExit (test)
109 \\source.zig:8:5: [address] in std.special.posixCallMainAndExit (test)
110 \\source.zig:4:5: [address] in std.special.posixCallMainAndExit (test)
111 \\source.zig:16:5: [address] in std.special.posixCallMainAndExit (test)
112 \\
113 ,
114 // release-fast
115 \\error: TheSkyIsFalling
116 \\
117 ,
118 // release-small
119 \\error: TheSkyIsFalling
120 \\
121 },
122 );
123 },
124 .macosx => {
125 cases.addCase(
126 "return",
127 source_return,
128 [_][]const u8{
129 // debug
130 \\error: TheSkyIsFalling
131 \\source.zig:4:5: [address] in _main.0 (test.o)
132 \\
133 ,
134 // release-safe
135 \\error: TheSkyIsFalling
136 \\source.zig:4:5: [address] in _main (test.o)
137 \\
138 ,
139 // release-fast
140 \\error: TheSkyIsFalling
141 \\
142 ,
143 // release-small
144 \\error: TheSkyIsFalling
145 \\
146 },
147 );
148 cases.addCase(
149 "try return",
150 source_try_return,
151 [_][]const u8{
152 // debug
153 \\error: TheSkyIsFalling
154 \\source.zig:4:5: [address] in _foo (test.o)
155 \\source.zig:8:5: [address] in _main.0 (test.o)
156 \\
157 ,
158 // release-safe
159 \\error: TheSkyIsFalling
160 \\source.zig:4:5: [address] in _main (test.o)
161 \\source.zig:8:5: [address] in _main (test.o)
162 \\
163 ,
164 // release-fast
165 \\error: TheSkyIsFalling
166 \\
167 ,
168 // release-small
169 \\error: TheSkyIsFalling
170 \\
171 },
172 );
173 cases.addCase(
174 "try try return return",
175 source_try_try_return_return,
176 [_][]const u8{
177 // debug
178 \\error: TheSkyIsFalling
179 \\source.zig:12:5: [address] in _make_error (test.o)
180 \\source.zig:8:5: [address] in _bar (test.o)
181 \\source.zig:4:5: [address] in _foo (test.o)
182 \\source.zig:16:5: [address] in _main.0 (test.o)
183 \\
184 ,
185 // release-safe
186 \\error: TheSkyIsFalling
187 \\source.zig:12:5: [address] in _main (test.o)
188 \\source.zig:8:5: [address] in _main (test.o)
189 \\source.zig:4:5: [address] in _main (test.o)
190 \\source.zig:16:5: [address] in _main (test.o)
191 \\
192 ,
193 // release-fast
194 \\error: TheSkyIsFalling
195 \\
196 ,
197 // release-small
198 \\error: TheSkyIsFalling
199 \\
200 },
201 );
202 },
203 .windows => {
204 cases.addCase(
205 "return",
206 source_return,
207 [_][]const u8{
208 // debug
209 \\error: TheSkyIsFalling
210 \\source.zig:4:5: [address] in main (test.obj)
211 \\
212 ,
213 // release-safe
214 // --disabled-- results in segmenetation fault
215 "",
216 // release-fast
217 \\error: TheSkyIsFalling
218 \\
219 ,
220 // release-small
221 \\error: TheSkyIsFalling
222 \\
223 },
224 );
225 cases.addCase(
226 "try return",
227 source_try_return,
228 [_][]const u8{
229 // debug
230 \\error: TheSkyIsFalling
231 \\source.zig:4:5: [address] in foo (test.obj)
232 \\source.zig:8:5: [address] in main (test.obj)
233 \\
234 ,
235 // release-safe
236 // --disabled-- results in segmenetation fault
237 "",
238 // release-fast
239 \\error: TheSkyIsFalling
240 \\
241 ,
242 // release-small
243 \\error: TheSkyIsFalling
244 \\
245 },
246 );
247 cases.addCase(
248 "try try return return",
249 source_try_try_return_return,
250 [_][]const u8{
251 // debug
252 \\error: TheSkyIsFalling
253 \\source.zig:12:5: [address] in make_error (test.obj)
254 \\source.zig:8:5: [address] in bar (test.obj)
255 \\source.zig:4:5: [address] in foo (test.obj)
256 \\source.zig:16:5: [address] in main (test.obj)
257 \\
258 ,
259 // release-safe
260 // --disabled-- results in segmenetation fault
261 "",
262 // release-fast
263 \\error: TheSkyIsFalling
264 \\
265 ,
266 // release-small
267 \\error: TheSkyIsFalling
268 \\
269 },
270 );
271 },
272 else => {},
273 }
274}
test/stage1/behavior.zig+1
...@@ -30,6 +30,7 @@ comptime {...@@ -30,6 +30,7 @@ comptime {
30 _ = @import("behavior/bugs/2114.zig");30 _ = @import("behavior/bugs/2114.zig");
31 _ = @import("behavior/bugs/2346.zig");31 _ = @import("behavior/bugs/2346.zig");
32 _ = @import("behavior/bugs/2578.zig");32 _ = @import("behavior/bugs/2578.zig");
33 _ = @import("behavior/bugs/2692.zig");
33 _ = @import("behavior/bugs/3112.zig");34 _ = @import("behavior/bugs/3112.zig");
34 _ = @import("behavior/bugs/394.zig");35 _ = @import("behavior/bugs/394.zig");
35 _ = @import("behavior/bugs/421.zig");36 _ = @import("behavior/bugs/421.zig");
test/stage1/behavior/async_fn.zig+61
...@@ -1031,3 +1031,64 @@ test "@typeOf an async function call of generic fn with error union type" {...@@ -1031,3 +1031,64 @@ test "@typeOf an async function call of generic fn with error union type" {
1031 };1031 };
1032 _ = async S.func(i32);1032 _ = async S.func(i32);
1033}1033}
1034
1035test "using @typeOf on a generic function call" {
1036 const S = struct {
1037 var global_frame: anyframe = undefined;
1038 var global_ok = false;
1039
1040 var buf: [100]u8 align(16) = undefined;
1041
1042 fn amain(x: var) void {
1043 if (x == 0) {
1044 global_ok = true;
1045 return;
1046 }
1047 suspend {
1048 global_frame = @frame();
1049 }
1050 const F = @typeOf(async amain(x - 1));
1051 const frame = @intToPtr(*F, @ptrToInt(&buf));
1052 return await @asyncCall(frame, {}, amain, x - 1);
1053 }
1054 };
1055 _ = async S.amain(u32(1));
1056 resume S.global_frame;
1057 expect(S.global_ok);
1058}
1059
1060test "recursive call of await @asyncCall with struct return type" {
1061 const S = struct {
1062 var global_frame: anyframe = undefined;
1063 var global_ok = false;
1064
1065 var buf: [100]u8 align(16) = undefined;
1066
1067 fn amain(x: var) Foo {
1068 if (x == 0) {
1069 global_ok = true;
1070 return Foo{ .x = 1, .y = 2, .z = 3 };
1071 }
1072 suspend {
1073 global_frame = @frame();
1074 }
1075 const F = @typeOf(async amain(x - 1));
1076 const frame = @intToPtr(*F, @ptrToInt(&buf));
1077 return await @asyncCall(frame, {}, amain, x - 1);
1078 }
1079
1080 const Foo = struct {
1081 x: u64,
1082 y: u64,
1083 z: u64,
1084 };
1085 };
1086 var res: S.Foo = undefined;
1087 var frame: @typeOf(async S.amain(u32(1))) = undefined;
1088 _ = @asyncCall(&frame, &res, S.amain, u32(1));
1089 resume S.global_frame;
1090 expect(S.global_ok);
1091 expect(res.x == 1);
1092 expect(res.y == 2);
1093 expect(res.z == 3);
1094}
test/stage1/behavior/bugs/2692.zig created+6
...@@ -0,0 +1,6 @@
1fn foo(a: []u8) void {}
2
3test "address of 0 length array" {
4 var pt: [0]u8 = undefined;
5 foo(&pt);
6}
test/stage1/behavior/if.zig+11
...@@ -63,3 +63,14 @@ test "labeled break inside comptime if inside runtime if" {...@@ -63,3 +63,14 @@ test "labeled break inside comptime if inside runtime if" {
63 }63 }
64 expect(answer == 42);64 expect(answer == 42);
65}65}
66
67test "const result loc, runtime if cond, else unreachable" {
68 const Num = enum {
69 One,
70 Two,
71 };
72
73 var t = true;
74 const x = if (t) Num.Two else unreachable;
75 if (x != .Two) @compileError("bad");
76}
test/stage1/behavior/struct.zig+33
...@@ -599,3 +599,36 @@ test "extern fn returns struct by value" {...@@ -599,3 +599,36 @@ test "extern fn returns struct by value" {
599 S.entry();599 S.entry();
600 comptime S.entry();600 comptime S.entry();
601}601}
602
603test "for loop over pointers to struct, getting field from struct pointer" {
604 const S = struct {
605 const Foo = struct {
606 name: []const u8,
607 };
608
609 var ok = true;
610
611 fn eql(a: []const u8) bool {
612 return true;
613 }
614
615 const ArrayList = struct {
616 fn toSlice(self: *ArrayList) []*Foo {
617 return ([*]*Foo)(undefined)[0..0];
618 }
619 };
620
621 fn doTheTest() void {
622 var objects: ArrayList = undefined;
623
624 for (objects.toSlice()) |obj| {
625 if (eql(obj.name)) {
626 ok = false;
627 }
628 }
629
630 expect(ok);
631 }
632 };
633 S.doTheTest();
634}
test/stage1/behavior/union.zig+10
...@@ -457,3 +457,13 @@ test "@unionInit can modify a pointer value" {...@@ -457,3 +457,13 @@ test "@unionInit can modify a pointer value" {
457 value_ptr.* = @unionInit(UnionInitEnum, "Byte", 2);457 value_ptr.* = @unionInit(UnionInitEnum, "Byte", 2);
458 expect(value.Byte == 2);458 expect(value.Byte == 2);
459}459}
460
461test "union no tag with struct member" {
462 const Struct = struct {};
463 const Union = union {
464 s: Struct,
465 pub fn foo(self: *@This()) void {}
466 };
467 var u = Union{ .s = Struct{} };
468 u.foo();
469}
test/tests.zig+210
...@@ -16,6 +16,7 @@ const LibExeObjStep = build.LibExeObjStep;...@@ -16,6 +16,7 @@ const LibExeObjStep = build.LibExeObjStep;
1616
17const compare_output = @import("compare_output.zig");17const compare_output = @import("compare_output.zig");
18const standalone = @import("standalone.zig");18const standalone = @import("standalone.zig");
19const stack_traces = @import("stack_traces.zig");
19const compile_errors = @import("compile_errors.zig");20const compile_errors = @import("compile_errors.zig");
20const assemble_and_link = @import("assemble_and_link.zig");21const assemble_and_link = @import("assemble_and_link.zig");
21const runtime_safety = @import("runtime_safety.zig");22const runtime_safety = @import("runtime_safety.zig");
...@@ -57,6 +58,21 @@ pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes:...@@ -57,6 +58,21 @@ pub fn addCompareOutputTests(b: *build.Builder, test_filter: ?[]const u8, modes:
57 return cases.step;58 return cases.step;
58}59}
5960
61pub fn addStackTraceTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
62 const cases = b.allocator.create(StackTracesContext) catch unreachable;
63 cases.* = StackTracesContext{
64 .b = b,
65 .step = b.step("test-stack-traces", "Run the stack trace tests"),
66 .test_index = 0,
67 .test_filter = test_filter,
68 .modes = modes,
69 };
70
71 stack_traces.addCases(cases);
72
73 return cases.step;
74}
75
60pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {76pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step {
61 const cases = b.allocator.create(CompareOutputContext) catch unreachable;77 const cases = b.allocator.create(CompareOutputContext) catch unreachable;
62 cases.* = CompareOutputContext{78 cases.* = CompareOutputContext{
...@@ -549,6 +565,200 @@ pub const CompareOutputContext = struct {...@@ -549,6 +565,200 @@ pub const CompareOutputContext = struct {
549 }565 }
550};566};
551567
568pub const StackTracesContext = struct {
569 b: *build.Builder,
570 step: *build.Step,
571 test_index: usize,
572 test_filter: ?[]const u8,
573 modes: []const Mode,
574
575 const Expect = [@typeInfo(Mode).Enum.fields.len][]const u8;
576
577 pub fn addCase(
578 self: *StackTracesContext,
579 name: []const u8,
580 source: []const u8,
581 expect: Expect,
582 ) void {
583 const b = self.b;
584
585 const source_pathname = fs.path.join(
586 b.allocator,
587 [_][]const u8{ b.cache_root, "source.zig" },
588 ) catch unreachable;
589
590 for (self.modes) |mode| {
591 const expect_for_mode = expect[@enumToInt(mode)];
592 if (expect_for_mode.len == 0) continue;
593
594 const annotated_case_name = fmt.allocPrint(self.b.allocator, "{} {} ({})", "stack-trace", name, @tagName(mode)) catch unreachable;
595 if (self.test_filter) |filter| {
596 if (mem.indexOf(u8, annotated_case_name, filter) == null) continue;
597 }
598
599 const exe = b.addExecutable("test", source_pathname);
600 exe.setBuildMode(mode);
601
602 const write_source = b.addWriteFile(source_pathname, source);
603 exe.step.dependOn(&write_source.step);
604
605 const run_and_compare = RunAndCompareStep.create(
606 self,
607 exe,
608 annotated_case_name,
609 mode,
610 expect_for_mode,
611 );
612
613 self.step.dependOn(&run_and_compare.step);
614 }
615 }
616
617 const RunAndCompareStep = struct {
618 step: build.Step,
619 context: *StackTracesContext,
620 exe: *LibExeObjStep,
621 name: []const u8,
622 mode: Mode,
623 expect_output: []const u8,
624 test_index: usize,
625
626 pub fn create(
627 context: *StackTracesContext,
628 exe: *LibExeObjStep,
629 name: []const u8,
630 mode: Mode,
631 expect_output: []const u8,
632 ) *RunAndCompareStep {
633 const allocator = context.b.allocator;
634 const ptr = allocator.create(RunAndCompareStep) catch unreachable;
635 ptr.* = RunAndCompareStep{
636 .step = build.Step.init("StackTraceCompareOutputStep", allocator, make),
637 .context = context,
638 .exe = exe,
639 .name = name,
640 .mode = mode,
641 .expect_output = expect_output,
642 .test_index = context.test_index,
643 };
644 ptr.step.dependOn(&exe.step);
645 context.test_index += 1;
646 return ptr;
647 }
648
649 fn make(step: *build.Step) !void {
650 const self = @fieldParentPtr(RunAndCompareStep, "step", step);
651 const b = self.context.b;
652
653 const full_exe_path = self.exe.getOutputPath();
654 var args = ArrayList([]const u8).init(b.allocator);
655 defer args.deinit();
656 args.append(full_exe_path) catch unreachable;
657
658 warn("Test {}/{} {}...", self.test_index + 1, self.context.test_index, self.name);
659
660 const child = std.ChildProcess.init(args.toSliceConst(), b.allocator) catch unreachable;
661 defer child.deinit();
662
663 child.stdin_behavior = .Ignore;
664 child.stdout_behavior = .Pipe;
665 child.stderr_behavior = .Pipe;
666 child.env_map = b.env_map;
667
668 child.spawn() catch |err| debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err));
669
670 var stdout = Buffer.initNull(b.allocator);
671 var stderr = Buffer.initNull(b.allocator);
672
673 var stdout_file_in_stream = child.stdout.?.inStream();
674 var stderr_file_in_stream = child.stderr.?.inStream();
675
676 stdout_file_in_stream.stream.readAllBuffer(&stdout, max_stdout_size) catch unreachable;
677 stderr_file_in_stream.stream.readAllBuffer(&stderr, max_stdout_size) catch unreachable;
678
679 const term = child.wait() catch |err| {
680 debug.panic("Unable to spawn {}: {}\n", full_exe_path, @errorName(err));
681 };
682
683 switch (term) {
684 .Exited => |code| {
685 const expect_code: u32 = 1;
686 if (code != expect_code) {
687 warn("Process {} exited with error code {} but expected code {}\n", full_exe_path, code, expect_code);
688 printInvocation(args.toSliceConst());
689 return error.TestFailed;
690 }
691 },
692 .Signal => |signum| {
693 warn("Process {} terminated on signal {}\n", full_exe_path, signum);
694 printInvocation(args.toSliceConst());
695 return error.TestFailed;
696 },
697 .Stopped => |signum| {
698 warn("Process {} stopped on signal {}\n", full_exe_path, signum);
699 printInvocation(args.toSliceConst());
700 return error.TestFailed;
701 },
702 .Unknown => |code| {
703 warn("Process {} terminated unexpectedly with error code {}\n", full_exe_path, code);
704 printInvocation(args.toSliceConst());
705 return error.TestFailed;
706 },
707 }
708
709 // process result
710 // - keep only basename of source file path
711 // - replace address with symbolic string
712 // - skip empty lines
713 const got: []const u8 = got_result: {
714 var buf = try Buffer.initSize(b.allocator, 0);
715 defer buf.deinit();
716 var bytes = stderr.toSliceConst();
717 if (bytes.len != 0 and bytes[bytes.len - 1] == '\n') bytes = bytes[0 .. bytes.len - 1];
718 var it = mem.separate(bytes, "\n");
719 process_lines: while (it.next()) |line| {
720 if (line.len == 0) continue;
721 const delims = [_][]const u8{ ":", ":", ":", " in " };
722 var marks = [_]usize{0} ** 4;
723 // offset search past `[drive]:` on windows
724 var pos: usize = if (builtin.os == .windows) 2 else 0;
725 for (delims) |delim, i| {
726 marks[i] = mem.indexOfPos(u8, line, pos, delim) orelse {
727 try buf.append(line);
728 try buf.append("\n");
729 continue :process_lines;
730 };
731 pos = marks[i] + delim.len;
732 }
733 pos = mem.lastIndexOfScalar(u8, line[0..marks[0]], fs.path.sep) orelse {
734 try buf.append(line);
735 try buf.append("\n");
736 continue :process_lines;
737 };
738 try buf.append(line[pos + 1 .. marks[2] + delims[2].len]);
739 try buf.append(" [address]");
740 try buf.append(line[marks[3]..]);
741 try buf.append("\n");
742 }
743 break :got_result buf.toOwnedSlice();
744 };
745
746 if (!mem.eql(u8, self.expect_output, got)) {
747 warn(
748 \\
749 \\========= Expected this output: =========
750 \\{}
751 \\================================================
752 \\{}
753 \\
754 , self.expect_output, got);
755 return error.TestFailed;
756 }
757 warn("OK\n");
758 }
759 };
760};
761
552pub const CompileErrorContext = struct {762pub const CompileErrorContext = struct {
553 b: *build.Builder,763 b: *build.Builder,
554 step: *build.Step,764 step: *build.Step,