From be0a9a72772566667d4c225972c6bc7c17b751ef Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Fri, 23 Aug 2019 15:05:15 -0400 Subject: [PATCH] pointer types lazily evaluate their element type --- src/all_types.hpp | 3 +- src/analyze.cpp | 22 ++++++------ src/ir.cpp | 85 ++++++++++++++++++++++++++++++----------------- 3 files changed, 68 insertions(+), 42 deletions(-) diff --git a/src/all_types.hpp b/src/all_types.hpp index 11bed48e8f..d23020593d 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -332,7 +332,8 @@ struct LazyValuePtrType { bool is_volatile; bool is_allowzero; - ZigType *elem_type; + ConstExprValue *elem_type_val; + AstNode *elem_type_src_node; ConstExprValue *align_val; // can be null PtrLen ptr_len; uint32_t bit_offset_in_host; diff --git a/src/analyze.cpp b/src/analyze.cpp index bfdeb5d41a..f140489ab3 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -956,7 +956,7 @@ ConstExprValue *analyze_const_value(CodeGen *g, Scope *scope, AstNode *node, Zig } static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, ZigType *parent_type, - bool *is_zero_bits) + ConstExprValue *parent_type_val, bool *is_zero_bits) { Error err; if (type_val->special != ConstValSpecialLazy) { @@ -972,15 +972,17 @@ static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, Zi zig_unreachable(); case LazyValueIdPtrType: { LazyValuePtrType *lazy_ptr_type = reinterpret_cast(type_val->data.x_lazy); - if (lazy_ptr_type->elem_type == parent_type) { + + if (parent_type_val == lazy_ptr_type->elem_type_val) { // Does a struct which contains a pointer field to itself have bits? Yes. *is_zero_bits = false; return ErrorNone; } else { - if ((err = type_resolve(g, lazy_ptr_type->elem_type, ResolveStatusZeroBitsKnown))) - return err; - *is_zero_bits = type_has_bits(lazy_ptr_type->elem_type); - return ErrorNone; + if (parent_type_val == nullptr) { + parent_type_val = type_val; + } + return type_val_resolve_zero_bits(g, lazy_ptr_type->elem_type_val, parent_type, + parent_type_val, is_zero_bits); } } case LazyValueIdSliceType: @@ -1030,9 +1032,7 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue } case LazyValueIdPtrType: { LazyValuePtrType *lazy_ptr_type = reinterpret_cast(type_val->data.x_lazy); - if (type_is_invalid(lazy_ptr_type->elem_type)) - return ReqCompTimeInvalid; - return type_requires_comptime(g, lazy_ptr_type->elem_type, parent_type); + return type_val_resolve_requires_comptime(g, lazy_ptr_type->elem_type_val, parent_type); } case LazyValueIdFnType: { LazyValueFnType *lazy_fn_type = reinterpret_cast(type_val->data.x_lazy); @@ -1102,7 +1102,7 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, Cons case LazyValueIdPtrType: { Error err; bool zero_bits; - if ((err = type_val_resolve_zero_bits(g, type_val, nullptr, &zero_bits))) { + if ((err = type_val_resolve_zero_bits(g, type_val, nullptr, nullptr, &zero_bits))) { return OnePossibleValueInvalid; } if (zero_bits) { @@ -2359,7 +2359,7 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) { } bool field_is_zero_bits; - if ((err = type_val_resolve_zero_bits(g, field_type_val, struct_type, &field_is_zero_bits))) { + if ((err = type_val_resolve_zero_bits(g, field_type_val, struct_type, nullptr, &field_is_zero_bits))) { struct_type->data.structure.resolve_status = ResolveStatusInvalid; return ErrorSemanticAnalyzeFail; } diff --git a/src/ir.cpp b/src/ir.cpp index 5f4cce328a..13ae0715a4 100644 --- a/src/ir.cpp +++ b/src/ir.cpp @@ -10850,17 +10850,32 @@ static ZigType *ir_resolve_const_type(CodeGen *codegen, IrExecutable *exec, AstN return val->data.x_type; } -static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { +static ConstExprValue *ir_resolve_type_lazy(IrAnalyze *ira, IrInstruction *type_value) { if (type_is_invalid(type_value->value.type)) - return ira->codegen->builtin_types.entry_invalid; + return nullptr; if (type_value->value.type->id != ZigTypeIdMetaType) { ir_add_error(ira, type_value, buf_sprintf("expected type 'type', found '%s'", buf_ptr(&type_value->value.type->name))); - return ira->codegen->builtin_types.entry_invalid; + return nullptr; } - return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->source_node, &type_value->value); + Error err; + if ((err = ir_resolve_const_val(ira->codegen, ira->new_irb.exec, type_value->source_node, + &type_value->value, LazyOk))) + { + return nullptr; + } + + return &type_value->value; +} + +static ZigType *ir_resolve_type(IrAnalyze *ira, IrInstruction *type_value) { + ConstExprValue *val = ir_resolve_type_lazy(ira, type_value); + if (val == nullptr) + return ira->codegen->builtin_types.entry_invalid; + + return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, type_value->source_node, val); } static ZigType *ir_resolve_int_type(IrAnalyze *ira, IrInstruction *type_value) { @@ -23907,30 +23922,10 @@ static IrInstruction *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstruct lazy_ptr_type->base.id = LazyValueIdPtrType; lazy_ptr_type->base.exec = ira->new_irb.exec; - ZigType *child_type = ir_resolve_type(ira, instruction->child_type->child); - if (type_is_invalid(child_type)) + lazy_ptr_type->elem_type_val = ir_resolve_type_lazy(ira, instruction->child_type->child); + if (lazy_ptr_type->elem_type_val == nullptr) return ira->codegen->invalid_instruction; - lazy_ptr_type->elem_type = child_type; - - if (child_type->id == ZigTypeIdUnreachable) { - ir_add_error(ira, &instruction->base, buf_sprintf("pointer to noreturn not allowed")); - return ira->codegen->invalid_instruction; - } else if (child_type->id == ZigTypeIdOpaque && instruction->ptr_len == PtrLenUnknown) { - ir_add_error(ira, &instruction->base, buf_sprintf("unknown-length pointer to opaque")); - return ira->codegen->invalid_instruction; - } else if (instruction->ptr_len == PtrLenC) { - if (!type_allowed_in_extern(ira->codegen, child_type)) { - ir_add_error(ira, &instruction->base, - buf_sprintf("C pointers cannot point to non-C-ABI-compatible type '%s'", buf_ptr(&child_type->name))); - return ira->codegen->invalid_instruction; - } else if (child_type->id == ZigTypeIdOpaque) { - ir_add_error(ira, &instruction->base, buf_sprintf("C pointers cannot point opaque types")); - return ira->codegen->invalid_instruction; - } else if (instruction->is_allow_zero) { - ir_add_error(ira, &instruction->base, buf_sprintf("C pointers always allow address zero")); - return ira->codegen->invalid_instruction; - } - } + lazy_ptr_type->elem_type_src_node = instruction->child_type->source_node; if (instruction->align_value != nullptr) { lazy_ptr_type->align_val = ir_resolve_const(ira, instruction->align_value->child, LazyOk); @@ -25593,15 +25588,45 @@ static Error ir_resolve_lazy_raw(CodeGen *codegen, AstNode *source_node, ConstEx if (!ir_resolve_const_align(codegen, exec, source_node, lazy_ptr_type->align_val, &align_bytes)) return ErrorSemanticAnalyzeFail; } + ZigType *elem_type = ir_resolve_const_type(codegen, exec, lazy_ptr_type->elem_type_src_node, + lazy_ptr_type->elem_type_val); + if (type_is_invalid(elem_type)) + return ErrorSemanticAnalyzeFail; + + if (elem_type->id == ZigTypeIdUnreachable) { + exec_add_error_node(codegen, exec, lazy_ptr_type->elem_type_src_node, + buf_create_from_str("pointer to noreturn not allowed")); + return ErrorSemanticAnalyzeFail; + } else if (elem_type->id == ZigTypeIdOpaque && lazy_ptr_type->ptr_len == PtrLenUnknown) { + exec_add_error_node(codegen, exec, lazy_ptr_type->elem_type_src_node, + buf_create_from_str("unknown-length pointer to opaque")); + return ErrorSemanticAnalyzeFail; + } else if (lazy_ptr_type->ptr_len == PtrLenC) { + if (!type_allowed_in_extern(codegen, elem_type)) { + exec_add_error_node(codegen, exec, lazy_ptr_type->elem_type_src_node, + buf_sprintf("C pointers cannot point to non-C-ABI-compatible type '%s'", + buf_ptr(&elem_type->name))); + return ErrorSemanticAnalyzeFail; + } else if (elem_type->id == ZigTypeIdOpaque) { + exec_add_error_node(codegen, exec, lazy_ptr_type->elem_type_src_node, + buf_sprintf("C pointers cannot point opaque types")); + return ErrorSemanticAnalyzeFail; + } else if (lazy_ptr_type->is_allowzero) { + exec_add_error_node(codegen, exec, lazy_ptr_type->elem_type_src_node, + buf_sprintf("C pointers always allow address zero")); + return ErrorSemanticAnalyzeFail; + } + } + ResolveStatus needed_status = (align_bytes == 0) ? ResolveStatusZeroBitsKnown : ResolveStatusAlignmentKnown; - if ((err = type_resolve(codegen, lazy_ptr_type->elem_type, needed_status))) + if ((err = type_resolve(codegen, elem_type, needed_status))) return err; - if (!type_has_bits(lazy_ptr_type->elem_type)) + if (!type_has_bits(elem_type)) align_bytes = 0; bool allow_zero = lazy_ptr_type->is_allowzero || lazy_ptr_type->ptr_len == PtrLenC; assert(val->type->id == ZigTypeIdMetaType); - val->data.x_type = get_pointer_to_type_extra(codegen, lazy_ptr_type->elem_type, + val->data.x_type = get_pointer_to_type_extra(codegen, elem_type, lazy_ptr_type->is_const, lazy_ptr_type->is_volatile, lazy_ptr_type->ptr_len, align_bytes, lazy_ptr_type->bit_offset_in_host, lazy_ptr_type->host_int_bytes, allow_zero);