authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-11 15:16:50-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-09-11 15:16:50-04:00
log7dd3c3814de0caf808bc112aa07044cdd8bba135
tree3ed6db0680f013c496535d447261462129454975
parentdd1338b0e6280b10b9b62ca73bf9ece34bd8524e
signaturelock-open Commit is signed but in an unrecognized format.

fix incorrect error union const value generation

closes #1442 zig needed to insert explicit padding into this structure before it got bitcasted.

5 files changed, 73 insertions(+), 28 deletions(-)

src/analyze.cpp+13-2
...@@ -5882,12 +5882,23 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {...@@ -5882,12 +5882,23 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
5882 }5882 }
5883 case ZigTypeIdErrorUnion:5883 case ZigTypeIdErrorUnion:
5884 {5884 {
5885 buf_appendf(buf, "(error union %s constant)", buf_ptr(&type_entry->name));5885 buf_appendf(buf, "%s(", buf_ptr(&type_entry->name));
5886 if (const_val->data.x_err_union.err == nullptr) {
5887 render_const_value(g, buf, const_val->data.x_err_union.payload);
5888 } else {
5889 buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name),
5890 buf_ptr(&const_val->data.x_err_union.err->name));
5891 }
5892 buf_appendf(buf, ")");
5886 return;5893 return;
5887 }5894 }
5888 case ZigTypeIdUnion:5895 case ZigTypeIdUnion:
5889 {5896 {
5890 buf_appendf(buf, "(union %s constant)", buf_ptr(&type_entry->name));5897 uint64_t tag = bigint_as_unsigned(&const_val->data.x_union.tag);
5898 TypeUnionField *field = &type_entry->data.unionation.fields[tag];
5899 buf_appendf(buf, "%s { .%s = ", buf_ptr(&type_entry->name), buf_ptr(field->name));
5900 render_const_value(g, buf, const_val->data.x_union.payload);
5901 buf_append_str(buf, "}");
5891 return;5902 return;
5892 }5903 }
5893 case ZigTypeIdErrorSet:5904 case ZigTypeIdErrorSet:
src/codegen.cpp+29-9
...@@ -5870,13 +5870,17 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5870,13 +5870,17 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
58705870
5871 if (make_unnamed_struct) {5871 if (make_unnamed_struct) {
5872 LLVMValueRef result = LLVMConstStruct(fields, 2, false);5872 LLVMValueRef result = LLVMConstStruct(fields, 2, false);
5873 size_t expected_sz = LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);5873 uint64_t last_field_offset = LLVMOffsetOfElement(g->target_data_ref, LLVMTypeOf(result), 1);
5874 size_t actual_sz = LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(result));5874 uint64_t end_offset = last_field_offset +
5875 if (actual_sz < expected_sz) {5875 LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(fields[1]));
5876 unsigned pad_sz = expected_sz - actual_sz;5876 uint64_t expected_sz = LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
5877 unsigned pad_sz = expected_sz - end_offset;
5878 if (pad_sz != 0) {
5877 fields[2] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), pad_sz));5879 fields[2] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), pad_sz));
5878 result = LLVMConstStruct(fields, 3, false);5880 result = LLVMConstStruct(fields, 3, false);
5879 }5881 }
5882 uint64_t actual_sz = LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(result));
5883 assert(actual_sz == expected_sz);
5880 return result;5884 return result;
5881 } else {5885 } else {
5882 return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);5886 return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);
...@@ -5917,13 +5921,29 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c...@@ -5917,13 +5921,29 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
5917 err_payload_value = gen_const_val(g, payload_val, "");5921 err_payload_value = gen_const_val(g, payload_val, "");
5918 make_unnamed_struct = is_llvm_value_unnamed_type(payload_val->type, err_payload_value);5922 make_unnamed_struct = is_llvm_value_unnamed_type(payload_val->type, err_payload_value);
5919 }5923 }
5920 LLVMValueRef fields[] = {
5921 err_tag_value,
5922 err_payload_value,
5923 };
5924 if (make_unnamed_struct) {5924 if (make_unnamed_struct) {
5925 return LLVMConstStruct(fields, 2, false);5925 uint64_t payload_off = LLVMOffsetOfElement(g->target_data_ref, type_entry->type_ref, 1);
5926 uint64_t err_sz = LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(err_tag_value));
5927 unsigned pad_sz = payload_off - err_sz;
5928 if (pad_sz == 0) {
5929 LLVMValueRef fields[] = {
5930 err_tag_value,
5931 err_payload_value,
5932 };
5933 return LLVMConstStruct(fields, 2, false);
5934 } else {
5935 LLVMValueRef fields[] = {
5936 err_tag_value,
5937 LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), pad_sz)),
5938 err_payload_value,
5939 };
5940 return LLVMConstStruct(fields, 3, false);
5941 }
5926 } else {5942 } else {
5943 LLVMValueRef fields[] = {
5944 err_tag_value,
5945 err_payload_value,
5946 };
5927 return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);5947 return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);
5928 }5948 }
5929 }5949 }
std/os/index.zig+19-17
...@@ -343,23 +343,25 @@ pub fn posixWrite(fd: i32, bytes: []const u8) !void {...@@ -343,23 +343,25 @@ pub fn posixWrite(fd: i32, bytes: []const u8) !void {
343 const amt_to_write = math.min(bytes.len - index, usize(max_bytes_len));343 const amt_to_write = math.min(bytes.len - index, usize(max_bytes_len));
344 const rc = posix.write(fd, bytes.ptr + index, amt_to_write);344 const rc = posix.write(fd, bytes.ptr + index, amt_to_write);
345 const write_err = posix.getErrno(rc);345 const write_err = posix.getErrno(rc);
346 if (write_err > 0) {346 switch (write_err) {
347 return switch (write_err) {347 0 => {
348 posix.EINTR => continue,348 index += rc;
349 posix.EINVAL, posix.EFAULT => unreachable,349 continue;
350 posix.EAGAIN => PosixWriteError.WouldBlock,350 },
351 posix.EBADF => PosixWriteError.FileClosed,351 posix.EINTR => continue,
352 posix.EDESTADDRREQ => PosixWriteError.DestinationAddressRequired,352 posix.EINVAL => unreachable,
353 posix.EDQUOT => PosixWriteError.DiskQuota,353 posix.EFAULT => unreachable,
354 posix.EFBIG => PosixWriteError.FileTooBig,354 posix.EAGAIN => return PosixWriteError.WouldBlock,
355 posix.EIO => PosixWriteError.InputOutput,355 posix.EBADF => return PosixWriteError.FileClosed,
356 posix.ENOSPC => PosixWriteError.NoSpaceLeft,356 posix.EDESTADDRREQ => return PosixWriteError.DestinationAddressRequired,
357 posix.EPERM => PosixWriteError.AccessDenied,357 posix.EDQUOT => return PosixWriteError.DiskQuota,
358 posix.EPIPE => PosixWriteError.BrokenPipe,358 posix.EFBIG => return PosixWriteError.FileTooBig,
359 else => unexpectedErrorPosix(write_err),359 posix.EIO => return PosixWriteError.InputOutput,
360 };360 posix.ENOSPC => return PosixWriteError.NoSpaceLeft,
361 posix.EPERM => return PosixWriteError.AccessDenied,
362 posix.EPIPE => return PosixWriteError.BrokenPipe,
363 else => return unexpectedErrorPosix(write_err),
361 }364 }
362 index += rc;
363 }365 }
364}366}
365367
...@@ -1614,7 +1616,7 @@ pub const Dir = struct {...@@ -1614,7 +1616,7 @@ pub const Dir = struct {
1614 return null;1616 return null;
1615 }1617 }
1616 const name_utf16le = mem.toSlice(u16, self.handle.find_file_data.cFileName[0..].ptr);1618 const name_utf16le = mem.toSlice(u16, self.handle.find_file_data.cFileName[0..].ptr);
1617 if (mem.eql(u16, name_utf16le, []u16{'.'}) or mem.eql(u16, name_utf16le, []u16{'.', '.'}))1619 if (mem.eql(u16, name_utf16le, []u16{'.'}) or mem.eql(u16, name_utf16le, []u16{ '.', '.' }))
1618 continue;1620 continue;
1619 // Trust that Windows gives us valid UTF-16LE1621 // Trust that Windows gives us valid UTF-16LE
1620 const name_utf8_len = std.unicode.utf16leToUtf8(self.handle.name_data[0..], name_utf16le) catch unreachable;1622 const name_utf8_len = std.unicode.utf16leToUtf8(self.handle.name_data[0..], name_utf16le) catch unreachable;
test/behavior.zig+1
...@@ -12,6 +12,7 @@ comptime {...@@ -12,6 +12,7 @@ comptime {
12 _ = @import("cases/bugs/1277.zig");12 _ = @import("cases/bugs/1277.zig");
13 _ = @import("cases/bugs/1381.zig");13 _ = @import("cases/bugs/1381.zig");
14 _ = @import("cases/bugs/1421.zig");14 _ = @import("cases/bugs/1421.zig");
15 _ = @import("cases/bugs/1442.zig");
15 _ = @import("cases/bugs/394.zig");16 _ = @import("cases/bugs/394.zig");
16 _ = @import("cases/bugs/655.zig");17 _ = @import("cases/bugs/655.zig");
17 _ = @import("cases/bugs/656.zig");18 _ = @import("cases/bugs/656.zig");
test/cases/bugs/1442.zig created+11
...@@ -0,0 +1,11 @@
1const std = @import("std");
2
3const Union = union(enum) {
4 Text: []const u8,
5 Color: u32,
6};
7
8test "const error union field alignment" {
9 var union_or_err: error!Union = Union{ .Color = 1234 };
10 std.debug.assertOrPanic((union_or_err catch unreachable).Color == 1234);
11}