debug symbols implemented; debugging with gdb works

This commit is contained in:
Andrew Kelley 2015-11-24 19:54:10 -07:00
parent ca836191e1
commit c7f4cadbc7
2 changed files with 31 additions and 9 deletions

View File

@ -40,7 +40,6 @@ readable, safe, optimal, and concise code to solve any computing problem.
## Roadmap
* Add debugging symbols.
* Debug/Release mode.
* C style comments.
* Unit tests.

View File

@ -13,6 +13,7 @@
#include <stdio.h>
#include <llvm/IR/IRBuilder.h>
#include <llvm/IR/DIBuilder.h>
#include <llvm/IR/DiagnosticInfo.h>
#include <llvm/IR/DiagnosticPrinter.h>
@ -62,6 +63,8 @@ struct CodeGen {
LLVMTargetMachineRef target_machine;
Buf in_file;
Buf in_dir;
ZigList<llvm::DIScope *> block_scopes;
llvm::DIFile *di_file;
};
struct TypeNode {
@ -375,6 +378,12 @@ void semantic_analyze(CodeGen *g) {
static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node);
static void add_debug_source_node(CodeGen *g, AstNode *node) {
llvm::unwrap(g->builder)->SetCurrentDebugLocation(llvm::DebugLoc::get(
node->line + 1, node->column + 1,
g->block_scopes.last()));
}
static LLVMValueRef gen_fn_call(CodeGen *g, AstNode *fn_call_node) {
assert(fn_call_node->type == NodeTypeFnCall);
@ -403,6 +412,7 @@ static LLVMValueRef gen_fn_call(CodeGen *g, AstNode *fn_call_node) {
param_values[i] = gen_expr(g, expr_node);
}
add_debug_source_node(g, fn_call_node);
LLVMValueRef result = LLVMBuildCall(g->builder, fn_table_entry->fn_value,
param_values, actual_param_count, "");
@ -464,6 +474,10 @@ static LLVMValueRef gen_expr(CodeGen *g, AstNode *expr_node) {
static void gen_block(CodeGen *g, AstNode *block_node) {
assert(block_node->type == NodeTypeBlock);
llvm::DILexicalBlock *di_block = g->dbuilder->createLexicalBlock(g->block_scopes.last(),
g->di_file, block_node->line + 1, block_node->column + 1);
g->block_scopes.append(di_block);
for (int i = 0; i < block_node->data.block.statements.length; i += 1) {
AstNode *statement_node = block_node->data.block.statements.at(i);
assert(statement_node->type == NodeTypeStatement);
@ -472,6 +486,8 @@ static void gen_block(CodeGen *g, AstNode *block_node) {
{
AstNode *expr_node = statement_node->data.statement.data.retrn.expression;
LLVMValueRef value = gen_expr(g, expr_node);
add_debug_source_node(g, statement_node);
LLVMBuildRet(g->builder, value);
break;
}
@ -483,9 +499,13 @@ static void gen_block(CodeGen *g, AstNode *block_node) {
}
}
}
g->block_scopes.pop();
}
static llvm::DISubroutineType *create_di_function_type(CodeGen *g, AstNodeFnProto *fn_proto, llvm::DIFile *unit) {
static llvm::DISubroutineType *create_di_function_type(CodeGen *g, AstNodeFnProto *fn_proto,
llvm::DIFile *di_file)
{
llvm::SmallVector<llvm::Metadata *, 8> types;
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
types.push_back(param_type);
}
return g->dbuilder->createSubroutineType(unit, g->dbuilder->getOrCreateTypeArray(types));
return g->dbuilder->createSubroutineType(di_file, g->dbuilder->getOrCreateTypeArray(types));
}
void code_gen(CodeGen *g) {
@ -509,6 +529,10 @@ void code_gen(CodeGen *g) {
buf_ptr(&g->in_file), buf_ptr(&g->in_dir),
buf_ptr(producer), is_optimized, flags, runtime_version);
g->block_scopes.append(g->compile_unit);
g->di_file = g->dbuilder->createFile(g->compile_unit->getFilename(), g->compile_unit->getDirectory());
auto it = g->fn_defs.entry_iterator();
for (;;) {
auto *entry = it.next();
@ -540,19 +564,18 @@ void code_gen(CodeGen *g) {
LLVMAddFunctionAttr(fn, LLVMNoUnwindAttribute);
// Add debug info.
llvm::DIFile *unit = g->dbuilder->createFile(g->compile_unit->getFilename(),
g->compile_unit->getDirectory());
llvm::DIScope *fn_scope = unit;
llvm::DIScope *fn_scope = g->di_file;
unsigned line_number = fn_def_node->line + 1;
unsigned scope_line = line_number;
bool is_definition = true;
unsigned flags = 0;
llvm::Function *unwrapped_function = reinterpret_cast<llvm::Function*>(llvm::unwrap(fn));
g->dbuilder->createFunction(
fn_scope, buf_ptr(&fn_proto->name), "", unit, line_number,
create_di_function_type(g, fn_proto, unit), internal_linkage,
llvm::DISubprogram *subprogram = g->dbuilder->createFunction(
fn_scope, buf_ptr(&fn_proto->name), "", g->di_file, line_number,
create_di_function_type(g, fn_proto, g->di_file), internal_linkage,
is_definition, scope_line, flags, is_optimized, unwrapped_function);
g->block_scopes.append(subprogram);
LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn, "entry");