mirror of
https://github.com/ziglang/zig.git
synced 2026-02-17 23:10:09 +00:00
integrate debug scopes with block context
This commit is contained in:
parent
1279fe0caa
commit
9c9ea93519
@ -443,10 +443,13 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
||||
TypeTableEntry *expected_type, AstNode *node)
|
||||
{
|
||||
TypeTableEntry *return_type = nullptr;
|
||||
assert(!node->codegen_node);
|
||||
node->codegen_node = allocate<CodeGenNode>(1);
|
||||
switch (node->type) {
|
||||
case NodeTypeBlock:
|
||||
{
|
||||
BlockContext *child_context = new_block_context(node, context);
|
||||
node->codegen_node->data.block_node.block_context = child_context;
|
||||
return_type = g->builtin_types.entry_void;
|
||||
for (int i = 0; i < node->data.block.statements.length; i += 1) {
|
||||
AstNode *child = node->data.block.statements.at(i);
|
||||
@ -538,8 +541,6 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
||||
FnTableEntry *fn_table_entry = get_context_fn_entry(context);
|
||||
auto table_entry = fn_table_entry->label_table.maybe_get(&node->data.go_to.name);
|
||||
if (table_entry) {
|
||||
assert(!node->codegen_node);
|
||||
node->codegen_node = allocate<CodeGenNode>(1);
|
||||
node->codegen_node->data.label_entry = table_entry->value;
|
||||
table_entry->value->used = true;
|
||||
} else {
|
||||
@ -792,12 +793,6 @@ static TypeTableEntry * analyze_expression(CodeGen *g, ImportTableEntry *import,
|
||||
assert(return_type);
|
||||
check_type_compatibility(g, node, expected_type, return_type);
|
||||
|
||||
if (node->codegen_node) {
|
||||
assert(node->type == NodeTypeGoto);
|
||||
} else {
|
||||
assert(node->type != NodeTypeGoto);
|
||||
node->codegen_node = allocate<CodeGenNode>(1);
|
||||
}
|
||||
node->codegen_node->expr_node.type_entry = return_type;
|
||||
node->codegen_node->expr_node.block_context = context;
|
||||
|
||||
@ -837,6 +832,7 @@ static void analyze_top_level_declaration(CodeGen *g, ImportTableEntry *import,
|
||||
variable_entry->type = type;
|
||||
variable_entry->is_const = true;
|
||||
variable_entry->decl_node = param_decl_node;
|
||||
variable_entry->arg_index = i;
|
||||
|
||||
LocalVariableTableEntry *existing_entry = find_local_variable(context, &variable_entry->name);
|
||||
if (!existing_entry) {
|
||||
|
||||
@ -102,8 +102,8 @@ static int count_non_void_params(CodeGen *g, ZigList<AstNode *> *params) {
|
||||
}
|
||||
|
||||
static void add_debug_source_node(CodeGen *g, AstNode *node) {
|
||||
// TODO g->block_scopes.last() is not always correct and should probably integrate with BlockContext
|
||||
LLVMZigSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1, g->block_scopes.last());
|
||||
LLVMZigSetCurrentDebugLocation(g->builder, node->line + 1, node->column + 1,
|
||||
g->cur_block_context->di_scope);
|
||||
}
|
||||
|
||||
static LLVMValueRef find_or_create_string(CodeGen *g, Buf *str) {
|
||||
@ -484,13 +484,7 @@ static LLVMValueRef gen_if_expr(CodeGen *g, AstNode *node) {
|
||||
static LLVMValueRef gen_block(CodeGen *g, AstNode *block_node, TypeTableEntry *implicit_return_type) {
|
||||
assert(block_node->type == NodeTypeBlock);
|
||||
|
||||
ImportTableEntry *import = g->cur_fn->import_entry;
|
||||
|
||||
LLVMZigDILexicalBlock *di_block = LLVMZigCreateLexicalBlock(g->dbuilder, g->block_scopes.last(),
|
||||
import->di_file, block_node->line + 1, block_node->column + 1);
|
||||
g->block_scopes.append(LLVMZigLexicalBlockToScope(di_block));
|
||||
|
||||
add_debug_source_node(g, block_node);
|
||||
g->cur_block_context = block_node->codegen_node->data.block_node.block_context;
|
||||
|
||||
LLVMValueRef return_value;
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
g->block_scopes.pop();
|
||||
|
||||
return return_value;
|
||||
}
|
||||
|
||||
@ -654,9 +646,6 @@ static LLVMZigDISubroutineType *create_di_function_type(CodeGen *g, AstNodeFnPro
|
||||
static void do_code_gen(CodeGen *g) {
|
||||
assert(!g->errors.length);
|
||||
|
||||
g->block_scopes.append(LLVMZigCompileUnitToScope(g->compile_unit));
|
||||
|
||||
|
||||
// Generate function prototypes
|
||||
for (int i = 0; i < g->fn_protos.length; i += 1) {
|
||||
FnTableEntry *fn_table_entry = g->fn_protos.at(i);
|
||||
@ -718,8 +707,6 @@ static void do_code_gen(CodeGen *g) {
|
||||
create_di_function_type(g, fn_proto, import->di_file), fn_table_entry->internal_linkage,
|
||||
is_definition, scope_line, flags, is_optimized, fn);
|
||||
|
||||
g->block_scopes.append(LLVMZigSubprogramToScope(subprogram));
|
||||
|
||||
LLVMBasicBlockRef entry_block = LLVMAppendBasicBlock(fn, "entry");
|
||||
LLVMPositionBuilderAtEnd(g->builder, entry_block);
|
||||
|
||||
@ -728,6 +715,9 @@ static void do_code_gen(CodeGen *g) {
|
||||
|
||||
FnDefNode *codegen_fn_def = &codegen_node->data.fn_def_node;
|
||||
assert(codegen_fn_def);
|
||||
|
||||
codegen_fn_def->block_context->di_scope = LLVMZigSubprogramToScope(subprogram);
|
||||
|
||||
int non_void_param_count = count_non_void_params(g, &fn_proto->params);
|
||||
assert(non_void_param_count == (int)LLVMCountParams(fn));
|
||||
LLVMValueRef *params = allocate<LLVMValueRef>(non_void_param_count);
|
||||
@ -746,15 +736,22 @@ static void do_code_gen(CodeGen *g) {
|
||||
|
||||
build_label_blocks(g, fn_def_node->data.fn_def.body);
|
||||
|
||||
// Set up debug info for blocks and variables and
|
||||
// allocate all local variables
|
||||
for (int i = 0; i < codegen_fn_def->all_block_contexts.length; i += 1) {
|
||||
BlockContext *block_context = codegen_fn_def->all_block_contexts.at(i);
|
||||
|
||||
// skip the block context for function parameters
|
||||
if (block_context->node->type == NodeTypeFnDef) {
|
||||
continue;
|
||||
if (block_context->parent) {
|
||||
LLVMZigDILexicalBlock *di_block = LLVMZigCreateLexicalBlock(g->dbuilder,
|
||||
block_context->parent->di_scope,
|
||||
import->di_file,
|
||||
block_context->node->line + 1,
|
||||
block_context->node->column + 1);
|
||||
block_context->di_scope = LLVMZigLexicalBlockToScope(di_block);
|
||||
}
|
||||
|
||||
g->cur_block_context = block_context;
|
||||
|
||||
auto it = block_context->variable_table.entry_iterator();
|
||||
for (;;) {
|
||||
auto *entry = it.next();
|
||||
@ -765,16 +762,29 @@ static void do_code_gen(CodeGen *g) {
|
||||
if (var->type == g->builtin_types.entry_void)
|
||||
continue;
|
||||
|
||||
add_debug_source_node(g, var->decl_node);
|
||||
var->value_ref = LLVMBuildAlloca(g->builder, var->type->type_ref, buf_ptr(&var->name));
|
||||
unsigned tag;
|
||||
unsigned arg_no;
|
||||
if (block_context->node->type == NodeTypeFnDef) {
|
||||
tag = LLVMZigTag_DW_arg_variable();
|
||||
arg_no = var->arg_index + 1;
|
||||
} else {
|
||||
tag = LLVMZigTag_DW_auto_variable();
|
||||
arg_no = 0;
|
||||
|
||||
add_debug_source_node(g, var->decl_node);
|
||||
var->value_ref = LLVMBuildAlloca(g->builder, var->type->type_ref, buf_ptr(&var->name));
|
||||
}
|
||||
|
||||
var->di_loc_var = LLVMZigCreateLocalVariable(g->dbuilder, tag,
|
||||
block_context->di_scope, buf_ptr(&var->name),
|
||||
import->di_file, var->decl_node->line + 1,
|
||||
var->type->di_type, !g->strip_debug_symbols, 0, arg_no);
|
||||
}
|
||||
}
|
||||
|
||||
TypeTableEntry *implicit_return_type = codegen_fn_def->implicit_return_type;
|
||||
gen_block(g, fn_def_node->data.fn_def.body, implicit_return_type);
|
||||
|
||||
g->block_scopes.pop();
|
||||
|
||||
}
|
||||
assert(!g->errors.length);
|
||||
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
#include "errmsg.hpp"
|
||||
|
||||
struct FnTableEntry;
|
||||
struct BlockContext;
|
||||
|
||||
struct TypeTableEntry {
|
||||
LLVMTypeRef type_ref;
|
||||
@ -96,7 +97,6 @@ struct CodeGen {
|
||||
bool is_native_target;
|
||||
Buf *root_source_dir;
|
||||
Buf *root_out_name;
|
||||
ZigList<LLVMZigDIScope *> block_scopes;
|
||||
|
||||
// The function definitions this module includes. There must be a corresponding
|
||||
// fn_protos entry.
|
||||
@ -108,6 +108,7 @@ struct CodeGen {
|
||||
OutType out_type;
|
||||
FnTableEntry *cur_fn;
|
||||
LLVMBasicBlockRef cur_basic_block;
|
||||
BlockContext *cur_block_context;
|
||||
bool c_stdint_used;
|
||||
AstNode *root_export_decl;
|
||||
int version_major;
|
||||
@ -125,6 +126,8 @@ struct LocalVariableTableEntry {
|
||||
bool is_const;
|
||||
bool is_ptr; // if true, value_ref is a pointer
|
||||
AstNode *decl_node;
|
||||
LLVMZigDILocalVariable *di_loc_var;
|
||||
int arg_index;
|
||||
};
|
||||
|
||||
struct BlockContext {
|
||||
@ -132,6 +135,7 @@ struct BlockContext {
|
||||
BlockContext *root; // always points to the BlockContext with the NodeTypeFnDef
|
||||
BlockContext *parent; // nullptr when this is the root
|
||||
HashMap<Buf *, LocalVariableTableEntry *, buf_hash, buf_eql_buf> variable_table;
|
||||
LLVMZigDIScope *di_scope;
|
||||
};
|
||||
|
||||
struct TypeNode {
|
||||
@ -146,6 +150,7 @@ struct FnDefNode {
|
||||
TypeTableEntry *implicit_return_type;
|
||||
BlockContext *block_context;
|
||||
bool skip;
|
||||
// Required to be a pre-order traversal of the AST. (parents must come before children)
|
||||
ZigList<BlockContext *> all_block_contexts;
|
||||
};
|
||||
|
||||
@ -160,6 +165,10 @@ struct AssignNode {
|
||||
LocalVariableTableEntry *var_entry;
|
||||
};
|
||||
|
||||
struct BlockNode {
|
||||
BlockContext *block_context;
|
||||
};
|
||||
|
||||
struct CodeGenNode {
|
||||
union {
|
||||
TypeNode type_node; // for NodeTypeType
|
||||
@ -167,6 +176,7 @@ struct CodeGenNode {
|
||||
FnProtoNode fn_proto_node; // for NodeTypeFnProto
|
||||
LabelTableEntry *label_entry; // for NodeTypeGoto and NodeTypeLabel
|
||||
AssignNode assign_node; // for NodeTypeBinOpExpr where op is BinOpTypeAssign
|
||||
BlockNode block_node; // for NodeTypeBlock
|
||||
} data;
|
||||
ExprNode expr_node; // for all the expression nodes
|
||||
};
|
||||
|
||||
@ -189,6 +189,14 @@ unsigned LLVMZigLang_DW_LANG_C99(void) {
|
||||
return dwarf::DW_LANG_C99;
|
||||
}
|
||||
|
||||
unsigned LLVMZigTag_DW_auto_variable(void) {
|
||||
return dwarf::DW_TAG_auto_variable;
|
||||
}
|
||||
|
||||
unsigned LLVMZigTag_DW_arg_variable(void) {
|
||||
return dwarf::DW_TAG_arg_variable;
|
||||
}
|
||||
|
||||
LLVMZigDIBuilder *LLVMZigCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved) {
|
||||
DIBuilder *di_builder = new DIBuilder(*unwrap(module), allow_unresolved);
|
||||
return reinterpret_cast<LLVMZigDIBuilder *>(di_builder);
|
||||
@ -211,16 +219,23 @@ LLVMZigDILexicalBlock *LLVMZigCreateLexicalBlock(LLVMZigDIBuilder *dbuilder, LLV
|
||||
return reinterpret_cast<LLVMZigDILexicalBlock*>(result);
|
||||
}
|
||||
|
||||
/*
|
||||
LLVMZigDILocalVariable *
|
||||
|
||||
DILocalVariable *createLocalVariable(unsigned Tag, DIScope *Scope,
|
||||
StringRef Name, DIFile *File,
|
||||
unsigned LineNo, DIType *Ty,
|
||||
bool AlwaysPreserve = false,
|
||||
unsigned Flags = 0,
|
||||
unsigned ArgNo = 0);
|
||||
*/
|
||||
LLVMZigDILocalVariable *LLVMZigCreateLocalVariable(LLVMZigDIBuilder *dbuilder, unsigned tag,
|
||||
LLVMZigDIScope *scope, const char *name, LLVMZigDIFile *file, unsigned line_no,
|
||||
LLVMZigDIType *type, bool always_preserve, unsigned flags, unsigned arg_no)
|
||||
{
|
||||
DILocalVariable *result = reinterpret_cast<DIBuilder*>(dbuilder)->createLocalVariable(
|
||||
tag,
|
||||
reinterpret_cast<DIScope*>(scope),
|
||||
name,
|
||||
reinterpret_cast<DIFile*>(file),
|
||||
line_no,
|
||||
reinterpret_cast<DIType*>(type),
|
||||
always_preserve,
|
||||
flags,
|
||||
arg_no);
|
||||
return reinterpret_cast<LLVMZigDILocalVariable*>(result);
|
||||
}
|
||||
|
||||
LLVMZigDIScope *LLVMZigLexicalBlockToScope(LLVMZigDILexicalBlock *lexical_block) {
|
||||
DIScope *scope = reinterpret_cast<DILexicalBlock*>(lexical_block);
|
||||
|
||||
@ -22,6 +22,7 @@ struct LLVMZigDIFile;
|
||||
struct LLVMZigDILexicalBlock;
|
||||
struct LLVMZigDISubprogram;
|
||||
struct LLVMZigDISubroutineType;
|
||||
struct LLVMZigDILocalVariable;
|
||||
struct LLVMZigInsertionPoint;
|
||||
|
||||
void LLVMZigInitializeLoopStrengthReducePass(LLVMPassRegistryRef R);
|
||||
@ -54,6 +55,8 @@ LLVMZigDISubroutineType *LLVMZigCreateSubroutineType(LLVMZigDIBuilder *dibuilder
|
||||
unsigned LLVMZigEncoding_DW_ATE_unsigned(void);
|
||||
unsigned LLVMZigEncoding_DW_ATE_signed(void);
|
||||
unsigned LLVMZigLang_DW_LANG_C99(void);
|
||||
unsigned LLVMZigTag_DW_auto_variable(void);
|
||||
unsigned LLVMZigTag_DW_arg_variable(void);
|
||||
|
||||
LLVMZigDIBuilder *LLVMZigCreateDIBuilder(LLVMModuleRef module, bool allow_unresolved);
|
||||
|
||||
@ -64,6 +67,10 @@ LLVMZigDIScope *LLVMZigCompileUnitToScope(LLVMZigDICompileUnit *compile_unit);
|
||||
LLVMZigDIScope *LLVMZigFileToScope(LLVMZigDIFile *difile);
|
||||
LLVMZigDIScope *LLVMZigSubprogramToScope(LLVMZigDISubprogram *subprogram);
|
||||
|
||||
LLVMZigDILocalVariable *LLVMZigCreateLocalVariable(LLVMZigDIBuilder *dbuilder, unsigned tag,
|
||||
LLVMZigDIScope *scope, const char *name, LLVMZigDIFile *file, unsigned line_no,
|
||||
LLVMZigDIType *type, bool always_preserve, unsigned flags, unsigned arg_no);
|
||||
|
||||
LLVMZigDILexicalBlock *LLVMZigCreateLexicalBlock(LLVMZigDIBuilder *dbuilder, LLVMZigDIScope *scope,
|
||||
LLVMZigDIFile *file, unsigned line, unsigned col);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user