make the zero-bit-ness of pointers lazy

this case works now:

```zig
const Foo = struct {
    field: @typeOf(func).ReturnType,
};
fn func(self: *Foo) void {}
```
This commit is contained in:
Andrew Kelley 2019-08-25 20:27:56 -04:00
parent 8f41da2216
commit 64e9b0ee46
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
2 changed files with 72 additions and 39 deletions

View File

@ -474,15 +474,21 @@ ZigType *get_pointer_to_type_extra(CodeGen *g, ZigType *child_type, bool is_cons
buf_ptr(&child_type->name)); buf_ptr(&child_type->name));
} }
if (type_has_bits(child_type)) { if (type_is_resolved(child_type, ResolveStatusZeroBitsKnown)) {
entry->abi_size = g->builtin_types.entry_usize->abi_size; if (type_has_bits(child_type)) {
entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits; entry->abi_size = g->builtin_types.entry_usize->abi_size;
entry->abi_align = g->builtin_types.entry_usize->abi_align; entry->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
entry->abi_align = g->builtin_types.entry_usize->abi_align;
} else {
assert(byte_alignment == 0);
entry->abi_size = 0;
entry->size_in_bits = 0;
entry->abi_align = 0;
}
} else { } else {
assert(byte_alignment == 0); entry->abi_size = SIZE_MAX;
entry->abi_size = 0; entry->size_in_bits = SIZE_MAX;
entry->size_in_bits = 0; entry->abi_align = UINT32_MAX;
entry->abi_align = 0;
} }
entry->data.pointer.ptr_len = ptr_len; entry->data.pointer.ptr_len = ptr_len;
@ -5585,6 +5591,25 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
return ErrorNone; return ErrorNone;
} }
static Error resolve_pointer_zero_bits(CodeGen *g, ZigType *ty) {
Error err;
ZigType *elem_type = ty->data.pointer.child_type;
if ((err = type_resolve(g, elem_type, ResolveStatusZeroBitsKnown)))
return err;
if (type_has_bits(elem_type)) {
ty->abi_size = g->builtin_types.entry_usize->abi_size;
ty->size_in_bits = g->builtin_types.entry_usize->size_in_bits;
ty->abi_align = g->builtin_types.entry_usize->abi_align;
} else {
ty->abi_size = 0;
ty->size_in_bits = 0;
ty->abi_align = 0;
}
return ErrorNone;
}
Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) { Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
if (type_is_invalid(ty)) if (type_is_invalid(ty))
return ErrorSemanticAnalyzeFail; return ErrorSemanticAnalyzeFail;
@ -5594,36 +5619,44 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
case ResolveStatusInvalid: case ResolveStatusInvalid:
zig_unreachable(); zig_unreachable();
case ResolveStatusZeroBitsKnown: case ResolveStatusZeroBitsKnown:
if (ty->id == ZigTypeIdStruct) { switch (ty->id) {
return resolve_struct_zero_bits(g, ty); case ZigTypeIdStruct:
} else if (ty->id == ZigTypeIdEnum) { return resolve_struct_zero_bits(g, ty);
return resolve_enum_zero_bits(g, ty); case ZigTypeIdEnum:
} else if (ty->id == ZigTypeIdUnion) { return resolve_enum_zero_bits(g, ty);
return resolve_union_zero_bits(g, ty); case ZigTypeIdUnion:
return resolve_union_zero_bits(g, ty);
case ZigTypeIdPointer:
return resolve_pointer_zero_bits(g, ty);
default:
return ErrorNone;
} }
return ErrorNone;
case ResolveStatusAlignmentKnown: case ResolveStatusAlignmentKnown:
if (ty->id == ZigTypeIdStruct) { switch (ty->id) {
return resolve_struct_alignment(g, ty); case ZigTypeIdStruct:
} else if (ty->id == ZigTypeIdEnum) { return resolve_struct_alignment(g, ty);
return resolve_enum_zero_bits(g, ty); case ZigTypeIdEnum:
} else if (ty->id == ZigTypeIdUnion) { return resolve_enum_zero_bits(g, ty);
return resolve_union_alignment(g, ty); case ZigTypeIdUnion:
} else if (ty->id == ZigTypeIdFnFrame) { return resolve_union_alignment(g, ty);
return resolve_async_frame(g, ty); case ZigTypeIdFnFrame:
return resolve_async_frame(g, ty);
default:
return ErrorNone;
} }
return ErrorNone;
case ResolveStatusSizeKnown: case ResolveStatusSizeKnown:
if (ty->id == ZigTypeIdStruct) { switch (ty->id) {
return resolve_struct_type(g, ty); case ZigTypeIdStruct:
} else if (ty->id == ZigTypeIdEnum) { return resolve_struct_type(g, ty);
return resolve_enum_zero_bits(g, ty); case ZigTypeIdEnum:
} else if (ty->id == ZigTypeIdUnion) { return resolve_enum_zero_bits(g, ty);
return resolve_union_type(g, ty); case ZigTypeIdUnion:
} else if (ty->id == ZigTypeIdFnFrame) { return resolve_union_type(g, ty);
return resolve_async_frame(g, ty); case ZigTypeIdFnFrame:
return resolve_async_frame(g, ty);
default:
return ErrorNone;
} }
return ErrorNone;
case ResolveStatusLLVMFwdDecl: case ResolveStatusLLVMFwdDecl:
case ResolveStatusLLVMFull: case ResolveStatusLLVMFull:
resolve_llvm_types(g, ty, status); resolve_llvm_types(g, ty, status);

View File

@ -25582,12 +25582,12 @@ static Error ir_resolve_lazy_raw(CodeGen *codegen, AstNode *source_node, ConstEx
} }
} }
ResolveStatus needed_status = (align_bytes == 0) ? if (align_bytes != 0) {
ResolveStatusZeroBitsKnown : ResolveStatusAlignmentKnown; if ((err = type_resolve(codegen, elem_type, ResolveStatusAlignmentKnown)))
if ((err = type_resolve(codegen, elem_type, needed_status))) return err;
return err; if (!type_has_bits(elem_type))
if (!type_has_bits(elem_type)) align_bytes = 0;
align_bytes = 0; }
bool allow_zero = lazy_ptr_type->is_allowzero || lazy_ptr_type->ptr_len == PtrLenC; bool allow_zero = lazy_ptr_type->is_allowzero || lazy_ptr_type->ptr_len == PtrLenC;
assert(val->type->id == ZigTypeIdMetaType); assert(val->type->id == ZigTypeIdMetaType);
val->data.x_type = get_pointer_to_type_extra(codegen, elem_type, val->data.x_type = get_pointer_to_type_extra(codegen, elem_type,