forked from OSchip/llvm-project
[llvm] API for encoding/decoding DWARF discriminators.
Summary: Added a pair of APIs for encoding/decoding the 3 components of a DWARF discriminator described in http://lists.llvm.org/pipermail/llvm-dev/2016-October/106532.html: the base discriminator, the duplication factor (useful in profile-guided optimization) and the copy index (used to identify copies of code in cases like loop unrolling) The encoding packs 3 unsigned values in 32 bits. This CL addresses 2 issues: - communicates overflow back to the user - supports encoding all 3 components together. Current APIs assume a sequencing of events. For example, creating a new discriminator based on an existing one by changing the base discriminator was not supported. Reviewers: davidxl, danielcdh, wmi, dblaikie Reviewed By: dblaikie Subscribers: zzheng, dmgreen, aprantl, JDevlieghere, llvm-commits Differential Revision: https://reviews.llvm.org/D55681 llvm-svn: 349973
This commit is contained in:
parent
8d20cfdfc6
commit
b53eeb6f4c
|
@ -1430,6 +1430,9 @@ class DILocation : public MDNode {
|
|||
|
||||
/// Reverse transformation as getPrefixEncodingFromUnsigned.
|
||||
static unsigned getUnsignedFromPrefixEncoding(unsigned U) {
|
||||
if (U & 1)
|
||||
return 0;
|
||||
U >>= 1;
|
||||
return (U & 0x20) ? (((U >> 1) & 0xfe0) | (U & 0x1f)) : (U & 0x1f);
|
||||
}
|
||||
|
||||
|
@ -1448,6 +1451,14 @@ class DILocation : public MDNode {
|
|||
getRawInlinedAt(), isImplicitCode());
|
||||
}
|
||||
|
||||
static unsigned encodeComponent(unsigned C) {
|
||||
return (C == 0) ? 1U : (getPrefixEncodingFromUnsigned(C) << 1);
|
||||
}
|
||||
|
||||
static unsigned encodingBits(unsigned C) {
|
||||
return (C == 0) ? 1 : (C > 0x1f ? 14 : 7);
|
||||
}
|
||||
|
||||
public:
|
||||
// Disallow replacing operands.
|
||||
void replaceOperandWith(unsigned I, Metadata *New) = delete;
|
||||
|
@ -1518,20 +1529,35 @@ public:
|
|||
/// order. If the lowest bit is 1, the current component is empty, and the
|
||||
/// next component will start in the next bit. Otherwise, the current
|
||||
/// component is non-empty, and its content starts in the next bit. The
|
||||
/// length of each components is either 5 bit or 12 bit: if the 7th bit
|
||||
/// value of each components is either 5 bit or 12 bit: if the 7th bit
|
||||
/// is 0, the bit 2~6 (5 bits) are used to represent the component; if the
|
||||
/// 7th bit is 1, the bit 2~6 (5 bits) and 8~14 (7 bits) are combined to
|
||||
/// represent the component.
|
||||
/// represent the component. Thus, the number of bits used for a component
|
||||
/// is either 0 (if it and all the next components are empty); 1 - if it is
|
||||
/// empty; 7 - if its value is up to and including 0x1f (lsb and msb are both
|
||||
/// 0); or 14, if its value is up to and including 0x1ff. Note that the last
|
||||
/// component is also capped at 0x1ff, even in the case when both first
|
||||
/// components are 0, and we'd technically have 29 bits available.
|
||||
///
|
||||
/// For precise control over the data being encoded in the discriminator,
|
||||
/// use encodeDiscriminator/decodeDiscriminator.
|
||||
///
|
||||
/// Use {get|set}BaseDiscriminator and cloneWithDuplicationFactor after reading
|
||||
/// their documentation, as their behavior has side-effects.
|
||||
|
||||
inline unsigned getDiscriminator() const;
|
||||
|
||||
/// Returns a new DILocation with updated \p Discriminator.
|
||||
inline const DILocation *cloneWithDiscriminator(unsigned Discriminator) const;
|
||||
|
||||
/// Returns a new DILocation with updated base discriminator \p BD.
|
||||
inline const DILocation *setBaseDiscriminator(unsigned BD) const;
|
||||
/// Returns a new DILocation with updated base discriminator \p BD. Only the
|
||||
/// base discriminator is set in the new DILocation, the other encoded values
|
||||
/// are elided.
|
||||
/// If the discriminator cannot be encoded, the function returns None.
|
||||
inline Optional<const DILocation *> setBaseDiscriminator(unsigned BD) const;
|
||||
|
||||
/// Returns the duplication factor stored in the discriminator.
|
||||
/// Returns the duplication factor stored in the discriminator, or 1 if no
|
||||
/// duplication factor (or 0) is encoded.
|
||||
inline unsigned getDuplicationFactor() const;
|
||||
|
||||
/// Returns the copy identifier stored in the discriminator.
|
||||
|
@ -1540,9 +1566,11 @@ public:
|
|||
/// Returns the base discriminator stored in the discriminator.
|
||||
inline unsigned getBaseDiscriminator() const;
|
||||
|
||||
/// Returns a new DILocation with duplication factor \p DF encoded in the
|
||||
/// discriminator.
|
||||
inline const DILocation *cloneWithDuplicationFactor(unsigned DF) const;
|
||||
/// Returns a new DILocation with duplication factor \p DF * current
|
||||
/// duplication factor encoded in the discriminator. The current duplication
|
||||
/// factor is as defined by getDuplicationFactor().
|
||||
/// Returns None if encoding failed.
|
||||
inline Optional<const DILocation *> cloneWithDuplicationFactor(unsigned DF) const;
|
||||
|
||||
/// When two instructions are combined into a single instruction we also
|
||||
/// need to combine the original locations into a single location.
|
||||
|
@ -1563,19 +1591,31 @@ public:
|
|||
|
||||
/// Returns the base discriminator for a given encoded discriminator \p D.
|
||||
static unsigned getBaseDiscriminatorFromDiscriminator(unsigned D) {
|
||||
if ((D & 1) == 0)
|
||||
return getUnsignedFromPrefixEncoding(D >> 1);
|
||||
else
|
||||
return 0;
|
||||
return getUnsignedFromPrefixEncoding(D);
|
||||
}
|
||||
|
||||
/// Returns the duplication factor for a given encoded discriminator \p D.
|
||||
/// Raw encoding of the discriminator. APIs such as setBaseDiscriminator or
|
||||
/// cloneWithDuplicationFactor have certain side-effects. This API, in
|
||||
/// conjunction with cloneWithDiscriminator, may be used to encode precisely
|
||||
/// the values provided. \p BD: base discriminator \p DF: duplication factor
|
||||
/// \p CI: copy index
|
||||
/// The return is None if the values cannot be encoded in 32 bits - for
|
||||
/// example, values for BD or DF larger than 12 bits. Otherwise, the return
|
||||
/// is the encoded value.
|
||||
static Optional<unsigned> encodeDiscriminator(unsigned BD, unsigned DF, unsigned CI);
|
||||
|
||||
/// Raw decoder for values in an encoded discriminator D.
|
||||
static void decodeDiscriminator(unsigned D, unsigned &BD, unsigned &DF,
|
||||
unsigned &CI);
|
||||
|
||||
/// Returns the duplication factor for a given encoded discriminator \p D, or
|
||||
/// 1 if no value or 0 is encoded.
|
||||
static unsigned getDuplicationFactorFromDiscriminator(unsigned D) {
|
||||
D = getNextComponentInDiscriminator(D);
|
||||
if (D == 0 || (D & 1))
|
||||
unsigned Ret = getUnsignedFromPrefixEncoding(D);
|
||||
if (Ret == 0)
|
||||
return 1;
|
||||
else
|
||||
return getUnsignedFromPrefixEncoding(D >> 1);
|
||||
return Ret;
|
||||
}
|
||||
|
||||
/// Returns the copy identifier for a given encoded discriminator \p D.
|
||||
|
@ -1999,28 +2039,24 @@ unsigned DILocation::getCopyIdentifier() const {
|
|||
return getCopyIdentifierFromDiscriminator(getDiscriminator());
|
||||
}
|
||||
|
||||
const DILocation *DILocation::setBaseDiscriminator(unsigned D) const {
|
||||
Optional<const DILocation *> DILocation::setBaseDiscriminator(unsigned D) const {
|
||||
if (D == 0)
|
||||
return this;
|
||||
else
|
||||
return cloneWithDiscriminator(getPrefixEncodingFromUnsigned(D) << 1);
|
||||
if (D > 0xfff)
|
||||
return None;
|
||||
return cloneWithDiscriminator(encodeComponent(D));
|
||||
}
|
||||
|
||||
const DILocation *DILocation::cloneWithDuplicationFactor(unsigned DF) const {
|
||||
Optional<const DILocation *> DILocation::cloneWithDuplicationFactor(unsigned DF) const {
|
||||
DF *= getDuplicationFactor();
|
||||
if (DF <= 1)
|
||||
return this;
|
||||
|
||||
unsigned BD = getBaseDiscriminator();
|
||||
unsigned CI = getCopyIdentifier() << (DF > 0x1f ? 14 : 7);
|
||||
unsigned D = CI | (getPrefixEncodingFromUnsigned(DF) << 1);
|
||||
|
||||
if (BD == 0)
|
||||
D = (D << 1) | 1;
|
||||
else
|
||||
D = (D << (BD > 0x1f ? 14 : 7)) | (getPrefixEncodingFromUnsigned(BD) << 1);
|
||||
|
||||
return cloneWithDiscriminator(D);
|
||||
unsigned CI = getCopyIdentifier();
|
||||
if (Optional<unsigned> D = encodeDiscriminator(BD, DF, CI))
|
||||
return cloneWithDiscriminator(*D);
|
||||
return None;
|
||||
}
|
||||
|
||||
class DINamespace : public DIScope {
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
|
||||
#include <numeric>
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
DILocation::DILocation(LLVMContext &C, StorageType Storage, unsigned Line,
|
||||
|
@ -113,6 +115,47 @@ const DILocation *DILocation::getMergedLocation(const DILocation *LocA,
|
|||
return DILocation::get(Result->getContext(), 0, 0, S, L);
|
||||
}
|
||||
|
||||
Optional<unsigned> DILocation::encodeDiscriminator(unsigned BD, unsigned DF, unsigned CI) {
|
||||
SmallVector<unsigned, 3> Components = {BD, DF, CI};
|
||||
uint64_t RemainingWork = 0U;
|
||||
// We use RemainingWork to figure out if we have no remaining components to
|
||||
// encode. For example: if BD != 0 but DF == 0 && CI == 0, we don't need to
|
||||
// encode anything for the latter 2.
|
||||
// Since any of the input components is at most 32 bits, their sum will be
|
||||
// less than 34 bits, and thus RemainingWork won't overflow.
|
||||
RemainingWork = std::accumulate(Components.begin(), Components.end(), RemainingWork);
|
||||
|
||||
int I = 0;
|
||||
unsigned Ret = 0;
|
||||
unsigned NextBitInsertionIndex = 0;
|
||||
while (RemainingWork > 0) {
|
||||
unsigned C = Components[I++];
|
||||
RemainingWork -= C;
|
||||
unsigned EC = encodeComponent(C);
|
||||
Ret |= (EC << NextBitInsertionIndex);
|
||||
NextBitInsertionIndex += encodingBits(C);
|
||||
}
|
||||
|
||||
// Encoding may be unsuccessful because of overflow. We determine success by
|
||||
// checking equivalence of components before & after encoding. Alternatively,
|
||||
// we could determine Success during encoding, but the current alternative is
|
||||
// simpler.
|
||||
unsigned TBD, TDF, TCI = 0;
|
||||
decodeDiscriminator(Ret, TBD, TDF, TCI);
|
||||
if (TBD == BD && TDF == DF && TCI == CI)
|
||||
return Ret;
|
||||
return None;
|
||||
}
|
||||
|
||||
void DILocation::decodeDiscriminator(unsigned D, unsigned &BD, unsigned &DF,
|
||||
unsigned &CI) {
|
||||
BD = getUnsignedFromPrefixEncoding(D);
|
||||
DF = getUnsignedFromPrefixEncoding(getNextComponentInDiscriminator(D));
|
||||
CI = getUnsignedFromPrefixEncoding(
|
||||
getNextComponentInDiscriminator(getNextComponentInDiscriminator(D)));
|
||||
}
|
||||
|
||||
|
||||
DINode::DIFlags DINode::getFlag(StringRef Flag) {
|
||||
return StringSwitch<DIFlags>(Flag)
|
||||
#define HANDLE_DI_FLAG(ID, NAME) .Case("DIFlag" #NAME, Flag##NAME)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include "llvm/IR/DebugInfoMetadata.h"
|
||||
#include "llvm/ProfileData/SampleProf.h"
|
||||
#include "llvm/ProfileData/SampleProfReader.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Transforms/IPO/SampleProfile.h"
|
||||
using namespace llvm;
|
||||
|
||||
|
@ -107,27 +108,36 @@ bool X86DiscriminateMemOps::runOnMachineFunction(MachineFunction &MF) {
|
|||
if (!DI) {
|
||||
DI = ReferenceDI;
|
||||
}
|
||||
DenseSet<unsigned> &Set = Seen[diToLocation(DI)];
|
||||
Location L = diToLocation(DI);
|
||||
DenseSet<unsigned> &Set = Seen[L];
|
||||
const std::pair<DenseSet<unsigned>::iterator, bool> TryInsert =
|
||||
Set.insert(DI->getBaseDiscriminator());
|
||||
if (!TryInsert.second) {
|
||||
DI = DI->setBaseDiscriminator(++MemOpDiscriminators[diToLocation(DI)]);
|
||||
updateDebugInfo(&MI, DI);
|
||||
Changed = true;
|
||||
const std::pair<DenseSet<unsigned>::iterator, bool> MustInsert =
|
||||
Set.insert(DI->getBaseDiscriminator());
|
||||
// FIXME (mtrofin): check if the to-be inserted base discriminator can
|
||||
// be added. This requires a new API on DILocation.
|
||||
// The assumption is that this scenario is infrequent/OK not to support.
|
||||
// If evidence points otherwise, we can explore synthesize unique DIs by
|
||||
// adding fake line numbers.
|
||||
if (!MustInsert.second) {
|
||||
LLVM_DEBUG(dbgs()
|
||||
<< "Unable to create a unique discriminator in "
|
||||
unsigned BF, DF, CI = 0;
|
||||
DILocation::decodeDiscriminator(DI->getDiscriminator(), BF, DF, CI);
|
||||
Optional<unsigned> EncodedDiscriminator = DILocation::encodeDiscriminator(
|
||||
MemOpDiscriminators[L] + 1, DF, CI);
|
||||
|
||||
if (!EncodedDiscriminator) {
|
||||
// FIXME(mtrofin): The assumption is that this scenario is infrequent/OK
|
||||
// not to support. If evidence points otherwise, we can explore synthesizeing
|
||||
// unique DIs by adding fake line numbers, or by constructing 64 bit
|
||||
// discriminators.
|
||||
LLVM_DEBUG(dbgs() << "Unable to create a unique discriminator "
|
||||
"for instruction with memory operand in: "
|
||||
<< DI->getFilename() << " Line: " << DI->getLine()
|
||||
<< " Column: " << DI->getColumn()
|
||||
<< ". This is likely due to a large macro expansion.\n");
|
||||
<< ". This is likely due to a large macro expansion. \n");
|
||||
continue;
|
||||
}
|
||||
// Since we were able to encode, bump the MemOpDiscriminators.
|
||||
++MemOpDiscriminators[L];
|
||||
DI = DI->cloneWithDiscriminator(EncodedDiscriminator.getValue());
|
||||
updateDebugInfo(&MI, DI);
|
||||
Changed = true;
|
||||
std::pair<DenseSet<unsigned>::iterator, bool> MustInsert =
|
||||
Set.insert(DI->getBaseDiscriminator());
|
||||
assert(MustInsert.second && "New discriminator shouldn't be present in set");
|
||||
}
|
||||
|
||||
// Bump the reference DI to avoid cramming discriminators on line 0.
|
||||
|
|
|
@ -209,10 +209,18 @@ static bool addDiscriminators(Function &F) {
|
|||
// Only the lowest 7 bits are used to represent a discriminator to fit
|
||||
// it in 1 byte ULEB128 representation.
|
||||
unsigned Discriminator = R.second ? ++LDM[L] : LDM[L];
|
||||
I.setDebugLoc(DIL->setBaseDiscriminator(Discriminator));
|
||||
LLVM_DEBUG(dbgs() << DIL->getFilename() << ":" << DIL->getLine() << ":"
|
||||
<< DIL->getColumn() << ":" << Discriminator << " " << I
|
||||
<< "\n");
|
||||
auto NewDIL = DIL->setBaseDiscriminator(Discriminator);
|
||||
if (!NewDIL) {
|
||||
LLVM_DEBUG(dbgs() << "Could not encode discriminator: "
|
||||
<< DIL->getFilename() << ":" << DIL->getLine() << ":"
|
||||
<< DIL->getColumn() << ":" << Discriminator << " "
|
||||
<< I << "\n");
|
||||
} else {
|
||||
I.setDebugLoc(NewDIL.getValue());
|
||||
LLVM_DEBUG(dbgs() << DIL->getFilename() << ":" << DIL->getLine() << ":"
|
||||
<< DIL->getColumn() << ":" << Discriminator << " " << I
|
||||
<< "\n");
|
||||
}
|
||||
Changed = true;
|
||||
}
|
||||
}
|
||||
|
@ -239,8 +247,17 @@ static bool addDiscriminators(Function &F) {
|
|||
std::make_pair(CurrentDIL->getFilename(), CurrentDIL->getLine());
|
||||
if (!CallLocations.insert(L).second) {
|
||||
unsigned Discriminator = ++LDM[L];
|
||||
Current->setDebugLoc(CurrentDIL->setBaseDiscriminator(Discriminator));
|
||||
Changed = true;
|
||||
auto NewDIL = CurrentDIL->setBaseDiscriminator(Discriminator);
|
||||
if (!NewDIL) {
|
||||
LLVM_DEBUG(dbgs()
|
||||
<< "Could not encode discriminator: "
|
||||
<< CurrentDIL->getFilename() << ":"
|
||||
<< CurrentDIL->getLine() << ":" << CurrentDIL->getColumn()
|
||||
<< ":" << Discriminator << " " << I << "\n");
|
||||
} else {
|
||||
Current->setDebugLoc(NewDIL.getValue());
|
||||
Changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -598,8 +598,15 @@ LoopUnrollResult llvm::UnrollLoop(
|
|||
for (BasicBlock *BB : L->getBlocks())
|
||||
for (Instruction &I : *BB)
|
||||
if (!isa<DbgInfoIntrinsic>(&I))
|
||||
if (const DILocation *DIL = I.getDebugLoc())
|
||||
I.setDebugLoc(DIL->cloneWithDuplicationFactor(Count));
|
||||
if (const DILocation *DIL = I.getDebugLoc()) {
|
||||
auto NewDIL = DIL->cloneWithDuplicationFactor(Count);
|
||||
if (NewDIL)
|
||||
I.setDebugLoc(NewDIL.getValue());
|
||||
else
|
||||
LLVM_DEBUG(dbgs()
|
||||
<< "Failed to create new discriminator: "
|
||||
<< DIL->getFilename() << " Line: " << DIL->getLine());
|
||||
}
|
||||
|
||||
for (unsigned It = 1; It != Count; ++It) {
|
||||
std::vector<BasicBlock*> NewBlocks;
|
||||
|
|
|
@ -300,8 +300,15 @@ LoopUnrollResult llvm::UnrollAndJamLoop(
|
|||
for (BasicBlock *BB : L->getBlocks())
|
||||
for (Instruction &I : *BB)
|
||||
if (!isa<DbgInfoIntrinsic>(&I))
|
||||
if (const DILocation *DIL = I.getDebugLoc())
|
||||
I.setDebugLoc(DIL->cloneWithDuplicationFactor(Count));
|
||||
if (const DILocation *DIL = I.getDebugLoc()) {
|
||||
auto NewDIL = DIL->cloneWithDuplicationFactor(Count);
|
||||
if (NewDIL)
|
||||
I.setDebugLoc(NewDIL.getValue());
|
||||
else
|
||||
LLVM_DEBUG(dbgs()
|
||||
<< "Failed to create new discriminator: "
|
||||
<< DIL->getFilename() << " Line: " << DIL->getLine());
|
||||
}
|
||||
|
||||
// Copy all blocks
|
||||
for (unsigned It = 1; It != Count; ++It) {
|
||||
|
|
|
@ -759,8 +759,15 @@ void InnerLoopVectorizer::setDebugLocFromInst(IRBuilder<> &B, const Value *Ptr)
|
|||
if (const Instruction *Inst = dyn_cast_or_null<Instruction>(Ptr)) {
|
||||
const DILocation *DIL = Inst->getDebugLoc();
|
||||
if (DIL && Inst->getFunction()->isDebugInfoForProfiling() &&
|
||||
!isa<DbgInfoIntrinsic>(Inst))
|
||||
B.SetCurrentDebugLocation(DIL->cloneWithDuplicationFactor(UF * VF));
|
||||
!isa<DbgInfoIntrinsic>(Inst)) {
|
||||
auto NewDIL = DIL->cloneWithDuplicationFactor(UF * VF);
|
||||
if (NewDIL)
|
||||
B.SetCurrentDebugLocation(NewDIL.getValue());
|
||||
else
|
||||
LLVM_DEBUG(dbgs()
|
||||
<< "Failed to create new discriminator: "
|
||||
<< DIL->getFilename() << " Line: " << DIL->getLine());
|
||||
}
|
||||
else
|
||||
B.SetCurrentDebugLocation(DIL);
|
||||
} else
|
||||
|
|
|
@ -981,6 +981,107 @@ TEST_F(DILocationTest, cloneTemporary) {
|
|||
EXPECT_TRUE(L2->isTemporary());
|
||||
}
|
||||
|
||||
TEST_F(DILocationTest, discriminatorEncoding) {
|
||||
EXPECT_EQ(0U, DILocation::encodeDiscriminator(0, 0, 0).getValue());
|
||||
|
||||
// Encode base discriminator as a component: lsb is 0, then the value.
|
||||
// The other components are all absent, so we leave all the other bits 0.
|
||||
EXPECT_EQ(2U, DILocation::encodeDiscriminator(1, 0, 0).getValue());
|
||||
|
||||
// Base discriminator component is empty, so lsb is 1. Next component is not
|
||||
// empty, so its lsb is 0, then its value (1). Next component is empty.
|
||||
// So the bit pattern is 101.
|
||||
EXPECT_EQ(5U, DILocation::encodeDiscriminator(0, 1, 0).getValue());
|
||||
|
||||
// First 2 components are empty, so the bit pattern is 11. Then the
|
||||
// next component - ending up with 1011.
|
||||
EXPECT_EQ(0xbU, DILocation::encodeDiscriminator(0, 0, 1).getValue());
|
||||
|
||||
// The bit pattern for the first 2 components is 11. The next bit is 0,
|
||||
// because the last component is not empty. We have 29 bits usable for
|
||||
// encoding, but we cap it at 12 bits uniformously for all components. We
|
||||
// encode the last component over 14 bits.
|
||||
EXPECT_EQ(0xfffbU, DILocation::encodeDiscriminator(0, 0, 0xfff).getValue());
|
||||
|
||||
EXPECT_EQ(0x102U, DILocation::encodeDiscriminator(1, 1, 0).getValue());
|
||||
|
||||
EXPECT_EQ(0x13eU, DILocation::encodeDiscriminator(0x1f, 1, 0).getValue());
|
||||
|
||||
EXPECT_EQ(0x87feU, DILocation::encodeDiscriminator(0x1ff, 1, 0).getValue());
|
||||
|
||||
EXPECT_EQ(0x1f3eU, DILocation::encodeDiscriminator(0x1f, 0x1f, 0).getValue());
|
||||
|
||||
EXPECT_EQ(0x3ff3eU,
|
||||
DILocation::encodeDiscriminator(0x1f, 0x1ff, 0).getValue());
|
||||
|
||||
EXPECT_EQ(0x1ff87feU,
|
||||
DILocation::encodeDiscriminator(0x1ff, 0x1ff, 0).getValue());
|
||||
|
||||
EXPECT_EQ(0xfff9f3eU,
|
||||
DILocation::encodeDiscriminator(0x1f, 0x1f, 0xfff).getValue());
|
||||
|
||||
EXPECT_EQ(0xffc3ff3eU,
|
||||
DILocation::encodeDiscriminator(0x1f, 0x1ff, 0x1ff).getValue());
|
||||
|
||||
EXPECT_EQ(0xffcf87feU,
|
||||
DILocation::encodeDiscriminator(0x1ff, 0x1f, 0x1ff).getValue());
|
||||
|
||||
EXPECT_EQ(0xe1ff87feU,
|
||||
DILocation::encodeDiscriminator(0x1ff, 0x1ff, 7).getValue());
|
||||
}
|
||||
|
||||
TEST_F(DILocationTest, discriminatorEncodingNegativeTests) {
|
||||
EXPECT_EQ(None, DILocation::encodeDiscriminator(0, 0, 0x1000));
|
||||
EXPECT_EQ(None, DILocation::encodeDiscriminator(0x1000, 0, 0));
|
||||
EXPECT_EQ(None, DILocation::encodeDiscriminator(0, 0x1000, 0));
|
||||
EXPECT_EQ(None, DILocation::encodeDiscriminator(0, 0, 0x1000));
|
||||
EXPECT_EQ(None, DILocation::encodeDiscriminator(0x1ff, 0x1ff, 8));
|
||||
EXPECT_EQ(None,
|
||||
DILocation::encodeDiscriminator(std::numeric_limits<uint32_t>::max(),
|
||||
std::numeric_limits<uint32_t>::max(),
|
||||
0));
|
||||
}
|
||||
|
||||
TEST_F(DILocationTest, discriminatorSpecialCases) {
|
||||
// We don't test getCopyIdentifier here because the only way
|
||||
// to set it is by constructing an encoded discriminator using
|
||||
// encodeDiscriminator, which is already tested.
|
||||
auto L1 = DILocation::get(Context, 1, 2, getSubprogram());
|
||||
EXPECT_EQ(0U, L1->getBaseDiscriminator());
|
||||
EXPECT_EQ(1U, L1->getDuplicationFactor());
|
||||
|
||||
auto L2 = L1->setBaseDiscriminator(1).getValue();
|
||||
EXPECT_EQ(0U, L1->getBaseDiscriminator());
|
||||
EXPECT_EQ(1U, L1->getDuplicationFactor());
|
||||
|
||||
EXPECT_EQ(1U, L2->getBaseDiscriminator());
|
||||
EXPECT_EQ(1U, L2->getDuplicationFactor());
|
||||
|
||||
auto L3 = L2->cloneWithDuplicationFactor(2).getValue();
|
||||
EXPECT_EQ(1U, L3->getBaseDiscriminator());
|
||||
EXPECT_EQ(2U, L3->getDuplicationFactor());
|
||||
|
||||
auto L4 = L3->cloneWithDuplicationFactor(4).getValue();
|
||||
EXPECT_EQ(1U, L4->getBaseDiscriminator());
|
||||
EXPECT_EQ(8U, L4->getDuplicationFactor());
|
||||
|
||||
auto L5 = L4->setBaseDiscriminator(2).getValue();
|
||||
EXPECT_EQ(2U, L5->getBaseDiscriminator());
|
||||
EXPECT_EQ(1U, L5->getDuplicationFactor());
|
||||
|
||||
// Check extreme cases
|
||||
auto L6 = L1->setBaseDiscriminator(0xfff).getValue();
|
||||
EXPECT_EQ(0xfffU, L6->getBaseDiscriminator());
|
||||
EXPECT_EQ(
|
||||
0xfffU,
|
||||
L6->cloneWithDuplicationFactor(0xfff).getValue()->getDuplicationFactor());
|
||||
|
||||
// Check we return None for unencodable cases.
|
||||
EXPECT_EQ(None, L4->setBaseDiscriminator(0x1000));
|
||||
EXPECT_EQ(None, L4->cloneWithDuplicationFactor(0x1000));
|
||||
}
|
||||
|
||||
|
||||
typedef MetadataTest GenericDINodeTest;
|
||||
|
||||
TEST_F(GenericDINodeTest, get) {
|
||||
|
|
Loading…
Reference in New Issue