make `@sizeOf` lazy
parent
94bbb46ca6
commit
d9f0446b1f
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
111
src/ir.cpp
111
src/ir.cpp
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue