authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-19 11:40:21-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2018-06-19 11:40:21-04:00
log9f2324389d4aec5d38e840ab09fd9af558a77913
tree685b621eb041c178af40c0044c74f689d8d6af7b
parent1ca90b585692c9611c64412844d2f3a7b3e11340
parenta3ddd0826bd9c799768c0c707de72c21befa742a
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #1134 from ziglang/no-explicit-casting

remove "cast harder" casting syntax; add new casting builtins

24 files changed, 697 insertions(+), 222 deletions(-)

doc/langref.html.in+122-28
...@@ -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);
...@@ -1901,9 +1900,9 @@ const Value = enum(u2) {...@@ -1901,9 +1900,9 @@ const Value = enum(u2) {
1901// Now you can cast between u2 and Value.1900// Now you can cast between u2 and Value.
1902// The ordinal value starts from 0, counting up for each member.1901// The ordinal value starts from 0, counting up for each member.
1903test "enum ordinal value" {1902test "enum ordinal value" {
1904 assert(u2(Value.Zero) == 0);1903 assert(@enumToInt(Value.Zero) == 0);
1905 assert(u2(Value.One) == 1);1904 assert(@enumToInt(Value.One) == 1);
1906 assert(u2(Value.Two) == 2);1905 assert(@enumToInt(Value.Two) == 2);
1907}1906}
19081907
1909// You can override the ordinal value for an enum.1908// You can override the ordinal value for an enum.
...@@ -1913,9 +1912,9 @@ const Value2 = enum(u32) {...@@ -1913,9 +1912,9 @@ const Value2 = enum(u32) {
1913 Million = 1000000,1912 Million = 1000000,
1914};1913};
1915test "set enum ordinal value" {1914test "set enum ordinal value" {
1916 assert(u32(Value2.Hundred) == 100);1915 assert(@enumToInt(Value2.Hundred) == 100);
1917 assert(u32(Value2.Thousand) == 1000);1916 assert(@enumToInt(Value2.Thousand) == 1000);
1918 assert(u32(Value2.Million) == 1000000);1917 assert(@enumToInt(Value2.Million) == 1000000);
1919}1918}
19201919
1921// Enums can have methods, the same as structs and unions.1920// Enums can have methods, the same as structs and unions.
...@@ -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 safety-protected {#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>
...@@ -4919,12 +4930,23 @@ test "main" {...@@ -4919,12 +4930,23 @@ test "main" {
4919 </p>4930 </p>
4920 {#see_also|@import#}4931 {#see_also|@import#}
4921 {#header_close#}4932 {#header_close#}
4922 {#header_open|@export#}4933
4923 <pre><code class="zig">@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8</code></pre>4934 {#header_open|@enumToInt#}
4935 <pre><code class="zig">@enumToInt(enum_value: var) var</code></pre>
4924 <p>4936 <p>
4925 Creates a symbol in the output object file.4937 Converts an enumeration value into its integer tag type.
4938 </p>
4939 {#see_also|@intToEnum#}
4940 {#header_close#}
4941
4942 {#header_open|@errSetCast#}
4943 <pre><code class="zig">@errSetCast(comptime T: DestType, value: var) DestType</code></pre>
4944 <p>
4945 Converts an error value from one error set to another error set. Attempting to convert an error
4946 which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}.
4926 </p>4947 </p>
4927 {#header_close#}4948 {#header_close#}
4949
4928 {#header_open|@errorName#}4950 {#header_open|@errorName#}
4929 <pre><code class="zig">@errorName(err: error) []u8</code></pre>4951 <pre><code class="zig">@errorName(err: error) []u8</code></pre>
4930 <p>4952 <p>
...@@ -4941,6 +4963,7 @@ test "main" {...@@ -4941,6 +4963,7 @@ test "main" {
4941 error name table will be generated.4963 error name table will be generated.
4942 </p>4964 </p>
4943 {#header_close#}4965 {#header_close#}
4966
4944 {#header_open|@errorReturnTrace#}4967 {#header_open|@errorReturnTrace#}
4945 <pre><code class="zig">@errorReturnTrace() ?*builtin.StackTrace</code></pre>4968 <pre><code class="zig">@errorReturnTrace() ?*builtin.StackTrace</code></pre>
4946 <p>4969 <p>
...@@ -4949,6 +4972,33 @@ test "main" {...@@ -4949,6 +4972,33 @@ test "main" {
4949 stack trace object. Otherwise returns `null`.4972 stack trace object. Otherwise returns `null`.
4950 </p>4973 </p>
4951 {#header_close#}4974 {#header_close#}
4975
4976 {#header_open|@errorToInt#}
4977 <pre><code class="zig">@errorToInt(err: var) @IntType(false, @sizeOf(error) * 8)</code></pre>
4978 <p>
4979 Supports the following types:
4980 </p>
4981 <ul>
4982 <li>error unions</li>
4983 <li><code>E!void</code></li>
4984 </ul>
4985 <p>
4986 Converts an error to the integer representation of an error.
4987 </p>
4988 <p>
4989 It is generally recommended to avoid this
4990 cast, as the integer representation of an error is not stable across source code changes.
4991 </p>
4992 {#see_also|@intToError#}
4993 {#header_close#}
4994
4995 {#header_open|@export#}
4996 <pre><code class="zig">@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8</code></pre>
4997 <p>
4998 Creates a symbol in the output object file.
4999 </p>
5000 {#header_close#}
5001
4952 {#header_open|@fence#}5002 {#header_open|@fence#}
4953 <pre><code class="zig">@fence(order: AtomicOrder)</code></pre>5003 <pre><code class="zig">@fence(order: AtomicOrder)</code></pre>
4954 <p>5004 <p>
...@@ -5049,8 +5099,36 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -5049,8 +5099,36 @@ fn add(a: i32, b: i32) i32 { return a + b; }
5049 <p>5099 <p>
5050 Converts an integer to another integer while keeping the same numerical value.5100 Converts an integer to another integer while keeping the same numerical value.
5051 Attempting to convert a number which is out of range of the destination type results in5101 Attempting to convert a number which is out of range of the destination type results in
5052 {#link|Undefined Behavior#}.5102 safety-protected {#link|Undefined Behavior#}.
5103 </p>
5104 {#header_close#}
5105
5106 {#header_open|@intToEnum#}
5107 <pre><code class="zig">@intToEnum(comptime DestType: type, int_value: @TagType(DestType)) DestType</code></pre>
5108 <p>
5109 Converts an integer into an {#link|enum#} value.
5110 </p>
5111 <p>
5112 Attempting to convert an integer which represents no value in the chosen enum type invokes
5113 safety-checked {#link|Undefined Behavior#}.
5114 </p>
5115 {#see_also|@enumToInt#}
5116 {#header_close#}
5117
5118 {#header_open|@intToError#}
5119 <pre><code class="zig">@intToError(value: @IntType(false, @sizeOf(error) * 8)) error</code></pre>
5120 <p>
5121 Converts from the integer representation of an error into the global error set type.
5053 </p>5122 </p>
5123 <p>
5124 It is generally recommended to avoid this
5125 cast, as the integer representation of an error is not stable across source code changes.
5126 </p>
5127 <p>
5128 Attempting to convert an integer that does not correspond to any error results in
5129 safety-protected {#link|Undefined Behavior#}.
5130 </p>
5131 {#see_also|@errorToInt#}
5054 {#header_close#}5132 {#header_close#}
50555133
5056 {#header_open|@intToFloat#}5134 {#header_open|@intToFloat#}
...@@ -5456,8 +5534,9 @@ pub const FloatMode = enum {...@@ -5456,8 +5534,9 @@ pub const FloatMode = enum {
5456 </p>5534 </p>
5457 {#see_also|@shlExact|@shlWithOverflow#}5535 {#see_also|@shlExact|@shlWithOverflow#}
5458 {#header_close#}5536 {#header_close#}
5537
5459 {#header_open|@sizeOf#}5538 {#header_open|@sizeOf#}
5460 <pre><code class="zig">@sizeOf(comptime T: type) (number literal)</code></pre>5539 <pre><code class="zig">@sizeOf(comptime T: type) comptime_int</code></pre>
5461 <p>5540 <p>
5462 This function returns the number of bytes it takes to store <code>T</code> in memory.5541 This function returns the number of bytes it takes to store <code>T</code> in memory.
5463 </p>5542 </p>
...@@ -5465,6 +5544,15 @@ pub const FloatMode = enum {...@@ -5465,6 +5544,15 @@ pub const FloatMode = enum {
5465 The result is a target-specific compile time constant.5544 The result is a target-specific compile time constant.
5466 </p>5545 </p>
5467 {#header_close#}5546 {#header_close#}
5547
5548 {#header_open|@sliceToBytes#}
5549 <pre><code class="zig">@sliceToBytes(value: var) []u8</code></pre>
5550 <p>
5551 Converts a slice or array to a slice of <code>u8</code>. The resulting slice has the same
5552 {#link|pointer|Pointers#} properties as the parameter.
5553 </p>
5554 {#header_close#}
5555
5468 {#header_open|@sqrt#}5556 {#header_open|@sqrt#}
5469 <pre><code class="zig">@sqrt(comptime T: type, value: T) T</code></pre>5557 <pre><code class="zig">@sqrt(comptime T: type, value: T) T</code></pre>
5470 <p>5558 <p>
...@@ -5817,10 +5905,10 @@ pub fn build(b: &Builder) void {...@@ -5817,10 +5905,10 @@ pub fn build(b: &Builder) void {
5817 {#header_open|Undefined Behavior#}5905 {#header_open|Undefined Behavior#}
5818 <p>5906 <p>
5819 Zig has many instances of undefined behavior. If undefined behavior is5907 Zig has many instances of undefined behavior. If undefined behavior is
5820 detected at compile-time, Zig emits an error. Most undefined behavior that5908 detected at compile-time, Zig emits a compile error and refuses to continue.
5821 cannot be detected at compile-time can be detected at runtime. In these cases,5909 Most undefined behavior that cannot be detected at compile-time can be detected
5822 Zig has safety checks. Safety checks can be disabled on a per-block basis5910 at runtime. In these cases, Zig has safety checks. Safety checks can be disabled
5823 with {#link|setRuntimeSafety#}. The {#link|ReleaseFast#}5911 on a per-block basis with {#link|setRuntimeSafety#}. The {#link|ReleaseFast#}
5824 build mode disables all safety checks in order to facilitate optimizations.5912 build mode disables all safety checks in order to facilitate optimizations.
5825 </p>5913 </p>
5826 <p>5914 <p>
...@@ -6091,8 +6179,8 @@ fn getNumberOrFail() !i32 {...@@ -6091,8 +6179,8 @@ fn getNumberOrFail() !i32 {
6091 {#code_begin|test_err|integer value 11 represents no error#}6179 {#code_begin|test_err|integer value 11 represents no error#}
6092comptime {6180comptime {
6093 const err = error.AnError;6181 const err = error.AnError;
6094 const number = u32(err) + 10;6182 const number = @errorToInt(err) + 10;
6095 const invalid_err = error(number);6183 const invalid_err = @intToError(number);
6096}6184}
6097 {#code_end#}6185 {#code_end#}
6098 <p>At runtime crashes with the message <code>invalid error code</code> and a stack trace.</p>6186 <p>At runtime crashes with the message <code>invalid error code</code> and a stack trace.</p>
...@@ -6101,6 +6189,11 @@ comptime {...@@ -6101,6 +6189,11 @@ comptime {
6101 <p>TODO</p>6189 <p>TODO</p>
61026190
6103 {#header_close#}6191 {#header_close#}
6192
6193 {#header_open|Invalid Error Set Cast#}
6194 <p>TODO</p>
6195 {#header_close#}
6196
6104 {#header_open|Incorrect Pointer Alignment#}6197 {#header_open|Incorrect Pointer Alignment#}
6105 <p>TODO</p>6198 <p>TODO</p>
61066199
...@@ -6109,6 +6202,7 @@ comptime {...@@ -6109,6 +6202,7 @@ comptime {
6109 <p>TODO</p>6202 <p>TODO</p>
61106203
6111 {#header_close#}6204 {#header_close#}
6205
6112 {#header_close#}6206 {#header_close#}
6113 {#header_open|Memory#}6207 {#header_open|Memory#}
6114 <p>TODO: explain no default allocator in zig</p>6208 <p>TODO: explain no default allocator in zig</p>
...@@ -6793,7 +6887,7 @@ hljs.registerLanguage("zig", function(t) {...@@ -6793,7 +6887,7 @@ hljs.registerLanguage("zig", function(t) {
6793 a = t.IR + "\\s*\\(",6887 a = t.IR + "\\s*\\(",
6794 c = {6888 c = {
6795 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",6889 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",
6796 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",6890 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 errorToInt intToError enumToInt intToEnum",
6797 literal: "true false null undefined"6891 literal: "true false null undefined"
6798 },6892 },
6799 n = [e, t.CLCM, t.CBCM, s, r];6893 n = [e, t.CLCM, t.CBCM, s, r];
src/all_types.hpp+49
...@@ -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
...@@ -1359,9 +1370,16 @@ enum BuiltinFnId {...@@ -1359,9 +1370,16 @@ enum BuiltinFnId {
1359 BuiltinFnIdTruncate,1370 BuiltinFnIdTruncate,
1360 BuiltinFnIdIntCast,1371 BuiltinFnIdIntCast,
1361 BuiltinFnIdFloatCast,1372 BuiltinFnIdFloatCast,
1373 BuiltinFnIdErrSetCast,
1374 BuiltinFnIdToBytes,
1375 BuiltinFnIdFromBytes,
1362 BuiltinFnIdIntToFloat,1376 BuiltinFnIdIntToFloat,
1363 BuiltinFnIdFloatToInt,1377 BuiltinFnIdFloatToInt,
1364 BuiltinFnIdBoolToInt,1378 BuiltinFnIdBoolToInt,
1379 BuiltinFnIdErrToInt,
1380 BuiltinFnIdIntToErr,
1381 BuiltinFnIdEnumToInt,
1382 BuiltinFnIdIntToEnum,
1365 BuiltinFnIdIntType,1383 BuiltinFnIdIntType,
1366 BuiltinFnIdSetCold,1384 BuiltinFnIdSetCold,
1367 BuiltinFnIdSetRuntimeSafety,1385 BuiltinFnIdSetRuntimeSafety,
...@@ -2076,6 +2094,7 @@ enum IrInstructionId {...@@ -2076,6 +2094,7 @@ enum IrInstructionId {
2076 IrInstructionIdIntToPtr,2094 IrInstructionIdIntToPtr,
2077 IrInstructionIdPtrToInt,2095 IrInstructionIdPtrToInt,
2078 IrInstructionIdIntToEnum,2096 IrInstructionIdIntToEnum,
2097 IrInstructionIdEnumToInt,
2079 IrInstructionIdIntToErr,2098 IrInstructionIdIntToErr,
2080 IrInstructionIdErrToInt,2099 IrInstructionIdErrToInt,
2081 IrInstructionIdCheckSwitchProngs,2100 IrInstructionIdCheckSwitchProngs,
...@@ -2121,6 +2140,9 @@ enum IrInstructionId {...@@ -2121,6 +2140,9 @@ enum IrInstructionId {
2121 IrInstructionIdMergeErrRetTraces,2140 IrInstructionIdMergeErrRetTraces,
2122 IrInstructionIdMarkErrRetTracePtr,2141 IrInstructionIdMarkErrRetTracePtr,
2123 IrInstructionIdSqrt,2142 IrInstructionIdSqrt,
2143 IrInstructionIdErrSetCast,
2144 IrInstructionIdToBytes,
2145 IrInstructionIdFromBytes,
2124};2146};
21252147
2126struct IrInstruction {2148struct IrInstruction {
...@@ -2656,6 +2678,26 @@ struct IrInstructionFloatCast {...@@ -2656,6 +2678,26 @@ struct IrInstructionFloatCast {
2656 IrInstruction *target;2678 IrInstruction *target;
2657};2679};
26582680
2681struct IrInstructionErrSetCast {
2682 IrInstruction base;
2683
2684 IrInstruction *dest_type;
2685 IrInstruction *target;
2686};
2687
2688struct IrInstructionToBytes {
2689 IrInstruction base;
2690
2691 IrInstruction *target;
2692};
2693
2694struct IrInstructionFromBytes {
2695 IrInstruction base;
2696
2697 IrInstruction *dest_child_type;
2698 IrInstruction *target;
2699};
2700
2659struct IrInstructionIntToFloat {2701struct IrInstructionIntToFloat {
2660 IrInstruction base;2702 IrInstruction base;
26612703
...@@ -2866,6 +2908,13 @@ struct IrInstructionIntToPtr {...@@ -2866,6 +2908,13 @@ struct IrInstructionIntToPtr {
2866struct IrInstructionIntToEnum {2908struct IrInstructionIntToEnum {
2867 IrInstruction base;2909 IrInstruction base;
28682910
2911 IrInstruction *dest_type;
2912 IrInstruction *target;
2913};
2914
2915struct IrInstructionEnumToInt {
2916 IrInstruction base;
2917
2869 IrInstruction *target;2918 IrInstruction *target;
2870};2919};
28712920
src/codegen.cpp+11
...@@ -4727,6 +4727,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -4727,6 +4727,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
4727 case IrInstructionIdIntToFloat:4727 case IrInstructionIdIntToFloat:
4728 case IrInstructionIdFloatToInt:4728 case IrInstructionIdFloatToInt:
4729 case IrInstructionIdBoolToInt:4729 case IrInstructionIdBoolToInt:
4730 case IrInstructionIdErrSetCast:
4731 case IrInstructionIdFromBytes:
4732 case IrInstructionIdToBytes:
4733 case IrInstructionIdEnumToInt:
4730 zig_unreachable();4734 zig_unreachable();
47314735
4732 case IrInstructionIdReturn:4736 case IrInstructionIdReturn:
...@@ -6320,6 +6324,10 @@ static void define_builtin_fns(CodeGen *g) {...@@ -6320,6 +6324,10 @@ static void define_builtin_fns(CodeGen *g) {
6320 create_builtin_fn(g, BuiltinFnIdIntToFloat, "intToFloat", 2);6324 create_builtin_fn(g, BuiltinFnIdIntToFloat, "intToFloat", 2);
6321 create_builtin_fn(g, BuiltinFnIdFloatToInt, "floatToInt", 2);6325 create_builtin_fn(g, BuiltinFnIdFloatToInt, "floatToInt", 2);
6322 create_builtin_fn(g, BuiltinFnIdBoolToInt, "boolToInt", 1);6326 create_builtin_fn(g, BuiltinFnIdBoolToInt, "boolToInt", 1);
6327 create_builtin_fn(g, BuiltinFnIdErrToInt, "errorToInt", 1);
6328 create_builtin_fn(g, BuiltinFnIdIntToErr, "intToError", 1);
6329 create_builtin_fn(g, BuiltinFnIdEnumToInt, "enumToInt", 1);
6330 create_builtin_fn(g, BuiltinFnIdIntToEnum, "intToEnum", 2);
6323 create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);6331 create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
6324 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);6332 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
6325 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int6333 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
...@@ -6356,6 +6364,9 @@ static void define_builtin_fns(CodeGen *g) {...@@ -6356,6 +6364,9 @@ static void define_builtin_fns(CodeGen *g) {
6356 create_builtin_fn(g, BuiltinFnIdErrorReturnTrace, "errorReturnTrace", 0);6364 create_builtin_fn(g, BuiltinFnIdErrorReturnTrace, "errorReturnTrace", 0);
6357 create_builtin_fn(g, BuiltinFnIdAtomicRmw, "atomicRmw", 5);6365 create_builtin_fn(g, BuiltinFnIdAtomicRmw, "atomicRmw", 5);
6358 create_builtin_fn(g, BuiltinFnIdAtomicLoad, "atomicLoad", 3);6366 create_builtin_fn(g, BuiltinFnIdAtomicLoad, "atomicLoad", 3);
6367 create_builtin_fn(g, BuiltinFnIdErrSetCast, "errSetCast", 2);
6368 create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);
6369 create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
6359}6370}
63606371
6361static const char *bool_to_str(bool b) {6372static const char *bool_to_str(bool b) {
src/ir.cpp+389-90
...@@ -468,6 +468,18 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFloatCast *) {...@@ -468,6 +468,18 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFloatCast *) {
468 return IrInstructionIdFloatCast;468 return IrInstructionIdFloatCast;
469}469}
470470
471static constexpr IrInstructionId ir_instruction_id(IrInstructionErrSetCast *) {
472 return IrInstructionIdErrSetCast;
473}
474
475static constexpr IrInstructionId ir_instruction_id(IrInstructionToBytes *) {
476 return IrInstructionIdToBytes;
477}
478
479static constexpr IrInstructionId ir_instruction_id(IrInstructionFromBytes *) {
480 return IrInstructionIdFromBytes;
481}
482
471static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToFloat *) {483static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToFloat *) {
472 return IrInstructionIdIntToFloat;484 return IrInstructionIdIntToFloat;
473}485}
...@@ -588,6 +600,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToEnum *) {...@@ -588,6 +600,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToEnum *) {
588 return IrInstructionIdIntToEnum;600 return IrInstructionIdIntToEnum;
589}601}
590602
603static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumToInt *) {
604 return IrInstructionIdEnumToInt;
605}
606
591static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToErr *) {607static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToErr *) {
592 return IrInstructionIdIntToErr;608 return IrInstructionIdIntToErr;
593}609}
...@@ -1941,6 +1957,37 @@ static IrInstruction *ir_build_float_cast(IrBuilder *irb, Scope *scope, AstNode...@@ -1941,6 +1957,37 @@ static IrInstruction *ir_build_float_cast(IrBuilder *irb, Scope *scope, AstNode
1941 return &instruction->base;1957 return &instruction->base;
1942}1958}
19431959
1960static IrInstruction *ir_build_err_set_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) {
1961 IrInstructionErrSetCast *instruction = ir_build_instruction<IrInstructionErrSetCast>(irb, scope, source_node);
1962 instruction->dest_type = dest_type;
1963 instruction->target = target;
1964
1965 ir_ref_instruction(dest_type, irb->current_basic_block);
1966 ir_ref_instruction(target, irb->current_basic_block);
1967
1968 return &instruction->base;
1969}
1970
1971static IrInstruction *ir_build_to_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target) {
1972 IrInstructionToBytes *instruction = ir_build_instruction<IrInstructionToBytes>(irb, scope, source_node);
1973 instruction->target = target;
1974
1975 ir_ref_instruction(target, irb->current_basic_block);
1976
1977 return &instruction->base;
1978}
1979
1980static IrInstruction *ir_build_from_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_child_type, IrInstruction *target) {
1981 IrInstructionFromBytes *instruction = ir_build_instruction<IrInstructionFromBytes>(irb, scope, source_node);
1982 instruction->dest_child_type = dest_child_type;
1983 instruction->target = target;
1984
1985 ir_ref_instruction(dest_child_type, irb->current_basic_block);
1986 ir_ref_instruction(target, irb->current_basic_block);
1987
1988 return &instruction->base;
1989}
1990
1944static IrInstruction *ir_build_int_to_float(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) {1991static IrInstruction *ir_build_int_to_float(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) {
1945 IrInstructionIntToFloat *instruction = ir_build_instruction<IrInstructionIntToFloat>(irb, scope, source_node);1992 IrInstructionIntToFloat *instruction = ir_build_instruction<IrInstructionIntToFloat>(irb, scope, source_node);
1946 instruction->dest_type = dest_type;1993 instruction->dest_type = dest_type;
...@@ -2335,10 +2382,26 @@ static IrInstruction *ir_build_ptr_to_int(IrBuilder *irb, Scope *scope, AstNode...@@ -2335,10 +2382,26 @@ static IrInstruction *ir_build_ptr_to_int(IrBuilder *irb, Scope *scope, AstNode
2335}2382}
23362383
2337static IrInstruction *ir_build_int_to_enum(IrBuilder *irb, Scope *scope, AstNode *source_node,2384static IrInstruction *ir_build_int_to_enum(IrBuilder *irb, Scope *scope, AstNode *source_node,
2338 IrInstruction *target)2385 IrInstruction *dest_type, IrInstruction *target)
2339{2386{
2340 IrInstructionIntToEnum *instruction = ir_build_instruction<IrInstructionIntToEnum>(2387 IrInstructionIntToEnum *instruction = ir_build_instruction<IrInstructionIntToEnum>(
2341 irb, scope, source_node);2388 irb, scope, source_node);
2389 instruction->dest_type = dest_type;
2390 instruction->target = target;
2391
2392 if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block);
2393 ir_ref_instruction(target, irb->current_basic_block);
2394
2395 return &instruction->base;
2396}
2397
2398
2399
2400static IrInstruction *ir_build_enum_to_int(IrBuilder *irb, Scope *scope, AstNode *source_node,
2401 IrInstruction *target)
2402{
2403 IrInstructionEnumToInt *instruction = ir_build_instruction<IrInstructionEnumToInt>(
2404 irb, scope, source_node);
2342 instruction->target = target;2405 instruction->target = target;
23432406
2344 ir_ref_instruction(target, irb->current_basic_block);2407 ir_ref_instruction(target, irb->current_basic_block);
...@@ -4054,6 +4117,46 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4054,6 +4117,46 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4054 IrInstruction *result = ir_build_float_cast(irb, scope, node, arg0_value, arg1_value);4117 IrInstruction *result = ir_build_float_cast(irb, scope, node, arg0_value, arg1_value);
4055 return ir_lval_wrap(irb, scope, result, lval);4118 return ir_lval_wrap(irb, scope, result, lval);
4056 }4119 }
4120 case BuiltinFnIdErrSetCast:
4121 {
4122 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4123 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4124 if (arg0_value == irb->codegen->invalid_instruction)
4125 return arg0_value;
4126
4127 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4128 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
4129 if (arg1_value == irb->codegen->invalid_instruction)
4130 return arg1_value;
4131
4132 IrInstruction *result = ir_build_err_set_cast(irb, scope, node, arg0_value, arg1_value);
4133 return ir_lval_wrap(irb, scope, result, lval);
4134 }
4135 case BuiltinFnIdFromBytes:
4136 {
4137 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4138 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4139 if (arg0_value == irb->codegen->invalid_instruction)
4140 return arg0_value;
4141
4142 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4143 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
4144 if (arg1_value == irb->codegen->invalid_instruction)
4145 return arg1_value;
4146
4147 IrInstruction *result = ir_build_from_bytes(irb, scope, node, arg0_value, arg1_value);
4148 return ir_lval_wrap(irb, scope, result, lval);
4149 }
4150 case BuiltinFnIdToBytes:
4151 {
4152 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4153 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4154 if (arg0_value == irb->codegen->invalid_instruction)
4155 return arg0_value;
4156
4157 IrInstruction *result = ir_build_to_bytes(irb, scope, node, arg0_value);
4158 return ir_lval_wrap(irb, scope, result, lval);
4159 }
4057 case BuiltinFnIdIntToFloat:4160 case BuiltinFnIdIntToFloat:
4058 {4161 {
4059 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);4162 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
...@@ -4084,6 +4187,26 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4084,6 +4187,26 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4084 IrInstruction *result = ir_build_float_to_int(irb, scope, node, arg0_value, arg1_value);4187 IrInstruction *result = ir_build_float_to_int(irb, scope, node, arg0_value, arg1_value);
4085 return ir_lval_wrap(irb, scope, result, lval);4188 return ir_lval_wrap(irb, scope, result, lval);
4086 }4189 }
4190 case BuiltinFnIdErrToInt:
4191 {
4192 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4193 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4194 if (arg0_value == irb->codegen->invalid_instruction)
4195 return arg0_value;
4196
4197 IrInstruction *result = ir_build_err_to_int(irb, scope, node, arg0_value);
4198 return ir_lval_wrap(irb, scope, result, lval);
4199 }
4200 case BuiltinFnIdIntToErr:
4201 {
4202 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4203 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4204 if (arg0_value == irb->codegen->invalid_instruction)
4205 return arg0_value;
4206
4207 IrInstruction *result = ir_build_int_to_err(irb, scope, node, arg0_value);
4208 return ir_lval_wrap(irb, scope, result, lval);
4209 }
4087 case BuiltinFnIdBoolToInt:4210 case BuiltinFnIdBoolToInt:
4088 {4211 {
4089 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);4212 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
...@@ -4605,6 +4728,31 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4605,6 +4728,31 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4605 // this value does not mean anything since we passed non-null values for other arg4728 // this value does not mean anything since we passed non-null values for other arg
4606 AtomicOrderMonotonic);4729 AtomicOrderMonotonic);
4607 }4730 }
4731 case BuiltinFnIdIntToEnum:
4732 {
4733 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4734 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4735 if (arg0_value == irb->codegen->invalid_instruction)
4736 return arg0_value;
4737
4738 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4739 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
4740 if (arg1_value == irb->codegen->invalid_instruction)
4741 return arg1_value;
4742
4743 IrInstruction *result = ir_build_int_to_enum(irb, scope, node, arg0_value, arg1_value);
4744 return ir_lval_wrap(irb, scope, result, lval);
4745 }
4746 case BuiltinFnIdEnumToInt:
4747 {
4748 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4749 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4750 if (arg0_value == irb->codegen->invalid_instruction)
4751 return arg0_value;
4752
4753 IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value);
4754 return ir_lval_wrap(irb, scope, result, lval);
4755 }
4608 }4756 }
4609 zig_unreachable();4757 zig_unreachable();
4610}4758}
...@@ -9073,11 +9221,6 @@ static bool is_container(TypeTableEntry *type) {...@@ -9073,11 +9221,6 @@ static bool is_container(TypeTableEntry *type) {
9073 type->id == TypeTableEntryIdUnion;9221 type->id == TypeTableEntryIdUnion;
9074}9222}
90759223
9076static bool is_u8(TypeTableEntry *type) {
9077 return type->id == TypeTableEntryIdInt &&
9078 !type->data.integral.is_signed && type->data.integral.bit_count == 8;
9079}
9080
9081static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) {9224static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) {
9082 assert(old_bb);9225 assert(old_bb);
90839226
...@@ -9631,6 +9774,8 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s...@@ -9631,6 +9774,8 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
9631 IrInstruction *result = ir_build_slice(&ira->new_irb, source_instr->scope,9774 IrInstruction *result = ir_build_slice(&ira->new_irb, source_instr->scope,
9632 source_instr->source_node, array_ptr, start, end, false);9775 source_instr->source_node, array_ptr, start, end, false);
9633 result->value.type = wanted_type;9776 result->value.type = wanted_type;
9777 result->value.data.rh_slice.id = RuntimeHintSliceIdLen;
9778 result->value.data.rh_slice.len = array_type->data.array.len;
9634 ir_add_alloca(ira, result, result->value.type);9779 ir_add_alloca(ira, result, result->value.type);
96359780
9636 return result;9781 return result;
...@@ -9851,7 +9996,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour...@@ -9851,7 +9996,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
9851 }9996 }
98529997
9853 IrInstruction *result = ir_build_int_to_enum(&ira->new_irb, source_instr->scope,9998 IrInstruction *result = ir_build_int_to_enum(&ira->new_irb, source_instr->scope,
9854 source_instr->source_node, target);9999 source_instr->source_node, nullptr, target);
9855 result->value.type = wanted_type;10000 result->value.type = wanted_type;
9856 return result;10001 return result;
9857}10002}
...@@ -10073,7 +10218,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10073,7 +10218,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10073 return ira->codegen->invalid_instruction;10218 return ira->codegen->invalid_instruction;
10074 }10219 }
1007510220
10076 // explicit match or non-const to const10221 // perfect match or non-const to const
10077 if (types_match_const_cast_only(ira, wanted_type, actual_type, source_node, false).id == ConstCastResultIdOk) {10222 if (types_match_const_cast_only(ira, wanted_type, actual_type, source_node, false).id == ConstCastResultIdOk) {
10078 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);10223 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
10079 }10224 }
...@@ -10104,13 +10249,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10104,13 +10249,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10104 }10249 }
1010510250
1010610251
10107 // explicit error set cast
10108 if (wanted_type->id == TypeTableEntryIdErrorSet &&
10109 actual_type->id == TypeTableEntryIdErrorSet)
10110 {
10111 return ir_analyze_err_set_cast(ira, source_instr, value, wanted_type);
10112 }
10113
10114 // explicit cast from [N]T to []const T10252 // explicit cast from [N]T to []const T
10115 if (is_slice(wanted_type) && actual_type->id == TypeTableEntryIdArray) {10253 if (is_slice(wanted_type) && actual_type->id == TypeTableEntryIdArray) {
10116 TypeTableEntry *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;10254 TypeTableEntry *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
...@@ -10142,7 +10280,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10142,7 +10280,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10142 }10280 }
10143 }10281 }
1014410282
10145 // explicit cast from [N]T to &const []const N10283 // explicit cast from [N]T to &const []const T
10146 if (wanted_type->id == TypeTableEntryIdPointer &&10284 if (wanted_type->id == TypeTableEntryIdPointer &&
10147 wanted_type->data.pointer.is_const &&10285 wanted_type->data.pointer.is_const &&
10148 is_slice(wanted_type->data.pointer.child_type) &&10286 is_slice(wanted_type->data.pointer.child_type) &&
...@@ -10191,52 +10329,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10191,52 +10329,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10191 }10329 }
10192 }10330 }
1019310331
10194 // explicit cast from []T to []u8 or []u8 to []T
10195 if (is_slice(wanted_type) && is_slice(actual_type)) {
10196 TypeTableEntry *wanted_ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
10197 TypeTableEntry *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry;
10198 if ((is_u8(wanted_ptr_type->data.pointer.child_type) || is_u8(actual_ptr_type->data.pointer.child_type)) &&
10199 (wanted_ptr_type->data.pointer.is_const || !actual_ptr_type->data.pointer.is_const))
10200 {
10201 uint32_t src_align_bytes = get_ptr_align(actual_ptr_type);
10202 uint32_t dest_align_bytes = get_ptr_align(wanted_ptr_type);
10203
10204 if (dest_align_bytes > src_align_bytes) {
10205 ErrorMsg *msg = ir_add_error(ira, source_instr,
10206 buf_sprintf("cast increases pointer alignment"));
10207 add_error_note(ira->codegen, msg, source_instr->source_node,
10208 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&actual_type->name), src_align_bytes));
10209 add_error_note(ira->codegen, msg, source_instr->source_node,
10210 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&wanted_type->name), dest_align_bytes));
10211 return ira->codegen->invalid_instruction;
10212 }
10213
10214 if (!ir_emit_global_runtime_side_effect(ira, source_instr))
10215 return ira->codegen->invalid_instruction;
10216 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpResizeSlice, true);
10217 }
10218 }
10219
10220 // explicit cast from [N]u8 to []const T
10221 if (is_slice(wanted_type) &&
10222 wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const &&
10223 actual_type->id == TypeTableEntryIdArray &&
10224 is_u8(actual_type->data.array.child_type))
10225 {
10226 if (!ir_emit_global_runtime_side_effect(ira, source_instr))
10227 return ira->codegen->invalid_instruction;
10228 uint64_t child_type_size = type_size(ira->codegen,
10229 wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type);
10230 if (actual_type->data.array.len % child_type_size == 0) {
10231 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpBytesToSlice, true);
10232 } else {
10233 ir_add_error_node(ira, source_instr->source_node,
10234 buf_sprintf("unable to convert %s to %s: size mismatch",
10235 buf_ptr(&actual_type->name), buf_ptr(&wanted_type->name)));
10236 return ira->codegen->invalid_instruction;
10237 }
10238 }
10239
10240 // explicit *[N]T to [*]T10332 // explicit *[N]T to [*]T
10241 if (wanted_type->id == TypeTableEntryIdPointer &&10333 if (wanted_type->id == TypeTableEntryIdPointer &&
10242 wanted_type->data.pointer.ptr_len == PtrLenUnknown &&10334 wanted_type->data.pointer.ptr_len == PtrLenUnknown &&
...@@ -10438,31 +10530,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10438,31 +10530,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10438 return ir_analyze_number_to_literal(ira, source_instr, value, wanted_type);10530 return ir_analyze_number_to_literal(ira, source_instr, value, wanted_type);
10439 }10531 }
1044010532
10441 // explicit cast from T!void to integer type which can fit it
10442 bool actual_type_is_void_err = actual_type->id == TypeTableEntryIdErrorUnion &&
10443 !type_has_bits(actual_type->data.error_union.payload_type);
10444 bool actual_type_is_err_set = actual_type->id == TypeTableEntryIdErrorSet;
10445 if ((actual_type_is_void_err || actual_type_is_err_set) && wanted_type->id == TypeTableEntryIdInt) {
10446 return ir_analyze_err_to_int(ira, source_instr, value, wanted_type);
10447 }
10448
10449 // explicit cast from integer to error set
10450 if (wanted_type->id == TypeTableEntryIdErrorSet && actual_type->id == TypeTableEntryIdInt &&
10451 !actual_type->data.integral.is_signed)
10452 {
10453 return ir_analyze_int_to_err(ira, source_instr, value, wanted_type);
10454 }
10455
10456 // explicit cast from integer to enum type with no payload
10457 if (actual_type->id == TypeTableEntryIdInt && wanted_type->id == TypeTableEntryIdEnum) {
10458 return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type);
10459 }
10460
10461 // explicit cast from enum type with no payload to integer
10462 if (wanted_type->id == TypeTableEntryIdInt && actual_type->id == TypeTableEntryIdEnum) {
10463 return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type);
10464 }
10465
10466 // explicit cast from union to the enum type of the union10533 // explicit cast from union to the enum type of the union
10467 if (actual_type->id == TypeTableEntryIdUnion && wanted_type->id == TypeTableEntryIdEnum) {10534 if (actual_type->id == TypeTableEntryIdUnion && wanted_type->id == TypeTableEntryIdEnum) {
10468 type_ensure_zero_bits_known(ira->codegen, actual_type);10535 type_ensure_zero_bits_known(ira->codegen, actual_type);
...@@ -17593,6 +17660,137 @@ static TypeTableEntry *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstr...@@ -17593,6 +17660,137 @@ static TypeTableEntry *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstr
17593 return dest_type;17660 return dest_type;
17594}17661}
1759517662
17663static TypeTableEntry *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInstructionErrSetCast *instruction) {
17664 TypeTableEntry *dest_type = ir_resolve_type(ira, instruction->dest_type->other);
17665 if (type_is_invalid(dest_type))
17666 return ira->codegen->builtin_types.entry_invalid;
17667
17668 if (dest_type->id != TypeTableEntryIdErrorSet) {
17669 ir_add_error(ira, instruction->dest_type,
17670 buf_sprintf("expected error set type, found '%s'", buf_ptr(&dest_type->name)));
17671 return ira->codegen->builtin_types.entry_invalid;
17672 }
17673
17674 IrInstruction *target = instruction->target->other;
17675 if (type_is_invalid(target->value.type))
17676 return ira->codegen->builtin_types.entry_invalid;
17677
17678 if (target->value.type->id != TypeTableEntryIdErrorSet) {
17679 ir_add_error(ira, instruction->target,
17680 buf_sprintf("expected error set type, found '%s'", buf_ptr(&target->value.type->name)));
17681 return ira->codegen->builtin_types.entry_invalid;
17682 }
17683
17684 IrInstruction *result = ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type);
17685 if (type_is_invalid(result->value.type))
17686 return ira->codegen->builtin_types.entry_invalid;
17687 ir_link_new_instruction(result, &instruction->base);
17688 return dest_type;
17689}
17690
17691static TypeTableEntry *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {
17692 TypeTableEntry *dest_child_type = ir_resolve_type(ira, instruction->dest_child_type->other);
17693 if (type_is_invalid(dest_child_type))
17694 return ira->codegen->builtin_types.entry_invalid;
17695
17696 IrInstruction *target = instruction->target->other;
17697 if (type_is_invalid(target->value.type))
17698 return ira->codegen->builtin_types.entry_invalid;
17699
17700 bool src_ptr_const;
17701 bool src_ptr_volatile;
17702 uint32_t src_ptr_align;
17703 if (target->value.type->id == TypeTableEntryIdPointer) {
17704 src_ptr_const = target->value.type->data.pointer.is_const;
17705 src_ptr_volatile = target->value.type->data.pointer.is_volatile;
17706 src_ptr_align = target->value.type->data.pointer.alignment;
17707 } else if (is_slice(target->value.type)) {
17708 TypeTableEntry *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;
17709 src_ptr_const = src_ptr_type->data.pointer.is_const;
17710 src_ptr_volatile = src_ptr_type->data.pointer.is_volatile;
17711 src_ptr_align = src_ptr_type->data.pointer.alignment;
17712 } else {
17713 src_ptr_const = true;
17714 src_ptr_volatile = false;
17715 src_ptr_align = get_abi_alignment(ira->codegen, target->value.type);
17716 }
17717
17718 TypeTableEntry *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_child_type,
17719 src_ptr_const, src_ptr_volatile, PtrLenUnknown,
17720 src_ptr_align, 0, 0);
17721 TypeTableEntry *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);
17722
17723 TypeTableEntry *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
17724 src_ptr_const, src_ptr_volatile, PtrLenUnknown,
17725 src_ptr_align, 0, 0);
17726 TypeTableEntry *u8_slice = get_slice_type(ira->codegen, u8_ptr);
17727
17728 IrInstruction *casted_value = ir_implicit_cast(ira, target, u8_slice);
17729 if (type_is_invalid(casted_value->value.type))
17730 return ira->codegen->builtin_types.entry_invalid;
17731
17732 bool have_known_len = false;
17733 uint64_t known_len;
17734
17735 if (instr_is_comptime(casted_value)) {
17736 ConstExprValue *val = ir_resolve_const(ira, casted_value, UndefBad);
17737 if (!val)
17738 return ira->codegen->builtin_types.entry_invalid;
17739
17740 ConstExprValue *len_val = &val->data.x_struct.fields[slice_len_index];
17741 if (value_is_comptime(len_val)) {
17742 known_len = bigint_as_unsigned(&len_val->data.x_bigint);
17743 have_known_len = true;
17744 }
17745 }
17746
17747 if (casted_value->value.data.rh_slice.id == RuntimeHintSliceIdLen) {
17748 known_len = casted_value->value.data.rh_slice.len;
17749 have_known_len = true;
17750 }
17751
17752 if (have_known_len) {
17753 uint64_t child_type_size = type_size(ira->codegen, dest_child_type);
17754 uint64_t remainder = known_len % child_type_size;
17755 if (remainder != 0) {
17756 ErrorMsg *msg = ir_add_error(ira, &instruction->base,
17757 buf_sprintf("unable to convert [%" ZIG_PRI_u64 "]u8 to %s: size mismatch",
17758 known_len, buf_ptr(&dest_slice_type->name)));
17759 add_error_note(ira->codegen, msg, instruction->dest_child_type->source_node,
17760 buf_sprintf("%s has size %" ZIG_PRI_u64 "; remaining bytes: %" ZIG_PRI_u64,
17761 buf_ptr(&dest_child_type->name), child_type_size, remainder));
17762 return ira->codegen->builtin_types.entry_invalid;
17763 }
17764 }
17765
17766 IrInstruction *result = ir_resolve_cast(ira, &instruction->base, casted_value, dest_slice_type, CastOpResizeSlice, true);
17767 ir_link_new_instruction(result, &instruction->base);
17768 return dest_slice_type;
17769}
17770
17771static TypeTableEntry *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) {
17772 IrInstruction *target = instruction->target->other;
17773 if (type_is_invalid(target->value.type))
17774 return ira->codegen->builtin_types.entry_invalid;
17775
17776 if (!is_slice(target->value.type)) {
17777 ir_add_error(ira, instruction->target,
17778 buf_sprintf("expected slice, found '%s'", buf_ptr(&target->value.type->name)));
17779 return ira->codegen->builtin_types.entry_invalid;
17780 }
17781
17782 TypeTableEntry *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;
17783
17784 TypeTableEntry *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
17785 src_ptr_type->data.pointer.is_const, src_ptr_type->data.pointer.is_volatile, PtrLenUnknown,
17786 src_ptr_type->data.pointer.alignment, 0, 0);
17787 TypeTableEntry *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);
17788
17789 IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);
17790 ir_link_new_instruction(result, &instruction->base);
17791 return dest_slice_type;
17792}
17793
17596static TypeTableEntry *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) {17794static TypeTableEntry *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) {
17597 TypeTableEntry *dest_type = ir_resolve_type(ira, instruction->dest_type->other);17795 TypeTableEntry *dest_type = ir_resolve_type(ira, instruction->dest_type->other);
17598 if (type_is_invalid(dest_type))17796 if (type_is_invalid(dest_type))
...@@ -17627,6 +17825,39 @@ static TypeTableEntry *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrIns...@@ -17627,6 +17825,39 @@ static TypeTableEntry *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrIns
17627 return dest_type;17825 return dest_type;
17628}17826}
1762917827
17828static TypeTableEntry *ir_analyze_instruction_err_to_int(IrAnalyze *ira, IrInstructionErrToInt *instruction) {
17829 IrInstruction *target = instruction->target->other;
17830 if (type_is_invalid(target->value.type))
17831 return ira->codegen->builtin_types.entry_invalid;
17832
17833 IrInstruction *casted_target;
17834 if (target->value.type->id == TypeTableEntryIdErrorSet) {
17835 casted_target = target;
17836 } else {
17837 casted_target = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_global_error_set);
17838 if (type_is_invalid(casted_target->value.type))
17839 return ira->codegen->builtin_types.entry_invalid;
17840 }
17841
17842 IrInstruction *result = ir_analyze_err_to_int(ira, &instruction->base, casted_target, ira->codegen->err_tag_type);
17843 ir_link_new_instruction(result, &instruction->base);
17844 return result->value.type;
17845}
17846
17847static TypeTableEntry *ir_analyze_instruction_int_to_err(IrAnalyze *ira, IrInstructionIntToErr *instruction) {
17848 IrInstruction *target = instruction->target->other;
17849 if (type_is_invalid(target->value.type))
17850 return ira->codegen->builtin_types.entry_invalid;
17851
17852 IrInstruction *casted_target = ir_implicit_cast(ira, target, ira->codegen->err_tag_type);
17853 if (type_is_invalid(casted_target->value.type))
17854 return ira->codegen->builtin_types.entry_invalid;
17855
17856 IrInstruction *result = ir_analyze_int_to_err(ira, &instruction->base, casted_target, ira->codegen->builtin_types.entry_global_error_set);
17857 ir_link_new_instruction(result, &instruction->base);
17858 return result->value.type;
17859}
17860
17630static TypeTableEntry *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, IrInstructionBoolToInt *instruction) {17861static TypeTableEntry *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, IrInstructionBoolToInt *instruction) {
17631 IrInstruction *target = instruction->target->other;17862 IrInstruction *target = instruction->target->other;
17632 if (type_is_invalid(target->value.type))17863 if (type_is_invalid(target->value.type))
...@@ -20066,13 +20297,63 @@ static TypeTableEntry *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstruction...@@ -20066,13 +20297,63 @@ static TypeTableEntry *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstruction
20066 return result->value.type;20297 return result->value.type;
20067}20298}
2006820299
20300static TypeTableEntry *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {
20301 IrInstruction *target = instruction->target->other;
20302 if (type_is_invalid(target->value.type))
20303 return ira->codegen->builtin_types.entry_invalid;
20304
20305 if (target->value.type->id != TypeTableEntryIdEnum) {
20306 ir_add_error(ira, instruction->target,
20307 buf_sprintf("expected enum, found type '%s'", buf_ptr(&target->value.type->name)));
20308 return ira->codegen->builtin_types.entry_invalid;
20309 }
20310
20311 type_ensure_zero_bits_known(ira->codegen, target->value.type);
20312 if (type_is_invalid(target->value.type))
20313 return ira->codegen->builtin_types.entry_invalid;
20314
20315 TypeTableEntry *tag_type = target->value.type->data.enumeration.tag_int_type;
20316
20317 IrInstruction *result = ir_analyze_enum_to_int(ira, &instruction->base, target, tag_type);
20318 ir_link_new_instruction(result, &instruction->base);
20319 return result->value.type;
20320}
20321
20322static TypeTableEntry *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstructionIntToEnum *instruction) {
20323 IrInstruction *dest_type_value = instruction->dest_type->other;
20324 TypeTableEntry *dest_type = ir_resolve_type(ira, dest_type_value);
20325 if (type_is_invalid(dest_type))
20326 return ira->codegen->builtin_types.entry_invalid;
20327
20328 if (dest_type->id != TypeTableEntryIdEnum) {
20329 ir_add_error(ira, instruction->dest_type,
20330 buf_sprintf("expected enum, found type '%s'", buf_ptr(&dest_type->name)));
20331 return ira->codegen->builtin_types.entry_invalid;
20332 }
20333
20334 type_ensure_zero_bits_known(ira->codegen, dest_type);
20335 if (type_is_invalid(dest_type))
20336 return ira->codegen->builtin_types.entry_invalid;
20337
20338 TypeTableEntry *tag_type = dest_type->data.enumeration.tag_int_type;
20339
20340 IrInstruction *target = instruction->target->other;
20341 if (type_is_invalid(target->value.type))
20342 return ira->codegen->builtin_types.entry_invalid;
20343
20344 IrInstruction *casted_target = ir_implicit_cast(ira, target, tag_type);
20345 if (type_is_invalid(casted_target->value.type))
20346 return ira->codegen->builtin_types.entry_invalid;
20347
20348 IrInstruction *result = ir_analyze_int_to_enum(ira, &instruction->base, casted_target, dest_type);
20349 ir_link_new_instruction(result, &instruction->base);
20350 return result->value.type;
20351}
20352
20069static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {20353static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
20070 switch (instruction->id) {20354 switch (instruction->id) {
20071 case IrInstructionIdInvalid:20355 case IrInstructionIdInvalid:
20072 case IrInstructionIdWidenOrShorten:20356 case IrInstructionIdWidenOrShorten:
20073 case IrInstructionIdIntToEnum:
20074 case IrInstructionIdIntToErr:
20075 case IrInstructionIdErrToInt:
20076 case IrInstructionIdStructInit:20357 case IrInstructionIdStructInit:
20077 case IrInstructionIdUnionInit:20358 case IrInstructionIdUnionInit:
20078 case IrInstructionIdStructFieldPtr:20359 case IrInstructionIdStructFieldPtr:
...@@ -20193,6 +20474,12 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -20193,6 +20474,12 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
20193 return ir_analyze_instruction_int_cast(ira, (IrInstructionIntCast *)instruction);20474 return ir_analyze_instruction_int_cast(ira, (IrInstructionIntCast *)instruction);
20194 case IrInstructionIdFloatCast:20475 case IrInstructionIdFloatCast:
20195 return ir_analyze_instruction_float_cast(ira, (IrInstructionFloatCast *)instruction);20476 return ir_analyze_instruction_float_cast(ira, (IrInstructionFloatCast *)instruction);
20477 case IrInstructionIdErrSetCast:
20478 return ir_analyze_instruction_err_set_cast(ira, (IrInstructionErrSetCast *)instruction);
20479 case IrInstructionIdFromBytes:
20480 return ir_analyze_instruction_from_bytes(ira, (IrInstructionFromBytes *)instruction);
20481 case IrInstructionIdToBytes:
20482 return ir_analyze_instruction_to_bytes(ira, (IrInstructionToBytes *)instruction);
20196 case IrInstructionIdIntToFloat:20483 case IrInstructionIdIntToFloat:
20197 return ir_analyze_instruction_int_to_float(ira, (IrInstructionIntToFloat *)instruction);20484 return ir_analyze_instruction_int_to_float(ira, (IrInstructionIntToFloat *)instruction);
20198 case IrInstructionIdFloatToInt:20485 case IrInstructionIdFloatToInt:
...@@ -20327,6 +20614,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -20327,6 +20614,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
20327 return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);20614 return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);
20328 case IrInstructionIdSqrt:20615 case IrInstructionIdSqrt:
20329 return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction);20616 return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction);
20617 case IrInstructionIdIntToErr:
20618 return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);
20619 case IrInstructionIdErrToInt:
20620 return ir_analyze_instruction_err_to_int(ira, (IrInstructionErrToInt *)instruction);
20621 case IrInstructionIdIntToEnum:
20622 return ir_analyze_instruction_int_to_enum(ira, (IrInstructionIntToEnum *)instruction);
20623 case IrInstructionIdEnumToInt:
20624 return ir_analyze_instruction_enum_to_int(ira, (IrInstructionEnumToInt *)instruction);
20330 }20625 }
20331 zig_unreachable();20626 zig_unreachable();
20332}20627}
...@@ -20544,9 +20839,13 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -20544,9 +20839,13 @@ bool ir_has_side_effects(IrInstruction *instruction) {
20544 case IrInstructionIdAtomicLoad:20839 case IrInstructionIdAtomicLoad:
20545 case IrInstructionIdIntCast:20840 case IrInstructionIdIntCast:
20546 case IrInstructionIdFloatCast:20841 case IrInstructionIdFloatCast:
20842 case IrInstructionIdErrSetCast:
20547 case IrInstructionIdIntToFloat:20843 case IrInstructionIdIntToFloat:
20548 case IrInstructionIdFloatToInt:20844 case IrInstructionIdFloatToInt:
20549 case IrInstructionIdBoolToInt:20845 case IrInstructionIdBoolToInt:
20846 case IrInstructionIdFromBytes:
20847 case IrInstructionIdToBytes:
20848 case IrInstructionIdEnumToInt:
20550 return false;20849 return false;
2055120850
20552 case IrInstructionIdAsm:20851 case IrInstructionIdAsm:
src/ir_print.cpp+45
...@@ -664,6 +664,28 @@ static void ir_print_float_cast(IrPrint *irp, IrInstructionFloatCast *instructio...@@ -664,6 +664,28 @@ static void ir_print_float_cast(IrPrint *irp, IrInstructionFloatCast *instructio
664 fprintf(irp->f, ")");664 fprintf(irp->f, ")");
665}665}
666666
667static void ir_print_err_set_cast(IrPrint *irp, IrInstructionErrSetCast *instruction) {
668 fprintf(irp->f, "@errSetCast(");
669 ir_print_other_instruction(irp, instruction->dest_type);
670 fprintf(irp->f, ", ");
671 ir_print_other_instruction(irp, instruction->target);
672 fprintf(irp->f, ")");
673}
674
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
667static void ir_print_int_to_float(IrPrint *irp, IrInstructionIntToFloat *instruction) {689static void ir_print_int_to_float(IrPrint *irp, IrInstructionIntToFloat *instruction) {
668 fprintf(irp->f, "@intToFloat(");690 fprintf(irp->f, "@intToFloat(");
669 ir_print_other_instruction(irp, instruction->dest_type);691 ir_print_other_instruction(irp, instruction->dest_type);
...@@ -906,6 +928,17 @@ static void ir_print_int_to_ptr(IrPrint *irp, IrInstructionIntToPtr *instruction...@@ -906,6 +928,17 @@ static void ir_print_int_to_ptr(IrPrint *irp, IrInstructionIntToPtr *instruction
906928
907static void ir_print_int_to_enum(IrPrint *irp, IrInstructionIntToEnum *instruction) {929static void ir_print_int_to_enum(IrPrint *irp, IrInstructionIntToEnum *instruction) {
908 fprintf(irp->f, "@intToEnum(");930 fprintf(irp->f, "@intToEnum(");
931 if (instruction->dest_type == nullptr) {
932 fprintf(irp->f, "(null)");
933 } else {
934 ir_print_other_instruction(irp, instruction->dest_type);
935 }
936 ir_print_other_instruction(irp, instruction->target);
937 fprintf(irp->f, ")");
938}
939
940static void ir_print_enum_to_int(IrPrint *irp, IrInstructionEnumToInt *instruction) {
941 fprintf(irp->f, "@enumToInt(");
909 ir_print_other_instruction(irp, instruction->target);942 ir_print_other_instruction(irp, instruction->target);
910 fprintf(irp->f, ")");943 fprintf(irp->f, ")");
911}944}
...@@ -1461,6 +1494,15 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1461,6 +1494,15 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1461 case IrInstructionIdFloatCast:1494 case IrInstructionIdFloatCast:
1462 ir_print_float_cast(irp, (IrInstructionFloatCast *)instruction);1495 ir_print_float_cast(irp, (IrInstructionFloatCast *)instruction);
1463 break;1496 break;
1497 case IrInstructionIdErrSetCast:
1498 ir_print_err_set_cast(irp, (IrInstructionErrSetCast *)instruction);
1499 break;
1500 case IrInstructionIdFromBytes:
1501 ir_print_from_bytes(irp, (IrInstructionFromBytes *)instruction);
1502 break;
1503 case IrInstructionIdToBytes:
1504 ir_print_to_bytes(irp, (IrInstructionToBytes *)instruction);
1505 break;
1464 case IrInstructionIdIntToFloat:1506 case IrInstructionIdIntToFloat:
1465 ir_print_int_to_float(irp, (IrInstructionIntToFloat *)instruction);1507 ir_print_int_to_float(irp, (IrInstructionIntToFloat *)instruction);
1466 break;1508 break;
...@@ -1686,6 +1728,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1686,6 +1728,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1686 case IrInstructionIdAtomicLoad:1728 case IrInstructionIdAtomicLoad:
1687 ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);1729 ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);
1688 break;1730 break;
1731 case IrInstructionIdEnumToInt:
1732 ir_print_enum_to_int(irp, (IrInstructionEnumToInt *)instruction);
1733 break;
1689 }1734 }
1690 fprintf(irp->f, "\n");1735 fprintf(irp->f, "\n");
1691}1736}
std/cstr.zig+1-1
...@@ -79,7 +79,7 @@ pub const NullTerminated2DArray = struct {...@@ -79,7 +79,7 @@ pub const NullTerminated2DArray = struct {
79 errdefer allocator.free(buf);79 errdefer allocator.free(buf);
8080
81 var write_index = index_size;81 var write_index = index_size;
82 const index_buf = ([]?[*]u8)(buf);82 const index_buf = @bytesToSlice(?[*]u8, buf);
8383
84 var i: usize = 0;84 var i: usize = 0;
85 for (slices) |slice| {85 for (slices) |slice| {
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/json.zig+1-1
...@@ -180,7 +180,7 @@ pub const StreamingParser = struct {...@@ -180,7 +180,7 @@ pub const StreamingParser = struct {
180 pub fn fromInt(x: var) State {180 pub fn fromInt(x: var) State {
181 debug.assert(x == 0 or x == 1);181 debug.assert(x == 0 or x == 1);
182 const T = @TagType(State);182 const T = @TagType(State);
183 return State(@intCast(T, x));183 return @intToEnum(State, @intCast(T, x));
184 }184 }
185 };185 };
186186
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/child_process.zig+2-2
...@@ -318,7 +318,7 @@ pub const ChildProcess = struct {...@@ -318,7 +318,7 @@ pub const ChildProcess = struct {
318 // Here we potentially return the fork child's error318 // Here we potentially return the fork child's error
319 // from the parent pid.319 // from the parent pid.
320 if (err_int != @maxValue(ErrInt)) {320 if (err_int != @maxValue(ErrInt)) {
321 return SpawnError(err_int);321 return @errSetCast(SpawnError, @intToError(err_int));
322 }322 }
323323
324 return statusToTerm(status);324 return statusToTerm(status);
...@@ -756,7 +756,7 @@ fn destroyPipe(pipe: *const [2]i32) void {...@@ -756,7 +756,7 @@ fn destroyPipe(pipe: *const [2]i32) void {
756// Child of fork calls this to report an error to the fork parent.756// Child of fork calls this to report an error to the fork parent.
757// Then the child exits.757// Then the child exits.
758fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {758fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
759 _ = writeIntFd(fd, ErrInt(err));759 _ = writeIntFd(fd, ErrInt(@errorToInt(err)));
760 posix.exit(1);760 posix.exit(1);
761}761}
762762
std/os/index.zig+1-1
...@@ -1805,7 +1805,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {...@@ -1805,7 +1805,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {
1805 const buf = try allocator.alignedAlloc(u8, @alignOf([]u8), total_bytes);1805 const buf = try allocator.alignedAlloc(u8, @alignOf([]u8), total_bytes);
1806 errdefer allocator.free(buf);1806 errdefer allocator.free(buf);
18071807
1808 const result_slice_list = ([][]u8)(buf[0..slice_list_bytes]);1808 const result_slice_list = @bytesToSlice([]u8, buf[0..slice_list_bytes]);
1809 const result_contents = buf[slice_list_bytes..];1809 const result_contents = buf[slice_list_bytes..];
1810 mem.copy(u8, result_contents, contents_slice);1810 mem.copy(u8, result_contents, contents_slice);
18111811
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+9-3
...@@ -140,8 +140,8 @@ test "explicit cast from integer to error type" {...@@ -140,8 +140,8 @@ test "explicit cast from integer to error type" {
140 comptime testCastIntToErr(error.ItBroke);140 comptime testCastIntToErr(error.ItBroke);
141}141}
142fn testCastIntToErr(err: error) void {142fn testCastIntToErr(err: error) void {
143 const x = usize(err);143 const x = @errorToInt(err);
144 const y = error(x);144 const y = @intToError(x);
145 assert(error.ItBroke == y);145 assert(error.ItBroke == y);
146}146}
147147
...@@ -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/enum.zig+8-8
...@@ -92,14 +92,14 @@ test "enum to int" {...@@ -92,14 +92,14 @@ test "enum to int" {
92}92}
9393
94fn shouldEqual(n: Number, expected: u3) void {94fn shouldEqual(n: Number, expected: u3) void {
95 assert(u3(n) == expected);95 assert(@enumToInt(n) == expected);
96}96}
9797
98test "int to enum" {98test "int to enum" {
99 testIntToEnumEval(3);99 testIntToEnumEval(3);
100}100}
101fn testIntToEnumEval(x: i32) void {101fn testIntToEnumEval(x: i32) void {
102 assert(IntToEnumNumber(@intCast(u3, x)) == IntToEnumNumber.Three);102 assert(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three);
103}103}
104const IntToEnumNumber = enum {104const IntToEnumNumber = enum {
105 Zero,105 Zero,
...@@ -768,7 +768,7 @@ test "casting enum to its tag type" {...@@ -768,7 +768,7 @@ test "casting enum to its tag type" {
768}768}
769769
770fn testCastEnumToTagType(value: Small2) void {770fn testCastEnumToTagType(value: Small2) void {
771 assert(u2(value) == 1);771 assert(@enumToInt(value) == 1);
772}772}
773773
774const MultipleChoice = enum(u32) {774const MultipleChoice = enum(u32) {
...@@ -784,7 +784,7 @@ test "enum with specified tag values" {...@@ -784,7 +784,7 @@ test "enum with specified tag values" {
784}784}
785785
786fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void {786fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void {
787 assert(u32(x) == 60);787 assert(@enumToInt(x) == 60);
788 assert(1234 == switch (x) {788 assert(1234 == switch (x) {
789 MultipleChoice.A => 1,789 MultipleChoice.A => 1,
790 MultipleChoice.B => 2,790 MultipleChoice.B => 2,
...@@ -811,7 +811,7 @@ test "enum with specified and unspecified tag values" {...@@ -811,7 +811,7 @@ test "enum with specified and unspecified tag values" {
811}811}
812812
813fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {813fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
814 assert(u32(x) == 1000);814 assert(@enumToInt(x) == 1000);
815 assert(1234 == switch (x) {815 assert(1234 == switch (x) {
816 MultipleChoice2.A => 1,816 MultipleChoice2.A => 1,
817 MultipleChoice2.B => 2,817 MultipleChoice2.B => 2,
...@@ -826,8 +826,8 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {...@@ -826,8 +826,8 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
826}826}
827827
828test "cast integer literal to enum" {828test "cast integer literal to enum" {
829 assert(MultipleChoice2(0) == MultipleChoice2.Unspecified1);829 assert(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
830 assert(MultipleChoice2(40) == MultipleChoice2.B);830 assert(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);
831}831}
832832
833const EnumWithOneMember = enum {833const EnumWithOneMember = enum {
...@@ -865,7 +865,7 @@ const EnumWithTagValues = enum(u4) {...@@ -865,7 +865,7 @@ const EnumWithTagValues = enum(u4) {
865 D = 1 << 3,865 D = 1 << 3,
866};866};
867test "enum with tag values don't require parens" {867test "enum with tag values don't require parens" {
868 assert(u4(EnumWithTagValues.C) == 0b0100);868 assert(@enumToInt(EnumWithTagValues.C) == 0b0100);
869}869}
870870
871test "enum with 1 field but explicit tag type should still have the tag type" {871test "enum with 1 field but explicit tag type should still have the tag type" {
test/cases/error.zig+7-7
...@@ -31,8 +31,8 @@ test "@errorName" {...@@ -31,8 +31,8 @@ test "@errorName" {
31}31}
3232
33test "error values" {33test "error values" {
34 const a = i32(error.err1);34 const a = @errorToInt(error.err1);
35 const b = i32(error.err2);35 const b = @errorToInt(error.err2);
36 assert(a != b);36 assert(a != b);
37}37}
3838
...@@ -124,8 +124,8 @@ const Set2 = error{...@@ -124,8 +124,8 @@ const Set2 = error{
124};124};
125125
126fn testExplicitErrorSetCast(set1: Set1) void {126fn testExplicitErrorSetCast(set1: Set1) void {
127 var x = Set2(set1);127 var x = @errSetCast(Set2, set1);
128 var y = Set1(x);128 var y = @errSetCast(Set1, x);
129 assert(y == error.A);129 assert(y == error.A);
130}130}
131131
...@@ -147,14 +147,14 @@ test "syntax: optional operator in front of error union operator" {...@@ -147,14 +147,14 @@ test "syntax: optional operator in front of error union operator" {
147}147}
148148
149test "comptime err to int of error set with only 1 possible value" {149test "comptime err to int of error set with only 1 possible value" {
150 testErrToIntWithOnePossibleValue(error.A, u32(error.A));150 testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
151 comptime testErrToIntWithOnePossibleValue(error.A, u32(error.A));151 comptime testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
152}152}
153fn testErrToIntWithOnePossibleValue(153fn testErrToIntWithOnePossibleValue(
154 x: error{A},154 x: error{A},
155 comptime value: u32,155 comptime value: u32,
156) void {156) void {
157 if (u32(x) != value) {157 if (@errorToInt(x) != value) {
158 @compileError("bad");158 @compileError("bad");
159 }159 }
160}160}
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/cases/type_info.zig+1-1
...@@ -130,7 +130,7 @@ fn testErrorSet() void {...@@ -130,7 +130,7 @@ fn testErrorSet() void {
130 assert(TypeId(error_set_info) == TypeId.ErrorSet);130 assert(TypeId(error_set_info) == TypeId.ErrorSet);
131 assert(error_set_info.ErrorSet.errors.len == 3);131 assert(error_set_info.ErrorSet.errors.len == 3);
132 assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));132 assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
133 assert(error_set_info.ErrorSet.errors[2].value == usize(TestErrorSet.Third));133 assert(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third));
134134
135 const error_union_info = @typeInfo(TestErrorSet!usize);135 const error_union_info = @typeInfo(TestErrorSet!usize);
136 assert(TypeId(error_union_info) == TypeId.ErrorUnion);136 assert(TypeId(error_union_info) == TypeId.ErrorUnion);
test/cases/union.zig+2-2
...@@ -126,7 +126,7 @@ const MultipleChoice = union(enum(u32)) {...@@ -126,7 +126,7 @@ const MultipleChoice = union(enum(u32)) {
126test "simple union(enum(u32))" {126test "simple union(enum(u32))" {
127 var x = MultipleChoice.C;127 var x = MultipleChoice.C;
128 assert(x == MultipleChoice.C);128 assert(x == MultipleChoice.C);
129 assert(u32(@TagType(MultipleChoice)(x)) == 60);129 assert(@enumToInt(@TagType(MultipleChoice)(x)) == 60);
130}130}
131131
132const MultipleChoice2 = union(enum(u32)) {132const MultipleChoice2 = union(enum(u32)) {
...@@ -148,7 +148,7 @@ test "union(enum(u32)) with specified and unspecified tag values" {...@@ -148,7 +148,7 @@ test "union(enum(u32)) with specified and unspecified tag values" {
148}148}
149149
150fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: *const MultipleChoice2) void {150fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: *const MultipleChoice2) void {
151 assert(u32(@TagType(MultipleChoice2)(x.*)) == 60);151 assert(@enumToInt(@TagType(MultipleChoice2)(x.*)) == 60);
152 assert(1123 == switch (x.*) {152 assert(1123 == switch (x.*) {
153 MultipleChoice2.A => 1,153 MultipleChoice2.A => 1,
154 MultipleChoice2.B => 2,154 MultipleChoice2.B => 2,
test/compile_errors.zig+27-56
...@@ -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(
...@@ -467,25 +467,34 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -467,25 +467,34 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
467467
468 cases.add(468 cases.add(
469 "int to err global invalid number",469 "int to err global invalid number",
470 \\const Set1 = error{A, B};470 \\const Set1 = error{
471 \\ A,
472 \\ B,
473 \\};
471 \\comptime {474 \\comptime {
472 \\ var x: usize = 3;475 \\ var x: u16 = 3;
473 \\ var y = error(x);476 \\ var y = @intToError(x);
474 \\}477 \\}
475 ,478 ,
476 ".tmp_source.zig:4:18: error: integer value 3 represents no error",479 ".tmp_source.zig:7:13: error: integer value 3 represents no error",
477 );480 );
478481
479 cases.add(482 cases.add(
480 "int to err non global invalid number",483 "int to err non global invalid number",
481 \\const Set1 = error{A, B};484 \\const Set1 = error{
482 \\const Set2 = error{A, C};485 \\ A,
486 \\ B,
487 \\};
488 \\const Set2 = error{
489 \\ A,
490 \\ C,
491 \\};
483 \\comptime {492 \\comptime {
484 \\ var x = usize(Set1.B);493 \\ var x = @errorToInt(Set1.B);
485 \\ var y = Set2(x);494 \\ var y = @errSetCast(Set2, @intToError(x));
486 \\}495 \\}
487 ,496 ,
488 ".tmp_source.zig:5:17: error: integer value 2 represents no error in 'Set2'",497 ".tmp_source.zig:11:13: error: error.B not a member of error set 'Set2'",
489 );498 );
490499
491 cases.add(500 cases.add(
...@@ -2086,10 +2095,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2086,10 +2095,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2086 "convert fixed size array to slice with invalid size",2095 "convert fixed size array to slice with invalid size",
2087 \\export fn f() void {2096 \\export fn f() void {
2088 \\ var array: [5]u8 = undefined;2097 \\ var array: [5]u8 = undefined;
2089 \\ var foo = ([]const u32)(array)[0];2098 \\ var foo = @bytesToSlice(u32, array)[0];
2090 \\}2099 \\}
2091 ,2100 ,
2092 ".tmp_source.zig:3:28: error: unable to convert [5]u8 to []const u32: size mismatch",2101 ".tmp_source.zig:3:15: error: unable to convert [5]u8 to []align(1) const u32: size mismatch",
2102 ".tmp_source.zig:3:29: note: u32 has size 4; remaining bytes: 1",
2093 );2103 );
20942104
2095 cases.add(2105 cases.add(
...@@ -2611,17 +2621,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2611,17 +2621,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2611 ".tmp_source.zig:2:21: error: expected pointer, found 'usize'",2621 ".tmp_source.zig:2:21: error: expected pointer, found 'usize'",
2612 );2622 );
26132623
2614 cases.add(
2615 "too many error values to cast to small integer",
2616 \\const Error = error { A, B, C, D, E, F, G, H };
2617 \\fn foo(e: Error) u2 {
2618 \\ return u2(e);
2619 \\}
2620 \\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
2621 ,
2622 ".tmp_source.zig:3:14: error: too many error values to fit in 'u2'",
2623 );
2624
2625 cases.add(2624 cases.add(
2626 "asm at compile time",2625 "asm at compile time",
2627 \\comptime {2626 \\comptime {
...@@ -3239,18 +3238,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3239,18 +3238,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3239 ".tmp_source.zig:3:26: note: '*u32' has alignment 4",3238 ".tmp_source.zig:3:26: note: '*u32' has alignment 4",
3240 );3239 );
32413240
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(3241 cases.add(
3255 "@alignCast expects pointer or slice",3242 "@alignCast expects pointer or slice",
3256 \\export fn entry() void {3243 \\export fn entry() void {
...@@ -3722,22 +3709,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3722,22 +3709,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3722 ".tmp_source.zig:9:22: error: expected type 'u2', found 'Small'",3709 ".tmp_source.zig:9:22: error: expected type 'u2', found 'Small'",
3723 );3710 );
37243711
3725 cases.add(
3726 "explicitly casting enum to non tag type",
3727 \\const Small = enum(u2) {
3728 \\ One,
3729 \\ Two,
3730 \\ Three,
3731 \\ Four,
3732 \\};
3733 \\
3734 \\export fn entry() void {
3735 \\ var x = u3(Small.Two);
3736 \\}
3737 ,
3738 ".tmp_source.zig:9:15: error: enum to integer cast to 'u3' instead of its tag type, 'u2'",
3739 );
3740
3741 cases.add(3712 cases.add(
3742 "explicitly casting non tag type to enum",3713 "explicitly casting non tag type to enum",
3743 \\const Small = enum(u2) {3714 \\const Small = enum(u2) {
...@@ -3749,10 +3720,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3749,10 +3720,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3749 \\3720 \\
3750 \\export fn entry() void {3721 \\export fn entry() void {
3751 \\ var y = u3(3);3722 \\ var y = u3(3);
3752 \\ var x = Small(y);3723 \\ var x = @intToEnum(Small, y);
3753 \\}3724 \\}
3754 ,3725 ,
3755 ".tmp_source.zig:10:18: error: integer to enum cast from 'u3' instead of its tag type, 'u2'",3726 ".tmp_source.zig:10:31: error: expected type 'u2', found 'u3'",
3756 );3727 );
37573728
3758 cases.add(3729 cases.add(
...@@ -4033,10 +4004,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4033,10 +4004,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4033 \\ B = 11,4004 \\ B = 11,
4034 \\};4005 \\};
4035 \\export fn entry() void {4006 \\export fn entry() void {
4036 \\ var x = Foo(0);4007 \\ var x = @intToEnum(Foo, 0);
4037 \\}4008 \\}
4038 ,4009 ,
4039 ".tmp_source.zig:6:16: error: enum 'Foo' has no tag matching integer value 0",4010 ".tmp_source.zig:6:13: error: enum 'Foo' has no tag matching integer value 0",
4040 ".tmp_source.zig:1:13: note: 'Foo' declared here",4011 ".tmp_source.zig:1:13: note: 'Foo' declared here",
4041 );4012 );
40424013
test/runtime_safety.zig+7-7
...@@ -175,7 +175,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -175,7 +175,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
175 \\ if (x.len == 0) return error.Whatever;175 \\ if (x.len == 0) return error.Whatever;
176 \\}176 \\}
177 \\fn widenSlice(slice: []align(1) const u8) []align(1) const i32 {177 \\fn widenSlice(slice: []align(1) const u8) []align(1) const i32 {
178 \\ return ([]align(1) const i32)(slice);178 \\ return @bytesToSlice(i32, slice);
179 \\}179 \\}
180 );180 );
181181
...@@ -227,12 +227,12 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -227,12 +227,12 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
227 \\pub fn main() void {227 \\pub fn main() void {
228 \\ _ = bar(9999);228 \\ _ = bar(9999);
229 \\}229 \\}
230 \\fn bar(x: u32) error {230 \\fn bar(x: u16) error {
231 \\ return error(x);231 \\ return @intToError(x);
232 \\}232 \\}
233 );233 );
234234
235 cases.addRuntimeSafety("cast integer to non-global error set and no match",235 cases.addRuntimeSafety("@errSetCast error not present in destination",
236 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {236 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
237 \\ @import("std").os.exit(126);237 \\ @import("std").os.exit(126);
238 \\}238 \\}
...@@ -242,7 +242,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -242,7 +242,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
242 \\ _ = foo(Set1.B);242 \\ _ = foo(Set1.B);
243 \\}243 \\}
244 \\fn foo(set1: Set1) Set2 {244 \\fn foo(set1: Set1) Set2 {
245 \\ return Set2(set1);245 \\ return @errSetCast(Set2, set1);
246 \\}246 \\}
247 );247 );
248248
...@@ -252,12 +252,12 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -252,12 +252,12 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
252 \\}252 \\}
253 \\pub fn main() !void {253 \\pub fn main() !void {
254 \\ var array align(4) = []u32{0x11111111, 0x11111111};254 \\ var array align(4) = []u32{0x11111111, 0x11111111};
255 \\ const bytes = ([]u8)(array[0..]);255 \\ const bytes = @sliceToBytes(array[0..]);
256 \\ if (foo(bytes) != 0x11111111) return error.Wrong;256 \\ if (foo(bytes) != 0x11111111) return error.Wrong;
257 \\}257 \\}
258 \\fn foo(bytes: []u8) u32 {258 \\fn foo(bytes: []u8) u32 {
259 \\ const slice4 = bytes[1..5];259 \\ const slice4 = bytes[1..5];
260 \\ const int_slice = ([]u32)(@alignCast(4, slice4));260 \\ const int_slice = @bytesToSlice(u32, @alignCast(4, slice4));
261 \\ return int_slice[0];261 \\ return int_slice[0];
262 \\}262 \\}
263 );263 );