| ... | ... | @@ -13,6 +13,7 @@ |
| 13 | 13 | |
| 14 | 14 | #include <stdio.h> |
| 15 | 15 | |
| 16 | #include <llvm/IR/IRBuilder.h> |
| 16 | 17 | #include <llvm/IR/DIBuilder.h> |
| 17 | 18 | #include <llvm/IR/DiagnosticInfo.h> |
| 18 | 19 | #include <llvm/IR/DiagnosticPrinter.h> |
| ... | ... | @@ -62,6 +63,8 @@ struct CodeGen { |
| 62 | 63 | LLVMTargetMachineRef target_machine; |
| 63 | 64 | Buf in_file; |
| 64 | 65 | Buf in_dir; |
| 66 | ZigList<llvm::DIScope *> block_scopes; |
| 67 | llvm::DIFile *di_file; |
| 65 | 68 | }; |
| 66 | 69 | |
| 67 | 70 | struct TypeNode { |
| ... | ... | @@ -375,6 +378,12 @@ void semantic_analyze(CodeGen *g) { |
| 375 | 378 | |
| 376 | 379 | static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node); |
| 377 | 380 | |
| 381 | static void add_debug_source_node(CodeGen *g, AstNode *node) { |
| 382 | llvm::unwrap(g->builder)->SetCurrentDebugLocation(llvm::DebugLoc::get( |
| 383 | node->line + 1, node->column + 1, |
| 384 | g->block_scopes.last())); |
| 385 | } |
| 386 | |
| 378 | 387 | static LLVMValueRef gen_fn_call(CodeGen *g, AstNode *fn_call_node) { |
| 379 | 388 | assert(fn_call_node->type == NodeTypeFnCall); |
| 380 | 389 | |
| ... | ... | @@ -403,6 +412,7 @@ static LLVMValueRef gen_fn_call(CodeGen *g, AstNode *fn_call_node) { |
| 403 | 412 | param_values[i] = gen_expr(g, expr_node); |
| 404 | 413 | } |
| 405 | 414 | |
| 415 | add_debug_source_node(g, fn_call_node); |
| 406 | 416 | LLVMValueRef result = LLVMBuildCall(g->builder, fn_table_entry->fn_value, |
| 407 | 417 | param_values, actual_param_count, ""); |
| 408 | 418 | |
| ... | ... | @@ -464,6 +474,10 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node) { |
| 464 | 474 | static void gen_block(CodeGen *g, AstNode *block_node) { |
| 465 | 475 | assert(block_node->type == NodeTypeBlock); |
| 466 | 476 | |
| 477 | llvm::DILexicalBlock *di_block = g->dbuilder->createLexicalBlock(g->block_scopes.last(), |
| 478 | g->di_file, block_node->line + 1, block_node->column + 1); |
| 479 | g->block_scopes.append(di_block); |
| 480 | |
| 467 | 481 | for (int i = 0; i < block_node->data.block.statements.length; i += 1) { |
| 468 | 482 | AstNode *statement_node = block_node->data.block.statements.at(i); |
| 469 | 483 | assert(statement_node->type == NodeTypeStatement); |
| ... | ... | @@ -472,6 +486,8 @@ static void gen_block(CodeGen *g, AstNode *block_node) { |
| 472 | 486 | { |
| 473 | 487 | AstNode *expr_node = statement_node->data.statement.data.retrn.expression; |
| 474 | 488 | LLVMValueRef value = gen_expr(g, expr_node); |
| 489 | |
| 490 | add_debug_source_node(g, statement_node); |
| 475 | 491 | LLVMBuildRet(g->builder, value); |
| 476 | 492 | break; |
| 477 | 493 | } |
| ... | ... | @@ -483,9 +499,13 @@ static void gen_block(CodeGen *g, AstNode *block_node) { |
| 483 | 499 | } |
| 484 | 500 | } |
| 485 | 501 | } |
| 502 | |
| 503 | g->block_scopes.pop(); |
| 486 | 504 | } |
| 487 | 505 | |
| 488 | | static llvm::DISubroutineType *create_di_function_type(CodeGen *g, AstNodeFnProto *fn_proto, llvm::DIFile *unit) { |
| 506 | static llvm::DISubroutineType *create_di_function_type(CodeGen *g, AstNodeFnProto *fn_proto, |
| 507 | llvm::DIFile *di_file) |
| 508 | { |
| 489 | 509 | llvm::SmallVector<llvm::Metadata *, 8> types; |
| 490 | 510 | |
| 491 | 511 | llvm::DIType *return_type = to_llvm_debug_type(fn_proto->return_type); |
| ... | ... | @@ -497,7 +517,7 @@ static llvm::DISubroutineType *create_di_function_type(CodeGen *g, AstNodeFnProt |
| 497 | 517 | types.push_back(param_type); |
| 498 | 518 | } |
| 499 | 519 | |
| 500 | | return g->dbuilder->createSubroutineType(unit, g->dbuilder->getOrCreateTypeArray(types)); |
| 520 | return g->dbuilder->createSubroutineType(di_file, g->dbuilder->getOrCreateTypeArray(types)); |
| 501 | 521 | } |
| 502 | 522 | |
| 503 | 523 | void code_gen(CodeGen *g) { |
| ... | ... | @@ -509,6 +529,10 @@ void code_gen(CodeGen *g) { |
| 509 | 529 | buf_ptr(&g->in_file), buf_ptr(&g->in_dir), |
| 510 | 530 | buf_ptr(producer), is_optimized, flags, runtime_version); |
| 511 | 531 | |
| 532 | g->block_scopes.append(g->compile_unit); |
| 533 | |
| 534 | g->di_file = g->dbuilder->createFile(g->compile_unit->getFilename(), g->compile_unit->getDirectory()); |
| 535 | |
| 512 | 536 | auto it = g->fn_defs.entry_iterator(); |
| 513 | 537 | for (;;) { |
| 514 | 538 | auto *entry = it.next(); |
| ... | ... | @@ -540,19 +564,18 @@ void code_gen(CodeGen *g) { |
| 540 | 564 | LLVMAddFunctionAttr(fn, LLVMNoUnwindAttribute); |
| 541 | 565 | |
| 542 | 566 | // Add debug info. |
| 543 | | llvm::DIFile *unit = g->dbuilder->createFile(g->compile_unit->getFilename(), |
| 544 | | g->compile_unit->getDirectory()); |
| 545 | | llvm::DIScope *fn_scope = unit; |
| 567 | llvm::DIScope *fn_scope = g->di_file; |
| 546 | 568 | unsigned line_number = fn_def_node->line + 1; |
| 547 | 569 | unsigned scope_line = line_number; |
| 548 | 570 | bool is_definition = true; |
| 549 | 571 | unsigned flags = 0; |
| 550 | 572 | llvm::Function *unwrapped_function = reinterpret_cast<llvm::Function*>(llvm::unwrap(fn)); |
| 551 | | g->dbuilder->createFunction( |
| 552 | | fn_scope, buf_ptr(&fn_proto->name), "", unit, line_number, |
| 553 | | create_di_function_type(g, fn_proto, unit), internal_linkage, |
| 573 | llvm::DISubprogram *subprogram = g->dbuilder->createFunction( |
| 574 | fn_scope, buf_ptr(&fn_proto->name), "", g->di_file, line_number, |
| 575 | create_di_function_type(g, fn_proto, g->di_file), internal_linkage, |
| 554 | 576 | is_definition, scope_line, flags, is_optimized, unwrapped_function); |
| 555 | 577 | |
| 578 | g->block_scopes.append(subprogram); |
| 556 | 579 | |
| 557 | 580 | |
| 558 | 581 | LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn, "entry"); |