aboutsummaryrefslogtreecommitdiffstats
path: root/lib/IR
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2014-12-01 14:51:49 -0800
committerStephen Hines <srhines@google.com>2014-12-02 16:08:10 -0800
commit37ed9c199ca639565f6ce88105f9e39e898d82d0 (patch)
tree8fb36d3910e3ee4c4e1b7422f4f017108efc52f5 /lib/IR
parentd2327b22152ced7bc46dc629fc908959e8a52d03 (diff)
downloadexternal_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.tar.gz
external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.tar.bz2
external_llvm-37ed9c199ca639565f6ce88105f9e39e898d82d0.zip
Update aosp/master LLVM for rebase to r222494.
Change-Id: Ic787f5e0124df789bd26f3f24680f45e678eef2d
Diffstat (limited to 'lib/IR')
-rw-r--r--lib/IR/Android.mk1
-rw-r--r--lib/IR/AsmWriter.cpp278
-rw-r--r--lib/IR/AsmWriter.h11
-rw-r--r--lib/IR/AttributeImpl.h26
-rw-r--r--lib/IR/Attributes.cpp110
-rw-r--r--lib/IR/AutoUpgrade.cpp211
-rw-r--r--lib/IR/BasicBlock.cpp50
-rw-r--r--lib/IR/CMakeLists.txt1
-rw-r--r--lib/IR/ConstantFold.cpp29
-rw-r--r--lib/IR/ConstantFold.h4
-rw-r--r--lib/IR/Constants.cpp509
-rw-r--r--lib/IR/ConstantsContext.h628
-rw-r--r--lib/IR/Core.cpp120
-rw-r--r--lib/IR/DIBuilder.cpp1271
-rw-r--r--lib/IR/DataLayout.cpp34
-rw-r--r--lib/IR/DebugInfo.cpp583
-rw-r--r--lib/IR/DebugLoc.cpp10
-rw-r--r--lib/IR/DiagnosticInfo.cpp29
-rw-r--r--lib/IR/DiagnosticPrinter.cpp2
-rw-r--r--lib/IR/Function.cpp122
-rw-r--r--lib/IR/GCOV.cpp13
-rw-r--r--lib/IR/Globals.cpp27
-rw-r--r--lib/IR/IRBuilder.cpp44
-rw-r--r--lib/IR/InlineAsm.cpp4
-rw-r--r--lib/IR/Instruction.cpp26
-rw-r--r--lib/IR/Instructions.cpp78
-rw-r--r--lib/IR/LLVMContext.cpp65
-rw-r--r--lib/IR/LLVMContextImpl.cpp18
-rw-r--r--lib/IR/LLVMContextImpl.h89
-rw-r--r--lib/IR/LeaksContext.h6
-rw-r--r--lib/IR/LegacyPassManager.cpp14
-rw-r--r--lib/IR/MDBuilder.cpp22
-rw-r--r--lib/IR/Mangler.cpp96
-rw-r--r--lib/IR/Metadata.cpp295
-rw-r--r--lib/IR/Module.cpp58
-rw-r--r--lib/IR/PassManager.cpp2
-rw-r--r--lib/IR/PassRegistry.cpp56
-rw-r--r--lib/IR/SymbolTableListTraitsImpl.h4
-rw-r--r--lib/IR/Type.cpp45
-rw-r--r--lib/IR/TypeFinder.cpp2
-rw-r--r--lib/IR/Use.cpp2
-rw-r--r--lib/IR/UseListOrder.cpp43
-rw-r--r--lib/IR/User.cpp3
-rw-r--r--lib/IR/Value.cpp120
-rw-r--r--lib/IR/ValueSymbolTable.cpp25
-rw-r--r--lib/IR/Verifier.cpp198
46 files changed, 3084 insertions, 2300 deletions
diff --git a/lib/IR/Android.mk b/lib/IR/Android.mk
index c51b241d1d..a3632cf06d 100644
--- a/lib/IR/Android.mk
+++ b/lib/IR/Android.mk
@@ -41,6 +41,7 @@ vmcore_SRC_FILES := \
Type.cpp \
TypeFinder.cpp \
Use.cpp \
+ UseListOrder.cpp \
User.cpp \
Value.cpp \
ValueSymbolTable.cpp \
diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp
index a7499bc09b..1961a20901 100644
--- a/lib/IR/AsmWriter.cpp
+++ b/lib/IR/AsmWriter.cpp
@@ -49,6 +49,213 @@ AssemblyAnnotationWriter::~AssemblyAnnotationWriter() {}
// Helper Functions
//===----------------------------------------------------------------------===//
+namespace {
+struct OrderMap {
+ DenseMap<const Value *, std::pair<unsigned, bool>> IDs;
+
+ unsigned size() const { return IDs.size(); }
+ std::pair<unsigned, bool> &operator[](const Value *V) { return IDs[V]; }
+ std::pair<unsigned, bool> lookup(const Value *V) const {
+ return IDs.lookup(V);
+ }
+ void index(const Value *V) {
+ // Explicitly sequence get-size and insert-value operations to avoid UB.
+ unsigned ID = IDs.size() + 1;
+ IDs[V].first = ID;
+ }
+};
+}
+
+static void orderValue(const Value *V, OrderMap &OM) {
+ if (OM.lookup(V).first)
+ return;
+
+ if (const Constant *C = dyn_cast<Constant>(V))
+ if (C->getNumOperands() && !isa<GlobalValue>(C))
+ for (const Value *Op : C->operands())
+ if (!isa<BasicBlock>(Op) && !isa<GlobalValue>(Op))
+ orderValue(Op, OM);
+
+ // Note: we cannot cache this lookup above, since inserting into the map
+ // changes the map's size, and thus affects the other IDs.
+ OM.index(V);
+}
+
+static OrderMap orderModule(const Module *M) {
+ // This needs to match the order used by ValueEnumerator::ValueEnumerator()
+ // and ValueEnumerator::incorporateFunction().
+ OrderMap OM;
+
+ for (const GlobalVariable &G : M->globals()) {
+ if (G.hasInitializer())
+ if (!isa<GlobalValue>(G.getInitializer()))
+ orderValue(G.getInitializer(), OM);
+ orderValue(&G, OM);
+ }
+ for (const GlobalAlias &A : M->aliases()) {
+ if (!isa<GlobalValue>(A.getAliasee()))
+ orderValue(A.getAliasee(), OM);
+ orderValue(&A, OM);
+ }
+ for (const Function &F : *M) {
+ if (F.hasPrefixData())
+ if (!isa<GlobalValue>(F.getPrefixData()))
+ orderValue(F.getPrefixData(), OM);
+ orderValue(&F, OM);
+
+ if (F.isDeclaration())
+ continue;
+
+ for (const Argument &A : F.args())
+ orderValue(&A, OM);
+ for (const BasicBlock &BB : F) {
+ orderValue(&BB, OM);
+ for (const Instruction &I : BB) {
+ for (const Value *Op : I.operands())
+ if ((isa<Constant>(*Op) && !isa<GlobalValue>(*Op)) ||
+ isa<InlineAsm>(*Op))
+ orderValue(Op, OM);
+ orderValue(&I, OM);
+ }
+ }
+ }
+ return OM;
+}
+
+static void predictValueUseListOrderImpl(const Value *V, const Function *F,
+ unsigned ID, const OrderMap &OM,
+ UseListOrderStack &Stack) {
+ // Predict use-list order for this one.
+ typedef std::pair<const Use *, unsigned> Entry;
+ SmallVector<Entry, 64> List;
+ for (const Use &U : V->uses())
+ // Check if this user will be serialized.
+ if (OM.lookup(U.getUser()).first)
+ List.push_back(std::make_pair(&U, List.size()));
+
+ if (List.size() < 2)
+ // We may have lost some users.
+ return;
+
+ bool GetsReversed =
+ !isa<GlobalVariable>(V) && !isa<Function>(V) && !isa<BasicBlock>(V);
+ if (auto *BA = dyn_cast<BlockAddress>(V))
+ ID = OM.lookup(BA->getBasicBlock()).first;
+ std::sort(List.begin(), List.end(), [&](const Entry &L, const Entry &R) {
+ const Use *LU = L.first;
+ const Use *RU = R.first;
+ if (LU == RU)
+ return false;
+
+ auto LID = OM.lookup(LU->getUser()).first;
+ auto RID = OM.lookup(RU->getUser()).first;
+
+ // If ID is 4, then expect: 7 6 5 1 2 3.
+ if (LID < RID) {
+ if (GetsReversed)
+ if (RID <= ID)
+ return true;
+ return false;
+ }
+ if (RID < LID) {
+ if (GetsReversed)
+ if (LID <= ID)
+ return false;
+ return true;
+ }
+
+ // LID and RID are equal, so we have different operands of the same user.
+ // Assume operands are added in order for all instructions.
+ if (GetsReversed)
+ if (LID <= ID)
+ return LU->getOperandNo() < RU->getOperandNo();
+ return LU->getOperandNo() > RU->getOperandNo();
+ });
+
+ if (std::is_sorted(
+ List.begin(), List.end(),
+ [](const Entry &L, const Entry &R) { return L.second < R.second; }))
+ // Order is already correct.
+ return;
+
+ // Store the shuffle.
+ Stack.emplace_back(V, F, List.size());
+ assert(List.size() == Stack.back().Shuffle.size() && "Wrong size");
+ for (size_t I = 0, E = List.size(); I != E; ++I)
+ Stack.back().Shuffle[I] = List[I].second;
+}
+
+static void predictValueUseListOrder(const Value *V, const Function *F,
+ OrderMap &OM, UseListOrderStack &Stack) {
+ auto &IDPair = OM[V];
+ assert(IDPair.first && "Unmapped value");
+ if (IDPair.second)
+ // Already predicted.
+ return;
+
+ // Do the actual prediction.
+ IDPair.second = true;
+ if (!V->use_empty() && std::next(V->use_begin()) != V->use_end())
+ predictValueUseListOrderImpl(V, F, IDPair.first, OM, Stack);
+
+ // Recursive descent into constants.
+ if (const Constant *C = dyn_cast<Constant>(V))
+ if (C->getNumOperands()) // Visit GlobalValues.
+ for (const Value *Op : C->operands())
+ if (isa<Constant>(Op)) // Visit GlobalValues.
+ predictValueUseListOrder(Op, F, OM, Stack);
+}
+
+static UseListOrderStack predictUseListOrder(const Module *M) {
+ OrderMap OM = orderModule(M);
+
+ // Use-list orders need to be serialized after all the users have been added
+ // to a value, or else the shuffles will be incomplete. Store them per
+ // function in a stack.
+ //
+ // Aside from function order, the order of values doesn't matter much here.
+ UseListOrderStack Stack;
+
+ // We want to visit the functions backward now so we can list function-local
+ // constants in the last Function they're used in. Module-level constants
+ // have already been visited above.
+ for (auto I = M->rbegin(), E = M->rend(); I != E; ++I) {
+ const Function &F = *I;
+ if (F.isDeclaration())
+ continue;
+ for (const BasicBlock &BB : F)
+ predictValueUseListOrder(&BB, &F, OM, Stack);
+ for (const Argument &A : F.args())
+ predictValueUseListOrder(&A, &F, OM, Stack);
+ for (const BasicBlock &BB : F)
+ for (const Instruction &I : BB)
+ for (const Value *Op : I.operands())
+ if (isa<Constant>(*Op) || isa<InlineAsm>(*Op)) // Visit GlobalValues.
+ predictValueUseListOrder(Op, &F, OM, Stack);
+ for (const BasicBlock &BB : F)
+ for (const Instruction &I : BB)
+ predictValueUseListOrder(&I, &F, OM, Stack);
+ }
+
+ // Visit globals last.
+ for (const GlobalVariable &G : M->globals())
+ predictValueUseListOrder(&G, nullptr, OM, Stack);
+ for (const Function &F : *M)
+ predictValueUseListOrder(&F, nullptr, OM, Stack);
+ for (const GlobalAlias &A : M->aliases())
+ predictValueUseListOrder(&A, nullptr, OM, Stack);
+ for (const GlobalVariable &G : M->globals())
+ if (G.hasInitializer())
+ predictValueUseListOrder(G.getInitializer(), nullptr, OM, Stack);
+ for (const GlobalAlias &A : M->aliases())
+ predictValueUseListOrder(A.getAliasee(), nullptr, OM, Stack);
+ for (const Function &F : *M)
+ if (F.hasPrefixData())
+ predictValueUseListOrder(F.getPrefixData(), nullptr, OM, Stack);
+
+ return Stack;
+}
+
static const Module *getModuleFromVal(const Value *V) {
if (const Argument *MA = dyn_cast<Argument>(V))
return MA->getParent() ? MA->getParent()->getParent() : nullptr;
@@ -78,6 +285,7 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
case CallingConv::X86_StdCall: Out << "x86_stdcallcc"; break;
case CallingConv::X86_FastCall: Out << "x86_fastcallcc"; break;
case CallingConv::X86_ThisCall: Out << "x86_thiscallcc"; break;
+ case CallingConv::X86_VectorCall:Out << "x86_vectorcallcc"; break;
case CallingConv::Intel_OCL_BI: Out << "intel_ocl_bicc"; break;
case CallingConv::ARM_APCS: Out << "arm_apcscc"; break;
case CallingConv::ARM_AAPCS: Out << "arm_aapcscc"; break;
@@ -347,6 +555,8 @@ public:
FunctionProcessed = false;
}
+ const Function *getFunction() const { return TheFunction; }
+
/// After calling incorporateFunction, use this method to remove the
/// most recently incorporated function from the SlotTracker. This
/// will reset the state of the machine back to just the module contents.
@@ -508,7 +718,7 @@ void SlotTracker::processFunction() {
ST_DEBUG("Inserting Instructions:\n");
- SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst;
+ SmallVector<std::pair<unsigned, MDNode *>, 4> MDForInst;
// Add all of the basic blocks and instructions with no names.
for (Function::const_iterator BB = TheFunction->begin(),
@@ -1279,6 +1489,9 @@ void AssemblyWriter::writeParamOperand(const Value *Operand,
void AssemblyWriter::printModule(const Module *M) {
Machine.initialize();
+ if (shouldPreserveAssemblyUseListOrder())
+ UseListOrders = predictUseListOrder(M);
+
if (!M->getModuleIdentifier().empty() &&
// Don't print the ID if it will start a new line (which would
// require a comment char before it).
@@ -1339,9 +1552,13 @@ void AssemblyWriter::printModule(const Module *M) {
I != E; ++I)
printAlias(I);
+ // Output global use-lists.
+ printUseLists(nullptr);
+
// Output all of the functions.
for (Module::const_iterator I = M->begin(), E = M->end(); I != E; ++I)
printFunction(I);
+ assert(UseListOrders.empty() && "All use-lists should have been consumed");
// Output all attribute groups.
if (!Machine.as_empty()) {
@@ -1509,6 +1726,7 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) {
PrintLLVMName(Out, GA);
Out << " = ";
}
+ PrintLinkage(GA->getLinkage(), Out);
PrintVisibility(GA->getVisibility(), Out);
PrintDLLStorageClass(GA->getDLLStorageClass(), Out);
PrintThreadLocalModel(GA->getThreadLocalMode(), Out);
@@ -1517,8 +1735,6 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) {
Out << "alias ";
- PrintLinkage(GA->getLinkage(), Out);
-
const Constant *Aliasee = GA->getAliasee();
if (!Aliasee) {
@@ -1693,6 +1909,9 @@ void AssemblyWriter::printFunction(const Function *F) {
for (Function::const_iterator I = F->begin(), E = F->end(); I != E; ++I)
printBasicBlock(I);
+ // Output the function's use-lists.
+ printUseLists(F);
+
Out << "}\n";
}
@@ -1956,6 +2175,14 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
Out << ", ";
writeParamOperand(CI->getArgOperand(op), PAL, op + 1);
}
+
+ // Emit an ellipsis if this is a musttail call in a vararg function. This
+ // is only to aid readability, musttail calls forward varargs by default.
+ if (CI->isMustTailCall() && CI->getParent() &&
+ CI->getParent()->getParent() &&
+ CI->getParent()->getParent()->isVarArg())
+ Out << ", ...";
+
Out << ')';
if (PAL.hasAttributes(AttributeSet::FunctionIndex))
Out << " #" << Machine.getAttributeGroupSlot(PAL.getFnAttributes());
@@ -2088,7 +2315,7 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
}
// Print Metadata info.
- SmallVector<std::pair<unsigned, MDNode*>, 4> InstMD;
+ SmallVector<std::pair<unsigned, MDNode *>, 4> InstMD;
I.getAllMetadata(InstMD);
if (!InstMD.empty()) {
SmallVector<StringRef, 8> MDNames;
@@ -2114,7 +2341,7 @@ static void WriteMDNodeComment(const MDNode *Node,
return;
Value *Op = Node->getOperand(0);
- if (!Op || !isa<ConstantInt>(Op) || cast<ConstantInt>(Op)->getBitWidth() < 32)
+ if (!Op || !isa<MDString>(Op))
return;
DIDescriptor Desc(Node);
@@ -2170,6 +2397,45 @@ void AssemblyWriter::writeAllAttributeGroups() {
} // namespace llvm
+void AssemblyWriter::printUseListOrder(const UseListOrder &Order) {
+ bool IsInFunction = Machine.getFunction();
+ if (IsInFunction)
+ Out << " ";
+
+ Out << "uselistorder";
+ if (const BasicBlock *BB =
+ IsInFunction ? nullptr : dyn_cast<BasicBlock>(Order.V)) {
+ Out << "_bb ";
+ writeOperand(BB->getParent(), false);
+ Out << ", ";
+ writeOperand(BB, false);
+ } else {
+ Out << " ";
+ writeOperand(Order.V, true);
+ }
+ Out << ", { ";
+
+ assert(Order.Shuffle.size() >= 2 && "Shuffle too small");
+ Out << Order.Shuffle[0];
+ for (unsigned I = 1, E = Order.Shuffle.size(); I != E; ++I)
+ Out << ", " << Order.Shuffle[I];
+ Out << " }\n";
+}
+
+void AssemblyWriter::printUseLists(const Function *F) {
+ auto hasMore =
+ [&]() { return !UseListOrders.empty() && UseListOrders.back().F == F; };
+ if (!hasMore())
+ // Nothing to do.
+ return;
+
+ Out << "\n; uselistorder directives\n";
+ while (hasMore()) {
+ printUseListOrder(UseListOrders.back());
+ UseListOrders.pop_back();
+ }
+}
+
//===----------------------------------------------------------------------===//
// External Interface declarations
//===----------------------------------------------------------------------===//
@@ -2291,7 +2557,7 @@ void Value::printAsOperand(raw_ostream &O, bool PrintType, const Module *M) cons
void Value::dump() const { print(dbgs()); dbgs() << '\n'; }
// Type::dump - allow easy printing of Types from the debugger.
-void Type::dump() const { print(dbgs()); }
+void Type::dump() const { print(dbgs()); dbgs() << '\n'; }
// Module::dump() - Allow printing of Modules from the debugger.
void Module::dump() const { print(dbgs(), nullptr); }
diff --git a/lib/IR/AsmWriter.h b/lib/IR/AsmWriter.h
index aef9c8a3e9..60da5ad335 100644
--- a/lib/IR/AsmWriter.h
+++ b/lib/IR/AsmWriter.h
@@ -12,14 +12,15 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_IR_ASSEMBLYWRITER_H
-#define LLVM_IR_ASSEMBLYWRITER_H
+#ifndef LLVM_LIB_IR_ASMWRITER_H
+#define LLVM_LIB_IR_ASMWRITER_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/TypeFinder.h"
+#include "llvm/IR/UseListOrder.h"
#include "llvm/Support/FormattedStream.h"
namespace llvm {
@@ -73,6 +74,7 @@ private:
TypePrinting TypePrinter;
AssemblyAnnotationWriter *AnnotationWriter;
SetVector<const Comdat *> Comdats;
+ UseListOrderStack UseListOrders;
public:
/// Construct an AssemblyWriter with an external SlotTracker
@@ -111,6 +113,9 @@ public:
void printInstructionLine(const Instruction &I);
void printInstruction(const Instruction &I);
+ void printUseListOrder(const UseListOrder &Order);
+ void printUseLists(const Function *F);
+
private:
void init();
@@ -121,4 +126,4 @@ private:
} // namespace llvm
-#endif //LLVM_IR_ASMWRITER_H
+#endif
diff --git a/lib/IR/AttributeImpl.h b/lib/IR/AttributeImpl.h
index 9f3fd3e606..0448dc1740 100644
--- a/lib/IR/AttributeImpl.h
+++ b/lib/IR/AttributeImpl.h
@@ -13,8 +13,8 @@
///
//===----------------------------------------------------------------------===//
-#ifndef LLVM_ATTRIBUTESIMPL_H
-#define LLVM_ATTRIBUTESIMPL_H
+#ifndef LLVM_LIB_IR_ATTRIBUTEIMPL_H
+#define LLVM_LIB_IR_ATTRIBUTEIMPL_H
#include "llvm/ADT/FoldingSet.h"
#include "llvm/IR/Attributes.h"
@@ -39,7 +39,7 @@ class AttributeImpl : public FoldingSetNode {
protected:
enum AttrEntryKind {
EnumAttrEntry,
- AlignAttrEntry,
+ IntAttrEntry,
StringAttrEntry
};
@@ -49,7 +49,7 @@ public:
virtual ~AttributeImpl();
bool isEnumAttribute() const { return KindID == EnumAttrEntry; }
- bool isAlignAttribute() const { return KindID == AlignAttrEntry; }
+ bool isIntAttribute() const { return KindID == IntAttrEntry; }
bool isStringAttribute() const { return KindID == StringAttrEntry; }
bool hasAttribute(Attribute::AttrKind A) const;
@@ -67,7 +67,7 @@ public:
void Profile(FoldingSetNodeID &ID) const {
if (isEnumAttribute())
Profile(ID, getKindAsEnum(), 0);
- else if (isAlignAttribute())
+ else if (isIntAttribute())
Profile(ID, getKindAsEnum(), getValueAsInt());
else
Profile(ID, getKindAsString(), getValueAsString());
@@ -108,19 +108,20 @@ public:
Attribute::AttrKind getEnumKind() const { return Kind; }
};
-class AlignAttributeImpl : public EnumAttributeImpl {
+class IntAttributeImpl : public EnumAttributeImpl {
void anchor() override;
- unsigned Align;
+ uint64_t Val;
public:
- AlignAttributeImpl(Attribute::AttrKind Kind, unsigned Align)
- : EnumAttributeImpl(AlignAttrEntry, Kind), Align(Align) {
+ IntAttributeImpl(Attribute::AttrKind Kind, uint64_t Val)
+ : EnumAttributeImpl(IntAttrEntry, Kind), Val(Val) {
assert(
- (Kind == Attribute::Alignment || Kind == Attribute::StackAlignment) &&
- "Wrong kind for alignment attribute!");
+ (Kind == Attribute::Alignment || Kind == Attribute::StackAlignment ||
+ Kind == Attribute::Dereferenceable) &&
+ "Wrong kind for int attribute!");
}
- unsigned getAlignment() const { return Align; }
+ uint64_t getValue() const { return Val; }
};
class StringAttributeImpl : public AttributeImpl {
@@ -164,6 +165,7 @@ public:
unsigned getAlignment() const;
unsigned getStackAlignment() const;
+ uint64_t getDereferenceableBytes() const;
std::string getAsString(bool InAttrGrp) const;
typedef const Attribute *iterator;
diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp
index 48a2ce858a..04545ea919 100644
--- a/lib/IR/Attributes.cpp
+++ b/lib/IR/Attributes.cpp
@@ -47,7 +47,7 @@ Attribute Attribute::get(LLVMContext &Context, Attribute::AttrKind Kind,
if (!Val)
PA = new EnumAttributeImpl(Kind);
else
- PA = new AlignAttributeImpl(Kind, Val);
+ PA = new IntAttributeImpl(Kind, Val);
pImpl->AttrsSet.InsertNode(PA, InsertPoint);
}
@@ -88,6 +88,12 @@ Attribute Attribute::getWithStackAlignment(LLVMContext &Context,
return get(Context, StackAlignment, Align);
}
+Attribute Attribute::getWithDereferenceableBytes(LLVMContext &Context,
+ uint64_t Bytes) {
+ assert(Bytes && "Bytes must be non-zero.");
+ return get(Context, Dereferenceable, Bytes);
+}
+
//===----------------------------------------------------------------------===//
// Attribute Accessor Methods
//===----------------------------------------------------------------------===//
@@ -96,8 +102,8 @@ bool Attribute::isEnumAttribute() const {
return pImpl && pImpl->isEnumAttribute();
}
-bool Attribute::isAlignAttribute() const {
- return pImpl && pImpl->isAlignAttribute();
+bool Attribute::isIntAttribute() const {
+ return pImpl && pImpl->isIntAttribute();
}
bool Attribute::isStringAttribute() const {
@@ -106,15 +112,15 @@ bool Attribute::isStringAttribute() const {
Attribute::AttrKind Attribute::getKindAsEnum() const {
if (!pImpl) return None;
- assert((isEnumAttribute() || isAlignAttribute()) &&
+ assert((isEnumAttribute() || isIntAttribute()) &&
"Invalid attribute type to get the kind as an enum!");
return pImpl ? pImpl->getKindAsEnum() : None;
}
uint64_t Attribute::getValueAsInt() const {
if (!pImpl) return 0;
- assert(isAlignAttribute() &&
- "Expected the attribute to be an alignment attribute!");
+ assert(isIntAttribute() &&
+ "Expected the attribute to be an integer attribute!");
return pImpl ? pImpl->getValueAsInt() : 0;
}
@@ -156,6 +162,14 @@ unsigned Attribute::getStackAlignment() const {
return pImpl->getValueAsInt();
}
+/// This returns the number of dereferenceable bytes.
+uint64_t Attribute::getDereferenceableBytes() const {
+ assert(hasAttribute(Attribute::Dereferenceable) &&
+ "Trying to get dereferenceable bytes from "
+ "non-dereferenceable attribute!");
+ return pImpl->getValueAsInt();
+}
+
std::string Attribute::getAsString(bool InAttrGrp) const {
if (!pImpl) return "";
@@ -263,6 +277,20 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return Result;
}
+ if (hasAttribute(Attribute::Dereferenceable)) {
+ std::string Result;
+ Result += "dereferenceable";
+ if (InAttrGrp) {
+ Result += "=";
+ Result += utostr(getValueAsInt());
+ } else {
+ Result += "(";
+ Result += utostr(getValueAsInt());
+ Result += ")";
+ }
+ return Result;
+ }
+
// Convert target-dependent attributes to strings of the form:
//
// "kind"
@@ -296,7 +324,7 @@ bool Attribute::operator<(Attribute A) const {
// Pin the vtables to this file.
AttributeImpl::~AttributeImpl() {}
void EnumAttributeImpl::anchor() {}
-void AlignAttributeImpl::anchor() {}
+void IntAttributeImpl::anchor() {}
void StringAttributeImpl::anchor() {}
bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
@@ -310,13 +338,13 @@ bool AttributeImpl::hasAttribute(StringRef Kind) const {
}
Attribute::AttrKind AttributeImpl::getKindAsEnum() const {
- assert(isEnumAttribute() || isAlignAttribute());
+ assert(isEnumAttribute() || isIntAttribute());
return static_cast<const EnumAttributeImpl *>(this)->getEnumKind();
}
uint64_t AttributeImpl::getValueAsInt() const {
- assert(isAlignAttribute());
- return static_cast<const AlignAttributeImpl *>(this)->getAlignment();
+ assert(isIntAttribute());
+ return static_cast<const IntAttributeImpl *>(this)->getValue();
}
StringRef AttributeImpl::getKindAsString() const {
@@ -334,18 +362,18 @@ bool AttributeImpl::operator<(const AttributeImpl &AI) const {
// relative to their enum value) and then strings.
if (isEnumAttribute()) {
if (AI.isEnumAttribute()) return getKindAsEnum() < AI.getKindAsEnum();
- if (AI.isAlignAttribute()) return true;
+ if (AI.isIntAttribute()) return true;
if (AI.isStringAttribute()) return true;
}
- if (isAlignAttribute()) {
+ if (isIntAttribute()) {
if (AI.isEnumAttribute()) return false;
- if (AI.isAlignAttribute()) return getValueAsInt() < AI.getValueAsInt();
+ if (AI.isIntAttribute()) return getValueAsInt() < AI.getValueAsInt();
if (AI.isStringAttribute()) return true;
}
if (AI.isEnumAttribute()) return false;
- if (AI.isAlignAttribute()) return false;
+ if (AI.isIntAttribute()) return false;
if (getKindAsString() == AI.getKindAsString())
return getValueAsString() < AI.getValueAsString();
return getKindAsString() < AI.getKindAsString();
@@ -398,6 +426,8 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {
case Attribute::InAlloca: return 1ULL << 43;
case Attribute::NonNull: return 1ULL << 44;
case Attribute::JumpTable: return 1ULL << 45;
+ case Attribute::Dereferenceable:
+ llvm_unreachable("dereferenceable attribute not supported in raw format");
}
llvm_unreachable("Unsupported attribute type");
}
@@ -482,6 +512,13 @@ unsigned AttributeSetNode::getStackAlignment() const {
return 0;
}
+uint64_t AttributeSetNode::getDereferenceableBytes() const {
+ for (iterator I = begin(), E = end(); I != E; ++I)
+ if (I->hasAttribute(Attribute::Dereferenceable))
+ return I->getDereferenceableBytes();
+ return 0;
+}
+
std::string AttributeSetNode::getAsString(bool InAttrGrp) const {
std::string Str;
for (iterator I = begin(), E = end(); I != E; ++I) {
@@ -515,6 +552,8 @@ uint64_t AttributeSetImpl::Raw(unsigned Index) const {
Mask |= (Log2_32(ASN->getAlignment()) + 1) << 16;
else if (Kind == Attribute::StackAlignment)
Mask |= (Log2_32(ASN->getStackAlignment()) + 1) << 26;
+ else if (Kind == Attribute::Dereferenceable)
+ llvm_unreachable("dereferenceable not supported in bit mask");
else
Mask |= AttributeImpl::getAttrMask(Kind);
}
@@ -620,6 +659,10 @@ AttributeSet AttributeSet::get(LLVMContext &C, unsigned Index,
else if (Kind == Attribute::StackAlignment)
Attrs.push_back(std::make_pair(Index, Attribute::
getWithStackAlignment(C, B.getStackAlignment())));
+ else if (Kind == Attribute::Dereferenceable)
+ Attrs.push_back(std::make_pair(Index,
+ Attribute::getWithDereferenceableBytes(C,
+ B.getDereferenceableBytes())));
else
Attrs.push_back(std::make_pair(Index, Attribute::get(C, Kind)));
}
@@ -877,6 +920,11 @@ unsigned AttributeSet::getStackAlignment(unsigned Index) const {
return ASN ? ASN->getStackAlignment() : 0;
}
+uint64_t AttributeSet::getDereferenceableBytes(unsigned Index) const {
+ AttributeSetNode *ASN = getAttributes(Index);
+ return ASN ? ASN->getDereferenceableBytes() : 0;
+}
+
std::string AttributeSet::getAsString(unsigned Index,
bool InAttrGrp) const {
AttributeSetNode *ASN = getAttributes(Index);
@@ -956,7 +1004,7 @@ void AttributeSet::dump() const {
//===----------------------------------------------------------------------===//
AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Index)
- : Attrs(0), Alignment(0), StackAlignment(0) {
+ : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) {
AttributeSetImpl *pImpl = AS.pImpl;
if (!pImpl) return;
@@ -973,13 +1021,14 @@ AttrBuilder::AttrBuilder(AttributeSet AS, unsigned Index)
void AttrBuilder::clear() {
Attrs.reset();
- Alignment = StackAlignment = 0;
+ Alignment = StackAlignment = DerefBytes = 0;
}
AttrBuilder &AttrBuilder::addAttribute(Attribute::AttrKind Val) {
assert((unsigned)Val < Attribute::EndAttrKinds && "Attribute out of range!");
assert(Val != Attribute::Alignment && Val != Attribute::StackAlignment &&
- "Adding alignment attribute without adding alignment value!");
+ Val != Attribute::Dereferenceable &&
+ "Adding integer attribute without adding a value!");
Attrs[Val] = true;
return *this;
}
@@ -997,6 +1046,8 @@ AttrBuilder &AttrBuilder::addAttribute(Attribute Attr) {
Alignment = Attr.getAlignment();
else if (Kind == Attribute::StackAlignment)
StackAlignment = Attr.getStackAlignment();
+ else if (Kind == Attribute::Dereferenceable)
+ DerefBytes = Attr.getDereferenceableBytes();
return *this;
}
@@ -1013,6 +1064,8 @@ AttrBuilder &AttrBuilder::removeAttribute(Attribute::AttrKind Val) {
Alignment = 0;
else if (Val == Attribute::StackAlignment)
StackAlignment = 0;
+ else if (Val == Attribute::Dereferenceable)
+ DerefBytes = 0;
return *this;
}
@@ -1029,7 +1082,7 @@ AttrBuilder &AttrBuilder::removeAttributes(AttributeSet A, uint64_t Index) {
for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot); I != E; ++I) {
Attribute Attr = *I;
- if (Attr.isEnumAttribute() || Attr.isAlignAttribute()) {
+ if (Attr.isEnumAttribute() || Attr.isIntAttribute()) {
Attribute::AttrKind Kind = I->getKindAsEnum();
Attrs[Kind] = false;
@@ -1037,6 +1090,8 @@ AttrBuilder &AttrBuilder::removeAttributes(AttributeSet A, uint64_t Index) {
Alignment = 0;
else if (Kind == Attribute::StackAlignment)
StackAlignment = 0;
+ else if (Kind == Attribute::Dereferenceable)
+ DerefBytes = 0;
} else {
assert(Attr.isStringAttribute() && "Invalid attribute type!");
std::map<std::string, std::string>::iterator
@@ -1079,6 +1134,14 @@ AttrBuilder &AttrBuilder::addStackAlignmentAttr(unsigned Align) {
return *this;
}
+AttrBuilder &AttrBuilder::addDereferenceableAttr(uint64_t Bytes) {
+ if (Bytes == 0) return *this;
+
+ Attrs[Attribute::Dereferenceable] = true;
+ DerefBytes = Bytes;
+ return *this;
+}
+
AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
// FIXME: What if both have alignments, but they don't match?!
if (!Alignment)
@@ -1087,6 +1150,9 @@ AttrBuilder &AttrBuilder::merge(const AttrBuilder &B) {
if (!StackAlignment)
StackAlignment = B.StackAlignment;
+ if (!DerefBytes)
+ DerefBytes = B.DerefBytes;
+
Attrs |= B.Attrs;
for (td_const_iterator I = B.TargetDepAttrs.begin(),
@@ -1117,7 +1183,7 @@ bool AttrBuilder::hasAttributes(AttributeSet A, uint64_t Index) const {
for (AttributeSet::iterator I = A.begin(Slot), E = A.end(Slot);
I != E; ++I) {
Attribute Attr = *I;
- if (Attr.isEnumAttribute() || Attr.isAlignAttribute()) {
+ if (Attr.isEnumAttribute() || Attr.isIntAttribute()) {
if (Attrs[I->getKindAsEnum()])
return true;
} else {
@@ -1142,7 +1208,8 @@ bool AttrBuilder::operator==(const AttrBuilder &B) {
if (B.TargetDepAttrs.find(I->first) == B.TargetDepAttrs.end())
return false;
- return Alignment == B.Alignment && StackAlignment == B.StackAlignment;
+ return Alignment == B.Alignment && StackAlignment == B.StackAlignment &&
+ DerefBytes == B.DerefBytes;
}
AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) {
@@ -1151,6 +1218,8 @@ AttrBuilder &AttrBuilder::addRawValue(uint64_t Val) {
for (Attribute::AttrKind I = Attribute::None; I != Attribute::EndAttrKinds;
I = Attribute::AttrKind(I + 1)) {
+ if (I == Attribute::Dereferenceable)
+ continue;
if (uint64_t A = (Val & AttributeImpl::getAttrMask(I))) {
Attrs[I] = true;
@@ -1184,6 +1253,7 @@ AttributeSet AttributeFuncs::typeIncompatible(Type *Ty, uint64_t Index) {
.addAttribute(Attribute::NoAlias)
.addAttribute(Attribute::NoCapture)
.addAttribute(Attribute::NonNull)
+ .addDereferenceableAttr(1) // the int here is ignored
.addAttribute(Attribute::ReadNone)
.addAttribute(Attribute::ReadOnly)
.addAttribute(Attribute::StructRet)
diff --git a/lib/IR/AutoUpgrade.cpp b/lib/IR/AutoUpgrade.cpp
index 6554b3c5da..c24dfead43 100644
--- a/lib/IR/AutoUpgrade.cpp
+++ b/lib/IR/AutoUpgrade.cpp
@@ -17,6 +17,7 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instruction.h"
@@ -43,6 +44,22 @@ static bool UpgradeSSE41Function(Function* F, Intrinsic::ID IID,
return true;
}
+// Upgrade the declarations of intrinsic functions whose 8-bit immediate mask
+// arguments have changed their type from i32 to i8.
+static bool UpgradeX86IntrinsicsWith8BitMask(Function *F, Intrinsic::ID IID,
+ Function *&NewFn) {
+ // Check that the last argument is an i32.
+ Type *LastArgType = F->getFunctionType()->getParamType(
+ F->getFunctionType()->getNumParams() - 1);
+ if (!LastArgType->isIntegerTy(32))
+ return false;
+
+ // Move this function aside and map down.
+ F->setName(F->getName() + ".old");
+ NewFn = Intrinsic::getDeclaration(F->getParent(), IID);
+ return true;
+}
+
static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
assert(F && "Illegal to upgrade a non-existent Function.");
@@ -90,6 +107,20 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
}
break;
}
+ case 'd': {
+ if (Name.startswith("dbg.declare") && F->arg_size() == 2) {
+ F->setName(Name + ".old");
+ NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::dbg_declare);
+ return true;
+ }
+ if (Name.startswith("dbg.value") && F->arg_size() == 3) {
+ F->setName(Name + ".old");
+ NewFn = Intrinsic::getDeclaration(F->getParent(), Intrinsic::dbg_value);
+ return true;
+ }
+ break;
+ }
+
case 'o':
// We only need to change the name to match the mangling including the
// address space.
@@ -130,6 +161,51 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
if (Name == "x86.sse41.ptestnzc")
return UpgradeSSE41Function(F, Intrinsic::x86_sse41_ptestnzc, NewFn);
}
+ // Several blend and other instructions with maskes used the wrong number of
+ // bits.
+ if (Name == "x86.sse41.pblendw")
+ return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_pblendw,
+ NewFn);
+ if (Name == "x86.sse41.blendpd")
+ return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_blendpd,
+ NewFn);
+ if (Name == "x86.sse41.blendps")
+ return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_blendps,
+ NewFn);
+ if (Name == "x86.sse41.insertps")
+ return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_insertps,
+ NewFn);
+ if (Name == "x86.sse41.dppd")
+ return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_dppd,
+ NewFn);
+ if (Name == "x86.sse41.dpps")
+ return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_dpps,
+ NewFn);
+ if (Name == "x86.sse41.mpsadbw")
+ return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_sse41_mpsadbw,
+ NewFn);
+ if (Name == "x86.avx.blend.pd.256")
+ return UpgradeX86IntrinsicsWith8BitMask(
+ F, Intrinsic::x86_avx_blend_pd_256, NewFn);
+ if (Name == "x86.avx.blend.ps.256")
+ return UpgradeX86IntrinsicsWith8BitMask(
+ F, Intrinsic::x86_avx_blend_ps_256, NewFn);
+ if (Name == "x86.avx.dp.ps.256")
+ return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_avx_dp_ps_256,
+ NewFn);
+ if (Name == "x86.avx2.pblendw")
+ return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_avx2_pblendw,
+ NewFn);
+ if (Name == "x86.avx2.pblendd.128")
+ return UpgradeX86IntrinsicsWith8BitMask(
+ F, Intrinsic::x86_avx2_pblendd_128, NewFn);
+ if (Name == "x86.avx2.pblendd.256")
+ return UpgradeX86IntrinsicsWith8BitMask(
+ F, Intrinsic::x86_avx2_pblendd_256, NewFn);
+ if (Name == "x86.avx2.mpsadbw")
+ return UpgradeX86IntrinsicsWith8BitMask(F, Intrinsic::x86_avx2_mpsadbw,
+ NewFn);
+
// frcz.ss/sd may need to have an argument dropped
if (Name.startswith("x86.xop.vfrcz.ss") && F->arg_size() == 2) {
F->setName(Name + ".old");
@@ -173,66 +249,27 @@ bool llvm::UpgradeIntrinsicFunction(Function *F, Function *&NewFn) {
return Upgraded;
}
-static bool UpgradeGlobalStructors(GlobalVariable *GV) {
- ArrayType *ATy = dyn_cast<ArrayType>(GV->getType()->getElementType());
- StructType *OldTy =
- ATy ? dyn_cast<StructType>(ATy->getElementType()) : nullptr;
-
- // Only upgrade an array of a two field struct with the appropriate field
- // types.
- if (!OldTy || OldTy->getNumElements() != 2)
- return false;
-
- // Get the upgraded 3 element type.
- PointerType *VoidPtrTy = Type::getInt8Ty(GV->getContext())->getPointerTo();
- Type *Tys[3] = {
- OldTy->getElementType(0),
- OldTy->getElementType(1),
- VoidPtrTy
- };
- StructType *NewTy =
- StructType::get(GV->getContext(), Tys, /*isPacked=*/false);
-
- // Build new constants with a null third field filled in.
- Constant *OldInitC = GV->getInitializer();
- ConstantArray *OldInit = dyn_cast<ConstantArray>(OldInitC);
- if (!OldInit && !isa<ConstantAggregateZero>(OldInitC))
- return false;
- std::vector<Constant *> Initializers;
- if (OldInit) {
- for (Use &U : OldInit->operands()) {
- ConstantStruct *Init = cast<ConstantStruct>(&U);
- Constant *NewInit =
- ConstantStruct::get(NewTy, Init->getOperand(0), Init->getOperand(1),
- Constant::getNullValue(VoidPtrTy), nullptr);
- Initializers.push_back(NewInit);
- }
- }
- assert(Initializers.size() == ATy->getNumElements());
-
- // Replace the old GV with a new one.
- ATy = ArrayType::get(NewTy, Initializers.size());
- Constant *NewInit = ConstantArray::get(ATy, Initializers);
- GlobalVariable *NewGV = new GlobalVariable(
- *GV->getParent(), ATy, GV->isConstant(), GV->getLinkage(), NewInit, "",
- GV, GV->getThreadLocalMode(), GV->getType()->getAddressSpace(),
- GV->isExternallyInitialized());
- NewGV->copyAttributesFrom(GV);
- NewGV->takeName(GV);
- assert(GV->use_empty() && "program cannot use initializer list");
- GV->eraseFromParent();
- return true;
-}
-
bool llvm::UpgradeGlobalVariable(GlobalVariable *GV) {
- if (GV->getName() == "llvm.global_ctors" ||
- GV->getName() == "llvm.global_dtors")
- return UpgradeGlobalStructors(GV);
-
// Nothing to do yet.
return false;
}
+static MDNode *getNodeField(const MDNode *DbgNode, unsigned Elt) {
+ if (!DbgNode || Elt >= DbgNode->getNumOperands())
+ return nullptr;
+ return dyn_cast_or_null<MDNode>(DbgNode->getOperand(Elt));
+}
+
+static DIExpression getExpression(Value *VarOperand, Function *F) {
+ // Old-style DIVariables have an optional expression as the 8th element.
+ DIExpression Expr(getNodeField(cast<MDNode>(VarOperand), 8));
+ if (!Expr) {
+ DIBuilder DIB(*F->getParent());
+ Expr = DIB.createExpression();
+ }
+ return Expr;
+}
+
// UpgradeIntrinsicCall - Upgrade a call to an old intrinsic to be a call the
// upgraded intrinsic. All argument and return casting must be provided in
// order to seamlessly integrate with existing context.
@@ -396,12 +433,32 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
}
std::string Name = CI->getName().str();
- CI->setName(Name + ".old");
+ if (!Name.empty())
+ CI->setName(Name + ".old");
switch (NewFn->getIntrinsicID()) {
default:
llvm_unreachable("Unknown function for CallInst upgrade.");
+ // Upgrade debug intrinsics to use an additional DIExpression argument.
+ case Intrinsic::dbg_declare: {
+ auto NewCI =
+ Builder.CreateCall3(NewFn, CI->getArgOperand(0), CI->getArgOperand(1),
+ getExpression(CI->getArgOperand(1), F), Name);
+ NewCI->setDebugLoc(CI->getDebugLoc());
+ CI->replaceAllUsesWith(NewCI);
+ CI->eraseFromParent();
+ return;
+ }
+ case Intrinsic::dbg_value: {
+ auto NewCI = Builder.CreateCall4(
+ NewFn, CI->getArgOperand(0), CI->getArgOperand(1), CI->getArgOperand(2),
+ getExpression(CI->getArgOperand(2), F), Name);
+ NewCI->setDebugLoc(CI->getDebugLoc());
+ CI->replaceAllUsesWith(NewCI);
+ CI->eraseFromParent();
+ return;
+ }
case Intrinsic::ctlz:
case Intrinsic::cttz:
assert(CI->getNumArgOperands() == 1 &&
@@ -419,14 +476,6 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
CI->eraseFromParent();
return;
- case Intrinsic::arm_neon_vclz: {
- // Change name from llvm.arm.neon.vclz.* to llvm.ctlz.*
- CI->replaceAllUsesWith(Builder.CreateCall2(NewFn, CI->getArgOperand(0),
- Builder.getFalse(),
- "llvm.ctlz." + Name.substr(14)));
- CI->eraseFromParent();
- return;
- }
case Intrinsic::ctpop: {
CI->replaceAllUsesWith(Builder.CreateCall(NewFn, CI->getArgOperand(0)));
CI->eraseFromParent();
@@ -468,6 +517,34 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
CI->eraseFromParent();
return;
}
+
+ case Intrinsic::x86_sse41_pblendw:
+ case Intrinsic::x86_sse41_blendpd:
+ case Intrinsic::x86_sse41_blendps:
+ case Intrinsic::x86_sse41_insertps:
+ case Intrinsic::x86_sse41_dppd:
+ case Intrinsic::x86_sse41_dpps:
+ case Intrinsic::x86_sse41_mpsadbw:
+ case Intrinsic::x86_avx_blend_pd_256:
+ case Intrinsic::x86_avx_blend_ps_256:
+ case Intrinsic::x86_avx_dp_ps_256:
+ case Intrinsic::x86_avx2_pblendw:
+ case Intrinsic::x86_avx2_pblendd_128:
+ case Intrinsic::x86_avx2_pblendd_256:
+ case Intrinsic::x86_avx2_mpsadbw: {
+ // Need to truncate the last argument from i32 to i8 -- this argument models
+ // an inherently 8-bit immediate operand to these x86 instructions.
+ SmallVector<Value *, 4> Args(CI->arg_operands().begin(),
+ CI->arg_operands().end());
+
+ // Replace the last argument with a trunc.
+ Args.back() = Builder.CreateTrunc(Args.back(), Type::getInt8Ty(C), "trunc");
+
+ CallInst *NewCall = Builder.CreateCall(NewFn, Args);
+ CI->replaceAllUsesWith(NewCall);
+ CI->eraseFromParent();
+ return;
+ }
}
}
@@ -580,7 +657,9 @@ bool llvm::UpgradeDebugInfo(Module &M) {
void llvm::UpgradeMDStringConstant(std::string &String) {
const std::string OldPrefix = "llvm.vectorizer.";
- if (String.find(OldPrefix) == 0) {
- String.replace(0, OldPrefix.size(), "llvm.loop.vectorize.");
+ if (String == "llvm.vectorizer.unroll") {
+ String = "llvm.loop.interleave.count";
+ } else if (String.find(OldPrefix) == 0) {
+ String.replace(0, OldPrefix.size(), "llvm.loop.vectorize.");
}
}
diff --git a/lib/IR/BasicBlock.cpp b/lib/IR/BasicBlock.cpp
index ba07433103..5ed9bed1ba 100644
--- a/lib/IR/BasicBlock.cpp
+++ b/lib/IR/BasicBlock.cpp
@@ -50,17 +50,24 @@ BasicBlock::BasicBlock(LLVMContext &C, const Twine &Name, Function *NewParent,
// Make sure that we get added to a function
LeakDetector::addGarbageObject(this);
- if (InsertBefore) {
- assert(NewParent &&
+ if (NewParent)
+ insertInto(NewParent, InsertBefore);
+ else
+ assert(!InsertBefore &&
"Cannot insert block before another block with no function!");
- NewParent->getBasicBlockList().insert(InsertBefore, this);
- } else if (NewParent) {
- NewParent->getBasicBlockList().push_back(this);
- }
setName(Name);
}
+void BasicBlock::insertInto(Function *NewParent, BasicBlock *InsertBefore) {
+ assert(NewParent && "Expected a parent");
+ assert(!Parent && "Already has a parent");
+
+ if (InsertBefore)
+ NewParent->getBasicBlockList().insert(InsertBefore, this);
+ else
+ NewParent->getBasicBlockList().push_back(this);
+}
BasicBlock::~BasicBlock() {
// If the address of the block is taken and it is being deleted (e.g. because
@@ -131,6 +138,37 @@ const TerminatorInst *BasicBlock::getTerminator() const {
return dyn_cast<TerminatorInst>(&InstList.back());
}
+CallInst *BasicBlock::getTerminatingMustTailCall() {
+ if (InstList.empty())
+ return nullptr;
+ ReturnInst *RI = dyn_cast<ReturnInst>(&InstList.back());
+ if (!RI || RI == &InstList.front())
+ return nullptr;
+
+ Instruction *Prev = RI->getPrevNode();
+ if (!Prev)
+ return nullptr;
+
+ if (Value *RV = RI->getReturnValue()) {
+ if (RV != Prev)
+ return nullptr;
+
+ // Look through the optional bitcast.
+ if (auto *BI = dyn_cast<BitCastInst>(Prev)) {
+ RV = BI->getOperand(0);
+ Prev = BI->getPrevNode();
+ if (!Prev || RV != Prev)
+ return nullptr;
+ }
+ }
+
+ if (auto *CI = dyn_cast<CallInst>(Prev)) {
+ if (CI->isMustTailCall())
+ return CI;
+ }
+ return nullptr;
+}
+
Instruction* BasicBlock::getFirstNonPHI() {
BasicBlock::iterator i = begin();
// All valid basic blocks should have a terminator,
diff --git a/lib/IR/CMakeLists.txt b/lib/IR/CMakeLists.txt
index 38a80b18bd..b3889e6fdf 100644
--- a/lib/IR/CMakeLists.txt
+++ b/lib/IR/CMakeLists.txt
@@ -39,6 +39,7 @@ add_llvm_library(LLVMCore
Type.cpp
TypeFinder.cpp
Use.cpp
+ UseListOrder.cpp
User.cpp
Value.cpp
ValueSymbolTable.cpp
diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp
index 395ac3907b..cdfb41f7dc 100644
--- a/lib/IR/ConstantFold.cpp
+++ b/lib/IR/ConstantFold.cpp
@@ -593,8 +593,13 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
bool ignored;
uint64_t x[2];
uint32_t DestBitWidth = cast<IntegerType>(DestTy)->getBitWidth();
- (void) V.convertToInteger(x, DestBitWidth, opc==Instruction::FPToSI,
- APFloat::rmTowardZero, &ignored);
+ if (APFloat::opInvalidOp ==
+ V.convertToInteger(x, DestBitWidth, opc==Instruction::FPToSI,
+ APFloat::rmTowardZero, &ignored)) {
+ // Undefined behavior invoked - the destination type can't represent
+ // the input constant.
+ return UndefValue::get(DestTy);
+ }
APInt Val(DestBitWidth, x);
return ConstantInt::get(FPC->getContext(), Val);
}
@@ -653,9 +658,13 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
APInt api = CI->getValue();
APFloat apf(DestTy->getFltSemantics(),
APInt::getNullValue(DestTy->getPrimitiveSizeInBits()));
- (void)apf.convertFromAPInt(api,
- opc==Instruction::SIToFP,
- APFloat::rmNearestTiesToEven);
+ if (APFloat::opOverflow &
+ apf.convertFromAPInt(api, opc==Instruction::SIToFP,
+ APFloat::rmNearestTiesToEven)) {
+ // Undefined behavior invoked - the destination type can't represent
+ // the input constant.
+ return UndefValue::get(DestTy);
+ }
return ConstantFP::get(V->getContext(), apf);
}
return nullptr;
@@ -674,6 +683,9 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
}
return nullptr;
case Instruction::Trunc: {
+ if (V->getType()->isVectorTy())
+ return nullptr;
+
uint32_t DestBitWidth = cast<IntegerType>(DestTy)->getBitWidth();
if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) {
return ConstantInt::get(V->getContext(),
@@ -2144,9 +2156,10 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
// If all indices are known integers and normalized, we can do a simple
// check for the "inbounds" property.
- if (!Unknown && !inBounds &&
- isa<GlobalVariable>(C) && isInBoundsIndices(Idxs))
- return ConstantExpr::getInBoundsGetElementPtr(C, Idxs);
+ if (!Unknown && !inBounds)
+ if (auto *GV = dyn_cast<GlobalVariable>(C))
+ if (!GV->hasExternalWeakLinkage() && isInBoundsIndices(Idxs))
+ return ConstantExpr::getInBoundsGetElementPtr(C, Idxs);
return nullptr;
}
diff --git a/lib/IR/ConstantFold.h b/lib/IR/ConstantFold.h
index e12f27a7cb..a516abe024 100644
--- a/lib/IR/ConstantFold.h
+++ b/lib/IR/ConstantFold.h
@@ -16,8 +16,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef CONSTANTFOLDING_H
-#define CONSTANTFOLDING_H
+#ifndef LLVM_LIB_IR_CONSTANTFOLD_H
+#define LLVM_LIB_IR_CONSTANTFOLD_H
#include "llvm/ADT/ArrayRef.h"
diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp
index b815936ac4..e0cb835c2c 100644
--- a/lib/IR/Constants.cpp
+++ b/lib/IR/Constants.cpp
@@ -107,6 +107,28 @@ bool Constant::isAllOnesValue() const {
return false;
}
+bool Constant::isOneValue() const {
+ // Check for 1 integers
+ if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
+ return CI->isOne();
+
+ // Check for FP which are bitcasted from 1 integers
+ if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
+ return CFP->getValueAPF().bitcastToAPInt() == 1;
+
+ // Check for constant vectors which are splats of 1 values.
+ if (const ConstantVector *CV = dyn_cast<ConstantVector>(this))
+ if (Constant *Splat = CV->getSplatValue())
+ return Splat->isOneValue();
+
+ // Check for constant vectors which are splats of 1 values.
+ if (const ConstantDataVector *CV = dyn_cast<ConstantDataVector>(this))
+ if (Constant *Splat = CV->getSplatValue())
+ return Splat->isOneValue();
+
+ return false;
+}
+
bool Constant::isMinSignedValue() const {
// Check for INT_MIN integers
if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
@@ -129,6 +151,29 @@ bool Constant::isMinSignedValue() const {
return false;
}
+bool Constant::isNotMinSignedValue() const {
+ // Check for INT_MIN integers
+ if (const ConstantInt *CI = dyn_cast<ConstantInt>(this))
+ return !CI->isMinValue(/*isSigned=*/true);
+
+ // Check for FP which are bitcasted from INT_MIN integers
+ if (const ConstantFP *CFP = dyn_cast<ConstantFP>(this))
+ return !CFP->getValueAPF().bitcastToAPInt().isMinSignedValue();
+
+ // Check for constant vectors which are splats of INT_MIN values.
+ if (const ConstantVector *CV = dyn_cast<ConstantVector>(this))
+ if (Constant *Splat = CV->getSplatValue())
+ return Splat->isNotMinSignedValue();
+
+ // Check for constant vectors which are splats of INT_MIN values.
+ if (const ConstantDataVector *CV = dyn_cast<ConstantDataVector>(this))
+ if (Constant *Splat = CV->getSplatValue())
+ return Splat->isNotMinSignedValue();
+
+ // It *may* contain INT_MIN, we can't tell.
+ return false;
+}
+
// Constructor to create a '0' constant of arbitrary type...
Constant *Constant::getNullValue(Type *Ty) {
switch (Ty->getTypeID()) {
@@ -261,7 +306,7 @@ void Constant::destroyConstantImpl() {
}
static bool canTrapImpl(const Constant *C,
- SmallPtrSet<const ConstantExpr *, 4> &NonTrappingOps) {
+ SmallPtrSetImpl<const ConstantExpr *> &NonTrappingOps) {
assert(C->getType()->isFirstClassType() && "Cannot evaluate aggregate vals!");
// The only thing that could possibly trap are constant exprs.
const ConstantExpr *CE = dyn_cast<ConstantExpr>(C);
@@ -271,7 +316,7 @@ static bool canTrapImpl(const Constant *C,
// ConstantExpr traps if any operands can trap.
for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) {
if (ConstantExpr *Op = dyn_cast<ConstantExpr>(CE->getOperand(i))) {
- if (NonTrappingOps.insert(Op) && canTrapImpl(Op, NonTrappingOps))
+ if (NonTrappingOps.insert(Op).second && canTrapImpl(Op, NonTrappingOps))
return true;
}
}
@@ -318,7 +363,7 @@ ConstHasGlobalValuePredicate(const Constant *C,
const Constant *ConstOp = dyn_cast<Constant>(Op);
if (!ConstOp)
continue;
- if (Visited.insert(ConstOp))
+ if (Visited.insert(ConstOp).second)
WorkList.push_back(ConstOp);
}
}
@@ -781,6 +826,11 @@ ConstantArray::ConstantArray(ArrayType *T, ArrayRef<Constant *> V)
}
Constant *ConstantArray::get(ArrayType *Ty, ArrayRef<Constant*> V) {
+ if (Constant *C = getImpl(Ty, V))
+ return C;
+ return Ty->getContext().pImpl->ArrayConstants.getOrCreate(Ty, V);
+}
+Constant *ConstantArray::getImpl(ArrayType *Ty, ArrayRef<Constant*> V) {
// Empty arrays are canonicalized to ConstantAggregateZero.
if (V.empty())
return ConstantAggregateZero::get(Ty);
@@ -789,7 +839,6 @@ Constant *ConstantArray::get(ArrayType *Ty, ArrayRef<Constant*> V) {
assert(V[i]->getType() == Ty->getElementType() &&
"Wrong type in array element initializer");
}
- LLVMContextImpl *pImpl = Ty->getContext().pImpl;
// If this is an all-zero array, return a ConstantAggregateZero object. If
// all undef, return an UndefValue, if "all simple", then return a
@@ -871,7 +920,7 @@ Constant *ConstantArray::get(ArrayType *Ty, ArrayRef<Constant*> V) {
}
// Otherwise, we really do want to create a ConstantArray.
- return pImpl->ArrayConstants.getOrCreate(Ty, V);
+ return nullptr;
}
/// getTypeForElements - Return an anonymous struct type to use for a constant
@@ -959,9 +1008,14 @@ ConstantVector::ConstantVector(VectorType *T, ArrayRef<Constant *> V)
// ConstantVector accessors.
Constant *ConstantVector::get(ArrayRef<Constant*> V) {
+ if (Constant *C = getImpl(V))
+ return C;
+ VectorType *Ty = VectorType::get(V.front()->getType(), V.size());
+ return Ty->getContext().pImpl->VectorConstants.getOrCreate(Ty, V);
+}
+Constant *ConstantVector::getImpl(ArrayRef<Constant*> V) {
assert(!V.empty() && "Vectors can't be empty");
VectorType *T = VectorType::get(V.front()->getType(), V.size());
- LLVMContextImpl *pImpl = T->getContext().pImpl;
// If this is an all-undef or all-zero vector, return a
// ConstantAggregateZero or UndefValue.
@@ -1053,7 +1107,7 @@ Constant *ConstantVector::get(ArrayRef<Constant*> V) {
// Otherwise, the element type isn't compatible with ConstantDataVector, or
// the operand list constants a ConstantExpr or something else strange.
- return pImpl->VectorConstants.getOrCreate(T, V);
+ return nullptr;
}
Constant *ConstantVector::getSplat(unsigned NumElts, Constant *V) {
@@ -1141,8 +1195,8 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const {
/// getWithOperands - This returns the current constant expression with the
/// operands replaced with the specified values. The specified array must
/// have the same number of operands as our current one.
-Constant *ConstantExpr::
-getWithOperands(ArrayRef<Constant*> Ops, Type *Ty) const {
+Constant *ConstantExpr::getWithOperands(ArrayRef<Constant *> Ops, Type *Ty,
+ bool OnlyIfReduced) const {
assert(Ops.size() == getNumOperands() && "Operand count mismatch!");
bool AnyChange = Ty != getType();
for (unsigned i = 0; i != Ops.size(); ++i)
@@ -1151,6 +1205,7 @@ getWithOperands(ArrayRef<Constant*> Ops, Type *Ty) const {
if (!AnyChange) // No operands changed, return self.
return const_cast<ConstantExpr*>(this);
+ Type *OnlyIfReducedTy = OnlyIfReduced ? Ty : nullptr;
switch (getOpcode()) {
case Instruction::Trunc:
case Instruction::ZExt:
@@ -1165,28 +1220,34 @@ getWithOperands(ArrayRef<Constant*> Ops, Type *Ty) const {
case Instruction::IntToPtr:
case Instruction::BitCast:
case Instruction::AddrSpaceCast:
- return ConstantExpr::getCast(getOpcode(), Ops[0], Ty);
+ return ConstantExpr::getCast(getOpcode(), Ops[0], Ty, OnlyIfReduced);
case Instruction::Select:
- return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2]);
+ return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2], OnlyIfReducedTy);
case Instruction::InsertElement:
- return ConstantExpr::getInsertElement(Ops[0], Ops[1], Ops[2]);
+ return ConstantExpr::getInsertElement(Ops[0], Ops[1], Ops[2],
+ OnlyIfReducedTy);
case Instruction::ExtractElement:
- return ConstantExpr::getExtractElement(Ops[0], Ops[1]);
+ return ConstantExpr::getExtractElement(Ops[0], Ops[1], OnlyIfReducedTy);
case Instruction::InsertValue:
- return ConstantExpr::getInsertValue(Ops[0], Ops[1], getIndices());
+ return ConstantExpr::getInsertValue(Ops[0], Ops[1], getIndices(),
+ OnlyIfReducedTy);
case Instruction::ExtractValue:
- return ConstantExpr::getExtractValue(Ops[0], getIndices());
+ return ConstantExpr::getExtractValue(Ops[0], getIndices(), OnlyIfReducedTy);
case Instruction::ShuffleVector:
- return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]);
+ return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2],
+ OnlyIfReducedTy);
case Instruction::GetElementPtr:
return ConstantExpr::getGetElementPtr(Ops[0], Ops.slice(1),
- cast<GEPOperator>(this)->isInBounds());
+ cast<GEPOperator>(this)->isInBounds(),
+ OnlyIfReducedTy);
case Instruction::ICmp:
case Instruction::FCmp:
- return ConstantExpr::getCompare(getPredicate(), Ops[0], Ops[1]);
+ return ConstantExpr::getCompare(getPredicate(), Ops[0], Ops[1],
+ OnlyIfReducedTy);
default:
assert(getNumOperands() == 2 && "Must be binary operator?");
- return ConstantExpr::get(getOpcode(), Ops[0], Ops[1], SubclassOptionalData);
+ return ConstantExpr::get(getOpcode(), Ops[0], Ops[1], SubclassOptionalData,
+ OnlyIfReducedTy);
}
}
@@ -1447,27 +1508,21 @@ void BlockAddress::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) {
// and return early.
BlockAddress *&NewBA =
getContext().pImpl->BlockAddresses[std::make_pair(NewF, NewBB)];
- if (!NewBA) {
- getBasicBlock()->AdjustBlockAddressRefCount(-1);
-
- // Remove the old entry, this can't cause the map to rehash (just a
- // tombstone will get added).
- getContext().pImpl->BlockAddresses.erase(std::make_pair(getFunction(),
- getBasicBlock()));
- NewBA = this;
- setOperand(0, NewF);
- setOperand(1, NewBB);
- getBasicBlock()->AdjustBlockAddressRefCount(1);
+ if (NewBA) {
+ replaceUsesOfWithOnConstantImpl(NewBA);
return;
}
- // Otherwise, I do need to replace this with an existing value.
- assert(NewBA != this && "I didn't contain From!");
-
- // Everyone using this now uses the replacement.
- replaceAllUsesWith(NewBA);
+ getBasicBlock()->AdjustBlockAddressRefCount(-1);
- destroyConstant();
+ // Remove the old entry, this can't cause the map to rehash (just a
+ // tombstone will get added).
+ getContext().pImpl->BlockAddresses.erase(std::make_pair(getFunction(),
+ getBasicBlock()));
+ NewBA = this;
+ setOperand(0, NewF);
+ setOperand(1, NewBB);
+ getBasicBlock()->AdjustBlockAddressRefCount(1);
}
//---- ConstantExpr::get() implementations.
@@ -1475,22 +1530,26 @@ void BlockAddress::replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U) {
/// This is a utility function to handle folding of casts and lookup of the
/// cast in the ExprConstants map. It is used by the various get* methods below.
-static inline Constant *getFoldedCast(
- Instruction::CastOps opc, Constant *C, Type *Ty) {
+static Constant *getFoldedCast(Instruction::CastOps opc, Constant *C, Type *Ty,
+ bool OnlyIfReduced = false) {
assert(Ty->isFirstClassType() && "Cannot cast to an aggregate type!");
// Fold a few common cases
if (Constant *FC = ConstantFoldCastInstruction(opc, C, Ty))
return FC;
+ if (OnlyIfReduced)
+ return nullptr;
+
LLVMContextImpl *pImpl = Ty->getContext().pImpl;
// Look up the constant in the table first to ensure uniqueness.
- ExprMapKeyType Key(opc, C);
+ ConstantExprKeyType Key(opc, C);
return pImpl->ExprConstants.getOrCreate(Ty, Key);
}
-Constant *ConstantExpr::getCast(unsigned oc, Constant *C, Type *Ty) {
+Constant *ConstantExpr::getCast(unsigned oc, Constant *C, Type *Ty,
+ bool OnlyIfReduced) {
Instruction::CastOps opc = Instruction::CastOps(oc);
assert(Instruction::isCast(opc) && "opcode out of range");
assert(C && Ty && "Null arguments to getCast");
@@ -1499,19 +1558,32 @@ Constant *ConstantExpr::getCast(unsigned oc, Constant *C, Type *Ty) {
switch (opc) {
default:
llvm_unreachable("Invalid cast opcode");
- case Instruction::Trunc: return getTrunc(C, Ty);
- case Instruction::ZExt: return getZExt(C, Ty);
- case Instruction::SExt: return getSExt(C, Ty);
- case Instruction::FPTrunc: return getFPTrunc(C, Ty);
- case Instruction::FPExt: return getFPExtend(C, Ty);
- case Instruction::UIToFP: return getUIToFP(C, Ty);
- case Instruction::SIToFP: return getSIToFP(C, Ty);
- case Instruction::FPToUI: return getFPToUI(C, Ty);
- case Instruction::FPToSI: return getFPToSI(C, Ty);
- case Instruction::PtrToInt: return getPtrToInt(C, Ty);
- case Instruction::IntToPtr: return getIntToPtr(C, Ty);
- case Instruction::BitCast: return getBitCast(C, Ty);
- case Instruction::AddrSpaceCast: return getAddrSpaceCast(C, Ty);
+ case Instruction::Trunc:
+ return getTrunc(C, Ty, OnlyIfReduced);
+ case Instruction::ZExt:
+ return getZExt(C, Ty, OnlyIfReduced);
+ case Instruction::SExt:
+ return getSExt(C, Ty, OnlyIfReduced);
+ case Instruction::FPTrunc:
+ return getFPTrunc(C, Ty, OnlyIfReduced);
+ case Instruction::FPExt:
+ return getFPExtend(C, Ty, OnlyIfReduced);
+ case Instruction::UIToFP:
+ return getUIToFP(C, Ty, OnlyIfReduced);
+ case Instruction::SIToFP:
+ return getSIToFP(C, Ty, OnlyIfReduced);
+ case Instruction::FPToUI:
+ return getFPToUI(C, Ty, OnlyIfReduced);
+ case Instruction::FPToSI:
+ return getFPToSI(C, Ty, OnlyIfReduced);
+ case Instruction::PtrToInt:
+ return getPtrToInt(C, Ty, OnlyIfReduced);
+ case Instruction::IntToPtr:
+ return getIntToPtr(C, Ty, OnlyIfReduced);
+ case Instruction::BitCast:
+ return getBitCast(C, Ty, OnlyIfReduced);
+ case Instruction::AddrSpaceCast:
+ return getAddrSpaceCast(C, Ty, OnlyIfReduced);
}
}
@@ -1584,7 +1656,7 @@ Constant *ConstantExpr::getFPCast(Constant *C, Type *Ty) {
return getCast(opcode, C, Ty);
}
-Constant *ConstantExpr::getTrunc(Constant *C, Type *Ty) {
+Constant *ConstantExpr::getTrunc(Constant *C, Type *Ty, bool OnlyIfReduced) {
#ifndef NDEBUG
bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
bool toVec = Ty->getTypeID() == Type::VectorTyID;
@@ -1595,10 +1667,10 @@ Constant *ConstantExpr::getTrunc(Constant *C, Type *Ty) {
assert(C->getType()->getScalarSizeInBits() > Ty->getScalarSizeInBits()&&
"SrcTy must be larger than DestTy for Trunc!");
- return getFoldedCast(Instruction::Trunc, C, Ty);
+ return getFoldedCast(Instruction::Trunc, C, Ty, OnlyIfReduced);
}
-Constant *ConstantExpr::getSExt(Constant *C, Type *Ty) {
+Constant *ConstantExpr::getSExt(Constant *C, Type *Ty, bool OnlyIfReduced) {
#ifndef NDEBUG
bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
bool toVec = Ty->getTypeID() == Type::VectorTyID;
@@ -1609,10 +1681,10 @@ Constant *ConstantExpr::getSExt(Constant *C, Type *Ty) {
assert(C->getType()->getScalarSizeInBits() < Ty->getScalarSizeInBits()&&
"SrcTy must be smaller than DestTy for SExt!");
- return getFoldedCast(Instruction::SExt, C, Ty);
+ return getFoldedCast(Instruction::SExt, C, Ty, OnlyIfReduced);
}
-Constant *ConstantExpr::getZExt(Constant *C, Type *Ty) {
+Constant *ConstantExpr::getZExt(Constant *C, Type *Ty, bool OnlyIfReduced) {
#ifndef NDEBUG
bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
bool toVec = Ty->getTypeID() == Type::VectorTyID;
@@ -1623,10 +1695,10 @@ Constant *ConstantExpr::getZExt(Constant *C, Type *Ty) {
assert(C->getType()->getScalarSizeInBits() < Ty->getScalarSizeInBits()&&
"SrcTy must be smaller than DestTy for ZExt!");
- return getFoldedCast(Instruction::ZExt, C, Ty);
+ return getFoldedCast(Instruction::ZExt, C, Ty, OnlyIfReduced);
}
-Constant *ConstantExpr::getFPTrunc(Constant *C, Type *Ty) {
+Constant *ConstantExpr::getFPTrunc(Constant *C, Type *Ty, bool OnlyIfReduced) {
#ifndef NDEBUG
bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
bool toVec = Ty->getTypeID() == Type::VectorTyID;
@@ -1635,10 +1707,10 @@ Constant *ConstantExpr::getFPTrunc(Constant *C, Type *Ty) {
assert(C->getType()->isFPOrFPVectorTy() && Ty->isFPOrFPVectorTy() &&
C->getType()->getScalarSizeInBits() > Ty->getScalarSizeInBits()&&
"This is an illegal floating point truncation!");
- return getFoldedCast(Instruction::FPTrunc, C, Ty);
+ return getFoldedCast(Instruction::FPTrunc, C, Ty, OnlyIfReduced);
}
-Constant *ConstantExpr::getFPExtend(Constant *C, Type *Ty) {
+Constant *ConstantExpr::getFPExtend(Constant *C, Type *Ty, bool OnlyIfReduced) {
#ifndef NDEBUG
bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
bool toVec = Ty->getTypeID() == Type::VectorTyID;
@@ -1647,10 +1719,10 @@ Constant *ConstantExpr::getFPExtend(Constant *C, Type *Ty) {
assert(C->getType()->isFPOrFPVectorTy() && Ty->isFPOrFPVectorTy() &&
C->getType()->getScalarSizeInBits() < Ty->getScalarSizeInBits()&&
"This is an illegal floating point extension!");
- return getFoldedCast(Instruction::FPExt, C, Ty);
+ return getFoldedCast(Instruction::FPExt, C, Ty, OnlyIfReduced);
}
-Constant *ConstantExpr::getUIToFP(Constant *C, Type *Ty) {
+Constant *ConstantExpr::getUIToFP(Constant *C, Type *Ty, bool OnlyIfReduced) {
#ifndef NDEBUG
bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
bool toVec = Ty->getTypeID() == Type::VectorTyID;
@@ -1658,10 +1730,10 @@ Constant *ConstantExpr::getUIToFP(Constant *C, Type *Ty) {
assert((fromVec == toVec) && "Cannot convert from scalar to/from vector");
assert(C->getType()->isIntOrIntVectorTy() && Ty->isFPOrFPVectorTy() &&
"This is an illegal uint to floating point cast!");
- return getFoldedCast(Instruction::UIToFP, C, Ty);
+ return getFoldedCast(Instruction::UIToFP, C, Ty, OnlyIfReduced);
}
-Constant *ConstantExpr::getSIToFP(Constant *C, Type *Ty) {
+Constant *ConstantExpr::getSIToFP(Constant *C, Type *Ty, bool OnlyIfReduced) {
#ifndef NDEBUG
bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
bool toVec = Ty->getTypeID() == Type::VectorTyID;
@@ -1669,10 +1741,10 @@ Constant *ConstantExpr::getSIToFP(Constant *C, Type *Ty) {
assert((fromVec == toVec) && "Cannot convert from scalar to/from vector");
assert(C->getType()->isIntOrIntVectorTy() && Ty->isFPOrFPVectorTy() &&
"This is an illegal sint to floating point cast!");
- return getFoldedCast(Instruction::SIToFP, C, Ty);
+ return getFoldedCast(Instruction::SIToFP, C, Ty, OnlyIfReduced);
}
-Constant *ConstantExpr::getFPToUI(Constant *C, Type *Ty) {
+Constant *ConstantExpr::getFPToUI(Constant *C, Type *Ty, bool OnlyIfReduced) {
#ifndef NDEBUG
bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
bool toVec = Ty->getTypeID() == Type::VectorTyID;
@@ -1680,10 +1752,10 @@ Constant *ConstantExpr::getFPToUI(Constant *C, Type *Ty) {
assert((fromVec == toVec) && "Cannot convert from scalar to/from vector");
assert(C->getType()->isFPOrFPVectorTy() && Ty->isIntOrIntVectorTy() &&
"This is an illegal floating point to uint cast!");
- return getFoldedCast(Instruction::FPToUI, C, Ty);
+ return getFoldedCast(Instruction::FPToUI, C, Ty, OnlyIfReduced);
}
-Constant *ConstantExpr::getFPToSI(Constant *C, Type *Ty) {
+Constant *ConstantExpr::getFPToSI(Constant *C, Type *Ty, bool OnlyIfReduced) {
#ifndef NDEBUG
bool fromVec = C->getType()->getTypeID() == Type::VectorTyID;
bool toVec = Ty->getTypeID() == Type::VectorTyID;
@@ -1691,10 +1763,11 @@ Constant *ConstantExpr::getFPToSI(Constant *C, Type *Ty) {
assert((fromVec == toVec) && "Cannot convert from scalar to/from vector");
assert(C->getType()->isFPOrFPVectorTy() && Ty->isIntOrIntVectorTy() &&
"This is an illegal floating point to sint cast!");
- return getFoldedCast(Instruction::FPToSI, C, Ty);
+ return getFoldedCast(Instruction::FPToSI, C, Ty, OnlyIfReduced);
}
-Constant *ConstantExpr::getPtrToInt(Constant *C, Type *DstTy) {
+Constant *ConstantExpr::getPtrToInt(Constant *C, Type *DstTy,
+ bool OnlyIfReduced) {
assert(C->getType()->getScalarType()->isPointerTy() &&
"PtrToInt source must be pointer or pointer vector");
assert(DstTy->getScalarType()->isIntegerTy() &&
@@ -1703,10 +1776,11 @@ Constant *ConstantExpr::getPtrToInt(Constant *C, Type *DstTy) {
if (isa<VectorType>(C->getType()))
assert(C->getType()->getVectorNumElements()==DstTy->getVectorNumElements()&&
"Invalid cast between a different number of vector elements");
- return getFoldedCast(Instruction::PtrToInt, C, DstTy);
+ return getFoldedCast(Instruction::PtrToInt, C, DstTy, OnlyIfReduced);
}
-Constant *ConstantExpr::getIntToPtr(Constant *C, Type *DstTy) {
+Constant *ConstantExpr::getIntToPtr(Constant *C, Type *DstTy,
+ bool OnlyIfReduced) {
assert(C->getType()->getScalarType()->isIntegerTy() &&
"IntToPtr source must be integer or integer vector");
assert(DstTy->getScalarType()->isPointerTy() &&
@@ -1715,10 +1789,11 @@ Constant *ConstantExpr::getIntToPtr(Constant *C, Type *DstTy) {
if (isa<VectorType>(C->getType()))
assert(C->getType()->getVectorNumElements()==DstTy->getVectorNumElements()&&
"Invalid cast between a different number of vector elements");
- return getFoldedCast(Instruction::IntToPtr, C, DstTy);
+ return getFoldedCast(Instruction::IntToPtr, C, DstTy, OnlyIfReduced);
}
-Constant *ConstantExpr::getBitCast(Constant *C, Type *DstTy) {
+Constant *ConstantExpr::getBitCast(Constant *C, Type *DstTy,
+ bool OnlyIfReduced) {
assert(CastInst::castIsValid(Instruction::BitCast, C, DstTy) &&
"Invalid constantexpr bitcast!");
@@ -1726,10 +1801,11 @@ Constant *ConstantExpr::getBitCast(Constant *C, Type *DstTy) {
// speedily.
if (C->getType() == DstTy) return C;
- return getFoldedCast(Instruction::BitCast, C, DstTy);
+ return getFoldedCast(Instruction::BitCast, C, DstTy, OnlyIfReduced);
}
-Constant *ConstantExpr::getAddrSpaceCast(Constant *C, Type *DstTy) {
+Constant *ConstantExpr::getAddrSpaceCast(Constant *C, Type *DstTy,
+ bool OnlyIfReduced) {
assert(CastInst::castIsValid(Instruction::AddrSpaceCast, C, DstTy) &&
"Invalid constantexpr addrspacecast!");
@@ -1746,11 +1822,11 @@ Constant *ConstantExpr::getAddrSpaceCast(Constant *C, Type *DstTy) {
}
C = getBitCast(C, MidTy);
}
- return getFoldedCast(Instruction::AddrSpaceCast, C, DstTy);
+ return getFoldedCast(Instruction::AddrSpaceCast, C, DstTy, OnlyIfReduced);
}
Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
- unsigned Flags) {
+ unsigned Flags, Type *OnlyIfReducedTy) {
// Check the operands for consistency first.
assert(Opcode >= Instruction::BinaryOpsBegin &&
Opcode < Instruction::BinaryOpsEnd &&
@@ -1819,8 +1895,11 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
if (Constant *FC = ConstantFoldBinaryInstruction(Opcode, C1, C2))
return FC; // Fold a few common cases.
+ if (OnlyIfReducedTy == C1->getType())
+ return nullptr;
+
Constant *ArgVec[] = { C1, C2 };
- ExprMapKeyType Key(Opcode, ArgVec, 0, Flags);
+ ConstantExprKeyType Key(Opcode, ArgVec, 0, Flags);
LLVMContextImpl *pImpl = C1->getContext().pImpl;
return pImpl->ExprConstants.getOrCreate(C1->getType(), Key);
@@ -1840,7 +1919,7 @@ Constant *ConstantExpr::getAlignOf(Type* Ty) {
// alignof is implemented as: (i64) gep ({i1,Ty}*)null, 0, 1
// Note that a non-inbounds gep is used, as null isn't within any object.
Type *AligningTy =
- StructType::get(Type::getInt1Ty(Ty->getContext()), Ty, NULL);
+ StructType::get(Type::getInt1Ty(Ty->getContext()), Ty, nullptr);
Constant *NullPtr = Constant::getNullValue(AligningTy->getPointerTo(0));
Constant *Zero = ConstantInt::get(Type::getInt64Ty(Ty->getContext()), 0);
Constant *One = ConstantInt::get(Type::getInt32Ty(Ty->getContext()), 1);
@@ -1868,8 +1947,8 @@ Constant *ConstantExpr::getOffsetOf(Type* Ty, Constant *FieldNo) {
Type::getInt64Ty(Ty->getContext()));
}
-Constant *ConstantExpr::getCompare(unsigned short Predicate,
- Constant *C1, Constant *C2) {
+Constant *ConstantExpr::getCompare(unsigned short Predicate, Constant *C1,
+ Constant *C2, bool OnlyIfReduced) {
assert(C1->getType() == C2->getType() && "Op types should be identical!");
switch (Predicate) {
@@ -1880,31 +1959,35 @@ Constant *ConstantExpr::getCompare(unsigned short Predicate,
case CmpInst::FCMP_UEQ: case CmpInst::FCMP_UGT: case CmpInst::FCMP_UGE:
case CmpInst::FCMP_ULT: case CmpInst::FCMP_ULE: case CmpInst::FCMP_UNE:
case CmpInst::FCMP_TRUE:
- return getFCmp(Predicate, C1, C2);
+ return getFCmp(Predicate, C1, C2, OnlyIfReduced);
case CmpInst::ICMP_EQ: case CmpInst::ICMP_NE: case CmpInst::ICMP_UGT:
case CmpInst::ICMP_UGE: case CmpInst::ICMP_ULT: case CmpInst::ICMP_ULE:
case CmpInst::ICMP_SGT: case CmpInst::ICMP_SGE: case CmpInst::ICMP_SLT:
case CmpInst::ICMP_SLE:
- return getICmp(Predicate, C1, C2);
+ return getICmp(Predicate, C1, C2, OnlyIfReduced);
}
}
-Constant *ConstantExpr::getSelect(Constant *C, Constant *V1, Constant *V2) {
+Constant *ConstantExpr::getSelect(Constant *C, Constant *V1, Constant *V2,
+ Type *OnlyIfReducedTy) {
assert(!SelectInst::areInvalidOperands(C, V1, V2)&&"Invalid select operands");
if (Constant *SC = ConstantFoldSelectInstruction(C, V1, V2))
return SC; // Fold common cases
+ if (OnlyIfReducedTy == V1->getType())
+ return nullptr;
+
Constant *ArgVec[] = { C, V1, V2 };
- ExprMapKeyType Key(Instruction::Select, ArgVec);
+ ConstantExprKeyType Key(Instruction::Select, ArgVec);
LLVMContextImpl *pImpl = C->getContext().pImpl;
return pImpl->ExprConstants.getOrCreate(V1->getType(), Key);
}
Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef<Value *> Idxs,
- bool InBounds) {
+ bool InBounds, Type *OnlyIfReducedTy) {
assert(C->getType()->isPtrOrPtrVectorTy() &&
"Non-pointer type for constant GetElementPtr expression");
@@ -1919,6 +2002,9 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef<Value *> Idxs,
if (VectorType *VecTy = dyn_cast<VectorType>(C->getType()))
ReqTy = VectorType::get(ReqTy, VecTy->getNumElements());
+ if (OnlyIfReducedTy == ReqTy)
+ return nullptr;
+
// Look up the constant in the table first to ensure uniqueness
std::vector<Constant*> ArgVec;
ArgVec.reserve(1 + Idxs.size());
@@ -1932,15 +2018,15 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, ArrayRef<Value *> Idxs,
"getelementptr index type missmatch");
ArgVec.push_back(cast<Constant>(Idxs[i]));
}
- const ExprMapKeyType Key(Instruction::GetElementPtr, ArgVec, 0,
- InBounds ? GEPOperator::IsInBounds : 0);
+ const ConstantExprKeyType Key(Instruction::GetElementPtr, ArgVec, 0,
+ InBounds ? GEPOperator::IsInBounds : 0);
LLVMContextImpl *pImpl = C->getContext().pImpl;
return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
}
-Constant *
-ConstantExpr::getICmp(unsigned short pred, Constant *LHS, Constant *RHS) {
+Constant *ConstantExpr::getICmp(unsigned short pred, Constant *LHS,
+ Constant *RHS, bool OnlyIfReduced) {
assert(LHS->getType() == RHS->getType());
assert(pred >= ICmpInst::FIRST_ICMP_PREDICATE &&
pred <= ICmpInst::LAST_ICMP_PREDICATE && "Invalid ICmp Predicate");
@@ -1948,10 +2034,13 @@ ConstantExpr::getICmp(unsigned short pred, Constant *LHS, Constant *RHS) {
if (Constant *FC = ConstantFoldCompareInstruction(pred, LHS, RHS))
return FC; // Fold a few common cases...
+ if (OnlyIfReduced)
+ return nullptr;
+
// Look up the constant in the table first to ensure uniqueness
Constant *ArgVec[] = { LHS, RHS };
// Get the key type with both the opcode and predicate
- const ExprMapKeyType Key(Instruction::ICmp, ArgVec, pred);
+ const ConstantExprKeyType Key(Instruction::ICmp, ArgVec, pred);
Type *ResultTy = Type::getInt1Ty(LHS->getContext());
if (VectorType *VT = dyn_cast<VectorType>(LHS->getType()))
@@ -1961,18 +2050,21 @@ ConstantExpr::getICmp(unsigned short pred, Constant *LHS, Constant *RHS) {
return pImpl->ExprConstants.getOrCreate(ResultTy, Key);
}
-Constant *
-ConstantExpr::getFCmp(unsigned short pred, Constant *LHS, Constant *RHS) {
+Constant *ConstantExpr::getFCmp(unsigned short pred, Constant *LHS,
+ Constant *RHS, bool OnlyIfReduced) {
assert(LHS->getType() == RHS->getType());
assert(pred <= FCmpInst::LAST_FCMP_PREDICATE && "Invalid FCmp Predicate");
if (Constant *FC = ConstantFoldCompareInstruction(pred, LHS, RHS))
return FC; // Fold a few common cases...
+ if (OnlyIfReduced)
+ return nullptr;
+
// Look up the constant in the table first to ensure uniqueness
Constant *ArgVec[] = { LHS, RHS };
// Get the key type with both the opcode and predicate
- const ExprMapKeyType Key(Instruction::FCmp, ArgVec, pred);
+ const ConstantExprKeyType Key(Instruction::FCmp, ArgVec, pred);
Type *ResultTy = Type::getInt1Ty(LHS->getContext());
if (VectorType *VT = dyn_cast<VectorType>(LHS->getType()))
@@ -1982,7 +2074,8 @@ ConstantExpr::getFCmp(unsigned short pred, Constant *LHS, Constant *RHS) {
return pImpl->ExprConstants.getOrCreate(ResultTy, Key);
}
-Constant *ConstantExpr::getExtractElement(Constant *Val, Constant *Idx) {
+Constant *ConstantExpr::getExtractElement(Constant *Val, Constant *Idx,
+ Type *OnlyIfReducedTy) {
assert(Val->getType()->isVectorTy() &&
"Tried to create extractelement operation on non-vector type!");
assert(Idx->getType()->isIntegerTy() &&
@@ -1991,17 +2084,20 @@ Constant *ConstantExpr::getExtractElement(Constant *Val, Constant *Idx) {
if (Constant *FC = ConstantFoldExtractElementInstruction(Val, Idx))
return FC; // Fold a few common cases.
+ Type *ReqTy = Val->getType()->getVectorElementType();
+ if (OnlyIfReducedTy == ReqTy)
+ return nullptr;
+
// Look up the constant in the table first to ensure uniqueness
Constant *ArgVec[] = { Val, Idx };
- const ExprMapKeyType Key(Instruction::ExtractElement, ArgVec);
+ const ConstantExprKeyType Key(Instruction::ExtractElement, ArgVec);
LLVMContextImpl *pImpl = Val->getContext().pImpl;
- Type *ReqTy = Val->getType()->getVectorElementType();
return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
}
-Constant *ConstantExpr::getInsertElement(Constant *Val, Constant *Elt,
- Constant *Idx) {
+Constant *ConstantExpr::getInsertElement(Constant *Val, Constant *Elt,
+ Constant *Idx, Type *OnlyIfReducedTy) {
assert(Val->getType()->isVectorTy() &&
"Tried to create insertelement operation on non-vector type!");
assert(Elt->getType() == Val->getType()->getVectorElementType() &&
@@ -2011,16 +2107,20 @@ Constant *ConstantExpr::getInsertElement(Constant *Val, Constant *Elt,
if (Constant *FC = ConstantFoldInsertElementInstruction(Val, Elt, Idx))
return FC; // Fold a few common cases.
+
+ if (OnlyIfReducedTy == Val->getType())
+ return nullptr;
+
// Look up the constant in the table first to ensure uniqueness
Constant *ArgVec[] = { Val, Elt, Idx };
- const ExprMapKeyType Key(Instruction::InsertElement, ArgVec);
+ const ConstantExprKeyType Key(Instruction::InsertElement, ArgVec);
LLVMContextImpl *pImpl = Val->getContext().pImpl;
return pImpl->ExprConstants.getOrCreate(Val->getType(), Key);
}
-Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2,
- Constant *Mask) {
+Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2,
+ Constant *Mask, Type *OnlyIfReducedTy) {
assert(ShuffleVectorInst::isValidOperands(V1, V2, Mask) &&
"Invalid shuffle vector constant expr operands!");
@@ -2031,16 +2131,20 @@ Constant *ConstantExpr::getShuffleVector(Constant *V1, Constant *V2,
Type *EltTy = V1->getType()->getVectorElementType();
Type *ShufTy = VectorType::get(EltTy, NElts);
+ if (OnlyIfReducedTy == ShufTy)
+ return nullptr;
+
// Look up the constant in the table first to ensure uniqueness
Constant *ArgVec[] = { V1, V2, Mask };
- const ExprMapKeyType Key(Instruction::ShuffleVector, ArgVec);
+ const ConstantExprKeyType Key(Instruction::ShuffleVector, ArgVec);
LLVMContextImpl *pImpl = ShufTy->getContext().pImpl;
return pImpl->ExprConstants.getOrCreate(ShufTy, Key);
}
Constant *ConstantExpr::getInsertValue(Constant *Agg, Constant *Val,
- ArrayRef<unsigned> Idxs) {
+ ArrayRef<unsigned> Idxs,
+ Type *OnlyIfReducedTy) {
assert(Agg->getType()->isFirstClassType() &&
"Non-first-class type for constant insertvalue expression");
@@ -2052,15 +2156,18 @@ Constant *ConstantExpr::getInsertValue(Constant *Agg, Constant *Val,
if (Constant *FC = ConstantFoldInsertValueInstruction(Agg, Val, Idxs))
return FC;
+ if (OnlyIfReducedTy == ReqTy)
+ return nullptr;
+
Constant *ArgVec[] = { Agg, Val };
- const ExprMapKeyType Key(Instruction::InsertValue, ArgVec, 0, 0, Idxs);
+ const ConstantExprKeyType Key(Instruction::InsertValue, ArgVec, 0, 0, Idxs);
LLVMContextImpl *pImpl = Agg->getContext().pImpl;
return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
}
-Constant *ConstantExpr::getExtractValue(Constant *Agg,
- ArrayRef<unsigned> Idxs) {
+Constant *ConstantExpr::getExtractValue(Constant *Agg, ArrayRef<unsigned> Idxs,
+ Type *OnlyIfReducedTy) {
assert(Agg->getType()->isFirstClassType() &&
"Tried to create extractelement operation on non-first-class type!");
@@ -2073,8 +2180,11 @@ Constant *ConstantExpr::getExtractValue(Constant *Agg,
if (Constant *FC = ConstantFoldExtractValueInstruction(Agg, Idxs))
return FC;
+ if (OnlyIfReducedTy == ReqTy)
+ return nullptr;
+
Constant *ArgVec[] = { Agg };
- const ExprMapKeyType Key(Instruction::ExtractValue, ArgVec, 0, 0, Idxs);
+ const ConstantExprKeyType Key(Instruction::ExtractValue, ArgVec, 0, 0, Idxs);
LLVMContextImpl *pImpl = Agg->getContext().pImpl;
return pImpl->ExprConstants.getOrCreate(ReqTy, Key);
@@ -2326,14 +2436,16 @@ Constant *ConstantDataSequential::getImpl(StringRef Elements, Type *Ty) {
return ConstantAggregateZero::get(Ty);
// Do a lookup to see if we have already formed one of these.
- StringMap<ConstantDataSequential*>::MapEntryTy &Slot =
- Ty->getContext().pImpl->CDSConstants.GetOrCreateValue(Elements);
+ auto &Slot =
+ *Ty->getContext()
+ .pImpl->CDSConstants.insert(std::make_pair(Elements, nullptr))
+ .first;
// The bucket can point to a linked list of different CDS's that have the same
// body but different types. For example, 0,0,0,1 could be a 4 element array
// of i8, or a 1-element array of i32. They'll both end up in the same
/// StringMap bucket, linked up by their Next pointers. Walk the list.
- ConstantDataSequential **Entry = &Slot.getValue();
+ ConstantDataSequential **Entry = &Slot.second;
for (ConstantDataSequential *Node = *Entry; Node;
Entry = &Node->Next, Node = *Entry)
if (Node->getType() == Ty)
@@ -2342,10 +2454,10 @@ Constant *ConstantDataSequential::getImpl(StringRef Elements, Type *Ty) {
// Okay, we didn't get a hit. Create a node of the right class, link it in,
// and return it.
if (isa<ArrayType>(Ty))
- return *Entry = new ConstantDataArray(Ty, Slot.getKeyData());
+ return *Entry = new ConstantDataArray(Ty, Slot.first().data());
assert(isa<VectorType>(Ty));
- return *Entry = new ConstantDataVector(Ty, Slot.getKeyData());
+ return *Entry = new ConstantDataVector(Ty, Slot.first().data());
}
void ConstantDataSequential::destroyConstant() {
@@ -2431,7 +2543,7 @@ Constant *ConstantDataArray::getString(LLVMContext &Context,
StringRef Str, bool AddNull) {
if (!AddNull) {
const uint8_t *Data = reinterpret_cast<const uint8_t *>(Str.data());
- return get(Context, ArrayRef<uint8_t>(const_cast<uint8_t *>(Data),
+ return get(Context, makeArrayRef(const_cast<uint8_t *>(Data),
Str.size()));
}
@@ -2602,7 +2714,7 @@ bool ConstantDataSequential::isCString() const {
}
/// getSplatValue - If this is a splat constant, meaning that all of the
-/// elements have the same value, return that value. Otherwise return NULL.
+/// elements have the same value, return that value. Otherwise return nullptr.
Constant *ConstantDataVector::getSplatValue() const {
const char *Base = getRawDataValues().data();
@@ -2630,16 +2742,23 @@ Constant *ConstantDataVector::getSplatValue() const {
/// work, but would be really slow because it would have to unique each updated
/// array instance.
///
+void Constant::replaceUsesOfWithOnConstantImpl(Constant *Replacement) {
+ // I do need to replace this with an existing value.
+ assert(Replacement != this && "I didn't contain From!");
+
+ // Everyone using this now uses the replacement.
+ replaceAllUsesWith(Replacement);
+
+ // Delete the old constant!
+ destroyConstant();
+}
+
void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
Use *U) {
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
Constant *ToC = cast<Constant>(To);
- LLVMContextImpl *pImpl = getType()->getContext().pImpl;
-
SmallVector<Constant*, 8> Values;
- LLVMContextImpl::ArrayConstantsTy::LookupKey Lookup;
- Lookup.first = cast<ArrayType>(getType());
Values.reserve(getNumOperands()); // Build replacement array.
// Fill values with the modified operands of the constant array. Also,
@@ -2658,51 +2777,25 @@ void ConstantArray::replaceUsesOfWithOnConstant(Value *From, Value *To,
AllSame &= Val == ToC;
}
- Constant *Replacement = nullptr;
if (AllSame && ToC->isNullValue()) {
- Replacement = ConstantAggregateZero::get(getType());
- } else if (AllSame && isa<UndefValue>(ToC)) {
- Replacement = UndefValue::get(getType());
- } else {
- // Check to see if we have this array type already.
- Lookup.second = makeArrayRef(Values);
- LLVMContextImpl::ArrayConstantsTy::MapTy::iterator I =
- pImpl->ArrayConstants.find(Lookup);
-
- if (I != pImpl->ArrayConstants.map_end()) {
- Replacement = I->first;
- } else {
- // Okay, the new shape doesn't exist in the system yet. Instead of
- // creating a new constant array, inserting it, replaceallusesof'ing the
- // old with the new, then deleting the old... just update the current one
- // in place!
- pImpl->ArrayConstants.remove(this);
-
- // Update to the new value. Optimize for the case when we have a single
- // operand that we're changing, but handle bulk updates efficiently.
- if (NumUpdated == 1) {
- unsigned OperandToUpdate = U - OperandList;
- assert(getOperand(OperandToUpdate) == From &&
- "ReplaceAllUsesWith broken!");
- setOperand(OperandToUpdate, ToC);
- } else {
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
- if (getOperand(i) == From)
- setOperand(i, ToC);
- }
- pImpl->ArrayConstants.insert(this);
- return;
- }
+ replaceUsesOfWithOnConstantImpl(ConstantAggregateZero::get(getType()));
+ return;
+ }
+ if (AllSame && isa<UndefValue>(ToC)) {
+ replaceUsesOfWithOnConstantImpl(UndefValue::get(getType()));
+ return;
}
- // Otherwise, I do need to replace this with an existing value.
- assert(Replacement != this && "I didn't contain From!");
-
- // Everyone using this now uses the replacement.
- replaceAllUsesWith(Replacement);
+ // Check for any other type of constant-folding.
+ if (Constant *C = getImpl(getType(), Values)) {
+ replaceUsesOfWithOnConstantImpl(C);
+ return;
+ }
- // Delete the old constant!
- destroyConstant();
+ // Update to the new value.
+ if (Constant *C = getContext().pImpl->ArrayConstants.replaceOperandsInPlace(
+ Values, this, From, ToC, NumUpdated, U - OperandList))
+ replaceUsesOfWithOnConstantImpl(C);
}
void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
@@ -2714,8 +2807,6 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
assert(getOperand(OperandToUpdate) == From && "ReplaceAllUsesWith broken!");
SmallVector<Constant*, 8> Values;
- LLVMContextImpl::StructConstantsTy::LookupKey Lookup;
- Lookup.first = cast<StructType>(getType());
Values.reserve(getNumOperands()); // Build replacement struct.
// Fill values with the modified operands of the constant struct. Also,
@@ -2742,64 +2833,47 @@ void ConstantStruct::replaceUsesOfWithOnConstant(Value *From, Value *To,
}
Values[OperandToUpdate] = ToC;
- LLVMContextImpl *pImpl = getContext().pImpl;
-
- Constant *Replacement = nullptr;
if (isAllZeros) {
- Replacement = ConstantAggregateZero::get(getType());
- } else if (isAllUndef) {
- Replacement = UndefValue::get(getType());
- } else {
- // Check to see if we have this struct type already.
- Lookup.second = makeArrayRef(Values);
- LLVMContextImpl::StructConstantsTy::MapTy::iterator I =
- pImpl->StructConstants.find(Lookup);
-
- if (I != pImpl->StructConstants.map_end()) {
- Replacement = I->first;
- } else {
- // Okay, the new shape doesn't exist in the system yet. Instead of
- // creating a new constant struct, inserting it, replaceallusesof'ing the
- // old with the new, then deleting the old... just update the current one
- // in place!
- pImpl->StructConstants.remove(this);
-
- // Update to the new value.
- setOperand(OperandToUpdate, ToC);
- pImpl->StructConstants.insert(this);
- return;
- }
+ replaceUsesOfWithOnConstantImpl(ConstantAggregateZero::get(getType()));
+ return;
+ }
+ if (isAllUndef) {
+ replaceUsesOfWithOnConstantImpl(UndefValue::get(getType()));
+ return;
}
- assert(Replacement != this && "I didn't contain From!");
-
- // Everyone using this now uses the replacement.
- replaceAllUsesWith(Replacement);
-
- // Delete the old constant!
- destroyConstant();
+ // Update to the new value.
+ if (Constant *C = getContext().pImpl->StructConstants.replaceOperandsInPlace(
+ Values, this, From, ToC))
+ replaceUsesOfWithOnConstantImpl(C);
}
void ConstantVector::replaceUsesOfWithOnConstant(Value *From, Value *To,
Use *U) {
assert(isa<Constant>(To) && "Cannot make Constant refer to non-constant!");
+ Constant *ToC = cast<Constant>(To);
SmallVector<Constant*, 8> Values;
Values.reserve(getNumOperands()); // Build replacement array...
+ unsigned NumUpdated = 0;
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
Constant *Val = getOperand(i);
- if (Val == From) Val = cast<Constant>(To);
+ if (Val == From) {
+ ++NumUpdated;
+ Val = ToC;
+ }
Values.push_back(Val);
}
- Constant *Replacement = get(Values);
- assert(Replacement != this && "I didn't contain From!");
-
- // Everyone using this now uses the replacement.
- replaceAllUsesWith(Replacement);
+ if (Constant *C = getImpl(Values)) {
+ replaceUsesOfWithOnConstantImpl(C);
+ return;
+ }
- // Delete the old constant!
- destroyConstant();
+ // Update to the new value.
+ if (Constant *C = getContext().pImpl->VectorConstants.replaceOperandsInPlace(
+ Values, this, From, ToC, NumUpdated, U - OperandList))
+ replaceUsesOfWithOnConstantImpl(C);
}
void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
@@ -2808,19 +2882,26 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV,
Constant *To = cast<Constant>(ToV);
SmallVector<Constant*, 8> NewOps;
+ unsigned NumUpdated = 0;
for (unsigned i = 0, e = getNumOperands(); i != e; ++i) {
Constant *Op = getOperand(i);
- NewOps.push_back(Op == From ? To : Op);
+ if (Op == From) {
+ ++NumUpdated;
+ Op = To;
+ }
+ NewOps.push_back(Op);
}
+ assert(NumUpdated && "I didn't contain From!");
- Constant *Replacement = getWithOperands(NewOps);
- assert(Replacement != this && "I didn't contain From!");
-
- // Everyone using this now uses the replacement.
- replaceAllUsesWith(Replacement);
+ if (Constant *C = getWithOperands(NewOps, getType(), true)) {
+ replaceUsesOfWithOnConstantImpl(C);
+ return;
+ }
- // Delete the old constant!
- destroyConstant();
+ // Update to the new value.
+ if (Constant *C = getContext().pImpl->ExprConstants.replaceOperandsInPlace(
+ NewOps, this, From, To, NumUpdated, U - OperandList))
+ replaceUsesOfWithOnConstantImpl(C);
}
Instruction *ConstantExpr::getAsInstruction() {
diff --git a/lib/IR/ConstantsContext.h b/lib/IR/ConstantsContext.h
index f06509fb73..571dec2e0f 100644
--- a/lib/IR/ConstantsContext.h
+++ b/lib/IR/ConstantsContext.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_CONSTANTSCONTEXT_H
-#define LLVM_CONSTANTSCONTEXT_H
+#ifndef LLVM_LIB_IR_CONSTANTSCONTEXT_H
+#define LLVM_LIB_IR_CONSTANTSCONTEXT_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/Hashing.h"
@@ -29,8 +29,6 @@
#define DEBUG_TYPE "ir"
namespace llvm {
-template<class ValType>
-struct ConstantTraits;
/// UnaryConstantExpr - This class is private to Constants.cpp, and is used
/// behind the scenes to implement unary constant exprs.
@@ -169,11 +167,10 @@ public:
void *operator new(size_t s) {
return User::operator new(s, 1);
}
- ExtractValueConstantExpr(Constant *Agg,
- const SmallVector<unsigned, 4> &IdxList,
+ ExtractValueConstantExpr(Constant *Agg, ArrayRef<unsigned> IdxList,
Type *DestTy)
- : ConstantExpr(DestTy, Instruction::ExtractValue, &Op<0>(), 1),
- Indices(IdxList) {
+ : ConstantExpr(DestTy, Instruction::ExtractValue, &Op<0>(), 1),
+ Indices(IdxList.begin(), IdxList.end()) {
Op<0>() = Agg;
}
@@ -196,10 +193,9 @@ public:
return User::operator new(s, 2);
}
InsertValueConstantExpr(Constant *Agg, Constant *Val,
- const SmallVector<unsigned, 4> &IdxList,
- Type *DestTy)
- : ConstantExpr(DestTy, Instruction::InsertValue, &Op<0>(), 2),
- Indices(IdxList) {
+ ArrayRef<unsigned> IdxList, Type *DestTy)
+ : ConstantExpr(DestTy, Instruction::InsertValue, &Op<0>(), 2),
+ Indices(IdxList.begin(), IdxList.end()) {
Op<0>() = Agg;
Op<1>() = Val;
}
@@ -316,379 +312,241 @@ struct OperandTraits<CompareConstantExpr> :
};
DEFINE_TRANSPARENT_OPERAND_ACCESSORS(CompareConstantExpr, Value)
-struct ExprMapKeyType {
- ExprMapKeyType(unsigned opc,
- ArrayRef<Constant*> ops,
- unsigned short flags = 0,
- unsigned short optionalflags = 0,
- ArrayRef<unsigned> inds = None)
- : opcode(opc), subclassoptionaldata(optionalflags), subclassdata(flags),
- operands(ops.begin(), ops.end()), indices(inds.begin(), inds.end()) {}
- uint8_t opcode;
- uint8_t subclassoptionaldata;
- uint16_t subclassdata;
- std::vector<Constant*> operands;
- SmallVector<unsigned, 4> indices;
- bool operator==(const ExprMapKeyType& that) const {
- return this->opcode == that.opcode &&
- this->subclassdata == that.subclassdata &&
- this->subclassoptionaldata == that.subclassoptionaldata &&
- this->operands == that.operands &&
- this->indices == that.indices;
- }
- bool operator<(const ExprMapKeyType & that) const {
- return std::tie(opcode, operands, subclassdata, subclassoptionaldata,
- indices) <
- std::tie(that.opcode, that.operands, that.subclassdata,
- that.subclassoptionaldata, that.indices);
- }
-
- bool operator!=(const ExprMapKeyType& that) const {
- return !(*this == that);
- }
-};
-
-struct InlineAsmKeyType {
- InlineAsmKeyType(StringRef AsmString,
- StringRef Constraints, bool hasSideEffects,
- bool isAlignStack, InlineAsm::AsmDialect asmDialect)
- : asm_string(AsmString), constraints(Constraints),
- has_side_effects(hasSideEffects), is_align_stack(isAlignStack),
- asm_dialect(asmDialect) {}
- std::string asm_string;
- std::string constraints;
- bool has_side_effects;
- bool is_align_stack;
- InlineAsm::AsmDialect asm_dialect;
- bool operator==(const InlineAsmKeyType& that) const {
- return this->asm_string == that.asm_string &&
- this->constraints == that.constraints &&
- this->has_side_effects == that.has_side_effects &&
- this->is_align_stack == that.is_align_stack &&
- this->asm_dialect == that.asm_dialect;
- }
- bool operator<(const InlineAsmKeyType& that) const {
- return std::tie(asm_string, constraints, has_side_effects, is_align_stack,
- asm_dialect) <
- std::tie(that.asm_string, that.constraints, that.has_side_effects,
- that.is_align_stack, that.asm_dialect);
- }
-
- bool operator!=(const InlineAsmKeyType& that) const {
- return !(*this == that);
- }
-};
+template <class ConstantClass> struct ConstantAggrKeyType;
+struct InlineAsmKeyType;
+struct ConstantExprKeyType;
-// The number of operands for each ConstantCreator::create method is
-// determined by the ConstantTraits template.
-// ConstantCreator - A class that is used to create constants by
-// ConstantUniqueMap*. This class should be partially specialized if there is
-// something strange that needs to be done to interface to the ctor for the
-// constant.
-//
-template<typename T, typename Alloc>
-struct ConstantTraits< std::vector<T, Alloc> > {
- static unsigned uses(const std::vector<T, Alloc>& v) {
- return v.size();
- }
-};
-
-template<>
-struct ConstantTraits<Constant *> {
- static unsigned uses(Constant * const & v) {
- return 1;
- }
+template <class ConstantClass> struct ConstantInfo;
+template <> struct ConstantInfo<ConstantExpr> {
+ typedef ConstantExprKeyType ValType;
+ typedef Type TypeClass;
};
-
-template<class ConstantClass, class TypeClass, class ValType>
-struct ConstantCreator {
- static ConstantClass *create(TypeClass *Ty, const ValType &V) {
- return new(ConstantTraits<ValType>::uses(V)) ConstantClass(Ty, V);
+template <> struct ConstantInfo<InlineAsm> {
+ typedef InlineAsmKeyType ValType;
+ typedef PointerType TypeClass;
+};
+template <> struct ConstantInfo<ConstantArray> {
+ typedef ConstantAggrKeyType<ConstantArray> ValType;
+ typedef ArrayType TypeClass;
+};
+template <> struct ConstantInfo<ConstantStruct> {
+ typedef ConstantAggrKeyType<ConstantStruct> ValType;
+ typedef StructType TypeClass;
+};
+template <> struct ConstantInfo<ConstantVector> {
+ typedef ConstantAggrKeyType<ConstantVector> ValType;
+ typedef VectorType TypeClass;
+};
+
+template <class ConstantClass> struct ConstantAggrKeyType {
+ ArrayRef<Constant *> Operands;
+ ConstantAggrKeyType(ArrayRef<Constant *> Operands) : Operands(Operands) {}
+ ConstantAggrKeyType(ArrayRef<Constant *> Operands, const ConstantClass *)
+ : Operands(Operands) {}
+ ConstantAggrKeyType(const ConstantClass *C,
+ SmallVectorImpl<Constant *> &Storage) {
+ assert(Storage.empty() && "Expected empty storage");
+ for (unsigned I = 0, E = C->getNumOperands(); I != E; ++I)
+ Storage.push_back(C->getOperand(I));
+ Operands = Storage;
+ }
+
+ bool operator==(const ConstantAggrKeyType &X) const {
+ return Operands == X.Operands;
+ }
+ bool operator==(const ConstantClass *C) const {
+ if (Operands.size() != C->getNumOperands())
+ return false;
+ for (unsigned I = 0, E = Operands.size(); I != E; ++I)
+ if (Operands[I] != C->getOperand(I))
+ return false;
+ return true;
}
-};
-
-template<class ConstantClass, class TypeClass>
-struct ConstantArrayCreator {
- static ConstantClass *create(TypeClass *Ty, ArrayRef<Constant*> V) {
- return new(V.size()) ConstantClass(Ty, V);
+ unsigned getHash() const {
+ return hash_combine_range(Operands.begin(), Operands.end());
}
-};
-template<class ConstantClass>
-struct ConstantKeyData {
- typedef void ValType;
- static ValType getValType(ConstantClass *C) {
- llvm_unreachable("Unknown Constant type!");
+ typedef typename ConstantInfo<ConstantClass>::TypeClass TypeClass;
+ ConstantClass *create(TypeClass *Ty) const {
+ return new (Operands.size()) ConstantClass(Ty, Operands);
}
};
-template<>
-struct ConstantCreator<ConstantExpr, Type, ExprMapKeyType> {
- static ConstantExpr *create(Type *Ty, const ExprMapKeyType &V,
- unsigned short pred = 0) {
- if (Instruction::isCast(V.opcode))
- return new UnaryConstantExpr(V.opcode, V.operands[0], Ty);
- if ((V.opcode >= Instruction::BinaryOpsBegin &&
- V.opcode < Instruction::BinaryOpsEnd))
- return new BinaryConstantExpr(V.opcode, V.operands[0], V.operands[1],
- V.subclassoptionaldata);
- if (V.opcode == Instruction::Select)
- return new SelectConstantExpr(V.operands[0], V.operands[1],
- V.operands[2]);
- if (V.opcode == Instruction::ExtractElement)
- return new ExtractElementConstantExpr(V.operands[0], V.operands[1]);
- if (V.opcode == Instruction::InsertElement)
- return new InsertElementConstantExpr(V.operands[0], V.operands[1],
- V.operands[2]);
- if (V.opcode == Instruction::ShuffleVector)
- return new ShuffleVectorConstantExpr(V.operands[0], V.operands[1],
- V.operands[2]);
- if (V.opcode == Instruction::InsertValue)
- return new InsertValueConstantExpr(V.operands[0], V.operands[1],
- V.indices, Ty);
- if (V.opcode == Instruction::ExtractValue)
- return new ExtractValueConstantExpr(V.operands[0], V.indices, Ty);
- if (V.opcode == Instruction::GetElementPtr) {
- std::vector<Constant*> IdxList(V.operands.begin()+1, V.operands.end());
- return GetElementPtrConstantExpr::Create(V.operands[0], IdxList, Ty,
- V.subclassoptionaldata);
+struct InlineAsmKeyType {
+ StringRef AsmString;
+ StringRef Constraints;
+ bool HasSideEffects;
+ bool IsAlignStack;
+ InlineAsm::AsmDialect AsmDialect;
+
+ InlineAsmKeyType(StringRef AsmString, StringRef Constraints,
+ bool HasSideEffects, bool IsAlignStack,
+ InlineAsm::AsmDialect AsmDialect)
+ : AsmString(AsmString), Constraints(Constraints),
+ HasSideEffects(HasSideEffects), IsAlignStack(IsAlignStack),
+ AsmDialect(AsmDialect) {}
+ InlineAsmKeyType(const InlineAsm *Asm, SmallVectorImpl<Constant *> &)
+ : AsmString(Asm->getAsmString()), Constraints(Asm->getConstraintString()),
+ HasSideEffects(Asm->hasSideEffects()),
+ IsAlignStack(Asm->isAlignStack()), AsmDialect(Asm->getDialect()) {}
+
+ bool operator==(const InlineAsmKeyType &X) const {
+ return HasSideEffects == X.HasSideEffects &&
+ IsAlignStack == X.IsAlignStack && AsmDialect == X.AsmDialect &&
+ AsmString == X.AsmString && Constraints == X.Constraints;
+ }
+ bool operator==(const InlineAsm *Asm) const {
+ return HasSideEffects == Asm->hasSideEffects() &&
+ IsAlignStack == Asm->isAlignStack() &&
+ AsmDialect == Asm->getDialect() &&
+ AsmString == Asm->getAsmString() &&
+ Constraints == Asm->getConstraintString();
+ }
+ unsigned getHash() const {
+ return hash_combine(AsmString, Constraints, HasSideEffects, IsAlignStack,
+ AsmDialect);
+ }
+
+ typedef ConstantInfo<InlineAsm>::TypeClass TypeClass;
+ InlineAsm *create(TypeClass *Ty) const {
+ return new InlineAsm(Ty, AsmString, Constraints, HasSideEffects,
+ IsAlignStack, AsmDialect);
+ }
+};
+
+struct ConstantExprKeyType {
+ uint8_t Opcode;
+ uint8_t SubclassOptionalData;
+ uint16_t SubclassData;
+ ArrayRef<Constant *> Ops;
+ ArrayRef<unsigned> Indexes;
+
+ ConstantExprKeyType(unsigned Opcode, ArrayRef<Constant *> Ops,
+ unsigned short SubclassData = 0,
+ unsigned short SubclassOptionalData = 0,
+ ArrayRef<unsigned> Indexes = None)
+ : Opcode(Opcode), SubclassOptionalData(SubclassOptionalData),
+ SubclassData(SubclassData), Ops(Ops), Indexes(Indexes) {}
+ ConstantExprKeyType(ArrayRef<Constant *> Operands, const ConstantExpr *CE)
+ : Opcode(CE->getOpcode()),
+ SubclassOptionalData(CE->getRawSubclassOptionalData()),
+ SubclassData(CE->isCompare() ? CE->getPredicate() : 0), Ops(Operands),
+ Indexes(CE->hasIndices() ? CE->getIndices() : ArrayRef<unsigned>()) {}
+ ConstantExprKeyType(const ConstantExpr *CE,
+ SmallVectorImpl<Constant *> &Storage)
+ : Opcode(CE->getOpcode()),
+ SubclassOptionalData(CE->getRawSubclassOptionalData()),
+ SubclassData(CE->isCompare() ? CE->getPredicate() : 0),
+ Indexes(CE->hasIndices() ? CE->getIndices() : ArrayRef<unsigned>()) {
+ assert(Storage.empty() && "Expected empty storage");
+ for (unsigned I = 0, E = CE->getNumOperands(); I != E; ++I)
+ Storage.push_back(CE->getOperand(I));
+ Ops = Storage;
+ }
+
+ bool operator==(const ConstantExprKeyType &X) const {
+ return Opcode == X.Opcode && SubclassData == X.SubclassData &&
+ SubclassOptionalData == X.SubclassOptionalData && Ops == X.Ops &&
+ Indexes == X.Indexes;
+ }
+
+ bool operator==(const ConstantExpr *CE) const {
+ if (Opcode != CE->getOpcode())
+ return false;
+ if (SubclassOptionalData != CE->getRawSubclassOptionalData())
+ return false;
+ if (Ops.size() != CE->getNumOperands())
+ return false;
+ if (SubclassData != (CE->isCompare() ? CE->getPredicate() : 0))
+ return false;
+ for (unsigned I = 0, E = Ops.size(); I != E; ++I)
+ if (Ops[I] != CE->getOperand(I))
+ return false;
+ if (Indexes != (CE->hasIndices() ? CE->getIndices() : ArrayRef<unsigned>()))
+ return false;
+ return true;
+ }
+
+ unsigned getHash() const {
+ return hash_combine(Opcode, SubclassOptionalData, SubclassData,
+ hash_combine_range(Ops.begin(), Ops.end()),
+ hash_combine_range(Indexes.begin(), Indexes.end()));
+ }
+
+ typedef ConstantInfo<ConstantExpr>::TypeClass TypeClass;
+ ConstantExpr *create(TypeClass *Ty) const {
+ switch (Opcode) {
+ default:
+ if (Instruction::isCast(Opcode))
+ return new UnaryConstantExpr(Opcode, Ops[0], Ty);
+ if ((Opcode >= Instruction::BinaryOpsBegin &&
+ Opcode < Instruction::BinaryOpsEnd))
+ return new BinaryConstantExpr(Opcode, Ops[0], Ops[1],
+ SubclassOptionalData);
+ llvm_unreachable("Invalid ConstantExpr!");
+ case Instruction::Select:
+ return new SelectConstantExpr(Ops[0], Ops[1], Ops[2]);
+ case Instruction::ExtractElement:
+ return new ExtractElementConstantExpr(Ops[0], Ops[1]);
+ case Instruction::InsertElement:
+ return new InsertElementConstantExpr(Ops[0], Ops[1], Ops[2]);
+ case Instruction::ShuffleVector:
+ return new ShuffleVectorConstantExpr(Ops[0], Ops[1], Ops[2]);
+ case Instruction::InsertValue:
+ return new InsertValueConstantExpr(Ops[0], Ops[1], Indexes, Ty);
+ case Instruction::ExtractValue:
+ return new ExtractValueConstantExpr(Ops[0], Indexes, Ty);
+ case Instruction::GetElementPtr:
+ return GetElementPtrConstantExpr::Create(Ops[0], Ops.slice(1), Ty,
+ SubclassOptionalData);
+ case Instruction::ICmp:
+ return new CompareConstantExpr(Ty, Instruction::ICmp, SubclassData,
+ Ops[0], Ops[1]);
+ case Instruction::FCmp:
+ return new CompareConstantExpr(Ty, Instruction::FCmp, SubclassData,
+ Ops[0], Ops[1]);
}
-
- // The compare instructions are weird. We have to encode the predicate
- // value and it is combined with the instruction opcode by multiplying
- // the opcode by one hundred. We must decode this to get the predicate.
- if (V.opcode == Instruction::ICmp)
- return new CompareConstantExpr(Ty, Instruction::ICmp, V.subclassdata,
- V.operands[0], V.operands[1]);
- if (V.opcode == Instruction::FCmp)
- return new CompareConstantExpr(Ty, Instruction::FCmp, V.subclassdata,
- V.operands[0], V.operands[1]);
- llvm_unreachable("Invalid ConstantExpr!");
- }
-};
-
-template<>
-struct ConstantKeyData<ConstantExpr> {
- typedef ExprMapKeyType ValType;
- static ValType getValType(ConstantExpr *CE) {
- std::vector<Constant*> Operands;
- Operands.reserve(CE->getNumOperands());
- for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i)
- Operands.push_back(cast<Constant>(CE->getOperand(i)));
- return ExprMapKeyType(CE->getOpcode(), Operands,
- CE->isCompare() ? CE->getPredicate() : 0,
- CE->getRawSubclassOptionalData(),
- CE->hasIndices() ?
- CE->getIndices() : ArrayRef<unsigned>());
- }
-};
-
-template<>
-struct ConstantCreator<InlineAsm, PointerType, InlineAsmKeyType> {
- static InlineAsm *create(PointerType *Ty, const InlineAsmKeyType &Key) {
- return new InlineAsm(Ty, Key.asm_string, Key.constraints,
- Key.has_side_effects, Key.is_align_stack,
- Key.asm_dialect);
}
};
-template<>
-struct ConstantKeyData<InlineAsm> {
- typedef InlineAsmKeyType ValType;
- static ValType getValType(InlineAsm *Asm) {
- return InlineAsmKeyType(Asm->getAsmString(), Asm->getConstraintString(),
- Asm->hasSideEffects(), Asm->isAlignStack(),
- Asm->getDialect());
- }
-};
-
-template<class ValType, class ValRefType, class TypeClass, class ConstantClass,
- bool HasLargeKey = false /*true for arrays and structs*/ >
-class ConstantUniqueMap {
-public:
- typedef std::pair<TypeClass*, ValType> MapKey;
- typedef std::map<MapKey, ConstantClass *> MapTy;
- typedef std::map<ConstantClass *, typename MapTy::iterator> InverseMapTy;
-private:
- /// Map - This is the main map from the element descriptor to the Constants.
- /// This is the primary way we avoid creating two of the same shape
- /// constant.
- MapTy Map;
-
- /// InverseMap - If "HasLargeKey" is true, this contains an inverse mapping
- /// from the constants to their element in Map. This is important for
- /// removal of constants from the array, which would otherwise have to scan
- /// through the map with very large keys.
- InverseMapTy InverseMap;
-
-public:
- typename MapTy::iterator map_begin() { return Map.begin(); }
- typename MapTy::iterator map_end() { return Map.end(); }
-
- void freeConstants() {
- for (typename MapTy::iterator I=Map.begin(), E=Map.end();
- I != E; ++I) {
- // Asserts that use_empty().
- delete I->second;
- }
- }
-
- /// InsertOrGetItem - Return an iterator for the specified element.
- /// If the element exists in the map, the returned iterator points to the
- /// entry and Exists=true. If not, the iterator points to the newly
- /// inserted entry and returns Exists=false. Newly inserted entries have
- /// I->second == 0, and should be filled in.
- typename MapTy::iterator InsertOrGetItem(std::pair<MapKey, ConstantClass *>
- &InsertVal,
- bool &Exists) {
- std::pair<typename MapTy::iterator, bool> IP = Map.insert(InsertVal);
- Exists = !IP.second;
- return IP.first;
- }
-
-private:
- typename MapTy::iterator FindExistingElement(ConstantClass *CP) {
- if (HasLargeKey) {
- typename InverseMapTy::iterator IMI = InverseMap.find(CP);
- assert(IMI != InverseMap.end() && IMI->second != Map.end() &&
- IMI->second->second == CP &&
- "InverseMap corrupt!");
- return IMI->second;
- }
-
- typename MapTy::iterator I =
- Map.find(MapKey(static_cast<TypeClass*>(CP->getType()),
- ConstantKeyData<ConstantClass>::getValType(CP)));
- if (I == Map.end() || I->second != CP) {
- // FIXME: This should not use a linear scan. If this gets to be a
- // performance problem, someone should look at this.
- for (I = Map.begin(); I != Map.end() && I->second != CP; ++I)
- /* empty */;
- }
- return I;
- }
-
- ConstantClass *Create(TypeClass *Ty, ValRefType V,
- typename MapTy::iterator I) {
- ConstantClass* Result =
- ConstantCreator<ConstantClass,TypeClass,ValType>::create(Ty, V);
-
- assert(Result->getType() == Ty && "Type specified is not correct!");
- I = Map.insert(I, std::make_pair(MapKey(Ty, V), Result));
-
- if (HasLargeKey) // Remember the reverse mapping if needed.
- InverseMap.insert(std::make_pair(Result, I));
-
- return Result;
- }
+template <class ConstantClass> class ConstantUniqueMap {
public:
-
- /// getOrCreate - Return the specified constant from the map, creating it if
- /// necessary.
- ConstantClass *getOrCreate(TypeClass *Ty, ValRefType V) {
- MapKey Lookup(Ty, V);
- ConstantClass* Result = nullptr;
-
- typename MapTy::iterator I = Map.find(Lookup);
- // Is it in the map?
- if (I != Map.end())
- Result = I->second;
-
- if (!Result) {
- // If no preexisting value, create one now...
- Result = Create(Ty, V, I);
- }
-
- return Result;
- }
-
- void remove(ConstantClass *CP) {
- typename MapTy::iterator I = FindExistingElement(CP);
- assert(I != Map.end() && "Constant not found in constant table!");
- assert(I->second == CP && "Didn't find correct element?");
-
- if (HasLargeKey) // Remember the reverse mapping if needed.
- InverseMap.erase(CP);
-
- Map.erase(I);
- }
-
- /// MoveConstantToNewSlot - If we are about to change C to be the element
- /// specified by I, update our internal data structures to reflect this
- /// fact.
- void MoveConstantToNewSlot(ConstantClass *C, typename MapTy::iterator I) {
- // First, remove the old location of the specified constant in the map.
- typename MapTy::iterator OldI = FindExistingElement(C);
- assert(OldI != Map.end() && "Constant not found in constant table!");
- assert(OldI->second == C && "Didn't find correct element?");
-
- // Remove the old entry from the map.
- Map.erase(OldI);
-
- // Update the inverse map so that we know that this constant is now
- // located at descriptor I.
- if (HasLargeKey) {
- assert(I->second == C && "Bad inversemap entry!");
- InverseMap[C] = I;
- }
- }
+ typedef typename ConstantInfo<ConstantClass>::ValType ValType;
+ typedef typename ConstantInfo<ConstantClass>::TypeClass TypeClass;
+ typedef std::pair<TypeClass *, ValType> LookupKey;
- void dump() const {
- DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n");
- }
-};
-
-// Unique map for aggregate constants
-template<class TypeClass, class ConstantClass>
-class ConstantAggrUniqueMap {
-public:
- typedef ArrayRef<Constant*> Operands;
- typedef std::pair<TypeClass*, Operands> LookupKey;
private:
struct MapInfo {
- typedef DenseMapInfo<ConstantClass*> ConstantClassInfo;
- typedef DenseMapInfo<Constant*> ConstantInfo;
- typedef DenseMapInfo<TypeClass*> TypeClassInfo;
- static inline ConstantClass* getEmptyKey() {
+ typedef DenseMapInfo<ConstantClass *> ConstantClassInfo;
+ static inline ConstantClass *getEmptyKey() {
return ConstantClassInfo::getEmptyKey();
}
- static inline ConstantClass* getTombstoneKey() {
+ static inline ConstantClass *getTombstoneKey() {
return ConstantClassInfo::getTombstoneKey();
}
static unsigned getHashValue(const ConstantClass *CP) {
- SmallVector<Constant*, 8> CPOperands;
- CPOperands.reserve(CP->getNumOperands());
- for (unsigned I = 0, E = CP->getNumOperands(); I < E; ++I)
- CPOperands.push_back(CP->getOperand(I));
- return getHashValue(LookupKey(CP->getType(), CPOperands));
+ SmallVector<Constant *, 8> Storage;
+ return getHashValue(LookupKey(CP->getType(), ValType(CP, Storage)));
}
static bool isEqual(const ConstantClass *LHS, const ConstantClass *RHS) {
return LHS == RHS;
}
static unsigned getHashValue(const LookupKey &Val) {
- return hash_combine(Val.first, hash_combine_range(Val.second.begin(),
- Val.second.end()));
+ return hash_combine(Val.first, Val.second.getHash());
}
static bool isEqual(const LookupKey &LHS, const ConstantClass *RHS) {
if (RHS == getEmptyKey() || RHS == getTombstoneKey())
return false;
- if (LHS.first != RHS->getType()
- || LHS.second.size() != RHS->getNumOperands())
+ if (LHS.first != RHS->getType())
return false;
- for (unsigned I = 0, E = RHS->getNumOperands(); I < E; ++I) {
- if (LHS.second[I] != RHS->getOperand(I))
- return false;
- }
- return true;
+ return LHS.second == RHS;
}
};
+
public:
typedef DenseMap<ConstantClass *, char, MapInfo> MapTy;
private:
- /// Map - This is the main map from the element descriptor to the Constants.
- /// This is the primary way we avoid creating two of the same shape
- /// constant.
MapTy Map;
public:
@@ -696,44 +554,33 @@ public:
typename MapTy::iterator map_end() { return Map.end(); }
void freeConstants() {
- for (typename MapTy::iterator I=Map.begin(), E=Map.end();
- I != E; ++I) {
+ for (auto &I : Map)
// Asserts that use_empty().
- delete I->first;
- }
+ delete I.first;
}
private:
- typename MapTy::iterator findExistingElement(ConstantClass *CP) {
- return Map.find(CP);
- }
-
- ConstantClass *Create(TypeClass *Ty, Operands V, typename MapTy::iterator I) {
- ConstantClass* Result =
- ConstantArrayCreator<ConstantClass,TypeClass>::create(Ty, V);
+ ConstantClass *create(TypeClass *Ty, ValType V) {
+ ConstantClass *Result = V.create(Ty);
assert(Result->getType() == Ty && "Type specified is not correct!");
- Map[Result] = '\0';
+ insert(Result);
return Result;
}
-public:
- /// getOrCreate - Return the specified constant from the map, creating it if
- /// necessary.
- ConstantClass *getOrCreate(TypeClass *Ty, Operands V) {
+public:
+ /// Return the specified constant from the map, creating it if necessary.
+ ConstantClass *getOrCreate(TypeClass *Ty, ValType V) {
LookupKey Lookup(Ty, V);
- ConstantClass* Result = nullptr;
+ ConstantClass *Result = nullptr;
- typename MapTy::iterator I = Map.find_as(Lookup);
- // Is it in the map?
- if (I != Map.end())
+ auto I = find(Lookup);
+ if (I == Map.end())
+ Result = create(Ty, V);
+ else
Result = I->first;
-
- if (!Result) {
- // If no preexisting value, create one now...
- Result = Create(Ty, V, I);
- }
+ assert(Result && "Unexpected nullptr");
return Result;
}
@@ -744,23 +591,44 @@ public:
}
/// Insert the constant into its proper slot.
- void insert(ConstantClass *CP) {
- Map[CP] = '\0';
- }
+ void insert(ConstantClass *CP) { Map[CP] = '\0'; }
/// Remove this constant from the map
void remove(ConstantClass *CP) {
- typename MapTy::iterator I = findExistingElement(CP);
+ typename MapTy::iterator I = Map.find(CP);
assert(I != Map.end() && "Constant not found in constant table!");
assert(I->first == CP && "Didn't find correct element?");
Map.erase(I);
}
- void dump() const {
- DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n");
+ ConstantClass *replaceOperandsInPlace(ArrayRef<Constant *> Operands,
+ ConstantClass *CP, Value *From,
+ Constant *To, unsigned NumUpdated = 0,
+ unsigned OperandNo = ~0u) {
+ LookupKey Lookup(CP->getType(), ValType(Operands, CP));
+ auto I = find(Lookup);
+ if (I != Map.end())
+ return I->first;
+
+ // Update to the new value. Optimize for the case when we have a single
+ // operand that we're changing, but handle bulk updates efficiently.
+ remove(CP);
+ if (NumUpdated == 1) {
+ assert(OperandNo < CP->getNumOperands() && "Invalid index");
+ assert(CP->getOperand(OperandNo) != To && "I didn't contain From!");
+ CP->setOperand(OperandNo, To);
+ } else {
+ for (unsigned I = 0, E = CP->getNumOperands(); I != E; ++I)
+ if (CP->getOperand(I) == From)
+ CP->setOperand(I, To);
+ }
+ insert(CP);
+ return nullptr;
}
+
+ void dump() const { DEBUG(dbgs() << "Constant.cpp: ConstantUniqueMap\n"); }
};
-}
+} // end namespace llvm
#endif
diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp
index 87099a6c4e..3576137dd3 100644
--- a/lib/IR/Core.cpp
+++ b/lib/IR/Core.cpp
@@ -183,20 +183,22 @@ void LLVMDumpModule(LLVMModuleRef M) {
LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename,
char **ErrorMessage) {
- std::string error;
- raw_fd_ostream dest(Filename, error, sys::fs::F_Text);
- if (!error.empty()) {
- *ErrorMessage = strdup(error.c_str());
+ std::error_code EC;
+ raw_fd_ostream dest(Filename, EC, sys::fs::F_Text);
+ if (EC) {
+ *ErrorMessage = strdup(EC.message().c_str());
return true;
}
unwrap(M)->print(dest, nullptr);
- if (!error.empty()) {
- *ErrorMessage = strdup(error.c_str());
+ dest.close();
+
+ if (dest.has_error()) {
+ *ErrorMessage = strdup("Error printing to file");
return true;
}
- dest.flush();
+
return false;
}
@@ -558,8 +560,8 @@ LLVMValueRef LLVMGetMetadata(LLVMValueRef Inst, unsigned KindID) {
}
void LLVMSetMetadata(LLVMValueRef Inst, unsigned KindID, LLVMValueRef MD) {
- unwrap<Instruction>(Inst)->setMetadata(KindID,
- MD ? unwrap<MDNode>(MD) : nullptr);
+ unwrap<Instruction>(Inst)
+ ->setMetadata(KindID, MD ? unwrap<MDNode>(MD) : nullptr);
}
/*--.. Conversion functions ................................................--*/
@@ -603,6 +605,11 @@ LLVMValueRef LLVMGetOperand(LLVMValueRef Val, unsigned Index) {
return wrap(cast<User>(V)->getOperand(Index));
}
+LLVMUseRef LLVMGetOperandUse(LLVMValueRef Val, unsigned Index) {
+ Value *V = unwrap(Val);
+ return wrap(&cast<User>(V)->getOperandUse(Index));
+}
+
void LLVMSetOperand(LLVMValueRef Val, unsigned Index, LLVMValueRef Op) {
unwrap<User>(Val)->setOperand(Index, unwrap(Op));
}
@@ -767,6 +774,27 @@ long long LLVMConstIntGetSExtValue(LLVMValueRef ConstantVal) {
return unwrap<ConstantInt>(ConstantVal)->getSExtValue();
}
+double LLVMConstRealGetDouble(LLVMValueRef ConstantVal, LLVMBool *LosesInfo) {
+ ConstantFP *cFP = unwrap<ConstantFP>(ConstantVal) ;
+ Type *Ty = cFP->getType();
+
+ if (Ty->isFloatTy()) {
+ *LosesInfo = false;
+ return cFP->getValueAPF().convertToFloat();
+ }
+
+ if (Ty->isDoubleTy()) {
+ *LosesInfo = false;
+ return cFP->getValueAPF().convertToDouble();
+ }
+
+ bool APFLosesInfo;
+ APFloat APF = cFP->getValueAPF();
+ APF.convert(APFloat::IEEEdouble, APFloat::rmNearestTiesToEven, &APFLosesInfo);
+ *LosesInfo = APFLosesInfo;
+ return APF.convertToDouble();
+}
+
/*--.. Operations on composite constants ...................................--*/
LLVMValueRef LLVMConstStringInContext(LLVMContextRef C, const char *Str,
@@ -790,11 +818,27 @@ LLVMValueRef LLVMConstString(const char *Str, unsigned Length,
return LLVMConstStringInContext(LLVMGetGlobalContext(), Str, Length,
DontNullTerminate);
}
+
+LLVMValueRef LLVMGetElementAsConstant(LLVMValueRef c, unsigned idx) {
+ return wrap(static_cast<ConstantDataSequential*>(unwrap(c))->getElementAsConstant(idx));
+}
+
+LLVMBool LLVMIsConstantString(LLVMValueRef c) {
+ return static_cast<ConstantDataSequential*>(unwrap(c))->isString();
+}
+
+const char *LLVMGetAsString(LLVMValueRef c, size_t* Length) {
+ StringRef str = static_cast<ConstantDataSequential*>(unwrap(c))->getAsString();
+ *Length = str.size();
+ return str.data();
+}
+
LLVMValueRef LLVMConstArray(LLVMTypeRef ElementTy,
LLVMValueRef *ConstantVals, unsigned Length) {
ArrayRef<Constant*> V(unwrap<Constant>(ConstantVals, Length), Length);
return wrap(ConstantArray::get(ArrayType::get(unwrap(ElementTy), Length), V));
}
+
LLVMValueRef LLVMConstStruct(LLVMValueRef *ConstantVals, unsigned Count,
LLVMBool Packed) {
return LLVMConstStructInContext(LLVMGetGlobalContext(), ConstantVals, Count,
@@ -1859,12 +1903,27 @@ LLVMIntPredicate LLVMGetICmpPredicate(LLVMValueRef Inst) {
return (LLVMIntPredicate)0;
}
+LLVMRealPredicate LLVMGetFCmpPredicate(LLVMValueRef Inst) {
+ if (FCmpInst *I = dyn_cast<FCmpInst>(unwrap(Inst)))
+ return (LLVMRealPredicate)I->getPredicate();
+ if (ConstantExpr *CE = dyn_cast<ConstantExpr>(unwrap(Inst)))
+ if (CE->getOpcode() == Instruction::FCmp)
+ return (LLVMRealPredicate)CE->getPredicate();
+ return (LLVMRealPredicate)0;
+}
+
LLVMOpcode LLVMGetInstructionOpcode(LLVMValueRef Inst) {
if (Instruction *C = dyn_cast<Instruction>(unwrap(Inst)))
return map_to_llvmopcode(C->getOpcode());
return (LLVMOpcode)0;
}
+LLVMValueRef LLVMInstructionClone(LLVMValueRef Inst) {
+ if (Instruction *C = dyn_cast<Instruction>(unwrap(Inst)))
+ return wrap(C->clone());
+ return nullptr;
+}
+
/*--.. Call and invoke instructions ........................................--*/
unsigned LLVMGetInstructionCallConv(LLVMValueRef Instr) {
@@ -1926,6 +1985,34 @@ void LLVMSetTailCall(LLVMValueRef Call, LLVMBool isTailCall) {
unwrap<CallInst>(Call)->setTailCall(isTailCall);
}
+/*--.. Operations on terminators ...........................................--*/
+
+unsigned LLVMGetNumSuccessors(LLVMValueRef Term) {
+ return unwrap<TerminatorInst>(Term)->getNumSuccessors();
+}
+
+LLVMBasicBlockRef LLVMGetSuccessor(LLVMValueRef Term, unsigned i) {
+ return wrap(unwrap<TerminatorInst>(Term)->getSuccessor(i));
+}
+
+void LLVMSetSuccessor(LLVMValueRef Term, unsigned i, LLVMBasicBlockRef block) {
+ return unwrap<TerminatorInst>(Term)->setSuccessor(i,unwrap(block));
+}
+
+/*--.. Operations on branch instructions (only) ............................--*/
+
+LLVMBool LLVMIsConditional(LLVMValueRef Branch) {
+ return unwrap<BranchInst>(Branch)->isConditional();
+}
+
+LLVMValueRef LLVMGetCondition(LLVMValueRef Branch) {
+ return wrap(unwrap<BranchInst>(Branch)->getCondition());
+}
+
+void LLVMSetCondition(LLVMValueRef Branch, LLVMValueRef Cond) {
+ return unwrap<BranchInst>(Branch)->setCondition(unwrap(Cond));
+}
+
/*--.. Operations on switch instructions (only) ............................--*/
LLVMBasicBlockRef LLVMGetSwitchDefaultDest(LLVMValueRef Switch) {
@@ -2313,7 +2400,7 @@ static AtomicOrdering mapFromLLVMOrdering(LLVMAtomicOrdering Ordering) {
case LLVMAtomicOrderingSequentiallyConsistent:
return SequentiallyConsistent;
}
-
+
llvm_unreachable("Invalid LLVMAtomicOrdering value!");
}
@@ -2632,10 +2719,9 @@ LLVMMemoryBufferRef LLVMCreateMemoryBufferWithMemoryRange(
const char *BufferName,
LLVMBool RequiresNullTerminator) {
- return wrap(MemoryBuffer::getMemBuffer(
- StringRef(InputData, InputDataLength),
- StringRef(BufferName),
- RequiresNullTerminator));
+ return wrap(MemoryBuffer::getMemBuffer(StringRef(InputData, InputDataLength),
+ StringRef(BufferName),
+ RequiresNullTerminator).release());
}
LLVMMemoryBufferRef LLVMCreateMemoryBufferWithMemoryRangeCopy(
@@ -2643,9 +2729,9 @@ LLVMMemoryBufferRef LLVMCreateMemoryBufferWithMemoryRangeCopy(
size_t InputDataLength,
const char *BufferName) {
- return wrap(MemoryBuffer::getMemBufferCopy(
- StringRef(InputData, InputDataLength),
- StringRef(BufferName)));
+ return wrap(
+ MemoryBuffer::getMemBufferCopy(StringRef(InputData, InputDataLength),
+ StringRef(BufferName)).release());
}
const char *LLVMGetBufferStart(LLVMMemoryBufferRef MemBuf) {
diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp
index 218787c993..4fe2be61b8 100644
--- a/lib/IR/DIBuilder.cpp
+++ b/lib/IR/DIBuilder.cpp
@@ -23,10 +23,29 @@
using namespace llvm;
using namespace llvm::dwarf;
-static Constant *GetTagConstant(LLVMContext &VMContext, unsigned Tag) {
- assert((Tag & LLVMDebugVersionMask) == 0 &&
- "Tag too large for debug encoding!");
- return ConstantInt::get(Type::getInt32Ty(VMContext), Tag | LLVMDebugVersion);
+namespace {
+class HeaderBuilder {
+ SmallVector<char, 256> Chars;
+
+public:
+ explicit HeaderBuilder(Twine T) { T.toVector(Chars); }
+ HeaderBuilder(const HeaderBuilder &X) : Chars(X.Chars) {}
+ HeaderBuilder(HeaderBuilder &&X) : Chars(std::move(X.Chars)) {}
+
+ template <class Twineable> HeaderBuilder &concat(Twineable &&X) {
+ Chars.push_back(0);
+ Twine(X).toVector(Chars);
+ return *this;
+ }
+
+ MDString *get(LLVMContext &Context) const {
+ return MDString::get(Context, StringRef(Chars.begin(), Chars.size()));
+ }
+
+ static HeaderBuilder get(unsigned Tag) {
+ return HeaderBuilder("0x" + Twine::utohexstr(Tag));
+ }
+};
}
DIBuilder::DIBuilder(Module &m)
@@ -34,7 +53,6 @@ DIBuilder::DIBuilder(Module &m)
TempRetainTypes(nullptr), TempSubprograms(nullptr), TempGVs(nullptr),
DeclareFn(nullptr), ValueFn(nullptr) {}
-/// finalize - Construct any deferred debug info descriptors.
void DIBuilder::finalize() {
DIArray Enums = getOrCreateArray(AllEnumTypes);
DIType(TempEnumTypes).replaceAllUsesWith(Enums);
@@ -46,7 +64,7 @@ void DIBuilder::finalize() {
// TrackingVHs back into Values.
SmallPtrSet<Value *, 16> RetainSet;
for (unsigned I = 0, E = AllRetainTypes.size(); I < E; I++)
- if (RetainSet.insert(AllRetainTypes[I]))
+ if (RetainSet.insert(AllRetainTypes[I]).second)
RetainValues.push_back(AllRetainTypes[I]);
DIArray RetainTypes = getOrCreateArray(RetainValues);
DIType(TempRetainTypes).replaceAllUsesWith(RetainTypes);
@@ -55,13 +73,10 @@ void DIBuilder::finalize() {
DIType(TempSubprograms).replaceAllUsesWith(SPs);
for (unsigned i = 0, e = SPs.getNumElements(); i != e; ++i) {
DISubprogram SP(SPs.getElement(i));
- SmallVector<Value *, 4> Variables;
- if (NamedMDNode *NMD = getFnSpecificMDNode(M, SP)) {
- for (unsigned ii = 0, ee = NMD->getNumOperands(); ii != ee; ++ii)
- Variables.push_back(NMD->getOperand(ii));
- NMD->eraseFromParent();
- }
if (MDNode *Temp = SP.getVariablesNodes()) {
+ SmallVector<Value *, 4> Variables;
+ for (Value *V : PreservedVariables.lookup(SP))
+ Variables.push_back(V);
DIArray AV = getOrCreateArray(Variables);
DIType(Temp).replaceAllUsesWith(AV);
}
@@ -77,8 +92,7 @@ void DIBuilder::finalize() {
DIType(TempImportedModules).replaceAllUsesWith(IMs);
}
-/// getNonCompileUnitScope - If N is compile unit return NULL otherwise return
-/// N.
+/// If N is compile unit return NULL otherwise return N.
static MDNode *getNonCompileUnitScope(MDNode *N) {
if (DIDescriptor(N).isCompileUnit())
return nullptr;
@@ -95,8 +109,6 @@ static MDNode *createFilePathPair(LLVMContext &VMContext, StringRef Filename,
return MDNode::get(VMContext, Pair);
}
-/// createCompileUnit - A CompileUnit provides an anchor for all debugging
-/// information generated during this instance of compilation.
DICompileUnit DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename,
StringRef Directory,
StringRef Producer, bool isOptimized,
@@ -110,7 +122,7 @@ DICompileUnit DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename,
"Invalid Language tag");
assert(!Filename.empty() &&
"Unable to create compile unit without filename");
- Value *TElts[] = { GetTagConstant(VMContext, DW_TAG_base_type) };
+ Value *TElts[] = {HeaderBuilder::get(DW_TAG_base_type).get(VMContext)};
TempEnumTypes = MDNode::getTemporary(VMContext, TElts);
TempRetainTypes = MDNode::getTemporary(VMContext, TElts);
@@ -121,22 +133,18 @@ DICompileUnit DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename,
TempImportedModules = MDNode::getTemporary(VMContext, TElts);
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_compile_unit),
- createFilePathPair(VMContext, Filename, Directory),
- ConstantInt::get(Type::getInt32Ty(VMContext), Lang),
- MDString::get(VMContext, Producer),
- ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized),
- MDString::get(VMContext, Flags),
- ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeVer),
- TempEnumTypes,
- TempRetainTypes,
- TempSubprograms,
- TempGVs,
- TempImportedModules,
- MDString::get(VMContext, SplitName),
- ConstantInt::get(Type::getInt32Ty(VMContext), Kind)
- };
+ Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_compile_unit)
+ .concat(Lang)
+ .concat(Producer)
+ .concat(isOptimized)
+ .concat(Flags)
+ .concat(RunTimeVer)
+ .concat(SplitName)
+ .concat(Kind)
+ .get(VMContext),
+ createFilePathPair(VMContext, Filename, Directory),
+ TempEnumTypes, TempRetainTypes, TempSubprograms, TempGVs,
+ TempImportedModules};
MDNode *CUNode = MDNode::get(VMContext, Elts);
@@ -158,24 +166,9 @@ createImportedModule(LLVMContext &C, dwarf::Tag Tag, DIScope Context,
Value *NS, unsigned Line, StringRef Name,
SmallVectorImpl<TrackingVH<MDNode>> &AllImportedModules) {
const MDNode *R;
- if (Name.empty()) {
- Value *Elts[] = {
- GetTagConstant(C, Tag),
- Context,
- NS,
- ConstantInt::get(Type::getInt32Ty(C), Line),
- };
- R = MDNode::get(C, Elts);
- } else {
- Value *Elts[] = {
- GetTagConstant(C, Tag),
- Context,
- NS,
- ConstantInt::get(Type::getInt32Ty(C), Line),
- MDString::get(C, Name)
- };
- R = MDNode::get(C, Elts);
- }
+ Value *Elts[] = {HeaderBuilder::get(Tag).concat(Line).concat(Name).get(C),
+ Context, NS};
+ R = MDNode::get(C, Elts);
DIImportedEntity M(R);
assert(M.Verify() && "Imported module should be valid");
AllImportedModules.push_back(TrackingVH<MDNode>(M));
@@ -197,10 +190,13 @@ DIImportedEntity DIBuilder::createImportedModule(DIScope Context,
}
DIImportedEntity DIBuilder::createImportedDeclaration(DIScope Context,
- DIScope Decl,
+ DIDescriptor Decl,
unsigned Line, StringRef Name) {
+ // Make sure to use the unique identifier based metadata reference for
+ // types that have one.
+ Value *V = Decl.isType() ? static_cast<Value*>(DIType(Decl).getRef()) : Decl;
return ::createImportedModule(VMContext, dwarf::DW_TAG_imported_declaration,
- Context, Decl.getRef(), Line, Name,
+ Context, V, Line, Name,
AllImportedModules);
}
@@ -211,54 +207,44 @@ DIImportedEntity DIBuilder::createImportedDeclaration(DIScope Context,
Context, Imp, Line, Name, AllImportedModules);
}
-/// createFile - Create a file descriptor to hold debugging information
-/// for a file.
DIFile DIBuilder::createFile(StringRef Filename, StringRef Directory) {
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_file_type),
- createFilePathPair(VMContext, Filename, Directory)
- };
+ Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_file_type).get(VMContext),
+ createFilePathPair(VMContext, Filename, Directory)};
return DIFile(MDNode::get(VMContext, Elts));
}
-/// createEnumerator - Create a single enumerator value.
DIEnumerator DIBuilder::createEnumerator(StringRef Name, int64_t Val) {
assert(!Name.empty() && "Unable to create enumerator without name");
Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_enumerator),
- MDString::get(VMContext, Name),
- ConstantInt::get(Type::getInt64Ty(VMContext), Val)
- };
+ HeaderBuilder::get(dwarf::DW_TAG_enumerator).concat(Name).concat(Val).get(
+ VMContext)};
return DIEnumerator(MDNode::get(VMContext, Elts));
}
-/// \brief Create a DWARF unspecified type.
DIBasicType DIBuilder::createUnspecifiedType(StringRef Name) {
assert(!Name.empty() && "Unable to create type without name");
// Unspecified types are encoded in DIBasicType format. Line number, filename,
// size, alignment, offset and flags are always empty here.
Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_type),
- nullptr, // Filename
- nullptr, // Unused
- MDString::get(VMContext, Name),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags;
- ConstantInt::get(Type::getInt32Ty(VMContext), 0) // Encoding
+ HeaderBuilder::get(dwarf::DW_TAG_unspecified_type)
+ .concat(Name)
+ .concat(0)
+ .concat(0)
+ .concat(0)
+ .concat(0)
+ .concat(0)
+ .concat(0)
+ .get(VMContext),
+ nullptr, // Filename
+ nullptr // Unused
};
return DIBasicType(MDNode::get(VMContext, Elts));
}
-/// \brief Create C++11 nullptr type.
DIBasicType DIBuilder::createNullPtrType() {
return createUnspecifiedType("decltype(nullptr)");
}
-/// createBasicType - Create debugging information entry for a basic
-/// type, e.g 'char'.
DIBasicType
DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits,
uint64_t AlignInBits, unsigned Encoding) {
@@ -266,160 +252,139 @@ DIBuilder::createBasicType(StringRef Name, uint64_t SizeInBits,
// Basic types are encoded in DIBasicType format. Line number, filename,
// offset and flags are always empty here.
Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_base_type),
- nullptr, // File/directory name
- nullptr, // Unused
- MDString::get(VMContext, Name),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line
- ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
- ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags;
- ConstantInt::get(Type::getInt32Ty(VMContext), Encoding)
+ HeaderBuilder::get(dwarf::DW_TAG_base_type)
+ .concat(Name)
+ .concat(0) // Line
+ .concat(SizeInBits)
+ .concat(AlignInBits)
+ .concat(0) // Offset
+ .concat(0) // Flags
+ .concat(Encoding)
+ .get(VMContext),
+ nullptr, // Filename
+ nullptr // Unused
};
return DIBasicType(MDNode::get(VMContext, Elts));
}
-/// createQualifiedType - Create debugging information entry for a qualified
-/// type, e.g. 'const int'.
DIDerivedType DIBuilder::createQualifiedType(unsigned Tag, DIType FromTy) {
// Qualified types are encoded in DIDerivedType format.
- Value *Elts[] = {
- GetTagConstant(VMContext, Tag),
- nullptr, // Filename
- nullptr, // Unused
- MDString::get(VMContext, StringRef()), // Empty name.
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags
- FromTy.getRef()
- };
+ Value *Elts[] = {HeaderBuilder::get(Tag)
+ .concat(StringRef()) // Name
+ .concat(0) // Line
+ .concat(0) // Size
+ .concat(0) // Align
+ .concat(0) // Offset
+ .concat(0) // Flags
+ .get(VMContext),
+ nullptr, // Filename
+ nullptr, // Unused
+ FromTy.getRef()};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
-/// createPointerType - Create debugging information entry for a pointer.
DIDerivedType
DIBuilder::createPointerType(DIType PointeeTy, uint64_t SizeInBits,
uint64_t AlignInBits, StringRef Name) {
// Pointer types are encoded in DIDerivedType format.
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_pointer_type),
- nullptr, // Filename
- nullptr, // Unused
- MDString::get(VMContext, Name),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line
- ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
- ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags
- PointeeTy.getRef()
- };
+ Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_pointer_type)
+ .concat(Name)
+ .concat(0) // Line
+ .concat(SizeInBits)
+ .concat(AlignInBits)
+ .concat(0) // Offset
+ .concat(0) // Flags
+ .get(VMContext),
+ nullptr, // Filename
+ nullptr, // Unused
+ PointeeTy.getRef()};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
DIDerivedType DIBuilder::createMemberPointerType(DIType PointeeTy,
DIType Base) {
// Pointer types are encoded in DIDerivedType format.
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_ptr_to_member_type),
- nullptr, // Filename
- nullptr, // Unused
- nullptr,
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags
- PointeeTy.getRef(),
- Base.getRef()
- };
+ Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_ptr_to_member_type)
+ .concat(StringRef())
+ .concat(0) // Line
+ .concat(0) // Size
+ .concat(0) // Align
+ .concat(0) // Offset
+ .concat(0) // Flags
+ .get(VMContext),
+ nullptr, // Filename
+ nullptr, // Unused
+ PointeeTy.getRef(), Base.getRef()};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
-/// createReferenceType - Create debugging information entry for a reference
-/// type.
DIDerivedType DIBuilder::createReferenceType(unsigned Tag, DIType RTy) {
assert(RTy.isType() && "Unable to create reference type");
// References are encoded in DIDerivedType format.
- Value *Elts[] = {
- GetTagConstant(VMContext, Tag),
- nullptr, // Filename
- nullptr, // TheCU,
- nullptr, // Name
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags
- RTy.getRef()
- };
+ Value *Elts[] = {HeaderBuilder::get(Tag)
+ .concat(StringRef()) // Name
+ .concat(0) // Line
+ .concat(0) // Size
+ .concat(0) // Align
+ .concat(0) // Offset
+ .concat(0) // Flags
+ .get(VMContext),
+ nullptr, // Filename
+ nullptr, // TheCU,
+ RTy.getRef()};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
-/// createTypedef - Create debugging information entry for a typedef.
DIDerivedType DIBuilder::createTypedef(DIType Ty, StringRef Name, DIFile File,
unsigned LineNo, DIDescriptor Context) {
// typedefs are encoded in DIDerivedType format.
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_typedef),
- File.getFileNode(),
- DIScope(getNonCompileUnitScope(Context)).getRef(),
- MDString::get(VMContext, Name),
- ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags
- Ty.getRef()
- };
+ Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_typedef)
+ .concat(Name)
+ .concat(LineNo)
+ .concat(0) // Size
+ .concat(0) // Align
+ .concat(0) // Offset
+ .concat(0) // Flags
+ .get(VMContext),
+ File.getFileNode(),
+ DIScope(getNonCompileUnitScope(Context)).getRef(),
+ Ty.getRef()};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
-/// createFriend - Create debugging information entry for a 'friend'.
DIDerivedType DIBuilder::createFriend(DIType Ty, DIType FriendTy) {
// typedefs are encoded in DIDerivedType format.
assert(Ty.isType() && "Invalid type!");
assert(FriendTy.isType() && "Invalid friend type!");
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_friend),
- nullptr,
- Ty.getRef(),
- nullptr, // Name
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags
- FriendTy.getRef()
- };
+ Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_friend)
+ .concat(StringRef()) // Name
+ .concat(0) // Line
+ .concat(0) // Size
+ .concat(0) // Align
+ .concat(0) // Offset
+ .concat(0) // Flags
+ .get(VMContext),
+ nullptr, Ty.getRef(), FriendTy.getRef()};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
-/// createInheritance - Create debugging information entry to establish
-/// inheritance relationship between two types.
DIDerivedType DIBuilder::createInheritance(DIType Ty, DIType BaseTy,
uint64_t BaseOffset,
unsigned Flags) {
assert(Ty.isType() && "Unable to create inheritance");
// TAG_inheritance is encoded in DIDerivedType format.
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_inheritance),
- nullptr,
- Ty.getRef(),
- nullptr, // Name
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align
- ConstantInt::get(Type::getInt64Ty(VMContext), BaseOffset),
- ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
- BaseTy.getRef()
- };
+ Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_inheritance)
+ .concat(StringRef()) // Name
+ .concat(0) // Line
+ .concat(0) // Size
+ .concat(0) // Align
+ .concat(BaseOffset)
+ .concat(Flags)
+ .get(VMContext),
+ nullptr, Ty.getRef(), BaseTy.getRef()};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
-/// createMemberType - Create debugging information entry for a member.
DIDerivedType DIBuilder::createMemberType(DIDescriptor Scope, StringRef Name,
DIFile File, unsigned LineNumber,
uint64_t SizeInBits,
@@ -427,76 +392,41 @@ DIDerivedType DIBuilder::createMemberType(DIDescriptor Scope, StringRef Name,
uint64_t OffsetInBits, unsigned Flags,
DIType Ty) {
// TAG_member is encoded in DIDerivedType format.
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_member),
- File.getFileNode(),
- DIScope(getNonCompileUnitScope(Scope)).getRef(),
- MDString::get(VMContext, Name),
- ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
- ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
- ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
- ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits),
- ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
- Ty.getRef()
- };
+ Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_member)
+ .concat(Name)
+ .concat(LineNumber)
+ .concat(SizeInBits)
+ .concat(AlignInBits)
+ .concat(OffsetInBits)
+ .concat(Flags)
+ .get(VMContext),
+ File.getFileNode(),
+ DIScope(getNonCompileUnitScope(Scope)).getRef(),
+ Ty.getRef()};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
-/// createStaticMemberType - Create debugging information entry for a
-/// C++ static data member.
-DIDerivedType
-DIBuilder::createStaticMemberType(DIDescriptor Scope, StringRef Name,
- DIFile File, unsigned LineNumber,
- DIType Ty, unsigned Flags,
- llvm::Value *Val) {
+DIDerivedType DIBuilder::createStaticMemberType(DIDescriptor Scope,
+ StringRef Name, DIFile File,
+ unsigned LineNumber, DIType Ty,
+ unsigned Flags,
+ llvm::Constant *Val) {
// TAG_member is encoded in DIDerivedType format.
Flags |= DIDescriptor::FlagStaticMember;
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_member),
- File.getFileNode(),
- DIScope(getNonCompileUnitScope(Scope)).getRef(),
- MDString::get(VMContext, Name),
- ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
- ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
- Ty.getRef(),
- Val
- };
+ Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_member)
+ .concat(Name)
+ .concat(LineNumber)
+ .concat(0) // Size
+ .concat(0) // Align
+ .concat(0) // Offset
+ .concat(Flags)
+ .get(VMContext),
+ File.getFileNode(),
+ DIScope(getNonCompileUnitScope(Scope)).getRef(), Ty.getRef(),
+ Val};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
-/// createObjCIVar - Create debugging information entry for Objective-C
-/// instance variable.
-DIDerivedType
-DIBuilder::createObjCIVar(StringRef Name, DIFile File, unsigned LineNumber,
- uint64_t SizeInBits, uint64_t AlignInBits,
- uint64_t OffsetInBits, unsigned Flags, DIType Ty,
- StringRef PropertyName, StringRef GetterName,
- StringRef SetterName, unsigned PropertyAttributes) {
- // TAG_member is encoded in DIDerivedType format.
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_member),
- File.getFileNode(),
- getNonCompileUnitScope(File),
- MDString::get(VMContext, Name),
- ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
- ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
- ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
- ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits),
- ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
- Ty,
- MDString::get(VMContext, PropertyName),
- MDString::get(VMContext, GetterName),
- MDString::get(VMContext, SetterName),
- ConstantInt::get(Type::getInt32Ty(VMContext), PropertyAttributes)
- };
- return DIDerivedType(MDNode::get(VMContext, Elts));
-}
-
-/// createObjCIVar - Create debugging information entry for Objective-C
-/// instance variable.
DIDerivedType DIBuilder::createObjCIVar(StringRef Name, DIFile File,
unsigned LineNumber,
uint64_t SizeInBits,
@@ -504,88 +434,66 @@ DIDerivedType DIBuilder::createObjCIVar(StringRef Name, DIFile File,
uint64_t OffsetInBits, unsigned Flags,
DIType Ty, MDNode *PropertyNode) {
// TAG_member is encoded in DIDerivedType format.
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_member),
- File.getFileNode(),
- getNonCompileUnitScope(File),
- MDString::get(VMContext, Name),
- ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
- ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
- ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
- ConstantInt::get(Type::getInt64Ty(VMContext), OffsetInBits),
- ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
- Ty,
- PropertyNode
- };
+ Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_member)
+ .concat(Name)
+ .concat(LineNumber)
+ .concat(SizeInBits)
+ .concat(AlignInBits)
+ .concat(OffsetInBits)
+ .concat(Flags)
+ .get(VMContext),
+ File.getFileNode(), getNonCompileUnitScope(File), Ty,
+ PropertyNode};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
-/// createObjCProperty - Create debugging information entry for Objective-C
-/// property.
DIObjCProperty
DIBuilder::createObjCProperty(StringRef Name, DIFile File, unsigned LineNumber,
StringRef GetterName, StringRef SetterName,
unsigned PropertyAttributes, DIType Ty) {
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_APPLE_property),
- MDString::get(VMContext, Name),
- File,
- ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
- MDString::get(VMContext, GetterName),
- MDString::get(VMContext, SetterName),
- ConstantInt::get(Type::getInt32Ty(VMContext), PropertyAttributes),
- Ty
- };
+ Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_APPLE_property)
+ .concat(Name)
+ .concat(LineNumber)
+ .concat(GetterName)
+ .concat(SetterName)
+ .concat(PropertyAttributes)
+ .get(VMContext),
+ File, Ty};
return DIObjCProperty(MDNode::get(VMContext, Elts));
}
-/// createTemplateTypeParameter - Create debugging information for template
-/// type parameter.
DITemplateTypeParameter
DIBuilder::createTemplateTypeParameter(DIDescriptor Context, StringRef Name,
DIType Ty, MDNode *File, unsigned LineNo,
unsigned ColumnNo) {
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_template_type_parameter),
- DIScope(getNonCompileUnitScope(Context)).getRef(),
- MDString::get(VMContext, Name),
- Ty.getRef(),
- File,
- ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
- ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo)
- };
+ Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_template_type_parameter)
+ .concat(Name)
+ .concat(LineNo)
+ .concat(ColumnNo)
+ .get(VMContext),
+ DIScope(getNonCompileUnitScope(Context)).getRef(),
+ Ty.getRef(), File};
return DITemplateTypeParameter(MDNode::get(VMContext, Elts));
}
-DITemplateValueParameter
-DIBuilder::createTemplateValueParameter(unsigned Tag, DIDescriptor Context,
- StringRef Name, DIType Ty,
- Value *Val, MDNode *File,
- unsigned LineNo,
- unsigned ColumnNo) {
+static DITemplateValueParameter createTemplateValueParameterHelper(
+ LLVMContext &VMContext, unsigned Tag, DIDescriptor Context, StringRef Name,
+ DIType Ty, Value *Val, MDNode *File, unsigned LineNo, unsigned ColumnNo) {
Value *Elts[] = {
- GetTagConstant(VMContext, Tag),
- DIScope(getNonCompileUnitScope(Context)).getRef(),
- MDString::get(VMContext, Name),
- Ty.getRef(),
- Val,
- File,
- ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
- ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo)
- };
+ HeaderBuilder::get(Tag).concat(Name).concat(LineNo).concat(ColumnNo).get(
+ VMContext),
+ DIScope(getNonCompileUnitScope(Context)).getRef(), Ty.getRef(), Val,
+ File};
return DITemplateValueParameter(MDNode::get(VMContext, Elts));
}
-/// createTemplateValueParameter - Create debugging information for template
-/// value parameter.
DITemplateValueParameter
DIBuilder::createTemplateValueParameter(DIDescriptor Context, StringRef Name,
- DIType Ty, Value *Val,
- MDNode *File, unsigned LineNo,
- unsigned ColumnNo) {
- return createTemplateValueParameter(dwarf::DW_TAG_template_value_parameter,
- Context, Name, Ty, Val, File, LineNo,
- ColumnNo);
+ DIType Ty, Constant *Val, MDNode *File,
+ unsigned LineNo, unsigned ColumnNo) {
+ return createTemplateValueParameterHelper(
+ VMContext, dwarf::DW_TAG_template_value_parameter, Context, Name, Ty, Val,
+ File, LineNo, ColumnNo);
}
DITemplateValueParameter
@@ -593,8 +501,8 @@ DIBuilder::createTemplateTemplateParameter(DIDescriptor Context, StringRef Name,
DIType Ty, StringRef Val,
MDNode *File, unsigned LineNo,
unsigned ColumnNo) {
- return createTemplateValueParameter(
- dwarf::DW_TAG_GNU_template_template_param, Context, Name, Ty,
+ return createTemplateValueParameterHelper(
+ VMContext, dwarf::DW_TAG_GNU_template_template_param, Context, Name, Ty,
MDString::get(VMContext, Val), File, LineNo, ColumnNo);
}
@@ -603,12 +511,11 @@ DIBuilder::createTemplateParameterPack(DIDescriptor Context, StringRef Name,
DIType Ty, DIArray Val,
MDNode *File, unsigned LineNo,
unsigned ColumnNo) {
- return createTemplateValueParameter(dwarf::DW_TAG_GNU_template_parameter_pack,
- Context, Name, Ty, Val, File, LineNo,
- ColumnNo);
+ return createTemplateValueParameterHelper(
+ VMContext, dwarf::DW_TAG_GNU_template_parameter_pack, Context, Name, Ty,
+ Val, File, LineNo, ColumnNo);
}
-/// createClassType - Create debugging information entry for a class.
DICompositeType DIBuilder::createClassType(DIDescriptor Context, StringRef Name,
DIFile File, unsigned LineNumber,
uint64_t SizeInBits,
@@ -623,23 +530,19 @@ DICompositeType DIBuilder::createClassType(DIDescriptor Context, StringRef Name,
"createClassType should be called with a valid Context");
// TAG_class_type is encoded in DICompositeType format.
Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_class_type),
- File.getFileNode(),
- DIScope(getNonCompileUnitScope(Context)).getRef(),
- MDString::get(VMContext, Name),
- ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
- ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
- ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
- ConstantInt::get(Type::getInt32Ty(VMContext), OffsetInBits),
- ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
- DerivedFrom.getRef(),
- Elements,
- ConstantInt::get(Type::getInt32Ty(VMContext), 0),
- VTableHolder.getRef(),
- TemplateParams,
- UniqueIdentifier.empty() ? nullptr
- : MDString::get(VMContext, UniqueIdentifier)
- };
+ HeaderBuilder::get(dwarf::DW_TAG_class_type)
+ .concat(Name)
+ .concat(LineNumber)
+ .concat(SizeInBits)
+ .concat(AlignInBits)
+ .concat(OffsetInBits)
+ .concat(Flags)
+ .concat(0)
+ .get(VMContext),
+ File.getFileNode(), DIScope(getNonCompileUnitScope(Context)).getRef(),
+ DerivedFrom.getRef(), Elements, VTableHolder.getRef(), TemplateParams,
+ UniqueIdentifier.empty() ? nullptr
+ : MDString::get(VMContext, UniqueIdentifier)};
DICompositeType R(MDNode::get(VMContext, Elts));
assert(R.isCompositeType() &&
"createClassType should return a DICompositeType");
@@ -648,7 +551,6 @@ DICompositeType DIBuilder::createClassType(DIDescriptor Context, StringRef Name,
return R;
}
-/// createStructType - Create debugging information entry for a struct.
DICompositeType DIBuilder::createStructType(DIDescriptor Context,
StringRef Name, DIFile File,
unsigned LineNumber,
@@ -661,23 +563,19 @@ DICompositeType DIBuilder::createStructType(DIDescriptor Context,
StringRef UniqueIdentifier) {
// TAG_structure_type is encoded in DICompositeType format.
Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_structure_type),
- File.getFileNode(),
- DIScope(getNonCompileUnitScope(Context)).getRef(),
- MDString::get(VMContext, Name),
- ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
- ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
- ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0),
- ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
- DerivedFrom.getRef(),
- Elements,
- ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeLang),
- VTableHolder.getRef(),
- nullptr,
- UniqueIdentifier.empty() ? nullptr
- : MDString::get(VMContext, UniqueIdentifier)
- };
+ HeaderBuilder::get(dwarf::DW_TAG_structure_type)
+ .concat(Name)
+ .concat(LineNumber)
+ .concat(SizeInBits)
+ .concat(AlignInBits)
+ .concat(0)
+ .concat(Flags)
+ .concat(RunTimeLang)
+ .get(VMContext),
+ File.getFileNode(), DIScope(getNonCompileUnitScope(Context)).getRef(),
+ DerivedFrom.getRef(), Elements, VTableHolder.getRef(), nullptr,
+ UniqueIdentifier.empty() ? nullptr
+ : MDString::get(VMContext, UniqueIdentifier)};
DICompositeType R(MDNode::get(VMContext, Elts));
assert(R.isCompositeType() &&
"createStructType should return a DICompositeType");
@@ -686,7 +584,6 @@ DICompositeType DIBuilder::createStructType(DIDescriptor Context,
return R;
}
-/// createUnionType - Create debugging information entry for an union.
DICompositeType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name,
DIFile File, unsigned LineNumber,
uint64_t SizeInBits,
@@ -696,79 +593,64 @@ DICompositeType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name,
StringRef UniqueIdentifier) {
// TAG_union_type is encoded in DICompositeType format.
Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_union_type),
- File.getFileNode(),
- DIScope(getNonCompileUnitScope(Scope)).getRef(),
- MDString::get(VMContext, Name),
- ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
- ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
- ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
- ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
- nullptr,
- Elements,
- ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeLang),
- nullptr,
- nullptr,
- UniqueIdentifier.empty() ? nullptr
- : MDString::get(VMContext, UniqueIdentifier)
- };
+ HeaderBuilder::get(dwarf::DW_TAG_union_type)
+ .concat(Name)
+ .concat(LineNumber)
+ .concat(SizeInBits)
+ .concat(AlignInBits)
+ .concat(0) // Offset
+ .concat(Flags)
+ .concat(RunTimeLang)
+ .get(VMContext),
+ File.getFileNode(), DIScope(getNonCompileUnitScope(Scope)).getRef(),
+ nullptr, Elements, nullptr, nullptr,
+ UniqueIdentifier.empty() ? nullptr
+ : MDString::get(VMContext, UniqueIdentifier)};
DICompositeType R(MDNode::get(VMContext, Elts));
if (!UniqueIdentifier.empty())
retainType(R);
return R;
}
-/// createSubroutineType - Create subroutine type.
-DICompositeType DIBuilder::createSubroutineType(DIFile File,
- DIArray ParameterTypes,
- unsigned Flags) {
+DISubroutineType DIBuilder::createSubroutineType(DIFile File,
+ DITypeArray ParameterTypes,
+ unsigned Flags) {
// TAG_subroutine_type is encoded in DICompositeType format.
Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_subroutine_type),
- Constant::getNullValue(Type::getInt32Ty(VMContext)),
- nullptr,
- MDString::get(VMContext, ""),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align
- ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
- ConstantInt::get(Type::getInt32Ty(VMContext), Flags), // Flags
- nullptr,
- ParameterTypes,
- ConstantInt::get(Type::getInt32Ty(VMContext), 0),
- nullptr,
- nullptr,
- nullptr // Type Identifer
+ HeaderBuilder::get(dwarf::DW_TAG_subroutine_type)
+ .concat(StringRef())
+ .concat(0) // Line
+ .concat(0) // Size
+ .concat(0) // Align
+ .concat(0) // Offset
+ .concat(Flags) // Flags
+ .concat(0)
+ .get(VMContext),
+ nullptr, nullptr, nullptr, ParameterTypes, nullptr, nullptr,
+ nullptr // Type Identifer
};
- return DICompositeType(MDNode::get(VMContext, Elts));
+ return DISubroutineType(MDNode::get(VMContext, Elts));
}
-/// createEnumerationType - Create debugging information entry for an
-/// enumeration.
DICompositeType DIBuilder::createEnumerationType(
DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber,
uint64_t SizeInBits, uint64_t AlignInBits, DIArray Elements,
DIType UnderlyingType, StringRef UniqueIdentifier) {
// TAG_enumeration_type is encoded in DICompositeType format.
Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_enumeration_type),
- File.getFileNode(),
- DIScope(getNonCompileUnitScope(Scope)).getRef(),
- MDString::get(VMContext, Name),
- ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
- ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
- ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags
- UnderlyingType.getRef(),
- Elements,
- ConstantInt::get(Type::getInt32Ty(VMContext), 0),
- nullptr,
- nullptr,
- UniqueIdentifier.empty() ? nullptr
- : MDString::get(VMContext, UniqueIdentifier)
- };
+ HeaderBuilder::get(dwarf::DW_TAG_enumeration_type)
+ .concat(Name)
+ .concat(LineNumber)
+ .concat(SizeInBits)
+ .concat(AlignInBits)
+ .concat(0) // Offset
+ .concat(0) // Flags
+ .concat(0)
+ .get(VMContext),
+ File.getFileNode(), DIScope(getNonCompileUnitScope(Scope)).getRef(),
+ UnderlyingType.getRef(), Elements, nullptr, nullptr,
+ UniqueIdentifier.empty() ? nullptr
+ : MDString::get(VMContext, UniqueIdentifier)};
DICompositeType CTy(MDNode::get(VMContext, Elts));
AllEnumTypes.push_back(CTy);
if (!UniqueIdentifier.empty())
@@ -776,114 +658,96 @@ DICompositeType DIBuilder::createEnumerationType(
return CTy;
}
-/// createArrayType - Create debugging information entry for an array.
DICompositeType DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits,
DIType Ty, DIArray Subscripts) {
// TAG_array_type is encoded in DICompositeType format.
Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_array_type),
- nullptr, // Filename/Directory,
- nullptr, // Unused
- MDString::get(VMContext, ""),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line
- ConstantInt::get(Type::getInt64Ty(VMContext), Size),
- ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags
- Ty.getRef(),
- Subscripts,
- ConstantInt::get(Type::getInt32Ty(VMContext), 0),
- nullptr,
- nullptr,
- nullptr // Type Identifer
+ HeaderBuilder::get(dwarf::DW_TAG_array_type)
+ .concat(StringRef())
+ .concat(0) // Line
+ .concat(Size)
+ .concat(AlignInBits)
+ .concat(0) // Offset
+ .concat(0) // Flags
+ .concat(0)
+ .get(VMContext),
+ nullptr, // Filename/Directory,
+ nullptr, // Unused
+ Ty.getRef(), Subscripts, nullptr, nullptr,
+ nullptr // Type Identifer
};
return DICompositeType(MDNode::get(VMContext, Elts));
}
-/// createVectorType - Create debugging information entry for a vector.
DICompositeType DIBuilder::createVectorType(uint64_t Size, uint64_t AlignInBits,
DIType Ty, DIArray Subscripts) {
// A vector is an array type with the FlagVector flag applied.
Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_array_type),
- nullptr, // Filename/Directory,
- nullptr, // Unused
- MDString::get(VMContext, ""),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line
- ConstantInt::get(Type::getInt64Ty(VMContext), Size),
- ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset
- ConstantInt::get(Type::getInt32Ty(VMContext), DIType::FlagVector),
- Ty.getRef(),
- Subscripts,
- ConstantInt::get(Type::getInt32Ty(VMContext), 0),
- nullptr,
- nullptr,
- nullptr // Type Identifer
+ HeaderBuilder::get(dwarf::DW_TAG_array_type)
+ .concat("")
+ .concat(0) // Line
+ .concat(Size)
+ .concat(AlignInBits)
+ .concat(0) // Offset
+ .concat(DIType::FlagVector)
+ .concat(0)
+ .get(VMContext),
+ nullptr, // Filename/Directory,
+ nullptr, // Unused
+ Ty.getRef(), Subscripts, nullptr, nullptr,
+ nullptr // Type Identifer
};
return DICompositeType(MDNode::get(VMContext, Elts));
}
-/// createArtificialType - Create a new DIType with "artificial" flag set.
-DIType DIBuilder::createArtificialType(DIType Ty) {
- if (Ty.isArtificial())
- return Ty;
+static HeaderBuilder setTypeFlagsInHeader(StringRef Header,
+ unsigned FlagsToSet) {
+ DIHeaderFieldIterator I(Header);
+ std::advance(I, 6);
+ unsigned Flags;
+ if (I->getAsInteger(0, Flags))
+ Flags = 0;
+ Flags |= FlagsToSet;
+
+ return HeaderBuilder(Twine(I.getPrefix())).concat(Flags).concat(
+ I.getSuffix());
+}
+
+static DIType createTypeWithFlags(LLVMContext &Context, DIType Ty,
+ unsigned FlagsToSet) {
SmallVector<Value *, 9> Elts;
MDNode *N = Ty;
- assert (N && "Unexpected input DIType!");
- for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
- Elts.push_back(N->getOperand(i));
-
- unsigned CurFlags = Ty.getFlags();
- CurFlags = CurFlags | DIType::FlagArtificial;
+ assert(N && "Unexpected input DIType!");
+ // Update header field.
+ Elts.push_back(setTypeFlagsInHeader(Ty.getHeader(), FlagsToSet).get(Context));
+ for (unsigned I = 1, E = N->getNumOperands(); I != E; ++I)
+ Elts.push_back(N->getOperand(I));
- // Flags are stored at this slot.
- // FIXME: Add an enum for this magic value.
- Elts[8] = ConstantInt::get(Type::getInt32Ty(VMContext), CurFlags);
+ return DIType(MDNode::get(Context, Elts));
+}
- return DIType(MDNode::get(VMContext, Elts));
+DIType DIBuilder::createArtificialType(DIType Ty) {
+ if (Ty.isArtificial())
+ return Ty;
+ return createTypeWithFlags(VMContext, Ty, DIType::FlagArtificial);
}
-/// createObjectPointerType - Create a new type with both the object pointer
-/// and artificial flags set.
DIType DIBuilder::createObjectPointerType(DIType Ty) {
if (Ty.isObjectPointer())
return Ty;
-
- SmallVector<Value *, 9> Elts;
- MDNode *N = Ty;
- assert (N && "Unexpected input DIType!");
- for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
- Elts.push_back(N->getOperand(i));
-
- unsigned CurFlags = Ty.getFlags();
- CurFlags = CurFlags | (DIType::FlagObjectPointer | DIType::FlagArtificial);
-
- // Flags are stored at this slot.
- // FIXME: Add an enum for this magic value.
- Elts[8] = ConstantInt::get(Type::getInt32Ty(VMContext), CurFlags);
-
- return DIType(MDNode::get(VMContext, Elts));
+ unsigned Flags = DIType::FlagObjectPointer | DIType::FlagArtificial;
+ return createTypeWithFlags(VMContext, Ty, Flags);
}
-/// retainType - Retain DIType in a module even if it is not referenced
-/// through debug info anchors.
void DIBuilder::retainType(DIType T) {
AllRetainTypes.push_back(TrackingVH<MDNode>(T));
}
-/// createUnspecifiedParameter - Create unspeicified type descriptor
-/// for the subroutine type.
-DIDescriptor DIBuilder::createUnspecifiedParameter() {
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_unspecified_parameters)
- };
- return DIDescriptor(MDNode::get(VMContext, Elts));
+DIBasicType DIBuilder::createUnspecifiedParameter() {
+ return DIBasicType();
}
-/// createForwardDecl - Create a temporary forward-declared type that
-/// can be RAUW'd if the full type is seen.
DICompositeType
DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope,
DIFile F, unsigned Line, unsigned RuntimeLang,
@@ -891,23 +755,20 @@ DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope,
StringRef UniqueIdentifier) {
// Create a temporary MDNode.
Value *Elts[] = {
- GetTagConstant(VMContext, Tag),
- F.getFileNode(),
- DIScope(getNonCompileUnitScope(Scope)).getRef(),
- MDString::get(VMContext, Name),
- ConstantInt::get(Type::getInt32Ty(VMContext), Line),
- ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
- ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset
- ConstantInt::get(Type::getInt32Ty(VMContext), DIDescriptor::FlagFwdDecl),
- nullptr,
- DIArray(),
- ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang),
- nullptr,
- nullptr, //TemplateParams
- UniqueIdentifier.empty() ? nullptr
- : MDString::get(VMContext, UniqueIdentifier)
- };
+ HeaderBuilder::get(Tag)
+ .concat(Name)
+ .concat(Line)
+ .concat(SizeInBits)
+ .concat(AlignInBits)
+ .concat(0) // Offset
+ .concat(DIDescriptor::FlagFwdDecl)
+ .concat(RuntimeLang)
+ .get(VMContext),
+ F.getFileNode(), DIScope(getNonCompileUnitScope(Scope)).getRef(), nullptr,
+ DIArray(), nullptr,
+ nullptr, // TemplateParams
+ UniqueIdentifier.empty() ? nullptr
+ : MDString::get(VMContext, UniqueIdentifier)};
MDNode *Node = MDNode::get(VMContext, Elts);
DICompositeType RetTy(Node);
assert(RetTy.isCompositeType() &&
@@ -917,123 +778,102 @@ DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope,
return RetTy;
}
-/// createForwardDecl - Create a temporary forward-declared type that
-/// can be RAUW'd if the full type is seen.
DICompositeType DIBuilder::createReplaceableForwardDecl(
unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F, unsigned Line,
unsigned RuntimeLang, uint64_t SizeInBits, uint64_t AlignInBits,
StringRef UniqueIdentifier) {
// Create a temporary MDNode.
Value *Elts[] = {
- GetTagConstant(VMContext, Tag),
- F.getFileNode(),
- DIScope(getNonCompileUnitScope(Scope)).getRef(),
- MDString::get(VMContext, Name),
- ConstantInt::get(Type::getInt32Ty(VMContext), Line),
- ConstantInt::get(Type::getInt64Ty(VMContext), SizeInBits),
- ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset
- ConstantInt::get(Type::getInt32Ty(VMContext), DIDescriptor::FlagFwdDecl),
- nullptr,
- DIArray(),
- ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang),
- nullptr,
- nullptr, //TemplateParams
- UniqueIdentifier.empty() ? nullptr
- : MDString::get(VMContext, UniqueIdentifier)
- };
+ HeaderBuilder::get(Tag)
+ .concat(Name)
+ .concat(Line)
+ .concat(SizeInBits)
+ .concat(AlignInBits)
+ .concat(0) // Offset
+ .concat(DIDescriptor::FlagFwdDecl)
+ .concat(RuntimeLang)
+ .get(VMContext),
+ F.getFileNode(), DIScope(getNonCompileUnitScope(Scope)).getRef(), nullptr,
+ DIArray(), nullptr,
+ nullptr, // TemplateParams
+ UniqueIdentifier.empty() ? nullptr
+ : MDString::get(VMContext, UniqueIdentifier)};
MDNode *Node = MDNode::getTemporary(VMContext, Elts);
DICompositeType RetTy(Node);
assert(RetTy.isCompositeType() &&
- "createForwardDecl result should be a DIType");
+ "createReplaceableForwardDecl result should be a DIType");
if (!UniqueIdentifier.empty())
retainType(RetTy);
return RetTy;
}
-/// getOrCreateArray - Get a DIArray, create one if required.
DIArray DIBuilder::getOrCreateArray(ArrayRef<Value *> Elements) {
return DIArray(MDNode::get(VMContext, Elements));
}
-/// getOrCreateSubrange - Create a descriptor for a value range. This
-/// implicitly uniques the values returned.
+DITypeArray DIBuilder::getOrCreateTypeArray(ArrayRef<Value *> Elements) {
+ SmallVector<llvm::Value *, 16> Elts;
+ for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
+ if (Elements[i] && isa<MDNode>(Elements[i]))
+ Elts.push_back(DIType(cast<MDNode>(Elements[i])).getRef());
+ else
+ Elts.push_back(Elements[i]);
+ }
+ return DITypeArray(MDNode::get(VMContext, Elts));
+}
+
DISubrange DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Count) {
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_subrange_type),
- ConstantInt::get(Type::getInt64Ty(VMContext), Lo),
- ConstantInt::get(Type::getInt64Ty(VMContext), Count)
- };
+ Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_subrange_type)
+ .concat(Lo)
+ .concat(Count)
+ .get(VMContext)};
return DISubrange(MDNode::get(VMContext, Elts));
}
-/// \brief Create a new descriptor for the specified global.
-DIGlobalVariable DIBuilder::createGlobalVariable(StringRef Name,
- StringRef LinkageName,
- DIFile F, unsigned LineNumber,
- DITypeRef Ty, bool isLocalToUnit,
- Value *Val) {
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_variable),
- Constant::getNullValue(Type::getInt32Ty(VMContext)),
- nullptr, // TheCU,
- MDString::get(VMContext, Name),
- MDString::get(VMContext, Name),
- MDString::get(VMContext, LinkageName),
- F,
- ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
- Ty,
- ConstantInt::get(Type::getInt32Ty(VMContext), isLocalToUnit),
- ConstantInt::get(Type::getInt32Ty(VMContext), 1), /* isDefinition*/
- Val,
- DIDescriptor()
- };
- MDNode *Node = MDNode::get(VMContext, Elts);
- AllGVs.push_back(Node);
- return DIGlobalVariable(Node);
-}
-
-/// \brief Create a new descriptor for the specified global.
-DIGlobalVariable DIBuilder::createGlobalVariable(StringRef Name, DIFile F,
- unsigned LineNumber,
- DITypeRef Ty,
- bool isLocalToUnit,
- Value *Val) {
- return createGlobalVariable(Name, Name, F, LineNumber, Ty, isLocalToUnit,
- Val);
-}
-
-/// createStaticVariable - Create a new descriptor for the specified static
-/// variable.
-DIGlobalVariable DIBuilder::createStaticVariable(DIDescriptor Context,
- StringRef Name,
- StringRef LinkageName,
- DIFile F, unsigned LineNumber,
- DITypeRef Ty,
- bool isLocalToUnit,
- Value *Val, MDNode *Decl) {
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_variable),
- Constant::getNullValue(Type::getInt32Ty(VMContext)),
- getNonCompileUnitScope(Context),
- MDString::get(VMContext, Name),
- MDString::get(VMContext, Name),
- MDString::get(VMContext, LinkageName),
- F,
- ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
- Ty,
- ConstantInt::get(Type::getInt32Ty(VMContext), isLocalToUnit),
- ConstantInt::get(Type::getInt32Ty(VMContext), 1), /* isDefinition*/
- Val,
- DIDescriptor(Decl)
- };
- MDNode *Node = MDNode::get(VMContext, Elts);
- AllGVs.push_back(Node);
- return DIGlobalVariable(Node);
+static DIGlobalVariable createGlobalVariableHelper(
+ LLVMContext &VMContext, DIDescriptor Context, StringRef Name,
+ StringRef LinkageName, DIFile F, unsigned LineNumber, DITypeRef Ty,
+ bool isLocalToUnit, Constant *Val, MDNode *Decl, bool isDefinition,
+ std::function<MDNode *(ArrayRef<Value *>)> CreateFunc) {
+ Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_variable)
+ .concat(Name)
+ .concat(Name)
+ .concat(LinkageName)
+ .concat(LineNumber)
+ .concat(isLocalToUnit)
+ .concat(isDefinition)
+ .get(VMContext),
+ DIScope(getNonCompileUnitScope(Context)).getRef(), F, Ty, Val,
+ DIDescriptor(Decl)};
+
+ return DIGlobalVariable(CreateFunc(Elts));
+}
+
+DIGlobalVariable DIBuilder::createGlobalVariable(
+ DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile F,
+ unsigned LineNumber, DITypeRef Ty, bool isLocalToUnit, Constant *Val,
+ MDNode *Decl) {
+ return createGlobalVariableHelper(VMContext, Context, Name, LinkageName, F,
+ LineNumber, Ty, isLocalToUnit, Val, Decl, true,
+ [&] (ArrayRef<Value *> Elts) -> MDNode * {
+ MDNode *Node = MDNode::get(VMContext, Elts);
+ AllGVs.push_back(Node);
+ return Node;
+ });
+}
+
+DIGlobalVariable DIBuilder::createTempGlobalVariableFwdDecl(
+ DIDescriptor Context, StringRef Name, StringRef LinkageName, DIFile F,
+ unsigned LineNumber, DITypeRef Ty, bool isLocalToUnit, Constant *Val,
+ MDNode *Decl) {
+ return createGlobalVariableHelper(VMContext, Context, Name, LinkageName, F,
+ LineNumber, Ty, isLocalToUnit, Val, Decl, false,
+ [&] (ArrayRef<Value *> Elts) {
+ return MDNode::getTemporary(VMContext, Elts);
+ });
}
-/// createVariable - Create a new descriptor for the specified variable.
DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope,
StringRef Name, DIFile File,
unsigned LineNo, DITypeRef Ty,
@@ -1042,24 +882,20 @@ DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope,
DIDescriptor Context(getNonCompileUnitScope(Scope));
assert((!Context || Context.isScope()) &&
"createLocalVariable should be called with a valid Context");
- Value *Elts[] = {
- GetTagConstant(VMContext, Tag),
- getNonCompileUnitScope(Scope),
- MDString::get(VMContext, Name),
- File,
- ConstantInt::get(Type::getInt32Ty(VMContext), (LineNo | (ArgNo << 24))),
- Ty,
- ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
- Constant::getNullValue(Type::getInt32Ty(VMContext))
- };
+ Value *Elts[] = {HeaderBuilder::get(Tag)
+ .concat(Name)
+ .concat(LineNo | (ArgNo << 24))
+ .concat(Flags)
+ .get(VMContext),
+ getNonCompileUnitScope(Scope), File, Ty};
MDNode *Node = MDNode::get(VMContext, Elts);
if (AlwaysPreserve) {
// The optimizer may remove local variable. If there is an interest
// to preserve variable info in such situation then stash it in a
// named mdnode.
DISubprogram Fn(getDISubprogram(Scope));
- NamedMDNode *FnLocals = getOrInsertFnSpecificMDNode(M, Fn);
- FnLocals->addOperand(Node);
+ assert(Fn && "Missing subprogram for local variable");
+ PreservedVariables[Fn].push_back(Node);
}
DIVariable RetVar(Node);
assert(RetVar.isVariable() &&
@@ -1067,33 +903,20 @@ DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope,
return RetVar;
}
-/// createComplexVariable - Create a new descriptor for the specified variable
-/// which has a complex address expression for its address.
-DIVariable DIBuilder::createComplexVariable(unsigned Tag, DIDescriptor Scope,
- StringRef Name, DIFile F,
- unsigned LineNo,
- DITypeRef Ty,
- ArrayRef<Value *> Addr,
- unsigned ArgNo) {
- assert(Addr.size() > 0 && "complex address is empty");
- Value *Elts[] = {
- GetTagConstant(VMContext, Tag),
- getNonCompileUnitScope(Scope),
- MDString::get(VMContext, Name),
- F,
- ConstantInt::get(Type::getInt32Ty(VMContext),
- (LineNo | (ArgNo << 24))),
- Ty,
- Constant::getNullValue(Type::getInt32Ty(VMContext)),
- Constant::getNullValue(Type::getInt32Ty(VMContext)),
- MDNode::get(VMContext, Addr)
- };
- return DIVariable(MDNode::get(VMContext, Elts));
+DIExpression DIBuilder::createExpression(ArrayRef<int64_t> Addr) {
+ auto Header = HeaderBuilder::get(DW_TAG_expression);
+ for (int64_t I : Addr)
+ Header.concat(I);
+ Value *Elts[] = {Header.get(VMContext)};
+ return DIExpression(MDNode::get(VMContext, Elts));
+}
+
+DIExpression DIBuilder::createPieceExpression(unsigned OffsetInBytes,
+ unsigned SizeInBytes) {
+ int64_t Addr[] = {dwarf::DW_OP_piece, OffsetInBytes, SizeInBytes};
+ return createExpression(Addr);
}
-/// createFunction - Create a new descriptor for the specified function.
-/// FIXME: this is added for dragonegg. Once we update dragonegg
-/// to call resolve function, this will be removed.
DISubprogram DIBuilder::createFunction(DIScopeRef Context, StringRef Name,
StringRef LinkageName, DIFile File,
unsigned LineNo, DICompositeType Ty,
@@ -1109,7 +932,39 @@ DISubprogram DIBuilder::createFunction(DIScopeRef Context, StringRef Name,
Flags, isOptimized, Fn, TParams, Decl);
}
-/// createFunction - Create a new descriptor for the specified function.
+static DISubprogram
+createFunctionHelper(LLVMContext &VMContext, DIDescriptor Context, StringRef Name,
+ StringRef LinkageName, DIFile File, unsigned LineNo,
+ DICompositeType Ty, bool isLocalToUnit, bool isDefinition,
+ unsigned ScopeLine, unsigned Flags, bool isOptimized,
+ Function *Fn, MDNode *TParams, MDNode *Decl, MDNode *Vars,
+ std::function<MDNode *(ArrayRef<Value *>)> CreateFunc) {
+ assert(Ty.getTag() == dwarf::DW_TAG_subroutine_type &&
+ "function types should be subroutines");
+ Value *Elts[] = {
+ HeaderBuilder::get(dwarf::DW_TAG_subprogram)
+ .concat(Name)
+ .concat(Name)
+ .concat(LinkageName)
+ .concat(LineNo)
+ .concat(isLocalToUnit)
+ .concat(isDefinition)
+ .concat(0)
+ .concat(0)
+ .concat(Flags)
+ .concat(isOptimized)
+ .concat(ScopeLine)
+ .get(VMContext),
+ File.getFileNode(), DIScope(getNonCompileUnitScope(Context)).getRef(), Ty,
+ nullptr, Fn, TParams, Decl, Vars};
+
+ DISubprogram S(CreateFunc(Elts));
+ assert(S.isSubprogram() &&
+ "createFunction should return a valid DISubprogram");
+ return S;
+}
+
+
DISubprogram DIBuilder::createFunction(DIDescriptor Context, StringRef Name,
StringRef LinkageName, DIFile File,
unsigned LineNo, DICompositeType Ty,
@@ -1117,43 +972,36 @@ DISubprogram DIBuilder::createFunction(DIDescriptor Context, StringRef Name,
unsigned ScopeLine, unsigned Flags,
bool isOptimized, Function *Fn,
MDNode *TParams, MDNode *Decl) {
- assert(Ty.getTag() == dwarf::DW_TAG_subroutine_type &&
- "function types should be subroutines");
- Value *TElts[] = { GetTagConstant(VMContext, DW_TAG_base_type) };
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_subprogram),
- File.getFileNode(),
- DIScope(getNonCompileUnitScope(Context)).getRef(),
- MDString::get(VMContext, Name),
- MDString::get(VMContext, Name),
- MDString::get(VMContext, LinkageName),
- ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
- Ty,
- ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit),
- ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0),
- nullptr,
- ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
- ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized),
- Fn,
- TParams,
- Decl,
- MDNode::getTemporary(VMContext, TElts),
- ConstantInt::get(Type::getInt32Ty(VMContext), ScopeLine)
- };
- MDNode *Node = MDNode::get(VMContext, Elts);
+ return createFunctionHelper(VMContext, Context, Name, LinkageName, File,
+ LineNo, Ty, isLocalToUnit, isDefinition, ScopeLine,
+ Flags, isOptimized, Fn, TParams, Decl,
+ MDNode::getTemporary(VMContext, None),
+ [&] (ArrayRef<Value *> Elts) -> MDNode *{
+ MDNode *Node = MDNode::get(VMContext, Elts);
+ // Create a named metadata so that we
+ // do not lose this mdnode.
+ if (isDefinition)
+ AllSubprograms.push_back(Node);
+ return Node;
+ });
+}
- // Create a named metadata so that we do not lose this mdnode.
- if (isDefinition)
- AllSubprograms.push_back(Node);
- DISubprogram S(Node);
- assert(S.isSubprogram() &&
- "createFunction should return a valid DISubprogram");
- return S;
+DISubprogram
+DIBuilder::createTempFunctionFwdDecl(DIDescriptor Context, StringRef Name,
+ StringRef LinkageName, DIFile File,
+ unsigned LineNo, DICompositeType Ty,
+ bool isLocalToUnit, bool isDefinition,
+ unsigned ScopeLine, unsigned Flags,
+ bool isOptimized, Function *Fn,
+ MDNode *TParams, MDNode *Decl) {
+ return createFunctionHelper(VMContext, Context, Name, LinkageName, File,
+ LineNo, Ty, isLocalToUnit, isDefinition, ScopeLine,
+ Flags, isOptimized, Fn, TParams, Decl, nullptr,
+ [&] (ArrayRef<Value *> Elts) {
+ return MDNode::getTemporary(VMContext, Elts);
+ });
}
-/// createMethod - Create a new descriptor for the specified C++ method.
DISubprogram DIBuilder::createMethod(DIDescriptor Context, StringRef Name,
StringRef LinkageName, DIFile F,
unsigned LineNo, DICompositeType Ty,
@@ -1167,29 +1015,22 @@ DISubprogram DIBuilder::createMethod(DIDescriptor Context, StringRef Name,
assert(getNonCompileUnitScope(Context) &&
"Methods should have both a Context and a context that isn't "
"the compile unit.");
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_subprogram),
- F.getFileNode(),
- DIScope(Context).getRef(),
- MDString::get(VMContext, Name),
- MDString::get(VMContext, Name),
- MDString::get(VMContext, LinkageName),
- ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
- Ty,
- ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit),
- ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition),
- ConstantInt::get(Type::getInt32Ty(VMContext), VK),
- ConstantInt::get(Type::getInt32Ty(VMContext), VIndex),
- VTableHolder.getRef(),
- ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
- ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized),
- Fn,
- TParam,
- Constant::getNullValue(Type::getInt32Ty(VMContext)),
- nullptr,
- // FIXME: Do we want to use different scope/lines?
- ConstantInt::get(Type::getInt32Ty(VMContext), LineNo)
- };
+ Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_subprogram)
+ .concat(Name)
+ .concat(Name)
+ .concat(LinkageName)
+ .concat(LineNo)
+ .concat(isLocalToUnit)
+ .concat(isDefinition)
+ .concat(VK)
+ .concat(VIndex)
+ .concat(Flags)
+ .concat(isOptimized)
+ .concat(LineNo)
+ // FIXME: Do we want to use different scope/lines?
+ .get(VMContext),
+ F.getFileNode(), DIScope(Context).getRef(), Ty,
+ VTableHolder.getRef(), Fn, TParam, nullptr, nullptr};
MDNode *Node = MDNode::get(VMContext, Elts);
if (isDefinition)
AllSubprograms.push_back(Node);
@@ -1198,32 +1039,26 @@ DISubprogram DIBuilder::createMethod(DIDescriptor Context, StringRef Name,
return S;
}
-/// createNameSpace - This creates new descriptor for a namespace
-/// with the specified parent scope.
DINameSpace DIBuilder::createNameSpace(DIDescriptor Scope, StringRef Name,
DIFile File, unsigned LineNo) {
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_namespace),
- File.getFileNode(),
- getNonCompileUnitScope(Scope),
- MDString::get(VMContext, Name),
- ConstantInt::get(Type::getInt32Ty(VMContext), LineNo)
- };
+ Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_namespace)
+ .concat(Name)
+ .concat(LineNo)
+ .get(VMContext),
+ File.getFileNode(), getNonCompileUnitScope(Scope)};
DINameSpace R(MDNode::get(VMContext, Elts));
assert(R.Verify() &&
"createNameSpace should return a verifiable DINameSpace");
return R;
}
-/// createLexicalBlockFile - This creates a new MDNode that encapsulates
-/// an existing scope with a new filename.
DILexicalBlockFile DIBuilder::createLexicalBlockFile(DIDescriptor Scope,
- DIFile File) {
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_lexical_block),
- File.getFileNode(),
- Scope
- };
+ DIFile File,
+ unsigned Discriminator) {
+ Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_lexical_block)
+ .concat(Discriminator)
+ .get(VMContext),
+ File.getFileNode(), Scope};
DILexicalBlockFile R(MDNode::get(VMContext, Elts));
assert(
R.Verify() &&
@@ -1232,8 +1067,7 @@ DILexicalBlockFile DIBuilder::createLexicalBlockFile(DIDescriptor Scope,
}
DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File,
- unsigned Line, unsigned Col,
- unsigned Discriminator) {
+ unsigned Line, unsigned Col) {
// FIXME: This isn't thread safe nor the right way to defeat MDNode uniquing.
// I believe the right way is to have a self-referential element in the node.
// Also: why do we bother with line/column - they're not used and the
@@ -1243,23 +1077,20 @@ DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File,
// Defeat MDNode uniquing for lexical blocks by using unique id.
static unsigned int unique_id = 0;
- Value *Elts[] = {
- GetTagConstant(VMContext, dwarf::DW_TAG_lexical_block),
- File.getFileNode(),
- getNonCompileUnitScope(Scope),
- ConstantInt::get(Type::getInt32Ty(VMContext), Line),
- ConstantInt::get(Type::getInt32Ty(VMContext), Col),
- ConstantInt::get(Type::getInt32Ty(VMContext), Discriminator),
- ConstantInt::get(Type::getInt32Ty(VMContext), unique_id++)
- };
+ Value *Elts[] = {HeaderBuilder::get(dwarf::DW_TAG_lexical_block)
+ .concat(Line)
+ .concat(Col)
+ .concat(unique_id++)
+ .get(VMContext),
+ File.getFileNode(), getNonCompileUnitScope(Scope)};
DILexicalBlock R(MDNode::get(VMContext, Elts));
assert(R.Verify() &&
"createLexicalBlock should return a verifiable DILexicalBlock");
return R;
}
-/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call.
Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo,
+ DIExpression Expr,
Instruction *InsertBefore) {
assert(Storage && "no storage passed to dbg.declare");
assert(VarInfo.isVariable() &&
@@ -1267,12 +1098,12 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo,
if (!DeclareFn)
DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
- Value *Args[] = { MDNode::get(Storage->getContext(), Storage), VarInfo };
+ Value *Args[] = {MDNode::get(Storage->getContext(), Storage), VarInfo, Expr};
return CallInst::Create(DeclareFn, Args, "", InsertBefore);
}
-/// insertDeclare - Insert a new llvm.dbg.declare intrinsic call.
Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo,
+ DIExpression Expr,
BasicBlock *InsertAtEnd) {
assert(Storage && "no storage passed to dbg.declare");
assert(VarInfo.isVariable() &&
@@ -1280,7 +1111,7 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo,
if (!DeclareFn)
DeclareFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_declare);
- Value *Args[] = { MDNode::get(Storage->getContext(), Storage), VarInfo };
+ Value *Args[] = {MDNode::get(Storage->getContext(), Storage), VarInfo, Expr};
// If this block already has a terminator then insert this intrinsic
// before the terminator.
@@ -1290,9 +1121,9 @@ Instruction *DIBuilder::insertDeclare(Value *Storage, DIVariable VarInfo,
return CallInst::Create(DeclareFn, Args, "", InsertAtEnd);
}
-/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset,
DIVariable VarInfo,
+ DIExpression Expr,
Instruction *InsertBefore) {
assert(V && "no value passed to dbg.value");
assert(VarInfo.isVariable() &&
@@ -1300,15 +1131,15 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset,
if (!ValueFn)
ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value);
- Value *Args[] = { MDNode::get(V->getContext(), V),
- ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset),
- VarInfo };
+ Value *Args[] = {MDNode::get(V->getContext(), V),
+ ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset),
+ VarInfo, Expr};
return CallInst::Create(ValueFn, Args, "", InsertBefore);
}
-/// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call.
Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset,
DIVariable VarInfo,
+ DIExpression Expr,
BasicBlock *InsertAtEnd) {
assert(V && "no value passed to dbg.value");
assert(VarInfo.isVariable() &&
@@ -1316,8 +1147,8 @@ Instruction *DIBuilder::insertDbgValueIntrinsic(Value *V, uint64_t Offset,
if (!ValueFn)
ValueFn = Intrinsic::getDeclaration(&M, Intrinsic::dbg_value);
- Value *Args[] = { MDNode::get(V->getContext(), V),
- ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset),
- VarInfo };
+ Value *Args[] = {MDNode::get(V->getContext(), V),
+ ConstantInt::get(Type::getInt64Ty(V->getContext()), Offset),
+ VarInfo, Expr};
return CallInst::Create(ValueFn, Args, "", InsertAtEnd);
}
diff --git a/lib/IR/DataLayout.cpp b/lib/IR/DataLayout.cpp
index dea05fbef4..8a057f552a 100644
--- a/lib/IR/DataLayout.cpp
+++ b/lib/IR/DataLayout.cpp
@@ -55,7 +55,7 @@ StructLayout::StructLayout(StructType *ST, const DataLayout &DL) {
// Add padding if necessary to align the data element properly.
if ((StructSize & (TyAlign-1)) != 0)
- StructSize = DataLayout::RoundUpAlignment(StructSize, TyAlign);
+ StructSize = RoundUpToAlignment(StructSize, TyAlign);
// Keep track of maximum alignment constraint.
StructAlignment = std::max(TyAlign, StructAlignment);
@@ -70,7 +70,7 @@ StructLayout::StructLayout(StructType *ST, const DataLayout &DL) {
// Add padding to the end of the struct so that it could be put in an array
// and all array elements would be aligned correctly.
if ((StructSize & (StructAlignment-1)) != 0)
- StructSize = DataLayout::RoundUpAlignment(StructSize, StructAlignment);
+ StructSize = RoundUpToAlignment(StructSize, StructAlignment);
}
@@ -179,7 +179,7 @@ void DataLayout::reset(StringRef Desc) {
clear();
LayoutMap = nullptr;
- LittleEndian = false;
+ BigEndian = false;
StackNaturalAlign = 0;
ManglingMode = MM_None;
@@ -239,10 +239,10 @@ void DataLayout::parseSpecifier(StringRef Desc) {
// FIXME: remove this on LLVM 4.0.
break;
case 'E':
- LittleEndian = false;
+ BigEndian = true;
break;
case 'e':
- LittleEndian = true;
+ BigEndian = false;
break;
case 'p': {
// Address space.
@@ -345,6 +345,10 @@ void DataLayout::parseSpecifier(StringRef Desc) {
}
DataLayout::DataLayout(const Module *M) : LayoutMap(nullptr) {
+ init(M);
+}
+
+void DataLayout::init(const Module *M) {
const DataLayout *Other = M->getDataLayout();
if (Other)
*this = *Other;
@@ -353,7 +357,7 @@ DataLayout::DataLayout(const Module *M) : LayoutMap(nullptr) {
}
bool DataLayout::operator==(const DataLayout &Other) const {
- bool Ret = LittleEndian == Other.LittleEndian &&
+ bool Ret = BigEndian == Other.BigEndian &&
StackNaturalAlign == Other.StackNaturalAlign &&
ManglingMode == Other.ManglingMode &&
LegalIntWidths == Other.LegalIntWidths &&
@@ -522,7 +526,7 @@ std::string DataLayout::getStringRepresentation() const {
std::string Result;
raw_string_ostream OS(Result);
- OS << (LittleEndian ? "e" : "E");
+ OS << (BigEndian ? "E" : "e");
switch (ManglingMode) {
case MM_None:
@@ -637,7 +641,7 @@ unsigned DataLayout::getAlignment(Type *Ty, bool abi_or_pref) const {
? getPointerABIAlignment(0)
: getPointerPrefAlignment(0));
case Type::PointerTyID: {
- unsigned AS = dyn_cast<PointerType>(Ty)->getAddressSpace();
+ unsigned AS = cast<PointerType>(Ty)->getAddressSpace();
return (abi_or_pref
? getPointerABIAlignment(AS)
: getPointerPrefAlignment(AS));
@@ -796,17 +800,17 @@ unsigned DataLayout::getPreferredAlignmentLog(const GlobalVariable *GV) const {
}
DataLayoutPass::DataLayoutPass() : ImmutablePass(ID), DL("") {
- report_fatal_error("Bad DataLayoutPass ctor used. Tool did not specify a "
- "DataLayout to use?");
+ initializeDataLayoutPassPass(*PassRegistry::getPassRegistry());
}
DataLayoutPass::~DataLayoutPass() {}
-DataLayoutPass::DataLayoutPass(const DataLayout &DL)
- : ImmutablePass(ID), DL(DL) {
- initializeDataLayoutPassPass(*PassRegistry::getPassRegistry());
+bool DataLayoutPass::doInitialization(Module &M) {
+ DL.init(&M);
+ return false;
}
-DataLayoutPass::DataLayoutPass(const Module *M) : ImmutablePass(ID), DL(M) {
- initializeDataLayoutPassPass(*PassRegistry::getPassRegistry());
+bool DataLayoutPass::doFinalization(Module &M) {
+ DL.reset("");
+ return false;
}
diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp
index 5e39b242db..bb5161dcb9 100644
--- a/lib/IR/DebugInfo.cpp
+++ b/lib/IR/DebugInfo.cpp
@@ -19,6 +19,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DIBuilder.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
@@ -46,10 +47,9 @@ bool DIDescriptor::Verify() const {
DILexicalBlockFile(DbgNode).Verify() ||
DISubrange(DbgNode).Verify() || DIEnumerator(DbgNode).Verify() ||
DIObjCProperty(DbgNode).Verify() ||
- DIUnspecifiedParameter(DbgNode).Verify() ||
DITemplateTypeParameter(DbgNode).Verify() ||
DITemplateValueParameter(DbgNode).Verify() ||
- DIImportedEntity(DbgNode).Verify());
+ DIImportedEntity(DbgNode).Verify() || DIExpression(DbgNode).Verify());
}
static Value *getField(const MDNode *DbgNode, unsigned Elt) {
@@ -138,25 +138,53 @@ void DIDescriptor::replaceFunctionField(unsigned Elt, Function *F) {
}
}
-uint64_t DIVariable::getAddrElement(unsigned Idx) const {
- DIDescriptor ComplexExpr = getDescriptorField(8);
- if (Idx < ComplexExpr->getNumOperands())
- if (auto *CI = dyn_cast_or_null<ConstantInt>(ComplexExpr->getOperand(Idx)))
- return CI->getZExtValue();
+static unsigned DIVariableInlinedAtIndex = 4;
+MDNode *DIVariable::getInlinedAt() const {
+ return getNodeField(DbgNode, DIVariableInlinedAtIndex);
+}
- assert(false && "non-existing complex address element requested");
- return 0;
+/// \brief Return the size reported by the variable's type.
+unsigned DIVariable::getSizeInBits(const DITypeIdentifierMap &Map) {
+ DIType Ty = getType().resolve(Map);
+ // Follow derived types until we reach a type that
+ // reports back a size.
+ while (Ty.isDerivedType() && !Ty.getSizeInBits()) {
+ DIDerivedType DT(&*Ty);
+ Ty = DT.getTypeDerivedFrom().resolve(Map);
+ }
+ assert(Ty.getSizeInBits() && "type with size 0");
+ return Ty.getSizeInBits();
+}
+
+uint64_t DIExpression::getElement(unsigned Idx) const {
+ unsigned I = Idx + 1;
+ assert(I < getNumHeaderFields() &&
+ "non-existing complex address element requested");
+ return getHeaderFieldAs<int64_t>(I);
}
-/// getInlinedAt - If this variable is inlined then return inline location.
-MDNode *DIVariable::getInlinedAt() const { return getNodeField(DbgNode, 7); }
+bool DIExpression::isVariablePiece() const {
+ return getNumElements() && getElement(0) == dwarf::DW_OP_piece;
+}
+
+uint64_t DIExpression::getPieceOffset() const {
+ assert(isVariablePiece());
+ return getElement(1);
+}
+
+uint64_t DIExpression::getPieceSize() const {
+ assert(isVariablePiece());
+ return getElement(2);
+}
//===----------------------------------------------------------------------===//
// Predicates
//===----------------------------------------------------------------------===//
-/// isBasicType - Return true if the specified tag is legal for
-/// DIBasicType.
+bool DIDescriptor::isSubroutineType() const {
+ return isCompositeType() && getTag() == dwarf::DW_TAG_subroutine_type;
+}
+
bool DIDescriptor::isBasicType() const {
if (!DbgNode)
return false;
@@ -169,7 +197,6 @@ bool DIDescriptor::isBasicType() const {
}
}
-/// isDerivedType - Return true if the specified tag is legal for DIDerivedType.
bool DIDescriptor::isDerivedType() const {
if (!DbgNode)
return false;
@@ -192,8 +219,6 @@ bool DIDescriptor::isDerivedType() const {
}
}
-/// isCompositeType - Return true if the specified tag is legal for
-/// DICompositeType.
bool DIDescriptor::isCompositeType() const {
if (!DbgNode)
return false;
@@ -210,7 +235,6 @@ bool DIDescriptor::isCompositeType() const {
}
}
-/// isVariable - Return true if the specified tag is legal for DIVariable.
bool DIDescriptor::isVariable() const {
if (!DbgNode)
return false;
@@ -223,32 +247,19 @@ bool DIDescriptor::isVariable() const {
}
}
-/// isType - Return true if the specified tag is legal for DIType.
bool DIDescriptor::isType() const {
return isBasicType() || isCompositeType() || isDerivedType();
}
-/// isSubprogram - Return true if the specified tag is legal for
-/// DISubprogram.
bool DIDescriptor::isSubprogram() const {
return DbgNode && getTag() == dwarf::DW_TAG_subprogram;
}
-/// isGlobalVariable - Return true if the specified tag is legal for
-/// DIGlobalVariable.
bool DIDescriptor::isGlobalVariable() const {
return DbgNode && (getTag() == dwarf::DW_TAG_variable ||
getTag() == dwarf::DW_TAG_constant);
}
-/// isUnspecifiedParmeter - Return true if the specified tag is
-/// DW_TAG_unspecified_parameters.
-bool DIDescriptor::isUnspecifiedParameter() const {
- return DbgNode && getTag() == dwarf::DW_TAG_unspecified_parameters;
-}
-
-/// isScope - Return true if the specified tag is one of the scope
-/// related tag.
bool DIDescriptor::isScope() const {
if (!DbgNode)
return false;
@@ -265,83 +276,67 @@ bool DIDescriptor::isScope() const {
return isType();
}
-/// isTemplateTypeParameter - Return true if the specified tag is
-/// DW_TAG_template_type_parameter.
bool DIDescriptor::isTemplateTypeParameter() const {
return DbgNode && getTag() == dwarf::DW_TAG_template_type_parameter;
}
-/// isTemplateValueParameter - Return true if the specified tag is
-/// DW_TAG_template_value_parameter.
bool DIDescriptor::isTemplateValueParameter() const {
return DbgNode && (getTag() == dwarf::DW_TAG_template_value_parameter ||
getTag() == dwarf::DW_TAG_GNU_template_template_param ||
getTag() == dwarf::DW_TAG_GNU_template_parameter_pack);
}
-/// isCompileUnit - Return true if the specified tag is DW_TAG_compile_unit.
bool DIDescriptor::isCompileUnit() const {
return DbgNode && getTag() == dwarf::DW_TAG_compile_unit;
}
-/// isFile - Return true if the specified tag is DW_TAG_file_type.
bool DIDescriptor::isFile() const {
return DbgNode && getTag() == dwarf::DW_TAG_file_type;
}
-/// isNameSpace - Return true if the specified tag is DW_TAG_namespace.
bool DIDescriptor::isNameSpace() const {
return DbgNode && getTag() == dwarf::DW_TAG_namespace;
}
-/// isLexicalBlockFile - Return true if the specified descriptor is a
-/// lexical block with an extra file.
bool DIDescriptor::isLexicalBlockFile() const {
return DbgNode && getTag() == dwarf::DW_TAG_lexical_block &&
- (DbgNode->getNumOperands() == 3);
+ DbgNode->getNumOperands() == 3 && getNumHeaderFields() == 2;
}
-/// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block.
bool DIDescriptor::isLexicalBlock() const {
+ // FIXME: There are always exactly 4 header fields in DILexicalBlock, but
+ // something relies on this returning true for DILexicalBlockFile.
return DbgNode && getTag() == dwarf::DW_TAG_lexical_block &&
- (DbgNode->getNumOperands() > 3);
+ DbgNode->getNumOperands() == 3 &&
+ (getNumHeaderFields() == 2 || getNumHeaderFields() == 4);
}
-/// isSubrange - Return true if the specified tag is DW_TAG_subrange_type.
bool DIDescriptor::isSubrange() const {
return DbgNode && getTag() == dwarf::DW_TAG_subrange_type;
}
-/// isEnumerator - Return true if the specified tag is DW_TAG_enumerator.
bool DIDescriptor::isEnumerator() const {
return DbgNode && getTag() == dwarf::DW_TAG_enumerator;
}
-/// isObjCProperty - Return true if the specified tag is DW_TAG_APPLE_property.
bool DIDescriptor::isObjCProperty() const {
return DbgNode && getTag() == dwarf::DW_TAG_APPLE_property;
}
-/// \brief Return true if the specified tag is DW_TAG_imported_module or
-/// DW_TAG_imported_declaration.
bool DIDescriptor::isImportedEntity() const {
return DbgNode && (getTag() == dwarf::DW_TAG_imported_module ||
getTag() == dwarf::DW_TAG_imported_declaration);
}
+bool DIDescriptor::isExpression() const {
+ return DbgNode && (getTag() == dwarf::DW_TAG_expression);
+}
+
//===----------------------------------------------------------------------===//
// Simple Descriptor Constructors and other Methods
//===----------------------------------------------------------------------===//
-unsigned DIArray::getNumElements() const {
- if (!DbgNode)
- return 0;
- return DbgNode->getNumOperands();
-}
-
-/// replaceAllUsesWith - Replace all uses of the MDNode used by this
-/// type with the one in the passed descriptor.
-void DIType::replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D) {
+void DIDescriptor::replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D) {
assert(DbgNode && "Trying to replace an unverified type!");
@@ -362,12 +357,10 @@ void DIType::replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D) {
const Value *V = cast_or_null<Value>(DN);
Node->replaceAllUsesWith(const_cast<Value *>(V));
MDNode::deleteTemporary(Node);
- DbgNode = D;
+ DbgNode = DN;
}
-/// replaceAllUsesWith - Replace all uses of the MDNode used by this
-/// type with the one in D.
-void DIType::replaceAllUsesWith(MDNode *D) {
+void DIDescriptor::replaceAllUsesWith(MDNode *D) {
assert(DbgNode && "Trying to replace an unverified type!");
assert(DbgNode != D && "This replacement should always happen");
@@ -378,7 +371,6 @@ void DIType::replaceAllUsesWith(MDNode *D) {
MDNode::deleteTemporary(Node);
}
-/// Verify - Verify that a compile unit is well formed.
bool DICompileUnit::Verify() const {
if (!isCompileUnit())
return false;
@@ -388,19 +380,19 @@ bool DICompileUnit::Verify() const {
if (getFilename().empty())
return false;
- return DbgNode->getNumOperands() == 14;
+ return DbgNode->getNumOperands() == 7 && getNumHeaderFields() == 8;
}
-/// Verify - Verify that an ObjC property is well formed.
bool DIObjCProperty::Verify() const {
if (!isObjCProperty())
return false;
// Don't worry about the rest of the strings for now.
- return DbgNode->getNumOperands() == 8;
+ return DbgNode->getNumOperands() == 3 && getNumHeaderFields() == 6;
}
-/// Check if a field at position Elt of a MDNode is a MDNode.
+/// \brief Check if a field at position Elt of a MDNode is a MDNode.
+///
/// We currently allow an empty string and an integer.
/// But we don't allow a non-empty string in a MDNode field.
static bool fieldIsMDNode(const MDNode *DbgNode, unsigned Elt) {
@@ -412,41 +404,42 @@ static bool fieldIsMDNode(const MDNode *DbgNode, unsigned Elt) {
return true;
}
-/// Check if a field at position Elt of a MDNode is a MDString.
+/// \brief Check if a field at position Elt of a MDNode is a MDString.
static bool fieldIsMDString(const MDNode *DbgNode, unsigned Elt) {
Value *Fld = getField(DbgNode, Elt);
return !Fld || isa<MDString>(Fld);
}
-/// Check if a value can be a reference to a type.
-static bool isTypeRef(const Value *Val) {
- return !Val ||
- (isa<MDString>(Val) && !cast<MDString>(Val)->getString().empty()) ||
- (isa<MDNode>(Val) && DIType(cast<MDNode>(Val)).isType());
+/// \brief Check if a value can be a reference to a type.
+static bool isTypeRef(const Metadata *MD) {
+ if (!MD)
+ return true;
+ if (auto *S = dyn_cast<MDString>(MD))
+ return !S->getString().empty();
+ if (auto *N = dyn_cast<MDNode>(MD))
+ return DIType(N).isType();
+ return false;
}
-/// Check if a field at position Elt of a MDNode can be a reference to a type.
+/// \brief Check if referenced field might be a type.
static bool fieldIsTypeRef(const MDNode *DbgNode, unsigned Elt) {
- Value *Fld = getField(DbgNode, Elt);
- return isTypeRef(Fld);
+ return isTypeRef(dyn_cast_or_null<Metadata>(getField(DbgNode, Elt)));
}
-/// Check if a value can be a ScopeRef.
-static bool isScopeRef(const Value *Val) {
- return !Val ||
- (isa<MDString>(Val) && !cast<MDString>(Val)->getString().empty()) ||
- // Not checking for Val->isScope() here, because it would work
- // only for lexical scopes and not all subclasses of DIScope.
- isa<MDNode>(Val);
+/// \brief Check if a value can be a ScopeRef.
+static bool isScopeRef(const Metadata *MD) {
+ if (!MD)
+ return true;
+ if (auto *S = dyn_cast<MDString>(MD))
+ return !S->getString().empty();
+ return isa<MDNode>(MD);
}
-/// Check if a field at position Elt of a MDNode can be a ScopeRef.
+/// \brief Check if a field at position Elt of a MDNode can be a ScopeRef.
static bool fieldIsScopeRef(const MDNode *DbgNode, unsigned Elt) {
- Value *Fld = getField(DbgNode, Elt);
- return isScopeRef(Fld);
+ return isScopeRef(dyn_cast_or_null<Metadata>(getField(DbgNode, Elt)));
}
-/// Verify - Verify that a type descriptor is well formed.
bool DIType::Verify() const {
if (!isType())
return false;
@@ -467,6 +460,7 @@ bool DIType::Verify() const {
Tag != dwarf::DW_TAG_inheritance && Tag != dwarf::DW_TAG_friend &&
getFilename().empty())
return false;
+
// DIType is abstract, it should be a BasicType, a DerivedType or
// a CompositeType.
if (isBasicType())
@@ -479,89 +473,113 @@ bool DIType::Verify() const {
return false;
}
-/// Verify - Verify that a basic type descriptor is well formed.
bool DIBasicType::Verify() const {
- return isBasicType() && DbgNode->getNumOperands() == 10;
+ return isBasicType() && DbgNode->getNumOperands() == 3 &&
+ getNumHeaderFields() == 8;
}
-/// Verify - Verify that a derived type descriptor is well formed.
bool DIDerivedType::Verify() const {
- // Make sure DerivedFrom @ field 9 is TypeRef.
- if (!fieldIsTypeRef(DbgNode, 9))
+ // Make sure DerivedFrom @ field 3 is TypeRef.
+ if (!fieldIsTypeRef(DbgNode, 3))
return false;
if (getTag() == dwarf::DW_TAG_ptr_to_member_type)
- // Make sure ClassType @ field 10 is a TypeRef.
- if (!fieldIsTypeRef(DbgNode, 10))
+ // Make sure ClassType @ field 4 is a TypeRef.
+ if (!fieldIsTypeRef(DbgNode, 4))
return false;
- return isDerivedType() && DbgNode->getNumOperands() >= 10 &&
- DbgNode->getNumOperands() <= 14;
+ return isDerivedType() && DbgNode->getNumOperands() >= 4 &&
+ DbgNode->getNumOperands() <= 8 && getNumHeaderFields() >= 7 &&
+ getNumHeaderFields() <= 8;
}
-/// Verify - Verify that a composite type descriptor is well formed.
bool DICompositeType::Verify() const {
if (!isCompositeType())
return false;
- // Make sure DerivedFrom @ field 9 and ContainingType @ field 12 are TypeRef.
- if (!fieldIsTypeRef(DbgNode, 9))
+ // Make sure DerivedFrom @ field 3 and ContainingType @ field 5 are TypeRef.
+ if (!fieldIsTypeRef(DbgNode, 3))
return false;
- if (!fieldIsTypeRef(DbgNode, 12))
+ if (!fieldIsTypeRef(DbgNode, 5))
return false;
- // Make sure the type identifier at field 14 is MDString, it can be null.
- if (!fieldIsMDString(DbgNode, 14))
+ // Make sure the type identifier at field 7 is MDString, it can be null.
+ if (!fieldIsMDString(DbgNode, 7))
return false;
// A subroutine type can't be both & and &&.
if (isLValueReference() && isRValueReference())
return false;
- return DbgNode->getNumOperands() == 15;
+ return DbgNode->getNumOperands() == 8 && getNumHeaderFields() == 8;
}
-/// Verify - Verify that a subprogram descriptor is well formed.
bool DISubprogram::Verify() const {
if (!isSubprogram())
return false;
- // Make sure context @ field 2 is a ScopeRef and type @ field 7 is a MDNode.
+ // Make sure context @ field 2 is a ScopeRef and type @ field 3 is a MDNode.
if (!fieldIsScopeRef(DbgNode, 2))
return false;
- if (!fieldIsMDNode(DbgNode, 7))
+ if (!fieldIsMDNode(DbgNode, 3))
return false;
- // Containing type @ field 12.
- if (!fieldIsTypeRef(DbgNode, 12))
+ // Containing type @ field 4.
+ if (!fieldIsTypeRef(DbgNode, 4))
return false;
// A subprogram can't be both & and &&.
if (isLValueReference() && isRValueReference())
return false;
- return DbgNode->getNumOperands() == 20;
+ // If a DISubprogram has an llvm::Function*, then scope chains from all
+ // instructions within the function should lead to this DISubprogram.
+ if (auto *F = getFunction()) {
+ LLVMContext &Ctxt = F->getContext();
+ for (auto &BB : *F) {
+ for (auto &I : BB) {
+ DebugLoc DL = I.getDebugLoc();
+ if (DL.isUnknown())
+ continue;
+
+ MDNode *Scope = nullptr;
+ MDNode *IA = nullptr;
+ // walk the inlined-at scopes
+ while (DL.getScopeAndInlinedAt(Scope, IA, F->getContext()), IA)
+ DL = DebugLoc::getFromDILocation(IA);
+ DL.getScopeAndInlinedAt(Scope, IA, Ctxt);
+ assert(!IA);
+ while (!DIDescriptor(Scope).isSubprogram()) {
+ DILexicalBlockFile D(Scope);
+ Scope = D.isLexicalBlockFile()
+ ? D.getScope()
+ : DebugLoc::getFromDILexicalBlock(Scope).getScope(Ctxt);
+ }
+ if (!DISubprogram(Scope).describes(F))
+ return false;
+ }
+ }
+ }
+ return DbgNode->getNumOperands() == 9 && getNumHeaderFields() == 12;
}
-/// Verify - Verify that a global variable descriptor is well formed.
bool DIGlobalVariable::Verify() const {
if (!isGlobalVariable())
return false;
if (getDisplayName().empty())
return false;
- // Make sure context @ field 2 is an MDNode.
- if (!fieldIsMDNode(DbgNode, 2))
+ // Make sure context @ field 1 is a ScopeRef.
+ if (!fieldIsScopeRef(DbgNode, 1))
return false;
- // Make sure that type @ field 8 is a DITypeRef.
- if (!fieldIsTypeRef(DbgNode, 8))
+ // Make sure that type @ field 3 is a DITypeRef.
+ if (!fieldIsTypeRef(DbgNode, 3))
return false;
- // Make sure StaticDataMemberDeclaration @ field 12 is MDNode.
- if (!fieldIsMDNode(DbgNode, 12))
+ // Make sure StaticDataMemberDeclaration @ field 5 is MDNode.
+ if (!fieldIsMDNode(DbgNode, 5))
return false;
- return DbgNode->getNumOperands() == 13;
+ return DbgNode->getNumOperands() == 6 && getNumHeaderFields() == 7;
}
-/// Verify - Verify that a variable descriptor is well formed.
bool DIVariable::Verify() const {
if (!isVariable())
return false;
@@ -569,19 +587,31 @@ bool DIVariable::Verify() const {
// Make sure context @ field 1 is an MDNode.
if (!fieldIsMDNode(DbgNode, 1))
return false;
- // Make sure that type @ field 5 is a DITypeRef.
- if (!fieldIsTypeRef(DbgNode, 5))
+ // Make sure that type @ field 3 is a DITypeRef.
+ if (!fieldIsTypeRef(DbgNode, 3))
return false;
- // Variable without a complex expression.
- if (DbgNode->getNumOperands() == 8)
+ // Check the number of header fields, which is common between complex and
+ // simple variables.
+ if (getNumHeaderFields() != 4)
+ return false;
+
+ // Variable without an inline location.
+ if (DbgNode->getNumOperands() == 4)
+ return true;
+
+ // Variable with an inline location.
+ return getInlinedAt() != nullptr && DbgNode->getNumOperands() == 5;
+}
+
+bool DIExpression::Verify() const {
+ // Empty DIExpressions may be represented as a nullptr.
+ if (!DbgNode)
return true;
- // Make sure the complex expression is an MDNode.
- return (DbgNode->getNumOperands() == 9 && fieldIsMDNode(DbgNode, 8));
+ return isExpression() && DbgNode->getNumOperands() == 1;
}
-/// Verify - Verify that a location descriptor is well formed.
bool DILocation::Verify() const {
if (!DbgNode)
return false;
@@ -589,69 +619,59 @@ bool DILocation::Verify() const {
return DbgNode->getNumOperands() == 4;
}
-/// Verify - Verify that a namespace descriptor is well formed.
bool DINameSpace::Verify() const {
if (!isNameSpace())
return false;
- return DbgNode->getNumOperands() == 5;
+ return DbgNode->getNumOperands() == 3 && getNumHeaderFields() == 3;
}
-/// \brief Retrieve the MDNode for the directory/file pair.
MDNode *DIFile::getFileNode() const { return getNodeField(DbgNode, 1); }
-/// \brief Verify that the file descriptor is well formed.
bool DIFile::Verify() const {
return isFile() && DbgNode->getNumOperands() == 2;
}
-/// \brief Verify that the enumerator descriptor is well formed.
bool DIEnumerator::Verify() const {
- return isEnumerator() && DbgNode->getNumOperands() == 3;
+ return isEnumerator() && DbgNode->getNumOperands() == 1 &&
+ getNumHeaderFields() == 3;
}
-/// \brief Verify that the subrange descriptor is well formed.
bool DISubrange::Verify() const {
- return isSubrange() && DbgNode->getNumOperands() == 3;
+ return isSubrange() && DbgNode->getNumOperands() == 1 &&
+ getNumHeaderFields() == 3;
}
-/// \brief Verify that the lexical block descriptor is well formed.
bool DILexicalBlock::Verify() const {
- return isLexicalBlock() && DbgNode->getNumOperands() == 7;
+ return isLexicalBlock() && DbgNode->getNumOperands() == 3 &&
+ getNumHeaderFields() == 4;
}
-/// \brief Verify that the file-scoped lexical block descriptor is well formed.
bool DILexicalBlockFile::Verify() const {
- return isLexicalBlockFile() && DbgNode->getNumOperands() == 3;
-}
-
-/// \brief Verify that an unspecified parameter descriptor is well formed.
-bool DIUnspecifiedParameter::Verify() const {
- return isUnspecifiedParameter() && DbgNode->getNumOperands() == 1;
+ return isLexicalBlockFile() && DbgNode->getNumOperands() == 3 &&
+ getNumHeaderFields() == 2;
}
-/// \brief Verify that the template type parameter descriptor is well formed.
bool DITemplateTypeParameter::Verify() const {
- return isTemplateTypeParameter() && DbgNode->getNumOperands() == 7;
+ return isTemplateTypeParameter() && DbgNode->getNumOperands() == 4 &&
+ getNumHeaderFields() == 4;
}
-/// \brief Verify that the template value parameter descriptor is well formed.
bool DITemplateValueParameter::Verify() const {
- return isTemplateValueParameter() && DbgNode->getNumOperands() == 8;
+ return isTemplateValueParameter() && DbgNode->getNumOperands() == 5 &&
+ getNumHeaderFields() == 4;
}
-/// \brief Verify that the imported module descriptor is well formed.
bool DIImportedEntity::Verify() const {
- return isImportedEntity() &&
- (DbgNode->getNumOperands() == 4 || DbgNode->getNumOperands() == 5);
+ return isImportedEntity() && DbgNode->getNumOperands() == 3 &&
+ getNumHeaderFields() == 3;
}
-/// getObjCProperty - Return property node, if this ivar is associated with one.
MDNode *DIDerivedType::getObjCProperty() const {
- return getNodeField(DbgNode, 10);
+ return getNodeField(DbgNode, 4);
}
MDString *DICompositeType::getIdentifier() const {
- return cast_or_null<MDString>(getField(DbgNode, 14));
+ return cast_or_null<MDString>(getField(DbgNode, 7));
}
#ifndef NDEBUG
@@ -669,27 +689,21 @@ static void VerifySubsetOf(const MDNode *LHS, const MDNode *RHS) {
}
#endif
-/// \brief Set the array of member DITypes.
-void DICompositeType::setTypeArray(DIArray Elements, DIArray TParams) {
- assert((!TParams || DbgNode->getNumOperands() == 15) &&
- "If you're setting the template parameters this should include a slot "
- "for that!");
+void DICompositeType::setArraysHelper(MDNode *Elements, MDNode *TParams) {
TrackingVH<MDNode> N(*this);
if (Elements) {
#ifndef NDEBUG
// Check that the new list of members contains all the old members as well.
- if (const MDNode *El = cast_or_null<MDNode>(N->getOperand(10)))
+ if (const MDNode *El = cast_or_null<MDNode>(N->getOperand(4)))
VerifySubsetOf(El, Elements);
#endif
- N->replaceOperandWith(10, Elements);
+ N->replaceOperandWith(4, Elements);
}
if (TParams)
- N->replaceOperandWith(13, TParams);
+ N->replaceOperandWith(6, TParams);
DbgNode = N;
}
-/// Generate a reference to this DIType. Uses the type identifier instead
-/// of the actual MDNode if possible, to help type uniquing.
DIScopeRef DIScope::getRef() const {
if (!isCompositeType())
return DIScopeRef(*this);
@@ -699,15 +713,12 @@ DIScopeRef DIScope::getRef() const {
return DIScopeRef(DTy.getIdentifier());
}
-/// \brief Set the containing type.
void DICompositeType::setContainingType(DICompositeType ContainingType) {
TrackingVH<MDNode> N(*this);
- N->replaceOperandWith(12, ContainingType.getRef());
+ N->replaceOperandWith(5, ContainingType.getRef());
DbgNode = N;
}
-/// isInlinedFnArgument - Return true if this variable provides debugging
-/// information for an inlined function arguments.
bool DIVariable::isInlinedFnArgument(const Function *CurFn) {
assert(CurFn && "Invalid function");
if (!getContext().isSubprogram())
@@ -717,8 +728,6 @@ bool DIVariable::isInlinedFnArgument(const Function *CurFn) {
return !DISubprogram(getContext()).describes(CurFn);
}
-/// describes - Return true if this subprogram provides debugging
-/// information for the function F.
bool DISubprogram::describes(const Function *F) {
assert(F && "Invalid function");
if (F == getFunction())
@@ -731,27 +740,18 @@ bool DISubprogram::describes(const Function *F) {
return false;
}
-unsigned DISubprogram::isOptimized() const {
- assert(DbgNode && "Invalid subprogram descriptor!");
- if (DbgNode->getNumOperands() == 15)
- return getUnsignedField(14);
- return 0;
-}
-
MDNode *DISubprogram::getVariablesNodes() const {
- return getNodeField(DbgNode, 18);
+ return getNodeField(DbgNode, 8);
}
DIArray DISubprogram::getVariables() const {
- return DIArray(getNodeField(DbgNode, 18));
+ return DIArray(getNodeField(DbgNode, 8));
}
Value *DITemplateValueParameter::getValue() const {
- return getField(DbgNode, 4);
+ return getField(DbgNode, 3);
}
-// If the current node has a parent scope then return that,
-// else return an empty scope.
DIScopeRef DIScope::getContext() const {
if (isType())
@@ -773,7 +773,6 @@ DIScopeRef DIScope::getContext() const {
return DIScopeRef(nullptr);
}
-// If the scope node has a name, return that, else return an empty string.
StringRef DIScope::getName() const {
if (isType())
return DIType(DbgNode).getName();
@@ -800,44 +799,58 @@ StringRef DIScope::getDirectory() const {
}
DIArray DICompileUnit::getEnumTypes() const {
- if (!DbgNode || DbgNode->getNumOperands() < 13)
+ if (!DbgNode || DbgNode->getNumOperands() < 7)
return DIArray();
- return DIArray(getNodeField(DbgNode, 7));
+ return DIArray(getNodeField(DbgNode, 2));
}
DIArray DICompileUnit::getRetainedTypes() const {
- if (!DbgNode || DbgNode->getNumOperands() < 13)
+ if (!DbgNode || DbgNode->getNumOperands() < 7)
return DIArray();
- return DIArray(getNodeField(DbgNode, 8));
+ return DIArray(getNodeField(DbgNode, 3));
}
DIArray DICompileUnit::getSubprograms() const {
- if (!DbgNode || DbgNode->getNumOperands() < 13)
+ if (!DbgNode || DbgNode->getNumOperands() < 7)
return DIArray();
- return DIArray(getNodeField(DbgNode, 9));
+ return DIArray(getNodeField(DbgNode, 4));
}
DIArray DICompileUnit::getGlobalVariables() const {
- if (!DbgNode || DbgNode->getNumOperands() < 13)
+ if (!DbgNode || DbgNode->getNumOperands() < 7)
return DIArray();
- return DIArray(getNodeField(DbgNode, 10));
+ return DIArray(getNodeField(DbgNode, 5));
}
DIArray DICompileUnit::getImportedEntities() const {
- if (!DbgNode || DbgNode->getNumOperands() < 13)
+ if (!DbgNode || DbgNode->getNumOperands() < 7)
return DIArray();
- return DIArray(getNodeField(DbgNode, 11));
+ return DIArray(getNodeField(DbgNode, 6));
+}
+
+void DICompileUnit::replaceSubprograms(DIArray Subprograms) {
+ assert(Verify() && "Expected compile unit");
+ if (Subprograms == getSubprograms())
+ return;
+
+ const_cast<MDNode *>(DbgNode)->replaceOperandWith(4, Subprograms);
+}
+
+void DICompileUnit::replaceGlobalVariables(DIArray GlobalVariables) {
+ assert(Verify() && "Expected compile unit");
+ if (GlobalVariables == getGlobalVariables())
+ return;
+
+ const_cast<MDNode *>(DbgNode)->replaceOperandWith(5, GlobalVariables);
}
-/// copyWithNewScope - Return a copy of this location, replacing the
-/// current scope with the given one.
DILocation DILocation::copyWithNewScope(LLVMContext &Ctx,
- DILexicalBlock NewScope) {
+ DILexicalBlockFile NewScope) {
SmallVector<Value *, 10> Elts;
assert(Verify());
for (unsigned I = 0; I < DbgNode->getNumOperands(); ++I) {
@@ -850,78 +863,43 @@ DILocation DILocation::copyWithNewScope(LLVMContext &Ctx,
return DILocation(NewDIL);
}
-/// computeNewDiscriminator - Generate a new discriminator value for this
-/// file and line location.
unsigned DILocation::computeNewDiscriminator(LLVMContext &Ctx) {
std::pair<const char *, unsigned> Key(getFilename().data(), getLineNumber());
return ++Ctx.pImpl->DiscriminatorTable[Key];
}
-/// fixupSubprogramName - Replace contains special characters used
-/// in a typical Objective-C names with '.' in a given string.
-static void fixupSubprogramName(DISubprogram Fn, SmallVectorImpl<char> &Out) {
- StringRef FName =
- Fn.getFunction() ? Fn.getFunction()->getName() : Fn.getName();
- FName = Function::getRealLinkageName(FName);
-
- StringRef Prefix("llvm.dbg.lv.");
- Out.reserve(FName.size() + Prefix.size());
- Out.append(Prefix.begin(), Prefix.end());
-
- bool isObjCLike = false;
- for (size_t i = 0, e = FName.size(); i < e; ++i) {
- char C = FName[i];
- if (C == '[')
- isObjCLike = true;
+DIVariable llvm::createInlinedVariable(MDNode *DV, MDNode *InlinedScope,
+ LLVMContext &VMContext) {
+ assert(DIVariable(DV).Verify() && "Expected a DIVariable");
+ if (!InlinedScope)
+ return cleanseInlinedVariable(DV, VMContext);
- if (isObjCLike && (C == '[' || C == ']' || C == ' ' || C == ':' ||
- C == '+' || C == '(' || C == ')'))
- Out.push_back('.');
- else
- Out.push_back(C);
- }
-}
+ // Insert inlined scope.
+ SmallVector<Value *, 8> Elts;
+ for (unsigned I = 0, E = DIVariableInlinedAtIndex; I != E; ++I)
+ Elts.push_back(DV->getOperand(I));
+ Elts.push_back(InlinedScope);
-/// getFnSpecificMDNode - Return a NameMDNode, if available, that is
-/// suitable to hold function specific information.
-NamedMDNode *llvm::getFnSpecificMDNode(const Module &M, DISubprogram Fn) {
- SmallString<32> Name;
- fixupSubprogramName(Fn, Name);
- return M.getNamedMetadata(Name.str());
+ DIVariable Inlined(MDNode::get(VMContext, Elts));
+ assert(Inlined.Verify() && "Expected to create a DIVariable");
+ return Inlined;
}
-/// getOrInsertFnSpecificMDNode - Return a NameMDNode that is suitable
-/// to hold function specific information.
-NamedMDNode *llvm::getOrInsertFnSpecificMDNode(Module &M, DISubprogram Fn) {
- SmallString<32> Name;
- fixupSubprogramName(Fn, Name);
- return M.getOrInsertNamedMetadata(Name.str());
-}
+DIVariable llvm::cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext) {
+ assert(DIVariable(DV).Verify() && "Expected a DIVariable");
+ if (!DIVariable(DV).getInlinedAt())
+ return DIVariable(DV);
-/// createInlinedVariable - Create a new inlined variable based on current
-/// variable.
-/// @param DV Current Variable.
-/// @param InlinedScope Location at current variable is inlined.
-DIVariable llvm::createInlinedVariable(MDNode *DV, MDNode *InlinedScope,
- LLVMContext &VMContext) {
- SmallVector<Value *, 16> Elts;
- // Insert inlined scope as 7th element.
- for (unsigned i = 0, e = DV->getNumOperands(); i != e; ++i)
- i == 7 ? Elts.push_back(InlinedScope) : Elts.push_back(DV->getOperand(i));
- return DIVariable(MDNode::get(VMContext, Elts));
-}
+ // Remove inlined scope.
+ SmallVector<Value *, 8> Elts;
+ for (unsigned I = 0, E = DIVariableInlinedAtIndex; I != E; ++I)
+ Elts.push_back(DV->getOperand(I));
-/// cleanseInlinedVariable - Remove inlined scope from the variable.
-DIVariable llvm::cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext) {
- SmallVector<Value *, 16> Elts;
- // Insert inlined scope as 7th element.
- for (unsigned i = 0, e = DV->getNumOperands(); i != e; ++i)
- i == 7 ? Elts.push_back(Constant::getNullValue(Type::getInt32Ty(VMContext)))
- : Elts.push_back(DV->getOperand(i));
- return DIVariable(MDNode::get(VMContext, Elts));
+ DIVariable Cleansed(MDNode::get(VMContext, Elts));
+ assert(Cleansed.Verify() && "Expected to create a DIVariable");
+ return Cleansed;
}
-/// getDISubprogram - Find subprogram that is enclosing this scope.
DISubprogram llvm::getDISubprogram(const MDNode *Scope) {
DIDescriptor D(Scope);
if (D.isSubprogram())
@@ -936,7 +914,23 @@ DISubprogram llvm::getDISubprogram(const MDNode *Scope) {
return DISubprogram();
}
-/// getDICompositeType - Find underlying composite type.
+DISubprogram llvm::getDISubprogram(const Function *F) {
+ // We look for the first instr that has a debug annotation leading back to F.
+ for (auto &BB : *F) {
+ auto Inst = std::find_if(BB.begin(), BB.end(), [](const Instruction &Inst) {
+ return !Inst.getDebugLoc().isUnknown();
+ });
+ if (Inst == BB.end())
+ continue;
+ DebugLoc DLoc = Inst->getDebugLoc();
+ const MDNode *Scope = DLoc.getScopeNode(F->getParent()->getContext());
+ DISubprogram Subprogram = getDISubprogram(Scope);
+ return Subprogram.describes(F) ? Subprogram : DISubprogram();
+ }
+
+ return DISubprogram();
+}
+
DICompositeType llvm::getDICompositeType(DIType T) {
if (T.isCompositeType())
return DICompositeType(T);
@@ -953,7 +947,6 @@ DICompositeType llvm::getDICompositeType(DIType T) {
return DICompositeType();
}
-/// Update DITypeIdentifierMap by going through retained types of each CU.
DITypeIdentifierMap
llvm::generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes) {
DITypeIdentifierMap Map;
@@ -1002,7 +995,6 @@ void DebugInfoFinder::InitializeTypeMap(const Module &M) {
}
}
-/// processModule - Process entire module and collect debug info.
void DebugInfoFinder::processModule(const Module &M) {
InitializeTypeMap(M);
if (NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu")) {
@@ -1013,7 +1005,7 @@ void DebugInfoFinder::processModule(const Module &M) {
for (unsigned i = 0, e = GVs.getNumElements(); i != e; ++i) {
DIGlobalVariable DIG(GVs.getElement(i));
if (addGlobalVariable(DIG)) {
- processScope(DIG.getContext());
+ processScope(DIG.getContext().resolve(TypeIdentifierMap));
processType(DIG.getType().resolve(TypeIdentifierMap));
}
}
@@ -1041,7 +1033,6 @@ void DebugInfoFinder::processModule(const Module &M) {
}
}
-/// processLocation - Process DILocation.
void DebugInfoFinder::processLocation(const Module &M, DILocation Loc) {
if (!Loc)
return;
@@ -1050,7 +1041,6 @@ void DebugInfoFinder::processLocation(const Module &M, DILocation Loc) {
processLocation(M, Loc.getOrigLocation());
}
-/// processType - Process DIType.
void DebugInfoFinder::processType(DIType DT) {
if (!addType(DT))
return;
@@ -1058,7 +1048,13 @@ void DebugInfoFinder::processType(DIType DT) {
if (DT.isCompositeType()) {
DICompositeType DCT(DT);
processType(DCT.getTypeDerivedFrom().resolve(TypeIdentifierMap));
- DIArray DA = DCT.getTypeArray();
+ if (DT.isSubroutineType()) {
+ DITypeArray DTA = DISubroutineType(DT).getTypeArray();
+ for (unsigned i = 0, e = DTA.getNumElements(); i != e; ++i)
+ processType(DTA.getElement(i).resolve(TypeIdentifierMap));
+ return;
+ }
+ DIArray DA = DCT.getElements();
for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) {
DIDescriptor D = DA.getElement(i);
if (D.isType())
@@ -1100,7 +1096,6 @@ void DebugInfoFinder::processScope(DIScope Scope) {
}
}
-/// processSubprogram - Process DISubprogram.
void DebugInfoFinder::processSubprogram(DISubprogram SP) {
if (!addSubprogram(SP))
return;
@@ -1121,7 +1116,6 @@ void DebugInfoFinder::processSubprogram(DISubprogram SP) {
}
}
-/// processDeclare - Process DbgDeclareInst.
void DebugInfoFinder::processDeclare(const Module &M,
const DbgDeclareInst *DDI) {
MDNode *N = dyn_cast<MDNode>(DDI->getVariable());
@@ -1133,7 +1127,7 @@ void DebugInfoFinder::processDeclare(const Module &M,
if (!DV.isVariable())
return;
- if (!NodesSeen.insert(DV))
+ if (!NodesSeen.insert(DV).second)
return;
processScope(DIVariable(N).getContext());
processType(DIVariable(N).getType().resolve(TypeIdentifierMap));
@@ -1149,53 +1143,49 @@ void DebugInfoFinder::processValue(const Module &M, const DbgValueInst *DVI) {
if (!DV.isVariable())
return;
- if (!NodesSeen.insert(DV))
+ if (!NodesSeen.insert(DV).second)
return;
processScope(DIVariable(N).getContext());
processType(DIVariable(N).getType().resolve(TypeIdentifierMap));
}
-/// addType - Add type into Tys.
bool DebugInfoFinder::addType(DIType DT) {
if (!DT)
return false;
- if (!NodesSeen.insert(DT))
+ if (!NodesSeen.insert(DT).second)
return false;
TYs.push_back(DT);
return true;
}
-/// addCompileUnit - Add compile unit into CUs.
bool DebugInfoFinder::addCompileUnit(DICompileUnit CU) {
if (!CU)
return false;
- if (!NodesSeen.insert(CU))
+ if (!NodesSeen.insert(CU).second)
return false;
CUs.push_back(CU);
return true;
}
-/// addGlobalVariable - Add global variable into GVs.
bool DebugInfoFinder::addGlobalVariable(DIGlobalVariable DIG) {
if (!DIG)
return false;
- if (!NodesSeen.insert(DIG))
+ if (!NodesSeen.insert(DIG).second)
return false;
GVs.push_back(DIG);
return true;
}
-// addSubprogram - Add subprgoram into SPs.
bool DebugInfoFinder::addSubprogram(DISubprogram SP) {
if (!SP)
return false;
- if (!NodesSeen.insert(SP))
+ if (!NodesSeen.insert(SP).second)
return false;
SPs.push_back(SP);
@@ -1209,7 +1199,7 @@ bool DebugInfoFinder::addScope(DIScope Scope) {
// as null for now.
if (Scope->getNumOperands() == 0)
return false;
- if (!NodesSeen.insert(Scope))
+ if (!NodesSeen.insert(Scope).second)
return false;
Scopes.push_back(Scope);
return true;
@@ -1219,13 +1209,11 @@ bool DebugInfoFinder::addScope(DIScope Scope) {
// DIDescriptor: dump routines for all descriptors.
//===----------------------------------------------------------------------===//
-/// dump - Print descriptor to dbgs() with a newline.
void DIDescriptor::dump() const {
print(dbgs());
dbgs() << '\n';
}
-/// print - Print descriptor.
void DIDescriptor::print(raw_ostream &OS) const {
if (!DbgNode)
return;
@@ -1259,6 +1247,8 @@ void DIDescriptor::print(raw_ostream &OS) const {
DINameSpace(DbgNode).printInternal(OS);
} else if (this->isScope()) {
DIScope(DbgNode).printInternal(OS);
+ } else if (this->isExpression()) {
+ DIExpression(DbgNode).printInternal(OS);
}
}
@@ -1311,6 +1301,8 @@ void DIType::printInternal(raw_ostream &OS) const {
OS << " [private]";
else if (isProtected())
OS << " [protected]";
+ else if (isPublic())
+ OS << " [public]";
if (isArtificial())
OS << " [artificial]";
@@ -1341,7 +1333,7 @@ void DIDerivedType::printInternal(raw_ostream &OS) const {
void DICompositeType::printInternal(raw_ostream &OS) const {
DIType::printInternal(OS);
- DIArray A = getTypeArray();
+ DIArray A = getElements();
OS << " [" << A.getNumElements() << " elements]";
}
@@ -1370,6 +1362,8 @@ void DISubprogram::printInternal(raw_ostream &OS) const {
OS << " [private]";
else if (isProtected())
OS << " [protected]";
+ else if (isPublic())
+ OS << " [public]";
if (isLValueReference())
OS << " [reference]";
@@ -1406,6 +1400,30 @@ void DIVariable::printInternal(raw_ostream &OS) const {
OS << " [line " << getLineNumber() << ']';
}
+void DIExpression::printInternal(raw_ostream &OS) const {
+ for (unsigned I = 0; I < getNumElements(); ++I) {
+ uint64_t OpCode = getElement(I);
+ OS << " [" << OperationEncodingString(OpCode);
+ switch (OpCode) {
+ case DW_OP_plus: {
+ OS << " " << getElement(++I);
+ break;
+ }
+ case DW_OP_piece: {
+ unsigned Offset = getElement(++I);
+ unsigned Size = getElement(++I);
+ OS << " offset=" << Offset << ", size=" << Size;
+ break;
+ }
+ default:
+ // Else bail out early. This may be a line table entry.
+ OS << "Unknown]";
+ return;
+ }
+ OS << "]";
+ }
+}
+
void DIObjCProperty::printInternal(raw_ostream &OS) const {
StringRef Name = getObjCPropertyName();
if (!Name.empty())
@@ -1449,30 +1467,22 @@ void DIVariable::printExtendedName(raw_ostream &OS) const {
}
}
-/// Specialize constructor to make sure it has the correct type.
-template <> DIRef<DIScope>::DIRef(const Value *V) : Val(V) {
+template <> DIRef<DIScope>::DIRef(const Metadata *V) : Val(V) {
assert(isScopeRef(V) && "DIScopeRef should be a MDString or MDNode");
}
-template <> DIRef<DIType>::DIRef(const Value *V) : Val(V) {
+template <> DIRef<DIType>::DIRef(const Metadata *V) : Val(V) {
assert(isTypeRef(V) && "DITypeRef should be a MDString or MDNode");
}
-/// Specialize getFieldAs to handle fields that are references to DIScopes.
template <>
DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const {
- return DIScopeRef(getField(DbgNode, Elt));
+ return DIScopeRef(cast_or_null<Metadata>(getField(DbgNode, Elt)));
}
-/// Specialize getFieldAs to handle fields that are references to DITypes.
template <> DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const {
- return DITypeRef(getField(DbgNode, Elt));
+ return DITypeRef(cast_or_null<Metadata>(getField(DbgNode, Elt)));
}
-/// Strip debug info in the module if it exists.
-/// To do this, we remove all calls to the debugger intrinsics and any named
-/// metadata for debugging. We also remove debug locations for instructions.
-/// Return true if module is modified.
bool llvm::StripDebugInfo(Module &M) {
-
bool Changed = false;
// Remove all of the calls to the debugger intrinsics, and remove them from
@@ -1519,7 +1529,6 @@ bool llvm::StripDebugInfo(Module &M) {
return Changed;
}
-/// Return Debug Info Metadata Version by checking module flags.
unsigned llvm::getDebugMetadataVersionFromModule(const Module &M) {
Value *Val = M.getModuleFlag("Debug Info Version");
if (!Val)
diff --git a/lib/IR/DebugLoc.cpp b/lib/IR/DebugLoc.cpp
index e8bdccebae..718da852fe 100644
--- a/lib/IR/DebugLoc.cpp
+++ b/lib/IR/DebugLoc.cpp
@@ -79,14 +79,8 @@ MDNode *DebugLoc::getScopeNode(const LLVMContext &Ctx) const {
DebugLoc DebugLoc::getFnDebugLoc(const LLVMContext &Ctx) const {
const MDNode *Scope = getScopeNode(Ctx);
DISubprogram SP = getDISubprogram(Scope);
- if (SP.isSubprogram()) {
- // Check for number of operands since the compatibility is
- // cheap here. FIXME: Name the magic constant.
- if (SP->getNumOperands() > 19)
- return DebugLoc::get(SP.getScopeLineNumber(), 0, SP);
- else
- return DebugLoc::get(SP.getLineNumber(), 0, SP);
- }
+ if (SP.isSubprogram())
+ return DebugLoc::get(SP.getScopeLineNumber(), 0, SP);
return DebugLoc();
}
diff --git a/lib/IR/DiagnosticInfo.cpp b/lib/IR/DiagnosticInfo.cpp
index 2727063600..37cce2b0d7 100644
--- a/lib/IR/DiagnosticInfo.cpp
+++ b/lib/IR/DiagnosticInfo.cpp
@@ -127,20 +127,20 @@ void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const {
DP << getMsg();
}
-bool DiagnosticInfoOptimizationRemarkBase::isLocationAvailable() const {
+bool DiagnosticInfoOptimizationBase::isLocationAvailable() const {
return getDebugLoc().isUnknown() == false;
}
-void DiagnosticInfoOptimizationRemarkBase::getLocation(StringRef *Filename,
- unsigned *Line,
- unsigned *Column) const {
+void DiagnosticInfoOptimizationBase::getLocation(StringRef *Filename,
+ unsigned *Line,
+ unsigned *Column) const {
DILocation DIL(getDebugLoc().getAsMDNode(getFunction().getContext()));
*Filename = DIL.getFilename();
*Line = DIL.getLineNumber();
*Column = DIL.getColumnNumber();
}
-const std::string DiagnosticInfoOptimizationRemarkBase::getLocationStr() const {
+const std::string DiagnosticInfoOptimizationBase::getLocationStr() const {
StringRef Filename("<unknown>");
unsigned Line = 0;
unsigned Column = 0;
@@ -149,7 +149,7 @@ const std::string DiagnosticInfoOptimizationRemarkBase::getLocationStr() const {
return Twine(Filename + ":" + Twine(Line) + ":" + Twine(Column)).str();
}
-void DiagnosticInfoOptimizationRemarkBase::print(DiagnosticPrinter &DP) const {
+void DiagnosticInfoOptimizationBase::print(DiagnosticPrinter &DP) const {
DP << getLocationStr() << ": " << getMsg();
}
@@ -189,3 +189,20 @@ void llvm::emitOptimizationRemarkAnalysis(LLVMContext &Ctx,
Ctx.diagnose(
DiagnosticInfoOptimizationRemarkAnalysis(PassName, Fn, DLoc, Msg));
}
+
+bool DiagnosticInfoOptimizationFailure::isEnabled() const {
+ // Only print warnings.
+ return getSeverity() == DS_Warning;
+}
+
+void llvm::emitLoopVectorizeWarning(LLVMContext &Ctx, const Function &Fn,
+ const DebugLoc &DLoc, const Twine &Msg) {
+ Ctx.diagnose(DiagnosticInfoOptimizationFailure(
+ Fn, DLoc, Twine("loop not vectorized: " + Msg)));
+}
+
+void llvm::emitLoopInterleaveWarning(LLVMContext &Ctx, const Function &Fn,
+ const DebugLoc &DLoc, const Twine &Msg) {
+ Ctx.diagnose(DiagnosticInfoOptimizationFailure(
+ Fn, DLoc, Twine("loop not interleaved: " + Msg)));
+}
diff --git a/lib/IR/DiagnosticPrinter.cpp b/lib/IR/DiagnosticPrinter.cpp
index 5e160266c8..f25fc20a19 100644
--- a/lib/IR/DiagnosticPrinter.cpp
+++ b/lib/IR/DiagnosticPrinter.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This file defines the a diagnostic printer relying on raw_ostream.
+// This file defines a diagnostic printer relying on raw_ostream.
//
//===----------------------------------------------------------------------===//
diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp
index 14435711bb..32b2ec5845 100644
--- a/lib/IR/Function.cpp
+++ b/lib/IR/Function.cpp
@@ -77,11 +77,17 @@ unsigned Argument::getArgNo() const {
}
/// hasNonNullAttr - Return true if this argument has the nonnull attribute on
-/// it in its containing function.
+/// it in its containing function. Also returns true if at least one byte is
+/// known to be dereferenceable and the pointer is in addrspace(0).
bool Argument::hasNonNullAttr() const {
if (!getType()->isPointerTy()) return false;
- return getParent()->getAttributes().
- hasAttribute(getArgNo()+1, Attribute::NonNull);
+ if (getParent()->getAttributes().
+ hasAttribute(getArgNo()+1, Attribute::NonNull))
+ return true;
+ else if (getDereferenceableBytes() > 0 &&
+ getType()->getPointerAddressSpace() == 0)
+ return true;
+ return false;
}
/// hasByValAttr - Return true if this argument has the byval attribute on it
@@ -113,6 +119,12 @@ unsigned Argument::getParamAlignment() const {
}
+uint64_t Argument::getDereferenceableBytes() const {
+ assert(getType()->isPointerTy() &&
+ "Only pointers have dereferenceable bytes");
+ return getParent()->getDereferenceableBytes(getArgNo()+1);
+}
+
/// hasNestAttr - Return true if this argument has the nest attribute on
/// it in its containing function.
bool Argument::hasNestAttr() const {
@@ -154,6 +166,20 @@ bool Argument::hasReturnedAttr() const {
hasAttribute(getArgNo()+1, Attribute::Returned);
}
+/// hasZExtAttr - Return true if this argument has the zext attribute on it in
+/// its containing function.
+bool Argument::hasZExtAttr() const {
+ return getParent()->getAttributes().
+ hasAttribute(getArgNo()+1, Attribute::ZExt);
+}
+
+/// hasSExtAttr Return true if this argument has the sext attribute on it in its
+/// containing function.
+bool Argument::hasSExtAttr() const {
+ return getParent()->getAttributes().
+ hasAttribute(getArgNo()+1, Attribute::SExt);
+}
+
/// Return true if this argument has the readonly or readnone attribute on it
/// in its containing function.
bool Argument::onlyReadsMemory() const {
@@ -187,6 +213,12 @@ void Argument::removeAttr(AttributeSet AS) {
// Helper Methods in Function
//===----------------------------------------------------------------------===//
+bool Function::isMaterializable() const {
+ return getGlobalObjectSubClassData();
+}
+
+void Function::setIsMaterializable(bool V) { setGlobalObjectSubClassData(V); }
+
LLVMContext &Function::getContext() const {
return getType()->getContext();
}
@@ -215,12 +247,13 @@ void Function::eraseFromParent() {
// Function Implementation
//===----------------------------------------------------------------------===//
-Function::Function(FunctionType *Ty, LinkageTypes Linkage,
- const Twine &name, Module *ParentModule)
- : GlobalObject(PointerType::getUnqual(Ty),
- Value::FunctionVal, nullptr, 0, Linkage, name) {
+Function::Function(FunctionType *Ty, LinkageTypes Linkage, const Twine &name,
+ Module *ParentModule)
+ : GlobalObject(PointerType::getUnqual(Ty), Value::FunctionVal, nullptr, 0,
+ Linkage, name) {
assert(FunctionType::isValidReturnType(getReturnType()) &&
"invalid return type");
+ setIsMaterializable(false);
SymTab = new ValueSymbolTable();
// If the function has arguments, mark them as lazily built.
@@ -292,6 +325,8 @@ void Function::setParent(Module *parent) {
// delete.
//
void Function::dropAllReferences() {
+ setIsMaterializable(false);
+
for (iterator I = begin(), E = end(); I != E; ++I)
I->dropAllReferences();
@@ -420,6 +455,33 @@ unsigned Function::lookupIntrinsicID() const {
return 0;
}
+/// Returns a stable mangling for the type specified for use in the name
+/// mangling scheme used by 'any' types in intrinsic signatures.
+static std::string getMangledTypeStr(Type* Ty) {
+ std::string Result;
+ if (PointerType* PTyp = dyn_cast<PointerType>(Ty)) {
+ Result += "p" + llvm::utostr(PTyp->getAddressSpace()) +
+ getMangledTypeStr(PTyp->getElementType());
+ } else if (ArrayType* ATyp = dyn_cast<ArrayType>(Ty)) {
+ Result += "a" + llvm::utostr(ATyp->getNumElements()) +
+ getMangledTypeStr(ATyp->getElementType());
+ } else if (StructType* STyp = dyn_cast<StructType>(Ty)) {
+ if (!STyp->isLiteral())
+ Result += STyp->getName();
+ else
+ llvm_unreachable("TODO: implement literal types");
+ } else if (FunctionType* FT = dyn_cast<FunctionType>(Ty)) {
+ Result += "f_" + getMangledTypeStr(FT->getReturnType());
+ for (size_t i = 0; i < FT->getNumParams(); i++)
+ Result += getMangledTypeStr(FT->getParamType(i));
+ if (FT->isVarArg())
+ Result += "vararg";
+ Result += "f"; //ensure distinguishable
+ } else if (Ty)
+ Result += EVT::getEVT(Ty).getEVTString();
+ return Result;
+}
+
std::string Intrinsic::getName(ID id, ArrayRef<Type*> Tys) {
assert(id < num_intrinsics && "Invalid intrinsic ID!");
static const char * const Table[] = {
@@ -432,12 +494,7 @@ std::string Intrinsic::getName(ID id, ArrayRef<Type*> Tys) {
return Table[id];
std::string Result(Table[id]);
for (unsigned i = 0; i < Tys.size(); ++i) {
- if (PointerType* PTyp = dyn_cast<PointerType>(Tys[i])) {
- Result += ".p" + llvm::utostr(PTyp->getAddressSpace()) +
- EVT::getEVT(PTyp->getElementType()).getEVTString();
- }
- else if (Tys[i])
- Result += "." + EVT::getEVT(Tys[i]).getEVTString();
+ Result += "." + getMangledTypeStr(Tys[i]);
}
return Result;
}
@@ -467,19 +524,20 @@ enum IIT_Info {
IIT_ARG = 15,
// Values from 16+ are only encodable with the inefficient encoding.
- IIT_MMX = 16,
- IIT_METADATA = 17,
- IIT_EMPTYSTRUCT = 18,
- IIT_STRUCT2 = 19,
- IIT_STRUCT3 = 20,
- IIT_STRUCT4 = 21,
- IIT_STRUCT5 = 22,
- IIT_EXTEND_ARG = 23,
- IIT_TRUNC_ARG = 24,
- IIT_ANYPTR = 25,
- IIT_V1 = 26,
- IIT_VARARG = 27,
- IIT_HALF_VEC_ARG = 28
+ IIT_V64 = 16,
+ IIT_MMX = 17,
+ IIT_METADATA = 18,
+ IIT_EMPTYSTRUCT = 19,
+ IIT_STRUCT2 = 20,
+ IIT_STRUCT3 = 21,
+ IIT_STRUCT4 = 22,
+ IIT_STRUCT5 = 23,
+ IIT_EXTEND_ARG = 24,
+ IIT_TRUNC_ARG = 25,
+ IIT_ANYPTR = 26,
+ IIT_V1 = 27,
+ IIT_VARARG = 28,
+ IIT_HALF_VEC_ARG = 29
};
@@ -550,6 +608,10 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 32));
DecodeIITType(NextElt, Infos, OutputTable);
return;
+ case IIT_V64:
+ OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 64));
+ DecodeIITType(NextElt, Infos, OutputTable);
+ return;
case IIT_PTR:
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Pointer, 0));
DecodeIITType(NextElt, Infos, OutputTable);
@@ -666,7 +728,7 @@ static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos,
assert(D.Struct_NumElements <= 5 && "Can't handle this yet");
for (unsigned i = 0, e = D.Struct_NumElements; i != e; ++i)
Elts[i] = DecodeFixedType(Infos, Tys, Context);
- return StructType::get(Context, ArrayRef<Type*>(Elts,D.Struct_NumElements));
+ return StructType::get(Context, makeArrayRef(Elts,D.Struct_NumElements));
}
case IITDescriptor::Argument:
@@ -708,6 +770,12 @@ FunctionType *Intrinsic::getType(LLVMContext &Context,
while (!TableRef.empty())
ArgTys.push_back(DecodeFixedType(TableRef, Tys, Context));
+ // DecodeFixedType returns Void for IITDescriptor::Void and IITDescriptor::VarArg
+ // If we see void type as the type of the last argument, it is vararg intrinsic
+ if (!ArgTys.empty() && ArgTys.back()->isVoidTy()) {
+ ArgTys.pop_back();
+ return FunctionType::get(ResultTy, ArgTys, true);
+ }
return FunctionType::get(ResultTy, ArgTys, false);
}
diff --git a/lib/IR/GCOV.cpp b/lib/IR/GCOV.cpp
index 1667401f88..245c500cf6 100644
--- a/lib/IR/GCOV.cpp
+++ b/lib/IR/GCOV.cpp
@@ -298,7 +298,8 @@ uint64_t GCOVFunction::getExitCount() const {
/// dump - Dump GCOVFunction content to dbgs() for debugging purposes.
void GCOVFunction::dump() const {
- dbgs() << "===== " << Name << " @ " << Filename << ":" << LineNumber << "\n";
+ dbgs() << "===== " << Name << " (" << Ident << ") @ " << Filename << ":"
+ << LineNumber << "\n";
for (const auto &Block : Blocks)
Block->dump();
}
@@ -517,11 +518,11 @@ FileInfo::openCoveragePath(StringRef CoveragePath) {
if (Options.NoOutput)
return llvm::make_unique<raw_null_ostream>();
- std::string ErrorInfo;
- auto OS = llvm::make_unique<raw_fd_ostream>(CoveragePath.str().c_str(),
- ErrorInfo, sys::fs::F_Text);
- if (!ErrorInfo.empty()) {
- errs() << ErrorInfo << "\n";
+ std::error_code EC;
+ auto OS = llvm::make_unique<raw_fd_ostream>(CoveragePath.str(), EC,
+ sys::fs::F_Text);
+ if (EC) {
+ errs() << EC.message() << "\n";
return llvm::make_unique<raw_null_ostream>();
}
return std::move(OS);
diff --git a/lib/IR/Globals.cpp b/lib/IR/Globals.cpp
index 244e3e4bae..e181d623b8 100644
--- a/lib/IR/Globals.cpp
+++ b/lib/IR/Globals.cpp
@@ -29,13 +29,15 @@ using namespace llvm;
//===----------------------------------------------------------------------===//
bool GlobalValue::isMaterializable() const {
- return getParent() && getParent()->isMaterializable(this);
+ if (const Function *F = dyn_cast<Function>(this))
+ return F->isMaterializable();
+ return false;
}
bool GlobalValue::isDematerializable() const {
return getParent() && getParent()->isDematerializable(this);
}
-bool GlobalValue::Materialize(std::string *ErrInfo) {
- return getParent()->Materialize(this, ErrInfo);
+std::error_code GlobalValue::materialize() {
+ return getParent()->materialize(this);
}
void GlobalValue::Dematerialize() {
getParent()->Dematerialize(this);
@@ -77,10 +79,24 @@ void GlobalObject::setAlignment(unsigned Align) {
assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
assert(Align <= MaximumAlignment &&
"Alignment is greater than MaximumAlignment!");
- setGlobalValueSubClassData(Log2_32(Align) + 1);
+ unsigned AlignmentData = Log2_32(Align) + 1;
+ unsigned OldData = getGlobalValueSubClassData();
+ setGlobalValueSubClassData((OldData & ~AlignmentMask) | AlignmentData);
assert(getAlignment() == Align && "Alignment representation error!");
}
+unsigned GlobalObject::getGlobalObjectSubClassData() const {
+ unsigned ValueData = getGlobalValueSubClassData();
+ return ValueData >> AlignmentBits;
+}
+
+void GlobalObject::setGlobalObjectSubClassData(unsigned Val) {
+ unsigned OldData = getGlobalValueSubClassData();
+ setGlobalValueSubClassData((OldData & AlignmentMask) |
+ (Val << AlignmentBits));
+ assert(getGlobalObjectSubClassData() == Val && "representation error");
+}
+
void GlobalObject::copyAttributesFrom(const GlobalValue *Src) {
const auto *GV = cast<GlobalObject>(Src);
GlobalValue::copyAttributesFrom(GV);
@@ -117,7 +133,7 @@ bool GlobalValue::isDeclaration() const {
// Functions are definitions if they have a body.
if (const Function *F = dyn_cast<Function>(this))
- return F->empty();
+ return F->empty() && !F->isMaterializable();
// Aliases are always definitions.
assert(isa<GlobalAlias>(this));
@@ -230,6 +246,7 @@ void GlobalVariable::copyAttributesFrom(const GlobalValue *Src) {
GlobalObject::copyAttributesFrom(Src);
const GlobalVariable *SrcVar = cast<GlobalVariable>(Src);
setThreadLocalMode(SrcVar->getThreadLocalMode());
+ setExternallyInitialized(SrcVar->isExternallyInitialized());
}
diff --git a/lib/IR/IRBuilder.cpp b/lib/IR/IRBuilder.cpp
index 435e54f0ea..a4c5d9766a 100644
--- a/lib/IR/IRBuilder.cpp
+++ b/lib/IR/IRBuilder.cpp
@@ -62,7 +62,8 @@ static CallInst *createCallHelper(Value *Callee, ArrayRef<Value *> Ops,
CallInst *IRBuilderBase::
CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align,
- bool isVolatile, MDNode *TBAATag) {
+ bool isVolatile, MDNode *TBAATag, MDNode *ScopeTag,
+ MDNode *NoAliasTag) {
Ptr = getCastedInt8PtrValue(Ptr);
Value *Ops[] = { Ptr, Val, Size, getInt32(Align), getInt1(isVolatile) };
Type *Tys[] = { Ptr->getType(), Size->getType() };
@@ -74,13 +75,20 @@ CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align,
// Set the TBAA info if present.
if (TBAATag)
CI->setMetadata(LLVMContext::MD_tbaa, TBAATag);
-
+
+ if (ScopeTag)
+ CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag);
+
+ if (NoAliasTag)
+ CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag);
+
return CI;
}
CallInst *IRBuilderBase::
CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align,
- bool isVolatile, MDNode *TBAATag, MDNode *TBAAStructTag) {
+ bool isVolatile, MDNode *TBAATag, MDNode *TBAAStructTag,
+ MDNode *ScopeTag, MDNode *NoAliasTag) {
Dst = getCastedInt8PtrValue(Dst);
Src = getCastedInt8PtrValue(Src);
@@ -98,13 +106,20 @@ CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align,
// Set the TBAA Struct info if present.
if (TBAAStructTag)
CI->setMetadata(LLVMContext::MD_tbaa_struct, TBAAStructTag);
-
+
+ if (ScopeTag)
+ CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag);
+
+ if (NoAliasTag)
+ CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag);
+
return CI;
}
CallInst *IRBuilderBase::
CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align,
- bool isVolatile, MDNode *TBAATag) {
+ bool isVolatile, MDNode *TBAATag, MDNode *ScopeTag,
+ MDNode *NoAliasTag) {
Dst = getCastedInt8PtrValue(Dst);
Src = getCastedInt8PtrValue(Src);
@@ -118,7 +133,13 @@ CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align,
// Set the TBAA info if present.
if (TBAATag)
CI->setMetadata(LLVMContext::MD_tbaa, TBAATag);
-
+
+ if (ScopeTag)
+ CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag);
+
+ if (NoAliasTag)
+ CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag);
+
return CI;
}
@@ -151,3 +172,14 @@ CallInst *IRBuilderBase::CreateLifetimeEnd(Value *Ptr, ConstantInt *Size) {
Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::lifetime_end);
return createCallHelper(TheFn, Ops, this);
}
+
+CallInst *IRBuilderBase::CreateAssumption(Value *Cond) {
+ assert(Cond->getType() == getInt1Ty() &&
+ "an assumption condition must be of type i1");
+
+ Value *Ops[] = { Cond };
+ Module *M = BB->getParent()->getParent();
+ Value *FnAssume = Intrinsic::getDeclaration(M, Intrinsic::assume);
+ return createCallHelper(FnAssume, Ops, this);
+}
+
diff --git a/lib/IR/InlineAsm.cpp b/lib/IR/InlineAsm.cpp
index a3e1da3b18..16d874f32f 100644
--- a/lib/IR/InlineAsm.cpp
+++ b/lib/IR/InlineAsm.cpp
@@ -91,6 +91,10 @@ bool InlineAsm::ConstraintInfo::Parse(StringRef Str,
if (*I == '~') {
Type = isClobber;
++I;
+
+ // '{' must immediately follow '~'.
+ if (I != E && *I != '{')
+ return true;
} else if (*I == '=') {
++I;
Type = isOutput;
diff --git a/lib/IR/Instruction.cpp b/lib/IR/Instruction.cpp
index 86421c4ae9..3ee66f5698 100644
--- a/lib/IR/Instruction.cpp
+++ b/lib/IR/Instruction.cpp
@@ -143,6 +143,11 @@ void Instruction::setFastMathFlags(FastMathFlags FMF) {
cast<FPMathOperator>(this)->setFastMathFlags(FMF);
}
+void Instruction::copyFastMathFlags(FastMathFlags FMF) {
+ assert(isa<FPMathOperator>(this) && "copying fast-math flag on invalid op");
+ cast<FPMathOperator>(this)->copyFastMathFlags(FMF);
+}
+
/// Determine whether the unsafe-algebra flag is set.
bool Instruction::hasUnsafeAlgebra() const {
assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op");
@@ -175,7 +180,7 @@ bool Instruction::hasAllowReciprocal() const {
/// Convenience function for getting all the fast-math flags, which must be an
/// operator which supports these flags. See LangRef.html for the meaning of
-/// these flats.
+/// these flags.
FastMathFlags Instruction::getFastMathFlags() const {
assert(isa<FPMathOperator>(this) && "getting fast-math flag on invalid op");
return cast<FPMathOperator>(this)->getFastMathFlags();
@@ -183,7 +188,7 @@ FastMathFlags Instruction::getFastMathFlags() const {
/// Copy I's fast-math flags
void Instruction::copyFastMathFlags(const Instruction *I) {
- setFastMathFlags(I->getFastMathFlags());
+ copyFastMathFlags(I->getFastMathFlags());
}
@@ -438,6 +443,21 @@ bool Instruction::mayWriteToMemory() const {
}
}
+bool Instruction::isAtomic() const {
+ switch (getOpcode()) {
+ default:
+ return false;
+ case Instruction::AtomicCmpXchg:
+ case Instruction::AtomicRMW:
+ case Instruction::Fence:
+ return true;
+ case Instruction::Load:
+ return cast<LoadInst>(this)->getOrdering() != NotAtomic;
+ case Instruction::Store:
+ return cast<StoreInst>(this)->getOrdering() != NotAtomic;
+ }
+}
+
bool Instruction::mayThrow() const {
if (const CallInst *CI = dyn_cast<CallInst>(this))
return !CI->doesNotThrow();
@@ -528,7 +548,7 @@ Instruction *Instruction::clone() const {
// Otherwise, enumerate and copy over metadata from the old instruction to the
// new one.
- SmallVector<std::pair<unsigned, MDNode*>, 4> TheMDs;
+ SmallVector<std::pair<unsigned, MDNode *>, 4> TheMDs;
getAllMetadataOtherThanDebugLoc(TheMDs);
for (const auto &MD : TheMDs)
New->setMetadata(MD.first, MD.second);
diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp
index a5ceacb563..57a4f0b61d 100644
--- a/lib/IR/Instructions.cpp
+++ b/lib/IR/Instructions.cpp
@@ -364,8 +364,9 @@ bool CallInst::paramHasAttr(unsigned i, Attribute::AttrKind A) const {
/// IsConstantOne - Return true only if val is constant int 1
static bool IsConstantOne(Value *val) {
- assert(val && "IsConstantOne does not work with NULL val");
- return isa<ConstantInt>(val) && cast<ConstantInt>(val)->isOne();
+ assert(val && "IsConstantOne does not work with nullptr val");
+ const ConstantInt *CVal = dyn_cast<ConstantInt>(val);
+ return CVal && CVal->isOne();
}
static Instruction *createMalloc(Instruction *InsertBefore,
@@ -418,7 +419,7 @@ static Instruction *createMalloc(Instruction *InsertBefore,
Value *MallocFunc = MallocF;
if (!MallocFunc)
// prototype malloc as "void *malloc(size_t)"
- MallocFunc = M->getOrInsertFunction("malloc", BPTy, IntPtrTy, NULL);
+ MallocFunc = M->getOrInsertFunction("malloc", BPTy, IntPtrTy, nullptr);
PointerType *AllocPtrType = PointerType::getUnqual(AllocTy);
CallInst *MCall = nullptr;
Instruction *Result = nullptr;
@@ -491,7 +492,7 @@ static Instruction* createFree(Value* Source, Instruction *InsertBefore,
Type *VoidTy = Type::getVoidTy(M->getContext());
Type *IntPtrTy = Type::getInt8PtrTy(M->getContext());
// prototype free as "void free(void*)"
- Value *FreeFunc = M->getOrInsertFunction("free", VoidTy, IntPtrTy, NULL);
+ Value *FreeFunc = M->getOrInsertFunction("free", VoidTy, IntPtrTy, nullptr);
CallInst* Result = nullptr;
Value *PtrCast = Source;
if (InsertBefore) {
@@ -2030,6 +2031,39 @@ bool BinaryOperator::isExact() const {
return cast<PossiblyExactOperator>(this)->isExact();
}
+void BinaryOperator::copyIRFlags(const Value *V) {
+ // Copy the wrapping flags.
+ if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) {
+ setHasNoSignedWrap(OB->hasNoSignedWrap());
+ setHasNoUnsignedWrap(OB->hasNoUnsignedWrap());
+ }
+
+ // Copy the exact flag.
+ if (auto *PE = dyn_cast<PossiblyExactOperator>(V))
+ setIsExact(PE->isExact());
+
+ // Copy the fast-math flags.
+ if (auto *FP = dyn_cast<FPMathOperator>(V))
+ copyFastMathFlags(FP->getFastMathFlags());
+}
+
+void BinaryOperator::andIRFlags(const Value *V) {
+ if (auto *OB = dyn_cast<OverflowingBinaryOperator>(V)) {
+ setHasNoSignedWrap(hasNoSignedWrap() & OB->hasNoSignedWrap());
+ setHasNoUnsignedWrap(hasNoUnsignedWrap() & OB->hasNoUnsignedWrap());
+ }
+
+ if (auto *PE = dyn_cast<PossiblyExactOperator>(V))
+ setIsExact(isExact() & PE->isExact());
+
+ if (auto *FP = dyn_cast<FPMathOperator>(V)) {
+ FastMathFlags FM = getFastMathFlags();
+ FM &= FP->getFastMathFlags();
+ copyFastMathFlags(FM);
+ }
+}
+
+
//===----------------------------------------------------------------------===//
// FPMathOperator Class
//===----------------------------------------------------------------------===//
@@ -2039,7 +2073,7 @@ bool BinaryOperator::isExact() const {
/// default precision.
float FPMathOperator::getFPAccuracy() const {
const MDNode *MD =
- cast<Instruction>(this)->getMetadata(LLVMContext::MD_fpmath);
+ cast<Instruction>(this)->getMetadata(LLVMContext::MD_fpmath);
if (!MD)
return 0.0;
ConstantFP *Accuracy = cast<ConstantFP>(MD->getOperand(0));
@@ -2478,11 +2512,7 @@ CastInst *CastInst::CreatePointerCast(Value *S, Type *Ty,
if (Ty->isIntOrIntVectorTy())
return Create(Instruction::PtrToInt, S, Ty, Name, InsertAtEnd);
- Type *STy = S->getType();
- if (STy->getPointerAddressSpace() != Ty->getPointerAddressSpace())
- return Create(Instruction::AddrSpaceCast, S, Ty, Name, InsertAtEnd);
-
- return Create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
+ return CreatePointerBitCastOrAddrSpaceCast(S, Ty, Name, InsertAtEnd);
}
/// @brief Create a BitCast or a PtrToInt cast instruction
@@ -2500,14 +2530,36 @@ CastInst *CastInst::CreatePointerCast(Value *S, Type *Ty,
if (Ty->isIntOrIntVectorTy())
return Create(Instruction::PtrToInt, S, Ty, Name, InsertBefore);
- Type *STy = S->getType();
- if (STy->getPointerAddressSpace() != Ty->getPointerAddressSpace())
+ return CreatePointerBitCastOrAddrSpaceCast(S, Ty, Name, InsertBefore);
+}
+
+CastInst *CastInst::CreatePointerBitCastOrAddrSpaceCast(
+ Value *S, Type *Ty,
+ const Twine &Name,
+ BasicBlock *InsertAtEnd) {
+ assert(S->getType()->isPtrOrPtrVectorTy() && "Invalid cast");
+ assert(Ty->isPtrOrPtrVectorTy() && "Invalid cast");
+
+ if (S->getType()->getPointerAddressSpace() != Ty->getPointerAddressSpace())
+ return Create(Instruction::AddrSpaceCast, S, Ty, Name, InsertAtEnd);
+
+ return Create(Instruction::BitCast, S, Ty, Name, InsertAtEnd);
+}
+
+CastInst *CastInst::CreatePointerBitCastOrAddrSpaceCast(
+ Value *S, Type *Ty,
+ const Twine &Name,
+ Instruction *InsertBefore) {
+ assert(S->getType()->isPtrOrPtrVectorTy() && "Invalid cast");
+ assert(Ty->isPtrOrPtrVectorTy() && "Invalid cast");
+
+ if (S->getType()->getPointerAddressSpace() != Ty->getPointerAddressSpace())
return Create(Instruction::AddrSpaceCast, S, Ty, Name, InsertBefore);
return Create(Instruction::BitCast, S, Ty, Name, InsertBefore);
}
-CastInst *CastInst::CreateIntegerCast(Value *C, Type *Ty,
+CastInst *CastInst::CreateIntegerCast(Value *C, Type *Ty,
bool isSigned, const Twine &Name,
Instruction *InsertBefore) {
assert(C->getType()->isIntOrIntVectorTy() && Ty->isIntOrIntVectorTy() &&
diff --git a/lib/IR/LLVMContext.cpp b/lib/IR/LLVMContext.cpp
index de825f00b2..c62bc0936c 100644
--- a/lib/IR/LLVMContext.cpp
+++ b/lib/IR/LLVMContext.cpp
@@ -66,6 +66,33 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
unsigned InvariantLdId = getMDKindID("invariant.load");
assert(InvariantLdId == MD_invariant_load && "invariant.load kind id drifted");
(void)InvariantLdId;
+
+ // Create the 'alias.scope' metadata kind.
+ unsigned AliasScopeID = getMDKindID("alias.scope");
+ assert(AliasScopeID == MD_alias_scope && "alias.scope kind id drifted");
+ (void)AliasScopeID;
+
+ // Create the 'noalias' metadata kind.
+ unsigned NoAliasID = getMDKindID("noalias");
+ assert(NoAliasID == MD_noalias && "noalias kind id drifted");
+ (void)NoAliasID;
+
+ // Create the 'nontemporal' metadata kind.
+ unsigned NonTemporalID = getMDKindID("nontemporal");
+ assert(NonTemporalID == MD_nontemporal && "nontemporal kind id drifted");
+ (void)NonTemporalID;
+
+ // Create the 'llvm.mem.parallel_loop_access' metadata kind.
+ unsigned MemParallelLoopAccessID = getMDKindID("llvm.mem.parallel_loop_access");
+ assert(MemParallelLoopAccessID == MD_mem_parallel_loop_access &&
+ "mem_parallel_loop_access kind id drifted");
+ (void)MemParallelLoopAccessID;
+
+
+ // Create the 'nonnull' metadata kind.
+ unsigned NonNullID = getMDKindID("nonnull");
+ assert(NonNullID == MD_nonnull && "nonnull kind id drifted");
+ (void)NonNullID;
}
LLVMContext::~LLVMContext() { delete pImpl; }
@@ -102,9 +129,11 @@ void *LLVMContext::getInlineAsmDiagnosticContext() const {
}
void LLVMContext::setDiagnosticHandler(DiagnosticHandlerTy DiagnosticHandler,
- void *DiagnosticContext) {
+ void *DiagnosticContext,
+ bool RespectFilters) {
pImpl->DiagnosticHandler = DiagnosticHandler;
pImpl->DiagnosticContext = DiagnosticContext;
+ pImpl->RespectDiagnosticFilters = RespectFilters;
}
LLVMContext::DiagnosticHandlerTy LLVMContext::getDiagnosticHandler() const {
@@ -135,13 +164,7 @@ void LLVMContext::emitError(const Instruction *I, const Twine &ErrorStr) {
diagnose(DiagnosticInfoInlineAsm(*I, ErrorStr));
}
-void LLVMContext::diagnose(const DiagnosticInfo &DI) {
- // If there is a report handler, use it.
- if (pImpl->DiagnosticHandler) {
- pImpl->DiagnosticHandler(DI, pImpl->DiagnosticContext);
- return;
- }
-
+static bool isDiagnosticEnabled(const DiagnosticInfo &DI) {
// Optimization remarks are selective. They need to check whether the regexp
// pattern, passed via one of the -pass-remarks* flags, matches the name of
// the pass that is emitting the diagnostic. If there is no match, ignore the
@@ -149,19 +172,32 @@ void LLVMContext::diagnose(const DiagnosticInfo &DI) {
switch (DI.getKind()) {
case llvm::DK_OptimizationRemark:
if (!cast<DiagnosticInfoOptimizationRemark>(DI).isEnabled())
- return;
+ return false;
break;
case llvm::DK_OptimizationRemarkMissed:
if (!cast<DiagnosticInfoOptimizationRemarkMissed>(DI).isEnabled())
- return;
+ return false;
break;
case llvm::DK_OptimizationRemarkAnalysis:
if (!cast<DiagnosticInfoOptimizationRemarkAnalysis>(DI).isEnabled())
- return;
+ return false;
break;
default:
break;
}
+ return true;
+}
+
+void LLVMContext::diagnose(const DiagnosticInfo &DI) {
+ // If there is a report handler, use it.
+ if (pImpl->DiagnosticHandler) {
+ if (!pImpl->RespectDiagnosticFilters || isDiagnosticEnabled(DI))
+ pImpl->DiagnosticHandler(DI, pImpl->DiagnosticContext);
+ return;
+ }
+
+ if (!isDiagnosticEnabled(DI))
+ return;
// Otherwise, print the message with a prefix based on the severity.
std::string MsgStorage;
@@ -217,9 +253,10 @@ unsigned LLVMContext::getMDKindID(StringRef Name) const {
assert(isValidName(Name) && "Invalid MDNode name");
// If this is new, assign it its ID.
- return
- pImpl->CustomMDKindNames.GetOrCreateValue(
- Name, pImpl->CustomMDKindNames.size()).second;
+ return pImpl->CustomMDKindNames.insert(std::make_pair(
+ Name,
+ pImpl->CustomMDKindNames.size()))
+ .first->second;
}
/// getHandlerNames - Populate client supplied smallvector using custome
diff --git a/lib/IR/LLVMContextImpl.cpp b/lib/IR/LLVMContextImpl.cpp
index 4c2791f0a8..3fd0bb37a4 100644
--- a/lib/IR/LLVMContextImpl.cpp
+++ b/lib/IR/LLVMContextImpl.cpp
@@ -40,6 +40,7 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
InlineAsmDiagContext = nullptr;
DiagnosticHandler = nullptr;
DiagnosticContext = nullptr;
+ RespectDiagnosticFilters = false;
YieldCallback = nullptr;
YieldOpaqueHandle = nullptr;
NamedStructTypesUniqueID = 0;
@@ -75,7 +76,7 @@ LLVMContextImpl::~LLVMContextImpl() {
// Free the constants. This is important to do here to ensure that they are
// freed before the LeakDetector is torn down.
std::for_each(ExprConstants.map_begin(), ExprConstants.map_end(),
- DropReferences());
+ DropFirst());
std::for_each(ArrayConstants.map_begin(), ArrayConstants.map_end(),
DropFirst());
std::for_each(StructConstants.map_begin(), StructConstants.map_end(),
@@ -121,20 +122,19 @@ LLVMContextImpl::~LLVMContextImpl() {
// Destroy MDNodes. ~MDNode can move and remove nodes between the MDNodeSet
// and the NonUniquedMDNodes sets, so copy the values out first.
- SmallVector<MDNode*, 8> MDNodes;
+ SmallVector<GenericMDNode *, 8> MDNodes;
MDNodes.reserve(MDNodeSet.size() + NonUniquedMDNodes.size());
- for (FoldingSetIterator<MDNode> I = MDNodeSet.begin(), E = MDNodeSet.end();
- I != E; ++I)
- MDNodes.push_back(&*I);
+ MDNodes.append(MDNodeSet.begin(), MDNodeSet.end());
MDNodes.append(NonUniquedMDNodes.begin(), NonUniquedMDNodes.end());
- for (SmallVectorImpl<MDNode *>::iterator I = MDNodes.begin(),
- E = MDNodes.end(); I != E; ++I)
- (*I)->destroy();
+ for (GenericMDNode *I : MDNodes)
+ I->dropAllReferences();
+ for (GenericMDNode *I : MDNodes)
+ delete I;
assert(MDNodeSet.empty() && NonUniquedMDNodes.empty() &&
"Destroying all MDNodes didn't empty the Context's sets.");
// Destroy MDStrings.
- DeleteContainerSeconds(MDStringCache);
+ MDStringCache.clear();
}
// ConstantsContext anchors
diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h
index 808c239bff..e743ec3abc 100644
--- a/lib/IR/LLVMContextImpl.h
+++ b/lib/IR/LLVMContextImpl.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_LLVMCONTEXT_IMPL_H
-#define LLVM_LLVMCONTEXT_IMPL_H
+#ifndef LLVM_LIB_IR_LLVMCONTEXTIMPL_H
+#define LLVM_LIB_IR_LLVMCONTEXTIMPL_H
#include "AttributeImpl.h"
#include "ConstantsContext.h"
@@ -22,6 +22,7 @@
#include "llvm/ADT/APInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/ADT/Hashing.h"
#include "llvm/ADT/SmallPtrSet.h"
@@ -150,7 +151,7 @@ struct FunctionTypeKeyInfo {
ReturnType(R), Params(P), isVarArg(V) {}
KeyTy(const FunctionType* FT) :
ReturnType(FT->getReturnType()),
- Params(ArrayRef<Type*>(FT->param_begin(), FT->param_end())),
+ Params(makeArrayRef(FT->param_begin(), FT->param_end())),
isVarArg(FT->isVarArg()) {}
bool operator==(const KeyTy& that) const {
if (ReturnType != that.ReturnType)
@@ -190,23 +191,52 @@ struct FunctionTypeKeyInfo {
}
};
-// Provide a FoldingSetTrait::Equals specialization for MDNode that can use a
-// shortcut to avoid comparing all operands.
-template<> struct FoldingSetTrait<MDNode> : DefaultFoldingSetTrait<MDNode> {
- static bool Equals(const MDNode &X, const FoldingSetNodeID &ID,
- unsigned IDHash, FoldingSetNodeID &TempID) {
- assert(!X.isNotUniqued() && "Non-uniqued MDNode in FoldingSet?");
- // First, check if the cached hashes match. If they don't we can skip the
- // expensive operand walk.
- if (X.Hash != IDHash)
- return false;
+/// \brief DenseMapInfo for GenericMDNode.
+///
+/// Note that we don't need the is-function-local bit, since that's implicit in
+/// the operands.
+struct GenericMDNodeInfo {
+ struct KeyTy {
+ ArrayRef<Value *> Ops;
+ unsigned Hash;
+
+ KeyTy(ArrayRef<Value *> Ops)
+ : Ops(Ops), Hash(hash_combine_range(Ops.begin(), Ops.end())) {}
+
+ KeyTy(GenericMDNode *N, SmallVectorImpl<Value *> &Storage) {
+ Storage.resize(N->getNumOperands());
+ for (unsigned I = 0, E = N->getNumOperands(); I != E; ++I)
+ Storage[I] = N->getOperand(I);
+ Ops = Storage;
+ Hash = hash_combine_range(Ops.begin(), Ops.end());
+ }
- // If they match we have to compare the operands.
- X.Profile(TempID);
- return TempID == ID;
+ bool operator==(const GenericMDNode *RHS) const {
+ if (RHS == getEmptyKey() || RHS == getTombstoneKey())
+ return false;
+ if (Hash != RHS->getHash() || Ops.size() != RHS->getNumOperands())
+ return false;
+ for (unsigned I = 0, E = Ops.size(); I != E; ++I)
+ if (Ops[I] != RHS->getOperand(I))
+ return false;
+ return true;
+ }
+ };
+ static inline GenericMDNode *getEmptyKey() {
+ return DenseMapInfo<GenericMDNode *>::getEmptyKey();
+ }
+ static inline GenericMDNode *getTombstoneKey() {
+ return DenseMapInfo<GenericMDNode *>::getTombstoneKey();
}
- static unsigned ComputeHash(const MDNode &X, FoldingSetNodeID &) {
- return X.Hash; // Return cached hash.
+ static unsigned getHashValue(const KeyTy &Key) { return Key.Hash; }
+ static unsigned getHashValue(const GenericMDNode *U) {
+ return U->getHash();
+ }
+ static bool isEqual(const KeyTy &LHS, const GenericMDNode *RHS) {
+ return LHS == RHS;
+ }
+ static bool isEqual(const GenericMDNode *LHS, const GenericMDNode *RHS) {
+ return LHS == RHS;
}
};
@@ -244,6 +274,7 @@ public:
LLVMContext::DiagnosticHandlerTy DiagnosticHandler;
void *DiagnosticContext;
+ bool RespectDiagnosticFilters;
LLVMContext::YieldCallbackTy YieldCallback;
void *YieldOpaqueHandle;
@@ -260,25 +291,25 @@ public:
FoldingSet<AttributeSetImpl> AttrsLists;
FoldingSet<AttributeSetNode> AttrsSetNodes;
- StringMap<Value*> MDStringCache;
+ StringMap<MDString> MDStringCache;
- FoldingSet<MDNode> MDNodeSet;
+ DenseSet<GenericMDNode *, GenericMDNodeInfo> MDNodeSet;
// MDNodes may be uniqued or not uniqued. When they're not uniqued, they
// aren't in the MDNodeSet, but they're still shared between objects, so no
// one object can destroy them. This set allows us to at least destroy them
// on Context destruction.
- SmallPtrSet<MDNode*, 1> NonUniquedMDNodes;
-
+ SmallPtrSet<GenericMDNode *, 1> NonUniquedMDNodes;
+
DenseMap<Type*, ConstantAggregateZero*> CAZConstants;
- typedef ConstantAggrUniqueMap<ArrayType, ConstantArray> ArrayConstantsTy;
+ typedef ConstantUniqueMap<ConstantArray> ArrayConstantsTy;
ArrayConstantsTy ArrayConstants;
- typedef ConstantAggrUniqueMap<StructType, ConstantStruct> StructConstantsTy;
+ typedef ConstantUniqueMap<ConstantStruct> StructConstantsTy;
StructConstantsTy StructConstants;
- typedef ConstantAggrUniqueMap<VectorType, ConstantVector> VectorConstantsTy;
+ typedef ConstantUniqueMap<ConstantVector> VectorConstantsTy;
VectorConstantsTy VectorConstants;
DenseMap<PointerType*, ConstantPointerNull*> CPNConstants;
@@ -289,12 +320,10 @@ public:
DenseMap<std::pair<const Function *, const BasicBlock *>, BlockAddress *>
BlockAddresses;
- ConstantUniqueMap<ExprMapKeyType, const ExprMapKeyType&, Type, ConstantExpr>
- ExprConstants;
+ ConstantUniqueMap<ConstantExpr> ExprConstants;
+
+ ConstantUniqueMap<InlineAsm> InlineAsms;
- ConstantUniqueMap<InlineAsmKeyType, const InlineAsmKeyType&, PointerType,
- InlineAsm> InlineAsms;
-
ConstantInt *TheTrueVal;
ConstantInt *TheFalseVal;
diff --git a/lib/IR/LeaksContext.h b/lib/IR/LeaksContext.h
index 52ac170459..3e485abdfd 100644
--- a/lib/IR/LeaksContext.h
+++ b/lib/IR/LeaksContext.h
@@ -12,8 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_IR_LEAKSCONTEXT_H
-#define LLVM_IR_LEAKSCONTEXT_H
+#ifndef LLVM_LIB_IR_LEAKSCONTEXT_H
+#define LLVM_LIB_IR_LEAKSCONTEXT_H
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/Value.h"
@@ -95,4 +95,4 @@ private:
}
-#endif // LLVM_IR_LEAKSCONTEXT_H
+#endif
diff --git a/lib/IR/LegacyPassManager.cpp b/lib/IR/LegacyPassManager.cpp
index d3f3482dc0..28fa74cbfd 100644
--- a/lib/IR/LegacyPassManager.cpp
+++ b/lib/IR/LegacyPassManager.cpp
@@ -573,9 +573,8 @@ void PMTopLevelManager::collectLastUses(SmallVectorImpl<Pass *> &LastUses,
return;
SmallPtrSet<Pass *, 8> &LU = DMI->second;
- for (SmallPtrSet<Pass *, 8>::iterator I = LU.begin(),
- E = LU.end(); I != E; ++I) {
- LastUses.push_back(*I);
+ for (Pass *LUP : LU) {
+ LastUses.push_back(LUP);
}
}
@@ -1404,11 +1403,8 @@ void FunctionPassManager::add(Pass *P) {
/// so, return true.
///
bool FunctionPassManager::run(Function &F) {
- if (F.isMaterializable()) {
- std::string errstr;
- if (F.Materialize(&errstr))
- report_fatal_error("Error reading bitcode file: " + Twine(errstr));
- }
+ if (std::error_code EC = F.materialize())
+ report_fatal_error("Error reading bitcode file: " + EC.message());
return FPM->run(F);
}
@@ -1684,7 +1680,7 @@ void MPPassManager::addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) {
if (!FoundPass) {
FoundPass = RequiredPass;
// This should be guaranteed to add RequiredPass to the passmanager given
- // that we checked for an avaiable analysis above.
+ // that we checked for an available analysis above.
FPP->add(RequiredPass);
}
// Register P as the last user of FoundPass or RequiredPass.
diff --git a/lib/IR/MDBuilder.cpp b/lib/IR/MDBuilder.cpp
index 65cdf38852..3ec613c2f6 100644
--- a/lib/IR/MDBuilder.cpp
+++ b/lib/IR/MDBuilder.cpp
@@ -60,10 +60,17 @@ MDNode *MDBuilder::createRange(const APInt &Lo, const APInt &Hi) {
return MDNode::get(Context, Range);
}
-MDNode *MDBuilder::createAnonymousTBAARoot() {
+MDNode *MDBuilder::createAnonymousAARoot(StringRef Name, MDNode *Extra) {
// To ensure uniqueness the root node is self-referential.
- MDNode *Dummy = MDNode::getTemporary(Context, ArrayRef<Value *>());
- MDNode *Root = MDNode::get(Context, Dummy);
+ MDNode *Dummy = MDNode::getTemporary(Context, None);
+
+ SmallVector<Value *, 3> Args(1, Dummy);
+ if (Extra)
+ Args.push_back(Extra);
+ if (!Name.empty())
+ Args.push_back(createString(Name));
+ MDNode *Root = MDNode::get(Context, Args);
+
// At this point we have
// !0 = metadata !{} <- dummy
// !1 = metadata !{metadata !0} <- root
@@ -93,6 +100,15 @@ MDNode *MDBuilder::createTBAANode(StringRef Name, MDNode *Parent,
}
}
+MDNode *MDBuilder::createAliasScopeDomain(StringRef Name) {
+ return MDNode::get(Context, createString(Name));
+}
+
+MDNode *MDBuilder::createAliasScope(StringRef Name, MDNode *Domain) {
+ Value *Ops[2] = { createString(Name), Domain };
+ return MDNode::get(Context, Ops);
+}
+
/// \brief Return metadata for a tbaa.struct node with the given
/// struct field descriptions.
MDNode *MDBuilder::createTBAAStructNode(ArrayRef<TBAAStructField> Fields) {
diff --git a/lib/IR/Mangler.cpp b/lib/IR/Mangler.cpp
index 27d973b94f..5eeb7978e2 100644
--- a/lib/IR/Mangler.cpp
+++ b/lib/IR/Mangler.cpp
@@ -22,23 +22,25 @@ using namespace llvm;
static void getNameWithPrefixx(raw_ostream &OS, const Twine &GVName,
Mangler::ManglerPrefixTy PrefixTy,
- const DataLayout &DL, bool UseAt) {
+ const DataLayout &DL, char Prefix) {
SmallString<256> TmpData;
StringRef Name = GVName.toStringRef(TmpData);
assert(!Name.empty() && "getNameWithPrefix requires non-empty name");
+ // No need to do anything special if the global has the special "do not
+ // mangle" flag in the name.
+ if (Name[0] == '\1') {
+ OS << Name.substr(1);
+ return;
+ }
+
if (PrefixTy == Mangler::Private)
OS << DL.getPrivateGlobalPrefix();
else if (PrefixTy == Mangler::LinkerPrivate)
OS << DL.getLinkerPrivateGlobalPrefix();
- if (UseAt) {
- OS << '@';
- } else {
- char Prefix = DL.getGlobalPrefix();
- if (Prefix != '\0')
- OS << Prefix;
- }
+ if (Prefix != '\0')
+ OS << Prefix;
// If this is a simple string that doesn't need escaping, just append it.
OS << Name;
@@ -46,7 +48,8 @@ static void getNameWithPrefixx(raw_ostream &OS, const Twine &GVName,
void Mangler::getNameWithPrefix(raw_ostream &OS, const Twine &GVName,
ManglerPrefixTy PrefixTy) const {
- return getNameWithPrefixx(OS, GVName, PrefixTy, *DL, false);
+ char Prefix = DL->getGlobalPrefix();
+ return getNameWithPrefixx(OS, GVName, PrefixTy, *DL, Prefix);
}
void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,
@@ -56,11 +59,21 @@ void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,
return getNameWithPrefix(OS, GVName, PrefixTy);
}
-/// AddFastCallStdCallSuffix - Microsoft fastcall and stdcall functions require
-/// a suffix on their name indicating the number of words of arguments they
-/// take.
-static void AddFastCallStdCallSuffix(raw_ostream &OS, const Function *F,
- const DataLayout &TD) {
+static bool hasByteCountSuffix(CallingConv::ID CC) {
+ switch (CC) {
+ case CallingConv::X86_FastCall:
+ case CallingConv::X86_StdCall:
+ case CallingConv::X86_VectorCall:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/// Microsoft fastcall and stdcall functions require a suffix on their name
+/// indicating the number of words of arguments they take.
+static void addByteCountSuffix(raw_ostream &OS, const Function *F,
+ const DataLayout &TD) {
// Calculate arguments size total.
unsigned ArgWords = 0;
for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
@@ -69,8 +82,9 @@ static void AddFastCallStdCallSuffix(raw_ostream &OS, const Function *F,
// 'Dereference' type in case of byval or inalloca parameter attribute.
if (AI->hasByValOrInAllocaAttr())
Ty = cast<PointerType>(Ty)->getElementType();
- // Size should be aligned to DWORD boundary
- ArgWords += ((TD.getTypeAllocSize(Ty) + 3)/4)*4;
+ // Size should be aligned to pointer size.
+ unsigned PtrSize = TD.getPointerSize();
+ ArgWords += RoundUpToAlignment(TD.getTypeAllocSize(Ty), PtrSize);
}
OS << '@' << ArgWords;
@@ -99,41 +113,41 @@ void Mangler::getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV,
}
StringRef Name = GV->getName();
-
- // No need to do anything special if the global has the special "do not
- // mangle" flag in the name.
- if (Name[0] == '\1') {
- OS << Name.substr(1);
- return;
- }
-
- bool UseAt = false;
- const Function *MSFunc = nullptr;
- CallingConv::ID CC;
- if (DL->hasMicrosoftFastStdCallMangling()) {
- if ((MSFunc = dyn_cast<Function>(GV))) {
- CC = MSFunc->getCallingConv();
- // fastcall functions need to start with @ instead of _.
- if (CC == CallingConv::X86_FastCall)
- UseAt = true;
- }
+ char Prefix = DL->getGlobalPrefix();
+
+ // Mangle functions with Microsoft calling conventions specially. Only do
+ // this mangling for x86_64 vectorcall and 32-bit x86.
+ const Function *MSFunc = dyn_cast<Function>(GV);
+ if (Name.startswith("\01"))
+ MSFunc = nullptr; // Don't mangle when \01 is present.
+ CallingConv::ID CC =
+ MSFunc ? MSFunc->getCallingConv() : (unsigned)CallingConv::C;
+ if (!DL->hasMicrosoftFastStdCallMangling() &&
+ CC != CallingConv::X86_VectorCall)
+ MSFunc = nullptr;
+ if (MSFunc) {
+ if (CC == CallingConv::X86_FastCall)
+ Prefix = '@'; // fastcall functions have an @ prefix instead of _.
+ else if (CC == CallingConv::X86_VectorCall)
+ Prefix = '\0'; // vectorcall functions have no prefix.
}
- getNameWithPrefixx(OS, Name, PrefixTy, *DL, UseAt);
+ getNameWithPrefixx(OS, Name, PrefixTy, *DL, Prefix);
if (!MSFunc)
return;
- // If we are supposed to add a microsoft-style suffix for stdcall/fastcall,
- // add it.
- // fastcall and stdcall functions usually need @42 at the end to specify
- // the argument info.
+ // If we are supposed to add a microsoft-style suffix for stdcall, fastcall,
+ // or vectorcall, add it. These functions have a suffix of @N where N is the
+ // cumulative byte size of all of the parameters to the function in decimal.
+ if (CC == CallingConv::X86_VectorCall)
+ OS << '@'; // vectorcall functions use a double @ suffix.
FunctionType *FT = MSFunc->getFunctionType();
- if ((CC == CallingConv::X86_FastCall || CC == CallingConv::X86_StdCall) &&
+ if (hasByteCountSuffix(CC) &&
// "Pure" variadic functions do not receive @0 suffix.
(!FT->isVarArg() || FT->getNumParams() == 0 ||
(FT->getNumParams() == 1 && MSFunc->hasStructRetAttr())))
- AddFastCallStdCallSuffix(OS, MSFunc, *DL);
+ addByteCountSuffix(OS, MSFunc, *DL);
}
void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,
diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp
index 59137e47fa..27ba9f7a87 100644
--- a/lib/IR/Metadata.cpp
+++ b/lib/IR/Metadata.cpp
@@ -25,25 +25,34 @@
#include "llvm/IR/LeakDetector.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/ValueHandle.h"
+
using namespace llvm;
+Metadata::Metadata(LLVMContext &Context, unsigned ID)
+ : Value(Type::getMetadataTy(Context), ID) {}
+
//===----------------------------------------------------------------------===//
// MDString implementation.
//
void MDString::anchor() { }
-MDString::MDString(LLVMContext &C)
- : Value(Type::getMetadataTy(C), Value::MDStringVal) {}
-
MDString *MDString::get(LLVMContext &Context, StringRef Str) {
- LLVMContextImpl *pImpl = Context.pImpl;
- StringMapEntry<Value*> &Entry =
- pImpl->MDStringCache.GetOrCreateValue(Str);
- Value *&S = Entry.getValue();
- if (!S) S = new MDString(Context);
- S->setValueName(&Entry);
- return cast<MDString>(S);
+ auto &Store = Context.pImpl->MDStringCache;
+ auto I = Store.find(Str);
+ if (I != Store.end())
+ return &I->second;
+
+ auto *Entry =
+ StringMapEntry<MDString>::Create(Str, Store.getAllocator(), Context);
+ bool WasInserted = Store.insert(Entry);
+ (void)WasInserted;
+ assert(WasInserted && "Expected entry to be inserted");
+ return &Entry->second;
+}
+
+StringRef MDString::getString() const {
+ return StringMapEntry<MDString>::GetStringMapEntryFromValue(*this).first();
}
//===----------------------------------------------------------------------===//
@@ -57,26 +66,25 @@ class MDNodeOperand : public CallbackVH {
MDNodeOperand *Cur = this;
while (Cur->getValPtrInt() != 1)
- --Cur;
+ ++Cur;
assert(Cur->getValPtrInt() == 1 &&
- "Couldn't find the beginning of the operand list!");
- return reinterpret_cast<MDNode*>(Cur) - 1;
+ "Couldn't find the end of the operand list!");
+ return reinterpret_cast<MDNode *>(Cur + 1);
}
public:
- MDNodeOperand(Value *V) : CallbackVH(V) {}
+ MDNodeOperand() {}
virtual ~MDNodeOperand();
void set(Value *V) {
- unsigned IsFirst = this->getValPtrInt();
+ unsigned IsLast = this->getValPtrInt();
this->setValPtr(V);
- this->setAsFirstOperand(IsFirst);
+ this->setAsLastOperand(IsLast);
}
- /// setAsFirstOperand - Accessor method to mark the operand as the first in
- /// the list.
- void setAsFirstOperand(unsigned V) { this->setValPtrInt(V); }
+ /// \brief Accessor method to mark the operand as the first in the list.
+ void setAsLastOperand(unsigned I) { this->setValPtrInt(I); }
void deleted() override;
void allUsesReplacedWith(Value *NV) override;
@@ -98,12 +106,11 @@ void MDNodeOperand::allUsesReplacedWith(Value *NV) {
// MDNode implementation.
//
-/// getOperandPtr - Helper function to get the MDNodeOperand's coallocated on
-/// the end of the MDNode.
+/// \brief Get the MDNodeOperand's coallocated on the end of the MDNode.
static MDNodeOperand *getOperandPtr(MDNode *N, unsigned Op) {
// Use <= instead of < to permit a one-past-the-end address.
assert(Op <= N->getNumOperands() && "Invalid operand number");
- return reinterpret_cast<MDNodeOperand*>(N + 1) + Op;
+ return reinterpret_cast<MDNodeOperand *>(N) - N->getNumOperands() + Op;
}
void MDNode::replaceOperandWith(unsigned i, Value *Val) {
@@ -111,40 +118,54 @@ void MDNode::replaceOperandWith(unsigned i, Value *Val) {
replaceOperand(Op, Val);
}
-MDNode::MDNode(LLVMContext &C, ArrayRef<Value*> Vals, bool isFunctionLocal)
-: Value(Type::getMetadataTy(C), Value::MDNodeVal) {
+void *MDNode::operator new(size_t Size, unsigned NumOps) {
+ void *Ptr = ::operator new(Size + NumOps * sizeof(MDNodeOperand));
+ MDNodeOperand *Op = static_cast<MDNodeOperand *>(Ptr);
+ if (NumOps) {
+ MDNodeOperand *Last = Op + NumOps;
+ for (; Op != Last; ++Op)
+ new (Op) MDNodeOperand();
+ (Op - 1)->setAsLastOperand(1);
+ }
+ return Op;
+}
+
+void MDNode::operator delete(void *Mem) {
+ MDNode *N = static_cast<MDNode *>(Mem);
+ MDNodeOperand *Op = static_cast<MDNodeOperand *>(Mem);
+ for (unsigned I = 0, E = N->NumOperands; I != E; ++I)
+ (--Op)->~MDNodeOperand();
+ ::operator delete(Op);
+}
+
+MDNode::MDNode(LLVMContext &C, unsigned ID, ArrayRef<Value *> Vals,
+ bool isFunctionLocal)
+ : Metadata(C, ID) {
NumOperands = Vals.size();
if (isFunctionLocal)
setValueSubclassData(getSubclassDataFromValue() | FunctionLocalBit);
- // Initialize the operand list, which is co-allocated on the end of the node.
+ // Initialize the operand list.
unsigned i = 0;
- for (MDNodeOperand *Op = getOperandPtr(this, 0), *E = Op+NumOperands;
- Op != E; ++Op, ++i) {
- new (Op) MDNodeOperand(Vals[i]);
-
- // Mark the first MDNodeOperand as being the first in the list of operands.
- if (i == 0)
- Op->setAsFirstOperand(1);
- }
+ for (MDNodeOperand *Op = getOperandPtr(this, 0), *E = Op + NumOperands;
+ Op != E; ++Op, ++i)
+ Op->set(Vals[i]);
}
-/// ~MDNode - Destroy MDNode.
-MDNode::~MDNode() {
- assert((getSubclassDataFromValue() & DestroyFlag) != 0 &&
- "Not being destroyed through destroy()?");
+GenericMDNode::~GenericMDNode() {
LLVMContextImpl *pImpl = getType()->getContext().pImpl;
if (isNotUniqued()) {
pImpl->NonUniquedMDNodes.erase(this);
} else {
- pImpl->MDNodeSet.RemoveNode(this);
+ pImpl->MDNodeSet.erase(this);
}
+}
- // Destroy the operands.
- for (MDNodeOperand *Op = getOperandPtr(this, 0), *E = Op+NumOperands;
+void GenericMDNode::dropAllReferences() {
+ for (MDNodeOperand *Op = getOperandPtr(this, 0), *E = Op + NumOperands;
Op != E; ++Op)
- Op->~MDNodeOperand();
+ Op->set(nullptr);
}
static const Function *getFunctionForValue(Value *V) {
@@ -201,16 +222,7 @@ const Function *MDNode::getFunction() const {
#endif
}
-// destroy - Delete this node. Only when there are no uses.
-void MDNode::destroy() {
- setValueSubclassData(getSubclassDataFromValue() | DestroyFlag);
- // Placement delete, then free the memory.
- this->~MDNode();
- free(this);
-}
-
-/// isFunctionLocalValue - Return true if this is a value that would require a
-/// function-local MDNode.
+/// \brief Check if the Value would require a function-local MDNode.
static bool isFunctionLocalValue(Value *V) {
return isa<Instruction>(V) || isa<Argument>(V) || isa<BasicBlock>(V) ||
(isa<MDNode>(V) && cast<MDNode>(V)->isFunctionLocal());
@@ -218,21 +230,14 @@ static bool isFunctionLocalValue(Value *V) {
MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef<Value*> Vals,
FunctionLocalness FL, bool Insert) {
- LLVMContextImpl *pImpl = Context.pImpl;
-
- // Add all the operand pointers. Note that we don't have to add the
- // isFunctionLocal bit because that's implied by the operands.
- // Note that if the operands are later nulled out, the node will be
- // removed from the uniquing map.
- FoldingSetNodeID ID;
- for (Value *V : Vals)
- ID.AddPointer(V);
-
- void *InsertPoint;
- MDNode *N = pImpl->MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint);
+ auto &Store = Context.pImpl->MDNodeSet;
- if (N || !Insert)
- return N;
+ GenericMDNodeInfo::KeyTy Key(Vals);
+ auto I = Store.find_as(Key);
+ if (I != Store.end())
+ return *I;
+ if (!Insert)
+ return nullptr;
bool isFunctionLocal = false;
switch (FL) {
@@ -254,15 +259,11 @@ MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef<Value*> Vals,
}
// Coallocate space for the node and Operands together, then placement new.
- void *Ptr = malloc(sizeof(MDNode) + Vals.size() * sizeof(MDNodeOperand));
- N = new (Ptr) MDNode(Context, Vals, isFunctionLocal);
-
- // Cache the operand hash.
- N->Hash = ID.ComputeHash();
-
- // InsertPoint will have been set by the FindNodeOrInsertPos call.
- pImpl->MDNodeSet.InsertNode(N, InsertPoint);
+ GenericMDNode *N =
+ new (Vals.size()) GenericMDNode(Context, Vals, isFunctionLocal);
+ N->Hash = Key.Hash;
+ Store.insert(N);
return N;
}
@@ -281,48 +282,33 @@ MDNode *MDNode::getIfExists(LLVMContext &Context, ArrayRef<Value*> Vals) {
}
MDNode *MDNode::getTemporary(LLVMContext &Context, ArrayRef<Value*> Vals) {
- MDNode *N =
- (MDNode *)malloc(sizeof(MDNode) + Vals.size() * sizeof(MDNodeOperand));
- N = new (N) MDNode(Context, Vals, FL_No);
- N->setValueSubclassData(N->getSubclassDataFromValue() |
- NotUniquedBit);
+ MDNode *N = new (Vals.size()) MDNodeFwdDecl(Context, Vals, FL_No);
+ N->setValueSubclassData(N->getSubclassDataFromValue() | NotUniquedBit);
LeakDetector::addGarbageObject(N);
return N;
}
void MDNode::deleteTemporary(MDNode *N) {
assert(N->use_empty() && "Temporary MDNode has uses!");
- assert(!N->getContext().pImpl->MDNodeSet.RemoveNode(N) &&
- "Deleting a non-temporary uniqued node!");
- assert(!N->getContext().pImpl->NonUniquedMDNodes.erase(N) &&
- "Deleting a non-temporary non-uniqued node!");
+ assert(isa<MDNodeFwdDecl>(N) && "Expected forward declaration");
assert((N->getSubclassDataFromValue() & NotUniquedBit) &&
"Temporary MDNode does not have NotUniquedBit set!");
- assert((N->getSubclassDataFromValue() & DestroyFlag) == 0 &&
- "Temporary MDNode has DestroyFlag set!");
LeakDetector::removeGarbageObject(N);
- N->destroy();
+ delete cast<MDNodeFwdDecl>(N);
}
-/// getOperand - Return specified operand.
+/// \brief Return specified operand.
Value *MDNode::getOperand(unsigned i) const {
assert(i < getNumOperands() && "Invalid operand number");
return *getOperandPtr(const_cast<MDNode*>(this), i);
}
-void MDNode::Profile(FoldingSetNodeID &ID) const {
- // Add all the operand pointers. Note that we don't have to add the
- // isFunctionLocal bit because that's implied by the operands.
- // Note that if the operands are later nulled out, the node will be
- // removed from the uniquing map.
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
- ID.AddPointer(getOperand(i));
-}
-
void MDNode::setIsNotUniqued() {
setValueSubclassData(getSubclassDataFromValue() | NotUniquedBit);
LLVMContextImpl *pImpl = getType()->getContext().pImpl;
- pImpl->NonUniquedMDNodes.insert(this);
+ auto *G = cast<GenericMDNode>(this);
+ G->Hash = 0;
+ pImpl->NonUniquedMDNodes.insert(G);
}
// Replace value from this node's operand list.
@@ -350,44 +336,45 @@ void MDNode::replaceOperand(MDNodeOperand *Op, Value *To) {
if (From == To)
return;
- // Update the operand.
- Op->set(To);
-
// If this node is already not being uniqued (because one of the operands
// already went to null), then there is nothing else to do here.
- if (isNotUniqued()) return;
+ if (isNotUniqued()) {
+ Op->set(To);
+ return;
+ }
- LLVMContextImpl *pImpl = getType()->getContext().pImpl;
+ auto &Store = getContext().pImpl->MDNodeSet;
+ auto *N = cast<GenericMDNode>(this);
- // Remove "this" from the context map. FoldingSet doesn't have to reprofile
- // this node to remove it, so we don't care what state the operands are in.
- pImpl->MDNodeSet.RemoveNode(this);
+ // Remove "this" from the context map.
+ Store.erase(N);
+
+ // Update the operand.
+ Op->set(To);
// If we are dropping an argument to null, we choose to not unique the MDNode
// anymore. This commonly occurs during destruction, and uniquing these
// brings little reuse. Also, this means we don't need to include
- // isFunctionLocal bits in FoldingSetNodeIDs for MDNodes.
+ // isFunctionLocal bits in the hash for MDNodes.
if (!To) {
setIsNotUniqued();
return;
}
- // Now that the node is out of the folding set, get ready to reinsert it.
- // First, check to see if another node with the same operands already exists
- // in the set. If so, then this node is redundant.
- FoldingSetNodeID ID;
- Profile(ID);
- void *InsertPoint;
- if (MDNode *N = pImpl->MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint)) {
- replaceAllUsesWith(N);
- destroy();
+ // Now that the node is out of the table, get ready to reinsert it. First,
+ // check to see if another node with the same operands already exists in the
+ // set. If so, then this node is redundant.
+ SmallVector<Value *, 8> Vals;
+ GenericMDNodeInfo::KeyTy Key(N, Vals);
+ auto I = Store.find_as(Key);
+ if (I != Store.end()) {
+ N->replaceAllUsesWith(*I);
+ delete N;
return;
}
- // Cache the operand hash.
- Hash = ID.ComputeHash();
- // InsertPoint will have been set by the FindNodeOrInsertPos call.
- pImpl->MDNodeSet.InsertNode(this, InsertPoint);
+ N->Hash = Key.Hash;
+ Store.insert(N);
// If this MDValue was previously function-local but no longer is, clear
// its function-local flag.
@@ -406,6 +393,41 @@ void MDNode::replaceOperand(MDNodeOperand *Op, Value *To) {
}
}
+MDNode *MDNode::concatenate(MDNode *A, MDNode *B) {
+ if (!A)
+ return B;
+ if (!B)
+ return A;
+
+ SmallVector<Value *, 4> Vals(A->getNumOperands() +
+ B->getNumOperands());
+
+ unsigned j = 0;
+ for (unsigned i = 0, ie = A->getNumOperands(); i != ie; ++i)
+ Vals[j++] = A->getOperand(i);
+ for (unsigned i = 0, ie = B->getNumOperands(); i != ie; ++i)
+ Vals[j++] = B->getOperand(i);
+
+ return MDNode::get(A->getContext(), Vals);
+}
+
+MDNode *MDNode::intersect(MDNode *A, MDNode *B) {
+ if (!A || !B)
+ return nullptr;
+
+ SmallVector<Value *, 4> Vals;
+ for (unsigned i = 0, ie = A->getNumOperands(); i != ie; ++i) {
+ Value *V = A->getOperand(i);
+ for (unsigned j = 0, je = B->getNumOperands(); j != je; ++j)
+ if (V == B->getOperand(j)) {
+ Vals.push_back(V);
+ break;
+ }
+ }
+
+ return MDNode::get(A->getContext(), Vals);
+}
+
MDNode *MDNode::getMostGenericFPMath(MDNode *A, MDNode *B) {
if (!A || !B)
return nullptr;
@@ -524,49 +546,41 @@ MDNode *MDNode::getMostGenericRange(MDNode *A, MDNode *B) {
//
static SmallVector<TrackingVH<MDNode>, 4> &getNMDOps(void *Operands) {
- return *(SmallVector<TrackingVH<MDNode>, 4>*)Operands;
+ return *(SmallVector<TrackingVH<MDNode>, 4> *)Operands;
}
NamedMDNode::NamedMDNode(const Twine &N)
- : Name(N.str()), Parent(nullptr),
- Operands(new SmallVector<TrackingVH<MDNode>, 4>()) {
-}
+ : Name(N.str()), Parent(nullptr),
+ Operands(new SmallVector<TrackingVH<MDNode>, 4>()) {}
NamedMDNode::~NamedMDNode() {
dropAllReferences();
delete &getNMDOps(Operands);
}
-/// getNumOperands - Return number of NamedMDNode operands.
unsigned NamedMDNode::getNumOperands() const {
return (unsigned)getNMDOps(Operands).size();
}
-/// getOperand - Return specified operand.
MDNode *NamedMDNode::getOperand(unsigned i) const {
assert(i < getNumOperands() && "Invalid Operand number!");
- return dyn_cast<MDNode>(&*getNMDOps(Operands)[i]);
+ return &*getNMDOps(Operands)[i];
}
-/// addOperand - Add metadata Operand.
void NamedMDNode::addOperand(MDNode *M) {
assert(!M->isFunctionLocal() &&
"NamedMDNode operands must not be function-local!");
getNMDOps(Operands).push_back(TrackingVH<MDNode>(M));
}
-/// eraseFromParent - Drop all references and remove the node from parent
-/// module.
void NamedMDNode::eraseFromParent() {
getParent()->eraseNamedMetadata(this);
}
-/// dropAllReferences - Remove all uses and clear node vector.
void NamedMDNode::dropAllReferences() {
getNMDOps(Operands).clear();
}
-/// getName - Return a constant reference to this named metadata's name.
StringRef NamedMDNode::getName() const {
return StringRef(Name);
}
@@ -576,7 +590,8 @@ StringRef NamedMDNode::getName() const {
//
void Instruction::setMetadata(StringRef Kind, MDNode *Node) {
- if (!Node && !hasMetadata()) return;
+ if (!Node && !hasMetadata())
+ return;
setMetadata(getContext().getMDKindID(Kind), Node);
}
@@ -632,7 +647,8 @@ void Instruction::dropUnknownMetadata(ArrayRef<unsigned> KnownIDs) {
/// node. This updates/replaces metadata if already present, or removes it if
/// Node is null.
void Instruction::setMetadata(unsigned KindID, MDNode *Node) {
- if (!Node && !hasMetadata()) return;
+ if (!Node && !hasMetadata())
+ return;
// Handle 'dbg' as a special case since it is not stored in the hash table.
if (KindID == LLVMContext::MD_dbg) {
@@ -687,6 +703,12 @@ void Instruction::setMetadata(unsigned KindID, MDNode *Node) {
// Otherwise, removing an entry that doesn't exist on the instruction.
}
+void Instruction::setAAMetadata(const AAMDNodes &N) {
+ setMetadata(LLVMContext::MD_tbaa, N.TBAA);
+ setMetadata(LLVMContext::MD_alias_scope, N.Scope);
+ setMetadata(LLVMContext::MD_noalias, N.NoAlias);
+}
+
MDNode *Instruction::getMetadataImpl(unsigned KindID) const {
// Handle 'dbg' as a special case since it is not stored in the hash table.
if (KindID == LLVMContext::MD_dbg)
@@ -703,8 +725,8 @@ MDNode *Instruction::getMetadataImpl(unsigned KindID) const {
return nullptr;
}
-void Instruction::getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned,
- MDNode*> > &Result) const {
+void Instruction::getAllMetadataImpl(
+ SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const {
Result.clear();
// Handle 'dbg' as a special case since it is not stored in the hash table.
@@ -728,9 +750,8 @@ void Instruction::getAllMetadataImpl(SmallVectorImpl<std::pair<unsigned,
array_pod_sort(Result.begin(), Result.end());
}
-void Instruction::
-getAllMetadataOtherThanDebugLocImpl(SmallVectorImpl<std::pair<unsigned,
- MDNode*> > &Result) const {
+void Instruction::getAllMetadataOtherThanDebugLocImpl(
+ SmallVectorImpl<std::pair<unsigned, MDNode *>> &Result) const {
Result.clear();
assert(hasMetadataHashEntry() &&
getContext().pImpl->MetadataStore.count(this) &&
diff --git a/lib/IR/Module.cpp b/lib/IR/Module.cpp
index f1b1f9a2ac..14e534b8b1 100644
--- a/lib/IR/Module.cpp
+++ b/lib/IR/Module.cpp
@@ -259,6 +259,17 @@ void Module::eraseNamedMetadata(NamedMDNode *NMD) {
NamedMDList.erase(NMD);
}
+bool Module::isValidModFlagBehavior(Value *V, ModFlagBehavior &MFB) {
+ if (ConstantInt *Behavior = dyn_cast<ConstantInt>(V)) {
+ uint64_t Val = Behavior->getLimitedValue();
+ if (Val >= ModFlagBehaviorFirstVal && Val <= ModFlagBehaviorLastVal) {
+ MFB = static_cast<ModFlagBehavior>(Val);
+ return true;
+ }
+ }
+ return false;
+}
+
/// getModuleFlagsMetadata - Returns the module flags in the provided vector.
void Module::
getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const {
@@ -266,15 +277,15 @@ getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const {
if (!ModFlags) return;
for (const MDNode *Flag : ModFlags->operands()) {
- if (Flag->getNumOperands() >= 3 && isa<ConstantInt>(Flag->getOperand(0)) &&
+ ModFlagBehavior MFB;
+ if (Flag->getNumOperands() >= 3 &&
+ isValidModFlagBehavior(Flag->getOperand(0), MFB) &&
isa<MDString>(Flag->getOperand(1))) {
// Check the operands of the MDNode before accessing the operands.
// The verifier will actually catch these failures.
- ConstantInt *Behavior = cast<ConstantInt>(Flag->getOperand(0));
MDString *Key = cast<MDString>(Flag->getOperand(1));
Value *Val = Flag->getOperand(2);
- Flags.push_back(ModuleFlagEntry(ModFlagBehavior(Behavior->getZExtValue()),
- Key, Val));
+ Flags.push_back(ModuleFlagEntry(MFB, Key, Val));
}
}
}
@@ -378,28 +389,17 @@ void Module::setMaterializer(GVMaterializer *GVM) {
Materializer.reset(GVM);
}
-bool Module::isMaterializable(const GlobalValue *GV) const {
- if (Materializer)
- return Materializer->isMaterializable(GV);
- return false;
-}
-
bool Module::isDematerializable(const GlobalValue *GV) const {
if (Materializer)
return Materializer->isDematerializable(GV);
return false;
}
-bool Module::Materialize(GlobalValue *GV, std::string *ErrInfo) {
+std::error_code Module::materialize(GlobalValue *GV) {
if (!Materializer)
- return false;
+ return std::error_code();
- std::error_code EC = Materializer->Materialize(GV);
- if (!EC)
- return false;
- if (ErrInfo)
- *ErrInfo = EC.message();
- return true;
+ return Materializer->materialize(GV);
}
void Module::Dematerialize(GlobalValue *GV) {
@@ -413,13 +413,10 @@ std::error_code Module::materializeAll() {
return Materializer->MaterializeModule(this);
}
-std::error_code Module::materializeAllPermanently(bool ReleaseBuffer) {
+std::error_code Module::materializeAllPermanently() {
if (std::error_code EC = materializeAll())
return EC;
- if (ReleaseBuffer)
- Materializer->releaseBuffer();
-
Materializer.reset();
return std::error_code();
}
@@ -455,9 +452,20 @@ unsigned Module::getDwarfVersion() const {
}
Comdat *Module::getOrInsertComdat(StringRef Name) {
- Comdat C;
- StringMapEntry<Comdat> &Entry =
- ComdatSymTab.GetOrCreateValue(Name, std::move(C));
+ auto &Entry = *ComdatSymTab.insert(std::make_pair(Name, Comdat())).first;
Entry.second.Name = &Entry;
return &Entry.second;
}
+
+PICLevel::Level Module::getPICLevel() const {
+ Value *Val = getModuleFlag("PIC Level");
+
+ if (Val == NULL)
+ return PICLevel::Default;
+
+ return static_cast<PICLevel::Level>(cast<ConstantInt>(Val)->getZExtValue());
+}
+
+void Module::setPICLevel(PICLevel::Level PL) {
+ addModuleFlag(ModFlagBehavior::Error, "PIC Level", PL);
+}
diff --git a/lib/IR/PassManager.cpp b/lib/IR/PassManager.cpp
index 0defb6ab3e..2e2a7cb495 100644
--- a/lib/IR/PassManager.cpp
+++ b/lib/IR/PassManager.cpp
@@ -53,7 +53,7 @@ ModuleAnalysisManager::getResultImpl(void *PassID, Module *M) {
// If we don't have a cached result for this module, look up the pass and run
// it to produce a result, which we then add to the cache.
if (Inserted)
- RI->second = std::move(lookupPass(PassID).run(M, this));
+ RI->second = lookupPass(PassID).run(M, this);
return *RI->second;
}
diff --git a/lib/IR/PassRegistry.cpp b/lib/IR/PassRegistry.cpp
index 91940a9c7f..b879fef3f4 100644
--- a/lib/IR/PassRegistry.cpp
+++ b/lib/IR/PassRegistry.cpp
@@ -36,8 +36,7 @@ PassRegistry *PassRegistry::getPassRegistry() {
// Accessors
//
-PassRegistry::~PassRegistry() {
-}
+PassRegistry::~PassRegistry() {}
const PassInfo *PassRegistry::getPassInfo(const void *TI) const {
sys::SmartScopedReader<true> Guard(Lock);
@@ -58,77 +57,62 @@ const PassInfo *PassRegistry::getPassInfo(StringRef Arg) const {
void PassRegistry::registerPass(const PassInfo &PI, bool ShouldFree) {
sys::SmartScopedWriter<true> Guard(Lock);
bool Inserted =
- PassInfoMap.insert(std::make_pair(PI.getTypeInfo(),&PI)).second;
+ PassInfoMap.insert(std::make_pair(PI.getTypeInfo(), &PI)).second;
assert(Inserted && "Pass registered multiple times!");
(void)Inserted;
PassInfoStringMap[PI.getPassArgument()] = &PI;
-
+
// Notify any listeners.
- for (std::vector<PassRegistrationListener*>::iterator
- I = Listeners.begin(), E = Listeners.end(); I != E; ++I)
- (*I)->passRegistered(&PI);
-
- if (ShouldFree) ToFree.push_back(std::unique_ptr<const PassInfo>(&PI));
-}
+ for (auto *Listener : Listeners)
+ Listener->passRegistered(&PI);
-void PassRegistry::unregisterPass(const PassInfo &PI) {
- sys::SmartScopedWriter<true> Guard(Lock);
- MapType::iterator I = PassInfoMap.find(PI.getTypeInfo());
- assert(I != PassInfoMap.end() && "Pass registered but not in map!");
-
- // Remove pass from the map.
- PassInfoMap.erase(I);
- PassInfoStringMap.erase(PI.getPassArgument());
+ if (ShouldFree)
+ ToFree.push_back(std::unique_ptr<const PassInfo>(&PI));
}
void PassRegistry::enumerateWith(PassRegistrationListener *L) {
sys::SmartScopedReader<true> Guard(Lock);
- for (auto I = PassInfoMap.begin(), E = PassInfoMap.end(); I != E; ++I)
- L->passEnumerate(I->second);
+ for (auto PassInfoPair : PassInfoMap)
+ L->passEnumerate(PassInfoPair.second);
}
-
/// Analysis Group Mechanisms.
-void PassRegistry::registerAnalysisGroup(const void *InterfaceID,
+void PassRegistry::registerAnalysisGroup(const void *InterfaceID,
const void *PassID,
- PassInfo& Registeree,
- bool isDefault,
+ PassInfo &Registeree, bool isDefault,
bool ShouldFree) {
- PassInfo *InterfaceInfo = const_cast<PassInfo*>(getPassInfo(InterfaceID));
+ PassInfo *InterfaceInfo = const_cast<PassInfo *>(getPassInfo(InterfaceID));
if (!InterfaceInfo) {
// First reference to Interface, register it now.
registerPass(Registeree);
InterfaceInfo = &Registeree;
}
- assert(Registeree.isAnalysisGroup() &&
+ assert(Registeree.isAnalysisGroup() &&
"Trying to join an analysis group that is a normal pass!");
if (PassID) {
- PassInfo *ImplementationInfo = const_cast<PassInfo*>(getPassInfo(PassID));
+ PassInfo *ImplementationInfo = const_cast<PassInfo *>(getPassInfo(PassID));
assert(ImplementationInfo &&
"Must register pass before adding to AnalysisGroup!");
sys::SmartScopedWriter<true> Guard(Lock);
-
+
// Make sure we keep track of the fact that the implementation implements
// the interface.
ImplementationInfo->addInterfaceImplemented(InterfaceInfo);
- AnalysisGroupInfo &AGI = AnalysisGroupInfoMap[InterfaceInfo];
- assert(AGI.Implementations.count(ImplementationInfo) == 0 &&
- "Cannot add a pass to the same analysis group more than once!");
- AGI.Implementations.insert(ImplementationInfo);
if (isDefault) {
assert(InterfaceInfo->getNormalCtor() == nullptr &&
"Default implementation for analysis group already specified!");
- assert(ImplementationInfo->getNormalCtor() &&
- "Cannot specify pass as default if it does not have a default ctor");
+ assert(
+ ImplementationInfo->getNormalCtor() &&
+ "Cannot specify pass as default if it does not have a default ctor");
InterfaceInfo->setNormalCtor(ImplementationInfo->getNormalCtor());
InterfaceInfo->setTargetMachineCtor(
ImplementationInfo->getTargetMachineCtor());
}
}
-
+
if (ShouldFree)
ToFree.push_back(std::unique_ptr<const PassInfo>(&Registeree));
}
@@ -140,7 +124,7 @@ void PassRegistry::addRegistrationListener(PassRegistrationListener *L) {
void PassRegistry::removeRegistrationListener(PassRegistrationListener *L) {
sys::SmartScopedWriter<true> Guard(Lock);
-
+
auto I = std::find(Listeners.begin(), Listeners.end(), L);
Listeners.erase(I);
}
diff --git a/lib/IR/SymbolTableListTraitsImpl.h b/lib/IR/SymbolTableListTraitsImpl.h
index 8302597c94..a18f98261a 100644
--- a/lib/IR/SymbolTableListTraitsImpl.h
+++ b/lib/IR/SymbolTableListTraitsImpl.h
@@ -13,8 +13,8 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLVM_SYMBOLTABLELISTTRAITS_IMPL_H
-#define LLVM_SYMBOLTABLELISTTRAITS_IMPL_H
+#ifndef LLVM_LIB_IR_SYMBOLTABLELISTTRAITSIMPL_H
+#define LLVM_LIB_IR_SYMBOLTABLELISTTRAITSIMPL_H
#include "llvm/IR/SymbolTableListTraits.h"
#include "llvm/IR/ValueSymbolTable.h"
diff --git a/lib/IR/Type.cpp b/lib/IR/Type.cpp
index 1efde47b85..0458b5f35b 100644
--- a/lib/IR/Type.cpp
+++ b/lib/IR/Type.cpp
@@ -89,9 +89,13 @@ bool Type::canLosslesslyBitCastTo(Type *Ty) const {
// At this point we have only various mismatches of the first class types
// remaining and ptr->ptr. Just select the lossless conversions. Everything
- // else is not lossless.
- if (this->isPointerTy())
- return Ty->isPointerTy();
+ // else is not lossless. Conservatively assume we can't losslessly convert
+ // between pointers with different address spaces.
+ if (const PointerType *PTy = dyn_cast<PointerType>(this)) {
+ if (const PointerType *OtherPTy = dyn_cast<PointerType>(Ty))
+ return PTy->getAddressSpace() == OtherPTy->getAddressSpace();
+ return false;
+ }
return false; // Other types have no identity values
}
@@ -155,7 +159,7 @@ int Type::getFPMantissaWidth() const {
/// isSizedDerivedType - Derived types like structures and arrays are sized
/// iff all of the members of the type are sized as well. Since asking for
/// their size is relatively uncommon, move this operation out of line.
-bool Type::isSizedDerivedType(SmallPtrSet<const Type*, 4> *Visited) const {
+bool Type::isSizedDerivedType(SmallPtrSetImpl<const Type*> *Visited) const {
if (const ArrayType *ATy = dyn_cast<ArrayType>(this))
return ATy->getElementType()->isSized(Visited);
@@ -454,10 +458,11 @@ void StructType::setName(StringRef Name) {
}
// Look up the entry for the name.
- EntryTy *Entry = &getContext().pImpl->NamedStructTypes.GetOrCreateValue(Name);
-
+ auto IterBool =
+ getContext().pImpl->NamedStructTypes.insert(std::make_pair(Name, this));
+
// While we have a name collision, try a random rename.
- if (Entry->getValue()) {
+ if (!IterBool.second) {
SmallString<64> TempStr(Name);
TempStr.push_back('.');
raw_svector_ostream TmpStream(TempStr);
@@ -467,19 +472,16 @@ void StructType::setName(StringRef Name) {
TempStr.resize(NameSize + 1);
TmpStream.resync();
TmpStream << getContext().pImpl->NamedStructTypesUniqueID++;
-
- Entry = &getContext().pImpl->
- NamedStructTypes.GetOrCreateValue(TmpStream.str());
- } while (Entry->getValue());
- }
- // Okay, we found an entry that isn't used. It's us!
- Entry->setValue(this);
+ IterBool = getContext().pImpl->NamedStructTypes.insert(
+ std::make_pair(TmpStream.str(), this));
+ } while (!IterBool.second);
+ }
// Delete the old string data.
if (SymbolTableEntry)
((EntryTy *)SymbolTableEntry)->Destroy(SymbolTable.getAllocator());
- SymbolTableEntry = Entry;
+ SymbolTableEntry = &*IterBool.first;
}
//===----------------------------------------------------------------------===//
@@ -506,7 +508,9 @@ StructType *StructType::get(Type *type, ...) {
StructFields.push_back(type);
type = va_arg(ap, llvm::Type*);
}
- return llvm::StructType::get(Ctx, StructFields);
+ auto *Ret = llvm::StructType::get(Ctx, StructFields);
+ va_end(ap);
+ return Ret;
}
StructType *StructType::create(LLVMContext &Context, ArrayRef<Type*> Elements,
@@ -547,16 +551,18 @@ StructType *StructType::create(StringRef Name, Type *type, ...) {
StructFields.push_back(type);
type = va_arg(ap, llvm::Type*);
}
- return llvm::StructType::create(Ctx, StructFields, Name);
+ auto *Ret = llvm::StructType::create(Ctx, StructFields, Name);
+ va_end(ap);
+ return Ret;
}
-bool StructType::isSized(SmallPtrSet<const Type*, 4> *Visited) const {
+bool StructType::isSized(SmallPtrSetImpl<const Type*> *Visited) const {
if ((getSubclassData() & SCDB_IsSized) != 0)
return true;
if (isOpaque())
return false;
- if (Visited && !Visited->insert(this))
+ if (Visited && !Visited->insert(this).second)
return false;
// Okay, our struct is sized if all of the elements are, but if one of the
@@ -591,6 +597,7 @@ void StructType::setBody(Type *type, ...) {
type = va_arg(ap, llvm::Type*);
}
setBody(StructFields);
+ va_end(ap);
}
bool StructType::isValidElementType(Type *ElemTy) {
diff --git a/lib/IR/TypeFinder.cpp b/lib/IR/TypeFinder.cpp
index 689b903891..6796075bfc 100644
--- a/lib/IR/TypeFinder.cpp
+++ b/lib/IR/TypeFinder.cpp
@@ -40,7 +40,7 @@ void TypeFinder::run(const Module &M, bool onlyNamed) {
}
// Get types from functions.
- SmallVector<std::pair<unsigned, MDNode*>, 4> MDForInst;
+ SmallVector<std::pair<unsigned, MDNode *>, 4> MDForInst;
for (Module::const_iterator FI = M.begin(), E = M.end(); FI != E; ++FI) {
incorporateType(FI->getType());
diff --git a/lib/IR/Use.cpp b/lib/IR/Use.cpp
index 047861c258..cae845d99f 100644
--- a/lib/IR/Use.cpp
+++ b/lib/IR/Use.cpp
@@ -52,7 +52,7 @@ unsigned Use::getOperandNo() const {
// Sets up the waymarking algorithm's tags for a series of Uses. See the
// algorithm details here:
//
-// http://www.llvm.org/docs/ProgrammersManual.html#UserLayout
+// http://www.llvm.org/docs/ProgrammersManual.html#the-waymarking-algorithm
//
Use *Use::initTags(Use *const Start, Use *Stop) {
ptrdiff_t Done = 0;
diff --git a/lib/IR/UseListOrder.cpp b/lib/IR/UseListOrder.cpp
new file mode 100644
index 0000000000..d064e67026
--- /dev/null
+++ b/lib/IR/UseListOrder.cpp
@@ -0,0 +1,43 @@
+//===- UseListOrder.cpp - Implement Use List Order ------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Implement structures and command-line options for preserving use-list order.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/UseListOrder.h"
+#include "llvm/Support/CommandLine.h"
+
+using namespace llvm;
+
+static cl::opt<bool> PreserveBitcodeUseListOrder(
+ "preserve-bc-use-list-order",
+ cl::desc("Experimental support to preserve bitcode use-list order."),
+ cl::init(false), cl::Hidden);
+
+static cl::opt<bool> PreserveAssemblyUseListOrder(
+ "preserve-ll-use-list-order",
+ cl::desc("Experimental support to preserve assembly use-list order."),
+ cl::init(false), cl::Hidden);
+
+bool llvm::shouldPreserveBitcodeUseListOrder() {
+ return PreserveBitcodeUseListOrder;
+}
+
+bool llvm::shouldPreserveAssemblyUseListOrder() {
+ return PreserveAssemblyUseListOrder;
+}
+
+void llvm::setPreserveBitcodeUseListOrder(bool ShouldPreserve) {
+ PreserveBitcodeUseListOrder = ShouldPreserve;
+}
+
+void llvm::setPreserveAssemblyUseListOrder(bool ShouldPreserve) {
+ PreserveAssemblyUseListOrder = ShouldPreserve;
+}
diff --git a/lib/IR/User.cpp b/lib/IR/User.cpp
index 940682826a..ee83eacf2b 100644
--- a/lib/IR/User.cpp
+++ b/lib/IR/User.cpp
@@ -20,9 +20,6 @@ namespace llvm {
void User::anchor() {}
-// replaceUsesOfWith - Replaces all references to the "From" definition with
-// references to the "To" definition.
-//
void User::replaceUsesOfWith(Value *From, Value *To) {
if (From == To) return; // Duh what?
diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp
index 35c241a608..4e0c11f15f 100644
--- a/lib/IR/Value.cpp
+++ b/lib/IR/Value.cpp
@@ -15,6 +15,7 @@
#include "LLVMContextImpl.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
@@ -44,7 +45,8 @@ static inline Type *checkType(Type *Ty) {
Value::Value(Type *ty, unsigned scid)
: VTy(checkType(ty)), UseList(nullptr), Name(nullptr), SubclassID(scid),
- HasValueHandle(0), SubclassOptionalData(0), SubclassData(0) {
+ HasValueHandle(0), SubclassOptionalData(0), SubclassData(0),
+ NumOperands(0) {
// FIXME: Why isn't this in the subclass gunk??
// Note, we cannot call isa<CallInst> before the CallInst has been
// constructed.
@@ -87,8 +89,6 @@ Value::~Value() {
LeakDetector::removeGarbageObject(this);
}
-/// hasNUses - Return true if this Value has exactly N users.
-///
bool Value::hasNUses(unsigned N) const {
const_use_iterator UI = use_begin(), E = use_end();
@@ -97,9 +97,6 @@ bool Value::hasNUses(unsigned N) const {
return UI == E;
}
-/// hasNUsesOrMore - Return true if this value has N users or more. This is
-/// logically equivalent to getNumUses() >= N.
-///
bool Value::hasNUsesOrMore(unsigned N) const {
const_use_iterator UI = use_begin(), E = use_end();
@@ -109,8 +106,6 @@ bool Value::hasNUsesOrMore(unsigned N) const {
return true;
}
-/// isUsedInBasicBlock - Return true if this value is used in the specified
-/// basic block.
bool Value::isUsedInBasicBlock(const BasicBlock *BB) const {
// This can be computed either by scanning the instructions in BB, or by
// scanning the use list of this Value. Both lists can be very long, but
@@ -132,10 +127,6 @@ bool Value::isUsedInBasicBlock(const BasicBlock *BB) const {
return false;
}
-
-/// getNumUses - This method computes the number of uses of this Value. This
-/// is a linear time operation. Use hasOneUse or hasNUses to check for specific
-/// values.
unsigned Value::getNumUses() const {
return (unsigned)std::distance(use_begin(), use_end());
}
@@ -235,9 +226,6 @@ void Value::setName(const Twine &NewName) {
Name = ST->createValueName(NameRef, this);
}
-
-/// takeName - transfer the name from V to this value, setting V's name to
-/// empty. It is an error to call V->takeName(V).
void Value::takeName(Value *V) {
assert(SubclassID != MDStringVal && "Cannot take the name of an MDString!");
@@ -302,9 +290,9 @@ void Value::takeName(Value *V) {
}
#ifndef NDEBUG
-static bool contains(SmallPtrSet<ConstantExpr *, 4> &Cache, ConstantExpr *Expr,
+static bool contains(SmallPtrSetImpl<ConstantExpr *> &Cache, ConstantExpr *Expr,
Constant *C) {
- if (!Cache.insert(Expr))
+ if (!Cache.insert(Expr).second)
return false;
for (auto &O : Expr->operands()) {
@@ -413,7 +401,7 @@ static Value *stripPointerCastsAndOffsets(Value *V) {
return V;
}
assert(V->getType()->isPointerTy() && "Unexpected operand type!");
- } while (Visited.insert(V));
+ } while (Visited.insert(V).second);
return V;
}
@@ -454,7 +442,8 @@ Value *Value::stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
return V;
Offset = GEPOffset;
V = GEP->getPointerOperand();
- } else if (Operator::getOpcode(V) == Instruction::BitCast) {
+ } else if (Operator::getOpcode(V) == Instruction::BitCast ||
+ Operator::getOpcode(V) == Instruction::AddrSpaceCast) {
V = cast<Operator>(V)->getOperand(0);
} else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) {
V = GA->getAliasee();
@@ -462,7 +451,7 @@ Value *Value::stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
return V;
}
assert(V->getType()->isPointerTy() && "Unexpected operand type!");
- } while (Visited.insert(V));
+ } while (Visited.insert(V).second);
return V;
}
@@ -471,10 +460,12 @@ Value *Value::stripInBoundsOffsets() {
return stripPointerCastsAndOffsets<PSK_InBounds>(this);
}
-/// isDereferenceablePointer - Test if this value is always a pointer to
-/// allocated and suitably aligned memory for a simple load or store.
+/// \brief Check if Value is always a dereferenceable pointer.
+///
+/// Test if V is always a pointer to allocated and suitably aligned memory for
+/// a simple load or store.
static bool isDereferenceablePointer(const Value *V, const DataLayout *DL,
- SmallPtrSet<const Value *, 32> &Visited) {
+ SmallPtrSetImpl<const Value *> &Visited) {
// Note that it is not safe to speculate into a malloc'd region because
// malloc may return null.
@@ -504,14 +495,34 @@ static bool isDereferenceablePointer(const Value *V, const DataLayout *DL,
if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(V))
return !GV->hasExternalWeakLinkage();
- // byval arguments are ok.
- if (const Argument *A = dyn_cast<Argument>(V))
- return A->hasByValAttr();
+ // byval arguments are okay. Arguments specifically marked as
+ // dereferenceable are okay too.
+ if (const Argument *A = dyn_cast<Argument>(V)) {
+ if (A->hasByValAttr())
+ return true;
+ else if (uint64_t Bytes = A->getDereferenceableBytes()) {
+ Type *Ty = V->getType()->getPointerElementType();
+ if (Ty->isSized() && DL && DL->getTypeStoreSize(Ty) <= Bytes)
+ return true;
+ }
+
+ return false;
+ }
+
+ // Return values from call sites specifically marked as dereferenceable are
+ // also okay.
+ if (ImmutableCallSite CS = V) {
+ if (uint64_t Bytes = CS.getDereferenceableBytes(0)) {
+ Type *Ty = V->getType()->getPointerElementType();
+ if (Ty->isSized() && DL && DL->getTypeStoreSize(Ty) <= Bytes)
+ return true;
+ }
+ }
// For GEPs, determine if the indexing lands within the allocated object.
if (const GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
// Conservatively require that the base pointer be fully dereferenceable.
- if (!Visited.insert(GEP->getOperand(0)))
+ if (!Visited.insert(GEP->getOperand(0)).second)
return false;
if (!isDereferenceablePointer(GEP->getOperand(0), DL, Visited))
return false;
@@ -543,21 +554,39 @@ static bool isDereferenceablePointer(const Value *V, const DataLayout *DL,
return true;
}
+ if (const AddrSpaceCastInst *ASC = dyn_cast<AddrSpaceCastInst>(V))
+ return isDereferenceablePointer(ASC->getOperand(0), DL, Visited);
+
// If we don't know, assume the worst.
return false;
}
-/// isDereferenceablePointer - Test if this value is always a pointer to
-/// allocated and suitably aligned memory for a simple load or store.
bool Value::isDereferenceablePointer(const DataLayout *DL) const {
+ // When dereferenceability information is provided by a dereferenceable
+ // attribute, we know exactly how many bytes are dereferenceable. If we can
+ // determine the exact offset to the attributed variable, we can use that
+ // information here.
+ Type *Ty = getType()->getPointerElementType();
+ if (Ty->isSized() && DL) {
+ APInt Offset(DL->getTypeStoreSizeInBits(getType()), 0);
+ const Value *BV = stripAndAccumulateInBoundsConstantOffsets(*DL, Offset);
+
+ APInt DerefBytes(Offset.getBitWidth(), 0);
+ if (const Argument *A = dyn_cast<Argument>(BV))
+ DerefBytes = A->getDereferenceableBytes();
+ else if (ImmutableCallSite CS = BV)
+ DerefBytes = CS.getDereferenceableBytes(0);
+
+ if (DerefBytes.getBoolValue() && Offset.isNonNegative()) {
+ if (DerefBytes.uge(Offset + DL->getTypeStoreSize(Ty)))
+ return true;
+ }
+ }
+
SmallPtrSet<const Value *, 32> Visited;
return ::isDereferenceablePointer(this, DL, Visited);
}
-/// DoPHITranslation - If this value is a PHI node with CurBB as its parent,
-/// return the value in the PHI node corresponding to PredBB. If not, return
-/// ourself. This is useful if you want to know the value something has in a
-/// predecessor block.
Value *Value::DoPHITranslation(const BasicBlock *CurBB,
const BasicBlock *PredBB) {
PHINode *PN = dyn_cast<PHINode>(this);
@@ -568,12 +597,29 @@ Value *Value::DoPHITranslation(const BasicBlock *CurBB,
LLVMContext &Value::getContext() const { return VTy->getContext(); }
+void Value::reverseUseList() {
+ if (!UseList || !UseList->Next)
+ // No need to reverse 0 or 1 uses.
+ return;
+
+ Use *Head = UseList;
+ Use *Current = UseList->Next;
+ Head->Next = nullptr;
+ while (Current) {
+ Use *Next = Current->Next;
+ Current->Next = Head;
+ Head->setPrev(&Current->Next);
+ Head = Current;
+ Current = Next;
+ }
+ UseList = Head;
+ Head->setPrev(&UseList);
+}
+
//===----------------------------------------------------------------------===//
// ValueHandleBase Class
//===----------------------------------------------------------------------===//
-/// AddToExistingUseList - Add this ValueHandle to the use list for VP, where
-/// List is known to point into the existing use list.
void ValueHandleBase::AddToExistingUseList(ValueHandleBase **List) {
assert(List && "Handle list is null?");
@@ -597,7 +643,6 @@ void ValueHandleBase::AddToExistingUseListAfter(ValueHandleBase *List) {
Next->setPrevPtr(&Next);
}
-/// AddToUseList - Add this ValueHandle to the use list for VP.
void ValueHandleBase::AddToUseList() {
assert(VP.getPointer() && "Null pointer doesn't have a use list!");
@@ -641,7 +686,6 @@ void ValueHandleBase::AddToUseList() {
}
}
-/// RemoveFromUseList - Remove this ValueHandle from its current use list.
void ValueHandleBase::RemoveFromUseList() {
assert(VP.getPointer() && VP.getPointer()->HasValueHandle &&
"Pointer doesn't have a use list!");
@@ -729,6 +773,8 @@ void ValueHandleBase::ValueIsDeleted(Value *V) {
void ValueHandleBase::ValueIsRAUWd(Value *Old, Value *New) {
assert(Old->HasValueHandle &&"Should only be called if ValueHandles present");
assert(Old != New && "Changing value into itself!");
+ assert(Old->getType() == New->getType() &&
+ "replaceAllUses of value with new value of different type!");
// Get the linked list base, which is guaranteed to exist since the
// HasValueHandle flag is set.
diff --git a/lib/IR/ValueSymbolTable.cpp b/lib/IR/ValueSymbolTable.cpp
index e9e979a9a7..2b23f6dd15 100644
--- a/lib/IR/ValueSymbolTable.cpp
+++ b/lib/IR/ValueSymbolTable.cpp
@@ -56,11 +56,10 @@ void ValueSymbolTable::reinsertValue(Value* V) {
raw_svector_ostream(UniqueName) << ++LastUnique;
// Try insert the vmap entry with this suffix.
- ValueName &NewName = vmap.GetOrCreateValue(UniqueName);
- if (!NewName.getValue()) {
+ auto IterBool = vmap.insert(std::make_pair(UniqueName, V));
+ if (IterBool.second) {
// Newly inserted name. Success!
- NewName.setValue(V);
- V->Name = &NewName;
+ V->Name = &*IterBool.first;
//DEBUG(dbgs() << " Inserted value: " << UniqueName << ": " << *V << "\n");
return;
}
@@ -78,12 +77,11 @@ void ValueSymbolTable::removeValueName(ValueName *V) {
/// auto-renames the name and returns that instead.
ValueName *ValueSymbolTable::createValueName(StringRef Name, Value *V) {
// In the common case, the name is not already in the symbol table.
- ValueName &Entry = vmap.GetOrCreateValue(Name);
- if (!Entry.getValue()) {
- Entry.setValue(V);
+ auto IterBool = vmap.insert(std::make_pair(Name, V));
+ if (IterBool.second) {
//DEBUG(dbgs() << " Inserted value: " << Entry.getKeyData() << ": "
// << *V << "\n");
- return &Entry;
+ return &*IterBool.first;
}
// Otherwise, there is a naming conflict. Rename this value.
@@ -95,12 +93,11 @@ ValueName *ValueSymbolTable::createValueName(StringRef Name, Value *V) {
raw_svector_ostream(UniqueName) << ++LastUnique;
// Try insert the vmap entry with this suffix.
- ValueName &NewName = vmap.GetOrCreateValue(UniqueName);
- if (!NewName.getValue()) {
- // Newly inserted name. Success!
- NewName.setValue(V);
- //DEBUG(dbgs() << " Inserted value: " << UniqueName << ": " << *V << "\n");
- return &NewName;
+ auto IterBool = vmap.insert(std::make_pair(UniqueName, V));
+ if (IterBool.second) {
+ // DEBUG(dbgs() << " Inserted value: " << UniqueName << ": " << *V <<
+ // "\n");
+ return &*IterBool.first;
}
}
}
diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp
index 314bad36b1..9698dbd77f 100644
--- a/lib/IR/Verifier.cpp
+++ b/lib/IR/Verifier.cpp
@@ -257,7 +257,7 @@ private:
void visitGlobalVariable(const GlobalVariable &GV);
void visitGlobalAlias(const GlobalAlias &GA);
void visitAliaseeSubExpr(const GlobalAlias &A, const Constant &C);
- void visitAliaseeSubExpr(SmallPtrSet<const GlobalAlias *, 4> &Visited,
+ void visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias *> &Visited,
const GlobalAlias &A, const Constant &C);
void visitNamedMDNode(const NamedMDNode &NMD);
void visitMDNode(MDNode &MD, Function *F);
@@ -269,6 +269,8 @@ private:
SmallVectorImpl<const MDNode *> &Requirements);
void visitFunction(const Function &F);
void visitBasicBlock(BasicBlock &BB);
+ void visitRangeMetadata(Instruction& I, MDNode* Range, Type* Ty);
+
// InstVisitor overrides...
using InstVisitor<Verifier>::visit;
@@ -375,11 +377,13 @@ void Verifier::visit(Instruction &I) {
void Verifier::visitGlobalValue(const GlobalValue &GV) {
- Assert1(!GV.isDeclaration() || GV.isMaterializable() ||
- GV.hasExternalLinkage() || GV.hasExternalWeakLinkage(),
+ Assert1(!GV.isDeclaration() || GV.hasExternalLinkage() ||
+ GV.hasExternalWeakLinkage(),
"Global is external, but doesn't have external or weak linkage!",
&GV);
+ Assert1(GV.getAlignment() <= Value::MaximumAlignment,
+ "huge alignment values are unsupported", &GV);
Assert1(!GV.hasAppendingLinkage() || isa<GlobalVariable>(GV),
"Only global variables can have appending linkage!", &GV);
@@ -476,7 +480,7 @@ void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
while (!WorkStack.empty()) {
const Value *V = WorkStack.pop_back_val();
- if (!Visited.insert(V))
+ if (!Visited.insert(V).second)
continue;
if (const User *U = dyn_cast<User>(V)) {
@@ -500,13 +504,13 @@ void Verifier::visitAliaseeSubExpr(const GlobalAlias &GA, const Constant &C) {
visitAliaseeSubExpr(Visited, GA, C);
}
-void Verifier::visitAliaseeSubExpr(SmallPtrSet<const GlobalAlias *, 4> &Visited,
+void Verifier::visitAliaseeSubExpr(SmallPtrSetImpl<const GlobalAlias*> &Visited,
const GlobalAlias &GA, const Constant &C) {
if (const auto *GV = dyn_cast<GlobalValue>(&C)) {
Assert1(!GV->isDeclaration(), "Alias must point to a definition", &GA);
if (const auto *GA2 = dyn_cast<GlobalAlias>(GV)) {
- Assert1(Visited.insert(GA2), "Aliases cannot form a cycle", &GA);
+ Assert1(Visited.insert(GA2).second, "Aliases cannot form a cycle", &GA);
Assert1(!GA2->mayBeOverridden(), "Alias cannot point to a weak alias",
&GA);
@@ -564,7 +568,7 @@ void Verifier::visitNamedMDNode(const NamedMDNode &NMD) {
void Verifier::visitMDNode(MDNode &MD, Function *F) {
// Only visit each node once. Metadata can be mutually recursive, so this
// avoids infinite recursion here, as well as being an optimization.
- if (!MDNodes.insert(&MD))
+ if (!MDNodes.insert(&MD).second)
return;
for (unsigned i = 0, e = MD.getNumOperands(); i != e; ++i) {
@@ -605,11 +609,10 @@ void Verifier::visitComdat(const Comdat &C) {
Assert1(GV,
"comdat selection kind requires a global value with the same name",
&C);
- // The Module is invalid if the GlobalValue has local linkage. Allowing
- // otherwise opens us up to seeing the underling global value get renamed if
- // collisions occur.
+ // The Module is invalid if the GlobalValue has private linkage. Entities
+ // with private linkage don't have entries in the symbol table.
if (GV)
- Assert1(!GV->hasLocalLinkage(), "comdat global value has local linkage",
+ Assert1(!GV->hasPrivateLinkage(), "comdat global value has private linkage",
GV);
}
@@ -672,24 +675,23 @@ Verifier::visitModuleFlag(const MDNode *Op,
// constant int), the flag ID (an MDString), and the value.
Assert1(Op->getNumOperands() == 3,
"incorrect number of operands in module flag", Op);
- ConstantInt *Behavior = dyn_cast<ConstantInt>(Op->getOperand(0));
+ Module::ModFlagBehavior MFB;
+ if (!Module::isValidModFlagBehavior(Op->getOperand(0), MFB)) {
+ Assert1(
+ dyn_cast<ConstantInt>(Op->getOperand(0)),
+ "invalid behavior operand in module flag (expected constant integer)",
+ Op->getOperand(0));
+ Assert1(false,
+ "invalid behavior operand in module flag (unexpected constant)",
+ Op->getOperand(0));
+ }
MDString *ID = dyn_cast<MDString>(Op->getOperand(1));
- Assert1(Behavior,
- "invalid behavior operand in module flag (expected constant integer)",
- Op->getOperand(0));
- unsigned BehaviorValue = Behavior->getZExtValue();
Assert1(ID,
"invalid ID operand in module flag (expected metadata string)",
Op->getOperand(1));
// Sanity check the values for behaviors with additional requirements.
- switch (BehaviorValue) {
- default:
- Assert1(false,
- "invalid behavior operand in module flag (unexpected constant)",
- Op->getOperand(0));
- break;
-
+ switch (MFB) {
case Module::Error:
case Module::Warning:
case Module::Override:
@@ -725,7 +727,7 @@ Verifier::visitModuleFlag(const MDNode *Op,
}
// Unless this is a "requires" flag, check the ID is unique.
- if (BehaviorValue != Module::Require) {
+ if (MFB != Module::Require) {
bool Inserted = SeenIDs.insert(std::make_pair(ID, Op)).second;
Assert1(Inserted,
"module flag identifiers must be unique (or of 'require' type)",
@@ -1054,20 +1056,19 @@ void Verifier::visitFunction(const Function &F) {
"Attribute 'builtin' can only be applied to a callsite.", &F);
// Check that this function meets the restrictions on this calling convention.
+ // Sometimes varargs is used for perfectly forwarding thunks, so some of these
+ // restrictions can be lifted.
switch (F.getCallingConv()) {
default:
- break;
case CallingConv::C:
break;
case CallingConv::Fast:
case CallingConv::Cold:
- case CallingConv::X86_FastCall:
- case CallingConv::X86_ThisCall:
case CallingConv::Intel_OCL_BI:
case CallingConv::PTX_Kernel:
case CallingConv::PTX_Device:
- Assert1(!F.isVarArg(),
- "Varargs functions must have C calling conventions!", &F);
+ Assert1(!F.isVarArg(), "Calling convention does not support varargs or "
+ "perfect forwarding!", &F);
break;
}
@@ -1175,6 +1176,12 @@ void Verifier::visitBasicBlock(BasicBlock &BB) {
}
}
}
+
+ // Check that all instructions have their parent pointers set up correctly.
+ for (auto &I : BB)
+ {
+ Assert(I.getParent() == &BB, "Instruction has bogus parent pointer!");
+ }
}
void Verifier::visitTerminatorInst(TerminatorInst &I) {
@@ -1217,7 +1224,7 @@ void Verifier::visitSwitchInst(SwitchInst &SI) {
for (SwitchInst::CaseIt i = SI.case_begin(), e = SI.case_end(); i != e; ++i) {
Assert1(i.getCaseValue()->getType() == SwitchTy,
"Switch constants must all be same type as switch value!", &SI);
- Assert2(Constants.insert(i.getCaseValue()),
+ Assert2(Constants.insert(i.getCaseValue()).second,
"Duplicate integer as switch case", &SI, i.getCaseValue());
}
@@ -1886,12 +1893,63 @@ static bool isContiguous(const ConstantRange &A, const ConstantRange &B) {
return A.getUpper() == B.getLower() || A.getLower() == B.getUpper();
}
+void Verifier::visitRangeMetadata(Instruction& I,
+ MDNode* Range, Type* Ty) {
+ assert(Range &&
+ Range == I.getMetadata(LLVMContext::MD_range) &&
+ "precondition violation");
+
+ unsigned NumOperands = Range->getNumOperands();
+ Assert1(NumOperands % 2 == 0, "Unfinished range!", Range);
+ unsigned NumRanges = NumOperands / 2;
+ Assert1(NumRanges >= 1, "It should have at least one range!", Range);
+
+ ConstantRange LastRange(1); // Dummy initial value
+ for (unsigned i = 0; i < NumRanges; ++i) {
+ ConstantInt *Low = dyn_cast<ConstantInt>(Range->getOperand(2*i));
+ Assert1(Low, "The lower limit must be an integer!", Low);
+ ConstantInt *High = dyn_cast<ConstantInt>(Range->getOperand(2*i + 1));
+ Assert1(High, "The upper limit must be an integer!", High);
+ Assert1(High->getType() == Low->getType() &&
+ High->getType() == Ty, "Range types must match instruction type!",
+ &I);
+
+ APInt HighV = High->getValue();
+ APInt LowV = Low->getValue();
+ ConstantRange CurRange(LowV, HighV);
+ Assert1(!CurRange.isEmptySet() && !CurRange.isFullSet(),
+ "Range must not be empty!", Range);
+ if (i != 0) {
+ Assert1(CurRange.intersectWith(LastRange).isEmptySet(),
+ "Intervals are overlapping", Range);
+ Assert1(LowV.sgt(LastRange.getLower()), "Intervals are not in order",
+ Range);
+ Assert1(!isContiguous(CurRange, LastRange), "Intervals are contiguous",
+ Range);
+ }
+ LastRange = ConstantRange(LowV, HighV);
+ }
+ if (NumRanges > 2) {
+ APInt FirstLow =
+ dyn_cast<ConstantInt>(Range->getOperand(0))->getValue();
+ APInt FirstHigh =
+ dyn_cast<ConstantInt>(Range->getOperand(1))->getValue();
+ ConstantRange FirstRange(FirstLow, FirstHigh);
+ Assert1(FirstRange.intersectWith(LastRange).isEmptySet(),
+ "Intervals are overlapping", Range);
+ Assert1(!isContiguous(FirstRange, LastRange), "Intervals are contiguous",
+ Range);
+ }
+}
+
void Verifier::visitLoadInst(LoadInst &LI) {
PointerType *PTy = dyn_cast<PointerType>(LI.getOperand(0)->getType());
Assert1(PTy, "Load operand must be a pointer.", &LI);
Type *ElTy = PTy->getElementType();
Assert2(ElTy == LI.getType(),
"Load result type does not match pointer operand type!", &LI, ElTy);
+ Assert1(LI.getAlignment() <= Value::MaximumAlignment,
+ "huge alignment values are unsupported", &LI);
if (LI.isAtomic()) {
Assert1(LI.getOrdering() != Release && LI.getOrdering() != AcquireRelease,
"Load cannot have Release ordering", &LI);
@@ -1911,52 +1969,6 @@ void Verifier::visitLoadInst(LoadInst &LI) {
"Non-atomic load cannot have SynchronizationScope specified", &LI);
}
- if (MDNode *Range = LI.getMetadata(LLVMContext::MD_range)) {
- unsigned NumOperands = Range->getNumOperands();
- Assert1(NumOperands % 2 == 0, "Unfinished range!", Range);
- unsigned NumRanges = NumOperands / 2;
- Assert1(NumRanges >= 1, "It should have at least one range!", Range);
-
- ConstantRange LastRange(1); // Dummy initial value
- for (unsigned i = 0; i < NumRanges; ++i) {
- ConstantInt *Low = dyn_cast<ConstantInt>(Range->getOperand(2*i));
- Assert1(Low, "The lower limit must be an integer!", Low);
- ConstantInt *High = dyn_cast<ConstantInt>(Range->getOperand(2*i + 1));
- Assert1(High, "The upper limit must be an integer!", High);
- Assert1(High->getType() == Low->getType() &&
- High->getType() == ElTy, "Range types must match load type!",
- &LI);
-
- APInt HighV = High->getValue();
- APInt LowV = Low->getValue();
- ConstantRange CurRange(LowV, HighV);
- Assert1(!CurRange.isEmptySet() && !CurRange.isFullSet(),
- "Range must not be empty!", Range);
- if (i != 0) {
- Assert1(CurRange.intersectWith(LastRange).isEmptySet(),
- "Intervals are overlapping", Range);
- Assert1(LowV.sgt(LastRange.getLower()), "Intervals are not in order",
- Range);
- Assert1(!isContiguous(CurRange, LastRange), "Intervals are contiguous",
- Range);
- }
- LastRange = ConstantRange(LowV, HighV);
- }
- if (NumRanges > 2) {
- APInt FirstLow =
- dyn_cast<ConstantInt>(Range->getOperand(0))->getValue();
- APInt FirstHigh =
- dyn_cast<ConstantInt>(Range->getOperand(1))->getValue();
- ConstantRange FirstRange(FirstLow, FirstHigh);
- Assert1(FirstRange.intersectWith(LastRange).isEmptySet(),
- "Intervals are overlapping", Range);
- Assert1(!isContiguous(FirstRange, LastRange), "Intervals are contiguous",
- Range);
- }
-
-
- }
-
visitInstruction(LI);
}
@@ -1967,6 +1979,8 @@ void Verifier::visitStoreInst(StoreInst &SI) {
Assert2(ElTy == SI.getOperand(0)->getType(),
"Stored value type does not match pointer operand type!",
&SI, ElTy);
+ Assert1(SI.getAlignment() <= Value::MaximumAlignment,
+ "huge alignment values are unsupported", &SI);
if (SI.isAtomic()) {
Assert1(SI.getOrdering() != Acquire && SI.getOrdering() != AcquireRelease,
"Store cannot have Acquire ordering", &SI);
@@ -1998,6 +2012,8 @@ void Verifier::visitAllocaInst(AllocaInst &AI) {
&AI);
Assert1(AI.getArraySize()->getType()->isIntegerTy(),
"Alloca array size must have integer type", &AI);
+ Assert1(AI.getAlignment() <= Value::MaximumAlignment,
+ "huge alignment values are unsupported", &AI);
visitInstruction(AI);
}
@@ -2207,11 +2223,15 @@ void Verifier::visitInstruction(Instruction &I) {
if (Function *F = dyn_cast<Function>(I.getOperand(i))) {
// Check to make sure that the "address of" an intrinsic function is never
// taken.
- Assert1(!F->isIntrinsic() || i == (isa<CallInst>(I) ? e-1 : 0),
+ Assert1(!F->isIntrinsic() || i == (isa<CallInst>(I) ? e-1 :
+ isa<InvokeInst>(I) ? e-3 : 0),
"Cannot take the address of an intrinsic!", &I);
Assert1(!F->isIntrinsic() || isa<CallInst>(I) ||
- F->getIntrinsicID() == Intrinsic::donothing,
- "Cannot invoke an intrinsinc other than donothing", &I);
+ F->getIntrinsicID() == Intrinsic::donothing ||
+ F->getIntrinsicID() == Intrinsic::experimental_patchpoint_void ||
+ F->getIntrinsicID() == Intrinsic::experimental_patchpoint_i64,
+ "Cannot invoke an intrinsinc other than"
+ " donothing or patchpoint", &I);
Assert1(F->getParent() == M, "Referencing function in another module!",
&I);
} else if (BasicBlock *OpBB = dyn_cast<BasicBlock>(I.getOperand(i))) {
@@ -2239,7 +2259,7 @@ void Verifier::visitInstruction(Instruction &I) {
while (!Stack.empty()) {
const ConstantExpr *V = Stack.pop_back_val();
- if (!Visited.insert(V))
+ if (!Visited.insert(V).second)
continue;
VerifyConstantExprBitcastType(V);
@@ -2267,9 +2287,19 @@ void Verifier::visitInstruction(Instruction &I) {
}
}
- MDNode *MD = I.getMetadata(LLVMContext::MD_range);
- Assert1(!MD || isa<LoadInst>(I) || isa<CallInst>(I) || isa<InvokeInst>(I),
- "Ranges are only for loads, calls and invokes!", &I);
+ if (MDNode *Range = I.getMetadata(LLVMContext::MD_range)) {
+ Assert1(isa<LoadInst>(I) || isa<CallInst>(I) || isa<InvokeInst>(I),
+ "Ranges are only for loads, calls and invokes!", &I);
+ visitRangeMetadata(I, Range, I.getType());
+ }
+
+ if (I.getMetadata(LLVMContext::MD_nonnull)) {
+ Assert1(I.getType()->isPointerTy(),
+ "nonnull applies only to pointer types", &I);
+ Assert1(isa<LoadInst>(I),
+ "nonnull applies only to load instructions, use attributes"
+ " for calls or invokes", &I);
+ }
InstsInThisBlock.insert(&I);
}
@@ -2608,7 +2638,7 @@ bool llvm::verifyModule(const Module &M, raw_ostream *OS) {
bool Broken = false;
for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I)
- if (!I->isDeclaration())
+ if (!I->isDeclaration() && !I->isMaterializable())
Broken |= !V.verify(*I);
// Note that this function's return value is inverted from what you would