diff options
| author | William Sengir <william@sengir.com> | 2022-03-13 00:28:34 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2022-03-15 00:38:20 -0400 |
| commit | c757f197903940115c1d42883240ec1fe7ef660c (patch) | |
| tree | 31915696778776c3a906df85cbf08e428f052b90 /src/codegen | |
| parent | f36bf8506c9c1fa48dadd699b3122acd15890cf6 (diff) | |
| download | zig-c757f197903940115c1d42883240ec1fe7ef660c.tar.gz zig-c757f197903940115c1d42883240ec1fe7ef660c.zip | |
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.
Diffstat (limited to 'src/codegen')
| -rw-r--r-- | src/codegen/llvm.zig | 51 | ||||
| -rw-r--r-- | src/codegen/llvm/bindings.zig | 38 |
2 files changed, 83 insertions, 6 deletions
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index 4aba6de5a3..4d59b73f20 100644 --- a/src/codegen/llvm.zig +++ b/src/codegen/llvm.zig @@ -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()); + } } } diff --git a/src/codegen/llvm/bindings.zig b/src/codegen/llvm/bindings.zig index 6afd754d37..c54d226f66 100644 --- a/src/codegen/llvm/bindings.zig +++ b/src/codegen/llvm/bindings.zig @@ -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; |
