fdeazeve created this revision. Herald added a subscriber: kristof.beyls. Herald added a project: All. fdeazeve requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
With codegen prior to this patch, truly indirect arguments -- i.e. those that are not `byval` -- can have their debug information lost even at O0. Because indirect arguments are passed by pointer, and this pointer is likely placed in a register as per the function call ABI, debug information is lost as soon as the register gets clobbered. This patch solves the issue by storing the address of the parameter on the stack, using a similar strategy employed when C++ references are passed. In other words, this patch changes codegen from: define @foo(ptr %arg) { call void @llvm.dbg.declare(%arg, [...], metadata !DIExpression()) To: define @foo(ptr %arg) { %ptr_storage = alloca ptr store ptr %arg, ptr %ptr_storage call void @llvm.dbg.declare(%ptr_storage, [...], metadata !DIExpression(DW_OP_deref)) Some common cases where this may happen with C or C++ function calls: 1. "Big enough" trivial structures passed by value under the ARM ABI. 2. Structures that are non-trivial for the purposes of call (as per the Itanium ABI) when passed by value. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D141381 Files: clang/lib/CodeGen/CGDebugInfo.cpp clang/lib/CodeGen/CGDebugInfo.h clang/lib/CodeGen/CGDecl.cpp clang/test/CodeGenCXX/debug-info.cpp
Index: clang/test/CodeGenCXX/debug-info.cpp =================================================================== --- clang/test/CodeGenCXX/debug-info.cpp +++ clang/test/CodeGenCXX/debug-info.cpp @@ -4,7 +4,13 @@ // CHECK: @_ZN6pr96081xE ={{.*}} global ptr null, align 8, !dbg [[X:![0-9]+]] // CHECK: define{{.*}} void @_ZN7pr147634funcENS_3fooE -// CHECK: call void @llvm.dbg.declare({{.*}}, metadata ![[F:[0-9]+]], metadata !DIExpression()) +// CHECK-SAME: ptr noundef [[param:%.*]]) +// CHECK-NEXT: entry: +// CHECK-NEXT: alloca ptr, align 8 +// CHECK-NEXT: [[param_addr_storage:%.*]] = alloca ptr, align 8 +// CHECK-NEXT: store +// CHECK-NEXT: store ptr [[param]], ptr [[param_addr_storage]], align 8 +// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[param_addr_storage]], metadata ![[F:[0-9]+]], metadata !DIExpression(DW_OP_deref)) // !llvm.dbg.cu pulls in globals and their types first. // CHECK-NOT: !DIGlobalVariable(name: "c" Index: clang/lib/CodeGen/CGDecl.cpp =================================================================== --- clang/lib/CodeGen/CGDecl.cpp +++ clang/lib/CodeGen/CGDecl.cpp @@ -2475,6 +2475,13 @@ Address AllocaPtr = Address::invalid(); bool DoStore = false; bool IsScalar = hasScalarEvaluationKind(Ty); + bool UseIndirectDebugAddress = false; + const bool ShouldEmitDebugInfo = [&] { + // Emit debug info for param declarations in non-thunk functions. + return getDebugInfo() && CGM.getCodeGenOpts().hasReducedDebugInfo() && + !CurFuncIsThunk && !NoDebugInfo; + }(); + // If we already have a pointer to the argument, reuse the input pointer. if (Arg.isIndirect()) { // If we have a prettier pointer type at this point, bitcast to that. @@ -2486,6 +2493,19 @@ auto AllocaAS = CGM.getASTAllocaAddressSpace(); auto *V = DeclPtr.getPointer(); AllocaPtr = DeclPtr; + + // For truly ABI indirect arguments, that is, they are not `byval`, store + // the address of the argument on the stack to preserve debug information. + ABIArgInfo ArgInfo = CurFnInfo->arguments()[ArgNo - 1].info; + if (ShouldEmitDebugInfo && ArgInfo.isIndirect()) + UseIndirectDebugAddress = !ArgInfo.getIndirectByVal(); + if (UseIndirectDebugAddress) { + auto PtrTy = getContext().getPointerType(Ty); + AllocaPtr = CreateMemTemp(PtrTy, getContext().getTypeAlignInChars(PtrTy), + D.getName() + ".indirect_addr"); + EmitStoreOfScalar(V, AllocaPtr, /* Volatile */ false, PtrTy); + } + auto SrcLangAS = getLangOpts().OpenCL ? LangAS::opencl_private : AllocaAS; auto DestLangAS = getLangOpts().OpenCL ? LangAS::opencl_private : LangAS::Default; @@ -2597,15 +2617,13 @@ setAddrOfLocalVar(&D, DeclPtr); - // Emit debug info for param declarations in non-thunk functions. - if (CGDebugInfo *DI = getDebugInfo()) { - if (CGM.getCodeGenOpts().hasReducedDebugInfo() && !CurFuncIsThunk && - !NoDebugInfo) { - llvm::DILocalVariable *DILocalVar = DI->EmitDeclareOfArgVariable( - &D, AllocaPtr.getPointer(), ArgNo, Builder); - if (const auto *Var = dyn_cast_or_null<ParmVarDecl>(&D)) - DI->getParamDbgMappings().insert({Var, DILocalVar}); - } + if (ShouldEmitDebugInfo) { + CGDebugInfo *DI = getDebugInfo(); + assert(DI); + llvm::DILocalVariable *DILocalVar = DI->EmitDeclareOfArgVariable( + &D, AllocaPtr.getPointer(), ArgNo, Builder, UseIndirectDebugAddress); + if (const auto *Var = dyn_cast_or_null<ParmVarDecl>(&D)) + DI->getParamDbgMappings().insert({Var, DILocalVar}); } if (D.hasAttr<AnnotateAttr>()) Index: clang/lib/CodeGen/CGDebugInfo.h =================================================================== --- clang/lib/CodeGen/CGDebugInfo.h +++ clang/lib/CodeGen/CGDebugInfo.h @@ -488,10 +488,10 @@ /// Emit call to \c llvm.dbg.declare for an argument variable /// declaration. - llvm::DILocalVariable *EmitDeclareOfArgVariable(const VarDecl *Decl, - llvm::Value *AI, - unsigned ArgNo, - CGBuilderTy &Builder); + llvm::DILocalVariable * + EmitDeclareOfArgVariable(const VarDecl *Decl, llvm::Value *AI, unsigned ArgNo, + CGBuilderTy &Builder, + const bool UsePointerValue = false); /// Emit call to \c llvm.dbg.declare for the block-literal argument /// to a block invocation function. Index: clang/lib/CodeGen/CGDebugInfo.cpp =================================================================== --- clang/lib/CodeGen/CGDebugInfo.cpp +++ clang/lib/CodeGen/CGDebugInfo.cpp @@ -4822,9 +4822,10 @@ llvm::DILocalVariable * CGDebugInfo::EmitDeclareOfArgVariable(const VarDecl *VD, llvm::Value *AI, - unsigned ArgNo, CGBuilderTy &Builder) { + unsigned ArgNo, CGBuilderTy &Builder, + const bool UsePointerValue) { assert(CGM.getCodeGenOpts().hasReducedDebugInfo()); - return EmitDeclare(VD, AI, ArgNo, Builder); + return EmitDeclare(VD, AI, ArgNo, Builder, UsePointerValue); } namespace {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits