aboutsummaryrefslogtreecommitdiffstats
path: root/lib/IR
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2014-02-11 20:01:10 -0800
committerStephen Hines <srhines@google.com>2014-02-11 20:01:10 -0800
commitce9904c6ea8fd669978a8eefb854b330eb9828ff (patch)
tree2418ee2e96ea220977c8fb74959192036ab5b133 /lib/IR
parentc27b10b198c1d9e9b51f2303994313ec2778edd7 (diff)
parentdbb832b83351cec97b025b61c26536ef50c3181c (diff)
downloadexternal_llvm-ce9904c6ea8fd669978a8eefb854b330eb9828ff.zip
external_llvm-ce9904c6ea8fd669978a8eefb854b330eb9828ff.tar.gz
external_llvm-ce9904c6ea8fd669978a8eefb854b330eb9828ff.tar.bz2
Merge remote-tracking branch 'upstream/release_34' into merge-20140211
Conflicts: lib/Linker/LinkModules.cpp lib/Support/Unix/Signals.inc Change-Id: Ia54f291fa5dc828052d2412736e8495c1282aa64
Diffstat (limited to 'lib/IR')
-rw-r--r--lib/IR/AsmWriter.cpp9
-rw-r--r--lib/IR/AttributeImpl.h3
-rw-r--r--lib/IR/Attributes.cpp7
-rw-r--r--lib/IR/AutoUpgrade.cpp108
-rw-r--r--lib/IR/CMakeLists.txt3
-rw-r--r--lib/IR/ConstantFold.cpp80
-rw-r--r--lib/IR/Constants.cpp27
-rw-r--r--lib/IR/Core.cpp114
-rw-r--r--lib/IR/DIBuilder.cpp358
-rw-r--r--lib/IR/DataLayout.cpp7
-rw-r--r--lib/IR/DebugInfo.cpp478
-rw-r--r--lib/IR/Function.cpp48
-rw-r--r--lib/IR/GCOV.cpp287
-rw-r--r--lib/IR/Globals.cpp16
-rw-r--r--lib/IR/Instruction.cpp25
-rw-r--r--lib/IR/Instructions.cpp328
-rw-r--r--lib/IR/LLVMContextImpl.h5
-rw-r--r--lib/IR/LegacyPassManager.cpp1920
-rw-r--r--lib/IR/Metadata.cpp4
-rw-r--r--lib/IR/Module.cpp42
-rw-r--r--lib/IR/PassManager.cpp1983
-rw-r--r--lib/IR/Type.cpp6
-rw-r--r--lib/IR/TypeFinder.cpp31
-rw-r--r--lib/IR/Value.cpp47
-rw-r--r--lib/IR/ValueTypes.cpp10
-rw-r--r--lib/IR/Verifier.cpp174
26 files changed, 3530 insertions, 2590 deletions
diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp
index f275305..7decffd 100644
--- a/lib/IR/AsmWriter.cpp
+++ b/lib/IR/AsmWriter.cpp
@@ -74,6 +74,8 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
default: Out << "cc" << cc; break;
case CallingConv::Fast: Out << "fastcc"; break;
case CallingConv::Cold: Out << "coldcc"; break;
+ case CallingConv::WebKit_JS: Out << "webkit_jscc"; break;
+ case CallingConv::AnyReg: Out << "anyregcc"; break;
case CallingConv::X86_StdCall: Out << "x86_stdcallcc"; break;
case CallingConv::X86_FastCall: Out << "x86_fastcallcc"; break;
case CallingConv::X86_ThisCall: Out << "x86_thiscallcc"; break;
@@ -1394,9 +1396,6 @@ static void PrintLinkage(GlobalValue::LinkageTypes LT,
case GlobalValue::InternalLinkage: Out << "internal "; break;
case GlobalValue::LinkOnceAnyLinkage: Out << "linkonce "; break;
case GlobalValue::LinkOnceODRLinkage: Out << "linkonce_odr "; break;
- case GlobalValue::LinkOnceODRAutoHideLinkage:
- Out << "linkonce_odr_auto_hide ";
- break;
case GlobalValue::WeakAnyLinkage: Out << "weak "; break;
case GlobalValue::WeakODRLinkage: Out << "weak_odr "; break;
case GlobalValue::CommonLinkage: Out << "common "; break;
@@ -1647,6 +1646,10 @@ void AssemblyWriter::printFunction(const Function *F) {
Out << " align " << F->getAlignment();
if (F->hasGC())
Out << " gc \"" << F->getGC() << '"';
+ if (F->hasPrefixData()) {
+ Out << " prefix ";
+ writeOperand(F->getPrefixData(), true);
+ }
if (F->isDeclaration()) {
Out << '\n';
} else {
diff --git a/lib/IR/AttributeImpl.h b/lib/IR/AttributeImpl.h
index 9da3f96..ea954ac 100644
--- a/lib/IR/AttributeImpl.h
+++ b/lib/IR/AttributeImpl.h
@@ -94,6 +94,7 @@ public:
/// attribute enties, which are for target-dependent attributes.
class EnumAttributeImpl : public AttributeImpl {
+ virtual void anchor();
Attribute::AttrKind Kind;
protected:
@@ -108,6 +109,7 @@ public:
};
class AlignAttributeImpl : public EnumAttributeImpl {
+ virtual void anchor();
unsigned Align;
public:
@@ -122,6 +124,7 @@ public:
};
class StringAttributeImpl : public AttributeImpl {
+ virtual void anchor();
std::string Kind;
std::string Val;
diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp
index f466d16..0f2b7a0 100644
--- a/lib/IR/Attributes.cpp
+++ b/lib/IR/Attributes.cpp
@@ -196,6 +196,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "noreturn";
if (hasAttribute(Attribute::NoUnwind))
return "nounwind";
+ if (hasAttribute(Attribute::OptimizeNone))
+ return "optnone";
if (hasAttribute(Attribute::OptimizeForSize))
return "optsize";
if (hasAttribute(Attribute::ReadNone))
@@ -284,7 +286,11 @@ bool Attribute::operator<(Attribute A) const {
// AttributeImpl Definition
//===----------------------------------------------------------------------===//
+// Pin the vtabels to this file.
AttributeImpl::~AttributeImpl() {}
+void EnumAttributeImpl::anchor() {}
+void AlignAttributeImpl::anchor() {}
+void StringAttributeImpl::anchor() {}
bool AttributeImpl::hasAttribute(Attribute::AttrKind A) const {
if (isStringAttribute()) return false;
@@ -381,6 +387,7 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {
case Attribute::Returned: return 1ULL << 39;
case Attribute::Cold: return 1ULL << 40;
case Attribute::Builtin: return 1ULL << 41;
+ case Attribute::OptimizeNone: return 1ULL << 42;
}
llvm_unreachable("Unsupported attribute type");
}
diff --git a/lib/IR/AutoUpgrade.cpp b/lib/IR/AutoUpgrade.cpp
index a4f5289..d12bf7b 100644
--- a/lib/IR/AutoUpgrade.cpp
+++ b/lib/IR/AutoUpgrade.cpp
@@ -12,6 +12,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/AutoUpgrade.h"
+#include "llvm/DebugInfo.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
@@ -88,6 +89,20 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
}
break;
}
+ case 'o':
+ // We only need to change the name to match the mangling including the
+ // address space.
+ if (F->arg_size() == 2 && Name.startswith("objectsize.")) {
+ Type *Tys[2] = { F->getReturnType(), F->arg_begin()->getType() };
+ if (F->getName() != Intrinsic::getName(Intrinsic::objectsize, Tys)) {
+ F->setName(Name + ".old");
+ NewFn = Intrinsic::getDeclaration(F->getParent(),
+ Intrinsic::objectsize, Tys);
+ return true;
+ }
+ }
+ break;
+
case 'x': {
if (Name.startswith("x86.sse2.pcmpeq.") ||
Name.startswith("x86.sse2.pcmpgt.") ||
@@ -97,6 +112,7 @@ static bool UpgradeIntrinsicFunction1(Function *F, Function *&NewFn) {
Name == "x86.avx.movnt.dq.256" ||
Name == "x86.avx.movnt.pd.256" ||
Name == "x86.avx.movnt.ps.256" ||
+ Name == "x86.sse42.crc32.64.8" ||
(Name.startswith("x86.xop.vpcom") && F->arg_size() == 2)) {
NewFn = 0;
return true;
@@ -257,6 +273,12 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
Function *VPCOM = Intrinsic::getDeclaration(F->getParent(), intID);
Rep = Builder.CreateCall3(VPCOM, CI->getArgOperand(0),
CI->getArgOperand(1), Builder.getInt8(Imm));
+ } else if (Name == "llvm.x86.sse42.crc32.64.8") {
+ Function *CRC32 = Intrinsic::getDeclaration(F->getParent(),
+ Intrinsic::x86_sse42_crc32_32_8);
+ Value *Trunc0 = Builder.CreateTrunc(CI->getArgOperand(0), Type::getInt32Ty(C));
+ Rep = Builder.CreateCall2(CRC32, Trunc0, CI->getArgOperand(1));
+ Rep = Builder.CreateZExt(Rep, CI->getType(), "");
} else {
bool PD128 = false, PD256 = false, PS128 = false, PS256 = false;
if (Name == "llvm.x86.avx.vpermil.pd.256")
@@ -317,6 +339,14 @@ void llvm::UpgradeIntrinsicCall(CallInst *CI, Function *NewFn) {
CI->eraseFromParent();
return;
+ case Intrinsic::objectsize:
+ CI->replaceAllUsesWith(Builder.CreateCall2(NewFn,
+ CI->getArgOperand(0),
+ CI->getArgOperand(1),
+ Name));
+ 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),
@@ -391,3 +421,81 @@ void llvm::UpgradeCallsToIntrinsic(Function* F) {
}
}
+void llvm::UpgradeInstWithTBAATag(Instruction *I) {
+ MDNode *MD = I->getMetadata(LLVMContext::MD_tbaa);
+ assert(MD && "UpgradeInstWithTBAATag should have a TBAA tag");
+ // Check if the tag uses struct-path aware TBAA format.
+ if (isa<MDNode>(MD->getOperand(0)) && MD->getNumOperands() >= 3)
+ return;
+
+ if (MD->getNumOperands() == 3) {
+ Value *Elts[] = {
+ MD->getOperand(0),
+ MD->getOperand(1)
+ };
+ MDNode *ScalarType = MDNode::get(I->getContext(), Elts);
+ // Create a MDNode <ScalarType, ScalarType, offset 0, const>
+ Value *Elts2[] = {
+ ScalarType, ScalarType,
+ Constant::getNullValue(Type::getInt64Ty(I->getContext())),
+ MD->getOperand(2)
+ };
+ I->setMetadata(LLVMContext::MD_tbaa, MDNode::get(I->getContext(), Elts2));
+ } else {
+ // Create a MDNode <MD, MD, offset 0>
+ Value *Elts[] = {MD, MD,
+ Constant::getNullValue(Type::getInt64Ty(I->getContext()))};
+ I->setMetadata(LLVMContext::MD_tbaa, MDNode::get(I->getContext(), Elts));
+ }
+}
+
+Instruction *llvm::UpgradeBitCastInst(unsigned Opc, Value *V, Type *DestTy,
+ Instruction *&Temp) {
+ if (Opc != Instruction::BitCast)
+ return 0;
+
+ Temp = 0;
+ Type *SrcTy = V->getType();
+ if (SrcTy->isPtrOrPtrVectorTy() && DestTy->isPtrOrPtrVectorTy() &&
+ SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace()) {
+ LLVMContext &Context = V->getContext();
+
+ // We have no information about target data layout, so we assume that
+ // the maximum pointer size is 64bit.
+ Type *MidTy = Type::getInt64Ty(Context);
+ Temp = CastInst::Create(Instruction::PtrToInt, V, MidTy);
+
+ return CastInst::Create(Instruction::IntToPtr, Temp, DestTy);
+ }
+
+ return 0;
+}
+
+Value *llvm::UpgradeBitCastExpr(unsigned Opc, Constant *C, Type *DestTy) {
+ if (Opc != Instruction::BitCast)
+ return 0;
+
+ Type *SrcTy = C->getType();
+ if (SrcTy->isPtrOrPtrVectorTy() && DestTy->isPtrOrPtrVectorTy() &&
+ SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace()) {
+ LLVMContext &Context = C->getContext();
+
+ // We have no information about target data layout, so we assume that
+ // the maximum pointer size is 64bit.
+ Type *MidTy = Type::getInt64Ty(Context);
+
+ return ConstantExpr::getIntToPtr(ConstantExpr::getPtrToInt(C, MidTy),
+ DestTy);
+ }
+
+ return 0;
+}
+
+/// Check the debug info version number, if it is out-dated, drop the debug
+/// info. Return true if module is modified.
+bool llvm::UpgradeDebugInfo(Module &M) {
+ if (getDebugMetadataVersionFromModule(M) == DEBUG_METADATA_VERSION)
+ return false;
+
+ return StripDebugInfo(M);
+}
diff --git a/lib/IR/CMakeLists.txt b/lib/IR/CMakeLists.txt
index c2a4ee3..581946c 100644
--- a/lib/IR/CMakeLists.txt
+++ b/lib/IR/CMakeLists.txt
@@ -6,10 +6,10 @@ add_llvm_library(LLVMCore
ConstantFold.cpp
Constants.cpp
Core.cpp
+ DIBuilder.cpp
DataLayout.cpp
DebugInfo.cpp
DebugLoc.cpp
- DIBuilder.cpp
Dominators.cpp
Function.cpp
GCOV.cpp
@@ -23,6 +23,7 @@ add_llvm_library(LLVMCore
LLVMContext.cpp
LLVMContextImpl.cpp
LeakDetector.cpp
+ LegacyPassManager.cpp
Metadata.cpp
Module.cpp
Pass.cpp
diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp
index 8c5a983..f5e225c 100644
--- a/lib/IR/ConstantFold.cpp
+++ b/lib/IR/ConstantFold.cpp
@@ -689,6 +689,8 @@ Constant *llvm::ConstantFoldCastInstruction(unsigned opc, Constant *V,
}
case Instruction::BitCast:
return FoldBitCast(V, DestTy);
+ case Instruction::AddrSpaceCast:
+ return 0;
}
}
@@ -1897,6 +1899,37 @@ static bool isInBoundsIndices(ArrayRef<IndexTy> Idxs) {
return true;
}
+/// \brief Test whether a given ConstantInt is in-range for a SequentialType.
+static bool isIndexInRangeOfSequentialType(const SequentialType *STy,
+ const ConstantInt *CI) {
+ if (const PointerType *PTy = dyn_cast<PointerType>(STy))
+ // Only handle pointers to sized types, not pointers to functions.
+ return PTy->getElementType()->isSized();
+
+ uint64_t NumElements = 0;
+ // Determine the number of elements in our sequential type.
+ if (const ArrayType *ATy = dyn_cast<ArrayType>(STy))
+ NumElements = ATy->getNumElements();
+ else if (const VectorType *VTy = dyn_cast<VectorType>(STy))
+ NumElements = VTy->getNumElements();
+
+ assert((isa<ArrayType>(STy) || NumElements > 0) &&
+ "didn't expect non-array type to have zero elements!");
+
+ // We cannot bounds check the index if it doesn't fit in an int64_t.
+ if (CI->getValue().getActiveBits() > 64)
+ return false;
+
+ // A negative index or an index past the end of our sequential type is
+ // considered out-of-range.
+ int64_t IndexVal = CI->getSExtValue();
+ if (IndexVal < 0 || (NumElements > 0 && (uint64_t)IndexVal >= NumElements))
+ return false;
+
+ // Otherwise, it is in-range.
+ return true;
+}
+
template<typename IndexTy>
static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
bool inBounds,
@@ -1940,7 +1973,32 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
I != E; ++I)
LastTy = *I;
- if ((LastTy && isa<SequentialType>(LastTy)) || Idx0->isNullValue()) {
+ // We cannot combine indices if doing so would take us outside of an
+ // array or vector. Doing otherwise could trick us if we evaluated such a
+ // GEP as part of a load.
+ //
+ // e.g. Consider if the original GEP was:
+ // i8* getelementptr ({ [2 x i8], i32, i8, [3 x i8] }* @main.c,
+ // i32 0, i32 0, i64 0)
+ //
+ // If we then tried to offset it by '8' to get to the third element,
+ // an i8, we should *not* get:
+ // i8* getelementptr ({ [2 x i8], i32, i8, [3 x i8] }* @main.c,
+ // i32 0, i32 0, i64 8)
+ //
+ // This GEP tries to index array element '8 which runs out-of-bounds.
+ // Subsequent evaluation would get confused and produce erroneous results.
+ //
+ // The following prohibits such a GEP from being formed by checking to see
+ // if the index is in-range with respect to an array or vector.
+ bool PerformFold = false;
+ if (Idx0->isNullValue())
+ PerformFold = true;
+ else if (SequentialType *STy = dyn_cast_or_null<SequentialType>(LastTy))
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(Idx0))
+ PerformFold = isIndexInRangeOfSequentialType(STy, CI);
+
+ if (PerformFold) {
SmallVector<Value*, 16> NewIndices;
NewIndices.reserve(Idxs.size() + CE->getNumOperands());
for (unsigned i = 1, e = CE->getNumOperands()-1; i != e; ++i)
@@ -2000,8 +2058,8 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
}
// Check to see if any array indices are not within the corresponding
- // notional array bounds. If so, try to determine if they can be factored
- // out into preceding dimensions.
+ // notional array or vector bounds. If so, try to determine if they can be
+ // factored out into preceding dimensions.
bool Unknown = false;
SmallVector<Constant *, 8> NewIdxs;
Type *Ty = C->getType();
@@ -2009,16 +2067,20 @@ static Constant *ConstantFoldGetElementPtrImpl(Constant *C,
for (unsigned i = 0, e = Idxs.size(); i != e;
Prev = Ty, Ty = cast<CompositeType>(Ty)->getTypeAtIndex(Idxs[i]), ++i) {
if (ConstantInt *CI = dyn_cast<ConstantInt>(Idxs[i])) {
- if (ArrayType *ATy = dyn_cast<ArrayType>(Ty))
- if (ATy->getNumElements() <= INT64_MAX &&
- ATy->getNumElements() != 0 &&
- CI->getSExtValue() >= (int64_t)ATy->getNumElements()) {
+ if (isa<ArrayType>(Ty) || isa<VectorType>(Ty))
+ if (CI->getSExtValue() > 0 &&
+ !isIndexInRangeOfSequentialType(cast<SequentialType>(Ty), CI)) {
if (isa<SequentialType>(Prev)) {
// It's out of range, but we can factor it into the prior
// dimension.
NewIdxs.resize(Idxs.size());
- ConstantInt *Factor = ConstantInt::get(CI->getType(),
- ATy->getNumElements());
+ uint64_t NumElements = 0;
+ if (const ArrayType *ATy = dyn_cast<ArrayType>(Ty))
+ NumElements = ATy->getNumElements();
+ else
+ NumElements = cast<VectorType>(Ty)->getNumElements();
+
+ ConstantInt *Factor = ConstantInt::get(CI->getType(), NumElements);
NewIdxs[i] = ConstantExpr::getSRem(CI, Factor);
Constant *PrevIdx = cast<Constant>(Idxs[i-1]);
diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp
index 9067b34..690ac59 100644
--- a/lib/IR/Constants.cpp
+++ b/lib/IR/Constants.cpp
@@ -1126,6 +1126,7 @@ getWithOperands(ArrayRef<Constant*> Ops, Type *Ty) const {
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
+ case Instruction::AddrSpaceCast:
return ConstantExpr::getCast(getOpcode(), Ops[0], Ty);
case Instruction::Select:
return ConstantExpr::getSelect(Ops[0], Ops[1], Ops[2]);
@@ -1461,6 +1462,7 @@ Constant *ConstantExpr::getCast(unsigned oc, Constant *C, Type *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);
}
}
@@ -1489,10 +1491,26 @@ Constant *ConstantExpr::getPointerCast(Constant *S, Type *Ty) {
if (Ty->isIntOrIntVectorTy())
return getPtrToInt(S, Ty);
+
+ unsigned SrcAS = S->getType()->getPointerAddressSpace();
+ if (Ty->isPtrOrPtrVectorTy() && SrcAS != Ty->getPointerAddressSpace())
+ return getAddrSpaceCast(S, Ty);
+
return getBitCast(S, Ty);
}
-Constant *ConstantExpr::getIntegerCast(Constant *C, Type *Ty,
+Constant *ConstantExpr::getPointerBitCastOrAddrSpaceCast(Constant *S,
+ Type *Ty) {
+ assert(S->getType()->isPtrOrPtrVectorTy() && "Invalid cast");
+ assert(Ty->isPtrOrPtrVectorTy() && "Invalid cast");
+
+ if (S->getType()->getPointerAddressSpace() != Ty->getPointerAddressSpace())
+ return getAddrSpaceCast(S, Ty);
+
+ return getBitCast(S, Ty);
+}
+
+Constant *ConstantExpr::getIntegerCast(Constant *C, Type *Ty,
bool isSigned) {
assert(C->getType()->isIntOrIntVectorTy() &&
Ty->isIntOrIntVectorTy() && "Invalid cast");
@@ -1662,6 +1680,13 @@ Constant *ConstantExpr::getBitCast(Constant *C, Type *DstTy) {
return getFoldedCast(Instruction::BitCast, C, DstTy);
}
+Constant *ConstantExpr::getAddrSpaceCast(Constant *C, Type *DstTy) {
+ assert(CastInst::castIsValid(Instruction::AddrSpaceCast, C, DstTy) &&
+ "Invalid constantexpr addrspacecast!");
+
+ return getFoldedCast(Instruction::AddrSpaceCast, C, DstTy);
+}
+
Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2,
unsigned Flags) {
// Check the operands for consistency first.
diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp
index 66610bd..c70f459 100644
--- a/lib/IR/Core.cpp
+++ b/lib/IR/Core.cpp
@@ -97,7 +97,7 @@ LLVMModuleRef LLVMModuleCreateWithName(const char *ModuleID) {
return wrap(new Module(ModuleID, getGlobalContext()));
}
-LLVMModuleRef LLVMModuleCreateWithNameInContext(const char *ModuleID,
+LLVMModuleRef LLVMModuleCreateWithNameInContext(const char *ModuleID,
LLVMContextRef C) {
return wrap(new Module(ModuleID, *unwrap(C)));
}
@@ -147,6 +147,16 @@ LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename,
return false;
}
+char *LLVMPrintModuleToString(LLVMModuleRef M) {
+ std::string buf;
+ raw_string_ostream os(buf);
+
+ unwrap(M)->print(os, NULL);
+ os.flush();
+
+ return strdup(buf.c_str());
+}
+
/*--.. Operations on inline assembler ......................................--*/
void LLVMSetModuleInlineAsm(LLVMModuleRef M, const char *Asm) {
unwrap(M)->setModuleInlineAsm(StringRef(Asm));
@@ -210,6 +220,20 @@ LLVMContextRef LLVMGetTypeContext(LLVMTypeRef Ty) {
return wrap(&unwrap(Ty)->getContext());
}
+void LLVMDumpType(LLVMTypeRef Ty) {
+ return unwrap(Ty)->dump();
+}
+
+char *LLVMPrintTypeToString(LLVMTypeRef Ty) {
+ std::string buf;
+ raw_string_ostream os(buf);
+
+ unwrap(Ty)->print(os);
+ os.flush();
+
+ return strdup(buf.c_str());
+}
+
/*--.. Operations on integer types .........................................--*/
LLVMTypeRef LLVMInt1TypeInContext(LLVMContextRef C) {
@@ -450,6 +474,16 @@ void LLVMDumpValue(LLVMValueRef Val) {
unwrap(Val)->dump();
}
+char* LLVMPrintValueToString(LLVMValueRef Val) {
+ std::string buf;
+ raw_string_ostream os(buf);
+
+ unwrap(Val)->print(os);
+ os.flush();
+
+ return strdup(buf.c_str());
+}
+
void LLVMReplaceAllUsesWith(LLVMValueRef OldVal, LLVMValueRef NewVal) {
unwrap(OldVal)->replaceAllUsesWith(unwrap(NewVal));
}
@@ -681,7 +715,7 @@ LLVMValueRef LLVMConstStringInContext(LLVMContextRef C, const char *Str,
return wrap(ConstantDataArray::getString(*unwrap(C), StringRef(Str, Length),
DontNullTerminate == 0));
}
-LLVMValueRef LLVMConstStructInContext(LLVMContextRef C,
+LLVMValueRef LLVMConstStructInContext(LLVMContextRef C,
LLVMValueRef *ConstantVals,
unsigned Count, LLVMBool Packed) {
Constant **Elements = unwrap<Constant>(ConstantVals, Count);
@@ -999,6 +1033,12 @@ LLVMValueRef LLVMConstBitCast(LLVMValueRef ConstantVal, LLVMTypeRef ToType) {
unwrap(ToType)));
}
+LLVMValueRef LLVMConstAddrSpaceCast(LLVMValueRef ConstantVal,
+ LLVMTypeRef ToType) {
+ return wrap(ConstantExpr::getAddrSpaceCast(unwrap<Constant>(ConstantVal),
+ unwrap(ToType)));
+}
+
LLVMValueRef LLVMConstZExtOrBitCast(LLVMValueRef ConstantVal,
LLVMTypeRef ToType) {
return wrap(ConstantExpr::getZExtOrBitCast(unwrap<Constant>(ConstantVal),
@@ -1110,8 +1150,6 @@ LLVMLinkage LLVMGetLinkage(LLVMValueRef Global) {
return LLVMLinkOnceAnyLinkage;
case GlobalValue::LinkOnceODRLinkage:
return LLVMLinkOnceODRLinkage;
- case GlobalValue::LinkOnceODRAutoHideLinkage:
- return LLVMLinkOnceODRAutoHideLinkage;
case GlobalValue::WeakAnyLinkage:
return LLVMWeakAnyLinkage;
case GlobalValue::WeakODRLinkage:
@@ -1156,7 +1194,8 @@ void LLVMSetLinkage(LLVMValueRef Global, LLVMLinkage Linkage) {
GV->setLinkage(GlobalValue::LinkOnceODRLinkage);
break;
case LLVMLinkOnceODRAutoHideLinkage:
- GV->setLinkage(GlobalValue::LinkOnceODRAutoHideLinkage);
+ DEBUG(errs() << "LLVMSetLinkage(): LLVMLinkOnceODRAutoHideLinkage is no "
+ "longer supported.");
break;
case LLVMWeakAnyLinkage:
GV->setLinkage(GlobalValue::WeakAnyLinkage);
@@ -1216,12 +1255,30 @@ void LLVMSetVisibility(LLVMValueRef Global, LLVMVisibility Viz) {
->setVisibility(static_cast<GlobalValue::VisibilityTypes>(Viz));
}
-unsigned LLVMGetAlignment(LLVMValueRef Global) {
- return unwrap<GlobalValue>(Global)->getAlignment();
+/*--.. Operations on global variables, load and store instructions .........--*/
+
+unsigned LLVMGetAlignment(LLVMValueRef V) {
+ Value *P = unwrap<Value>(V);
+ if (GlobalValue *GV = dyn_cast<GlobalValue>(P))
+ return GV->getAlignment();
+ if (LoadInst *LI = dyn_cast<LoadInst>(P))
+ return LI->getAlignment();
+ if (StoreInst *SI = dyn_cast<StoreInst>(P))
+ return SI->getAlignment();
+
+ llvm_unreachable("only GlobalValue, LoadInst and StoreInst have alignment");
}
-void LLVMSetAlignment(LLVMValueRef Global, unsigned Bytes) {
- unwrap<GlobalValue>(Global)->setAlignment(Bytes);
+void LLVMSetAlignment(LLVMValueRef V, unsigned Bytes) {
+ Value *P = unwrap<Value>(V);
+ if (GlobalValue *GV = dyn_cast<GlobalValue>(P))
+ GV->setAlignment(Bytes);
+ else if (LoadInst *LI = dyn_cast<LoadInst>(P))
+ LI->setAlignment(Bytes);
+ else if (StoreInst *SI = dyn_cast<StoreInst>(P))
+ SI->setAlignment(Bytes);
+ else
+ llvm_unreachable("only GlobalValue, LoadInst and StoreInst have alignment");
}
/*--.. Operations on global variables ......................................--*/
@@ -1553,7 +1610,7 @@ LLVMAttribute LLVMGetAttribute(LLVMValueRef Arg) {
return (LLVMAttribute)A->getParent()->getAttributes().
Raw(A->getArgNo()+1);
}
-
+
void LLVMSetParamAlignment(LLVMValueRef Arg, unsigned align) {
Argument *A = unwrap<Argument>(Arg);
@@ -1745,7 +1802,7 @@ void LLVMSetInstructionCallConv(LLVMValueRef Instr, unsigned CC) {
llvm_unreachable("LLVMSetInstructionCallConv applies only to call and invoke!");
}
-void LLVMAddInstrAttribute(LLVMValueRef Instr, unsigned index,
+void LLVMAddInstrAttribute(LLVMValueRef Instr, unsigned index,
LLVMAttribute PA) {
CallSite Call = CallSite(unwrap<Instruction>(Instr));
AttrBuilder B(PA);
@@ -1755,7 +1812,7 @@ void LLVMAddInstrAttribute(LLVMValueRef Instr, unsigned index,
index, B)));
}
-void LLVMRemoveInstrAttribute(LLVMValueRef Instr, unsigned index,
+void LLVMRemoveInstrAttribute(LLVMValueRef Instr, unsigned index,
LLVMAttribute PA) {
CallSite Call = CallSite(unwrap<Instruction>(Instr));
AttrBuilder B(PA);
@@ -1765,7 +1822,7 @@ void LLVMRemoveInstrAttribute(LLVMValueRef Instr, unsigned index,
index, B)));
}
-void LLVMSetInstrParamAlignment(LLVMValueRef Instr, unsigned index,
+void LLVMSetInstrParamAlignment(LLVMValueRef Instr, unsigned index,
unsigned align) {
CallSite Call = CallSite(unwrap<Instruction>(Instr));
AttrBuilder B;
@@ -2119,8 +2176,8 @@ LLVMValueRef LLVMBuildMalloc(LLVMBuilderRef B, LLVMTypeRef Ty,
Type* ITy = Type::getInt32Ty(unwrap(B)->GetInsertBlock()->getContext());
Constant* AllocSize = ConstantExpr::getSizeOf(unwrap(Ty));
AllocSize = ConstantExpr::getTruncOrBitCast(AllocSize, ITy);
- Instruction* Malloc = CallInst::CreateMalloc(unwrap(B)->GetInsertBlock(),
- ITy, unwrap(Ty), AllocSize,
+ Instruction* Malloc = CallInst::CreateMalloc(unwrap(B)->GetInsertBlock(),
+ ITy, unwrap(Ty), AllocSize,
0, 0, "");
return wrap(unwrap(B)->Insert(Malloc, Twine(Name)));
}
@@ -2130,8 +2187,8 @@ LLVMValueRef LLVMBuildArrayMalloc(LLVMBuilderRef B, LLVMTypeRef Ty,
Type* ITy = Type::getInt32Ty(unwrap(B)->GetInsertBlock()->getContext());
Constant* AllocSize = ConstantExpr::getSizeOf(unwrap(Ty));
AllocSize = ConstantExpr::getTruncOrBitCast(AllocSize, ITy);
- Instruction* Malloc = CallInst::CreateMalloc(unwrap(B)->GetInsertBlock(),
- ITy, unwrap(Ty), AllocSize,
+ Instruction* Malloc = CallInst::CreateMalloc(unwrap(B)->GetInsertBlock(),
+ ITy, unwrap(Ty), AllocSize,
unwrap(Val), 0, "");
return wrap(unwrap(B)->Insert(Malloc, Twine(Name)));
}
@@ -2157,7 +2214,7 @@ LLVMValueRef LLVMBuildLoad(LLVMBuilderRef B, LLVMValueRef PointerVal,
return wrap(unwrap(B)->CreateLoad(unwrap(PointerVal), Name));
}
-LLVMValueRef LLVMBuildStore(LLVMBuilderRef B, LLVMValueRef Val,
+LLVMValueRef LLVMBuildStore(LLVMBuilderRef B, LLVMValueRef Val,
LLVMValueRef PointerVal) {
return wrap(unwrap(B)->CreateStore(unwrap(Val), unwrap(PointerVal)));
}
@@ -2267,6 +2324,11 @@ LLVMValueRef LLVMBuildBitCast(LLVMBuilderRef B, LLVMValueRef Val,
return wrap(unwrap(B)->CreateBitCast(unwrap(Val), unwrap(DestTy), Name));
}
+LLVMValueRef LLVMBuildAddrSpaceCast(LLVMBuilderRef B, LLVMValueRef Val,
+ LLVMTypeRef DestTy, const char *Name) {
+ return wrap(unwrap(B)->CreateAddrSpaceCast(unwrap(Val), unwrap(DestTy), Name));
+}
+
LLVMValueRef LLVMBuildZExtOrBitCast(LLVMBuilderRef B, LLVMValueRef Val,
LLVMTypeRef DestTy, const char *Name) {
return wrap(unwrap(B)->CreateZExtOrBitCast(unwrap(Val), unwrap(DestTy),
@@ -2396,9 +2458,9 @@ LLVMValueRef LLVMBuildPtrDiff(LLVMBuilderRef B, LLVMValueRef LHS,
return wrap(unwrap(B)->CreatePtrDiff(unwrap(LHS), unwrap(RHS), Name));
}
-LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op,
- LLVMValueRef PTR, LLVMValueRef Val,
- LLVMAtomicOrdering ordering,
+LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op,
+ LLVMValueRef PTR, LLVMValueRef Val,
+ LLVMAtomicOrdering ordering,
LLVMBool singleThread) {
AtomicRMWInst::BinOp intop;
switch (op) {
@@ -2421,14 +2483,14 @@ LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op,
case LLVMAtomicOrderingMonotonic: intordering = Monotonic; break;
case LLVMAtomicOrderingAcquire: intordering = Acquire; break;
case LLVMAtomicOrderingRelease: intordering = Release; break;
- case LLVMAtomicOrderingAcquireRelease:
- intordering = AcquireRelease;
+ case LLVMAtomicOrderingAcquireRelease:
+ intordering = AcquireRelease;
break;
- case LLVMAtomicOrderingSequentiallyConsistent:
- intordering = SequentiallyConsistent;
+ case LLVMAtomicOrderingSequentiallyConsistent:
+ intordering = SequentiallyConsistent;
break;
}
- return wrap(unwrap(B)->CreateAtomicRMW(intop, unwrap(PTR), unwrap(Val),
+ return wrap(unwrap(B)->CreateAtomicRMW(intop, unwrap(PTR), unwrap(Val),
intordering, singleThread ? SingleThread : CrossThread));
}
diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp
index 3005f77..c4a9f41 100644
--- a/lib/IR/DIBuilder.cpp
+++ b/lib/IR/DIBuilder.cpp
@@ -30,17 +30,24 @@ static Constant *GetTagConstant(LLVMContext &VMContext, unsigned Tag) {
}
DIBuilder::DIBuilder(Module &m)
- : M(m), VMContext(M.getContext()), TempEnumTypes(0),
- TempRetainTypes(0), TempSubprograms(0), TempGVs(0), DeclareFn(0),
- ValueFn(0)
-{}
+ : M(m), VMContext(M.getContext()), TempEnumTypes(0), TempRetainTypes(0),
+ TempSubprograms(0), TempGVs(0), DeclareFn(0), ValueFn(0) {}
/// finalize - Construct any deferred debug info descriptors.
void DIBuilder::finalize() {
DIArray Enums = getOrCreateArray(AllEnumTypes);
DIType(TempEnumTypes).replaceAllUsesWith(Enums);
- DIArray RetainTypes = getOrCreateArray(AllRetainTypes);
+ SmallVector<Value *, 16> RetainValues;
+ // Declarations and definitions of the same type may be retained. Some
+ // clients RAUW these pairs, leaving duplicates in the retained types
+ // list. Use a set to remove the duplicates while we transform the
+ // TrackingVHs back into Values.
+ SmallPtrSet<Value *, 16> RetainSet;
+ for (unsigned I = 0, E = AllRetainTypes.size(); I < E; I++)
+ if (RetainSet.insert(AllRetainTypes[I]))
+ RetainValues.push_back(AllRetainTypes[I]);
+ DIArray RetainTypes = getOrCreateArray(RetainValues);
DIType(TempRetainTypes).replaceAllUsesWith(RetainTypes);
DIArray SPs = getOrCreateArray(AllSubprograms);
@@ -79,7 +86,7 @@ static MDNode *createFilePathPair(LLVMContext &VMContext, StringRef Filename,
assert(!Filename.empty() && "Unable to create file without name");
Value *Pair[] = {
MDString::get(VMContext, Filename),
- MDString::get(VMContext, Directory),
+ MDString::get(VMContext, Directory)
};
return MDNode::get(VMContext, Pair);
}
@@ -274,7 +281,7 @@ DIDerivedType DIBuilder::createQualifiedType(unsigned Tag, DIType FromTy) {
ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align
ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags
- FromTy
+ FromTy.getRef()
};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
@@ -294,7 +301,7 @@ DIBuilder::createPointerType(DIType PointeeTy, uint64_t SizeInBits,
ConstantInt::get(Type::getInt64Ty(VMContext), AlignInBits),
ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags
- PointeeTy
+ PointeeTy.getRef()
};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
@@ -308,12 +315,12 @@ DIDerivedType DIBuilder::createMemberPointerType(DIType PointeeTy,
NULL, // Unused
NULL,
ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Line
- ConstantInt::get(Type::getInt64Ty(VMContext), 0),
- ConstantInt::get(Type::getInt64Ty(VMContext), 0),
+ 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,
- Base
+ PointeeTy.getRef(),
+ Base.getRef()
};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
@@ -333,7 +340,7 @@ DIDerivedType DIBuilder::createReferenceType(unsigned Tag, DIType RTy) {
ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align
ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags
- RTy
+ RTy.getRef()
};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
@@ -346,14 +353,14 @@ DIDerivedType DIBuilder::createTypedef(DIType Ty, StringRef Name, DIFile File,
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_typedef),
File.getFileNode(),
- getNonCompileUnitScope(Context),
+ 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
+ Ty.getRef()
};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
@@ -366,56 +373,59 @@ DIDerivedType DIBuilder::createFriend(DIType Ty, DIType FriendTy) {
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_friend),
NULL,
- Ty,
+ Ty.getRef(),
NULL, // 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
+ 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) {
+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),
NULL,
- Ty,
+ Ty.getRef(),
NULL, // 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
+ 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, uint64_t AlignInBits, uint64_t OffsetInBits,
- unsigned Flags, DIType Ty) {
+DIDerivedType DIBuilder::createMemberType(DIDescriptor Scope, StringRef Name,
+ DIFile File, unsigned LineNumber,
+ uint64_t SizeInBits,
+ uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags,
+ DIType Ty) {
// TAG_member is encoded in DIDerivedType format.
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_member),
File.getFileNode(),
- getNonCompileUnitScope(Scope),
+ 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
+ Ty.getRef()
};
return DIDerivedType(MDNode::get(VMContext, Elts));
}
@@ -432,14 +442,14 @@ DIBuilder::createStaticMemberType(DIDescriptor Scope, StringRef Name,
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_member),
File.getFileNode(),
- getNonCompileUnitScope(Scope),
+ DIScope(getNonCompileUnitScope(Scope)).getRef(),
MDString::get(VMContext, Name),
ConstantInt::get(Type::getInt32Ty(VMContext), LineNumber),
- ConstantInt::get(Type::getInt64Ty(VMContext), 0/*SizeInBits*/),
- ConstantInt::get(Type::getInt64Ty(VMContext), 0/*AlignInBits*/),
- ConstantInt::get(Type::getInt64Ty(VMContext), 0/*OffsetInBits*/),
+ 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,
+ Ty.getRef(),
Val
};
return DIDerivedType(MDNode::get(VMContext, Elts));
@@ -448,13 +458,11 @@ DIBuilder::createStaticMemberType(DIDescriptor Scope, StringRef Name,
/// createObjCIVar - Create debugging information entry for Objective-C
/// instance variable.
DIDerivedType
-DIBuilder::createObjCIVar(StringRef Name,
- DIFile File, unsigned LineNumber,
+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) {
+ 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),
@@ -477,12 +485,12 @@ DIBuilder::createObjCIVar(StringRef Name,
/// 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, MDNode *PropertyNode) {
+DIDerivedType DIBuilder::createObjCIVar(StringRef Name, DIFile File,
+ unsigned LineNumber,
+ uint64_t SizeInBits,
+ uint64_t AlignInBits,
+ uint64_t OffsetInBits, unsigned Flags,
+ DIType Ty, MDNode *PropertyNode) {
// TAG_member is encoded in DIDerivedType format.
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_member),
@@ -502,12 +510,10 @@ DIBuilder::createObjCIVar(StringRef Name,
/// 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) {
+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),
@@ -529,9 +535,9 @@ DIBuilder::createTemplateTypeParameter(DIDescriptor Context, StringRef Name,
unsigned ColumnNo) {
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_template_type_parameter),
- getNonCompileUnitScope(Context),
+ DIScope(getNonCompileUnitScope(Context)).getRef(),
MDString::get(VMContext, Name),
- Ty,
+ Ty.getRef(),
File,
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
ConstantInt::get(Type::getInt32Ty(VMContext), ColumnNo)
@@ -547,9 +553,9 @@ DIBuilder::createTemplateValueParameter(unsigned Tag, DIDescriptor Context,
unsigned ColumnNo) {
Value *Elts[] = {
GetTagConstant(VMContext, Tag),
- getNonCompileUnitScope(Context),
+ DIScope(getNonCompileUnitScope(Context)).getRef(),
MDString::get(VMContext, Name),
- Ty,
+ Ty.getRef(),
Val,
File,
ConstantInt::get(Type::getInt32Ty(VMContext), LineNo),
@@ -598,30 +604,34 @@ DICompositeType DIBuilder::createClassType(DIDescriptor Context, StringRef Name,
uint64_t OffsetInBits,
unsigned Flags, DIType DerivedFrom,
DIArray Elements,
- MDNode *VTableHolder,
- MDNode *TemplateParams) {
+ DIType VTableHolder,
+ MDNode *TemplateParams,
+ StringRef UniqueIdentifier) {
assert((!Context || Context.isScope() || Context.isType()) &&
"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(),
- getNonCompileUnitScope(Context),
+ 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,
+ DerivedFrom.getRef(),
Elements,
ConstantInt::get(Type::getInt32Ty(VMContext), 0),
- VTableHolder,
- TemplateParams
+ VTableHolder.getRef(),
+ TemplateParams,
+ UniqueIdentifier.empty() ? NULL : MDString::get(VMContext, UniqueIdentifier)
};
DICompositeType R(MDNode::get(VMContext, Elts));
assert(R.isCompositeType() &&
"createClassType should return a DICompositeType");
+ if (!UniqueIdentifier.empty())
+ retainType(R);
return R;
}
@@ -634,27 +644,31 @@ DICompositeType DIBuilder::createStructType(DIDescriptor Context,
unsigned Flags, DIType DerivedFrom,
DIArray Elements,
unsigned RunTimeLang,
- MDNode *VTableHolder) {
+ DIType VTableHolder,
+ StringRef UniqueIdentifier) {
// TAG_structure_type is encoded in DICompositeType format.
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_structure_type),
File.getFileNode(),
- getNonCompileUnitScope(Context),
+ 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,
+ DerivedFrom.getRef(),
Elements,
ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeLang),
- VTableHolder,
+ VTableHolder.getRef(),
NULL,
+ UniqueIdentifier.empty() ? NULL : MDString::get(VMContext, UniqueIdentifier)
};
DICompositeType R(MDNode::get(VMContext, Elts));
assert(R.isCompositeType() &&
"createStructType should return a DICompositeType");
+ if (!UniqueIdentifier.empty())
+ retainType(R);
return R;
}
@@ -664,45 +678,52 @@ DICompositeType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name,
uint64_t SizeInBits,
uint64_t AlignInBits, unsigned Flags,
DIArray Elements,
- unsigned RunTimeLang) {
+ unsigned RunTimeLang,
+ StringRef UniqueIdentifier) {
// TAG_union_type is encoded in DICompositeType format.
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_union_type),
File.getFileNode(),
- getNonCompileUnitScope(Scope),
+ 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),
+ ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
NULL,
Elements,
ConstantInt::get(Type::getInt32Ty(VMContext), RunTimeLang),
- Constant::getNullValue(Type::getInt32Ty(VMContext)),
- NULL
+ NULL,
+ NULL,
+ UniqueIdentifier.empty() ? NULL : MDString::get(VMContext, UniqueIdentifier)
};
- return DICompositeType(MDNode::get(VMContext, Elts));
+ DICompositeType R(MDNode::get(VMContext, Elts));
+ if (!UniqueIdentifier.empty())
+ retainType(R);
+ return R;
}
/// createSubroutineType - Create subroutine type.
-DICompositeType
-DIBuilder::createSubroutineType(DIFile File, DIArray ParameterTypes) {
+DICompositeType DIBuilder::createSubroutineType(DIFile File,
+ DIArray ParameterTypes) {
// TAG_subroutine_type is encoded in DICompositeType format.
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_subroutine_type),
Constant::getNullValue(Type::getInt32Ty(VMContext)),
- Constant::getNullValue(Type::getInt32Ty(VMContext)),
+ NULL,
MDString::get(VMContext, ""),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0),
- ConstantInt::get(Type::getInt64Ty(VMContext), 0),
- ConstantInt::get(Type::getInt64Ty(VMContext), 0),
- ConstantInt::get(Type::getInt64Ty(VMContext), 0),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0),
+ 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
NULL,
ParameterTypes,
ConstantInt::get(Type::getInt32Ty(VMContext), 0),
- Constant::getNullValue(Type::getInt32Ty(VMContext))
+ NULL,
+ NULL,
+ NULL // Type Identifer
};
return DICompositeType(MDNode::get(VMContext, Elts));
}
@@ -712,26 +733,30 @@ DIBuilder::createSubroutineType(DIFile File, DIArray ParameterTypes) {
DICompositeType DIBuilder::createEnumerationType(
DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber,
uint64_t SizeInBits, uint64_t AlignInBits, DIArray Elements,
- DIType UnderlyingType) {
+ DIType UnderlyingType, StringRef UniqueIdentifier) {
// TAG_enumeration_type is encoded in DICompositeType format.
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_enumeration_type),
File.getFileNode(),
- getNonCompileUnitScope(Scope),
+ 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),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0),
- UnderlyingType,
+ ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset
+ ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags
+ UnderlyingType.getRef(),
Elements,
ConstantInt::get(Type::getInt32Ty(VMContext), 0),
- Constant::getNullValue(Type::getInt32Ty(VMContext))
+ NULL,
+ NULL,
+ UniqueIdentifier.empty() ? NULL : MDString::get(VMContext, UniqueIdentifier)
};
- MDNode *Node = MDNode::get(VMContext, Elts);
- AllEnumTypes.push_back(Node);
- return DICompositeType(Node);
+ DICompositeType CTy(MDNode::get(VMContext, Elts));
+ AllEnumTypes.push_back(CTy);
+ if (!UniqueIdentifier.empty())
+ retainType(CTy);
+ return CTy;
}
/// createArrayType - Create debugging information entry for an array.
@@ -743,15 +768,17 @@ DICompositeType DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits,
NULL, // Filename/Directory,
NULL, // Unused
MDString::get(VMContext, ""),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0),
+ 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),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0),
- Ty,
+ ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset
+ ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags
+ Ty.getRef(),
Subscripts,
ConstantInt::get(Type::getInt32Ty(VMContext), 0),
- Constant::getNullValue(Type::getInt32Ty(VMContext))
+ NULL,
+ NULL,
+ NULL // Type Identifer
};
return DICompositeType(MDNode::get(VMContext, Elts));
}
@@ -759,22 +786,23 @@ DICompositeType DIBuilder::createArrayType(uint64_t Size, uint64_t AlignInBits,
/// 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),
NULL, // Filename/Directory,
NULL, // Unused
MDString::get(VMContext, ""),
- ConstantInt::get(Type::getInt32Ty(VMContext), 0),
+ 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),
+ ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset
ConstantInt::get(Type::getInt32Ty(VMContext), DIType::FlagVector),
- Ty,
+ Ty.getRef(),
Subscripts,
ConstantInt::get(Type::getInt32Ty(VMContext), 0),
- Constant::getNullValue(Type::getInt32Ty(VMContext))
+ NULL,
+ NULL,
+ NULL // Type Identifer
};
return DICompositeType(MDNode::get(VMContext, Elts));
}
@@ -787,17 +815,14 @@ DIType DIBuilder::createArtificialType(DIType Ty) {
SmallVector<Value *, 9> Elts;
MDNode *N = Ty;
assert (N && "Unexpected input DIType!");
- for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
- if (Value *V = N->getOperand(i))
- Elts.push_back(V);
- else
- Elts.push_back(Constant::getNullValue(Type::getInt32Ty(VMContext)));
- }
+ for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i)
+ Elts.push_back(N->getOperand(i));
unsigned CurFlags = Ty.getFlags();
CurFlags = CurFlags | 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));
@@ -812,17 +837,14 @@ DIType DIBuilder::createObjectPointerType(DIType Ty) {
SmallVector<Value *, 9> Elts;
MDNode *N = Ty;
assert (N && "Unexpected input DIType!");
- for (unsigned i = 0, e = N->getNumOperands(); i != e; ++i) {
- if (Value *V = N->getOperand(i))
- Elts.push_back(V);
- else
- Elts.push_back(Constant::getNullValue(Type::getInt32Ty(VMContext)));
- }
+ 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));
@@ -831,7 +853,7 @@ DIType DIBuilder::createObjectPointerType(DIType Ty) {
/// retainType - Retain DIType in a module even if it is not referenced
/// through debug info anchors.
void DIBuilder::retainType(DIType T) {
- AllRetainTypes.push_back(T);
+ AllRetainTypes.push_back(TrackingVH<MDNode>(T));
}
/// createUnspecifiedParameter - Create unspeicified type descriptor
@@ -845,31 +867,35 @@ DIDescriptor DIBuilder::createUnspecifiedParameter() {
/// createForwardDecl - Create a temporary forward-declared type that
/// can be RAUW'd if the full type is seen.
-DIType DIBuilder::createForwardDecl(unsigned Tag, StringRef Name,
- DIDescriptor Scope, DIFile F,
- unsigned Line, unsigned RuntimeLang,
- uint64_t SizeInBits,
- uint64_t AlignInBits) {
+DICompositeType
+DIBuilder::createForwardDecl(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(),
- getNonCompileUnitScope(Scope),
+ 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),
- ConstantInt::get(Type::getInt32Ty(VMContext),
- DIDescriptor::FlagFwdDecl),
+ ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Offset
+ ConstantInt::get(Type::getInt32Ty(VMContext), DIDescriptor::FlagFwdDecl),
NULL,
DIArray(),
- ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang)
+ ConstantInt::get(Type::getInt32Ty(VMContext), RuntimeLang),
+ NULL,
+ NULL, //TemplateParams
+ UniqueIdentifier.empty() ? NULL : MDString::get(VMContext, UniqueIdentifier)
};
MDNode *Node = MDNode::getTemporary(VMContext, Elts);
- DIType RetTy(Node);
- assert(RetTy.isType() &&
+ DICompositeType RetTy(Node);
+ assert(RetTy.isCompositeType() &&
"createForwardDecl result should be a DIType");
+ if (!UniqueIdentifier.empty())
+ retainType(RetTy);
return RetTy;
}
@@ -895,10 +921,11 @@ DISubrange DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Count) {
}
/// \brief Create a new descriptor for the specified global.
-DIGlobalVariable DIBuilder::
-createGlobalVariable(StringRef Name, StringRef LinkageName, DIFile F,
- unsigned LineNumber, DIType Ty, bool isLocalToUnit,
- Value *Val) {
+DIGlobalVariable DIBuilder::createGlobalVariable(StringRef Name,
+ StringRef LinkageName,
+ DIFile F, unsigned LineNumber,
+ DIType Ty, bool isLocalToUnit,
+ Value *Val) {
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_variable),
Constant::getNullValue(Type::getInt32Ty(VMContext)),
@@ -920,19 +947,22 @@ createGlobalVariable(StringRef Name, StringRef LinkageName, DIFile F,
}
/// \brief Create a new descriptor for the specified global.
-DIGlobalVariable DIBuilder::
-createGlobalVariable(StringRef Name, DIFile F, unsigned LineNumber,
- DIType Ty, bool isLocalToUnit, Value *Val) {
+DIGlobalVariable DIBuilder::createGlobalVariable(StringRef Name, DIFile F,
+ unsigned LineNumber, DIType 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,
- DIType Ty, bool isLocalToUnit, Value *Val, MDNode *Decl) {
+DIGlobalVariable DIBuilder::createStaticVariable(DIDescriptor Context,
+ StringRef Name,
+ StringRef LinkageName,
+ DIFile F, unsigned LineNumber,
+ DIType Ty, bool isLocalToUnit,
+ Value *Val, MDNode *Decl) {
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_variable),
Constant::getNullValue(Type::getInt32Ty(VMContext)),
@@ -1012,24 +1042,38 @@ DIVariable DIBuilder::createComplexVariable(unsigned Tag, DIDescriptor Scope,
}
/// createFunction - Create a new descriptor for the specified function.
-DISubprogram DIBuilder::createFunction(DIDescriptor Context,
- StringRef Name,
- StringRef LinkageName,
- DIFile File, unsigned LineNo,
- DICompositeType Ty,
+/// 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,
+ bool isLocalToUnit, bool isDefinition,
+ unsigned ScopeLine, unsigned Flags,
+ bool isOptimized, Function *Fn,
+ MDNode *TParams, MDNode *Decl) {
+ // dragonegg does not generate identifier for types, so using an empty map
+ // to resolve the context should be fine.
+ DITypeIdentifierMap EmptyMap;
+ return createFunction(Context.resolve(EmptyMap), Name, LinkageName, File,
+ LineNo, Ty, isLocalToUnit, isDefinition, ScopeLine,
+ Flags, isOptimized, Fn, TParams, Decl);
+}
+
+/// createFunction - Create a new descriptor for the specified function.
+DISubprogram DIBuilder::createFunction(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) {
+ 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(),
- getNonCompileUnitScope(Context),
+ DIScope(getNonCompileUnitScope(Context)).getRef(),
MDString::get(VMContext, Name),
MDString::get(VMContext, Name),
MDString::get(VMContext, LinkageName),
@@ -1059,26 +1103,24 @@ DISubprogram DIBuilder::createFunction(DIDescriptor Context,
}
/// createMethod - Create a new descriptor for the specified C++ method.
-DISubprogram DIBuilder::createMethod(DIDescriptor Context,
- StringRef Name,
- StringRef LinkageName,
- DIFile F,
+DISubprogram DIBuilder::createMethod(DIDescriptor Context, StringRef Name,
+ StringRef LinkageName, DIFile F,
unsigned LineNo, DICompositeType Ty,
- bool isLocalToUnit,
- bool isDefinition,
+ bool isLocalToUnit, bool isDefinition,
unsigned VK, unsigned VIndex,
- MDNode *VTableHolder,
- unsigned Flags,
- bool isOptimized,
- Function *Fn,
+ DIType VTableHolder, unsigned Flags,
+ bool isOptimized, Function *Fn,
MDNode *TParam) {
assert(Ty.getTag() == dwarf::DW_TAG_subroutine_type &&
"function types should be subroutines");
+ assert(getNonCompileUnitScope(Context) &&
+ "Methods should have both a Context and a context that isn't "
+ "the compile unit.");
Value *TElts[] = { GetTagConstant(VMContext, DW_TAG_base_type) };
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_subprogram),
F.getFileNode(),
- getNonCompileUnitScope(Context),
+ DIScope(Context).getRef(),
MDString::get(VMContext, Name),
MDString::get(VMContext, Name),
MDString::get(VMContext, LinkageName),
@@ -1086,9 +1128,9 @@ DISubprogram DIBuilder::createMethod(DIDescriptor Context,
Ty,
ConstantInt::get(Type::getInt1Ty(VMContext), isLocalToUnit),
ConstantInt::get(Type::getInt1Ty(VMContext), isDefinition),
- ConstantInt::get(Type::getInt32Ty(VMContext), (unsigned)VK),
+ ConstantInt::get(Type::getInt32Ty(VMContext), VK),
ConstantInt::get(Type::getInt32Ty(VMContext), VIndex),
- VTableHolder,
+ VTableHolder.getRef(),
ConstantInt::get(Type::getInt32Ty(VMContext), Flags),
ConstantInt::get(Type::getInt1Ty(VMContext), isOptimized),
Fn,
diff --git a/lib/IR/DataLayout.cpp b/lib/IR/DataLayout.cpp
index d786d33..6bdc09e 100644
--- a/lib/IR/DataLayout.cpp
+++ b/lib/IR/DataLayout.cpp
@@ -629,6 +629,13 @@ Type *DataLayout::getSmallestLegalIntType(LLVMContext &C, unsigned Width) const
return 0;
}
+unsigned DataLayout::getLargestLegalIntTypeSize() const {
+ unsigned MaxWidth = 0;
+ for (unsigned i = 0, e = (unsigned)LegalIntWidths.size(); i != e; ++i)
+ MaxWidth = std::max<unsigned>(MaxWidth, LegalIntWidths[i]);
+ return MaxWidth;
+}
+
uint64_t DataLayout::getIndexedOffset(Type *ptrTy,
ArrayRef<Value *> Indices) const {
Type *Ty = ptrTy;
diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp
index ff37542..70a756f 100644
--- a/lib/IR/DebugInfo.cpp
+++ b/lib/IR/DebugInfo.cpp
@@ -75,8 +75,8 @@ uint64_t DIDescriptor::getUInt64Field(unsigned Elt) const {
return 0;
if (Elt < DbgNode->getNumOperands())
- if (ConstantInt *CI
- = dyn_cast_or_null<ConstantInt>(DbgNode->getOperand(Elt)))
+ if (ConstantInt *CI =
+ dyn_cast_or_null<ConstantInt>(DbgNode->getOperand(Elt)))
return CI->getZExtValue();
return 0;
@@ -87,8 +87,8 @@ int64_t DIDescriptor::getInt64Field(unsigned Elt) const {
return 0;
if (Elt < DbgNode->getNumOperands())
- if (ConstantInt *CI
- = dyn_cast_or_null<ConstantInt>(DbgNode->getOperand(Elt)))
+ if (ConstantInt *CI =
+ dyn_cast_or_null<ConstantInt>(DbgNode->getOperand(Elt)))
return CI->getSExtValue();
return 0;
@@ -104,7 +104,7 @@ GlobalVariable *DIDescriptor::getGlobalVariableField(unsigned Elt) const {
return 0;
if (Elt < DbgNode->getNumOperands())
- return dyn_cast_or_null<GlobalVariable>(DbgNode->getOperand(Elt));
+ return dyn_cast_or_null<GlobalVariable>(DbgNode->getOperand(Elt));
return 0;
}
@@ -113,7 +113,7 @@ Constant *DIDescriptor::getConstantField(unsigned Elt) const {
return 0;
if (Elt < DbgNode->getNumOperands())
- return dyn_cast_or_null<Constant>(DbgNode->getOperand(Elt));
+ return dyn_cast_or_null<Constant>(DbgNode->getOperand(Elt));
return 0;
}
@@ -122,7 +122,7 @@ Function *DIDescriptor::getFunctionField(unsigned Elt) const {
return 0;
if (Elt < DbgNode->getNumOperands())
- return dyn_cast_or_null<Function>(DbgNode->getOperand(Elt));
+ return dyn_cast_or_null<Function>(DbgNode->getOperand(Elt));
return 0;
}
@@ -131,19 +131,17 @@ void DIDescriptor::replaceFunctionField(unsigned Elt, Function *F) {
return;
if (Elt < DbgNode->getNumOperands()) {
- MDNode *Node = const_cast<MDNode*>(DbgNode);
+ MDNode *Node = const_cast<MDNode *>(DbgNode);
Node->replaceOperandWith(Elt, F);
}
}
unsigned DIVariable::getNumAddrElements() const {
- return DbgNode->getNumOperands()-8;
+ return DbgNode->getNumOperands() - 8;
}
/// getInlinedAt - If this variable is inlined then return inline location.
-MDNode *DIVariable::getInlinedAt() const {
- return getNodeField(DbgNode, 7);
-}
+MDNode *DIVariable::getInlinedAt() const { return getNodeField(DbgNode, 7); }
//===----------------------------------------------------------------------===//
// Predicates
@@ -152,7 +150,8 @@ MDNode *DIVariable::getInlinedAt() const {
/// isBasicType - Return true if the specified tag is legal for
/// DIBasicType.
bool DIDescriptor::isBasicType() const {
- if (!DbgNode) return false;
+ if (!DbgNode)
+ return false;
switch (getTag()) {
case dwarf::DW_TAG_base_type:
case dwarf::DW_TAG_unspecified_type:
@@ -164,7 +163,8 @@ bool DIDescriptor::isBasicType() const {
/// isDerivedType - Return true if the specified tag is legal for DIDerivedType.
bool DIDescriptor::isDerivedType() const {
- if (!DbgNode) return false;
+ if (!DbgNode)
+ return false;
switch (getTag()) {
case dwarf::DW_TAG_typedef:
case dwarf::DW_TAG_pointer_type:
@@ -187,7 +187,8 @@ bool DIDescriptor::isDerivedType() const {
/// isCompositeType - Return true if the specified tag is legal for
/// DICompositeType.
bool DIDescriptor::isCompositeType() const {
- if (!DbgNode) return false;
+ if (!DbgNode)
+ return false;
switch (getTag()) {
case dwarf::DW_TAG_array_type:
case dwarf::DW_TAG_structure_type:
@@ -203,7 +204,8 @@ bool DIDescriptor::isCompositeType() const {
/// isVariable - Return true if the specified tag is legal for DIVariable.
bool DIDescriptor::isVariable() const {
- if (!DbgNode) return false;
+ if (!DbgNode)
+ return false;
switch (getTag()) {
case dwarf::DW_TAG_auto_variable:
case dwarf::DW_TAG_arg_variable:
@@ -240,17 +242,19 @@ bool DIDescriptor::isUnspecifiedParameter() const {
/// isScope - Return true if the specified tag is one of the scope
/// related tag.
bool DIDescriptor::isScope() const {
- if (!DbgNode) return false;
+ if (!DbgNode)
+ return false;
switch (getTag()) {
case dwarf::DW_TAG_compile_unit:
case dwarf::DW_TAG_lexical_block:
case dwarf::DW_TAG_subprogram:
case dwarf::DW_TAG_namespace:
+ case dwarf::DW_TAG_file_type:
return true;
default:
break;
}
- return false;
+ return isType();
}
/// isTemplateTypeParameter - Return true if the specified tag is
@@ -286,13 +290,13 @@ bool DIDescriptor::isNameSpace() const {
/// lexical block with an extra file.
bool DIDescriptor::isLexicalBlockFile() const {
return DbgNode && getTag() == dwarf::DW_TAG_lexical_block &&
- (DbgNode->getNumOperands() == 3);
+ (DbgNode->getNumOperands() == 3);
}
/// isLexicalBlock - Return true if the specified tag is DW_TAG_lexical_block.
bool DIDescriptor::isLexicalBlock() const {
return DbgNode && getTag() == dwarf::DW_TAG_lexical_block &&
- (DbgNode->getNumOperands() > 3);
+ (DbgNode->getNumOperands() > 3);
}
/// isSubrange - Return true if the specified tag is DW_TAG_subrange_type.
@@ -339,10 +343,10 @@ void DIType::replaceAllUsesWith(DIDescriptor &D) {
// this detail by allowing a value to be replaced with replaceAllUsesWith()
// itself.
if (DbgNode != D) {
- MDNode *Node = const_cast<MDNode*>(DbgNode);
+ MDNode *Node = const_cast<MDNode *>(DbgNode);
const MDNode *DN = D;
const Value *V = cast_or_null<Value>(DN);
- Node->replaceAllUsesWith(const_cast<Value*>(V));
+ Node->replaceAllUsesWith(const_cast<Value *>(V));
MDNode::deleteTemporary(Node);
}
}
@@ -359,31 +363,14 @@ void DIType::replaceAllUsesWith(MDNode *D) {
// this detail by allowing a value to be replaced with replaceAllUsesWith()
// itself.
if (DbgNode != D) {
- MDNode *Node = const_cast<MDNode*>(DbgNode);
+ MDNode *Node = const_cast<MDNode *>(DbgNode);
const MDNode *DN = D;
const Value *V = cast_or_null<Value>(DN);
- Node->replaceAllUsesWith(const_cast<Value*>(V));
+ Node->replaceAllUsesWith(const_cast<Value *>(V));
MDNode::deleteTemporary(Node);
}
}
-/// isUnsignedDIType - Return true if type encoding is unsigned.
-bool DIType::isUnsignedDIType() {
- DIDerivedType DTy(DbgNode);
- if (DTy.Verify())
- return DTy.getTypeDerivedFrom().isUnsignedDIType();
-
- DIBasicType BTy(DbgNode);
- if (BTy.Verify()) {
- unsigned Encoding = BTy.getEncoding();
- if (Encoding == dwarf::DW_ATE_unsigned ||
- Encoding == dwarf::DW_ATE_unsigned_char ||
- Encoding == dwarf::DW_ATE_boolean)
- return true;
- }
- return false;
-}
-
/// Verify - Verify that a compile unit is well formed.
bool DICompileUnit::Verify() const {
if (!isCompileUnit())
@@ -413,22 +400,53 @@ static bool fieldIsMDNode(const MDNode *DbgNode, unsigned Elt) {
// FIXME: This function should return true, if the field is null or the field
// is indeed a MDNode: return !Fld || isa<MDNode>(Fld).
Value *Fld = getField(DbgNode, Elt);
- if (Fld && isa<MDString>(Fld) &&
- !cast<MDString>(Fld)->getString().empty())
+ if (Fld && isa<MDString>(Fld) && !cast<MDString>(Fld)->getString().empty())
return false;
return true;
}
+/// 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());
+}
+
+/// Check if a field at position Elt of a MDNode can be a reference to a type.
+static bool fieldIsTypeRef(const MDNode *DbgNode, unsigned Elt) {
+ Value *Fld = getField(DbgNode, Elt);
+ return isTypeRef(Fld);
+}
+
+/// Check if a value can be a ScopeRef.
+static bool isScopeRef(const Value *Val) {
+ return !Val ||
+ (isa<MDString>(Val) && !cast<MDString>(Val)->getString().empty()) ||
+ (isa<MDNode>(Val) && DIScope(cast<MDNode>(Val)).isScope());
+}
+
+/// 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);
+}
+
/// Verify - Verify that a type descriptor is well formed.
bool DIType::Verify() const {
if (!isType())
return false;
// Make sure Context @ field 2 is MDNode.
- if (!fieldIsMDNode(DbgNode, 2))
+ if (!fieldIsScopeRef(DbgNode, 2))
return false;
// FIXME: Sink this into the various subclass verifies.
- unsigned Tag = getTag();
+ uint16_t Tag = getTag();
if (!isBasicType() && Tag != dwarf::DW_TAG_const_type &&
Tag != dwarf::DW_TAG_volatile_type && Tag != dwarf::DW_TAG_pointer_type &&
Tag != dwarf::DW_TAG_ptr_to_member_type &&
@@ -460,12 +478,12 @@ bool DIBasicType::Verify() const {
/// Verify - Verify that a derived type descriptor is well formed.
bool DIDerivedType::Verify() const {
- // Make sure DerivedFrom @ field 9 is MDNode.
- if (!fieldIsMDNode(DbgNode, 9))
+ // Make sure DerivedFrom @ field 9 is TypeRef.
+ if (!fieldIsTypeRef(DbgNode, 9))
return false;
if (getTag() == dwarf::DW_TAG_ptr_to_member_type)
- // Make sure ClassType @ field 10 is MDNode.
- if (!fieldIsMDNode(DbgNode, 10))
+ // Make sure ClassType @ field 10 is a TypeRef.
+ if (!fieldIsTypeRef(DbgNode, 10))
return false;
return isDerivedType() && DbgNode->getNumOperands() >= 10 &&
@@ -477,13 +495,17 @@ bool DICompositeType::Verify() const {
if (!isCompositeType())
return false;
- // Make sure DerivedFrom @ field 9 and ContainingType @ field 12 are MDNodes.
- if (!fieldIsMDNode(DbgNode, 9))
+ // Make sure DerivedFrom @ field 9 and ContainingType @ field 12 are TypeRef.
+ if (!fieldIsTypeRef(DbgNode, 9))
return false;
- if (!fieldIsMDNode(DbgNode, 12))
+ if (!fieldIsTypeRef(DbgNode, 12))
return false;
- return DbgNode->getNumOperands() >= 10 && DbgNode->getNumOperands() <= 14;
+ // Make sure the type identifier at field 14 is MDString, it can be null.
+ if (!fieldIsMDString(DbgNode, 14))
+ return false;
+
+ return DbgNode->getNumOperands() == 15;
}
/// Verify - Verify that a subprogram descriptor is well formed.
@@ -491,13 +513,13 @@ bool DISubprogram::Verify() const {
if (!isSubprogram())
return false;
- // Make sure context @ field 2 and type @ field 7 are MDNodes.
- if (!fieldIsMDNode(DbgNode, 2))
+ // Make sure context @ field 2 is a ScopeRef and type @ field 7 is a MDNode.
+ if (!fieldIsScopeRef(DbgNode, 2))
return false;
if (!fieldIsMDNode(DbgNode, 7))
return false;
// Containing type @ field 12.
- if (!fieldIsMDNode(DbgNode, 12))
+ if (!fieldIsTypeRef(DbgNode, 12))
return false;
return DbgNode->getNumOperands() == 20;
}
@@ -550,9 +572,7 @@ bool DINameSpace::Verify() const {
}
/// \brief Retrieve the MDNode for the directory/file pair.
-MDNode *DIFile::getFileNode() const {
- return getNodeField(DbgNode, 1);
-}
+MDNode *DIFile::getFileNode() const { return getNodeField(DbgNode, 1); }
/// \brief Verify that the file descriptor is well formed.
bool DIFile::Verify() const {
@@ -595,56 +615,77 @@ bool DIImportedEntity::Verify() const {
(DbgNode->getNumOperands() == 4 || DbgNode->getNumOperands() == 5);
}
-/// getOriginalTypeSize - If this type is derived from a base type then
-/// return base type size.
-uint64_t DIDerivedType::getOriginalTypeSize() const {
- unsigned Tag = getTag();
-
- if (Tag != dwarf::DW_TAG_member && Tag != dwarf::DW_TAG_typedef &&
- Tag != dwarf::DW_TAG_const_type && Tag != dwarf::DW_TAG_volatile_type &&
- Tag != dwarf::DW_TAG_restrict_type)
- return getSizeInBits();
-
- DIType BaseType = getTypeDerivedFrom();
-
- // If this type is not derived from any type then take conservative approach.
- if (!BaseType.isValid())
- return getSizeInBits();
-
- // If this is a derived type, go ahead and get the base type, unless it's a
- // reference then it's just the size of the field. Pointer types have no need
- // of this since they're a different type of qualification on the type.
- if (BaseType.getTag() == dwarf::DW_TAG_reference_type ||
- BaseType.getTag() == dwarf::DW_TAG_rvalue_reference_type)
- return getSizeInBits();
-
- if (BaseType.isDerivedType())
- return DIDerivedType(BaseType).getOriginalTypeSize();
-
- return BaseType.getSizeInBits();
-}
-
/// getObjCProperty - Return property node, if this ivar is associated with one.
MDNode *DIDerivedType::getObjCProperty() const {
return getNodeField(DbgNode, 10);
}
+MDString *DICompositeType::getIdentifier() const {
+ return cast_or_null<MDString>(getField(DbgNode, 14));
+}
+
+#ifndef NDEBUG
+static void VerifySubsetOf(const MDNode *LHS, const MDNode *RHS) {
+ for (unsigned i = 0; i != LHS->getNumOperands(); ++i) {
+ // Skip the 'empty' list (that's a single i32 0, rather than truly empty).
+ if (i == 0 && isa<ConstantInt>(LHS->getOperand(i)))
+ continue;
+ const MDNode *E = cast<MDNode>(LHS->getOperand(i));
+ bool found = false;
+ for (unsigned j = 0; !found && j != RHS->getNumOperands(); ++j)
+ found = E == RHS->getOperand(j);
+ assert(found && "Losing a member during member list replacement");
+ }
+}
+#endif
+
/// \brief Set the array of member DITypes.
void DICompositeType::setTypeArray(DIArray Elements, DIArray TParams) {
- assert((!TParams || DbgNode->getNumOperands() == 14) &&
+ assert((!TParams || DbgNode->getNumOperands() == 15) &&
"If you're setting the template parameters this should include a slot "
"for that!");
TrackingVH<MDNode> N(*this);
- N->replaceOperandWith(10, Elements);
+ 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)))
+ VerifySubsetOf(El, Elements);
+#endif
+ N->replaceOperandWith(10, Elements);
+ }
if (TParams)
N->replaceOperandWith(13, TParams);
DbgNode = N;
}
+void DICompositeType::addMember(DIDescriptor D) {
+ SmallVector<llvm::Value *, 16> M;
+ DIArray OrigM = getTypeArray();
+ unsigned Elements = OrigM.getNumElements();
+ if (Elements == 1 && !OrigM.getElement(0))
+ Elements = 0;
+ M.reserve(Elements + 1);
+ for (unsigned i = 0; i != Elements; ++i)
+ M.push_back(OrigM.getElement(i));
+ M.push_back(D);
+ setTypeArray(DIArray(MDNode::get(DbgNode->getContext(), M)));
+}
+
+/// 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);
+ DICompositeType DTy(DbgNode);
+ if (!DTy.getIdentifier())
+ return DIScopeRef(*this);
+ return DIScopeRef(DTy.getIdentifier());
+}
+
/// \brief Set the containing type.
void DICompositeType::setContainingType(DICompositeType ContainingType) {
TrackingVH<MDNode> N(*this);
- N->replaceOperandWith(12, ContainingType);
+ N->replaceOperandWith(12, ContainingType.getRef());
DbgNode = N;
}
@@ -674,7 +715,7 @@ bool DISubprogram::describes(const Function *F) {
}
unsigned DISubprogram::isOptimized() const {
- assert (DbgNode && "Invalid subprogram descriptor!");
+ assert(DbgNode && "Invalid subprogram descriptor!");
if (DbgNode->getNumOperands() == 15)
return getUnsignedField(14);
return 0;
@@ -694,25 +735,39 @@ Value *DITemplateValueParameter::getValue() const {
// If the current node has a parent scope then return that,
// else return an empty scope.
-DIScope DIScope::getContext() const {
+DIScopeRef DIScope::getContext() const {
if (isType())
return DIType(DbgNode).getContext();
if (isSubprogram())
- return DISubprogram(DbgNode).getContext();
+ return DIScopeRef(DISubprogram(DbgNode).getContext());
if (isLexicalBlock())
- return DILexicalBlock(DbgNode).getContext();
+ return DIScopeRef(DILexicalBlock(DbgNode).getContext());
if (isLexicalBlockFile())
- return DILexicalBlockFile(DbgNode).getContext();
+ return DIScopeRef(DILexicalBlockFile(DbgNode).getContext());
if (isNameSpace())
- return DINameSpace(DbgNode).getContext();
+ return DIScopeRef(DINameSpace(DbgNode).getContext());
assert((isFile() || isCompileUnit()) && "Unhandled type of scope.");
- return DIScope();
+ return DIScopeRef(NULL);
+}
+
+// If the scope node has a name, return that, else return an empty string.
+StringRef DIScope::getName() const {
+ if (isType())
+ return DIType(DbgNode).getName();
+ if (isSubprogram())
+ return DISubprogram(DbgNode).getName();
+ if (isNameSpace())
+ return DINameSpace(DbgNode).getName();
+ assert((isLexicalBlock() || isLexicalBlockFile() || isFile() ||
+ isCompileUnit()) &&
+ "Unhandled type of scope.");
+ return StringRef();
}
StringRef DIScope::getFilename() const {
@@ -748,7 +803,6 @@ DIArray DICompileUnit::getSubprograms() const {
return DIArray(getNodeField(DbgNode, 9));
}
-
DIArray DICompileUnit::getGlobalVariables() const {
if (!DbgNode || DbgNode->getNumOperands() < 13)
return DIArray();
@@ -813,8 +867,7 @@ DIVariable llvm::createInlinedVariable(MDNode *DV, MDNode *InlinedScope,
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));
+ i == 7 ? Elts.push_back(InlinedScope) : Elts.push_back(DV->getOperand(i));
return DIVariable(MDNode::get(VMContext, Elts));
}
@@ -823,9 +876,8 @@ 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));
+ i == 7 ? Elts.push_back(Constant::getNullValue(Type::getInt32Ty(VMContext)))
+ : Elts.push_back(DV->getOperand(i));
return DIVariable(MDNode::get(VMContext, Elts));
}
@@ -849,23 +901,42 @@ DICompositeType llvm::getDICompositeType(DIType T) {
if (T.isCompositeType())
return DICompositeType(T);
- if (T.isDerivedType())
- return getDICompositeType(DIDerivedType(T).getTypeDerivedFrom());
+ if (T.isDerivedType()) {
+ // This function is currently used by dragonegg and dragonegg does
+ // not generate identifier for types, so using an empty map to resolve
+ // DerivedFrom should be fine.
+ DITypeIdentifierMap EmptyMap;
+ return getDICompositeType(
+ DIDerivedType(T).getTypeDerivedFrom().resolve(EmptyMap));
+ }
return DICompositeType();
}
-/// isSubprogramContext - Return true if Context is either a subprogram
-/// or another context nested inside a subprogram.
-bool llvm::isSubprogramContext(const MDNode *Context) {
- if (!Context)
- return false;
- DIDescriptor D(Context);
- if (D.isSubprogram())
- return true;
- if (D.isType())
- return isSubprogramContext(DIType(Context).getContext());
- return false;
+/// Update DITypeIdentifierMap by going through retained types of each CU.
+DITypeIdentifierMap
+llvm::generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes) {
+ DITypeIdentifierMap Map;
+ for (unsigned CUi = 0, CUe = CU_Nodes->getNumOperands(); CUi != CUe; ++CUi) {
+ DICompileUnit CU(CU_Nodes->getOperand(CUi));
+ DIArray Retain = CU.getRetainedTypes();
+ for (unsigned Ti = 0, Te = Retain.getNumElements(); Ti != Te; ++Ti) {
+ if (!Retain.getElement(Ti).isCompositeType())
+ continue;
+ DICompositeType Ty(Retain.getElement(Ti));
+ if (MDString *TypeId = Ty.getIdentifier()) {
+ // Definition has priority over declaration.
+ // Try to insert (TypeId, Ty) to Map.
+ std::pair<DITypeIdentifierMap::iterator, bool> P =
+ Map.insert(std::make_pair(TypeId, Ty));
+ // If TypeId already exists in Map and this is a definition, replace
+ // whatever we had (declaration or definition) with the definition.
+ if (!P.second && !Ty.isForwardDecl())
+ P.first->second = Ty;
+ }
+ }
+ }
+ return Map;
}
//===----------------------------------------------------------------------===//
@@ -879,10 +950,21 @@ void DebugInfoFinder::reset() {
TYs.clear();
Scopes.clear();
NodesSeen.clear();
+ TypeIdentifierMap.clear();
+ TypeMapInitialized = false;
+}
+
+void DebugInfoFinder::InitializeTypeMap(const Module &M) {
+ if (!TypeMapInitialized)
+ if (NamedMDNode *CU_Nodes = M.getNamedMetadata("llvm.dbg.cu")) {
+ TypeIdentifierMap = generateDITypeIdentifierMap(CU_Nodes);
+ TypeMapInitialized = true;
+ }
}
/// 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")) {
for (unsigned i = 0, e = CU_Nodes->getNumOperands(); i != e; ++i) {
DICompileUnit CU(CU_Nodes->getOperand(i));
@@ -904,27 +986,38 @@ void DebugInfoFinder::processModule(const Module &M) {
DIArray RetainedTypes = CU.getRetainedTypes();
for (unsigned i = 0, e = RetainedTypes.getNumElements(); i != e; ++i)
processType(DIType(RetainedTypes.getElement(i)));
- // FIXME: We really shouldn't be bailing out after visiting just one CU
- return;
+ DIArray Imports = CU.getImportedEntities();
+ for (unsigned i = 0, e = Imports.getNumElements(); i != e; ++i) {
+ DIImportedEntity Import = DIImportedEntity(Imports.getElement(i));
+ DIDescriptor Entity = Import.getEntity();
+ if (Entity.isType())
+ processType(DIType(Entity));
+ else if (Entity.isSubprogram())
+ processSubprogram(DISubprogram(Entity));
+ else if (Entity.isNameSpace())
+ processScope(DINameSpace(Entity).getContext());
+ }
}
}
}
/// processLocation - Process DILocation.
-void DebugInfoFinder::processLocation(DILocation Loc) {
- if (!Loc) return;
+void DebugInfoFinder::processLocation(const Module &M, DILocation Loc) {
+ if (!Loc)
+ return;
+ InitializeTypeMap(M);
processScope(Loc.getScope());
- processLocation(Loc.getOrigLocation());
+ processLocation(M, Loc.getOrigLocation());
}
/// processType - Process DIType.
void DebugInfoFinder::processType(DIType DT) {
if (!addType(DT))
return;
- processScope(DT.getContext());
+ processScope(DT.getContext().resolve(TypeIdentifierMap));
if (DT.isCompositeType()) {
DICompositeType DCT(DT);
- processType(DCT.getTypeDerivedFrom());
+ processType(DCT.getTypeDerivedFrom().resolve(TypeIdentifierMap));
DIArray DA = DCT.getTypeArray();
for (unsigned i = 0, e = DA.getNumElements(); i != e; ++i) {
DIDescriptor D = DA.getElement(i);
@@ -935,7 +1028,7 @@ void DebugInfoFinder::processType(DIType DT) {
}
} else if (DT.isDerivedType()) {
DIDerivedType DDT(DT);
- processType(DDT.getTypeDerivedFrom());
+ processType(DDT.getTypeDerivedFrom().resolve(TypeIdentifierMap));
}
}
@@ -975,8 +1068,7 @@ void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) {
else if (Context.isLexicalBlockFile()) {
DILexicalBlockFile DBF = DILexicalBlockFile(Context);
return processLexicalBlock(DILexicalBlock(DBF.getScope()));
- }
- else
+ } else
return processSubprogram(DISubprogram(Context));
}
@@ -984,14 +1076,30 @@ void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) {
void DebugInfoFinder::processSubprogram(DISubprogram SP) {
if (!addSubprogram(SP))
return;
- processScope(SP.getContext());
+ processScope(SP.getContext().resolve(TypeIdentifierMap));
processType(SP.getType());
+ DIArray TParams = SP.getTemplateParams();
+ for (unsigned I = 0, E = TParams.getNumElements(); I != E; ++I) {
+ DIDescriptor Element = TParams.getElement(I);
+ if (Element.isTemplateTypeParameter()) {
+ DITemplateTypeParameter TType(Element);
+ processScope(TType.getContext().resolve(TypeIdentifierMap));
+ processType(TType.getType().resolve(TypeIdentifierMap));
+ } else if (Element.isTemplateValueParameter()) {
+ DITemplateValueParameter TVal(Element);
+ processScope(TVal.getContext().resolve(TypeIdentifierMap));
+ processType(TVal.getType().resolve(TypeIdentifierMap));
+ }
+ }
}
/// processDeclare - Process DbgDeclareInst.
-void DebugInfoFinder::processDeclare(const DbgDeclareInst *DDI) {
+void DebugInfoFinder::processDeclare(const Module &M,
+ const DbgDeclareInst *DDI) {
MDNode *N = dyn_cast<MDNode>(DDI->getVariable());
- if (!N) return;
+ if (!N)
+ return;
+ InitializeTypeMap(M);
DIDescriptor DV(N);
if (!DV.isVariable())
@@ -1003,9 +1111,11 @@ void DebugInfoFinder::processDeclare(const DbgDeclareInst *DDI) {
processType(DIVariable(N).getType());
}
-void DebugInfoFinder::processValue(const DbgValueInst *DVI) {
+void DebugInfoFinder::processValue(const Module &M, const DbgValueInst *DVI) {
MDNode *N = dyn_cast<MDNode>(DVI->getVariable());
- if (!N) return;
+ if (!N)
+ return;
+ InitializeTypeMap(M);
DIDescriptor DV(N);
if (!DV.isVariable())
@@ -1083,12 +1193,14 @@ bool DebugInfoFinder::addScope(DIScope Scope) {
/// dump - Print descriptor to dbgs() with a newline.
void DIDescriptor::dump() const {
- print(dbgs()); dbgs() << '\n';
+ print(dbgs());
+ dbgs() << '\n';
}
/// print - Print descriptor.
void DIDescriptor::print(raw_ostream &OS) const {
- if (!DbgNode) return;
+ if (!DbgNode)
+ return;
if (const char *Tag = dwarf::TagString(getTag()))
OS << "[ " << Tag << " ]";
@@ -1150,7 +1262,8 @@ void DIEnumerator::printInternal(raw_ostream &OS) const {
}
void DIType::printInternal(raw_ostream &OS) const {
- if (!DbgNode) return;
+ if (!DbgNode)
+ return;
StringRef Res = getName();
if (!Res.empty())
@@ -1158,13 +1271,11 @@ void DIType::printInternal(raw_ostream &OS) const {
// TODO: Print context?
- OS << " [line " << getLineNumber()
- << ", size " << getSizeInBits()
- << ", align " << getAlignInBits()
- << ", offset " << getOffsetInBits();
+ OS << " [line " << getLineNumber() << ", size " << getSizeInBits()
+ << ", align " << getAlignInBits() << ", offset " << getOffsetInBits();
if (isBasicType())
if (const char *Enc =
- dwarf::AttributeEncodingString(DIBasicType(DbgNode).getEncoding()))
+ dwarf::AttributeEncodingString(DIBasicType(DbgNode).getEncoding()))
OS << ", enc " << Enc;
OS << "]";
@@ -1260,16 +1371,15 @@ void DIObjCProperty::printInternal(raw_ostream &OS) const {
if (!Name.empty())
OS << " [" << Name << ']';
- OS << " [line " << getLineNumber()
- << ", properties " << getUnsignedField(6) << ']';
+ OS << " [line " << getLineNumber() << ", properties " << getUnsignedField(6)
+ << ']';
}
static void printDebugLoc(DebugLoc DL, raw_ostream &CommentOS,
const LLVMContext &Ctx) {
- if (!DL.isUnknown()) { // Print source line info.
+ if (!DL.isUnknown()) { // Print source line info.
DIScope Scope(DL.getScope(Ctx));
- assert(Scope.isScope() &&
- "Scope of a DebugLoc should be a DIScope.");
+ assert(Scope.isScope() && "Scope of a DebugLoc should be a DIScope.");
// Omit the directory, because it's likely to be long and uninteresting.
CommentOS << Scope.getFilename();
CommentOS << ':' << DL.getLine();
@@ -1298,3 +1408,81 @@ 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) {
+ assert(isScopeRef(V) && "DIScopeRef should be a MDString or MDNode");
+}
+template <> DIRef<DIType>::DIRef(const Value *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));
+}
+/// Specialize getFieldAs to handle fields that are references to DITypes.
+template <> DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const {
+ return DITypeRef(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
+ // the module.
+ if (Function *Declare = M.getFunction("llvm.dbg.declare")) {
+ while (!Declare->use_empty()) {
+ CallInst *CI = cast<CallInst>(Declare->use_back());
+ CI->eraseFromParent();
+ }
+ Declare->eraseFromParent();
+ Changed = true;
+ }
+
+ if (Function *DbgVal = M.getFunction("llvm.dbg.value")) {
+ while (!DbgVal->use_empty()) {
+ CallInst *CI = cast<CallInst>(DbgVal->use_back());
+ CI->eraseFromParent();
+ }
+ DbgVal->eraseFromParent();
+ Changed = true;
+ }
+
+ for (Module::named_metadata_iterator NMI = M.named_metadata_begin(),
+ NME = M.named_metadata_end(); NMI != NME;) {
+ NamedMDNode *NMD = NMI;
+ ++NMI;
+ if (NMD->getName().startswith("llvm.dbg.")) {
+ NMD->eraseFromParent();
+ Changed = true;
+ }
+ }
+
+ for (Module::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI)
+ for (Function::iterator FI = MI->begin(), FE = MI->end(); FI != FE;
+ ++FI)
+ for (BasicBlock::iterator BI = FI->begin(), BE = FI->end(); BI != BE;
+ ++BI) {
+ if (!BI->getDebugLoc().isUnknown()) {
+ Changed = true;
+ BI->setDebugLoc(DebugLoc());
+ }
+ }
+
+ 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)
+ return 0;
+ return cast<ConstantInt>(Val)->getZExtValue();
+}
diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp
index bf9d949..e8a2402 100644
--- a/lib/IR/Function.cpp
+++ b/lib/IR/Function.cpp
@@ -276,6 +276,9 @@ void Function::dropAllReferences() {
// blockaddresses, but BasicBlock's destructor takes care of those.
while (!BasicBlocks.empty())
BasicBlocks.begin()->eraseFromParent();
+
+ // Prefix data is stored in a side table.
+ setPrefixData(0);
}
void Function::addAttribute(unsigned i, Attribute::AttrKind attr) {
@@ -351,6 +354,10 @@ void Function::copyAttributesFrom(const GlobalValue *Src) {
setGC(SrcF->getGC());
else
clearGC();
+ if (SrcF->hasPrefixData())
+ setPrefixData(SrcF->getPrefixData());
+ else
+ setPrefixData(0);
}
/// getIntrinsicID - This method returns the ID number of the specified
@@ -446,7 +453,9 @@ enum IIT_Info {
IIT_STRUCT5 = 22,
IIT_EXTEND_VEC_ARG = 23,
IIT_TRUNC_VEC_ARG = 24,
- IIT_ANYPTR = 25
+ IIT_ANYPTR = 25,
+ IIT_V1 = 26,
+ IIT_VARARG = 27
};
@@ -460,6 +469,9 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
case IIT_Done:
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Void, 0));
return;
+ case IIT_VARARG:
+ OutputTable.push_back(IITDescriptor::get(IITDescriptor::VarArg, 0));
+ return;
case IIT_MMX:
OutputTable.push_back(IITDescriptor::get(IITDescriptor::MMX, 0));
return;
@@ -490,6 +502,10 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
case IIT_I64:
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Integer, 64));
return;
+ case IIT_V1:
+ OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 1));
+ DecodeIITType(NextElt, Infos, OutputTable);
+ return;
case IIT_V2:
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Vector, 2));
DecodeIITType(NextElt, Infos, OutputTable);
@@ -601,6 +617,7 @@ static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos,
switch (D.Kind) {
case IITDescriptor::Void: return Type::getVoidTy(Context);
+ case IITDescriptor::VarArg: return Type::getVoidTy(Context);
case IITDescriptor::MMX: return Type::getX86_MMXTy(Context);
case IITDescriptor::Metadata: return Type::getMetadataTy(Context);
case IITDescriptor::Half: return Type::getHalfTy(Context);
@@ -720,3 +737,32 @@ bool Function::callsFunctionThatReturnsTwice() const {
return false;
}
+
+Constant *Function::getPrefixData() const {
+ assert(hasPrefixData());
+ const LLVMContextImpl::PrefixDataMapTy &PDMap =
+ getContext().pImpl->PrefixDataMap;
+ assert(PDMap.find(this) != PDMap.end());
+ return cast<Constant>(PDMap.find(this)->second->getReturnValue());
+}
+
+void Function::setPrefixData(Constant *PrefixData) {
+ if (!PrefixData && !hasPrefixData())
+ return;
+
+ unsigned SCData = getSubclassDataFromValue();
+ LLVMContextImpl::PrefixDataMapTy &PDMap = getContext().pImpl->PrefixDataMap;
+ ReturnInst *&PDHolder = PDMap[this];
+ if (PrefixData) {
+ if (PDHolder)
+ PDHolder->setOperand(0, PrefixData);
+ else
+ PDHolder = ReturnInst::Create(getContext(), PrefixData);
+ SCData |= 2;
+ } else {
+ delete PDHolder;
+ PDMap.erase(this);
+ SCData &= ~2;
+ }
+ setValueSubclassData(SCData);
+}
diff --git a/lib/IR/GCOV.cpp b/lib/IR/GCOV.cpp
index e9baa5c..f0f8c7d 100644
--- a/lib/IR/GCOV.cpp
+++ b/lib/IR/GCOV.cpp
@@ -7,14 +7,16 @@
//
//===----------------------------------------------------------------------===//
//
-// GCOV implements the interface to read and write coverage files that use
+// GCOV implements the interface to read and write coverage files that use
// 'gcov' format.
//
//===----------------------------------------------------------------------===//
+#include "llvm/Support/Debug.h"
#include "llvm/Support/GCOV.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryObject.h"
#include "llvm/Support/system_error.h"
using namespace llvm;
@@ -43,25 +45,45 @@ bool GCOVFile::read(GCOVBuffer &Buffer) {
if (Format == GCOV::InvalidGCOV)
return false;
- unsigned i = 0;
- while (1) {
- GCOVFunction *GFun = NULL;
- if (isGCDAFile(Format)) {
- // Use existing function while reading .gcda file.
- assert(i < Functions.size() && ".gcda data does not match .gcno data");
- GFun = Functions[i];
- } else if (isGCNOFile(Format)){
- GFun = new GCOVFunction();
+ if (isGCNOFile(Format)) {
+ while (true) {
+ if (!Buffer.readFunctionTag()) break;
+ GCOVFunction *GFun = new GCOVFunction();
+ if (!GFun->read(Buffer, Format))
+ return false;
Functions.push_back(GFun);
}
- if (!GFun || !GFun->read(Buffer, Format))
- break;
- ++i;
}
+ else if (isGCDAFile(Format)) {
+ for (size_t i = 0, e = Functions.size(); i < e; ++i) {
+ if (!Buffer.readFunctionTag()) {
+ errs() << "Unexpected number of functions.\n";
+ return false;
+ }
+ if (!Functions[i]->read(Buffer, Format))
+ return false;
+ }
+ if (Buffer.readObjectTag()) {
+ uint32_t Length;
+ uint32_t Dummy;
+ if (!Buffer.readInt(Length)) return false;
+ if (!Buffer.readInt(Dummy)) return false; // checksum
+ if (!Buffer.readInt(Dummy)) return false; // num
+ if (!Buffer.readInt(RunCount)) return false;;
+ Buffer.advanceCursor(Length-3);
+ }
+ while (Buffer.readProgramTag()) {
+ uint32_t Length;
+ if (!Buffer.readInt(Length)) return false;
+ Buffer.advanceCursor(Length);
+ ++ProgramCount;
+ }
+ }
+
return true;
}
-/// dump - Dump GCOVFile content on standard out for debugging purposes.
+/// dump - Dump GCOVFile content to dbgs() for debugging purposes.
void GCOVFile::dump() {
for (SmallVectorImpl<GCOVFunction *>::iterator I = Functions.begin(),
E = Functions.end(); I != E; ++I)
@@ -72,9 +94,10 @@ void GCOVFile::dump() {
/// reading .gcno and .gcda files.
void GCOVFile::collectLineCounts(FileInfo &FI) {
for (SmallVectorImpl<GCOVFunction *>::iterator I = Functions.begin(),
- E = Functions.end(); I != E; ++I)
+ E = Functions.end(); I != E; ++I)
(*I)->collectLineCounts(FI);
- FI.print();
+ FI.setRunCount(RunCount);
+ FI.setProgramCount(ProgramCount);
}
//===----------------------------------------------------------------------===//
@@ -85,76 +108,121 @@ GCOVFunction::~GCOVFunction() {
DeleteContainerPointers(Blocks);
}
-/// read - Read a aunction from the buffer. Return false if buffer cursor
+/// read - Read a function from the buffer. Return false if buffer cursor
/// does not point to a function tag.
bool GCOVFunction::read(GCOVBuffer &Buff, GCOV::GCOVFormat Format) {
- if (!Buff.readFunctionTag())
- return false;
-
- Buff.readInt(); // Function header length
- Ident = Buff.readInt();
- Buff.readInt(); // Checksum #1
+ uint32_t Dummy;
+ if (!Buff.readInt(Dummy)) return false; // Function header length
+ if (!Buff.readInt(Ident)) return false;
+ if (!Buff.readInt(Dummy)) return false; // Checksum #1
if (Format != GCOV::GCNO_402 && Format != GCOV::GCDA_402)
- Buff.readInt(); // Checksum #2
+ if (!Buff.readInt(Dummy)) return false; // Checksum #2
+
+ if (!Buff.readString(Name)) return false;
- Name = Buff.readString();
if (Format == GCOV::GCNO_402 || Format == GCOV::GCNO_404)
- Filename = Buff.readString();
+ if (!Buff.readString(Filename)) return false;
if (Format == GCOV::GCDA_402 || Format == GCOV::GCDA_404) {
- Buff.readArcTag();
- uint32_t Count = Buff.readInt() / 2;
- for (unsigned i = 0, e = Count; i != e; ++i) {
- Blocks[i]->addCount(Buff.readInt64());
+ if (!Buff.readArcTag()) {
+ errs() << "Arc tag not found.\n";
+ return false;
+ }
+ uint32_t Count;
+ if (!Buff.readInt(Count)) return false;
+ Count /= 2;
+
+ // This for loop adds the counts for each block. A second nested loop is
+ // required to combine the edge counts that are contained in the GCDA file.
+ for (uint32_t Line = 0; Count > 0; ++Line) {
+ if (Line >= Blocks.size()) {
+ errs() << "Unexpected number of edges.\n";
+ return false;
+ }
+ GCOVBlock &Block = *Blocks[Line];
+ for (size_t Edge = 0, End = Block.getNumEdges(); Edge < End; ++Edge) {
+ if (Count == 0) {
+ errs() << "Unexpected number of edges.\n";
+ return false;
+ }
+ uint64_t ArcCount;
+ if (!Buff.readInt64(ArcCount)) return false;
+ Block.addCount(ArcCount);
+ --Count;
+ }
}
return true;
}
- LineNumber = Buff.readInt();
+ if (!Buff.readInt(LineNumber)) return false;
// read blocks.
- bool BlockTagFound = Buff.readBlockTag();
- (void)BlockTagFound;
- assert(BlockTagFound && "Block Tag not found!");
- uint32_t BlockCount = Buff.readInt();
- for (int i = 0, e = BlockCount; i != e; ++i) {
- Buff.readInt(); // Block flags;
- Blocks.push_back(new GCOVBlock(i));
+ if (!Buff.readBlockTag()) {
+ errs() << "Block tag not found.\n";
+ return false;
+ }
+ uint32_t BlockCount;
+ if (!Buff.readInt(BlockCount)) return false;
+ for (uint32_t i = 0, e = BlockCount; i != e; ++i) {
+ if (!Buff.readInt(Dummy)) return false; // Block flags;
+ Blocks.push_back(new GCOVBlock(*this, i));
}
// read edges.
while (Buff.readEdgeTag()) {
- uint32_t EdgeCount = (Buff.readInt() - 1) / 2;
- uint32_t BlockNo = Buff.readInt();
- assert(BlockNo < BlockCount && "Unexpected Block number!");
- for (int i = 0, e = EdgeCount; i != e; ++i) {
- Blocks[BlockNo]->addEdge(Buff.readInt());
- Buff.readInt(); // Edge flag
+ uint32_t EdgeCount;
+ if (!Buff.readInt(EdgeCount)) return false;
+ EdgeCount = (EdgeCount - 1) / 2;
+ uint32_t BlockNo;
+ if (!Buff.readInt(BlockNo)) return false;
+ if (BlockNo >= BlockCount) {
+ errs() << "Unexpected block number.\n";
+ return false;
+ }
+ for (uint32_t i = 0, e = EdgeCount; i != e; ++i) {
+ uint32_t Dst;
+ if (!Buff.readInt(Dst)) return false;
+ Blocks[BlockNo]->addEdge(Dst);
+ if (!Buff.readInt(Dummy)) return false; // Edge flag
}
}
// read line table.
while (Buff.readLineTag()) {
- uint32_t LineTableLength = Buff.readInt();
- uint32_t Size = Buff.getCursor() + LineTableLength*4;
- uint32_t BlockNo = Buff.readInt();
- assert(BlockNo < BlockCount && "Unexpected Block number!");
+ uint32_t LineTableLength;
+ if (!Buff.readInt(LineTableLength)) return false;
+ uint32_t EndPos = Buff.getCursor() + LineTableLength*4;
+ uint32_t BlockNo;
+ if (!Buff.readInt(BlockNo)) return false;
+ if (BlockNo >= BlockCount) {
+ errs() << "Unexpected block number.\n";
+ return false;
+ }
GCOVBlock *Block = Blocks[BlockNo];
- Buff.readInt(); // flag
- while (Buff.getCursor() != (Size - 4)) {
- StringRef Filename = Buff.readString();
- if (Buff.getCursor() == (Size - 4)) break;
- while (uint32_t L = Buff.readInt())
- Block->addLine(Filename, L);
+ if (!Buff.readInt(Dummy)) return false; // flag
+ while (Buff.getCursor() != (EndPos - 4)) {
+ StringRef F;
+ if (!Buff.readString(F)) return false;
+ if (F != Filename) {
+ errs() << "Multiple sources for a single basic block.\n";
+ return false;
+ }
+ if (Buff.getCursor() == (EndPos - 4)) break;
+ while (true) {
+ uint32_t Line;
+ if (!Buff.readInt(Line)) return false;
+ if (!Line) break;
+ Block->addLine(Line);
+ }
}
- Buff.readInt(); // flag
+ if (!Buff.readInt(Dummy)) return false; // flag
}
return true;
}
-/// dump - Dump GCOVFunction content on standard out for debugging purposes.
+/// dump - Dump GCOVFunction content to dbgs() for debugging purposes.
void GCOVFunction::dump() {
- outs() << "===== " << Name << " @ " << Filename << ":" << LineNumber << "\n";
+ dbgs() << "===== " << Name << " @ " << Filename << ":" << LineNumber << "\n";
for (SmallVectorImpl<GCOVBlock *>::iterator I = Blocks.begin(),
E = Blocks.end(); I != E; ++I)
(*I)->dump();
@@ -174,110 +242,73 @@ void GCOVFunction::collectLineCounts(FileInfo &FI) {
/// ~GCOVBlock - Delete GCOVBlock and its content.
GCOVBlock::~GCOVBlock() {
Edges.clear();
- DeleteContainerSeconds(Lines);
-}
-
-void GCOVBlock::addLine(StringRef Filename, uint32_t LineNo) {
- GCOVLines *&LinesForFile = Lines[Filename];
- if (!LinesForFile)
- LinesForFile = new GCOVLines();
- LinesForFile->add(LineNo);
+ Lines.clear();
}
/// collectLineCounts - Collect line counts. This must be used after
/// reading .gcno and .gcda files.
void GCOVBlock::collectLineCounts(FileInfo &FI) {
- for (StringMap<GCOVLines *>::iterator I = Lines.begin(),
+ for (SmallVectorImpl<uint32_t>::iterator I = Lines.begin(),
E = Lines.end(); I != E; ++I)
- I->second->collectLineCounts(FI, I->first(), Counter);
+ FI.addLineCount(Parent.getFilename(), *I, Counter);
}
-/// dump - Dump GCOVBlock content on standard out for debugging purposes.
+/// dump - Dump GCOVBlock content to dbgs() for debugging purposes.
void GCOVBlock::dump() {
- outs() << "Block : " << Number << " Counter : " << Counter << "\n";
+ dbgs() << "Block : " << Number << " Counter : " << Counter << "\n";
if (!Edges.empty()) {
- outs() << "\tEdges : ";
+ dbgs() << "\tEdges : ";
for (SmallVectorImpl<uint32_t>::iterator I = Edges.begin(), E = Edges.end();
I != E; ++I)
- outs() << (*I) << ",";
- outs() << "\n";
+ dbgs() << (*I) << ",";
+ dbgs() << "\n";
}
if (!Lines.empty()) {
- outs() << "\tLines : ";
- for (StringMap<GCOVLines *>::iterator LI = Lines.begin(),
- LE = Lines.end(); LI != LE; ++LI) {
- outs() << LI->first() << " -> ";
- LI->second->dump();
- outs() << "\n";
- }
+ dbgs() << "\tLines : ";
+ for (SmallVectorImpl<uint32_t>::iterator I = Lines.begin(),
+ E = Lines.end(); I != E; ++I)
+ dbgs() << (*I) << ",";
+ dbgs() << "\n";
}
}
//===----------------------------------------------------------------------===//
-// GCOVLines implementation.
-
-/// collectLineCounts - Collect line counts. This must be used after
-/// reading .gcno and .gcda files.
-void GCOVLines::collectLineCounts(FileInfo &FI, StringRef Filename,
- uint32_t Count) {
- for (SmallVectorImpl<uint32_t>::iterator I = Lines.begin(),
- E = Lines.end(); I != E; ++I)
- FI.addLineCount(Filename, *I, Count);
-}
-
-/// dump - Dump GCOVLines content on standard out for debugging purposes.
-void GCOVLines::dump() {
- for (SmallVectorImpl<uint32_t>::iterator I = Lines.begin(),
- E = Lines.end(); I != E; ++I)
- outs() << (*I) << ",";
-}
-
-//===----------------------------------------------------------------------===//
// FileInfo implementation.
-/// addLineCount - Add line count for the given line number in a file.
-void FileInfo::addLineCount(StringRef Filename, uint32_t Line, uint32_t Count) {
- if (LineInfo.find(Filename) == LineInfo.end()) {
- OwningPtr<MemoryBuffer> Buff;
- if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
- errs() << Filename << ": " << ec.message() << "\n";
- return;
- }
- StringRef AllLines = Buff.take()->getBuffer();
- LineCounts L(AllLines.count('\n')+2);
- L[Line-1] = Count;
- LineInfo[Filename] = L;
- return;
- }
- LineCounts &L = LineInfo[Filename];
- L[Line-1] = Count;
-}
-
/// print - Print source files with collected line count information.
-void FileInfo::print() {
+void FileInfo::print(raw_fd_ostream &OS, StringRef gcnoFile,
+ StringRef gcdaFile) {
for (StringMap<LineCounts>::iterator I = LineInfo.begin(), E = LineInfo.end();
I != E; ++I) {
StringRef Filename = I->first();
- outs() << Filename << "\n";
+ OS << " -: 0:Source:" << Filename << "\n";
+ OS << " -: 0:Graph:" << gcnoFile << "\n";
+ OS << " -: 0:Data:" << gcdaFile << "\n";
+ OS << " -: 0:Runs:" << RunCount << "\n";
+ OS << " -: 0:Programs:" << ProgramCount << "\n";
LineCounts &L = LineInfo[Filename];
OwningPtr<MemoryBuffer> Buff;
if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
errs() << Filename << ": " << ec.message() << "\n";
return;
}
- StringRef AllLines = Buff.take()->getBuffer();
- for (unsigned i = 0, e = L.size(); i != e; ++i) {
- if (L[i])
- outs() << L[i] << ":\t";
- else
- outs() << " :\t";
+ StringRef AllLines = Buff->getBuffer();
+ uint32_t i = 0;
+ while (!AllLines.empty()) {
+ if (L.find(i) != L.end()) {
+ if (L[i] == 0)
+ OS << " #####:";
+ else
+ OS << format("%9" PRIu64 ":", L[i]);
+ } else {
+ OS << " -:";
+ }
std::pair<StringRef, StringRef> P = AllLines.split('\n');
if (AllLines != P.first)
- outs() << P.first;
- outs() << "\n";
+ OS << format("%5u:", i+1) << P.first;
+ OS << "\n";
AllLines = P.second;
+ ++i;
}
}
}
-
-
diff --git a/lib/IR/Globals.cpp b/lib/IR/Globals.cpp
index 6d547f3..da3b02a 100644
--- a/lib/IR/Globals.cpp
+++ b/lib/IR/Globals.cpp
@@ -229,14 +229,14 @@ void GlobalAlias::setAliasee(Constant *Aliasee) {
setOperand(0, Aliasee);
}
-const GlobalValue *GlobalAlias::getAliasedGlobal() const {
- const Constant *C = getAliasee();
+GlobalValue *GlobalAlias::getAliasedGlobal() {
+ Constant *C = getAliasee();
if (C == 0) return 0;
- if (const GlobalValue *GV = dyn_cast<GlobalValue>(C))
+ if (GlobalValue *GV = dyn_cast<GlobalValue>(C))
return GV;
- const ConstantExpr *CE = cast<ConstantExpr>(C);
+ ConstantExpr *CE = cast<ConstantExpr>(C);
assert((CE->getOpcode() == Instruction::BitCast ||
CE->getOpcode() == Instruction::GetElementPtr) &&
"Unsupported aliasee");
@@ -244,18 +244,18 @@ const GlobalValue *GlobalAlias::getAliasedGlobal() const {
return cast<GlobalValue>(CE->getOperand(0));
}
-const GlobalValue *GlobalAlias::resolveAliasedGlobal(bool stopOnWeak) const {
- SmallPtrSet<const GlobalValue*, 3> Visited;
+GlobalValue *GlobalAlias::resolveAliasedGlobal(bool stopOnWeak) {
+ SmallPtrSet<GlobalValue*, 3> Visited;
// Check if we need to stop early.
if (stopOnWeak && mayBeOverridden())
return this;
- const GlobalValue *GV = getAliasedGlobal();
+ GlobalValue *GV = getAliasedGlobal();
Visited.insert(GV);
// Iterate over aliasing chain, stopping on weak alias if necessary.
- while (const GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) {
+ while (GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) {
if (stopOnWeak && GA->mayBeOverridden())
break;
diff --git a/lib/IR/Instruction.cpp b/lib/IR/Instruction.cpp
index 2b5a0b3..a7773c4 100644
--- a/lib/IR/Instruction.cpp
+++ b/lib/IR/Instruction.cpp
@@ -223,18 +223,19 @@ const char *Instruction::getOpcodeName(unsigned OpCode) {
case GetElementPtr: return "getelementptr";
// Convert instructions...
- case Trunc: return "trunc";
- case ZExt: return "zext";
- case SExt: return "sext";
- case FPTrunc: return "fptrunc";
- case FPExt: return "fpext";
- case FPToUI: return "fptoui";
- case FPToSI: return "fptosi";
- case UIToFP: return "uitofp";
- case SIToFP: return "sitofp";
- case IntToPtr: return "inttoptr";
- case PtrToInt: return "ptrtoint";
- case BitCast: return "bitcast";
+ case Trunc: return "trunc";
+ case ZExt: return "zext";
+ case SExt: return "sext";
+ case FPTrunc: return "fptrunc";
+ case FPExt: return "fpext";
+ case FPToUI: return "fptoui";
+ case FPToSI: return "fptosi";
+ case UIToFP: return "uitofp";
+ case SIToFP: return "sitofp";
+ case IntToPtr: return "inttoptr";
+ case PtrToInt: return "ptrtoint";
+ case BitCast: return "bitcast";
+ case AddrSpaceCast: return "addrspacecast";
// Other instructions...
case ICmp: return "icmp";
diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp
index 205cb43..8a6b77b 100644
--- a/lib/IR/Instructions.cpp
+++ b/lib/IR/Instructions.cpp
@@ -2095,7 +2095,9 @@ bool CastInst::isNoopCast(Instruction::CastOps Opcode,
case Instruction::SIToFP:
case Instruction::FPToUI:
case Instruction::FPToSI:
- return false; // These always modify bits
+ case Instruction::AddrSpaceCast:
+ // TODO: Target informations may give a more accurate answer here.
+ return false;
case Instruction::BitCast:
return true; // BitCast never modifies bits.
case Instruction::PtrToInt:
@@ -2137,44 +2139,46 @@ unsigned CastInst::isEliminableCastPair(
// ZEXT < Integral Unsigned Integer Any
// SEXT < Integral Signed Integer Any
// FPTOUI n/a FloatPt n/a Integral Unsigned
- // FPTOSI n/a FloatPt n/a Integral Signed
- // UITOFP n/a Integral Unsigned FloatPt n/a
- // SITOFP n/a Integral Signed FloatPt n/a
- // FPTRUNC > FloatPt n/a FloatPt n/a
- // FPEXT < FloatPt n/a FloatPt n/a
+ // FPTOSI n/a FloatPt n/a Integral Signed
+ // UITOFP n/a Integral Unsigned FloatPt n/a
+ // SITOFP n/a Integral Signed FloatPt n/a
+ // FPTRUNC > FloatPt n/a FloatPt n/a
+ // FPEXT < FloatPt n/a FloatPt n/a
// PTRTOINT n/a Pointer n/a Integral Unsigned
// INTTOPTR n/a Integral Unsigned Pointer n/a
- // BITCAST = FirstClass n/a FirstClass n/a
+ // BITCAST = FirstClass n/a FirstClass n/a
+ // ADDRSPCST n/a Pointer n/a Pointer n/a
//
// NOTE: some transforms are safe, but we consider them to be non-profitable.
// For example, we could merge "fptoui double to i32" + "zext i32 to i64",
// into "fptoui double to i64", but this loses information about the range
- // of the produced value (we no longer know the top-part is all zeros).
+ // of the produced value (we no longer know the top-part is all zeros).
// Further this conversion is often much more expensive for typical hardware,
- // and causes issues when building libgcc. We disallow fptosi+sext for the
+ // and causes issues when building libgcc. We disallow fptosi+sext for the
// same reason.
- const unsigned numCastOps =
+ const unsigned numCastOps =
Instruction::CastOpsEnd - Instruction::CastOpsBegin;
static const uint8_t CastResults[numCastOps][numCastOps] = {
- // T F F U S F F P I B -+
- // R Z S P P I I T P 2 N T |
- // U E E 2 2 2 2 R E I T C +- secondOp
- // N X X U S F F N X N 2 V |
- // C T T I I P P C T T P T -+
- { 1, 0, 0,99,99, 0, 0,99,99,99, 0, 3 }, // Trunc -+
- { 8, 1, 9,99,99, 2, 0,99,99,99, 2, 3 }, // ZExt |
- { 8, 0, 1,99,99, 0, 2,99,99,99, 0, 3 }, // SExt |
- { 0, 0, 0,99,99, 0, 0,99,99,99, 0, 3 }, // FPToUI |
- { 0, 0, 0,99,99, 0, 0,99,99,99, 0, 3 }, // FPToSI |
- { 99,99,99, 0, 0,99,99, 0, 0,99,99, 4 }, // UIToFP +- firstOp
- { 99,99,99, 0, 0,99,99, 0, 0,99,99, 4 }, // SIToFP |
- { 99,99,99, 0, 0,99,99, 1, 0,99,99, 4 }, // FPTrunc |
- { 99,99,99, 2, 2,99,99,10, 2,99,99, 4 }, // FPExt |
- { 1, 0, 0,99,99, 0, 0,99,99,99, 7, 3 }, // PtrToInt |
- { 99,99,99,99,99,99,99,99,99,13,99,12 }, // IntToPtr |
- { 5, 5, 5, 6, 6, 5, 5, 6, 6,11, 5, 1 }, // BitCast -+
+ // T F F U S F F P I B A -+
+ // R Z S P P I I T P 2 N T S |
+ // U E E 2 2 2 2 R E I T C C +- secondOp
+ // N X X U S F F N X N 2 V V |
+ // C T T I I P P C T T P T T -+
+ { 1, 0, 0,99,99, 0, 0,99,99,99, 0, 3, 0}, // Trunc -+
+ { 8, 1, 9,99,99, 2, 0,99,99,99, 2, 3, 0}, // ZExt |
+ { 8, 0, 1,99,99, 0, 2,99,99,99, 0, 3, 0}, // SExt |
+ { 0, 0, 0,99,99, 0, 0,99,99,99, 0, 3, 0}, // FPToUI |
+ { 0, 0, 0,99,99, 0, 0,99,99,99, 0, 3, 0}, // FPToSI |
+ { 99,99,99, 0, 0,99,99, 0, 0,99,99, 4, 0}, // UIToFP +- firstOp
+ { 99,99,99, 0, 0,99,99, 0, 0,99,99, 4, 0}, // SIToFP |
+ { 99,99,99, 0, 0,99,99, 1, 0,99,99, 4, 0}, // FPTrunc |
+ { 99,99,99, 2, 2,99,99,10, 2,99,99, 4, 0}, // FPExt |
+ { 1, 0, 0,99,99, 0, 0,99,99,99, 7, 3, 0}, // PtrToInt |
+ { 99,99,99,99,99,99,99,99,99,11,99,15, 0}, // IntToPtr |
+ { 5, 5, 5, 6, 6, 5, 5, 6, 6,16, 5, 1,14}, // BitCast |
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,13,12}, // AddrSpaceCast -+
};
-
+
// If either of the casts are a bitcast from scalar to vector, disallow the
// merging. However, bitcast of A->B->A are allowed.
bool isFirstBitcast = (firstOp == Instruction::BitCast);
@@ -2191,47 +2195,50 @@ unsigned CastInst::isEliminableCastPair(
[secondOp-Instruction::CastOpsBegin];
switch (ElimCase) {
case 0:
- // categorically disallowed
+ // Categorically disallowed.
return 0;
case 1:
- // allowed, use first cast's opcode
+ // Allowed, use first cast's opcode.
return firstOp;
case 2:
- // allowed, use second cast's opcode
+ // Allowed, use second cast's opcode.
return secondOp;
case 3:
- // no-op cast in second op implies firstOp as long as the DestTy
+ // No-op cast in second op implies firstOp as long as the DestTy
// is integer and we are not converting between a vector and a
// non vector type.
if (!SrcTy->isVectorTy() && DstTy->isIntegerTy())
return firstOp;
return 0;
case 4:
- // no-op cast in second op implies firstOp as long as the DestTy
+ // No-op cast in second op implies firstOp as long as the DestTy
// is floating point.
if (DstTy->isFloatingPointTy())
return firstOp;
return 0;
case 5:
- // no-op cast in first op implies secondOp as long as the SrcTy
+ // No-op cast in first op implies secondOp as long as the SrcTy
// is an integer.
if (SrcTy->isIntegerTy())
return secondOp;
return 0;
case 6:
- // no-op cast in first op implies secondOp as long as the SrcTy
+ // No-op cast in first op implies secondOp as long as the SrcTy
// is a floating point.
if (SrcTy->isFloatingPointTy())
return secondOp;
return 0;
case 7: {
+ // Cannot simplify if address spaces are different!
+ if (SrcTy->getPointerAddressSpace() != DstTy->getPointerAddressSpace())
+ return 0;
+
unsigned MidSize = MidTy->getScalarSizeInBits();
- // Check the address spaces first. If we know they are in the same address
- // space, the pointer sizes must be the same so we can still fold this
- // without knowing the actual sizes as long we know that the intermediate
- // pointer is the largest possible pointer size.
- if (MidSize == 64 &&
- SrcTy->getPointerAddressSpace() == DstTy->getPointerAddressSpace())
+ // We can still fold this without knowing the actual sizes as long we
+ // know that the intermediate pointer is the largest possible
+ // pointer size.
+ // FIXME: Is this always true?
+ if (MidSize == 64)
return Instruction::BitCast;
// ptrtoint, inttoptr -> bitcast (ptr -> ptr) if int size is >= ptr size.
@@ -2254,7 +2261,8 @@ unsigned CastInst::isEliminableCastPair(
return firstOp;
return secondOp;
}
- case 9: // zext, sext -> zext, because sext can't sign extend after zext
+ case 9:
+ // zext, sext -> zext, because sext can't sign extend after zext
return Instruction::ZExt;
case 10:
// fpext followed by ftrunc is allowed if the bit size returned to is
@@ -2263,46 +2271,6 @@ unsigned CastInst::isEliminableCastPair(
return Instruction::BitCast;
return 0; // If the types are not the same we can't eliminate it.
case 11: {
- // bitcast followed by ptrtoint is allowed as long as the bitcast is a
- // pointer to pointer cast, and the pointers are the same size.
- PointerType *SrcPtrTy = dyn_cast<PointerType>(SrcTy);
- PointerType *MidPtrTy = dyn_cast<PointerType>(MidTy);
- if (!SrcPtrTy || !MidPtrTy)
- return 0;
-
- // If the address spaces are the same, we know they are the same size
- // without size information
- if (SrcPtrTy->getAddressSpace() == MidPtrTy->getAddressSpace())
- return secondOp;
-
- if (!SrcIntPtrTy || !MidIntPtrTy)
- return 0;
-
- if (SrcIntPtrTy->getScalarSizeInBits() ==
- MidIntPtrTy->getScalarSizeInBits())
- return secondOp;
-
- return 0;
- }
- case 12: {
- // inttoptr, bitcast -> inttoptr if bitcast is a ptr to ptr cast
- // and the ptrs are to address spaces of the same size
- PointerType *MidPtrTy = dyn_cast<PointerType>(MidTy);
- PointerType *DstPtrTy = dyn_cast<PointerType>(DstTy);
- if (!MidPtrTy || !DstPtrTy)
- return 0;
-
- if (MidPtrTy->getAddressSpace() == DstPtrTy->getAddressSpace())
- return firstOp;
-
- if (MidIntPtrTy &&
- DstIntPtrTy &&
- MidIntPtrTy->getScalarSizeInBits() ==
- DstIntPtrTy->getScalarSizeInBits())
- return firstOp;
- return 0;
- }
- case 13: {
// inttoptr, ptrtoint -> bitcast if SrcSize<=PtrSize and SrcSize==DstSize
if (!MidIntPtrTy)
return 0;
@@ -2313,8 +2281,65 @@ unsigned CastInst::isEliminableCastPair(
return Instruction::BitCast;
return 0;
}
+ case 12: {
+ // addrspacecast, addrspacecast -> bitcast, if SrcAS == DstAS
+ // addrspacecast, addrspacecast -> addrspacecast, if SrcAS != DstAS
+ if (SrcTy->getPointerAddressSpace() != DstTy->getPointerAddressSpace())
+ return Instruction::AddrSpaceCast;
+ return Instruction::BitCast;
+ }
+ case 13:
+ // FIXME: this state can be merged with (1), but the following assert
+ // is useful to check the correcteness of the sequence due to semantic
+ // change of bitcast.
+ assert(
+ SrcTy->isPtrOrPtrVectorTy() &&
+ MidTy->isPtrOrPtrVectorTy() &&
+ DstTy->isPtrOrPtrVectorTy() &&
+ SrcTy->getPointerAddressSpace() != MidTy->getPointerAddressSpace() &&
+ MidTy->getPointerAddressSpace() == DstTy->getPointerAddressSpace() &&
+ "Illegal addrspacecast, bitcast sequence!");
+ // Allowed, use first cast's opcode
+ return firstOp;
+ case 14:
+ // FIXME: this state can be merged with (2), but the following assert
+ // is useful to check the correcteness of the sequence due to semantic
+ // change of bitcast.
+ assert(
+ SrcTy->isPtrOrPtrVectorTy() &&
+ MidTy->isPtrOrPtrVectorTy() &&
+ DstTy->isPtrOrPtrVectorTy() &&
+ SrcTy->getPointerAddressSpace() == MidTy->getPointerAddressSpace() &&
+ MidTy->getPointerAddressSpace() != DstTy->getPointerAddressSpace() &&
+ "Illegal bitcast, addrspacecast sequence!");
+ // Allowed, use second cast's opcode
+ return secondOp;
+ case 15:
+ // FIXME: this state can be merged with (1), but the following assert
+ // is useful to check the correcteness of the sequence due to semantic
+ // change of bitcast.
+ assert(
+ SrcTy->isIntOrIntVectorTy() &&
+ MidTy->isPtrOrPtrVectorTy() &&
+ DstTy->isPtrOrPtrVectorTy() &&
+ MidTy->getPointerAddressSpace() == DstTy->getPointerAddressSpace() &&
+ "Illegal inttoptr, bitcast sequence!");
+ // Allowed, use first cast's opcode
+ return firstOp;
+ case 16:
+ // FIXME: this state can be merged with (2), but the following assert
+ // is useful to check the correcteness of the sequence due to semantic
+ // change of bitcast.
+ assert(
+ SrcTy->isPtrOrPtrVectorTy() &&
+ MidTy->isPtrOrPtrVectorTy() &&
+ DstTy->isIntOrIntVectorTy() &&
+ SrcTy->getPointerAddressSpace() == MidTy->getPointerAddressSpace() &&
+ "Illegal bitcast, ptrtoint sequence!");
+ // Allowed, use second cast's opcode
+ return secondOp;
case 99:
- // cast combination can't happen (error in input). This is for all cases
+ // Cast combination can't happen (error in input). This is for all cases
// where the MidTy is not the same for the two cast instructions.
llvm_unreachable("Invalid Cast Combination");
default:
@@ -2327,19 +2352,20 @@ CastInst *CastInst::Create(Instruction::CastOps op, Value *S, Type *Ty,
assert(castIsValid(op, S, Ty) && "Invalid cast!");
// Construct and return the appropriate CastInst subclass
switch (op) {
- case Trunc: return new TruncInst (S, Ty, Name, InsertBefore);
- case ZExt: return new ZExtInst (S, Ty, Name, InsertBefore);
- case SExt: return new SExtInst (S, Ty, Name, InsertBefore);
- case FPTrunc: return new FPTruncInst (S, Ty, Name, InsertBefore);
- case FPExt: return new FPExtInst (S, Ty, Name, InsertBefore);
- case UIToFP: return new UIToFPInst (S, Ty, Name, InsertBefore);
- case SIToFP: return new SIToFPInst (S, Ty, Name, InsertBefore);
- case FPToUI: return new FPToUIInst (S, Ty, Name, InsertBefore);
- case FPToSI: return new FPToSIInst (S, Ty, Name, InsertBefore);
- case PtrToInt: return new PtrToIntInst (S, Ty, Name, InsertBefore);
- case IntToPtr: return new IntToPtrInst (S, Ty, Name, InsertBefore);
- case BitCast: return new BitCastInst (S, Ty, Name, InsertBefore);
- default: llvm_unreachable("Invalid opcode provided");
+ case Trunc: return new TruncInst (S, Ty, Name, InsertBefore);
+ case ZExt: return new ZExtInst (S, Ty, Name, InsertBefore);
+ case SExt: return new SExtInst (S, Ty, Name, InsertBefore);
+ case FPTrunc: return new FPTruncInst (S, Ty, Name, InsertBefore);
+ case FPExt: return new FPExtInst (S, Ty, Name, InsertBefore);
+ case UIToFP: return new UIToFPInst (S, Ty, Name, InsertBefore);
+ case SIToFP: return new SIToFPInst (S, Ty, Name, InsertBefore);
+ case FPToUI: return new FPToUIInst (S, Ty, Name, InsertBefore);
+ case FPToSI: return new FPToSIInst (S, Ty, Name, InsertBefore);
+ case PtrToInt: return new PtrToIntInst (S, Ty, Name, InsertBefore);
+ case IntToPtr: return new IntToPtrInst (S, Ty, Name, InsertBefore);
+ case BitCast: return new BitCastInst (S, Ty, Name, InsertBefore);
+ case AddrSpaceCast: return new AddrSpaceCastInst (S, Ty, Name, InsertBefore);
+ default: llvm_unreachable("Invalid opcode provided");
}
}
@@ -2348,19 +2374,20 @@ CastInst *CastInst::Create(Instruction::CastOps op, Value *S, Type *Ty,
assert(castIsValid(op, S, Ty) && "Invalid cast!");
// Construct and return the appropriate CastInst subclass
switch (op) {
- case Trunc: return new TruncInst (S, Ty, Name, InsertAtEnd);
- case ZExt: return new ZExtInst (S, Ty, Name, InsertAtEnd);
- case SExt: return new SExtInst (S, Ty, Name, InsertAtEnd);
- case FPTrunc: return new FPTruncInst (S, Ty, Name, InsertAtEnd);
- case FPExt: return new FPExtInst (S, Ty, Name, InsertAtEnd);
- case UIToFP: return new UIToFPInst (S, Ty, Name, InsertAtEnd);
- case SIToFP: return new SIToFPInst (S, Ty, Name, InsertAtEnd);
- case FPToUI: return new FPToUIInst (S, Ty, Name, InsertAtEnd);
- case FPToSI: return new FPToSIInst (S, Ty, Name, InsertAtEnd);
- case PtrToInt: return new PtrToIntInst (S, Ty, Name, InsertAtEnd);
- case IntToPtr: return new IntToPtrInst (S, Ty, Name, InsertAtEnd);
- case BitCast: return new BitCastInst (S, Ty, Name, InsertAtEnd);
- default: llvm_unreachable("Invalid opcode provided");
+ case Trunc: return new TruncInst (S, Ty, Name, InsertAtEnd);
+ case ZExt: return new ZExtInst (S, Ty, Name, InsertAtEnd);
+ case SExt: return new SExtInst (S, Ty, Name, InsertAtEnd);
+ case FPTrunc: return new FPTruncInst (S, Ty, Name, InsertAtEnd);
+ case FPExt: return new FPExtInst (S, Ty, Name, InsertAtEnd);
+ case UIToFP: return new UIToFPInst (S, Ty, Name, InsertAtEnd);
+ case SIToFP: return new SIToFPInst (S, Ty, Name, InsertAtEnd);
+ case FPToUI: return new FPToUIInst (S, Ty, Name, InsertAtEnd);
+ case FPToSI: return new FPToSIInst (S, Ty, Name, InsertAtEnd);
+ case PtrToInt: return new PtrToIntInst (S, Ty, Name, InsertAtEnd);
+ case IntToPtr: return new IntToPtrInst (S, Ty, Name, InsertAtEnd);
+ case BitCast: return new BitCastInst (S, Ty, Name, InsertAtEnd);
+ case AddrSpaceCast: return new AddrSpaceCastInst (S, Ty, Name, InsertAtEnd);
+ default: llvm_unreachable("Invalid opcode provided");
}
}
@@ -2425,6 +2452,11 @@ 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);
}
@@ -2442,6 +2474,11 @@ 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 Create(Instruction::AddrSpaceCast, S, Ty, Name, InsertBefore);
+
return Create(Instruction::BitCast, S, Ty, Name, InsertBefore);
}
@@ -2687,7 +2724,8 @@ CastInst::getCastOpcode(
return BitCast;
} else if (DestTy->isPointerTy()) {
if (SrcTy->isPointerTy()) {
- // TODO: Address space pointer sizes may not match
+ if (DestTy->getPointerAddressSpace() != SrcTy->getPointerAddressSpace())
+ return AddrSpaceCast;
return BitCast; // ptr -> ptr
} else if (SrcTy->isIntegerTy()) {
return IntToPtr; // int -> ptr
@@ -2782,13 +2820,27 @@ CastInst::castIsValid(Instruction::CastOps op, Value *S, Type *DstTy) {
case Instruction::BitCast:
// BitCast implies a no-op cast of type only. No bits change.
// However, you can't cast pointers to anything but pointers.
- if (SrcTy->isPointerTy() != DstTy->isPointerTy())
+ if (SrcTy->isPtrOrPtrVectorTy() != DstTy->isPtrOrPtrVectorTy())
return false;
- // Now we know we're not dealing with a pointer/non-pointer mismatch. In all
- // these cases, the cast is okay if the source and destination bit widths
- // are identical.
- return SrcTy->getPrimitiveSizeInBits() == DstTy->getPrimitiveSizeInBits();
+ // For non pointer cases, the cast is okay if the source and destination bit
+ // widths are identical.
+ if (!SrcTy->isPtrOrPtrVectorTy())
+ return SrcTy->getPrimitiveSizeInBits() == DstTy->getPrimitiveSizeInBits();
+
+ // If both are pointers then the address spaces must match and vector of
+ // pointers must have the same number of elements.
+ return SrcTy->getPointerAddressSpace() == DstTy->getPointerAddressSpace() &&
+ SrcTy->isVectorTy() == DstTy->isVectorTy() &&
+ (!SrcTy->isVectorTy() ||
+ SrcTy->getVectorNumElements() == SrcTy->getVectorNumElements());
+
+ case Instruction::AddrSpaceCast:
+ return SrcTy->isPtrOrPtrVectorTy() && DstTy->isPtrOrPtrVectorTy() &&
+ SrcTy->getPointerAddressSpace() != DstTy->getPointerAddressSpace() &&
+ SrcTy->isVectorTy() == DstTy->isVectorTy() &&
+ (!SrcTy->isVectorTy() ||
+ SrcTy->getVectorNumElements() == SrcTy->getVectorNumElements());
}
}
@@ -2935,6 +2987,18 @@ BitCastInst::BitCastInst(
assert(castIsValid(getOpcode(), S, Ty) && "Illegal BitCast");
}
+AddrSpaceCastInst::AddrSpaceCastInst(
+ Value *S, Type *Ty, const Twine &Name, Instruction *InsertBefore
+) : CastInst(Ty, AddrSpaceCast, S, Name, InsertBefore) {
+ assert(castIsValid(getOpcode(), S, Ty) && "Illegal AddrSpaceCast");
+}
+
+AddrSpaceCastInst::AddrSpaceCastInst(
+ Value *S, Type *Ty, const Twine &Name, BasicBlock *InsertAtEnd
+) : CastInst(Ty, AddrSpaceCast, S, Name, InsertAtEnd) {
+ assert(castIsValid(getOpcode(), S, Ty) && "Illegal AddrSpaceCast");
+}
+
//===----------------------------------------------------------------------===//
// CmpInst Classes
//===----------------------------------------------------------------------===//
@@ -3267,7 +3331,6 @@ SwitchInst::SwitchInst(const SwitchInst &SI)
OL[i] = InOL[i];
OL[i+1] = InOL[i+1];
}
- TheSubsets = SI.TheSubsets;
SubclassOptionalData = SI.SubclassOptionalData;
}
@@ -3279,16 +3342,6 @@ SwitchInst::~SwitchInst() {
/// addCase - Add an entry to the switch instruction...
///
void SwitchInst::addCase(ConstantInt *OnVal, BasicBlock *Dest) {
- IntegersSubsetToBB Mapping;
-
- // FIXME: Currently we work with ConstantInt based cases.
- // So inititalize IntItem container directly from ConstantInt.
- Mapping.add(IntItem::fromConstantInt(OnVal));
- IntegersSubset CaseRanges = Mapping.getCase();
- addCase(CaseRanges, Dest);
-}
-
-void SwitchInst::addCase(IntegersSubset& OnVal, BasicBlock *Dest) {
unsigned NewCaseIdx = getNumCases();
unsigned OpNo = NumOperands;
if (OpNo+2 > ReservedSpace)
@@ -3296,17 +3349,14 @@ void SwitchInst::addCase(IntegersSubset& OnVal, BasicBlock *Dest) {
// Initialize some new operands.
assert(OpNo+1 < ReservedSpace && "Growing didn't work!");
NumOperands = OpNo+2;
-
- SubsetsIt TheSubsetsIt = TheSubsets.insert(TheSubsets.end(), OnVal);
-
- CaseIt Case(this, NewCaseIdx, TheSubsetsIt);
- Case.updateCaseValueOperand(OnVal);
+ CaseIt Case(this, NewCaseIdx);
+ Case.setValue(OnVal);
Case.setSuccessor(Dest);
}
/// removeCase - This method removes the specified case and its successor
/// from the switch instruction.
-void SwitchInst::removeCase(CaseIt& i) {
+void SwitchInst::removeCase(CaseIt i) {
unsigned idx = i.getCaseIndex();
assert(2 + idx*2 < getNumOperands() && "Case index out of range!!!");
@@ -3323,16 +3373,6 @@ void SwitchInst::removeCase(CaseIt& i) {
// Nuke the last value.
OL[NumOps-2].set(0);
OL[NumOps-2+1].set(0);
-
- // Do the same with TheCases collection:
- if (i.SubsetIt != --TheSubsets.end()) {
- *i.SubsetIt = TheSubsets.back();
- TheSubsets.pop_back();
- } else {
- TheSubsets.pop_back();
- i.SubsetIt = TheSubsets.end();
- }
-
NumOperands = NumOps-2;
}
@@ -3577,6 +3617,10 @@ BitCastInst *BitCastInst::clone_impl() const {
return new BitCastInst(getOperand(0), getType());
}
+AddrSpaceCastInst *AddrSpaceCastInst::clone_impl() const {
+ return new AddrSpaceCastInst(getOperand(0), getType());
+}
+
CallInst *CallInst::clone_impl() const {
return new(getNumOperands()) CallInst(*this);
}
diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h
index 0c659b8..407b985 100644
--- a/lib/IR/LLVMContextImpl.h
+++ b/lib/IR/LLVMContextImpl.h
@@ -355,6 +355,11 @@ public:
typedef DenseMap<const Function*, unsigned> IntrinsicIDCacheTy;
IntrinsicIDCacheTy IntrinsicIDCache;
+ /// \brief Mapping from a function to its prefix data, which is stored as the
+ /// operand of an unparented ReturnInst so that the prefix data has a Use.
+ typedef DenseMap<const Function *, ReturnInst *> PrefixDataMapTy;
+ PrefixDataMapTy PrefixDataMap;
+
int getOrAddScopeRecordIdxEntry(MDNode *N, int ExistingIdx);
int getOrAddScopeInlinedAtIdxEntry(MDNode *Scope, MDNode *IA,int ExistingIdx);
diff --git a/lib/IR/LegacyPassManager.cpp b/lib/IR/LegacyPassManager.cpp
new file mode 100644
index 0000000..a431d82
--- /dev/null
+++ b/lib/IR/LegacyPassManager.cpp
@@ -0,0 +1,1920 @@
+//===- LegacyPassManager.cpp - LLVM Pass Infrastructure Implementation ----===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the legacy LLVM Pass Manager infrastructure.
+//
+//===----------------------------------------------------------------------===//
+
+
+#include "llvm/Assembly/PrintModulePass.h"
+#include "llvm/Assembly/Writer.h"
+#include "llvm/IR/LegacyPassManager.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/LegacyPassManagers.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/ManagedStatic.h"
+#include "llvm/Support/Mutex.h"
+#include "llvm/Support/PassNameParser.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <map>
+using namespace llvm;
+using namespace llvm::legacy;
+
+// See PassManagers.h for Pass Manager infrastructure overview.
+
+//===----------------------------------------------------------------------===//
+// Pass debugging information. Often it is useful to find out what pass is
+// running when a crash occurs in a utility. When this library is compiled with
+// debugging on, a command line option (--debug-pass) is enabled that causes the
+// pass name to be printed before it executes.
+//
+
+namespace {
+// Different debug levels that can be enabled...
+enum PassDebugLevel {
+ Disabled, Arguments, Structure, Executions, Details
+};
+}
+
+static cl::opt<enum PassDebugLevel>
+PassDebugging("debug-pass", cl::Hidden,
+ cl::desc("Print PassManager debugging information"),
+ cl::values(
+ clEnumVal(Disabled , "disable debug output"),
+ clEnumVal(Arguments , "print pass arguments to pass to 'opt'"),
+ clEnumVal(Structure , "print pass structure before run()"),
+ clEnumVal(Executions, "print pass name before it is executed"),
+ clEnumVal(Details , "print pass details when it is executed"),
+ clEnumValEnd));
+
+namespace {
+typedef llvm::cl::list<const llvm::PassInfo *, bool, PassNameParser>
+PassOptionList;
+}
+
+// Print IR out before/after specified passes.
+static PassOptionList
+PrintBefore("print-before",
+ llvm::cl::desc("Print IR before specified passes"),
+ cl::Hidden);
+
+static PassOptionList
+PrintAfter("print-after",
+ llvm::cl::desc("Print IR after specified passes"),
+ cl::Hidden);
+
+static cl::opt<bool>
+PrintBeforeAll("print-before-all",
+ llvm::cl::desc("Print IR before each pass"),
+ cl::init(false));
+static cl::opt<bool>
+PrintAfterAll("print-after-all",
+ llvm::cl::desc("Print IR after each pass"),
+ cl::init(false));
+
+/// This is a helper to determine whether to print IR before or
+/// after a pass.
+
+static bool ShouldPrintBeforeOrAfterPass(const PassInfo *PI,
+ PassOptionList &PassesToPrint) {
+ for (unsigned i = 0, ie = PassesToPrint.size(); i < ie; ++i) {
+ const llvm::PassInfo *PassInf = PassesToPrint[i];
+ if (PassInf)
+ if (PassInf->getPassArgument() == PI->getPassArgument()) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/// This is a utility to check whether a pass should have IR dumped
+/// before it.
+static bool ShouldPrintBeforePass(const PassInfo *PI) {
+ return PrintBeforeAll || ShouldPrintBeforeOrAfterPass(PI, PrintBefore);
+}
+
+/// This is a utility to check whether a pass should have IR dumped
+/// after it.
+static bool ShouldPrintAfterPass(const PassInfo *PI) {
+ return PrintAfterAll || ShouldPrintBeforeOrAfterPass(PI, PrintAfter);
+}
+
+/// isPassDebuggingExecutionsOrMore - Return true if -debug-pass=Executions
+/// or higher is specified.
+bool PMDataManager::isPassDebuggingExecutionsOrMore() const {
+ return PassDebugging >= Executions;
+}
+
+
+
+
+void PassManagerPrettyStackEntry::print(raw_ostream &OS) const {
+ if (V == 0 && M == 0)
+ OS << "Releasing pass '";
+ else
+ OS << "Running pass '";
+
+ OS << P->getPassName() << "'";
+
+ if (M) {
+ OS << " on module '" << M->getModuleIdentifier() << "'.\n";
+ return;
+ }
+ if (V == 0) {
+ OS << '\n';
+ return;
+ }
+
+ OS << " on ";
+ if (isa<Function>(V))
+ OS << "function";
+ else if (isa<BasicBlock>(V))
+ OS << "basic block";
+ else
+ OS << "value";
+
+ OS << " '";
+ WriteAsOperand(OS, V, /*PrintTy=*/false, M);
+ OS << "'\n";
+}
+
+
+namespace {
+//===----------------------------------------------------------------------===//
+// BBPassManager
+//
+/// BBPassManager manages BasicBlockPass. It batches all the
+/// pass together and sequence them to process one basic block before
+/// processing next basic block.
+class BBPassManager : public PMDataManager, public FunctionPass {
+
+public:
+ static char ID;
+ explicit BBPassManager()
+ : PMDataManager(), FunctionPass(ID) {}
+
+ /// Execute all of the passes scheduled for execution. Keep track of
+ /// whether any of the passes modifies the function, and if so, return true.
+ bool runOnFunction(Function &F);
+
+ /// Pass Manager itself does not invalidate any analysis info.
+ void getAnalysisUsage(AnalysisUsage &Info) const {
+ Info.setPreservesAll();
+ }
+
+ bool doInitialization(Module &M);
+ bool doInitialization(Function &F);
+ bool doFinalization(Module &M);
+ bool doFinalization(Function &F);
+
+ virtual PMDataManager *getAsPMDataManager() { return this; }
+ virtual Pass *getAsPass() { return this; }
+
+ virtual const char *getPassName() const {
+ return "BasicBlock Pass Manager";
+ }
+
+ // Print passes managed by this manager
+ void dumpPassStructure(unsigned Offset) {
+ llvm::dbgs().indent(Offset*2) << "BasicBlockPass Manager\n";
+ for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
+ BasicBlockPass *BP = getContainedPass(Index);
+ BP->dumpPassStructure(Offset + 1);
+ dumpLastUses(BP, Offset+1);
+ }
+ }
+
+ BasicBlockPass *getContainedPass(unsigned N) {
+ assert(N < PassVector.size() && "Pass number out of range!");
+ BasicBlockPass *BP = static_cast<BasicBlockPass *>(PassVector[N]);
+ return BP;
+ }
+
+ virtual PassManagerType getPassManagerType() const {
+ return PMT_BasicBlockPassManager;
+ }
+};
+
+char BBPassManager::ID = 0;
+} // End anonymous namespace
+
+namespace llvm {
+namespace legacy {
+//===----------------------------------------------------------------------===//
+// FunctionPassManagerImpl
+//
+/// FunctionPassManagerImpl manages FPPassManagers
+class FunctionPassManagerImpl : public Pass,
+ public PMDataManager,
+ public PMTopLevelManager {
+ virtual void anchor();
+private:
+ bool wasRun;
+public:
+ static char ID;
+ explicit FunctionPassManagerImpl() :
+ Pass(PT_PassManager, ID), PMDataManager(),
+ PMTopLevelManager(new FPPassManager()), wasRun(false) {}
+
+ /// add - Add a pass to the queue of passes to run. This passes ownership of
+ /// the Pass to the PassManager. When the PassManager is destroyed, the pass
+ /// will be destroyed as well, so there is no need to delete the pass. This
+ /// implies that all passes MUST be allocated with 'new'.
+ void add(Pass *P) {
+ schedulePass(P);
+ }
+
+ /// createPrinterPass - Get a function printer pass.
+ Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const {
+ return createPrintFunctionPass(Banner, &O);
+ }
+
+ // Prepare for running an on the fly pass, freeing memory if needed
+ // from a previous run.
+ void releaseMemoryOnTheFly();
+
+ /// run - Execute all of the passes scheduled for execution. Keep track of
+ /// whether any of the passes modifies the module, and if so, return true.
+ bool run(Function &F);
+
+ /// doInitialization - Run all of the initializers for the function passes.
+ ///
+ bool doInitialization(Module &M);
+
+ /// doFinalization - Run all of the finalizers for the function passes.
+ ///
+ bool doFinalization(Module &M);
+
+
+ virtual PMDataManager *getAsPMDataManager() { return this; }
+ virtual Pass *getAsPass() { return this; }
+ virtual PassManagerType getTopLevelPassManagerType() {
+ return PMT_FunctionPassManager;
+ }
+
+ /// Pass Manager itself does not invalidate any analysis info.
+ void getAnalysisUsage(AnalysisUsage &Info) const {
+ Info.setPreservesAll();
+ }
+
+ FPPassManager *getContainedManager(unsigned N) {
+ assert(N < PassManagers.size() && "Pass number out of range!");
+ FPPassManager *FP = static_cast<FPPassManager *>(PassManagers[N]);
+ return FP;
+ }
+};
+
+void FunctionPassManagerImpl::anchor() {}
+
+char FunctionPassManagerImpl::ID = 0;
+} // End of legacy namespace
+} // End of llvm namespace
+
+namespace {
+//===----------------------------------------------------------------------===//
+// MPPassManager
+//
+/// MPPassManager manages ModulePasses and function pass managers.
+/// It batches all Module passes and function pass managers together and
+/// sequences them to process one module.
+class MPPassManager : public Pass, public PMDataManager {
+public:
+ static char ID;
+ explicit MPPassManager() :
+ Pass(PT_PassManager, ID), PMDataManager() { }
+
+ // Delete on the fly managers.
+ virtual ~MPPassManager() {
+ for (std::map<Pass *, FunctionPassManagerImpl *>::iterator
+ I = OnTheFlyManagers.begin(), E = OnTheFlyManagers.end();
+ I != E; ++I) {
+ FunctionPassManagerImpl *FPP = I->second;
+ delete FPP;
+ }
+ }
+
+ /// createPrinterPass - Get a module printer pass.
+ Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const {
+ return createPrintModulePass(&O, false, Banner);
+ }
+
+ /// run - Execute all of the passes scheduled for execution. Keep track of
+ /// whether any of the passes modifies the module, and if so, return true.
+ bool runOnModule(Module &M);
+
+ using llvm::Pass::doInitialization;
+ using llvm::Pass::doFinalization;
+
+ /// doInitialization - Run all of the initializers for the module passes.
+ ///
+ bool doInitialization();
+
+ /// doFinalization - Run all of the finalizers for the module passes.
+ ///
+ bool doFinalization();
+
+ /// Pass Manager itself does not invalidate any analysis info.
+ void getAnalysisUsage(AnalysisUsage &Info) const {
+ Info.setPreservesAll();
+ }
+
+ /// Add RequiredPass into list of lower level passes required by pass P.
+ /// RequiredPass is run on the fly by Pass Manager when P requests it
+ /// through getAnalysis interface.
+ virtual void addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass);
+
+ /// Return function pass corresponding to PassInfo PI, that is
+ /// required by module pass MP. Instantiate analysis pass, by using
+ /// its runOnFunction() for function F.
+ virtual Pass* getOnTheFlyPass(Pass *MP, AnalysisID PI, Function &F);
+
+ virtual const char *getPassName() const {
+ return "Module Pass Manager";
+ }
+
+ virtual PMDataManager *getAsPMDataManager() { return this; }
+ virtual Pass *getAsPass() { return this; }
+
+ // Print passes managed by this manager
+ void dumpPassStructure(unsigned Offset) {
+ llvm::dbgs().indent(Offset*2) << "ModulePass Manager\n";
+ for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
+ ModulePass *MP = getContainedPass(Index);
+ MP->dumpPassStructure(Offset + 1);
+ std::map<Pass *, FunctionPassManagerImpl *>::const_iterator I =
+ OnTheFlyManagers.find(MP);
+ if (I != OnTheFlyManagers.end())
+ I->second->dumpPassStructure(Offset + 2);
+ dumpLastUses(MP, Offset+1);
+ }
+ }
+
+ ModulePass *getContainedPass(unsigned N) {
+ assert(N < PassVector.size() && "Pass number out of range!");
+ return static_cast<ModulePass *>(PassVector[N]);
+ }
+
+ virtual PassManagerType getPassManagerType() const {
+ return PMT_ModulePassManager;
+ }
+
+ private:
+ /// Collection of on the fly FPPassManagers. These managers manage
+ /// function passes that are required by module passes.
+ std::map<Pass *, FunctionPassManagerImpl *> OnTheFlyManagers;
+};
+
+char MPPassManager::ID = 0;
+} // End anonymous namespace
+
+namespace llvm {
+namespace legacy {
+//===----------------------------------------------------------------------===//
+// PassManagerImpl
+//
+
+/// PassManagerImpl manages MPPassManagers
+class PassManagerImpl : public Pass,
+ public PMDataManager,
+ public PMTopLevelManager {
+ virtual void anchor();
+
+public:
+ static char ID;
+ explicit PassManagerImpl() :
+ Pass(PT_PassManager, ID), PMDataManager(),
+ PMTopLevelManager(new MPPassManager()) {}
+
+ /// add - Add a pass to the queue of passes to run. This passes ownership of
+ /// the Pass to the PassManager. When the PassManager is destroyed, the pass
+ /// will be destroyed as well, so there is no need to delete the pass. This
+ /// implies that all passes MUST be allocated with 'new'.
+ void add(Pass *P) {
+ schedulePass(P);
+ }
+
+ /// createPrinterPass - Get a module printer pass.
+ Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const {
+ return createPrintModulePass(&O, false, Banner);
+ }
+
+ /// run - Execute all of the passes scheduled for execution. Keep track of
+ /// whether any of the passes modifies the module, and if so, return true.
+ bool run(Module &M);
+
+ using llvm::Pass::doInitialization;
+ using llvm::Pass::doFinalization;
+
+ /// doInitialization - Run all of the initializers for the module passes.
+ ///
+ bool doInitialization();
+
+ /// doFinalization - Run all of the finalizers for the module passes.
+ ///
+ bool doFinalization();
+
+ /// Pass Manager itself does not invalidate any analysis info.
+ void getAnalysisUsage(AnalysisUsage &Info) const {
+ Info.setPreservesAll();
+ }
+
+ virtual PMDataManager *getAsPMDataManager() { return this; }
+ virtual Pass *getAsPass() { return this; }
+ virtual PassManagerType getTopLevelPassManagerType() {
+ return PMT_ModulePassManager;
+ }
+
+ MPPassManager *getContainedManager(unsigned N) {
+ assert(N < PassManagers.size() && "Pass number out of range!");
+ MPPassManager *MP = static_cast<MPPassManager *>(PassManagers[N]);
+ return MP;
+ }
+};
+
+void PassManagerImpl::anchor() {}
+
+char PassManagerImpl::ID = 0;
+} // End of legacy namespace
+} // End of llvm namespace
+
+namespace {
+
+//===----------------------------------------------------------------------===//
+/// TimingInfo Class - This class is used to calculate information about the
+/// amount of time each pass takes to execute. This only happens when
+/// -time-passes is enabled on the command line.
+///
+
+static ManagedStatic<sys::SmartMutex<true> > TimingInfoMutex;
+
+class TimingInfo {
+ DenseMap<Pass*, Timer*> TimingData;
+ TimerGroup TG;
+public:
+ // Use 'create' member to get this.
+ TimingInfo() : TG("... Pass execution timing report ...") {}
+
+ // TimingDtor - Print out information about timing information
+ ~TimingInfo() {
+ // Delete all of the timers, which accumulate their info into the
+ // TimerGroup.
+ for (DenseMap<Pass*, Timer*>::iterator I = TimingData.begin(),
+ E = TimingData.end(); I != E; ++I)
+ delete I->second;
+ // TimerGroup is deleted next, printing the report.
+ }
+
+ // createTheTimeInfo - This method either initializes the TheTimeInfo pointer
+ // to a non null value (if the -time-passes option is enabled) or it leaves it
+ // null. It may be called multiple times.
+ static void createTheTimeInfo();
+
+ /// getPassTimer - Return the timer for the specified pass if it exists.
+ Timer *getPassTimer(Pass *P) {
+ if (P->getAsPMDataManager())
+ return 0;
+
+ sys::SmartScopedLock<true> Lock(*TimingInfoMutex);
+ Timer *&T = TimingData[P];
+ if (T == 0)
+ T = new Timer(P->getPassName(), TG);
+ return T;
+ }
+};
+
+} // End of anon namespace
+
+static TimingInfo *TheTimeInfo;
+
+//===----------------------------------------------------------------------===//
+// PMTopLevelManager implementation
+
+/// Initialize top level manager. Create first pass manager.
+PMTopLevelManager::PMTopLevelManager(PMDataManager *PMDM) {
+ PMDM->setTopLevelManager(this);
+ addPassManager(PMDM);
+ activeStack.push(PMDM);
+}
+
+/// Set pass P as the last user of the given analysis passes.
+void
+PMTopLevelManager::setLastUser(ArrayRef<Pass*> AnalysisPasses, Pass *P) {
+ unsigned PDepth = 0;
+ if (P->getResolver())
+ PDepth = P->getResolver()->getPMDataManager().getDepth();
+
+ for (SmallVectorImpl<Pass *>::const_iterator I = AnalysisPasses.begin(),
+ E = AnalysisPasses.end(); I != E; ++I) {
+ Pass *AP = *I;
+ LastUser[AP] = P;
+
+ if (P == AP)
+ continue;
+
+ // Update the last users of passes that are required transitive by AP.
+ AnalysisUsage *AnUsage = findAnalysisUsage(AP);
+ const AnalysisUsage::VectorType &IDs = AnUsage->getRequiredTransitiveSet();
+ SmallVector<Pass *, 12> LastUses;
+ SmallVector<Pass *, 12> LastPMUses;
+ for (AnalysisUsage::VectorType::const_iterator I = IDs.begin(),
+ E = IDs.end(); I != E; ++I) {
+ Pass *AnalysisPass = findAnalysisPass(*I);
+ assert(AnalysisPass && "Expected analysis pass to exist.");
+ AnalysisResolver *AR = AnalysisPass->getResolver();
+ assert(AR && "Expected analysis resolver to exist.");
+ unsigned APDepth = AR->getPMDataManager().getDepth();
+
+ if (PDepth == APDepth)
+ LastUses.push_back(AnalysisPass);
+ else if (PDepth > APDepth)
+ LastPMUses.push_back(AnalysisPass);
+ }
+
+ setLastUser(LastUses, P);
+
+ // If this pass has a corresponding pass manager, push higher level
+ // analysis to this pass manager.
+ if (P->getResolver())
+ setLastUser(LastPMUses, P->getResolver()->getPMDataManager().getAsPass());
+
+
+ // If AP is the last user of other passes then make P last user of
+ // such passes.
+ for (DenseMap<Pass *, Pass *>::iterator LUI = LastUser.begin(),
+ LUE = LastUser.end(); LUI != LUE; ++LUI) {
+ if (LUI->second == AP)
+ // DenseMap iterator is not invalidated here because
+ // this is just updating existing entries.
+ LastUser[LUI->first] = P;
+ }
+ }
+}
+
+/// Collect passes whose last user is P
+void PMTopLevelManager::collectLastUses(SmallVectorImpl<Pass *> &LastUses,
+ Pass *P) {
+ DenseMap<Pass *, SmallPtrSet<Pass *, 8> >::iterator DMI =
+ InversedLastUser.find(P);
+ if (DMI == InversedLastUser.end())
+ 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);
+ }
+
+}
+
+AnalysisUsage *PMTopLevelManager::findAnalysisUsage(Pass *P) {
+ AnalysisUsage *AnUsage = NULL;
+ DenseMap<Pass *, AnalysisUsage *>::iterator DMI = AnUsageMap.find(P);
+ if (DMI != AnUsageMap.end())
+ AnUsage = DMI->second;
+ else {
+ AnUsage = new AnalysisUsage();
+ P->getAnalysisUsage(*AnUsage);
+ AnUsageMap[P] = AnUsage;
+ }
+ return AnUsage;
+}
+
+/// Schedule pass P for execution. Make sure that passes required by
+/// P are run before P is run. Update analysis info maintained by
+/// the manager. Remove dead passes. This is a recursive function.
+void PMTopLevelManager::schedulePass(Pass *P) {
+
+ // TODO : Allocate function manager for this pass, other wise required set
+ // may be inserted into previous function manager
+
+ // Give pass a chance to prepare the stage.
+ P->preparePassManager(activeStack);
+
+ // If P is an analysis pass and it is available then do not
+ // generate the analysis again. Stale analysis info should not be
+ // available at this point.
+ const PassInfo *PI =
+ PassRegistry::getPassRegistry()->getPassInfo(P->getPassID());
+ if (PI && PI->isAnalysis() && findAnalysisPass(P->getPassID())) {
+ delete P;
+ return;
+ }
+
+ AnalysisUsage *AnUsage = findAnalysisUsage(P);
+
+ bool checkAnalysis = true;
+ while (checkAnalysis) {
+ checkAnalysis = false;
+
+ const AnalysisUsage::VectorType &RequiredSet = AnUsage->getRequiredSet();
+ for (AnalysisUsage::VectorType::const_iterator I = RequiredSet.begin(),
+ E = RequiredSet.end(); I != E; ++I) {
+
+ Pass *AnalysisPass = findAnalysisPass(*I);
+ if (!AnalysisPass) {
+ const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(*I);
+
+ if (PI == NULL) {
+ // Pass P is not in the global PassRegistry
+ dbgs() << "Pass '" << P->getPassName() << "' is not initialized." << "\n";
+ dbgs() << "Verify if there is a pass dependency cycle." << "\n";
+ dbgs() << "Required Passes:" << "\n";
+ for (AnalysisUsage::VectorType::const_iterator I2 = RequiredSet.begin(),
+ E = RequiredSet.end(); I2 != E && I2 != I; ++I2) {
+ Pass *AnalysisPass2 = findAnalysisPass(*I2);
+ if (AnalysisPass2) {
+ dbgs() << "\t" << AnalysisPass2->getPassName() << "\n";
+ } else {
+ dbgs() << "\t" << "Error: Required pass not found! Possible causes:" << "\n";
+ dbgs() << "\t\t" << "- Pass misconfiguration (e.g.: missing macros)" << "\n";
+ dbgs() << "\t\t" << "- Corruption of the global PassRegistry" << "\n";
+ }
+ }
+ }
+
+ assert(PI && "Expected required passes to be initialized");
+ AnalysisPass = PI->createPass();
+ if (P->getPotentialPassManagerType () ==
+ AnalysisPass->getPotentialPassManagerType())
+ // Schedule analysis pass that is managed by the same pass manager.
+ schedulePass(AnalysisPass);
+ else if (P->getPotentialPassManagerType () >
+ AnalysisPass->getPotentialPassManagerType()) {
+ // Schedule analysis pass that is managed by a new manager.
+ schedulePass(AnalysisPass);
+ // Recheck analysis passes to ensure that required analyses that
+ // are already checked are still available.
+ checkAnalysis = true;
+ } else
+ // Do not schedule this analysis. Lower level analsyis
+ // passes are run on the fly.
+ delete AnalysisPass;
+ }
+ }
+ }
+
+ // Now all required passes are available.
+ if (ImmutablePass *IP = P->getAsImmutablePass()) {
+ // P is a immutable pass and it will be managed by this
+ // top level manager. Set up analysis resolver to connect them.
+ PMDataManager *DM = getAsPMDataManager();
+ AnalysisResolver *AR = new AnalysisResolver(*DM);
+ P->setResolver(AR);
+ DM->initializeAnalysisImpl(P);
+ addImmutablePass(IP);
+ DM->recordAvailableAnalysis(IP);
+ return;
+ }
+
+ if (PI && !PI->isAnalysis() && ShouldPrintBeforePass(PI)) {
+ Pass *PP = P->createPrinterPass(
+ dbgs(), std::string("*** IR Dump Before ") + P->getPassName() + " ***");
+ PP->assignPassManager(activeStack, getTopLevelPassManagerType());
+ }
+
+ // Add the requested pass to the best available pass manager.
+ P->assignPassManager(activeStack, getTopLevelPassManagerType());
+
+ if (PI && !PI->isAnalysis() && ShouldPrintAfterPass(PI)) {
+ Pass *PP = P->createPrinterPass(
+ dbgs(), std::string("*** IR Dump After ") + P->getPassName() + " ***");
+ PP->assignPassManager(activeStack, getTopLevelPassManagerType());
+ }
+}
+
+/// Find the pass that implements Analysis AID. Search immutable
+/// passes and all pass managers. If desired pass is not found
+/// then return NULL.
+Pass *PMTopLevelManager::findAnalysisPass(AnalysisID AID) {
+
+ // Check pass managers
+ for (SmallVectorImpl<PMDataManager *>::iterator I = PassManagers.begin(),
+ E = PassManagers.end(); I != E; ++I)
+ if (Pass *P = (*I)->findAnalysisPass(AID, false))
+ return P;
+
+ // Check other pass managers
+ for (SmallVectorImpl<PMDataManager *>::iterator
+ I = IndirectPassManagers.begin(),
+ E = IndirectPassManagers.end(); I != E; ++I)
+ if (Pass *P = (*I)->findAnalysisPass(AID, false))
+ return P;
+
+ // Check the immutable passes. Iterate in reverse order so that we find
+ // the most recently registered passes first.
+ for (SmallVectorImpl<ImmutablePass *>::reverse_iterator I =
+ ImmutablePasses.rbegin(), E = ImmutablePasses.rend(); I != E; ++I) {
+ AnalysisID PI = (*I)->getPassID();
+ if (PI == AID)
+ return *I;
+
+ // If Pass not found then check the interfaces implemented by Immutable Pass
+ const PassInfo *PassInf =
+ PassRegistry::getPassRegistry()->getPassInfo(PI);
+ assert(PassInf && "Expected all immutable passes to be initialized");
+ const std::vector<const PassInfo*> &ImmPI =
+ PassInf->getInterfacesImplemented();
+ for (std::vector<const PassInfo*>::const_iterator II = ImmPI.begin(),
+ EE = ImmPI.end(); II != EE; ++II) {
+ if ((*II)->getTypeInfo() == AID)
+ return *I;
+ }
+ }
+
+ return 0;
+}
+
+// Print passes managed by this top level manager.
+void PMTopLevelManager::dumpPasses() const {
+
+ if (PassDebugging < Structure)
+ return;
+
+ // Print out the immutable passes
+ for (unsigned i = 0, e = ImmutablePasses.size(); i != e; ++i) {
+ ImmutablePasses[i]->dumpPassStructure(0);
+ }
+
+ // Every class that derives from PMDataManager also derives from Pass
+ // (sometimes indirectly), but there's no inheritance relationship
+ // between PMDataManager and Pass, so we have to getAsPass to get
+ // from a PMDataManager* to a Pass*.
+ for (SmallVectorImpl<PMDataManager *>::const_iterator I =
+ PassManagers.begin(), E = PassManagers.end(); I != E; ++I)
+ (*I)->getAsPass()->dumpPassStructure(1);
+}
+
+void PMTopLevelManager::dumpArguments() const {
+
+ if (PassDebugging < Arguments)
+ return;
+
+ dbgs() << "Pass Arguments: ";
+ for (SmallVectorImpl<ImmutablePass *>::const_iterator I =
+ ImmutablePasses.begin(), E = ImmutablePasses.end(); I != E; ++I)
+ if (const PassInfo *PI =
+ PassRegistry::getPassRegistry()->getPassInfo((*I)->getPassID())) {
+ assert(PI && "Expected all immutable passes to be initialized");
+ if (!PI->isAnalysisGroup())
+ dbgs() << " -" << PI->getPassArgument();
+ }
+ for (SmallVectorImpl<PMDataManager *>::const_iterator I =
+ PassManagers.begin(), E = PassManagers.end(); I != E; ++I)
+ (*I)->dumpPassArguments();
+ dbgs() << "\n";
+}
+
+void PMTopLevelManager::initializeAllAnalysisInfo() {
+ for (SmallVectorImpl<PMDataManager *>::iterator I = PassManagers.begin(),
+ E = PassManagers.end(); I != E; ++I)
+ (*I)->initializeAnalysisInfo();
+
+ // Initailize other pass managers
+ for (SmallVectorImpl<PMDataManager *>::iterator
+ I = IndirectPassManagers.begin(), E = IndirectPassManagers.end();
+ I != E; ++I)
+ (*I)->initializeAnalysisInfo();
+
+ for (DenseMap<Pass *, Pass *>::iterator DMI = LastUser.begin(),
+ DME = LastUser.end(); DMI != DME; ++DMI) {
+ DenseMap<Pass *, SmallPtrSet<Pass *, 8> >::iterator InvDMI =
+ InversedLastUser.find(DMI->second);
+ if (InvDMI != InversedLastUser.end()) {
+ SmallPtrSet<Pass *, 8> &L = InvDMI->second;
+ L.insert(DMI->first);
+ } else {
+ SmallPtrSet<Pass *, 8> L; L.insert(DMI->first);
+ InversedLastUser[DMI->second] = L;
+ }
+ }
+}
+
+/// Destructor
+PMTopLevelManager::~PMTopLevelManager() {
+ for (SmallVectorImpl<PMDataManager *>::iterator I = PassManagers.begin(),
+ E = PassManagers.end(); I != E; ++I)
+ delete *I;
+
+ for (SmallVectorImpl<ImmutablePass *>::iterator
+ I = ImmutablePasses.begin(), E = ImmutablePasses.end(); I != E; ++I)
+ delete *I;
+
+ for (DenseMap<Pass *, AnalysisUsage *>::iterator DMI = AnUsageMap.begin(),
+ DME = AnUsageMap.end(); DMI != DME; ++DMI)
+ delete DMI->second;
+}
+
+//===----------------------------------------------------------------------===//
+// PMDataManager implementation
+
+/// Augement AvailableAnalysis by adding analysis made available by pass P.
+void PMDataManager::recordAvailableAnalysis(Pass *P) {
+ AnalysisID PI = P->getPassID();
+
+ AvailableAnalysis[PI] = P;
+
+ assert(!AvailableAnalysis.empty());
+
+ // This pass is the current implementation of all of the interfaces it
+ // implements as well.
+ const PassInfo *PInf = PassRegistry::getPassRegistry()->getPassInfo(PI);
+ if (PInf == 0) return;
+ const std::vector<const PassInfo*> &II = PInf->getInterfacesImplemented();
+ for (unsigned i = 0, e = II.size(); i != e; ++i)
+ AvailableAnalysis[II[i]->getTypeInfo()] = P;
+}
+
+// Return true if P preserves high level analysis used by other
+// passes managed by this manager
+bool PMDataManager::preserveHigherLevelAnalysis(Pass *P) {
+ AnalysisUsage *AnUsage = TPM->findAnalysisUsage(P);
+ if (AnUsage->getPreservesAll())
+ return true;
+
+ const AnalysisUsage::VectorType &PreservedSet = AnUsage->getPreservedSet();
+ for (SmallVectorImpl<Pass *>::iterator I = HigherLevelAnalysis.begin(),
+ E = HigherLevelAnalysis.end(); I != E; ++I) {
+ Pass *P1 = *I;
+ if (P1->getAsImmutablePass() == 0 &&
+ std::find(PreservedSet.begin(), PreservedSet.end(),
+ P1->getPassID()) ==
+ PreservedSet.end())
+ return false;
+ }
+
+ return true;
+}
+
+/// verifyPreservedAnalysis -- Verify analysis preserved by pass P.
+void PMDataManager::verifyPreservedAnalysis(Pass *P) {
+ // Don't do this unless assertions are enabled.
+#ifdef NDEBUG
+ return;
+#endif
+ AnalysisUsage *AnUsage = TPM->findAnalysisUsage(P);
+ const AnalysisUsage::VectorType &PreservedSet = AnUsage->getPreservedSet();
+
+ // Verify preserved analysis
+ for (AnalysisUsage::VectorType::const_iterator I = PreservedSet.begin(),
+ E = PreservedSet.end(); I != E; ++I) {
+ AnalysisID AID = *I;
+ if (Pass *AP = findAnalysisPass(AID, true)) {
+ TimeRegion PassTimer(getPassTimer(AP));
+ AP->verifyAnalysis();
+ }
+ }
+}
+
+/// Remove Analysis not preserved by Pass P
+void PMDataManager::removeNotPreservedAnalysis(Pass *P) {
+ AnalysisUsage *AnUsage = TPM->findAnalysisUsage(P);
+ if (AnUsage->getPreservesAll())
+ return;
+
+ const AnalysisUsage::VectorType &PreservedSet = AnUsage->getPreservedSet();
+ for (DenseMap<AnalysisID, Pass*>::iterator I = AvailableAnalysis.begin(),
+ E = AvailableAnalysis.end(); I != E; ) {
+ DenseMap<AnalysisID, Pass*>::iterator Info = I++;
+ if (Info->second->getAsImmutablePass() == 0 &&
+ std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) ==
+ PreservedSet.end()) {
+ // Remove this analysis
+ if (PassDebugging >= Details) {
+ Pass *S = Info->second;
+ dbgs() << " -- '" << P->getPassName() << "' is not preserving '";
+ dbgs() << S->getPassName() << "'\n";
+ }
+ AvailableAnalysis.erase(Info);
+ }
+ }
+
+ // Check inherited analysis also. If P is not preserving analysis
+ // provided by parent manager then remove it here.
+ for (unsigned Index = 0; Index < PMT_Last; ++Index) {
+
+ if (!InheritedAnalysis[Index])
+ continue;
+
+ for (DenseMap<AnalysisID, Pass*>::iterator
+ I = InheritedAnalysis[Index]->begin(),
+ E = InheritedAnalysis[Index]->end(); I != E; ) {
+ DenseMap<AnalysisID, Pass *>::iterator Info = I++;
+ if (Info->second->getAsImmutablePass() == 0 &&
+ std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) ==
+ PreservedSet.end()) {
+ // Remove this analysis
+ if (PassDebugging >= Details) {
+ Pass *S = Info->second;
+ dbgs() << " -- '" << P->getPassName() << "' is not preserving '";
+ dbgs() << S->getPassName() << "'\n";
+ }
+ InheritedAnalysis[Index]->erase(Info);
+ }
+ }
+ }
+}
+
+/// Remove analysis passes that are not used any longer
+void PMDataManager::removeDeadPasses(Pass *P, StringRef Msg,
+ enum PassDebuggingString DBG_STR) {
+
+ SmallVector<Pass *, 12> DeadPasses;
+
+ // If this is a on the fly manager then it does not have TPM.
+ if (!TPM)
+ return;
+
+ TPM->collectLastUses(DeadPasses, P);
+
+ if (PassDebugging >= Details && !DeadPasses.empty()) {
+ dbgs() << " -*- '" << P->getPassName();
+ dbgs() << "' is the last user of following pass instances.";
+ dbgs() << " Free these instances\n";
+ }
+
+ for (SmallVectorImpl<Pass *>::iterator I = DeadPasses.begin(),
+ E = DeadPasses.end(); I != E; ++I)
+ freePass(*I, Msg, DBG_STR);
+}
+
+void PMDataManager::freePass(Pass *P, StringRef Msg,
+ enum PassDebuggingString DBG_STR) {
+ dumpPassInfo(P, FREEING_MSG, DBG_STR, Msg);
+
+ {
+ // If the pass crashes releasing memory, remember this.
+ PassManagerPrettyStackEntry X(P);
+ TimeRegion PassTimer(getPassTimer(P));
+
+ P->releaseMemory();
+ }
+
+ AnalysisID PI = P->getPassID();
+ if (const PassInfo *PInf = PassRegistry::getPassRegistry()->getPassInfo(PI)) {
+ // Remove the pass itself (if it is not already removed).
+ AvailableAnalysis.erase(PI);
+
+ // Remove all interfaces this pass implements, for which it is also
+ // listed as the available implementation.
+ const std::vector<const PassInfo*> &II = PInf->getInterfacesImplemented();
+ for (unsigned i = 0, e = II.size(); i != e; ++i) {
+ DenseMap<AnalysisID, Pass*>::iterator Pos =
+ AvailableAnalysis.find(II[i]->getTypeInfo());
+ if (Pos != AvailableAnalysis.end() && Pos->second == P)
+ AvailableAnalysis.erase(Pos);
+ }
+ }
+}
+
+/// Add pass P into the PassVector. Update
+/// AvailableAnalysis appropriately if ProcessAnalysis is true.
+void PMDataManager::add(Pass *P, bool ProcessAnalysis) {
+ // This manager is going to manage pass P. Set up analysis resolver
+ // to connect them.
+ AnalysisResolver *AR = new AnalysisResolver(*this);
+ P->setResolver(AR);
+
+ // If a FunctionPass F is the last user of ModulePass info M
+ // then the F's manager, not F, records itself as a last user of M.
+ SmallVector<Pass *, 12> TransferLastUses;
+
+ if (!ProcessAnalysis) {
+ // Add pass
+ PassVector.push_back(P);
+ return;
+ }
+
+ // At the moment, this pass is the last user of all required passes.
+ SmallVector<Pass *, 12> LastUses;
+ SmallVector<Pass *, 8> RequiredPasses;
+ SmallVector<AnalysisID, 8> ReqAnalysisNotAvailable;
+
+ unsigned PDepth = this->getDepth();
+
+ collectRequiredAnalysis(RequiredPasses,
+ ReqAnalysisNotAvailable, P);
+ for (SmallVectorImpl<Pass *>::iterator I = RequiredPasses.begin(),
+ E = RequiredPasses.end(); I != E; ++I) {
+ Pass *PRequired = *I;
+ unsigned RDepth = 0;
+
+ assert(PRequired->getResolver() && "Analysis Resolver is not set");
+ PMDataManager &DM = PRequired->getResolver()->getPMDataManager();
+ RDepth = DM.getDepth();
+
+ if (PDepth == RDepth)
+ LastUses.push_back(PRequired);
+ else if (PDepth > RDepth) {
+ // Let the parent claim responsibility of last use
+ TransferLastUses.push_back(PRequired);
+ // Keep track of higher level analysis used by this manager.
+ HigherLevelAnalysis.push_back(PRequired);
+ } else
+ llvm_unreachable("Unable to accommodate Required Pass");
+ }
+
+ // Set P as P's last user until someone starts using P.
+ // However, if P is a Pass Manager then it does not need
+ // to record its last user.
+ if (P->getAsPMDataManager() == 0)
+ LastUses.push_back(P);
+ TPM->setLastUser(LastUses, P);
+
+ if (!TransferLastUses.empty()) {
+ Pass *My_PM = getAsPass();
+ TPM->setLastUser(TransferLastUses, My_PM);
+ TransferLastUses.clear();
+ }
+
+ // Now, take care of required analyses that are not available.
+ for (SmallVectorImpl<AnalysisID>::iterator
+ I = ReqAnalysisNotAvailable.begin(),
+ E = ReqAnalysisNotAvailable.end() ;I != E; ++I) {
+ const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(*I);
+ Pass *AnalysisPass = PI->createPass();
+ this->addLowerLevelRequiredPass(P, AnalysisPass);
+ }
+
+ // Take a note of analysis required and made available by this pass.
+ // Remove the analysis not preserved by this pass
+ removeNotPreservedAnalysis(P);
+ recordAvailableAnalysis(P);
+
+ // Add pass
+ PassVector.push_back(P);
+}
+
+
+/// Populate RP with analysis pass that are required by
+/// pass P and are available. Populate RP_NotAvail with analysis
+/// pass that are required by pass P but are not available.
+void PMDataManager::collectRequiredAnalysis(SmallVectorImpl<Pass *> &RP,
+ SmallVectorImpl<AnalysisID> &RP_NotAvail,
+ Pass *P) {
+ AnalysisUsage *AnUsage = TPM->findAnalysisUsage(P);
+ const AnalysisUsage::VectorType &RequiredSet = AnUsage->getRequiredSet();
+ for (AnalysisUsage::VectorType::const_iterator
+ I = RequiredSet.begin(), E = RequiredSet.end(); I != E; ++I) {
+ if (Pass *AnalysisPass = findAnalysisPass(*I, true))
+ RP.push_back(AnalysisPass);
+ else
+ RP_NotAvail.push_back(*I);
+ }
+
+ const AnalysisUsage::VectorType &IDs = AnUsage->getRequiredTransitiveSet();
+ for (AnalysisUsage::VectorType::const_iterator I = IDs.begin(),
+ E = IDs.end(); I != E; ++I) {
+ if (Pass *AnalysisPass = findAnalysisPass(*I, true))
+ RP.push_back(AnalysisPass);
+ else
+ RP_NotAvail.push_back(*I);
+ }
+}
+
+// All Required analyses should be available to the pass as it runs! Here
+// we fill in the AnalysisImpls member of the pass so that it can
+// successfully use the getAnalysis() method to retrieve the
+// implementations it needs.
+//
+void PMDataManager::initializeAnalysisImpl(Pass *P) {
+ AnalysisUsage *AnUsage = TPM->findAnalysisUsage(P);
+
+ for (AnalysisUsage::VectorType::const_iterator
+ I = AnUsage->getRequiredSet().begin(),
+ E = AnUsage->getRequiredSet().end(); I != E; ++I) {
+ Pass *Impl = findAnalysisPass(*I, true);
+ if (Impl == 0)
+ // This may be analysis pass that is initialized on the fly.
+ // If that is not the case then it will raise an assert when it is used.
+ continue;
+ AnalysisResolver *AR = P->getResolver();
+ assert(AR && "Analysis Resolver is not set");
+ AR->addAnalysisImplsPair(*I, Impl);
+ }
+}
+
+/// Find the pass that implements Analysis AID. If desired pass is not found
+/// then return NULL.
+Pass *PMDataManager::findAnalysisPass(AnalysisID AID, bool SearchParent) {
+
+ // Check if AvailableAnalysis map has one entry.
+ DenseMap<AnalysisID, Pass*>::const_iterator I = AvailableAnalysis.find(AID);
+
+ if (I != AvailableAnalysis.end())
+ return I->second;
+
+ // Search Parents through TopLevelManager
+ if (SearchParent)
+ return TPM->findAnalysisPass(AID);
+
+ return NULL;
+}
+
+// Print list of passes that are last used by P.
+void PMDataManager::dumpLastUses(Pass *P, unsigned Offset) const{
+
+ SmallVector<Pass *, 12> LUses;
+
+ // If this is a on the fly manager then it does not have TPM.
+ if (!TPM)
+ return;
+
+ TPM->collectLastUses(LUses, P);
+
+ for (SmallVectorImpl<Pass *>::iterator I = LUses.begin(),
+ E = LUses.end(); I != E; ++I) {
+ llvm::dbgs() << "--" << std::string(Offset*2, ' ');
+ (*I)->dumpPassStructure(0);
+ }
+}
+
+void PMDataManager::dumpPassArguments() const {
+ for (SmallVectorImpl<Pass *>::const_iterator I = PassVector.begin(),
+ E = PassVector.end(); I != E; ++I) {
+ if (PMDataManager *PMD = (*I)->getAsPMDataManager())
+ PMD->dumpPassArguments();
+ else
+ if (const PassInfo *PI =
+ PassRegistry::getPassRegistry()->getPassInfo((*I)->getPassID()))
+ if (!PI->isAnalysisGroup())
+ dbgs() << " -" << PI->getPassArgument();
+ }
+}
+
+void PMDataManager::dumpPassInfo(Pass *P, enum PassDebuggingString S1,
+ enum PassDebuggingString S2,
+ StringRef Msg) {
+ if (PassDebugging < Executions)
+ return;
+ dbgs() << (void*)this << std::string(getDepth()*2+1, ' ');
+ switch (S1) {
+ case EXECUTION_MSG:
+ dbgs() << "Executing Pass '" << P->getPassName();
+ break;
+ case MODIFICATION_MSG:
+ dbgs() << "Made Modification '" << P->getPassName();
+ break;
+ case FREEING_MSG:
+ dbgs() << " Freeing Pass '" << P->getPassName();
+ break;
+ default:
+ break;
+ }
+ switch (S2) {
+ case ON_BASICBLOCK_MSG:
+ dbgs() << "' on BasicBlock '" << Msg << "'...\n";
+ break;
+ case ON_FUNCTION_MSG:
+ dbgs() << "' on Function '" << Msg << "'...\n";
+ break;
+ case ON_MODULE_MSG:
+ dbgs() << "' on Module '" << Msg << "'...\n";
+ break;
+ case ON_REGION_MSG:
+ dbgs() << "' on Region '" << Msg << "'...\n";
+ break;
+ case ON_LOOP_MSG:
+ dbgs() << "' on Loop '" << Msg << "'...\n";
+ break;
+ case ON_CG_MSG:
+ dbgs() << "' on Call Graph Nodes '" << Msg << "'...\n";
+ break;
+ default:
+ break;
+ }
+}
+
+void PMDataManager::dumpRequiredSet(const Pass *P) const {
+ if (PassDebugging < Details)
+ return;
+
+ AnalysisUsage analysisUsage;
+ P->getAnalysisUsage(analysisUsage);
+ dumpAnalysisUsage("Required", P, analysisUsage.getRequiredSet());
+}
+
+void PMDataManager::dumpPreservedSet(const Pass *P) const {
+ if (PassDebugging < Details)
+ return;
+
+ AnalysisUsage analysisUsage;
+ P->getAnalysisUsage(analysisUsage);
+ dumpAnalysisUsage("Preserved", P, analysisUsage.getPreservedSet());
+}
+
+void PMDataManager::dumpAnalysisUsage(StringRef Msg, const Pass *P,
+ const AnalysisUsage::VectorType &Set) const {
+ assert(PassDebugging >= Details);
+ if (Set.empty())
+ return;
+ dbgs() << (const void*)P << std::string(getDepth()*2+3, ' ') << Msg << " Analyses:";
+ for (unsigned i = 0; i != Set.size(); ++i) {
+ if (i) dbgs() << ',';
+ const PassInfo *PInf = PassRegistry::getPassRegistry()->getPassInfo(Set[i]);
+ if (!PInf) {
+ // Some preserved passes, such as AliasAnalysis, may not be initialized by
+ // all drivers.
+ dbgs() << " Uninitialized Pass";
+ continue;
+ }
+ dbgs() << ' ' << PInf->getPassName();
+ }
+ dbgs() << '\n';
+}
+
+/// Add RequiredPass into list of lower level passes required by pass P.
+/// RequiredPass is run on the fly by Pass Manager when P requests it
+/// through getAnalysis interface.
+/// This should be handled by specific pass manager.
+void PMDataManager::addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) {
+ if (TPM) {
+ TPM->dumpArguments();
+ TPM->dumpPasses();
+ }
+
+ // Module Level pass may required Function Level analysis info
+ // (e.g. dominator info). Pass manager uses on the fly function pass manager
+ // to provide this on demand. In that case, in Pass manager terminology,
+ // module level pass is requiring lower level analysis info managed by
+ // lower level pass manager.
+
+ // When Pass manager is not able to order required analysis info, Pass manager
+ // checks whether any lower level manager will be able to provide this
+ // analysis info on demand or not.
+#ifndef NDEBUG
+ dbgs() << "Unable to schedule '" << RequiredPass->getPassName();
+ dbgs() << "' required by '" << P->getPassName() << "'\n";
+#endif
+ llvm_unreachable("Unable to schedule pass");
+}
+
+Pass *PMDataManager::getOnTheFlyPass(Pass *P, AnalysisID PI, Function &F) {
+ llvm_unreachable("Unable to find on the fly pass");
+}
+
+// Destructor
+PMDataManager::~PMDataManager() {
+ for (SmallVectorImpl<Pass *>::iterator I = PassVector.begin(),
+ E = PassVector.end(); I != E; ++I)
+ delete *I;
+}
+
+//===----------------------------------------------------------------------===//
+// NOTE: Is this the right place to define this method ?
+// getAnalysisIfAvailable - Return analysis result or null if it doesn't exist.
+Pass *AnalysisResolver::getAnalysisIfAvailable(AnalysisID ID, bool dir) const {
+ return PM.findAnalysisPass(ID, dir);
+}
+
+Pass *AnalysisResolver::findImplPass(Pass *P, AnalysisID AnalysisPI,
+ Function &F) {
+ return PM.getOnTheFlyPass(P, AnalysisPI, F);
+}
+
+//===----------------------------------------------------------------------===//
+// BBPassManager implementation
+
+/// Execute all of the passes scheduled for execution by invoking
+/// runOnBasicBlock method. Keep track of whether any of the passes modifies
+/// the function, and if so, return true.
+bool BBPassManager::runOnFunction(Function &F) {
+ if (F.isDeclaration())
+ return false;
+
+ bool Changed = doInitialization(F);
+
+ for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
+ for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
+ BasicBlockPass *BP = getContainedPass(Index);
+ bool LocalChanged = false;
+
+ dumpPassInfo(BP, EXECUTION_MSG, ON_BASICBLOCK_MSG, I->getName());
+ dumpRequiredSet(BP);
+
+ initializeAnalysisImpl(BP);
+
+ {
+ // If the pass crashes, remember this.
+ PassManagerPrettyStackEntry X(BP, *I);
+ TimeRegion PassTimer(getPassTimer(BP));
+
+ LocalChanged |= BP->runOnBasicBlock(*I);
+ }
+
+ Changed |= LocalChanged;
+ if (LocalChanged)
+ dumpPassInfo(BP, MODIFICATION_MSG, ON_BASICBLOCK_MSG,
+ I->getName());
+ dumpPreservedSet(BP);
+
+ verifyPreservedAnalysis(BP);
+ removeNotPreservedAnalysis(BP);
+ recordAvailableAnalysis(BP);
+ removeDeadPasses(BP, I->getName(), ON_BASICBLOCK_MSG);
+ }
+
+ return doFinalization(F) || Changed;
+}
+
+// Implement doInitialization and doFinalization
+bool BBPassManager::doInitialization(Module &M) {
+ bool Changed = false;
+
+ for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index)
+ Changed |= getContainedPass(Index)->doInitialization(M);
+
+ return Changed;
+}
+
+bool BBPassManager::doFinalization(Module &M) {
+ bool Changed = false;
+
+ for (int Index = getNumContainedPasses() - 1; Index >= 0; --Index)
+ Changed |= getContainedPass(Index)->doFinalization(M);
+
+ return Changed;
+}
+
+bool BBPassManager::doInitialization(Function &F) {
+ bool Changed = false;
+
+ for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
+ BasicBlockPass *BP = getContainedPass(Index);
+ Changed |= BP->doInitialization(F);
+ }
+
+ return Changed;
+}
+
+bool BBPassManager::doFinalization(Function &F) {
+ bool Changed = false;
+
+ for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
+ BasicBlockPass *BP = getContainedPass(Index);
+ Changed |= BP->doFinalization(F);
+ }
+
+ return Changed;
+}
+
+
+//===----------------------------------------------------------------------===//
+// FunctionPassManager implementation
+
+/// Create new Function pass manager
+FunctionPassManager::FunctionPassManager(Module *m) : M(m) {
+ FPM = new FunctionPassManagerImpl();
+ // FPM is the top level manager.
+ FPM->setTopLevelManager(FPM);
+
+ AnalysisResolver *AR = new AnalysisResolver(*FPM);
+ FPM->setResolver(AR);
+}
+
+FunctionPassManager::~FunctionPassManager() {
+ delete FPM;
+}
+
+/// add - Add a pass to the queue of passes to run. This passes
+/// ownership of the Pass to the PassManager. When the
+/// PassManager_X is destroyed, the pass will be destroyed as well, so
+/// there is no need to delete the pass. (TODO delete passes.)
+/// This implies that all passes MUST be allocated with 'new'.
+void FunctionPassManager::add(Pass *P) {
+ FPM->add(P);
+}
+
+/// run - Execute all of the passes scheduled for execution. Keep
+/// track of whether any of the passes modifies the function, and if
+/// 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));
+ }
+ return FPM->run(F);
+}
+
+
+/// doInitialization - Run all of the initializers for the function passes.
+///
+bool FunctionPassManager::doInitialization() {
+ return FPM->doInitialization(*M);
+}
+
+/// doFinalization - Run all of the finalizers for the function passes.
+///
+bool FunctionPassManager::doFinalization() {
+ return FPM->doFinalization(*M);
+}
+
+//===----------------------------------------------------------------------===//
+// FunctionPassManagerImpl implementation
+//
+bool FunctionPassManagerImpl::doInitialization(Module &M) {
+ bool Changed = false;
+
+ dumpArguments();
+ dumpPasses();
+
+ SmallVectorImpl<ImmutablePass *>& IPV = getImmutablePasses();
+ for (SmallVectorImpl<ImmutablePass *>::const_iterator I = IPV.begin(),
+ E = IPV.end(); I != E; ++I) {
+ Changed |= (*I)->doInitialization(M);
+ }
+
+ for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index)
+ Changed |= getContainedManager(Index)->doInitialization(M);
+
+ return Changed;
+}
+
+bool FunctionPassManagerImpl::doFinalization(Module &M) {
+ bool Changed = false;
+
+ for (int Index = getNumContainedManagers() - 1; Index >= 0; --Index)
+ Changed |= getContainedManager(Index)->doFinalization(M);
+
+ SmallVectorImpl<ImmutablePass *>& IPV = getImmutablePasses();
+ for (SmallVectorImpl<ImmutablePass *>::const_iterator I = IPV.begin(),
+ E = IPV.end(); I != E; ++I) {
+ Changed |= (*I)->doFinalization(M);
+ }
+
+ return Changed;
+}
+
+/// cleanup - After running all passes, clean up pass manager cache.
+void FPPassManager::cleanup() {
+ for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
+ FunctionPass *FP = getContainedPass(Index);
+ AnalysisResolver *AR = FP->getResolver();
+ assert(AR && "Analysis Resolver is not set");
+ AR->clearAnalysisImpls();
+ }
+}
+
+void FunctionPassManagerImpl::releaseMemoryOnTheFly() {
+ if (!wasRun)
+ return;
+ for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) {
+ FPPassManager *FPPM = getContainedManager(Index);
+ for (unsigned Index = 0; Index < FPPM->getNumContainedPasses(); ++Index) {
+ FPPM->getContainedPass(Index)->releaseMemory();
+ }
+ }
+ wasRun = false;
+}
+
+// Execute all the passes managed by this top level manager.
+// Return true if any function is modified by a pass.
+bool FunctionPassManagerImpl::run(Function &F) {
+ bool Changed = false;
+ TimingInfo::createTheTimeInfo();
+
+ initializeAllAnalysisInfo();
+ for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index)
+ Changed |= getContainedManager(Index)->runOnFunction(F);
+
+ for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index)
+ getContainedManager(Index)->cleanup();
+
+ wasRun = true;
+ return Changed;
+}
+
+//===----------------------------------------------------------------------===//
+// FPPassManager implementation
+
+char FPPassManager::ID = 0;
+/// Print passes managed by this manager
+void FPPassManager::dumpPassStructure(unsigned Offset) {
+ dbgs().indent(Offset*2) << "FunctionPass Manager\n";
+ for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
+ FunctionPass *FP = getContainedPass(Index);
+ FP->dumpPassStructure(Offset + 1);
+ dumpLastUses(FP, Offset+1);
+ }
+}
+
+
+/// Execute all of the passes scheduled for execution by invoking
+/// runOnFunction method. Keep track of whether any of the passes modifies
+/// the function, and if so, return true.
+bool FPPassManager::runOnFunction(Function &F) {
+ if (F.isDeclaration())
+ return false;
+
+ bool Changed = false;
+
+ // Collect inherited analysis from Module level pass manager.
+ populateInheritedAnalysis(TPM->activeStack);
+
+ for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
+ FunctionPass *FP = getContainedPass(Index);
+ bool LocalChanged = false;
+
+ dumpPassInfo(FP, EXECUTION_MSG, ON_FUNCTION_MSG, F.getName());
+ dumpRequiredSet(FP);
+
+ initializeAnalysisImpl(FP);
+
+ {
+ PassManagerPrettyStackEntry X(FP, F);
+ TimeRegion PassTimer(getPassTimer(FP));
+
+ LocalChanged |= FP->runOnFunction(F);
+ }
+
+ Changed |= LocalChanged;
+ if (LocalChanged)
+ dumpPassInfo(FP, MODIFICATION_MSG, ON_FUNCTION_MSG, F.getName());
+ dumpPreservedSet(FP);
+
+ verifyPreservedAnalysis(FP);
+ removeNotPreservedAnalysis(FP);
+ recordAvailableAnalysis(FP);
+ removeDeadPasses(FP, F.getName(), ON_FUNCTION_MSG);
+ }
+ return Changed;
+}
+
+bool FPPassManager::runOnModule(Module &M) {
+ bool Changed = false;
+
+ for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
+ Changed |= runOnFunction(*I);
+
+ return Changed;
+}
+
+bool FPPassManager::doInitialization(Module &M) {
+ bool Changed = false;
+
+ for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index)
+ Changed |= getContainedPass(Index)->doInitialization(M);
+
+ return Changed;
+}
+
+bool FPPassManager::doFinalization(Module &M) {
+ bool Changed = false;
+
+ for (int Index = getNumContainedPasses() - 1; Index >= 0; --Index)
+ Changed |= getContainedPass(Index)->doFinalization(M);
+
+ return Changed;
+}
+
+//===----------------------------------------------------------------------===//
+// MPPassManager implementation
+
+/// Execute all of the passes scheduled for execution by invoking
+/// runOnModule method. Keep track of whether any of the passes modifies
+/// the module, and if so, return true.
+bool
+MPPassManager::runOnModule(Module &M) {
+ bool Changed = false;
+
+ // Initialize on-the-fly passes
+ for (std::map<Pass *, FunctionPassManagerImpl *>::iterator
+ I = OnTheFlyManagers.begin(), E = OnTheFlyManagers.end();
+ I != E; ++I) {
+ FunctionPassManagerImpl *FPP = I->second;
+ Changed |= FPP->doInitialization(M);
+ }
+
+ // Initialize module passes
+ for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index)
+ Changed |= getContainedPass(Index)->doInitialization(M);
+
+ for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
+ ModulePass *MP = getContainedPass(Index);
+ bool LocalChanged = false;
+
+ dumpPassInfo(MP, EXECUTION_MSG, ON_MODULE_MSG, M.getModuleIdentifier());
+ dumpRequiredSet(MP);
+
+ initializeAnalysisImpl(MP);
+
+ {
+ PassManagerPrettyStackEntry X(MP, M);
+ TimeRegion PassTimer(getPassTimer(MP));
+
+ LocalChanged |= MP->runOnModule(M);
+ }
+
+ Changed |= LocalChanged;
+ if (LocalChanged)
+ dumpPassInfo(MP, MODIFICATION_MSG, ON_MODULE_MSG,
+ M.getModuleIdentifier());
+ dumpPreservedSet(MP);
+
+ verifyPreservedAnalysis(MP);
+ removeNotPreservedAnalysis(MP);
+ recordAvailableAnalysis(MP);
+ removeDeadPasses(MP, M.getModuleIdentifier(), ON_MODULE_MSG);
+ }
+
+ // Finalize module passes
+ for (int Index = getNumContainedPasses() - 1; Index >= 0; --Index)
+ Changed |= getContainedPass(Index)->doFinalization(M);
+
+ // Finalize on-the-fly passes
+ for (std::map<Pass *, FunctionPassManagerImpl *>::iterator
+ I = OnTheFlyManagers.begin(), E = OnTheFlyManagers.end();
+ I != E; ++I) {
+ FunctionPassManagerImpl *FPP = I->second;
+ // We don't know when is the last time an on-the-fly pass is run,
+ // so we need to releaseMemory / finalize here
+ FPP->releaseMemoryOnTheFly();
+ Changed |= FPP->doFinalization(M);
+ }
+
+ return Changed;
+}
+
+/// Add RequiredPass into list of lower level passes required by pass P.
+/// RequiredPass is run on the fly by Pass Manager when P requests it
+/// through getAnalysis interface.
+void MPPassManager::addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) {
+ assert(P->getPotentialPassManagerType() == PMT_ModulePassManager &&
+ "Unable to handle Pass that requires lower level Analysis pass");
+ assert((P->getPotentialPassManagerType() <
+ RequiredPass->getPotentialPassManagerType()) &&
+ "Unable to handle Pass that requires lower level Analysis pass");
+
+ FunctionPassManagerImpl *FPP = OnTheFlyManagers[P];
+ if (!FPP) {
+ FPP = new FunctionPassManagerImpl();
+ // FPP is the top level manager.
+ FPP->setTopLevelManager(FPP);
+
+ OnTheFlyManagers[P] = FPP;
+ }
+ FPP->add(RequiredPass);
+
+ // Register P as the last user of RequiredPass.
+ if (RequiredPass) {
+ SmallVector<Pass *, 1> LU;
+ LU.push_back(RequiredPass);
+ FPP->setLastUser(LU, P);
+ }
+}
+
+/// Return function pass corresponding to PassInfo PI, that is
+/// required by module pass MP. Instantiate analysis pass, by using
+/// its runOnFunction() for function F.
+Pass* MPPassManager::getOnTheFlyPass(Pass *MP, AnalysisID PI, Function &F){
+ FunctionPassManagerImpl *FPP = OnTheFlyManagers[MP];
+ assert(FPP && "Unable to find on the fly pass");
+
+ FPP->releaseMemoryOnTheFly();
+ FPP->run(F);
+ return ((PMTopLevelManager*)FPP)->findAnalysisPass(PI);
+}
+
+
+//===----------------------------------------------------------------------===//
+// PassManagerImpl implementation
+
+//
+/// run - Execute all of the passes scheduled for execution. Keep track of
+/// whether any of the passes modifies the module, and if so, return true.
+bool PassManagerImpl::run(Module &M) {
+ bool Changed = false;
+ TimingInfo::createTheTimeInfo();
+
+ dumpArguments();
+ dumpPasses();
+
+ SmallVectorImpl<ImmutablePass *>& IPV = getImmutablePasses();
+ for (SmallVectorImpl<ImmutablePass *>::const_iterator I = IPV.begin(),
+ E = IPV.end(); I != E; ++I) {
+ Changed |= (*I)->doInitialization(M);
+ }
+
+ initializeAllAnalysisInfo();
+ for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index)
+ Changed |= getContainedManager(Index)->runOnModule(M);
+
+ for (SmallVectorImpl<ImmutablePass *>::const_iterator I = IPV.begin(),
+ E = IPV.end(); I != E; ++I) {
+ Changed |= (*I)->doFinalization(M);
+ }
+
+ return Changed;
+}
+
+//===----------------------------------------------------------------------===//
+// PassManager implementation
+
+/// Create new pass manager
+PassManager::PassManager() {
+ PM = new PassManagerImpl();
+ // PM is the top level manager
+ PM->setTopLevelManager(PM);
+}
+
+PassManager::~PassManager() {
+ delete PM;
+}
+
+/// add - Add a pass to the queue of passes to run. This passes ownership of
+/// the Pass to the PassManager. When the PassManager is destroyed, the pass
+/// will be destroyed as well, so there is no need to delete the pass. This
+/// implies that all passes MUST be allocated with 'new'.
+void PassManager::add(Pass *P) {
+ PM->add(P);
+}
+
+/// run - Execute all of the passes scheduled for execution. Keep track of
+/// whether any of the passes modifies the module, and if so, return true.
+bool PassManager::run(Module &M) {
+ return PM->run(M);
+}
+
+//===----------------------------------------------------------------------===//
+// TimingInfo implementation
+
+bool llvm::TimePassesIsEnabled = false;
+static cl::opt<bool,true>
+EnableTiming("time-passes", cl::location(TimePassesIsEnabled),
+ cl::desc("Time each pass, printing elapsed time for each on exit"));
+
+// createTheTimeInfo - This method either initializes the TheTimeInfo pointer to
+// a non null value (if the -time-passes option is enabled) or it leaves it
+// null. It may be called multiple times.
+void TimingInfo::createTheTimeInfo() {
+ if (!TimePassesIsEnabled || TheTimeInfo) return;
+
+ // Constructed the first time this is called, iff -time-passes is enabled.
+ // This guarantees that the object will be constructed before static globals,
+ // thus it will be destroyed before them.
+ static ManagedStatic<TimingInfo> TTI;
+ TheTimeInfo = &*TTI;
+}
+
+/// If TimingInfo is enabled then start pass timer.
+Timer *llvm::getPassTimer(Pass *P) {
+ if (TheTimeInfo)
+ return TheTimeInfo->getPassTimer(P);
+ return 0;
+}
+
+//===----------------------------------------------------------------------===//
+// PMStack implementation
+//
+
+// Pop Pass Manager from the stack and clear its analysis info.
+void PMStack::pop() {
+
+ PMDataManager *Top = this->top();
+ Top->initializeAnalysisInfo();
+
+ S.pop_back();
+}
+
+// Push PM on the stack and set its top level manager.
+void PMStack::push(PMDataManager *PM) {
+ assert(PM && "Unable to push. Pass Manager expected");
+ assert(PM->getDepth()==0 && "Pass Manager depth set too early");
+
+ if (!this->empty()) {
+ assert(PM->getPassManagerType() > this->top()->getPassManagerType()
+ && "pushing bad pass manager to PMStack");
+ PMTopLevelManager *TPM = this->top()->getTopLevelManager();
+
+ assert(TPM && "Unable to find top level manager");
+ TPM->addIndirectPassManager(PM);
+ PM->setTopLevelManager(TPM);
+ PM->setDepth(this->top()->getDepth()+1);
+ } else {
+ assert((PM->getPassManagerType() == PMT_ModulePassManager
+ || PM->getPassManagerType() == PMT_FunctionPassManager)
+ && "pushing bad pass manager to PMStack");
+ PM->setDepth(1);
+ }
+
+ S.push_back(PM);
+}
+
+// Dump content of the pass manager stack.
+void PMStack::dump() const {
+ for (std::vector<PMDataManager *>::const_iterator I = S.begin(),
+ E = S.end(); I != E; ++I)
+ dbgs() << (*I)->getAsPass()->getPassName() << ' ';
+
+ if (!S.empty())
+ dbgs() << '\n';
+}
+
+/// Find appropriate Module Pass Manager in the PM Stack and
+/// add self into that manager.
+void ModulePass::assignPassManager(PMStack &PMS,
+ PassManagerType PreferredType) {
+ // Find Module Pass Manager
+ while (!PMS.empty()) {
+ PassManagerType TopPMType = PMS.top()->getPassManagerType();
+ if (TopPMType == PreferredType)
+ break; // We found desired pass manager
+ else if (TopPMType > PMT_ModulePassManager)
+ PMS.pop(); // Pop children pass managers
+ else
+ break;
+ }
+ assert(!PMS.empty() && "Unable to find appropriate Pass Manager");
+ PMS.top()->add(this);
+}
+
+/// Find appropriate Function Pass Manager or Call Graph Pass Manager
+/// in the PM Stack and add self into that manager.
+void FunctionPass::assignPassManager(PMStack &PMS,
+ PassManagerType PreferredType) {
+
+ // Find Function Pass Manager
+ while (!PMS.empty()) {
+ if (PMS.top()->getPassManagerType() > PMT_FunctionPassManager)
+ PMS.pop();
+ else
+ break;
+ }
+
+ // Create new Function Pass Manager if needed.
+ FPPassManager *FPP;
+ if (PMS.top()->getPassManagerType() == PMT_FunctionPassManager) {
+ FPP = (FPPassManager *)PMS.top();
+ } else {
+ assert(!PMS.empty() && "Unable to create Function Pass Manager");
+ PMDataManager *PMD = PMS.top();
+
+ // [1] Create new Function Pass Manager
+ FPP = new FPPassManager();
+ FPP->populateInheritedAnalysis(PMS);
+
+ // [2] Set up new manager's top level manager
+ PMTopLevelManager *TPM = PMD->getTopLevelManager();
+ TPM->addIndirectPassManager(FPP);
+
+ // [3] Assign manager to manage this new manager. This may create
+ // and push new managers into PMS
+ FPP->assignPassManager(PMS, PMD->getPassManagerType());
+
+ // [4] Push new manager into PMS
+ PMS.push(FPP);
+ }
+
+ // Assign FPP as the manager of this pass.
+ FPP->add(this);
+}
+
+/// Find appropriate Basic Pass Manager or Call Graph Pass Manager
+/// in the PM Stack and add self into that manager.
+void BasicBlockPass::assignPassManager(PMStack &PMS,
+ PassManagerType PreferredType) {
+ BBPassManager *BBP;
+
+ // Basic Pass Manager is a leaf pass manager. It does not handle
+ // any other pass manager.
+ if (!PMS.empty() &&
+ PMS.top()->getPassManagerType() == PMT_BasicBlockPassManager) {
+ BBP = (BBPassManager *)PMS.top();
+ } else {
+ // If leaf manager is not Basic Block Pass manager then create new
+ // basic Block Pass manager.
+ assert(!PMS.empty() && "Unable to create BasicBlock Pass Manager");
+ PMDataManager *PMD = PMS.top();
+
+ // [1] Create new Basic Block Manager
+ BBP = new BBPassManager();
+
+ // [2] Set up new manager's top level manager
+ // Basic Block Pass Manager does not live by itself
+ PMTopLevelManager *TPM = PMD->getTopLevelManager();
+ TPM->addIndirectPassManager(BBP);
+
+ // [3] Assign manager to manage this new manager. This may create
+ // and push new managers into PMS
+ BBP->assignPassManager(PMS, PreferredType);
+
+ // [4] Push new manager into PMS
+ PMS.push(BBP);
+ }
+
+ // Assign BBP as the manager of this pass.
+ BBP->add(this);
+}
+
+PassManagerBase::~PassManagerBase() {}
diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp
index bd4d9c0..a32d25c 100644
--- a/lib/IR/Metadata.cpp
+++ b/lib/IR/Metadata.cpp
@@ -65,7 +65,7 @@ class MDNodeOperand : public CallbackVH {
public:
MDNodeOperand(Value *V) : CallbackVH(V) {}
- ~MDNodeOperand() {}
+ virtual ~MDNodeOperand();
void set(Value *V) {
unsigned IsFirst = this->getValPtrInt();
@@ -82,6 +82,8 @@ public:
};
} // end namespace llvm.
+// Provide out-of-line definition to prevent weak vtable.
+MDNodeOperand::~MDNodeOperand() {}
void MDNodeOperand::deleted() {
getParent()->replaceOperand(this, 0);
diff --git a/lib/IR/Module.cpp b/lib/IR/Module.cpp
index 968b8f4..4f240c7 100644
--- a/lib/IR/Module.cpp
+++ b/lib/IR/Module.cpp
@@ -245,7 +245,7 @@ GlobalVariable *Module::getGlobalVariable(StringRef Name, bool AllowLocal) {
/// 1. If it does not exist, add a declaration of the global and return it.
/// 2. Else, the global exists but has the wrong type: return the function
/// with a constantexpr cast to the right type.
-/// 3. Finally, if the existing global is the correct delclaration, return the
+/// 3. Finally, if the existing global is the correct declaration, return the
/// existing global.
Constant *Module::getOrInsertGlobal(StringRef Name, Type *Ty) {
// See if we have a definition for the specified global already.
@@ -260,8 +260,10 @@ Constant *Module::getOrInsertGlobal(StringRef Name, Type *Ty) {
// If the variable exists but has the wrong type, return a bitcast to the
// right type.
- if (GV->getType() != PointerType::getUnqual(Ty))
- return ConstantExpr::getBitCast(GV, PointerType::getUnqual(Ty));
+ Type *GVTy = GV->getType();
+ PointerType *PTy = PointerType::get(Ty, GVTy->getPointerAddressSpace());
+ if (GVTy != PTy)
+ return ConstantExpr::getBitCast(GV, PTy);
// Otherwise, we just found the existing function or a prototype.
return GV;
@@ -316,11 +318,16 @@ getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const {
for (unsigned i = 0, e = ModFlags->getNumOperands(); i != e; ++i) {
MDNode *Flag = ModFlags->getOperand(i);
- 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));
+ if (Flag->getNumOperands() >= 3 && isa<ConstantInt>(Flag->getOperand(0)) &&
+ 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));
+ }
}
}
@@ -399,9 +406,15 @@ bool Module::isDematerializable(const GlobalValue *GV) const {
}
bool Module::Materialize(GlobalValue *GV, std::string *ErrInfo) {
- if (Materializer)
- return Materializer->Materialize(GV, ErrInfo);
- return false;
+ if (!Materializer)
+ return false;
+
+ error_code EC = Materializer->Materialize(GV);
+ if (!EC)
+ return false;
+ if (ErrInfo)
+ *ErrInfo = EC.message();
+ return true;
}
void Module::Dematerialize(GlobalValue *GV) {
@@ -412,7 +425,12 @@ void Module::Dematerialize(GlobalValue *GV) {
bool Module::MaterializeAll(std::string *ErrInfo) {
if (!Materializer)
return false;
- return Materializer->MaterializeModule(this, ErrInfo);
+ error_code EC = Materializer->MaterializeModule(this);
+ if (!EC)
+ return false;
+ if (ErrInfo)
+ *ErrInfo = EC.message();
+ return true;
}
bool Module::MaterializeAllPermanently(std::string *ErrInfo) {
diff --git a/lib/IR/PassManager.cpp b/lib/IR/PassManager.cpp
index ee53c85..966af7d 100644
--- a/lib/IR/PassManager.cpp
+++ b/lib/IR/PassManager.cpp
@@ -1,4 +1,4 @@
-//===- PassManager.cpp - LLVM Pass Infrastructure Implementation ----------===//
+//===- PassManager.h - Infrastructure for managing & running IR passes ----===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,1907 +6,152 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the LLVM Pass Manager infrastructure.
-//
-//===----------------------------------------------------------------------===//
+#include "llvm/IR/PassManager.h"
+#include "llvm/ADT/STLExtras.h"
-#include "llvm/PassManagers.h"
-#include "llvm/Assembly/PrintModulePass.h"
-#include "llvm/Assembly/Writer.h"
-#include "llvm/IR/Module.h"
-#include "llvm/PassManager.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/Mutex.h"
-#include "llvm/Support/PassNameParser.h"
-#include "llvm/Support/Timer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <map>
using namespace llvm;
-// See PassManagers.h for Pass Manager infrastructure overview.
-
-namespace llvm {
-
-//===----------------------------------------------------------------------===//
-// Pass debugging information. Often it is useful to find out what pass is
-// running when a crash occurs in a utility. When this library is compiled with
-// debugging on, a command line option (--debug-pass) is enabled that causes the
-// pass name to be printed before it executes.
-//
-
-// Different debug levels that can be enabled...
-enum PassDebugLevel {
- Disabled, Arguments, Structure, Executions, Details
-};
-
-static cl::opt<enum PassDebugLevel>
-PassDebugging("debug-pass", cl::Hidden,
- cl::desc("Print PassManager debugging information"),
- cl::values(
- clEnumVal(Disabled , "disable debug output"),
- clEnumVal(Arguments , "print pass arguments to pass to 'opt'"),
- clEnumVal(Structure , "print pass structure before run()"),
- clEnumVal(Executions, "print pass name before it is executed"),
- clEnumVal(Details , "print pass details when it is executed"),
- clEnumValEnd));
-
-typedef llvm::cl::list<const llvm::PassInfo *, bool, PassNameParser>
-PassOptionList;
-
-// Print IR out before/after specified passes.
-static PassOptionList
-PrintBefore("print-before",
- llvm::cl::desc("Print IR before specified passes"),
- cl::Hidden);
-
-static PassOptionList
-PrintAfter("print-after",
- llvm::cl::desc("Print IR after specified passes"),
- cl::Hidden);
-
-static cl::opt<bool>
-PrintBeforeAll("print-before-all",
- llvm::cl::desc("Print IR before each pass"),
- cl::init(false));
-static cl::opt<bool>
-PrintAfterAll("print-after-all",
- llvm::cl::desc("Print IR after each pass"),
- cl::init(false));
-
-/// This is a helper to determine whether to print IR before or
-/// after a pass.
-
-static bool ShouldPrintBeforeOrAfterPass(const PassInfo *PI,
- PassOptionList &PassesToPrint) {
- for (unsigned i = 0, ie = PassesToPrint.size(); i < ie; ++i) {
- const llvm::PassInfo *PassInf = PassesToPrint[i];
- if (PassInf)
- if (PassInf->getPassArgument() == PI->getPassArgument()) {
- return true;
- }
- }
- return false;
-}
-
-/// This is a utility to check whether a pass should have IR dumped
-/// before it.
-static bool ShouldPrintBeforePass(const PassInfo *PI) {
- return PrintBeforeAll || ShouldPrintBeforeOrAfterPass(PI, PrintBefore);
-}
-
-/// This is a utility to check whether a pass should have IR dumped
-/// after it.
-static bool ShouldPrintAfterPass(const PassInfo *PI) {
- return PrintAfterAll || ShouldPrintBeforeOrAfterPass(PI, PrintAfter);
-}
-
-} // End of llvm namespace
-
-/// isPassDebuggingExecutionsOrMore - Return true if -debug-pass=Executions
-/// or higher is specified.
-bool PMDataManager::isPassDebuggingExecutionsOrMore() const {
- return PassDebugging >= Executions;
-}
-
-
-
-
-void PassManagerPrettyStackEntry::print(raw_ostream &OS) const {
- if (V == 0 && M == 0)
- OS << "Releasing pass '";
- else
- OS << "Running pass '";
-
- OS << P->getPassName() << "'";
-
- if (M) {
- OS << " on module '" << M->getModuleIdentifier() << "'.\n";
- return;
- }
- if (V == 0) {
- OS << '\n';
- return;
- }
-
- OS << " on ";
- if (isa<Function>(V))
- OS << "function";
- else if (isa<BasicBlock>(V))
- OS << "basic block";
- else
- OS << "value";
-
- OS << " '";
- WriteAsOperand(OS, V, /*PrintTy=*/false, M);
- OS << "'\n";
+void ModulePassManager::run() {
+ for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx)
+ if (Passes[Idx]->run(M))
+ if (AM) AM->invalidateAll(M);
}
-
-namespace {
-
-//===----------------------------------------------------------------------===//
-// BBPassManager
-//
-/// BBPassManager manages BasicBlockPass. It batches all the
-/// pass together and sequence them to process one basic block before
-/// processing next basic block.
-class BBPassManager : public PMDataManager, public FunctionPass {
-
-public:
- static char ID;
- explicit BBPassManager()
- : PMDataManager(), FunctionPass(ID) {}
-
- /// Execute all of the passes scheduled for execution. Keep track of
- /// whether any of the passes modifies the function, and if so, return true.
- bool runOnFunction(Function &F);
-
- /// Pass Manager itself does not invalidate any analysis info.
- void getAnalysisUsage(AnalysisUsage &Info) const {
- Info.setPreservesAll();
- }
-
- bool doInitialization(Module &M);
- bool doInitialization(Function &F);
- bool doFinalization(Module &M);
- bool doFinalization(Function &F);
-
- virtual PMDataManager *getAsPMDataManager() { return this; }
- virtual Pass *getAsPass() { return this; }
-
- virtual const char *getPassName() const {
- return "BasicBlock Pass Manager";
- }
-
- // Print passes managed by this manager
- void dumpPassStructure(unsigned Offset) {
- llvm::dbgs().indent(Offset*2) << "BasicBlockPass Manager\n";
- for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
- BasicBlockPass *BP = getContainedPass(Index);
- BP->dumpPassStructure(Offset + 1);
- dumpLastUses(BP, Offset+1);
- }
- }
-
- BasicBlockPass *getContainedPass(unsigned N) {
- assert(N < PassVector.size() && "Pass number out of range!");
- BasicBlockPass *BP = static_cast<BasicBlockPass *>(PassVector[N]);
- return BP;
- }
-
- virtual PassManagerType getPassManagerType() const {
- return PMT_BasicBlockPassManager;
- }
-};
-
-char BBPassManager::ID = 0;
-}
-
-namespace llvm {
-
-//===----------------------------------------------------------------------===//
-// FunctionPassManagerImpl
-//
-/// FunctionPassManagerImpl manages FPPassManagers
-class FunctionPassManagerImpl : public Pass,
- public PMDataManager,
- public PMTopLevelManager {
- virtual void anchor();
-private:
- bool wasRun;
-public:
- static char ID;
- explicit FunctionPassManagerImpl() :
- Pass(PT_PassManager, ID), PMDataManager(),
- PMTopLevelManager(new FPPassManager()), wasRun(false) {}
-
- /// add - Add a pass to the queue of passes to run. This passes ownership of
- /// the Pass to the PassManager. When the PassManager is destroyed, the pass
- /// will be destroyed as well, so there is no need to delete the pass. This
- /// implies that all passes MUST be allocated with 'new'.
- void add(Pass *P) {
- schedulePass(P);
- }
-
- /// createPrinterPass - Get a function printer pass.
- Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const {
- return createPrintFunctionPass(Banner, &O);
- }
-
- // Prepare for running an on the fly pass, freeing memory if needed
- // from a previous run.
- void releaseMemoryOnTheFly();
-
- /// run - Execute all of the passes scheduled for execution. Keep track of
- /// whether any of the passes modifies the module, and if so, return true.
- bool run(Function &F);
-
- /// doInitialization - Run all of the initializers for the function passes.
- ///
- bool doInitialization(Module &M);
-
- /// doFinalization - Run all of the finalizers for the function passes.
- ///
- bool doFinalization(Module &M);
-
-
- virtual PMDataManager *getAsPMDataManager() { return this; }
- virtual Pass *getAsPass() { return this; }
- virtual PassManagerType getTopLevelPassManagerType() {
- return PMT_FunctionPassManager;
- }
-
- /// Pass Manager itself does not invalidate any analysis info.
- void getAnalysisUsage(AnalysisUsage &Info) const {
- Info.setPreservesAll();
- }
-
- FPPassManager *getContainedManager(unsigned N) {
- assert(N < PassManagers.size() && "Pass number out of range!");
- FPPassManager *FP = static_cast<FPPassManager *>(PassManagers[N]);
- return FP;
- }
-};
-
-void FunctionPassManagerImpl::anchor() {}
-
-char FunctionPassManagerImpl::ID = 0;
-
-//===----------------------------------------------------------------------===//
-// MPPassManager
-//
-/// MPPassManager manages ModulePasses and function pass managers.
-/// It batches all Module passes and function pass managers together and
-/// sequences them to process one module.
-class MPPassManager : public Pass, public PMDataManager {
-public:
- static char ID;
- explicit MPPassManager() :
- Pass(PT_PassManager, ID), PMDataManager() { }
-
- // Delete on the fly managers.
- virtual ~MPPassManager() {
- for (std::map<Pass *, FunctionPassManagerImpl *>::iterator
- I = OnTheFlyManagers.begin(), E = OnTheFlyManagers.end();
- I != E; ++I) {
- FunctionPassManagerImpl *FPP = I->second;
- delete FPP;
- }
- }
-
- /// createPrinterPass - Get a module printer pass.
- Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const {
- return createPrintModulePass(&O, false, Banner);
- }
-
- /// run - Execute all of the passes scheduled for execution. Keep track of
- /// whether any of the passes modifies the module, and if so, return true.
- bool runOnModule(Module &M);
-
- using llvm::Pass::doInitialization;
- using llvm::Pass::doFinalization;
-
- /// doInitialization - Run all of the initializers for the module passes.
- ///
- bool doInitialization();
-
- /// doFinalization - Run all of the finalizers for the module passes.
- ///
- bool doFinalization();
-
- /// Pass Manager itself does not invalidate any analysis info.
- void getAnalysisUsage(AnalysisUsage &Info) const {
- Info.setPreservesAll();
- }
-
- /// Add RequiredPass into list of lower level passes required by pass P.
- /// RequiredPass is run on the fly by Pass Manager when P requests it
- /// through getAnalysis interface.
- virtual void addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass);
-
- /// Return function pass corresponding to PassInfo PI, that is
- /// required by module pass MP. Instantiate analysis pass, by using
- /// its runOnFunction() for function F.
- virtual Pass* getOnTheFlyPass(Pass *MP, AnalysisID PI, Function &F);
-
- virtual const char *getPassName() const {
- return "Module Pass Manager";
- }
-
- virtual PMDataManager *getAsPMDataManager() { return this; }
- virtual Pass *getAsPass() { return this; }
-
- // Print passes managed by this manager
- void dumpPassStructure(unsigned Offset) {
- llvm::dbgs().indent(Offset*2) << "ModulePass Manager\n";
- for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
- ModulePass *MP = getContainedPass(Index);
- MP->dumpPassStructure(Offset + 1);
- std::map<Pass *, FunctionPassManagerImpl *>::const_iterator I =
- OnTheFlyManagers.find(MP);
- if (I != OnTheFlyManagers.end())
- I->second->dumpPassStructure(Offset + 2);
- dumpLastUses(MP, Offset+1);
- }
- }
-
- ModulePass *getContainedPass(unsigned N) {
- assert(N < PassVector.size() && "Pass number out of range!");
- return static_cast<ModulePass *>(PassVector[N]);
- }
-
- virtual PassManagerType getPassManagerType() const {
- return PMT_ModulePassManager;
- }
-
- private:
- /// Collection of on the fly FPPassManagers. These managers manage
- /// function passes that are required by module passes.
- std::map<Pass *, FunctionPassManagerImpl *> OnTheFlyManagers;
-};
-
-char MPPassManager::ID = 0;
-//===----------------------------------------------------------------------===//
-// PassManagerImpl
-//
-
-/// PassManagerImpl manages MPPassManagers
-class PassManagerImpl : public Pass,
- public PMDataManager,
- public PMTopLevelManager {
- virtual void anchor();
-
-public:
- static char ID;
- explicit PassManagerImpl() :
- Pass(PT_PassManager, ID), PMDataManager(),
- PMTopLevelManager(new MPPassManager()) {}
-
- /// add - Add a pass to the queue of passes to run. This passes ownership of
- /// the Pass to the PassManager. When the PassManager is destroyed, the pass
- /// will be destroyed as well, so there is no need to delete the pass. This
- /// implies that all passes MUST be allocated with 'new'.
- void add(Pass *P) {
- schedulePass(P);
- }
-
- /// createPrinterPass - Get a module printer pass.
- Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const {
- return createPrintModulePass(&O, false, Banner);
- }
-
- /// run - Execute all of the passes scheduled for execution. Keep track of
- /// whether any of the passes modifies the module, and if so, return true.
- bool run(Module &M);
-
- using llvm::Pass::doInitialization;
- using llvm::Pass::doFinalization;
-
- /// doInitialization - Run all of the initializers for the module passes.
- ///
- bool doInitialization();
-
- /// doFinalization - Run all of the finalizers for the module passes.
- ///
- bool doFinalization();
-
- /// Pass Manager itself does not invalidate any analysis info.
- void getAnalysisUsage(AnalysisUsage &Info) const {
- Info.setPreservesAll();
- }
-
- virtual PMDataManager *getAsPMDataManager() { return this; }
- virtual Pass *getAsPass() { return this; }
- virtual PassManagerType getTopLevelPassManagerType() {
- return PMT_ModulePassManager;
- }
-
- MPPassManager *getContainedManager(unsigned N) {
- assert(N < PassManagers.size() && "Pass number out of range!");
- MPPassManager *MP = static_cast<MPPassManager *>(PassManagers[N]);
- return MP;
- }
-};
-
-void PassManagerImpl::anchor() {}
-
-char PassManagerImpl::ID = 0;
-} // End of llvm namespace
-
-namespace {
-
-//===----------------------------------------------------------------------===//
-/// TimingInfo Class - This class is used to calculate information about the
-/// amount of time each pass takes to execute. This only happens when
-/// -time-passes is enabled on the command line.
-///
-
-static ManagedStatic<sys::SmartMutex<true> > TimingInfoMutex;
-
-class TimingInfo {
- DenseMap<Pass*, Timer*> TimingData;
- TimerGroup TG;
-public:
- // Use 'create' member to get this.
- TimingInfo() : TG("... Pass execution timing report ...") {}
-
- // TimingDtor - Print out information about timing information
- ~TimingInfo() {
- // Delete all of the timers, which accumulate their info into the
- // TimerGroup.
- for (DenseMap<Pass*, Timer*>::iterator I = TimingData.begin(),
- E = TimingData.end(); I != E; ++I)
- delete I->second;
- // TimerGroup is deleted next, printing the report.
- }
-
- // createTheTimeInfo - This method either initializes the TheTimeInfo pointer
- // to a non null value (if the -time-passes option is enabled) or it leaves it
- // null. It may be called multiple times.
- static void createTheTimeInfo();
-
- /// getPassTimer - Return the timer for the specified pass if it exists.
- Timer *getPassTimer(Pass *P) {
- if (P->getAsPMDataManager())
- return 0;
-
- sys::SmartScopedLock<true> Lock(*TimingInfoMutex);
- Timer *&T = TimingData[P];
- if (T == 0)
- T = new Timer(P->getPassName(), TG);
- return T;
- }
-};
-
-} // End of anon namespace
-
-static TimingInfo *TheTimeInfo;
-
-//===----------------------------------------------------------------------===//
-// PMTopLevelManager implementation
-
-/// Initialize top level manager. Create first pass manager.
-PMTopLevelManager::PMTopLevelManager(PMDataManager *PMDM) {
- PMDM->setTopLevelManager(this);
- addPassManager(PMDM);
- activeStack.push(PMDM);
-}
-
-/// Set pass P as the last user of the given analysis passes.
-void
-PMTopLevelManager::setLastUser(ArrayRef<Pass*> AnalysisPasses, Pass *P) {
- unsigned PDepth = 0;
- if (P->getResolver())
- PDepth = P->getResolver()->getPMDataManager().getDepth();
-
- for (SmallVectorImpl<Pass *>::const_iterator I = AnalysisPasses.begin(),
- E = AnalysisPasses.end(); I != E; ++I) {
- Pass *AP = *I;
- LastUser[AP] = P;
-
- if (P == AP)
- continue;
-
- // Update the last users of passes that are required transitive by AP.
- AnalysisUsage *AnUsage = findAnalysisUsage(AP);
- const AnalysisUsage::VectorType &IDs = AnUsage->getRequiredTransitiveSet();
- SmallVector<Pass *, 12> LastUses;
- SmallVector<Pass *, 12> LastPMUses;
- for (AnalysisUsage::VectorType::const_iterator I = IDs.begin(),
- E = IDs.end(); I != E; ++I) {
- Pass *AnalysisPass = findAnalysisPass(*I);
- assert(AnalysisPass && "Expected analysis pass to exist.");
- AnalysisResolver *AR = AnalysisPass->getResolver();
- assert(AR && "Expected analysis resolver to exist.");
- unsigned APDepth = AR->getPMDataManager().getDepth();
-
- if (PDepth == APDepth)
- LastUses.push_back(AnalysisPass);
- else if (PDepth > APDepth)
- LastPMUses.push_back(AnalysisPass);
- }
-
- setLastUser(LastUses, P);
-
- // If this pass has a corresponding pass manager, push higher level
- // analysis to this pass manager.
- if (P->getResolver())
- setLastUser(LastPMUses, P->getResolver()->getPMDataManager().getAsPass());
-
-
- // If AP is the last user of other passes then make P last user of
- // such passes.
- for (DenseMap<Pass *, Pass *>::iterator LUI = LastUser.begin(),
- LUE = LastUser.end(); LUI != LUE; ++LUI) {
- if (LUI->second == AP)
- // DenseMap iterator is not invalidated here because
- // this is just updating existing entries.
- LastUser[LUI->first] = P;
- }
- }
-}
-
-/// Collect passes whose last user is P
-void PMTopLevelManager::collectLastUses(SmallVectorImpl<Pass *> &LastUses,
- Pass *P) {
- DenseMap<Pass *, SmallPtrSet<Pass *, 8> >::iterator DMI =
- InversedLastUser.find(P);
- if (DMI == InversedLastUser.end())
- 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);
- }
-
-}
-
-AnalysisUsage *PMTopLevelManager::findAnalysisUsage(Pass *P) {
- AnalysisUsage *AnUsage = NULL;
- DenseMap<Pass *, AnalysisUsage *>::iterator DMI = AnUsageMap.find(P);
- if (DMI != AnUsageMap.end())
- AnUsage = DMI->second;
- else {
- AnUsage = new AnalysisUsage();
- P->getAnalysisUsage(*AnUsage);
- AnUsageMap[P] = AnUsage;
- }
- return AnUsage;
-}
-
-/// Schedule pass P for execution. Make sure that passes required by
-/// P are run before P is run. Update analysis info maintained by
-/// the manager. Remove dead passes. This is a recursive function.
-void PMTopLevelManager::schedulePass(Pass *P) {
-
- // TODO : Allocate function manager for this pass, other wise required set
- // may be inserted into previous function manager
-
- // Give pass a chance to prepare the stage.
- P->preparePassManager(activeStack);
-
- // If P is an analysis pass and it is available then do not
- // generate the analysis again. Stale analysis info should not be
- // available at this point.
- const PassInfo *PI =
- PassRegistry::getPassRegistry()->getPassInfo(P->getPassID());
- if (PI && PI->isAnalysis() && findAnalysisPass(P->getPassID())) {
- delete P;
- return;
- }
-
- AnalysisUsage *AnUsage = findAnalysisUsage(P);
-
- bool checkAnalysis = true;
- while (checkAnalysis) {
- checkAnalysis = false;
-
- const AnalysisUsage::VectorType &RequiredSet = AnUsage->getRequiredSet();
- for (AnalysisUsage::VectorType::const_iterator I = RequiredSet.begin(),
- E = RequiredSet.end(); I != E; ++I) {
-
- Pass *AnalysisPass = findAnalysisPass(*I);
- if (!AnalysisPass) {
- const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(*I);
-
- if (PI == NULL) {
- // Pass P is not in the global PassRegistry
- dbgs() << "Pass '" << P->getPassName() << "' is not initialized." << "\n";
- dbgs() << "Verify if there is a pass dependency cycle." << "\n";
- dbgs() << "Required Passes:" << "\n";
- for (AnalysisUsage::VectorType::const_iterator I2 = RequiredSet.begin(),
- E = RequiredSet.end(); I2 != E && I2 != I; ++I2) {
- Pass *AnalysisPass2 = findAnalysisPass(*I2);
- if (AnalysisPass2) {
- dbgs() << "\t" << AnalysisPass2->getPassName() << "\n";
- } else {
- dbgs() << "\t" << "Error: Required pass not found! Possible causes:" << "\n";
- dbgs() << "\t\t" << "- Pass misconfiguration (e.g.: missing macros)" << "\n";
- dbgs() << "\t\t" << "- Corruption of the global PassRegistry" << "\n";
- }
- }
- }
-
- assert(PI && "Expected required passes to be initialized");
- AnalysisPass = PI->createPass();
- if (P->getPotentialPassManagerType () ==
- AnalysisPass->getPotentialPassManagerType())
- // Schedule analysis pass that is managed by the same pass manager.
- schedulePass(AnalysisPass);
- else if (P->getPotentialPassManagerType () >
- AnalysisPass->getPotentialPassManagerType()) {
- // Schedule analysis pass that is managed by a new manager.
- schedulePass(AnalysisPass);
- // Recheck analysis passes to ensure that required analyses that
- // are already checked are still available.
- checkAnalysis = true;
- } else
- // Do not schedule this analysis. Lower level analsyis
- // passes are run on the fly.
- delete AnalysisPass;
+bool FunctionPassManager::run(Module *M) {
+ bool Changed = false;
+ for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
+ for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx)
+ if (Passes[Idx]->run(I)) {
+ Changed = true;
+ if (AM) AM->invalidateAll(I);
}
- }
- }
-
- // Now all required passes are available.
- if (ImmutablePass *IP = P->getAsImmutablePass()) {
- // P is a immutable pass and it will be managed by this
- // top level manager. Set up analysis resolver to connect them.
- PMDataManager *DM = getAsPMDataManager();
- AnalysisResolver *AR = new AnalysisResolver(*DM);
- P->setResolver(AR);
- DM->initializeAnalysisImpl(P);
- addImmutablePass(IP);
- DM->recordAvailableAnalysis(IP);
- return;
- }
-
- if (PI && !PI->isAnalysis() && ShouldPrintBeforePass(PI)) {
- Pass *PP = P->createPrinterPass(
- dbgs(), std::string("*** IR Dump Before ") + P->getPassName() + " ***");
- PP->assignPassManager(activeStack, getTopLevelPassManagerType());
- }
-
- // Add the requested pass to the best available pass manager.
- P->assignPassManager(activeStack, getTopLevelPassManagerType());
-
- if (PI && !PI->isAnalysis() && ShouldPrintAfterPass(PI)) {
- Pass *PP = P->createPrinterPass(
- dbgs(), std::string("*** IR Dump After ") + P->getPassName() + " ***");
- PP->assignPassManager(activeStack, getTopLevelPassManagerType());
- }
-}
-
-/// Find the pass that implements Analysis AID. Search immutable
-/// passes and all pass managers. If desired pass is not found
-/// then return NULL.
-Pass *PMTopLevelManager::findAnalysisPass(AnalysisID AID) {
-
- // Check pass managers
- for (SmallVectorImpl<PMDataManager *>::iterator I = PassManagers.begin(),
- E = PassManagers.end(); I != E; ++I)
- if (Pass *P = (*I)->findAnalysisPass(AID, false))
- return P;
-
- // Check other pass managers
- for (SmallVectorImpl<PMDataManager *>::iterator
- I = IndirectPassManagers.begin(),
- E = IndirectPassManagers.end(); I != E; ++I)
- if (Pass *P = (*I)->findAnalysisPass(AID, false))
- return P;
-
- // Check the immutable passes. Iterate in reverse order so that we find
- // the most recently registered passes first.
- for (SmallVectorImpl<ImmutablePass *>::reverse_iterator I =
- ImmutablePasses.rbegin(), E = ImmutablePasses.rend(); I != E; ++I) {
- AnalysisID PI = (*I)->getPassID();
- if (PI == AID)
- return *I;
-
- // If Pass not found then check the interfaces implemented by Immutable Pass
- const PassInfo *PassInf =
- PassRegistry::getPassRegistry()->getPassInfo(PI);
- assert(PassInf && "Expected all immutable passes to be initialized");
- const std::vector<const PassInfo*> &ImmPI =
- PassInf->getInterfacesImplemented();
- for (std::vector<const PassInfo*>::const_iterator II = ImmPI.begin(),
- EE = ImmPI.end(); II != EE; ++II) {
- if ((*II)->getTypeInfo() == AID)
- return *I;
- }
- }
-
- return 0;
-}
-
-// Print passes managed by this top level manager.
-void PMTopLevelManager::dumpPasses() const {
-
- if (PassDebugging < Structure)
- return;
-
- // Print out the immutable passes
- for (unsigned i = 0, e = ImmutablePasses.size(); i != e; ++i) {
- ImmutablePasses[i]->dumpPassStructure(0);
- }
-
- // Every class that derives from PMDataManager also derives from Pass
- // (sometimes indirectly), but there's no inheritance relationship
- // between PMDataManager and Pass, so we have to getAsPass to get
- // from a PMDataManager* to a Pass*.
- for (SmallVectorImpl<PMDataManager *>::const_iterator I =
- PassManagers.begin(), E = PassManagers.end(); I != E; ++I)
- (*I)->getAsPass()->dumpPassStructure(1);
-}
-
-void PMTopLevelManager::dumpArguments() const {
-
- if (PassDebugging < Arguments)
- return;
-
- dbgs() << "Pass Arguments: ";
- for (SmallVectorImpl<ImmutablePass *>::const_iterator I =
- ImmutablePasses.begin(), E = ImmutablePasses.end(); I != E; ++I)
- if (const PassInfo *PI =
- PassRegistry::getPassRegistry()->getPassInfo((*I)->getPassID())) {
- assert(PI && "Expected all immutable passes to be initialized");
- if (!PI->isAnalysisGroup())
- dbgs() << " -" << PI->getPassArgument();
- }
- for (SmallVectorImpl<PMDataManager *>::const_iterator I =
- PassManagers.begin(), E = PassManagers.end(); I != E; ++I)
- (*I)->dumpPassArguments();
- dbgs() << "\n";
+ return Changed;
}
-void PMTopLevelManager::initializeAllAnalysisInfo() {
- for (SmallVectorImpl<PMDataManager *>::iterator I = PassManagers.begin(),
- E = PassManagers.end(); I != E; ++I)
- (*I)->initializeAnalysisInfo();
+void AnalysisManager::invalidateAll(Function *F) {
+ assert(F->getParent() == M && "Invalidating a function from another module!");
- // Initailize other pass managers
- for (SmallVectorImpl<PMDataManager *>::iterator
- I = IndirectPassManagers.begin(), E = IndirectPassManagers.end();
+ // First invalidate any module results we still have laying about.
+ // FIXME: This is a total hack based on the fact that erasure doesn't
+ // invalidate iteration for DenseMap.
+ for (ModuleAnalysisResultMapT::iterator I = ModuleAnalysisResults.begin(),
+ E = ModuleAnalysisResults.end();
I != E; ++I)
- (*I)->initializeAnalysisInfo();
-
- for (DenseMap<Pass *, Pass *>::iterator DMI = LastUser.begin(),
- DME = LastUser.end(); DMI != DME; ++DMI) {
- DenseMap<Pass *, SmallPtrSet<Pass *, 8> >::iterator InvDMI =
- InversedLastUser.find(DMI->second);
- if (InvDMI != InversedLastUser.end()) {
- SmallPtrSet<Pass *, 8> &L = InvDMI->second;
- L.insert(DMI->first);
+ if (I->second->invalidate(M))
+ ModuleAnalysisResults.erase(I);
+
+ // Now clear all the invalidated results associated specifically with this
+ // function.
+ SmallVector<void *, 8> InvalidatedPassIDs;
+ FunctionAnalysisResultListT &ResultsList = FunctionAnalysisResultLists[F];
+ for (FunctionAnalysisResultListT::iterator I = ResultsList.begin(),
+ E = ResultsList.end();
+ I != E;)
+ if (I->second->invalidate(F)) {
+ InvalidatedPassIDs.push_back(I->first);
+ I = ResultsList.erase(I);
} else {
- SmallPtrSet<Pass *, 8> L; L.insert(DMI->first);
- InversedLastUser[DMI->second] = L;
+ ++I;
}
- }
-}
-
-/// Destructor
-PMTopLevelManager::~PMTopLevelManager() {
- for (SmallVectorImpl<PMDataManager *>::iterator I = PassManagers.begin(),
- E = PassManagers.end(); I != E; ++I)
- delete *I;
-
- for (SmallVectorImpl<ImmutablePass *>::iterator
- I = ImmutablePasses.begin(), E = ImmutablePasses.end(); I != E; ++I)
- delete *I;
-
- for (DenseMap<Pass *, AnalysisUsage *>::iterator DMI = AnUsageMap.begin(),
- DME = AnUsageMap.end(); DMI != DME; ++DMI)
- delete DMI->second;
-}
-
-//===----------------------------------------------------------------------===//
-// PMDataManager implementation
-
-/// Augement AvailableAnalysis by adding analysis made available by pass P.
-void PMDataManager::recordAvailableAnalysis(Pass *P) {
- AnalysisID PI = P->getPassID();
-
- AvailableAnalysis[PI] = P;
-
- assert(!AvailableAnalysis.empty());
-
- // This pass is the current implementation of all of the interfaces it
- // implements as well.
- const PassInfo *PInf = PassRegistry::getPassRegistry()->getPassInfo(PI);
- if (PInf == 0) return;
- const std::vector<const PassInfo*> &II = PInf->getInterfacesImplemented();
- for (unsigned i = 0, e = II.size(); i != e; ++i)
- AvailableAnalysis[II[i]->getTypeInfo()] = P;
+ while (!InvalidatedPassIDs.empty())
+ FunctionAnalysisResults.erase(
+ std::make_pair(InvalidatedPassIDs.pop_back_val(), F));
}
-// Return true if P preserves high level analysis used by other
-// passes managed by this manager
-bool PMDataManager::preserveHigherLevelAnalysis(Pass *P) {
- AnalysisUsage *AnUsage = TPM->findAnalysisUsage(P);
- if (AnUsage->getPreservesAll())
- return true;
-
- const AnalysisUsage::VectorType &PreservedSet = AnUsage->getPreservedSet();
- for (SmallVectorImpl<Pass *>::iterator I = HigherLevelAnalysis.begin(),
- E = HigherLevelAnalysis.end(); I != E; ++I) {
- Pass *P1 = *I;
- if (P1->getAsImmutablePass() == 0 &&
- std::find(PreservedSet.begin(), PreservedSet.end(),
- P1->getPassID()) ==
- PreservedSet.end())
- return false;
- }
-
- return true;
-}
-
-/// verifyPreservedAnalysis -- Verify analysis preserved by pass P.
-void PMDataManager::verifyPreservedAnalysis(Pass *P) {
- // Don't do this unless assertions are enabled.
-#ifdef NDEBUG
- return;
-#endif
- AnalysisUsage *AnUsage = TPM->findAnalysisUsage(P);
- const AnalysisUsage::VectorType &PreservedSet = AnUsage->getPreservedSet();
-
- // Verify preserved analysis
- for (AnalysisUsage::VectorType::const_iterator I = PreservedSet.begin(),
- E = PreservedSet.end(); I != E; ++I) {
- AnalysisID AID = *I;
- if (Pass *AP = findAnalysisPass(AID, true)) {
- TimeRegion PassTimer(getPassTimer(AP));
- AP->verifyAnalysis();
- }
- }
-}
-
-/// Remove Analysis not preserved by Pass P
-void PMDataManager::removeNotPreservedAnalysis(Pass *P) {
- AnalysisUsage *AnUsage = TPM->findAnalysisUsage(P);
- if (AnUsage->getPreservesAll())
- return;
-
- const AnalysisUsage::VectorType &PreservedSet = AnUsage->getPreservedSet();
- for (DenseMap<AnalysisID, Pass*>::iterator I = AvailableAnalysis.begin(),
- E = AvailableAnalysis.end(); I != E; ) {
- DenseMap<AnalysisID, Pass*>::iterator Info = I++;
- if (Info->second->getAsImmutablePass() == 0 &&
- std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) ==
- PreservedSet.end()) {
- // Remove this analysis
- if (PassDebugging >= Details) {
- Pass *S = Info->second;
- dbgs() << " -- '" << P->getPassName() << "' is not preserving '";
- dbgs() << S->getPassName() << "'\n";
- }
- AvailableAnalysis.erase(Info);
- }
- }
-
- // Check inherited analysis also. If P is not preserving analysis
- // provided by parent manager then remove it here.
- for (unsigned Index = 0; Index < PMT_Last; ++Index) {
-
- if (!InheritedAnalysis[Index])
- continue;
-
- for (DenseMap<AnalysisID, Pass*>::iterator
- I = InheritedAnalysis[Index]->begin(),
- E = InheritedAnalysis[Index]->end(); I != E; ) {
- DenseMap<AnalysisID, Pass *>::iterator Info = I++;
- if (Info->second->getAsImmutablePass() == 0 &&
- std::find(PreservedSet.begin(), PreservedSet.end(), Info->first) ==
- PreservedSet.end()) {
- // Remove this analysis
- if (PassDebugging >= Details) {
- Pass *S = Info->second;
- dbgs() << " -- '" << P->getPassName() << "' is not preserving '";
- dbgs() << S->getPassName() << "'\n";
- }
- InheritedAnalysis[Index]->erase(Info);
- }
- }
- }
-}
-
-/// Remove analysis passes that are not used any longer
-void PMDataManager::removeDeadPasses(Pass *P, StringRef Msg,
- enum PassDebuggingString DBG_STR) {
-
- SmallVector<Pass *, 12> DeadPasses;
-
- // If this is a on the fly manager then it does not have TPM.
- if (!TPM)
- return;
-
- TPM->collectLastUses(DeadPasses, P);
-
- if (PassDebugging >= Details && !DeadPasses.empty()) {
- dbgs() << " -*- '" << P->getPassName();
- dbgs() << "' is the last user of following pass instances.";
- dbgs() << " Free these instances\n";
- }
-
- for (SmallVectorImpl<Pass *>::iterator I = DeadPasses.begin(),
- E = DeadPasses.end(); I != E; ++I)
- freePass(*I, Msg, DBG_STR);
-}
-
-void PMDataManager::freePass(Pass *P, StringRef Msg,
- enum PassDebuggingString DBG_STR) {
- dumpPassInfo(P, FREEING_MSG, DBG_STR, Msg);
-
- {
- // If the pass crashes releasing memory, remember this.
- PassManagerPrettyStackEntry X(P);
- TimeRegion PassTimer(getPassTimer(P));
-
- P->releaseMemory();
- }
-
- AnalysisID PI = P->getPassID();
- if (const PassInfo *PInf = PassRegistry::getPassRegistry()->getPassInfo(PI)) {
- // Remove the pass itself (if it is not already removed).
- AvailableAnalysis.erase(PI);
-
- // Remove all interfaces this pass implements, for which it is also
- // listed as the available implementation.
- const std::vector<const PassInfo*> &II = PInf->getInterfacesImplemented();
- for (unsigned i = 0, e = II.size(); i != e; ++i) {
- DenseMap<AnalysisID, Pass*>::iterator Pos =
- AvailableAnalysis.find(II[i]->getTypeInfo());
- if (Pos != AvailableAnalysis.end() && Pos->second == P)
- AvailableAnalysis.erase(Pos);
- }
- }
-}
-
-/// Add pass P into the PassVector. Update
-/// AvailableAnalysis appropriately if ProcessAnalysis is true.
-void PMDataManager::add(Pass *P, bool ProcessAnalysis) {
- // This manager is going to manage pass P. Set up analysis resolver
- // to connect them.
- AnalysisResolver *AR = new AnalysisResolver(*this);
- P->setResolver(AR);
-
- // If a FunctionPass F is the last user of ModulePass info M
- // then the F's manager, not F, records itself as a last user of M.
- SmallVector<Pass *, 12> TransferLastUses;
-
- if (!ProcessAnalysis) {
- // Add pass
- PassVector.push_back(P);
- return;
- }
-
- // At the moment, this pass is the last user of all required passes.
- SmallVector<Pass *, 12> LastUses;
- SmallVector<Pass *, 8> RequiredPasses;
- SmallVector<AnalysisID, 8> ReqAnalysisNotAvailable;
-
- unsigned PDepth = this->getDepth();
-
- collectRequiredAnalysis(RequiredPasses,
- ReqAnalysisNotAvailable, P);
- for (SmallVectorImpl<Pass *>::iterator I = RequiredPasses.begin(),
- E = RequiredPasses.end(); I != E; ++I) {
- Pass *PRequired = *I;
- unsigned RDepth = 0;
-
- assert(PRequired->getResolver() && "Analysis Resolver is not set");
- PMDataManager &DM = PRequired->getResolver()->getPMDataManager();
- RDepth = DM.getDepth();
-
- if (PDepth == RDepth)
- LastUses.push_back(PRequired);
- else if (PDepth > RDepth) {
- // Let the parent claim responsibility of last use
- TransferLastUses.push_back(PRequired);
- // Keep track of higher level analysis used by this manager.
- HigherLevelAnalysis.push_back(PRequired);
- } else
- llvm_unreachable("Unable to accommodate Required Pass");
- }
-
- // Set P as P's last user until someone starts using P.
- // However, if P is a Pass Manager then it does not need
- // to record its last user.
- if (P->getAsPMDataManager() == 0)
- LastUses.push_back(P);
- TPM->setLastUser(LastUses, P);
-
- if (!TransferLastUses.empty()) {
- Pass *My_PM = getAsPass();
- TPM->setLastUser(TransferLastUses, My_PM);
- TransferLastUses.clear();
- }
-
- // Now, take care of required analyses that are not available.
- for (SmallVectorImpl<AnalysisID>::iterator
- I = ReqAnalysisNotAvailable.begin(),
- E = ReqAnalysisNotAvailable.end() ;I != E; ++I) {
- const PassInfo *PI = PassRegistry::getPassRegistry()->getPassInfo(*I);
- Pass *AnalysisPass = PI->createPass();
- this->addLowerLevelRequiredPass(P, AnalysisPass);
- }
-
- // Take a note of analysis required and made available by this pass.
- // Remove the analysis not preserved by this pass
- removeNotPreservedAnalysis(P);
- recordAvailableAnalysis(P);
-
- // Add pass
- PassVector.push_back(P);
-}
-
-
-/// Populate RP with analysis pass that are required by
-/// pass P and are available. Populate RP_NotAvail with analysis
-/// pass that are required by pass P but are not available.
-void PMDataManager::collectRequiredAnalysis(SmallVectorImpl<Pass *> &RP,
- SmallVectorImpl<AnalysisID> &RP_NotAvail,
- Pass *P) {
- AnalysisUsage *AnUsage = TPM->findAnalysisUsage(P);
- const AnalysisUsage::VectorType &RequiredSet = AnUsage->getRequiredSet();
- for (AnalysisUsage::VectorType::const_iterator
- I = RequiredSet.begin(), E = RequiredSet.end(); I != E; ++I) {
- if (Pass *AnalysisPass = findAnalysisPass(*I, true))
- RP.push_back(AnalysisPass);
- else
- RP_NotAvail.push_back(*I);
- }
-
- const AnalysisUsage::VectorType &IDs = AnUsage->getRequiredTransitiveSet();
- for (AnalysisUsage::VectorType::const_iterator I = IDs.begin(),
- E = IDs.end(); I != E; ++I) {
- if (Pass *AnalysisPass = findAnalysisPass(*I, true))
- RP.push_back(AnalysisPass);
- else
- RP_NotAvail.push_back(*I);
- }
-}
-
-// All Required analyses should be available to the pass as it runs! Here
-// we fill in the AnalysisImpls member of the pass so that it can
-// successfully use the getAnalysis() method to retrieve the
-// implementations it needs.
-//
-void PMDataManager::initializeAnalysisImpl(Pass *P) {
- AnalysisUsage *AnUsage = TPM->findAnalysisUsage(P);
-
- for (AnalysisUsage::VectorType::const_iterator
- I = AnUsage->getRequiredSet().begin(),
- E = AnUsage->getRequiredSet().end(); I != E; ++I) {
- Pass *Impl = findAnalysisPass(*I, true);
- if (Impl == 0)
- // This may be analysis pass that is initialized on the fly.
- // If that is not the case then it will raise an assert when it is used.
- continue;
- AnalysisResolver *AR = P->getResolver();
- assert(AR && "Analysis Resolver is not set");
- AR->addAnalysisImplsPair(*I, Impl);
- }
-}
-
-/// Find the pass that implements Analysis AID. If desired pass is not found
-/// then return NULL.
-Pass *PMDataManager::findAnalysisPass(AnalysisID AID, bool SearchParent) {
-
- // Check if AvailableAnalysis map has one entry.
- DenseMap<AnalysisID, Pass*>::const_iterator I = AvailableAnalysis.find(AID);
-
- if (I != AvailableAnalysis.end())
- return I->second;
-
- // Search Parents through TopLevelManager
- if (SearchParent)
- return TPM->findAnalysisPass(AID);
-
- return NULL;
-}
-
-// Print list of passes that are last used by P.
-void PMDataManager::dumpLastUses(Pass *P, unsigned Offset) const{
-
- SmallVector<Pass *, 12> LUses;
-
- // If this is a on the fly manager then it does not have TPM.
- if (!TPM)
- return;
-
- TPM->collectLastUses(LUses, P);
-
- for (SmallVectorImpl<Pass *>::iterator I = LUses.begin(),
- E = LUses.end(); I != E; ++I) {
- llvm::dbgs() << "--" << std::string(Offset*2, ' ');
- (*I)->dumpPassStructure(0);
- }
-}
-
-void PMDataManager::dumpPassArguments() const {
- for (SmallVectorImpl<Pass *>::const_iterator I = PassVector.begin(),
- E = PassVector.end(); I != E; ++I) {
- if (PMDataManager *PMD = (*I)->getAsPMDataManager())
- PMD->dumpPassArguments();
- else
- if (const PassInfo *PI =
- PassRegistry::getPassRegistry()->getPassInfo((*I)->getPassID()))
- if (!PI->isAnalysisGroup())
- dbgs() << " -" << PI->getPassArgument();
- }
-}
-
-void PMDataManager::dumpPassInfo(Pass *P, enum PassDebuggingString S1,
- enum PassDebuggingString S2,
- StringRef Msg) {
- if (PassDebugging < Executions)
- return;
- dbgs() << (void*)this << std::string(getDepth()*2+1, ' ');
- switch (S1) {
- case EXECUTION_MSG:
- dbgs() << "Executing Pass '" << P->getPassName();
- break;
- case MODIFICATION_MSG:
- dbgs() << "Made Modification '" << P->getPassName();
- break;
- case FREEING_MSG:
- dbgs() << " Freeing Pass '" << P->getPassName();
- break;
- default:
- break;
- }
- switch (S2) {
- case ON_BASICBLOCK_MSG:
- dbgs() << "' on BasicBlock '" << Msg << "'...\n";
- break;
- case ON_FUNCTION_MSG:
- dbgs() << "' on Function '" << Msg << "'...\n";
- break;
- case ON_MODULE_MSG:
- dbgs() << "' on Module '" << Msg << "'...\n";
- break;
- case ON_REGION_MSG:
- dbgs() << "' on Region '" << Msg << "'...\n";
- break;
- case ON_LOOP_MSG:
- dbgs() << "' on Loop '" << Msg << "'...\n";
- break;
- case ON_CG_MSG:
- dbgs() << "' on Call Graph Nodes '" << Msg << "'...\n";
- break;
- default:
- break;
- }
-}
-
-void PMDataManager::dumpRequiredSet(const Pass *P) const {
- if (PassDebugging < Details)
- return;
-
- AnalysisUsage analysisUsage;
- P->getAnalysisUsage(analysisUsage);
- dumpAnalysisUsage("Required", P, analysisUsage.getRequiredSet());
-}
-
-void PMDataManager::dumpPreservedSet(const Pass *P) const {
- if (PassDebugging < Details)
- return;
-
- AnalysisUsage analysisUsage;
- P->getAnalysisUsage(analysisUsage);
- dumpAnalysisUsage("Preserved", P, analysisUsage.getPreservedSet());
-}
-
-void PMDataManager::dumpAnalysisUsage(StringRef Msg, const Pass *P,
- const AnalysisUsage::VectorType &Set) const {
- assert(PassDebugging >= Details);
- if (Set.empty())
- return;
- dbgs() << (const void*)P << std::string(getDepth()*2+3, ' ') << Msg << " Analyses:";
- for (unsigned i = 0; i != Set.size(); ++i) {
- if (i) dbgs() << ',';
- const PassInfo *PInf = PassRegistry::getPassRegistry()->getPassInfo(Set[i]);
- if (!PInf) {
- // Some preserved passes, such as AliasAnalysis, may not be initialized by
- // all drivers.
- dbgs() << " Uninitialized Pass";
- continue;
- }
- dbgs() << ' ' << PInf->getPassName();
- }
- dbgs() << '\n';
-}
-
-/// Add RequiredPass into list of lower level passes required by pass P.
-/// RequiredPass is run on the fly by Pass Manager when P requests it
-/// through getAnalysis interface.
-/// This should be handled by specific pass manager.
-void PMDataManager::addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) {
- if (TPM) {
- TPM->dumpArguments();
- TPM->dumpPasses();
- }
-
- // Module Level pass may required Function Level analysis info
- // (e.g. dominator info). Pass manager uses on the fly function pass manager
- // to provide this on demand. In that case, in Pass manager terminology,
- // module level pass is requiring lower level analysis info managed by
- // lower level pass manager.
-
- // When Pass manager is not able to order required analysis info, Pass manager
- // checks whether any lower level manager will be able to provide this
- // analysis info on demand or not.
-#ifndef NDEBUG
- dbgs() << "Unable to schedule '" << RequiredPass->getPassName();
- dbgs() << "' required by '" << P->getPassName() << "'\n";
-#endif
- llvm_unreachable("Unable to schedule pass");
-}
-
-Pass *PMDataManager::getOnTheFlyPass(Pass *P, AnalysisID PI, Function &F) {
- llvm_unreachable("Unable to find on the fly pass");
-}
-
-// Destructor
-PMDataManager::~PMDataManager() {
- for (SmallVectorImpl<Pass *>::iterator I = PassVector.begin(),
- E = PassVector.end(); I != E; ++I)
- delete *I;
-}
-
-//===----------------------------------------------------------------------===//
-// NOTE: Is this the right place to define this method ?
-// getAnalysisIfAvailable - Return analysis result or null if it doesn't exist.
-Pass *AnalysisResolver::getAnalysisIfAvailable(AnalysisID ID, bool dir) const {
- return PM.findAnalysisPass(ID, dir);
-}
-
-Pass *AnalysisResolver::findImplPass(Pass *P, AnalysisID AnalysisPI,
- Function &F) {
- return PM.getOnTheFlyPass(P, AnalysisPI, F);
-}
-
-//===----------------------------------------------------------------------===//
-// BBPassManager implementation
-
-/// Execute all of the passes scheduled for execution by invoking
-/// runOnBasicBlock method. Keep track of whether any of the passes modifies
-/// the function, and if so, return true.
-bool BBPassManager::runOnFunction(Function &F) {
- if (F.isDeclaration())
- return false;
-
- bool Changed = doInitialization(F);
-
- for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I)
- for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
- BasicBlockPass *BP = getContainedPass(Index);
- bool LocalChanged = false;
-
- dumpPassInfo(BP, EXECUTION_MSG, ON_BASICBLOCK_MSG, I->getName());
- dumpRequiredSet(BP);
-
- initializeAnalysisImpl(BP);
-
- {
- // If the pass crashes, remember this.
- PassManagerPrettyStackEntry X(BP, *I);
- TimeRegion PassTimer(getPassTimer(BP));
-
- LocalChanged |= BP->runOnBasicBlock(*I);
+void AnalysisManager::invalidateAll(Module *M) {
+ // First invalidate any module results we still have laying about.
+ // FIXME: This is a total hack based on the fact that erasure doesn't
+ // invalidate iteration for DenseMap.
+ for (ModuleAnalysisResultMapT::iterator I = ModuleAnalysisResults.begin(),
+ E = ModuleAnalysisResults.end();
+ I != E; ++I)
+ if (I->second->invalidate(M))
+ ModuleAnalysisResults.erase(I);
+
+ // Now walk all of the functions for which there are cached results, and
+ // attempt to invalidate each of those as the entire module may have changed.
+ // FIXME: How do we handle functions which have been deleted or RAUWed?
+ SmallVector<void *, 8> InvalidatedPassIDs;
+ for (FunctionAnalysisResultListMapT::iterator
+ FI = FunctionAnalysisResultLists.begin(),
+ FE = FunctionAnalysisResultLists.end();
+ FI != FE; ++FI) {
+ Function *F = FI->first;
+ FunctionAnalysisResultListT &ResultsList = FI->second;
+ for (FunctionAnalysisResultListT::iterator I = ResultsList.begin(),
+ E = ResultsList.end();
+ I != E;)
+ if (I->second->invalidate(F)) {
+ InvalidatedPassIDs.push_back(I->first);
+ I = ResultsList.erase(I);
+ } else {
+ ++I;
}
-
- Changed |= LocalChanged;
- if (LocalChanged)
- dumpPassInfo(BP, MODIFICATION_MSG, ON_BASICBLOCK_MSG,
- I->getName());
- dumpPreservedSet(BP);
-
- verifyPreservedAnalysis(BP);
- removeNotPreservedAnalysis(BP);
- recordAvailableAnalysis(BP);
- removeDeadPasses(BP, I->getName(), ON_BASICBLOCK_MSG);
- }
-
- return doFinalization(F) || Changed;
-}
-
-// Implement doInitialization and doFinalization
-bool BBPassManager::doInitialization(Module &M) {
- bool Changed = false;
-
- for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index)
- Changed |= getContainedPass(Index)->doInitialization(M);
-
- return Changed;
-}
-
-bool BBPassManager::doFinalization(Module &M) {
- bool Changed = false;
-
- for (int Index = getNumContainedPasses() - 1; Index >= 0; --Index)
- Changed |= getContainedPass(Index)->doFinalization(M);
-
- return Changed;
-}
-
-bool BBPassManager::doInitialization(Function &F) {
- bool Changed = false;
-
- for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
- BasicBlockPass *BP = getContainedPass(Index);
- Changed |= BP->doInitialization(F);
+ while (!InvalidatedPassIDs.empty())
+ FunctionAnalysisResults.erase(
+ std::make_pair(InvalidatedPassIDs.pop_back_val(), F));
}
-
- return Changed;
}
-bool BBPassManager::doFinalization(Function &F) {
- bool Changed = false;
+const AnalysisManager::AnalysisResultConcept<Module> &
+AnalysisManager::getResultImpl(void *PassID, Module *M) {
+ assert(M == this->M && "Wrong module used when querying the AnalysisManager");
+ ModuleAnalysisResultMapT::iterator RI;
+ bool Inserted;
+ llvm::tie(RI, Inserted) = ModuleAnalysisResults.insert(std::make_pair(
+ PassID, polymorphic_ptr<AnalysisResultConcept<Module> >()));
- for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
- BasicBlockPass *BP = getContainedPass(Index);
- Changed |= BP->doFinalization(F);
+ if (Inserted) {
+ // We don't have a cached result for this result. Look up the pass and run
+ // it to produce a result, which we then add to the cache.
+ ModuleAnalysisPassMapT::const_iterator PI =
+ ModuleAnalysisPasses.find(PassID);
+ assert(PI != ModuleAnalysisPasses.end() &&
+ "Analysis passes must be registered prior to being queried!");
+ RI->second = PI->second->run(M);
}
- return Changed;
+ return *RI->second;
}
+const AnalysisManager::AnalysisResultConcept<Function> &
+AnalysisManager::getResultImpl(void *PassID, Function *F) {
+ assert(F->getParent() == M && "Analyzing a function from another module!");
-//===----------------------------------------------------------------------===//
-// FunctionPassManager implementation
-
-/// Create new Function pass manager
-FunctionPassManager::FunctionPassManager(Module *m) : M(m) {
- FPM = new FunctionPassManagerImpl();
- // FPM is the top level manager.
- FPM->setTopLevelManager(FPM);
-
- AnalysisResolver *AR = new AnalysisResolver(*FPM);
- FPM->setResolver(AR);
-}
-
-FunctionPassManager::~FunctionPassManager() {
- delete FPM;
-}
+ FunctionAnalysisResultMapT::iterator RI;
+ bool Inserted;
+ llvm::tie(RI, Inserted) = FunctionAnalysisResults.insert(std::make_pair(
+ std::make_pair(PassID, F), FunctionAnalysisResultListT::iterator()));
-/// add - Add a pass to the queue of passes to run. This passes
-/// ownership of the Pass to the PassManager. When the
-/// PassManager_X is destroyed, the pass will be destroyed as well, so
-/// there is no need to delete the pass. (TODO delete passes.)
-/// This implies that all passes MUST be allocated with 'new'.
-void FunctionPassManager::add(Pass *P) {
- FPM->add(P);
-}
-
-/// run - Execute all of the passes scheduled for execution. Keep
-/// track of whether any of the passes modifies the function, and if
-/// 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 (Inserted) {
+ // We don't have a cached result for this result. Look up the pass and run
+ // it to produce a result, which we then add to the cache.
+ FunctionAnalysisPassMapT::const_iterator PI =
+ FunctionAnalysisPasses.find(PassID);
+ assert(PI != FunctionAnalysisPasses.end() &&
+ "Analysis passes must be registered prior to being queried!");
+ FunctionAnalysisResultListT &ResultList = FunctionAnalysisResultLists[F];
+ ResultList.push_back(std::make_pair(PassID, PI->second->run(F)));
+ RI->second = llvm::prior(ResultList.end());
}
- return FPM->run(F);
-}
-
-/// doInitialization - Run all of the initializers for the function passes.
-///
-bool FunctionPassManager::doInitialization() {
- return FPM->doInitialization(*M);
-}
-
-/// doFinalization - Run all of the finalizers for the function passes.
-///
-bool FunctionPassManager::doFinalization() {
- return FPM->doFinalization(*M);
-}
-
-//===----------------------------------------------------------------------===//
-// FunctionPassManagerImpl implementation
-//
-bool FunctionPassManagerImpl::doInitialization(Module &M) {
- bool Changed = false;
-
- dumpArguments();
- dumpPasses();
-
- SmallVectorImpl<ImmutablePass *>& IPV = getImmutablePasses();
- for (SmallVectorImpl<ImmutablePass *>::const_iterator I = IPV.begin(),
- E = IPV.end(); I != E; ++I) {
- Changed |= (*I)->doInitialization(M);
- }
-
- for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index)
- Changed |= getContainedManager(Index)->doInitialization(M);
-
- return Changed;
+ return *RI->second->second;
}
-bool FunctionPassManagerImpl::doFinalization(Module &M) {
- bool Changed = false;
-
- for (int Index = getNumContainedManagers() - 1; Index >= 0; --Index)
- Changed |= getContainedManager(Index)->doFinalization(M);
-
- SmallVectorImpl<ImmutablePass *>& IPV = getImmutablePasses();
- for (SmallVectorImpl<ImmutablePass *>::const_iterator I = IPV.begin(),
- E = IPV.end(); I != E; ++I) {
- Changed |= (*I)->doFinalization(M);
- }
-
- return Changed;
+void AnalysisManager::invalidateImpl(void *PassID, Module *M) {
+ assert(M == this->M && "Invalidating a pass over a different module!");
+ ModuleAnalysisResults.erase(PassID);
}
-/// cleanup - After running all passes, clean up pass manager cache.
-void FPPassManager::cleanup() {
- for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
- FunctionPass *FP = getContainedPass(Index);
- AnalysisResolver *AR = FP->getResolver();
- assert(AR && "Analysis Resolver is not set");
- AR->clearAnalysisImpls();
- }
-}
+void AnalysisManager::invalidateImpl(void *PassID, Function *F) {
+ assert(F->getParent() == M &&
+ "Invalidating a pass over a function from another module!");
-void FunctionPassManagerImpl::releaseMemoryOnTheFly() {
- if (!wasRun)
+ FunctionAnalysisResultMapT::iterator RI =
+ FunctionAnalysisResults.find(std::make_pair(PassID, F));
+ if (RI == FunctionAnalysisResults.end())
return;
- for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index) {
- FPPassManager *FPPM = getContainedManager(Index);
- for (unsigned Index = 0; Index < FPPM->getNumContainedPasses(); ++Index) {
- FPPM->getContainedPass(Index)->releaseMemory();
- }
- }
- wasRun = false;
-}
-
-// Execute all the passes managed by this top level manager.
-// Return true if any function is modified by a pass.
-bool FunctionPassManagerImpl::run(Function &F) {
- bool Changed = false;
- TimingInfo::createTheTimeInfo();
-
- initializeAllAnalysisInfo();
- for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index)
- Changed |= getContainedManager(Index)->runOnFunction(F);
-
- for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index)
- getContainedManager(Index)->cleanup();
-
- wasRun = true;
- return Changed;
-}
-//===----------------------------------------------------------------------===//
-// FPPassManager implementation
-
-char FPPassManager::ID = 0;
-/// Print passes managed by this manager
-void FPPassManager::dumpPassStructure(unsigned Offset) {
- dbgs().indent(Offset*2) << "FunctionPass Manager\n";
- for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
- FunctionPass *FP = getContainedPass(Index);
- FP->dumpPassStructure(Offset + 1);
- dumpLastUses(FP, Offset+1);
- }
-}
-
-
-/// Execute all of the passes scheduled for execution by invoking
-/// runOnFunction method. Keep track of whether any of the passes modifies
-/// the function, and if so, return true.
-bool FPPassManager::runOnFunction(Function &F) {
- if (F.isDeclaration())
- return false;
-
- bool Changed = false;
-
- // Collect inherited analysis from Module level pass manager.
- populateInheritedAnalysis(TPM->activeStack);
-
- for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
- FunctionPass *FP = getContainedPass(Index);
- bool LocalChanged = false;
-
- dumpPassInfo(FP, EXECUTION_MSG, ON_FUNCTION_MSG, F.getName());
- dumpRequiredSet(FP);
-
- initializeAnalysisImpl(FP);
-
- {
- PassManagerPrettyStackEntry X(FP, F);
- TimeRegion PassTimer(getPassTimer(FP));
-
- LocalChanged |= FP->runOnFunction(F);
- }
-
- Changed |= LocalChanged;
- if (LocalChanged)
- dumpPassInfo(FP, MODIFICATION_MSG, ON_FUNCTION_MSG, F.getName());
- dumpPreservedSet(FP);
-
- verifyPreservedAnalysis(FP);
- removeNotPreservedAnalysis(FP);
- recordAvailableAnalysis(FP);
- removeDeadPasses(FP, F.getName(), ON_FUNCTION_MSG);
- }
- return Changed;
-}
-
-bool FPPassManager::runOnModule(Module &M) {
- bool Changed = false;
-
- for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
- Changed |= runOnFunction(*I);
-
- return Changed;
-}
-
-bool FPPassManager::doInitialization(Module &M) {
- bool Changed = false;
-
- for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index)
- Changed |= getContainedPass(Index)->doInitialization(M);
-
- return Changed;
-}
-
-bool FPPassManager::doFinalization(Module &M) {
- bool Changed = false;
-
- for (int Index = getNumContainedPasses() - 1; Index >= 0; --Index)
- Changed |= getContainedPass(Index)->doFinalization(M);
-
- return Changed;
+ FunctionAnalysisResultLists[F].erase(RI->second);
}
-
-//===----------------------------------------------------------------------===//
-// MPPassManager implementation
-
-/// Execute all of the passes scheduled for execution by invoking
-/// runOnModule method. Keep track of whether any of the passes modifies
-/// the module, and if so, return true.
-bool
-MPPassManager::runOnModule(Module &M) {
- bool Changed = false;
-
- // Initialize on-the-fly passes
- for (std::map<Pass *, FunctionPassManagerImpl *>::iterator
- I = OnTheFlyManagers.begin(), E = OnTheFlyManagers.end();
- I != E; ++I) {
- FunctionPassManagerImpl *FPP = I->second;
- Changed |= FPP->doInitialization(M);
- }
-
- // Initialize module passes
- for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index)
- Changed |= getContainedPass(Index)->doInitialization(M);
-
- for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
- ModulePass *MP = getContainedPass(Index);
- bool LocalChanged = false;
-
- dumpPassInfo(MP, EXECUTION_MSG, ON_MODULE_MSG, M.getModuleIdentifier());
- dumpRequiredSet(MP);
-
- initializeAnalysisImpl(MP);
-
- {
- PassManagerPrettyStackEntry X(MP, M);
- TimeRegion PassTimer(getPassTimer(MP));
-
- LocalChanged |= MP->runOnModule(M);
- }
-
- Changed |= LocalChanged;
- if (LocalChanged)
- dumpPassInfo(MP, MODIFICATION_MSG, ON_MODULE_MSG,
- M.getModuleIdentifier());
- dumpPreservedSet(MP);
-
- verifyPreservedAnalysis(MP);
- removeNotPreservedAnalysis(MP);
- recordAvailableAnalysis(MP);
- removeDeadPasses(MP, M.getModuleIdentifier(), ON_MODULE_MSG);
- }
-
- // Finalize module passes
- for (int Index = getNumContainedPasses() - 1; Index >= 0; --Index)
- Changed |= getContainedPass(Index)->doFinalization(M);
-
- // Finalize on-the-fly passes
- for (std::map<Pass *, FunctionPassManagerImpl *>::iterator
- I = OnTheFlyManagers.begin(), E = OnTheFlyManagers.end();
- I != E; ++I) {
- FunctionPassManagerImpl *FPP = I->second;
- // We don't know when is the last time an on-the-fly pass is run,
- // so we need to releaseMemory / finalize here
- FPP->releaseMemoryOnTheFly();
- Changed |= FPP->doFinalization(M);
- }
-
- return Changed;
-}
-
-/// Add RequiredPass into list of lower level passes required by pass P.
-/// RequiredPass is run on the fly by Pass Manager when P requests it
-/// through getAnalysis interface.
-void MPPassManager::addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) {
- assert(P->getPotentialPassManagerType() == PMT_ModulePassManager &&
- "Unable to handle Pass that requires lower level Analysis pass");
- assert((P->getPotentialPassManagerType() <
- RequiredPass->getPotentialPassManagerType()) &&
- "Unable to handle Pass that requires lower level Analysis pass");
-
- FunctionPassManagerImpl *FPP = OnTheFlyManagers[P];
- if (!FPP) {
- FPP = new FunctionPassManagerImpl();
- // FPP is the top level manager.
- FPP->setTopLevelManager(FPP);
-
- OnTheFlyManagers[P] = FPP;
- }
- FPP->add(RequiredPass);
-
- // Register P as the last user of RequiredPass.
- if (RequiredPass) {
- SmallVector<Pass *, 1> LU;
- LU.push_back(RequiredPass);
- FPP->setLastUser(LU, P);
- }
-}
-
-/// Return function pass corresponding to PassInfo PI, that is
-/// required by module pass MP. Instantiate analysis pass, by using
-/// its runOnFunction() for function F.
-Pass* MPPassManager::getOnTheFlyPass(Pass *MP, AnalysisID PI, Function &F){
- FunctionPassManagerImpl *FPP = OnTheFlyManagers[MP];
- assert(FPP && "Unable to find on the fly pass");
-
- FPP->releaseMemoryOnTheFly();
- FPP->run(F);
- return ((PMTopLevelManager*)FPP)->findAnalysisPass(PI);
-}
-
-
-//===----------------------------------------------------------------------===//
-// PassManagerImpl implementation
-
-//
-/// run - Execute all of the passes scheduled for execution. Keep track of
-/// whether any of the passes modifies the module, and if so, return true.
-bool PassManagerImpl::run(Module &M) {
- bool Changed = false;
- TimingInfo::createTheTimeInfo();
-
- dumpArguments();
- dumpPasses();
-
- SmallVectorImpl<ImmutablePass *>& IPV = getImmutablePasses();
- for (SmallVectorImpl<ImmutablePass *>::const_iterator I = IPV.begin(),
- E = IPV.end(); I != E; ++I) {
- Changed |= (*I)->doInitialization(M);
- }
-
- initializeAllAnalysisInfo();
- for (unsigned Index = 0; Index < getNumContainedManagers(); ++Index)
- Changed |= getContainedManager(Index)->runOnModule(M);
-
- for (SmallVectorImpl<ImmutablePass *>::const_iterator I = IPV.begin(),
- E = IPV.end(); I != E; ++I) {
- Changed |= (*I)->doFinalization(M);
- }
-
- return Changed;
-}
-
-//===----------------------------------------------------------------------===//
-// PassManager implementation
-
-/// Create new pass manager
-PassManager::PassManager() {
- PM = new PassManagerImpl();
- // PM is the top level manager
- PM->setTopLevelManager(PM);
-}
-
-PassManager::~PassManager() {
- delete PM;
-}
-
-/// add - Add a pass to the queue of passes to run. This passes ownership of
-/// the Pass to the PassManager. When the PassManager is destroyed, the pass
-/// will be destroyed as well, so there is no need to delete the pass. This
-/// implies that all passes MUST be allocated with 'new'.
-void PassManager::add(Pass *P) {
- PM->add(P);
-}
-
-/// run - Execute all of the passes scheduled for execution. Keep track of
-/// whether any of the passes modifies the module, and if so, return true.
-bool PassManager::run(Module &M) {
- return PM->run(M);
-}
-
-//===----------------------------------------------------------------------===//
-// TimingInfo implementation
-
-bool llvm::TimePassesIsEnabled = false;
-static cl::opt<bool,true>
-EnableTiming("time-passes", cl::location(TimePassesIsEnabled),
- cl::desc("Time each pass, printing elapsed time for each on exit"));
-
-// createTheTimeInfo - This method either initializes the TheTimeInfo pointer to
-// a non null value (if the -time-passes option is enabled) or it leaves it
-// null. It may be called multiple times.
-void TimingInfo::createTheTimeInfo() {
- if (!TimePassesIsEnabled || TheTimeInfo) return;
-
- // Constructed the first time this is called, iff -time-passes is enabled.
- // This guarantees that the object will be constructed before static globals,
- // thus it will be destroyed before them.
- static ManagedStatic<TimingInfo> TTI;
- TheTimeInfo = &*TTI;
-}
-
-/// If TimingInfo is enabled then start pass timer.
-Timer *llvm::getPassTimer(Pass *P) {
- if (TheTimeInfo)
- return TheTimeInfo->getPassTimer(P);
- return 0;
-}
-
-//===----------------------------------------------------------------------===//
-// PMStack implementation
-//
-
-// Pop Pass Manager from the stack and clear its analysis info.
-void PMStack::pop() {
-
- PMDataManager *Top = this->top();
- Top->initializeAnalysisInfo();
-
- S.pop_back();
-}
-
-// Push PM on the stack and set its top level manager.
-void PMStack::push(PMDataManager *PM) {
- assert(PM && "Unable to push. Pass Manager expected");
- assert(PM->getDepth()==0 && "Pass Manager depth set too early");
-
- if (!this->empty()) {
- assert(PM->getPassManagerType() > this->top()->getPassManagerType()
- && "pushing bad pass manager to PMStack");
- PMTopLevelManager *TPM = this->top()->getTopLevelManager();
-
- assert(TPM && "Unable to find top level manager");
- TPM->addIndirectPassManager(PM);
- PM->setTopLevelManager(TPM);
- PM->setDepth(this->top()->getDepth()+1);
- } else {
- assert((PM->getPassManagerType() == PMT_ModulePassManager
- || PM->getPassManagerType() == PMT_FunctionPassManager)
- && "pushing bad pass manager to PMStack");
- PM->setDepth(1);
- }
-
- S.push_back(PM);
-}
-
-// Dump content of the pass manager stack.
-void PMStack::dump() const {
- for (std::vector<PMDataManager *>::const_iterator I = S.begin(),
- E = S.end(); I != E; ++I)
- dbgs() << (*I)->getAsPass()->getPassName() << ' ';
-
- if (!S.empty())
- dbgs() << '\n';
-}
-
-/// Find appropriate Module Pass Manager in the PM Stack and
-/// add self into that manager.
-void ModulePass::assignPassManager(PMStack &PMS,
- PassManagerType PreferredType) {
- // Find Module Pass Manager
- while (!PMS.empty()) {
- PassManagerType TopPMType = PMS.top()->getPassManagerType();
- if (TopPMType == PreferredType)
- break; // We found desired pass manager
- else if (TopPMType > PMT_ModulePassManager)
- PMS.pop(); // Pop children pass managers
- else
- break;
- }
- assert(!PMS.empty() && "Unable to find appropriate Pass Manager");
- PMS.top()->add(this);
-}
-
-/// Find appropriate Function Pass Manager or Call Graph Pass Manager
-/// in the PM Stack and add self into that manager.
-void FunctionPass::assignPassManager(PMStack &PMS,
- PassManagerType PreferredType) {
-
- // Find Function Pass Manager
- while (!PMS.empty()) {
- if (PMS.top()->getPassManagerType() > PMT_FunctionPassManager)
- PMS.pop();
- else
- break;
- }
-
- // Create new Function Pass Manager if needed.
- FPPassManager *FPP;
- if (PMS.top()->getPassManagerType() == PMT_FunctionPassManager) {
- FPP = (FPPassManager *)PMS.top();
- } else {
- assert(!PMS.empty() && "Unable to create Function Pass Manager");
- PMDataManager *PMD = PMS.top();
-
- // [1] Create new Function Pass Manager
- FPP = new FPPassManager();
- FPP->populateInheritedAnalysis(PMS);
-
- // [2] Set up new manager's top level manager
- PMTopLevelManager *TPM = PMD->getTopLevelManager();
- TPM->addIndirectPassManager(FPP);
-
- // [3] Assign manager to manage this new manager. This may create
- // and push new managers into PMS
- FPP->assignPassManager(PMS, PMD->getPassManagerType());
-
- // [4] Push new manager into PMS
- PMS.push(FPP);
- }
-
- // Assign FPP as the manager of this pass.
- FPP->add(this);
-}
-
-/// Find appropriate Basic Pass Manager or Call Graph Pass Manager
-/// in the PM Stack and add self into that manager.
-void BasicBlockPass::assignPassManager(PMStack &PMS,
- PassManagerType PreferredType) {
- BBPassManager *BBP;
-
- // Basic Pass Manager is a leaf pass manager. It does not handle
- // any other pass manager.
- if (!PMS.empty() &&
- PMS.top()->getPassManagerType() == PMT_BasicBlockPassManager) {
- BBP = (BBPassManager *)PMS.top();
- } else {
- // If leaf manager is not Basic Block Pass manager then create new
- // basic Block Pass manager.
- assert(!PMS.empty() && "Unable to create BasicBlock Pass Manager");
- PMDataManager *PMD = PMS.top();
-
- // [1] Create new Basic Block Manager
- BBP = new BBPassManager();
-
- // [2] Set up new manager's top level manager
- // Basic Block Pass Manager does not live by itself
- PMTopLevelManager *TPM = PMD->getTopLevelManager();
- TPM->addIndirectPassManager(BBP);
-
- // [3] Assign manager to manage this new manager. This may create
- // and push new managers into PMS
- BBP->assignPassManager(PMS, PreferredType);
-
- // [4] Push new manager into PMS
- PMS.push(BBP);
- }
-
- // Assign BBP as the manager of this pass.
- BBP->add(this);
-}
-
-PassManagerBase::~PassManagerBase() {}
diff --git a/lib/IR/Type.cpp b/lib/IR/Type.cpp
index 46c61fc..432cbc9 100644
--- a/lib/IR/Type.cpp
+++ b/lib/IR/Type.cpp
@@ -616,11 +616,7 @@ bool StructType::isLayoutIdentical(StructType *Other) const {
/// getTypeByName - Return the type with the specified name, or null if there
/// is none by that name.
StructType *Module::getTypeByName(StringRef Name) const {
- StringMap<StructType*>::iterator I =
- getContext().pImpl->NamedStructTypes.find(Name);
- if (I != getContext().pImpl->NamedStructTypes.end())
- return I->second;
- return 0;
+ return getContext().pImpl->NamedStructTypes.lookup(Name);
}
diff --git a/lib/IR/TypeFinder.cpp b/lib/IR/TypeFinder.cpp
index d5e6203..689b903 100644
--- a/lib/IR/TypeFinder.cpp
+++ b/lib/IR/TypeFinder.cpp
@@ -44,6 +44,9 @@ void TypeFinder::run(const Module &M, bool onlyNamed) {
for (Module::const_iterator FI = M.begin(), E = M.end(); FI != E; ++FI) {
incorporateType(FI->getType());
+ if (FI->hasPrefixData())
+ incorporateValue(FI->getPrefixData());
+
// First incorporate the arguments.
for (Function::const_arg_iterator AI = FI->arg_begin(),
AE = FI->arg_end(); AI != AE; ++AI)
@@ -91,19 +94,27 @@ void TypeFinder::clear() {
/// incorporateType - This method adds the type to the list of used structures
/// if it's not in there already.
void TypeFinder::incorporateType(Type *Ty) {
- // Check to see if we're already visited this type.
+ // Check to see if we've already visited this type.
if (!VisitedTypes.insert(Ty).second)
return;
- // If this is a structure or opaque type, add a name for the type.
- if (StructType *STy = dyn_cast<StructType>(Ty))
- if (!OnlyNamed || STy->hasName())
- StructTypes.push_back(STy);
-
- // Recursively walk all contained types.
- for (Type::subtype_iterator I = Ty->subtype_begin(),
- E = Ty->subtype_end(); I != E; ++I)
- incorporateType(*I);
+ SmallVector<Type *, 4> TypeWorklist;
+ TypeWorklist.push_back(Ty);
+ do {
+ Ty = TypeWorklist.pop_back_val();
+
+ // If this is a structure or opaque type, add a name for the type.
+ if (StructType *STy = dyn_cast<StructType>(Ty))
+ if (!OnlyNamed || STy->hasName())
+ StructTypes.push_back(STy);
+
+ // Add all unvisited subtypes to worklist for processing
+ for (Type::subtype_reverse_iterator I = Ty->subtype_rbegin(),
+ E = Ty->subtype_rend();
+ I != E; ++I)
+ if (VisitedTypes.insert(*I).second)
+ TypeWorklist.push_back(*I);
+ } while (!TypeWorklist.empty());
}
/// incorporateValue - This method is used to walk operand lists finding types
diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp
index 81d7efa..62a3b31 100644
--- a/lib/IR/Value.cpp
+++ b/lib/IR/Value.cpp
@@ -365,7 +365,8 @@ static Value *stripPointerCastsAndOffsets(Value *V) {
break;
}
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)) {
if (StripKind == PSK_ZeroIndices || GA->mayBeOverridden())
@@ -393,6 +394,42 @@ Value *Value::stripInBoundsConstantOffsets() {
return stripPointerCastsAndOffsets<PSK_InBoundsConstantIndices>(this);
}
+Value *Value::stripAndAccumulateInBoundsConstantOffsets(const DataLayout &DL,
+ APInt &Offset) {
+ if (!getType()->isPointerTy())
+ return this;
+
+ assert(Offset.getBitWidth() == DL.getPointerSizeInBits(cast<PointerType>(
+ getType())->getAddressSpace()) &&
+ "The offset must have exactly as many bits as our pointer.");
+
+ // Even though we don't look through PHI nodes, we could be called on an
+ // instruction in an unreachable block, which may be on a cycle.
+ SmallPtrSet<Value *, 4> Visited;
+ Visited.insert(this);
+ Value *V = this;
+ do {
+ if (GEPOperator *GEP = dyn_cast<GEPOperator>(V)) {
+ if (!GEP->isInBounds())
+ return V;
+ APInt GEPOffset(Offset);
+ if (!GEP->accumulateConstantOffset(DL, GEPOffset))
+ return V;
+ Offset = GEPOffset;
+ V = GEP->getPointerOperand();
+ } else if (Operator::getOpcode(V) == Instruction::BitCast) {
+ V = cast<Operator>(V)->getOperand(0);
+ } else if (GlobalAlias *GA = dyn_cast<GlobalAlias>(V)) {
+ V = GA->getAliasee();
+ } else {
+ return V;
+ }
+ assert(V->getType()->isPointerTy() && "Unexpected operand type!");
+ } while (Visited.insert(V));
+
+ return V;
+}
+
Value *Value::stripInBoundsOffsets() {
return stripPointerCastsAndOffsets<PSK_InBounds>(this);
}
@@ -698,9 +735,5 @@ void ValueHandleBase::ValueIsRAUWd(Value *Old, Value *New) {
#endif
}
-// Default implementation for CallbackVH.
-void CallbackVH::allUsesReplacedWith(Value *) {}
-
-void CallbackVH::deleted() {
- setValPtr(NULL);
-}
+// Pin the vtable to this file.
+void CallbackVH::anchor() {}
diff --git a/lib/IR/ValueTypes.cpp b/lib/IR/ValueTypes.cpp
index ba04d60..2d4da95 100644
--- a/lib/IR/ValueTypes.cpp
+++ b/lib/IR/ValueTypes.cpp
@@ -134,6 +134,7 @@ std::string EVT::getEVTString() const {
case MVT::v16i1: return "v16i1";
case MVT::v32i1: return "v32i1";
case MVT::v64i1: return "v64i1";
+ case MVT::v1i8: return "v1i8";
case MVT::v2i8: return "v2i8";
case MVT::v4i8: return "v4i8";
case MVT::v8i8: return "v8i8";
@@ -156,11 +157,15 @@ std::string EVT::getEVTString() const {
case MVT::v4i64: return "v4i64";
case MVT::v8i64: return "v8i64";
case MVT::v16i64: return "v16i64";
+ case MVT::v1f32: return "v1f32";
case MVT::v2f32: return "v2f32";
case MVT::v2f16: return "v2f16";
+ case MVT::v4f16: return "v4f16";
+ case MVT::v8f16: return "v8f16";
case MVT::v4f32: return "v4f32";
case MVT::v8f32: return "v8f32";
case MVT::v16f32: return "v16f32";
+ case MVT::v1f64: return "v1f64";
case MVT::v2f64: return "v2f64";
case MVT::v4f64: return "v4f64";
case MVT::v8f64: return "v8f64";
@@ -197,6 +202,7 @@ Type *EVT::getTypeForEVT(LLVMContext &Context) const {
case MVT::v16i1: return VectorType::get(Type::getInt1Ty(Context), 16);
case MVT::v32i1: return VectorType::get(Type::getInt1Ty(Context), 32);
case MVT::v64i1: return VectorType::get(Type::getInt1Ty(Context), 64);
+ case MVT::v1i8: return VectorType::get(Type::getInt8Ty(Context), 1);
case MVT::v2i8: return VectorType::get(Type::getInt8Ty(Context), 2);
case MVT::v4i8: return VectorType::get(Type::getInt8Ty(Context), 4);
case MVT::v8i8: return VectorType::get(Type::getInt8Ty(Context), 8);
@@ -220,10 +226,14 @@ Type *EVT::getTypeForEVT(LLVMContext &Context) const {
case MVT::v8i64: return VectorType::get(Type::getInt64Ty(Context), 8);
case MVT::v16i64: return VectorType::get(Type::getInt64Ty(Context), 16);
case MVT::v2f16: return VectorType::get(Type::getHalfTy(Context), 2);
+ case MVT::v4f16: return VectorType::get(Type::getHalfTy(Context), 4);
+ case MVT::v8f16: return VectorType::get(Type::getHalfTy(Context), 8);
+ case MVT::v1f32: return VectorType::get(Type::getFloatTy(Context), 1);
case MVT::v2f32: return VectorType::get(Type::getFloatTy(Context), 2);
case MVT::v4f32: return VectorType::get(Type::getFloatTy(Context), 4);
case MVT::v8f32: return VectorType::get(Type::getFloatTy(Context), 8);
case MVT::v16f32: return VectorType::get(Type::getFloatTy(Context), 16);
+ case MVT::v1f64: return VectorType::get(Type::getDoubleTy(Context), 1);
case MVT::v2f64: return VectorType::get(Type::getDoubleTy(Context), 2);
case MVT::v4f64: return VectorType::get(Type::getDoubleTy(Context), 4);
case MVT::v8f64: return VectorType::get(Type::getDoubleTy(Context), 8);
diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp
index 0eda97f..da6b573 100644
--- a/lib/IR/Verifier.cpp
+++ b/lib/IR/Verifier.cpp
@@ -78,7 +78,7 @@
using namespace llvm;
static cl::opt<bool> DisableDebugInfoVerifier("disable-debug-info-verifier",
- cl::init(false));
+ cl::init(true));
namespace { // Anonymous namespace for class
struct PreVerifier : public FunctionPass {
@@ -167,7 +167,6 @@ namespace {
bool doInitialization(Module &M) {
Mod = &M;
Context = &M.getContext();
- Finder.reset();
DL = getAnalysisIfAvailable<DataLayout>();
@@ -183,10 +182,15 @@ namespace {
Mod = F.getParent();
if (!Context) Context = &F.getContext();
+ Finder.reset();
visit(F);
InstsInThisBlock.clear();
PersonalityFn = 0;
+ if (!DisableDebugInfoVerifier)
+ // Verify Debug Info.
+ verifyDebugInfo();
+
// We must abort before returning back to the pass manager, or else the
// pass manager may try to run other passes on the broken module.
return abortIfBroken();
@@ -214,9 +218,14 @@ namespace {
visitNamedMDNode(*I);
visitModuleFlags(M);
+ visitModuleIdents(M);
- // Verify Debug Info.
- verifyDebugInfo(M);
+ if (!DisableDebugInfoVerifier) {
+ Finder.reset();
+ Finder.processModule(M);
+ // Verify Debug Info.
+ verifyDebugInfo();
+ }
// If the module is broken, abort at this time.
return abortIfBroken();
@@ -258,6 +267,7 @@ namespace {
void visitGlobalAlias(GlobalAlias &GA);
void visitNamedMDNode(NamedMDNode &NMD);
void visitMDNode(MDNode &MD, Function *F);
+ void visitModuleIdents(Module &M);
void visitModuleFlags(Module &M);
void visitModuleFlag(MDNode *Op, DenseMap<MDString*, MDNode*> &SeenIDs,
SmallVectorImpl<MDNode*> &Requirements);
@@ -279,6 +289,7 @@ namespace {
void visitIntToPtrInst(IntToPtrInst &I);
void visitPtrToIntInst(PtrToIntInst &I);
void visitBitCastInst(BitCastInst &I);
+ void visitAddrSpaceCastInst(AddrSpaceCastInst &I);
void visitPHINode(PHINode &PN);
void visitBinaryOperator(BinaryOperator &B);
void visitICmpInst(ICmpInst &IC);
@@ -317,6 +328,8 @@ namespace {
bool VerifyIntrinsicType(Type *Ty,
ArrayRef<Intrinsic::IITDescriptor> &Infos,
SmallVectorImpl<Type*> &ArgTys);
+ bool VerifyIntrinsicIsVarArg(bool isVarArg,
+ ArrayRef<Intrinsic::IITDescriptor> &Infos);
bool VerifyAttributeCount(AttributeSet Attrs, unsigned Params);
void VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx,
bool isFunction, const Value *V);
@@ -328,7 +341,7 @@ namespace {
void VerifyBitcastType(const Value *V, Type *DestTy, Type *SrcTy);
void VerifyConstantExprBitcastType(const ConstantExpr *CE);
- void verifyDebugInfo(Module &M);
+ void verifyDebugInfo();
void WriteValue(const Value *V) {
if (!V) return;
@@ -427,10 +440,6 @@ void Verifier::visitGlobalValue(GlobalValue &GV) {
Assert1(GVar && GVar->getType()->getElementType()->isArrayTy(),
"Only global arrays can have appending linkage!", GVar);
}
-
- Assert1(!GV.hasLinkOnceODRAutoHideLinkage() || GV.hasDefaultVisibility(),
- "linkonce_odr_auto_hide can only have default visibility!",
- &GV);
}
void Verifier::visitGlobalVariable(GlobalVariable &GV) {
@@ -527,8 +536,7 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) {
void Verifier::visitGlobalAlias(GlobalAlias &GA) {
Assert1(!GA.getName().empty(),
"Alias name cannot be empty!", &GA);
- Assert1(GA.hasExternalLinkage() || GA.hasLocalLinkage() ||
- GA.hasWeakLinkage(),
+ Assert1(GlobalAlias::isValidLinkage(GA.getLinkage()),
"Alias should have external or external weak linkage!", &GA);
Assert1(GA.getAliasee(),
"Aliasee cannot be NULL!", &GA);
@@ -612,6 +620,24 @@ void Verifier::visitMDNode(MDNode &MD, Function *F) {
}
}
+void Verifier::visitModuleIdents(Module &M) {
+ const NamedMDNode *Idents = M.getNamedMetadata("llvm.ident");
+ if (!Idents)
+ return;
+
+ // llvm.ident takes a list of metadata entry. Each entry has only one string.
+ // Scan each llvm.ident entry and make sure that this requirement is met.
+ for (unsigned i = 0, e = Idents->getNumOperands(); i != e; ++i) {
+ const MDNode *N = Idents->getOperand(i);
+ Assert1(N->getNumOperands() == 1,
+ "incorrect number of operands in llvm.ident metadata", N);
+ Assert1(isa<MDString>(N->getOperand(0)),
+ ("invalid value for llvm.ident metadata entry operand"
+ "(the operand should be a string)"),
+ N->getOperand(0));
+ }
+}
+
void Verifier::visitModuleFlags(Module &M) {
const NamedMDNode *Flags = M.getModuleFlagsMetadata();
if (!Flags) return;
@@ -751,7 +777,8 @@ void Verifier::VerifyAttributeTypes(AttributeSet Attrs, unsigned Idx,
I->getKindAsEnum() == Attribute::NoDuplicate ||
I->getKindAsEnum() == Attribute::Builtin ||
I->getKindAsEnum() == Attribute::NoBuiltin ||
- I->getKindAsEnum() == Attribute::Cold) {
+ I->getKindAsEnum() == Attribute::Cold ||
+ I->getKindAsEnum() == Attribute::OptimizeNone) {
if (!isFunction) {
CheckFailed("Attribute '" + I->getAsString() +
"' only applies to functions!", V);
@@ -897,6 +924,21 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs,
Attrs.hasAttribute(AttributeSet::FunctionIndex,
Attribute::AlwaysInline)),
"Attributes 'noinline and alwaysinline' are incompatible!", V);
+
+ if (Attrs.hasAttribute(AttributeSet::FunctionIndex,
+ Attribute::OptimizeNone)) {
+ Assert1(Attrs.hasAttribute(AttributeSet::FunctionIndex,
+ Attribute::NoInline),
+ "Attribute 'optnone' requires 'noinline'!", V);
+
+ Assert1(!Attrs.hasAttribute(AttributeSet::FunctionIndex,
+ Attribute::OptimizeForSize),
+ "Attributes 'optsize and optnone' are incompatible!", V);
+
+ Assert1(!Attrs.hasAttribute(AttributeSet::FunctionIndex,
+ Attribute::MinSize),
+ "Attributes 'minsize and optnone' are incompatible!", V);
+ }
}
void Verifier::VerifyBitcastType(const Value *V, Type *DestTy, Type *SrcTy) {
@@ -930,11 +972,9 @@ void Verifier::VerifyBitcastType(const Value *V, Type *DestTy, Type *SrcTy) {
unsigned SrcAS = SrcTy->getPointerAddressSpace();
unsigned DstAS = DestTy->getPointerAddressSpace();
- unsigned SrcASSize = DL->getPointerSizeInBits(SrcAS);
- unsigned DstASSize = DL->getPointerSizeInBits(DstAS);
- Assert1(SrcASSize == DstASSize,
- "Bitcasts between pointers of different address spaces must have "
- "the same size pointers, otherwise use PtrToInt/IntToPtr.", V);
+ Assert1(SrcAS == DstAS,
+ "Bitcasts between pointers of different address spaces is not legal."
+ "Use AddrSpaceCast instead.", V);
}
void Verifier::VerifyConstantExprBitcastType(const ConstantExpr *CE) {
@@ -1152,27 +1192,12 @@ void Verifier::visitSwitchInst(SwitchInst &SI) {
// Check to make sure that all of the constants in the switch instruction
// have the same type as the switched-on value.
Type *SwitchTy = SI.getCondition()->getType();
- IntegerType *IntTy = cast<IntegerType>(SwitchTy);
- IntegersSubsetToBB Mapping;
- std::map<IntegersSubset::Range, unsigned> RangeSetMap;
+ SmallPtrSet<ConstantInt*, 32> Constants;
for (SwitchInst::CaseIt i = SI.case_begin(), e = SI.case_end(); i != e; ++i) {
- IntegersSubset CaseRanges = i.getCaseValueEx();
- for (unsigned ri = 0, rie = CaseRanges.getNumItems(); ri < rie; ++ri) {
- IntegersSubset::Range r = CaseRanges.getItem(ri);
- Assert1(((const APInt&)r.getLow()).getBitWidth() == IntTy->getBitWidth(),
- "Switch constants must all be same type as switch value!", &SI);
- Assert1(((const APInt&)r.getHigh()).getBitWidth() == IntTy->getBitWidth(),
- "Switch constants must all be same type as switch value!", &SI);
- Mapping.add(r);
- RangeSetMap[r] = i.getCaseIndex();
- }
- }
-
- IntegersSubsetToBB::RangeIterator errItem;
- if (!Mapping.verify(errItem)) {
- unsigned CaseIndex = RangeSetMap[errItem->first];
- SwitchInst::CaseIt i(&SI, CaseIndex);
- Assert2(false, "Duplicate integer as switch case", &SI, i.getCaseValueEx());
+ Assert1(i.getCaseValue()->getType() == SwitchTy,
+ "Switch constants must all be same type as switch value!", &SI);
+ Assert2(Constants.insert(i.getCaseValue()),
+ "Duplicate integer as switch case", &SI, i.getCaseValue());
}
visitTerminatorInst(SI);
@@ -1435,6 +1460,22 @@ void Verifier::visitBitCastInst(BitCastInst &I) {
visitInstruction(I);
}
+void Verifier::visitAddrSpaceCastInst(AddrSpaceCastInst &I) {
+ Type *SrcTy = I.getOperand(0)->getType();
+ Type *DestTy = I.getType();
+
+ Assert1(SrcTy->isPtrOrPtrVectorTy(),
+ "AddrSpaceCast source must be a pointer", &I);
+ Assert1(DestTy->isPtrOrPtrVectorTy(),
+ "AddrSpaceCast result must be a pointer", &I);
+ Assert1(SrcTy->getPointerAddressSpace() != DestTy->getPointerAddressSpace(),
+ "AddrSpaceCast must be between different address spaces", &I);
+ if (SrcTy->isVectorTy())
+ Assert1(SrcTy->getVectorNumElements() == DestTy->getVectorNumElements(),
+ "AddrSpaceCast vector pointer number of elements mismatch", &I);
+ visitInstruction(I);
+}
+
/// visitPHINode - Ensure that a PHI node is well formed.
///
void Verifier::visitPHINode(PHINode &PN) {
@@ -1537,14 +1578,6 @@ void Verifier::VerifyCallSite(CallSite CS) {
"Function has metadata parameter but isn't an intrinsic", I);
}
- // If the call site has the 'builtin' attribute, verify that it's applied to a
- // direct call to a function with the 'nobuiltin' attribute.
- if (CS.hasFnAttr(Attribute::Builtin))
- Assert1(CS.getCalledFunction() &&
- CS.getCalledFunction()->hasFnAttribute(Attribute::NoBuiltin),
- "Attribute 'builtin' can only be used in a call to a function with "
- "the 'nobuiltin' attribute.", I);
-
visitInstruction(*I);
}
@@ -2098,7 +2131,7 @@ void Verifier::visitInstruction(Instruction &I) {
if (!DisableDebugInfoVerifier) {
MD = I.getMetadata(LLVMContext::MD_dbg);
- Finder.processLocation(DILocation(MD));
+ Finder.processLocation(*Mod, DILocation(MD));
}
InstsInThisBlock.insert(&I);
@@ -2121,6 +2154,7 @@ bool Verifier::VerifyIntrinsicType(Type *Ty,
switch (D.Kind) {
case IITDescriptor::Void: return !Ty->isVoidTy();
+ case IITDescriptor::VarArg: return true;
case IITDescriptor::MMX: return !Ty->isX86_MMXTy();
case IITDescriptor::Metadata: return !Ty->isMetadataTy();
case IITDescriptor::Half: return !Ty->isHalfTy();
@@ -2185,6 +2219,33 @@ bool Verifier::VerifyIntrinsicType(Type *Ty,
llvm_unreachable("unhandled");
}
+/// \brief Verify if the intrinsic has variable arguments.
+/// This method is intended to be called after all the fixed arguments have been
+/// verified first.
+///
+/// This method returns true on error and does not print an error message.
+bool
+Verifier::VerifyIntrinsicIsVarArg(bool isVarArg,
+ ArrayRef<Intrinsic::IITDescriptor> &Infos) {
+ using namespace Intrinsic;
+
+ // If there are no descriptors left, then it can't be a vararg.
+ if (Infos.empty())
+ return isVarArg ? true : false;
+
+ // There should be only one descriptor remaining at this point.
+ if (Infos.size() != 1)
+ return true;
+
+ // Check and verify the descriptor.
+ IITDescriptor D = Infos.front();
+ Infos = Infos.slice(1);
+ if (D.Kind == IITDescriptor::VarArg)
+ return isVarArg ? false : true;
+
+ return true;
+}
+
/// visitIntrinsicFunction - Allow intrinsics to be verified in different ways.
///
void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
@@ -2195,7 +2256,7 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
// Verify that the intrinsic prototype lines up with what the .td files
// describe.
FunctionType *IFTy = IF->getFunctionType();
- Assert1(!IFTy->isVarArg(), "Intrinsic prototypes are not varargs", IF);
+ bool IsVarArg = IFTy->isVarArg();
SmallVector<Intrinsic::IITDescriptor, 8> Table;
getIntrinsicInfoTableEntries(ID, Table);
@@ -2207,6 +2268,16 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
for (unsigned i = 0, e = IFTy->getNumParams(); i != e; ++i)
Assert1(!VerifyIntrinsicType(IFTy->getParamType(i), TableRef, ArgTys),
"Intrinsic has incorrect argument type!", IF);
+
+ // Verify if the intrinsic call matches the vararg property.
+ if (IsVarArg)
+ Assert1(!VerifyIntrinsicIsVarArg(IsVarArg, TableRef),
+ "Intrinsic was not defined with variable arguments!", IF);
+ else
+ Assert1(!VerifyIntrinsicIsVarArg(IsVarArg, TableRef),
+ "Callsite was not defined with variable arguments!", IF);
+
+ // All descriptors should be absorbed by now.
Assert1(TableRef.empty(), "Intrinsic has too few arguments!", IF);
// Now that we have the intrinsic ID and the actual argument types (and we
@@ -2238,13 +2309,13 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
Assert1(MD->getNumOperands() == 1,
"invalid llvm.dbg.declare intrinsic call 2", &CI);
if (!DisableDebugInfoVerifier)
- Finder.processDeclare(cast<DbgDeclareInst>(&CI));
+ Finder.processDeclare(*Mod, cast<DbgDeclareInst>(&CI));
} break;
case Intrinsic::dbg_value: { //llvm.dbg.value
if (!DisableDebugInfoVerifier) {
Assert1(CI.getArgOperand(0) && isa<MDNode>(CI.getArgOperand(0)),
"invalid llvm.dbg.value intrinsic call 1", &CI);
- Finder.processValue(cast<DbgValueInst>(&CI));
+ Finder.processValue(*Mod, cast<DbgValueInst>(&CI));
}
break;
}
@@ -2309,11 +2380,9 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
}
}
-void Verifier::verifyDebugInfo(Module &M) {
+void Verifier::verifyDebugInfo() {
// Verify Debug Info.
if (!DisableDebugInfoVerifier) {
- Finder.processModule(M);
-
for (DebugInfoFinder::iterator I = Finder.compile_unit_begin(),
E = Finder.compile_unit_end(); I != E; ++I)
Assert1(DICompileUnit(*I).Verify(), "DICompileUnit does not Verify!", *I);
@@ -2352,6 +2421,7 @@ bool llvm::verifyFunction(const Function &f, VerifierFailureAction action) {
FunctionPassManager FPM(F.getParent());
Verifier *V = new Verifier(action);
FPM.add(V);
+ FPM.doInitialization();
FPM.run(F);
return V->Broken;
}