| author | |
| committer | |
| log | 5308eb7045b7b6a48356c6e814baf2a45a094d80 |
| tree | 88b2bd51d15a72b1aa27c51fdc54a2c51d8c827a |
| parent | d62f7c6b605a672f032aff8870496d2ae2366017 |
| parent | 77a5f888be664f9ef09e2c93f52338448e992e00 |
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) |
| 23 | if(GIT_EXE) | 23 | if(GIT_EXE) |
| 24 | execute_process( | 24 | execute_process( |
| 25 | COMMAND ${GIT_EXE} -C ${CMAKE_SOURCE_DIR} name-rev HEAD --tags --name-only --no-undefined --always | 25 | 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_REV | 27 | 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() |
| 35 | endif() | 39 | endif() |
| 36 | message("Configuring zig version ${ZIG_VERSION}") | 40 | message("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 { |
| 138 | 138 | ||
| 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 | } |
| 149 | 150 |
doc/docgen.zig+2-2| ... | @@ -307,7 +307,7 @@ const Node = union(enum) { | ... | @@ -307,7 +307,7 @@ const Node = union(enum) { |
| 307 | const Toc = struct { | 307 | const 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 | }; |
| 312 | 312 | ||
| 313 | const Action = enum { | 313 | const Action = enum { |
| ... | @@ -316,7 +316,7 @@ const Action = enum { | ... | @@ -316,7 +316,7 @@ const Action = enum { |
| 316 | }; | 316 | }; |
| 317 | 317 | ||
| 318 | fn genToc(allocator: *mem.Allocator, tokenizer: *Tokenizer) !Toc { | 318 | fn 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(); |
| 321 | 321 | ||
| 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; |
| 5 | 5 | ||
| 6 | const Allocator = mem.Allocator; | 6 | const Allocator = mem.Allocator; |
| 7 | const ArrayList = std.ArrayList; | 7 | const ArrayList = std.ArrayList; |
| 8 | const HashMap = std.HashMap; | 8 | const StringHashMap = std.StringHashMap; |
| 9 | 9 | ||
| 10 | fn trimStart(slice: []const u8, ch: u8) []const u8 { | 10 | fn 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 | } |
| 75 | 75 | ||
| 76 | const HashMapFlags = HashMap([]const u8, FlagArg, std.hash.Fnv1a_32.hash, mem.eql_slice_u8); | 76 | const HashMapFlags = StringHashMap(FlagArg); |
| 77 | 77 | ||
| 78 | // A store for querying found flags and positional arguments. | 78 | // A store for querying found flags and positional arguments. |
| 79 | pub const Args = struct { | 79 | pub 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); |
| 253 | 253 | ||
| 254 | const CompileErrList = std.ArrayList(*Msg); | 254 | const CompileErrList = std.ArrayList(*Msg); |
| 255 | 255 |
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 scope | 20 | // TODO when we destroy the decl, deref the tree scope |
| 21 | tree_scope: *Scope.AstTree, | 21 | tree_scope: *Scope.AstTree, |
| 22 | 22 | ||
| 23 | pub const Table = std.HashMap([]const u8, *Decl, mem.hash_slice_u8, mem.eql_slice_u8); | 23 | pub const Table = std.StringHashMap(*Decl); |
| 24 | 24 | ||
| 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, |
| 543 | 543 | ||
| 544 | const SeenMap = std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8); | 544 | const SeenMap = std.StringHashMap(void); |
| 545 | }; | 545 | }; |
| 546 | 546 | ||
| 547 | fn parseLibcPaths(allocator: *Allocator, libc: *LibCInstallation, libc_paths_file: []const u8) void { | 547 | fn 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_dir | 10 | /// relative to root_src_dir |
| 11 | table: Table, | 11 | table: Table, |
| 12 | 12 | ||
| 13 | pub const Table = std.HashMap([]const u8, *Package, mem.hash_slice_u8, mem.eql_slice_u8); | 13 | pub const Table = std.StringHashMap(*Package); |
| 14 | 14 | ||
| 15 | /// makes internal copies of root_src_dir and root_src_path | 15 | /// makes internal copies of root_src_dir and root_src_path |
| 16 | /// allocator should be an arena allocator because Package never frees anything | 16 | /// 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, |
| 345 | 345 | ||
| 346 | const SeenMap = std.HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8); | 346 | const SeenMap = std.StringHashMap(void); |
| 347 | }; | 347 | }; |
| 348 | 348 | ||
| 349 | fn printErrMsgToFile( | 349 | fn 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(); |
| 377 | 377 | ||
| 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); |
| 380 | 380 | ||
| 381 | if (!color_on) return; | 381 | if (!color_on) return; |
| 382 | 382 |
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; | ||
| 1992 | 1993 | ||
| 1993 | //////////////////////////// Participates in Input Parameter Cache Hash | 1994 | //////////////////////////// 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; | ||
| 2006 | 2008 | ||
| 2007 | ZigLibCInstallation *libc; | 2009 | ZigLibCInstallation *libc; |
| 2008 | 2010 |
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 | } |
| 2673 | 2673 | ||
| 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; |
| 2675 | 2679 | ||
| 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 | } |
| 4193 | 4197 | ||
| 4194 | static void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn) { | 4198 | void 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 * |
| 256 | ZigType *resolve_union_field_type(CodeGen *g, TypeUnionField *union_field); | 256 | ZigType *resolve_union_field_type(CodeGen *g, TypeUnionField *union_field); |
| 257 | ZigType *resolve_struct_field_type(CodeGen *g, TypeStructField *struct_field); | 257 | ZigType *resolve_struct_field_type(CodeGen *g, TypeStructField *struct_field); |
| 258 | 258 | ||
| 259 | void add_async_error_notes(CodeGen *g, ErrorMsg *msg, ZigFn *fn); | ||
| 260 | |||
| 259 | #endif | 261 | #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 | } | ||
| 3525 | 3534 | ||
| 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 | } |
| 3767 | 3776 | ||
| 3768 | static LLVMValueRef gen_frame_size(CodeGen *g, LLVMValueRef fn_val) { | 3777 | static 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 |
| 4103 | static LLVMValueRef ir_render_struct_field_ptr(CodeGen *g, IrExecutable *executable, | 4113 | static 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; |
| 4108 | 4120 | ||
| ... | @@ -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 | } |
| 4122 | 4134 | ||
| 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) { |
| 7199 | 7216 | ||
| 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 | } | ||
| 7203 | 7222 | ||
| 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); |
| 8875 | 8907 | ||
| 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); | ||
| 8895 | 8937 | ||
| 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); |
| 8897 | 8939 | ||
| ... | @@ -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); |
| 14842 | 14850 | ||
| ... | @@ -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 | } |
| 15650 | 15658 | ||
| 15659 | static 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 | |||
| 15651 | static IrInstruction *ir_analyze_fn_call(IrAnalyze *ira, IrInstructionCallSrc *call_instruction, | 15685 | static 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 | } |
| 15828 | 15862 | ||
| 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 | } |
| 16065 | 16074 | ||
| 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 | } |
| 16072 | 16085 | ||
| 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 | } |
| 16213 | 16226 | ||
| 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 | } |
| 16224 | 16241 | ||
| 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; |
| 17476 | 17498 | ||
| ... | @@ -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 | } |
| 22525 | 22547 | ||
| 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 | } |
| 2512 | 2512 | ||
| 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-path | 689 | // 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) { |
| 842 | 842 | ||
| 843 | void ZigLLVMAddModuleDebugInfoFlag(LLVMModuleRef module) { | 843 | void 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 | } |
| 846 | 847 | ||
| 847 | void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module) { | 848 | void ZigLLVMAddModuleCodeViewFlag(LLVMModuleRef module) { |
std/buf_map.zig+2-2| ... | @@ -1,5 +1,5 @@ | ... | @@ -1,5 +1,5 @@ |
| 1 | const std = @import("std.zig"); | 1 | const std = @import("std.zig"); |
| 2 | const HashMap = std.HashMap; | 2 | const StringHashMap = std.StringHashMap; |
| 3 | const mem = std.mem; | 3 | const mem = std.mem; |
| 4 | const Allocator = mem.Allocator; | 4 | const Allocator = mem.Allocator; |
| 5 | const testing = std.testing; | 5 | const testing = std.testing; |
| ... | @@ -9,7 +9,7 @@ const testing = std.testing; | ... | @@ -9,7 +9,7 @@ const testing = std.testing; |
| 9 | pub const BufMap = struct { | 9 | pub const BufMap = struct { |
| 10 | hash_map: BufMapHashMap, | 10 | hash_map: BufMapHashMap, |
| 11 | 11 | ||
| 12 | const BufMapHashMap = HashMap([]const u8, []const u8, mem.hash_slice_u8, mem.eql_slice_u8); | 12 | const BufMapHashMap = StringHashMap([]const u8); |
| 13 | 13 | ||
| 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 @@ |
| 1 | const std = @import("std.zig"); | 1 | const std = @import("std.zig"); |
| 2 | const HashMap = @import("hash_map.zig").HashMap; | 2 | const StringHashMap = std.StringHashMap; |
| 3 | const mem = @import("mem.zig"); | 3 | const mem = @import("mem.zig"); |
| 4 | const Allocator = mem.Allocator; | 4 | const Allocator = mem.Allocator; |
| 5 | const testing = std.testing; | 5 | const testing = std.testing; |
| ... | @@ -7,7 +7,7 @@ const testing = std.testing; | ... | @@ -7,7 +7,7 @@ const testing = std.testing; |
| 7 | pub const BufSet = struct { | 7 | pub const BufSet = struct { |
| 8 | hash_map: BufSetHashMap, | 8 | hash_map: BufSetHashMap, |
| 9 | 9 | ||
| 10 | const BufSetHashMap = HashMap([]const u8, void, mem.hash_slice_u8, mem.eql_slice_u8); | 10 | const BufSetHashMap = StringHashMap(void); |
| 11 | 11 | ||
| 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; |
| 4 | const fs = std.fs; | 4 | const fs = std.fs; |
| 5 | const mem = std.mem; | 5 | const mem = std.mem; |
| 6 | const debug = std.debug; | 6 | const debug = std.debug; |
| 7 | const panic = std.debug.panic; | ||
| 7 | const assert = debug.assert; | 8 | const assert = debug.assert; |
| 8 | const warn = std.debug.warn; | 9 | const warn = std.debug.warn; |
| 9 | const ArrayList = std.ArrayList; | 10 | const ArrayList = std.ArrayList; |
| 10 | const HashMap = std.HashMap; | 11 | const StringHashMap = std.StringHashMap; |
| 11 | const Allocator = mem.Allocator; | 12 | const Allocator = mem.Allocator; |
| 12 | const process = std.process; | 13 | const process = std.process; |
| 13 | const BufSet = std.BufSet; | 14 | const 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 | }; |
| 62 | 63 | ||
| 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); |
| 65 | 66 | ||
| 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 | } |
| 165 | 166 | ||
| 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 | } |
| 169 | 171 | ||
| 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; |
| 443 | 446 | ||
| ... | @@ -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 | } |
| 484 | 487 | ||
| ... | @@ -644,8 +647,6 @@ pub const Builder = struct { | ... | @@ -644,8 +647,6 @@ pub const Builder = struct { |
| 644 | } | 647 | } |
| 645 | 648 | ||
| 646 | pub fn validateUserInputDidItFail(self: *Builder) bool { | 649 | pub fn validateUserInputDidItFail(self: *Builder) bool { |
| 647 | self.resolveInstallPrefix(); | ||
| 648 | |||
| 649 | // make sure all args are used | 650 | // 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); |
| 857 | 858 | ||
| 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 | } |
| 1318 | 1320 | ||
| 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 | } |
| 1616 | 1622 | ||
| 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 | } |
| 1861 | 1871 | ||
| 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 | } |
| 1866 | 1876 | ||
| 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 | } |
| 1883 | 1893 | ||
| 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 << 1 | 110 | q.shiftLeft1(s); // q = p << 1 |
| 111 | r.shiftLeft1(q); // r = p << 2 | 111 | r.shiftLeft1(q); // r = p << 2 |
| 112 | s.shiftLeft1(r); // p = p << 3 | 112 | 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; | ||
| 116 | 114 | ||
| 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); |
| 404 | 402 | ||
| 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)); |
| 407 | 412 | ||
| ... | @@ -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)); |
| 414 | 419 | ||
| 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 | } |
| 24 | 24 | ||
| 25 | pub fn eqlString(a: []const u8, b: []const u8) bool { | 25 | pub 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 | } |
| 30 | 28 | ||
| 31 | pub fn hashString(s: []const u8) u32 { | 29 | pub 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" { |
| 989 | const Allocator = std.mem.Allocator; | 989 | const Allocator = std.mem.Allocator; |
| 990 | const ArenaAllocator = std.heap.ArenaAllocator; | 990 | const ArenaAllocator = std.heap.ArenaAllocator; |
| 991 | const ArrayList = std.ArrayList; | 991 | const ArrayList = std.ArrayList; |
| 992 | const HashMap = std.HashMap; | 992 | const StringHashMap = std.StringHashMap; |
| 993 | 993 | ||
| 994 | pub const ValueTree = struct { | 994 | pub 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 | }; |
| 1002 | 1002 | ||
| 1003 | pub const ObjectMap = HashMap([]const u8, Value, mem.hash_slice_u8, mem.eql_slice_u8); | 1003 | pub const ObjectMap = StringHashMap(Value); |
| 1004 | 1004 | ||
| 1005 | pub const Value = union(enum) { | 1005 | pub 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. |
| 340 | pub fn eql(comptime T: type, a: []const T, b: []const T) bool { | 340 | pub 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; |
| 739 | 740 | ||
| 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{})); |
| 744 | 745 | ||
| 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})); |
| 749 | 750 | ||
| 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 })); |
| 754 | 755 | ||
| 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 })); |
| 759 | 760 | ||
| 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})); |
| 764 | 765 | ||
| 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 | |||
| 771 | pub 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 | |||
| 780 | pub fn eql_slice_u8(a: []const u8, b: []const u8) bool { | ||
| 781 | return eql(u8, a, b); | ||
| 782 | } | 770 | } |
| 783 | 771 | ||
| 784 | /// Returns an iterator that iterates over the slices of `buffer` that are not | 772 | /// 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 | } |
| 125 | 125 | ||
| 126 | builder.resolveInstallPrefix(); | ||
| 126 | try runBuild(builder); | 127 | try runBuild(builder); |
| 127 | 128 | ||
| 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 options | 152 | // 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 | } |
| 156 | 158 |
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 | } |
| 2421 | 2421 | ||
| 2422 | test "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 | |||
| 2453 | test "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 | |||
| 2478 | test "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 | |||
| 2422 | test "zig fmt: comments at several places in struct init" { | 2510 | test "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 | }, |
| 484 | 484 | ||
| 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( |
| 580 | 594 | ||
| 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 | }, |
| 586 | 611 | ||
| ... | @@ -615,7 +640,7 @@ fn renderExpression( | ... | @@ -615,7 +640,7 @@ fn renderExpression( |
| 615 | 640 | ||
| 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 | } |
| 621 | 646 | ||
| ... | @@ -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).*; |
| 719 | 744 | ||
| 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 | }); |
| 1192 | 1217 | ||
| 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 | }; |
| 1197 | 1222 | ||
| 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 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const std = @import("std"); | ||
| 3 | const os = std.os; | ||
| 4 | const tests = @import("tests.zig"); | ||
| 5 | |||
| 6 | pub 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 | |||
| 1035 | test "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 | |||
| 1060 | test "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 @@ | ||
| 1 | fn foo(a: []u8) void {} | ||
| 2 | |||
| 3 | test "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 | |||
| 67 | test "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 | |||
| 603 | test "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 | |||
| 461 | test "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; |
| 16 | 16 | ||
| 17 | const compare_output = @import("compare_output.zig"); | 17 | const compare_output = @import("compare_output.zig"); |
| 18 | const standalone = @import("standalone.zig"); | 18 | const standalone = @import("standalone.zig"); |
| 19 | const stack_traces = @import("stack_traces.zig"); | ||
| 19 | const compile_errors = @import("compile_errors.zig"); | 20 | const compile_errors = @import("compile_errors.zig"); |
| 20 | const assemble_and_link = @import("assemble_and_link.zig"); | 21 | const assemble_and_link = @import("assemble_and_link.zig"); |
| 21 | const runtime_safety = @import("runtime_safety.zig"); | 22 | const 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 | } |
| 59 | 60 | ||
| 61 | pub 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 | |||
| 60 | pub fn addRuntimeSafetyTests(b: *build.Builder, test_filter: ?[]const u8, modes: []const Mode) *build.Step { | 76 | pub 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 | }; |
| 551 | 567 | ||
| 568 | pub 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 | |||
| 552 | pub const CompileErrorContext = struct { | 762 | pub const CompileErrorContext = struct { |
| 553 | b: *build.Builder, | 763 | b: *build.Builder, |
| 554 | step: *build.Step, | 764 | step: *build.Step, |