authorgravatar for william@sengir.comWilliam Sengir <william@sengir.com> 2022-03-13 00:28:34-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-03-15 00:38:20-04:00
logc757f197903940115c1d42883240ec1fe7ef660c
tree31915696778776c3a906df85cbf08e428f052b90
parentf36bf8506c9c1fa48dadd699b3122acd15890cf6

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.

5 files changed, 150 insertions(+), 8 deletions(-)

src/Module.zig+1-1
...@@ -663,7 +663,7 @@ pub const Decl = struct {...@@ -663,7 +663,7 @@ pub const Decl = struct {
663 return (try decl.typedValue()).val;663 return (try decl.typedValue()).val;
664 }664 }
665665
666 pub fn isFunction(decl: *Decl) !bool {666 pub fn isFunction(decl: Decl) !bool {
667 const tv = try decl.typedValue();667 const tv = try decl.typedValue();
668 return tv.ty.zigTypeTag() == .Fn;668 return tv.ty.zigTypeTag() == .Fn;
669 }669 }
src/codegen/llvm.zig+47-4
...@@ -164,8 +164,9 @@ pub const Object = struct {...@@ -164,8 +164,9 @@ pub const Object = struct {
164 di_builder: ?*llvm.DIBuilder,164 di_builder: ?*llvm.DIBuilder,
165 /// One of these mappings:165 /// One of these mappings:
166 /// - *Module.File => *DIFile166 /// - *Module.File => *DIFile
167 /// - *Module.Decl => *DISubprogram167 /// - *Module.Decl (Fn) => *DISubprogram
168 di_map: std.AutoHashMapUnmanaged(*const anyopaque, *llvm.DIScope),168 /// - *Module.Decl (Non-Fn) => *DIGlobalVariable
169 di_map: std.AutoHashMapUnmanaged(*const anyopaque, *llvm.DINode),
169 di_compile_unit: ?*llvm.DICompileUnit,170 di_compile_unit: ?*llvm.DICompileUnit,
170 context: *const llvm.Context,171 context: *const llvm.Context,
171 target_machine: *const llvm.TargetMachine,172 target_machine: *const llvm.TargetMachine,
...@@ -591,6 +592,7 @@ pub const Object = struct {...@@ -591,6 +592,7 @@ pub const Object = struct {
591 dg.module.comp.bin_file.options.optimize_mode != .Debug,592 dg.module.comp.bin_file.options.optimize_mode != .Debug,
592 null, // decl_subprogram593 null, // decl_subprogram
593 );594 );
595 try dg.object.di_map.put(gpa, decl, subprogram.toNode());
594596
595 llvm_func.fnSetSubprogram(subprogram);597 llvm_func.fnSetSubprogram(subprogram);
596598
...@@ -667,6 +669,17 @@ pub const Object = struct {...@@ -667,6 +669,17 @@ pub const Object = struct {
667 llvm_global.setValueName(decl.name);669 llvm_global.setValueName(decl.name);
668 llvm_global.setUnnamedAddr(.False);670 llvm_global.setUnnamedAddr(.False);
669 llvm_global.setLinkage(.External);671 llvm_global.setLinkage(.External);
672 if (self.di_map.get(decl)) |di_node| {
673 if (try decl.isFunction()) {
674 const di_func = @ptrCast(*llvm.DISubprogram, di_node);
675 const linkage_name = llvm.MDString.get(self.context, decl.name, std.mem.len(decl.name));
676 di_func.replaceLinkageName(linkage_name);
677 } else {
678 const di_global = @ptrCast(*llvm.DIGlobalVariable, di_node);
679 const linkage_name = llvm.MDString.get(self.context, decl.name, std.mem.len(decl.name));
680 di_global.replaceLinkageName(linkage_name);
681 }
682 }
670 if (decl.val.castTag(.variable)) |variable| {683 if (decl.val.castTag(.variable)) |variable| {
671 if (variable.data.is_threadlocal) {684 if (variable.data.is_threadlocal) {
672 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);685 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
...@@ -681,6 +694,17 @@ pub const Object = struct {...@@ -681,6 +694,17 @@ pub const Object = struct {
681 const exp_name = exports[0].options.name;694 const exp_name = exports[0].options.name;
682 llvm_global.setValueName2(exp_name.ptr, exp_name.len);695 llvm_global.setValueName2(exp_name.ptr, exp_name.len);
683 llvm_global.setUnnamedAddr(.False);696 llvm_global.setUnnamedAddr(.False);
697 if (self.di_map.get(decl)) |di_node| {
698 if (try decl.isFunction()) {
699 const di_func = @ptrCast(*llvm.DISubprogram, di_node);
700 const linkage_name = llvm.MDString.get(self.context, exp_name.ptr, exp_name.len);
701 di_func.replaceLinkageName(linkage_name);
702 } else {
703 const di_global = @ptrCast(*llvm.DIGlobalVariable, di_node);
704 const linkage_name = llvm.MDString.get(self.context, exp_name.ptr, exp_name.len);
705 di_global.replaceLinkageName(linkage_name);
706 }
707 }
684 switch (exports[0].options.linkage) {708 switch (exports[0].options.linkage) {
685 .Internal => unreachable,709 .Internal => unreachable,
686 .Strong => llvm_global.setLinkage(.External),710 .Strong => llvm_global.setLinkage(.External),
...@@ -746,7 +770,7 @@ pub const Object = struct {...@@ -746,7 +770,7 @@ pub const Object = struct {
746 const dir_path_z = try gpa.dupeZ(u8, dir_path);770 const dir_path_z = try gpa.dupeZ(u8, dir_path);
747 defer gpa.free(dir_path_z);771 defer gpa.free(dir_path_z);
748 const di_file = o.di_builder.?.createFile(sub_file_path_z, dir_path_z);772 const di_file = o.di_builder.?.createFile(sub_file_path_z, dir_path_z);
749 gop.value_ptr.* = di_file.toScope();773 gop.value_ptr.* = di_file.toNode();
750 return di_file;774 return di_file;
751 }775 }
752};776};
...@@ -784,7 +808,7 @@ pub const DeclGen = struct {...@@ -784,7 +808,7 @@ pub const DeclGen = struct {
784 _ = try dg.resolveLlvmFunction(extern_fn.data.owner_decl);808 _ = try dg.resolveLlvmFunction(extern_fn.data.owner_decl);
785 } else {809 } else {
786 const target = dg.module.getTarget();810 const target = dg.module.getTarget();
787 const global = try dg.resolveGlobalDecl(decl);811 var global = try dg.resolveGlobalDecl(decl);
788 global.setAlignment(decl.getAlignment(target));812 global.setAlignment(decl.getAlignment(target));
789 assert(decl.has_tv);813 assert(decl.has_tv);
790 const init_val = if (decl.val.castTag(.variable)) |payload| init_val: {814 const init_val = if (decl.val.castTag(.variable)) |payload| init_val: {
...@@ -828,8 +852,27 @@ pub const DeclGen = struct {...@@ -828,8 +852,27 @@ pub const DeclGen = struct {
828 dg.object.decl_map.putAssumeCapacity(decl, new_global);852 dg.object.decl_map.putAssumeCapacity(decl, new_global);
829 new_global.takeName(global);853 new_global.takeName(global);
830 global.deleteGlobal();854 global.deleteGlobal();
855 global = new_global;
831 }856 }
832 }857 }
858
859 if (dg.object.di_builder) |dib| {
860 const di_file = try dg.object.getDIFile(dg.gpa, decl.src_namespace.file_scope);
861
862 const line_number = decl.src_line + 1;
863 const is_internal_linkage = !dg.module.decl_exports.contains(decl);
864 const di_global = dib.createGlobalVariable(
865 di_file.toScope(),
866 decl.name,
867 global.getValueName(),
868 di_file,
869 line_number,
870 try dg.lowerDebugType(decl.ty),
871 is_internal_linkage,
872 );
873
874 try dg.object.di_map.put(dg.gpa, dg.decl, di_global.toNode());
875 }
833 }876 }
834 }877 }
835878
src/codegen/llvm/bindings.zig+36-2
...@@ -855,7 +855,17 @@ pub const Builder = opaque {...@@ -855,7 +855,17 @@ pub const Builder = opaque {
855 extern fn LLVMBuildShuffleVector(*const Builder, V1: *const Value, V2: *const Value, Mask: *const Value, Name: [*:0]const u8) *const Value;855 extern fn LLVMBuildShuffleVector(*const Builder, V1: *const Value, V2: *const Value, Mask: *const Value, Name: [*:0]const u8) *const Value;
856};856};
857857
858pub const DIScope = opaque {};858pub const MDString = opaque {
859 pub const get = LLVMMDStringInContext2;
860 extern fn LLVMMDStringInContext2(C: *const Context, Str: [*]const u8, SLen: usize) *MDString;
861};
862
863pub const DIScope = opaque {
864 pub const toNode = ZigLLVMScopeToNode;
865 extern fn ZigLLVMScopeToNode(scope: *DIScope) *DINode;
866};
867
868pub const DINode = opaque {};
859pub const Metadata = opaque {};869pub const Metadata = opaque {};
860870
861pub const IntPredicate = enum(c_uint) {871pub const IntPredicate = enum(c_uint) {
...@@ -1421,28 +1431,52 @@ pub const address_space = struct {...@@ -1421,28 +1431,52 @@ pub const address_space = struct {
14211431
1422pub const DIEnumerator = opaque {};1432pub const DIEnumerator = opaque {};
1423pub const DILocalVariable = opaque {};1433pub const DILocalVariable = opaque {};
1424pub const DIGlobalVariable = opaque {};
1425pub const DILocation = opaque {};1434pub const DILocation = opaque {};
14261435
1436pub 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};
1427pub const DIType = opaque {1443pub const DIType = opaque {
1428 pub const toScope = ZigLLVMTypeToScope;1444 pub const toScope = ZigLLVMTypeToScope;
1429 extern fn ZigLLVMTypeToScope(ty: *DIType) *DIScope;1445 extern fn ZigLLVMTypeToScope(ty: *DIType) *DIScope;
1446
1447 pub const toNode = ZigLLVMTypeToNode;
1448 extern fn ZigLLVMTypeToNode(ty: *DIType) *DINode;
1430};1449};
1431pub const DIFile = opaque {1450pub const DIFile = opaque {
1432 pub const toScope = ZigLLVMFileToScope;1451 pub const toScope = ZigLLVMFileToScope;
1433 extern fn ZigLLVMFileToScope(difile: *DIFile) *DIScope;1452 extern fn ZigLLVMFileToScope(difile: *DIFile) *DIScope;
1453
1454 pub const toNode = ZigLLVMFileToNode;
1455 extern fn ZigLLVMFileToNode(difile: *DIFile) *DINode;
1434};1456};
1435pub const DILexicalBlock = opaque {1457pub const DILexicalBlock = opaque {
1436 pub const toScope = ZigLLVMLexicalBlockToScope;1458 pub const toScope = ZigLLVMLexicalBlockToScope;
1437 extern fn ZigLLVMLexicalBlockToScope(lexical_block: *DILexicalBlock) *DIScope;1459 extern fn ZigLLVMLexicalBlockToScope(lexical_block: *DILexicalBlock) *DIScope;
1460
1461 pub const toNode = ZigLLVMLexicalBlockToNode;
1462 extern fn ZigLLVMLexicalBlockToNode(lexical_block: *DILexicalBlock) *DINode;
1438};1463};
1439pub const DICompileUnit = opaque {1464pub const DICompileUnit = opaque {
1440 pub const toScope = ZigLLVMCompileUnitToScope;1465 pub const toScope = ZigLLVMCompileUnitToScope;
1441 extern fn ZigLLVMCompileUnitToScope(compile_unit: *DICompileUnit) *DIScope;1466 extern fn ZigLLVMCompileUnitToScope(compile_unit: *DICompileUnit) *DIScope;
1467
1468 pub const toNode = ZigLLVMCompileUnitToNode;
1469 extern fn ZigLLVMCompileUnitToNode(compile_unit: *DICompileUnit) *DINode;
1442};1470};
1443pub const DISubprogram = opaque {1471pub const DISubprogram = opaque {
1444 pub const toScope = ZigLLVMSubprogramToScope;1472 pub const toScope = ZigLLVMSubprogramToScope;
1445 extern fn ZigLLVMSubprogramToScope(subprogram: *DISubprogram) *DIScope;1473 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;
1446};1480};
14471481
1448pub const getDebugLoc = ZigLLVMGetDebugLoc;1482pub const getDebugLoc = ZigLLVMGetDebugLoc;
src/zig_llvm.cpp+51-1
...@@ -842,7 +842,7 @@ ZigLLVMDIGlobalVariable *ZigLLVMCreateGlobalVariable(ZigLLVMDIBuilder *dbuilder,...@@ -842,7 +842,7 @@ ZigLLVMDIGlobalVariable *ZigLLVMCreateGlobalVariable(ZigLLVMDIBuilder *dbuilder,
842 line_no,842 line_no,
843 reinterpret_cast<DIType*>(di_type),843 reinterpret_cast<DIType*>(di_type),
844 is_local_to_unit);844 is_local_to_unit);
845 return reinterpret_cast<ZigLLVMDIGlobalVariable*>(result);845 return reinterpret_cast<ZigLLVMDIGlobalVariable*>(result->getVariable());
846}846}
847847
848ZigLLVMDILocalVariable *ZigLLVMCreateParameterVariable(ZigLLVMDIBuilder *dbuilder,848ZigLLVMDILocalVariable *ZigLLVMCreateParameterVariable(ZigLLVMDIBuilder *dbuilder,
...@@ -887,6 +887,56 @@ ZigLLVMDIScope *ZigLLVMTypeToScope(ZigLLVMDIType *type) {...@@ -887,6 +887,56 @@ ZigLLVMDIScope *ZigLLVMTypeToScope(ZigLLVMDIType *type) {
887 return reinterpret_cast<ZigLLVMDIScope*>(scope);887 return reinterpret_cast<ZigLLVMDIScope*>(scope);
888}888}
889889
890ZigLLVMDINode *ZigLLVMLexicalBlockToNode(ZigLLVMDILexicalBlock *lexical_block) {
891 DINode *node = reinterpret_cast<DILexicalBlock*>(lexical_block);
892 return reinterpret_cast<ZigLLVMDINode*>(node);
893}
894
895ZigLLVMDINode *ZigLLVMCompileUnitToNode(ZigLLVMDICompileUnit *compile_unit) {
896 DINode *node = reinterpret_cast<DICompileUnit*>(compile_unit);
897 return reinterpret_cast<ZigLLVMDINode*>(node);
898}
899
900ZigLLVMDINode *ZigLLVMFileToNode(ZigLLVMDIFile *difile) {
901 DINode *node = reinterpret_cast<DIFile*>(difile);
902 return reinterpret_cast<ZigLLVMDINode*>(node);
903}
904
905ZigLLVMDINode *ZigLLVMSubprogramToNode(ZigLLVMDISubprogram *subprogram) {
906 DINode *node = reinterpret_cast<DISubprogram*>(subprogram);
907 return reinterpret_cast<ZigLLVMDINode*>(node);
908}
909
910ZigLLVMDINode *ZigLLVMTypeToNode(ZigLLVMDIType *type) {
911 DINode *node = reinterpret_cast<DIType*>(type);
912 return reinterpret_cast<ZigLLVMDINode*>(node);
913}
914
915ZigLLVMDINode *ZigLLVMScopeToNode(ZigLLVMDIScope *scope) {
916 DINode *node = reinterpret_cast<DIScope*>(scope);
917 return reinterpret_cast<ZigLLVMDINode*>(node);
918}
919
920ZigLLVMDINode *ZigLLVMGlobalVariableToNode(ZigLLVMDIGlobalVariable *global_variable) {
921 DINode *node = reinterpret_cast<DIGlobalVariable*>(global_variable);
922 return reinterpret_cast<ZigLLVMDINode*>(node);
923}
924
925void ZigLLVMSubprogramReplaceLinkageName(ZigLLVMDISubprogram *subprogram,
926 ZigLLVMMDString *linkage_name)
927{
928 MDString *linkage_name_md = reinterpret_cast<MDString*>(linkage_name);
929 reinterpret_cast<DISubprogram*>(subprogram)->replaceLinkageName(linkage_name_md);
930}
931
932void ZigLLVMGlobalVariableReplaceLinkageName(ZigLLVMDIGlobalVariable *global_variable,
933 ZigLLVMMDString *linkage_name)
934{
935 Metadata *linkage_name_md = reinterpret_cast<MDString*>(linkage_name);
936 // NOTE: Operand index must match llvm::DIGlobalVariable
937 reinterpret_cast<DIGlobalVariable*>(global_variable)->replaceOperandWith(5, linkage_name_md);
938}
939
890ZigLLVMDICompileUnit *ZigLLVMCreateCompileUnit(ZigLLVMDIBuilder *dibuilder,940ZigLLVMDICompileUnit *ZigLLVMCreateCompileUnit(ZigLLVMDIBuilder *dibuilder,
891 unsigned lang, ZigLLVMDIFile *difile, const char *producer,941 unsigned lang, ZigLLVMDIFile *difile, const char *producer,
892 bool is_optimized, const char *flags, unsigned runtime_version, const char *split_name,942 bool is_optimized, const char *flags, unsigned runtime_version, const char *split_name,
src/zig_llvm.h+15
...@@ -38,6 +38,8 @@ struct ZigLLVMDIGlobalVariable;...@@ -38,6 +38,8 @@ struct ZigLLVMDIGlobalVariable;
38struct ZigLLVMDILocation;38struct ZigLLVMDILocation;
39struct ZigLLVMDIEnumerator;39struct ZigLLVMDIEnumerator;
40struct ZigLLVMInsertionPoint;40struct ZigLLVMInsertionPoint;
41struct ZigLLVMDINode;
42struct ZigLLVMMDString;
4143
42ZIG_EXTERN_C void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R);44ZIG_EXTERN_C void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R);
43ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);45ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
...@@ -238,6 +240,19 @@ ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMFileToScope(struct ZigLLVMDIFile *dif...@@ -238,6 +240,19 @@ ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMFileToScope(struct ZigLLVMDIFile *dif
238ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMSubprogramToScope(struct ZigLLVMDISubprogram *subprogram);240ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMSubprogramToScope(struct ZigLLVMDISubprogram *subprogram);
239ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMTypeToScope(struct ZigLLVMDIType *type);241ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMTypeToScope(struct ZigLLVMDIType *type);
240242
243ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMLexicalBlockToNode(struct ZigLLVMDILexicalBlock *lexical_block);
244ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMCompileUnitToNode(struct ZigLLVMDICompileUnit *compile_unit);
245ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMFileToNode(struct ZigLLVMDIFile *difile);
246ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMSubprogramToNode(struct ZigLLVMDISubprogram *subprogram);
247ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMTypeToNode(struct ZigLLVMDIType *type);
248ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMScopeToNode(struct ZigLLVMDIScope *scope);
249ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMGlobalVariableToNode(struct ZigLLVMDIGlobalVariable *global_variable);
250
251ZIG_EXTERN_C void ZigLLVMSubprogramReplaceLinkageName(struct ZigLLVMDISubprogram *subprogram,
252 struct ZigLLVMMDString *linkage_name);
253ZIG_EXTERN_C void ZigLLVMGlobalVariableReplaceLinkageName(struct ZigLLVMDIGlobalVariable *global_variable,
254 struct ZigLLVMMDString *linkage_name);
255
241ZIG_EXTERN_C struct ZigLLVMDILocalVariable *ZigLLVMCreateAutoVariable(struct ZigLLVMDIBuilder *dbuilder,256ZIG_EXTERN_C struct ZigLLVMDILocalVariable *ZigLLVMCreateAutoVariable(struct ZigLLVMDIBuilder *dbuilder,
242 struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_no,257 struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_no,
243 struct ZigLLVMDIType *type, bool always_preserve, unsigned flags);258 struct ZigLLVMDIType *type, bool always_preserve, unsigned flags);