authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-03-18 11:24:58-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2017-03-18 11:28:43-04:00
logfa7c64ccd511703fef9971c4d07c447c9aeda49c
tree6f41eb742160ec1584b6adb719ec1327f9e3c831
parentaf536ac343564e5120f99cbf3b7fc9efa984eb93

lazy analysis of top level declarations

previously, we had lazy analysis of top level declarations, but if a declaration was referenced within a compile-time if or switch statement, that would still add the top level declaration to the resolution queue. now we have a declref ir instruction, which is only resolved if we analyze the instruction. this takes into account comptime branching. closes #270

4 files changed, 127 insertions(+), 55 deletions(-)

src/all_types.hpp+14
......@@ -1610,6 +1610,12 @@ struct IrBasicBlock {
16101610 IrInstruction *must_be_comptime_source_instr;
16111611};
16121612
1613struct LVal {
1614 bool is_ptr;
1615 bool is_const;
1616 bool is_volatile;
1617};
1618
16131619enum IrInstructionId {
16141620 IrInstructionIdInvalid,
16151621 IrInstructionIdBr,
......@@ -1701,6 +1707,7 @@ enum IrInstructionId {
17011707 IrInstructionIdCanImplicitCast,
17021708 IrInstructionIdSetGlobalAlign,
17031709 IrInstructionIdSetGlobalSection,
1710 IrInstructionIdDeclRef,
17041711};
17051712
17061713struct IrInstruction {
......@@ -2421,6 +2428,13 @@ struct IrInstructionSetGlobalSection {
24212428 IrInstruction *value;
24222429};
24232430
2431struct IrInstructionDeclRef {
2432 IrInstruction base;
2433
2434 Tld *tld;
2435 LVal lval;
2436};
2437
24242438static const size_t slice_ptr_index = 0;
24252439static const size_t slice_len_index = 1;
24262440
src/codegen.cpp+1
......@@ -2519,6 +2519,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
25192519 case IrInstructionIdCanImplicitCast:
25202520 case IrInstructionIdSetGlobalAlign:
25212521 case IrInstructionIdSetGlobalSection:
2522 case IrInstructionIdDeclRef:
25222523 zig_unreachable();
25232524 case IrInstructionIdReturn:
25242525 return ir_render_return(g, executable, (IrInstructionReturn *)instruction);
src/ir.cpp+102-55
......@@ -44,12 +44,6 @@ struct IrAnalyze {
4444 IrBasicBlock *const_predecessor_bb;
4545};
4646
47struct LVal {
48 bool is_ptr;
49 bool is_const;
50 bool is_volatile;
51};
52
5347static const LVal LVAL_NONE = { false, false, false };
5448static const LVal LVAL_PTR = { true, false, false };
5549
......@@ -534,6 +528,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionSetGlobalSection
534528 return IrInstructionIdSetGlobalSection;
535529}
536530
531static constexpr IrInstructionId ir_instruction_id(IrInstructionDeclRef *) {
532 return IrInstructionIdDeclRef;
533}
534
537535template<typename T>
538536static T *ir_create_instruction(IrBuilder *irb, Scope *scope, AstNode *source_node) {
539537 T *special_instruction = allocate<T>(1);
......@@ -686,14 +684,20 @@ static IrInstruction *ir_build_const_type(IrBuilder *irb, Scope *scope, AstNode
686684 return instruction;
687685}
688686
689static IrInstruction *ir_build_const_fn(IrBuilder *irb, Scope *scope, AstNode *source_node, FnTableEntry *fn_entry) {
690 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
687static IrInstruction *ir_create_const_fn(IrBuilder *irb, Scope *scope, AstNode *source_node, FnTableEntry *fn_entry) {
688 IrInstructionConst *const_instruction = ir_create_instruction<IrInstructionConst>(irb, scope, source_node);
691689 const_instruction->base.value.type = fn_entry->type_entry;
692690 const_instruction->base.value.special = ConstValSpecialStatic;
693691 const_instruction->base.value.data.x_fn = fn_entry;
694692 return &const_instruction->base;
695693}
696694
695static IrInstruction *ir_build_const_fn(IrBuilder *irb, Scope *scope, AstNode *source_node, FnTableEntry *fn_entry) {
696 IrInstruction *instruction = ir_create_const_fn(irb, scope, source_node, fn_entry);
697 ir_instruction_append(irb->current_basic_block, instruction);
698 return instruction;
699}
700
697701static IrInstruction *ir_build_const_import(IrBuilder *irb, Scope *scope, AstNode *source_node, ImportTableEntry *import) {
698702 IrInstructionConst *const_instruction = ir_build_instruction<IrInstructionConst>(irb, scope, source_node);
699703 const_instruction->base.value.type = irb->codegen->builtin_types.entry_namespace;
......@@ -2088,6 +2092,17 @@ static IrInstruction *ir_build_set_global_section(IrBuilder *irb, Scope *scope,
20882092 return &instruction->base;
20892093}
20902094
2095static IrInstruction *ir_build_decl_ref(IrBuilder *irb, Scope *scope, AstNode *source_node,
2096 Tld *tld, LVal lval)
2097{
2098 IrInstructionDeclRef *instruction = ir_build_instruction<IrInstructionDeclRef>(
2099 irb, scope, source_node);
2100 instruction->tld = tld;
2101 instruction->lval = lval;
2102
2103 return &instruction->base;
2104}
2105
20912106static IrInstruction *ir_instruction_br_get_dep(IrInstructionBr *instruction, size_t index) {
20922107 return nullptr;
20932108}
......@@ -2727,6 +2742,10 @@ static IrInstruction *ir_instruction_setglobalsection_get_dep(IrInstructionSetGl
27272742 }
27282743}
27292744
2745static IrInstruction *ir_instruction_declref_get_dep(IrInstructionDeclRef *instruction, size_t index) {
2746 return nullptr;
2747}
2748
27302749static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t index) {
27312750 switch (instruction->id) {
27322751 case IrInstructionIdInvalid:
......@@ -2909,6 +2928,8 @@ static IrInstruction *ir_instruction_get_dep(IrInstruction *instruction, size_t
29092928 return ir_instruction_setglobalalign_get_dep((IrInstructionSetGlobalAlign *) instruction, index);
29102929 case IrInstructionIdSetGlobalSection:
29112930 return ir_instruction_setglobalsection_get_dep((IrInstructionSetGlobalSection *) instruction, index);
2931 case IrInstructionIdDeclRef:
2932 return ir_instruction_declref_get_dep((IrInstructionDeclRef *) instruction, index);
29122933 }
29132934 zig_unreachable();
29142935}
......@@ -3574,52 +3595,6 @@ static IrInstruction *ir_gen_var_literal(IrBuilder *irb, Scope *scope, AstNode *
35743595 return ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_var);
35753596}
35763597
3577static IrInstruction *ir_gen_decl_ref(IrBuilder *irb, AstNode *source_node, Tld *tld,
3578 LVal lval, Scope *scope)
3579{
3580 resolve_top_level_decl(irb->codegen, tld, lval.is_ptr);
3581 if (tld->resolution == TldResolutionInvalid)
3582 return irb->codegen->invalid_instruction;
3583
3584 switch (tld->id) {
3585 case TldIdContainer:
3586 zig_unreachable();
3587 case TldIdVar:
3588 {
3589 TldVar *tld_var = (TldVar *)tld;
3590 VariableTableEntry *var = tld_var->var;
3591 IrInstruction *var_ptr = ir_build_var_ptr(irb, scope, source_node, var,
3592 !lval.is_ptr || lval.is_const, lval.is_ptr && lval.is_volatile);
3593 if (lval.is_ptr)
3594 return var_ptr;
3595 else
3596 return ir_build_load_ptr(irb, scope, source_node, var_ptr);
3597 }
3598 case TldIdFn:
3599 {
3600 TldFn *tld_fn = (TldFn *)tld;
3601 FnTableEntry *fn_entry = tld_fn->fn_entry;
3602 assert(fn_entry->type_entry);
3603 IrInstruction *ref_instruction = ir_build_const_fn(irb, scope, source_node, fn_entry);
3604 if (lval.is_ptr)
3605 return ir_build_ref(irb, scope, source_node, ref_instruction, true, false);
3606 else
3607 return ref_instruction;
3608 }
3609 case TldIdTypeDef:
3610 {
3611 TldTypeDef *tld_typedef = (TldTypeDef *)tld;
3612 TypeTableEntry *typedef_type = tld_typedef->type_entry;
3613 IrInstruction *ref_instruction = ir_build_const_type(irb, scope, source_node, typedef_type);
3614 if (lval.is_ptr)
3615 return ir_build_ref(irb, scope, source_node, ref_instruction, true, false);
3616 else
3617 return ref_instruction;
3618 }
3619 }
3620 zig_unreachable();
3621}
3622
36233598static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node, LVal lval) {
36243599 assert(node->type == NodeTypeSymbol);
36253600
......@@ -3656,7 +3631,7 @@ static IrInstruction *ir_gen_symbol(IrBuilder *irb, Scope *scope, AstNode *node,
36563631
36573632 Tld *tld = find_decl(irb->codegen, scope, variable_name);
36583633 if (tld)
3659 return ir_gen_decl_ref(irb, node, tld, lval, scope);
3634 return ir_build_decl_ref(irb, scope, node, tld, lval);
36603635
36613636 if (node->owner->any_imports_failed) {
36623637 // skip the error message since we had a failing import in this file
......@@ -12152,6 +12127,75 @@ static TypeTableEntry *ir_analyze_instruction_can_implicit_cast(IrAnalyze *ira,
1215212127 return ira->codegen->builtin_types.entry_bool;
1215312128}
1215412129
12130static TypeTableEntry *ir_analyze_instruction_decl_ref(IrAnalyze *ira,
12131 IrInstructionDeclRef *instruction)
12132{
12133 Tld *tld = instruction->tld;
12134 LVal lval = instruction->lval;
12135
12136 resolve_top_level_decl(ira->codegen, tld, lval.is_ptr);
12137 if (tld->resolution == TldResolutionInvalid)
12138 return ira->codegen->builtin_types.entry_invalid;
12139
12140 switch (tld->id) {
12141 case TldIdContainer:
12142 zig_unreachable();
12143 case TldIdVar:
12144 {
12145 TldVar *tld_var = (TldVar *)tld;
12146 VariableTableEntry *var = tld_var->var;
12147
12148 IrInstruction *var_ptr = ir_get_var_ptr(ira, &instruction->base, var,
12149 !lval.is_ptr || lval.is_const, lval.is_ptr && lval.is_volatile);
12150 if (type_is_invalid(var_ptr->value.type))
12151 return ira->codegen->builtin_types.entry_invalid;
12152
12153 if (lval.is_ptr) {
12154 ir_link_new_instruction(var_ptr, &instruction->base);
12155 return var_ptr->value.type;
12156 } else {
12157 IrInstruction *loaded_instr = ir_get_deref(ira, &instruction->base, var_ptr);
12158 ir_link_new_instruction(loaded_instr, &instruction->base);
12159 return loaded_instr->value.type;
12160 }
12161 }
12162 case TldIdFn:
12163 {
12164 TldFn *tld_fn = (TldFn *)tld;
12165 FnTableEntry *fn_entry = tld_fn->fn_entry;
12166 assert(fn_entry->type_entry);
12167
12168 IrInstruction *ref_instruction = ir_create_const_fn(&ira->new_irb, instruction->base.scope,
12169 instruction->base.source_node, fn_entry);
12170 if (lval.is_ptr) {
12171 IrInstruction *ptr_instr = ir_get_ref(ira, &instruction->base, ref_instruction, true, false);
12172 ir_link_new_instruction(ptr_instr, &instruction->base);
12173 return ptr_instr->value.type;
12174 } else {
12175 ir_link_new_instruction(ref_instruction, &instruction->base);
12176 return ref_instruction->value.type;
12177 }
12178 }
12179 case TldIdTypeDef:
12180 {
12181 TldTypeDef *tld_typedef = (TldTypeDef *)tld;
12182 TypeTableEntry *typedef_type = tld_typedef->type_entry;
12183
12184 IrInstruction *ref_instruction = ir_create_const_type(&ira->new_irb, instruction->base.scope,
12185 instruction->base.source_node, typedef_type);
12186 if (lval.is_ptr) {
12187 IrInstruction *ptr_inst = ir_get_ref(ira, &instruction->base, ref_instruction, true, false);
12188 ir_link_new_instruction(ptr_inst, &instruction->base);
12189 return ptr_inst->value.type;
12190 } else {
12191 ir_link_new_instruction(ref_instruction, &instruction->base);
12192 return ref_instruction->value.type;
12193 }
12194 }
12195 }
12196 zig_unreachable();
12197}
12198
1215512199static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
1215612200 switch (instruction->id) {
1215712201 case IrInstructionIdInvalid:
......@@ -12317,6 +12361,8 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
1231712361 return ir_analyze_instruction_test_type(ira, (IrInstructionTestType *)instruction);
1231812362 case IrInstructionIdCanImplicitCast:
1231912363 return ir_analyze_instruction_can_implicit_cast(ira, (IrInstructionCanImplicitCast *)instruction);
12364 case IrInstructionIdDeclRef:
12365 return ir_analyze_instruction_decl_ref(ira, (IrInstructionDeclRef *)instruction);
1232012366 case IrInstructionIdMaybeWrap:
1232112367 case IrInstructionIdErrWrapCode:
1232212368 case IrInstructionIdErrWrapPayload:
......@@ -12495,6 +12541,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
1249512541 case IrInstructionIdTestType:
1249612542 case IrInstructionIdTypeName:
1249712543 case IrInstructionIdCanImplicitCast:
12544 case IrInstructionIdDeclRef:
1249812545 return false;
1249912546 case IrInstructionIdAsm:
1250012547 {
src/ir_print.cpp+10
......@@ -849,6 +849,13 @@ static void ir_print_set_global_section(IrPrint *irp, IrInstructionSetGlobalSect
849849 fprintf(irp->f, ")");
850850}
851851
852static void ir_print_decl_ref(IrPrint *irp, IrInstructionDeclRef *instruction) {
853 const char *ptr_str = instruction->lval.is_ptr ? "ptr " : "";
854 const char *const_str = instruction->lval.is_const ? "const " : "";
855 const char *volatile_str = instruction->lval.is_volatile ? "volatile " : "";
856 fprintf(irp->f, "declref %s%s%s%s", const_str, volatile_str, ptr_str, buf_ptr(instruction->tld->name));
857}
858
852859static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
853860 ir_print_prefix(irp, instruction);
854861 switch (instruction->id) {
......@@ -1121,6 +1128,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
11211128 case IrInstructionIdSetGlobalSection:
11221129 ir_print_set_global_section(irp, (IrInstructionSetGlobalSection *)instruction);
11231130 break;
1131 case IrInstructionIdDeclRef:
1132 ir_print_decl_ref(irp, (IrInstructionDeclRef *)instruction);
1133 break;
11241134 }
11251135 fprintf(irp->f, "\n");
11261136}