authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-18 17:25:29-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-18 17:25:29-04:00
log1aafbae5be518309b4c2194cdc24e22642514519
tree76146de4441517dbb0125364e3423ce3af12a49e
parent5d705fc6e35e75a604d3dbbb377ab01bf2b2b575

remove []u8 casting syntax. add `@bytesToSlice` and `@sliceToBytes`

See #1061

15 files changed, 277 insertions(+), 96 deletions(-)

doc/langref.html.in+33-12
...@@ -1456,8 +1456,7 @@ test "pointer array access" {...@@ -1456,8 +1456,7 @@ test "pointer array access" {
1456 // Taking an address of an individual element gives a1456 // Taking an address of an individual element gives a
1457 // pointer to a single item. This kind of pointer1457 // pointer to a single item. This kind of pointer
1458 // does not support pointer arithmetic.1458 // does not support pointer arithmetic.
14591459 var array = []u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
1460 var array = []u8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
1461 const ptr = &array[2];1460 const ptr = &array[2];
1462 assert(@typeOf(ptr) == *u8);1461 assert(@typeOf(ptr) == *u8);
14631462
...@@ -1469,7 +1468,7 @@ test "pointer array access" {...@@ -1469,7 +1468,7 @@ test "pointer array access" {
1469test "pointer slicing" {1468test "pointer slicing" {
1470 // In Zig, we prefer using slices over null-terminated pointers.1469 // In Zig, we prefer using slices over null-terminated pointers.
1471 // You can turn an array into a slice using slice syntax:1470 // You can turn an array into a slice using slice syntax:
1472 var array = []u8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};1471 var array = []u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
1473 const slice = array[2..4];1472 const slice = array[2..4];
1474 assert(slice.len == 2);1473 assert(slice.len == 2);
14751474
...@@ -1541,13 +1540,13 @@ test "pointer casting" {...@@ -1541,13 +1540,13 @@ test "pointer casting" {
1541 // To convert one pointer type to another, use @ptrCast. This is an unsafe1540 // To convert one pointer type to another, use @ptrCast. This is an unsafe
1542 // operation that Zig cannot protect you against. Use @ptrCast only when other1541 // operation that Zig cannot protect you against. Use @ptrCast only when other
1543 // conversions are not possible.1542 // conversions are not possible.
1544 const bytes align(@alignOf(u32)) = []u8{0x12, 0x12, 0x12, 0x12};1543 const bytes align(@alignOf(u32)) = []u8{ 0x12, 0x12, 0x12, 0x12 };
1545 const u32_ptr = @ptrCast(*const u32, &bytes[0]);1544 const u32_ptr = @ptrCast(*const u32, &bytes[0]);
1546 assert(u32_ptr.* == 0x12121212);1545 assert(u32_ptr.* == 0x12121212);
15471546
1548 // Even this example is contrived - there are better ways to do the above than1547 // Even this example is contrived - there are better ways to do the above than
1549 // pointer casting. For example, using a slice narrowing cast:1548 // pointer casting. For example, using a slice narrowing cast:
1550 const u32_value = ([]const u32)(bytes[0..])[0];1549 const u32_value = @bytesToSlice(u32, bytes[0..])[0];
1551 assert(u32_value == 0x12121212);1550 assert(u32_value == 0x12121212);
15521551
1553 // And even another way, the most straightforward way to do it:1552 // And even another way, the most straightforward way to do it:
...@@ -1630,13 +1629,13 @@ test "function alignment" {...@@ -1630,13 +1629,13 @@ test "function alignment" {
1630const assert = @import("std").debug.assert;1629const assert = @import("std").debug.assert;
16311630
1632test "pointer alignment safety" {1631test "pointer alignment safety" {
1633 var array align(4) = []u32{0x11111111, 0x11111111};1632 var array align(4) = []u32{ 0x11111111, 0x11111111 };
1634 const bytes = ([]u8)(array[0..]);1633 const bytes = @sliceToBytes(array[0..]);
1635 assert(foo(bytes) == 0x11111111);1634 assert(foo(bytes) == 0x11111111);
1636}1635}
1637fn foo(bytes: []u8) u32 {1636fn foo(bytes: []u8) u32 {
1638 const slice4 = bytes[1..5];1637 const slice4 = bytes[1..5];
1639 const int_slice = ([]u32)(@alignCast(4, slice4));1638 const int_slice = @bytesToSlice(u32, @alignCast(4, slice4));
1640 return int_slice[0];1639 return int_slice[0];
1641}1640}
1642 {#code_end#}1641 {#code_end#}
...@@ -1728,8 +1727,8 @@ test "slice pointer" {...@@ -1728,8 +1727,8 @@ test "slice pointer" {
1728test "slice widening" {1727test "slice widening" {
1729 // Zig supports slice widening and slice narrowing. Cast a slice of u81728 // Zig supports slice widening and slice narrowing. Cast a slice of u8
1730 // to a slice of anything else, and Zig will perform the length conversion.1729 // to a slice of anything else, and Zig will perform the length conversion.
1731 const array align(@alignOf(u32)) = []u8{0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13};1730 const array align(@alignOf(u32)) = []u8{ 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13 };
1732 const slice = ([]const u32)(array[0..]);1731 const slice = @bytesToSlice(u32, array[0..]);
1733 assert(slice.len == 2);1732 assert(slice.len == 2);
1734 assert(slice[0] == 0x12121212);1733 assert(slice[0] == 0x12121212);
1735 assert(slice[1] == 0x13131313);1734 assert(slice[1] == 0x13131313);
...@@ -4651,6 +4650,18 @@ comptime {...@@ -4651,6 +4650,18 @@ comptime {
4651 </p>4650 </p>
4652 {#header_close#}4651 {#header_close#}
46534652
4653 {#header_open|@bytesToSlice#}
4654 <pre><code class="zig">@bytesToSlice(comptime Element: type, bytes: []u8) []Element</code></pre>
4655 <p>
4656 Converts a slice of bytes or array of bytes into a slice of <code>Element</code>.
4657 The resulting slice has the same {#link|pointer|Pointers#} properties as the parameter.
4658 </p>
4659 <p>
4660 Attempting to convert a number of bytes with a length that does not evenly divide into a slice of
4661 elements results in {#link|Undefined Behavior#}.
4662 </p>
4663 {#header_close#}
4664
4654 {#header_open|@cDefine#}4665 {#header_open|@cDefine#}
4655 <pre><code class="zig">@cDefine(comptime name: []u8, value)</code></pre>4666 <pre><code class="zig">@cDefine(comptime name: []u8, value)</code></pre>
4656 <p>4667 <p>
...@@ -5467,8 +5478,9 @@ pub const FloatMode = enum {...@@ -5467,8 +5478,9 @@ pub const FloatMode = enum {
5467 </p>5478 </p>
5468 {#see_also|@shlExact|@shlWithOverflow#}5479 {#see_also|@shlExact|@shlWithOverflow#}
5469 {#header_close#}5480 {#header_close#}
5481
5470 {#header_open|@sizeOf#}5482 {#header_open|@sizeOf#}
5471 <pre><code class="zig">@sizeOf(comptime T: type) (number literal)</code></pre>5483 <pre><code class="zig">@sizeOf(comptime T: type) comptime_int</code></pre>
5472 <p>5484 <p>
5473 This function returns the number of bytes it takes to store <code>T</code> in memory.5485 This function returns the number of bytes it takes to store <code>T</code> in memory.
5474 </p>5486 </p>
...@@ -5476,6 +5488,15 @@ pub const FloatMode = enum {...@@ -5476,6 +5488,15 @@ pub const FloatMode = enum {
5476 The result is a target-specific compile time constant.5488 The result is a target-specific compile time constant.
5477 </p>5489 </p>
5478 {#header_close#}5490 {#header_close#}
5491
5492 {#header_open|@sliceToBytes#}
5493 <pre><code class="zig">@sliceToBytes(value: var) []u8</code></pre>
5494 <p>
5495 Converts a slice or array to a slice of <code>u8</code>. The resulting slice has the same
5496 {#link|pointer|Pointers#} properties as the parameter.
5497 </p>
5498 {#header_close#}
5499
5479 {#header_open|@sqrt#}5500 {#header_open|@sqrt#}
5480 <pre><code class="zig">@sqrt(comptime T: type, value: T) T</code></pre>5501 <pre><code class="zig">@sqrt(comptime T: type, value: T) T</code></pre>
5481 <p>5502 <p>
...@@ -6810,7 +6831,7 @@ hljs.registerLanguage("zig", function(t) {...@@ -6810,7 +6831,7 @@ hljs.registerLanguage("zig", function(t) {
6810 a = t.IR + "\\s*\\(",6831 a = t.IR + "\\s*\\(",
6811 c = {6832 c = {
6812 keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong resume cancel await async orelse",6833 keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong resume cancel await async orelse",
6813 built_in: "atomicLoad breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic ptrCast intCast floatCast intToFloat floatToInt boolToInt bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchgStrong cmpxchgWeak fence divExact truncate atomicRmw sqrt field typeInfo typeName newStackCall",6834 built_in: "atomicLoad breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic ptrCast intCast floatCast intToFloat floatToInt boolToInt bytesToSlice sliceToBytes errSetCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchgStrong cmpxchgWeak fence divExact truncate atomicRmw sqrt field typeInfo typeName newStackCall",
6814 literal: "true false null undefined"6835 literal: "true false null undefined"
6815 },6836 },
6816 n = [e, t.CLCM, t.CBCM, s, r];6837 n = [e, t.CLCM, t.CBCM, s, r];
src/all_types.hpp+28
...@@ -234,6 +234,16 @@ enum RuntimeHintPtr {...@@ -234,6 +234,16 @@ enum RuntimeHintPtr {
234 RuntimeHintPtrNonStack,234 RuntimeHintPtrNonStack,
235};235};
236236
237enum RuntimeHintSliceId {
238 RuntimeHintSliceIdUnknown,
239 RuntimeHintSliceIdLen,
240};
241
242struct RuntimeHintSlice {
243 enum RuntimeHintSliceId id;
244 uint64_t len;
245};
246
237struct ConstGlobalRefs {247struct ConstGlobalRefs {
238 LLVMValueRef llvm_value;248 LLVMValueRef llvm_value;
239 LLVMValueRef llvm_global;249 LLVMValueRef llvm_global;
...@@ -270,6 +280,7 @@ struct ConstExprValue {...@@ -270,6 +280,7 @@ struct ConstExprValue {
270 RuntimeHintErrorUnion rh_error_union;280 RuntimeHintErrorUnion rh_error_union;
271 RuntimeHintOptional rh_maybe;281 RuntimeHintOptional rh_maybe;
272 RuntimeHintPtr rh_ptr;282 RuntimeHintPtr rh_ptr;
283 RuntimeHintSlice rh_slice;
273 } data;284 } data;
274};285};
275286
...@@ -1360,6 +1371,8 @@ enum BuiltinFnId {...@@ -1360,6 +1371,8 @@ enum BuiltinFnId {
1360 BuiltinFnIdIntCast,1371 BuiltinFnIdIntCast,
1361 BuiltinFnIdFloatCast,1372 BuiltinFnIdFloatCast,
1362 BuiltinFnIdErrSetCast,1373 BuiltinFnIdErrSetCast,
1374 BuiltinFnIdToBytes,
1375 BuiltinFnIdFromBytes,
1363 BuiltinFnIdIntToFloat,1376 BuiltinFnIdIntToFloat,
1364 BuiltinFnIdFloatToInt,1377 BuiltinFnIdFloatToInt,
1365 BuiltinFnIdBoolToInt,1378 BuiltinFnIdBoolToInt,
...@@ -2123,6 +2136,8 @@ enum IrInstructionId {...@@ -2123,6 +2136,8 @@ enum IrInstructionId {
2123 IrInstructionIdMarkErrRetTracePtr,2136 IrInstructionIdMarkErrRetTracePtr,
2124 IrInstructionIdSqrt,2137 IrInstructionIdSqrt,
2125 IrInstructionIdErrSetCast,2138 IrInstructionIdErrSetCast,
2139 IrInstructionIdToBytes,
2140 IrInstructionIdFromBytes,
2126};2141};
21272142
2128struct IrInstruction {2143struct IrInstruction {
...@@ -2665,6 +2680,19 @@ struct IrInstructionErrSetCast {...@@ -2665,6 +2680,19 @@ struct IrInstructionErrSetCast {
2665 IrInstruction *target;2680 IrInstruction *target;
2666};2681};
26672682
2683struct IrInstructionToBytes {
2684 IrInstruction base;
2685
2686 IrInstruction *target;
2687};
2688
2689struct IrInstructionFromBytes {
2690 IrInstruction base;
2691
2692 IrInstruction *dest_child_type;
2693 IrInstruction *target;
2694};
2695
2668struct IrInstructionIntToFloat {2696struct IrInstructionIntToFloat {
2669 IrInstruction base;2697 IrInstruction base;
26702698
src/codegen.cpp+4
...@@ -4728,6 +4728,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -4728,6 +4728,8 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
4728 case IrInstructionIdFloatToInt:4728 case IrInstructionIdFloatToInt:
4729 case IrInstructionIdBoolToInt:4729 case IrInstructionIdBoolToInt:
4730 case IrInstructionIdErrSetCast:4730 case IrInstructionIdErrSetCast:
4731 case IrInstructionIdFromBytes:
4732 case IrInstructionIdToBytes:
4731 zig_unreachable();4733 zig_unreachable();
47324734
4733 case IrInstructionIdReturn:4735 case IrInstructionIdReturn:
...@@ -6358,6 +6360,8 @@ static void define_builtin_fns(CodeGen *g) {...@@ -6358,6 +6360,8 @@ static void define_builtin_fns(CodeGen *g) {
6358 create_builtin_fn(g, BuiltinFnIdAtomicRmw, "atomicRmw", 5);6360 create_builtin_fn(g, BuiltinFnIdAtomicRmw, "atomicRmw", 5);
6359 create_builtin_fn(g, BuiltinFnIdAtomicLoad, "atomicLoad", 3);6361 create_builtin_fn(g, BuiltinFnIdAtomicLoad, "atomicLoad", 3);
6360 create_builtin_fn(g, BuiltinFnIdErrSetCast, "errSetCast", 2);6362 create_builtin_fn(g, BuiltinFnIdErrSetCast, "errSetCast", 2);
6363 create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);
6364 create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
6361}6365}
63626366
6363static const char *bool_to_str(bool b) {6367static const char *bool_to_str(bool b) {
src/ir.cpp+165-52
...@@ -472,6 +472,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrSetCast *) {...@@ -472,6 +472,14 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionErrSetCast *) {
472 return IrInstructionIdErrSetCast;472 return IrInstructionIdErrSetCast;
473}473}
474474
475static constexpr IrInstructionId ir_instruction_id(IrInstructionToBytes *) {
476 return IrInstructionIdToBytes;
477}
478
479static constexpr IrInstructionId ir_instruction_id(IrInstructionFromBytes *) {
480 return IrInstructionIdFromBytes;
481}
482
475static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToFloat *) {483static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToFloat *) {
476 return IrInstructionIdIntToFloat;484 return IrInstructionIdIntToFloat;
477}485}
...@@ -1956,6 +1964,26 @@ static IrInstruction *ir_build_err_set_cast(IrBuilder *irb, Scope *scope, AstNod...@@ -1956,6 +1964,26 @@ static IrInstruction *ir_build_err_set_cast(IrBuilder *irb, Scope *scope, AstNod
1956 return &instruction->base;1964 return &instruction->base;
1957}1965}
19581966
1967static IrInstruction *ir_build_to_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target) {
1968 IrInstructionToBytes *instruction = ir_build_instruction<IrInstructionToBytes>(irb, scope, source_node);
1969 instruction->target = target;
1970
1971 ir_ref_instruction(target, irb->current_basic_block);
1972
1973 return &instruction->base;
1974}
1975
1976static IrInstruction *ir_build_from_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_child_type, IrInstruction *target) {
1977 IrInstructionFromBytes *instruction = ir_build_instruction<IrInstructionFromBytes>(irb, scope, source_node);
1978 instruction->dest_child_type = dest_child_type;
1979 instruction->target = target;
1980
1981 ir_ref_instruction(dest_child_type, irb->current_basic_block);
1982 ir_ref_instruction(target, irb->current_basic_block);
1983
1984 return &instruction->base;
1985}
1986
1959static IrInstruction *ir_build_int_to_float(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) {1987static IrInstruction *ir_build_int_to_float(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) {
1960 IrInstructionIntToFloat *instruction = ir_build_instruction<IrInstructionIntToFloat>(irb, scope, source_node);1988 IrInstructionIntToFloat *instruction = ir_build_instruction<IrInstructionIntToFloat>(irb, scope, source_node);
1961 instruction->dest_type = dest_type;1989 instruction->dest_type = dest_type;
...@@ -4084,6 +4112,31 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4084,6 +4112,31 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4084 IrInstruction *result = ir_build_err_set_cast(irb, scope, node, arg0_value, arg1_value);4112 IrInstruction *result = ir_build_err_set_cast(irb, scope, node, arg0_value, arg1_value);
4085 return ir_lval_wrap(irb, scope, result, lval);4113 return ir_lval_wrap(irb, scope, result, lval);
4086 }4114 }
4115 case BuiltinFnIdFromBytes:
4116 {
4117 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4118 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4119 if (arg0_value == irb->codegen->invalid_instruction)
4120 return arg0_value;
4121
4122 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4123 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
4124 if (arg1_value == irb->codegen->invalid_instruction)
4125 return arg1_value;
4126
4127 IrInstruction *result = ir_build_from_bytes(irb, scope, node, arg0_value, arg1_value);
4128 return ir_lval_wrap(irb, scope, result, lval);
4129 }
4130 case BuiltinFnIdToBytes:
4131 {
4132 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4133 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4134 if (arg0_value == irb->codegen->invalid_instruction)
4135 return arg0_value;
4136
4137 IrInstruction *result = ir_build_to_bytes(irb, scope, node, arg0_value);
4138 return ir_lval_wrap(irb, scope, result, lval);
4139 }
4087 case BuiltinFnIdIntToFloat:4140 case BuiltinFnIdIntToFloat:
4088 {4141 {
4089 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);4142 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
...@@ -9103,11 +9156,6 @@ static bool is_container(TypeTableEntry *type) {...@@ -9103,11 +9156,6 @@ static bool is_container(TypeTableEntry *type) {
9103 type->id == TypeTableEntryIdUnion;9156 type->id == TypeTableEntryIdUnion;
9104}9157}
91059158
9106static bool is_u8(TypeTableEntry *type) {
9107 return type->id == TypeTableEntryIdInt &&
9108 !type->data.integral.is_signed && type->data.integral.bit_count == 8;
9109}
9110
9111static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) {9159static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) {
9112 assert(old_bb);9160 assert(old_bb);
91139161
...@@ -9661,6 +9709,8 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s...@@ -9661,6 +9709,8 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
9661 IrInstruction *result = ir_build_slice(&ira->new_irb, source_instr->scope,9709 IrInstruction *result = ir_build_slice(&ira->new_irb, source_instr->scope,
9662 source_instr->source_node, array_ptr, start, end, false);9710 source_instr->source_node, array_ptr, start, end, false);
9663 result->value.type = wanted_type;9711 result->value.type = wanted_type;
9712 result->value.data.rh_slice.id = RuntimeHintSliceIdLen;
9713 result->value.data.rh_slice.len = array_type->data.array.len;
9664 ir_add_alloca(ira, result, result->value.type);9714 ir_add_alloca(ira, result, result->value.type);
96659715
9666 return result;9716 return result;
...@@ -10103,7 +10153,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10103,7 +10153,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10103 return ira->codegen->invalid_instruction;10153 return ira->codegen->invalid_instruction;
10104 }10154 }
1010510155
10106 // explicit match or non-const to const10156 // perfect match or non-const to const
10107 if (types_match_const_cast_only(ira, wanted_type, actual_type, source_node, false).id == ConstCastResultIdOk) {10157 if (types_match_const_cast_only(ira, wanted_type, actual_type, source_node, false).id == ConstCastResultIdOk) {
10108 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);10158 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
10109 }10159 }
...@@ -10214,52 +10264,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10214,52 +10264,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10214 }10264 }
10215 }10265 }
1021610266
10217 // explicit cast from []T to []u8 or []u8 to []T
10218 if (is_slice(wanted_type) && is_slice(actual_type)) {
10219 TypeTableEntry *wanted_ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
10220 TypeTableEntry *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry;
10221 if ((is_u8(wanted_ptr_type->data.pointer.child_type) || is_u8(actual_ptr_type->data.pointer.child_type)) &&
10222 (wanted_ptr_type->data.pointer.is_const || !actual_ptr_type->data.pointer.is_const))
10223 {
10224 uint32_t src_align_bytes = get_ptr_align(actual_ptr_type);
10225 uint32_t dest_align_bytes = get_ptr_align(wanted_ptr_type);
10226
10227 if (dest_align_bytes > src_align_bytes) {
10228 ErrorMsg *msg = ir_add_error(ira, source_instr,
10229 buf_sprintf("cast increases pointer alignment"));
10230 add_error_note(ira->codegen, msg, source_instr->source_node,
10231 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&actual_type->name), src_align_bytes));
10232 add_error_note(ira->codegen, msg, source_instr->source_node,
10233 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&wanted_type->name), dest_align_bytes));
10234 return ira->codegen->invalid_instruction;
10235 }
10236
10237 if (!ir_emit_global_runtime_side_effect(ira, source_instr))
10238 return ira->codegen->invalid_instruction;
10239 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpResizeSlice, true);
10240 }
10241 }
10242
10243 // explicit cast from [N]u8 to []const T
10244 if (is_slice(wanted_type) &&
10245 wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const &&
10246 actual_type->id == TypeTableEntryIdArray &&
10247 is_u8(actual_type->data.array.child_type))
10248 {
10249 if (!ir_emit_global_runtime_side_effect(ira, source_instr))
10250 return ira->codegen->invalid_instruction;
10251 uint64_t child_type_size = type_size(ira->codegen,
10252 wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type);
10253 if (actual_type->data.array.len % child_type_size == 0) {
10254 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpBytesToSlice, true);
10255 } else {
10256 ir_add_error_node(ira, source_instr->source_node,
10257 buf_sprintf("unable to convert %s to %s: size mismatch",
10258 buf_ptr(&actual_type->name), buf_ptr(&wanted_type->name)));
10259 return ira->codegen->invalid_instruction;
10260 }
10261 }
10262
10263 // explicit *[N]T to [*]T10267 // explicit *[N]T to [*]T
10264 if (wanted_type->id == TypeTableEntryIdPointer &&10268 if (wanted_type->id == TypeTableEntryIdPointer &&
10265 wanted_type->data.pointer.ptr_len == PtrLenUnknown &&10269 wanted_type->data.pointer.ptr_len == PtrLenUnknown &&
...@@ -17644,6 +17648,109 @@ static TypeTableEntry *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrIns...@@ -17644,6 +17648,109 @@ static TypeTableEntry *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrIns
17644 return dest_type;17648 return dest_type;
17645}17649}
1764617650
17651static TypeTableEntry *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {
17652 TypeTableEntry *dest_child_type = ir_resolve_type(ira, instruction->dest_child_type->other);
17653 if (type_is_invalid(dest_child_type))
17654 return ira->codegen->builtin_types.entry_invalid;
17655
17656 IrInstruction *target = instruction->target->other;
17657 if (type_is_invalid(target->value.type))
17658 return ira->codegen->builtin_types.entry_invalid;
17659
17660 bool src_ptr_const;
17661 bool src_ptr_volatile;
17662 uint32_t src_ptr_align;
17663 if (target->value.type->id == TypeTableEntryIdPointer) {
17664 src_ptr_const = target->value.type->data.pointer.is_const;
17665 src_ptr_volatile = target->value.type->data.pointer.is_volatile;
17666 src_ptr_align = target->value.type->data.pointer.alignment;
17667 } else if (is_slice(target->value.type)) {
17668 TypeTableEntry *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;
17669 src_ptr_const = src_ptr_type->data.pointer.is_const;
17670 src_ptr_volatile = src_ptr_type->data.pointer.is_volatile;
17671 src_ptr_align = src_ptr_type->data.pointer.alignment;
17672 } else {
17673 src_ptr_const = true;
17674 src_ptr_volatile = false;
17675 src_ptr_align = get_abi_alignment(ira->codegen, target->value.type);
17676 }
17677
17678 TypeTableEntry *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_child_type,
17679 src_ptr_const, src_ptr_volatile, PtrLenUnknown,
17680 src_ptr_align, 0, 0);
17681 TypeTableEntry *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);
17682
17683 TypeTableEntry *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
17684 src_ptr_const, src_ptr_volatile, PtrLenUnknown,
17685 src_ptr_align, 0, 0);
17686 TypeTableEntry *u8_slice = get_slice_type(ira->codegen, u8_ptr);
17687
17688 IrInstruction *casted_value = ir_implicit_cast(ira, target, u8_slice);
17689 if (type_is_invalid(casted_value->value.type))
17690 return ira->codegen->builtin_types.entry_invalid;
17691
17692 bool have_known_len = false;
17693 uint64_t known_len;
17694
17695 if (instr_is_comptime(casted_value)) {
17696 ConstExprValue *val = ir_resolve_const(ira, casted_value, UndefBad);
17697 if (!val)
17698 return ira->codegen->builtin_types.entry_invalid;
17699
17700 ConstExprValue *len_val = &val->data.x_struct.fields[slice_len_index];
17701 if (value_is_comptime(len_val)) {
17702 known_len = bigint_as_unsigned(&len_val->data.x_bigint);
17703 have_known_len = true;
17704 }
17705 }
17706
17707 if (casted_value->value.data.rh_slice.id == RuntimeHintSliceIdLen) {
17708 known_len = casted_value->value.data.rh_slice.len;
17709 have_known_len = true;
17710 }
17711
17712 if (have_known_len) {
17713 uint64_t child_type_size = type_size(ira->codegen, dest_child_type);
17714 uint64_t remainder = known_len % child_type_size;
17715 if (remainder != 0) {
17716 ErrorMsg *msg = ir_add_error(ira, &instruction->base,
17717 buf_sprintf("unable to convert [%" ZIG_PRI_u64 "]u8 to %s: size mismatch",
17718 known_len, buf_ptr(&dest_slice_type->name)));
17719 add_error_note(ira->codegen, msg, instruction->dest_child_type->source_node,
17720 buf_sprintf("%s has size %" ZIG_PRI_u64 "; remaining bytes: %" ZIG_PRI_u64,
17721 buf_ptr(&dest_child_type->name), child_type_size, remainder));
17722 return ira->codegen->builtin_types.entry_invalid;
17723 }
17724 }
17725
17726 IrInstruction *result = ir_resolve_cast(ira, &instruction->base, casted_value, dest_slice_type, CastOpResizeSlice, true);
17727 ir_link_new_instruction(result, &instruction->base);
17728 return dest_slice_type;
17729}
17730
17731static TypeTableEntry *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) {
17732 IrInstruction *target = instruction->target->other;
17733 if (type_is_invalid(target->value.type))
17734 return ira->codegen->builtin_types.entry_invalid;
17735
17736 if (!is_slice(target->value.type)) {
17737 ir_add_error(ira, instruction->target,
17738 buf_sprintf("expected slice, found '%s'", buf_ptr(&target->value.type->name)));
17739 return ira->codegen->builtin_types.entry_invalid;
17740 }
17741
17742 TypeTableEntry *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;
17743
17744 TypeTableEntry *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
17745 src_ptr_type->data.pointer.is_const, src_ptr_type->data.pointer.is_volatile, PtrLenUnknown,
17746 src_ptr_type->data.pointer.alignment, 0, 0);
17747 TypeTableEntry *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);
17748
17749 IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);
17750 ir_link_new_instruction(result, &instruction->base);
17751 return dest_slice_type;
17752}
17753
17647static TypeTableEntry *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) {17754static TypeTableEntry *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) {
17648 TypeTableEntry *dest_type = ir_resolve_type(ira, instruction->dest_type->other);17755 TypeTableEntry *dest_type = ir_resolve_type(ira, instruction->dest_type->other);
17649 if (type_is_invalid(dest_type))17756 if (type_is_invalid(dest_type))
...@@ -20246,6 +20353,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -20246,6 +20353,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
20246 return ir_analyze_instruction_float_cast(ira, (IrInstructionFloatCast *)instruction);20353 return ir_analyze_instruction_float_cast(ira, (IrInstructionFloatCast *)instruction);
20247 case IrInstructionIdErrSetCast:20354 case IrInstructionIdErrSetCast:
20248 return ir_analyze_instruction_err_set_cast(ira, (IrInstructionErrSetCast *)instruction);20355 return ir_analyze_instruction_err_set_cast(ira, (IrInstructionErrSetCast *)instruction);
20356 case IrInstructionIdFromBytes:
20357 return ir_analyze_instruction_from_bytes(ira, (IrInstructionFromBytes *)instruction);
20358 case IrInstructionIdToBytes:
20359 return ir_analyze_instruction_to_bytes(ira, (IrInstructionToBytes *)instruction);
20249 case IrInstructionIdIntToFloat:20360 case IrInstructionIdIntToFloat:
20250 return ir_analyze_instruction_int_to_float(ira, (IrInstructionIntToFloat *)instruction);20361 return ir_analyze_instruction_int_to_float(ira, (IrInstructionIntToFloat *)instruction);
20251 case IrInstructionIdFloatToInt:20362 case IrInstructionIdFloatToInt:
...@@ -20601,6 +20712,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -20601,6 +20712,8 @@ bool ir_has_side_effects(IrInstruction *instruction) {
20601 case IrInstructionIdIntToFloat:20712 case IrInstructionIdIntToFloat:
20602 case IrInstructionIdFloatToInt:20713 case IrInstructionIdFloatToInt:
20603 case IrInstructionIdBoolToInt:20714 case IrInstructionIdBoolToInt:
20715 case IrInstructionIdFromBytes:
20716 case IrInstructionIdToBytes:
20604 return false;20717 return false;
2060520718
20606 case IrInstructionIdAsm:20719 case IrInstructionIdAsm:
src/ir_print.cpp+20
...@@ -672,6 +672,20 @@ static void ir_print_err_set_cast(IrPrint *irp, IrInstructionErrSetCast *instruc...@@ -672,6 +672,20 @@ static void ir_print_err_set_cast(IrPrint *irp, IrInstructionErrSetCast *instruc
672 fprintf(irp->f, ")");672 fprintf(irp->f, ")");
673}673}
674674
675static void ir_print_from_bytes(IrPrint *irp, IrInstructionFromBytes *instruction) {
676 fprintf(irp->f, "@bytesToSlice(");
677 ir_print_other_instruction(irp, instruction->dest_child_type);
678 fprintf(irp->f, ", ");
679 ir_print_other_instruction(irp, instruction->target);
680 fprintf(irp->f, ")");
681}
682
683static void ir_print_to_bytes(IrPrint *irp, IrInstructionToBytes *instruction) {
684 fprintf(irp->f, "@sliceToBytes(");
685 ir_print_other_instruction(irp, instruction->target);
686 fprintf(irp->f, ")");
687}
688
675static void ir_print_int_to_float(IrPrint *irp, IrInstructionIntToFloat *instruction) {689static void ir_print_int_to_float(IrPrint *irp, IrInstructionIntToFloat *instruction) {
676 fprintf(irp->f, "@intToFloat(");690 fprintf(irp->f, "@intToFloat(");
677 ir_print_other_instruction(irp, instruction->dest_type);691 ir_print_other_instruction(irp, instruction->dest_type);
...@@ -1472,6 +1486,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1472,6 +1486,12 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1472 case IrInstructionIdErrSetCast:1486 case IrInstructionIdErrSetCast:
1473 ir_print_err_set_cast(irp, (IrInstructionErrSetCast *)instruction);1487 ir_print_err_set_cast(irp, (IrInstructionErrSetCast *)instruction);
1474 break;1488 break;
1489 case IrInstructionIdFromBytes:
1490 ir_print_from_bytes(irp, (IrInstructionFromBytes *)instruction);
1491 break;
1492 case IrInstructionIdToBytes:
1493 ir_print_to_bytes(irp, (IrInstructionToBytes *)instruction);
1494 break;
1475 case IrInstructionIdIntToFloat:1495 case IrInstructionIdIntToFloat:
1476 ir_print_int_to_float(irp, (IrInstructionIntToFloat *)instruction);1496 ir_print_int_to_float(irp, (IrInstructionIntToFloat *)instruction);
1477 break;1497 break;
std/heap.zig+1-1
...@@ -221,7 +221,7 @@ pub const ArenaAllocator = struct {...@@ -221,7 +221,7 @@ pub const ArenaAllocator = struct {
221 if (len >= actual_min_size) break;221 if (len >= actual_min_size) break;
222 }222 }
223 const buf = try self.child_allocator.alignedAlloc(u8, @alignOf(BufNode), len);223 const buf = try self.child_allocator.alignedAlloc(u8, @alignOf(BufNode), len);
224 const buf_node_slice = ([]BufNode)(buf[0..@sizeOf(BufNode)]);224 const buf_node_slice = @bytesToSlice(BufNode, buf[0..@sizeOf(BufNode)]);
225 const buf_node = &buf_node_slice[0];225 const buf_node = &buf_node_slice[0];
226 buf_node.* = BufNode{226 buf_node.* = BufNode{
227 .data = buf,227 .data = buf,
std/macho.zig+1-1
...@@ -161,7 +161,7 @@ pub fn loadSymbols(allocator: *mem.Allocator, in: *io.FileInStream) !SymbolTable...@@ -161,7 +161,7 @@ pub fn loadSymbols(allocator: *mem.Allocator, in: *io.FileInStream) !SymbolTable
161}161}
162162
163fn readNoEof(in: *io.FileInStream, comptime T: type, result: []T) !void {163fn readNoEof(in: *io.FileInStream, comptime T: type, result: []T) !void {
164 return in.stream.readNoEof(([]u8)(result));164 return in.stream.readNoEof(@sliceToBytes(result));
165}165}
166fn readOneNoEof(in: *io.FileInStream, comptime T: type, result: *T) !void {166fn readOneNoEof(in: *io.FileInStream, comptime T: type, result: *T) !void {
167 return readNoEof(in, T, (*[1]T)(result)[0..]);167 return readNoEof(in, T, (*[1]T)(result)[0..]);
std/mem.zig+6-6
...@@ -70,7 +70,7 @@ pub const Allocator = struct {...@@ -70,7 +70,7 @@ pub const Allocator = struct {
70 for (byte_slice) |*byte| {70 for (byte_slice) |*byte| {
71 byte.* = undefined;71 byte.* = undefined;
72 }72 }
73 return ([]align(alignment) T)(@alignCast(alignment, byte_slice));73 return @bytesToSlice(T, @alignCast(alignment, byte_slice));
74 }74 }
7575
76 pub fn realloc(self: *Allocator, comptime T: type, old_mem: []T, n: usize) ![]T {76 pub fn realloc(self: *Allocator, comptime T: type, old_mem: []T, n: usize) ![]T {
...@@ -86,7 +86,7 @@ pub const Allocator = struct {...@@ -86,7 +86,7 @@ pub const Allocator = struct {
86 return ([*]align(alignment) T)(undefined)[0..0];86 return ([*]align(alignment) T)(undefined)[0..0];
87 }87 }
8888
89 const old_byte_slice = ([]u8)(old_mem);89 const old_byte_slice = @sliceToBytes(old_mem);
90 const byte_count = math.mul(usize, @sizeOf(T), n) catch return Error.OutOfMemory;90 const byte_count = math.mul(usize, @sizeOf(T), n) catch return Error.OutOfMemory;
91 const byte_slice = try self.reallocFn(self, old_byte_slice, byte_count, alignment);91 const byte_slice = try self.reallocFn(self, old_byte_slice, byte_count, alignment);
92 assert(byte_slice.len == byte_count);92 assert(byte_slice.len == byte_count);
...@@ -96,7 +96,7 @@ pub const Allocator = struct {...@@ -96,7 +96,7 @@ pub const Allocator = struct {
96 byte.* = undefined;96 byte.* = undefined;
97 }97 }
98 }98 }
99 return ([]T)(@alignCast(alignment, byte_slice));99 return @bytesToSlice(T, @alignCast(alignment, byte_slice));
100 }100 }
101101
102 /// Reallocate, but `n` must be less than or equal to `old_mem.len`.102 /// Reallocate, but `n` must be less than or equal to `old_mem.len`.
...@@ -118,13 +118,13 @@ pub const Allocator = struct {...@@ -118,13 +118,13 @@ pub const Allocator = struct {
118 // n <= old_mem.len and the multiplication didn't overflow for that operation.118 // n <= old_mem.len and the multiplication didn't overflow for that operation.
119 const byte_count = @sizeOf(T) * n;119 const byte_count = @sizeOf(T) * n;
120120
121 const byte_slice = self.reallocFn(self, ([]u8)(old_mem), byte_count, alignment) catch unreachable;121 const byte_slice = self.reallocFn(self, @sliceToBytes(old_mem), byte_count, alignment) catch unreachable;
122 assert(byte_slice.len == byte_count);122 assert(byte_slice.len == byte_count);
123 return ([]align(alignment) T)(@alignCast(alignment, byte_slice));123 return @bytesToSlice(T, @alignCast(alignment, byte_slice));
124 }124 }
125125
126 pub fn free(self: *Allocator, memory: var) void {126 pub fn free(self: *Allocator, memory: var) void {
127 const bytes = ([]const u8)(memory);127 const bytes = @sliceToBytes(memory);
128 if (bytes.len == 0) return;128 if (bytes.len == 0) return;
129 const non_const_ptr = @intToPtr([*]u8, @ptrToInt(bytes.ptr));129 const non_const_ptr = @intToPtr([*]u8, @ptrToInt(bytes.ptr));
130 self.freeFn(self, non_const_ptr[0..bytes.len]);130 self.freeFn(self, non_const_ptr[0..bytes.len]);
std/net.zig+1-1
...@@ -68,7 +68,7 @@ pub const Address = struct {...@@ -68,7 +68,7 @@ pub const Address = struct {
6868
69pub fn parseIp4(buf: []const u8) !u32 {69pub fn parseIp4(buf: []const u8) !u32 {
70 var result: u32 = undefined;70 var result: u32 = undefined;
71 const out_ptr = ([]u8)((*[1]u32)(&result)[0..]);71 const out_ptr = @sliceToBytes((*[1]u32)(&result)[0..]);
7272
73 var x: u8 = 0;73 var x: u8 = 0;
74 var index: u8 = 0;74 var index: u8 = 0;
std/os/windows/util.zig+1-1
...@@ -79,7 +79,7 @@ pub fn windowsIsCygwinPty(handle: windows.HANDLE) bool {...@@ -79,7 +79,7 @@ pub fn windowsIsCygwinPty(handle: windows.HANDLE) bool {
7979
80 const name_info = @ptrCast(*const windows.FILE_NAME_INFO, &name_info_bytes[0]);80 const name_info = @ptrCast(*const windows.FILE_NAME_INFO, &name_info_bytes[0]);
81 const name_bytes = name_info_bytes[size .. size + usize(name_info.FileNameLength)];81 const name_bytes = name_info_bytes[size .. size + usize(name_info.FileNameLength)];
82 const name_wide = ([]u16)(name_bytes);82 const name_wide = @bytesToSlice(u16, name_bytes);
83 return mem.indexOf(u16, name_wide, []u16{ 'm', 's', 'y', 's', '-' }) != null or83 return mem.indexOf(u16, name_wide, []u16{ 'm', 's', 'y', 's', '-' }) != null or
84 mem.indexOf(u16, name_wide, []u16{ '-', 'p', 't', 'y' }) != null;84 mem.indexOf(u16, name_wide, []u16{ '-', 'p', 't', 'y' }) != null;
85}85}
test/cases/align.zig+1-1
...@@ -90,7 +90,7 @@ fn testBytesAlignSlice(b: u8) void {...@@ -90,7 +90,7 @@ fn testBytesAlignSlice(b: u8) void {
90 b,90 b,
91 b,91 b,
92 };92 };
93 const slice = ([]u32)(bytes[0..]);93 const slice: []u32 = @bytesToSlice(u32, bytes[0..]);
94 assert(slice[0] == 0x33333333);94 assert(slice[0] == 0x33333333);
95}95}
9696
test/cases/cast.zig+7-1
...@@ -372,7 +372,7 @@ test "const slice widen cast" {...@@ -372,7 +372,7 @@ test "const slice widen cast" {
372 0x12,372 0x12,
373 };373 };
374374
375 const u32_value = ([]const u32)(bytes[0..])[0];375 const u32_value = @bytesToSlice(u32, bytes[0..])[0];
376 assert(u32_value == 0x12121212);376 assert(u32_value == 0x12121212);
377377
378 assert(@bitCast(u32, bytes) == 0x12121212);378 assert(@bitCast(u32, bytes) == 0x12121212);
...@@ -420,3 +420,9 @@ test "comptime_int @intToFloat" {...@@ -420,3 +420,9 @@ test "comptime_int @intToFloat" {
420 assert(@typeOf(result) == f32);420 assert(@typeOf(result) == f32);
421 assert(result == 1234.0);421 assert(result == 1234.0);
422}422}
423
424test "@bytesToSlice keeps pointer alignment" {
425 var bytes = []u8{ 0x01, 0x02, 0x03, 0x04 };
426 const numbers = @bytesToSlice(u32, bytes[0..]);
427 comptime assert(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32);
428}
test/cases/misc.zig+2-2
...@@ -422,14 +422,14 @@ test "cast slice to u8 slice" {...@@ -422,14 +422,14 @@ test "cast slice to u8 slice" {
422 4,422 4,
423 };423 };
424 const big_thing_slice: []i32 = big_thing_array[0..];424 const big_thing_slice: []i32 = big_thing_array[0..];
425 const bytes = ([]u8)(big_thing_slice);425 const bytes = @sliceToBytes(big_thing_slice);
426 assert(bytes.len == 4 * 4);426 assert(bytes.len == 4 * 4);
427 bytes[4] = 0;427 bytes[4] = 0;
428 bytes[5] = 0;428 bytes[5] = 0;
429 bytes[6] = 0;429 bytes[6] = 0;
430 bytes[7] = 0;430 bytes[7] = 0;
431 assert(big_thing_slice[1] == 0);431 assert(big_thing_slice[1] == 0);
432 const big_thing_again = ([]align(1) i32)(bytes);432 const big_thing_again = @bytesToSlice(i32, bytes);
433 assert(big_thing_again[2] == 3);433 assert(big_thing_again[2] == 3);
434 big_thing_again[2] = -1;434 big_thing_again[2] = -1;
435 assert(bytes[8] == @maxValue(u8));435 assert(bytes[8] == @maxValue(u8));
test/cases/struct.zig+2-2
...@@ -302,7 +302,7 @@ test "packed array 24bits" {...@@ -302,7 +302,7 @@ test "packed array 24bits" {
302302
303 var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1);303 var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1);
304 bytes[bytes.len - 1] = 0xaa;304 bytes[bytes.len - 1] = 0xaa;
305 const ptr = &([]FooArray24Bits)(bytes[0 .. bytes.len - 1])[0];305 const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0];
306 assert(ptr.a == 0);306 assert(ptr.a == 0);
307 assert(ptr.b[0].field == 0);307 assert(ptr.b[0].field == 0);
308 assert(ptr.b[1].field == 0);308 assert(ptr.b[1].field == 0);
...@@ -351,7 +351,7 @@ test "aligned array of packed struct" {...@@ -351,7 +351,7 @@ test "aligned array of packed struct" {
351 }351 }
352352
353 var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned);353 var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned);
354 const ptr = &([]FooArrayOfAligned)(bytes[0..bytes.len])[0];354 const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0];
355355
356 assert(ptr.a[0].a == 0xbb);356 assert(ptr.a[0].a == 0xbb);
357 assert(ptr.a[0].b == 0xbb);357 assert(ptr.a[0].b == 0xbb);
test/compile_errors.zig+5-16
...@@ -404,10 +404,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -404,10 +404,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
404 \\const Set2 = error {A, C};404 \\const Set2 = error {A, C};
405 \\comptime {405 \\comptime {
406 \\ var x = Set1.B;406 \\ var x = Set1.B;
407 \\ var y = Set2(x);407 \\ var y = @errSetCast(Set2, x);
408 \\}408 \\}
409 ,409 ,
410 ".tmp_source.zig:5:17: error: error.B not a member of error set 'Set2'",410 ".tmp_source.zig:5:13: error: error.B not a member of error set 'Set2'",
411 );411 );
412412
413 cases.add(413 cases.add(
...@@ -2086,10 +2086,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2086,10 +2086,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2086 "convert fixed size array to slice with invalid size",2086 "convert fixed size array to slice with invalid size",
2087 \\export fn f() void {2087 \\export fn f() void {
2088 \\ var array: [5]u8 = undefined;2088 \\ var array: [5]u8 = undefined;
2089 \\ var foo = ([]const u32)(array)[0];2089 \\ var foo = @bytesToSlice(u32, array)[0];
2090 \\}2090 \\}
2091 ,2091 ,
2092 ".tmp_source.zig:3:28: error: unable to convert [5]u8 to []const u32: size mismatch",2092 ".tmp_source.zig:3:15: error: unable to convert [5]u8 to []align(1) const u32: size mismatch",
2093 ".tmp_source.zig:3:29: note: u32 has size 4; remaining bytes: 1",
2093 );2094 );
20942095
2095 cases.add(2096 cases.add(
...@@ -3239,18 +3240,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3239,18 +3240,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3239 ".tmp_source.zig:3:26: note: '*u32' has alignment 4",3240 ".tmp_source.zig:3:26: note: '*u32' has alignment 4",
3240 );3241 );
32413242
3242 cases.add(
3243 "increase pointer alignment in slice resize",
3244 \\export fn entry() u32 {
3245 \\ var bytes = []u8{0x01, 0x02, 0x03, 0x04};
3246 \\ return ([]u32)(bytes[0..])[0];
3247 \\}
3248 ,
3249 ".tmp_source.zig:3:19: error: cast increases pointer alignment",
3250 ".tmp_source.zig:3:19: note: '[]u8' has alignment 1",
3251 ".tmp_source.zig:3:19: note: '[]u32' has alignment 4",
3252 );
3253
3254 cases.add(3243 cases.add(
3255 "@alignCast expects pointer or slice",3244 "@alignCast expects pointer or slice",
3256 \\export fn entry() void {3245 \\export fn entry() void {