diff --git a/src/all_types.hpp b/src/all_types.hpp index e55f10d5e..36d3c0a39 100644 --- a/src/all_types.hpp +++ b/src/all_types.hpp @@ -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; diff --git a/src/analyze.cpp b/src/analyze.cpp index 2c934bcf6..411a0d7a0 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -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(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(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(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(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; diff --git a/src/analyze.hpp b/src/analyze.hpp index ebfd11f51..7fa014350 100644 --- a/src/analyze.hpp +++ b/src/analyze.hpp @@ -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); diff --git a/src/codegen.cpp b/src/codegen.cpp index 4065994d8..29ecb3a47 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -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"); } diff --git a/src/ir.cpp b/src/ir.cpp index 52cf69de8..b6a73638e 100644 --- a/src/ir.cpp +++ b/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(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(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(val->data.x_lazy); IrAnalyze *ira = lazy_slice_type->ira;