| author | |
| committer | |
| log | 6dba1f1c8eee5e2f037c7ef216bc64423aef8e00 |
| tree | f39a29e98b7e3404b114aaa08cd26d767a1666c1 |
| parent | ca180d3f02914d282505752a1d2fe08e175f9d99 |
* `@truncate` builtin allows casting to the same size integer.
It also performs two's complement casting between signed and
unsigned integers.
* The idiomatic way to convert between bytes and numbers is now
`mem.readInt` and `mem.writeInt` instead of an unsafe cast.
It works at compile time, is safer, and looks cleaner.
* Implicitly casting an array to a slice is allowed only if the
slice is const.
* Constant pointer values know if their memory is from a compile-
time constant value or a compile-time variable.
* Cast from [N]u8 to []T no longer allowed, but [N]u8 to []const T
still allowed.
* Fix inability to pass a mutable pointer to comptime variable at
compile-time to a function and have the function modify the
memory pointed to by the pointer.
* Add the `comptime T: type` parameter back to mem.eql. Prevents
accidentally creating instantiations for arrays.24 files changed, 460 insertions(+), 288 deletions(-)
doc/langref.md+19| ... | @@ -637,6 +637,25 @@ const b: u8 = @truncate(u8, a); | ... | @@ -637,6 +637,25 @@ const b: u8 = @truncate(u8, a); |
| 637 | // b is now 0xcd | 637 | // b is now 0xcd |
| 638 | ``` | 638 | ``` |
| 639 | 639 | ||
| 640 | This function always truncates the significant bits of the integer, regardless | ||
| 641 | of endianness on the target platform. | ||
| 642 | |||
| 643 | This function also performs a twos complement cast. For example, the following | ||
| 644 | produces a crash in debug mode and undefined behavior in release mode: | ||
| 645 | |||
| 646 | ```zig | ||
| 647 | const a = i16(-1); | ||
| 648 | const b = u16(a); | ||
| 649 | ``` | ||
| 650 | |||
| 651 | However this is well defined and working code: | ||
| 652 | |||
| 653 | ```zig | ||
| 654 | const a = i16(-1); | ||
| 655 | const b = @truncate(u16, a); | ||
| 656 | // b is now 0xffff | ||
| 657 | ``` | ||
| 658 | |||
| 640 | ### @compileError(comptime msg: []u8) | 659 | ### @compileError(comptime msg: []u8) |
| 641 | 660 | ||
| 642 | This function, when semantically analyzed, causes a compile error with the | 661 | This function, when semantically analyzed, causes a compile error with the |
example/guess_number/main.zig+4-3| ... | @@ -6,10 +6,11 @@ const os = std.os; | ... | @@ -6,10 +6,11 @@ const os = std.os; |
| 6 | pub fn main(args: [][]u8) -> %void { | 6 | pub fn main(args: [][]u8) -> %void { |
| 7 | %%io.stdout.printf("Welcome to the Guess Number Game in Zig.\n"); | 7 | %%io.stdout.printf("Welcome to the Guess Number Game in Zig.\n"); |
| 8 | 8 | ||
| 9 | var seed: [@sizeOf(usize)]u8 = undefined; | 9 | var seed_bytes: [@sizeOf(usize)]u8 = undefined; |
| 10 | %%os.getRandomBytes(seed); | 10 | %%os.getRandomBytes(seed_bytes[0...]); |
| 11 | const seed = std.mem.readInt(seed_bytes, usize, true); | ||
| 11 | var rand: Rand = undefined; | 12 | var rand: Rand = undefined; |
| 12 | rand.init(([]usize)(seed)[0]); | 13 | rand.init(seed); |
| 13 | 14 | ||
| 14 | const answer = rand.rangeUnsigned(u8, 0, 100) + 1; | 15 | const answer = rand.rangeUnsigned(u8, 0, 100) + 1; |
| 15 | 16 |
src/all_types.hpp+13-3| ... | @@ -119,11 +119,21 @@ enum ConstPtrSpecial { | ... | @@ -119,11 +119,21 @@ enum ConstPtrSpecial { |
| 119 | ConstPtrSpecialHardCodedAddr, | 119 | ConstPtrSpecialHardCodedAddr, |
| 120 | }; | 120 | }; |
| 121 | 121 | ||
| 122 | struct ConstPtrValue { | 122 | enum ConstPtrMut { |
| 123 | ConstPtrSpecial special; | 123 | // The pointer points to memory that is known at compile time and immutable. |
| 124 | ConstPtrMutComptimeConst, | ||
| 124 | // This means that the pointer points to memory used by a comptime variable, | 125 | // This means that the pointer points to memory used by a comptime variable, |
| 125 | // so attempting to write a non-compile-time known value is an error | 126 | // so attempting to write a non-compile-time known value is an error |
| 126 | bool comptime_var_mem; | 127 | // But the underlying value is allowed to change at compile time. |
| 128 | ConstPtrMutComptimeVar, | ||
| 129 | // The pointer points to memory that is known only at runtime. | ||
| 130 | // For example it may point to the initializer value of a variable. | ||
| 131 | ConstPtrMutRuntimeVar, | ||
| 132 | }; | ||
| 133 | |||
| 134 | struct ConstPtrValue { | ||
| 135 | ConstPtrSpecial special; | ||
| 136 | ConstPtrMut mut; | ||
| 127 | 137 | ||
| 128 | union { | 138 | union { |
| 129 | struct { | 139 | struct { |
src/analyze.cpp+13-2| ... | @@ -2833,7 +2833,18 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { | ... | @@ -2833,7 +2833,18 @@ static uint32_t hash_const_val(ConstExprValue *const_val) { |
| 2833 | const_val->data.x_arg_tuple.end_index * 2290442768; | 2833 | const_val->data.x_arg_tuple.end_index * 2290442768; |
| 2834 | case TypeTableEntryIdPointer: | 2834 | case TypeTableEntryIdPointer: |
| 2835 | { | 2835 | { |
| 2836 | uint32_t hash_val = const_val->data.x_ptr.comptime_var_mem ? 2216297012 : 170810250; | 2836 | uint32_t hash_val = 0; |
| 2837 | switch (const_val->data.x_ptr.mut) { | ||
| 2838 | case ConstPtrMutRuntimeVar: | ||
| 2839 | hash_val += 3500721036; | ||
| 2840 | break; | ||
| 2841 | case ConstPtrMutComptimeConst: | ||
| 2842 | hash_val += 4214318515; | ||
| 2843 | break; | ||
| 2844 | case ConstPtrMutComptimeVar: | ||
| 2845 | hash_val += 1103195694; | ||
| 2846 | break; | ||
| 2847 | } | ||
| 2837 | switch (const_val->data.x_ptr.special) { | 2848 | switch (const_val->data.x_ptr.special) { |
| 2838 | case ConstPtrSpecialInvalid: | 2849 | case ConstPtrSpecialInvalid: |
| 2839 | zig_unreachable(); | 2850 | zig_unreachable(); |
| ... | @@ -3339,7 +3350,7 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { | ... | @@ -3339,7 +3350,7 @@ bool const_values_equal(ConstExprValue *a, ConstExprValue *b) { |
| 3339 | case TypeTableEntryIdPointer: | 3350 | case TypeTableEntryIdPointer: |
| 3340 | if (a->data.x_ptr.special != b->data.x_ptr.special) | 3351 | if (a->data.x_ptr.special != b->data.x_ptr.special) |
| 3341 | return false; | 3352 | return false; |
| 3342 | if (a->data.x_ptr.comptime_var_mem != b->data.x_ptr.comptime_var_mem) | 3353 | if (a->data.x_ptr.mut != b->data.x_ptr.mut) |
| 3343 | return false; | 3354 | return false; |
| 3344 | switch (a->data.x_ptr.special) { | 3355 | switch (a->data.x_ptr.special) { |
| 3345 | case ConstPtrSpecialInvalid: | 3356 | case ConstPtrSpecialInvalid: |
src/codegen.cpp+17-5| ... | @@ -1859,9 +1859,18 @@ static LLVMValueRef ir_render_div_exact(CodeGen *g, IrExecutable *executable, Ir | ... | @@ -1859,9 +1859,18 @@ static LLVMValueRef ir_render_div_exact(CodeGen *g, IrExecutable *executable, Ir |
| 1859 | } | 1859 | } |
| 1860 | 1860 | ||
| 1861 | static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutable *executable, IrInstructionTruncate *instruction) { | 1861 | static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutable *executable, IrInstructionTruncate *instruction) { |
| 1862 | TypeTableEntry *dest_type = get_underlying_type(instruction->base.value.type); | ||
| 1863 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); | 1862 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); |
| 1864 | return LLVMBuildTrunc(g->builder, target_val, dest_type->type_ref, ""); | 1863 | TypeTableEntry *dest_type = get_underlying_type(instruction->base.value.type); |
| 1864 | TypeTableEntry *src_type = get_underlying_type(instruction->target->value.type); | ||
| 1865 | if (dest_type == src_type) { | ||
| 1866 | // no-op | ||
| 1867 | return target_val; | ||
| 1868 | } if (src_type->data.integral.bit_count == dest_type->data.integral.bit_count) { | ||
| 1869 | return LLVMBuildBitCast(g->builder, target_val, dest_type->type_ref, ""); | ||
| 1870 | } else { | ||
| 1871 | LLVMValueRef target_val = ir_llvm_value(g, instruction->target); | ||
| 1872 | return LLVMBuildTrunc(g->builder, target_val, dest_type->type_ref, ""); | ||
| 1873 | } | ||
| 1865 | } | 1874 | } |
| 1866 | 1875 | ||
| 1867 | static LLVMValueRef ir_render_alloca(CodeGen *g, IrExecutable *executable, IrInstructionAlloca *instruction) { | 1876 | static LLVMValueRef ir_render_alloca(CodeGen *g, IrExecutable *executable, IrInstructionAlloca *instruction) { |
| ... | @@ -1945,10 +1954,14 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns | ... | @@ -1945,10 +1954,14 @@ static LLVMValueRef ir_render_memcpy(CodeGen *g, IrExecutable *executable, IrIns |
| 1945 | static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInstructionSlice *instruction) { | 1954 | static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInstructionSlice *instruction) { |
| 1946 | assert(instruction->tmp_ptr); | 1955 | assert(instruction->tmp_ptr); |
| 1947 | 1956 | ||
| 1948 | TypeTableEntry *array_type = get_underlying_type(instruction->ptr->value.type); | 1957 | LLVMValueRef array_ptr_ptr = ir_llvm_value(g, instruction->ptr); |
| 1958 | TypeTableEntry *array_ptr_type = instruction->ptr->value.type; | ||
| 1959 | assert(array_ptr_type->id == TypeTableEntryIdPointer); | ||
| 1960 | bool is_volatile = array_ptr_type->data.pointer.is_volatile; | ||
| 1961 | TypeTableEntry *array_type = array_ptr_type->data.pointer.child_type; | ||
| 1962 | LLVMValueRef array_ptr = get_handle_value(g, array_ptr_ptr, array_type, is_volatile); | ||
| 1949 | 1963 | ||
| 1950 | LLVMValueRef tmp_struct_ptr = instruction->tmp_ptr; | 1964 | LLVMValueRef tmp_struct_ptr = instruction->tmp_ptr; |
| 1951 | LLVMValueRef array_ptr = ir_llvm_value(g, instruction->ptr); | ||
| 1952 | 1965 | ||
| 1953 | bool want_debug_safety = instruction->safety_check_on && ir_want_debug_safety(g, &instruction->base); | 1966 | bool want_debug_safety = instruction->safety_check_on && ir_want_debug_safety(g, &instruction->base); |
| 1954 | 1967 | ||
| ... | @@ -2582,7 +2595,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { | ... | @@ -2582,7 +2595,6 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val) { |
| 2582 | return LLVMGetUndef(canon_type->type_ref); | 2595 | return LLVMGetUndef(canon_type->type_ref); |
| 2583 | case ConstValSpecialStatic: | 2596 | case ConstValSpecialStatic: |
| 2584 | break; | 2597 | break; |
| 2585 | |||
| 2586 | } | 2598 | } |
| 2587 | 2599 | ||
| 2588 | switch (canon_type->id) { | 2600 | switch (canon_type->id) { |
src/ir.cpp+153-109| ... | @@ -1480,15 +1480,6 @@ static IrInstruction *ir_build_ref(IrBuilder *irb, Scope *scope, AstNode *source | ... | @@ -1480,15 +1480,6 @@ static IrInstruction *ir_build_ref(IrBuilder *irb, Scope *scope, AstNode *source |
| 1480 | return &instruction->base; | 1480 | return &instruction->base; |
| 1481 | } | 1481 | } |
| 1482 | 1482 | ||
| 1483 | static IrInstruction *ir_build_ref_from(IrBuilder *irb, IrInstruction *old_instruction, IrInstruction *value, | ||
| 1484 | bool is_const, bool is_volatile) | ||
| 1485 | { | ||
| 1486 | IrInstruction *new_instruction = ir_build_ref(irb, old_instruction->scope, old_instruction->source_node, | ||
| 1487 | value, is_const, is_volatile); | ||
| 1488 | ir_link_new_instruction(new_instruction, old_instruction); | ||
| 1489 | return new_instruction; | ||
| 1490 | } | ||
| 1491 | |||
| 1492 | static IrInstruction *ir_build_min_value(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { | 1483 | static IrInstruction *ir_build_min_value(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) { |
| 1493 | IrInstructionMinValue *instruction = ir_build_instruction<IrInstructionMinValue>(irb, scope, source_node); | 1484 | IrInstructionMinValue *instruction = ir_build_instruction<IrInstructionMinValue>(irb, scope, source_node); |
| 1494 | instruction->value = value; | 1485 | instruction->value = value; |
| ... | @@ -5290,7 +5281,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node) | ... | @@ -5290,7 +5281,7 @@ static IrInstruction *ir_gen_slice(IrBuilder *irb, Scope *scope, AstNode *node) |
| 5290 | AstNode *start_node = slice_expr->start; | 5281 | AstNode *start_node = slice_expr->start; |
| 5291 | AstNode *end_node = slice_expr->end; | 5282 | AstNode *end_node = slice_expr->end; |
| 5292 | 5283 | ||
| 5293 | IrInstruction *ptr_value = ir_gen_node(irb, array_node, scope); | 5284 | IrInstruction *ptr_value = ir_gen_node_extra(irb, array_node, scope, LVAL_PTR); |
| 5294 | if (ptr_value == irb->codegen->invalid_instruction) | 5285 | if (ptr_value == irb->codegen->invalid_instruction) |
| 5295 | return irb->codegen->invalid_instruction; | 5286 | return irb->codegen->invalid_instruction; |
| 5296 | 5287 | ||
| ... | @@ -5822,12 +5813,16 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, | ... | @@ -5822,12 +5813,16 @@ static ImplicitCastMatchResult ir_types_match_with_implicit_cast(IrAnalyze *ira, |
| 5822 | // implicit array to slice conversion | 5813 | // implicit array to slice conversion |
| 5823 | if (expected_type->id == TypeTableEntryIdStruct && | 5814 | if (expected_type->id == TypeTableEntryIdStruct && |
| 5824 | expected_type->data.structure.is_slice && | 5815 | expected_type->data.structure.is_slice && |
| 5825 | actual_type->id == TypeTableEntryIdArray && | 5816 | actual_type->id == TypeTableEntryIdArray) |
| 5826 | types_match_const_cast_only( | ||
| 5827 | expected_type->data.structure.fields[0].type_entry->data.pointer.child_type, | ||
| 5828 | actual_type->data.array.child_type)) | ||
| 5829 | { | 5817 | { |
| 5830 | return ImplicitCastMatchResultYes; | 5818 | TypeTableEntry *ptr_type = expected_type->data.structure.fields[slice_ptr_index].type_entry; |
| 5819 | assert(ptr_type->id == TypeTableEntryIdPointer); | ||
| 5820 | |||
| 5821 | if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) && | ||
| 5822 | types_match_const_cast_only(ptr_type->data.pointer.child_type, actual_type->data.array.child_type)) | ||
| 5823 | { | ||
| 5824 | return ImplicitCastMatchResultYes; | ||
| 5825 | } | ||
| 5831 | } | 5826 | } |
| 5832 | 5827 | ||
| 5833 | // implicit number literal to typed number | 5828 | // implicit number literal to typed number |
| ... | @@ -6180,7 +6175,7 @@ static TypeTableEntry *ir_finish_anal(IrAnalyze *ira, TypeTableEntry *result_typ | ... | @@ -6180,7 +6175,7 @@ static TypeTableEntry *ir_finish_anal(IrAnalyze *ira, TypeTableEntry *result_typ |
| 6180 | return result_type; | 6175 | return result_type; |
| 6181 | } | 6176 | } |
| 6182 | 6177 | ||
| 6183 | static ConstExprValue *ir_build_const_from(IrAnalyze *ira, IrInstruction *old_instruction) { | 6178 | static IrInstruction *ir_get_const(IrAnalyze *ira, IrInstruction *old_instruction) { |
| 6184 | IrInstruction *new_instruction; | 6179 | IrInstruction *new_instruction; |
| 6185 | if (old_instruction->id == IrInstructionIdVarPtr) { | 6180 | if (old_instruction->id == IrInstructionIdVarPtr) { |
| 6186 | IrInstructionVarPtr *old_var_ptr_instruction = (IrInstructionVarPtr *)old_instruction; | 6181 | IrInstructionVarPtr *old_var_ptr_instruction = (IrInstructionVarPtr *)old_instruction; |
| ... | @@ -6201,10 +6196,14 @@ static ConstExprValue *ir_build_const_from(IrAnalyze *ira, IrInstruction *old_in | ... | @@ -6201,10 +6196,14 @@ static ConstExprValue *ir_build_const_from(IrAnalyze *ira, IrInstruction *old_in |
| 6201 | old_instruction->scope, old_instruction->source_node); | 6196 | old_instruction->scope, old_instruction->source_node); |
| 6202 | new_instruction = &const_instruction->base; | 6197 | new_instruction = &const_instruction->base; |
| 6203 | } | 6198 | } |
| 6199 | new_instruction->value.special = ConstValSpecialStatic; | ||
| 6200 | return new_instruction; | ||
| 6201 | } | ||
| 6202 | |||
| 6203 | static ConstExprValue *ir_build_const_from(IrAnalyze *ira, IrInstruction *old_instruction) { | ||
| 6204 | IrInstruction *new_instruction = ir_get_const(ira, old_instruction); | ||
| 6204 | ir_link_new_instruction(new_instruction, old_instruction); | 6205 | ir_link_new_instruction(new_instruction, old_instruction); |
| 6205 | ConstExprValue *const_val = &new_instruction->value; | 6206 | return &new_instruction->value; |
| 6206 | const_val->special = ConstValSpecialStatic; | ||
| 6207 | return const_val; | ||
| 6208 | } | 6207 | } |
| 6209 | 6208 | ||
| 6210 | static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instruction) { | 6209 | static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instruction) { |
| ... | @@ -6212,33 +6211,47 @@ static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instructio | ... | @@ -6212,33 +6211,47 @@ static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instructio |
| 6212 | return ira->codegen->builtin_types.entry_void; | 6211 | return ira->codegen->builtin_types.entry_void; |
| 6213 | } | 6212 | } |
| 6214 | 6213 | ||
| 6215 | static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction, | 6214 | static IrInstruction *ir_get_const_ptr(IrAnalyze *ira, IrInstruction *instruction, |
| 6216 | ConstExprValue *pointee, TypeTableEntry *pointee_type, | 6215 | ConstExprValue *pointee, TypeTableEntry *pointee_type, |
| 6217 | bool comptime_var_mem, bool ptr_is_const, bool ptr_is_volatile) | 6216 | ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile) |
| 6218 | { | 6217 | { |
| 6219 | if (pointee_type->id == TypeTableEntryIdMetaType) { | 6218 | if (pointee_type->id == TypeTableEntryIdMetaType) { |
| 6220 | TypeTableEntry *type_entry = pointee->data.x_type; | 6219 | TypeTableEntry *type_entry = pointee->data.x_type; |
| 6221 | if (type_entry->id == TypeTableEntryIdUnreachable) { | 6220 | if (type_entry->id == TypeTableEntryIdUnreachable) { |
| 6222 | ir_add_error(ira, instruction, buf_sprintf("pointer to unreachable not allowed")); | 6221 | ir_add_error(ira, instruction, buf_sprintf("pointer to unreachable not allowed")); |
| 6223 | return ira->codegen->builtin_types.entry_invalid; | 6222 | return ira->codegen->invalid_instruction; |
| 6224 | } | 6223 | } |
| 6225 | 6224 | ||
| 6226 | ConstExprValue *const_val = ir_build_const_from(ira, instruction); | 6225 | IrInstruction *const_instr = ir_get_const(ira, instruction); |
| 6226 | ConstExprValue *const_val = &const_instr->value; | ||
| 6227 | const_val->type = pointee_type; | ||
| 6227 | type_ensure_zero_bits_known(ira->codegen, type_entry); | 6228 | type_ensure_zero_bits_known(ira->codegen, type_entry); |
| 6228 | const_val->data.x_type = get_pointer_to_type_volatile(ira->codegen, type_entry, | 6229 | const_val->data.x_type = get_pointer_to_type_volatile(ira->codegen, type_entry, |
| 6229 | ptr_is_const, ptr_is_volatile); | 6230 | ptr_is_const, ptr_is_volatile); |
| 6230 | return pointee_type; | 6231 | return const_instr; |
| 6231 | } else { | 6232 | } else { |
| 6232 | TypeTableEntry *ptr_type = get_pointer_to_type_volatile(ira->codegen, pointee_type, | 6233 | TypeTableEntry *ptr_type = get_pointer_to_type_volatile(ira->codegen, pointee_type, |
| 6233 | ptr_is_const, ptr_is_volatile); | 6234 | ptr_is_const, ptr_is_volatile); |
| 6234 | ConstExprValue *const_val = ir_build_const_from(ira, instruction); | 6235 | IrInstruction *const_instr = ir_get_const(ira, instruction); |
| 6236 | ConstExprValue *const_val = &const_instr->value; | ||
| 6237 | const_val->type = ptr_type; | ||
| 6235 | const_val->data.x_ptr.special = ConstPtrSpecialRef; | 6238 | const_val->data.x_ptr.special = ConstPtrSpecialRef; |
| 6236 | const_val->data.x_ptr.comptime_var_mem = comptime_var_mem; | 6239 | const_val->data.x_ptr.mut = ptr_mut; |
| 6237 | const_val->data.x_ptr.data.ref.pointee = pointee; | 6240 | const_val->data.x_ptr.data.ref.pointee = pointee; |
| 6238 | return ptr_type; | 6241 | return const_instr; |
| 6239 | } | 6242 | } |
| 6240 | } | 6243 | } |
| 6241 | 6244 | ||
| 6245 | static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction, | ||
| 6246 | ConstExprValue *pointee, TypeTableEntry *pointee_type, | ||
| 6247 | ConstPtrMut ptr_mut, bool ptr_is_const, bool ptr_is_volatile) | ||
| 6248 | { | ||
| 6249 | IrInstruction *const_instr = ir_get_const_ptr(ira, instruction, pointee, | ||
| 6250 | pointee_type, ptr_mut, ptr_is_const, ptr_is_volatile); | ||
| 6251 | ir_link_new_instruction(const_instr, instruction); | ||
| 6252 | return const_instr->value.type; | ||
| 6253 | } | ||
| 6254 | |||
| 6242 | static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *instruction, uint64_t value) { | 6255 | static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *instruction, uint64_t value) { |
| 6243 | ConstExprValue *const_val = ir_build_const_from(ira, instruction); | 6256 | ConstExprValue *const_val = ir_build_const_from(ira, instruction); |
| 6244 | bignum_init_unsigned(&const_val->data.x_bignum, value); | 6257 | bignum_init_unsigned(&const_val->data.x_bignum, value); |
| ... | @@ -6513,6 +6526,37 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so | ... | @@ -6513,6 +6526,37 @@ static IrInstruction *ir_analyze_null_to_maybe(IrAnalyze *ira, IrInstruction *so |
| 6513 | return &const_instruction->base; | 6526 | return &const_instruction->base; |
| 6514 | } | 6527 | } |
| 6515 | 6528 | ||
| 6529 | static IrInstruction *ir_get_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value, | ||
| 6530 | bool is_const, bool is_volatile) | ||
| 6531 | { | ||
| 6532 | if (value->value.type->id == TypeTableEntryIdInvalid) | ||
| 6533 | return ira->codegen->invalid_instruction; | ||
| 6534 | |||
| 6535 | if (value->id == IrInstructionIdLoadPtr) { | ||
| 6536 | IrInstructionLoadPtr *load_ptr_inst = (IrInstructionLoadPtr *) value; | ||
| 6537 | if (load_ptr_inst->ptr->value.type->data.pointer.is_const) { | ||
| 6538 | return load_ptr_inst->ptr; | ||
| 6539 | } | ||
| 6540 | } | ||
| 6541 | |||
| 6542 | if (instr_is_comptime(value)) { | ||
| 6543 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); | ||
| 6544 | if (!val) | ||
| 6545 | return ira->codegen->invalid_instruction; | ||
| 6546 | return ir_get_const_ptr(ira, source_instruction, val, value->value.type, | ||
| 6547 | ConstPtrMutComptimeConst, is_const, is_volatile); | ||
| 6548 | } | ||
| 6549 | |||
| 6550 | TypeTableEntry *ptr_type = get_pointer_to_type_volatile(ira->codegen, value->value.type, is_const, is_volatile); | ||
| 6551 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); | ||
| 6552 | assert(fn_entry); | ||
| 6553 | IrInstruction *new_instruction = ir_build_ref(&ira->new_irb, source_instruction->scope, | ||
| 6554 | source_instruction->source_node, value, is_const, is_volatile); | ||
| 6555 | new_instruction->value.type = ptr_type; | ||
| 6556 | fn_entry->alloca_list.append(new_instruction); | ||
| 6557 | return new_instruction; | ||
| 6558 | } | ||
| 6559 | |||
| 6516 | static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr, | 6560 | static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr, |
| 6517 | IrInstruction *array, TypeTableEntry *wanted_type) | 6561 | IrInstruction *array, TypeTableEntry *wanted_type) |
| 6518 | { | 6562 | { |
| ... | @@ -6536,19 +6580,14 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s | ... | @@ -6536,19 +6580,14 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s |
| 6536 | source_instr->source_node, ira->codegen->builtin_types.entry_usize); | 6580 | source_instr->source_node, ira->codegen->builtin_types.entry_usize); |
| 6537 | init_const_usize(ira->codegen, &end->value, array_type->data.array.len); | 6581 | init_const_usize(ira->codegen, &end->value, array_type->data.array.len); |
| 6538 | 6582 | ||
| 6539 | bool is_const; | 6583 | IrInstruction *array_ptr = ir_get_ref(ira, source_instr, array, true, false); |
| 6540 | if (array->id == IrInstructionIdLoadPtr) { | ||
| 6541 | IrInstructionLoadPtr *load_ptr_inst = (IrInstructionLoadPtr *) array; | ||
| 6542 | is_const = load_ptr_inst->ptr->value.type->data.pointer.is_const; | ||
| 6543 | } else { | ||
| 6544 | is_const = true; | ||
| 6545 | } | ||
| 6546 | 6584 | ||
| 6547 | IrInstruction *result = ir_build_slice(&ira->new_irb, source_instr->scope, | 6585 | IrInstruction *result = ir_build_slice(&ira->new_irb, source_instr->scope, |
| 6548 | source_instr->source_node, array, start, end, is_const, false); | 6586 | source_instr->source_node, array_ptr, start, end, false, false); |
| 6549 | TypeTableEntry *child_type = array_type->data.array.child_type; | 6587 | TypeTableEntry *child_type = array_type->data.array.child_type; |
| 6550 | result->value.type = get_slice_type(ira->codegen, child_type, is_const); | 6588 | result->value.type = get_slice_type(ira->codegen, child_type, true); |
| 6551 | ir_add_alloca(ira, result, result->value.type); | 6589 | ir_add_alloca(ira, result, result->value.type); |
| 6590 | |||
| 6552 | return result; | 6591 | return result; |
| 6553 | } | 6592 | } |
| 6554 | 6593 | ||
| ... | @@ -6780,29 +6819,31 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst | ... | @@ -6780,29 +6819,31 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst |
| 6780 | } | 6819 | } |
| 6781 | 6820 | ||
| 6782 | // explicit cast from array to slice | 6821 | // explicit cast from array to slice |
| 6783 | if (is_slice(wanted_type) && | 6822 | if (is_slice(wanted_type) && actual_type->id == TypeTableEntryIdArray) { |
| 6784 | actual_type->id == TypeTableEntryIdArray && | 6823 | TypeTableEntry *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry; |
| 6785 | types_match_const_cast_only( | 6824 | assert(ptr_type->id == TypeTableEntryIdPointer); |
| 6786 | wanted_type->data.structure.fields[0].type_entry->data.pointer.child_type, | 6825 | if ((ptr_type->data.pointer.is_const || actual_type->data.array.len == 0) && |
| 6787 | actual_type->data.array.child_type)) | 6826 | types_match_const_cast_only(ptr_type->data.pointer.child_type, actual_type->data.array.child_type)) |
| 6788 | { | 6827 | { |
| 6789 | return ir_analyze_array_to_slice(ira, source_instr, value, wanted_type); | 6828 | return ir_analyze_array_to_slice(ira, source_instr, value, wanted_type); |
| 6829 | } | ||
| 6790 | } | 6830 | } |
| 6791 | 6831 | ||
| 6792 | // explicit cast from []T to []u8 or []u8 to []T | 6832 | // explicit cast from []T to []u8 or []u8 to []T |
| 6793 | if (is_slice(wanted_type) && is_slice(actual_type) && | 6833 | if (is_slice(wanted_type) && is_slice(actual_type) && |
| 6794 | (is_u8(wanted_type->data.structure.fields[0].type_entry->data.pointer.child_type) || | 6834 | (is_u8(wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type) || |
| 6795 | is_u8(actual_type->data.structure.fields[0].type_entry->data.pointer.child_type)) && | 6835 | is_u8(actual_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type)) && |
| 6796 | (wanted_type->data.structure.fields[0].type_entry->data.pointer.is_const || | 6836 | (wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const || |
| 6797 | !actual_type->data.structure.fields[0].type_entry->data.pointer.is_const)) | 6837 | !actual_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const)) |
| 6798 | { | 6838 | { |
| 6799 | if (!ir_emit_global_runtime_side_effect(ira, source_instr)) | 6839 | if (!ir_emit_global_runtime_side_effect(ira, source_instr)) |
| 6800 | return ira->codegen->invalid_instruction; | 6840 | return ira->codegen->invalid_instruction; |
| 6801 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpResizeSlice, true); | 6841 | return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpResizeSlice, true); |
| 6802 | } | 6842 | } |
| 6803 | 6843 | ||
| 6804 | // explicit cast from [N]u8 to []T | 6844 | // explicit cast from [N]u8 to []const T |
| 6805 | if (is_slice(wanted_type) && | 6845 | if (is_slice(wanted_type) && |
| 6846 | wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const && | ||
| 6806 | actual_type->id == TypeTableEntryIdArray && | 6847 | actual_type->id == TypeTableEntryIdArray && |
| 6807 | is_u8(actual_type->data.array.child_type)) | 6848 | is_u8(actual_type->data.array.child_type)) |
| 6808 | { | 6849 | { |
| ... | @@ -7010,9 +7051,9 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc | ... | @@ -7010,9 +7051,9 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 7010 | } else if (type_entry->id == TypeTableEntryIdPointer) { | 7051 | } else if (type_entry->id == TypeTableEntryIdPointer) { |
| 7011 | TypeTableEntry *child_type = type_entry->data.pointer.child_type; | 7052 | TypeTableEntry *child_type = type_entry->data.pointer.child_type; |
| 7012 | if (instr_is_comptime(ptr)) { | 7053 | if (instr_is_comptime(ptr)) { |
| 7013 | // Dereferencing a mutable pointer at compile time is not allowed | 7054 | if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst || |
| 7014 | // unless that pointer is from a comptime variable | 7055 | ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) |
| 7015 | if (type_entry->data.pointer.is_const || ptr->value.data.x_ptr.comptime_var_mem) { | 7056 | { |
| 7016 | ConstExprValue *pointee = const_ptr_pointee(&ptr->value); | 7057 | ConstExprValue *pointee = const_ptr_pointee(&ptr->value); |
| 7017 | if (pointee->special != ConstValSpecialRuntime) { | 7058 | if (pointee->special != ConstValSpecialRuntime) { |
| 7018 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope, | 7059 | IrInstruction *result = ir_create_const(&ira->new_irb, source_instruction->scope, |
| ... | @@ -7053,23 +7094,9 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc | ... | @@ -7053,23 +7094,9 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc |
| 7053 | static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value, | 7094 | static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value, |
| 7054 | bool is_const, bool is_volatile) | 7095 | bool is_const, bool is_volatile) |
| 7055 | { | 7096 | { |
| 7056 | if (value->value.type->id == TypeTableEntryIdInvalid) | 7097 | IrInstruction *result = ir_get_ref(ira, source_instruction, value, is_const, is_volatile); |
| 7057 | return ira->codegen->builtin_types.entry_invalid; | 7098 | ir_link_new_instruction(result, source_instruction); |
| 7058 | 7099 | return result->value.type; | |
| 7059 | if (instr_is_comptime(value)) { | ||
| 7060 | ConstExprValue *val = ir_resolve_const(ira, value, UndefBad); | ||
| 7061 | if (!val) | ||
| 7062 | return ira->codegen->builtin_types.entry_invalid; | ||
| 7063 | return ir_analyze_const_ptr(ira, source_instruction, val, value->value.type, false, is_const, is_volatile); | ||
| 7064 | } | ||
| 7065 | |||
| 7066 | TypeTableEntry *ptr_type = get_pointer_to_type_volatile(ira->codegen, value->value.type, is_const, is_volatile); | ||
| 7067 | FnTableEntry *fn_entry = exec_fn_entry(ira->new_irb.exec); | ||
| 7068 | assert(fn_entry); | ||
| 7069 | IrInstruction *new_instruction = ir_build_ref_from(&ira->new_irb, source_instruction, | ||
| 7070 | value, is_const, is_volatile); | ||
| 7071 | fn_entry->alloca_list.append(new_instruction); | ||
| 7072 | return ptr_type; | ||
| 7073 | } | 7100 | } |
| 7074 | 7101 | ||
| 7075 | static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) { | 7102 | static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) { |
| ... | @@ -8747,8 +8774,16 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc | ... | @@ -8747,8 +8774,16 @@ static TypeTableEntry *ir_analyze_var_ptr(IrAnalyze *ira, IrInstruction *instruc |
| 8747 | bool is_const = (var->value.type->id == TypeTableEntryIdMetaType) ? is_const_ptr : var->src_is_const; | 8774 | bool is_const = (var->value.type->id == TypeTableEntryIdMetaType) ? is_const_ptr : var->src_is_const; |
| 8748 | bool is_volatile = (var->value.type->id == TypeTableEntryIdMetaType) ? is_volatile_ptr : false; | 8775 | bool is_volatile = (var->value.type->id == TypeTableEntryIdMetaType) ? is_volatile_ptr : false; |
| 8749 | if (mem_slot && mem_slot->special != ConstValSpecialRuntime) { | 8776 | if (mem_slot && mem_slot->special != ConstValSpecialRuntime) { |
| 8750 | return ir_analyze_const_ptr(ira, instruction, mem_slot, var->value.type, | 8777 | ConstPtrMut ptr_mut; |
| 8751 | comptime_var_mem, is_const, is_volatile); | 8778 | if (comptime_var_mem) { |
| 8779 | ptr_mut = ConstPtrMutComptimeVar; | ||
| 8780 | } else if (var->gen_is_const) { | ||
| 8781 | ptr_mut = ConstPtrMutComptimeConst; | ||
| 8782 | } else { | ||
| 8783 | assert(!comptime_var_mem); | ||
| 8784 | ptr_mut = ConstPtrMutRuntimeVar; | ||
| 8785 | } | ||
| 8786 | return ir_analyze_const_ptr(ira, instruction, mem_slot, var->value.type, ptr_mut, is_const, is_volatile); | ||
| 8752 | } else { | 8787 | } else { |
| 8753 | ir_build_var_ptr_from(&ira->new_irb, instruction, var, is_const, is_volatile); | 8788 | ir_build_var_ptr_from(&ira->new_irb, instruction, var, is_const, is_volatile); |
| 8754 | type_ensure_zero_bits_known(ira->codegen, var->value.type); | 8789 | type_ensure_zero_bits_known(ira->codegen, var->value.type); |
| ... | @@ -8837,7 +8872,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -8837,7 +8872,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 8837 | is_const, is_volatile); | 8872 | is_const, is_volatile); |
| 8838 | } else { | 8873 | } else { |
| 8839 | return ir_analyze_const_ptr(ira, &elem_ptr_instruction->base, &ira->codegen->const_void_val, | 8874 | return ir_analyze_const_ptr(ira, &elem_ptr_instruction->base, &ira->codegen->const_void_val, |
| 8840 | ira->codegen->builtin_types.entry_void, false, is_const, is_volatile); | 8875 | ira->codegen->builtin_types.entry_void, ConstPtrMutComptimeConst, is_const, is_volatile); |
| 8841 | } | 8876 | } |
| 8842 | } else { | 8877 | } else { |
| 8843 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, | 8878 | ir_add_error_node(ira, elem_ptr_instruction->base.source_node, |
| ... | @@ -8872,8 +8907,8 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -8872,8 +8907,8 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 8872 | array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr)) | 8907 | array_ptr_val->data.x_ptr.special != ConstPtrSpecialHardCodedAddr)) |
| 8873 | { | 8908 | { |
| 8874 | ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base); | 8909 | ConstExprValue *out_val = ir_build_const_from(ira, &elem_ptr_instruction->base); |
| 8875 | out_val->data.x_ptr.comptime_var_mem = array_ptr->value.data.x_ptr.comptime_var_mem; | ||
| 8876 | if (array_type->id == TypeTableEntryIdPointer) { | 8910 | if (array_type->id == TypeTableEntryIdPointer) { |
| 8911 | out_val->data.x_ptr.mut = array_ptr_val->data.x_ptr.mut; | ||
| 8877 | size_t new_index; | 8912 | size_t new_index; |
| 8878 | size_t mem_size; | 8913 | size_t mem_size; |
| 8879 | size_t old_size; | 8914 | size_t old_size; |
| ... | @@ -8926,6 +8961,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -8926,6 +8961,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 8926 | index, slice_len)); | 8961 | index, slice_len)); |
| 8927 | return ira->codegen->builtin_types.entry_invalid; | 8962 | return ira->codegen->builtin_types.entry_invalid; |
| 8928 | } | 8963 | } |
| 8964 | out_val->data.x_ptr.mut = ptr_field->data.x_ptr.mut; | ||
| 8929 | switch (ptr_field->data.x_ptr.special) { | 8965 | switch (ptr_field->data.x_ptr.special) { |
| 8930 | case ConstPtrSpecialInvalid: | 8966 | case ConstPtrSpecialInvalid: |
| 8931 | zig_unreachable(); | 8967 | zig_unreachable(); |
| ... | @@ -8953,6 +8989,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc | ... | @@ -8953,6 +8989,7 @@ static TypeTableEntry *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruc |
| 8953 | } | 8989 | } |
| 8954 | } else if (array_type->id == TypeTableEntryIdArray) { | 8990 | } else if (array_type->id == TypeTableEntryIdArray) { |
| 8955 | out_val->data.x_ptr.special = ConstPtrSpecialBaseArray; | 8991 | out_val->data.x_ptr.special = ConstPtrSpecialBaseArray; |
| 8992 | out_val->data.x_ptr.mut = array_ptr->value.data.x_ptr.mut; | ||
| 8956 | out_val->data.x_ptr.data.base_array.array_val = array_ptr_val; | 8993 | out_val->data.x_ptr.data.base_array.array_val = array_ptr_val; |
| 8957 | out_val->data.x_ptr.data.base_array.elem_index = index; | 8994 | out_val->data.x_ptr.data.base_array.elem_index = index; |
| 8958 | } else { | 8995 | } else { |
| ... | @@ -9023,7 +9060,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field | ... | @@ -9023,7 +9060,7 @@ static TypeTableEntry *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field |
| 9023 | is_const, is_volatile); | 9060 | is_const, is_volatile); |
| 9024 | ConstExprValue *const_val = ir_build_const_from(ira, &field_ptr_instruction->base); | 9061 | ConstExprValue *const_val = ir_build_const_from(ira, &field_ptr_instruction->base); |
| 9025 | const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct; | 9062 | const_val->data.x_ptr.special = ConstPtrSpecialBaseStruct; |
| 9026 | const_val->data.x_ptr.comptime_var_mem = container_ptr->value.data.x_ptr.comptime_var_mem; | 9063 | const_val->data.x_ptr.mut = container_ptr->value.data.x_ptr.mut; |
| 9027 | const_val->data.x_ptr.data.base_struct.struct_val = struct_val; | 9064 | const_val->data.x_ptr.data.base_struct.struct_val = struct_val; |
| 9028 | const_val->data.x_ptr.data.base_struct.field_index = field->src_index; | 9065 | const_val->data.x_ptr.data.base_struct.field_index = field->src_index; |
| 9029 | return ptr_type; | 9066 | return ptr_type; |
| ... | @@ -9088,7 +9125,7 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source | ... | @@ -9088,7 +9125,7 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source |
| 9088 | bool ptr_is_const = true; | 9125 | bool ptr_is_const = true; |
| 9089 | bool ptr_is_volatile = false; | 9126 | bool ptr_is_volatile = false; |
| 9090 | return ir_analyze_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry, | 9127 | return ir_analyze_const_ptr(ira, source_instruction, const_val, fn_entry->type_entry, |
| 9091 | false, ptr_is_const, ptr_is_volatile); | 9128 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); |
| 9092 | } | 9129 | } |
| 9093 | case TldIdTypeDef: | 9130 | case TldIdTypeDef: |
| 9094 | { | 9131 | { |
| ... | @@ -9105,7 +9142,7 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source | ... | @@ -9105,7 +9142,7 @@ static TypeTableEntry *ir_analyze_decl_ref(IrAnalyze *ira, IrInstruction *source |
| 9105 | bool ptr_is_const = true; | 9142 | bool ptr_is_const = true; |
| 9106 | bool ptr_is_volatile = false; | 9143 | bool ptr_is_volatile = false; |
| 9107 | return ir_analyze_const_ptr(ira, source_instruction, const_val, ira->codegen->builtin_types.entry_type, | 9144 | return ir_analyze_const_ptr(ira, source_instruction, const_val, ira->codegen->builtin_types.entry_type, |
| 9108 | false, ptr_is_const, ptr_is_volatile); | 9145 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); |
| 9109 | } | 9146 | } |
| 9110 | } | 9147 | } |
| 9111 | zig_unreachable(); | 9148 | zig_unreachable(); |
| ... | @@ -9148,7 +9185,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -9148,7 +9185,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 9148 | bool ptr_is_const = true; | 9185 | bool ptr_is_const = true; |
| 9149 | bool ptr_is_volatile = false; | 9186 | bool ptr_is_volatile = false; |
| 9150 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val, | 9187 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val, |
| 9151 | usize, false, ptr_is_const, ptr_is_volatile); | 9188 | usize, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); |
| 9152 | } else { | 9189 | } else { |
| 9153 | ir_add_error_node(ira, source_node, | 9190 | ir_add_error_node(ira, source_node, |
| 9154 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), | 9191 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), |
| ... | @@ -9172,7 +9209,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -9172,7 +9209,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 9172 | bool ptr_is_const = true; | 9209 | bool ptr_is_const = true; |
| 9173 | bool ptr_is_volatile = false; | 9210 | bool ptr_is_volatile = false; |
| 9174 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val, | 9211 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, len_val, |
| 9175 | usize, false, ptr_is_const, ptr_is_volatile); | 9212 | usize, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); |
| 9176 | } else { | 9213 | } else { |
| 9177 | ir_add_error_node(ira, source_node, | 9214 | ir_add_error_node(ira, source_node, |
| 9178 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), | 9215 | buf_sprintf("no member named '%s' in '%s'", buf_ptr(field_name), |
| ... | @@ -9211,14 +9248,14 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -9211,14 +9248,14 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 9211 | bool ptr_is_volatile = false; | 9248 | bool ptr_is_volatile = false; |
| 9212 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | 9249 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| 9213 | create_const_enum_tag(child_type, field->value), child_type, | 9250 | create_const_enum_tag(child_type, field->value), child_type, |
| 9214 | false, ptr_is_const, ptr_is_volatile); | 9251 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); |
| 9215 | } else { | 9252 | } else { |
| 9216 | bool ptr_is_const = true; | 9253 | bool ptr_is_const = true; |
| 9217 | bool ptr_is_volatile = false; | 9254 | bool ptr_is_volatile = false; |
| 9218 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | 9255 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| 9219 | create_const_unsigned_negative(child_type->data.enumeration.tag_type, field->value, false), | 9256 | create_const_unsigned_negative(child_type->data.enumeration.tag_type, field->value, false), |
| 9220 | child_type->data.enumeration.tag_type, | 9257 | child_type->data.enumeration.tag_type, |
| 9221 | false, ptr_is_const, ptr_is_volatile); | 9258 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); |
| 9222 | } | 9259 | } |
| 9223 | } | 9260 | } |
| 9224 | } | 9261 | } |
| ... | @@ -9243,7 +9280,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -9243,7 +9280,7 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 9243 | bool ptr_is_const = true; | 9280 | bool ptr_is_const = true; |
| 9244 | bool ptr_is_volatile = false; | 9281 | bool ptr_is_volatile = false; |
| 9245 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, const_val, | 9282 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, const_val, |
| 9246 | child_type, false, ptr_is_const, ptr_is_volatile); | 9283 | child_type, ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); |
| 9247 | } | 9284 | } |
| 9248 | 9285 | ||
| 9249 | ir_add_error(ira, &field_ptr_instruction->base, | 9286 | ir_add_error(ira, &field_ptr_instruction->base, |
| ... | @@ -9257,14 +9294,14 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru | ... | @@ -9257,14 +9294,14 @@ static TypeTableEntry *ir_analyze_instruction_field_ptr(IrAnalyze *ira, IrInstru |
| 9257 | create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int, | 9294 | create_const_unsigned_negative(ira->codegen->builtin_types.entry_num_lit_int, |
| 9258 | child_type->data.integral.bit_count, false), | 9295 | child_type->data.integral.bit_count, false), |
| 9259 | ira->codegen->builtin_types.entry_num_lit_int, | 9296 | ira->codegen->builtin_types.entry_num_lit_int, |
| 9260 | false, ptr_is_const, ptr_is_volatile); | 9297 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); |
| 9261 | } else if (buf_eql_str(field_name, "is_signed")) { | 9298 | } else if (buf_eql_str(field_name, "is_signed")) { |
| 9262 | bool ptr_is_const = true; | 9299 | bool ptr_is_const = true; |
| 9263 | bool ptr_is_volatile = false; | 9300 | bool ptr_is_volatile = false; |
| 9264 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, | 9301 | return ir_analyze_const_ptr(ira, &field_ptr_instruction->base, |
| 9265 | create_const_bool(ira->codegen, child_type->data.integral.is_signed), | 9302 | create_const_bool(ira->codegen, child_type->data.integral.is_signed), |
| 9266 | ira->codegen->builtin_types.entry_bool, | 9303 | ira->codegen->builtin_types.entry_bool, |
| 9267 | false, ptr_is_const, ptr_is_volatile); | 9304 | ConstPtrMutComptimeConst, ptr_is_const, ptr_is_volatile); |
| 9268 | } else { | 9305 | } else { |
| 9269 | ir_add_error(ira, &field_ptr_instruction->base, | 9306 | ir_add_error(ira, &field_ptr_instruction->base, |
| 9270 | buf_sprintf("type '%s' has no member called '%s'", | 9307 | buf_sprintf("type '%s' has no member called '%s'", |
| ... | @@ -9352,8 +9389,8 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru | ... | @@ -9352,8 +9389,8 @@ static TypeTableEntry *ir_analyze_instruction_store_ptr(IrAnalyze *ira, IrInstru |
| 9352 | return ira->codegen->builtin_types.entry_invalid; | 9389 | return ira->codegen->builtin_types.entry_invalid; |
| 9353 | 9390 | ||
| 9354 | if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { | 9391 | if (instr_is_comptime(ptr) && ptr->value.data.x_ptr.special != ConstPtrSpecialHardCodedAddr) { |
| 9355 | bool comptime_var_mem = ptr->value.data.x_ptr.comptime_var_mem; | 9392 | assert(ptr->value.data.x_ptr.mut != ConstPtrMutComptimeConst); |
| 9356 | if (comptime_var_mem) { | 9393 | if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeVar) { |
| 9357 | if (instr_is_comptime(casted_value)) { | 9394 | if (instr_is_comptime(casted_value)) { |
| 9358 | ConstExprValue *dest_val = const_ptr_pointee(&ptr->value); | 9395 | ConstExprValue *dest_val = const_ptr_pointee(&ptr->value); |
| 9359 | if (dest_val->special != ConstValSpecialRuntime) { | 9396 | if (dest_val->special != ConstValSpecialRuntime) { |
| ... | @@ -11170,8 +11207,8 @@ static TypeTableEntry *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruc | ... | @@ -11170,8 +11207,8 @@ static TypeTableEntry *ir_analyze_instruction_truncate(IrAnalyze *ira, IrInstruc |
| 11170 | ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name))); | 11207 | ir_add_error(ira, target, buf_sprintf("expected %s integer type, found '%s'", sign_str, buf_ptr(&src_type->name))); |
| 11171 | // TODO if meta_type is type decl, add note pointing to type decl declaration | 11208 | // TODO if meta_type is type decl, add note pointing to type decl declaration |
| 11172 | return ira->codegen->builtin_types.entry_invalid; | 11209 | return ira->codegen->builtin_types.entry_invalid; |
| 11173 | } else if (canon_src_type->data.integral.bit_count <= canon_dest_type->data.integral.bit_count) { | 11210 | } else if (canon_src_type->data.integral.bit_count < canon_dest_type->data.integral.bit_count) { |
| 11174 | ir_add_error(ira, target, buf_sprintf("type '%s' has same or fewer bits than destination type '%s'", | 11211 | ir_add_error(ira, target, buf_sprintf("type '%s' has fewer bits than destination type '%s'", |
| 11175 | buf_ptr(&src_type->name), buf_ptr(&dest_type->name))); | 11212 | buf_ptr(&src_type->name), buf_ptr(&dest_type->name))); |
| 11176 | // TODO if meta_type is type decl, add note pointing to type decl declaration | 11213 | // TODO if meta_type is type decl, add note pointing to type decl declaration |
| 11177 | return ira->codegen->builtin_types.entry_invalid; | 11214 | return ira->codegen->builtin_types.entry_invalid; |
| ... | @@ -11457,10 +11494,15 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi | ... | @@ -11457,10 +11494,15 @@ static TypeTableEntry *ir_analyze_instruction_memcpy(IrAnalyze *ira, IrInstructi |
| 11457 | } | 11494 | } |
| 11458 | 11495 | ||
| 11459 | static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice *instruction) { | 11496 | static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice *instruction) { |
| 11460 | IrInstruction *ptr = instruction->ptr->other; | 11497 | IrInstruction *ptr_ptr = instruction->ptr->other; |
| 11461 | if (ptr->value.type->id == TypeTableEntryIdInvalid) | 11498 | if (ptr_ptr->value.type->id == TypeTableEntryIdInvalid) |
| 11462 | return ira->codegen->builtin_types.entry_invalid; | 11499 | return ira->codegen->builtin_types.entry_invalid; |
| 11463 | 11500 | ||
| 11501 | TypeTableEntry *ptr_type = ptr_ptr->value.type; | ||
| 11502 | assert(ptr_type->id == TypeTableEntryIdPointer); | ||
| 11503 | TypeTableEntry *non_canon_array_type = ptr_type->data.pointer.child_type; | ||
| 11504 | TypeTableEntry *canon_array_type = get_underlying_type(non_canon_array_type); | ||
| 11505 | |||
| 11464 | IrInstruction *start = instruction->start->other; | 11506 | IrInstruction *start = instruction->start->other; |
| 11465 | if (start->value.type->id == TypeTableEntryIdInvalid) | 11507 | if (start->value.type->id == TypeTableEntryIdInvalid) |
| 11466 | return ira->codegen->builtin_types.entry_invalid; | 11508 | return ira->codegen->builtin_types.entry_invalid; |
| ... | @@ -11482,44 +11524,42 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio | ... | @@ -11482,44 +11524,42 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio |
| 11482 | end = nullptr; | 11524 | end = nullptr; |
| 11483 | } | 11525 | } |
| 11484 | 11526 | ||
| 11485 | TypeTableEntry *array_type = get_underlying_type(ptr->value.type); | ||
| 11486 | |||
| 11487 | TypeTableEntry *return_type; | 11527 | TypeTableEntry *return_type; |
| 11488 | 11528 | ||
| 11489 | if (array_type->id == TypeTableEntryIdArray) { | 11529 | if (canon_array_type->id == TypeTableEntryIdArray) { |
| 11490 | return_type = get_slice_type(ira->codegen, array_type->data.array.child_type, instruction->is_const); | 11530 | return_type = get_slice_type(ira->codegen, canon_array_type->data.array.child_type, instruction->is_const); |
| 11491 | } else if (array_type->id == TypeTableEntryIdPointer) { | 11531 | } else if (canon_array_type->id == TypeTableEntryIdPointer) { |
| 11492 | return_type = get_slice_type(ira->codegen, array_type->data.pointer.child_type, instruction->is_const); | 11532 | return_type = get_slice_type(ira->codegen, canon_array_type->data.pointer.child_type, instruction->is_const); |
| 11493 | if (!end) { | 11533 | if (!end) { |
| 11494 | ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value")); | 11534 | ir_add_error(ira, &instruction->base, buf_sprintf("slice of pointer must include end value")); |
| 11495 | return ira->codegen->builtin_types.entry_invalid; | 11535 | return ira->codegen->builtin_types.entry_invalid; |
| 11496 | } | 11536 | } |
| 11497 | } else if (is_slice(array_type)) { | 11537 | } else if (is_slice(canon_array_type)) { |
| 11498 | return_type = get_slice_type(ira->codegen, | 11538 | return_type = get_slice_type(ira->codegen, |
| 11499 | array_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type, | 11539 | canon_array_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type, |
| 11500 | instruction->is_const); | 11540 | instruction->is_const); |
| 11501 | } else { | 11541 | } else { |
| 11502 | ir_add_error(ira, &instruction->base, | 11542 | ir_add_error(ira, &instruction->base, |
| 11503 | buf_sprintf("slice of non-array type '%s'", buf_ptr(&ptr->value.type->name))); | 11543 | buf_sprintf("slice of non-array type '%s'", buf_ptr(&non_canon_array_type->name))); |
| 11504 | // TODO if this is a typedecl, add error note showing the declaration of the type decl | 11544 | // TODO if this is a typedecl, add error note showing the declaration of the type decl |
| 11505 | return ira->codegen->builtin_types.entry_invalid; | 11545 | return ira->codegen->builtin_types.entry_invalid; |
| 11506 | } | 11546 | } |
| 11507 | 11547 | ||
| 11508 | if (ptr->value.special == ConstValSpecialStatic && | 11548 | if (instr_is_comptime(ptr_ptr) && |
| 11509 | casted_start->value.special == ConstValSpecialStatic && | 11549 | value_is_comptime(&casted_start->value) && |
| 11510 | (!end || end->value.special == ConstValSpecialStatic)) | 11550 | (!end || value_is_comptime(&end->value))) |
| 11511 | { | 11551 | { |
| 11512 | ConstExprValue *array_val; | 11552 | ConstExprValue *array_val; |
| 11513 | ConstExprValue *parent_ptr; | 11553 | ConstExprValue *parent_ptr; |
| 11514 | size_t abs_offset; | 11554 | size_t abs_offset; |
| 11515 | size_t rel_end; | 11555 | size_t rel_end; |
| 11516 | if (array_type->id == TypeTableEntryIdArray) { | 11556 | if (canon_array_type->id == TypeTableEntryIdArray) { |
| 11517 | array_val = &ptr->value; | 11557 | array_val = const_ptr_pointee(&ptr_ptr->value); |
| 11518 | abs_offset = 0; | 11558 | abs_offset = 0; |
| 11519 | rel_end = array_type->data.array.len; | 11559 | rel_end = canon_array_type->data.array.len; |
| 11520 | parent_ptr = nullptr; | 11560 | parent_ptr = nullptr; |
| 11521 | } else if (array_type->id == TypeTableEntryIdPointer) { | 11561 | } else if (canon_array_type->id == TypeTableEntryIdPointer) { |
| 11522 | parent_ptr = &ptr->value; | 11562 | parent_ptr = const_ptr_pointee(&ptr_ptr->value); |
| 11523 | switch (parent_ptr->data.x_ptr.special) { | 11563 | switch (parent_ptr->data.x_ptr.special) { |
| 11524 | case ConstPtrSpecialInvalid: | 11564 | case ConstPtrSpecialInvalid: |
| 11525 | zig_unreachable(); | 11565 | zig_unreachable(); |
| ... | @@ -11539,9 +11579,10 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio | ... | @@ -11539,9 +11579,10 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio |
| 11539 | array_val = nullptr; | 11579 | array_val = nullptr; |
| 11540 | break; | 11580 | break; |
| 11541 | } | 11581 | } |
| 11542 | } else if (is_slice(array_type)) { | 11582 | } else if (is_slice(canon_array_type)) { |
| 11543 | parent_ptr = &ptr->value.data.x_struct.fields[slice_ptr_index]; | 11583 | ConstExprValue *slice_ptr = const_ptr_pointee(&ptr_ptr->value); |
| 11544 | ConstExprValue *len_val = &ptr->value.data.x_struct.fields[slice_len_index]; | 11584 | parent_ptr = &slice_ptr->data.x_struct.fields[slice_ptr_index]; |
| 11585 | ConstExprValue *len_val = &slice_ptr->data.x_struct.fields[slice_len_index]; | ||
| 11545 | 11586 | ||
| 11546 | switch (parent_ptr->data.x_ptr.special) { | 11587 | switch (parent_ptr->data.x_ptr.special) { |
| 11547 | case ConstPtrSpecialInvalid: | 11588 | case ConstPtrSpecialInvalid: |
| ... | @@ -11596,6 +11637,9 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio | ... | @@ -11596,6 +11637,9 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio |
| 11596 | if (array_val) { | 11637 | if (array_val) { |
| 11597 | size_t index = abs_offset + start_scalar; | 11638 | size_t index = abs_offset + start_scalar; |
| 11598 | init_const_ptr_array(ira->codegen, ptr_val, array_val, index, instruction->is_const); | 11639 | init_const_ptr_array(ira->codegen, ptr_val, array_val, index, instruction->is_const); |
| 11640 | if (canon_array_type->id == TypeTableEntryIdArray) { | ||
| 11641 | ptr_val->data.x_ptr.mut = ptr_ptr->value.data.x_ptr.mut; | ||
| 11642 | } | ||
| 11599 | } else { | 11643 | } else { |
| 11600 | switch (parent_ptr->data.x_ptr.special) { | 11644 | switch (parent_ptr->data.x_ptr.special) { |
| 11601 | case ConstPtrSpecialInvalid: | 11645 | case ConstPtrSpecialInvalid: |
| ... | @@ -11620,7 +11664,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio | ... | @@ -11620,7 +11664,7 @@ static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructio |
| 11620 | } | 11664 | } |
| 11621 | } | 11665 | } |
| 11622 | 11666 | ||
| 11623 | IrInstruction *new_instruction = ir_build_slice_from(&ira->new_irb, &instruction->base, ptr, | 11667 | IrInstruction *new_instruction = ir_build_slice_from(&ira->new_irb, &instruction->base, ptr_ptr, |
| 11624 | casted_start, end, instruction->is_const, instruction->safety_check_on); | 11668 | casted_start, end, instruction->is_const, instruction->safety_check_on); |
| 11625 | ir_add_alloca(ira, new_instruction, return_type); | 11669 | ir_add_alloca(ira, new_instruction, return_type); |
| 11626 | 11670 |
std/debug.zig+1-1| ... | @@ -149,7 +149,7 @@ const Constant = struct { | ... | @@ -149,7 +149,7 @@ const Constant = struct { |
| 149 | return error.InvalidDebugInfo; | 149 | return error.InvalidDebugInfo; |
| 150 | if (self.signed) | 150 | if (self.signed) |
| 151 | return error.InvalidDebugInfo; | 151 | return error.InvalidDebugInfo; |
| 152 | return mem.sliceAsInt(self.payload, false, u64); | 152 | return mem.readInt(self.payload, u64, false); |
| 153 | } | 153 | } |
| 154 | }; | 154 | }; |
| 155 | 155 |
std/elf.zig+3-3| ... | @@ -93,8 +93,8 @@ pub const Elf = struct { | ... | @@ -93,8 +93,8 @@ pub const Elf = struct { |
| 93 | elf.auto_close_stream = false; | 93 | elf.auto_close_stream = false; |
| 94 | 94 | ||
| 95 | var magic: [4]u8 = undefined; | 95 | var magic: [4]u8 = undefined; |
| 96 | %return elf.in_stream.readNoEof(magic); | 96 | %return elf.in_stream.readNoEof(magic[0...]); |
| 97 | if (!mem.eql(magic, "\x7fELF")) return error.InvalidFormat; | 97 | if (!mem.eql(u8, magic, "\x7fELF")) return error.InvalidFormat; |
| 98 | 98 | ||
| 99 | elf.is_64 = switch (%return elf.in_stream.readByte()) { | 99 | elf.is_64 = switch (%return elf.in_stream.readByte()) { |
| 100 | 1 => false, | 100 | 1 => false, |
| ... | @@ -236,7 +236,7 @@ pub const Elf = struct { | ... | @@ -236,7 +236,7 @@ pub const Elf = struct { |
| 236 | elf.in_stream.close(); | 236 | elf.in_stream.close(); |
| 237 | } | 237 | } |
| 238 | 238 | ||
| 239 | pub fn findSection(elf: &Elf, name: []u8) -> %?&SectionHeader { | 239 | pub fn findSection(elf: &Elf, name: []const u8) -> %?&SectionHeader { |
| 240 | for (elf.section_headers) |*section| { | 240 | for (elf.section_headers) |*section| { |
| 241 | if (section.sh_type == SHT_NULL) continue; | 241 | if (section.sh_type == SHT_NULL) continue; |
| 242 | 242 |
std/endian.zig+8-10| ... | @@ -1,21 +1,19 @@ | ... | @@ -1,21 +1,19 @@ |
| 1 | pub inline fn swapIfLe(comptime T: type, x: T) -> T { | 1 | const mem = @import("mem.zig"); |
| 2 | |||
| 3 | pub fn swapIfLe(comptime T: type, x: T) -> T { | ||
| 2 | swapIf(false, T, x) | 4 | swapIf(false, T, x) |
| 3 | } | 5 | } |
| 4 | 6 | ||
| 5 | pub inline fn swapIfBe(comptime T: type, x: T) -> T { | 7 | pub fn swapIfBe(comptime T: type, x: T) -> T { |
| 6 | swapIf(true, T, x) | 8 | swapIf(true, T, x) |
| 7 | } | 9 | } |
| 8 | 10 | ||
| 9 | pub inline fn swapIf(is_be: bool, comptime T: type, x: T) -> T { | 11 | pub fn swapIf(is_be: bool, comptime T: type, x: T) -> T { |
| 10 | if (@compileVar("is_big_endian") == is_be) swap(T, x) else x | 12 | if (@compileVar("is_big_endian") == is_be) swap(T, x) else x |
| 11 | } | 13 | } |
| 12 | 14 | ||
| 13 | pub fn swap(comptime T: type, x: T) -> T { | 15 | pub fn swap(comptime T: type, x: T) -> T { |
| 14 | const x_slice = ([]u8)((&const x)[0...1]); | 16 | var buf: [@sizeOf(T)]u8 = undefined; |
| 15 | var result: T = undefined; | 17 | mem.writeInt(buf[0...], x, false); |
| 16 | const result_slice = ([]u8)((&result)[0...1]); | 18 | return mem.readInt(buf, T, true); |
| 17 | for (result_slice) |*b, i| { | ||
| 18 | *b = x_slice[@sizeOf(T) - i - 1]; | ||
| 19 | } | ||
| 20 | return result; | ||
| 21 | } | 19 | } |
std/io.zig+17-18| ... | @@ -6,7 +6,6 @@ const system = switch(@compileVar("os")) { | ... | @@ -6,7 +6,6 @@ const system = switch(@compileVar("os")) { |
| 6 | 6 | ||
| 7 | const errno = @import("errno.zig"); | 7 | const errno = @import("errno.zig"); |
| 8 | const math = @import("math.zig"); | 8 | const math = @import("math.zig"); |
| 9 | const endian = @import("endian.zig"); | ||
| 10 | const debug = @import("debug.zig"); | 9 | const debug = @import("debug.zig"); |
| 11 | const assert = debug.assert; | 10 | const assert = debug.assert; |
| 12 | const os = @import("os.zig"); | 11 | const os = @import("os.zig"); |
| ... | @@ -365,7 +364,7 @@ pub const InStream = struct { | ... | @@ -365,7 +364,7 @@ pub const InStream = struct { |
| 365 | 364 | ||
| 366 | pub fn readByte(is: &InStream) -> %u8 { | 365 | pub fn readByte(is: &InStream) -> %u8 { |
| 367 | var result: [1]u8 = undefined; | 366 | var result: [1]u8 = undefined; |
| 368 | %return is.readNoEof(result); | 367 | %return is.readNoEof(result[0...]); |
| 369 | return result[0]; | 368 | return result[0]; |
| 370 | } | 369 | } |
| 371 | 370 | ||
| ... | @@ -378,10 +377,9 @@ pub const InStream = struct { | ... | @@ -378,10 +377,9 @@ pub const InStream = struct { |
| 378 | } | 377 | } |
| 379 | 378 | ||
| 380 | pub fn readInt(is: &InStream, is_be: bool, comptime T: type) -> %T { | 379 | pub fn readInt(is: &InStream, is_be: bool, comptime T: type) -> %T { |
| 381 | var result: T = undefined; | 380 | var bytes: [@sizeOf(T)]u8 = undefined; |
| 382 | const result_slice = ([]u8)((&result)[0...1]); | 381 | %return is.readNoEof(bytes[0...]); |
| 383 | %return is.readNoEof(result_slice); | 382 | return mem.readInt(bytes, T, is_be); |
| 384 | return endian.swapIf(!is_be, T, result); | ||
| 385 | } | 383 | } |
| 386 | 384 | ||
| 387 | pub fn readVarInt(is: &InStream, is_be: bool, comptime T: type, size: usize) -> %T { | 385 | pub fn readVarInt(is: &InStream, is_be: bool, comptime T: type, size: usize) -> %T { |
| ... | @@ -390,7 +388,7 @@ pub const InStream = struct { | ... | @@ -390,7 +388,7 @@ pub const InStream = struct { |
| 390 | var input_buf: [8]u8 = undefined; | 388 | var input_buf: [8]u8 = undefined; |
| 391 | const input_slice = input_buf[0...size]; | 389 | const input_slice = input_buf[0...size]; |
| 392 | %return is.readNoEof(input_slice); | 390 | %return is.readNoEof(input_slice); |
| 393 | return mem.sliceAsInt(input_slice, is_be, T); | 391 | return mem.readInt(input_slice, T, is_be); |
| 394 | } | 392 | } |
| 395 | 393 | ||
| 396 | pub fn seekForward(is: &InStream, amount: usize) -> %void { | 394 | pub fn seekForward(is: &InStream, amount: usize) -> %void { |
| ... | @@ -589,18 +587,19 @@ fn testParseUnsignedComptime() { | ... | @@ -589,18 +587,19 @@ fn testParseUnsignedComptime() { |
| 589 | fn testBufPrintInt() { | 587 | fn testBufPrintInt() { |
| 590 | @setFnTest(this); | 588 | @setFnTest(this); |
| 591 | 589 | ||
| 592 | var buf: [max_int_digits]u8 = undefined; | 590 | var buffer: [max_int_digits]u8 = undefined; |
| 593 | assert(mem.eql(bufPrintIntToSlice(buf, i32(-12345678), 2, false, 0), "-101111000110000101001110")); | 591 | const buf = buffer[0...]; |
| 594 | assert(mem.eql(bufPrintIntToSlice(buf, i32(-12345678), 10, false, 0), "-12345678")); | 592 | assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 2, false, 0), "-101111000110000101001110")); |
| 595 | assert(mem.eql(bufPrintIntToSlice(buf, i32(-12345678), 16, false, 0), "-bc614e")); | 593 | assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 10, false, 0), "-12345678")); |
| 596 | assert(mem.eql(bufPrintIntToSlice(buf, i32(-12345678), 16, true, 0), "-BC614E")); | 594 | assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, false, 0), "-bc614e")); |
| 595 | assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-12345678), 16, true, 0), "-BC614E")); | ||
| 597 | 596 | ||
| 598 | assert(mem.eql(bufPrintIntToSlice(buf, u32(12345678), 10, true, 0), "12345678")); | 597 | assert(mem.eql(u8, bufPrintIntToSlice(buf, u32(12345678), 10, true, 0), "12345678")); |
| 599 | 598 | ||
| 600 | assert(mem.eql(bufPrintIntToSlice(buf, u32(666), 10, false, 6), "000666")); | 599 | assert(mem.eql(u8, bufPrintIntToSlice(buf, u32(666), 10, false, 6), "000666")); |
| 601 | assert(mem.eql(bufPrintIntToSlice(buf, u32(0x1234), 16, false, 6), "001234")); | 600 | assert(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 6), "001234")); |
| 602 | assert(mem.eql(bufPrintIntToSlice(buf, u32(0x1234), 16, false, 1), "1234")); | 601 | assert(mem.eql(u8, bufPrintIntToSlice(buf, u32(0x1234), 16, false, 1), "1234")); |
| 603 | 602 | ||
| 604 | assert(mem.eql(bufPrintIntToSlice(buf, i32(42), 10, false, 3), "+42")); | 603 | assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(42), 10, false, 3), "+42")); |
| 605 | assert(mem.eql(bufPrintIntToSlice(buf, i32(-42), 10, false, 3), "-42")); | 604 | assert(mem.eql(u8, bufPrintIntToSlice(buf, i32(-42), 10, false, 3), "-42")); |
| 606 | } | 605 | } |
std/mem.zig+78-23| ... | @@ -68,50 +68,105 @@ pub fn cmp(comptime T: type, a: []const T, b: []const T) -> Cmp { | ... | @@ -68,50 +68,105 @@ pub fn cmp(comptime T: type, a: []const T, b: []const T) -> Cmp { |
| 68 | return if (a.len > b.len) Cmp.Greater else if (a.len < b.len) Cmp.Less else Cmp.Equal; | 68 | return if (a.len > b.len) Cmp.Greater else if (a.len < b.len) Cmp.Less else Cmp.Equal; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | pub fn sliceAsInt(buf: []u8, is_be: bool, comptime T: type) -> T { | 71 | /// Compares two slices and returns whether they are equal. |
| 72 | var result: T = undefined; | 72 | pub fn eql(comptime T: type, a: []const T, b: []const T) -> bool { |
| 73 | const result_slice = ([]u8)((&result)[0...1]); | 73 | if (a.len != b.len) return false; |
| 74 | set(u8, result_slice, 0); | 74 | for (a) |item, index| { |
| 75 | const padding = @sizeOf(T) - buf.len; | 75 | if (b[index] != item) return false; |
| 76 | 76 | } | |
| 77 | if (is_be == @compileVar("is_big_endian")) { | 77 | return true; |
| 78 | copy(u8, result_slice, buf); | 78 | } |
| 79 | |||
| 80 | /// Reads an integer from memory with size equal to bytes.len. | ||
| 81 | /// T specifies the return type, which must be large enough to store | ||
| 82 | /// the result. | ||
| 83 | pub fn readInt(bytes: []const u8, comptime T: type, big_endian: bool) -> T { | ||
| 84 | var result: T = 0; | ||
| 85 | if (big_endian) { | ||
| 86 | for (bytes) |b| { | ||
| 87 | result = (result << 8) | b; | ||
| 88 | } | ||
| 79 | } else { | 89 | } else { |
| 80 | for (buf) |b, i| { | 90 | for (bytes) |b, index| { |
| 81 | const index = result_slice.len - i - 1 - padding; | 91 | result = result | (T(b) << T(index * 8)); |
| 82 | result_slice[index] = b; | ||
| 83 | } | 92 | } |
| 84 | } | 93 | } |
| 85 | return result; | 94 | return result; |
| 86 | } | 95 | } |
| 87 | 96 | ||
| 88 | /// Compares two slices and returns whether they are equal. | 97 | /// Writes an integer to memory with size equal to bytes.len. Pads with zeroes |
| 89 | pub fn eql(a: var, b: var) -> bool { | 98 | /// to fill the entire buffer provided. |
| 90 | if (a.len != b.len) return false; | 99 | /// value must be an integer. |
| 91 | for (a) |item, index| { | 100 | pub fn writeInt(buf: []u8, value: var, big_endian: bool) { |
| 92 | if (b[index] != item) return false; | 101 | const uint = @intType(false, @typeOf(value).bit_count); |
| 102 | var bits = @truncate(uint, value); | ||
| 103 | if (big_endian) { | ||
| 104 | var index: usize = buf.len; | ||
| 105 | while (index != 0) { | ||
| 106 | index -= 1; | ||
| 107 | |||
| 108 | buf[index] = @truncate(u8, bits); | ||
| 109 | bits >>= 8; | ||
| 110 | } | ||
| 111 | } else { | ||
| 112 | for (buf) |*b| { | ||
| 113 | *b = @truncate(u8, bits); | ||
| 114 | bits >>= 8; | ||
| 115 | } | ||
| 93 | } | 116 | } |
| 94 | return true; | 117 | assert(bits == 0); |
| 95 | } | 118 | } |
| 96 | 119 | ||
| 97 | fn testStringEquality() { | 120 | fn testStringEquality() { |
| 98 | @setFnTest(this); | 121 | @setFnTest(this); |
| 99 | 122 | ||
| 100 | assert(eql("abcd", "abcd")); | 123 | assert(eql(u8, "abcd", "abcd")); |
| 101 | assert(!eql("abcdef", "abZdef")); | 124 | assert(!eql(u8, "abcdef", "abZdef")); |
| 102 | assert(!eql("abcdefg", "abcdef")); | 125 | assert(!eql(u8, "abcdefg", "abcdef")); |
| 103 | } | 126 | } |
| 104 | 127 | ||
| 105 | fn testSliceAsInt() { | 128 | fn testReadInt() { |
| 106 | @setFnTest(this); | 129 | @setFnTest(this); |
| 130 | |||
| 131 | testReadIntImpl(); | ||
| 132 | comptime testReadIntImpl(); | ||
| 133 | } | ||
| 134 | fn testReadIntImpl() { | ||
| 135 | { | ||
| 136 | const bytes = []u8{ 0x12, 0x34, 0x56, 0x78 }; | ||
| 137 | assert(readInt(bytes, u32, true) == 0x12345678); | ||
| 138 | assert(readInt(bytes, u32, false) == 0x78563412); | ||
| 139 | } | ||
| 107 | { | 140 | { |
| 108 | const buf = []u8{0x00, 0x00, 0x12, 0x34}; | 141 | const buf = []u8{0x00, 0x00, 0x12, 0x34}; |
| 109 | const answer = sliceAsInt(buf[0...], true, u64); | 142 | const answer = readInt(buf, u64, true); |
| 110 | assert(answer == 0x00001234); | 143 | assert(answer == 0x00001234); |
| 111 | } | 144 | } |
| 112 | { | 145 | { |
| 113 | const buf = []u8{0x12, 0x34, 0x00, 0x00}; | 146 | const buf = []u8{0x12, 0x34, 0x00, 0x00}; |
| 114 | const answer = sliceAsInt(buf[0...], false, u64); | 147 | const answer = readInt(buf, u64, false); |
| 115 | assert(answer == 0x00003412); | 148 | assert(answer == 0x00003412); |
| 116 | } | 149 | } |
| 117 | } | 150 | } |
| 151 | |||
| 152 | fn testWriteInt() { | ||
| 153 | @setFnTest(this); | ||
| 154 | |||
| 155 | testWriteIntImpl(); | ||
| 156 | comptime testWriteIntImpl(); | ||
| 157 | } | ||
| 158 | fn testWriteIntImpl() { | ||
| 159 | var bytes: [4]u8 = undefined; | ||
| 160 | |||
| 161 | writeInt(bytes[0...], u32(0x12345678), true); | ||
| 162 | assert(eql(u8, bytes, []u8{ 0x12, 0x34, 0x56, 0x78 })); | ||
| 163 | |||
| 164 | writeInt(bytes[0...], u32(0x78563412), false); | ||
| 165 | assert(eql(u8, bytes, []u8{ 0x12, 0x34, 0x56, 0x78 })); | ||
| 166 | |||
| 167 | writeInt(bytes[0...], u16(0x1234), true); | ||
| 168 | assert(eql(u8, bytes, []u8{ 0x00, 0x00, 0x12, 0x34 })); | ||
| 169 | |||
| 170 | writeInt(bytes[0...], u16(0x1234), false); | ||
| 171 | assert(eql(u8, bytes, []u8{ 0x34, 0x12, 0x00, 0x00 })); | ||
| 172 | } |
std/net.zig+1-1| ... | @@ -134,7 +134,7 @@ pub fn connectAddr(addr: &Address, port: u16) -> %Connection { | ... | @@ -134,7 +134,7 @@ pub fn connectAddr(addr: &Address, port: u16) -> %Connection { |
| 134 | 134 | ||
| 135 | pub fn connect(hostname: []const u8, port: u16) -> %Connection { | 135 | pub fn connect(hostname: []const u8, port: u16) -> %Connection { |
| 136 | var addrs_buf: [1]Address = undefined; | 136 | var addrs_buf: [1]Address = undefined; |
| 137 | const addrs_slice = %return lookup(hostname, addrs_buf); | 137 | const addrs_slice = %return lookup(hostname, addrs_buf[0...]); |
| 138 | const main_addr = &addrs_slice[0]; | 138 | const main_addr = &addrs_slice[0]; |
| 139 | 139 | ||
| 140 | return connectAddr(main_addr, port); | 140 | return connectAddr(main_addr, port); |
std/rand.zig+12-9| ... | @@ -1,5 +1,6 @@ | ... | @@ -1,5 +1,6 @@ |
| 1 | const assert = @import("debug.zig").assert; | 1 | const assert = @import("debug.zig").assert; |
| 2 | const rand_test = @import("rand_test.zig"); | 2 | const rand_test = @import("rand_test.zig"); |
| 3 | const mem = @import("mem.zig"); | ||
| 3 | 4 | ||
| 4 | pub const MT19937_32 = MersenneTwister( | 5 | pub const MT19937_32 = MersenneTwister( |
| 5 | u32, 624, 397, 31, | 6 | u32, 624, 397, 31, |
| ... | @@ -28,14 +29,16 @@ pub const Rand = struct { | ... | @@ -28,14 +29,16 @@ pub const Rand = struct { |
| 28 | r.rng.init(seed); | 29 | r.rng.init(seed); |
| 29 | } | 30 | } |
| 30 | 31 | ||
| 31 | /// Get an integer with random bits. | 32 | /// Get an integer or boolean with random bits. |
| 32 | pub fn scalar(r: &Rand, comptime T: type) -> T { | 33 | pub fn scalar(r: &Rand, comptime T: type) -> T { |
| 33 | if (T == usize) { | 34 | if (T == usize) { |
| 34 | return r.rng.get(); | 35 | return r.rng.get(); |
| 36 | } else if (T == bool) { | ||
| 37 | return (r.rng.get() & 0b1) == 0; | ||
| 35 | } else { | 38 | } else { |
| 36 | var result: [@sizeOf(T)]u8 = undefined; | 39 | var result: [@sizeOf(T)]u8 = undefined; |
| 37 | r.fillBytes(result); | 40 | r.fillBytes(result[0...]); |
| 38 | return ([]T)(result)[0]; | 41 | return mem.readInt(result, T, false); |
| 39 | } | 42 | } |
| 40 | } | 43 | } |
| 41 | 44 | ||
| ... | @@ -43,12 +46,12 @@ pub const Rand = struct { | ... | @@ -43,12 +46,12 @@ pub const Rand = struct { |
| 43 | pub fn fillBytes(r: &Rand, buf: []u8) { | 46 | pub fn fillBytes(r: &Rand, buf: []u8) { |
| 44 | var bytes_left = buf.len; | 47 | var bytes_left = buf.len; |
| 45 | while (bytes_left >= @sizeOf(usize)) { | 48 | while (bytes_left >= @sizeOf(usize)) { |
| 46 | ([]usize)(buf[buf.len - bytes_left...])[0] = r.rng.get(); | 49 | mem.writeInt(buf[buf.len - bytes_left...], r.rng.get(), false); |
| 47 | bytes_left -= @sizeOf(usize); | 50 | bytes_left -= @sizeOf(usize); |
| 48 | } | 51 | } |
| 49 | if (bytes_left > 0) { | 52 | if (bytes_left > 0) { |
| 50 | var rand_val_array : [@sizeOf(usize)]u8 = undefined; | 53 | var rand_val_array: [@sizeOf(usize)]u8 = undefined; |
| 51 | ([]usize)(rand_val_array)[0] = r.rng.get(); | 54 | mem.writeInt(rand_val_array[0...], r.rng.get(), false); |
| 52 | while (bytes_left > 0) { | 55 | while (bytes_left > 0) { |
| 53 | buf[buf.len - bytes_left] = rand_val_array[@sizeOf(usize) - bytes_left]; | 56 | buf[buf.len - bytes_left] = rand_val_array[@sizeOf(usize) - bytes_left]; |
| 54 | bytes_left -= 1; | 57 | bytes_left -= 1; |
| ... | @@ -63,11 +66,11 @@ pub const Rand = struct { | ... | @@ -63,11 +66,11 @@ pub const Rand = struct { |
| 63 | const range = end - start; | 66 | const range = end - start; |
| 64 | const leftover = @maxValue(T) % range; | 67 | const leftover = @maxValue(T) % range; |
| 65 | const upper_bound = @maxValue(T) - leftover; | 68 | const upper_bound = @maxValue(T) - leftover; |
| 66 | var rand_val_array : [@sizeOf(T)]u8 = undefined; | 69 | var rand_val_array: [@sizeOf(T)]u8 = undefined; |
| 67 | 70 | ||
| 68 | while (true) { | 71 | while (true) { |
| 69 | r.fillBytes(rand_val_array); | 72 | r.fillBytes(rand_val_array[0...]); |
| 70 | const rand_val = ([]T)(rand_val_array)[0]; | 73 | const rand_val = mem.readInt(rand_val_array, T, false); |
| 71 | if (rand_val < upper_bound) { | 74 | if (rand_val < upper_bound) { |
| 72 | return start + (rand_val % range); | 75 | return start + (rand_val % range); |
| 73 | } | 76 | } |
std/sort.zig+24-24| ... | @@ -61,13 +61,13 @@ fn reverse(was: Cmp) -> Cmp { | ... | @@ -61,13 +61,13 @@ fn reverse(was: Cmp) -> Cmp { |
| 61 | fn testSort() { | 61 | fn testSort() { |
| 62 | @setFnTest(this); | 62 | @setFnTest(this); |
| 63 | 63 | ||
| 64 | const u8cases = [][][]u8 { | 64 | const u8cases = [][]const []const u8 { |
| 65 | [][]u8{"", ""}, | 65 | [][]const u8{"", ""}, |
| 66 | [][]u8{"a", "a"}, | 66 | [][]const u8{"a", "a"}, |
| 67 | [][]u8{"az", "az"}, | 67 | [][]const u8{"az", "az"}, |
| 68 | [][]u8{"za", "az"}, | 68 | [][]const u8{"za", "az"}, |
| 69 | [][]u8{"asdf", "adfs"}, | 69 | [][]const u8{"asdf", "adfs"}, |
| 70 | [][]u8{"one", "eno"}, | 70 | [][]const u8{"one", "eno"}, |
| 71 | }; | 71 | }; |
| 72 | 72 | ||
| 73 | for (u8cases) |case| { | 73 | for (u8cases) |case| { |
| ... | @@ -75,16 +75,16 @@ fn testSort() { | ... | @@ -75,16 +75,16 @@ fn testSort() { |
| 75 | const slice = buf[0...case[0].len]; | 75 | const slice = buf[0...case[0].len]; |
| 76 | mem.copy(u8, slice, case[0]); | 76 | mem.copy(u8, slice, case[0]); |
| 77 | sort(u8, slice, u8asc); | 77 | sort(u8, slice, u8asc); |
| 78 | assert(mem.eql(slice, case[1])); | 78 | assert(mem.eql(u8, slice, case[1])); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | const i32cases = [][][]i32 { | 81 | const i32cases = [][]const []const i32 { |
| 82 | [][]i32{[]i32{}, []i32{}}, | 82 | [][]const i32{[]i32{}, []i32{}}, |
| 83 | [][]i32{[]i32{1}, []i32{1}}, | 83 | [][]const i32{[]i32{1}, []i32{1}}, |
| 84 | [][]i32{[]i32{0, 1}, []i32{0, 1}}, | 84 | [][]const i32{[]i32{0, 1}, []i32{0, 1}}, |
| 85 | [][]i32{[]i32{1, 0}, []i32{0, 1}}, | 85 | [][]const i32{[]i32{1, 0}, []i32{0, 1}}, |
| 86 | [][]i32{[]i32{1, -1, 0}, []i32{-1, 0, 1}}, | 86 | [][]const i32{[]i32{1, -1, 0}, []i32{-1, 0, 1}}, |
| 87 | [][]i32{[]i32{2, 1, 3}, []i32{1, 2, 3}}, | 87 | [][]const i32{[]i32{2, 1, 3}, []i32{1, 2, 3}}, |
| 88 | }; | 88 | }; |
| 89 | 89 | ||
| 90 | for (i32cases) |case| { | 90 | for (i32cases) |case| { |
| ... | @@ -92,20 +92,20 @@ fn testSort() { | ... | @@ -92,20 +92,20 @@ fn testSort() { |
| 92 | const slice = buf[0...case[0].len]; | 92 | const slice = buf[0...case[0].len]; |
| 93 | mem.copy(i32, slice, case[0]); | 93 | mem.copy(i32, slice, case[0]); |
| 94 | sort(i32, slice, i32asc); | 94 | sort(i32, slice, i32asc); |
| 95 | assert(mem.eql(slice, case[1])); | 95 | assert(mem.eql(i32, slice, case[1])); |
| 96 | } | 96 | } |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | fn testSortDesc() { | 99 | fn testSortDesc() { |
| 100 | @setFnTest(this); | 100 | @setFnTest(this); |
| 101 | 101 | ||
| 102 | const rev_cases = [][][]i32 { | 102 | const rev_cases = [][]const []const i32 { |
| 103 | [][]i32{[]i32{}, []i32{}}, | 103 | [][]const i32{[]i32{}, []i32{}}, |
| 104 | [][]i32{[]i32{1}, []i32{1}}, | 104 | [][]const i32{[]i32{1}, []i32{1}}, |
| 105 | [][]i32{[]i32{0, 1}, []i32{1, 0}}, | 105 | [][]const i32{[]i32{0, 1}, []i32{1, 0}}, |
| 106 | [][]i32{[]i32{1, 0}, []i32{1, 0}}, | 106 | [][]const i32{[]i32{1, 0}, []i32{1, 0}}, |
| 107 | [][]i32{[]i32{1, -1, 0}, []i32{1, 0, -1}}, | 107 | [][]const i32{[]i32{1, -1, 0}, []i32{1, 0, -1}}, |
| 108 | [][]i32{[]i32{2, 1, 3}, []i32{3, 2, 1}}, | 108 | [][]const i32{[]i32{2, 1, 3}, []i32{3, 2, 1}}, |
| 109 | }; | 109 | }; |
| 110 | 110 | ||
| 111 | for (rev_cases) |case| { | 111 | for (rev_cases) |case| { |
| ... | @@ -113,6 +113,6 @@ fn testSortDesc() { | ... | @@ -113,6 +113,6 @@ fn testSortDesc() { |
| 113 | const slice = buf[0...case[0].len]; | 113 | const slice = buf[0...case[0].len]; |
| 114 | mem.copy(i32, slice, case[0]); | 114 | mem.copy(i32, slice, case[0]); |
| 115 | sort(i32, slice, i32desc); | 115 | sort(i32, slice, i32desc); |
| 116 | assert(mem.eql(slice, case[1])); | 116 | assert(mem.eql(i32, slice, case[1])); |
| 117 | } | 117 | } |
| 118 | } | 118 | } |
test/cases/array.zig+7-7| ... | @@ -23,7 +23,7 @@ fn arrays() { | ... | @@ -23,7 +23,7 @@ fn arrays() { |
| 23 | assert(accumulator == 15); | 23 | assert(accumulator == 15); |
| 24 | assert(getArrayLen(array) == 5); | 24 | assert(getArrayLen(array) == 5); |
| 25 | } | 25 | } |
| 26 | fn getArrayLen(a: []u32) -> usize { | 26 | fn getArrayLen(a: []const u32) -> usize { |
| 27 | a.len | 27 | a.len |
| 28 | } | 28 | } |
| 29 | 29 | ||
| ... | @@ -61,12 +61,12 @@ const some_array = []u8 {0, 1, 2, 3}; | ... | @@ -61,12 +61,12 @@ const some_array = []u8 {0, 1, 2, 3}; |
| 61 | fn nestedArrays() { | 61 | fn nestedArrays() { |
| 62 | @setFnTest(this); | 62 | @setFnTest(this); |
| 63 | 63 | ||
| 64 | const array_of_strings = [][]u8 {"hello", "this", "is", "my", "thing"}; | 64 | const array_of_strings = [][]const u8 {"hello", "this", "is", "my", "thing"}; |
| 65 | for (array_of_strings) |s, i| { | 65 | for (array_of_strings) |s, i| { |
| 66 | if (i == 0) assert(mem.eql(s, "hello")); | 66 | if (i == 0) assert(mem.eql(u8, s, "hello")); |
| 67 | if (i == 1) assert(mem.eql(s, "this")); | 67 | if (i == 1) assert(mem.eql(u8, s, "this")); |
| 68 | if (i == 2) assert(mem.eql(s, "is")); | 68 | if (i == 2) assert(mem.eql(u8, s, "is")); |
| 69 | if (i == 3) assert(mem.eql(s, "my")); | 69 | if (i == 3) assert(mem.eql(u8, s, "my")); |
| 70 | if (i == 4) assert(mem.eql(s, "thing")); | 70 | if (i == 4) assert(mem.eql(u8, s, "thing")); |
| 71 | } | 71 | } |
| 72 | } | 72 | } |
test/cases/enum_with_members.zig+4-4| ... | @@ -21,9 +21,9 @@ fn enumWithMembers() { | ... | @@ -21,9 +21,9 @@ fn enumWithMembers() { |
| 21 | const b = ET.UINT { 42 }; | 21 | const b = ET.UINT { 42 }; |
| 22 | var buf: [20]u8 = undefined; | 22 | var buf: [20]u8 = undefined; |
| 23 | 23 | ||
| 24 | assert(%%a.print(buf) == 3); | 24 | assert(%%a.print(buf[0...]) == 3); |
| 25 | assert(mem.eql(buf[0...3], "-42")); | 25 | assert(mem.eql(u8, buf[0...3], "-42")); |
| 26 | 26 | ||
| 27 | assert(%%b.print(buf) == 2); | 27 | assert(%%b.print(buf[0...]) == 2); |
| 28 | assert(mem.eql(buf[0...2], "42")); | 28 | assert(mem.eql(u8, buf[0...2], "42")); |
| 29 | } | 29 | } |
test/cases/error.zig+2-2| ... | @@ -28,8 +28,8 @@ fn gimmeItBroke() -> []const u8 { | ... | @@ -28,8 +28,8 @@ fn gimmeItBroke() -> []const u8 { |
| 28 | 28 | ||
| 29 | fn errorName() { | 29 | fn errorName() { |
| 30 | @setFnTest(this); | 30 | @setFnTest(this); |
| 31 | assert(mem.eql(@errorName(error.AnError), "AnError")); | 31 | assert(mem.eql(u8, @errorName(error.AnError), "AnError")); |
| 32 | assert(mem.eql(@errorName(error.ALongerErrorName), "ALongerErrorName")); | 32 | assert(mem.eql(u8, @errorName(error.ALongerErrorName), "ALongerErrorName")); |
| 33 | } | 33 | } |
| 34 | error AnError; | 34 | error AnError; |
| 35 | error ALongerErrorName; | 35 | error ALongerErrorName; |
test/cases/eval.zig+18| ... | @@ -283,3 +283,21 @@ fn callMethodOnBoundFnReferringToVarInstance() { | ... | @@ -283,3 +283,21 @@ fn callMethodOnBoundFnReferringToVarInstance() { |
| 283 | 283 | ||
| 284 | assert(bound_fn() == 1237); | 284 | assert(bound_fn() == 1237); |
| 285 | } | 285 | } |
| 286 | |||
| 287 | |||
| 288 | |||
| 289 | fn ptrToLocalArrayArgumentAtComptime() { | ||
| 290 | @setFnTest(this); | ||
| 291 | |||
| 292 | comptime { | ||
| 293 | var bytes: [10]u8 = undefined; | ||
| 294 | modifySomeBytes(bytes[0...]); | ||
| 295 | assert(bytes[0] == 'a'); | ||
| 296 | assert(bytes[9] == 'b'); | ||
| 297 | } | ||
| 298 | } | ||
| 299 | |||
| 300 | fn modifySomeBytes(bytes: []u8) { | ||
| 301 | bytes[0] = 'a'; | ||
| 302 | bytes[9] = 'b'; | ||
| 303 | } |
test/cases/for.zig+33-3| ... | @@ -22,12 +22,42 @@ fn forLoopWithPointerElemVar() { | ... | @@ -22,12 +22,42 @@ fn forLoopWithPointerElemVar() { |
| 22 | 22 | ||
| 23 | const source = "abcdefg"; | 23 | const source = "abcdefg"; |
| 24 | var target: [source.len]u8 = undefined; | 24 | var target: [source.len]u8 = undefined; |
| 25 | @memcpy(&target[0], &source[0], source.len); | 25 | mem.copy(u8, target[0...], source); |
| 26 | mangleString(target); | 26 | mangleString(target[0...]); |
| 27 | assert(mem.eql(target, "bcdefgh")); | 27 | assert(mem.eql(u8, target, "bcdefgh")); |
| 28 | } | 28 | } |
| 29 | fn mangleString(s: []u8) { | 29 | fn mangleString(s: []u8) { |
| 30 | for (s) |*c| { | 30 | for (s) |*c| { |
| 31 | *c += 1; | 31 | *c += 1; |
| 32 | } | 32 | } |
| 33 | } | 33 | } |
| 34 | |||
| 35 | fn basicForLoop() { | ||
| 36 | @setFnTest(this); | ||
| 37 | |||
| 38 | const expected_result = []u8{9, 8, 7, 6, 0, 1, 2, 3, 9, 8, 7, 6, 0, 1, 2, 3 }; | ||
| 39 | |||
| 40 | var buffer: [expected_result.len]u8 = undefined; | ||
| 41 | var buf_index: usize = 0; | ||
| 42 | |||
| 43 | const array = []u8 {9, 8, 7, 6}; | ||
| 44 | for (array) |item| { | ||
| 45 | buffer[buf_index] = item; | ||
| 46 | buf_index += 1; | ||
| 47 | } | ||
| 48 | for (array) |item, index| { | ||
| 49 | buffer[buf_index] = u8(index); | ||
| 50 | buf_index += 1; | ||
| 51 | } | ||
| 52 | const unknown_size: []const u8 = array; | ||
| 53 | for (unknown_size) |item| { | ||
| 54 | buffer[buf_index] = item; | ||
| 55 | buf_index += 1; | ||
| 56 | } | ||
| 57 | for (unknown_size) |item, index| { | ||
| 58 | buffer[buf_index] = u8(index); | ||
| 59 | buf_index += 1; | ||
| 60 | } | ||
| 61 | |||
| 62 | assert(mem.eql(u8, buffer[0...buf_index], expected_result)); | ||
| 63 | } |
test/cases/generics.zig+3-3| ... | @@ -136,7 +136,7 @@ fn genericFnWithImplicitCast() { | ... | @@ -136,7 +136,7 @@ fn genericFnWithImplicitCast() { |
| 136 | assert(getFirstByte(u8, []u8 {13}) == 13); | 136 | assert(getFirstByte(u8, []u8 {13}) == 13); |
| 137 | assert(getFirstByte(u16, []u16 {0, 13}) == 0); | 137 | assert(getFirstByte(u16, []u16 {0, 13}) == 0); |
| 138 | } | 138 | } |
| 139 | fn getByte(ptr: ?&u8) -> u8 {*??ptr} | 139 | fn getByte(ptr: ?&const u8) -> u8 {*??ptr} |
| 140 | fn getFirstByte(comptime T: type, mem: []T) -> u8 { | 140 | fn getFirstByte(comptime T: type, mem: []const T) -> u8 { |
| 141 | getByte((&u8)(&mem[0])) | 141 | getByte((&const u8)(&mem[0])) |
| 142 | } | 142 | } |
test/cases/misc.zig+22-22| ... | @@ -144,7 +144,7 @@ fn first4KeysOfHomeRow() -> []const u8 { | ... | @@ -144,7 +144,7 @@ fn first4KeysOfHomeRow() -> []const u8 { |
| 144 | fn ReturnStringFromFunction() { | 144 | fn ReturnStringFromFunction() { |
| 145 | @setFnTest(this); | 145 | @setFnTest(this); |
| 146 | 146 | ||
| 147 | assert(mem.eql(first4KeysOfHomeRow(), "aoeu")); | 147 | assert(mem.eql(u8, first4KeysOfHomeRow(), "aoeu")); |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | const g1 : i32 = 1233 + 1; | 150 | const g1 : i32 = 1233 + 1; |
| ... | @@ -210,31 +210,31 @@ fn emptyFn() {} | ... | @@ -210,31 +210,31 @@ fn emptyFn() {} |
| 210 | fn hexEscape() { | 210 | fn hexEscape() { |
| 211 | @setFnTest(this); | 211 | @setFnTest(this); |
| 212 | 212 | ||
| 213 | assert(mem.eql("\x68\x65\x6c\x6c\x6f", "hello")); | 213 | assert(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello")); |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | fn stringConcatenation() { | 216 | fn stringConcatenation() { |
| 217 | @setFnTest(this); | 217 | @setFnTest(this); |
| 218 | 218 | ||
| 219 | assert(mem.eql("OK" ++ " IT " ++ "WORKED", "OK IT WORKED")); | 219 | assert(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED")); |
| 220 | } | 220 | } |
| 221 | 221 | ||
| 222 | fn arrayMultOperator() { | 222 | fn arrayMultOperator() { |
| 223 | @setFnTest(this); | 223 | @setFnTest(this); |
| 224 | 224 | ||
| 225 | assert(mem.eql("ab" ** 5, "ababababab")); | 225 | assert(mem.eql(u8, "ab" ** 5, "ababababab")); |
| 226 | } | 226 | } |
| 227 | 227 | ||
| 228 | fn stringEscapes() { | 228 | fn stringEscapes() { |
| 229 | @setFnTest(this); | 229 | @setFnTest(this); |
| 230 | 230 | ||
| 231 | assert(mem.eql("\"", "\x22")); | 231 | assert(mem.eql(u8, "\"", "\x22")); |
| 232 | assert(mem.eql("\'", "\x27")); | 232 | assert(mem.eql(u8, "\'", "\x27")); |
| 233 | assert(mem.eql("\n", "\x0a")); | 233 | assert(mem.eql(u8, "\n", "\x0a")); |
| 234 | assert(mem.eql("\r", "\x0d")); | 234 | assert(mem.eql(u8, "\r", "\x0d")); |
| 235 | assert(mem.eql("\t", "\x09")); | 235 | assert(mem.eql(u8, "\t", "\x09")); |
| 236 | assert(mem.eql("\\", "\x5c")); | 236 | assert(mem.eql(u8, "\\", "\x5c")); |
| 237 | assert(mem.eql("\u1234\u0069", "\xe1\x88\xb4\x69")); | 237 | assert(mem.eql(u8, "\u1234\u0069", "\xe1\x88\xb4\x69")); |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | fn multilineString() { | 240 | fn multilineString() { |
| ... | @@ -246,7 +246,7 @@ fn multilineString() { | ... | @@ -246,7 +246,7 @@ fn multilineString() { |
| 246 | \\three | 246 | \\three |
| 247 | ; | 247 | ; |
| 248 | const s2 = "one\ntwo)\nthree"; | 248 | const s2 = "one\ntwo)\nthree"; |
| 249 | assert(mem.eql(s1, s2)); | 249 | assert(mem.eql(u8, s1, s2)); |
| 250 | } | 250 | } |
| 251 | 251 | ||
| 252 | fn multilineCString() { | 252 | fn multilineCString() { |
| ... | @@ -302,7 +302,7 @@ fn castUndefined() { | ... | @@ -302,7 +302,7 @@ fn castUndefined() { |
| 302 | @setFnTest(this); | 302 | @setFnTest(this); |
| 303 | 303 | ||
| 304 | const array: [100]u8 = undefined; | 304 | const array: [100]u8 = undefined; |
| 305 | const slice = ([]u8)(array); | 305 | const slice = ([]const u8)(array); |
| 306 | testCastUndefined(slice); | 306 | testCastUndefined(slice); |
| 307 | } | 307 | } |
| 308 | fn testCastUndefined(x: []const u8) {} | 308 | fn testCastUndefined(x: []const u8) {} |
| ... | @@ -344,14 +344,14 @@ fn pointerDereferencing() { | ... | @@ -344,14 +344,14 @@ fn pointerDereferencing() { |
| 344 | fn callResultOfIfElseExpression() { | 344 | fn callResultOfIfElseExpression() { |
| 345 | @setFnTest(this); | 345 | @setFnTest(this); |
| 346 | 346 | ||
| 347 | assert(mem.eql(f2(true), "a")); | 347 | assert(mem.eql(u8, f2(true), "a")); |
| 348 | assert(mem.eql(f2(false), "b")); | 348 | assert(mem.eql(u8, f2(false), "b")); |
| 349 | } | 349 | } |
| 350 | fn f2(x: bool) -> []u8 { | 350 | fn f2(x: bool) -> []const u8 { |
| 351 | return (if (x) fA else fB)(); | 351 | return (if (x) fA else fB)(); |
| 352 | } | 352 | } |
| 353 | fn fA() -> []u8 { "a" } | 353 | fn fA() -> []const u8 { "a" } |
| 354 | fn fB() -> []u8 { "b" } | 354 | fn fB() -> []const u8 { "b" } |
| 355 | 355 | ||
| 356 | 356 | ||
| 357 | fn constExpressionEvalHandlingOfVariables() { | 357 | fn constExpressionEvalHandlingOfVariables() { |
| ... | @@ -434,7 +434,7 @@ fn intToPtrCast() { | ... | @@ -434,7 +434,7 @@ fn intToPtrCast() { |
| 434 | fn pointerComparison() { | 434 | fn pointerComparison() { |
| 435 | @setFnTest(this); | 435 | @setFnTest(this); |
| 436 | 436 | ||
| 437 | const a = ([]u8)("a"); | 437 | const a = ([]const u8)("a"); |
| 438 | const b = &a; | 438 | const b = &a; |
| 439 | assert(ptrEql(b, b)); | 439 | assert(ptrEql(b, b)); |
| 440 | } | 440 | } |
| ... | @@ -463,7 +463,7 @@ fn castSliceToU8Slice() { | ... | @@ -463,7 +463,7 @@ fn castSliceToU8Slice() { |
| 463 | 463 | ||
| 464 | assert(@sizeOf(i32) == 4); | 464 | assert(@sizeOf(i32) == 4); |
| 465 | var big_thing_array = []i32{1, 2, 3, 4}; | 465 | var big_thing_array = []i32{1, 2, 3, 4}; |
| 466 | const big_thing_slice: []i32 = big_thing_array; | 466 | const big_thing_slice: []i32 = big_thing_array[0...]; |
| 467 | const bytes = ([]u8)(big_thing_slice); | 467 | const bytes = ([]u8)(big_thing_slice); |
| 468 | assert(bytes.len == 4 * 4); | 468 | assert(bytes.len == 4 * 4); |
| 469 | bytes[4] = 0; | 469 | bytes[4] = 0; |
| ... | @@ -562,8 +562,8 @@ fn typeName() { | ... | @@ -562,8 +562,8 @@ fn typeName() { |
| 562 | @setFnTest(this); | 562 | @setFnTest(this); |
| 563 | 563 | ||
| 564 | comptime { | 564 | comptime { |
| 565 | assert(mem.eql(@typeName(i64), "i64")); | 565 | assert(mem.eql(u8, @typeName(i64), "i64")); |
| 566 | assert(mem.eql(@typeName(&usize), "&usize")); | 566 | assert(mem.eql(u8, @typeName(&usize), "&usize")); |
| 567 | } | 567 | } |
| 568 | } | 568 | } |
| 569 | 569 |
test/cases/struct.zig+1-1| ... | @@ -205,7 +205,7 @@ fn passSliceOfEmptyStructToFn() { | ... | @@ -205,7 +205,7 @@ fn passSliceOfEmptyStructToFn() { |
| 205 | 205 | ||
| 206 | assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{ EmptyStruct2{} }) == 1); | 206 | assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{ EmptyStruct2{} }) == 1); |
| 207 | } | 207 | } |
| 208 | fn testPassSliceOfEmptyStructToFn(slice: []EmptyStruct2) -> usize { | 208 | fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) -> usize { |
| 209 | slice.len | 209 | slice.len |
| 210 | } | 210 | } |
| 211 | 211 |
test/cases/struct_contains_slice_of_itself.zig+2-2| ... | @@ -19,7 +19,7 @@ fn structContainsSliceOfItself() { | ... | @@ -19,7 +19,7 @@ fn structContainsSliceOfItself() { |
| 19 | }, | 19 | }, |
| 20 | Node { | 20 | Node { |
| 21 | .payload = 3, | 21 | .payload = 3, |
| 22 | .children = []Node{ | 22 | .children = ([]Node{ |
| 23 | Node { | 23 | Node { |
| 24 | .payload = 31, | 24 | .payload = 31, |
| 25 | .children = []Node{}, | 25 | .children = []Node{}, |
| ... | @@ -28,7 +28,7 @@ fn structContainsSliceOfItself() { | ... | @@ -28,7 +28,7 @@ fn structContainsSliceOfItself() { |
| 28 | .payload = 32, | 28 | .payload = 32, |
| 29 | .children = []Node{}, | 29 | .children = []Node{}, |
| 30 | }, | 30 | }, |
| 31 | }, | 31 | })[0...], |
| 32 | }, | 32 | }, |
| 33 | }; | 33 | }; |
| 34 | const root = Node { | 34 | const root = Node { |
test/run_tests.cpp+5-33| ... | @@ -465,27 +465,6 @@ fn print_ok(val: @typeOf(x)) -> @typeOf(foo) { | ... | @@ -465,27 +465,6 @@ fn print_ok(val: @typeOf(x)) -> @typeOf(foo) { |
| 465 | const foo : i32 = 0; | 465 | const foo : i32 = 0; |
| 466 | )SOURCE", "OK\n"); | 466 | )SOURCE", "OK\n"); |
| 467 | 467 | ||
| 468 | add_simple_case("for loops", R"SOURCE( | ||
| 469 | const io = @import("std").io; | ||
| 470 | |||
| 471 | pub fn main(args: [][]u8) -> %void { | ||
| 472 | const array = []u8 {9, 8, 7, 6}; | ||
| 473 | for (array) |item| { | ||
| 474 | %%io.stdout.printf("{}\n", item); | ||
| 475 | } | ||
| 476 | for (array) |item, index| { | ||
| 477 | %%io.stdout.printf("{}\n", index); | ||
| 478 | } | ||
| 479 | const unknown_size: []u8 = array; | ||
| 480 | for (unknown_size) |item| { | ||
| 481 | %%io.stdout.printf("{}\n", item); | ||
| 482 | } | ||
| 483 | for (unknown_size) |item, index| { | ||
| 484 | %%io.stdout.printf("{}\n", index); | ||
| 485 | } | ||
| 486 | } | ||
| 487 | )SOURCE", "9\n8\n7\n6\n0\n1\n2\n3\n9\n8\n7\n6\n0\n1\n2\n3\n"); | ||
| 488 | |||
| 489 | add_simple_case_libc("expose function pointer to C land", R"SOURCE( | 468 | add_simple_case_libc("expose function pointer to C land", R"SOURCE( |
| 490 | const c = @cImport(@cInclude("stdlib.h")); | 469 | const c = @cImport(@cInclude("stdlib.h")); |
| 491 | 470 | ||
| ... | @@ -1350,13 +1329,6 @@ fn f() -> i8 { | ... | @@ -1350,13 +1329,6 @@ fn f() -> i8 { |
| 1350 | } | 1329 | } |
| 1351 | )SOURCE", 1, ".tmp_source.zig:4:19: error: expected signed integer type, found 'u32'"); | 1330 | )SOURCE", 1, ".tmp_source.zig:4:19: error: expected signed integer type, found 'u32'"); |
| 1352 | 1331 | ||
| 1353 | add_compile_fail_case("truncate same bit count", R"SOURCE( | ||
| 1354 | fn f() -> i8 { | ||
| 1355 | const x: i8 = 10; | ||
| 1356 | @truncate(i8, x) | ||
| 1357 | } | ||
| 1358 | )SOURCE", 1, ".tmp_source.zig:4:19: error: type 'i8' has same or fewer bits than destination type 'i8'"); | ||
| 1359 | |||
| 1360 | add_compile_fail_case("%return in function with non error return type", R"SOURCE( | 1332 | add_compile_fail_case("%return in function with non error return type", R"SOURCE( |
| 1361 | fn f() { | 1333 | fn f() { |
| 1362 | %return something(); | 1334 | %return something(); |
| ... | @@ -1396,9 +1368,9 @@ fn f() -> i32 { | ... | @@ -1396,9 +1368,9 @@ fn f() -> i32 { |
| 1396 | add_compile_fail_case("convert fixed size array to slice with invalid size", R"SOURCE( | 1368 | add_compile_fail_case("convert fixed size array to slice with invalid size", R"SOURCE( |
| 1397 | fn f() { | 1369 | fn f() { |
| 1398 | var array: [5]u8 = undefined; | 1370 | var array: [5]u8 = undefined; |
| 1399 | var foo = ([]u32)(array)[0]; | 1371 | var foo = ([]const u32)(array)[0]; |
| 1400 | } | 1372 | } |
| 1401 | )SOURCE", 1, ".tmp_source.zig:4:22: error: unable to convert [5]u8 to []u32: size mismatch"); | 1373 | )SOURCE", 1, ".tmp_source.zig:4:28: error: unable to convert [5]u8 to []const u32: size mismatch"); |
| 1402 | 1374 | ||
| 1403 | add_compile_fail_case("non-pure function returns type", R"SOURCE( | 1375 | add_compile_fail_case("non-pure function returns type", R"SOURCE( |
| 1404 | var a: u32 = 0; | 1376 | var a: u32 = 0; |
| ... | @@ -1664,7 +1636,7 @@ pub fn main(args: [][]u8) -> %void { | ... | @@ -1664,7 +1636,7 @@ pub fn main(args: [][]u8) -> %void { |
| 1664 | const a = []i32{1, 2, 3, 4}; | 1636 | const a = []i32{1, 2, 3, 4}; |
| 1665 | baz(bar(a)); | 1637 | baz(bar(a)); |
| 1666 | } | 1638 | } |
| 1667 | fn bar(a: []i32) -> i32 { | 1639 | fn bar(a: []const i32) -> i32 { |
| 1668 | a[4] | 1640 | a[4] |
| 1669 | } | 1641 | } |
| 1670 | fn baz(a: i32) { } | 1642 | fn baz(a: i32) { } |
| ... | @@ -1799,8 +1771,8 @@ pub fn main(args: [][]u8) -> %void { | ... | @@ -1799,8 +1771,8 @@ pub fn main(args: [][]u8) -> %void { |
| 1799 | const x = widenSlice([]u8{1, 2, 3, 4, 5}); | 1771 | const x = widenSlice([]u8{1, 2, 3, 4, 5}); |
| 1800 | if (x.len == 0) return error.Whatever; | 1772 | if (x.len == 0) return error.Whatever; |
| 1801 | } | 1773 | } |
| 1802 | fn widenSlice(slice: []u8) -> []i32 { | 1774 | fn widenSlice(slice: []const u8) -> []const i32 { |
| 1803 | ([]i32)(slice) | 1775 | ([]const i32)(slice) |
| 1804 | } | 1776 | } |
| 1805 | )SOURCE"); | 1777 | )SOURCE"); |
| 1806 | 1778 |