[clang] [llvm] Add option to generate additional debug info for expression dereferencing pointer to pointers. (PR #81545)
David Blaikie via cfe-commits
cfe-commits at lists.llvm.org
Mon May 6 11:37:46 PDT 2024
================
@@ -5636,6 +5636,84 @@ 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::DIFile *Unit = Builder.getCurrentDebugLocation()->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 = dyn_cast<llvm::DILocalVariable>(
+ dyn_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());
+ auto SaveDebugLoc = Builder.getCurrentDebugLocation();
+ llvm::DebugLoc DL = Value->getDebugLoc();
+ if (DL.get())
+ Builder.SetCurrentDebugLocation(DL);
+
+ 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();
----------------
dwblaikie wrote:
Hmm - what breaks? I tried this with some hand-modified IR and it seems to produce the desired DWARF:
https://godbolt.org/z/n8a5Ef1Yj - `i` local has had the file/line removed, `j` local has not. Oh, and it even works if the name is removed - which might save a few bytes too? (I think if a name is going to be included, I'd expect it to be a reserved name, starting with `__`)
Ah, I see, you're also using the location for the DILocation of the debug intrinsic - I meant to refer only to the location (file, line, and column) of the DILocalVariable created by `createAutoVariable` (ie, I'm suggesting: ` DBuilder.createAutoVariable(LexicalBlockStack.back(), "", nullptr, 0, Type)`)
https://github.com/llvm/llvm-project/pull/81545
More information about the cfe-commits
mailing list