authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-12 17:22:35-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-02-12 17:35:51-05:00
log6dba1f1c8eee5e2f037c7ef216bc64423aef8e00
treef39a29e98b7e3404b114aaa08cd26d767a1666c1
parentca180d3f02914d282505752a1d2fe08e175f9d99

slice and array re-work plus some misc. changes

* `@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 0xcd637// b is now 0xcd
638```638```
639639
640This function always truncates the significant bits of the integer, regardless
641of endianness on the target platform.
642
643This function also performs a twos complement cast. For example, the following
644produces a crash in debug mode and undefined behavior in release mode:
645
646```zig
647const a = i16(-1);
648const b = u16(a);
649```
650
651However this is well defined and working code:
652
653```zig
654const a = i16(-1);
655const b = @truncate(u16, a);
656// b is now 0xffff
657```
658
640### @compileError(comptime msg: []u8)659### @compileError(comptime msg: []u8)
641660
642This function, when semantically analyzed, causes a compile error with the661This 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;
6pub fn main(args: [][]u8) -> %void {6pub 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");
88
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);
1314
14 const answer = rand.rangeUnsigned(u8, 0, 100) + 1;15 const answer = rand.rangeUnsigned(u8, 0, 100) + 1;
1516
src/all_types.hpp+13-3
...@@ -119,11 +119,21 @@ enum ConstPtrSpecial {...@@ -119,11 +119,21 @@ enum ConstPtrSpecial {
119 ConstPtrSpecialHardCodedAddr,119 ConstPtrSpecialHardCodedAddr,
120};120};
121121
122struct ConstPtrValue {122enum 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 error126 // 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
134struct ConstPtrValue {
135 ConstPtrSpecial special;
136 ConstPtrMut mut;
127137
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}
18601860
1861static LLVMValueRef ir_render_truncate(CodeGen *g, IrExecutable *executable, IrInstructionTruncate *instruction) {1861static 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}
18661875
1867static LLVMValueRef ir_render_alloca(CodeGen *g, IrExecutable *executable, IrInstructionAlloca *instruction) {1876static 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
1945static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInstructionSlice *instruction) {1954static LLVMValueRef ir_render_slice(CodeGen *g, IrExecutable *executable, IrInstructionSlice *instruction) {
1946 assert(instruction->tmp_ptr);1955 assert(instruction->tmp_ptr);
19471956
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);
19491963
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);
19521965
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);
19541967
...@@ -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 }
25872599
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}
14821482
1483static 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
1492static IrInstruction *ir_build_min_value(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *value) {1483static 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;
52925283
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;
52965287
...@@ -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 conversion5813 // 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 }
58325827
5833 // implicit number literal to typed number5828 // 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}
61826177
6183static ConstExprValue *ir_build_const_from(IrAnalyze *ira, IrInstruction *old_instruction) {6178static 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
6203static 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}
62096208
6210static TypeTableEntry *ir_analyze_void(IrAnalyze *ira, IrInstruction *instruction) {6209static 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}
62146213
6215static TypeTableEntry *ir_analyze_const_ptr(IrAnalyze *ira, IrInstruction *instruction,6214static 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 }
62256224
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}
62416244
6245static 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
6242static TypeTableEntry *ir_analyze_const_usize(IrAnalyze *ira, IrInstruction *instruction, uint64_t value) {6255static 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}
65156528
6529static 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
6516static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *source_instr,6560static 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);
65386582
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 }
65466584
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}
65546593
...@@ -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 }
67816820
6782 // explicit cast from array to slice6821 // 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 }
67916831
6792 // explicit cast from []T to []u8 or []u8 to []T6832 // 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 }
68036843
6804 // explicit cast from [N]u8 to []T6844 // 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 allowed7054 if (ptr->value.data.x_ptr.mut == ConstPtrMutComptimeConst ||
7014 // unless that pointer is from a comptime variable7055 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
7053static TypeTableEntry *ir_analyze_ref(IrAnalyze *ira, IrInstruction *source_instruction, IrInstruction *value,7094static 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);
70587099 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}
70747101
7075static bool ir_resolve_usize(IrAnalyze *ira, IrInstruction *value, uint64_t *out) {7102static 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 }
92489285
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;
93539390
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 declaration11208 // 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 declaration11213 // 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}
1145811495
11459static TypeTableEntry *ir_analyze_instruction_slice(IrAnalyze *ira, IrInstructionSlice *instruction) {11496static 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;
1146311500
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 }
1148411526
11485 TypeTableEntry *array_type = get_underlying_type(ptr->value.type);
11486
11487 TypeTableEntry *return_type;11527 TypeTableEntry *return_type;
1148811528
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 decl11544 // 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 }
1150711547
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];
1154511586
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 }
1162211666
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);
1162611670
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};
155155
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;
9494
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;
9898
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 }
238238
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;
242242
std/endian.zig+8-10
...@@ -1,21 +1,19 @@...@@ -1,21 +1,19 @@
1pub inline fn swapIfLe(comptime T: type, x: T) -> T {1const mem = @import("mem.zig");
2
3pub fn swapIfLe(comptime T: type, x: T) -> T {
2 swapIf(false, T, x)4 swapIf(false, T, x)
3}5}
46
5pub inline fn swapIfBe(comptime T: type, x: T) -> T {7pub fn swapIfBe(comptime T: type, x: T) -> T {
6 swapIf(true, T, x)8 swapIf(true, T, x)
7}9}
810
9pub inline fn swapIf(is_be: bool, comptime T: type, x: T) -> T {11pub fn swapIf(is_be: bool, comptime T: type, x: T) -> T {
10 if (@compileVar("is_big_endian") == is_be) swap(T, x) else x12 if (@compileVar("is_big_endian") == is_be) swap(T, x) else x
11}13}
1214
13pub fn swap(comptime T: type, x: T) -> T {15pub 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")) {
66
7const errno = @import("errno.zig");7const errno = @import("errno.zig");
8const math = @import("math.zig");8const math = @import("math.zig");
9const endian = @import("endian.zig");
10const debug = @import("debug.zig");9const debug = @import("debug.zig");
11const assert = debug.assert;10const assert = debug.assert;
12const os = @import("os.zig");11const os = @import("os.zig");
...@@ -365,7 +364,7 @@ pub const InStream = struct {...@@ -365,7 +364,7 @@ pub const InStream = struct {
365364
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 }
371370
...@@ -378,10 +377,9 @@ pub const InStream = struct {...@@ -378,10 +377,9 @@ pub const InStream = struct {
378 }377 }
379378
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 }
386384
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 }
395393
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() {
589fn testBufPrintInt() {587fn testBufPrintInt() {
590 @setFnTest(this);588 @setFnTest(this);
591589
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"));
597596
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"));
599598
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"));
603602
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}
7070
71pub 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;72pub 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;
7676 }
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.
83pub 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}
8796
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
89pub 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| {100pub 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}
96119
97fn testStringEquality() {120fn testStringEquality() {
98 @setFnTest(this);121 @setFnTest(this);
99122
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}
104127
105fn testSliceAsInt() {128fn testReadInt() {
106 @setFnTest(this);129 @setFnTest(this);
130
131 testReadIntImpl();
132 comptime testReadIntImpl();
133}
134fn 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
152fn testWriteInt() {
153 @setFnTest(this);
154
155 testWriteIntImpl();
156 comptime testWriteIntImpl();
157}
158fn 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 {
134134
135pub fn connect(hostname: []const u8, port: u16) -> %Connection {135pub 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];
139139
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 @@
1const assert = @import("debug.zig").assert;1const assert = @import("debug.zig").assert;
2const rand_test = @import("rand_test.zig");2const rand_test = @import("rand_test.zig");
3const mem = @import("mem.zig");
34
4pub const MT19937_32 = MersenneTwister(5pub 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 }
3031
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 }
4144
...@@ -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;
6770
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 {
61fn testSort() {61fn testSort() {
62 @setFnTest(this);62 @setFnTest(this);
6363
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 };
7272
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 }
8080
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 };
8989
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}
9898
99fn testSortDesc() {99fn testSortDesc() {
100 @setFnTest(this);100 @setFnTest(this);
101101
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 };
110110
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}
26fn getArrayLen(a: []u32) -> usize {26fn getArrayLen(a: []const u32) -> usize {
27 a.len27 a.len
28}28}
2929
...@@ -61,12 +61,12 @@ const some_array = []u8 {0, 1, 2, 3};...@@ -61,12 +61,12 @@ const some_array = []u8 {0, 1, 2, 3};
61fn nestedArrays() {61fn nestedArrays() {
62 @setFnTest(this);62 @setFnTest(this);
6363
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;
2323
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"));
2626
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 {
2828
29fn errorName() {29fn 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}
34error AnError;34error AnError;
35error ALongerErrorName;35error ALongerErrorName;
test/cases/eval.zig+18
...@@ -283,3 +283,21 @@ fn callMethodOnBoundFnReferringToVarInstance() {...@@ -283,3 +283,21 @@ fn callMethodOnBoundFnReferringToVarInstance() {
283283
284 assert(bound_fn() == 1237);284 assert(bound_fn() == 1237);
285}285}
286
287
288
289fn 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
300fn 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() {
2222
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}
29fn mangleString(s: []u8) {29fn mangleString(s: []u8) {
30 for (s) |*c| {30 for (s) |*c| {
31 *c += 1;31 *c += 1;
32 }32 }
33}33}
34
35fn 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}
139fn getByte(ptr: ?&u8) -> u8 {*??ptr}139fn getByte(ptr: ?&const u8) -> u8 {*??ptr}
140fn getFirstByte(comptime T: type, mem: []T) -> u8 {140fn 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 {
144fn ReturnStringFromFunction() {144fn ReturnStringFromFunction() {
145 @setFnTest(this);145 @setFnTest(this);
146146
147 assert(mem.eql(first4KeysOfHomeRow(), "aoeu"));147 assert(mem.eql(u8, first4KeysOfHomeRow(), "aoeu"));
148}148}
149149
150const g1 : i32 = 1233 + 1;150const g1 : i32 = 1233 + 1;
...@@ -210,31 +210,31 @@ fn emptyFn() {}...@@ -210,31 +210,31 @@ fn emptyFn() {}
210fn hexEscape() {210fn hexEscape() {
211 @setFnTest(this);211 @setFnTest(this);
212212
213 assert(mem.eql("\x68\x65\x6c\x6c\x6f", "hello"));213 assert(mem.eql(u8, "\x68\x65\x6c\x6c\x6f", "hello"));
214}214}
215215
216fn stringConcatenation() {216fn stringConcatenation() {
217 @setFnTest(this);217 @setFnTest(this);
218218
219 assert(mem.eql("OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));219 assert(mem.eql(u8, "OK" ++ " IT " ++ "WORKED", "OK IT WORKED"));
220}220}
221221
222fn arrayMultOperator() {222fn arrayMultOperator() {
223 @setFnTest(this);223 @setFnTest(this);
224224
225 assert(mem.eql("ab" ** 5, "ababababab"));225 assert(mem.eql(u8, "ab" ** 5, "ababababab"));
226}226}
227227
228fn stringEscapes() {228fn stringEscapes() {
229 @setFnTest(this);229 @setFnTest(this);
230230
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}
239239
240fn multilineString() {240fn multilineString() {
...@@ -246,7 +246,7 @@ fn multilineString() {...@@ -246,7 +246,7 @@ fn multilineString() {
246 \\three246 \\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}
251251
252fn multilineCString() {252fn multilineCString() {
...@@ -302,7 +302,7 @@ fn castUndefined() {...@@ -302,7 +302,7 @@ fn castUndefined() {
302 @setFnTest(this);302 @setFnTest(this);
303303
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}
308fn testCastUndefined(x: []const u8) {}308fn testCastUndefined(x: []const u8) {}
...@@ -344,14 +344,14 @@ fn pointerDereferencing() {...@@ -344,14 +344,14 @@ fn pointerDereferencing() {
344fn callResultOfIfElseExpression() {344fn callResultOfIfElseExpression() {
345 @setFnTest(this);345 @setFnTest(this);
346346
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}
350fn f2(x: bool) -> []u8 {350fn f2(x: bool) -> []const u8 {
351 return (if (x) fA else fB)();351 return (if (x) fA else fB)();
352}352}
353fn fA() -> []u8 { "a" }353fn fA() -> []const u8 { "a" }
354fn fB() -> []u8 { "b" }354fn fB() -> []const u8 { "b" }
355355
356356
357fn constExpressionEvalHandlingOfVariables() {357fn constExpressionEvalHandlingOfVariables() {
...@@ -434,7 +434,7 @@ fn intToPtrCast() {...@@ -434,7 +434,7 @@ fn intToPtrCast() {
434fn pointerComparison() {434fn pointerComparison() {
435 @setFnTest(this);435 @setFnTest(this);
436436
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() {
463463
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);
563563
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}
569569
test/cases/struct.zig+1-1
...@@ -205,7 +205,7 @@ fn passSliceOfEmptyStructToFn() {...@@ -205,7 +205,7 @@ fn passSliceOfEmptyStructToFn() {
205205
206 assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{ EmptyStruct2{} }) == 1);206 assert(testPassSliceOfEmptyStructToFn([]EmptyStruct2{ EmptyStruct2{} }) == 1);
207}207}
208fn testPassSliceOfEmptyStructToFn(slice: []EmptyStruct2) -> usize {208fn testPassSliceOfEmptyStructToFn(slice: []const EmptyStruct2) -> usize {
209 slice.len209 slice.len
210}210}
211211
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) {
465const foo : i32 = 0;465const foo : i32 = 0;
466 )SOURCE", "OK\n");466 )SOURCE", "OK\n");
467467
468 add_simple_case("for loops", R"SOURCE(
469const io = @import("std").io;
470
471pub 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(
490const c = @cImport(@cInclude("stdlib.h"));469const c = @cImport(@cInclude("stdlib.h"));
491470
...@@ -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'");
13521331
1353 add_compile_fail_case("truncate same bit count", R"SOURCE(
1354fn 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(
1361fn f() {1333fn 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(
1397fn f() {1369fn 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");
14021374
1403 add_compile_fail_case("non-pure function returns type", R"SOURCE(1375 add_compile_fail_case("non-pure function returns type", R"SOURCE(
1404var a: u32 = 0;1376var 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}
1667fn bar(a: []i32) -> i32 {1639fn bar(a: []const i32) -> i32 {
1668 a[4]1640 a[4]
1669}1641}
1670fn baz(a: i32) { }1642fn 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}
1802fn widenSlice(slice: []u8) -> []i32 {1774fn widenSlice(slice: []const u8) -> []const i32 {
1803 ([]i32)(slice)1775 ([]const i32)(slice)
1804}1776}
1805 )SOURCE");1777 )SOURCE");
18061778