From fdae5f5a07c043d9eeefe4933bcfbd03df581fde Mon Sep 17 00:00:00 2001 From: xackus <14938807+xackus@users.noreply.github.com> Date: Thu, 20 Feb 2020 20:01:52 +0100 Subject: [PATCH 1/4] implement bytesAsSlice, sliceAsBytes --- lib/std/mem.zig | 70 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 71be738def..f4c117e537 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -1486,6 +1486,76 @@ test "bytesToValue" { testing.expect(deadbeef == @as(u32, 0xDEADBEEF)); } +//TODO copy also is_volatile, etc. I tried to use @typeInfo, modify child type, use @Type, but ran into issues. +fn BytesAsSliceReturnType(comptime T: type, comptime bytesType: type) type { + if (comptime !trait.isSlice(bytesType) or comptime meta.Child(bytesType) != u8) { + @compileError("expected []u8, passed " ++ @typeName(bytesType)); + } + + const alignment = comptime meta.alignment(bytesType); + + return if (comptime trait.isConstPtr(bytesType)) []align(alignment) const T else []align(alignment) T; +} + +pub fn bytesAsSlice(comptime T: type, bytes: var) BytesAsSliceReturnType(T, @TypeOf(bytes)) { + // let's not give an undefined pointer to @ptrCast + // it may be equal to zero and fail a null check + if (bytes.len == 0) { + return &[0]T{}; + } + + const bytesType = @TypeOf(bytes); + const alignment = comptime meta.alignment(bytesType); + + const castTarget = if (comptime trait.isConstPtr(bytesType)) [*]align(alignment) const T else [*]align(alignment) T; + + return @ptrCast(castTarget, bytes.ptr)[0..@divExact(bytes.len, @sizeOf(T))]; +} + +test "bytesAsSlice" { + const bytes = [_]u8{ 0xDE, 0xAD, 0xBE, 0xEF }; + const slice = bytesAsSlice(u16, bytes[0..]); + testing.expect(slice.len == 2); + testing.expect(bigToNative(u16, slice[0]) == 0xDEAD); + testing.expect(bigToNative(u16, slice[1]) == 0xBEEF); +} + +//TODO copy also is_volatile, etc. I tried to use @typeInfo, modify child type, use @Type, but ran into issues. +fn SliceAsBytesReturnType(comptime sliceType: type) type { + if (comptime !trait.isSlice(sliceType)) { + @compileError("expected []T, passed " ++ @typeName(sliceType)); + } + + const alignment = comptime meta.alignment(sliceType); + + return if (comptime trait.isConstPtr(sliceType)) []align(alignment) const u8 else []align(alignment) u8; +} + +pub fn sliceAsBytes(slice: var) SliceAsBytesReturnType(@TypeOf(slice)) { + // let's not give an undefined pointer to @ptrCast + // it may be equal to zero and fail a null check + if (slice.len == 0) { + return &[0]u8{}; + } + + const sliceType = @TypeOf(slice); + const alignment = comptime meta.alignment(sliceType); + + const castTarget = if (comptime trait.isConstPtr(sliceType)) [*]align(alignment) const u8 else [*]align(alignment) u8; + + return @ptrCast(castTarget, slice.ptr)[0 .. slice.len * @sizeOf(comptime meta.Child(sliceType))]; +} + +test "sliceAsBytes" { + const bytes = [_]u16{ 0xDEAD, 0xBEEF }; + const slice = sliceAsBytes(bytes[0..]); + testing.expect(slice.len == 4); + testing.expect(eql(u8, slice, switch (builtin.endian) { + .Big => "\xDE\xAD\xBE\xEF", + .Little => "\xAD\xDE\xEF\xBE", + })); +} + fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type { if (trait.isConstPtr(T)) return *const [length]meta.Child(meta.Child(T)); From 783e8ad0319b950a1d42d5a93e4fbb9e9df1be10 Mon Sep 17 00:00:00 2001 From: xackus <14938807+xackus@users.noreply.github.com> Date: Fri, 21 Feb 2020 19:46:53 +0100 Subject: [PATCH 2/4] remove @bytesToSlice, @sliceToBytes from std lib --- lib/std/crypto/gimli.zig | 4 ++-- lib/std/cstr.zig | 2 +- lib/std/fifo.zig | 8 ++++---- lib/std/fs/watch.zig | 2 +- lib/std/heap.zig | 6 +++--- lib/std/io/in_stream.zig | 2 +- lib/std/mem.zig | 12 ++++++------ lib/std/net.zig | 4 ++-- lib/std/os.zig | 2 +- lib/std/process.zig | 2 +- lib/std/unicode.zig | 12 ++++++------ 11 files changed, 28 insertions(+), 28 deletions(-) diff --git a/lib/std/crypto/gimli.zig b/lib/std/crypto/gimli.zig index ed2c5e764f..30304f59cf 100644 --- a/lib/std/crypto/gimli.zig +++ b/lib/std/crypto/gimli.zig @@ -24,11 +24,11 @@ pub const State = struct { const Self = @This(); pub fn toSlice(self: *Self) []u8 { - return @sliceToBytes(self.data[0..]); + return mem.sliceAsBytes(self.data[0..]); } pub fn toSliceConst(self: *Self) []const u8 { - return @sliceToBytes(self.data[0..]); + return mem.sliceAsBytes(self.data[0..]); } pub fn permute(self: *Self) void { diff --git a/lib/std/cstr.zig b/lib/std/cstr.zig index 5d16e9387b..765e0a45cf 100644 --- a/lib/std/cstr.zig +++ b/lib/std/cstr.zig @@ -72,7 +72,7 @@ pub const NullTerminated2DArray = struct { errdefer allocator.free(buf); var write_index = index_size; - const index_buf = @bytesToSlice(?[*]u8, buf); + const index_buf = mem.bytesAsSlice(?[*]u8, buf); var i: usize = 0; for (slices) |slice| { diff --git a/lib/std/fifo.zig b/lib/std/fifo.zig index ac8589f2ce..85a0e4c9d2 100644 --- a/lib/std/fifo.zig +++ b/lib/std/fifo.zig @@ -101,7 +101,7 @@ pub fn LinearFifo( } } { // set unused area to undefined - const unused = @sliceToBytes(self.buf[self.count..]); + const unused = mem.sliceAsBytes(self.buf[self.count..]); @memset(unused.ptr, undefined, unused.len); } } @@ -166,12 +166,12 @@ pub fn LinearFifo( { // set old range to undefined. Note: may be wrapped around const slice = self.readableSliceMut(0); if (slice.len >= count) { - const unused = @sliceToBytes(slice[0..count]); + const unused = mem.sliceAsBytes(slice[0..count]); @memset(unused.ptr, undefined, unused.len); } else { - const unused = @sliceToBytes(slice[0..]); + const unused = mem.sliceAsBytes(slice[0..]); @memset(unused.ptr, undefined, unused.len); - const unused2 = @sliceToBytes(self.readableSliceMut(slice.len)[0 .. count - slice.len]); + const unused2 = mem.sliceAsBytes(self.readableSliceMut(slice.len)[0 .. count - slice.len]); @memset(unused2.ptr, undefined, unused2.len); } } diff --git a/lib/std/fs/watch.zig b/lib/std/fs/watch.zig index c904f110e2..0ff8c47ecf 100644 --- a/lib/std/fs/watch.zig +++ b/lib/std/fs/watch.zig @@ -26,7 +26,7 @@ fn eqlString(a: []const u16, b: []const u16) bool { } fn hashString(s: []const u16) u32 { - return @truncate(u32, std.hash.Wyhash.hash(0, @sliceToBytes(s))); + return @truncate(u32, std.hash.Wyhash.hash(0, mem.sliceAsBytes(s))); } const WatchEventError = error{ diff --git a/lib/std/heap.zig b/lib/std/heap.zig index 1bce45081d..135d7297a2 100644 --- a/lib/std/heap.zig +++ b/lib/std/heap.zig @@ -283,14 +283,14 @@ const WasmPageAllocator = struct { fn getBit(self: FreeBlock, idx: usize) PageStatus { const bit_offset = 0; - return @intToEnum(PageStatus, Io.get(@sliceToBytes(self.data), idx, bit_offset)); + return @intToEnum(PageStatus, Io.get(mem.sliceAsBytes(self.data), idx, bit_offset)); } fn setBits(self: FreeBlock, start_idx: usize, len: usize, val: PageStatus) void { const bit_offset = 0; var i: usize = 0; while (i < len) : (i += 1) { - Io.set(@sliceToBytes(self.data), start_idx + i, bit_offset, @enumToInt(val)); + Io.set(mem.sliceAsBytes(self.data), start_idx + i, bit_offset, @enumToInt(val)); } } @@ -552,7 +552,7 @@ pub const ArenaAllocator = struct { if (len >= actual_min_size) break; } const buf = try self.child_allocator.alignedAlloc(u8, @alignOf(BufNode), len); - const buf_node_slice = @bytesToSlice(BufNode, buf[0..@sizeOf(BufNode)]); + const buf_node_slice = mem.bytesAsSlice(BufNode, buf[0..@sizeOf(BufNode)]); const buf_node = &buf_node_slice[0]; buf_node.* = BufNode{ .data = buf, diff --git a/lib/std/io/in_stream.zig b/lib/std/io/in_stream.zig index ab02d20eed..4f3bac3c21 100644 --- a/lib/std/io/in_stream.zig +++ b/lib/std/io/in_stream.zig @@ -235,7 +235,7 @@ pub fn InStream(comptime ReadError: type) type { // Only extern and packed structs have defined in-memory layout. comptime assert(@typeInfo(T).Struct.layout != builtin.TypeInfo.ContainerLayout.Auto); var res: [1]T = undefined; - try self.readNoEof(@sliceToBytes(res[0..])); + try self.readNoEof(mem.sliceAsBytes(res[0..])); return res[0]; } diff --git a/lib/std/mem.zig b/lib/std/mem.zig index f4c117e537..01e289988b 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -132,7 +132,7 @@ pub const Allocator = struct { // their own frame with @Frame(func). return @intToPtr([*]T, @ptrToInt(byte_slice.ptr))[0..n]; } else { - return @bytesToSlice(T, @alignCast(a, byte_slice)); + return mem.bytesAsSlice(T, @alignCast(a, byte_slice)); } } @@ -173,7 +173,7 @@ pub const Allocator = struct { return @as([*]align(new_alignment) T, undefined)[0..0]; } - const old_byte_slice = @sliceToBytes(old_mem); + const old_byte_slice = mem.sliceAsBytes(old_mem); const byte_count = math.mul(usize, @sizeOf(T), new_n) catch return Error.OutOfMemory; // Note: can't set shrunk memory to undefined as memory shouldn't be modified on realloc failure const byte_slice = try self.reallocFn(self, old_byte_slice, Slice.alignment, byte_count, new_alignment); @@ -181,7 +181,7 @@ pub const Allocator = struct { if (new_n > old_mem.len) { @memset(byte_slice.ptr + old_byte_slice.len, undefined, byte_slice.len - old_byte_slice.len); } - return @bytesToSlice(T, @alignCast(new_alignment, byte_slice)); + return mem.bytesAsSlice(T, @alignCast(new_alignment, byte_slice)); } /// Prefer calling realloc to shrink if you can tolerate failure, such as @@ -221,18 +221,18 @@ pub const Allocator = struct { // new_n <= old_mem.len and the multiplication didn't overflow for that operation. const byte_count = @sizeOf(T) * new_n; - const old_byte_slice = @sliceToBytes(old_mem); + const old_byte_slice = mem.sliceAsBytes(old_mem); @memset(old_byte_slice.ptr + byte_count, undefined, old_byte_slice.len - byte_count); const byte_slice = self.shrinkFn(self, old_byte_slice, Slice.alignment, byte_count, new_alignment); assert(byte_slice.len == byte_count); - return @bytesToSlice(T, @alignCast(new_alignment, byte_slice)); + return mem.bytesAsSlice(T, @alignCast(new_alignment, byte_slice)); } /// Free an array allocated with `alloc`. To free a single item, /// see `destroy`. pub fn free(self: *Allocator, memory: var) void { const Slice = @typeInfo(@TypeOf(memory)).Pointer; - const bytes = @sliceToBytes(memory); + const bytes = mem.sliceAsBytes(memory); const bytes_len = bytes.len + if (Slice.sentinel != null) @sizeOf(Slice.child) else 0; if (bytes_len == 0) return; const non_const_ptr = @intToPtr([*]u8, @ptrToInt(bytes.ptr)); diff --git a/lib/std/net.zig b/lib/std/net.zig index 27056bf1db..19092f25ca 100644 --- a/lib/std/net.zig +++ b/lib/std/net.zig @@ -120,7 +120,7 @@ pub const Address = extern union { ip_slice[10] = 0xff; ip_slice[11] = 0xff; - const ptr = @sliceToBytes(@as(*const [1]u32, &addr)[0..]); + const ptr = mem.sliceAsBytes(@as(*const [1]u32, &addr)[0..]); ip_slice[12] = ptr[0]; ip_slice[13] = ptr[1]; @@ -164,7 +164,7 @@ pub const Address = extern union { .addr = undefined, }, }; - const out_ptr = @sliceToBytes(@as(*[1]u32, &result.in.addr)[0..]); + const out_ptr = mem.sliceAsBytes(@as(*[1]u32, &result.in.addr)[0..]); var x: u8 = 0; var index: u8 = 0; diff --git a/lib/std/os.zig b/lib/std/os.zig index 0f492a25f2..038839eeaf 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -1778,7 +1778,7 @@ pub fn isCygwinPty(handle: fd_t) bool { const name_info = @ptrCast(*const windows.FILE_NAME_INFO, &name_info_bytes[0]); const name_bytes = name_info_bytes[size .. size + @as(usize, name_info.FileNameLength)]; - const name_wide = @bytesToSlice(u16, name_bytes); + const name_wide = mem.bytesAsSlice(u16, name_bytes); return mem.indexOf(u16, name_wide, &[_]u16{ 'm', 's', 'y', 's', '-' }) != null or mem.indexOf(u16, name_wide, &[_]u16{ '-', 'p', 't', 'y' }) != null; } diff --git a/lib/std/process.zig b/lib/std/process.zig index 89307b44da..d9ec0a056d 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -436,7 +436,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![][]u8 { const buf = try allocator.alignedAlloc(u8, @alignOf([]u8), total_bytes); errdefer allocator.free(buf); - const result_slice_list = @bytesToSlice([]u8, buf[0..slice_list_bytes]); + const result_slice_list = mem.bytesAsSlice([]u8, buf[0..slice_list_bytes]); const result_contents = buf[slice_list_bytes..]; mem.copy(u8, result_contents, contents_slice); diff --git a/lib/std/unicode.zig b/lib/std/unicode.zig index ed24f83c33..85c91602d0 100644 --- a/lib/std/unicode.zig +++ b/lib/std/unicode.zig @@ -243,7 +243,7 @@ pub const Utf16LeIterator = struct { pub fn init(s: []const u16) Utf16LeIterator { return Utf16LeIterator{ - .bytes = @sliceToBytes(s), + .bytes = mem.sliceAsBytes(s), .i = 0, }; } @@ -496,7 +496,7 @@ pub fn utf16leToUtf8(utf8: []u8, utf16le: []const u16) !usize { test "utf16leToUtf8" { var utf16le: [2]u16 = undefined; - const utf16le_as_bytes = @sliceToBytes(utf16le[0..]); + const utf16le_as_bytes = mem.sliceAsBytes(utf16le[0..]); { mem.writeIntSliceLittle(u16, utf16le_as_bytes[0..], 'A'); @@ -606,12 +606,12 @@ test "utf8ToUtf16Le" { { const length = try utf8ToUtf16Le(utf16le[0..], "𐐷"); testing.expectEqual(@as(usize, 2), length); - testing.expectEqualSlices(u8, "\x01\xd8\x37\xdc", @sliceToBytes(utf16le[0..])); + testing.expectEqualSlices(u8, "\x01\xd8\x37\xdc", mem.sliceAsBytes(utf16le[0..])); } { const length = try utf8ToUtf16Le(utf16le[0..], "\u{10FFFF}"); testing.expectEqual(@as(usize, 2), length); - testing.expectEqualSlices(u8, "\xff\xdb\xff\xdf", @sliceToBytes(utf16le[0..])); + testing.expectEqualSlices(u8, "\xff\xdb\xff\xdf", mem.sliceAsBytes(utf16le[0..])); } } @@ -619,13 +619,13 @@ test "utf8ToUtf16LeWithNull" { { const utf16 = try utf8ToUtf16LeWithNull(testing.allocator, "𐐷"); defer testing.allocator.free(utf16); - testing.expectEqualSlices(u8, "\x01\xd8\x37\xdc", @sliceToBytes(utf16[0..])); + testing.expectEqualSlices(u8, "\x01\xd8\x37\xdc", mem.sliceAsBytes(utf16[0..])); testing.expect(utf16[2] == 0); } { const utf16 = try utf8ToUtf16LeWithNull(testing.allocator, "\u{10FFFF}"); defer testing.allocator.free(utf16); - testing.expectEqualSlices(u8, "\xff\xdb\xff\xdf", @sliceToBytes(utf16[0..])); + testing.expectEqualSlices(u8, "\xff\xdb\xff\xdf", mem.sliceAsBytes(utf16[0..])); testing.expect(utf16[2] == 0); } } From 7664c3bc11988fd1ee2b3f26d1f08ac80d873c64 Mon Sep 17 00:00:00 2001 From: xackus <14938807+xackus@users.noreply.github.com> Date: Sun, 23 Feb 2020 18:03:50 +0100 Subject: [PATCH 3/4] remove @bytesToSlice, @sliceToBytes from tests, docs --- doc/langref.html.in | 61 +++----------- lib/std/mem.zig | 114 ++++++++++++++++++++++---- lib/std/meta/trait.zig | 16 ++++ test/compile_errors.zig | 10 --- test/runtime_safety.zig | 16 ++-- test/stage1/behavior.zig | 1 - test/stage1/behavior/align.zig | 14 ---- test/stage1/behavior/async_fn.zig | 4 +- test/stage1/behavior/bugs/1851.zig | 2 +- test/stage1/behavior/cast.zig | 20 ----- test/stage1/behavior/eval.zig | 10 --- test/stage1/behavior/misc.zig | 21 ----- test/stage1/behavior/slicetobytes.zig | 29 ------- test/stage1/behavior/struct.zig | 4 +- 14 files changed, 141 insertions(+), 181 deletions(-) delete mode 100644 test/stage1/behavior/slicetobytes.zig diff --git a/doc/langref.html.in b/doc/langref.html.in index 71f97b3f06..4ac9cf47e0 100644 --- a/doc/langref.html.in +++ b/doc/langref.html.in @@ -2025,7 +2025,8 @@ test "volatile" { conversions are not possible.

