mirror of
https://github.com/ziglang/zig.git
synced 2026-02-14 13:30:45 +00:00
stage2: add debug info for globals in the LLVM backend
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 qualify every export.
This commit is contained in:
parent
f36bf8506c
commit
c757f19790
@ -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;
|
||||
}
|
||||
|
||||
@ -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,
|
||||
@ -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);
|
||||
|
||||
@ -667,6 +669,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);
|
||||
@ -681,6 +694,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),
|
||||
@ -746,7 +770,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;
|
||||
}
|
||||
};
|
||||
@ -784,7 +808,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: {
|
||||
@ -828,8 +852,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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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) {
|
||||
@ -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;
|
||||
|
||||
@ -842,7 +842,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,
|
||||
@ -887,6 +887,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,
|
||||
|
||||
@ -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);
|
||||
@ -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);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user