aboutsummaryrefslogtreecommitdiff
path: root/src/codegen
diff options
context:
space:
mode:
authorWilliam Sengir <william@sengir.com>2022-03-13 00:28:34 -0700
committerAndrew Kelley <andrew@ziglang.org>2022-03-15 00:38:20 -0400
commitc757f197903940115c1d42883240ec1fe7ef660c (patch)
tree31915696778776c3a906df85cbf08e428f052b90 /src/codegen
parentf36bf8506c9c1fa48dadd699b3122acd15890cf6 (diff)
downloadzig-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.zig51
-rw-r--r--src/codegen/llvm/bindings.zig38
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;