summaryrefslogtreecommitdiff
path: root/lib/IR/DebugInfoMetadata.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/IR/DebugInfoMetadata.cpp')
-rw-r--r--lib/IR/DebugInfoMetadata.cpp234
1 files changed, 173 insertions, 61 deletions
diff --git a/lib/IR/DebugInfoMetadata.cpp b/lib/IR/DebugInfoMetadata.cpp
index 75ddd47b2591..910e8c2fb74f 100644
--- a/lib/IR/DebugInfoMetadata.cpp
+++ b/lib/IR/DebugInfoMetadata.cpp
@@ -68,16 +68,16 @@ DILocation *DILocation::getImpl(LLVMContext &Context, unsigned Line,
Storage, Context.pImpl->DILocations);
}
-const DILocation *
-DILocation::getMergedLocation(const DILocation *LocA, const DILocation *LocB,
- const Instruction *ForInst) {
+const DILocation *DILocation::getMergedLocation(const DILocation *LocA,
+ const DILocation *LocB,
+ bool GenerateLocation) {
if (!LocA || !LocB)
return nullptr;
if (LocA == LocB || !LocA->canDiscriminate(*LocB))
return LocA;
- if (!dyn_cast_or_null<CallInst>(ForInst))
+ if (!GenerateLocation)
return nullptr;
SmallPtrSet<DILocation *, 5> InlinedLocationsA;
@@ -249,17 +249,26 @@ void GenericDINode::recalculateHash() {
DISubrange *DISubrange::getImpl(LLVMContext &Context, int64_t Count, int64_t Lo,
StorageType Storage, bool ShouldCreate) {
- DEFINE_GETIMPL_LOOKUP(DISubrange, (Count, Lo));
- DEFINE_GETIMPL_STORE_NO_OPS(DISubrange, (Count, Lo));
+ auto *CountNode = ConstantAsMetadata::get(
+ ConstantInt::getSigned(Type::getInt64Ty(Context), Count));
+ return getImpl(Context, CountNode, Lo, Storage, ShouldCreate);
+}
+
+DISubrange *DISubrange::getImpl(LLVMContext &Context, Metadata *CountNode,
+ int64_t Lo, StorageType Storage,
+ bool ShouldCreate) {
+ DEFINE_GETIMPL_LOOKUP(DISubrange, (CountNode, Lo));
+ Metadata *Ops[] = { CountNode };
+ DEFINE_GETIMPL_STORE(DISubrange, (CountNode, Lo), Ops);
}
DIEnumerator *DIEnumerator::getImpl(LLVMContext &Context, int64_t Value,
- MDString *Name, StorageType Storage,
- bool ShouldCreate) {
+ bool IsUnsigned, MDString *Name,
+ StorageType Storage, bool ShouldCreate) {
assert(isCanonical(Name) && "Expected canonical MDString");
- DEFINE_GETIMPL_LOOKUP(DIEnumerator, (Value, Name));
+ DEFINE_GETIMPL_LOOKUP(DIEnumerator, (Value, IsUnsigned, Name));
Metadata *Ops[] = {Name};
- DEFINE_GETIMPL_STORE(DIEnumerator, (Value), Ops);
+ DEFINE_GETIMPL_STORE(DIEnumerator, (Value, IsUnsigned), Ops);
}
DIBasicType *DIBasicType::getImpl(LLVMContext &Context, unsigned Tag,
@@ -274,6 +283,19 @@ DIBasicType *DIBasicType::getImpl(LLVMContext &Context, unsigned Tag,
Ops);
}
+Optional<DIBasicType::Signedness> DIBasicType::getSignedness() const {
+ switch (getEncoding()) {
+ case dwarf::DW_ATE_signed:
+ case dwarf::DW_ATE_signed_char:
+ return Signedness::Signed;
+ case dwarf::DW_ATE_unsigned:
+ case dwarf::DW_ATE_unsigned_char:
+ return Signedness::Unsigned;
+ default:
+ return None;
+ }
+}
+
DIDerivedType *DIDerivedType::getImpl(
LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File,
unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
@@ -296,17 +318,18 @@ DICompositeType *DICompositeType::getImpl(
unsigned Line, Metadata *Scope, Metadata *BaseType, uint64_t SizeInBits,
uint32_t AlignInBits, uint64_t OffsetInBits, DIFlags Flags,
Metadata *Elements, unsigned RuntimeLang, Metadata *VTableHolder,
- Metadata *TemplateParams, MDString *Identifier, StorageType Storage,
- bool ShouldCreate) {
+ Metadata *TemplateParams, MDString *Identifier, Metadata *Discriminator,
+ StorageType Storage, bool ShouldCreate) {
assert(isCanonical(Name) && "Expected canonical MDString");
// Keep this in sync with buildODRType.
DEFINE_GETIMPL_LOOKUP(
DICompositeType, (Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, Identifier));
+ VTableHolder, TemplateParams, Identifier, Discriminator));
Metadata *Ops[] = {File, Scope, Name, BaseType,
- Elements, VTableHolder, TemplateParams, Identifier};
+ Elements, VTableHolder, TemplateParams, Identifier,
+ Discriminator};
DEFINE_GETIMPL_STORE(DICompositeType, (Tag, Line, RuntimeLang, SizeInBits,
AlignInBits, OffsetInBits, Flags),
Ops);
@@ -317,7 +340,7 @@ DICompositeType *DICompositeType::buildODRType(
Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
- Metadata *VTableHolder, Metadata *TemplateParams) {
+ Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator) {
assert(!Identifier.getString().empty() && "Expected valid identifier");
if (!Context.isODRUniquingDebugTypes())
return nullptr;
@@ -326,7 +349,7 @@ DICompositeType *DICompositeType::buildODRType(
return CT = DICompositeType::getDistinct(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang,
- VTableHolder, TemplateParams, &Identifier);
+ VTableHolder, TemplateParams, &Identifier, Discriminator);
// Only mutate CT if it's a forward declaration and the new operands aren't.
assert(CT->getRawIdentifier() == &Identifier && "Wrong ODR identifier?");
@@ -337,7 +360,8 @@ DICompositeType *DICompositeType::buildODRType(
CT->mutate(Tag, Line, RuntimeLang, SizeInBits, AlignInBits, OffsetInBits,
Flags);
Metadata *Ops[] = {File, Scope, Name, BaseType,
- Elements, VTableHolder, TemplateParams, &Identifier};
+ Elements, VTableHolder, TemplateParams, &Identifier,
+ Discriminator};
assert((std::end(Ops) - std::begin(Ops)) == (int)CT->getNumOperands() &&
"Mismatched number of operands");
for (unsigned I = 0, E = CT->getNumOperands(); I != E; ++I)
@@ -351,7 +375,7 @@ DICompositeType *DICompositeType::getODRType(
Metadata *File, unsigned Line, Metadata *Scope, Metadata *BaseType,
uint64_t SizeInBits, uint32_t AlignInBits, uint64_t OffsetInBits,
DIFlags Flags, Metadata *Elements, unsigned RuntimeLang,
- Metadata *VTableHolder, Metadata *TemplateParams) {
+ Metadata *VTableHolder, Metadata *TemplateParams, Metadata *Discriminator) {
assert(!Identifier.getString().empty() && "Expected valid identifier");
if (!Context.isODRUniquingDebugTypes())
return nullptr;
@@ -360,7 +384,7 @@ DICompositeType *DICompositeType::getODRType(
CT = DICompositeType::getDistinct(
Context, Tag, Name, File, Line, Scope, BaseType, SizeInBits,
AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, VTableHolder,
- TemplateParams, &Identifier);
+ TemplateParams, &Identifier, Discriminator);
return CT;
}
@@ -383,34 +407,39 @@ DISubroutineType *DISubroutineType::getImpl(LLVMContext &Context, DIFlags Flags,
// FIXME: Implement this string-enum correspondence with a .def file and macros,
// so that the association is explicit rather than implied.
-static const char *ChecksumKindName[DIFile::CSK_Last + 1] = {
- "CSK_None",
+static const char *ChecksumKindName[DIFile::CSK_Last] = {
"CSK_MD5",
"CSK_SHA1"
};
-DIFile::ChecksumKind DIFile::getChecksumKind(StringRef CSKindStr) {
- return StringSwitch<DIFile::ChecksumKind>(CSKindStr)
- .Case("CSK_MD5", DIFile::CSK_MD5)
- .Case("CSK_SHA1", DIFile::CSK_SHA1)
- .Default(DIFile::CSK_None);
+StringRef DIFile::getChecksumKindAsString(ChecksumKind CSKind) {
+ assert(CSKind <= DIFile::CSK_Last && "Invalid checksum kind");
+ // The first space was originally the CSK_None variant, which is now
+ // obsolete, but the space is still reserved in ChecksumKind, so we account
+ // for it here.
+ return ChecksumKindName[CSKind - 1];
}
-StringRef DIFile::getChecksumKindAsString() const {
- assert(CSKind <= DIFile::CSK_Last && "Invalid checksum kind");
- return ChecksumKindName[CSKind];
+Optional<DIFile::ChecksumKind> DIFile::getChecksumKind(StringRef CSKindStr) {
+ return StringSwitch<Optional<DIFile::ChecksumKind>>(CSKindStr)
+ .Case("CSK_MD5", DIFile::CSK_MD5)
+ .Case("CSK_SHA1", DIFile::CSK_SHA1)
+ .Default(None);
}
DIFile *DIFile::getImpl(LLVMContext &Context, MDString *Filename,
- MDString *Directory, DIFile::ChecksumKind CSKind,
- MDString *Checksum, StorageType Storage,
+ MDString *Directory,
+ Optional<DIFile::ChecksumInfo<MDString *>> CS,
+ Optional<MDString *> Source, StorageType Storage,
bool ShouldCreate) {
assert(isCanonical(Filename) && "Expected canonical MDString");
assert(isCanonical(Directory) && "Expected canonical MDString");
- assert(isCanonical(Checksum) && "Expected canonical MDString");
- DEFINE_GETIMPL_LOOKUP(DIFile, (Filename, Directory, CSKind, Checksum));
- Metadata *Ops[] = {Filename, Directory, Checksum};
- DEFINE_GETIMPL_STORE(DIFile, (CSKind), Ops);
+ assert((!CS || isCanonical(CS->Value)) && "Expected canonical MDString");
+ assert((!Source || isCanonical(*Source)) && "Expected canonical MDString");
+ DEFINE_GETIMPL_LOOKUP(DIFile, (Filename, Directory, CS, Source));
+ Metadata *Ops[] = {Filename, Directory, CS ? CS->Value : nullptr,
+ Source.getValueOr(nullptr)};
+ DEFINE_GETIMPL_STORE(DIFile, (CS, Source), Ops);
}
DICompileUnit *DICompileUnit::getImpl(
@@ -446,7 +475,7 @@ DICompileUnit::getEmissionKind(StringRef Str) {
.Default(None);
}
-const char *DICompileUnit::EmissionKindString(DebugEmissionKind EK) {
+const char *DICompileUnit::emissionKindString(DebugEmissionKind EK) {
switch (EK) {
case NoDebug: return "NoDebug";
case FullDebug: return "FullDebug";
@@ -473,7 +502,7 @@ DISubprogram *DISubprogram::getImpl(
bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine,
Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex,
int ThisAdjustment, DIFlags Flags, bool IsOptimized, Metadata *Unit,
- Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables,
+ Metadata *TemplateParams, Metadata *Declaration, Metadata *RetainedNodes,
Metadata *ThrownTypes, StorageType Storage, bool ShouldCreate) {
assert(isCanonical(Name) && "Expected canonical MDString");
assert(isCanonical(LinkageName) && "Expected canonical MDString");
@@ -481,10 +510,10 @@ DISubprogram *DISubprogram::getImpl(
DISubprogram, (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit,
IsDefinition, ScopeLine, ContainingType, Virtuality,
VirtualIndex, ThisAdjustment, Flags, IsOptimized, Unit,
- TemplateParams, Declaration, Variables, ThrownTypes));
+ TemplateParams, Declaration, RetainedNodes, ThrownTypes));
SmallVector<Metadata *, 11> Ops = {
- File, Scope, Name, LinkageName, Type, Unit,
- Declaration, Variables, ContainingType, TemplateParams, ThrownTypes};
+ File, Scope, Name, LinkageName, Type, Unit,
+ Declaration, RetainedNodes, ContainingType, TemplateParams, ThrownTypes};
if (!ThrownTypes) {
Ops.pop_back();
if (!TemplateParams) {
@@ -637,6 +666,18 @@ Optional<uint64_t> DIVariable::getSizeInBits() const {
return None;
}
+DILabel *DILabel::getImpl(LLVMContext &Context, Metadata *Scope,
+ MDString *Name, Metadata *File, unsigned Line,
+ StorageType Storage,
+ bool ShouldCreate) {
+ assert(Scope && "Expected scope");
+ assert(isCanonical(Name) && "Expected canonical MDString");
+ DEFINE_GETIMPL_LOOKUP(DILabel,
+ (Scope, Name, File, Line));
+ Metadata *Ops[] = {Scope, Name, File};
+ DEFINE_GETIMPL_STORE(DILabel, (Line), Ops);
+}
+
DIExpression *DIExpression::getImpl(LLVMContext &Context,
ArrayRef<uint64_t> Elements,
StorageType Storage, bool ShouldCreate) {
@@ -695,8 +736,19 @@ bool DIExpression::isValid() const {
case dwarf::DW_OP_plus:
case dwarf::DW_OP_minus:
case dwarf::DW_OP_mul:
+ case dwarf::DW_OP_div:
+ case dwarf::DW_OP_mod:
+ case dwarf::DW_OP_or:
+ case dwarf::DW_OP_and:
+ case dwarf::DW_OP_xor:
+ case dwarf::DW_OP_shl:
+ case dwarf::DW_OP_shr:
+ case dwarf::DW_OP_shra:
case dwarf::DW_OP_deref:
case dwarf::DW_OP_xderef:
+ case dwarf::DW_OP_lit0:
+ case dwarf::DW_OP_not:
+ case dwarf::DW_OP_dup:
break;
}
}
@@ -756,31 +808,94 @@ DIExpression *DIExpression::prepend(const DIExpression *Expr, bool DerefBefore,
SmallVector<uint64_t, 8> Ops;
if (DerefBefore)
Ops.push_back(dwarf::DW_OP_deref);
-
+
appendOffset(Ops, Offset);
if (DerefAfter)
Ops.push_back(dwarf::DW_OP_deref);
- if (Expr)
- for (auto Op : Expr->expr_ops()) {
- // A DW_OP_stack_value comes at the end, but before a DW_OP_LLVM_fragment.
- if (StackValue) {
- if (Op.getOp() == dwarf::DW_OP_stack_value)
- StackValue = false;
- else if (Op.getOp() == dwarf::DW_OP_LLVM_fragment) {
- Ops.push_back(dwarf::DW_OP_stack_value);
- StackValue = false;
- }
+ return prependOpcodes(Expr, Ops, StackValue);
+}
+
+DIExpression *DIExpression::prependOpcodes(const DIExpression *Expr,
+ SmallVectorImpl<uint64_t> &Ops,
+ bool StackValue) {
+ assert(Expr && "Can't prepend ops to this expression");
+
+ // If there are no ops to prepend, do not even add the DW_OP_stack_value.
+ if (Ops.empty())
+ StackValue = false;
+ for (auto Op : Expr->expr_ops()) {
+ // A DW_OP_stack_value comes at the end, but before a DW_OP_LLVM_fragment.
+ if (StackValue) {
+ if (Op.getOp() == dwarf::DW_OP_stack_value)
+ StackValue = false;
+ else if (Op.getOp() == dwarf::DW_OP_LLVM_fragment) {
+ Ops.push_back(dwarf::DW_OP_stack_value);
+ StackValue = false;
}
- Ops.push_back(Op.getOp());
- for (unsigned I = 0; I < Op.getNumArgs(); ++I)
- Ops.push_back(Op.getArg(I));
}
+ Op.appendToVector(Ops);
+ }
if (StackValue)
Ops.push_back(dwarf::DW_OP_stack_value);
return DIExpression::get(Expr->getContext(), Ops);
}
+DIExpression *DIExpression::append(const DIExpression *Expr,
+ ArrayRef<uint64_t> Ops) {
+ assert(Expr && !Ops.empty() && "Can't append ops to this expression");
+
+ // Copy Expr's current op list.
+ SmallVector<uint64_t, 16> NewOps;
+ for (auto Op : Expr->expr_ops()) {
+ // Append new opcodes before DW_OP_{stack_value, LLVM_fragment}.
+ if (Op.getOp() == dwarf::DW_OP_stack_value ||
+ Op.getOp() == dwarf::DW_OP_LLVM_fragment) {
+ NewOps.append(Ops.begin(), Ops.end());
+
+ // Ensure that the new opcodes are only appended once.
+ Ops = None;
+ }
+ Op.appendToVector(NewOps);
+ }
+
+ NewOps.append(Ops.begin(), Ops.end());
+ return DIExpression::get(Expr->getContext(), NewOps);
+}
+
+DIExpression *DIExpression::appendToStack(const DIExpression *Expr,
+ ArrayRef<uint64_t> Ops) {
+ assert(Expr && !Ops.empty() && "Can't append ops to this expression");
+ assert(none_of(Ops,
+ [](uint64_t Op) {
+ return Op == dwarf::DW_OP_stack_value ||
+ Op == dwarf::DW_OP_LLVM_fragment;
+ }) &&
+ "Can't append this op");
+
+ // Append a DW_OP_deref after Expr's current op list if it's non-empty and
+ // has no DW_OP_stack_value.
+ //
+ // Match .* DW_OP_stack_value (DW_OP_LLVM_fragment A B)?.
+ Optional<FragmentInfo> FI = Expr->getFragmentInfo();
+ unsigned DropUntilStackValue = FI.hasValue() ? 3 : 0;
+ ArrayRef<uint64_t> ExprOpsBeforeFragment =
+ Expr->getElements().drop_back(DropUntilStackValue);
+ bool NeedsDeref = (Expr->getNumElements() > DropUntilStackValue) &&
+ (ExprOpsBeforeFragment.back() != dwarf::DW_OP_stack_value);
+ bool NeedsStackValue = NeedsDeref || ExprOpsBeforeFragment.empty();
+
+ // Append a DW_OP_deref after Expr's current op list if needed, then append
+ // the new ops, and finally ensure that a single DW_OP_stack_value is present.
+ SmallVector<uint64_t, 16> NewOps;
+ if (NeedsDeref)
+ NewOps.push_back(dwarf::DW_OP_deref);
+ NewOps.append(Ops.begin(), Ops.end());
+ if (NeedsStackValue)
+ NewOps.push_back(dwarf::DW_OP_stack_value);
+ return DIExpression::append(Expr, NewOps);
+}
+
Optional<DIExpression *> DIExpression::createFragmentExpression(
const DIExpression *Expr, unsigned OffsetInBits, unsigned SizeInBits) {
SmallVector<uint64_t, 8> Ops;
@@ -800,17 +915,15 @@ Optional<DIExpression *> DIExpression::createFragmentExpression(
case dwarf::DW_OP_LLVM_fragment: {
// Make the new offset point into the existing fragment.
uint64_t FragmentOffsetInBits = Op.getArg(0);
- // Op.getArg(0) is FragmentOffsetInBits.
- // Op.getArg(1) is FragmentSizeInBits.
- assert((OffsetInBits + SizeInBits <= Op.getArg(0) + Op.getArg(1)) &&
+ uint64_t FragmentSizeInBits = Op.getArg(1);
+ (void)FragmentSizeInBits;
+ assert((OffsetInBits + SizeInBits <= FragmentSizeInBits) &&
"new fragment outside of original fragment");
OffsetInBits += FragmentOffsetInBits;
continue;
}
}
- Ops.push_back(Op.getOp());
- for (unsigned I = 0; I < Op.getNumArgs(); ++I)
- Ops.push_back(Op.getArg(I));
+ Op.appendToVector(Ops);
}
}
Ops.push_back(dwarf::DW_OP_LLVM_fragment);
@@ -883,4 +996,3 @@ DIMacroFile *DIMacroFile::getImpl(LLVMContext &Context, unsigned MIType,
Metadata *Ops[] = { File, Elements };
DEFINE_GETIMPL_STORE(DIMacroFile, (MIType, Line), Ops);
}
-