{#code_begin|test#} -const assert = @import("std").debug.assert; +const std = @import("std"); +const assert = std.debug.assert; test "pointer casting" { const bytes align(@alignOf(u32)) = [_]u8{ 0x12, 0x12, 0x12, 0x12 }; @@ -2034,7 +2035,7 @@ test "pointer casting" { // Even this example is contrived - there are better ways to do the above than // pointer casting. For example, using a slice narrowing cast: - const u32_value = @bytesToSlice(u32, bytes[0..])[0]; + const u32_value = std.mem.bytesAsSlice(u32, bytes[0..])[0]; assert(u32_value == 0x12121212); // And even another way, the most straightforward way to do it: @@ -2114,16 +2115,16 @@ test "function alignment" { {#link|safety check|Incorrect Pointer Alignment#}:

{#code_begin|test_safety|incorrect alignment#} -const assert = @import("std").debug.assert; +const std = @import("std"); test "pointer alignment safety" { var array align(4) = [_]u32{ 0x11111111, 0x11111111 }; - const bytes = @sliceToBytes(array[0..]); - assert(foo(bytes) == 0x11111111); + const bytes = std.mem.sliceAsBytes(array[0..]); + std.debug.assert(foo(bytes) == 0x11111111); } fn foo(bytes: []u8) u32 { const slice4 = bytes[1..5]; - const int_slice = @bytesToSlice(u32, @alignCast(4, slice4)); + const int_slice = std.mem.bytesAsSlice(u32, @alignCast(4, slice4)); return int_slice[0]; } {#code_end#} @@ -2249,7 +2250,7 @@ test "slice widening" { // Zig supports slice widening and slice narrowing. Cast a slice of u8 // to a slice of anything else, and Zig will perform the length conversion. const array align(@alignOf(u32)) = [_]u8{ 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13 }; - const slice = @bytesToSlice(u32, array[0..]); + const slice = mem.bytesAsSlice(u32, array[0..]); assert(slice.len == 2); assert(slice[0] == 0x12121212); assert(slice[1] == 0x13131313); @@ -5186,7 +5187,6 @@ test "coercion of zero bit types" {
  • {#link|@bitCast#} - change type but maintain bit representation
  • {#link|@alignCast#} - make a pointer have more alignment
  • {#link|@boolToInt#} - convert true to 1 and false to 0
  • -
  • {#link|@bytesToSlice#} - convert a slice of bytes to a slice of another type
  • {#link|@enumToInt#} - obtain the integer tag value of an enum or tagged union
  • {#link|@errSetCast#} - convert to a smaller error set
  • {#link|@errorToInt#} - obtain the integer value of an error code
  • @@ -5199,7 +5199,6 @@ test "coercion of zero bit types" {
  • {#link|@intToPtr#} - convert an address to a pointer
  • {#link|@ptrCast#} - convert between pointer types
  • {#link|@ptrToInt#} - obtain the address of a pointer
  • -
  • {#link|@sliceToBytes#} - convert a slice of anything to a slice of bytes
  • {#link|@truncate#} - convert between integer types, chopping off bits
  • {#header_close#} @@ -6929,18 +6928,6 @@ async fn func(y: *i32) void { {#see_also|@bitOffsetOf#} {#header_close#} - {#header_open|@bytesToSlice#} -
    {#syntax#}@bytesToSlice(comptime Element: type, bytes: []u8) []Element{#endsyntax#}
    -

    - Converts a slice of bytes or array of bytes into a slice of {#syntax#}Element{#endsyntax#}. - The resulting slice has the same {#link|pointer|Pointers#} properties as the parameter. -

    -

    - Attempting to convert a number of bytes with a length that does not evenly divide into a slice of - elements results in safety-protected {#link|Undefined Behavior#}. -

    - {#header_close#} - {#header_open|@call#}
    {#syntax#}@call(options: std.builtin.CallOptions, function: var, args: var) var{#endsyntax#}

    @@ -8101,14 +8088,6 @@ test "@setRuntimeSafety" { {#see_also|@bitSizeOf|@typeInfo#} {#header_close#} - {#header_open|@sliceToBytes#} -

    {#syntax#}@sliceToBytes(value: var) []u8{#endsyntax#}
    -

    - Converts a slice or array to a slice of {#syntax#}u8{#endsyntax#}. The resulting slice has the same - {#link|pointer|Pointers#} properties as the parameter. -

    - {#header_close#} - {#header_open|@splat#}
    {#syntax#}@splat(comptime len: u32, scalar: var) @Vector(len, @TypeOf(scalar)){#endsyntax#}

    @@ -8919,25 +8898,6 @@ pub fn main() void { var b: u32 = 3; var c = @divExact(a, b); std.debug.warn("value: {}\n", .{c}); -} - {#code_end#} - {#header_close#} - {#header_open|Slice Widen Remainder#} -

    At compile-time:

    - {#code_begin|test_err|unable to convert#} -comptime { - var bytes = [5]u8{ 1, 2, 3, 4, 5 }; - var slice = @bytesToSlice(u32, bytes[0..]); -} - {#code_end#} -

    At runtime:

    - {#code_begin|exe_err#} -const std = @import("std"); - -pub fn main() void { - var bytes = [5]u8{ 1, 2, 3, 4, 5 }; - var slice = @bytesToSlice(u32, bytes[0..]); - std.debug.warn("value: {}\n", .{slice[0]}); } {#code_end#} {#header_close#} @@ -9119,14 +9079,15 @@ comptime { {#code_end#}

    At runtime:

    {#code_begin|exe_err#} +const mem = @import("std").mem; pub fn main() !void { var array align(4) = [_]u32{ 0x11111111, 0x11111111 }; - const bytes = @sliceToBytes(array[0..]); + const bytes = mem.sliceAsBytes(array[0..]); if (foo(bytes) != 0x11111111) return error.Wrong; } fn foo(bytes: []u8) u32 { const slice4 = bytes[1..5]; - const int_slice = @bytesToSlice(u32, @alignCast(4, slice4)); + const int_slice = mem.bytesAsSlice(u32, @alignCast(4, slice4)); return int_slice[0]; } {#code_end#} diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 01e289988b..20ad567431 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -1488,28 +1488,34 @@ test "bytesToValue" { //TODO copy also is_volatile, etc. I tried to use @typeInfo, modify child type, use @Type, but ran into issues. fn BytesAsSliceReturnType(comptime T: type, comptime bytesType: type) type { - if (comptime !trait.isSlice(bytesType) or comptime meta.Child(bytesType) != u8) { - @compileError("expected []u8, passed " ++ @typeName(bytesType)); + if (!(trait.isSlice(bytesType) and meta.Child(bytesType) == u8) and !(trait.isPtrTo(.Array)(bytesType) and meta.Child(meta.Child(bytesType)) == u8)) { + @compileError("expected []u8 or *[_]u8, passed " ++ @typeName(bytesType)); } - const alignment = comptime meta.alignment(bytesType); + if (trait.isPtrTo(.Array)(bytesType) and @typeInfo(meta.Child(bytesType)).Array.len % @sizeOf(T) != 0) { + @compileError("number of bytes in " ++ @typeName(bytesType) ++ " is not divisible by size of " ++ @typeName(T)); + } - return if (comptime trait.isConstPtr(bytesType)) []align(alignment) const T else []align(alignment) T; + const alignment = meta.alignment(bytesType); + + return if (trait.isConstPtr(bytesType)) []align(alignment) const T else []align(alignment) T; } pub fn bytesAsSlice(comptime T: type, bytes: var) BytesAsSliceReturnType(T, @TypeOf(bytes)) { + const bytesSlice = if (comptime trait.isPtrTo(.Array)(@TypeOf(bytes))) bytes[0..] else bytes; + // let's not give an undefined pointer to @ptrCast // it may be equal to zero and fail a null check - if (bytes.len == 0) { + if (bytesSlice.len == 0) { return &[0]T{}; } - const bytesType = @TypeOf(bytes); + const bytesType = @TypeOf(bytesSlice); const alignment = comptime meta.alignment(bytesType); const castTarget = if (comptime trait.isConstPtr(bytesType)) [*]align(alignment) const T else [*]align(alignment) T; - return @ptrCast(castTarget, bytes.ptr)[0..@divExact(bytes.len, @sizeOf(T))]; + return @ptrCast(castTarget, bytesSlice.ptr)[0..@divExact(bytes.len, @sizeOf(T))]; } test "bytesAsSlice" { @@ -1520,30 +1526,59 @@ test "bytesAsSlice" { testing.expect(bigToNative(u16, slice[1]) == 0xBEEF); } +test "bytesAsSlice keeps pointer alignment" { + var bytes = [_]u8{ 0x01, 0x02, 0x03, 0x04 }; + const numbers = bytesAsSlice(u32, bytes[0..]); + comptime testing.expect(@TypeOf(numbers) == []align(@alignOf(@TypeOf(bytes))) u32); +} + +test "bytesAsSlice on a packed struct" { + const F = packed struct { + a: u8, + }; + + var b = [1]u8{9}; + var f = bytesAsSlice(F, &b); + testing.expect(f[0].a == 9); +} + +test "bytesAsSlice with specified alignment" { + var bytes align(4) = [_]u8{ + 0x33, + 0x33, + 0x33, + 0x33, + }; + const slice: []u32 = std.mem.bytesAsSlice(u32, bytes[0..]); + testing.expect(slice[0] == 0x33333333); +} + //TODO copy also is_volatile, etc. I tried to use @typeInfo, modify child type, use @Type, but ran into issues. fn SliceAsBytesReturnType(comptime sliceType: type) type { - if (comptime !trait.isSlice(sliceType)) { - @compileError("expected []T, passed " ++ @typeName(sliceType)); + if (!trait.isSlice(sliceType) and !trait.isPtrTo(.Array)(sliceType)) { + @compileError("expected []T or *[_]T, passed " ++ @typeName(sliceType)); } - const alignment = comptime meta.alignment(sliceType); + const alignment = meta.alignment(sliceType); - return if (comptime trait.isConstPtr(sliceType)) []align(alignment) const u8 else []align(alignment) u8; + return if (trait.isConstPtr(sliceType)) []align(alignment) const u8 else []align(alignment) u8; } pub fn sliceAsBytes(slice: var) SliceAsBytesReturnType(@TypeOf(slice)) { + const actualSlice = if (comptime trait.isPtrTo(.Array)(@TypeOf(slice))) slice[0..] else slice; + // let's not give an undefined pointer to @ptrCast // it may be equal to zero and fail a null check - if (slice.len == 0) { + if (actualSlice.len == 0) { return &[0]u8{}; } - const sliceType = @TypeOf(slice); + const sliceType = @TypeOf(actualSlice); const alignment = comptime meta.alignment(sliceType); const castTarget = if (comptime trait.isConstPtr(sliceType)) [*]align(alignment) const u8 else [*]align(alignment) u8; - return @ptrCast(castTarget, slice.ptr)[0 .. slice.len * @sizeOf(comptime meta.Child(sliceType))]; + return @ptrCast(castTarget, actualSlice.ptr)[0 .. actualSlice.len * @sizeOf(comptime meta.Child(sliceType))]; } test "sliceAsBytes" { @@ -1556,6 +1591,57 @@ test "sliceAsBytes" { })); } +test "sliceAsBytes packed struct at runtime and comptime" { + const Foo = packed struct { + a: u4, + b: u4, + }; + const S = struct { + fn doTheTest() void { + var foo: Foo = undefined; + var slice = sliceAsBytes(@as(*[1]Foo, &foo)[0..1]); + slice[0] = 0x13; + switch (builtin.endian) { + .Big => { + testing.expect(foo.a == 0x1); + testing.expect(foo.b == 0x3); + }, + .Little => { + testing.expect(foo.a == 0x3); + testing.expect(foo.b == 0x1); + }, + } + } + }; + S.doTheTest(); + comptime S.doTheTest(); +} + +test "sliceAsBytes and bytesAsSlice back" { + testing.expect(@sizeOf(i32) == 4); + + var big_thing_array = [_]i32{ 1, 2, 3, 4 }; + const big_thing_slice: []i32 = big_thing_array[0..]; + + const bytes = sliceAsBytes(big_thing_slice); + testing.expect(bytes.len == 4 * 4); + + bytes[4] = 0; + bytes[5] = 0; + bytes[6] = 0; + bytes[7] = 0; + testing.expect(big_thing_slice[1] == 0); + + const big_thing_again = bytesAsSlice(i32, bytes); + testing.expect(big_thing_again[2] == 3); + + big_thing_again[2] = -1; + testing.expect(bytes[8] == math.maxInt(u8)); + testing.expect(bytes[9] == math.maxInt(u8)); + testing.expect(bytes[10] == math.maxInt(u8)); + testing.expect(bytes[11] == math.maxInt(u8)); +} + fn SubArrayPtrReturnType(comptime T: type, comptime length: usize) type { if (trait.isConstPtr(T)) return *const [length]meta.Child(meta.Child(T)); diff --git a/lib/std/meta/trait.zig b/lib/std/meta/trait.zig index b1fd233ff2..b17a4a2a93 100644 --- a/lib/std/meta/trait.zig +++ b/lib/std/meta/trait.zig @@ -135,6 +135,22 @@ test "std.meta.trait.isPtrTo" { testing.expect(!isPtrTo(.Struct)(**struct {})); } +pub fn isSliceOf(comptime id: builtin.TypeId) TraitFn { + const Closure = struct { + pub fn trait(comptime T: type) bool { + if (!comptime isSlice(T)) return false; + return id == @typeId(meta.Child(T)); + } + }; + return Closure.trait; +} + +test "std.meta.trait.isSliceOf" { + testing.expect(!isSliceOf(.Struct)(struct {})); + testing.expect(isSliceOf(.Struct)([]struct {})); + testing.expect(!isSliceOf(.Struct)([][]struct {})); +} + ///////////Strait trait Fns //@TODO: diff --git a/test/compile_errors.zig b/test/compile_errors.zig index 1b32786e40..6213e8435f 100644 --- a/test/compile_errors.zig +++ b/test/compile_errors.zig @@ -4747,16 +4747,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void { "tmp.zig:1:15: error: comptime parameter not allowed in function with calling convention 'C'", }); - cases.add("convert fixed size array to slice with invalid size", - \\export fn f() void { - \\ var array: [5]u8 = undefined; - \\ var foo = @bytesToSlice(u32, &array)[0]; - \\} - , &[_][]const u8{ - "tmp.zig:3:15: error: unable to convert [5]u8 to []align(1) u32: size mismatch", - "tmp.zig:3:29: note: u32 has size 4; remaining bytes: 1", - }); - cases.add("non-pure function returns type", \\var a: u32 = 0; \\pub fn List(comptime T: type) type { diff --git a/test/runtime_safety.zig b/test/runtime_safety.zig index 2217a7f2df..e4ea7f52db 100644 --- a/test/runtime_safety.zig +++ b/test/runtime_safety.zig @@ -553,15 +553,16 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { ); cases.addRuntimeSafety("cast []u8 to bigger slice of wrong size", - \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { - \\ @import("std").os.exit(126); + \\const std = @import("std"); + \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { + \\ std.os.exit(126); \\} \\pub fn main() !void { \\ const x = widenSlice(&[_]u8{1, 2, 3, 4, 5}); \\ if (x.len == 0) return error.Whatever; \\} \\fn widenSlice(slice: []align(1) const u8) []align(1) const i32 { - \\ return @bytesToSlice(i32, slice); + \\ return std.mem.bytesAsSlice(i32, slice); \\} ); @@ -656,17 +657,18 @@ pub fn addCases(cases: *tests.CompareOutputContext) void { ); cases.addRuntimeSafety("@alignCast misaligned", - \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn { - \\ @import("std").os.exit(126); + \\const std = @import("std"); + \\pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace) noreturn { + \\ std.os.exit(126); \\} \\pub fn main() !void { \\ var array align(4) = [_]u32{0x11111111, 0x11111111}; - \\ const bytes = @sliceToBytes(array[0..]); + \\ const bytes = std.mem.sliceAsBytes(array[0..]); \\ if (foo(bytes) != 0x11111111) return error.Wrong; \\} \\fn foo(bytes: []u8) u32 { \\ const slice4 = bytes[1..5]; - \\ const int_slice = @bytesToSlice(u32, @alignCast(4, slice4)); + \\ const int_slice = std.mem.bytesAsSlice(u32, @alignCast(4, slice4)); \\ return int_slice[0]; \\} ); diff --git a/test/stage1/behavior.zig b/test/stage1/behavior.zig index ea8720d98c..6e0d4c5e22 100644 --- a/test/stage1/behavior.zig +++ b/test/stage1/behavior.zig @@ -92,7 +92,6 @@ comptime { _ = @import("behavior/shuffle.zig"); _ = @import("behavior/sizeof_and_typeof.zig"); _ = @import("behavior/slice.zig"); - _ = @import("behavior/slicetobytes.zig"); _ = @import("behavior/struct.zig"); _ = @import("behavior/struct_contains_null_ptr_itself.zig"); _ = @import("behavior/struct_contains_slice_of_itself.zig"); diff --git a/test/stage1/behavior/align.zig b/test/stage1/behavior/align.zig index c83d2379b4..5a5138d567 100644 --- a/test/stage1/behavior/align.zig +++ b/test/stage1/behavior/align.zig @@ -81,20 +81,6 @@ fn testBytesAlign(b: u8) void { expect(ptr.* == 0x33333333); } -test "specifying alignment allows slice cast" { - testBytesAlignSlice(0x33); -} -fn testBytesAlignSlice(b: u8) void { - var bytes align(4) = [_]u8{ - b, - b, - b, - b, - }; - const slice: []u32 = @bytesToSlice(u32, bytes[0..]); - expect(slice[0] == 0x33333333); -} - test "@alignCast pointers" { var x: u32 align(4) = 1; expectsOnly1(&x); diff --git a/test/stage1/behavior/async_fn.zig b/test/stage1/behavior/async_fn.zig index b04d4e2b5d..6583adec66 100644 --- a/test/stage1/behavior/async_fn.zig +++ b/test/stage1/behavior/async_fn.zig @@ -334,7 +334,7 @@ test "async fn with inferred error set" { var frame: [1]@Frame(middle) = undefined; var fn_ptr = middle; var result: @TypeOf(fn_ptr).ReturnType.ErrorSet!void = undefined; - _ = @asyncCall(@sliceToBytes(frame[0..]), &result, fn_ptr); + _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, fn_ptr); resume global_frame; std.testing.expectError(error.Fail, result); } @@ -954,7 +954,7 @@ test "@asyncCall with comptime-known function, but not awaited directly" { fn doTheTest() void { var frame: [1]@Frame(middle) = undefined; var result: @TypeOf(middle).ReturnType.ErrorSet!void = undefined; - _ = @asyncCall(@sliceToBytes(frame[0..]), &result, middle); + _ = @asyncCall(std.mem.sliceAsBytes(frame[0..]), &result, middle); resume global_frame; std.testing.expectError(error.Fail, result); } diff --git a/test/stage1/behavior/bugs/1851.zig b/test/stage1/behavior/bugs/1851.zig index f3e7393b96..d6cf17651d 100644 --- a/test/stage1/behavior/bugs/1851.zig +++ b/test/stage1/behavior/bugs/1851.zig @@ -13,7 +13,7 @@ test "allocation and looping over 3-byte integer" { x[0] = 0xFFFFFF; x[1] = 0xFFFFFF; - const bytes = @sliceToBytes(x); + const bytes = std.mem.sliceAsBytes(x); expect(@TypeOf(bytes) == []align(4) u8); expect(bytes.len == 8); diff --git a/test/stage1/behavior/cast.zig b/test/stage1/behavior/cast.zig index f393bfebb5..76d3b784ec 100644 --- a/test/stage1/behavior/cast.zig +++ b/test/stage1/behavior/cast.zig @@ -304,20 +304,6 @@ fn cast128Float(x: u128) f128 { return @bitCast(f128, x); } -test "const slice widen cast" { - const bytes align(4) = [_]u8{ - 0x12, - 0x12, - 0x12, - 0x12, - }; - - const u32_value = @bytesToSlice(u32, bytes[0..])[0]; - expect(u32_value == 0x12121212); - - expect(@bitCast(u32, bytes) == 0x12121212); -} - test "single-item pointer of array to slice and to unknown length pointer" { testCastPtrOfArrayToSliceAndPtr(); comptime testCastPtrOfArrayToSliceAndPtr(); @@ -392,12 +378,6 @@ test "comptime_int @intToFloat" { } } -test "@bytesToSlice keeps pointer alignment" { - var bytes = [_]u8{ 0x01, 0x02, 0x03, 0x04 }; - const numbers = @bytesToSlice(u32, bytes[0..]); - comptime expect(@TypeOf(numbers) == []align(@alignOf(@TypeOf(bytes))) u32); -} - test "@intCast i32 to u7" { var x: u128 = maxInt(u128); var y: i32 = 120; diff --git a/test/stage1/behavior/eval.zig b/test/stage1/behavior/eval.zig index ed81fae791..099434a869 100644 --- a/test/stage1/behavior/eval.zig +++ b/test/stage1/behavior/eval.zig @@ -711,16 +711,6 @@ test "bit shift a u1" { expect(y == 1); } -test "@bytesToslice on a packed struct" { - const F = packed struct { - a: u8, - }; - - var b = [1]u8{9}; - var f = @bytesToSlice(F, &b); - expect(f[0].a == 9); -} - test "comptime pointer cast array and then slice" { const array = [_]u8{ 1, 2, 3, 4, 5, 6, 7, 8 }; diff --git a/test/stage1/behavior/misc.zig b/test/stage1/behavior/misc.zig index c77b49f03a..a3a008c1d2 100644 --- a/test/stage1/behavior/misc.zig +++ b/test/stage1/behavior/misc.zig @@ -3,7 +3,6 @@ const expect = std.testing.expect; const expectEqualSlices = std.testing.expectEqualSlices; const mem = std.mem; const builtin = @import("builtin"); -const maxInt = std.math.maxInt; // normal comment @@ -377,26 +376,6 @@ test "string concatenation" { expect(b[len] == 0); } -test "cast slice to u8 slice" { - expect(@sizeOf(i32) == 4); - var big_thing_array = [_]i32{ 1, 2, 3, 4 }; - const big_thing_slice: []i32 = big_thing_array[0..]; - const bytes = @sliceToBytes(big_thing_slice); - expect(bytes.len == 4 * 4); - bytes[4] = 0; - bytes[5] = 0; - bytes[6] = 0; - bytes[7] = 0; - expect(big_thing_slice[1] == 0); - const big_thing_again = @bytesToSlice(i32, bytes); - expect(big_thing_again[2] == 3); - big_thing_again[2] = -1; - expect(bytes[8] == maxInt(u8)); - expect(bytes[9] == maxInt(u8)); - expect(bytes[10] == maxInt(u8)); - expect(bytes[11] == maxInt(u8)); -} - test "pointer to void return type" { testPointerToVoidReturnType() catch unreachable; } diff --git a/test/stage1/behavior/slicetobytes.zig b/test/stage1/behavior/slicetobytes.zig deleted file mode 100644 index c0eb4a8f9b..0000000000 --- a/test/stage1/behavior/slicetobytes.zig +++ /dev/null @@ -1,29 +0,0 @@ -const std = @import("std"); -const builtin = @import("builtin"); -const expect = std.testing.expect; - -test "@sliceToBytes packed struct at runtime and comptime" { - const Foo = packed struct { - a: u4, - b: u4, - }; - const S = struct { - fn doTheTest() void { - var foo: Foo = undefined; - var slice = @sliceToBytes(@as(*[1]Foo, &foo)[0..1]); - slice[0] = 0x13; - switch (builtin.endian) { - builtin.Endian.Big => { - expect(foo.a == 0x1); - expect(foo.b == 0x3); - }, - builtin.Endian.Little => { - expect(foo.a == 0x3); - expect(foo.b == 0x1); - }, - } - } - }; - S.doTheTest(); - comptime S.doTheTest(); -} diff --git a/test/stage1/behavior/struct.zig b/test/stage1/behavior/struct.zig index 8e5ab29db3..ecec7fe5d6 100644 --- a/test/stage1/behavior/struct.zig +++ b/test/stage1/behavior/struct.zig @@ -315,7 +315,7 @@ test "packed array 24bits" { var bytes = [_]u8{0} ** (@sizeOf(FooArray24Bits) + 1); bytes[bytes.len - 1] = 0xaa; - const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0]; + const ptr = &std.mem.bytesAsSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0]; expect(ptr.a == 0); expect(ptr.b[0].field == 0); expect(ptr.b[1].field == 0); @@ -364,7 +364,7 @@ test "aligned array of packed struct" { } var bytes = [_]u8{0xbb} ** @sizeOf(FooArrayOfAligned); - const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0]; + const ptr = &std.mem.bytesAsSlice(FooArrayOfAligned, bytes[0..])[0]; expect(ptr.a[0].a == 0xbb); expect(ptr.a[0].b == 0xbb); From 9c35f680f73538b8c36121ff938cc0b19eadbb42 Mon Sep 17 00:00:00 2001 From: xackus <14938807+xackus@users.noreply.github.com> Date: Sun, 23 Feb 2020 19:03:55 +0100 Subject: [PATCH 4/4] nuke @bytesToSlice, @sliceToBytes in stage1 --- src/all_types.hpp | 28 ----- src/codegen.cpp | 74 -------------- src/ir.cpp | 256 ---------------------------------------------- src/ir_print.cpp | 36 ------- 4 files changed, 394 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index c1348d3abd..117a0004f0 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -1750,8 +1750,6 @@ enum BuiltinFnId { BuiltinFnIdIntCast, BuiltinFnIdFloatCast, BuiltinFnIdErrSetCast, - BuiltinFnIdToBytes, - BuiltinFnIdFromBytes, BuiltinFnIdIntToFloat, BuiltinFnIdFloatToInt, BuiltinFnIdBoolToInt, @@ -1821,7 +1819,6 @@ enum PanicMsgId { PanicMsgIdDivisionByZero, PanicMsgIdRemainderDivisionByZero, PanicMsgIdExactDivisionRemainder, - PanicMsgIdSliceWidenRemainder, PanicMsgIdUnwrapOptionalFail, PanicMsgIdInvalidErrorCode, PanicMsgIdIncorrectAlignment, @@ -2699,8 +2696,6 @@ enum IrInstSrcId { IrInstSrcIdSaveErrRetAddr, IrInstSrcIdAddImplicitReturnType, IrInstSrcIdErrSetCast, - IrInstSrcIdToBytes, - IrInstSrcIdFromBytes, IrInstSrcIdCheckRuntimeScope, IrInstSrcIdHasDecl, IrInstSrcIdUndeclaredIdent, @@ -2739,7 +2734,6 @@ enum IrInstGenId { IrInstGenIdCall, IrInstGenIdReturn, IrInstGenIdCast, - IrInstGenIdResizeSlice, IrInstGenIdUnreachable, IrInstGenIdAsm, IrInstGenIdTestNonNull, @@ -3271,13 +3265,6 @@ struct IrInstGenCast { CastOp cast_op; }; -struct IrInstGenResizeSlice { - IrInstGen base; - - IrInstGen *operand; - IrInstGen *result_loc; -}; - struct IrInstSrcContainerInitList { IrInstSrc base; @@ -3629,21 +3616,6 @@ struct IrInstSrcErrSetCast { IrInstSrc *target; }; -struct IrInstSrcToBytes { - IrInstSrc base; - - IrInstSrc *target; - ResultLoc *result_loc; -}; - -struct IrInstSrcFromBytes { - IrInstSrc base; - - IrInstSrc *dest_child_type; - IrInstSrc *target; - ResultLoc *result_loc; -}; - struct IrInstSrcIntToFloat { IrInstSrc base; diff --git a/src/codegen.cpp b/src/codegen.cpp index a28d2d469d..c193b4e443 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -972,8 +972,6 @@ static Buf *panic_msg_buf(PanicMsgId msg_id) { return buf_create_from_str("remainder division by zero or negative value"); case PanicMsgIdExactDivisionRemainder: return buf_create_from_str("exact division produced remainder"); - case PanicMsgIdSliceWidenRemainder: - return buf_create_from_str("slice widening size mismatch"); case PanicMsgIdUnwrapOptionalFail: return buf_create_from_str("attempt to unwrap null"); case PanicMsgIdUnreachable: @@ -3085,74 +3083,6 @@ static void add_error_range_check(CodeGen *g, ZigType *err_set_type, ZigType *in } } -static LLVMValueRef ir_render_resize_slice(CodeGen *g, IrExecutableGen *executable, - IrInstGenResizeSlice *instruction) -{ - ZigType *actual_type = instruction->operand->value->type; - ZigType *wanted_type = instruction->base.value->type; - LLVMValueRef expr_val = ir_llvm_value(g, instruction->operand); - assert(expr_val); - - LLVMValueRef result_loc = ir_llvm_value(g, instruction->result_loc); - assert(wanted_type->id == ZigTypeIdStruct); - assert(wanted_type->data.structure.special == StructSpecialSlice); - assert(actual_type->id == ZigTypeIdStruct); - assert(actual_type->data.structure.special == StructSpecialSlice); - - ZigType *actual_pointer_type = actual_type->data.structure.fields[0]->type_entry; - ZigType *actual_child_type = actual_pointer_type->data.pointer.child_type; - ZigType *wanted_pointer_type = wanted_type->data.structure.fields[0]->type_entry; - ZigType *wanted_child_type = wanted_pointer_type->data.pointer.child_type; - - - size_t actual_ptr_index = actual_type->data.structure.fields[slice_ptr_index]->gen_index; - size_t actual_len_index = actual_type->data.structure.fields[slice_len_index]->gen_index; - size_t wanted_ptr_index = wanted_type->data.structure.fields[slice_ptr_index]->gen_index; - size_t wanted_len_index = wanted_type->data.structure.fields[slice_len_index]->gen_index; - - LLVMValueRef src_ptr_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_ptr_index, ""); - LLVMValueRef src_ptr = gen_load_untyped(g, src_ptr_ptr, 0, false, ""); - LLVMValueRef src_ptr_casted = LLVMBuildBitCast(g->builder, src_ptr, - get_llvm_type(g, wanted_type->data.structure.fields[0]->type_entry), ""); - LLVMValueRef dest_ptr_ptr = LLVMBuildStructGEP(g->builder, result_loc, - (unsigned)wanted_ptr_index, ""); - gen_store_untyped(g, src_ptr_casted, dest_ptr_ptr, 0, false); - - LLVMValueRef src_len_ptr = LLVMBuildStructGEP(g->builder, expr_val, (unsigned)actual_len_index, ""); - LLVMValueRef src_len = gen_load_untyped(g, src_len_ptr, 0, false, ""); - uint64_t src_size = type_size(g, actual_child_type); - uint64_t dest_size = type_size(g, wanted_child_type); - - LLVMValueRef new_len; - if (dest_size == 1) { - LLVMValueRef src_size_val = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, src_size, false); - new_len = LLVMBuildMul(g->builder, src_len, src_size_val, ""); - } else if (src_size == 1) { - LLVMValueRef dest_size_val = LLVMConstInt(g->builtin_types.entry_usize->llvm_type, dest_size, false); - if (ir_want_runtime_safety(g, &instruction->base)) { - LLVMValueRef remainder_val = LLVMBuildURem(g->builder, src_len, dest_size_val, ""); - LLVMValueRef zero = LLVMConstNull(g->builtin_types.entry_usize->llvm_type); - LLVMValueRef ok_bit = LLVMBuildICmp(g->builder, LLVMIntEQ, remainder_val, zero, ""); - LLVMBasicBlockRef ok_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenOk"); - LLVMBasicBlockRef fail_block = LLVMAppendBasicBlock(g->cur_fn_val, "SliceWidenFail"); - LLVMBuildCondBr(g->builder, ok_bit, ok_block, fail_block); - - LLVMPositionBuilderAtEnd(g->builder, fail_block); - gen_safety_crash(g, PanicMsgIdSliceWidenRemainder); - - LLVMPositionBuilderAtEnd(g->builder, ok_block); - } - new_len = LLVMBuildExactUDiv(g->builder, src_len, dest_size_val, ""); - } else { - zig_unreachable(); - } - - LLVMValueRef dest_len_ptr = LLVMBuildStructGEP(g->builder, result_loc, (unsigned)wanted_len_index, ""); - gen_store_untyped(g, new_len, dest_len_ptr, 0, false); - - return result_loc; -} - static LLVMValueRef ir_render_cast(CodeGen *g, IrExecutableGen *executable, IrInstGenCast *cast_instruction) { @@ -6485,8 +6415,6 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutableGen *executabl return ir_render_assert_zero(g, executable, (IrInstGenAssertZero *)instruction); case IrInstGenIdAssertNonNull: return ir_render_assert_non_null(g, executable, (IrInstGenAssertNonNull *)instruction); - case IrInstGenIdResizeSlice: - return ir_render_resize_slice(g, executable, (IrInstGenResizeSlice *)instruction); case IrInstGenIdPtrOfArrayToSlice: return ir_render_ptr_of_array_to_slice(g, executable, (IrInstGenPtrOfArrayToSlice *)instruction); case IrInstGenIdSuspendBegin: @@ -8317,8 +8245,6 @@ static void define_builtin_fns(CodeGen *g) { create_builtin_fn(g, BuiltinFnIdAtomicLoad, "atomicLoad", 3); create_builtin_fn(g, BuiltinFnIdAtomicStore, "atomicStore", 4); create_builtin_fn(g, BuiltinFnIdErrSetCast, "errSetCast", 2); - create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1); - create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2); create_builtin_fn(g, BuiltinFnIdThis, "This", 0); create_builtin_fn(g, BuiltinFnIdHasDecl, "hasDecl", 2); create_builtin_fn(g, BuiltinFnIdUnionInit, "unionInit", 3); diff --git a/src/ir.cpp b/src/ir.cpp index 5f50586f72..80fef04496 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -383,10 +383,6 @@ static void destroy_instruction_src(IrInstSrc *inst) { return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdErrSetCast: return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdFromBytes: - return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdToBytes: - return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdIntToFloat: return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdFloatToInt: @@ -707,8 +703,6 @@ void destroy_instruction_gen(IrInstGen *inst) { return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdAssertNonNull: return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstGenIdResizeSlice: - return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdAlloca: return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstGenIdSuspendBegin: @@ -1563,14 +1557,6 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrSetCast *) { return IrInstSrcIdErrSetCast; } -static constexpr IrInstSrcId ir_inst_id(IrInstSrcToBytes *) { - return IrInstSrcIdToBytes; -} - -static constexpr IrInstSrcId ir_inst_id(IrInstSrcFromBytes *) { - return IrInstSrcIdFromBytes; -} - static constexpr IrInstSrcId ir_inst_id(IrInstSrcCheckRuntimeScope *) { return IrInstSrcIdCheckRuntimeScope; } @@ -1700,10 +1686,6 @@ static constexpr IrInstGenId ir_inst_id(IrInstGenCast *) { return IrInstGenIdCast; } -static constexpr IrInstGenId ir_inst_id(IrInstGenResizeSlice *) { - return IrInstGenIdResizeSlice; -} - static constexpr IrInstGenId ir_inst_id(IrInstGenUnreachable *) { return IrInstGenIdUnreachable; } @@ -2759,21 +2741,6 @@ static IrInstGen *ir_build_var_decl_gen(IrAnalyze *ira, IrInst *source_instructi return &inst->base; } -static IrInstGen *ir_build_resize_slice(IrAnalyze *ira, IrInst *source_instruction, - IrInstGen *operand, ZigType *ty, IrInstGen *result_loc) -{ - IrInstGenResizeSlice *instruction = ir_build_inst_gen(&ira->new_irb, - source_instruction->scope, source_instruction->source_node); - instruction->base.value->type = ty; - instruction->operand = operand; - instruction->result_loc = result_loc; - - ir_ref_inst_gen(operand, ira->new_irb.current_basic_block); - if (result_loc != nullptr) ir_ref_inst_gen(result_loc, ira->new_irb.current_basic_block); - - return &instruction->base; -} - static IrInstSrc *ir_build_export(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *target, IrInstSrc *options) { @@ -3540,32 +3507,6 @@ static IrInstSrc *ir_build_err_set_cast(IrBuilderSrc *irb, Scope *scope, AstNode return &instruction->base; } -static IrInstSrc *ir_build_to_bytes(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *target, - ResultLoc *result_loc) -{ - IrInstSrcToBytes *instruction = ir_build_instruction(irb, scope, source_node); - instruction->target = target; - instruction->result_loc = result_loc; - - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - -static IrInstSrc *ir_build_from_bytes(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, - IrInstSrc *dest_child_type, IrInstSrc *target, ResultLoc *result_loc) -{ - IrInstSrcFromBytes *instruction = ir_build_instruction(irb, scope, source_node); - instruction->dest_child_type = dest_child_type; - instruction->target = target; - instruction->result_loc = result_loc; - - ir_ref_instruction(dest_child_type, irb->current_basic_block); - ir_ref_instruction(target, irb->current_basic_block); - - return &instruction->base; -} - static IrInstSrc *ir_build_int_to_float(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *dest_type, IrInstSrc *target) { @@ -6597,31 +6538,6 @@ static IrInstSrc *ir_gen_builtin_fn_call(IrBuilderSrc *irb, Scope *scope, AstNod IrInstSrc *result = ir_build_err_set_cast(irb, scope, node, arg0_value, arg1_value); return ir_lval_wrap(irb, scope, result, lval, result_loc); } - case BuiltinFnIdFromBytes: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - AstNode *arg1_node = node->data.fn_call_expr.params.at(1); - IrInstSrc *arg1_value = ir_gen_node(irb, arg1_node, scope); - if (arg1_value == irb->codegen->invalid_inst_src) - return arg1_value; - - IrInstSrc *result = ir_build_from_bytes(irb, scope, node, arg0_value, arg1_value, result_loc); - return ir_lval_wrap(irb, scope, result, lval, result_loc); - } - case BuiltinFnIdToBytes: - { - AstNode *arg0_node = node->data.fn_call_expr.params.at(0); - IrInstSrc *arg0_value = ir_gen_node(irb, arg0_node, scope); - if (arg0_value == irb->codegen->invalid_inst_src) - return arg0_value; - - IrInstSrc *result = ir_build_to_bytes(irb, scope, node, arg0_value, result_loc); - return ir_lval_wrap(irb, scope, result, lval, result_loc); - } case BuiltinFnIdIntToFloat: { AstNode *arg0_node = node->data.fn_call_expr.params.at(0); @@ -25489,171 +25405,6 @@ static IrInstGen *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInstSrcE return ir_analyze_err_set_cast(ira, &instruction->base.base, target, dest_type); } -static IrInstGen *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstSrcFromBytes *instruction) { - Error err; - - ZigType *dest_child_type = ir_resolve_type(ira, instruction->dest_child_type->child); - if (type_is_invalid(dest_child_type)) - return ira->codegen->invalid_inst_gen; - - IrInstGen *target = instruction->target->child; - if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_inst_gen; - - bool src_ptr_const; - bool src_ptr_volatile; - uint32_t src_ptr_align; - if (target->value->type->id == ZigTypeIdPointer) { - src_ptr_const = target->value->type->data.pointer.is_const; - src_ptr_volatile = target->value->type->data.pointer.is_volatile; - - if ((err = resolve_ptr_align(ira, target->value->type, &src_ptr_align))) - return ira->codegen->invalid_inst_gen; - } else if (is_slice(target->value->type)) { - ZigType *src_ptr_type = target->value->type->data.structure.fields[slice_ptr_index]->type_entry; - src_ptr_const = src_ptr_type->data.pointer.is_const; - src_ptr_volatile = src_ptr_type->data.pointer.is_volatile; - - if ((err = resolve_ptr_align(ira, src_ptr_type, &src_ptr_align))) - return ira->codegen->invalid_inst_gen; - } else { - src_ptr_const = true; - src_ptr_volatile = false; - - if ((err = type_resolve(ira->codegen, target->value->type, ResolveStatusAlignmentKnown))) - return ira->codegen->invalid_inst_gen; - - src_ptr_align = get_abi_alignment(ira->codegen, target->value->type); - } - - if (src_ptr_align != 0) { - if ((err = type_resolve(ira->codegen, dest_child_type, ResolveStatusAlignmentKnown))) - return ira->codegen->invalid_inst_gen; - } - - ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_child_type, - src_ptr_const, src_ptr_volatile, PtrLenUnknown, - src_ptr_align, 0, 0, false); - ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type); - - ZigType *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8, - src_ptr_const, src_ptr_volatile, PtrLenUnknown, - src_ptr_align, 0, 0, false); - ZigType *u8_slice = get_slice_type(ira->codegen, u8_ptr); - - IrInstGen *casted_value = ir_implicit_cast2(ira, &instruction->target->base, target, u8_slice); - if (type_is_invalid(casted_value->value->type)) - return ira->codegen->invalid_inst_gen; - - bool have_known_len = false; - uint64_t known_len; - - if (instr_is_comptime(casted_value)) { - ZigValue *val = ir_resolve_const(ira, casted_value, UndefBad); - if (!val) - return ira->codegen->invalid_inst_gen; - - ZigValue *len_val = val->data.x_struct.fields[slice_len_index]; - if (value_is_comptime(len_val)) { - known_len = bigint_as_u64(&len_val->data.x_bigint); - have_known_len = true; - } - } - - IrInstGen *result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc, - dest_slice_type, nullptr, true, true); - if (result_loc != nullptr && (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable)) { - return result_loc; - } - - if (target->value->type->id == ZigTypeIdPointer && - target->value->type->data.pointer.ptr_len == PtrLenSingle && - target->value->type->data.pointer.child_type->id == ZigTypeIdArray) - { - known_len = target->value->type->data.pointer.child_type->data.array.len; - have_known_len = true; - } else if (casted_value->value->data.rh_slice.id == RuntimeHintSliceIdLen) { - known_len = casted_value->value->data.rh_slice.len; - have_known_len = true; - } - - if (have_known_len) { - if ((err = type_resolve(ira->codegen, dest_child_type, ResolveStatusSizeKnown))) - return ira->codegen->invalid_inst_gen; - uint64_t child_type_size = type_size(ira->codegen, dest_child_type); - uint64_t remainder = known_len % child_type_size; - if (remainder != 0) { - ErrorMsg *msg = ir_add_error(ira, &instruction->base.base, - buf_sprintf("unable to convert [%" ZIG_PRI_u64 "]u8 to %s: size mismatch", - known_len, buf_ptr(&dest_slice_type->name))); - add_error_note(ira->codegen, msg, instruction->dest_child_type->base.source_node, - buf_sprintf("%s has size %" ZIG_PRI_u64 "; remaining bytes: %" ZIG_PRI_u64, - buf_ptr(&dest_child_type->name), child_type_size, remainder)); - return ira->codegen->invalid_inst_gen; - } - } - - return ir_build_resize_slice(ira, &instruction->base.base, casted_value, dest_slice_type, result_loc); -} - -static IrInstGen *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstSrcToBytes *instruction) { - Error err; - - IrInstGen *target = instruction->target->child; - if (type_is_invalid(target->value->type)) - return ira->codegen->invalid_inst_gen; - - if (!is_slice(target->value->type)) { - ir_add_error(ira, &instruction->target->base, - buf_sprintf("expected slice, found '%s'", buf_ptr(&target->value->type->name))); - return ira->codegen->invalid_inst_gen; - } - - ZigType *src_ptr_type = target->value->type->data.structure.fields[slice_ptr_index]->type_entry; - - uint32_t alignment; - if ((err = resolve_ptr_align(ira, src_ptr_type, &alignment))) - return ira->codegen->invalid_inst_gen; - - ZigType *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8, - src_ptr_type->data.pointer.is_const, src_ptr_type->data.pointer.is_volatile, PtrLenUnknown, - alignment, 0, 0, false); - ZigType *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type); - - if (instr_is_comptime(target)) { - ZigValue *target_val = ir_resolve_const(ira, target, UndefBad); - if (target_val == nullptr) - return ira->codegen->invalid_inst_gen; - - IrInstGen *result = ir_const(ira, &instruction->base.base, dest_slice_type); - result->value->data.x_struct.fields = alloc_const_vals_ptrs(ira->codegen, 2); - - ZigValue *ptr_val = result->value->data.x_struct.fields[slice_ptr_index]; - ZigValue *target_ptr_val = target_val->data.x_struct.fields[slice_ptr_index]; - copy_const_val(ira->codegen, ptr_val, target_ptr_val); - ptr_val->type = dest_ptr_type; - - ZigValue *len_val = result->value->data.x_struct.fields[slice_len_index]; - len_val->special = ConstValSpecialStatic; - len_val->type = ira->codegen->builtin_types.entry_usize; - ZigValue *target_len_val = target_val->data.x_struct.fields[slice_len_index]; - ZigType *elem_type = src_ptr_type->data.pointer.child_type; - BigInt elem_size_bigint; - bigint_init_unsigned(&elem_size_bigint, type_size(ira->codegen, elem_type)); - bigint_mul(&len_val->data.x_bigint, &target_len_val->data.x_bigint, &elem_size_bigint); - - return result; - } - - IrInstGen *result_loc = ir_resolve_result(ira, &instruction->base.base, instruction->result_loc, - dest_slice_type, nullptr, true, true); - if (type_is_invalid(result_loc->value->type) || result_loc->value->type->id == ZigTypeIdUnreachable) { - return result_loc; - } - - return ir_build_resize_slice(ira, &instruction->base.base, target, dest_slice_type, result_loc); -} - static Error resolve_ptr_align(IrAnalyze *ira, ZigType *ty, uint32_t *result_align) { Error err; @@ -29783,10 +29534,6 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc return ir_analyze_instruction_float_cast(ira, (IrInstSrcFloatCast *)instruction); case IrInstSrcIdErrSetCast: return ir_analyze_instruction_err_set_cast(ira, (IrInstSrcErrSetCast *)instruction); - case IrInstSrcIdFromBytes: - return ir_analyze_instruction_from_bytes(ira, (IrInstSrcFromBytes *)instruction); - case IrInstSrcIdToBytes: - return ir_analyze_instruction_to_bytes(ira, (IrInstSrcToBytes *)instruction); case IrInstSrcIdIntToFloat: return ir_analyze_instruction_int_to_float(ira, (IrInstSrcIntToFloat *)instruction); case IrInstSrcIdFloatToInt: @@ -30113,7 +29860,6 @@ bool ir_inst_gen_has_side_effects(IrInstGen *instruction) { case IrInstGenIdCmpxchg: case IrInstGenIdAssertZero: case IrInstGenIdAssertNonNull: - case IrInstGenIdResizeSlice: case IrInstGenIdPtrOfArrayToSlice: case IrInstGenIdSlice: case IrInstGenIdOptionalWrap: @@ -30339,8 +30085,6 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) { case IrInstSrcIdIntToFloat: case IrInstSrcIdFloatToInt: case IrInstSrcIdBoolToInt: - case IrInstSrcIdFromBytes: - case IrInstSrcIdToBytes: case IrInstSrcIdEnumToInt: case IrInstSrcIdHasDecl: case IrInstSrcIdAlloca: diff --git a/src/ir_print.cpp b/src/ir_print.cpp index c0a127dd16..6d04db6168 100644 --- a/src/ir_print.cpp +++ b/src/ir_print.cpp @@ -307,10 +307,6 @@ const char* ir_inst_src_type_str(IrInstSrcId id) { return "SrcAddImplicitReturnType"; case IrInstSrcIdErrSetCast: return "SrcErrSetCast"; - case IrInstSrcIdToBytes: - return "SrcToBytes"; - case IrInstSrcIdFromBytes: - return "SrcFromBytes"; case IrInstSrcIdCheckRuntimeScope: return "SrcCheckRuntimeScope"; case IrInstSrcIdHasDecl: @@ -383,8 +379,6 @@ const char* ir_inst_gen_type_str(IrInstGenId id) { return "GenReturn"; case IrInstGenIdCast: return "GenCast"; - case IrInstGenIdResizeSlice: - return "GenResizeSlice"; case IrInstGenIdUnreachable: return "GenUnreachable"; case IrInstGenIdAsm: @@ -1644,20 +1638,6 @@ static void ir_print_err_set_cast(IrPrintSrc *irp, IrInstSrcErrSetCast *instruct fprintf(irp->f, ")"); } -static void ir_print_from_bytes(IrPrintSrc *irp, IrInstSrcFromBytes *instruction) { - fprintf(irp->f, "@bytesToSlice("); - ir_print_other_inst_src(irp, instruction->dest_child_type); - fprintf(irp->f, ", "); - ir_print_other_inst_src(irp, instruction->target); - fprintf(irp->f, ")"); -} - -static void ir_print_to_bytes(IrPrintSrc *irp, IrInstSrcToBytes *instruction) { - fprintf(irp->f, "@sliceToBytes("); - ir_print_other_inst_src(irp, instruction->target); - fprintf(irp->f, ")"); -} - static void ir_print_int_to_float(IrPrintSrc *irp, IrInstSrcIntToFloat *instruction) { fprintf(irp->f, "@intToFloat("); ir_print_other_inst_src(irp, instruction->dest_type); @@ -2142,13 +2122,6 @@ static void ir_print_assert_non_null(IrPrintGen *irp, IrInstGenAssertNonNull *in fprintf(irp->f, ")"); } -static void ir_print_resize_slice(IrPrintGen *irp, IrInstGenResizeSlice *instruction) { - fprintf(irp->f, "@resizeSlice("); - ir_print_other_inst_gen(irp, instruction->operand); - fprintf(irp->f, ")result="); - ir_print_other_inst_gen(irp, instruction->result_loc); -} - static void ir_print_alloca_src(IrPrintSrc *irp, IrInstSrcAlloca *instruction) { fprintf(irp->f, "Alloca(align="); ir_print_other_inst_src(irp, instruction->align); @@ -2793,12 +2766,6 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai case IrInstSrcIdErrSetCast: ir_print_err_set_cast(irp, (IrInstSrcErrSetCast *)instruction); break; - case IrInstSrcIdFromBytes: - ir_print_from_bytes(irp, (IrInstSrcFromBytes *)instruction); - break; - case IrInstSrcIdToBytes: - ir_print_to_bytes(irp, (IrInstSrcToBytes *)instruction); - break; case IrInstSrcIdIntToFloat: ir_print_int_to_float(irp, (IrInstSrcIntToFloat *)instruction); break; @@ -3273,9 +3240,6 @@ static void ir_print_inst_gen(IrPrintGen *irp, IrInstGen *instruction, bool trai case IrInstGenIdAssertNonNull: ir_print_assert_non_null(irp, (IrInstGenAssertNonNull *)instruction); break; - case IrInstGenIdResizeSlice: - ir_print_resize_slice(irp, (IrInstGenResizeSlice *)instruction); - break; case IrInstGenIdAlloca: ir_print_alloca_gen(irp, (IrInstGenAlloca *)instruction); break;