summaryrefslogtreecommitdiff
path: root/clang/lib/CodeGen/CGDebugInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/CodeGen/CGDebugInfo.cpp')
-rw-r--r--clang/lib/CodeGen/CGDebugInfo.cpp205
1 files changed, 97 insertions, 108 deletions
diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp
index 681a475f9e4b..3d8a715b692d 100644
--- a/clang/lib/CodeGen/CGDebugInfo.cpp
+++ b/clang/lib/CodeGen/CGDebugInfo.cpp
@@ -32,6 +32,7 @@
#include "clang/Basic/FileManager.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/Version.h"
+#include "clang/CodeGen/ModuleBuilder.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Lex/HeaderSearchOptions.h"
#include "clang/Lex/ModuleMap.h"
@@ -865,7 +866,16 @@ llvm::DIType *CGDebugInfo::CreateType(const BuiltinType *BT) {
return SingletonId; \
}
#include "clang/Basic/WebAssemblyReferenceTypes.def"
-
+#define AMDGPU_OPAQUE_PTR_TYPE(Name, MangledName, AS, Width, Align, Id, \
+ SingletonId) \
+ case BuiltinType::Id: { \
+ if (!SingletonId) \
+ SingletonId = \
+ DBuilder.createForwardDecl(llvm::dwarf::DW_TAG_structure_type, \
+ MangledName, TheCU, TheCU->getFile(), 0); \
+ return SingletonId; \
+ }
+#include "clang/Basic/AMDGPUTypes.def"
case BuiltinType::UChar:
case BuiltinType::Char_U:
Encoding = llvm::dwarf::DW_ATE_unsigned_char;
@@ -1722,6 +1732,28 @@ llvm::DIType *CGDebugInfo::createFieldType(
offsetInBits, flags, debugType, Annotations);
}
+llvm::DISubprogram *
+CGDebugInfo::createInlinedTrapSubprogram(StringRef FuncName,
+ llvm::DIFile *FileScope) {
+ // We are caching the subprogram because we don't want to duplicate
+ // subprograms with the same message. Note that `SPFlagDefinition` prevents
+ // subprograms from being uniqued.
+ llvm::DISubprogram *&SP = InlinedTrapFuncMap[FuncName];
+
+ if (!SP) {
+ llvm::DISubroutineType *DIFnTy = DBuilder.createSubroutineType(nullptr);
+ SP = DBuilder.createFunction(
+ /*Scope=*/FileScope, /*Name=*/FuncName, /*LinkageName=*/StringRef(),
+ /*File=*/FileScope, /*LineNo=*/0, /*Ty=*/DIFnTy,
+ /*ScopeLine=*/0,
+ /*Flags=*/llvm::DINode::FlagArtificial,
+ /*SPFlags=*/llvm::DISubprogram::SPFlagDefinition,
+ /*TParams=*/nullptr, /*ThrownTypes=*/nullptr, /*Annotations=*/nullptr);
+ }
+
+ return SP;
+}
+
void CGDebugInfo::CollectRecordLambdaFields(
const CXXRecordDecl *CXXDecl, SmallVectorImpl<llvm::Metadata *> &elements,
llvm::DIType *RecordTy) {
@@ -3518,6 +3550,23 @@ llvm::DIMacroFile *CGDebugInfo::CreateTempMacroFile(llvm::DIMacroFile *Parent,
return DBuilder.createTempMacroFile(Parent, Line, FName);
}
+llvm::DILocation *CGDebugInfo::CreateTrapFailureMessageFor(
+ llvm::DebugLoc TrapLocation, StringRef Category, StringRef FailureMsg) {
+ // Create a debug location from `TrapLocation` that adds an artificial inline
+ // frame.
+ SmallString<64> FuncName(ClangTrapPrefix);
+
+ FuncName += "$";
+ FuncName += Category;
+ FuncName += "$";
+ FuncName += FailureMsg;
+
+ llvm::DISubprogram *TrapSP =
+ createInlinedTrapSubprogram(FuncName, TrapLocation->getFile());
+ return llvm::DILocation::get(CGM.getLLVMContext(), /*Line=*/0, /*Column=*/0,
+ /*Scope=*/TrapSP, /*InlinedAt=*/TrapLocation);
+}
+
static QualType UnwrapTypeForDebugInfo(QualType T, const ASTContext &C) {
Qualifiers Quals;
do {
@@ -4874,40 +4923,6 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const VarDecl *VD,
return D;
}
-llvm::DIType *CGDebugInfo::CreateBindingDeclType(const BindingDecl *BD) {
- llvm::DIFile *Unit = getOrCreateFile(BD->getLocation());
-
- // If the declaration is bound to a bitfield struct field, its type may have a
- // size that is different from its deduced declaration type's.
- if (const MemberExpr *ME = dyn_cast<MemberExpr>(BD->getBinding())) {
- if (const FieldDecl *FD = dyn_cast<FieldDecl>(ME->getMemberDecl())) {
- if (FD->isBitField()) {
- ASTContext &Context = CGM.getContext();
- const CGRecordLayout &RL =
- CGM.getTypes().getCGRecordLayout(FD->getParent());
- const CGBitFieldInfo &Info = RL.getBitFieldInfo(FD);
-
- // Find an integer type with the same bitwidth as the bitfield size. If
- // no suitable type is present in the target, give up on producing debug
- // information as it would be wrong. It is certainly possible to produce
- // correct debug info, but the logic isn't currently implemented.
- uint64_t BitfieldSizeInBits = Info.Size;
- QualType IntTy =
- Context.getIntTypeForBitwidth(BitfieldSizeInBits, Info.IsSigned);
- if (IntTy.isNull())
- return nullptr;
- Qualifiers Quals = BD->getType().getQualifiers();
- QualType FinalTy = Context.getQualifiedType(IntTy, Quals);
- llvm::DIType *Ty = getOrCreateType(FinalTy, Unit);
- assert(Ty);
- return Ty;
- }
- }
- }
-
- return getOrCreateType(BD->getType(), Unit);
-}
-
llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD,
llvm::Value *Storage,
std::optional<unsigned> ArgNo,
@@ -4922,7 +4937,8 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD,
if (isa<DeclRefExpr>(BD->getBinding()))
return nullptr;
- llvm::DIType *Ty = CreateBindingDeclType(BD);
+ llvm::DIFile *Unit = getOrCreateFile(BD->getLocation());
+ llvm::DIType *Ty = getOrCreateType(BD->getType(), Unit);
// If there is no debug info for this type then do not emit debug info
// for this variable.
@@ -4948,7 +4964,6 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD,
unsigned Column = getColumnNumber(BD->getLocation());
StringRef Name = BD->getName();
auto *Scope = cast<llvm::DIScope>(LexicalBlockStack.back());
- llvm::DIFile *Unit = getOrCreateFile(BD->getLocation());
// Create the descriptor for the variable.
llvm::DILocalVariable *D = DBuilder.createAutoVariable(
Scope, Name, Unit, Line, Ty, CGM.getLangOpts().Optimize,
@@ -4962,13 +4977,29 @@ llvm::DILocalVariable *CGDebugInfo::EmitDeclare(const BindingDecl *BD,
const ASTRecordLayout &layout =
CGM.getContext().getASTRecordLayout(parent);
const uint64_t fieldOffset = layout.getFieldOffset(fieldIndex);
-
- if (fieldOffset != 0) {
- // Currently if the field offset is not a multiple of byte, the produced
- // location would not be accurate. Therefore give up.
- if (fieldOffset % CGM.getContext().getCharWidth() != 0)
- return nullptr;
-
+ if (FD->isBitField()) {
+ const CGRecordLayout &RL =
+ CGM.getTypes().getCGRecordLayout(FD->getParent());
+ const CGBitFieldInfo &Info = RL.getBitFieldInfo(FD);
+ // Use DW_OP_plus_uconst to adjust to the start of the bitfield
+ // storage.
+ if (!Info.StorageOffset.isZero()) {
+ Expr.push_back(llvm::dwarf::DW_OP_plus_uconst);
+ Expr.push_back(Info.StorageOffset.getQuantity());
+ }
+ // Use LLVM_extract_bits to extract the appropriate bits from this
+ // bitfield.
+ Expr.push_back(Info.IsSigned
+ ? llvm::dwarf::DW_OP_LLVM_extract_bits_sext
+ : llvm::dwarf::DW_OP_LLVM_extract_bits_zext);
+ Expr.push_back(Info.Offset);
+ // If we have an oversized bitfield then the value won't be more than
+ // the size of the type.
+ const uint64_t TypeSize = CGM.getContext().getTypeSize(BD->getType());
+ Expr.push_back(std::min((uint64_t)Info.Size, TypeSize));
+ } else if (fieldOffset != 0) {
+ assert(fieldOffset % CGM.getContext().getCharWidth() == 0 &&
+ "Unexpected non-bitfield with non-byte-aligned offset");
Expr.push_back(llvm::dwarf::DW_OP_plus_uconst);
Expr.push_back(
CGM.getContext().toCharUnitsFromBits(fieldOffset).getQuantity());
@@ -5754,80 +5785,38 @@ void CGDebugInfo::EmitPseudoVariable(CGBuilderTy &Builder,
llvm::codegenoptions::DebugLineTablesOnly)
return;
- llvm::DebugLoc SaveDebugLoc = Builder.getCurrentDebugLocation();
- if (!SaveDebugLoc.get())
+ llvm::DILocation *DIL = Value->getDebugLoc().get();
+ if (!DIL)
return;
- llvm::DIFile *Unit = SaveDebugLoc->getFile();
+ llvm::DIFile *Unit = DIL->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
+ // case we have nothing to do. Clang emits a 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;
- }
- }
- }
- }
- }
+ // 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;
}
- // 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);
+ llvm::DILocalVariable *D =
+ DBuilder.createAutoVariable(LexicalBlockStack.back(), "", nullptr, 0,
+ Type, false, llvm::DINode::FlagArtificial);
+
+ if (auto InsertPoint = Value->getInsertionPointAfterDef()) {
+ DBuilder.insertDbgValueIntrinsic(Value, D, DBuilder.createExpression(), DIL,
+ &**InsertPoint);
+ }
}
void CGDebugInfo::EmitGlobalAlias(const llvm::GlobalValue *GV,