| author | |
| committer | |
| log | 773bf8013391d2b309cfcb50bf9e1c7db25cc3f2 |
| tree | f9afac31b7211b157ca47c8bef022e405b13bed7 |
| parent | c26f543970771acba5484553e2c10ec90b3c39eb |
| parent | 280187031a68c577e84c72add037271153d27c62 |
19 files changed, 233 insertions(+), 53 deletions(-)
.builds/freebsd.yml created+22| ... | @@ -0,0 +1,22 @@ | ||
| 1 | arch: x86_64 | ||
| 2 | image: freebsd | ||
| 3 | packages: | ||
| 4 | - cmake | ||
| 5 | - ninja | ||
| 6 | - llvm70 | ||
| 7 | sources: | ||
| 8 | - https://github.com/ziglang/zig.git | ||
| 9 | tasks: | ||
| 10 | - build: | | ||
| 11 | cd zig && mkdir build && cd build | ||
| 12 | cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release | ||
| 13 | ninja install | ||
| 14 | - test: | | ||
| 15 | cd zig/build | ||
| 16 | bin/zig test ../test/behavior.zig | ||
| 17 | # TODO enable all tests | ||
| 18 | #bin/zig build --build-file ../build.zig test | ||
| 19 | # TODO integrate with the download page updater and make a | ||
| 20 | # static build available to download for FreeBSD. | ||
| 21 | # This will require setting up a cache of LLVM/Clang built | ||
| 22 | # statically. | ||
doc/langref.html.in+1-1| ... | @@ -165,7 +165,7 @@ const std = @import("std"); | ... | @@ -165,7 +165,7 @@ const std = @import("std"); |
| 165 | 165 | ||
| 166 | pub fn main() !void { | 166 | pub fn main() !void { |
| 167 | // If this program is run without stdout attached, exit with an error. | 167 | // If this program is run without stdout attached, exit with an error. |
| 168 | var stdout_file = try std.io.getStdOut(); | 168 | const stdout_file = try std.io.getStdOut(); |
| 169 | // If this program encounters pipe failure when printing to stdout, exit | 169 | // If this program encounters pipe failure when printing to stdout, exit |
| 170 | // with an error. | 170 | // with an error. |
| 171 | try stdout_file.write("Hello, world!\n"); | 171 | try stdout_file.write("Hello, world!\n"); |
example/hello_world/hello.zig+1-1| ... | @@ -2,7 +2,7 @@ const std = @import("std"); | ... | @@ -2,7 +2,7 @@ const std = @import("std"); |
| 2 | 2 | ||
| 3 | pub fn main() !void { | 3 | pub fn main() !void { |
| 4 | // If this program is run without stdout attached, exit with an error. | 4 | // If this program is run without stdout attached, exit with an error. |
| 5 | var stdout_file = try std.io.getStdOut(); | 5 | const stdout_file = try std.io.getStdOut(); |
| 6 | // If this program encounters pipe failure when printing to stdout, exit | 6 | // If this program encounters pipe failure when printing to stdout, exit |
| 7 | // with an error. | 7 | // with an error. |
| 8 | try stdout_file.write("Hello, world!\n"); | 8 | try stdout_file.write("Hello, world!\n"); |
src-self-hosted/compilation.zig+1| ... | @@ -300,6 +300,7 @@ pub const Compilation = struct { | ... | @@ -300,6 +300,7 @@ pub const Compilation = struct { |
| 300 | UserResourceLimitReached, | 300 | UserResourceLimitReached, |
| 301 | InvalidUtf8, | 301 | InvalidUtf8, |
| 302 | BadPathName, | 302 | BadPathName, |
| 303 | DeviceBusy, | ||
| 303 | }; | 304 | }; |
| 304 | 305 | ||
| 305 | pub const Event = union(enum) { | 306 | pub const Event = union(enum) { |
src/analyze.cpp+33-22| ... | @@ -2681,39 +2681,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { | ... | @@ -2681,39 +2681,50 @@ static Error resolve_struct_alignment(CodeGen *g, ZigType *struct_type) { |
| 2681 | assert(decl_node->type == NodeTypeContainerDecl); | 2681 | assert(decl_node->type == NodeTypeContainerDecl); |
| 2682 | assert(struct_type->di_type); | 2682 | assert(struct_type->di_type); |
| 2683 | 2683 | ||
| 2684 | size_t field_count = struct_type->data.structure.src_field_count; | ||
| 2684 | if (struct_type->data.structure.layout == ContainerLayoutPacked) { | 2685 | if (struct_type->data.structure.layout == ContainerLayoutPacked) { |
| 2685 | struct_type->data.structure.abi_alignment = 1; | 2686 | struct_type->data.structure.abi_alignment = 1; |
| 2686 | } | 2687 | for (size_t i = 0; i < field_count; i += 1) { |
| 2687 | 2688 | TypeStructField *field = &struct_type->data.structure.fields[i]; | |
| 2688 | size_t field_count = struct_type->data.structure.src_field_count; | 2689 | if (field->type_entry != nullptr && type_is_invalid(field->type_entry)) { |
| 2689 | for (size_t i = 0; i < field_count; i += 1) { | 2690 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2690 | TypeStructField *field = &struct_type->data.structure.fields[i]; | 2691 | break; |
| 2691 | 2692 | } | |
| 2692 | // If this assertion trips, look up the call stack. Probably something is | ||
| 2693 | // calling type_resolve with ResolveStatusAlignmentKnown when it should only | ||
| 2694 | // be resolving ResolveStatusZeroBitsKnown | ||
| 2695 | assert(field->type_entry != nullptr); | ||
| 2696 | |||
| 2697 | if (type_is_invalid(field->type_entry)) { | ||
| 2698 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | ||
| 2699 | break; | ||
| 2700 | } | 2693 | } |
| 2694 | } else for (size_t i = 0; i < field_count; i += 1) { | ||
| 2695 | TypeStructField *field = &struct_type->data.structure.fields[i]; | ||
| 2696 | uint32_t this_field_align; | ||
| 2697 | |||
| 2698 | // TODO If we have no type_entry for the field, we've already failed to | ||
| 2699 | // compile the program correctly. This stage1 compiler needs a deeper | ||
| 2700 | // reworking to make this correct, or we can ignore the problem | ||
| 2701 | // and make sure it is fixed in stage2. This workaround is for when | ||
| 2702 | // there is a false positive of a dependency loop, of alignment depending | ||
| 2703 | // on itself. When this false positive happens we assume a pointer-aligned | ||
| 2704 | // field, which is usually fine but could be incorrectly over-aligned or | ||
| 2705 | // even under-aligned. See https://github.com/ziglang/zig/issues/1512 | ||
| 2706 | if (field->type_entry == nullptr) { | ||
| 2707 | this_field_align = LLVMABIAlignmentOfType(g->target_data_ref, LLVMPointerType(LLVMInt8Type(), 0)); | ||
| 2708 | } else { | ||
| 2709 | if (type_is_invalid(field->type_entry)) { | ||
| 2710 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | ||
| 2711 | break; | ||
| 2712 | } | ||
| 2701 | 2713 | ||
| 2702 | if (!type_has_bits(field->type_entry)) | 2714 | if (!type_has_bits(field->type_entry)) |
| 2703 | continue; | 2715 | continue; |
| 2704 | 2716 | ||
| 2705 | // alignment of structs is the alignment of the most-aligned field | ||
| 2706 | if (struct_type->data.structure.layout != ContainerLayoutPacked) { | ||
| 2707 | if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) { | 2717 | if ((err = type_resolve(g, field->type_entry, ResolveStatusAlignmentKnown))) { |
| 2708 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; | 2718 | struct_type->data.structure.resolve_status = ResolveStatusInvalid; |
| 2709 | break; | 2719 | break; |
| 2710 | } | 2720 | } |
| 2711 | 2721 | ||
| 2712 | uint32_t this_field_align = get_abi_alignment(g, field->type_entry); | 2722 | this_field_align = get_abi_alignment(g, field->type_entry); |
| 2713 | assert(this_field_align != 0); | 2723 | assert(this_field_align != 0); |
| 2714 | if (this_field_align > struct_type->data.structure.abi_alignment) { | 2724 | } |
| 2715 | struct_type->data.structure.abi_alignment = this_field_align; | 2725 | // alignment of structs is the alignment of the most-aligned field |
| 2716 | } | 2726 | if (this_field_align > struct_type->data.structure.abi_alignment) { |
| 2727 | struct_type->data.structure.abi_alignment = this_field_align; | ||
| 2717 | } | 2728 | } |
| 2718 | } | 2729 | } |
| 2719 | 2730 |
src/ir.cpp+50-15| ... | @@ -159,7 +159,7 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op | ... | @@ -159,7 +159,7 @@ static ZigType *ir_resolve_atomic_operand_type(IrAnalyze *ira, IrInstruction *op |
| 159 | static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval); | 159 | static IrInstruction *ir_lval_wrap(IrBuilder *irb, Scope *scope, IrInstruction *value, LVal lval); |
| 160 | static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align); | 160 | static ZigType *adjust_ptr_align(CodeGen *g, ZigType *ptr_type, uint32_t new_align); |
| 161 | static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align); | 161 | static ZigType *adjust_slice_align(CodeGen *g, ZigType *slice_type, uint32_t new_align); |
| 162 | static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); | 162 | static Error buf_read_value_bytes(IrAnalyze *ira, AstNode *source_node, uint8_t *buf, ConstExprValue *val); |
| 163 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); | 163 | static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val); |
| 164 | static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, | 164 | static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, |
| 165 | ConstExprValue *out_val, ConstExprValue *ptr_val); | 165 | ConstExprValue *out_val, ConstExprValue *ptr_val); |
| ... | @@ -12495,6 +12495,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct | ... | @@ -12495,6 +12495,7 @@ static IrInstruction *ir_analyze_instruction_decl_var(IrAnalyze *ira, IrInstruct |
| 12495 | case ReqCompTimeNo: | 12495 | case ReqCompTimeNo: |
| 12496 | if (casted_init_value->value.special == ConstValSpecialStatic && | 12496 | if (casted_init_value->value.special == ConstValSpecialStatic && |
| 12497 | casted_init_value->value.type->id == ZigTypeIdFn && | 12497 | casted_init_value->value.type->id == ZigTypeIdFn && |
| 12498 | casted_init_value->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr && | ||
| 12498 | casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways) | 12499 | casted_init_value->value.data.x_ptr.data.fn.fn_entry->fn_inline == FnInlineAlways) |
| 12499 | { | 12500 | { |
| 12500 | var_class_requires_const = true; | 12501 | var_class_requires_const = true; |
| ... | @@ -13724,7 +13725,8 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, | ... | @@ -13724,7 +13725,8 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, |
| 13724 | Buf buf = BUF_INIT; | 13725 | Buf buf = BUF_INIT; |
| 13725 | buf_resize(&buf, src_size); | 13726 | buf_resize(&buf, src_size); |
| 13726 | buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee); | 13727 | buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), pointee); |
| 13727 | buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val); | 13728 | if ((err = buf_read_value_bytes(ira, source_node, (uint8_t*)buf_ptr(&buf), out_val))) |
| 13729 | return err; | ||
| 13728 | return ErrorNone; | 13730 | return ErrorNone; |
| 13729 | } | 13731 | } |
| 13730 | 13732 | ||
| ... | @@ -13758,7 +13760,8 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, | ... | @@ -13758,7 +13760,8 @@ static Error ir_read_const_ptr(IrAnalyze *ira, AstNode *source_node, |
| 13758 | ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[elem_index + i]; | 13760 | ConstExprValue *elem_val = &array_val->data.x_array.data.s_none.elements[elem_index + i]; |
| 13759 | buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val); | 13761 | buf_write_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf) + (i * elem_size), elem_val); |
| 13760 | } | 13762 | } |
| 13761 | buf_read_value_bytes(ira->codegen, (uint8_t*)buf_ptr(&buf), out_val); | 13763 | if ((err = buf_read_value_bytes(ira, source_node, (uint8_t*)buf_ptr(&buf), out_val))) |
| 13764 | return err; | ||
| 13762 | return ErrorNone; | 13765 | return ErrorNone; |
| 13763 | } | 13766 | } |
| 13764 | case ConstPtrSpecialBaseStruct: | 13767 | case ConstPtrSpecialBaseStruct: |
| ... | @@ -20076,7 +20079,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue | ... | @@ -20076,7 +20079,8 @@ static void buf_write_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 20076 | zig_unreachable(); | 20079 | zig_unreachable(); |
| 20077 | } | 20080 | } |
| 20078 | 20081 | ||
| 20079 | static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue *val) { | 20082 | static Error buf_read_value_bytes(IrAnalyze *ira, AstNode *source_node, uint8_t *buf, ConstExprValue *val) { |
| 20083 | Error err; | ||
| 20080 | assert(val->special == ConstValSpecialStatic); | 20084 | assert(val->special == ConstValSpecialStatic); |
| 20081 | switch (val->type->id) { | 20085 | switch (val->type->id) { |
| 20082 | case ZigTypeIdInvalid: | 20086 | case ZigTypeIdInvalid: |
| ... | @@ -20093,30 +20097,60 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue | ... | @@ -20093,30 +20097,60 @@ static void buf_read_value_bytes(CodeGen *codegen, uint8_t *buf, ConstExprValue |
| 20093 | case ZigTypeIdPromise: | 20097 | case ZigTypeIdPromise: |
| 20094 | zig_unreachable(); | 20098 | zig_unreachable(); |
| 20095 | case ZigTypeIdVoid: | 20099 | case ZigTypeIdVoid: |
| 20096 | return; | 20100 | return ErrorNone; |
| 20097 | case ZigTypeIdBool: | 20101 | case ZigTypeIdBool: |
| 20098 | val->data.x_bool = (buf[0] != 0); | 20102 | val->data.x_bool = (buf[0] != 0); |
| 20099 | return; | 20103 | return ErrorNone; |
| 20100 | case ZigTypeIdInt: | 20104 | case ZigTypeIdInt: |
| 20101 | bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count, | 20105 | bigint_read_twos_complement(&val->data.x_bigint, buf, val->type->data.integral.bit_count, |
| 20102 | codegen->is_big_endian, val->type->data.integral.is_signed); | 20106 | ira->codegen->is_big_endian, val->type->data.integral.is_signed); |
| 20103 | return; | 20107 | return ErrorNone; |
| 20104 | case ZigTypeIdFloat: | 20108 | case ZigTypeIdFloat: |
| 20105 | float_read_ieee597(val, buf, codegen->is_big_endian); | 20109 | float_read_ieee597(val, buf, ira->codegen->is_big_endian); |
| 20106 | return; | 20110 | return ErrorNone; |
| 20107 | case ZigTypeIdPointer: | 20111 | case ZigTypeIdPointer: |
| 20108 | { | 20112 | { |
| 20109 | val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr; | 20113 | val->data.x_ptr.special = ConstPtrSpecialHardCodedAddr; |
| 20110 | BigInt bn; | 20114 | BigInt bn; |
| 20111 | bigint_read_twos_complement(&bn, buf, codegen->builtin_types.entry_usize->data.integral.bit_count, | 20115 | bigint_read_twos_complement(&bn, buf, ira->codegen->builtin_types.entry_usize->data.integral.bit_count, |
| 20112 | codegen->is_big_endian, false); | 20116 | ira->codegen->is_big_endian, false); |
| 20113 | val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn); | 20117 | val->data.x_ptr.data.hard_coded_addr.addr = bigint_as_unsigned(&bn); |
| 20114 | return; | 20118 | return ErrorNone; |
| 20115 | } | 20119 | } |
| 20116 | case ZigTypeIdArray: | 20120 | case ZigTypeIdArray: |
| 20117 | zig_panic("TODO buf_read_value_bytes array type"); | 20121 | zig_panic("TODO buf_read_value_bytes array type"); |
| 20118 | case ZigTypeIdStruct: | 20122 | case ZigTypeIdStruct: |
| 20119 | zig_panic("TODO buf_read_value_bytes struct type"); | 20123 | switch (val->type->data.structure.layout) { |
| 20124 | case ContainerLayoutAuto: { | ||
| 20125 | ErrorMsg *msg = ir_add_error_node(ira, source_node, | ||
| 20126 | buf_sprintf("non-extern, non-packed struct '%s' cannot have its bytes reinterpreted", | ||
| 20127 | buf_ptr(&val->type->name))); | ||
| 20128 | add_error_note(ira->codegen, msg, val->type->data.structure.decl_node, | ||
| 20129 | buf_sprintf("declared here")); | ||
| 20130 | return ErrorSemanticAnalyzeFail; | ||
| 20131 | } | ||
| 20132 | case ContainerLayoutExtern: { | ||
| 20133 | size_t src_field_count = val->type->data.structure.src_field_count; | ||
| 20134 | val->data.x_struct.fields = create_const_vals(src_field_count); | ||
| 20135 | for (size_t field_i = 0; field_i < src_field_count; field_i += 1) { | ||
| 20136 | ConstExprValue *field_val = &val->data.x_struct.fields[field_i]; | ||
| 20137 | field_val->special = ConstValSpecialStatic; | ||
| 20138 | TypeStructField *type_field = &val->type->data.structure.fields[field_i]; | ||
| 20139 | field_val->type = type_field->type_entry; | ||
| 20140 | if (type_field->gen_index == SIZE_MAX) | ||
| 20141 | continue; | ||
| 20142 | size_t offset = LLVMOffsetOfElement(ira->codegen->target_data_ref, val->type->type_ref, | ||
| 20143 | type_field->gen_index); | ||
| 20144 | uint8_t *new_buf = buf + offset; | ||
| 20145 | if ((err = buf_read_value_bytes(ira, source_node, new_buf, field_val))) | ||
| 20146 | return err; | ||
| 20147 | } | ||
| 20148 | return ErrorNone; | ||
| 20149 | } | ||
| 20150 | case ContainerLayoutPacked: | ||
| 20151 | zig_panic("TODO buf_read_value_bytes packed struct"); | ||
| 20152 | } | ||
| 20153 | zig_unreachable(); | ||
| 20120 | case ZigTypeIdOptional: | 20154 | case ZigTypeIdOptional: |
| 20121 | zig_panic("TODO buf_read_value_bytes maybe type"); | 20155 | zig_panic("TODO buf_read_value_bytes maybe type"); |
| 20122 | case ZigTypeIdErrorUnion: | 20156 | case ZigTypeIdErrorUnion: |
| ... | @@ -20219,7 +20253,8 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct | ... | @@ -20219,7 +20253,8 @@ static IrInstruction *ir_analyze_instruction_bit_cast(IrAnalyze *ira, IrInstruct |
| 20219 | IrInstruction *result = ir_const(ira, &instruction->base, dest_type); | 20253 | IrInstruction *result = ir_const(ira, &instruction->base, dest_type); |
| 20220 | uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes); | 20254 | uint8_t *buf = allocate_nonzero<uint8_t>(src_size_bytes); |
| 20221 | buf_write_value_bytes(ira->codegen, buf, val); | 20255 | buf_write_value_bytes(ira->codegen, buf, val); |
| 20222 | buf_read_value_bytes(ira->codegen, buf, &result->value); | 20256 | if ((err = buf_read_value_bytes(ira, instruction->base.source_node, buf, &result->value))) |
| 20257 | return ira->codegen->invalid_instruction; | ||
| 20223 | return result; | 20258 | return result; |
| 20224 | } | 20259 | } |
| 20225 | 20260 |
src/translate_c.cpp+8| ... | @@ -4776,6 +4776,14 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const | ... | @@ -4776,6 +4776,14 @@ Error parse_h_file(ImportTableEntry *import, ZigList<ErrorMsg *> *errors, const |
| 4776 | 4776 | ||
| 4777 | clang_argv.append(target_file); | 4777 | clang_argv.append(target_file); |
| 4778 | 4778 | ||
| 4779 | if (codegen->verbose_cimport) { | ||
| 4780 | fprintf(stderr, "clang"); | ||
| 4781 | for (size_t i = 0; i < clang_argv.length; i += 1) { | ||
| 4782 | fprintf(stderr, " %s", clang_argv.at(i)); | ||
| 4783 | } | ||
| 4784 | fprintf(stderr, "\n"); | ||
| 4785 | } | ||
| 4786 | |||
| 4779 | // to make the [start...end] argument work | 4787 | // to make the [start...end] argument work |
| 4780 | clang_argv.append(nullptr); | 4788 | clang_argv.append(nullptr); |
| 4781 | 4789 |
std/array_list.zig+11| ... | @@ -398,3 +398,14 @@ test "std.ArrayList.insertSlice" { | ... | @@ -398,3 +398,14 @@ test "std.ArrayList.insertSlice" { |
| 398 | assert(list.len == 6); | 398 | assert(list.len == 6); |
| 399 | assert(list.items[0] == 1); | 399 | assert(list.items[0] == 1); |
| 400 | } | 400 | } |
| 401 | |||
| 402 | const Item = struct { | ||
| 403 | integer: i32, | ||
| 404 | sub_items: ArrayList(Item), | ||
| 405 | }; | ||
| 406 | |||
| 407 | test "std.ArrayList: ArrayList(T) of struct T" { | ||
| 408 | var root = Item{ .integer = 1, .sub_items = ArrayList(Item).init(debug.global_allocator) }; | ||
| 409 | try root.sub_items.append( Item{ .integer = 42, .sub_items = ArrayList(Item).init(debug.global_allocator) } ); | ||
| 410 | assert(root.sub_items.items[0].integer == 42); | ||
| 411 | } |
std/dynamic_library.zig+1-3| ... | @@ -19,7 +19,6 @@ pub const DynLib = switch (builtin.os) { | ... | @@ -19,7 +19,6 @@ pub const DynLib = switch (builtin.os) { |
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | pub const LinuxDynLib = struct { | 21 | pub const LinuxDynLib = struct { |
| 22 | allocator: *mem.Allocator, | ||
| 23 | elf_lib: ElfLib, | 22 | elf_lib: ElfLib, |
| 24 | fd: i32, | 23 | fd: i32, |
| 25 | map_addr: usize, | 24 | map_addr: usize, |
| ... | @@ -27,7 +26,7 @@ pub const LinuxDynLib = struct { | ... | @@ -27,7 +26,7 @@ pub const LinuxDynLib = struct { |
| 27 | 26 | ||
| 28 | /// Trusts the file | 27 | /// Trusts the file |
| 29 | pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib { | 28 | pub fn open(allocator: *mem.Allocator, path: []const u8) !DynLib { |
| 30 | const fd = try std.os.posixOpen(allocator, path, 0, linux.O_RDONLY | linux.O_CLOEXEC); | 29 | const fd = try std.os.posixOpen(path, 0, linux.O_RDONLY | linux.O_CLOEXEC); |
| 31 | errdefer std.os.close(fd); | 30 | errdefer std.os.close(fd); |
| 32 | 31 | ||
| 33 | const size = @intCast(usize, (try std.os.posixFStat(fd)).size); | 32 | const size = @intCast(usize, (try std.os.posixFStat(fd)).size); |
| ... | @@ -45,7 +44,6 @@ pub const LinuxDynLib = struct { | ... | @@ -45,7 +44,6 @@ pub const LinuxDynLib = struct { |
| 45 | const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size]; | 44 | const bytes = @intToPtr([*]align(std.os.page_size) u8, addr)[0..size]; |
| 46 | 45 | ||
| 47 | return DynLib{ | 46 | return DynLib{ |
| 48 | .allocator = allocator, | ||
| 49 | .elf_lib = try ElfLib.init(bytes), | 47 | .elf_lib = try ElfLib.init(bytes), |
| 50 | .fd = fd, | 48 | .fd = fd, |
| 51 | .map_addr = addr, | 49 | .map_addr = addr, |
std/fmt/index.zig+7| ... | @@ -243,6 +243,9 @@ pub fn formatType( | ... | @@ -243,6 +243,9 @@ pub fn formatType( |
| 243 | } | 243 | } |
| 244 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value)); | 244 | return format(context, Errors, output, "{}@{x}", @typeName(T.Child), @ptrToInt(&value)); |
| 245 | }, | 245 | }, |
| 246 | builtin.TypeId.Fn => { | ||
| 247 | return format(context, Errors, output, "{}@{x}", @typeName(T), @ptrToInt(value)); | ||
| 248 | }, | ||
| 246 | else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"), | 249 | else => @compileError("Unable to format type '" ++ @typeName(T) ++ "'"), |
| 247 | } | 250 | } |
| 248 | } | 251 | } |
| ... | @@ -1013,6 +1016,10 @@ test "fmt.format" { | ... | @@ -1013,6 +1016,10 @@ test "fmt.format" { |
| 1013 | const value = @intToPtr(fn () void, 0xdeadbeef); | 1016 | const value = @intToPtr(fn () void, 0xdeadbeef); |
| 1014 | try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value); | 1017 | try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value); |
| 1015 | } | 1018 | } |
| 1019 | { | ||
| 1020 | const value = @intToPtr(fn () void, 0xdeadbeef); | ||
| 1021 | try testFmt("pointer: fn() void@deadbeef\n", "pointer: {}\n", value); | ||
| 1022 | } | ||
| 1016 | try testFmt("buf: Test \n", "buf: {s5}\n", "Test"); | 1023 | try testFmt("buf: Test \n", "buf: {s5}\n", "Test"); |
| 1017 | try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test"); | 1024 | try testFmt("buf: Test\n Other text", "buf: {s}\n Other text", "Test"); |
| 1018 | try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C"); | 1025 | try testFmt("cstr: Test C\n", "cstr: {s}\n", c"Test C"); |
std/index.zig+2-1| ... | @@ -57,7 +57,8 @@ test "std" { | ... | @@ -57,7 +57,8 @@ test "std" { |
| 57 | _ = @import("mutex.zig"); | 57 | _ = @import("mutex.zig"); |
| 58 | _ = @import("segmented_list.zig"); | 58 | _ = @import("segmented_list.zig"); |
| 59 | _ = @import("spinlock.zig"); | 59 | _ = @import("spinlock.zig"); |
| 60 | 60 | ||
| 61 | _ = @import("dynamic_library.zig"); | ||
| 61 | _ = @import("base64.zig"); | 62 | _ = @import("base64.zig"); |
| 62 | _ = @import("build.zig"); | 63 | _ = @import("build.zig"); |
| 63 | _ = @import("c/index.zig"); | 64 | _ = @import("c/index.zig"); |
std/io.zig+5-5| ... | @@ -155,32 +155,32 @@ pub fn InStream(comptime ReadError: type) type { | ... | @@ -155,32 +155,32 @@ pub fn InStream(comptime ReadError: type) type { |
| 155 | pub fn readIntNative(self: *Self, comptime T: type) !T { | 155 | pub fn readIntNative(self: *Self, comptime T: type) !T { |
| 156 | var bytes: [@sizeOf(T)]u8 = undefined; | 156 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 157 | try self.readNoEof(bytes[0..]); | 157 | try self.readNoEof(bytes[0..]); |
| 158 | return mem.readIntSliceNative(T, bytes); | 158 | return mem.readIntNative(T, &bytes); |
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | /// Reads a foreign-endian integer | 161 | /// Reads a foreign-endian integer |
| 162 | pub fn readIntForeign(self: *Self, comptime T: type) !T { | 162 | pub fn readIntForeign(self: *Self, comptime T: type) !T { |
| 163 | var bytes: [@sizeOf(T)]u8 = undefined; | 163 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 164 | try self.readNoEof(bytes[0..]); | 164 | try self.readNoEof(bytes[0..]); |
| 165 | return mem.readIntSliceForeign(T, bytes); | 165 | return mem.readIntForeign(T, &bytes); |
| 166 | } | 166 | } |
| 167 | 167 | ||
| 168 | pub fn readIntLittle(self: *Self, comptime T: type) !T { | 168 | pub fn readIntLittle(self: *Self, comptime T: type) !T { |
| 169 | var bytes: [@sizeOf(T)]u8 = undefined; | 169 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 170 | try self.readNoEof(bytes[0..]); | 170 | try self.readNoEof(bytes[0..]); |
| 171 | return mem.readIntSliceLittle(T, bytes); | 171 | return mem.readIntLittle(T, &bytes); |
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | pub fn readIntBig(self: *Self, comptime T: type) !T { | 174 | pub fn readIntBig(self: *Self, comptime T: type) !T { |
| 175 | var bytes: [@sizeOf(T)]u8 = undefined; | 175 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 176 | try self.readNoEof(bytes[0..]); | 176 | try self.readNoEof(bytes[0..]); |
| 177 | return mem.readIntSliceBig(T, bytes); | 177 | return mem.readIntBig(T, &bytes); |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T { | 180 | pub fn readInt(self: *Self, comptime T: type, endian: builtin.Endian) !T { |
| 181 | var bytes: [@sizeOf(T)]u8 = undefined; | 181 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 182 | try self.readNoEof(bytes[0..]); | 182 | try self.readNoEof(bytes[0..]); |
| 183 | return mem.readIntSlice(T, bytes, endian); | 183 | return mem.readInt(T, &bytes, endian); |
| 184 | } | 184 | } |
| 185 | 185 | ||
| 186 | pub fn readVarInt(self: *Self, comptime ReturnType: type, endian: builtin.Endian, size: usize) !ReturnType { | 186 | pub fn readVarInt(self: *Self, comptime ReturnType: type, endian: builtin.Endian, size: usize) !ReturnType { |
std/os/index.zig+5| ... | @@ -459,6 +459,7 @@ pub const PosixOpenError = error{ | ... | @@ -459,6 +459,7 @@ pub const PosixOpenError = error{ |
| 459 | NoSpaceLeft, | 459 | NoSpaceLeft, |
| 460 | NotDir, | 460 | NotDir, |
| 461 | PathAlreadyExists, | 461 | PathAlreadyExists, |
| 462 | DeviceBusy, | ||
| 462 | 463 | ||
| 463 | /// See https://github.com/ziglang/zig/issues/1396 | 464 | /// See https://github.com/ziglang/zig/issues/1396 |
| 464 | Unexpected, | 465 | Unexpected, |
| ... | @@ -497,6 +498,7 @@ pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 { | ... | @@ -497,6 +498,7 @@ pub fn posixOpenC(file_path: [*]const u8, flags: u32, perm: usize) !i32 { |
| 497 | posix.ENOTDIR => return PosixOpenError.NotDir, | 498 | posix.ENOTDIR => return PosixOpenError.NotDir, |
| 498 | posix.EPERM => return PosixOpenError.AccessDenied, | 499 | posix.EPERM => return PosixOpenError.AccessDenied, |
| 499 | posix.EEXIST => return PosixOpenError.PathAlreadyExists, | 500 | posix.EEXIST => return PosixOpenError.PathAlreadyExists, |
| 501 | posix.EBUSY => return PosixOpenError.DeviceBusy, | ||
| 500 | else => return unexpectedErrorPosix(err), | 502 | else => return unexpectedErrorPosix(err), |
| 501 | } | 503 | } |
| 502 | } | 504 | } |
| ... | @@ -1402,6 +1404,7 @@ const DeleteTreeError = error{ | ... | @@ -1402,6 +1404,7 @@ const DeleteTreeError = error{ |
| 1402 | FileSystem, | 1404 | FileSystem, |
| 1403 | FileBusy, | 1405 | FileBusy, |
| 1404 | DirNotEmpty, | 1406 | DirNotEmpty, |
| 1407 | DeviceBusy, | ||
| 1405 | 1408 | ||
| 1406 | /// On Windows, file paths must be valid Unicode. | 1409 | /// On Windows, file paths must be valid Unicode. |
| 1407 | InvalidUtf8, | 1410 | InvalidUtf8, |
| ... | @@ -1463,6 +1466,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError! | ... | @@ -1463,6 +1466,7 @@ pub fn deleteTree(allocator: *Allocator, full_path: []const u8) DeleteTreeError! |
| 1463 | error.Unexpected, | 1466 | error.Unexpected, |
| 1464 | error.InvalidUtf8, | 1467 | error.InvalidUtf8, |
| 1465 | error.BadPathName, | 1468 | error.BadPathName, |
| 1469 | error.DeviceBusy, | ||
| 1466 | => return err, | 1470 | => return err, |
| 1467 | }; | 1471 | }; |
| 1468 | defer dir.close(); | 1472 | defer dir.close(); |
| ... | @@ -1545,6 +1549,7 @@ pub const Dir = struct { | ... | @@ -1545,6 +1549,7 @@ pub const Dir = struct { |
| 1545 | OutOfMemory, | 1549 | OutOfMemory, |
| 1546 | InvalidUtf8, | 1550 | InvalidUtf8, |
| 1547 | BadPathName, | 1551 | BadPathName, |
| 1552 | DeviceBusy, | ||
| 1548 | 1553 | ||
| 1549 | /// See https://github.com/ziglang/zig/issues/1396 | 1554 | /// See https://github.com/ziglang/zig/issues/1396 |
| 1550 | Unexpected, | 1555 | Unexpected, |
std/os/path.zig+1| ... | @@ -1093,6 +1093,7 @@ pub const RealError = error{ | ... | @@ -1093,6 +1093,7 @@ pub const RealError = error{ |
| 1093 | NoSpaceLeft, | 1093 | NoSpaceLeft, |
| 1094 | FileSystem, | 1094 | FileSystem, |
| 1095 | BadPathName, | 1095 | BadPathName, |
| 1096 | DeviceBusy, | ||
| 1096 | 1097 | ||
| 1097 | /// On Windows, file paths must be valid Unicode. | 1098 | /// On Windows, file paths must be valid Unicode. |
| 1098 | InvalidUtf8, | 1099 | InvalidUtf8, |
test/behavior.zig+1| ... | @@ -42,6 +42,7 @@ comptime { | ... | @@ -42,6 +42,7 @@ comptime { |
| 42 | _ = @import("cases/if.zig"); | 42 | _ = @import("cases/if.zig"); |
| 43 | _ = @import("cases/import.zig"); | 43 | _ = @import("cases/import.zig"); |
| 44 | _ = @import("cases/incomplete_struct_param_tld.zig"); | 44 | _ = @import("cases/incomplete_struct_param_tld.zig"); |
| 45 | _ = @import("cases/inttoptr.zig"); | ||
| 45 | _ = @import("cases/ir_block_deps.zig"); | 46 | _ = @import("cases/ir_block_deps.zig"); |
| 46 | _ = @import("cases/math.zig"); | 47 | _ = @import("cases/math.zig"); |
| 47 | _ = @import("cases/merge_error_sets.zig"); | 48 | _ = @import("cases/merge_error_sets.zig"); |
test/cases/inttoptr.zig created+13| ... | @@ -0,0 +1,13 @@ | ||
| 1 | const builtin = @import("builtin"); | ||
| 2 | const std = @import("std"); | ||
| 3 | const assertOrPanic = std.debug.assertOrPanic; | ||
| 4 | |||
| 5 | test "casting random address to function pointer" { | ||
| 6 | randomAddressToFunction(); | ||
| 7 | comptime randomAddressToFunction(); | ||
| 8 | } | ||
| 9 | |||
| 10 | fn randomAddressToFunction() void { | ||
| 11 | var addr: usize = 0xdeadbeef; | ||
| 12 | var ptr = @intToPtr(fn () void, addr); | ||
| 13 | } | ||
test/cases/ptrcast.zig+19| ... | @@ -15,3 +15,22 @@ fn testReinterpretBytesAsInteger() void { | ... | @@ -15,3 +15,22 @@ fn testReinterpretBytesAsInteger() void { |
| 15 | }; | 15 | }; |
| 16 | assertOrPanic(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected); | 16 | assertOrPanic(@ptrCast(*align(1) const u32, bytes[1..5].ptr).* == expected); |
| 17 | } | 17 | } |
| 18 | |||
| 19 | test "reinterpret bytes of an array into an extern struct" { | ||
| 20 | testReinterpretBytesAsExternStruct(); | ||
| 21 | comptime testReinterpretBytesAsExternStruct(); | ||
| 22 | } | ||
| 23 | |||
| 24 | fn testReinterpretBytesAsExternStruct() void { | ||
| 25 | var bytes align(2) = []u8{ 1, 2, 3, 4, 5, 6 }; | ||
| 26 | |||
| 27 | const S = extern struct { | ||
| 28 | a: u8, | ||
| 29 | b: u16, | ||
| 30 | c: u8, | ||
| 31 | }; | ||
| 32 | |||
| 33 | var ptr = @ptrCast(*const S, &bytes); | ||
| 34 | var val = ptr.c; | ||
| 35 | assertOrPanic(val == 5); | ||
| 36 | } |
test/cases/struct_contains_slice_of_itself.zig+42| ... | @@ -5,6 +5,11 @@ const Node = struct { | ... | @@ -5,6 +5,11 @@ const Node = struct { |
| 5 | children: []Node, | 5 | children: []Node, |
| 6 | }; | 6 | }; |
| 7 | 7 | ||
| 8 | const NodeAligned = struct { | ||
| 9 | payload: i32, | ||
| 10 | children: []align(@alignOf(NodeAligned)) NodeAligned, | ||
| 11 | }; | ||
| 12 | |||
| 8 | test "struct contains slice of itself" { | 13 | test "struct contains slice of itself" { |
| 9 | var other_nodes = []Node{ | 14 | var other_nodes = []Node{ |
| 10 | Node{ | 15 | Node{ |
| ... | @@ -41,3 +46,40 @@ test "struct contains slice of itself" { | ... | @@ -41,3 +46,40 @@ test "struct contains slice of itself" { |
| 41 | assert(root.children[2].children[0].payload == 31); | 46 | assert(root.children[2].children[0].payload == 31); |
| 42 | assert(root.children[2].children[1].payload == 32); | 47 | assert(root.children[2].children[1].payload == 32); |
| 43 | } | 48 | } |
| 49 | |||
| 50 | test "struct contains aligned slice of itself" { | ||
| 51 | var other_nodes = []NodeAligned{ | ||
| 52 | NodeAligned{ | ||
| 53 | .payload = 31, | ||
| 54 | .children = []NodeAligned{}, | ||
| 55 | }, | ||
| 56 | NodeAligned{ | ||
| 57 | .payload = 32, | ||
| 58 | .children = []NodeAligned{}, | ||
| 59 | }, | ||
| 60 | }; | ||
| 61 | var nodes = []NodeAligned{ | ||
| 62 | NodeAligned{ | ||
| 63 | .payload = 1, | ||
| 64 | .children = []NodeAligned{}, | ||
| 65 | }, | ||
| 66 | NodeAligned{ | ||
| 67 | .payload = 2, | ||
| 68 | .children = []NodeAligned{}, | ||
| 69 | }, | ||
| 70 | NodeAligned{ | ||
| 71 | .payload = 3, | ||
| 72 | .children = other_nodes[0..], | ||
| 73 | }, | ||
| 74 | }; | ||
| 75 | const root = NodeAligned{ | ||
| 76 | .payload = 1234, | ||
| 77 | .children = nodes[0..], | ||
| 78 | }; | ||
| 79 | assert(root.payload == 1234); | ||
| 80 | assert(root.children[0].payload == 1); | ||
| 81 | assert(root.children[1].payload == 2); | ||
| 82 | assert(root.children[2].payload == 3); | ||
| 83 | assert(root.children[2].children[0].payload == 31); | ||
| 84 | assert(root.children[2].children[1].payload == 32); | ||
| 85 | } |
test/cases/type_info.zig+10-5| ... | @@ -144,15 +144,20 @@ test "type info: enum info" { | ... | @@ -144,15 +144,20 @@ test "type info: enum info" { |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | fn testEnum() void { | 146 | fn testEnum() void { |
| 147 | const Os = @import("builtin").Os; | 147 | const Os = enum { |
| 148 | Windows, | ||
| 149 | Macos, | ||
| 150 | Linux, | ||
| 151 | FreeBSD, | ||
| 152 | }; | ||
| 148 | 153 | ||
| 149 | const os_info = @typeInfo(Os); | 154 | const os_info = @typeInfo(Os); |
| 150 | assert(TypeId(os_info) == TypeId.Enum); | 155 | assert(TypeId(os_info) == TypeId.Enum); |
| 151 | assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto); | 156 | assert(os_info.Enum.layout == TypeInfo.ContainerLayout.Auto); |
| 152 | assert(os_info.Enum.fields.len == 32); | 157 | assert(os_info.Enum.fields.len == 4); |
| 153 | assert(mem.eql(u8, os_info.Enum.fields[1].name, "ananas")); | 158 | assert(mem.eql(u8, os_info.Enum.fields[1].name, "Macos")); |
| 154 | assert(os_info.Enum.fields[10].value == 10); | 159 | assert(os_info.Enum.fields[3].value == 3); |
| 155 | assert(os_info.Enum.tag_type == u5); | 160 | assert(os_info.Enum.tag_type == u2); |
| 156 | assert(os_info.Enum.defs.len == 0); | 161 | assert(os_info.Enum.defs.len == 0); |
| 157 | } | 162 | } |
| 158 | 163 |