https://github.com/huangjd created https://github.com/llvm/llvm-project/pull/95174
The option is causing the binary output to be different when compiled under `-O0`, because it introduce dbg.declare on pseudovariables. Going to change this implementation to use dbg.value instead. >From c72d4de2a1dc4e641d61b3f31185181855a1d434 Mon Sep 17 00:00:00 2001 From: William Huang <williamjhu...@google.com> Date: Tue, 11 Jun 2024 17:19:07 -0400 Subject: [PATCH 1/2] Revert "[Clang] Extend EmitPseudoVariable to support debug records (#94956)" This reverts commit 5c268cfaae521dc2db1af58085e3c8d66a5533fe. --- clang/lib/CodeGen/CGDebugInfo.cpp | 32 +++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 11e2d549d8a45..681a475f9e4be 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -5766,16 +5766,28 @@ void CGDebugInfo::EmitPseudoVariable(CGBuilderTy &Builder, // it is loaded upon use, so we identify such pattern here. if (llvm::LoadInst *Load = dyn_cast<llvm::LoadInst>(Value)) { llvm::Value *Var = Load->getPointerOperand(); - // There can be implicit type cast applied on a variable if it is an opaque - // ptr, in this case its debug info may not match the actual type of object - // being used as in the next instruction, so we will need to emit a pseudo - // variable for type-casted value. - auto DeclareTypeMatches = [&](auto *DbgDeclare) { - return DbgDeclare->getVariable()->getType() == Type; - }; - if (any_of(llvm::findDbgDeclares(Var), DeclareTypeMatches) || - any_of(llvm::findDVRDeclares(Var), DeclareTypeMatches)) - return; + if (llvm::Metadata *MDValue = llvm::ValueAsMetadata::getIfExists(Var)) { + if (llvm::Value *DbgValue = llvm::MetadataAsValue::getIfExists( + CGM.getLLVMContext(), MDValue)) { + for (llvm::User *U : DbgValue->users()) { + if (llvm::CallInst *DbgDeclare = dyn_cast<llvm::CallInst>(U)) { + if (DbgDeclare->getCalledFunction()->getIntrinsicID() == + llvm::Intrinsic::dbg_declare && + DbgDeclare->getArgOperand(0) == DbgValue) { + // There can be implicit type cast applied on a variable if it is + // an opaque ptr, in this case its debug info may not match the + // actual type of object being used as in the next instruction, so + // we will need to emit a pseudo variable for type-casted value. + llvm::DILocalVariable *MDNode = cast<llvm::DILocalVariable>( + cast<llvm::MetadataAsValue>(DbgDeclare->getOperand(1)) + ->getMetadata()); + if (MDNode->getType() == Type) + return; + } + } + } + } + } } // Find the correct location to insert a sequence of instructions to >From 83a179ba9db812492f37ccbe00f58f534a993fe1 Mon Sep 17 00:00:00 2001 From: William Huang <williamjhu...@google.com> Date: Tue, 11 Jun 2024 17:19:22 -0400 Subject: [PATCH 2/2] Revert "Add option to generate additional debug info for expression dereferencing pointer to pointers. (#94100)" This reverts commit 5cb00785aa56d4acc97b083df5305d2959f6bd4a. --- clang/lib/CodeGen/CGDebugInfo.cpp | 84 ------------ clang/lib/CodeGen/CGDebugInfo.h | 6 - clang/lib/CodeGen/CGExprScalar.cpp | 21 +-- .../test/CodeGenCXX/debug-info-ptr-to-ptr.cpp | 120 ------------------ 4 files changed, 1 insertion(+), 230 deletions(-) delete mode 100644 clang/test/CodeGenCXX/debug-info-ptr-to-ptr.cpp diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 681a475f9e4be..99e12da0081af 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -5746,90 +5746,6 @@ void CGDebugInfo::EmitExternalVariable(llvm::GlobalVariable *Var, Var->addDebugInfo(GVE); } -void CGDebugInfo::EmitPseudoVariable(CGBuilderTy &Builder, - llvm::Instruction *Value, QualType Ty) { - // Only when -g2 or above is specified, debug info for variables will be - // generated. - if (CGM.getCodeGenOpts().getDebugInfo() <= - llvm::codegenoptions::DebugLineTablesOnly) - return; - - llvm::DebugLoc SaveDebugLoc = Builder.getCurrentDebugLocation(); - if (!SaveDebugLoc.get()) - return; - - llvm::DIFile *Unit = SaveDebugLoc->getFile(); - llvm::DIType *Type = getOrCreateType(Ty, Unit); - - // Check if Value is already a declared variable and has debug info, in this - // case we have nothing to do. Clang emits declared variable as alloca, and - // it is loaded upon use, so we identify such pattern here. - if (llvm::LoadInst *Load = dyn_cast<llvm::LoadInst>(Value)) { - llvm::Value *Var = Load->getPointerOperand(); - if (llvm::Metadata *MDValue = llvm::ValueAsMetadata::getIfExists(Var)) { - if (llvm::Value *DbgValue = llvm::MetadataAsValue::getIfExists( - CGM.getLLVMContext(), MDValue)) { - for (llvm::User *U : DbgValue->users()) { - if (llvm::CallInst *DbgDeclare = dyn_cast<llvm::CallInst>(U)) { - if (DbgDeclare->getCalledFunction()->getIntrinsicID() == - llvm::Intrinsic::dbg_declare && - DbgDeclare->getArgOperand(0) == DbgValue) { - // There can be implicit type cast applied on a variable if it is - // an opaque ptr, in this case its debug info may not match the - // actual type of object being used as in the next instruction, so - // we will need to emit a pseudo variable for type-casted value. - llvm::DILocalVariable *MDNode = cast<llvm::DILocalVariable>( - cast<llvm::MetadataAsValue>(DbgDeclare->getOperand(1)) - ->getMetadata()); - if (MDNode->getType() == Type) - return; - } - } - } - } - } - } - - // Find the correct location to insert a sequence of instructions to - // materialize Value on the stack. - auto SaveInsertionPoint = Builder.saveIP(); - if (llvm::InvokeInst *Invoke = dyn_cast<llvm::InvokeInst>(Value)) - Builder.SetInsertPoint(Invoke->getNormalDest()->begin()); - else if (llvm::Instruction *Next = Value->getIterator()->getNextNode()) - Builder.SetInsertPoint(Next); - else - Builder.SetInsertPoint(Value->getParent()); - llvm::DebugLoc DL = Value->getDebugLoc(); - if (DL.get()) - Builder.SetCurrentDebugLocation(DL); - else if (!Builder.getCurrentDebugLocation().get()) - Builder.SetCurrentDebugLocation(SaveDebugLoc); - - llvm::AllocaInst *PseudoVar = Builder.CreateAlloca(Value->getType()); - Address PseudoVarAddr(PseudoVar, Value->getType(), - CharUnits::fromQuantity(PseudoVar->getAlign())); - llvm::LoadInst *Load = Builder.CreateLoad(PseudoVarAddr); - Value->replaceAllUsesWith(Load); - Builder.SetInsertPoint(Load); - Builder.CreateStore(Value, PseudoVarAddr); - - // Emit debug info for materialized Value. - unsigned Line = Builder.getCurrentDebugLocation().getLine(); - unsigned Column = Builder.getCurrentDebugLocation().getCol(); - llvm::DILocalVariable *D = DBuilder.createAutoVariable( - LexicalBlockStack.back(), "", nullptr, 0, Type, false, - llvm::DINode::FlagArtificial); - llvm::DILocation *DIL = - llvm::DILocation::get(CGM.getLLVMContext(), Line, Column, - LexicalBlockStack.back(), CurInlinedAt); - SmallVector<uint64_t> Expr; - DBuilder.insertDeclare(PseudoVar, D, DBuilder.createExpression(Expr), DIL, - Load); - - Builder.restoreIP(SaveInsertionPoint); - Builder.SetCurrentDebugLocation(SaveDebugLoc); -} - void CGDebugInfo::EmitGlobalAlias(const llvm::GlobalValue *GV, const GlobalDecl GD) { diff --git a/clang/lib/CodeGen/CGDebugInfo.h b/clang/lib/CodeGen/CGDebugInfo.h index da466837aa3c3..8fe738be21568 100644 --- a/clang/lib/CodeGen/CGDebugInfo.h +++ b/clang/lib/CodeGen/CGDebugInfo.h @@ -530,12 +530,6 @@ class CGDebugInfo { /// Emit information about an external variable. void EmitExternalVariable(llvm::GlobalVariable *GV, const VarDecl *Decl); - /// Emit a pseudo variable and debug info for an intermediate value if it does - /// not correspond to a variable in the source code, so that a profiler can - /// track more accurate usage of certain instructions of interest. - void EmitPseudoVariable(CGBuilderTy &Builder, llvm::Instruction *Value, - QualType Ty); - /// Emit information about global variable alias. void EmitGlobalAlias(const llvm::GlobalValue *GV, const GlobalDecl Decl); diff --git a/clang/lib/CodeGen/CGExprScalar.cpp b/clang/lib/CodeGen/CGExprScalar.cpp index 58f0a3113b4f8..1b144c178ce96 100644 --- a/clang/lib/CodeGen/CGExprScalar.cpp +++ b/clang/lib/CodeGen/CGExprScalar.cpp @@ -1937,26 +1937,7 @@ Value *ScalarExprEmitter::VisitMemberExpr(MemberExpr *E) { } } - llvm::Value *Result = EmitLoadOfLValue(E); - - // If -fdebug-info-for-profiling is specified, emit a pseudo variable and its - // debug info for the pointer, even if there is no variable associated with - // the pointer's expression. - if (CGF.CGM.getCodeGenOpts().DebugInfoForProfiling && CGF.getDebugInfo()) { - if (llvm::LoadInst *Load = dyn_cast<llvm::LoadInst>(Result)) { - if (llvm::GetElementPtrInst *GEP = - dyn_cast<llvm::GetElementPtrInst>(Load->getPointerOperand())) { - if (llvm::Instruction *Pointer = - dyn_cast<llvm::Instruction>(GEP->getPointerOperand())) { - QualType Ty = E->getBase()->getType(); - if (!E->isArrow()) - Ty = CGF.getContext().getPointerType(Ty); - CGF.getDebugInfo()->EmitPseudoVariable(Builder, Pointer, Ty); - } - } - } - } - return Result; + return EmitLoadOfLValue(E); } Value *ScalarExprEmitter::VisitArraySubscriptExpr(ArraySubscriptExpr *E) { diff --git a/clang/test/CodeGenCXX/debug-info-ptr-to-ptr.cpp b/clang/test/CodeGenCXX/debug-info-ptr-to-ptr.cpp deleted file mode 100644 index baf791487771c..0000000000000 --- a/clang/test/CodeGenCXX/debug-info-ptr-to-ptr.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// Test debug info for intermediate value of a chained pointer deferencing -// expression when the flag -fdebug-info-for-pointer-type is enabled. -// RUN: %clang_cc1 -emit-llvm -triple x86_64-linux-gnu %s -fdebug-info-for-profiling -debug-info-kind=constructor -o - | FileCheck %s - -class A { -public: - int i; - char c; - void *p; - int arr[3]; -}; - -class B { -public: - A* a; -}; - -class C { -public: - B* b; - A* a; - A arr[10]; -}; - -// CHECK-LABEL: define dso_local noundef i32 @{{.*}}func1{{.*}}( -// CHECK: [[A_ADDR:%.*]] = getelementptr inbounds %class.B, ptr {{%.*}}, i32 0, i32 0, !dbg [[DBG1:![0-9]+]] -// CHECK-NEXT: [[A:%.*]] = load ptr, ptr [[A_ADDR]], align {{.*}}, !dbg [[DBG1]] -// CHECK-NEXT: [[PSEUDO1:%.*]] = alloca ptr, align {{.*}}, !dbg [[DBG1]] -// CHECK-NEXT: store ptr [[A]], ptr [[PSEUDO1]], align {{.*}}, !dbg [[DBG1]] -// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[PSEUDO1]], metadata [[META1:![0-9]+]], metadata !DIExpression()), !dbg [[DBG1]] -// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[PSEUDO1]], align {{.*}}, !dbg [[DBG1]] -// CHECK-NEXT: {{%.*}} = getelementptr inbounds %class.A, ptr [[TMP1]], i32 0, i32 0, -int func1(B *b) { - return b->a->i; -} - -// Should generate a pseudo variable when pointer is type-casted. -// CHECK-LABEL: define dso_local noundef ptr @{{.*}}func2{{.*}}( -// CHECK: call void @llvm.dbg.declare(metadata ptr [[B_ADDR:%.*]], metadata [[META2:![0-9]+]], metadata !DIExpression()) -// CHECK-NEXT: [[B:%.*]] = load ptr, ptr [[B_ADDR]], -// CHECK-NEXT: [[PSEUDO1:%.*]] = alloca ptr, -// CHECK-NEXT: store ptr [[B]], ptr [[PSEUDO1]], -// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[PSEUDO1]], metadata [[META3:![0-9]+]], metadata !DIExpression()) -// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[PSEUDO1]], -// CHECK-NEXT: {{%.*}} = getelementptr inbounds %class.B, ptr [[TMP1]], i32 0, -A* func2(void *b) { - return ((B*)b)->a; -} - -// Should not generate pseudo variable in this case. -// CHECK-LABEL: define dso_local noundef i32 @{{.*}}func3{{.*}}( -// CHECK: call void @llvm.dbg.declare(metadata ptr [[B_ADDR:%.*]], metadata [[META4:![0-9]+]], metadata !DIExpression()) -// CHECK: call void @llvm.dbg.declare(metadata ptr [[LOCAL1:%.*]], metadata [[META5:![0-9]+]], metadata !DIExpression()) -// CHECK-NOT: call void @llvm.dbg.declare(metadata ptr -int func3(B *b) { - A *local1 = b->a; - return local1->i; -} - -// CHECK-LABEL: define dso_local noundef signext i8 @{{.*}}func4{{.*}}( -// CHECK: [[A_ADDR:%.*]] = getelementptr inbounds %class.C, ptr {{%.*}}, i32 0, i32 1 -// CHECK-NEXT: [[A:%.*]] = load ptr, ptr [[A_ADDR]], -// CHECK-NEXT: [[PSEUDO1:%.*]] = alloca ptr, -// CHECK-NEXT: store ptr [[A]], ptr [[PSEUDO1]], -// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[PSEUDO1]], metadata [[META6:![0-9]+]], metadata !DIExpression()) -// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[PSEUDO1]], -// CHECK-NEXT: {{%.*}} = getelementptr inbounds %class.A, ptr [[TMP1]], i32 0, i32 0, -// CHECK: [[CALL:%.*]] = call noundef ptr @{{.*}}foo{{.*}}( -// CHECK-NEXT: [[PSEUDO2:%.*]] = alloca ptr, -// CHECK-NEXT: store ptr [[CALL]], ptr [[PSEUDO2]] -// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[PSEUDO2]], metadata [[META6]], metadata !DIExpression()) -// CHECK-NEXT: [[TMP2:%.*]] = load ptr, ptr [[PSEUDO2]] -// CHECK-NEXT: [[I1:%.*]] = getelementptr inbounds %class.A, ptr [[TMP2]], i32 0, i32 1 -char func4(C *c) { - extern A* foo(int x); - return foo(c->a->i)->c; -} - -// CHECK-LABEL: define dso_local noundef signext i8 @{{.*}}func5{{.*}}( -// CHECK: call void @llvm.dbg.declare(metadata ptr {{%.*}}, metadata [[META7:![0-9]+]], metadata !DIExpression()) -// CHECK: call void @llvm.dbg.declare(metadata ptr {{%.*}}, metadata [[META8:![0-9]+]], metadata !DIExpression()) -// CHECK: [[A_ADDR:%.*]] = getelementptr inbounds %class.A, ptr {{%.*}}, i64 {{%.*}}, -// CHECK-NEXT: [[PSEUDO1:%.*]] = alloca ptr, -// CHECK-NEXT: store ptr [[A_ADDR]], ptr [[PSEUDO1]], -// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr [[PSEUDO1]], metadata [[META9:![0-9]+]], metadata !DIExpression()) -// CHECK-NEXT: [[TMP1:%.*]] = load ptr, ptr [[PSEUDO1]], -// CHECK-NEXT: {{%.*}} = getelementptr inbounds %class.A, ptr [[TMP1]], i32 0, i32 1, -char func5(void *arr, int n) { - return ((A*)arr)[n].c; -} - -// CHECK-LABEL: define dso_local noundef i32 @{{.*}}func6{{.*}}( -// CHECK: call void @llvm.dbg.declare(metadata ptr {{%.*}}, metadata [[META10:![0-9]+]], metadata !DIExpression()) -// CHECK: call void @llvm.dbg.declare(metadata ptr {{%.*}}, metadata [[META11:![0-9]+]], metadata !DIExpression()) -int func6(B &b) { - return reinterpret_cast<A&>(b).i; -} - -// CHECK-DAG: [[META_A:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "A", -// CHECK-DAG: [[META_AP:![0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META_A]], -// CHECK-DAG: [[META_B:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "B", -// CHECK-DAG: [[META_BP:![0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META_B]], -// CHECK-DAG: [[META_C:![0-9]+]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "C", -// CHECK-DAG: [[META_CP:![0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: [[META_C]], -// CHECK-DAG: [[META_VP:![0-9]+]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: null, -// CHECK-DAG: [[META_I32:![0-9]+]] = !DIBasicType(name: "int", size: 32, -// CHECK-DAG: [[META_BR:![0-9]+]] = !DIDerivedType(tag: DW_TAG_reference_type, baseType: [[META_B]], - -// CHECK-DAG: [[DBG1]] = !DILocation(line: 34, column: 13, -// CHECK-DAG: [[META1]] = !DILocalVariable(scope: {{.*}}, type: [[META_AP]], flags: DIFlagArtificial) -// CHECK-DAG: [[META2]] = !DILocalVariable(name: "b", arg: 1, scope: {{.*}}, file: {{.*}}, line: 46, type: [[META_VP]]) -// CHECK-DAG: [[META3]] = !DILocalVariable(scope: {{.*}}, type: [[META_BP]], flags: DIFlagArtificial) -// CHECK-DAG: [[META4]] = !DILocalVariable(name: "b", arg: 1, scope: {{.*}}, file: {{.*}}, line: 55, type: [[META_BP]]) -// CHECK-DAG: [[META5]] = !DILocalVariable(name: "local1", scope: {{.*}}, file: {{.*}}, line: 56, type: [[META_AP]]) -// CHECK-DAG: [[META6]] = !DILocalVariable(scope: {{.*}}, type: [[META_AP]], flags: DIFlagArtificial) -// CHECK-DAG: [[META7]] = !DILocalVariable(name: "arr", arg: 1, scope: {{.*}}, file: {{.*}}, line: 88, type: [[META_VP]]) -// CHECK-DAG: [[META8]] = !DILocalVariable(name: "n", arg: 2, scope: {{.*}}, file: {{.*}}, line: 88, type: [[META_I32]]) -// CHECK-DAG: [[META9]] = !DILocalVariable(scope: {{.*}}, type: [[META_AP]], flags: DIFlagArtificial) -// CHECK-DAG: [[META10]] = !DILocalVariable(name: "b", arg: 1, scope: {{.*}}, file: {{.*}}, line: 95, type: [[META_BR]]) -// CHECK-DAG: [[META11]] = !DILocalVariable(scope: {{.*}}, type: [[META_AP]], flags: DIFlagArtificial) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits