commit 96c9a9bdb3f7b10aa1ce4833bf6adb0af1c82dc9 (tree)
parent 47be64af5add5c146541c16dbb043ddf97f97d34
Author: Andrew Kelley <superjoe30@gmail.com>
Date: Mon, 29 Jan 2018 13:26:09 -0500
Merge remote-tracking branch 'origin/master' into llvm6
Diffstat:
5 files changed, 57 insertions(+), 13 deletions(-)
diff --git a/src/analyze.cpp b/src/analyze.cpp
@@ -362,8 +362,10 @@ TypeTableEntry *get_pointer_to_type_extra(CodeGen *g, TypeTableEntry *child_type
} else {
assert(bit_offset == 0);
parent_pointer = &child_type->pointer_parent[(is_const ? 1 : 0)];
- if (*parent_pointer)
+ if (*parent_pointer) {
+ assert((*parent_pointer)->data.pointer.alignment == byte_alignment);
return *parent_pointer;
+ }
}
type_ensure_zero_bits_known(g, child_type);
@@ -1240,16 +1242,16 @@ static bool type_allowed_in_extern(CodeGen *g, TypeTableEntry *type_entry) {
case TypeTableEntryIdPointer:
return type_allowed_in_extern(g, type_entry->data.pointer.child_type);
case TypeTableEntryIdStruct:
- return type_entry->data.structure.layout == ContainerLayoutExtern;
+ return type_entry->data.structure.layout == ContainerLayoutExtern || type_entry->data.structure.layout == ContainerLayoutPacked;
case TypeTableEntryIdMaybe:
{
TypeTableEntry *child_type = type_entry->data.maybe.child_type;
return child_type->id == TypeTableEntryIdPointer || child_type->id == TypeTableEntryIdFn;
}
case TypeTableEntryIdEnum:
- return type_entry->data.enumeration.layout == ContainerLayoutExtern;
+ return type_entry->data.enumeration.layout == ContainerLayoutExtern || type_entry->data.enumeration.layout == ContainerLayoutPacked;
case TypeTableEntryIdUnion:
- return type_entry->data.unionation.layout == ContainerLayoutExtern;
+ return type_entry->data.unionation.layout == ContainerLayoutExtern || type_entry->data.unionation.layout == ContainerLayoutPacked;
}
zig_unreachable();
}
@@ -1376,6 +1378,10 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
fn_type_id.return_type = (fn_proto->return_type == nullptr) ?
g->builtin_types.entry_void : analyze_type_expr(g, child_scope, fn_proto->return_type);
+ if (type_is_invalid(fn_type_id.return_type)) {
+ return g->builtin_types.entry_invalid;
+ }
+
if (fn_type_id.cc != CallingConventionUnspecified && !type_allowed_in_extern(g, fn_type_id.return_type)) {
add_node_error(g, fn_proto->return_type,
buf_sprintf("return type '%s' not allowed in function with calling convention '%s'",
@@ -1386,7 +1392,7 @@ static TypeTableEntry *analyze_fn_type(CodeGen *g, AstNode *proto_node, Scope *c
switch (fn_type_id.return_type->id) {
case TypeTableEntryIdInvalid:
- return g->builtin_types.entry_invalid;
+ zig_unreachable();
case TypeTableEntryIdUndefLit:
case TypeTableEntryIdNullLit:
@@ -2352,6 +2358,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
bool create_enum_type = decl_node->data.container_decl.auto_enum || (enum_type_node == nullptr && want_safety);
bool *covered_enum_fields;
ZigLLVMDIEnumerator **di_enumerators;
+ uint32_t abi_alignment_so_far;
if (create_enum_type) {
occupied_tag_values.init(field_count);
@@ -2373,7 +2380,7 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
} else {
tag_int_type = get_smallest_unsigned_int_type(g, field_count - 1);
}
- union_type->data.unionation.abi_alignment = get_abi_alignment(g, tag_int_type);
+ abi_alignment_so_far = get_abi_alignment(g, tag_int_type);
tag_type = new_type_table_entry(TypeTableEntryIdEnum);
buf_resize(&tag_type->name, 0);
@@ -2404,9 +2411,10 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
}
tag_type = enum_type;
covered_enum_fields = allocate<bool>(enum_type->data.enumeration.src_field_count);
- union_type->data.unionation.abi_alignment = get_abi_alignment(g, enum_type);
+ abi_alignment_so_far = get_abi_alignment(g, enum_type);
} else {
tag_type = nullptr;
+ abi_alignment_so_far = 0;
}
union_type->data.unionation.tag_type = tag_type;
@@ -2504,12 +2512,14 @@ static void resolve_union_zero_bits(CodeGen *g, TypeTableEntry *union_type) {
uint32_t field_align_bytes = get_abi_alignment(g, field_type);
if (field_align_bytes > biggest_align_bytes) {
biggest_align_bytes = field_align_bytes;
- if (biggest_align_bytes > union_type->data.unionation.abi_alignment) {
- union_type->data.unionation.abi_alignment = biggest_align_bytes;
+ if (biggest_align_bytes > abi_alignment_so_far) {
+ abi_alignment_so_far = biggest_align_bytes;
}
}
}
+ union_type->data.unionation.abi_alignment = abi_alignment_so_far;
+
if (union_type->data.unionation.is_invalid)
return;
diff --git a/std/os/zen.zig b/std/os/zen.zig
@@ -42,7 +42,7 @@ pub fn map(v_addr: usize, p_addr: usize, size: usize, writable: bool) bool {
return syscall4(SYS_map, v_addr, p_addr, size, usize(writable)) != 0;
}
-pub fn createThread(function: fn()) u16 {
+pub fn createThread(function: fn()void) u16 {
return u16(syscall1(SYS_createThread, @ptrToInt(function)));
}
diff --git a/test/cases/misc.zig b/test/cases/misc.zig
@@ -617,3 +617,19 @@ test "cold function" {
fn thisIsAColdFn() void {
@setCold(true);
}
+
+
+const PackedStruct = packed struct { a: u8, b: u8, };
+const PackedUnion = packed union { a: u8, b: u32, };
+const PackedEnum = packed enum { A, B, };
+
+test "packed struct, enum, union parameters in extern function" {
+ testPackedStuff(
+ PackedStruct{.a = 1, .b = 2},
+ PackedUnion{.a = 1},
+ PackedEnum.A,
+ );
+}
+
+export fn testPackedStuff(a: &const PackedStruct, b: &const PackedUnion, c: PackedEnum) void {
+}
diff --git a/test/cases/struct.zig b/test/cases/struct.zig
@@ -404,3 +404,17 @@ test "native bit field understands endianness" {
assert(bitfields.f6 == 0x6);
assert(bitfields.f7 == 0x77);
}
+
+test "align 1 field before self referential align 8 field as slice return type" {
+ const result = alloc(Expr);
+ assert(result.len == 0);
+}
+
+const Expr = union(enum) {
+ Literal: u8,
+ Question: &Expr,
+};
+
+fn alloc(comptime T: type) []T {
+ return []T{};
+}
diff --git a/test/compile_errors.zig b/test/compile_errors.zig
@@ -1,12 +1,16 @@
const tests = @import("tests.zig");
pub fn addCases(cases: &tests.CompileErrorContext) void {
- cases.add("function with non-extern enum parameter",
+ cases.add("function with invalid return type",
+ \\export fn foo() boid {}
+ , ".tmp_source.zig:1:17: error: use of undeclared identifier 'boid'");
+
+ cases.add("function with non-extern non-packed enum parameter",
\\const Foo = enum { A, B, C };
\\export fn entry(foo: Foo) void { }
, ".tmp_source.zig:2:22: error: parameter of type 'Foo' not allowed in function with calling convention 'ccc'");
- cases.add("function with non-extern struct parameter",
+ cases.add("function with non-extern non-packed struct parameter",
\\const Foo = struct {
\\ A: i32,
\\ B: f32,
@@ -15,7 +19,7 @@ pub fn addCases(cases: &tests.CompileErrorContext) void {
\\export fn entry(foo: Foo) void { }
, ".tmp_source.zig:6:22: error: parameter of type 'Foo' not allowed in function with calling convention 'ccc'");
- cases.add("function with non-extern union parameter",
+ cases.add("function with non-extern non-packed union parameter",
\\const Foo = union {
\\ A: i32,
\\ B: f32,