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) {
58825882 }
58835883 case ZigTypeIdErrorUnion:
58845884 {
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, ")");
58865893 return;
58875894 }
58885895 case ZigTypeIdUnion:
58895896 {
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, "}");
58915902 return;
58925903 }
58935904 case ZigTypeIdErrorSet:
src/codegen.cpp+29-9
......@@ -5870,13 +5870,17 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
58705870
58715871 if (make_unnamed_struct) {
58725872 LLVMValueRef result = LLVMConstStruct(fields, 2, false);
5873 size_t expected_sz = LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
5874 size_t actual_sz = LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(result));
5875 if (actual_sz < expected_sz) {
5876 unsigned pad_sz = expected_sz - actual_sz;
5873 uint64_t last_field_offset = LLVMOffsetOfElement(g->target_data_ref, LLVMTypeOf(result), 1);
5874 uint64_t end_offset = last_field_offset +
5875 LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(fields[1]));
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) {
58775879 fields[2] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), pad_sz));
58785880 result = LLVMConstStruct(fields, 3, false);
58795881 }
5882 uint64_t actual_sz = LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(result));
5883 assert(actual_sz == expected_sz);
58805884 return result;
58815885 } else {
58825886 return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);
......@@ -5917,13 +5921,29 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
59175921 err_payload_value = gen_const_val(g, payload_val, "");
59185922 make_unnamed_struct = is_llvm_value_unnamed_type(payload_val->type, err_payload_value);
59195923 }
5920 LLVMValueRef fields[] = {
5921 err_tag_value,
5922 err_payload_value,
5923 };
59245924 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 }
59265942 } else {
5943 LLVMValueRef fields[] = {
5944 err_tag_value,
5945 err_payload_value,
5946 };
59275947 return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);
59285948 }
59295949 }
std/os/index.zig+19-17
......@@ -343,23 +343,25 @@ pub fn posixWrite(fd: i32, bytes: []const u8) !void {
343343 const amt_to_write = math.min(bytes.len - index, usize(max_bytes_len));
344344 const rc = posix.write(fd, bytes.ptr + index, amt_to_write);
345345 const write_err = posix.getErrno(rc);
346 if (write_err > 0) {
347 return switch (write_err) {
348 posix.EINTR => continue,
349 posix.EINVAL, posix.EFAULT => unreachable,
350 posix.EAGAIN => PosixWriteError.WouldBlock,
351 posix.EBADF => PosixWriteError.FileClosed,
352 posix.EDESTADDRREQ => PosixWriteError.DestinationAddressRequired,
353 posix.EDQUOT => PosixWriteError.DiskQuota,
354 posix.EFBIG => PosixWriteError.FileTooBig,
355 posix.EIO => PosixWriteError.InputOutput,
356 posix.ENOSPC => PosixWriteError.NoSpaceLeft,
357 posix.EPERM => PosixWriteError.AccessDenied,
358 posix.EPIPE => PosixWriteError.BrokenPipe,
359 else => unexpectedErrorPosix(write_err),
360 };
346 switch (write_err) {
347 0 => {
348 index += rc;
349 continue;
350 },
351 posix.EINTR => continue,
352 posix.EINVAL => unreachable,
353 posix.EFAULT => unreachable,
354 posix.EAGAIN => return PosixWriteError.WouldBlock,
355 posix.EBADF => return PosixWriteError.FileClosed,
356 posix.EDESTADDRREQ => return PosixWriteError.DestinationAddressRequired,
357 posix.EDQUOT => return PosixWriteError.DiskQuota,
358 posix.EFBIG => return PosixWriteError.FileTooBig,
359 posix.EIO => return PosixWriteError.InputOutput,
360 posix.ENOSPC => return PosixWriteError.NoSpaceLeft,
361 posix.EPERM => return PosixWriteError.AccessDenied,
362 posix.EPIPE => return PosixWriteError.BrokenPipe,
363 else => return unexpectedErrorPosix(write_err),
361364 }
362 index += rc;
363365 }
364366}
365367
......@@ -1614,7 +1616,7 @@ pub const Dir = struct {
16141616 return null;
16151617 }
16161618 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{ '.', '.' }))
16181620 continue;
16191621 // Trust that Windows gives us valid UTF-16LE
16201622 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 {
1212 _ = @import("cases/bugs/1277.zig");
1313 _ = @import("cases/bugs/1381.zig");
1414 _ = @import("cases/bugs/1421.zig");
15 _ = @import("cases/bugs/1442.zig");
1516 _ = @import("cases/bugs/394.zig");
1617 _ = @import("cases/bugs/655.zig");
1718 _ = @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}