| author | |
| committer | |
| log | 9f2324389d4aec5d38e840ab09fd9af558a77913 |
| tree | 685b621eb041c178af40c0044c74f689d8d6af7b |
| parent | 1ca90b585692c9611c64412844d2f3a7b3e11340 |
| parent | a3ddd0826bd9c799768c0c707de72c21befa742a |
| signature |
remove "cast harder" casting syntax; add new casting builtins24 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 a | 1456 | // Taking an address of an individual element gives a |
| 1457 | // pointer to a single item. This kind of pointer | 1457 | // pointer to a single item. This kind of pointer |
| 1458 | // does not support pointer arithmetic. | 1458 | // does not support pointer arithmetic. |
| 1459 | 1459 | 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); |
| 1463 | 1462 | ||
| ... | @@ -1469,7 +1468,7 @@ test "pointer array access" { | ... | @@ -1469,7 +1468,7 @@ test "pointer array access" { |
| 1469 | test "pointer slicing" { | 1468 | test "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); |
| 1475 | 1474 | ||
| ... | @@ -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 unsafe | 1540 | // 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 other | 1541 | // 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); |
| 1547 | 1546 | ||
| 1548 | // Even this example is contrived - there are better ways to do the above than | 1547 | // 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); |
| 1552 | 1551 | ||
| 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" { |
| 1630 | const assert = @import("std").debug.assert; | 1629 | const assert = @import("std").debug.assert; |
| 1631 | 1630 | ||
| 1632 | test "pointer alignment safety" { | 1631 | test "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 | } |
| 1637 | fn foo(bytes: []u8) u32 { | 1636 | fn 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" { |
| 1728 | test "slice widening" { | 1727 | test "slice widening" { |
| 1729 | // Zig supports slice widening and slice narrowing. Cast a slice of u8 | 1728 | // 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. |
| 1903 | test "enum ordinal value" { | 1902 | test "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 | } |
| 1908 | 1907 | ||
| 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 | }; |
| 1915 | test "set enum ordinal value" { | 1914 | test "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 | } |
| 1920 | 1919 | ||
| 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#} |
| 4653 | 4652 | ||
| 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 in | 5101 | 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#} |
| 5055 | 5133 | ||
| 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 is | 5907 | Zig has many instances of undefined behavior. If undefined behavior is |
| 5820 | detected at compile-time, Zig emits an error. Most undefined behavior that | 5908 | 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 basis | 5910 | 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#} |
| 6092 | comptime { | 6180 | comptime { |
| 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> |
| 6102 | 6190 | ||
| 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> |
| 6106 | 6199 | ||
| ... | @@ -6109,6 +6202,7 @@ comptime { | ... | @@ -6109,6 +6202,7 @@ comptime { |
| 6109 | <p>TODO</p> | 6202 | <p>TODO</p> |
| 6110 | 6203 | ||
| 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 | }; |
| 236 | 236 | ||
| 237 | enum RuntimeHintSliceId { | ||
| 238 | RuntimeHintSliceIdUnknown, | ||
| 239 | RuntimeHintSliceIdLen, | ||
| 240 | }; | ||
| 241 | |||
| 242 | struct RuntimeHintSlice { | ||
| 243 | enum RuntimeHintSliceId id; | ||
| 244 | uint64_t len; | ||
| 245 | }; | ||
| 246 | |||
| 237 | struct ConstGlobalRefs { | 247 | struct 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 | }; |
| 275 | 286 | ||
| ... | @@ -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 | }; |
| 2125 | 2147 | ||
| 2126 | struct IrInstruction { | 2148 | struct IrInstruction { |
| ... | @@ -2656,6 +2678,26 @@ struct IrInstructionFloatCast { | ... | @@ -2656,6 +2678,26 @@ struct IrInstructionFloatCast { |
| 2656 | IrInstruction *target; | 2678 | IrInstruction *target; |
| 2657 | }; | 2679 | }; |
| 2658 | 2680 | ||
| 2681 | struct IrInstructionErrSetCast { | ||
| 2682 | IrInstruction base; | ||
| 2683 | |||
| 2684 | IrInstruction *dest_type; | ||
| 2685 | IrInstruction *target; | ||
| 2686 | }; | ||
| 2687 | |||
| 2688 | struct IrInstructionToBytes { | ||
| 2689 | IrInstruction base; | ||
| 2690 | |||
| 2691 | IrInstruction *target; | ||
| 2692 | }; | ||
| 2693 | |||
| 2694 | struct IrInstructionFromBytes { | ||
| 2695 | IrInstruction base; | ||
| 2696 | |||
| 2697 | IrInstruction *dest_child_type; | ||
| 2698 | IrInstruction *target; | ||
| 2699 | }; | ||
| 2700 | |||
| 2659 | struct IrInstructionIntToFloat { | 2701 | struct IrInstructionIntToFloat { |
| 2660 | IrInstruction base; | 2702 | IrInstruction base; |
| 2661 | 2703 | ||
| ... | @@ -2866,6 +2908,13 @@ struct IrInstructionIntToPtr { | ... | @@ -2866,6 +2908,13 @@ struct IrInstructionIntToPtr { |
| 2866 | struct IrInstructionIntToEnum { | 2908 | struct IrInstructionIntToEnum { |
| 2867 | IrInstruction base; | 2909 | IrInstruction base; |
| 2868 | 2910 | ||
| 2911 | IrInstruction *dest_type; | ||
| 2912 | IrInstruction *target; | ||
| 2913 | }; | ||
| 2914 | |||
| 2915 | struct IrInstructionEnumToInt { | ||
| 2916 | IrInstruction base; | ||
| 2917 | |||
| 2869 | IrInstruction *target; | 2918 | IrInstruction *target; |
| 2870 | }; | 2919 | }; |
| 2871 | 2920 |
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(); |
| 4731 | 4735 | ||
| 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 Int | 6333 | 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 | } |
| 6360 | 6371 | ||
| 6361 | static const char *bool_to_str(bool b) { | 6372 | static 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 | } |
| 470 | 470 | ||
| 471 | static constexpr IrInstructionId ir_instruction_id(IrInstructionErrSetCast *) { | ||
| 472 | return IrInstructionIdErrSetCast; | ||
| 473 | } | ||
| 474 | |||
| 475 | static constexpr IrInstructionId ir_instruction_id(IrInstructionToBytes *) { | ||
| 476 | return IrInstructionIdToBytes; | ||
| 477 | } | ||
| 478 | |||
| 479 | static constexpr IrInstructionId ir_instruction_id(IrInstructionFromBytes *) { | ||
| 480 | return IrInstructionIdFromBytes; | ||
| 481 | } | ||
| 482 | |||
| 471 | static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToFloat *) { | 483 | static 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 | } |
| 590 | 602 | ||
| 603 | static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumToInt *) { | ||
| 604 | return IrInstructionIdEnumToInt; | ||
| 605 | } | ||
| 606 | |||
| 591 | static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToErr *) { | 607 | static 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 | } |
| 1943 | 1959 | ||
| 1960 | static 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 | |||
| 1971 | static 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 | |||
| 1980 | static 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 | |||
| 1944 | static IrInstruction *ir_build_int_to_float(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) { | 1991 | static 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 | } |
| 2336 | 2383 | ||
| 2337 | static IrInstruction *ir_build_int_to_enum(IrBuilder *irb, Scope *scope, AstNode *source_node, | 2384 | static 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 | |||
| 2400 | static 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; |
| 2343 | 2406 | ||
| 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 arg | 4728 | // 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 | } |
| 9075 | 9223 | ||
| 9076 | static bool is_u8(TypeTableEntry *type) { | ||
| 9077 | return type->id == TypeTableEntryIdInt && | ||
| 9078 | !type->data.integral.is_signed && type->data.integral.bit_count == 8; | ||
| 9079 | } | ||
| 9080 | |||
| 9081 | static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) { | 9224 | static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) { |
| 9082 | assert(old_bb); | 9225 | assert(old_bb); |
| 9083 | 9226 | ||
| ... | @@ -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); |
| 9635 | 9780 | ||
| 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 | } |
| 9852 | 9997 | ||
| 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 | } |
| 10075 | 10220 | ||
| 10076 | // explicit match or non-const to const | 10221 | // 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 | } |
| 10105 | 10250 | ||
| 10106 | 10251 | ||
| 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 T | 10252 | // 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 | } |
| 10144 | 10282 | ||
| 10145 | // explicit cast from [N]T to &const []const N | 10283 | // 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 | } |
| 10193 | 10331 | ||
| 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 [*]T | 10332 | // 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 | } |
| 10440 | 10532 | ||
| 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 union | 10533 | // 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 | } |
| 17595 | 17662 | ||
| 17663 | static 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 | |||
| 17691 | static 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 | |||
| 17771 | static 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 | |||
| 17596 | static TypeTableEntry *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) { | 17794 | static 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 | } |
| 17629 | 17827 | ||
| 17828 | static 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 | |||
| 17847 | static 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 | |||
| 17630 | static TypeTableEntry *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, IrInstructionBoolToInt *instruction) { | 17861 | static 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 | } |
| 20068 | 20299 | ||
| 20300 | static 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 | |||
| 20322 | static 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 | |||
| 20069 | static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) { | 20353 | static 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; |
| 20551 | 20850 | ||
| 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 | } |
| 666 | 666 | ||
| 667 | static 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 | |||
| 675 | static 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 | |||
| 683 | static 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 | |||
| 667 | static void ir_print_int_to_float(IrPrint *irp, IrInstructionIntToFloat *instruction) { | 689 | static 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 |
| 906 | 928 | ||
| 907 | static void ir_print_int_to_enum(IrPrint *irp, IrInstructionIntToEnum *instruction) { | 929 | static 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 | |||
| 940 | static 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); |
| 80 | 80 | ||
| 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); |
| 83 | 83 | ||
| 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 | }; |
| 186 | 186 |
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 | } |
| 162 | 162 | ||
| 163 | fn readNoEof(in: *io.FileInStream, comptime T: type, result: []T) !void { | 163 | fn 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 | } |
| 166 | fn readOneNoEof(in: *io.FileInStream, comptime T: type, result: *T) !void { | 166 | fn 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 | } |
| 75 | 75 | ||
| 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 | } |
| 88 | 88 | ||
| 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 | } |
| 101 | 101 | ||
| 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; |
| 120 | 120 | ||
| 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 | } |
| 125 | 125 | ||
| 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 { |
| 68 | 68 | ||
| 69 | pub fn parseIp4(buf: []const u8) !u32 { | 69 | pub 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..]); |
| 72 | 72 | ||
| 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 error | 318 | // 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 | } |
| 323 | 323 | ||
| 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. |
| 758 | fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn { | 758 | fn 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 | } |
| 762 | 762 |
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); |
| 1807 | 1807 | ||
| 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); |
| 1811 | 1811 |
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 { |
| 79 | 79 | ||
| 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 or | 83 | 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 | } |
| 96 | 96 |
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 | } |
| 142 | fn testCastIntToErr(err: error) void { | 142 | fn 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 | } |
| 147 | 147 | ||
| ... | @@ -372,7 +372,7 @@ test "const slice widen cast" { | ... | @@ -372,7 +372,7 @@ test "const slice widen cast" { |
| 372 | 0x12, | 372 | 0x12, |
| 373 | }; | 373 | }; |
| 374 | 374 | ||
| 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); |
| 377 | 377 | ||
| 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 | |||
| 424 | test "@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 | } |
| 93 | 93 | ||
| 94 | fn shouldEqual(n: Number, expected: u3) void { | 94 | fn shouldEqual(n: Number, expected: u3) void { |
| 95 | assert(u3(n) == expected); | 95 | assert(@enumToInt(n) == expected); |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | test "int to enum" { | 98 | test "int to enum" { |
| 99 | testIntToEnumEval(3); | 99 | testIntToEnumEval(3); |
| 100 | } | 100 | } |
| 101 | fn testIntToEnumEval(x: i32) void { | 101 | fn testIntToEnumEval(x: i32) void { |
| 102 | assert(IntToEnumNumber(@intCast(u3, x)) == IntToEnumNumber.Three); | 102 | assert(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three); |
| 103 | } | 103 | } |
| 104 | const IntToEnumNumber = enum { | 104 | const 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 | } |
| 769 | 769 | ||
| 770 | fn testCastEnumToTagType(value: Small2) void { | 770 | fn testCastEnumToTagType(value: Small2) void { |
| 771 | assert(u2(value) == 1); | 771 | assert(@enumToInt(value) == 1); |
| 772 | } | 772 | } |
| 773 | 773 | ||
| 774 | const MultipleChoice = enum(u32) { | 774 | const 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 | } |
| 785 | 785 | ||
| 786 | fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void { | 786 | fn 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 | } |
| 812 | 812 | ||
| 813 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void { | 813 | fn 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 | } |
| 827 | 827 | ||
| 828 | test "cast integer literal to enum" { | 828 | test "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 | } |
| 832 | 832 | ||
| 833 | const EnumWithOneMember = enum { | 833 | const 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 | }; |
| 867 | test "enum with tag values don't require parens" { | 867 | test "enum with tag values don't require parens" { |
| 868 | assert(u4(EnumWithTagValues.C) == 0b0100); | 868 | assert(@enumToInt(EnumWithTagValues.C) == 0b0100); |
| 869 | } | 869 | } |
| 870 | 870 | ||
| 871 | test "enum with 1 field but explicit tag type should still have the tag type" { | 871 | test "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 | } |
| 32 | 32 | ||
| 33 | test "error values" { | 33 | test "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 | } |
| 38 | 38 | ||
| ... | @@ -124,8 +124,8 @@ const Set2 = error{ | ... | @@ -124,8 +124,8 @@ const Set2 = error{ |
| 124 | }; | 124 | }; |
| 125 | 125 | ||
| 126 | fn testExplicitErrorSetCast(set1: Set1) void { | 126 | fn 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 | } |
| 131 | 131 | ||
| ... | @@ -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 | } |
| 148 | 148 | ||
| 149 | test "comptime err to int of error set with only 1 possible value" { | 149 | test "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 | } |
| 153 | fn testErrToIntWithOnePossibleValue( | 153 | fn 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" { |
| 302 | 302 | ||
| 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 | } |
| 352 | 352 | ||
| 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]; |
| 355 | 355 | ||
| 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)); |
| 134 | 134 | ||
| 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)) { |
| 126 | test "simple union(enum(u32))" { | 126 | test "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 | } |
| 131 | 131 | ||
| 132 | const MultipleChoice2 = union(enum(u32)) { | 132 | const 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 | } |
| 149 | 149 | ||
| 150 | fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: *const MultipleChoice2) void { | 150 | fn 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 | ); |
| 412 | 412 | ||
| 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 { |
| 467 | 467 | ||
| 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 | ); |
| 478 | 481 | ||
| 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 | ); |
| 490 | 499 | ||
| 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 | ); |
| 2094 | 2104 | ||
| 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 | ); |
| 2613 | 2623 | ||
| 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 | ); |
| 3241 | 3240 | ||
| 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 | ); |
| 3724 | 3711 | ||
| 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 | ); |
| 3757 | 3728 | ||
| 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 | ); |
| 4042 | 4013 |
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 | ); |
| 181 | 181 | ||
| ... | @@ -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 | ); |
| 234 | 234 | ||
| 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 | ); |
| 248 | 248 | ||
| ... | @@ -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 | ); |