diff --git a/src/Module.zig b/src/Module.zig index 868ce578ebe3..2365083bb0e7 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -663,7 +663,7 @@ pub const Decl = struct { return (try decl.typedValue()).val; } - pub fn isFunction(decl: *Decl) !bool { + pub fn isFunction(decl: Decl) !bool { const tv = try decl.typedValue(); return tv.ty.zigTypeTag() == .Fn; } diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig index c942a975df69..1032714b57a2 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); @@ -665,6 +667,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); @@ -679,6 +692,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), @@ -744,7 +768,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; } }; @@ -782,7 +806,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: { @@ -826,8 +850,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 f590e46c2300..b5af6b732172 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; diff --git a/src/zig_llvm.cpp b/src/zig_llvm.cpp index 21e83319d9a7..eb5854c0b711 100644 --- a/src/zig_llvm.cpp +++ b/src/zig_llvm.cpp @@ -840,7 +840,7 @@ ZigLLVMDIGlobalVariable *ZigLLVMCreateGlobalVariable(ZigLLVMDIBuilder *dbuilder, line_no, reinterpret_cast(di_type), is_local_to_unit); - return reinterpret_cast(result); + return reinterpret_cast(result->getVariable()); } ZigLLVMDILocalVariable *ZigLLVMCreateParameterVariable(ZigLLVMDIBuilder *dbuilder, @@ -885,6 +885,56 @@ ZigLLVMDIScope *ZigLLVMTypeToScope(ZigLLVMDIType *type) { return reinterpret_cast(scope); } +ZigLLVMDINode *ZigLLVMLexicalBlockToNode(ZigLLVMDILexicalBlock *lexical_block) { + DINode *node = reinterpret_cast(lexical_block); + return reinterpret_cast(node); +} + +ZigLLVMDINode *ZigLLVMCompileUnitToNode(ZigLLVMDICompileUnit *compile_unit) { + DINode *node = reinterpret_cast(compile_unit); + return reinterpret_cast(node); +} + +ZigLLVMDINode *ZigLLVMFileToNode(ZigLLVMDIFile *difile) { + DINode *node = reinterpret_cast(difile); + return reinterpret_cast(node); +} + +ZigLLVMDINode *ZigLLVMSubprogramToNode(ZigLLVMDISubprogram *subprogram) { + DINode *node = reinterpret_cast(subprogram); + return reinterpret_cast(node); +} + +ZigLLVMDINode *ZigLLVMTypeToNode(ZigLLVMDIType *type) { + DINode *node = reinterpret_cast(type); + return reinterpret_cast(node); +} + +ZigLLVMDINode *ZigLLVMScopeToNode(ZigLLVMDIScope *scope) { + DINode *node = reinterpret_cast(scope); + return reinterpret_cast(node); +} + +ZigLLVMDINode *ZigLLVMGlobalVariableToNode(ZigLLVMDIGlobalVariable *global_variable) { + DINode *node = reinterpret_cast(global_variable); + return reinterpret_cast(node); +} + +void ZigLLVMSubprogramReplaceLinkageName(ZigLLVMDISubprogram *subprogram, + ZigLLVMMDString *linkage_name) +{ + MDString *linkage_name_md = reinterpret_cast(linkage_name); + reinterpret_cast(subprogram)->replaceLinkageName(linkage_name_md); +} + +void ZigLLVMGlobalVariableReplaceLinkageName(ZigLLVMDIGlobalVariable *global_variable, + ZigLLVMMDString *linkage_name) +{ + Metadata *linkage_name_md = reinterpret_cast(linkage_name); + // NOTE: Operand index must match llvm::DIGlobalVariable + reinterpret_cast(global_variable)->replaceOperandWith(5, linkage_name_md); +} + ZigLLVMDICompileUnit *ZigLLVMCreateCompileUnit(ZigLLVMDIBuilder *dibuilder, unsigned lang, ZigLLVMDIFile *difile, const char *producer, bool is_optimized, const char *flags, unsigned runtime_version, const char *split_name, diff --git a/src/zig_llvm.h b/src/zig_llvm.h index b19ff1f9479e..417869ac6ba9 100644 --- a/src/zig_llvm.h +++ b/src/zig_llvm.h @@ -38,6 +38,8 @@ struct ZigLLVMDIGlobalVariable; struct ZigLLVMDILocation; struct ZigLLVMDIEnumerator; struct ZigLLVMInsertionPoint; +struct ZigLLVMDINode; +struct ZigLLVMMDString; ZIG_EXTERN_C void ZigLLVMInitializeLoopStrengthReducePass(LLVMPassRegistryRef R); ZIG_EXTERN_C void ZigLLVMInitializeLowerIntrinsicsPass(LLVMPassRegistryRef R); @@ -238,6 +240,19 @@ ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMFileToScope(struct ZigLLVMDIFile *dif ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMSubprogramToScope(struct ZigLLVMDISubprogram *subprogram); ZIG_EXTERN_C struct ZigLLVMDIScope *ZigLLVMTypeToScope(struct ZigLLVMDIType *type); +ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMLexicalBlockToNode(struct ZigLLVMDILexicalBlock *lexical_block); +ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMCompileUnitToNode(struct ZigLLVMDICompileUnit *compile_unit); +ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMFileToNode(struct ZigLLVMDIFile *difile); +ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMSubprogramToNode(struct ZigLLVMDISubprogram *subprogram); +ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMTypeToNode(struct ZigLLVMDIType *type); +ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMScopeToNode(struct ZigLLVMDIScope *scope); +ZIG_EXTERN_C struct ZigLLVMDINode *ZigLLVMGlobalVariableToNode(struct ZigLLVMDIGlobalVariable *global_variable); + +ZIG_EXTERN_C void ZigLLVMSubprogramReplaceLinkageName(struct ZigLLVMDISubprogram *subprogram, + struct ZigLLVMMDString *linkage_name); +ZIG_EXTERN_C void ZigLLVMGlobalVariableReplaceLinkageName(struct ZigLLVMDIGlobalVariable *global_variable, + struct ZigLLVMMDString *linkage_name); + ZIG_EXTERN_C struct ZigLLVMDILocalVariable *ZigLLVMCreateAutoVariable(struct ZigLLVMDIBuilder *dbuilder, struct ZigLLVMDIScope *scope, const char *name, struct ZigLLVMDIFile *file, unsigned line_no, struct ZigLLVMDIType *type, bool always_preserve, unsigned flags);