From 5cbb642525fa92e16dd3c9e978a9f8a34734de4c Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 18 Mar 2021 13:13:35 -0700 Subject: stage1: small mem usage improvement for IR move a boolean field to be represented implicitly with the enum tag. Just borrowing one of the many strategies of stage2. This simple change took the peak mem usage from std lib tests on my machine from 8.21 GiB to 8.11 GiB. --- src/stage1/ir.cpp | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) (limited to 'src/stage1/ir.cpp') diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index 7906df3b0d..c004e49e48 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -514,7 +514,8 @@ static void destroy_instruction_src(IrInstSrc *inst) { return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdSetAlignStack: return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdArgType: + case IrInstSrcIdArgTypeAllowVarFalse: + case IrInstSrcIdArgTypeAllowVarTrue: return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdExport: return heap::c_allocator.destroy(reinterpret_cast(inst)); @@ -1546,10 +1547,6 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcSetAlignStack *) { return IrInstSrcIdSetAlignStack; } -static constexpr IrInstSrcId ir_inst_id(IrInstSrcArgType *) { - return IrInstSrcIdArgType; -} - static constexpr IrInstSrcId ir_inst_id(IrInstSrcExport *) { return IrInstSrcIdExport; } @@ -4590,10 +4587,17 @@ static IrInstSrc *ir_build_set_align_stack(IrBuilderSrc *irb, Scope *scope, AstN static IrInstSrc *ir_build_arg_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *fn_type, IrInstSrc *arg_index, bool allow_var) { - IrInstSrcArgType *instruction = ir_build_instruction(irb, scope, source_node); + IrInstSrcArgType *instruction = heap::c_allocator.create(); + instruction->base.id = allow_var ? + IrInstSrcIdArgTypeAllowVarTrue : IrInstSrcIdArgTypeAllowVarFalse; + instruction->base.base.scope = scope; + instruction->base.base.source_node = source_node; + instruction->base.base.debug_id = exec_next_debug_id(irb->exec); + instruction->base.owner_bb = irb->current_basic_block; + ir_instruction_append(irb->current_basic_block, &instruction->base); + instruction->fn_type = fn_type; instruction->arg_index = arg_index; - instruction->allow_var = allow_var; ir_ref_instruction(fn_type, irb->current_basic_block); ir_ref_instruction(arg_index, irb->current_basic_block); @@ -30976,7 +30980,9 @@ static IrInstGen *ir_analyze_instruction_set_align_stack(IrAnalyze *ira, IrInstS return ir_const_void(ira, &instruction->base.base); } -static IrInstGen *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstSrcArgType *instruction) { +static IrInstGen *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstSrcArgType *instruction, + bool allow_var) +{ IrInstGen *fn_type_inst = instruction->fn_type->child; ZigType *fn_type = ir_resolve_type(ira, fn_type_inst); if (type_is_invalid(fn_type)) @@ -30998,7 +31004,7 @@ static IrInstGen *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstSrcArgTy FnTypeId *fn_type_id = &fn_type->data.fn.fn_type_id; if (arg_index >= fn_type_id->param_count) { - if (instruction->allow_var) { + if (allow_var) { // TODO remove this with var args return ir_const_type(ira, &instruction->base.base, ira->codegen->builtin_types.entry_anytype); } @@ -31013,7 +31019,7 @@ static IrInstGen *ir_analyze_instruction_arg_type(IrAnalyze *ira, IrInstSrcArgTy // Args are only unresolved if our function is generic. ir_assert(fn_type->data.fn.is_generic, &instruction->base.base); - if (instruction->allow_var) { + if (allow_var) { return ir_const_type(ira, &instruction->base.base, ira->codegen->builtin_types.entry_anytype); } else { ir_add_error(ira, &arg_index_inst->base, @@ -32383,8 +32389,10 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc return ir_analyze_instruction_reset_result(ira, (IrInstSrcResetResult *)instruction); case IrInstSrcIdSetAlignStack: return ir_analyze_instruction_set_align_stack(ira, (IrInstSrcSetAlignStack *)instruction); - case IrInstSrcIdArgType: - return ir_analyze_instruction_arg_type(ira, (IrInstSrcArgType *)instruction); + case IrInstSrcIdArgTypeAllowVarFalse: + return ir_analyze_instruction_arg_type(ira, (IrInstSrcArgType *)instruction, false); + case IrInstSrcIdArgTypeAllowVarTrue: + return ir_analyze_instruction_arg_type(ira, (IrInstSrcArgType *)instruction, true); case IrInstSrcIdExport: return ir_analyze_instruction_export(ira, (IrInstSrcExport *)instruction); case IrInstSrcIdExtern: @@ -32826,7 +32834,8 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) { case IrInstSrcIdAlignCast: case IrInstSrcIdImplicitCast: case IrInstSrcIdResolveResult: - case IrInstSrcIdArgType: + case IrInstSrcIdArgTypeAllowVarFalse: + case IrInstSrcIdArgTypeAllowVarTrue: case IrInstSrcIdErrorReturnTrace: case IrInstSrcIdErrorUnion: case IrInstSrcIdFloatOp: -- cgit v1.2.3 From a6f5aa71ac1e8c9a27ecfa6a50f0445a50545a5d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 18 Mar 2021 13:37:49 -0700 Subject: stage1: small IR memory optimization on CheckSwitchProngs --- src/stage1/all_types.hpp | 4 ++-- src/stage1/ir.cpp | 32 +++++++++++++++++++------------- src/stage1/ir_print.cpp | 19 ++++++++++++++----- 3 files changed, 35 insertions(+), 20 deletions(-) (limited to 'src/stage1/ir.cpp') diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index 5e1d4969db..e0cbf1c0c5 100644 --- a/src/stage1/all_types.hpp +++ b/src/stage1/all_types.hpp @@ -2610,7 +2610,8 @@ enum IrInstSrcId { IrInstSrcIdEnumToInt, IrInstSrcIdIntToErr, IrInstSrcIdErrToInt, - IrInstSrcIdCheckSwitchProngs, + IrInstSrcIdCheckSwitchProngsUnderYes, + IrInstSrcIdCheckSwitchProngsUnderNo, IrInstSrcIdCheckStatementIsVoid, IrInstSrcIdTypeName, IrInstSrcIdDeclRef, @@ -4021,7 +4022,6 @@ struct IrInstSrcCheckSwitchProngs { IrInstSrcCheckSwitchProngsRange *ranges; size_t range_count; AstNode* else_prong; - bool have_underscore_prong; }; struct IrInstSrcCheckStatementIsVoid { diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index c004e49e48..ad45d7682c 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -476,7 +476,8 @@ static void destroy_instruction_src(IrInstSrc *inst) { return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdErrToInt: return heap::c_allocator.destroy(reinterpret_cast(inst)); - case IrInstSrcIdCheckSwitchProngs: + case IrInstSrcIdCheckSwitchProngsUnderNo: + case IrInstSrcIdCheckSwitchProngsUnderYes: return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdCheckStatementIsVoid: return heap::c_allocator.destroy(reinterpret_cast(inst)); @@ -1471,10 +1472,6 @@ static constexpr IrInstSrcId ir_inst_id(IrInstSrcErrToInt *) { return IrInstSrcIdErrToInt; } -static constexpr IrInstSrcId ir_inst_id(IrInstSrcCheckSwitchProngs *) { - return IrInstSrcIdCheckSwitchProngs; -} - static constexpr IrInstSrcId ir_inst_id(IrInstSrcCheckStatementIsVoid *) { return IrInstSrcIdCheckStatementIsVoid; } @@ -4351,13 +4348,19 @@ static IrInstSrc *ir_build_check_switch_prongs(IrBuilderSrc *irb, Scope *scope, IrInstSrc *target_value, IrInstSrcCheckSwitchProngsRange *ranges, size_t range_count, AstNode* else_prong, bool have_underscore_prong) { - IrInstSrcCheckSwitchProngs *instruction = ir_build_instruction( - irb, scope, source_node); + IrInstSrcCheckSwitchProngs *instruction = heap::c_allocator.create(); + instruction->base.id = have_underscore_prong ? + IrInstSrcIdCheckSwitchProngsUnderYes : IrInstSrcIdCheckSwitchProngsUnderNo; + instruction->base.base.scope = scope; + instruction->base.base.source_node = source_node; + instruction->base.base.debug_id = exec_next_debug_id(irb->exec); + instruction->base.owner_bb = irb->current_basic_block; + ir_instruction_append(irb->current_basic_block, &instruction->base); + instruction->target_value = target_value; instruction->ranges = ranges; instruction->range_count = range_count; instruction->else_prong = else_prong; - instruction->have_underscore_prong = have_underscore_prong; ir_ref_instruction(target_value, irb->current_basic_block); for (size_t i = 0; i < range_count; i += 1) { @@ -29706,7 +29709,7 @@ static IrInstGen *ir_analyze_instruction_test_comptime(IrAnalyze *ira, IrInstSrc } static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, - IrInstSrcCheckSwitchProngs *instruction) + IrInstSrcCheckSwitchProngs *instruction, bool have_underscore_prong) { IrInstGen *target_value = instruction->target_value->child; ZigType *switch_type = target_value->value->type; @@ -29771,7 +29774,7 @@ static IrInstGen *ir_analyze_instruction_check_switch_prongs(IrAnalyze *ira, bigint_incr(&field_index); } } - if (instruction->have_underscore_prong) { + if (have_underscore_prong) { if (!switch_type->data.enumeration.non_exhaustive) { ir_add_error(ira, &instruction->base.base, buf_sprintf("switch on exhaustive enum has `_` prong")); @@ -32347,8 +32350,10 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc return ir_analyze_instruction_fn_proto(ira, (IrInstSrcFnProto *)instruction); case IrInstSrcIdTestComptime: return ir_analyze_instruction_test_comptime(ira, (IrInstSrcTestComptime *)instruction); - case IrInstSrcIdCheckSwitchProngs: - return ir_analyze_instruction_check_switch_prongs(ira, (IrInstSrcCheckSwitchProngs *)instruction); + case IrInstSrcIdCheckSwitchProngsUnderNo: + return ir_analyze_instruction_check_switch_prongs(ira, (IrInstSrcCheckSwitchProngs *)instruction, false); + case IrInstSrcIdCheckSwitchProngsUnderYes: + return ir_analyze_instruction_check_switch_prongs(ira, (IrInstSrcCheckSwitchProngs *)instruction, true); case IrInstSrcIdCheckStatementIsVoid: return ir_analyze_instruction_check_statement_is_void(ira, (IrInstSrcCheckStatementIsVoid *)instruction); case IrInstSrcIdDeclRef: @@ -32745,7 +32750,8 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) { case IrInstSrcIdMemcpy: case IrInstSrcIdBreakpoint: case IrInstSrcIdOverflowOp: // TODO when we support multiple returns this can be side effect free - case IrInstSrcIdCheckSwitchProngs: + case IrInstSrcIdCheckSwitchProngsUnderNo: + case IrInstSrcIdCheckSwitchProngsUnderYes: case IrInstSrcIdCheckStatementIsVoid: case IrInstSrcIdCheckRuntimeScope: case IrInstSrcIdPanic: diff --git a/src/stage1/ir_print.cpp b/src/stage1/ir_print.cpp index 6750b6178c..cdbada4f20 100644 --- a/src/stage1/ir_print.cpp +++ b/src/stage1/ir_print.cpp @@ -270,8 +270,10 @@ const char* ir_inst_src_type_str(IrInstSrcId id) { return "SrcIntToErr"; case IrInstSrcIdErrToInt: return "SrcErrToInt"; - case IrInstSrcIdCheckSwitchProngs: - return "SrcCheckSwitchProngs"; + case IrInstSrcIdCheckSwitchProngsUnderNo: + return "SrcCheckSwitchProngsUnderNo"; + case IrInstSrcIdCheckSwitchProngsUnderYes: + return "SrcCheckSwitchProngsUnderYes"; case IrInstSrcIdCheckStatementIsVoid: return "SrcCheckStatementIsVoid"; case IrInstSrcIdTypeName: @@ -2189,7 +2191,9 @@ static void ir_print_err_to_int(IrPrintGen *irp, IrInstGenErrToInt *instruction) ir_print_other_inst_gen(irp, instruction->target); } -static void ir_print_check_switch_prongs(IrPrintSrc *irp, IrInstSrcCheckSwitchProngs *instruction) { +static void ir_print_check_switch_prongs(IrPrintSrc *irp, IrInstSrcCheckSwitchProngs *instruction, + bool have_underscore_prong) +{ fprintf(irp->f, "@checkSwitchProngs("); ir_print_other_inst_src(irp, instruction->target_value); fprintf(irp->f, ","); @@ -2202,6 +2206,8 @@ static void ir_print_check_switch_prongs(IrPrintSrc *irp, IrInstSrcCheckSwitchPr } const char *have_else_str = instruction->else_prong != nullptr ? "yes" : "no"; fprintf(irp->f, ")else:%s", have_else_str); + const char *have_under_str = have_underscore_prong ? "yes" : "no"; + fprintf(irp->f, " _:%s", have_under_str); } static void ir_print_check_statement_is_void(IrPrintSrc *irp, IrInstSrcCheckStatementIsVoid *instruction) { @@ -2893,8 +2899,11 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai case IrInstSrcIdErrToInt: ir_print_err_to_int(irp, (IrInstSrcErrToInt *)instruction); break; - case IrInstSrcIdCheckSwitchProngs: - ir_print_check_switch_prongs(irp, (IrInstSrcCheckSwitchProngs *)instruction); + case IrInstSrcIdCheckSwitchProngsUnderNo: + ir_print_check_switch_prongs(irp, (IrInstSrcCheckSwitchProngs *)instruction, false); + break; + case IrInstSrcIdCheckSwitchProngsUnderYes: + ir_print_check_switch_prongs(irp, (IrInstSrcCheckSwitchProngs *)instruction, true); break; case IrInstSrcIdCheckStatementIsVoid: ir_print_check_statement_is_void(irp, (IrInstSrcCheckStatementIsVoid *)instruction); -- cgit v1.2.3 From 5e5b35f1077d5cf77a89aee5dde939de35f2e247 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 18 Mar 2021 14:03:06 -0700 Subject: stage1: small memory optimization for simple pointer types Avoid storing extra IR instruction data for simple pointer types. --- src/stage1/all_types.hpp | 17 +++++++++ src/stage1/analyze.cpp | 49 +++++++++++++++++++++++- src/stage1/ir.cpp | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ src/stage1/ir_print.cpp | 19 ++++++++++ 4 files changed, 183 insertions(+), 1 deletion(-) (limited to 'src/stage1/ir.cpp') diff --git a/src/stage1/all_types.hpp b/src/stage1/all_types.hpp index e0cbf1c0c5..b1d0bd2ce1 100644 --- a/src/stage1/all_types.hpp +++ b/src/stage1/all_types.hpp @@ -391,6 +391,8 @@ enum LazyValueId { LazyValueIdAlignOf, LazyValueIdSizeOf, LazyValueIdPtrType, + LazyValueIdPtrTypeSimple, + LazyValueIdPtrTypeSimpleConst, LazyValueIdOptType, LazyValueIdSliceType, LazyValueIdFnType, @@ -467,6 +469,13 @@ struct LazyValuePtrType { bool is_allowzero; }; +struct LazyValuePtrTypeSimple { + LazyValue base; + + IrAnalyze *ira; + IrInstGen *elem_type; +}; + struct LazyValueOptType { LazyValue base; @@ -2625,6 +2634,8 @@ enum IrInstSrcId { IrInstSrcIdHasField, IrInstSrcIdSetEvalBranchQuota, IrInstSrcIdPtrType, + IrInstSrcIdPtrTypeSimple, + IrInstSrcIdPtrTypeSimpleConst, IrInstSrcIdAlignCast, IrInstSrcIdImplicitCast, IrInstSrcIdResolveResult, @@ -3296,6 +3307,12 @@ struct IrInstSrcArrayType { IrInstSrc *child_type; }; +struct IrInstSrcPtrTypeSimple { + IrInstSrc base; + + IrInstSrc *child_type; +}; + struct IrInstSrcPtrType { IrInstSrc base; diff --git a/src/stage1/analyze.cpp b/src/stage1/analyze.cpp index a4e368288e..d46faac2f0 100644 --- a/src/stage1/analyze.cpp +++ b/src/stage1/analyze.cpp @@ -1237,6 +1237,22 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent parent_type_val, is_zero_bits); } } + case LazyValueIdPtrTypeSimple: + case LazyValueIdPtrTypeSimpleConst: { + LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast(type_val->data.x_lazy); + + if (parent_type_val == lazy_ptr_type->elem_type->value) { + // Does a struct which contains a pointer field to itself have bits? Yes. + *is_zero_bits = false; + return ErrorNone; + } else { + if (parent_type_val == nullptr) { + parent_type_val = type_val; + } + return type_val_resolve_zero_bits(g, lazy_ptr_type->elem_type->value, parent_type, + parent_type_val, is_zero_bits); + } + } case LazyValueIdArrayType: { LazyValueArrayType *lazy_array_type = reinterpret_cast(type_val->data.x_lazy); @@ -1285,6 +1301,8 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ZigValue *type_val, bool *is_o zig_unreachable(); case LazyValueIdSliceType: case LazyValueIdPtrType: + case LazyValueIdPtrTypeSimple: + case LazyValueIdPtrTypeSimpleConst: case LazyValueIdFnType: case LazyValueIdOptType: case LazyValueIdErrUnionType: @@ -1313,6 +1331,11 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ZigValue *type LazyValuePtrType *lazy_ptr_type = reinterpret_cast(type_val->data.x_lazy); return type_val_resolve_requires_comptime(g, lazy_ptr_type->elem_type->value); } + case LazyValueIdPtrTypeSimple: + case LazyValueIdPtrTypeSimpleConst: { + LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast(type_val->data.x_lazy); + return type_val_resolve_requires_comptime(g, lazy_ptr_type->elem_type->value); + } case LazyValueIdOptType: { LazyValueOptType *lazy_opt_type = reinterpret_cast(type_val->data.x_lazy); return type_val_resolve_requires_comptime(g, lazy_opt_type->payload_type->value); @@ -1413,6 +1436,24 @@ start_over: } return ErrorNone; } + case LazyValueIdPtrTypeSimple: + case LazyValueIdPtrTypeSimpleConst: { + LazyValuePtrTypeSimple *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; @@ -1449,6 +1490,8 @@ Error type_val_resolve_abi_align(CodeGen *g, AstNode *source_node, ZigValue *typ zig_unreachable(); case LazyValueIdSliceType: case LazyValueIdPtrType: + case LazyValueIdPtrTypeSimple: + case LazyValueIdPtrTypeSimpleConst: case LazyValueIdFnType: *abi_align = g->builtin_types.entry_usize->abi_align; return ErrorNone; @@ -1506,7 +1549,9 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV return OnePossibleValueYes; return type_val_resolve_has_one_possible_value(g, lazy_array_type->elem_type->value); } - case LazyValueIdPtrType: { + case LazyValueIdPtrType: + case LazyValueIdPtrTypeSimple: + case LazyValueIdPtrTypeSimpleConst: { Error err; bool zero_bits; if ((err = type_val_resolve_zero_bits(g, type_val, nullptr, nullptr, &zero_bits))) { @@ -5758,6 +5803,8 @@ static bool can_mutate_comptime_var_state(ZigValue *value) { case LazyValueIdAlignOf: case LazyValueIdSizeOf: case LazyValueIdPtrType: + case LazyValueIdPtrTypeSimple: + case LazyValueIdPtrTypeSimpleConst: case LazyValueIdOptType: case LazyValueIdSliceType: case LazyValueIdFnType: diff --git a/src/stage1/ir.cpp b/src/stage1/ir.cpp index ad45d7682c..16536dc71f 100644 --- a/src/stage1/ir.cpp +++ b/src/stage1/ir.cpp @@ -487,6 +487,9 @@ static void destroy_instruction_src(IrInstSrc *inst) { return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdPtrType: return heap::c_allocator.destroy(reinterpret_cast(inst)); + case IrInstSrcIdPtrTypeSimple: + case IrInstSrcIdPtrTypeSimpleConst: + return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdDeclRef: return heap::c_allocator.destroy(reinterpret_cast(inst)); case IrInstSrcIdPanic: @@ -2609,11 +2612,35 @@ static IrInstGen *ir_build_br_gen(IrAnalyze *ira, IrInst *source_instr, IrBasicB return &inst->base; } +static IrInstSrc *ir_build_ptr_type_simple(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, + IrInstSrc *child_type, bool is_const) +{ + IrInstSrcPtrTypeSimple *inst = heap::c_allocator.create(); + inst->base.id = is_const ? IrInstSrcIdPtrTypeSimpleConst : IrInstSrcIdPtrTypeSimple; + inst->base.base.scope = scope; + inst->base.base.source_node = source_node; + inst->base.base.debug_id = exec_next_debug_id(irb->exec); + inst->base.owner_bb = irb->current_basic_block; + ir_instruction_append(irb->current_basic_block, &inst->base); + + inst->child_type = child_type; + + ir_ref_instruction(child_type, irb->current_basic_block); + + return &inst->base; +} + static IrInstSrc *ir_build_ptr_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, IrInstSrc *child_type, bool is_const, bool is_volatile, PtrLen ptr_len, IrInstSrc *sentinel, IrInstSrc *align_value, uint32_t bit_offset_start, uint32_t host_int_bytes, bool is_allow_zero) { + if (!is_volatile && ptr_len == PtrLenSingle && sentinel == nullptr && align_value == nullptr && + bit_offset_start == 0 && host_int_bytes == 0 && is_allow_zero == 0) + { + return ir_build_ptr_type_simple(irb, scope, source_node, child_type, is_const); + } + IrInstSrcPtrType *inst = ir_build_instruction(irb, scope, source_node); inst->sentinel = sentinel; inst->align_value = align_value; @@ -30878,6 +30905,24 @@ static IrInstGen *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstSrcPtr return ir_build_ptr_to_int_gen(ira, &instruction->base.base, target); } +static IrInstGen *ir_analyze_instruction_ptr_type_simple(IrAnalyze *ira, + IrInstSrcPtrTypeSimple *instruction, bool is_const) +{ + IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_type); + result->value->special = ConstValSpecialLazy; + + LazyValuePtrTypeSimple *lazy_ptr_type = heap::c_allocator.create(); + lazy_ptr_type->ira = ira; ira_ref(ira); + result->value->data.x_lazy = &lazy_ptr_type->base; + lazy_ptr_type->base.id = is_const ? LazyValueIdPtrTypeSimpleConst : LazyValueIdPtrTypeSimple; + + lazy_ptr_type->elem_type = instruction->child_type->child; + if (ir_resolve_type_lazy(ira, lazy_ptr_type->elem_type) == nullptr) + return ira->codegen->invalid_inst_gen; + + return result; +} + static IrInstGen *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstSrcPtrType *instruction) { IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_type); result->value->special = ConstValSpecialLazy; @@ -32384,6 +32429,10 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc return ir_analyze_instruction_set_eval_branch_quota(ira, (IrInstSrcSetEvalBranchQuota *)instruction); case IrInstSrcIdPtrType: return ir_analyze_instruction_ptr_type(ira, (IrInstSrcPtrType *)instruction); + case IrInstSrcIdPtrTypeSimple: + return ir_analyze_instruction_ptr_type_simple(ira, (IrInstSrcPtrTypeSimple *)instruction, false); + case IrInstSrcIdPtrTypeSimpleConst: + return ir_analyze_instruction_ptr_type_simple(ira, (IrInstSrcPtrTypeSimple *)instruction, true); case IrInstSrcIdAlignCast: return ir_analyze_instruction_align_cast(ira, (IrInstSrcAlignCast *)instruction); case IrInstSrcIdImplicitCast: @@ -32757,6 +32806,8 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) { case IrInstSrcIdPanic: case IrInstSrcIdSetEvalBranchQuota: case IrInstSrcIdPtrType: + case IrInstSrcIdPtrTypeSimple: + case IrInstSrcIdPtrTypeSimpleConst: case IrInstSrcIdSetAlignStack: case IrInstSrcIdExport: case IrInstSrcIdExtern: @@ -33264,6 +33315,54 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. return ErrorNone; } + case LazyValueIdPtrTypeSimple: { + LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast(val->data.x_lazy); + IrAnalyze *ira = lazy_ptr_type->ira; + + ZigType *elem_type = ir_resolve_type(ira, lazy_ptr_type->elem_type); + if (type_is_invalid(elem_type)) + return ErrorSemanticAnalyzeFail; + + if (elem_type->id == ZigTypeIdUnreachable) { + ir_add_error(ira, &lazy_ptr_type->elem_type->base, + buf_create_from_str("pointer to noreturn not allowed")); + return ErrorSemanticAnalyzeFail; + } + + assert(val->type->id == ZigTypeIdMetaType); + val->data.x_type = get_pointer_to_type_extra2(ira->codegen, elem_type, + false, false, PtrLenSingle, 0, + 0, 0, + false, VECTOR_INDEX_NONE, nullptr, nullptr); + val->special = ConstValSpecialStatic; + + // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. + return ErrorNone; + } + case LazyValueIdPtrTypeSimpleConst: { + LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast(val->data.x_lazy); + IrAnalyze *ira = lazy_ptr_type->ira; + + ZigType *elem_type = ir_resolve_type(ira, lazy_ptr_type->elem_type); + if (type_is_invalid(elem_type)) + return ErrorSemanticAnalyzeFail; + + if (elem_type->id == ZigTypeIdUnreachable) { + ir_add_error(ira, &lazy_ptr_type->elem_type->base, + buf_create_from_str("pointer to noreturn not allowed")); + return ErrorSemanticAnalyzeFail; + } + + assert(val->type->id == ZigTypeIdMetaType); + val->data.x_type = get_pointer_to_type_extra2(ira->codegen, elem_type, + true, false, PtrLenSingle, 0, + 0, 0, + false, VECTOR_INDEX_NONE, nullptr, nullptr); + val->special = ConstValSpecialStatic; + + // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. + return ErrorNone; + } case LazyValueIdArrayType: { LazyValueArrayType *lazy_array_type = reinterpret_cast(val->data.x_lazy); IrAnalyze *ira = lazy_array_type->ira; diff --git a/src/stage1/ir_print.cpp b/src/stage1/ir_print.cpp index cdbada4f20..22b6c1ed5f 100644 --- a/src/stage1/ir_print.cpp +++ b/src/stage1/ir_print.cpp @@ -300,6 +300,10 @@ const char* ir_inst_src_type_str(IrInstSrcId id) { return "SrcSetEvalBranchQuota"; case IrInstSrcIdPtrType: return "SrcPtrType"; + case IrInstSrcIdPtrTypeSimple: + return "SrcPtrTypeSimple"; + case IrInstSrcIdPtrTypeSimpleConst: + return "SrcPtrTypeSimpleConst"; case IrInstSrcIdAlignCast: return "SrcAlignCast"; case IrInstSrcIdImplicitCast: @@ -2245,6 +2249,15 @@ static void ir_print_ptr_type(IrPrintSrc *irp, IrInstSrcPtrType *instruction) { ir_print_other_inst_src(irp, instruction->child_type); } +static void ir_print_ptr_type_simple(IrPrintSrc *irp, IrInstSrcPtrTypeSimple *instruction, + bool is_const) +{ + fprintf(irp->f, "&"); + const char *const_str = is_const ? "const " : ""; + fprintf(irp->f, "*%s", const_str); + ir_print_other_inst_src(irp, instruction->child_type); +} + static void ir_print_decl_ref(IrPrintSrc *irp, IrInstSrcDeclRef *instruction) { const char *ptr_str = (instruction->lval != LValNone) ? "ptr " : ""; fprintf(irp->f, "declref %s%s", ptr_str, buf_ptr(instruction->tld->name)); @@ -2917,6 +2930,12 @@ static void ir_print_inst_src(IrPrintSrc *irp, IrInstSrc *instruction, bool trai case IrInstSrcIdPtrType: ir_print_ptr_type(irp, (IrInstSrcPtrType *)instruction); break; + case IrInstSrcIdPtrTypeSimple: + ir_print_ptr_type_simple(irp, (IrInstSrcPtrTypeSimple *)instruction, false); + break; + case IrInstSrcIdPtrTypeSimpleConst: + ir_print_ptr_type_simple(irp, (IrInstSrcPtrTypeSimple *)instruction, true); + break; case IrInstSrcIdDeclRef: ir_print_decl_ref(irp, (IrInstSrcDeclRef *)instruction); break; -- cgit v1.2.3