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 {
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
......@@ -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
......@@ -667,6 +669,17 @@ pub const Object = struct {
667669 llvm_global.setValueName(decl.name);
668670 llvm_global.setUnnamedAddr(.False);
669671 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 }
670683 if (decl.val.castTag(.variable)) |variable| {
671684 if (variable.data.is_threadlocal) {
672685 llvm_global.setThreadLocalMode(.GeneralDynamicTLSModel);
......@@ -681,6 +694,17 @@ pub const Object = struct {
681694 const exp_name = exports[0].options.name;
682695 llvm_global.setValueName2(exp_name.ptr, exp_name.len);
683696 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 }
684708 switch (exports[0].options.linkage) {
685709 .Internal => unreachable,
686710 .Strong => llvm_global.setLinkage(.External),
......@@ -746,7 +770,7 @@ pub const Object = struct {
746770 const dir_path_z = try gpa.dupeZ(u8, dir_path);
747771 defer gpa.free(dir_path_z);
748772 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();
750774 return di_file;
751775 }
752776};
......@@ -784,7 +808,7 @@ pub const DeclGen = struct {
784808 _ = try dg.resolveLlvmFunction(extern_fn.data.owner_decl);
785809 } else {
786810 const target = dg.module.getTarget();
787 const global = try dg.resolveGlobalDecl(decl);
811 var global = try dg.resolveGlobalDecl(decl);
788812 global.setAlignment(decl.getAlignment(target));
789813 assert(decl.has_tv);
790814 const init_val = if (decl.val.castTag(.variable)) |payload| init_val: {
......@@ -828,8 +852,27 @@ pub const DeclGen = struct {
828852 dg.object.decl_map.putAssumeCapacity(decl, new_global);
829853 new_global.takeName(global);
830854 global.deleteGlobal();
855 global = new_global;
831856 }
832857 }
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 }
833876 }
834877 }
835878
src/codegen/llvm/bindings.zig+36-2
......@@ -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
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 {};
859869pub const Metadata = opaque {};
860870
861871pub const IntPredicate = enum(c_uint) {
......@@ -1421,28 +1431,52 @@ pub const address_space = struct {
14211431
14221432pub const DIEnumerator = opaque {};
14231433pub const DILocalVariable = opaque {};
1424pub const DIGlobalVariable = opaque {};
14251434pub 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};
14271443pub 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};
14311450pub 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};
14351457pub 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};
14391464pub 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};
14431471pub 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
14481482pub const getDebugLoc = ZigLLVMGetDebugLoc;
src/zig_llvm.cpp+51-1
......@@ -842,7 +842,7 @@ ZigLLVMDIGlobalVariable *ZigLLVMCreateGlobalVariable(ZigLLVMDIBuilder *dbuilder,
842842 line_no,
843843 reinterpret_cast<DIType*>(di_type),
844844 is_local_to_unit);
845 return reinterpret_cast<ZigLLVMDIGlobalVariable*>(result);
845 return reinterpret_cast<ZigLLVMDIGlobalVariable*>(result->getVariable());
846846}
847847
848848ZigLLVMDILocalVariable *ZigLLVMCreateParameterVariable(ZigLLVMDIBuilder *dbuilder,
......@@ -887,6 +887,56 @@ ZigLLVMDIScope *ZigLLVMTypeToScope(ZigLLVMDIType *type) {
887887 return reinterpret_cast<ZigLLVMDIScope*>(scope);
888888}
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
890940ZigLLVMDICompileUnit *ZigLLVMCreateCompileUnit(ZigLLVMDIBuilder *dibuilder,
891941 unsigned lang, ZigLLVMDIFile *difile, const char *producer,
892942 bool is_optimized, const char *flags, unsigned runtime_version, const char *split_name,
src/zig_llvm.h+15
......@@ -38,6 +38,8 @@ struct ZigLLVMDIGlobalVariable;
3838struct ZigLLVMDILocation;
3939struct ZigLLVMDIEnumerator;
4040struct ZigLLVMInsertionPoint;
41struct ZigLLVMDINode;
42struct ZigLLVMMDString;
4143
4244ZIG_EXTERN_C void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R);
4345ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R);
......@@ -238,6 +240,19 @@ ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMFileToScope(struct ZigLLVMDIFile *dif
238240ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMSubprogramToScope(struct ZigLLVMDISubprogram *subprogram);
239241ZIG_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
241256ZIG_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);