Skip to content

Commit 820d9be

Browse files
committed
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 qualifty every export.
1 parent 7ec2261 commit 820d9be

File tree

5 files changed

+150
-8
lines changed

5 files changed

+150
-8
lines changed

src/Module.zig

+1-1
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,7 @@ pub const Decl = struct {
663663
return (try decl.typedValue()).val;
664664
}
665665

666-
pub fn isFunction(decl: *Decl) !bool {
666+
pub fn isFunction(decl: Decl) !bool {
667667
const tv = try decl.typedValue();
668668
return tv.ty.zigTypeTag() == .Fn;
669669
}

src/codegen/llvm.zig

+47-4
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,9 @@ pub const Object = struct {
164164
di_builder: ?*llvm.DIBuilder,
165165
/// One of these mappings:
166166
/// - *Module.File => *DIFile
167-
/// - *Module.Decl => *DISubprogram
168-
di_map: std.AutoHashMapUnmanaged(*const anyopaque, *llvm.DIScope),
167+
/// - *Module.Decl (Fn) => *DISubprogram
168+
/// - *Module.Decl (Non-Fn) => *DIGlobalVariable
169+
di_map: std.AutoHashMapUnmanaged(*const anyopaque, *llvm.DINode),
169170
di_compile_unit: ?*llvm.DICompileUnit,
170171
context: *const llvm.Context,
171172
target_machine: *const llvm.TargetMachine,
@@ -591,6 +592,7 @@ pub const Object = struct {
591592
dg.module.comp.bin_file.options.optimize_mode != .Debug,
592593
null, // decl_subprogram
593594
);
595+
try dg.object.di_map.put(gpa, decl, subprogram.toNode());
594596

595597
llvm_func.fnSetSubprogram(subprogram);
596598

@@ -665,6 +667,17 @@ pub const Object = struct {
665667
llvm_global.setValueName(decl.name);
666668
llvm_global.setUnnamedAddr(.False);
667669
llvm_global.setLinkage(.External);
670+
if (self.di_map.get(decl)) |di_node| {
671+
if (try decl.isFunction()) {
672+
const di_func = @ptrCast(*llvm.DISubprogram, di_node);
673+
const linkage_name = llvm.MDString.get(self.context, decl.name, std.mem.len(decl.name));
674+
di_func.replaceLinkageName(linkage_name);
675+
} else {
676+
const di_global = @ptrCast(*llvm.DIGlobalVariable, di_node);
677+
const linkage_name = llvm.MDString.get(self.context, decl.name, std.mem.len(decl.name));
678+
di_global.replaceLinkageName(linkage_name);
679+
}
680+
}
668681
if (decl.val.castTag(.variable)) |variable| {
669682
if (variable.data.is_threadlocal) {
670683
llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
@@ -679,6 +692,17 @@ pub const Object = struct {
679692
const exp_name = exports[0].options.name;
680693
llvm_global.setValueName2(exp_name.ptr, exp_name.len);
681694
llvm_global.setUnnamedAddr(.False);
695+
if (self.di_map.get(decl)) |di_node| {
696+
if (try decl.isFunction()) {
697+
const di_func = @ptrCast(*llvm.DISubprogram, di_node);
698+
const linkage_name = llvm.MDString.get(self.context, exp_name.ptr, exp_name.len);
699+
di_func.replaceLinkageName(linkage_name);
700+
} else {
701+
const di_global = @ptrCast(*llvm.DIGlobalVariable, di_node);
702+
const linkage_name = llvm.MDString.get(self.context, exp_name.ptr, exp_name.len);
703+
di_global.replaceLinkageName(linkage_name);
704+
}
705+
}
682706
switch (exports[0].options.linkage) {
683707
.Internal => unreachable,
684708
.Strong => llvm_global.setLinkage(.External),
@@ -744,7 +768,7 @@ pub const Object = struct {
744768
const dir_path_z = try gpa.dupeZ(u8, dir_path);
745769
defer gpa.free(dir_path_z);
746770
const di_file = o.di_builder.?.createFile(sub_file_path_z, dir_path_z);
747-
gop.value_ptr.* = di_file.toScope();
771+
gop.value_ptr.* = di_file.toNode();
748772
return di_file;
749773
}
750774
};
@@ -782,7 +806,7 @@ pub const DeclGen = struct {
782806
_ = try dg.resolveLlvmFunction(extern_fn.data.owner_decl);
783807
} else {
784808
const target = dg.module.getTarget();
785-
const global = try dg.resolveGlobalDecl(decl);
809+
var global = try dg.resolveGlobalDecl(decl);
786810
global.setAlignment(decl.getAlignment(target));
787811
assert(decl.has_tv);
788812
const init_val = if (decl.val.castTag(.variable)) |payload| init_val: {
@@ -826,8 +850,27 @@ pub const DeclGen = struct {
826850
dg.object.decl_map.putAssumeCapacity(decl, new_global);
827851
new_global.takeName(global);
828852
global.deleteGlobal();
853+
global = new_global;
829854
}
830855
}
856+
857+
if (dg.object.di_builder) |dib| {
858+
const di_file = try dg.object.getDIFile(dg.gpa, decl.src_namespace.file_scope);
859+
860+
const line_number = decl.src_line + 1;
861+
const is_internal_linkage = !dg.module.decl_exports.contains(decl);
862+
const di_global = dib.createGlobalVariable(
863+
di_file.toScope(),
864+
decl.name,
865+
global.getValueName(),
866+
di_file,
867+
line_number,
868+
try dg.lowerDebugType(decl.ty),
869+
is_internal_linkage,
870+
);
871+
872+
try dg.object.di_map.put(dg.gpa, dg.decl, di_global.toNode());
873+
}
831874
}
832875
}
833876

src/codegen/llvm/bindings.zig

+36-2
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,17 @@ pub const Builder = opaque {
855855
extern fn LLVMBuildShuffleVector(*const Builder, V1: *const Value, V2: *const Value, Mask: *const Value, Name: [*:0]const u8) *const Value;
856856
};
857857

858-
pub const DIScope = opaque {};
858+
pub const MDString = opaque {
859+
pub const get = LLVMMDStringInContext2;
860+
extern fn LLVMMDStringInContext2(C: *const Context, Str: [*]const u8, SLen: usize) *MDString;
861+
};
862+
863+
pub const DIScope = opaque {
864+
pub const toNode = ZigLLVMScopeToNode;
865+
extern fn ZigLLVMScopeToNode(scope: *DIScope) *DINode;
866+
};
867+
868+
pub const DINode = opaque {};
859869
pub const Metadata = opaque {};
860870

861871
pub const IntPredicate = enum(c_uint) {
@@ -1421,28 +1431,52 @@ pub const address_space = struct {
14211431

14221432
pub const DIEnumerator = opaque {};
14231433
pub const DILocalVariable = opaque {};
1424-
pub const DIGlobalVariable = opaque {};
14251434
pub const DILocation = opaque {};
14261435

1436+
pub const DIGlobalVariable = opaque {
1437+
pub const toNode = ZigLLVMGlobalVariableToNode;
1438+
extern fn ZigLLVMGlobalVariableToNode(global_variable: *DIGlobalVariable) *DINode;
1439+
1440+
pub const replaceLinkageName = ZigLLVMGlobalVariableReplaceLinkageName;
1441+
extern fn ZigLLVMGlobalVariableReplaceLinkageName(global_variable: *DIGlobalVariable, linkage_name: *MDString) void;
1442+
};
14271443
pub const DIType = opaque {
14281444
pub const toScope = ZigLLVMTypeToScope;
14291445
extern fn ZigLLVMTypeToScope(ty: *DIType) *DIScope;
1446+
1447+
pub const toNode = ZigLLVMTypeToNode;
1448+
extern fn ZigLLVMTypeToNode(ty: *DIType) *DINode;
14301449
};
14311450
pub const DIFile = opaque {
14321451
pub const toScope = ZigLLVMFileToScope;
14331452
extern fn ZigLLVMFileToScope(difile: *DIFile) *DIScope;
1453+
1454+
pub const toNode = ZigLLVMFileToNode;
1455+
extern fn ZigLLVMFileToNode(difile: *DIFile) *DINode;
14341456
};
14351457
pub const DILexicalBlock = opaque {
14361458
pub const toScope = ZigLLVMLexicalBlockToScope;
14371459
extern fn ZigLLVMLexicalBlockToScope(lexical_block: *DILexicalBlock) *DIScope;
1460+
1461+
pub const toNode = ZigLLVMLexicalBlockToNode;
1462+
extern fn ZigLLVMLexicalBlockToNode(lexical_block: *DILexicalBlock) *DINode;
14381463
};
14391464
pub const DICompileUnit = opaque {
14401465
pub const toScope = ZigLLVMCompileUnitToScope;
14411466
extern fn ZigLLVMCompileUnitToScope(compile_unit: *DICompileUnit) *DIScope;
1467+
1468+
pub const toNode = ZigLLVMCompileUnitToNode;
1469+
extern fn ZigLLVMCompileUnitToNode(compile_unit: *DICompileUnit) *DINode;
14421470
};
14431471
pub const DISubprogram = opaque {
14441472
pub const toScope = ZigLLVMSubprogramToScope;
14451473
extern fn ZigLLVMSubprogramToScope(subprogram: *DISubprogram) *DIScope;
1474+
1475+
pub const toNode = ZigLLVMSubprogramToNode;
1476+
extern fn ZigLLVMSubprogramToNode(subprogram: *DISubprogram) *DINode;
1477+
1478+
pub const replaceLinkageName = ZigLLVMSubprogramReplaceLinkageName;
1479+
extern fn ZigLLVMSubprogramReplaceLinkageName(subprogram: *DISubprogram, linkage_name: *MDString) void;
14461480
};
14471481

14481482
pub const getDebugLoc = ZigLLVMGetDebugLoc;

src/zig_llvm.cpp

+51-1
Original file line numberDiff line numberDiff line change
@@ -840,7 +840,7 @@ ZigLLVMDIGlobalVariable *ZigLLVMCreateGlobalVariable(ZigLLVMDIBuilder *dbuilder,
840840
line_no,
841841
reinterpret_cast<DIType*>(di_type),
842842
is_local_to_unit);
843-
return reinterpret_cast<ZigLLVMDIGlobalVariable*>(result);
843+
return reinterpret_cast<ZigLLVMDIGlobalVariable*>(result->getVariable());
844844
}
845845

846846
ZigLLVMDILocalVariable *ZigLLVMCreateParameterVariable(ZigLLVMDIBuilder *dbuilder,
@@ -885,6 +885,56 @@ ZigLLVMDIScope *ZigLLVMTypeToScope(ZigLLVMDIType *type) {
885885
return reinterpret_cast<ZigLLVMDIScope*>(scope);
886886
}
887887

888+
ZigLLVMDINode *ZigLLVMLexicalBlockToNode(ZigLLVMDILexicalBlock *lexical_block) {
889+
DINode *node = reinterpret_cast<DILexicalBlock*>(lexical_block);
890+
return reinterpret_cast<ZigLLVMDINode*>(node);
891+
}
892+
893+
ZigLLVMDINode *ZigLLVMCompileUnitToNode(ZigLLVMDICompileUnit *compile_unit) {
894+
DINode *node = reinterpret_cast<DICompileUnit*>(compile_unit);
895+
return reinterpret_cast<ZigLLVMDINode*>(node);
896+
}
897+
898+
ZigLLVMDINode *ZigLLVMFileToNode(ZigLLVMDIFile *difile) {
899+
DINode *node = reinterpret_cast<DIFile*>(difile);
900+
return reinterpret_cast<ZigLLVMDINode*>(node);
901+
}
902+
903+
ZigLLVMDINode *ZigLLVMSubprogramToNode(ZigLLVMDISubprogram *subprogram) {
904+
DINode *node = reinterpret_cast<DISubprogram*>(subprogram);
905+
return reinterpret_cast<ZigLLVMDINode*>(node);
906+
}
907+
908+
ZigLLVMDINode *ZigLLVMTypeToNode(ZigLLVMDIType *type) {
909+
DINode *node = reinterpret_cast<DIType*>(type);
910+
return reinterpret_cast<ZigLLVMDINode*>(node);
911+
}
912+
913+
ZigLLVMDINode *ZigLLVMScopeToNode(ZigLLVMDIScope *scope) {
914+
DINode *node = reinterpret_cast<DIScope*>(scope);
915+
return reinterpret_cast<ZigLLVMDINode*>(node);
916+
}
917+
918+
ZigLLVMDINode *ZigLLVMGlobalVariableToNode(ZigLLVMDIGlobalVariable *global_variable) {
919+
DINode *node = reinterpret_cast<DIGlobalVariable*>(global_variable);
920+
return reinterpret_cast<ZigLLVMDINode*>(node);
921+
}
922+
923+
void ZigLLVMSubprogramReplaceLinkageName(ZigLLVMDISubprogram *subprogram,
924+
ZigLLVMMDString *linkage_name)
925+
{
926+
MDString *linkage_name_md = reinterpret_cast<MDString*>(linkage_name);
927+
reinterpret_cast<DISubprogram*>(subprogram)->replaceLinkageName(linkage_name_md);
928+
}
929+
930+
void ZigLLVMGlobalVariableReplaceLinkageName(ZigLLVMDIGlobalVariable *global_variable,
931+
ZigLLVMMDString *linkage_name)
932+
{
933+
Metadata *linkage_name_md = reinterpret_cast<MDString*>(linkage_name);
934+
// NOTE: Operand index must match llvm::DIGlobalVariable
935+
reinterpret_cast<DIGlobalVariable*>(global_variable)->replaceOperandWith(5, linkage_name_md);
936+
}
937+
888938
ZigLLVMDICompileUnit *ZigLLVMCreateCompileUnit(ZigLLVMDIBuilder *dibuilder,
889939
unsigned lang, ZigLLVMDIFile *difile, const char *producer,
890940
bool is_optimized, const char *flags, unsigned runtime_version, const char *split_name,

src/zig_llvm.h

+15
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ struct ZigLLVMDIGlobalVariable;
3838
struct ZigLLVMDILocation;
3939
struct ZigLLVMDIEnumerator;
4040
struct ZigLLVMInsertionPoint;
41+
struct ZigLLVMDINode;
42+
struct ZigLLVMMDString;
4143

4244
ZIG_EXTERN_C void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R);
4345
ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
@@ -238,6 +240,19 @@ ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMFileToScope(struct ZigLLVMDIFile *dif
238240
ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMSubprogramToScope(struct ZigLLVMDISubprogram *subprogram);
239241
ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMTypeToScope(struct ZigLLVMDIType *type);
240242

243+
ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMLexicalBlockToNode(struct ZigLLVMDILexicalBlock *lexical_block);
244+
ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMCompileUnitToNode(struct ZigLLVMDICompileUnit *compile_unit);
245+
ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMFileToNode(struct ZigLLVMDIFile *difile);
246+
ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMSubprogramToNode(struct ZigLLVMDISubprogram *subprogram);
247+
ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMTypeToNode(struct ZigLLVMDIType *type);
248+
ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMScopeToNode(struct ZigLLVMDIScope *scope);
249+
ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMGlobalVariableToNode(struct ZigLLVMDIGlobalVariable *global_variable);
250+
251+
ZIG_EXTERN_C void ZigLLVMSubprogramReplaceLinkageName(struct ZigLLVMDISubprogram *subprogram,
252+
struct ZigLLVMMDString *linkage_name);
253+
ZIG_EXTERN_C void ZigLLVMGlobalVariableReplaceLinkageName(struct ZigLLVMDIGlobalVariable *global_variable,
254+
struct ZigLLVMMDString *linkage_name);
255+
241256
ZIG_EXTERN_C struct ZigLLVMDILocalVariable *ZigLLVMCreateAutoVariable(struct ZigLLVMDIBuilder *dbuilder,
242257
struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_no,
243258
struct ZigLLVMDIType *type, bool always_preserve, unsigned flags);

0 commit comments

Comments
 (0)