make `@sizeOf` lazy

master
Andrew Kelley 2019-08-29 12:43:56 -04:00
parent 94bbb46ca6
commit d9f0446b1f
No known key found for this signature in database
GPG Key ID: 7C5F548F728501A9
5 changed files with 134 additions and 51 deletions

View File

@ -308,6 +308,7 @@ struct ConstGlobalRefs {
enum LazyValueId {
LazyValueIdInvalid,
LazyValueIdAlignOf,
LazyValueIdSizeOf,
LazyValueIdPtrType,
LazyValueIdOptType,
LazyValueIdSliceType,
@ -326,6 +327,13 @@ struct LazyValueAlignOf {
IrInstruction *target_type;
};
struct LazyValueSizeOf {
LazyValue base;
IrAnalyze *ira;
IrInstruction *target_type;
};
struct LazyValueSliceType {
LazyValue base;

View File

@ -997,6 +997,7 @@ static Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, Zi
switch (type_val->data.x_lazy->id) {
case LazyValueIdInvalid:
case LazyValueIdAlignOf:
case LazyValueIdSizeOf:
zig_unreachable();
case LazyValueIdPtrType: {
LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy);
@ -1036,6 +1037,7 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool
switch (type_val->data.x_lazy->id) {
case LazyValueIdInvalid:
case LazyValueIdAlignOf:
case LazyValueIdSizeOf:
zig_unreachable();
case LazyValueIdSliceType:
case LazyValueIdPtrType:
@ -1055,6 +1057,7 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue
switch (type_val->data.x_lazy->id) {
case LazyValueIdInvalid:
case LazyValueIdAlignOf:
case LazyValueIdSizeOf:
zig_unreachable();
case LazyValueIdSliceType: {
LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(type_val->data.x_lazy);
@ -1105,7 +1108,7 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ConstExprValue
zig_unreachable();
}
static Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ConstExprValue *type_val,
Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ConstExprValue *type_val,
size_t *abi_size, size_t *size_in_bits)
{
Error err;
@ -1123,12 +1126,42 @@ start_over:
switch (type_val->data.x_lazy->id) {
case LazyValueIdInvalid:
case LazyValueIdAlignOf:
case LazyValueIdSizeOf:
zig_unreachable();
case LazyValueIdSliceType:
*abi_size = g->builtin_types.entry_usize->abi_size * 2;
*size_in_bits = g->builtin_types.entry_usize->size_in_bits * 2;
case LazyValueIdSliceType: {
LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(type_val->data.x_lazy);
bool is_zero_bits;
if ((err = type_val_resolve_zero_bits(g, &lazy_slice_type->elem_type->value, nullptr,
nullptr, &is_zero_bits)))
{
return err;
}
if (is_zero_bits) {
*abi_size = g->builtin_types.entry_usize->abi_size;
*size_in_bits = g->builtin_types.entry_usize->size_in_bits;
} else {
*abi_size = g->builtin_types.entry_usize->abi_size * 2;
*size_in_bits = g->builtin_types.entry_usize->size_in_bits * 2;
}
return ErrorNone;
case LazyValueIdPtrType:
}
case LazyValueIdPtrType: {
LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy);
bool is_zero_bits;
if ((err = type_val_resolve_zero_bits(g, &lazy_ptr_type->elem_type->value, nullptr,
nullptr, &is_zero_bits)))
{
return err;
}
if (is_zero_bits) {
*abi_size = 0;
*size_in_bits = 0;
} else {
*abi_size = g->builtin_types.entry_usize->abi_size;
*size_in_bits = g->builtin_types.entry_usize->size_in_bits;
}
return ErrorNone;
}
case LazyValueIdFnType:
*abi_size = g->builtin_types.entry_usize->abi_size;
*size_in_bits = g->builtin_types.entry_usize->size_in_bits;
@ -1159,6 +1192,7 @@ Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, uint32_t
switch (type_val->data.x_lazy->id) {
case LazyValueIdInvalid:
case LazyValueIdAlignOf:
case LazyValueIdSizeOf:
zig_unreachable();
case LazyValueIdSliceType:
case LazyValueIdPtrType:
@ -1193,6 +1227,7 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, Cons
switch (type_val->data.x_lazy->id) {
case LazyValueIdInvalid:
case LazyValueIdAlignOf:
case LazyValueIdSizeOf:
zig_unreachable();
case LazyValueIdSliceType: // it has the len field
case LazyValueIdOptType: // it has the optional bit
@ -4202,7 +4237,12 @@ static void analyze_fn_async(CodeGen *g, ZigFn *fn, bool resolve_frame) {
return;
}
}
assert(callee->anal_state == FnAnalStateComplete);
if (callee->anal_state != FnAnalStateComplete) {
add_node_error(g, call->base.source_node,
buf_sprintf("call to function '%s' depends on itself", buf_ptr(&callee->symbol_name)));
fn->anal_state = FnAnalStateInvalid;
return;
}
analyze_fn_async(g, callee, true);
if (callee->anal_state == FnAnalStateInvalid) {
fn->anal_state = FnAnalStateInvalid;
@ -4480,6 +4520,8 @@ void semantic_analyze(CodeGen *g) {
ZigFn *fn = g->fn_defs.at(g->fn_defs_index);
g->trace_err = nullptr;
analyze_fn_async(g, fn, true);
if (fn->anal_state == FnAnalStateInvalid)
continue;
if (fn_is_async(fn) && fn->non_async_node != nullptr) {
ErrorMsg *msg = add_node_error(g, fn->proto_node,
buf_sprintf("'%s' cannot be async", buf_ptr(&fn->symbol_name)));
@ -5632,6 +5674,11 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
return ErrorSemanticAnalyzeFail;
}
analyze_fn_async(g, callee, true);
if (callee->inferred_async_node == inferred_async_checking) {
assert(g->errors.length != 0);
frame_type->data.frame.locals_struct = g->builtin_types.entry_invalid;
return ErrorSemanticAnalyzeFail;
}
if (!fn_is_async(callee))
continue;

View File

@ -247,6 +247,8 @@ void resolve_llvm_types_fn(CodeGen *g, ZigFn *fn);
bool fn_is_async(ZigFn *fn);
Error type_val_resolve_abi_align(CodeGen *g, ConstExprValue *type_val, uint32_t *abi_align);
Error type_val_resolve_abi_size(CodeGen *g, AstNode *source_node, ConstExprValue *type_val,
size_t *abi_size, size_t *size_in_bits);
ZigType *resolve_union_field_type(CodeGen *g, TypeUnionField *union_field);
ZigType *resolve_struct_field_type(CodeGen *g, TypeStructField *struct_field);

View File

@ -6845,6 +6845,7 @@ static void set_global_tls(CodeGen *g, ZigVar *var, LLVMValueRef global_value) {
}
static void do_code_gen(CodeGen *g) {
Error err;
assert(!g->errors.length);
generate_error_name_table(g);
@ -6858,6 +6859,8 @@ static void do_code_gen(CodeGen *g) {
// Generate debug info for it but that's it.
ConstExprValue *const_val = var->const_value;
assert(const_val->special != ConstValSpecialRuntime);
if ((err = ir_resolve_lazy(g, var->decl_node, const_val)))
zig_unreachable();
if (const_val->type != var->var_type) {
zig_panic("TODO debug info for var with ptr casted value");
}
@ -6875,6 +6878,8 @@ static void do_code_gen(CodeGen *g) {
// Generate debug info for it but that's it.
ConstExprValue *const_val = var->const_value;
assert(const_val->special != ConstValSpecialRuntime);
if ((err = ir_resolve_lazy(g, var->decl_node, const_val)))
zig_unreachable();
if (const_val->type != var->var_type) {
zig_panic("TODO debug info for var with ptr casted value");
}

View File

@ -18066,54 +18066,20 @@ static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
zig_unreachable();
}
static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira,
IrInstructionSizeOf *size_of_instruction)
{
Error err;
IrInstruction *type_value = size_of_instruction->type_value->child;
ZigType *type_entry = ir_resolve_type(ira, type_value);
static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, IrInstructionSizeOf *instruction) {
IrInstruction *result = ir_const(ira, &instruction->base, ira->codegen->builtin_types.entry_num_lit_int);
result->value.special = ConstValSpecialLazy;
if ((err = type_resolve(ira->codegen, type_entry, ResolveStatusSizeKnown)))
LazyValueSizeOf *lazy_size_of = allocate<LazyValueSizeOf>(1);
lazy_size_of->ira = ira;
result->value.data.x_lazy = &lazy_size_of->base;
lazy_size_of->base.id = LazyValueIdSizeOf;
lazy_size_of->target_type = instruction->type_value->child;
if (ir_resolve_type_lazy(ira, lazy_size_of->target_type) == nullptr)
return ira->codegen->invalid_instruction;
switch (type_entry->id) {
case ZigTypeIdInvalid: // handled above
zig_unreachable();
case ZigTypeIdUnreachable:
case ZigTypeIdUndefined:
case ZigTypeIdNull:
case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple:
case ZigTypeIdOpaque:
ir_add_error_node(ira, type_value->source_node,
buf_sprintf("no size available for type '%s'", buf_ptr(&type_entry->name)));
return ira->codegen->invalid_instruction;
case ZigTypeIdMetaType:
case ZigTypeIdEnumLiteral:
case ZigTypeIdComptimeFloat:
case ZigTypeIdComptimeInt:
case ZigTypeIdVoid:
case ZigTypeIdBool:
case ZigTypeIdInt:
case ZigTypeIdFloat:
case ZigTypeIdPointer:
case ZigTypeIdArray:
case ZigTypeIdStruct:
case ZigTypeIdOptional:
case ZigTypeIdErrorUnion:
case ZigTypeIdErrorSet:
case ZigTypeIdEnum:
case ZigTypeIdUnion:
case ZigTypeIdFn:
case ZigTypeIdVector:
case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame:
{
uint64_t size_in_bytes = type_size(ira->codegen, type_entry);
return ir_const_unsigned(ira, &size_of_instruction->base, size_in_bytes);
}
}
zig_unreachable();
return result;
}
static IrInstruction *ir_analyze_test_non_null(IrAnalyze *ira, IrInstruction *source_inst, IrInstruction *value) {
@ -25548,6 +25514,61 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ConstExprValue *val) {
bigint_init_unsigned(&val->data.x_bigint, align_in_bytes);
return ErrorNone;
}
case LazyValueIdSizeOf: {
LazyValueSizeOf *lazy_size_of = reinterpret_cast<LazyValueSizeOf *>(val->data.x_lazy);
IrAnalyze *ira = lazy_size_of->ira;
if (lazy_size_of->target_type->value.special == ConstValSpecialStatic) {
switch (lazy_size_of->target_type->value.data.x_type->id) {
case ZigTypeIdInvalid: // handled above
zig_unreachable();
case ZigTypeIdUnreachable:
case ZigTypeIdUndefined:
case ZigTypeIdNull:
case ZigTypeIdBoundFn:
case ZigTypeIdArgTuple:
case ZigTypeIdOpaque:
ir_add_error(ira, lazy_size_of->target_type,
buf_sprintf("no size available for type '%s'",
buf_ptr(&lazy_size_of->target_type->value.data.x_type->name)));
return ErrorSemanticAnalyzeFail;
case ZigTypeIdMetaType:
case ZigTypeIdEnumLiteral:
case ZigTypeIdComptimeFloat:
case ZigTypeIdComptimeInt:
case ZigTypeIdVoid:
case ZigTypeIdBool:
case ZigTypeIdInt:
case ZigTypeIdFloat:
case ZigTypeIdPointer:
case ZigTypeIdArray:
case ZigTypeIdStruct:
case ZigTypeIdOptional:
case ZigTypeIdErrorUnion:
case ZigTypeIdErrorSet:
case ZigTypeIdEnum:
case ZigTypeIdUnion:
case ZigTypeIdFn:
case ZigTypeIdVector:
case ZigTypeIdFnFrame:
case ZigTypeIdAnyFrame:
break;
}
}
uint64_t abi_size;
uint64_t size_in_bits;
if ((err = type_val_resolve_abi_size(ira->codegen, source_node, &lazy_size_of->target_type->value,
&abi_size, &size_in_bits)))
{
return err;
}
val->special = ConstValSpecialStatic;
assert(val->type->id == ZigTypeIdComptimeInt);
bigint_init_unsigned(&val->data.x_bigint, abi_size);
return ErrorNone;
}
case LazyValueIdSliceType: {
LazyValueSliceType *lazy_slice_type = reinterpret_cast<LazyValueSliceType *>(val->data.x_lazy);
IrAnalyze *ira = lazy_slice_type->ira;