Skip to content

Commit

Permalink
stage2: add debug info for globals in the LLVM backend
Browse files Browse the repository at this point in the history
LLVM backend: generate DIGlobalVariable's for non-function globals and
rename linkage names when exporting functions and globals.

zig_llvm.cpp: add some wrappers to convert a handful of DI classes
into DINode's since DIGlobalVariable is not a DIScope like the others.

zig_llvm.cpp: add some wrappers to allow replacing the LinkageName of
DISubprogram and DIGlobalVariable.

zig_llvm.cpp: fix DI class mixup causing nonsense reinterpret_cast.

The end result is that GDB is now usable since you now no longer need
to manually cast every global nor fully qualifty every export.
  • Loading branch information
sengir committed Mar 14, 2022
1 parent 7ec2261 commit 820d9be
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 8 deletions.
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

0 comments on commit 820d9be

Please sign in to comment.