| author | |
| committer | |
| log | 5e5b35f1077d5cf77a89aee5dde939de35f2e247 |
| tree | bdc9a4d88d63c21f1d482724291d627eea6a3d73 |
| parent | a6f5aa71ac1e8c9a27ecfa6a50f0445a50545a5d |
Avoid storing extra IR instruction data for simple pointer types.4 files changed, 183 insertions(+), 1 deletions(-)
src/stage1/all_types.hpp+17| ... | ... | @@ -391,6 +391,8 @@ enum LazyValueId { |
| 391 | 391 | LazyValueIdAlignOf, |
| 392 | 392 | LazyValueIdSizeOf, |
| 393 | 393 | LazyValueIdPtrType, |
| 394 | LazyValueIdPtrTypeSimple, | |
| 395 | LazyValueIdPtrTypeSimpleConst, | |
| 394 | 396 | LazyValueIdOptType, |
| 395 | 397 | LazyValueIdSliceType, |
| 396 | 398 | LazyValueIdFnType, |
| ... | ... | @@ -467,6 +469,13 @@ struct LazyValuePtrType { |
| 467 | 469 | bool is_allowzero; |
| 468 | 470 | }; |
| 469 | 471 | |
| 472 | struct LazyValuePtrTypeSimple { | |
| 473 | LazyValue base; | |
| 474 | ||
| 475 | IrAnalyze *ira; | |
| 476 | IrInstGen *elem_type; | |
| 477 | }; | |
| 478 | ||
| 470 | 479 | struct LazyValueOptType { |
| 471 | 480 | LazyValue base; |
| 472 | 481 | |
| ... | ... | @@ -2625,6 +2634,8 @@ enum IrInstSrcId { |
| 2625 | 2634 | IrInstSrcIdHasField, |
| 2626 | 2635 | IrInstSrcIdSetEvalBranchQuota, |
| 2627 | 2636 | IrInstSrcIdPtrType, |
| 2637 | IrInstSrcIdPtrTypeSimple, | |
| 2638 | IrInstSrcIdPtrTypeSimpleConst, | |
| 2628 | 2639 | IrInstSrcIdAlignCast, |
| 2629 | 2640 | IrInstSrcIdImplicitCast, |
| 2630 | 2641 | IrInstSrcIdResolveResult, |
| ... | ... | @@ -3296,6 +3307,12 @@ struct IrInstSrcArrayType { |
| 3296 | 3307 | IrInstSrc *child_type; |
| 3297 | 3308 | }; |
| 3298 | 3309 | |
| 3310 | struct IrInstSrcPtrTypeSimple { | |
| 3311 | IrInstSrc base; | |
| 3312 | ||
| 3313 | IrInstSrc *child_type; | |
| 3314 | }; | |
| 3315 | ||
| 3299 | 3316 | struct IrInstSrcPtrType { |
| 3300 | 3317 | IrInstSrc base; |
| 3301 | 3318 |
src/stage1/analyze.cpp+48-1| ... | ... | @@ -1237,6 +1237,22 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent |
| 1237 | 1237 | parent_type_val, is_zero_bits); |
| 1238 | 1238 | } |
| 1239 | 1239 | } |
| 1240 | case LazyValueIdPtrTypeSimple: | |
| 1241 | case LazyValueIdPtrTypeSimpleConst: { | |
| 1242 | LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(type_val->data.x_lazy); | |
| 1243 | ||
| 1244 | if (parent_type_val == lazy_ptr_type->elem_type->value) { | |
| 1245 | // Does a struct which contains a pointer field to itself have bits? Yes. | |
| 1246 | *is_zero_bits = false; | |
| 1247 | return ErrorNone; | |
| 1248 | } else { | |
| 1249 | if (parent_type_val == nullptr) { | |
| 1250 | parent_type_val = type_val; | |
| 1251 | } | |
| 1252 | return type_val_resolve_zero_bits(g, lazy_ptr_type->elem_type->value, parent_type, | |
| 1253 | parent_type_val, is_zero_bits); | |
| 1254 | } | |
| 1255 | } | |
| 1240 | 1256 | case LazyValueIdArrayType: { |
| 1241 | 1257 | LazyValueArrayType *lazy_array_type = |
| 1242 | 1258 | reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy); |
| ... | ... | @@ -1285,6 +1301,8 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ZigValue *type_val, bool *is_o |
| 1285 | 1301 | zig_unreachable(); |
| 1286 | 1302 | case LazyValueIdSliceType: |
| 1287 | 1303 | case LazyValueIdPtrType: |
| 1304 | case LazyValueIdPtrTypeSimple: | |
| 1305 | case LazyValueIdPtrTypeSimpleConst: | |
| 1288 | 1306 | case LazyValueIdFnType: |
| 1289 | 1307 | case LazyValueIdOptType: |
| 1290 | 1308 | case LazyValueIdErrUnionType: |
| ... | ... | @@ -1313,6 +1331,11 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ZigValue *type |
| 1313 | 1331 | LazyValuePtrType *lazy_ptr_type = reinterpret_cast<LazyValuePtrType *>(type_val->data.x_lazy); |
| 1314 | 1332 | return type_val_resolve_requires_comptime(g, lazy_ptr_type->elem_type->value); |
| 1315 | 1333 | } |
| 1334 | case LazyValueIdPtrTypeSimple: | |
| 1335 | case LazyValueIdPtrTypeSimpleConst: { | |
| 1336 | LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(type_val->data.x_lazy); | |
| 1337 | return type_val_resolve_requires_comptime(g, lazy_ptr_type->elem_type->value); | |
| 1338 | } | |
| 1316 | 1339 | case LazyValueIdOptType: { |
| 1317 | 1340 | LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy); |
| 1318 | 1341 | return type_val_resolve_requires_comptime(g, lazy_opt_type->payload_type->value); |
| ... | ... | @@ -1413,6 +1436,24 @@ start_over: |
| 1413 | 1436 | } |
| 1414 | 1437 | return ErrorNone; |
| 1415 | 1438 | } |
| 1439 | case LazyValueIdPtrTypeSimple: | |
| 1440 | case LazyValueIdPtrTypeSimpleConst: { | |
| 1441 | LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(type_val->data.x_lazy); | |
| 1442 | bool is_zero_bits; | |
| 1443 | if ((err = type_val_resolve_zero_bits(g, lazy_ptr_type->elem_type->value, nullptr, | |
| 1444 | nullptr, &is_zero_bits))) | |
| 1445 | { | |
| 1446 | return err; | |
| 1447 | } | |
| 1448 | if (is_zero_bits) { | |
| 1449 | *abi_size = 0; | |
| 1450 | *size_in_bits = 0; | |
| 1451 | } else { | |
| 1452 | *abi_size = g->builtin_types.entry_usize->abi_size; | |
| 1453 | *size_in_bits = g->builtin_types.entry_usize->size_in_bits; | |
| 1454 | } | |
| 1455 | return ErrorNone; | |
| 1456 | } | |
| 1416 | 1457 | case LazyValueIdFnType: |
| 1417 | 1458 | *abi_size = g->builtin_types.entry_usize->abi_size; |
| 1418 | 1459 | *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 |
| 1449 | 1490 | zig_unreachable(); |
| 1450 | 1491 | case LazyValueIdSliceType: |
| 1451 | 1492 | case LazyValueIdPtrType: |
| 1493 | case LazyValueIdPtrTypeSimple: | |
| 1494 | case LazyValueIdPtrTypeSimpleConst: | |
| 1452 | 1495 | case LazyValueIdFnType: |
| 1453 | 1496 | *abi_align = g->builtin_types.entry_usize->abi_align; |
| 1454 | 1497 | return ErrorNone; |
| ... | ... | @@ -1506,7 +1549,9 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV |
| 1506 | 1549 | return OnePossibleValueYes; |
| 1507 | 1550 | return type_val_resolve_has_one_possible_value(g, lazy_array_type->elem_type->value); |
| 1508 | 1551 | } |
| 1509 | case LazyValueIdPtrType: { | |
| 1552 | case LazyValueIdPtrType: | |
| 1553 | case LazyValueIdPtrTypeSimple: | |
| 1554 | case LazyValueIdPtrTypeSimpleConst: { | |
| 1510 | 1555 | Error err; |
| 1511 | 1556 | bool zero_bits; |
| 1512 | 1557 | 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) { |
| 5758 | 5803 | case LazyValueIdAlignOf: |
| 5759 | 5804 | case LazyValueIdSizeOf: |
| 5760 | 5805 | case LazyValueIdPtrType: |
| 5806 | case LazyValueIdPtrTypeSimple: | |
| 5807 | case LazyValueIdPtrTypeSimpleConst: | |
| 5761 | 5808 | case LazyValueIdOptType: |
| 5762 | 5809 | case LazyValueIdSliceType: |
| 5763 | 5810 | case LazyValueIdFnType: |
src/stage1/ir.cpp+99| ... | ... | @@ -487,6 +487,9 @@ static void destroy_instruction_src(IrInstSrc *inst) { |
| 487 | 487 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcTagName *>(inst)); |
| 488 | 488 | case IrInstSrcIdPtrType: |
| 489 | 489 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPtrType *>(inst)); |
| 490 | case IrInstSrcIdPtrTypeSimple: | |
| 491 | case IrInstSrcIdPtrTypeSimpleConst: | |
| 492 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcPtrTypeSimple *>(inst)); | |
| 490 | 493 | case IrInstSrcIdDeclRef: |
| 491 | 494 | return heap::c_allocator.destroy(reinterpret_cast<IrInstSrcDeclRef *>(inst)); |
| 492 | 495 | case IrInstSrcIdPanic: |
| ... | ... | @@ -2609,11 +2612,35 @@ static IrInstGen *ir_build_br_gen(IrAnalyze *ira, IrInst *source_instr, IrBasicB |
| 2609 | 2612 | return &inst->base; |
| 2610 | 2613 | } |
| 2611 | 2614 | |
| 2615 | static IrInstSrc *ir_build_ptr_type_simple(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, | |
| 2616 | IrInstSrc *child_type, bool is_const) | |
| 2617 | { | |
| 2618 | IrInstSrcPtrTypeSimple *inst = heap::c_allocator.create<IrInstSrcPtrTypeSimple>(); | |
| 2619 | inst->base.id = is_const ? IrInstSrcIdPtrTypeSimpleConst : IrInstSrcIdPtrTypeSimple; | |
| 2620 | inst->base.base.scope = scope; | |
| 2621 | inst->base.base.source_node = source_node; | |
| 2622 | inst->base.base.debug_id = exec_next_debug_id(irb->exec); | |
| 2623 | inst->base.owner_bb = irb->current_basic_block; | |
| 2624 | ir_instruction_append(irb->current_basic_block, &inst->base); | |
| 2625 | ||
| 2626 | inst->child_type = child_type; | |
| 2627 | ||
| 2628 | ir_ref_instruction(child_type, irb->current_basic_block); | |
| 2629 | ||
| 2630 | return &inst->base; | |
| 2631 | } | |
| 2632 | ||
| 2612 | 2633 | static IrInstSrc *ir_build_ptr_type(IrBuilderSrc *irb, Scope *scope, AstNode *source_node, |
| 2613 | 2634 | IrInstSrc *child_type, bool is_const, bool is_volatile, PtrLen ptr_len, |
| 2614 | 2635 | IrInstSrc *sentinel, IrInstSrc *align_value, |
| 2615 | 2636 | uint32_t bit_offset_start, uint32_t host_int_bytes, bool is_allow_zero) |
| 2616 | 2637 | { |
| 2638 | if (!is_volatile && ptr_len == PtrLenSingle && sentinel == nullptr && align_value == nullptr && | |
| 2639 | bit_offset_start == 0 && host_int_bytes == 0 && is_allow_zero == 0) | |
| 2640 | { | |
| 2641 | return ir_build_ptr_type_simple(irb, scope, source_node, child_type, is_const); | |
| 2642 | } | |
| 2643 | ||
| 2617 | 2644 | IrInstSrcPtrType *inst = ir_build_instruction<IrInstSrcPtrType>(irb, scope, source_node); |
| 2618 | 2645 | inst->sentinel = sentinel; |
| 2619 | 2646 | inst->align_value = align_value; |
| ... | ... | @@ -30878,6 +30905,24 @@ static IrInstGen *ir_analyze_instruction_ptr_to_int(IrAnalyze *ira, IrInstSrcPtr |
| 30878 | 30905 | return ir_build_ptr_to_int_gen(ira, &instruction->base.base, target); |
| 30879 | 30906 | } |
| 30880 | 30907 | |
| 30908 | static IrInstGen *ir_analyze_instruction_ptr_type_simple(IrAnalyze *ira, | |
| 30909 | IrInstSrcPtrTypeSimple *instruction, bool is_const) | |
| 30910 | { | |
| 30911 | IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_type); | |
| 30912 | result->value->special = ConstValSpecialLazy; | |
| 30913 | ||
| 30914 | LazyValuePtrTypeSimple *lazy_ptr_type = heap::c_allocator.create<LazyValuePtrTypeSimple>(); | |
| 30915 | lazy_ptr_type->ira = ira; ira_ref(ira); | |
| 30916 | result->value->data.x_lazy = &lazy_ptr_type->base; | |
| 30917 | lazy_ptr_type->base.id = is_const ? LazyValueIdPtrTypeSimpleConst : LazyValueIdPtrTypeSimple; | |
| 30918 | ||
| 30919 | lazy_ptr_type->elem_type = instruction->child_type->child; | |
| 30920 | if (ir_resolve_type_lazy(ira, lazy_ptr_type->elem_type) == nullptr) | |
| 30921 | return ira->codegen->invalid_inst_gen; | |
| 30922 | ||
| 30923 | return result; | |
| 30924 | } | |
| 30925 | ||
| 30881 | 30926 | static IrInstGen *ir_analyze_instruction_ptr_type(IrAnalyze *ira, IrInstSrcPtrType *instruction) { |
| 30882 | 30927 | IrInstGen *result = ir_const(ira, &instruction->base.base, ira->codegen->builtin_types.entry_type); |
| 30883 | 30928 | result->value->special = ConstValSpecialLazy; |
| ... | ... | @@ -32384,6 +32429,10 @@ static IrInstGen *ir_analyze_instruction_base(IrAnalyze *ira, IrInstSrc *instruc |
| 32384 | 32429 | return ir_analyze_instruction_set_eval_branch_quota(ira, (IrInstSrcSetEvalBranchQuota *)instruction); |
| 32385 | 32430 | case IrInstSrcIdPtrType: |
| 32386 | 32431 | return ir_analyze_instruction_ptr_type(ira, (IrInstSrcPtrType *)instruction); |
| 32432 | case IrInstSrcIdPtrTypeSimple: | |
| 32433 | return ir_analyze_instruction_ptr_type_simple(ira, (IrInstSrcPtrTypeSimple *)instruction, false); | |
| 32434 | case IrInstSrcIdPtrTypeSimpleConst: | |
| 32435 | return ir_analyze_instruction_ptr_type_simple(ira, (IrInstSrcPtrTypeSimple *)instruction, true); | |
| 32387 | 32436 | case IrInstSrcIdAlignCast: |
| 32388 | 32437 | return ir_analyze_instruction_align_cast(ira, (IrInstSrcAlignCast *)instruction); |
| 32389 | 32438 | case IrInstSrcIdImplicitCast: |
| ... | ... | @@ -32757,6 +32806,8 @@ bool ir_inst_src_has_side_effects(IrInstSrc *instruction) { |
| 32757 | 32806 | case IrInstSrcIdPanic: |
| 32758 | 32807 | case IrInstSrcIdSetEvalBranchQuota: |
| 32759 | 32808 | case IrInstSrcIdPtrType: |
| 32809 | case IrInstSrcIdPtrTypeSimple: | |
| 32810 | case IrInstSrcIdPtrTypeSimpleConst: | |
| 32760 | 32811 | case IrInstSrcIdSetAlignStack: |
| 32761 | 32812 | case IrInstSrcIdExport: |
| 32762 | 32813 | case IrInstSrcIdExtern: |
| ... | ... | @@ -33264,6 +33315,54 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) { |
| 33264 | 33315 | // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. |
| 33265 | 33316 | return ErrorNone; |
| 33266 | 33317 | } |
| 33318 | case LazyValueIdPtrTypeSimple: { | |
| 33319 | LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(val->data.x_lazy); | |
| 33320 | IrAnalyze *ira = lazy_ptr_type->ira; | |
| 33321 | ||
| 33322 | ZigType *elem_type = ir_resolve_type(ira, lazy_ptr_type->elem_type); | |
| 33323 | if (type_is_invalid(elem_type)) | |
| 33324 | return ErrorSemanticAnalyzeFail; | |
| 33325 | ||
| 33326 | if (elem_type->id == ZigTypeIdUnreachable) { | |
| 33327 | ir_add_error(ira, &lazy_ptr_type->elem_type->base, | |
| 33328 | buf_create_from_str("pointer to noreturn not allowed")); | |
| 33329 | return ErrorSemanticAnalyzeFail; | |
| 33330 | } | |
| 33331 | ||
| 33332 | assert(val->type->id == ZigTypeIdMetaType); | |
| 33333 | val->data.x_type = get_pointer_to_type_extra2(ira->codegen, elem_type, | |
| 33334 | false, false, PtrLenSingle, 0, | |
| 33335 | 0, 0, | |
| 33336 | false, VECTOR_INDEX_NONE, nullptr, nullptr); | |
| 33337 | val->special = ConstValSpecialStatic; | |
| 33338 | ||
| 33339 | // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. | |
| 33340 | return ErrorNone; | |
| 33341 | } | |
| 33342 | case LazyValueIdPtrTypeSimpleConst: { | |
| 33343 | LazyValuePtrTypeSimple *lazy_ptr_type = reinterpret_cast<LazyValuePtrTypeSimple *>(val->data.x_lazy); | |
| 33344 | IrAnalyze *ira = lazy_ptr_type->ira; | |
| 33345 | ||
| 33346 | ZigType *elem_type = ir_resolve_type(ira, lazy_ptr_type->elem_type); | |
| 33347 | if (type_is_invalid(elem_type)) | |
| 33348 | return ErrorSemanticAnalyzeFail; | |
| 33349 | ||
| 33350 | if (elem_type->id == ZigTypeIdUnreachable) { | |
| 33351 | ir_add_error(ira, &lazy_ptr_type->elem_type->base, | |
| 33352 | buf_create_from_str("pointer to noreturn not allowed")); | |
| 33353 | return ErrorSemanticAnalyzeFail; | |
| 33354 | } | |
| 33355 | ||
| 33356 | assert(val->type->id == ZigTypeIdMetaType); | |
| 33357 | val->data.x_type = get_pointer_to_type_extra2(ira->codegen, elem_type, | |
| 33358 | true, false, PtrLenSingle, 0, | |
| 33359 | 0, 0, | |
| 33360 | false, VECTOR_INDEX_NONE, nullptr, nullptr); | |
| 33361 | val->special = ConstValSpecialStatic; | |
| 33362 | ||
| 33363 | // We can't free the lazy value here, because multiple other ZigValues might be pointing to it. | |
| 33364 | return ErrorNone; | |
| 33365 | } | |
| 33267 | 33366 | case LazyValueIdArrayType: { |
| 33268 | 33367 | LazyValueArrayType *lazy_array_type = reinterpret_cast<LazyValueArrayType *>(val->data.x_lazy); |
| 33269 | 33368 | IrAnalyze *ira = lazy_array_type->ira; |
src/stage1/ir_print.cpp+19| ... | ... | @@ -300,6 +300,10 @@ const char* ir_inst_src_type_str(IrInstSrcId id) { |
| 300 | 300 | return "SrcSetEvalBranchQuota"; |
| 301 | 301 | case IrInstSrcIdPtrType: |
| 302 | 302 | return "SrcPtrType"; |
| 303 | case IrInstSrcIdPtrTypeSimple: | |
| 304 | return "SrcPtrTypeSimple"; | |
| 305 | case IrInstSrcIdPtrTypeSimpleConst: | |
| 306 | return "SrcPtrTypeSimpleConst"; | |
| 303 | 307 | case IrInstSrcIdAlignCast: |
| 304 | 308 | return "SrcAlignCast"; |
| 305 | 309 | case IrInstSrcIdImplicitCast: |
| ... | ... | @@ -2245,6 +2249,15 @@ static void ir_print_ptr_type(IrPrintSrc *irp, IrInstSrcPtrType *instruction) { |
| 2245 | 2249 | ir_print_other_inst_src(irp, instruction->child_type); |
| 2246 | 2250 | } |
| 2247 | 2251 | |
| 2252 | static void ir_print_ptr_type_simple(IrPrintSrc *irp, IrInstSrcPtrTypeSimple *instruction, | |
| 2253 | bool is_const) | |
| 2254 | { | |
| 2255 | fprintf(irp->f, "&"); | |
| 2256 | const char *const_str = is_const ? "const " : ""; | |
| 2257 | fprintf(irp->f, "*%s", const_str); | |
| 2258 | ir_print_other_inst_src(irp, instruction->child_type); | |
| 2259 | } | |
| 2260 | ||
| 2248 | 2261 | static void ir_print_decl_ref(IrPrintSrc *irp, IrInstSrcDeclRef *instruction) { |
| 2249 | 2262 | const char *ptr_str = (instruction->lval != LValNone) ? "ptr " : ""; |
| 2250 | 2263 | 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 |
| 2917 | 2930 | case IrInstSrcIdPtrType: |
| 2918 | 2931 | ir_print_ptr_type(irp, (IrInstSrcPtrType *)instruction); |
| 2919 | 2932 | break; |
| 2933 | case IrInstSrcIdPtrTypeSimple: | |
| 2934 | ir_print_ptr_type_simple(irp, (IrInstSrcPtrTypeSimple *)instruction, false); | |
| 2935 | break; | |
| 2936 | case IrInstSrcIdPtrTypeSimpleConst: | |
| 2937 | ir_print_ptr_type_simple(irp, (IrInstSrcPtrTypeSimple *)instruction, true); | |
| 2938 | break; | |
| 2920 | 2939 | case IrInstSrcIdDeclRef: |
| 2921 | 2940 | ir_print_decl_ref(irp, (IrInstSrcDeclRef *)instruction); |
| 2922 | 2941 | break; |