add lazy value support for optional types

this case works now:

```zig
const Node = struct {
    node: ?*Node,
};
```
This commit is contained in:
Andrew Kelley 2019-08-23 17:14:51 -04:00
parent f0034495fa
commit 101440c199
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
3 changed files with 57 additions and 47 deletions

View File

@ -302,6 +302,7 @@ enum LazyValueId {
LazyValueIdInvalid,
LazyValueIdAlignOf,
LazyValueIdPtrType,
LazyValueIdOptType,
LazyValueIdSliceType,
LazyValueIdFnType,
};
@ -340,6 +341,13 @@ struct LazyValuePtrType {
uint32_t host_int_bytes;
};
struct LazyValueOptType {
LazyValue base;
ConstExprValue *payload_type_val;
AstNode *payload_type_src_node;
};
struct LazyValueFnType {
LazyValue base;
bool is_generic;

View File

@ -992,6 +992,7 @@ static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, Zi
parent_type_val, is_zero_bits);
}
}
case LazyValueIdOptType:
case LazyValueIdSliceType:
*is_zero_bits = false;
return ErrorNone;
@ -1017,6 +1018,7 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool
case LazyValueIdSliceType:
case LazyValueIdPtrType:
case LazyValueIdFnType:
case LazyValueIdOptType:
*is_opaque_type = false;
return ErrorNone;
}
@ -1041,6 +1043,10 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue
LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy);
return type_val_resolve_requires_comptime(g, lazy_ptr_type->elem_type_val);
}
case LazyValueIdOptType: {
LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
return type_val_resolve_requires_comptime(g, lazy_opt_type->payload_type_val);
}
case LazyValueIdFnType: {
LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(type_val->data.x_lazy);
if (lazy_fn_type->is_generic)
@ -1091,6 +1097,10 @@ static Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, si
case LazyValueIdFnType:
*abi_align = g->builtin_types.entry_usize->abi_align;
return ErrorNone;
case LazyValueIdOptType: {
LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
return type_val_resolve_abi_align(g, lazy_opt_type->payload_type_val, abi_align);
}
}
zig_unreachable();
}
@ -1104,6 +1114,7 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, Cons
case LazyValueIdAlignOf:
zig_unreachable();
case LazyValueIdSliceType: // it has the len field
case LazyValueIdOptType: // it has the optional bit
case LazyValueIdFnType:
return OnePossibleValueNo;
case LazyValueIdPtrType: {

View File

@ -8212,6 +8212,7 @@ static Error eval_comptime_ptr_reinterpret(IrAnalyze *ira, CodeGen *codegen, Ast
{
Error err;
assert(ptr_val->type->id == ZigTypeIdPointer);
assert(ptr_val->special == ConstValSpecialStatic);
ConstExprValue tmp = {};
tmp.special = ConstValSpecialStatic;
tmp.type = ptr_val->type->data.pointer.child_type;
@ -16150,51 +16151,21 @@ static Error ir_read_const_ptr(IrAnalyze *ira, CodeGen *codegen, AstNode *source
zig_unreachable();
}
static IrInstruction *ir_analyze_optional_type(IrAnalyze *ira, IrInstructionUnOp *un_op_instruction) {
Error err;
IrInstruction *value = un_op_instruction->value->child;
ZigType *type_entry = ir_resolve_type(ira, value);
if (type_is_invalid(type_entry))
return ira->codegen->invalid_instruction;
if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusSizeKnown)))
return ira->codegen->invalid_instruction;
static IrInstruction *ir_analyze_optional_type(IrAnalyze *ira, IrInstructionUnOp *instruction) {
IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_type);
result->value.special = ConstValSpecialLazy;
switch (type_entry->id) {
case ZigTypeIdInvalid:
zig_unreachable();
case ZigTypeIdMetaType:
case ZigTypeIdVoid:
case ZigTypeIdBool:
case ZigTypeIdInt:
case ZigTypeIdVector:
case ZigTypeIdFloat:
case ZigTypeIdPointer:
case ZigTypeIdArray:
case ZigTypeIdStruct:
case ZigTypeIdComptimeFloat:
case ZigTypeIdComptimeInt:
case ZigTypeIdEnumLiteral:
case ZigTypeIdUndefined:
case ZigTypeIdNull:
case ZigTypeIdOptional:
case ZigTypeIdErrorUnion:
case ZigTypeIdErrorSet:
case ZigTypeIdEnum:
case ZigTypeIdUnion:
case ZigTypeIdFn:
case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple:
case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame:
return ir_const_type(ira, &un_op_instruction->base, get_optional_type(ira->codegen, type_entry));
LazyValueOptType *lazy_opt_type = allocate<LazyValueOptType>(1);
result->value.data.x_lazy = &lazy_opt_type->base;
lazy_opt_type->base.id = LazyValueIdOptType;
lazy_opt_type->base.exec = ira->new_irb.exec;
case ZigTypeIdUnreachable:
case ZigTypeIdOpaque:
ir_add_error_node(ira, un_op_instruction->base.source_node,
buf_sprintf("type '%s' not optional", buf_ptr(&type_entry->name)));
return ira->codegen->invalid_instruction;
}
zig_unreachable();
lazy_opt_type->payload_type_val = ir_resolve_type_lazy(ira, instruction->value->child);
if (lazy_opt_type->payload_type_val == nullptr)
return ira->codegen->invalid_instruction;
lazy_opt_type->payload_type_src_node = instruction->value->source_node;
return result;
}
static ErrorMsg *ir_eval_negation_scalar(IrAnalyze *ira, IrInstruction *source_instr, ZigType *scalar_type,
@ -19658,11 +19629,9 @@ static ZigType *ir_type_info_get_type(IrAnalyze *ira, const char *type_name, Zig
ZigVar *var = tld->var;
if ((err = type_resolve(ira->codegen, var->const_value->type, ResolveStatusSizeKnown)))
return ira->codegen->builtin_types.entry_invalid;
assert(var->const_value->type->id == ZigTypeIdMetaType);
return var->const_value->data.x_type;
return ir_resolve_const_type(ira->codegen, ira->new_irb.exec, nullptr, var->const_value);
}
static Error ir_make_type_info_decls(IrAnalyze *ira, IrInstruction *source_instr, ConstExprValue *out_val,
@ -25633,6 +25602,28 @@ static Error ir_resolve_lazy_raw(CodeGen *codegen, AstNode *source_node, ConstEx
val->special = ConstValSpecialStatic;
return ErrorNone;
}
case LazyValueIdOptType: {
LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(val->data.x_lazy);
ZigType *payload_type = ir_resolve_const_type(codegen, exec, lazy_opt_type->payload_type_src_node,
lazy_opt_type->payload_type_val);
if (type_is_invalid(payload_type))
return ErrorSemanticAnalyzeFail;
if (payload_type->id == ZigTypeIdOpaque || payload_type->id == ZigTypeIdUnreachable) {
exec_add_error_node(codegen, exec, lazy_opt_type->payload_type_src_node,
buf_sprintf("type '%s' cannot be optional", buf_ptr(&payload_type->name)));
return ErrorSemanticAnalyzeFail;
}
if ((err = type_resolve(codegen, payload_type, ResolveStatusSizeKnown)))
return err;
assert(val->type->id == ZigTypeIdMetaType);
val->data.x_type = get_optional_type(codegen, payload_type);
val->special = ConstValSpecialStatic;
return ErrorNone;
}
case LazyValueIdFnType: {
ZigType *fn_type = ir_resolve_lazy_fn_type(codegen, exec, source_node,
reinterpret_cast<LazyValueFnType *>(val->data.x_lazy));