| author | |
| committer | |
| log | 9c9ea935191190471c1b2fd30c8cffde74421456 |
| tree | fe709fbb92cb58cc6027883e37fe55a7cb916798 |
| parent | 1279fe0caaa83dd9f573dfe3c359098143224abc |
5 files changed, 80 insertions(+), 42 deletions(-)
src/analyze.cpp+4-8| ... | ... | @@ -443,10 +443,13 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 443 | 443 | TypeTableEntry *expected_type, AstNode *node) |
| 444 | 444 | { |
| 445 | 445 | TypeTableEntry *return_type = nullptr; |
| 446 | assert(!node->codegen_node); | |
| 447 | node->codegen_node = allocate<CodeGenNode>(1); | |
| 446 | 448 | switch (node->type) { |
| 447 | 449 | case NodeTypeBlock: |
| 448 | 450 | { |
| 449 | 451 | BlockContext *child_context = new_block_context(node, context); |
| 452 | node->codegen_node->data.block_node.block_context = child_context; | |
| 450 | 453 | return_type = g->builtin_types.entry_void; |
| 451 | 454 | for (int i = 0; i < node->data.block.statements.length; i += 1) { |
| 452 | 455 | AstNode *child = node->data.block.statements.at(i); |
| ... | ... | @@ -538,8 +541,6 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 538 | 541 | FnTableEntry *fn_table_entry = get_context_fn_entry(context); |
| 539 | 542 | auto table_entry = fn_table_entry->label_table.maybe_get(&node->data.go_to.name); |
| 540 | 543 | if (table_entry) { |
| 541 | assert(!node->codegen_node); | |
| 542 | node->codegen_node = allocate<CodeGenNode>(1); | |
| 543 | 544 | node->codegen_node->data.label_entry = table_entry->value; |
| 544 | 545 | table_entry->value->used = true; |
| 545 | 546 | } else { |
| ... | ... | @@ -792,12 +793,6 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import, |
| 792 | 793 | assert(return_type); |
| 793 | 794 | check_type_compatibility(g, node, expected_type, return_type); |
| 794 | 795 | |
| 795 | if (node->codegen_node) { | |
| 796 | assert(node->type == NodeTypeGoto); | |
| 797 | } else { | |
| 798 | assert(node->type != NodeTypeGoto); | |
| 799 | node->codegen_node = allocate<CodeGenNode>(1); | |
| 800 | } | |
| 801 | 796 | node->codegen_node->expr_node.type_entry = return_type; |
| 802 | 797 | node->codegen_node->expr_node.block_context = context; |
| 803 | 798 | |
| ... | ... | @@ -837,6 +832,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import, |
| 837 | 832 | variable_entry->type = type; |
| 838 | 833 | variable_entry->is_const = true; |
| 839 | 834 | variable_entry->decl_node = param_decl_node; |
| 835 | variable_entry->arg_index = i; | |
| 840 | 836 | |
| 841 | 837 | LocalVariableTableEntry *existing_entry = find_local_variable(context, &variable_entry->name); |
| 842 | 838 | if (!existing_entry) { |
src/codegen.cpp+33-23| ... | ... | @@ -102,8 +102,8 @@ static int count_non_void_params(CodeGen *g, ZigList<AstNode *> *params) { |
| 102 | 102 | } |
| 103 | 103 | |
| 104 | 104 | static void add_debug_source_node(CodeGen *g, AstNode *node) { |
| 105 | // TODO g->block_scopes.last() is not always correct and should probably integrate with BlockContext | |
| 106 | LLVMZigSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1, g->block_scopes.last()); | |
| 105 | LLVMZigSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1, | |
| 106 | g->cur_block_context->di_scope); | |
| 107 | 107 | } |
| 108 | 108 | |
| 109 | 109 | static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str) { |
| ... | ... | @@ -484,13 +484,7 @@ static LLVMValueRef gen_if_expr(CodeGen *g, AstNode *node) { |
| 484 | 484 | static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) { |
| 485 | 485 | assert(block_node->type == NodeTypeBlock); |
| 486 | 486 | |
| 487 | ImportTableEntry *import = g->cur_fn->import_entry; | |
| 488 | ||
| 489 | LLVMZigDILexicalBlock *di_block = LLVMZigCreateLexicalBlock(g->dbuilder, g->block_scopes.last(), | |
| 490 | import->di_file, block_node->line + 1, block_node->column + 1); | |
| 491 | g->block_scopes.append(LLVMZigLexicalBlockToScope(di_block)); | |
| 492 | ||
| 493 | add_debug_source_node(g, block_node); | |
| 487 | g->cur_block_context = block_node->codegen_node->data.block_node.block_context; | |
| 494 | 488 | |
| 495 | 489 | LLVMValueRef return_value; |
| 496 | 490 | for (int i = 0; i < block_node->data.block.statements.length; i += 1) { |
| ... | ... | @@ -506,8 +500,6 @@ static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *i |
| 506 | 500 | } |
| 507 | 501 | } |
| 508 | 502 | |
| 509 | g->block_scopes.pop(); | |
| 510 | ||
| 511 | 503 | return return_value; |
| 512 | 504 | } |
| 513 | 505 | |
| ... | ... | @@ -654,9 +646,6 @@ static LLVMZigDISubroutineType *create_di_function_type(CodeGen *g, AstNodeFnPro |
| 654 | 646 | static void do_code_gen(CodeGen *g) { |
| 655 | 647 | assert(!g->errors.length); |
| 656 | 648 | |
| 657 | g->block_scopes.append(LLVMZigCompileUnitToScope(g->compile_unit)); | |
| 658 | ||
| 659 | ||
| 660 | 649 | // Generate function prototypes |
| 661 | 650 | for (int i = 0; i < g->fn_protos.length; i += 1) { |
| 662 | 651 | FnTableEntry *fn_table_entry = g->fn_protos.at(i); |
| ... | ... | @@ -718,8 +707,6 @@ static void do_code_gen(CodeGen *g) { |
| 718 | 707 | create_di_function_type(g, fn_proto, import->di_file), fn_table_entry->internal_linkage, |
| 719 | 708 | is_definition, scope_line, flags, is_optimized, fn); |
| 720 | 709 | |
| 721 | g->block_scopes.append(LLVMZigSubprogramToScope(subprogram)); | |
| 722 | ||
| 723 | 710 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn, "entry"); |
| 724 | 711 | LLVMPositionBuilderAtEnd(g->builder, entry_block); |
| 725 | 712 | |
| ... | ... | @@ -728,6 +715,9 @@ static void do_code_gen(CodeGen *g) { |
| 728 | 715 | |
| 729 | 716 | FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node; |
| 730 | 717 | assert(codegen_fn_def); |
| 718 | ||
| 719 | codegen_fn_def->block_context->di_scope = LLVMZigSubprogramToScope(subprogram); | |
| 720 | ||
| 731 | 721 | int non_void_param_count = count_non_void_params(g, &fn_proto->params); |
| 732 | 722 | assert(non_void_param_count == (int)LLVMCountParams(fn)); |
| 733 | 723 | LLVMValueRef *params = allocate<LLVMValueRef>(non_void_param_count); |
| ... | ... | @@ -746,15 +736,22 @@ static void do_code_gen(CodeGen *g) { |
| 746 | 736 | |
| 747 | 737 | build_label_blocks(g, fn_def_node->data.fn_def.body); |
| 748 | 738 | |
| 739 | // Set up debug info for blocks and variables and | |
| 749 | 740 | // allocate all local variables |
| 750 | 741 | for (int i = 0; i < codegen_fn_def->all_block_contexts.length; i += 1) { |
| 751 | 742 | BlockContext *block_context = codegen_fn_def->all_block_contexts.at(i); |
| 752 | 743 | |
| 753 | // skip the block context for function parameters | |
| 754 | if (block_context->node->type == NodeTypeFnDef) { | |
| 755 | continue; | |
| 744 | if (block_context->parent) { | |
| 745 | LLVMZigDILexicalBlock *di_block = LLVMZigCreateLexicalBlock(g->dbuilder, | |
| 746 | block_context->parent->di_scope, | |
| 747 | import->di_file, | |
| 748 | block_context->node->line + 1, | |
| 749 | block_context->node->column + 1); | |
| 750 | block_context->di_scope = LLVMZigLexicalBlockToScope(di_block); | |
| 756 | 751 | } |
| 757 | 752 | |
| 753 | g->cur_block_context = block_context; | |
| 754 | ||
| 758 | 755 | auto it = block_context->variable_table.entry_iterator(); |
| 759 | 756 | for (;;) { |
| 760 | 757 | auto *entry = it.next(); |
| ... | ... | @@ -765,16 +762,29 @@ static void do_code_gen(CodeGen *g) { |
| 765 | 762 | if (var->type == g->builtin_types.entry_void) |
| 766 | 763 | continue; |
| 767 | 764 | |
| 768 | add_debug_source_node(g, var->decl_node); | |
| 769 | var->value_ref = LLVMBuildAlloca(g->builder, var->type->type_ref, buf_ptr(&var->name)); | |
| 765 | unsigned tag; | |
| 766 | unsigned arg_no; | |
| 767 | if (block_context->node->type == NodeTypeFnDef) { | |
| 768 | tag = LLVMZigTag_DW_arg_variable(); | |
| 769 | arg_no = var->arg_index + 1; | |
| 770 | } else { | |
| 771 | tag = LLVMZigTag_DW_auto_variable(); | |
| 772 | arg_no = 0; | |
| 773 | ||
| 774 | add_debug_source_node(g, var->decl_node); | |
| 775 | var->value_ref = LLVMBuildAlloca(g->builder, var->type->type_ref, buf_ptr(&var->name)); | |
| 776 | } | |
| 777 | ||
| 778 | var->di_loc_var = LLVMZigCreateLocalVariable(g->dbuilder, tag, | |
| 779 | block_context->di_scope, buf_ptr(&var->name), | |
| 780 | import->di_file, var->decl_node->line + 1, | |
| 781 | var->type->di_type, !g->strip_debug_symbols, 0, arg_no); | |
| 770 | 782 | } |
| 771 | 783 | } |
| 772 | 784 | |
| 773 | 785 | TypeTableEntry *implicit_return_type = codegen_fn_def->implicit_return_type; |
| 774 | 786 | gen_block(g, fn_def_node->data.fn_def.body, implicit_return_type); |
| 775 | 787 | |
| 776 | g->block_scopes.pop(); | |
| 777 | ||
| 778 | 788 | } |
| 779 | 789 | assert(!g->errors.length); |
| 780 | 790 |
src/semantic_info.hpp+11-1| ... | ... | @@ -14,6 +14,7 @@ |
| 14 | 14 | #include "errmsg.hpp" |
| 15 | 15 | |
| 16 | 16 | struct FnTableEntry; |
| 17 | struct BlockContext; | |
| 17 | 18 | |
| 18 | 19 | struct TypeTableEntry { |
| 19 | 20 | LLVMTypeRef type_ref; |
| ... | ... | @@ -96,7 +97,6 @@ struct CodeGen { |
| 96 | 97 | bool is_native_target; |
| 97 | 98 | Buf *root_source_dir; |
| 98 | 99 | Buf *root_out_name; |
| 99 | ZigList<LLVMZigDIScope *> block_scopes; | |
| 100 | 100 | |
| 101 | 101 | // The function definitions this module includes. There must be a corresponding |
| 102 | 102 | // fn_protos entry. |
| ... | ... | @@ -108,6 +108,7 @@ struct CodeGen { |
| 108 | 108 | OutType out_type; |
| 109 | 109 | FnTableEntry *cur_fn; |
| 110 | 110 | LLVMBasicBlockRef cur_basic_block; |
| 111 | BlockContext *cur_block_context; | |
| 111 | 112 | bool c_stdint_used; |
| 112 | 113 | AstNode *root_export_decl; |
| 113 | 114 | int version_major; |
| ... | ... | @@ -125,6 +126,8 @@ struct LocalVariableTableEntry { |
| 125 | 126 | bool is_const; |
| 126 | 127 | bool is_ptr; // if true, value_ref is a pointer |
| 127 | 128 | AstNode *decl_node; |
| 129 | LLVMZigDILocalVariable *di_loc_var; | |
| 130 | int arg_index; | |
| 128 | 131 | }; |
| 129 | 132 | |
| 130 | 133 | struct BlockContext { |
| ... | ... | @@ -132,6 +135,7 @@ struct BlockContext { |
| 132 | 135 | BlockContext *root; // always points to the BlockContext with the NodeTypeFnDef |
| 133 | 136 | BlockContext *parent; // nullptr when this is the root |
| 134 | 137 | HashMap<Buf *, LocalVariableTableEntry *, buf_hash, buf_eql_buf> variable_table; |
| 138 | LLVMZigDIScope *di_scope; | |
| 135 | 139 | }; |
| 136 | 140 | |
| 137 | 141 | struct TypeNode { |
| ... | ... | @@ -146,6 +150,7 @@ struct FnDefNode { |
| 146 | 150 | TypeTableEntry *implicit_return_type; |
| 147 | 151 | BlockContext *block_context; |
| 148 | 152 | bool skip; |
| 153 | // Required to be a pre-order traversal of the AST. (parents must come before children) | |
| 149 | 154 | ZigList<BlockContext *> all_block_contexts; |
| 150 | 155 | }; |
| 151 | 156 | |
| ... | ... | @@ -160,6 +165,10 @@ struct AssignNode { |
| 160 | 165 | LocalVariableTableEntry *var_entry; |
| 161 | 166 | }; |
| 162 | 167 | |
| 168 | struct BlockNode { | |
| 169 | BlockContext *block_context; | |
| 170 | }; | |
| 171 | ||
| 163 | 172 | struct CodeGenNode { |
| 164 | 173 | union { |
| 165 | 174 | TypeNode type_node; // for NodeTypeType |
| ... | ... | @@ -167,6 +176,7 @@ struct CodeGenNode { |
| 167 | 176 | FnProtoNode fn_proto_node; // for NodeTypeFnProto |
| 168 | 177 | LabelTableEntry *label_entry; // for NodeTypeGoto and NodeTypeLabel |
| 169 | 178 | AssignNode assign_node; // for NodeTypeBinOpExpr where op is BinOpTypeAssign |
| 179 | BlockNode block_node; // for NodeTypeBlock | |
| 170 | 180 | } data; |
| 171 | 181 | ExprNode expr_node; // for all the expression nodes |
| 172 | 182 | }; |
src/zig_llvm.cpp+25-10| ... | ... | @@ -189,6 +189,14 @@ unsigned LLVMZigLang_DW_LANG_C99(void) { |
| 189 | 189 | return dwarf::DW_LANG_C99; |
| 190 | 190 | } |
| 191 | 191 | |
| 192 | unsigned LLVMZigTag_DW_auto_variable(void) { | |
| 193 | return dwarf::DW_TAG_auto_variable; | |
| 194 | } | |
| 195 | ||
| 196 | unsigned LLVMZigTag_DW_arg_variable(void) { | |
| 197 | return dwarf::DW_TAG_arg_variable; | |
| 198 | } | |
| 199 | ||
| 192 | 200 | LLVMZigDIBuilder *LLVMZigCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved) { |
| 193 | 201 | DIBuilder *di_builder = new DIBuilder(*unwrap(module), allow_unresolved); |
| 194 | 202 | return reinterpret_cast<LLVMZigDIBuilder *>(di_builder); |
| ... | ... | @@ -211,16 +219,23 @@ LLVMZigDILexicalBlock *LLVMZigCreateLexicalBlock(LLVMZigDIBuilder *dbuilder, LLV |
| 211 | 219 | return reinterpret_cast<LLVMZigDILexicalBlock*>(result); |
| 212 | 220 | } |
| 213 | 221 | |
| 214 | /* | |
| 215 | LLVMZigDILocalVariable * | |
| 216 | ||
| 217 | DILocalVariable *createLocalVariable(unsigned Tag, DIScope *Scope, | |
| 218 | StringRef Name, DIFile *File, | |
| 219 | unsigned LineNo, DIType *Ty, | |
| 220 | bool AlwaysPreserve = false, | |
| 221 | unsigned Flags = 0, | |
| 222 | unsigned ArgNo = 0); | |
| 223 | */ | |
| 222 | ||
| 223 | LLVMZigDILocalVariable *LLVMZigCreateLocalVariable(LLVMZigDIBuilder *dbuilder, unsigned tag, | |
| 224 | LLVMZigDIScope *scope, const char *name, LLVMZigDIFile *file, unsigned line_no, | |
| 225 | LLVMZigDIType *type, bool always_preserve, unsigned flags, unsigned arg_no) | |
| 226 | { | |
| 227 | DILocalVariable *result = reinterpret_cast<DIBuilder*>(dbuilder)->createLocalVariable( | |
| 228 | tag, | |
| 229 | reinterpret_cast<DIScope*>(scope), | |
| 230 | name, | |
| 231 | reinterpret_cast<DIFile*>(file), | |
| 232 | line_no, | |
| 233 | reinterpret_cast<DIType*>(type), | |
| 234 | always_preserve, | |
| 235 | flags, | |
| 236 | arg_no); | |
| 237 | return reinterpret_cast<LLVMZigDILocalVariable*>(result); | |
| 238 | } | |
| 224 | 239 | |
| 225 | 240 | LLVMZigDIScope *LLVMZigLexicalBlockToScope(LLVMZigDILexicalBlock *lexical_block) { |
| 226 | 241 | DIScope *scope = reinterpret_cast<DILexicalBlock*>(lexical_block); |
src/zig_llvm.hpp+7| ... | ... | @@ -22,6 +22,7 @@ struct LLVMZigDIFile; |
| 22 | 22 | struct LLVMZigDILexicalBlock; |
| 23 | 23 | struct LLVMZigDISubprogram; |
| 24 | 24 | struct LLVMZigDISubroutineType; |
| 25 | struct LLVMZigDILocalVariable; | |
| 25 | 26 | struct LLVMZigInsertionPoint; |
| 26 | 27 | |
| 27 | 28 | void LLVMZigInitializeLoopStrengthReducePass(LLVMPassRegistryRef R); |
| ... | ... | @@ -54,6 +55,8 @@ LLVMZigDISubroutineType *LLVMZigCreateSubroutineType(LLVMZigDIBuilder *dibuilder |
| 54 | 55 | unsigned LLVMZigEncoding_DW_ATE_unsigned(void); |
| 55 | 56 | unsigned LLVMZigEncoding_DW_ATE_signed(void); |
| 56 | 57 | unsigned LLVMZigLang_DW_LANG_C99(void); |
| 58 | unsigned LLVMZigTag_DW_auto_variable(void); | |
| 59 | unsigned LLVMZigTag_DW_arg_variable(void); | |
| 57 | 60 | |
| 58 | 61 | LLVMZigDIBuilder *LLVMZigCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved); |
| 59 | 62 | |
| ... | ... | @@ -64,6 +67,10 @@ LLVMZigDIScope *LLVMZigCompileUnitToScope(LLVMZigDICompileUnit *compile_unit); |
| 64 | 67 | LLVMZigDIScope *LLVMZigFileToScope(LLVMZigDIFile *difile); |
| 65 | 68 | LLVMZigDIScope *LLVMZigSubprogramToScope(LLVMZigDISubprogram *subprogram); |
| 66 | 69 | |
| 70 | LLVMZigDILocalVariable *LLVMZigCreateLocalVariable(LLVMZigDIBuilder *dbuilder, unsigned tag, | |
| 71 | LLVMZigDIScope *scope, const char *name, LLVMZigDIFile *file, unsigned line_no, | |
| 72 | LLVMZigDIType *type, bool always_preserve, unsigned flags, unsigned arg_no); | |
| 73 | ||
| 67 | 74 | LLVMZigDILexicalBlock *LLVMZigCreateLexicalBlock(LLVMZigDIBuilder *dbuilder, LLVMZigDIScope *scope, |
| 68 | 75 | LLVMZigDIFile *file, unsigned line, unsigned col); |
| 69 | 76 |