Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

stage2: add debug info for globals in the LLVM backend #11147

Merged
merged 1 commit into from
Mar 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Module.zig
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,7 @@ pub const Decl = struct {
return (try decl.typedValue()).val;
}

pub fn isFunction(decl: *Decl) !bool {
pub fn isFunction(decl: Decl) !bool {
const tv = try decl.typedValue();
return tv.ty.zigTypeTag() == .Fn;
}
Expand Down
51 changes: 47 additions & 4 deletions src/codegen/llvm.zig
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,9 @@ pub const Object = struct {
di_builder: ?*llvm.DIBuilder,
/// One of these mappings:
/// - *Module.File => *DIFile
/// - *Module.Decl => *DISubprogram
di_map: std.AutoHashMapUnmanaged(*const anyopaque, *llvm.DIScope),
/// - *Module.Decl (Fn) => *DISubprogram
/// - *Module.Decl (Non-Fn) => *DIGlobalVariable
di_map: std.AutoHashMapUnmanaged(*const anyopaque, *llvm.DINode),
di_compile_unit: ?*llvm.DICompileUnit,
context: *const llvm.Context,
target_machine: *const llvm.TargetMachine,
Expand Down Expand Up @@ -591,6 +592,7 @@ pub const Object = struct {
dg.module.comp.bin_file.options.optimize_mode != .Debug,
null, // decl_subprogram
);
try dg.object.di_map.put(gpa, decl, subprogram.toNode());

llvm_func.fnSetSubprogram(subprogram);

Expand Down Expand Up @@ -665,6 +667,17 @@ pub const Object = struct {
llvm_global.setValueName(decl.name);
llvm_global.setUnnamedAddr(.False);
llvm_global.setLinkage(.External);
if (self.di_map.get(decl)) |di_node| {
if (try decl.isFunction()) {
const di_func = @ptrCast(*llvm.DISubprogram, di_node);
const linkage_name = llvm.MDString.get(self.context, decl.name, std.mem.len(decl.name));
di_func.replaceLinkageName(linkage_name);
} else {
const di_global = @ptrCast(*llvm.DIGlobalVariable, di_node);
const linkage_name = llvm.MDString.get(self.context, decl.name, std.mem.len(decl.name));
di_global.replaceLinkageName(linkage_name);
}
}
if (decl.val.castTag(.variable)) |variable| {
if (variable.data.is_threadlocal) {
llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
Expand All @@ -679,6 +692,17 @@ pub const Object = struct {
const exp_name = exports[0].options.name;
llvm_global.setValueName2(exp_name.ptr, exp_name.len);
llvm_global.setUnnamedAddr(.False);
if (self.di_map.get(decl)) |di_node| {
if (try decl.isFunction()) {
const di_func = @ptrCast(*llvm.DISubprogram, di_node);
const linkage_name = llvm.MDString.get(self.context, exp_name.ptr, exp_name.len);
di_func.replaceLinkageName(linkage_name);
} else {
const di_global = @ptrCast(*llvm.DIGlobalVariable, di_node);
const linkage_name = llvm.MDString.get(self.context, exp_name.ptr, exp_name.len);
di_global.replaceLinkageName(linkage_name);
}
}
switch (exports[0].options.linkage) {
.Internal => unreachable,
.Strong => llvm_global.setLinkage(.External),
Expand Down Expand Up @@ -744,7 +768,7 @@ pub const Object = struct {
const dir_path_z = try gpa.dupeZ(u8, dir_path);
defer gpa.free(dir_path_z);
const di_file = o.di_builder.?.createFile(sub_file_path_z, dir_path_z);
gop.value_ptr.* = di_file.toScope();
gop.value_ptr.* = di_file.toNode();
return di_file;
}
};
Expand Down Expand Up @@ -782,7 +806,7 @@ pub const DeclGen = struct {
_ = try dg.resolveLlvmFunction(extern_fn.data.owner_decl);
} else {
const target = dg.module.getTarget();
const global = try dg.resolveGlobalDecl(decl);
var global = try dg.resolveGlobalDecl(decl);
global.setAlignment(decl.getAlignment(target));
assert(decl.has_tv);
const init_val = if (decl.val.castTag(.variable)) |payload| init_val: {
Expand Down Expand Up @@ -826,8 +850,27 @@ pub const DeclGen = struct {
dg.object.decl_map.putAssumeCapacity(decl, new_global);
new_global.takeName(global);
global.deleteGlobal();
global = new_global;
}
}

if (dg.object.di_builder) |dib| {
const di_file = try dg.object.getDIFile(dg.gpa, decl.src_namespace.file_scope);

const line_number = decl.src_line + 1;
const is_internal_linkage = !dg.module.decl_exports.contains(decl);
const di_global = dib.createGlobalVariable(
di_file.toScope(),
decl.name,
global.getValueName(),
di_file,
line_number,
try dg.lowerDebugType(decl.ty),
is_internal_linkage,
);

try dg.object.di_map.put(dg.gpa, dg.decl, di_global.toNode());
}
}
}

Expand Down
38 changes: 36 additions & 2 deletions src/codegen/llvm/bindings.zig
Original file line number Diff line number Diff line change
Expand Up @@ -855,7 +855,17 @@ pub const Builder = opaque {
extern fn LLVMBuildShuffleVector(*const Builder, V1: *const Value, V2: *const Value, Mask: *const Value, Name: [*:0]const u8) *const Value;
};

pub const DIScope = opaque {};
pub const MDString = opaque {
pub const get = LLVMMDStringInContext2;
extern fn LLVMMDStringInContext2(C: *const Context, Str: [*]const u8, SLen: usize) *MDString;
};

pub const DIScope = opaque {
pub const toNode = ZigLLVMScopeToNode;
extern fn ZigLLVMScopeToNode(scope: *DIScope) *DINode;
};

pub const DINode = opaque {};
pub const Metadata = opaque {};

pub const IntPredicate = enum(c_uint) {
Expand Down Expand Up @@ -1421,28 +1431,52 @@ pub const address_space = struct {

pub const DIEnumerator = opaque {};
pub const DILocalVariable = opaque {};
pub const DIGlobalVariable = opaque {};
pub const DILocation = opaque {};

pub const DIGlobalVariable = opaque {
pub const toNode = ZigLLVMGlobalVariableToNode;
extern fn ZigLLVMGlobalVariableToNode(global_variable: *DIGlobalVariable) *DINode;

pub const replaceLinkageName = ZigLLVMGlobalVariableReplaceLinkageName;
extern fn ZigLLVMGlobalVariableReplaceLinkageName(global_variable: *DIGlobalVariable, linkage_name: *MDString) void;
};
pub const DIType = opaque {
pub const toScope = ZigLLVMTypeToScope;
extern fn ZigLLVMTypeToScope(ty: *DIType) *DIScope;

pub const toNode = ZigLLVMTypeToNode;
extern fn ZigLLVMTypeToNode(ty: *DIType) *DINode;
};
pub const DIFile = opaque {
pub const toScope = ZigLLVMFileToScope;
extern fn ZigLLVMFileToScope(difile: *DIFile) *DIScope;

pub const toNode = ZigLLVMFileToNode;
extern fn ZigLLVMFileToNode(difile: *DIFile) *DINode;
};
pub const DILexicalBlock = opaque {
pub const toScope = ZigLLVMLexicalBlockToScope;
extern fn ZigLLVMLexicalBlockToScope(lexical_block: *DILexicalBlock) *DIScope;

pub const toNode = ZigLLVMLexicalBlockToNode;
extern fn ZigLLVMLexicalBlockToNode(lexical_block: *DILexicalBlock) *DINode;
};
pub const DICompileUnit = opaque {
pub const toScope = ZigLLVMCompileUnitToScope;
extern fn ZigLLVMCompileUnitToScope(compile_unit: *DICompileUnit) *DIScope;

pub const toNode = ZigLLVMCompileUnitToNode;
extern fn ZigLLVMCompileUnitToNode(compile_unit: *DICompileUnit) *DINode;
};
pub const DISubprogram = opaque {
pub const toScope = ZigLLVMSubprogramToScope;
extern fn ZigLLVMSubprogramToScope(subprogram: *DISubprogram) *DIScope;

pub const toNode = ZigLLVMSubprogramToNode;
extern fn ZigLLVMSubprogramToNode(subprogram: *DISubprogram) *DINode;

pub const replaceLinkageName = ZigLLVMSubprogramReplaceLinkageName;
extern fn ZigLLVMSubprogramReplaceLinkageName(subprogram: *DISubprogram, linkage_name: *MDString) void;
};

pub const getDebugLoc = ZigLLVMGetDebugLoc;
Expand Down
52 changes: 51 additions & 1 deletion src/zig_llvm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -840,7 +840,7 @@ ZigLLVMDIGlobalVariable *ZigLLVMCreateGlobalVariable(ZigLLVMDIBuilder *dbuilder,
line_no,
reinterpret_cast<DIType*>(di_type),
is_local_to_unit);
return reinterpret_cast<ZigLLVMDIGlobalVariable*>(result);
return reinterpret_cast<ZigLLVMDIGlobalVariable*>(result->getVariable());
}

ZigLLVMDILocalVariable *ZigLLVMCreateParameterVariable(ZigLLVMDIBuilder *dbuilder,
Expand Down Expand Up @@ -885,6 +885,56 @@ ZigLLVMDIScope *ZigLLVMTypeToScope(ZigLLVMDIType *type) {
return reinterpret_cast<ZigLLVMDIScope*>(scope);
}

ZigLLVMDINode *ZigLLVMLexicalBlockToNode(ZigLLVMDILexicalBlock *lexical_block) {
DINode *node = reinterpret_cast<DILexicalBlock*>(lexical_block);
return reinterpret_cast<ZigLLVMDINode*>(node);
}

ZigLLVMDINode *ZigLLVMCompileUnitToNode(ZigLLVMDICompileUnit *compile_unit) {
DINode *node = reinterpret_cast<DICompileUnit*>(compile_unit);
return reinterpret_cast<ZigLLVMDINode*>(node);
}

ZigLLVMDINode *ZigLLVMFileToNode(ZigLLVMDIFile *difile) {
DINode *node = reinterpret_cast<DIFile*>(difile);
return reinterpret_cast<ZigLLVMDINode*>(node);
}

ZigLLVMDINode *ZigLLVMSubprogramToNode(ZigLLVMDISubprogram *subprogram) {
DINode *node = reinterpret_cast<DISubprogram*>(subprogram);
return reinterpret_cast<ZigLLVMDINode*>(node);
}

ZigLLVMDINode *ZigLLVMTypeToNode(ZigLLVMDIType *type) {
DINode *node = reinterpret_cast<DIType*>(type);
return reinterpret_cast<ZigLLVMDINode*>(node);
}

ZigLLVMDINode *ZigLLVMScopeToNode(ZigLLVMDIScope *scope) {
DINode *node = reinterpret_cast<DIScope*>(scope);
return reinterpret_cast<ZigLLVMDINode*>(node);
}

ZigLLVMDINode *ZigLLVMGlobalVariableToNode(ZigLLVMDIGlobalVariable *global_variable) {
DINode *node = reinterpret_cast<DIGlobalVariable*>(global_variable);
return reinterpret_cast<ZigLLVMDINode*>(node);
}

void ZigLLVMSubprogramReplaceLinkageName(ZigLLVMDISubprogram *subprogram,
ZigLLVMMDString *linkage_name)
{
MDString *linkage_name_md = reinterpret_cast<MDString*>(linkage_name);
reinterpret_cast<DISubprogram*>(subprogram)->replaceLinkageName(linkage_name_md);
}

void ZigLLVMGlobalVariableReplaceLinkageName(ZigLLVMDIGlobalVariable *global_variable,
ZigLLVMMDString *linkage_name)
{
Metadata *linkage_name_md = reinterpret_cast<MDString*>(linkage_name);
// NOTE: Operand index must match llvm::DIGlobalVariable
reinterpret_cast<DIGlobalVariable*>(global_variable)->replaceOperandWith(5, linkage_name_md);
}

ZigLLVMDICompileUnit *ZigLLVMCreateCompileUnit(ZigLLVMDIBuilder *dibuilder,
unsigned lang, ZigLLVMDIFile *difile, const char *producer,
bool is_optimized, const char *flags, unsigned runtime_version, const char *split_name,
Expand Down
15 changes: 15 additions & 0 deletions src/zig_llvm.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ struct ZigLLVMDIGlobalVariable;
struct ZigLLVMDILocation;
struct ZigLLVMDIEnumerator;
struct ZigLLVMInsertionPoint;
struct ZigLLVMDINode;
struct ZigLLVMMDString;

ZIG_EXTERN_C void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R);
ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
Expand Down Expand Up @@ -238,6 +240,19 @@ ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMFileToScope(struct ZigLLVMDIFile *dif
ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMSubprogramToScope(struct ZigLLVMDISubprogram *subprogram);
ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMTypeToScope(struct ZigLLVMDIType *type);

ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMLexicalBlockToNode(struct ZigLLVMDILexicalBlock *lexical_block);
ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMCompileUnitToNode(struct ZigLLVMDICompileUnit *compile_unit);
ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMFileToNode(struct ZigLLVMDIFile *difile);
ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMSubprogramToNode(struct ZigLLVMDISubprogram *subprogram);
ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMTypeToNode(struct ZigLLVMDIType *type);
ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMScopeToNode(struct ZigLLVMDIScope *scope);
ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMGlobalVariableToNode(struct ZigLLVMDIGlobalVariable *global_variable);

ZIG_EXTERN_C void ZigLLVMSubprogramReplaceLinkageName(struct ZigLLVMDISubprogram *subprogram,
struct ZigLLVMMDString *linkage_name);
ZIG_EXTERN_C void ZigLLVMGlobalVariableReplaceLinkageName(struct ZigLLVMDIGlobalVariable *global_variable,
struct ZigLLVMMDString *linkage_name);

ZIG_EXTERN_C struct ZigLLVMDILocalVariable *ZigLLVMCreateAutoVariable(struct ZigLLVMDIBuilder *dbuilder,
struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_no,
struct ZigLLVMDIType *type, bool always_preserve, unsigned flags);
Expand Down