fix incorrect error union const value generation
closes #1442 zig needed to insert explicit padding into this structure before it got bitcasted.
This commit is contained in:
parent
dd1338b0e6
commit
7dd3c3814d
@ -5882,12 +5882,23 @@ void render_const_value(CodeGen *g, Buf *buf, ConstExprValue *const_val) {
|
||||
}
|
||||
case ZigTypeIdErrorUnion:
|
||||
{
|
||||
buf_appendf(buf, "(error union %s constant)", buf_ptr(&type_entry->name));
|
||||
buf_appendf(buf, "%s(", buf_ptr(&type_entry->name));
|
||||
if (const_val->data.x_err_union.err == nullptr) {
|
||||
render_const_value(g, buf, const_val->data.x_err_union.payload);
|
||||
} else {
|
||||
buf_appendf(buf, "%s.%s", buf_ptr(&type_entry->data.error_union.err_set_type->name),
|
||||
buf_ptr(&const_val->data.x_err_union.err->name));
|
||||
}
|
||||
buf_appendf(buf, ")");
|
||||
return;
|
||||
}
|
||||
case ZigTypeIdUnion:
|
||||
{
|
||||
buf_appendf(buf, "(union %s constant)", buf_ptr(&type_entry->name));
|
||||
uint64_t tag = bigint_as_unsigned(&const_val->data.x_union.tag);
|
||||
TypeUnionField *field = &type_entry->data.unionation.fields[tag];
|
||||
buf_appendf(buf, "%s { .%s = ", buf_ptr(&type_entry->name), buf_ptr(field->name));
|
||||
render_const_value(g, buf, const_val->data.x_union.payload);
|
||||
buf_append_str(buf, "}");
|
||||
return;
|
||||
}
|
||||
case ZigTypeIdErrorSet:
|
||||
|
@ -5870,13 +5870,17 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
|
||||
if (make_unnamed_struct) {
|
||||
LLVMValueRef result = LLVMConstStruct(fields, 2, false);
|
||||
size_t expected_sz = LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
|
||||
size_t actual_sz = LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(result));
|
||||
if (actual_sz < expected_sz) {
|
||||
unsigned pad_sz = expected_sz - actual_sz;
|
||||
uint64_t last_field_offset = LLVMOffsetOfElement(g->target_data_ref, LLVMTypeOf(result), 1);
|
||||
uint64_t end_offset = last_field_offset +
|
||||
LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(fields[1]));
|
||||
uint64_t expected_sz = LLVMStoreSizeOfType(g->target_data_ref, type_entry->type_ref);
|
||||
unsigned pad_sz = expected_sz - end_offset;
|
||||
if (pad_sz != 0) {
|
||||
fields[2] = LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), pad_sz));
|
||||
result = LLVMConstStruct(fields, 3, false);
|
||||
}
|
||||
uint64_t actual_sz = LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(result));
|
||||
assert(actual_sz == expected_sz);
|
||||
return result;
|
||||
} else {
|
||||
return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);
|
||||
@ -5917,13 +5921,29 @@ static LLVMValueRef gen_const_val(CodeGen *g, ConstExprValue *const_val, const c
|
||||
err_payload_value = gen_const_val(g, payload_val, "");
|
||||
make_unnamed_struct = is_llvm_value_unnamed_type(payload_val->type, err_payload_value);
|
||||
}
|
||||
LLVMValueRef fields[] = {
|
||||
err_tag_value,
|
||||
err_payload_value,
|
||||
};
|
||||
if (make_unnamed_struct) {
|
||||
return LLVMConstStruct(fields, 2, false);
|
||||
uint64_t payload_off = LLVMOffsetOfElement(g->target_data_ref, type_entry->type_ref, 1);
|
||||
uint64_t err_sz = LLVMStoreSizeOfType(g->target_data_ref, LLVMTypeOf(err_tag_value));
|
||||
unsigned pad_sz = payload_off - err_sz;
|
||||
if (pad_sz == 0) {
|
||||
LLVMValueRef fields[] = {
|
||||
err_tag_value,
|
||||
err_payload_value,
|
||||
};
|
||||
return LLVMConstStruct(fields, 2, false);
|
||||
} else {
|
||||
LLVMValueRef fields[] = {
|
||||
err_tag_value,
|
||||
LLVMGetUndef(LLVMArrayType(LLVMInt8Type(), pad_sz)),
|
||||
err_payload_value,
|
||||
};
|
||||
return LLVMConstStruct(fields, 3, false);
|
||||
}
|
||||
} else {
|
||||
LLVMValueRef fields[] = {
|
||||
err_tag_value,
|
||||
err_payload_value,
|
||||
};
|
||||
return LLVMConstNamedStruct(type_entry->type_ref, fields, 2);
|
||||
}
|
||||
}
|
||||
|
@ -343,23 +343,25 @@ pub fn posixWrite(fd: i32, bytes: []const u8) !void {
|
||||
const amt_to_write = math.min(bytes.len - index, usize(max_bytes_len));
|
||||
const rc = posix.write(fd, bytes.ptr + index, amt_to_write);
|
||||
const write_err = posix.getErrno(rc);
|
||||
if (write_err > 0) {
|
||||
return switch (write_err) {
|
||||
posix.EINTR => continue,
|
||||
posix.EINVAL, posix.EFAULT => unreachable,
|
||||
posix.EAGAIN => PosixWriteError.WouldBlock,
|
||||
posix.EBADF => PosixWriteError.FileClosed,
|
||||
posix.EDESTADDRREQ => PosixWriteError.DestinationAddressRequired,
|
||||
posix.EDQUOT => PosixWriteError.DiskQuota,
|
||||
posix.EFBIG => PosixWriteError.FileTooBig,
|
||||
posix.EIO => PosixWriteError.InputOutput,
|
||||
posix.ENOSPC => PosixWriteError.NoSpaceLeft,
|
||||
posix.EPERM => PosixWriteError.AccessDenied,
|
||||
posix.EPIPE => PosixWriteError.BrokenPipe,
|
||||
else => unexpectedErrorPosix(write_err),
|
||||
};
|
||||
switch (write_err) {
|
||||
0 => {
|
||||
index += rc;
|
||||
continue;
|
||||
},
|
||||
posix.EINTR => continue,
|
||||
posix.EINVAL => unreachable,
|
||||
posix.EFAULT => unreachable,
|
||||
posix.EAGAIN => return PosixWriteError.WouldBlock,
|
||||
posix.EBADF => return PosixWriteError.FileClosed,
|
||||
posix.EDESTADDRREQ => return PosixWriteError.DestinationAddressRequired,
|
||||
posix.EDQUOT => return PosixWriteError.DiskQuota,
|
||||
posix.EFBIG => return PosixWriteError.FileTooBig,
|
||||
posix.EIO => return PosixWriteError.InputOutput,
|
||||
posix.ENOSPC => return PosixWriteError.NoSpaceLeft,
|
||||
posix.EPERM => return PosixWriteError.AccessDenied,
|
||||
posix.EPIPE => return PosixWriteError.BrokenPipe,
|
||||
else => return unexpectedErrorPosix(write_err),
|
||||
}
|
||||
index += rc;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1614,7 +1616,7 @@ pub const Dir = struct {
|
||||
return null;
|
||||
}
|
||||
const name_utf16le = mem.toSlice(u16, self.handle.find_file_data.cFileName[0..].ptr);
|
||||
if (mem.eql(u16, name_utf16le, []u16{'.'}) or mem.eql(u16, name_utf16le, []u16{'.', '.'}))
|
||||
if (mem.eql(u16, name_utf16le, []u16{'.'}) or mem.eql(u16, name_utf16le, []u16{ '.', '.' }))
|
||||
continue;
|
||||
// Trust that Windows gives us valid UTF-16LE
|
||||
const name_utf8_len = std.unicode.utf16leToUtf8(self.handle.name_data[0..], name_utf16le) catch unreachable;
|
||||
|
@ -12,6 +12,7 @@ comptime {
|
||||
_ = @import("cases/bugs/1277.zig");
|
||||
_ = @import("cases/bugs/1381.zig");
|
||||
_ = @import("cases/bugs/1421.zig");
|
||||
_ = @import("cases/bugs/1442.zig");
|
||||
_ = @import("cases/bugs/394.zig");
|
||||
_ = @import("cases/bugs/655.zig");
|
||||
_ = @import("cases/bugs/656.zig");
|
||||
|
11
test/cases/bugs/1442.zig
Normal file
11
test/cases/bugs/1442.zig
Normal file
@ -0,0 +1,11 @@
|
||||
const std = @import("std");
|
||||
|
||||
const Union = union(enum) {
|
||||
Text: []const u8,
|
||||
Color: u32,
|
||||
};
|
||||
|
||||
test "const error union field alignment" {
|
||||
var union_or_err: error!Union = Union{ .Color = 1234 };
|
||||
std.debug.assertOrPanic((union_or_err catch unreachable).Color == 1234);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user