aboutsummaryrefslogtreecommitdiffstats
path: root/lib/IR
diff options
context:
space:
mode:
authorStephen Hines <srhines@google.com>2014-04-23 16:57:46 -0700
committerStephen Hines <srhines@google.com>2014-04-24 15:53:16 -0700
commit36b56886974eae4f9c5ebc96befd3e7bfe5de338 (patch)
treee6cfb69fbbd937f450eeb83bfb83b9da3b01275a /lib/IR
parent69a8640022b04415ae9fac62f8ab090601d8f889 (diff)
downloadexternal_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.zip
external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.gz
external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.bz2
Update to LLVM 3.5a.
Change-Id: Ifadecab779f128e62e430c2b4f6ddd84953ed617
Diffstat (limited to 'lib/IR')
-rw-r--r--lib/IR/Android.mk8
-rw-r--r--lib/IR/AsmWriter.cpp167
-rw-r--r--lib/IR/AsmWriter.h6
-rw-r--r--lib/IR/AttributeImpl.h2
-rw-r--r--lib/IR/Attributes.cpp6
-rw-r--r--lib/IR/AutoUpgrade.cpp21
-rw-r--r--lib/IR/BasicBlock.cpp12
-rw-r--r--lib/IR/CMakeLists.txt15
-rw-r--r--lib/IR/ConstantFold.cpp23
-rw-r--r--lib/IR/ConstantRange.cpp734
-rw-r--r--lib/IR/Constants.cpp66
-rw-r--r--lib/IR/ConstantsContext.h47
-rw-r--r--lib/IR/Core.cpp116
-rw-r--r--lib/IR/DIBuilder.cpp57
-rw-r--r--lib/IR/DataLayout.cpp319
-rw-r--r--lib/IR/DebugInfo.cpp119
-rw-r--r--lib/IR/DebugLoc.cpp26
-rw-r--r--lib/IR/DiagnosticInfo.cpp66
-rw-r--r--lib/IR/DiagnosticPrinter.cpp107
-rw-r--r--lib/IR/Dominators.cpp94
-rw-r--r--lib/IR/Function.cpp90
-rw-r--r--lib/IR/GCOV.cpp663
-rw-r--r--lib/IR/GVMaterializer.cpp2
-rw-r--r--lib/IR/Globals.cpp49
-rw-r--r--lib/IR/IRPrintingPasses.cpp127
-rw-r--r--lib/IR/InlineAsm.cpp10
-rw-r--r--lib/IR/Instruction.cpp44
-rw-r--r--lib/IR/Instructions.cpp131
-rw-r--r--lib/IR/IntrinsicInst.cpp2
-rw-r--r--lib/IR/LLVMContext.cpp62
-rw-r--r--lib/IR/LLVMContextImpl.cpp2
-rw-r--r--lib/IR/LLVMContextImpl.h28
-rw-r--r--lib/IR/LeakDetector.cpp2
-rw-r--r--lib/IR/LegacyPassManager.cpp88
-rw-r--r--lib/IR/Mangler.cpp144
-rw-r--r--lib/IR/Metadata.cpp75
-rw-r--r--lib/IR/Module.cpp117
-rw-r--r--lib/IR/Pass.cpp34
-rw-r--r--lib/IR/PassManager.cpp248
-rw-r--r--lib/IR/PassRegistry.cpp2
-rw-r--r--lib/IR/PrintModulePass.cpp136
-rw-r--r--lib/IR/Type.cpp23
-rw-r--r--lib/IR/Use.cpp164
-rw-r--r--lib/IR/Value.cpp10
-rw-r--r--lib/IR/Verifier.cpp921
45 files changed, 3567 insertions, 1618 deletions
diff --git a/lib/IR/Android.mk b/lib/IR/Android.mk
index b2b99e4..071bb04 100644
--- a/lib/IR/Android.mk
+++ b/lib/IR/Android.mk
@@ -6,17 +6,21 @@ vmcore_SRC_FILES := \
AutoUpgrade.cpp \
BasicBlock.cpp \
ConstantFold.cpp \
+ ConstantRange.cpp \
Constants.cpp \
Core.cpp \
DataLayout.cpp \
DebugInfo.cpp \
DebugLoc.cpp \
+ DiagnosticInfo.cpp \
+ DiagnosticPrinter.cpp \
DIBuilder.cpp \
Dominators.cpp \
Function.cpp \
GVMaterializer.cpp \
Globals.cpp \
IRBuilder.cpp \
+ IRPrintingPasses.cpp \
InlineAsm.cpp \
Instruction.cpp \
Instructions.cpp \
@@ -25,12 +29,12 @@ vmcore_SRC_FILES := \
LLVMContextImpl.cpp \
LeakDetector.cpp \
LegacyPassManager.cpp \
+ Mangler.cpp \
Metadata.cpp \
Module.cpp \
Pass.cpp \
PassManager.cpp \
PassRegistry.cpp \
- PrintModulePass.cpp \
Type.cpp \
TypeFinder.cpp \
Use.cpp \
@@ -59,6 +63,7 @@ include $(BUILD_HOST_STATIC_LIBRARY)
# For the device
# =====================================================
include $(CLEAR_VARS)
+ifneq (true,$(DISABLE_LLVM_DEVICE_BUILDS))
REQUIRES_RTTI := 1
@@ -71,3 +76,4 @@ LOCAL_MODULE_TAGS := optional
include $(LLVM_DEVICE_BUILD_MK)
include $(LLVM_GEN_INTRINSICS_MK)
include $(BUILD_STATIC_LIBRARY)
+endif
diff --git a/lib/IR/AsmWriter.cpp b/lib/IR/AsmWriter.cpp
index 7decffd..d4670e4 100644
--- a/lib/IR/AsmWriter.cpp
+++ b/lib/IR/AsmWriter.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
//
-// This library implements the functionality defined in llvm/Assembly/Writer.h
+// This library implements the functionality defined in llvm/IR/Writer.h
//
// Note that these routines must be extremely tolerant of various errors in the
// LLVM code, because it can be used for debugging transformations.
@@ -15,18 +15,17 @@
//===----------------------------------------------------------------------===//
#include "AsmWriter.h"
-
-#include "llvm/Assembly/Writer.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/Assembly/AssemblyAnnotationWriter.h"
-#include "llvm/Assembly/PrintModulePass.h"
-#include "llvm/DebugInfo.h"
+#include "llvm/IR/AssemblyAnnotationWriter.h"
+#include "llvm/IR/CFG.h"
#include "llvm/IR/CallingConv.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
@@ -34,13 +33,11 @@
#include "llvm/IR/Operator.h"
#include "llvm/IR/TypeFinder.h"
#include "llvm/IR/ValueSymbolTable.h"
-#include "llvm/Support/CFG.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/MathExtras.h"
-
#include <algorithm>
#include <cctype>
using namespace llvm;
@@ -76,9 +73,12 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
case CallingConv::Cold: Out << "coldcc"; break;
case CallingConv::WebKit_JS: Out << "webkit_jscc"; break;
case CallingConv::AnyReg: Out << "anyregcc"; break;
+ case CallingConv::PreserveMost: Out << "preserve_mostcc"; break;
+ case CallingConv::PreserveAll: Out << "preserve_allcc"; 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;
+ case CallingConv::X86_CDeclMethod:Out << "x86_cdeclmethodcc"; break;
case CallingConv::Intel_OCL_BI: Out << "intel_ocl_bicc"; break;
case CallingConv::ARM_APCS: Out << "arm_apcscc"; break;
case CallingConv::ARM_AAPCS: Out << "arm_aapcscc"; break;
@@ -88,6 +88,8 @@ static void PrintCallingConv(unsigned cc, raw_ostream &Out) {
case CallingConv::PTX_Device: Out << "ptx_device"; break;
case CallingConv::X86_64_SysV: Out << "x86_64_sysvcc"; break;
case CallingConv::X86_64_Win64: Out << "x86_64_win64cc"; break;
+ case CallingConv::SPIR_FUNC: Out << "spir_func"; break;
+ case CallingConv::SPIR_KERNEL: Out << "spir_kernel"; break;
}
}
@@ -192,16 +194,16 @@ void TypePrinting::incorporateTypes(const Module &M) {
/// use of type names or up references to shorten the type name where possible.
void TypePrinting::print(Type *Ty, raw_ostream &OS) {
switch (Ty->getTypeID()) {
- case Type::VoidTyID: OS << "void"; break;
- case Type::HalfTyID: OS << "half"; break;
- case Type::FloatTyID: OS << "float"; break;
- case Type::DoubleTyID: OS << "double"; break;
- case Type::X86_FP80TyID: OS << "x86_fp80"; break;
- case Type::FP128TyID: OS << "fp128"; break;
- case Type::PPC_FP128TyID: OS << "ppc_fp128"; break;
- case Type::LabelTyID: OS << "label"; break;
- case Type::MetadataTyID: OS << "metadata"; break;
- case Type::X86_MMXTyID: OS << "x86_mmx"; break;
+ case Type::VoidTyID: OS << "void"; return;
+ case Type::HalfTyID: OS << "half"; return;
+ case Type::FloatTyID: OS << "float"; return;
+ case Type::DoubleTyID: OS << "double"; return;
+ case Type::X86_FP80TyID: OS << "x86_fp80"; return;
+ case Type::FP128TyID: OS << "fp128"; return;
+ case Type::PPC_FP128TyID: OS << "ppc_fp128"; return;
+ case Type::LabelTyID: OS << "label"; return;
+ case Type::MetadataTyID: OS << "metadata"; return;
+ case Type::X86_MMXTyID: OS << "x86_mmx"; return;
case Type::IntegerTyID:
OS << 'i' << cast<IntegerType>(Ty)->getBitWidth();
return;
@@ -261,10 +263,8 @@ void TypePrinting::print(Type *Ty, raw_ostream &OS) {
OS << '>';
return;
}
- default:
- OS << "<unrecognized-type>";
- return;
}
+ llvm_unreachable("Invalid TypeID");
}
void TypePrinting::printStructBody(StructType *STy, raw_ostream &OS) {
@@ -525,7 +525,7 @@ void SlotTracker::processFunction() {
// optimizer.
if (const CallInst *CI = dyn_cast<CallInst>(I)) {
if (Function *F = CI->getCalledFunction())
- if (F->getName().startswith("llvm."))
+ if (F->isIntrinsic())
for (unsigned i = 0, e = I->getNumOperands(); i != e; ++i)
if (MDNode *N = dyn_cast_or_null<MDNode>(I->getOperand(i)))
CreateMetadataSlot(N);
@@ -677,8 +677,6 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V,
SlotTracker *Machine,
const Module *Context);
-
-
static const char *getPredicateText(unsigned predicate) {
const char * pred = "unknown";
switch (predicate) {
@@ -813,8 +811,8 @@ static void WriteConstantInternal(raw_ostream &Out, const Constant *CV,
// output the string in hexadecimal format! Note that loading and storing
// floating point types changes the bits of NaNs on some hosts, notably
// x86, so we must not use these types.
- assert(sizeof(double) == sizeof(uint64_t) &&
- "assuming that double is 64 bits!");
+ static_assert(sizeof(double) == sizeof(uint64_t),
+ "assuming that double is 64 bits!");
char Buffer[40];
APFloat apf = CFP->getValueAPF();
// Halves and floats are represented in ASCII IR as double, convert.
@@ -1065,11 +1063,8 @@ static void WriteMDNodeBodyInternal(raw_ostream &Out, const MDNode *Node,
Out << "}";
}
-
-/// WriteAsOperand - Write the name of the specified value out to the specified
-/// ostream. This can be useful when you just want to print int %reg126, not
-/// the whole instruction that generated it.
-///
+// Full implementation of printing a Value as an operand with support for
+// TypePrinting, etc.
static void WriteAsOperandInternal(raw_ostream &Out, const Value *V,
TypePrinting *TypePrinter,
SlotTracker *Machine,
@@ -1176,31 +1171,6 @@ static void WriteAsOperandInternal(raw_ostream &Out, const Value *V,
Out << "<badref>";
}
-void WriteAsOperand(raw_ostream &Out, const Value *V,
- bool PrintType, const Module *Context) {
-
- // Fast path: Don't construct and populate a TypePrinting object if we
- // won't be needing any types printed.
- if (!PrintType &&
- ((!isa<Constant>(V) && !isa<MDNode>(V)) ||
- V->hasName() || isa<GlobalValue>(V))) {
- WriteAsOperandInternal(Out, V, 0, 0, Context);
- return;
- }
-
- if (Context == 0) Context = getModuleFromVal(V);
-
- TypePrinting TypePrinter;
- if (Context)
- TypePrinter.incorporateTypes(*Context);
- if (PrintType) {
- TypePrinter.print(V->getType(), Out);
- Out << ' ';
- }
-
- WriteAsOperandInternal(Out, V, &TypePrinter, 0, Context);
-}
-
void AssemblyWriter::init() {
if (TheModule)
TypePrinter.incorporateTypes(*TheModule);
@@ -1256,6 +1226,37 @@ void AssemblyWriter::writeAtomic(AtomicOrdering Ordering,
}
}
+void AssemblyWriter::writeAtomicCmpXchg(AtomicOrdering SuccessOrdering,
+ AtomicOrdering FailureOrdering,
+ SynchronizationScope SynchScope) {
+ assert(SuccessOrdering != NotAtomic && FailureOrdering != NotAtomic);
+
+ switch (SynchScope) {
+ case SingleThread: Out << " singlethread"; break;
+ case CrossThread: break;
+ }
+
+ switch (SuccessOrdering) {
+ default: Out << " <bad ordering " << int(SuccessOrdering) << ">"; break;
+ case Unordered: Out << " unordered"; break;
+ case Monotonic: Out << " monotonic"; break;
+ case Acquire: Out << " acquire"; break;
+ case Release: Out << " release"; break;
+ case AcquireRelease: Out << " acq_rel"; break;
+ case SequentiallyConsistent: Out << " seq_cst"; break;
+ }
+
+ switch (FailureOrdering) {
+ default: Out << " <bad ordering " << int(FailureOrdering) << ">"; break;
+ case Unordered: Out << " unordered"; break;
+ case Monotonic: Out << " monotonic"; break;
+ case Acquire: Out << " acquire"; break;
+ case Release: Out << " release"; break;
+ case AcquireRelease: Out << " acq_rel"; break;
+ case SequentiallyConsistent: Out << " seq_cst"; break;
+ }
+}
+
void AssemblyWriter::writeParamOperand(const Value *Operand,
AttributeSet Attrs, unsigned Idx) {
if (Operand == 0) {
@@ -1282,8 +1283,9 @@ void AssemblyWriter::printModule(const Module *M) {
M->getModuleIdentifier().find('\n') == std::string::npos)
Out << "; ModuleID = '" << M->getModuleIdentifier() << "'\n";
- if (!M->getDataLayout().empty())
- Out << "target datalayout = \"" << M->getDataLayout() << "\"\n";
+ const std::string &DL = M->getDataLayoutStr();
+ if (!DL.empty())
+ Out << "target datalayout = \"" << DL << "\"\n";
if (!M->getTargetTriple().empty())
Out << "target triple = \"" << M->getTargetTriple() << "\"\n";
@@ -1389,10 +1391,6 @@ static void PrintLinkage(GlobalValue::LinkageTypes LT,
switch (LT) {
case GlobalValue::ExternalLinkage: break;
case GlobalValue::PrivateLinkage: Out << "private "; break;
- case GlobalValue::LinkerPrivateLinkage: Out << "linker_private "; break;
- case GlobalValue::LinkerPrivateWeakLinkage:
- Out << "linker_private_weak ";
- break;
case GlobalValue::InternalLinkage: Out << "internal "; break;
case GlobalValue::LinkOnceAnyLinkage: Out << "linkonce "; break;
case GlobalValue::LinkOnceODRLinkage: Out << "linkonce_odr "; break;
@@ -1400,8 +1398,6 @@ static void PrintLinkage(GlobalValue::LinkageTypes LT,
case GlobalValue::WeakODRLinkage: Out << "weak_odr "; break;
case GlobalValue::CommonLinkage: Out << "common "; break;
case GlobalValue::AppendingLinkage: Out << "appending "; break;
- case GlobalValue::DLLImportLinkage: Out << "dllimport "; break;
- case GlobalValue::DLLExportLinkage: Out << "dllexport "; break;
case GlobalValue::ExternalWeakLinkage: Out << "extern_weak "; break;
case GlobalValue::AvailableExternallyLinkage:
Out << "available_externally ";
@@ -1419,6 +1415,15 @@ static void PrintVisibility(GlobalValue::VisibilityTypes Vis,
}
}
+static void PrintDLLStorageClass(GlobalValue::DLLStorageClassTypes SCT,
+ formatted_raw_ostream &Out) {
+ switch (SCT) {
+ case GlobalValue::DefaultStorageClass: break;
+ case GlobalValue::DLLImportStorageClass: Out << "dllimport "; break;
+ case GlobalValue::DLLExportStorageClass: Out << "dllexport "; break;
+ }
+}
+
static void PrintThreadLocalModel(GlobalVariable::ThreadLocalMode TLM,
formatted_raw_ostream &Out) {
switch (TLM) {
@@ -1451,6 +1456,7 @@ void AssemblyWriter::printGlobal(const GlobalVariable *GV) {
PrintLinkage(GV->getLinkage(), Out);
PrintVisibility(GV->getVisibility(), Out);
+ PrintDLLStorageClass(GV->getDLLStorageClass(), Out);
PrintThreadLocalModel(GV->getThreadLocalMode(), Out);
if (unsigned AddressSpace = GV->getType()->getAddressSpace())
@@ -1488,6 +1494,7 @@ void AssemblyWriter::printAlias(const GlobalAlias *GA) {
Out << " = ";
}
PrintVisibility(GA->getVisibility(), Out);
+ PrintDLLStorageClass(GA->getDLLStorageClass(), Out);
Out << "alias ";
@@ -1585,6 +1592,7 @@ void AssemblyWriter::printFunction(const Function *F) {
PrintLinkage(F->getLinkage(), Out);
PrintVisibility(F->getVisibility(), Out);
+ PrintDLLStorageClass(F->getDLLStorageClass(), Out);
// Print the calling convention.
if (F->getCallingConv() != CallingConv::C) {
@@ -1965,6 +1973,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
} else if (const AllocaInst *AI = dyn_cast<AllocaInst>(&I)) {
Out << ' ';
+ if (AI->isUsedWithInAlloca())
+ Out << "inalloca ";
TypePrinter.print(AI->getAllocatedType(), Out);
if (!AI->getArraySize() || AI->isArrayAllocation()) {
Out << ", ";
@@ -2035,7 +2045,8 @@ void AssemblyWriter::printInstruction(const Instruction &I) {
if (SI->getAlignment())
Out << ", align " << SI->getAlignment();
} else if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(&I)) {
- writeAtomic(CXI->getOrdering(), CXI->getSynchScope());
+ writeAtomicCmpXchg(CXI->getSuccessOrdering(), CXI->getFailureOrdering(),
+ CXI->getSynchScope());
} else if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(&I)) {
writeAtomic(RMWI->getOrdering(), RMWI->getSynchScope());
} else if (const FenceInst *FI = dyn_cast<FenceInst>(&I)) {
@@ -2195,7 +2206,7 @@ void Value::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW) const {
WriteConstantInternal(OS, C, TypePrinter, 0, 0);
} else if (isa<InlineAsm>(this) || isa<MDString>(this) ||
isa<Argument>(this)) {
- WriteAsOperand(OS, this, true, 0);
+ this->printAsOperand(OS);
} else {
// Otherwise we don't know what it is. Call the virtual function to
// allow a subclass to print itself.
@@ -2203,6 +2214,30 @@ void Value::print(raw_ostream &ROS, AssemblyAnnotationWriter *AAW) const {
}
}
+void Value::printAsOperand(raw_ostream &O, bool PrintType, const Module *M) const {
+ // Fast path: Don't construct and populate a TypePrinting object if we
+ // won't be needing any types printed.
+ if (!PrintType &&
+ ((!isa<Constant>(this) && !isa<MDNode>(this)) ||
+ hasName() || isa<GlobalValue>(this))) {
+ WriteAsOperandInternal(O, this, 0, 0, M);
+ return;
+ }
+
+ if (!M)
+ M = getModuleFromVal(this);
+
+ TypePrinting TypePrinter;
+ if (M)
+ TypePrinter.incorporateTypes(*M);
+ if (PrintType) {
+ TypePrinter.print(getType(), O);
+ O << ' ';
+ }
+
+ WriteAsOperandInternal(O, this, &TypePrinter, 0, M);
+}
+
// Value::printCustom - subclasses should override this to implement printing.
void Value::printCustom(raw_ostream &OS) const {
llvm_unreachable("Unknown value to print out!");
diff --git a/lib/IR/AsmWriter.h b/lib/IR/AsmWriter.h
index 8f4a377..b4ce6de 100644
--- a/lib/IR/AsmWriter.h
+++ b/lib/IR/AsmWriter.h
@@ -16,7 +16,6 @@
#define LLVM_IR_ASSEMBLYWRITER_H
#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/IR/Attributes.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/TypeFinder.h"
@@ -67,7 +66,7 @@ protected:
const Module *TheModule;
private:
- OwningPtr<SlotTracker> ModuleSlotTracker;
+ std::unique_ptr<SlotTracker> ModuleSlotTracker;
SlotTracker &Machine;
TypePrinting TypePrinter;
AssemblyAnnotationWriter *AnnotationWriter;
@@ -91,6 +90,9 @@ public:
void writeOperand(const Value *Op, bool PrintType);
void writeParamOperand(const Value *Operand, AttributeSet Attrs,unsigned Idx);
void writeAtomic(AtomicOrdering Ordering, SynchronizationScope SynchScope);
+ void writeAtomicCmpXchg(AtomicOrdering SuccessOrdering,
+ AtomicOrdering FailureOrdering,
+ SynchronizationScope SynchScope);
void writeAllMDNodes();
void writeMDNode(unsigned Slot, const MDNode *Node);
diff --git a/lib/IR/AttributeImpl.h b/lib/IR/AttributeImpl.h
index ea954ac..9f3fd3e 100644
--- a/lib/IR/AttributeImpl.h
+++ b/lib/IR/AttributeImpl.h
@@ -109,7 +109,7 @@ public:
};
class AlignAttributeImpl : public EnumAttributeImpl {
- virtual void anchor();
+ void anchor() override;
unsigned Align;
public:
diff --git a/lib/IR/Attributes.cpp b/lib/IR/Attributes.cpp
index 0f2b7a0..9d9d948 100644
--- a/lib/IR/Attributes.cpp
+++ b/lib/IR/Attributes.cpp
@@ -166,6 +166,8 @@ std::string Attribute::getAsString(bool InAttrGrp) const {
return "builtin";
if (hasAttribute(Attribute::ByVal))
return "byval";
+ if (hasAttribute(Attribute::InAlloca))
+ return "inalloca";
if (hasAttribute(Attribute::InlineHint))
return "inlinehint";
if (hasAttribute(Attribute::InReg))
@@ -388,6 +390,7 @@ uint64_t AttributeImpl::getAttrMask(Attribute::AttrKind Val) {
case Attribute::Cold: return 1ULL << 40;
case Attribute::Builtin: return 1ULL << 41;
case Attribute::OptimizeNone: return 1ULL << 42;
+ case Attribute::InAlloca: return 1ULL << 43;
}
llvm_unreachable("Unsupported attribute type");
}
@@ -1174,7 +1177,8 @@ AttributeSet AttributeFuncs::typeIncompatible(Type *Ty, uint64_t Index) {
.addAttribute(Attribute::NoCapture)
.addAttribute(Attribute::ReadNone)
.addAttribute(Attribute::ReadOnly)
- .addAttribute(Attribute::StructRet);
+ .addAttribute(Attribute::StructRet)
+ .addAttribute(Attribute::InAlloca);
return AttributeSet::get(Ty->getContext(), Index, Incompatible);
}
diff --git a/lib/IR/AutoUpgrade.cpp b/lib/IR/AutoUpgrade.cpp
index d12bf7b..b7429b3 100644
--- a/lib/IR/AutoUpgrade.cpp
+++ b/lib/IR/AutoUpgrade.cpp
@@ -11,17 +11,18 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/AutoUpgrade.h"
-#include "llvm/DebugInfo.h"
+#include "llvm/IR/AutoUpgrade.h"
+#include "llvm/IR/CFG.h"
+#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DebugInfo.h"
+#include "llvm/IR/DiagnosticInfo.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
-#include "llvm/Support/CFG.h"
-#include "llvm/Support/CallSite.h"
#include "llvm/Support/ErrorHandling.h"
#include <cstring>
using namespace llvm;
@@ -410,7 +411,7 @@ void llvm::UpgradeCallsToIntrinsic(Function* F) {
if (UpgradeIntrinsicFunction(F, NewFn)) {
if (NewFn != F) {
// Replace all uses to the old function with the new one if necessary.
- for (Value::use_iterator UI = F->use_begin(), UE = F->use_end();
+ for (Value::user_iterator UI = F->user_begin(), UE = F->user_end();
UI != UE; ) {
if (CallInst *CI = dyn_cast<CallInst>(*UI++))
UpgradeIntrinsicCall(CI, NewFn);
@@ -494,8 +495,14 @@ Value *llvm::UpgradeBitCastExpr(unsigned Opc, Constant *C, Type *DestTy) {
/// 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)
+ unsigned Version = getDebugMetadataVersionFromModule(M);
+ if (Version == DEBUG_METADATA_VERSION)
return false;
- return StripDebugInfo(M);
+ bool RetCode = StripDebugInfo(M);
+ if (RetCode) {
+ DiagnosticInfoDebugMetadataVersion DiagVersion(M, Version);
+ M.getContext().diagnose(DiagVersion);
+ }
+ return RetCode;
}
diff --git a/lib/IR/BasicBlock.cpp b/lib/IR/BasicBlock.cpp
index 41e58ec..3079f0a 100644
--- a/lib/IR/BasicBlock.cpp
+++ b/lib/IR/BasicBlock.cpp
@@ -14,13 +14,13 @@
#include "llvm/IR/BasicBlock.h"
#include "SymbolTableListTraitsImpl.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/CFG.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LeakDetector.h"
#include "llvm/IR/Type.h"
-#include "llvm/Support/CFG.h"
-#include "llvm/Support/LeakDetector.h"
#include <algorithm>
using namespace llvm;
@@ -30,6 +30,10 @@ ValueSymbolTable *BasicBlock::getValueSymbolTable() {
return 0;
}
+const DataLayout *BasicBlock::getDataLayout() const {
+ return getParent()->getDataLayout();
+}
+
LLVMContext &BasicBlock::getContext() const {
return getType()->getContext();
}
@@ -70,7 +74,7 @@ BasicBlock::~BasicBlock() {
Constant *Replacement =
ConstantInt::get(llvm::Type::getInt32Ty(getContext()), 1);
while (!use_empty()) {
- BlockAddress *BA = cast<BlockAddress>(use_back());
+ BlockAddress *BA = cast<BlockAddress>(user_back());
BA->replaceAllUsesWith(ConstantExpr::getIntToPtr(Replacement,
BA->getType()));
BA->destroyConstant();
@@ -300,7 +304,7 @@ BasicBlock *BasicBlock::splitBasicBlock(iterator I, const Twine &BBName) {
assert(I != InstList.end() &&
"Trying to get me to create degenerate basic block!");
- BasicBlock *InsertBefore = llvm::next(Function::iterator(this))
+ BasicBlock *InsertBefore = std::next(Function::iterator(this))
.getNodePtrUnchecked();
BasicBlock *New = BasicBlock::Create(getContext(), BBName,
getParent(), InsertBefore);
diff --git a/lib/IR/CMakeLists.txt b/lib/IR/CMakeLists.txt
index 581946c..09117aa 100644
--- a/lib/IR/CMakeLists.txt
+++ b/lib/IR/CMakeLists.txt
@@ -4,8 +4,11 @@ add_llvm_library(LLVMCore
AutoUpgrade.cpp
BasicBlock.cpp
ConstantFold.cpp
+ ConstantRange.cpp
Constants.cpp
Core.cpp
+ DiagnosticInfo.cpp
+ DiagnosticPrinter.cpp
DIBuilder.cpp
DataLayout.cpp
DebugInfo.cpp
@@ -16,6 +19,7 @@ add_llvm_library(LLVMCore
GVMaterializer.cpp
Globals.cpp
IRBuilder.cpp
+ IRPrintingPasses.cpp
InlineAsm.cpp
Instruction.cpp
Instructions.cpp
@@ -24,12 +28,12 @@ add_llvm_library(LLVMCore
LLVMContextImpl.cpp
LeakDetector.cpp
LegacyPassManager.cpp
+ Mangler.cpp
Metadata.cpp
Module.cpp
Pass.cpp
PassManager.cpp
PassRegistry.cpp
- PrintModulePass.cpp
Type.cpp
TypeFinder.cpp
Use.cpp
@@ -40,13 +44,4 @@ add_llvm_library(LLVMCore
Verifier.cpp
)
-# Workaround: It takes over 20 minutes to compile with msvc10.
-# FIXME: Suppressing optimizations to core libraries would not be good thing.
-if( MSVC_VERSION LESS 1700 )
-set_property(
- SOURCE Function.cpp
- PROPERTY COMPILE_FLAGS "/Og-"
- )
-endif()
-
add_dependencies(LLVMCore intrinsics_gen)
diff --git a/lib/IR/ConstantFold.cpp b/lib/IR/ConstantFold.cpp
index f5e225c..612aba0 100644
--- a/lib/IR/ConstantFold.cpp
+++ b/lib/IR/ConstantFold.cpp
@@ -22,13 +22,13 @@
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
+#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Operator.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MathExtras.h"
#include <limits>
@@ -705,12 +705,21 @@ Constant *llvm::ConstantFoldSelectInstruction(Constant *Cond,
SmallVector<Constant*, 16> Result;
Type *Ty = IntegerType::get(CondV->getContext(), 32);
for (unsigned i = 0, e = V1->getType()->getVectorNumElements(); i != e;++i){
- ConstantInt *Cond = dyn_cast<ConstantInt>(CondV->getOperand(i));
- if (Cond == 0) break;
-
- Constant *V = Cond->isNullValue() ? V2 : V1;
- Constant *Res = ConstantExpr::getExtractElement(V, ConstantInt::get(Ty, i));
- Result.push_back(Res);
+ Constant *V;
+ Constant *V1Element = ConstantExpr::getExtractElement(V1,
+ ConstantInt::get(Ty, i));
+ Constant *V2Element = ConstantExpr::getExtractElement(V2,
+ ConstantInt::get(Ty, i));
+ Constant *Cond = dyn_cast<Constant>(CondV->getOperand(i));
+ if (V1Element == V2Element) {
+ V = V1Element;
+ } else if (isa<UndefValue>(Cond)) {
+ V = isa<UndefValue>(V1Element) ? V1Element : V2Element;
+ } else {
+ if (!isa<ConstantInt>(Cond)) break;
+ V = Cond->isNullValue() ? V2Element : V1Element;
+ }
+ Result.push_back(V);
}
// If we were able to build the vector, return it.
diff --git a/lib/IR/ConstantRange.cpp b/lib/IR/ConstantRange.cpp
new file mode 100644
index 0000000..f8e9ba4
--- /dev/null
+++ b/lib/IR/ConstantRange.cpp
@@ -0,0 +1,734 @@
+//===-- ConstantRange.cpp - ConstantRange implementation ------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Represent a range of possible values that may occur when the program is run
+// for an integral value. This keeps track of a lower and upper bound for the
+// constant, which MAY wrap around the end of the numeric range. To do this, it
+// keeps track of a [lower, upper) bound, which specifies an interval just like
+// STL iterators. When used with boolean values, the following are important
+// ranges (other integral ranges use min/max values for special range values):
+//
+// [F, F) = {} = Empty set
+// [T, F) = {T}
+// [F, T) = {F}
+// [T, T) = {F, T} = Full set
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/InstrTypes.h"
+#include "llvm/IR/ConstantRange.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+/// Initialize a full (the default) or empty set for the specified type.
+///
+ConstantRange::ConstantRange(uint32_t BitWidth, bool Full) {
+ if (Full)
+ Lower = Upper = APInt::getMaxValue(BitWidth);
+ else
+ Lower = Upper = APInt::getMinValue(BitWidth);
+}
+
+/// Initialize a range to hold the single specified value.
+///
+ConstantRange::ConstantRange(APIntMoveTy V)
+ : Lower(std::move(V)), Upper(Lower + 1) {}
+
+ConstantRange::ConstantRange(APIntMoveTy L, APIntMoveTy U)
+ : Lower(std::move(L)), Upper(std::move(U)) {
+ assert(Lower.getBitWidth() == Upper.getBitWidth() &&
+ "ConstantRange with unequal bit widths");
+ assert((Lower != Upper || (Lower.isMaxValue() || Lower.isMinValue())) &&
+ "Lower == Upper, but they aren't min or max value!");
+}
+
+ConstantRange ConstantRange::makeICmpRegion(unsigned Pred,
+ const ConstantRange &CR) {
+ if (CR.isEmptySet())
+ return CR;
+
+ uint32_t W = CR.getBitWidth();
+ switch (Pred) {
+ default: llvm_unreachable("Invalid ICmp predicate to makeICmpRegion()");
+ case CmpInst::ICMP_EQ:
+ return CR;
+ case CmpInst::ICMP_NE:
+ if (CR.isSingleElement())
+ return ConstantRange(CR.getUpper(), CR.getLower());
+ return ConstantRange(W);
+ case CmpInst::ICMP_ULT: {
+ APInt UMax(CR.getUnsignedMax());
+ if (UMax.isMinValue())
+ return ConstantRange(W, /* empty */ false);
+ return ConstantRange(APInt::getMinValue(W), UMax);
+ }
+ case CmpInst::ICMP_SLT: {
+ APInt SMax(CR.getSignedMax());
+ if (SMax.isMinSignedValue())
+ return ConstantRange(W, /* empty */ false);
+ return ConstantRange(APInt::getSignedMinValue(W), SMax);
+ }
+ case CmpInst::ICMP_ULE: {
+ APInt UMax(CR.getUnsignedMax());
+ if (UMax.isMaxValue())
+ return ConstantRange(W);
+ return ConstantRange(APInt::getMinValue(W), UMax + 1);
+ }
+ case CmpInst::ICMP_SLE: {
+ APInt SMax(CR.getSignedMax());
+ if (SMax.isMaxSignedValue())
+ return ConstantRange(W);
+ return ConstantRange(APInt::getSignedMinValue(W), SMax + 1);
+ }
+ case CmpInst::ICMP_UGT: {
+ APInt UMin(CR.getUnsignedMin());
+ if (UMin.isMaxValue())
+ return ConstantRange(W, /* empty */ false);
+ return ConstantRange(UMin + 1, APInt::getNullValue(W));
+ }
+ case CmpInst::ICMP_SGT: {
+ APInt SMin(CR.getSignedMin());
+ if (SMin.isMaxSignedValue())
+ return ConstantRange(W, /* empty */ false);
+ return ConstantRange(SMin + 1, APInt::getSignedMinValue(W));
+ }
+ case CmpInst::ICMP_UGE: {
+ APInt UMin(CR.getUnsignedMin());
+ if (UMin.isMinValue())
+ return ConstantRange(W);
+ return ConstantRange(UMin, APInt::getNullValue(W));
+ }
+ case CmpInst::ICMP_SGE: {
+ APInt SMin(CR.getSignedMin());
+ if (SMin.isMinSignedValue())
+ return ConstantRange(W);
+ return ConstantRange(SMin, APInt::getSignedMinValue(W));
+ }
+ }
+}
+
+/// isFullSet - Return true if this set contains all of the elements possible
+/// for this data-type
+bool ConstantRange::isFullSet() const {
+ return Lower == Upper && Lower.isMaxValue();
+}
+
+/// isEmptySet - Return true if this set contains no members.
+///
+bool ConstantRange::isEmptySet() const {
+ return Lower == Upper && Lower.isMinValue();
+}
+
+/// isWrappedSet - Return true if this set wraps around the top of the range,
+/// for example: [100, 8)
+///
+bool ConstantRange::isWrappedSet() const {
+ return Lower.ugt(Upper);
+}
+
+/// isSignWrappedSet - Return true if this set wraps around the INT_MIN of
+/// its bitwidth, for example: i8 [120, 140).
+///
+bool ConstantRange::isSignWrappedSet() const {
+ return contains(APInt::getSignedMaxValue(getBitWidth())) &&
+ contains(APInt::getSignedMinValue(getBitWidth()));
+}
+
+/// getSetSize - Return the number of elements in this set.
+///
+APInt ConstantRange::getSetSize() const {
+ if (isFullSet()) {
+ APInt Size(getBitWidth()+1, 0);
+ Size.setBit(getBitWidth());
+ return Size;
+ }
+
+ // This is also correct for wrapped sets.
+ return (Upper - Lower).zext(getBitWidth()+1);
+}
+
+/// getUnsignedMax - Return the largest unsigned value contained in the
+/// ConstantRange.
+///
+APInt ConstantRange::getUnsignedMax() const {
+ if (isFullSet() || isWrappedSet())
+ return APInt::getMaxValue(getBitWidth());
+ return getUpper() - 1;
+}
+
+/// getUnsignedMin - Return the smallest unsigned value contained in the
+/// ConstantRange.
+///
+APInt ConstantRange::getUnsignedMin() const {
+ if (isFullSet() || (isWrappedSet() && getUpper() != 0))
+ return APInt::getMinValue(getBitWidth());
+ return getLower();
+}
+
+/// getSignedMax - Return the largest signed value contained in the
+/// ConstantRange.
+///
+APInt ConstantRange::getSignedMax() const {
+ APInt SignedMax(APInt::getSignedMaxValue(getBitWidth()));
+ if (!isWrappedSet()) {
+ if (getLower().sle(getUpper() - 1))
+ return getUpper() - 1;
+ return SignedMax;
+ }
+ if (getLower().isNegative() == getUpper().isNegative())
+ return SignedMax;
+ return getUpper() - 1;
+}
+
+/// getSignedMin - Return the smallest signed value contained in the
+/// ConstantRange.
+///
+APInt ConstantRange::getSignedMin() const {
+ APInt SignedMin(APInt::getSignedMinValue(getBitWidth()));
+ if (!isWrappedSet()) {
+ if (getLower().sle(getUpper() - 1))
+ return getLower();
+ return SignedMin;
+ }
+ if ((getUpper() - 1).slt(getLower())) {
+ if (getUpper() != SignedMin)
+ return SignedMin;
+ }
+ return getLower();
+}
+
+/// contains - Return true if the specified value is in the set.
+///
+bool ConstantRange::contains(const APInt &V) const {
+ if (Lower == Upper)
+ return isFullSet();
+
+ if (!isWrappedSet())
+ return Lower.ule(V) && V.ult(Upper);
+ return Lower.ule(V) || V.ult(Upper);
+}
+
+/// contains - Return true if the argument is a subset of this range.
+/// Two equal sets contain each other. The empty set contained by all other
+/// sets.
+///
+bool ConstantRange::contains(const ConstantRange &Other) const {
+ if (isFullSet() || Other.isEmptySet()) return true;
+ if (isEmptySet() || Other.isFullSet()) return false;
+
+ if (!isWrappedSet()) {
+ if (Other.isWrappedSet())
+ return false;
+
+ return Lower.ule(Other.getLower()) && Other.getUpper().ule(Upper);
+ }
+
+ if (!Other.isWrappedSet())
+ return Other.getUpper().ule(Upper) ||
+ Lower.ule(Other.getLower());
+
+ return Other.getUpper().ule(Upper) && Lower.ule(Other.getLower());
+}
+
+/// subtract - Subtract the specified constant from the endpoints of this
+/// constant range.
+ConstantRange ConstantRange::subtract(const APInt &Val) const {
+ assert(Val.getBitWidth() == getBitWidth() && "Wrong bit width");
+ // If the set is empty or full, don't modify the endpoints.
+ if (Lower == Upper)
+ return *this;
+ return ConstantRange(Lower - Val, Upper - Val);
+}
+
+/// \brief Subtract the specified range from this range (aka relative complement
+/// of the sets).
+ConstantRange ConstantRange::difference(const ConstantRange &CR) const {
+ return intersectWith(CR.inverse());
+}
+
+/// intersectWith - Return the range that results from the intersection of this
+/// range with another range. The resultant range is guaranteed to include all
+/// elements contained in both input ranges, and to have the smallest possible
+/// set size that does so. Because there may be two intersections with the
+/// same set size, A.intersectWith(B) might not be equal to B.intersectWith(A).
+ConstantRange ConstantRange::intersectWith(const ConstantRange &CR) const {
+ assert(getBitWidth() == CR.getBitWidth() &&
+ "ConstantRange types don't agree!");
+
+ // Handle common cases.
+ if ( isEmptySet() || CR.isFullSet()) return *this;
+ if (CR.isEmptySet() || isFullSet()) return CR;
+
+ if (!isWrappedSet() && CR.isWrappedSet())
+ return CR.intersectWith(*this);
+
+ if (!isWrappedSet() && !CR.isWrappedSet()) {
+ if (Lower.ult(CR.Lower)) {
+ if (Upper.ule(CR.Lower))
+ return ConstantRange(getBitWidth(), false);
+
+ if (Upper.ult(CR.Upper))
+ return ConstantRange(CR.Lower, Upper);
+
+ return CR;
+ }
+ if (Upper.ult(CR.Upper))
+ return *this;
+
+ if (Lower.ult(CR.Upper))
+ return ConstantRange(Lower, CR.Upper);
+
+ return ConstantRange(getBitWidth(), false);
+ }
+
+ if (isWrappedSet() && !CR.isWrappedSet()) {
+ if (CR.Lower.ult(Upper)) {
+ if (CR.Upper.ult(Upper))
+ return CR;
+
+ if (CR.Upper.ule(Lower))
+ return ConstantRange(CR.Lower, Upper);
+
+ if (getSetSize().ult(CR.getSetSize()))
+ return *this;
+ return CR;
+ }
+ if (CR.Lower.ult(Lower)) {
+ if (CR.Upper.ule(Lower))
+ return ConstantRange(getBitWidth(), false);
+
+ return ConstantRange(Lower, CR.Upper);
+ }
+ return CR;
+ }
+
+ if (CR.Upper.ult(Upper)) {
+ if (CR.Lower.ult(Upper)) {
+ if (getSetSize().ult(CR.getSetSize()))
+ return *this;
+ return CR;
+ }
+
+ if (CR.Lower.ult(Lower))
+ return ConstantRange(Lower, CR.Upper);
+
+ return CR;
+ }
+ if (CR.Upper.ule(Lower)) {
+ if (CR.Lower.ult(Lower))
+ return *this;
+
+ return ConstantRange(CR.Lower, Upper);
+ }
+ if (getSetSize().ult(CR.getSetSize()))
+ return *this;
+ return CR;
+}
+
+
+/// unionWith - Return the range that results from the union of this range with
+/// another range. The resultant range is guaranteed to include the elements of
+/// both sets, but may contain more. For example, [3, 9) union [12,15) is
+/// [3, 15), which includes 9, 10, and 11, which were not included in either
+/// set before.
+///
+ConstantRange ConstantRange::unionWith(const ConstantRange &CR) const {
+ assert(getBitWidth() == CR.getBitWidth() &&
+ "ConstantRange types don't agree!");
+
+ if ( isFullSet() || CR.isEmptySet()) return *this;
+ if (CR.isFullSet() || isEmptySet()) return CR;
+
+ if (!isWrappedSet() && CR.isWrappedSet()) return CR.unionWith(*this);
+
+ if (!isWrappedSet() && !CR.isWrappedSet()) {
+ if (CR.Upper.ult(Lower) || Upper.ult(CR.Lower)) {
+ // If the two ranges are disjoint, find the smaller gap and bridge it.
+ APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper;
+ if (d1.ult(d2))
+ return ConstantRange(Lower, CR.Upper);
+ return ConstantRange(CR.Lower, Upper);
+ }
+
+ APInt L = Lower, U = Upper;
+ if (CR.Lower.ult(L))
+ L = CR.Lower;
+ if ((CR.Upper - 1).ugt(U - 1))
+ U = CR.Upper;
+
+ if (L == 0 && U == 0)
+ return ConstantRange(getBitWidth());
+
+ return ConstantRange(L, U);
+ }
+
+ if (!CR.isWrappedSet()) {
+ // ------U L----- and ------U L----- : this
+ // L--U L--U : CR
+ if (CR.Upper.ule(Upper) || CR.Lower.uge(Lower))
+ return *this;
+
+ // ------U L----- : this
+ // L---------U : CR
+ if (CR.Lower.ule(Upper) && Lower.ule(CR.Upper))
+ return ConstantRange(getBitWidth());
+
+ // ----U L---- : this
+ // L---U : CR
+ // <d1> <d2>
+ if (Upper.ule(CR.Lower) && CR.Upper.ule(Lower)) {
+ APInt d1 = CR.Lower - Upper, d2 = Lower - CR.Upper;
+ if (d1.ult(d2))
+ return ConstantRange(Lower, CR.Upper);
+ return ConstantRange(CR.Lower, Upper);
+ }
+
+ // ----U L----- : this
+ // L----U : CR
+ if (Upper.ult(CR.Lower) && Lower.ult(CR.Upper))
+ return ConstantRange(CR.Lower, Upper);
+
+ // ------U L---- : this
+ // L-----U : CR
+ assert(CR.Lower.ult(Upper) && CR.Upper.ult(Lower) &&
+ "ConstantRange::unionWith missed a case with one range wrapped");
+ return ConstantRange(Lower, CR.Upper);
+ }
+
+ // ------U L---- and ------U L---- : this
+ // -U L----------- and ------------U L : CR
+ if (CR.Lower.ule(Upper) || Lower.ule(CR.Upper))
+ return ConstantRange(getBitWidth());
+
+ APInt L = Lower, U = Upper;
+ if (CR.Upper.ugt(U))
+ U = CR.Upper;
+ if (CR.Lower.ult(L))
+ L = CR.Lower;
+
+ return ConstantRange(L, U);
+}
+
+/// zeroExtend - Return a new range in the specified integer type, which must
+/// be strictly larger than the current type. The returned range will
+/// correspond to the possible range of values as if the source range had been
+/// zero extended.
+ConstantRange ConstantRange::zeroExtend(uint32_t DstTySize) const {
+ if (isEmptySet()) return ConstantRange(DstTySize, /*isFullSet=*/false);
+
+ unsigned SrcTySize = getBitWidth();
+ assert(SrcTySize < DstTySize && "Not a value extension");
+ if (isFullSet() || isWrappedSet()) {
+ // Change into [0, 1 << src bit width)
+ APInt LowerExt(DstTySize, 0);
+ if (!Upper) // special case: [X, 0) -- not really wrapping around
+ LowerExt = Lower.zext(DstTySize);
+ return ConstantRange(LowerExt, APInt::getOneBitSet(DstTySize, SrcTySize));
+ }
+
+ return ConstantRange(Lower.zext(DstTySize), Upper.zext(DstTySize));
+}
+
+/// signExtend - Return a new range in the specified integer type, which must
+/// be strictly larger than the current type. The returned range will
+/// correspond to the possible range of values as if the source range had been
+/// sign extended.
+ConstantRange ConstantRange::signExtend(uint32_t DstTySize) const {
+ if (isEmptySet()) return ConstantRange(DstTySize, /*isFullSet=*/false);
+
+ unsigned SrcTySize = getBitWidth();
+ assert(SrcTySize < DstTySize && "Not a value extension");
+
+ // special case: [X, INT_MIN) -- not really wrapping around
+ if (Upper.isMinSignedValue())
+ return ConstantRange(Lower.sext(DstTySize), Upper.zext(DstTySize));
+
+ if (isFullSet() || isSignWrappedSet()) {
+ return ConstantRange(APInt::getHighBitsSet(DstTySize,DstTySize-SrcTySize+1),
+ APInt::getLowBitsSet(DstTySize, SrcTySize-1) + 1);
+ }
+
+ return ConstantRange(Lower.sext(DstTySize), Upper.sext(DstTySize));
+}
+
+/// truncate - Return a new range in the specified integer type, which must be
+/// strictly smaller than the current type. The returned range will
+/// correspond to the possible range of values as if the source range had been
+/// truncated to the specified type.
+ConstantRange ConstantRange::truncate(uint32_t DstTySize) const {
+ assert(getBitWidth() > DstTySize && "Not a value truncation");
+ if (isEmptySet())
+ return ConstantRange(DstTySize, /*isFullSet=*/false);
+ if (isFullSet())
+ return ConstantRange(DstTySize, /*isFullSet=*/true);
+
+ APInt MaxValue = APInt::getMaxValue(DstTySize).zext(getBitWidth());
+ APInt MaxBitValue(getBitWidth(), 0);
+ MaxBitValue.setBit(DstTySize);
+
+ APInt LowerDiv(Lower), UpperDiv(Upper);
+ ConstantRange Union(DstTySize, /*isFullSet=*/false);
+
+ // Analyze wrapped sets in their two parts: [0, Upper) \/ [Lower, MaxValue]
+ // We use the non-wrapped set code to analyze the [Lower, MaxValue) part, and
+ // then we do the union with [MaxValue, Upper)
+ if (isWrappedSet()) {
+ // if Upper is greater than Max Value, it covers the whole truncated range.
+ if (Upper.uge(MaxValue))
+ return ConstantRange(DstTySize, /*isFullSet=*/true);
+
+ Union = ConstantRange(APInt::getMaxValue(DstTySize),Upper.trunc(DstTySize));
+ UpperDiv = APInt::getMaxValue(getBitWidth());
+
+ // Union covers the MaxValue case, so return if the remaining range is just
+ // MaxValue.
+ if (LowerDiv == UpperDiv)
+ return Union;
+ }
+
+ // Chop off the most significant bits that are past the destination bitwidth.
+ if (LowerDiv.uge(MaxValue)) {
+ APInt Div(getBitWidth(), 0);
+ APInt::udivrem(LowerDiv, MaxBitValue, Div, LowerDiv);
+ UpperDiv = UpperDiv - MaxBitValue * Div;
+ }
+
+ if (UpperDiv.ule(MaxValue))
+ return ConstantRange(LowerDiv.trunc(DstTySize),
+ UpperDiv.trunc(DstTySize)).unionWith(Union);
+
+ // The truncated value wrapps around. Check if we can do better than fullset.
+ APInt UpperModulo = UpperDiv - MaxBitValue;
+ if (UpperModulo.ult(LowerDiv))
+ return ConstantRange(LowerDiv.trunc(DstTySize),
+ UpperModulo.trunc(DstTySize)).unionWith(Union);
+
+ return ConstantRange(DstTySize, /*isFullSet=*/true);
+}
+
+/// zextOrTrunc - make this range have the bit width given by \p DstTySize. The
+/// value is zero extended, truncated, or left alone to make it that width.
+ConstantRange ConstantRange::zextOrTrunc(uint32_t DstTySize) const {
+ unsigned SrcTySize = getBitWidth();
+ if (SrcTySize > DstTySize)
+ return truncate(DstTySize);
+ if (SrcTySize < DstTySize)
+ return zeroExtend(DstTySize);
+ return *this;
+}
+
+/// sextOrTrunc - make this range have the bit width given by \p DstTySize. The
+/// value is sign extended, truncated, or left alone to make it that width.
+ConstantRange ConstantRange::sextOrTrunc(uint32_t DstTySize) const {
+ unsigned SrcTySize = getBitWidth();
+ if (SrcTySize > DstTySize)
+ return truncate(DstTySize);
+ if (SrcTySize < DstTySize)
+ return signExtend(DstTySize);
+ return *this;
+}
+
+ConstantRange
+ConstantRange::add(const ConstantRange &Other) const {
+ if (isEmptySet() || Other.isEmptySet())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/false);
+ if (isFullSet() || Other.isFullSet())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+
+ APInt Spread_X = getSetSize(), Spread_Y = Other.getSetSize();
+ APInt NewLower = getLower() + Other.getLower();
+ APInt NewUpper = getUpper() + Other.getUpper() - 1;
+ if (NewLower == NewUpper)
+ return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+
+ ConstantRange X = ConstantRange(NewLower, NewUpper);
+ if (X.getSetSize().ult(Spread_X) || X.getSetSize().ult(Spread_Y))
+ // We've wrapped, therefore, full set.
+ return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+
+ return X;
+}
+
+ConstantRange
+ConstantRange::sub(const ConstantRange &Other) const {
+ if (isEmptySet() || Other.isEmptySet())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/false);
+ if (isFullSet() || Other.isFullSet())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+
+ APInt Spread_X = getSetSize(), Spread_Y = Other.getSetSize();
+ APInt NewLower = getLower() - Other.getUpper() + 1;
+ APInt NewUpper = getUpper() - Other.getLower();
+ if (NewLower == NewUpper)
+ return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+
+ ConstantRange X = ConstantRange(NewLower, NewUpper);
+ if (X.getSetSize().ult(Spread_X) || X.getSetSize().ult(Spread_Y))
+ // We've wrapped, therefore, full set.
+ return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+
+ return X;
+}
+
+ConstantRange
+ConstantRange::multiply(const ConstantRange &Other) const {
+ // TODO: If either operand is a single element and the multiply is known to
+ // be non-wrapping, round the result min and max value to the appropriate
+ // multiple of that element. If wrapping is possible, at least adjust the
+ // range according to the greatest power-of-two factor of the single element.
+
+ if (isEmptySet() || Other.isEmptySet())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/false);
+
+ APInt this_min = getUnsignedMin().zext(getBitWidth() * 2);
+ APInt this_max = getUnsignedMax().zext(getBitWidth() * 2);
+ APInt Other_min = Other.getUnsignedMin().zext(getBitWidth() * 2);
+ APInt Other_max = Other.getUnsignedMax().zext(getBitWidth() * 2);
+
+ ConstantRange Result_zext = ConstantRange(this_min * Other_min,
+ this_max * Other_max + 1);
+ return Result_zext.truncate(getBitWidth());
+}
+
+ConstantRange
+ConstantRange::smax(const ConstantRange &Other) const {
+ // X smax Y is: range(smax(X_smin, Y_smin),
+ // smax(X_smax, Y_smax))
+ if (isEmptySet() || Other.isEmptySet())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/false);
+ APInt NewL = APIntOps::smax(getSignedMin(), Other.getSignedMin());
+ APInt NewU = APIntOps::smax(getSignedMax(), Other.getSignedMax()) + 1;
+ if (NewU == NewL)
+ return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+ return ConstantRange(NewL, NewU);
+}
+
+ConstantRange
+ConstantRange::umax(const ConstantRange &Other) const {
+ // X umax Y is: range(umax(X_umin, Y_umin),
+ // umax(X_umax, Y_umax))
+ if (isEmptySet() || Other.isEmptySet())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/false);
+ APInt NewL = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin());
+ APInt NewU = APIntOps::umax(getUnsignedMax(), Other.getUnsignedMax()) + 1;
+ if (NewU == NewL)
+ return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+ return ConstantRange(NewL, NewU);
+}
+
+ConstantRange
+ConstantRange::udiv(const ConstantRange &RHS) const {
+ if (isEmptySet() || RHS.isEmptySet() || RHS.getUnsignedMax() == 0)
+ return ConstantRange(getBitWidth(), /*isFullSet=*/false);
+ if (RHS.isFullSet())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+
+ APInt Lower = getUnsignedMin().udiv(RHS.getUnsignedMax());
+
+ APInt RHS_umin = RHS.getUnsignedMin();
+ if (RHS_umin == 0) {
+ // We want the lowest value in RHS excluding zero. Usually that would be 1
+ // except for a range in the form of [X, 1) in which case it would be X.
+ if (RHS.getUpper() == 1)
+ RHS_umin = RHS.getLower();
+ else
+ RHS_umin = APInt(getBitWidth(), 1);
+ }
+
+ APInt Upper = getUnsignedMax().udiv(RHS_umin) + 1;
+
+ // If the LHS is Full and the RHS is a wrapped interval containing 1 then
+ // this could occur.
+ if (Lower == Upper)
+ return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+
+ return ConstantRange(Lower, Upper);
+}
+
+ConstantRange
+ConstantRange::binaryAnd(const ConstantRange &Other) const {
+ if (isEmptySet() || Other.isEmptySet())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/false);
+
+ // TODO: replace this with something less conservative
+
+ APInt umin = APIntOps::umin(Other.getUnsignedMax(), getUnsignedMax());
+ if (umin.isAllOnesValue())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+ return ConstantRange(APInt::getNullValue(getBitWidth()), umin + 1);
+}
+
+ConstantRange
+ConstantRange::binaryOr(const ConstantRange &Other) const {
+ if (isEmptySet() || Other.isEmptySet())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/false);
+
+ // TODO: replace this with something less conservative
+
+ APInt umax = APIntOps::umax(getUnsignedMin(), Other.getUnsignedMin());
+ if (umax.isMinValue())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+ return ConstantRange(umax, APInt::getNullValue(getBitWidth()));
+}
+
+ConstantRange
+ConstantRange::shl(const ConstantRange &Other) const {
+ if (isEmptySet() || Other.isEmptySet())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/false);
+
+ APInt min = getUnsignedMin().shl(Other.getUnsignedMin());
+ APInt max = getUnsignedMax().shl(Other.getUnsignedMax());
+
+ // there's no overflow!
+ APInt Zeros(getBitWidth(), getUnsignedMax().countLeadingZeros());
+ if (Zeros.ugt(Other.getUnsignedMax()))
+ return ConstantRange(min, max + 1);
+
+ // FIXME: implement the other tricky cases
+ return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+}
+
+ConstantRange
+ConstantRange::lshr(const ConstantRange &Other) const {
+ if (isEmptySet() || Other.isEmptySet())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/false);
+
+ APInt max = getUnsignedMax().lshr(Other.getUnsignedMin());
+ APInt min = getUnsignedMin().lshr(Other.getUnsignedMax());
+ if (min == max + 1)
+ return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+
+ return ConstantRange(min, max + 1);
+}
+
+ConstantRange ConstantRange::inverse() const {
+ if (isFullSet())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/false);
+ if (isEmptySet())
+ return ConstantRange(getBitWidth(), /*isFullSet=*/true);
+ return ConstantRange(Upper, Lower);
+}
+
+/// print - Print out the bounds to a stream...
+///
+void ConstantRange::print(raw_ostream &OS) const {
+ if (isFullSet())
+ OS << "full-set";
+ else if (isEmptySet())
+ OS << "empty-set";
+ else
+ OS << "[" << Lower << "," << Upper << ")";
+}
+
+/// dump - Allow printing from a debugger easily...
+///
+void ConstantRange::dump() const {
+ print(dbgs());
+}
diff --git a/lib/IR/Constants.cpp b/lib/IR/Constants.cpp
index 690ac59..2a3a5fd 100644
--- a/lib/IR/Constants.cpp
+++ b/lib/IR/Constants.cpp
@@ -21,6 +21,7 @@
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/Module.h"
@@ -28,7 +29,6 @@
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/raw_ostream.h"
@@ -218,7 +218,7 @@ void Constant::destroyConstantImpl() {
// Constants) that they are, in fact, invalid now and should be deleted.
//
while (!use_empty()) {
- Value *V = use_back();
+ Value *V = user_back();
#ifndef NDEBUG // Only in -g mode...
if (!isa<Constant>(V)) {
dbgs() << "While deleting: " << *this
@@ -230,7 +230,7 @@ void Constant::destroyConstantImpl() {
cast<Constant>(V)->destroyConstant();
// The constant should remove itself from our use list...
- assert((use_empty() || use_back() != V) && "Constant not removed!");
+ assert((use_empty() || user_back() != V) && "Constant not removed!");
}
// Value has no outstanding references it is safe to delete it now...
@@ -307,8 +307,8 @@ bool Constant::isThreadDependent() const {
/// isConstantUsed - Return true if the constant has users other than constant
/// exprs and other dangling things.
bool Constant::isConstantUsed() const {
- for (const_use_iterator UI = use_begin(), E = use_end(); UI != E; ++UI) {
- const Constant *UC = dyn_cast<Constant>(*UI);
+ for (const User *U : users()) {
+ const Constant *UC = dyn_cast<Constant>(U);
if (UC == 0 || isa<GlobalValue>(UC))
return true;
@@ -377,7 +377,7 @@ static bool removeDeadUsersOfConstant(const Constant *C) {
if (isa<GlobalValue>(C)) return false; // Cannot remove this
while (!C->use_empty()) {
- const Constant *User = dyn_cast<Constant>(C->use_back());
+ const Constant *User = dyn_cast<Constant>(C->user_back());
if (!User) return false; // Non-constant usage;
if (!removeDeadUsersOfConstant(User))
return false; // Constant wasn't dead
@@ -393,8 +393,8 @@ static bool removeDeadUsersOfConstant(const Constant *C) {
/// that want to check to see if a global is unused, but don't want to deal
/// with potentially dead constants hanging off of the globals.
void Constant::removeDeadConstantUsers() const {
- Value::const_use_iterator I = use_begin(), E = use_end();
- Value::const_use_iterator LastNonDeadUser = E;
+ Value::const_user_iterator I = user_begin(), E = user_end();
+ Value::const_user_iterator LastNonDeadUser = E;
while (I != E) {
const Constant *User = dyn_cast<Constant>(*I);
if (User == 0) {
@@ -413,7 +413,7 @@ void Constant::removeDeadConstantUsers() const {
// If the constant was dead, then the iterator is invalidated.
if (LastNonDeadUser == E) {
- I = use_begin();
+ I = user_begin();
if (I == E) break;
} else {
I = LastNonDeadUser;
@@ -584,23 +584,21 @@ Constant *ConstantFP::get(Type *Ty, StringRef Str) {
return C;
}
+Constant *ConstantFP::getNegativeZero(Type *Ty) {
+ const fltSemantics &Semantics = *TypeToFloatSemantics(Ty->getScalarType());
+ APFloat NegZero = APFloat::getZero(Semantics, /*Negative=*/true);
+ Constant *C = get(Ty->getContext(), NegZero);
-ConstantFP *ConstantFP::getNegativeZero(Type *Ty) {
- LLVMContext &Context = Ty->getContext();
- APFloat apf = cast<ConstantFP>(Constant::getNullValue(Ty))->getValueAPF();
- apf.changeSign();
- return get(Context, apf);
+ if (VectorType *VTy = dyn_cast<VectorType>(Ty))
+ return ConstantVector::getSplat(VTy->getNumElements(), C);
+
+ return C;
}
Constant *ConstantFP::getZeroValueForNegation(Type *Ty) {
- Type *ScalarTy = Ty->getScalarType();
- if (ScalarTy->isFloatingPointTy()) {
- Constant *C = getNegativeZero(ScalarTy);
- if (VectorType *VTy = dyn_cast<VectorType>(Ty))
- return ConstantVector::getSplat(VTy->getNumElements(), C);
- return C;
- }
+ if (Ty->isFPOrFPVectorTy())
+ return getNegativeZero(Ty);
return Constant::getNullValue(Ty);
}
@@ -635,10 +633,14 @@ ConstantFP* ConstantFP::get(LLVMContext &Context, const APFloat& V) {
return Slot;
}
-ConstantFP *ConstantFP::getInfinity(Type *Ty, bool Negative) {
- const fltSemantics &Semantics = *TypeToFloatSemantics(Ty);
- return ConstantFP::get(Ty->getContext(),
- APFloat::getInf(Semantics, Negative));
+Constant *ConstantFP::getInfinity(Type *Ty, bool Negative) {
+ const fltSemantics &Semantics = *TypeToFloatSemantics(Ty->getScalarType());
+ Constant *C = get(Ty->getContext(), APFloat::getInf(Semantics, Negative));
+
+ if (VectorType *VTy = dyn_cast<VectorType>(Ty))
+ return ConstantVector::getSplat(VTy->getNumElements(), C);
+
+ return C;
}
ConstantFP::ConstantFP(Type *Ty, const APFloat& V)
@@ -1045,7 +1047,7 @@ bool ConstantExpr::isGEPWithNoNotionalOverIndexing() const {
if (getOpcode() != Instruction::GetElementPtr) return false;
gep_type_iterator GEPI = gep_type_begin(this), E = gep_type_end(this);
- User::const_op_iterator OI = llvm::next(this->op_begin());
+ User::const_op_iterator OI = std::next(this->op_begin());
// Skip the first index, as it has no static limit.
++GEPI;
@@ -1373,6 +1375,17 @@ BlockAddress::BlockAddress(Function *F, BasicBlock *BB)
BB->AdjustBlockAddressRefCount(1);
}
+BlockAddress *BlockAddress::lookup(const BasicBlock *BB) {
+ if (!BB->hasAddressTaken())
+ return 0;
+
+ const Function *F = BB->getParent();
+ assert(F != 0 && "Block must have a parent");
+ BlockAddress *BA =
+ F->getContext().pImpl->BlockAddresses.lookup(std::make_pair(F, BB));
+ assert(BA && "Refcount and block address map disagree!");
+ return BA;
+}
// destroyConstant - Remove the constant from the constant table.
//
@@ -2781,6 +2794,7 @@ Instruction *ConstantExpr::getAsInstruction() {
case Instruction::PtrToInt:
case Instruction::IntToPtr:
case Instruction::BitCast:
+ case Instruction::AddrSpaceCast:
return CastInst::Create((Instruction::CastOps)getOpcode(),
Ops[0], getType());
case Instruction::Select:
diff --git a/lib/IR/ConstantsContext.h b/lib/IR/ConstantsContext.h
index 32bed95..59b9d4d 100644
--- a/lib/IR/ConstantsContext.h
+++ b/lib/IR/ConstantsContext.h
@@ -32,7 +32,7 @@ struct ConstantTraits;
/// UnaryConstantExpr - This class is private to Constants.cpp, and is used
/// behind the scenes to implement unary constant exprs.
class UnaryConstantExpr : public ConstantExpr {
- virtual void anchor();
+ void anchor() override;
void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
public:
// allocate space for exactly one operand
@@ -49,7 +49,7 @@ public:
/// BinaryConstantExpr - This class is private to Constants.cpp, and is used
/// behind the scenes to implement binary constant exprs.
class BinaryConstantExpr : public ConstantExpr {
- virtual void anchor();
+ void anchor() override;
void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
public:
// allocate space for exactly two operands
@@ -70,7 +70,7 @@ public:
/// SelectConstantExpr - This class is private to Constants.cpp, and is used
/// behind the scenes to implement select constant exprs.
class SelectConstantExpr : public ConstantExpr {
- virtual void anchor();
+ void anchor() override;
void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
public:
// allocate space for exactly three operands
@@ -91,7 +91,7 @@ public:
/// Constants.cpp, and is used behind the scenes to implement
/// extractelement constant exprs.
class ExtractElementConstantExpr : public ConstantExpr {
- virtual void anchor();
+ void anchor() override;
void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
public:
// allocate space for exactly two operands
@@ -112,7 +112,7 @@ public:
/// Constants.cpp, and is used behind the scenes to implement
/// insertelement constant exprs.
class InsertElementConstantExpr : public ConstantExpr {
- virtual void anchor();
+ void anchor() override;
void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
public:
// allocate space for exactly three operands
@@ -134,7 +134,7 @@ public:
/// Constants.cpp, and is used behind the scenes to implement
/// shufflevector constant exprs.
class ShuffleVectorConstantExpr : public ConstantExpr {
- virtual void anchor();
+ void anchor() override;
void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
public:
// allocate space for exactly three operands
@@ -159,7 +159,7 @@ public:
/// Constants.cpp, and is used behind the scenes to implement
/// extractvalue constant exprs.
class ExtractValueConstantExpr : public ConstantExpr {
- virtual void anchor();
+ void anchor() override;
void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
public:
// allocate space for exactly one operand
@@ -185,7 +185,7 @@ public:
/// Constants.cpp, and is used behind the scenes to implement
/// insertvalue constant exprs.
class InsertValueConstantExpr : public ConstantExpr {
- virtual void anchor();
+ void anchor() override;
void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
public:
// allocate space for exactly one operand
@@ -212,7 +212,7 @@ public:
/// GetElementPtrConstantExpr - This class is private to Constants.cpp, and is
/// used behind the scenes to implement getelementpr constant exprs.
class GetElementPtrConstantExpr : public ConstantExpr {
- virtual void anchor();
+ void anchor() override;
GetElementPtrConstantExpr(Constant *C, ArrayRef<Constant*> IdxList,
Type *DestTy);
public:
@@ -233,7 +233,7 @@ public:
// behind the scenes to implement ICmp and FCmp constant expressions. This is
// needed in order to store the predicate value for these instructions.
class CompareConstantExpr : public ConstantExpr {
- virtual void anchor();
+ void anchor() override;
void *operator new(size_t, unsigned) LLVM_DELETED_FUNCTION;
public:
// allocate space for exactly two operands
@@ -334,14 +334,10 @@ struct ExprMapKeyType {
this->indices == that.indices;
}
bool operator<(const ExprMapKeyType & that) const {
- if (this->opcode != that.opcode) return this->opcode < that.opcode;
- if (this->operands != that.operands) return this->operands < that.operands;
- if (this->subclassdata != that.subclassdata)
- return this->subclassdata < that.subclassdata;
- if (this->subclassoptionaldata != that.subclassoptionaldata)
- return this->subclassoptionaldata < that.subclassoptionaldata;
- if (this->indices != that.indices) return this->indices < that.indices;
- return false;
+ return std::tie(opcode, operands, subclassdata, subclassoptionaldata,
+ indices) <
+ std::tie(that.opcode, that.operands, that.subclassdata,
+ that.subclassoptionaldata, that.indices);
}
bool operator!=(const ExprMapKeyType& that) const {
@@ -369,17 +365,10 @@ struct InlineAsmKeyType {
this->asm_dialect == that.asm_dialect;
}
bool operator<(const InlineAsmKeyType& that) const {
- if (this->asm_string != that.asm_string)
- return this->asm_string < that.asm_string;
- if (this->constraints != that.constraints)
- return this->constraints < that.constraints;
- if (this->has_side_effects != that.has_side_effects)
- return this->has_side_effects < that.has_side_effects;
- if (this->is_align_stack != that.is_align_stack)
- return this->is_align_stack < that.is_align_stack;
- if (this->asm_dialect != that.asm_dialect)
- return this->asm_dialect < that.asm_dialect;
- return false;
+ return std::tie(asm_string, constraints, has_side_effects, is_align_stack,
+ asm_dialect) <
+ std::tie(that.asm_string, that.constraints, that.has_side_effects,
+ that.is_align_stack, that.asm_dialect);
}
bool operator!=(const InlineAsmKeyType& that) const {
diff --git a/lib/IR/Core.cpp b/lib/IR/Core.cpp
index c70f459..f52f466 100644
--- a/lib/IR/Core.cpp
+++ b/lib/IR/Core.cpp
@@ -15,24 +15,24 @@
#include "llvm-c/Core.h"
#include "llvm/Bitcode/ReaderWriter.h"
#include "llvm/IR/Attributes.h"
+#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/InlineAsm.h"
#include "llvm/IR/IntrinsicInst.h"
-#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/PassManager.h"
-#include "llvm/Support/CallSite.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/Threading.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/system_error.h"
-#include "llvm/Support/Threading.h"
#include <cassert>
#include <cstdlib>
#include <cstring>
@@ -40,12 +40,11 @@
using namespace llvm;
void llvm::initializeCore(PassRegistry &Registry) {
- initializeDominatorTreePass(Registry);
- initializePrintModulePassPass(Registry);
- initializePrintFunctionPassPass(Registry);
+ initializeDominatorTreeWrapperPassPass(Registry);
+ initializePrintModulePassWrapperPass(Registry);
+ initializePrintFunctionPassWrapperPass(Registry);
initializePrintBasicBlockPassPass(Registry);
- initializeVerifierPass(Registry);
- initializePreVerifierPass(Registry);
+ initializeVerifierLegacyPassPass(Registry);
}
void LLVMInitializeCore(LLVMPassRegistryRef R) {
@@ -108,7 +107,7 @@ void LLVMDisposeModule(LLVMModuleRef M) {
/*--.. Data layout .........................................................--*/
const char * LLVMGetDataLayout(LLVMModuleRef M) {
- return unwrap(M)->getDataLayout().c_str();
+ return unwrap(M)->getDataLayoutStr().c_str();
}
void LLVMSetDataLayout(LLVMModuleRef M, const char *Triple) {
@@ -131,7 +130,7 @@ void LLVMDumpModule(LLVMModuleRef M) {
LLVMBool LLVMPrintModuleToFile(LLVMModuleRef M, const char *Filename,
char **ErrorMessage) {
std::string error;
- raw_fd_ostream dest(Filename, error);
+ raw_fd_ostream dest(Filename, error, sys::fs::F_Text);
if (!error.empty()) {
*ErrorMessage = strdup(error.c_str());
return true;
@@ -175,7 +174,6 @@ LLVMContextRef LLVMGetModuleContext(LLVMModuleRef M) {
LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty) {
switch (unwrap(Ty)->getTypeID()) {
- default: llvm_unreachable("Unhandled TypeID.");
case Type::VoidTyID:
return LLVMVoidTypeKind;
case Type::HalfTyID:
@@ -209,6 +207,7 @@ LLVMTypeKind LLVMGetTypeKind(LLVMTypeRef Ty) {
case Type::X86_MMXTyID:
return LLVMX86_MMXTypeKind;
}
+ llvm_unreachable("Unhandled TypeID.");
}
LLVMBool LLVMTypeIsSized(LLVMTypeRef Ty)
@@ -515,7 +514,7 @@ LLVMUseRef LLVMGetFirstUse(LLVMValueRef Val) {
Value::use_iterator I = V->use_begin();
if (I == V->use_end())
return 0;
- return wrap(&(I.getUse()));
+ return wrap(&*I);
}
LLVMUseRef LLVMGetNextUse(LLVMUseRef U) {
@@ -1160,14 +1159,6 @@ LLVMLinkage LLVMGetLinkage(LLVMValueRef Global) {
return LLVMInternalLinkage;
case GlobalValue::PrivateLinkage:
return LLVMPrivateLinkage;
- case GlobalValue::LinkerPrivateLinkage:
- return LLVMLinkerPrivateLinkage;
- case GlobalValue::LinkerPrivateWeakLinkage:
- return LLVMLinkerPrivateWeakLinkage;
- case GlobalValue::DLLImportLinkage:
- return LLVMDLLImportLinkage;
- case GlobalValue::DLLExportLinkage:
- return LLVMDLLExportLinkage;
case GlobalValue::ExternalWeakLinkage:
return LLVMExternalWeakLinkage;
case GlobalValue::CommonLinkage:
@@ -1213,16 +1204,18 @@ void LLVMSetLinkage(LLVMValueRef Global, LLVMLinkage Linkage) {
GV->setLinkage(GlobalValue::PrivateLinkage);
break;
case LLVMLinkerPrivateLinkage:
- GV->setLinkage(GlobalValue::LinkerPrivateLinkage);
+ GV->setLinkage(GlobalValue::PrivateLinkage);
break;
case LLVMLinkerPrivateWeakLinkage:
- GV->setLinkage(GlobalValue::LinkerPrivateWeakLinkage);
+ GV->setLinkage(GlobalValue::PrivateLinkage);
break;
case LLVMDLLImportLinkage:
- GV->setLinkage(GlobalValue::DLLImportLinkage);
+ DEBUG(errs()
+ << "LLVMSetLinkage(): LLVMDLLImportLinkage is no longer supported.");
break;
case LLVMDLLExportLinkage:
- GV->setLinkage(GlobalValue::DLLExportLinkage);
+ DEBUG(errs()
+ << "LLVMSetLinkage(): LLVMDLLExportLinkage is no longer supported.");
break;
case LLVMExternalWeakLinkage:
GV->setLinkage(GlobalValue::ExternalWeakLinkage);
@@ -1255,30 +1248,54 @@ void LLVMSetVisibility(LLVMValueRef Global, LLVMVisibility Viz) {
->setVisibility(static_cast<GlobalValue::VisibilityTypes>(Viz));
}
+LLVMDLLStorageClass LLVMGetDLLStorageClass(LLVMValueRef Global) {
+ return static_cast<LLVMDLLStorageClass>(
+ unwrap<GlobalValue>(Global)->getDLLStorageClass());
+}
+
+void LLVMSetDLLStorageClass(LLVMValueRef Global, LLVMDLLStorageClass Class) {
+ unwrap<GlobalValue>(Global)->setDLLStorageClass(
+ static_cast<GlobalValue::DLLStorageClassTypes>(Class));
+}
+
+LLVMBool LLVMHasUnnamedAddr(LLVMValueRef Global) {
+ return unwrap<GlobalValue>(Global)->hasUnnamedAddr();
+}
+
+void LLVMSetUnnamedAddr(LLVMValueRef Global, LLVMBool HasUnnamedAddr) {
+ unwrap<GlobalValue>(Global)->setUnnamedAddr(HasUnnamedAddr);
+}
+
/*--.. 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 (AllocaInst *AI = dyn_cast<AllocaInst>(P))
+ return AI->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");
+ llvm_unreachable(
+ "only GlobalValue, AllocaInst, LoadInst and StoreInst have alignment");
}
void LLVMSetAlignment(LLVMValueRef V, unsigned Bytes) {
Value *P = unwrap<Value>(V);
if (GlobalValue *GV = dyn_cast<GlobalValue>(P))
GV->setAlignment(Bytes);
+ else if (AllocaInst *AI = dyn_cast<AllocaInst>(P))
+ AI->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");
+ llvm_unreachable(
+ "only GlobalValue, AllocaInst, LoadInst and StoreInst have alignment");
}
/*--.. Operations on global variables ......................................--*/
@@ -2219,6 +2236,29 @@ LLVMValueRef LLVMBuildStore(LLVMBuilderRef B, LLVMValueRef Val,
return wrap(unwrap(B)->CreateStore(unwrap(Val), unwrap(PointerVal)));
}
+static AtomicOrdering mapFromLLVMOrdering(LLVMAtomicOrdering Ordering) {
+ switch (Ordering) {
+ case LLVMAtomicOrderingNotAtomic: return NotAtomic;
+ case LLVMAtomicOrderingUnordered: return Unordered;
+ case LLVMAtomicOrderingMonotonic: return Monotonic;
+ case LLVMAtomicOrderingAcquire: return Acquire;
+ case LLVMAtomicOrderingRelease: return Release;
+ case LLVMAtomicOrderingAcquireRelease: return AcquireRelease;
+ case LLVMAtomicOrderingSequentiallyConsistent:
+ return SequentiallyConsistent;
+ }
+
+ llvm_unreachable("Invalid LLVMAtomicOrdering value!");
+}
+
+LLVMValueRef LLVMBuildFence(LLVMBuilderRef B, LLVMAtomicOrdering Ordering,
+ LLVMBool isSingleThread, const char *Name) {
+ return wrap(
+ unwrap(B)->CreateFence(mapFromLLVMOrdering(Ordering),
+ isSingleThread ? SingleThread : CrossThread,
+ Name));
+}
+
LLVMValueRef LLVMBuildGEP(LLVMBuilderRef B, LLVMValueRef Pointer,
LLVMValueRef *Indices, unsigned NumIndices,
const char *Name) {
@@ -2476,22 +2516,8 @@ LLVMValueRef LLVMBuildAtomicRMW(LLVMBuilderRef B,LLVMAtomicRMWBinOp op,
case LLVMAtomicRMWBinOpUMax: intop = AtomicRMWInst::UMax; break;
case LLVMAtomicRMWBinOpUMin: intop = AtomicRMWInst::UMin; break;
}
- AtomicOrdering intordering;
- switch (ordering) {
- case LLVMAtomicOrderingNotAtomic: intordering = NotAtomic; break;
- case LLVMAtomicOrderingUnordered: intordering = Unordered; break;
- case LLVMAtomicOrderingMonotonic: intordering = Monotonic; break;
- case LLVMAtomicOrderingAcquire: intordering = Acquire; break;
- case LLVMAtomicOrderingRelease: intordering = Release; break;
- case LLVMAtomicOrderingAcquireRelease:
- intordering = AcquireRelease;
- break;
- case LLVMAtomicOrderingSequentiallyConsistent:
- intordering = SequentiallyConsistent;
- break;
- }
return wrap(unwrap(B)->CreateAtomicRMW(intop, unwrap(PTR), unwrap(Val),
- intordering, singleThread ? SingleThread : CrossThread));
+ mapFromLLVMOrdering(ordering), singleThread ? SingleThread : CrossThread));
}
@@ -2514,10 +2540,10 @@ LLVMBool LLVMCreateMemoryBufferWithContentsOfFile(
LLVMMemoryBufferRef *OutMemBuf,
char **OutMessage) {
- OwningPtr<MemoryBuffer> MB;
+ std::unique_ptr<MemoryBuffer> MB;
error_code ec;
if (!(ec = MemoryBuffer::getFile(Path, MB))) {
- *OutMemBuf = wrap(MB.take());
+ *OutMemBuf = wrap(MB.release());
return 0;
}
@@ -2527,10 +2553,10 @@ LLVMBool LLVMCreateMemoryBufferWithContentsOfFile(
LLVMBool LLVMCreateMemoryBufferWithSTDIN(LLVMMemoryBufferRef *OutMemBuf,
char **OutMessage) {
- OwningPtr<MemoryBuffer> MB;
+ std::unique_ptr<MemoryBuffer> MB;
error_code ec;
if (!(ec = MemoryBuffer::getSTDIN(MB))) {
- *OutMemBuf = wrap(MB.take());
+ *OutMemBuf = wrap(MB.release());
return 0;
}
diff --git a/lib/IR/DIBuilder.cpp b/lib/IR/DIBuilder.cpp
index c4a9f41..1ea381a 100644
--- a/lib/IR/DIBuilder.cpp
+++ b/lib/IR/DIBuilder.cpp
@@ -11,10 +11,10 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DIBuilder.h"
+#include "llvm/IR/DIBuilder.h"
#include "llvm/ADT/STLExtras.h"
-#include "llvm/DebugInfo.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Debug.h"
@@ -69,7 +69,10 @@ void DIBuilder::finalize() {
DIArray GVs = getOrCreateArray(AllGVs);
DIType(TempGVs).replaceAllUsesWith(GVs);
- DIArray IMs = getOrCreateArray(AllImportedModules);
+ SmallVector<Value *, 16> RetainValuesI;
+ for (unsigned I = 0, E = AllImportedModules.size(); I < E; I++)
+ RetainValuesI.push_back(AllImportedModules[I]);
+ DIArray IMs = getOrCreateArray(RetainValuesI);
DIType(TempImportedModules).replaceAllUsesWith(IMs);
}
@@ -97,7 +100,9 @@ DICompileUnit DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename,
StringRef Directory,
StringRef Producer, bool isOptimized,
StringRef Flags, unsigned RunTimeVer,
- StringRef SplitName) {
+ StringRef SplitName,
+ DebugEmissionKind Kind) {
+
assert(((Lang <= dwarf::DW_LANG_Python && Lang >= dwarf::DW_LANG_C89) ||
(Lang <= dwarf::DW_LANG_hi_user && Lang >= dwarf::DW_LANG_lo_user)) &&
"Invalid Language tag");
@@ -127,7 +132,8 @@ DICompileUnit DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename,
TempSubprograms,
TempGVs,
TempImportedModules,
- MDString::get(VMContext, SplitName)
+ MDString::get(VMContext, SplitName),
+ ConstantInt::get(Type::getInt32Ty(VMContext), Kind)
};
MDNode *CUNode = MDNode::get(VMContext, Elts);
@@ -142,7 +148,7 @@ DICompileUnit DIBuilder::createCompileUnit(unsigned Lang, StringRef Filename,
static DIImportedEntity
createImportedModule(LLVMContext &C, DIScope Context, DIDescriptor NS,
unsigned Line, StringRef Name,
- SmallVectorImpl<Value *> &AllImportedModules) {
+ SmallVectorImpl<TrackingVH<MDNode> > &AllImportedModules) {
const MDNode *R;
if (Name.empty()) {
Value *Elts[] = {
@@ -164,7 +170,7 @@ createImportedModule(LLVMContext &C, DIScope Context, DIDescriptor NS,
}
DIImportedEntity M(R);
assert(M.Verify() && "Imported module should be valid");
- AllImportedModules.push_back(M);
+ AllImportedModules.push_back(TrackingVH<MDNode>(M));
return M;
}
@@ -184,17 +190,17 @@ DIImportedEntity DIBuilder::createImportedModule(DIScope Context,
}
DIImportedEntity DIBuilder::createImportedDeclaration(DIScope Context,
- DIDescriptor Decl,
+ DIScope Decl,
unsigned Line) {
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_imported_declaration),
Context,
- Decl,
+ Decl.getRef(),
ConstantInt::get(Type::getInt32Ty(VMContext), Line),
};
DIImportedEntity M(MDNode::get(VMContext, Elts));
assert(M.Verify() && "Imported module should be valid");
- AllImportedModules.push_back(M);
+ AllImportedModules.push_back(TrackingVH<MDNode>(M));
return M;
}
@@ -706,7 +712,8 @@ DICompositeType DIBuilder::createUnionType(DIDescriptor Scope, StringRef Name,
/// createSubroutineType - Create subroutine type.
DICompositeType DIBuilder::createSubroutineType(DIFile File,
- DIArray ParameterTypes) {
+ DIArray ParameterTypes,
+ unsigned Flags) {
// TAG_subroutine_type is encoded in DICompositeType format.
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_subroutine_type),
@@ -717,7 +724,7 @@ DICompositeType DIBuilder::createSubroutineType(DIFile File,
ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Size
ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Align
ConstantInt::get(Type::getInt64Ty(VMContext), 0), // Offset
- ConstantInt::get(Type::getInt32Ty(VMContext), 0), // Flags
+ ConstantInt::get(Type::getInt32Ty(VMContext), Flags), // Flags
NULL,
ParameterTypes,
ConstantInt::get(Type::getInt32Ty(VMContext), 0),
@@ -901,10 +908,6 @@ DIBuilder::createForwardDecl(unsigned Tag, StringRef Name, DIDescriptor Scope,
/// getOrCreateArray - Get a DIArray, create one if required.
DIArray DIBuilder::getOrCreateArray(ArrayRef<Value *> Elements) {
- if (Elements.empty()) {
- Value *Null = Constant::getNullValue(Type::getInt32Ty(VMContext));
- return DIArray(MDNode::get(VMContext, Null));
- }
return DIArray(MDNode::get(VMContext, Elements));
}
@@ -924,7 +927,7 @@ DISubrange DIBuilder::getOrCreateSubrange(int64_t Lo, int64_t Count) {
DIGlobalVariable DIBuilder::createGlobalVariable(StringRef Name,
StringRef LinkageName,
DIFile F, unsigned LineNumber,
- DIType Ty, bool isLocalToUnit,
+ DITypeRef Ty, bool isLocalToUnit,
Value *Val) {
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_variable),
@@ -948,7 +951,8 @@ DIGlobalVariable DIBuilder::createGlobalVariable(StringRef Name,
/// \brief Create a new descriptor for the specified global.
DIGlobalVariable DIBuilder::createGlobalVariable(StringRef Name, DIFile F,
- unsigned LineNumber, DIType Ty,
+ unsigned LineNumber,
+ DITypeRef Ty,
bool isLocalToUnit,
Value *Val) {
return createGlobalVariable(Name, Name, F, LineNumber, Ty, isLocalToUnit,
@@ -961,7 +965,8 @@ DIGlobalVariable DIBuilder::createStaticVariable(DIDescriptor Context,
StringRef Name,
StringRef LinkageName,
DIFile F, unsigned LineNumber,
- DIType Ty, bool isLocalToUnit,
+ DITypeRef Ty,
+ bool isLocalToUnit,
Value *Val, MDNode *Decl) {
Value *Elts[] = {
GetTagConstant(VMContext, dwarf::DW_TAG_variable),
@@ -986,14 +991,12 @@ DIGlobalVariable DIBuilder::createStaticVariable(DIDescriptor Context,
/// createVariable - Create a new descriptor for the specified variable.
DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope,
StringRef Name, DIFile File,
- unsigned LineNo, DIType Ty,
+ unsigned LineNo, DITypeRef Ty,
bool AlwaysPreserve, unsigned Flags,
unsigned ArgNo) {
DIDescriptor Context(getNonCompileUnitScope(Scope));
assert((!Context || Context.isScope()) &&
"createLocalVariable should be called with a valid Context");
- assert(Ty.isType() &&
- "createLocalVariable should be called with a valid type");
Value *Elts[] = {
GetTagConstant(VMContext, Tag),
getNonCompileUnitScope(Scope),
@@ -1024,7 +1027,8 @@ DIVariable DIBuilder::createLocalVariable(unsigned Tag, DIDescriptor Scope,
DIVariable DIBuilder::createComplexVariable(unsigned Tag, DIDescriptor Scope,
StringRef Name, DIFile F,
unsigned LineNo,
- DIType Ty, ArrayRef<Value *> Addr,
+ DITypeRef Ty,
+ ArrayRef<Value *> Addr,
unsigned ArgNo) {
SmallVector<Value *, 15> Elts;
Elts.push_back(GetTagConstant(VMContext, Tag));
@@ -1098,7 +1102,8 @@ DISubprogram DIBuilder::createFunction(DIDescriptor Context, StringRef Name,
if (isDefinition)
AllSubprograms.push_back(Node);
DISubprogram S(Node);
- assert(S.isSubprogram() && "createFunction should return a valid DISubprogram");
+ assert(S.isSubprogram() &&
+ "createFunction should return a valid DISubprogram");
return S;
}
@@ -1182,7 +1187,8 @@ DILexicalBlockFile DIBuilder::createLexicalBlockFile(DIDescriptor Scope,
}
DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File,
- unsigned Line, unsigned Col) {
+ unsigned Line, unsigned Col,
+ unsigned Discriminator) {
// Defeat MDNode uniquing for lexical blocks by using unique id.
static unsigned int unique_id = 0;
Value *Elts[] = {
@@ -1191,6 +1197,7 @@ DILexicalBlock DIBuilder::createLexicalBlock(DIDescriptor Scope, DIFile File,
getNonCompileUnitScope(Scope),
ConstantInt::get(Type::getInt32Ty(VMContext), Line),
ConstantInt::get(Type::getInt32Ty(VMContext), Col),
+ ConstantInt::get(Type::getInt32Ty(VMContext), Discriminator),
ConstantInt::get(Type::getInt32Ty(VMContext), unique_id++)
};
DILexicalBlock R(MDNode::get(VMContext, Elts));
diff --git a/lib/IR/DataLayout.cpp b/lib/IR/DataLayout.cpp
index 6bdc09e..6c18387 100644
--- a/lib/IR/DataLayout.cpp
+++ b/lib/IR/DataLayout.cpp
@@ -18,11 +18,13 @@
#include "llvm/IR/DataLayout.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/GetElementPtrTypeIterator.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/Mutex.h"
@@ -33,9 +35,8 @@ using namespace llvm;
// Handle the Pass registration stuff necessary to use DataLayout's.
-// Register the default SparcV9 implementation...
-INITIALIZE_PASS(DataLayout, "datalayout", "Data Layout", false, true)
-char DataLayout::ID = 0;
+INITIALIZE_PASS(DataLayoutPass, "datalayout", "Data Layout", false, true)
+char DataLayoutPass::ID = 0;
//===----------------------------------------------------------------------===//
// Support for StructLayout
@@ -118,21 +119,21 @@ LayoutAlignElem::operator==(const LayoutAlignElem &rhs) const {
}
const LayoutAlignElem
-DataLayout::InvalidAlignmentElem = LayoutAlignElem::get(INVALID_ALIGN, 0, 0, 0);
+DataLayout::InvalidAlignmentElem = { INVALID_ALIGN, 0, 0, 0 };
//===----------------------------------------------------------------------===//
// PointerAlignElem, PointerAlign support
//===----------------------------------------------------------------------===//
PointerAlignElem
-PointerAlignElem::get(uint32_t addr_space, unsigned abi_align,
- unsigned pref_align, uint32_t bit_width) {
- assert(abi_align <= pref_align && "Preferred alignment worse than ABI!");
+PointerAlignElem::get(uint32_t AddressSpace, unsigned ABIAlign,
+ unsigned PrefAlign, uint32_t TypeByteWidth) {
+ assert(ABIAlign <= PrefAlign && "Preferred alignment worse than ABI!");
PointerAlignElem retval;
- retval.AddressSpace = addr_space;
- retval.ABIAlign = abi_align;
- retval.PrefAlign = pref_align;
- retval.TypeBitWidth = bit_width;
+ retval.AddressSpace = AddressSpace;
+ retval.ABIAlign = ABIAlign;
+ retval.PrefAlign = PrefAlign;
+ retval.TypeByteWidth = TypeByteWidth;
return retval;
}
@@ -141,36 +142,52 @@ PointerAlignElem::operator==(const PointerAlignElem &rhs) const {
return (ABIAlign == rhs.ABIAlign
&& AddressSpace == rhs.AddressSpace
&& PrefAlign == rhs.PrefAlign
- && TypeBitWidth == rhs.TypeBitWidth);
+ && TypeByteWidth == rhs.TypeByteWidth);
}
const PointerAlignElem
-DataLayout::InvalidPointerElem = PointerAlignElem::get(~0U, 0U, 0U, 0U);
+DataLayout::InvalidPointerElem = { 0U, 0U, 0U, ~0U };
//===----------------------------------------------------------------------===//
// DataLayout Class Implementation
//===----------------------------------------------------------------------===//
-void DataLayout::init(StringRef Desc) {
- initializeDataLayoutPass(*PassRegistry::getPassRegistry());
+const char *DataLayout::getManglingComponent(const Triple &T) {
+ if (T.isOSBinFormatMachO())
+ return "-m:o";
+ if (T.isOSWindows() && T.getArch() == Triple::x86 && T.isOSBinFormatCOFF())
+ return "-m:w";
+ return "-m:e";
+}
+
+static const LayoutAlignElem DefaultAlignments[] = {
+ { INTEGER_ALIGN, 1, 1, 1 }, // i1
+ { INTEGER_ALIGN, 8, 1, 1 }, // i8
+ { INTEGER_ALIGN, 16, 2, 2 }, // i16
+ { INTEGER_ALIGN, 32, 4, 4 }, // i32
+ { INTEGER_ALIGN, 64, 4, 8 }, // i64
+ { FLOAT_ALIGN, 16, 2, 2 }, // half
+ { FLOAT_ALIGN, 32, 4, 4 }, // float
+ { FLOAT_ALIGN, 64, 8, 8 }, // double
+ { FLOAT_ALIGN, 128, 16, 16 }, // ppcf128, quad, ...
+ { VECTOR_ALIGN, 64, 8, 8 }, // v2i32, v1i64, ...
+ { VECTOR_ALIGN, 128, 16, 16 }, // v16i8, v8i16, v4i32, ...
+ { AGGREGATE_ALIGN, 0, 0, 8 } // struct
+};
+
+void DataLayout::reset(StringRef Desc) {
+ clear();
LayoutMap = 0;
LittleEndian = false;
StackNaturalAlign = 0;
+ ManglingMode = MM_None;
// Default alignments
- setAlignment(INTEGER_ALIGN, 1, 1, 1); // i1
- setAlignment(INTEGER_ALIGN, 1, 1, 8); // i8
- setAlignment(INTEGER_ALIGN, 2, 2, 16); // i16
- setAlignment(INTEGER_ALIGN, 4, 4, 32); // i32
- setAlignment(INTEGER_ALIGN, 4, 8, 64); // i64
- setAlignment(FLOAT_ALIGN, 2, 2, 16); // half
- setAlignment(FLOAT_ALIGN, 4, 4, 32); // float
- setAlignment(FLOAT_ALIGN, 8, 8, 64); // double
- setAlignment(FLOAT_ALIGN, 16, 16, 128); // ppcf128, quad, ...
- setAlignment(VECTOR_ALIGN, 8, 8, 64); // v2i32, v1i64, ...
- setAlignment(VECTOR_ALIGN, 16, 16, 128); // v16i8, v8i16, v4i32, ...
- setAlignment(AGGREGATE_ALIGN, 0, 8, 0); // struct
+ for (const LayoutAlignElem &E : DefaultAlignments) {
+ setAlignment((AlignTypeEnum)E.AlignType, E.ABIAlign, E.PrefAlign,
+ E.TypeBitWidth);
+ }
setPointerAlignment(0, 8, 8, 8);
parseSpecifier(Desc);
@@ -185,11 +202,12 @@ static std::pair<StringRef, StringRef> split(StringRef Str, char Separator) {
return Split;
}
-/// Get an unsinged integer, including error checks.
+/// Get an unsigned integer, including error checks.
static unsigned getInt(StringRef R) {
unsigned Result;
bool error = R.getAsInteger(10, Result); (void)error;
- assert(!error && "not a number, or does not fit in an unsigned int");
+ if (error)
+ report_fatal_error("not a number, or does not fit in an unsigned int");
return Result;
}
@@ -216,6 +234,10 @@ void DataLayout::parseSpecifier(StringRef Desc) {
Tok = Tok.substr(1);
switch (Specifier) {
+ case 's':
+ // Ignored for backward compatibility.
+ // FIXME: remove this on LLVM 4.0.
+ break;
case 'E':
LittleEndian = false;
break;
@@ -250,8 +272,7 @@ void DataLayout::parseSpecifier(StringRef Desc) {
case 'i':
case 'v':
case 'f':
- case 'a':
- case 's': {
+ case 'a': {
AlignTypeEnum AlignType;
switch (Specifier) {
default:
@@ -259,12 +280,14 @@ void DataLayout::parseSpecifier(StringRef Desc) {
case 'v': AlignType = VECTOR_ALIGN; break;
case 'f': AlignType = FLOAT_ALIGN; break;
case 'a': AlignType = AGGREGATE_ALIGN; break;
- case 's': AlignType = STACK_ALIGN; break;
}
// Bit size.
unsigned Size = Tok.empty() ? 0 : getInt(Tok);
+ assert((AlignType != AGGREGATE_ALIGN || Size == 0) &&
+ "These specifications don't have a size");
+
// ABI alignment.
Split = split(Rest, ':');
unsigned ABIAlign = inBytes(getInt(Tok));
@@ -294,6 +317,26 @@ void DataLayout::parseSpecifier(StringRef Desc) {
StackNaturalAlign = inBytes(getInt(Tok));
break;
}
+ case 'm':
+ assert(Tok.empty());
+ assert(Rest.size() == 1);
+ switch(Rest[0]) {
+ default:
+ llvm_unreachable("Unknown mangling in datalayout string");
+ case 'e':
+ ManglingMode = MM_ELF;
+ break;
+ case 'o':
+ ManglingMode = MM_MachO;
+ break;
+ case 'm':
+ ManglingMode = MM_Mips;
+ break;
+ case 'w':
+ ManglingMode = MM_WINCOFF;
+ break;
+ }
+ break;
default:
llvm_unreachable("Unknown specifier in datalayout string");
break;
@@ -301,18 +344,22 @@ void DataLayout::parseSpecifier(StringRef Desc) {
}
}
-/// Default ctor.
-///
-/// @note This has to exist, because this is a pass, but it should never be
-/// used.
-DataLayout::DataLayout() : ImmutablePass(ID) {
- report_fatal_error("Bad DataLayout ctor used. "
- "Tool did not specify a DataLayout to use?");
+DataLayout::DataLayout(const Module *M) : LayoutMap(0) {
+ const DataLayout *Other = M->getDataLayout();
+ if (Other)
+ *this = *Other;
+ else
+ reset("");
}
-DataLayout::DataLayout(const Module *M)
- : ImmutablePass(ID) {
- init(M->getDataLayout());
+bool DataLayout::operator==(const DataLayout &Other) const {
+ bool Ret = LittleEndian == Other.LittleEndian &&
+ StackNaturalAlign == Other.StackNaturalAlign &&
+ ManglingMode == Other.ManglingMode &&
+ LegalIntWidths == Other.LegalIntWidths &&
+ Alignments == Other.Alignments && Pointers == Pointers;
+ assert(Ret == (getStringRepresentation() == Other.getStringRepresentation()));
+ return Ret;
}
void
@@ -321,12 +368,12 @@ DataLayout::setAlignment(AlignTypeEnum align_type, unsigned abi_align,
assert(abi_align <= pref_align && "Preferred alignment worse than ABI!");
assert(pref_align < (1 << 16) && "Alignment doesn't fit in bitfield");
assert(bit_width < (1 << 24) && "Bit width doesn't fit in bitfield");
- for (unsigned i = 0, e = Alignments.size(); i != e; ++i) {
- if (Alignments[i].AlignType == (unsigned)align_type &&
- Alignments[i].TypeBitWidth == bit_width) {
+ for (LayoutAlignElem &Elem : Alignments) {
+ if (Elem.AlignType == (unsigned)align_type &&
+ Elem.TypeBitWidth == bit_width) {
// Update the abi, preferred alignments.
- Alignments[i].ABIAlign = abi_align;
- Alignments[i].PrefAlign = pref_align;
+ Elem.ABIAlign = abi_align;
+ Elem.PrefAlign = pref_align;
return;
}
}
@@ -335,18 +382,26 @@ DataLayout::setAlignment(AlignTypeEnum align_type, unsigned abi_align,
pref_align, bit_width));
}
-void
-DataLayout::setPointerAlignment(uint32_t addr_space, unsigned abi_align,
- unsigned pref_align, uint32_t bit_width) {
- assert(abi_align <= pref_align && "Preferred alignment worse than ABI!");
- DenseMap<unsigned,PointerAlignElem>::iterator val = Pointers.find(addr_space);
- if (val == Pointers.end()) {
- Pointers[addr_space] = PointerAlignElem::get(addr_space,
- abi_align, pref_align, bit_width);
+DataLayout::PointersTy::iterator
+DataLayout::findPointerLowerBound(uint32_t AddressSpace) {
+ return std::lower_bound(Pointers.begin(), Pointers.end(), AddressSpace,
+ [](const PointerAlignElem &A, uint32_t AddressSpace) {
+ return A.AddressSpace < AddressSpace;
+ });
+}
+
+void DataLayout::setPointerAlignment(uint32_t AddrSpace, unsigned ABIAlign,
+ unsigned PrefAlign,
+ uint32_t TypeByteWidth) {
+ assert(ABIAlign <= PrefAlign && "Preferred alignment worse than ABI!");
+ PointersTy::iterator I = findPointerLowerBound(AddrSpace);
+ if (I == Pointers.end() || I->AddressSpace != AddrSpace) {
+ Pointers.insert(I, PointerAlignElem::get(AddrSpace, ABIAlign, PrefAlign,
+ TypeByteWidth));
} else {
- val->second.ABIAlign = abi_align;
- val->second.PrefAlign = pref_align;
- val->second.TypeBitWidth = bit_width;
+ I->ABIAlign = ABIAlign;
+ I->PrefAlign = PrefAlign;
+ I->TypeByteWidth = TypeByteWidth;
}
}
@@ -412,11 +467,10 @@ class StructLayoutMap {
LayoutInfoTy LayoutInfo;
public:
- virtual ~StructLayoutMap() {
+ ~StructLayoutMap() {
// Remove any layouts.
- for (LayoutInfoTy::iterator I = LayoutInfo.begin(), E = LayoutInfo.end();
- I != E; ++I) {
- StructLayout *Value = I->second;
+ for (const auto &I : LayoutInfo) {
+ StructLayout *Value = I.second;
Value->~StructLayout();
free(Value);
}
@@ -425,21 +479,20 @@ public:
StructLayout *&operator[](StructType *STy) {
return LayoutInfo[STy];
}
-
- // for debugging...
- virtual void dump() const {}
};
} // end anonymous namespace
-DataLayout::~DataLayout() {
- delete static_cast<StructLayoutMap*>(LayoutMap);
+void DataLayout::clear() {
+ LegalIntWidths.clear();
+ Alignments.clear();
+ Pointers.clear();
+ delete static_cast<StructLayoutMap *>(LayoutMap);
+ LayoutMap = 0;
}
-bool DataLayout::doFinalization(Module &M) {
- delete static_cast<StructLayoutMap*>(LayoutMap);
- LayoutMap = 0;
- return false;
+DataLayout::~DataLayout() {
+ clear();
}
const StructLayout *DataLayout::getStructLayout(StructType *Ty) const {
@@ -470,32 +523,49 @@ std::string DataLayout::getStringRepresentation() const {
raw_string_ostream OS(Result);
OS << (LittleEndian ? "e" : "E");
- SmallVector<unsigned, 8> addrSpaces;
- // Lets get all of the known address spaces and sort them
- // into increasing order so that we can emit the string
- // in a cleaner format.
- for (DenseMap<unsigned, PointerAlignElem>::const_iterator
- pib = Pointers.begin(), pie = Pointers.end();
- pib != pie; ++pib) {
- addrSpaces.push_back(pib->first);
+
+ switch (ManglingMode) {
+ case MM_None:
+ break;
+ case MM_ELF:
+ OS << "-m:e";
+ break;
+ case MM_MachO:
+ OS << "-m:o";
+ break;
+ case MM_WINCOFF:
+ OS << "-m:w";
+ break;
+ case MM_Mips:
+ OS << "-m:m";
+ break;
}
- std::sort(addrSpaces.begin(), addrSpaces.end());
- for (SmallVectorImpl<unsigned>::iterator asb = addrSpaces.begin(),
- ase = addrSpaces.end(); asb != ase; ++asb) {
- const PointerAlignElem &PI = Pointers.find(*asb)->second;
+
+ for (const PointerAlignElem &PI : Pointers) {
+ // Skip default.
+ if (PI.AddressSpace == 0 && PI.ABIAlign == 8 && PI.PrefAlign == 8 &&
+ PI.TypeByteWidth == 8)
+ continue;
+
OS << "-p";
if (PI.AddressSpace) {
OS << PI.AddressSpace;
}
- OS << ":" << PI.TypeBitWidth*8 << ':' << PI.ABIAlign*8
- << ':' << PI.PrefAlign*8;
+ OS << ":" << PI.TypeByteWidth*8 << ':' << PI.ABIAlign*8;
+ if (PI.PrefAlign != PI.ABIAlign)
+ OS << ':' << PI.PrefAlign*8;
}
- OS << "-S" << StackNaturalAlign*8;
- for (unsigned i = 0, e = Alignments.size(); i != e; ++i) {
- const LayoutAlignElem &AI = Alignments[i];
- OS << '-' << (char)AI.AlignType << AI.TypeBitWidth << ':'
- << AI.ABIAlign*8 << ':' << AI.PrefAlign*8;
+ for (const LayoutAlignElem &AI : Alignments) {
+ if (std::find(std::begin(DefaultAlignments), std::end(DefaultAlignments),
+ AI) != std::end(DefaultAlignments))
+ continue;
+ OS << '-' << (char)AI.AlignType;
+ if (AI.TypeBitWidth)
+ OS << AI.TypeBitWidth;
+ OS << ':' << AI.ABIAlign*8;
+ if (AI.ABIAlign != AI.PrefAlign)
+ OS << ':' << AI.PrefAlign*8;
}
if (!LegalIntWidths.empty()) {
@@ -504,9 +574,40 @@ std::string DataLayout::getStringRepresentation() const {
for (unsigned i = 1, e = LegalIntWidths.size(); i != e; ++i)
OS << ':' << (unsigned)LegalIntWidths[i];
}
+
+ if (StackNaturalAlign)
+ OS << "-S" << StackNaturalAlign*8;
+
return OS.str();
}
+unsigned DataLayout::getPointerABIAlignment(unsigned AS) const {
+ PointersTy::const_iterator I = findPointerLowerBound(AS);
+ if (I == Pointers.end() || I->AddressSpace != AS) {
+ I = findPointerLowerBound(0);
+ assert(I->AddressSpace == 0);
+ }
+ return I->ABIAlign;
+}
+
+unsigned DataLayout::getPointerPrefAlignment(unsigned AS) const {
+ PointersTy::const_iterator I = findPointerLowerBound(AS);
+ if (I == Pointers.end() || I->AddressSpace != AS) {
+ I = findPointerLowerBound(0);
+ assert(I->AddressSpace == 0);
+ }
+ return I->PrefAlign;
+}
+
+unsigned DataLayout::getPointerSize(unsigned AS) const {
+ PointersTy::const_iterator I = findPointerLowerBound(AS);
+ if (I == Pointers.end() || I->AddressSpace != AS) {
+ I = findPointerLowerBound(0);
+ assert(I->AddressSpace == 0);
+ }
+ return I->TypeByteWidth;
+}
+
unsigned DataLayout::getPointerTypeSizeInBits(Type *Ty) const {
assert(Ty->isPtrOrPtrVectorTy() &&
"This should only be called with a pointer or pointer vector type");
@@ -589,14 +690,6 @@ unsigned DataLayout::getABIIntegerTypeAlignment(unsigned BitWidth) const {
return getAlignmentInfo(INTEGER_ALIGN, BitWidth, true, 0);
}
-unsigned DataLayout::getCallFrameTypeAlignment(Type *Ty) const {
- for (unsigned i = 0, e = Alignments.size(); i != e; ++i)
- if (Alignments[i].AlignType == STACK_ALIGN)
- return Alignments[i].ABIAlign;
-
- return getABITypeAlignment(Ty);
-}
-
unsigned DataLayout::getPrefTypeAlignment(Type *Ty) const {
return getAlignment(Ty, false);
}
@@ -623,17 +716,15 @@ Type *DataLayout::getIntPtrType(Type *Ty) const {
}
Type *DataLayout::getSmallestLegalIntType(LLVMContext &C, unsigned Width) const {
- for (unsigned i = 0, e = (unsigned)LegalIntWidths.size(); i != e; ++i)
- if (Width <= LegalIntWidths[i])
- return Type::getIntNTy(C, LegalIntWidths[i]);
+ for (unsigned LegalIntWidth : LegalIntWidths)
+ if (Width <= LegalIntWidth)
+ return Type::getIntNTy(C, LegalIntWidth);
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;
+ auto Max = std::max_element(LegalIntWidths.begin(), LegalIntWidths.end());
+ return Max != LegalIntWidths.end() ? *Max : 0;
}
uint64_t DataLayout::getIndexedOffset(Type *ptrTy,
@@ -703,3 +794,19 @@ unsigned DataLayout::getPreferredAlignment(const GlobalVariable *GV) const {
unsigned DataLayout::getPreferredAlignmentLog(const GlobalVariable *GV) const {
return Log2_32(getPreferredAlignment(GV));
}
+
+DataLayoutPass::DataLayoutPass() : ImmutablePass(ID), DL("") {
+ report_fatal_error("Bad DataLayoutPass ctor used. Tool did not specify a "
+ "DataLayout to use?");
+}
+
+DataLayoutPass::~DataLayoutPass() {}
+
+DataLayoutPass::DataLayoutPass(const DataLayout &DL)
+ : ImmutablePass(ID), DL(DL) {
+ initializeDataLayoutPassPass(*PassRegistry::getPassRegistry());
+}
+
+DataLayoutPass::DataLayoutPass(const Module *M) : ImmutablePass(ID), DL(M) {
+ initializeDataLayoutPassPass(*PassRegistry::getPassRegistry());
+}
diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp
index 70a756f..c9d68af 100644
--- a/lib/IR/DebugInfo.cpp
+++ b/lib/IR/DebugInfo.cpp
@@ -12,7 +12,8 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/DebugInfo.h"
+#include "llvm/IR/DebugInfo.h"
+#include "LLVMContextImpl.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
@@ -23,9 +24,9 @@
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/Module.h"
+#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Dwarf.h"
-#include "llvm/Support/ValueHandle.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
using namespace llvm::dwarf;
@@ -45,6 +46,7 @@ bool DIDescriptor::Verify() const {
DILexicalBlockFile(DbgNode).Verify() ||
DISubrange(DbgNode).Verify() || DIEnumerator(DbgNode).Verify() ||
DIObjCProperty(DbgNode).Verify() ||
+ DIUnspecifiedParameter(DbgNode).Verify() ||
DITemplateTypeParameter(DbgNode).Verify() ||
DITemplateValueParameter(DbgNode).Verify() ||
DIImportedEntity(DbgNode).Verify());
@@ -381,7 +383,7 @@ bool DICompileUnit::Verify() const {
if (getFilename().empty())
return false;
- return DbgNode->getNumOperands() == 13;
+ return DbgNode->getNumOperands() == 14;
}
/// Verify - Verify that an ObjC property is well formed.
@@ -427,8 +429,10 @@ static bool fieldIsTypeRef(const MDNode *DbgNode, unsigned Elt) {
/// Check if a value can be a ScopeRef.
static bool isScopeRef(const Value *Val) {
return !Val ||
- (isa<MDString>(Val) && !cast<MDString>(Val)->getString().empty()) ||
- (isa<MDNode>(Val) && DIScope(cast<MDNode>(Val)).isScope());
+ (isa<MDString>(Val) && !cast<MDString>(Val)->getString().empty()) ||
+ // Not checking for Val->isScope() here, because it would work
+ // only for lexical scopes and not all subclasses of DIScope.
+ isa<MDNode>(Val);
}
/// Check if a field at position Elt of a MDNode can be a ScopeRef.
@@ -461,14 +465,13 @@ bool DIType::Verify() const {
// DIType is abstract, it should be a BasicType, a DerivedType or
// a CompositeType.
if (isBasicType())
- DIBasicType(DbgNode).Verify();
+ return DIBasicType(DbgNode).Verify();
else if (isCompositeType())
- DICompositeType(DbgNode).Verify();
+ return DICompositeType(DbgNode).Verify();
else if (isDerivedType())
- DIDerivedType(DbgNode).Verify();
+ return DIDerivedType(DbgNode).Verify();
else
return false;
- return true;
}
/// Verify - Verify that a basic type descriptor is well formed.
@@ -505,6 +508,10 @@ bool DICompositeType::Verify() const {
if (!fieldIsMDString(DbgNode, 14))
return false;
+ // A subroutine type can't be both & and &&.
+ if (isLValueReference() && isRValueReference())
+ return false;
+
return DbgNode->getNumOperands() == 15;
}
@@ -521,6 +528,11 @@ bool DISubprogram::Verify() const {
// Containing type @ field 12.
if (!fieldIsTypeRef(DbgNode, 12))
return false;
+
+ // A subprogram can't be both & and &&.
+ if (isLValueReference() && isRValueReference())
+ return false;
+
return DbgNode->getNumOperands() == 20;
}
@@ -531,10 +543,11 @@ bool DIGlobalVariable::Verify() const {
if (getDisplayName().empty())
return false;
- // Make sure context @ field 2 and type @ field 8 are MDNodes.
+ // Make sure context @ field 2 is an MDNode.
if (!fieldIsMDNode(DbgNode, 2))
return false;
- if (!fieldIsMDNode(DbgNode, 8))
+ // Make sure that type @ field 8 is a DITypeRef.
+ if (!fieldIsTypeRef(DbgNode, 8))
return false;
// Make sure StaticDataMemberDeclaration @ field 12 is MDNode.
if (!fieldIsMDNode(DbgNode, 12))
@@ -548,10 +561,11 @@ bool DIVariable::Verify() const {
if (!isVariable())
return false;
- // Make sure context @ field 1 and type @ field 5 are MDNodes.
+ // Make sure context @ field 1 is an MDNode.
if (!fieldIsMDNode(DbgNode, 1))
return false;
- if (!fieldIsMDNode(DbgNode, 5))
+ // Make sure that type @ field 5 is a DITypeRef.
+ if (!fieldIsTypeRef(DbgNode, 5))
return false;
return DbgNode->getNumOperands() >= 8;
}
@@ -591,7 +605,7 @@ bool DISubrange::Verify() const {
/// \brief Verify that the lexical block descriptor is well formed.
bool DILexicalBlock::Verify() const {
- return isLexicalBlock() && DbgNode->getNumOperands() == 6;
+ return isLexicalBlock() && DbgNode->getNumOperands() == 7;
}
/// \brief Verify that the file-scoped lexical block descriptor is well formed.
@@ -599,6 +613,11 @@ bool DILexicalBlockFile::Verify() const {
return isLexicalBlockFile() && DbgNode->getNumOperands() == 3;
}
+/// \brief Verify that an unspecified parameter descriptor is well formed.
+bool DIUnspecifiedParameter::Verify() const {
+ return isUnspecifiedParameter() && DbgNode->getNumOperands() == 1;
+}
+
/// \brief Verify that the template type parameter descriptor is well formed.
bool DITemplateTypeParameter::Verify() const {
return isTemplateTypeParameter() && DbgNode->getNumOperands() == 7;
@@ -658,19 +677,6 @@ void DICompositeType::setTypeArray(DIArray Elements, DIArray 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 {
@@ -817,6 +823,29 @@ DIArray DICompileUnit::getImportedEntities() const {
return DIArray(getNodeField(DbgNode, 11));
}
+/// copyWithNewScope - Return a copy of this location, replacing the
+/// current scope with the given one.
+DILocation DILocation::copyWithNewScope(LLVMContext &Ctx,
+ DILexicalBlock NewScope) {
+ SmallVector<Value *, 10> Elts;
+ assert(Verify());
+ for (unsigned I = 0; I < DbgNode->getNumOperands(); ++I) {
+ if (I != 2)
+ Elts.push_back(DbgNode->getOperand(I));
+ else
+ Elts.push_back(NewScope);
+ }
+ MDNode *NewDIL = MDNode::get(Ctx, Elts);
+ return DILocation(NewDIL);
+}
+
+/// computeNewDiscriminator - Generate a new discriminator value for this
+/// file and line location.
+unsigned DILocation::computeNewDiscriminator(LLVMContext &Ctx) {
+ std::pair<const char *, unsigned> Key(getFilename().data(), getLineNumber());
+ return ++Ctx.pImpl->DiscriminatorTable[Key];
+}
+
/// fixupSubprogramName - Replace contains special characters used
/// in a typical Objective-C names with '.' in a given string.
static void fixupSubprogramName(DISubprogram Fn, SmallVectorImpl<char> &Out) {
@@ -974,7 +1003,7 @@ void DebugInfoFinder::processModule(const Module &M) {
DIGlobalVariable DIG(GVs.getElement(i));
if (addGlobalVariable(DIG)) {
processScope(DIG.getContext());
- processType(DIG.getType());
+ processType(DIG.getType().resolve(TypeIdentifierMap));
}
}
DIArray SPs = CU.getSubprograms();
@@ -989,7 +1018,7 @@ void DebugInfoFinder::processModule(const Module &M) {
DIArray Imports = CU.getImportedEntities();
for (unsigned i = 0, e = Imports.getNumElements(); i != e; ++i) {
DIImportedEntity Import = DIImportedEntity(Imports.getElement(i));
- DIDescriptor Entity = Import.getEntity();
+ DIDescriptor Entity = Import.getEntity().resolve(TypeIdentifierMap);
if (Entity.isType())
processType(DIType(Entity));
else if (Entity.isSubprogram())
@@ -1060,18 +1089,6 @@ void DebugInfoFinder::processScope(DIScope Scope) {
}
}
-/// processLexicalBlock
-void DebugInfoFinder::processLexicalBlock(DILexicalBlock LB) {
- DIScope Context = LB.getContext();
- if (Context.isLexicalBlock())
- return processLexicalBlock(DILexicalBlock(Context));
- else if (Context.isLexicalBlockFile()) {
- DILexicalBlockFile DBF = DILexicalBlockFile(Context);
- return processLexicalBlock(DILexicalBlock(DBF.getScope()));
- } else
- return processSubprogram(DISubprogram(Context));
-}
-
/// processSubprogram - Process DISubprogram.
void DebugInfoFinder::processSubprogram(DISubprogram SP) {
if (!addSubprogram(SP))
@@ -1108,7 +1125,7 @@ void DebugInfoFinder::processDeclare(const Module &M,
if (!NodesSeen.insert(DV))
return;
processScope(DIVariable(N).getContext());
- processType(DIVariable(N).getType());
+ processType(DIVariable(N).getType().resolve(TypeIdentifierMap));
}
void DebugInfoFinder::processValue(const Module &M, const DbgValueInst *DVI) {
@@ -1124,7 +1141,7 @@ void DebugInfoFinder::processValue(const Module &M, const DbgValueInst *DVI) {
if (!NodesSeen.insert(DV))
return;
processScope(DIVariable(N).getContext());
- processType(DIVariable(N).getType());
+ processType(DIVariable(N).getType().resolve(TypeIdentifierMap));
}
/// addType - Add type into Tys.
@@ -1298,6 +1315,12 @@ void DIType::printInternal(raw_ostream &OS) const {
OS << " [vector]";
if (isStaticMember())
OS << " [static]";
+
+ if (isLValueReference())
+ OS << " [reference]";
+
+ if (isRValueReference())
+ OS << " [rvalue reference]";
}
void DIDerivedType::printInternal(raw_ostream &OS) const {
@@ -1337,6 +1360,12 @@ void DISubprogram::printInternal(raw_ostream &OS) const {
else if (isProtected())
OS << " [protected]";
+ if (isLValueReference())
+ OS << " [reference]";
+
+ if (isRValueReference())
+ OS << " [rvalue reference]";
+
StringRef Res = getName();
if (!Res.empty())
OS << " [" << Res << ']';
@@ -1439,7 +1468,7 @@ bool llvm::StripDebugInfo(Module &M) {
// the module.
if (Function *Declare = M.getFunction("llvm.dbg.declare")) {
while (!Declare->use_empty()) {
- CallInst *CI = cast<CallInst>(Declare->use_back());
+ CallInst *CI = cast<CallInst>(Declare->user_back());
CI->eraseFromParent();
}
Declare->eraseFromParent();
@@ -1448,7 +1477,7 @@ bool llvm::StripDebugInfo(Module &M) {
if (Function *DbgVal = M.getFunction("llvm.dbg.value")) {
while (!DbgVal->use_empty()) {
- CallInst *CI = cast<CallInst>(DbgVal->use_back());
+ CallInst *CI = cast<CallInst>(DbgVal->user_back());
CI->eraseFromParent();
}
DbgVal->eraseFromParent();
diff --git a/lib/IR/DebugLoc.cpp b/lib/IR/DebugLoc.cpp
index c57b5a3..1a2521e 100644
--- a/lib/IR/DebugLoc.cpp
+++ b/lib/IR/DebugLoc.cpp
@@ -7,10 +7,10 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Support/DebugLoc.h"
+#include "llvm/IR/DebugLoc.h"
#include "LLVMContextImpl.h"
#include "llvm/ADT/DenseMapInfo.h"
-#include "llvm/DebugInfo.h"
+#include "llvm/IR/DebugInfo.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
@@ -70,6 +70,26 @@ void DebugLoc::getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA,
IA = Ctx.pImpl->ScopeInlinedAtRecords[-ScopeIdx-1].second.get();
}
+MDNode *DebugLoc::getScopeNode(const LLVMContext &Ctx) const {
+ if (MDNode *InlinedAt = getInlinedAt(Ctx))
+ return DebugLoc::getFromDILocation(InlinedAt).getScopeNode(Ctx);
+ return getScope(Ctx);
+}
+
+DebugLoc DebugLoc::getFnDebugLoc(const LLVMContext &Ctx) {
+ const MDNode *Scope = getScopeNode(Ctx);
+ DISubprogram SP = getDISubprogram(Scope);
+ if (SP.isSubprogram()) {
+ // Check for number of operands since the compatibility is
+ // cheap here. FIXME: Name the magic constant.
+ if (SP->getNumOperands() > 19)
+ return DebugLoc::get(SP.getScopeLineNumber(), 0, SP);
+ else
+ return DebugLoc::get(SP.getLineNumber(), 0, SP);
+ }
+
+ return DebugLoc();
+}
DebugLoc DebugLoc::get(unsigned Line, unsigned Col,
MDNode *Scope, MDNode *InlinedAt) {
@@ -96,7 +116,7 @@ DebugLoc DebugLoc::get(unsigned Line, unsigned Col,
}
/// getAsMDNode - This method converts the compressed DebugLoc node into a
-/// DILocation compatible MDNode.
+/// DILocation-compatible MDNode.
MDNode *DebugLoc::getAsMDNode(const LLVMContext &Ctx) const {
if (isUnknown()) return 0;
diff --git a/lib/IR/DiagnosticInfo.cpp b/lib/IR/DiagnosticInfo.cpp
new file mode 100644
index 0000000..d59d4cf
--- /dev/null
+++ b/lib/IR/DiagnosticInfo.cpp
@@ -0,0 +1,66 @@
+//===- llvm/Support/DiagnosticInfo.cpp - Diagnostic Definitions -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the different classes involved in low level diagnostics.
+//
+// Diagnostics reporting is still done as part of the LLVMContext.
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Instruction.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/Support/Atomic.h"
+#include <string>
+
+using namespace llvm;
+
+int llvm::getNextAvailablePluginDiagnosticKind() {
+ static sys::cas_flag PluginKindID = DK_FirstPluginKind;
+ return (int)sys::AtomicIncrement(&PluginKindID);
+}
+
+DiagnosticInfoInlineAsm::DiagnosticInfoInlineAsm(const Instruction &I,
+ const Twine &MsgStr,
+ DiagnosticSeverity Severity)
+ : DiagnosticInfo(DK_InlineAsm, Severity), LocCookie(0), MsgStr(MsgStr),
+ Instr(&I) {
+ if (const MDNode *SrcLoc = I.getMetadata("srcloc")) {
+ if (SrcLoc->getNumOperands() != 0)
+ if (const ConstantInt *CI = dyn_cast<ConstantInt>(SrcLoc->getOperand(0)))
+ LocCookie = CI->getZExtValue();
+ }
+}
+
+void DiagnosticInfoInlineAsm::print(DiagnosticPrinter &DP) const {
+ DP << getMsgStr();
+ if (getLocCookie())
+ DP << " at line " << getLocCookie();
+}
+
+void DiagnosticInfoStackSize::print(DiagnosticPrinter &DP) const {
+ DP << "stack size limit exceeded (" << getStackSize() << ") in "
+ << getFunction();
+}
+
+void DiagnosticInfoDebugMetadataVersion::print(DiagnosticPrinter &DP) const {
+ DP << "ignoring debug info with an invalid version (" << getMetadataVersion()
+ << ") in " << getModule();
+}
+
+void DiagnosticInfoSampleProfile::print(DiagnosticPrinter &DP) const {
+ if (getFileName() && getLineNum() > 0)
+ DP << getFileName() << ":" << getLineNum() << ": ";
+ else if (getFileName())
+ DP << getFileName() << ": ";
+ DP << getMsg();
+}
diff --git a/lib/IR/DiagnosticPrinter.cpp b/lib/IR/DiagnosticPrinter.cpp
new file mode 100644
index 0000000..5e16026
--- /dev/null
+++ b/lib/IR/DiagnosticPrinter.cpp
@@ -0,0 +1,107 @@
+//===- llvm/Support/DiagnosticInfo.cpp - Diagnostic Definitions -*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines the a diagnostic printer relying on raw_ostream.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/IR/DiagnosticPrinter.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/Value.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm;
+
+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(char C) {
+ Stream << C;
+ return *this;
+}
+
+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(unsigned char C) {
+ Stream << C;
+ return *this;
+}
+
+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(signed char C) {
+ Stream << C;
+ return *this;
+}
+
+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(StringRef Str) {
+ Stream << Str;
+ return *this;
+}
+
+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const char *Str) {
+ Stream << Str;
+ return *this;
+}
+
+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(
+ const std::string &Str) {
+ Stream << Str;
+ return *this;
+}
+
+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(unsigned long N) {
+ Stream << N;
+ return *this;
+}
+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(long N) {
+ Stream << N;
+ return *this;
+}
+
+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(
+ unsigned long long N) {
+ Stream << N;
+ return *this;
+}
+
+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(long long N) {
+ Stream << N;
+ return *this;
+}
+
+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const void *P) {
+ Stream << P;
+ return *this;
+}
+
+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(unsigned int N) {
+ Stream << N;
+ return *this;
+}
+
+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(int N) {
+ Stream << N;
+ return *this;
+}
+
+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(double N) {
+ Stream << N;
+ return *this;
+}
+
+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const Twine &Str) {
+ Str.print(Stream);
+ return *this;
+}
+
+// IR related types.
+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const Value &V) {
+ Stream << V.getName();
+ return *this;
+}
+
+DiagnosticPrinter &DiagnosticPrinterRawOStream::operator<<(const Module &M) {
+ Stream << M.getModuleIdentifier();
+ return *this;
+}
diff --git a/lib/IR/Dominators.cpp b/lib/IR/Dominators.cpp
index a1160cd..d6649d6 100644
--- a/lib/IR/Dominators.cpp
+++ b/lib/IR/Dominators.cpp
@@ -14,17 +14,16 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Analysis/Dominators.h"
+#include "llvm/IR/Dominators.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/Analysis/DominatorInternals.h"
-#include "llvm/Assembly/Writer.h"
+#include "llvm/IR/CFG.h"
#include "llvm/IR/Instructions.h"
-#include "llvm/Support/CFG.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/GenericDomTreeConstruction.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
using namespace llvm;
@@ -57,41 +56,23 @@ bool BasicBlockEdge::isSingleEdge() const {
//===----------------------------------------------------------------------===//
//
// Provide public access to DominatorTree information. Implementation details
-// can be found in DominatorInternals.h.
+// can be found in Dominators.h, GenericDomTree.h, and
+// GenericDomTreeConstruction.h.
//
//===----------------------------------------------------------------------===//
TEMPLATE_INSTANTIATION(class llvm::DomTreeNodeBase<BasicBlock>);
TEMPLATE_INSTANTIATION(class llvm::DominatorTreeBase<BasicBlock>);
-char DominatorTree::ID = 0;
-INITIALIZE_PASS(DominatorTree, "domtree",
- "Dominator Tree Construction", true, true)
-
-bool DominatorTree::runOnFunction(Function &F) {
- DT->recalculate(F);
- return false;
-}
-
-void DominatorTree::verifyAnalysis() const {
- if (!VerifyDomInfo) return;
-
- Function &F = *getRoot()->getParent();
-
- DominatorTree OtherDT;
- OtherDT.getBase().recalculate(F);
- if (compare(OtherDT)) {
- errs() << "DominatorTree is not up to date!\nComputed:\n";
- print(errs());
- errs() << "\nActual:\n";
- OtherDT.print(errs());
- abort();
- }
-}
-
-void DominatorTree::print(raw_ostream &OS, const Module *) const {
- DT->print(OS);
-}
+#define LLVM_COMMA ,
+TEMPLATE_INSTANTIATION(void llvm::Calculate<Function LLVM_COMMA BasicBlock *>(
+ DominatorTreeBase<GraphTraits<BasicBlock *>::NodeType> &DT LLVM_COMMA
+ Function &F));
+TEMPLATE_INSTANTIATION(
+ void llvm::Calculate<Function LLVM_COMMA Inverse<BasicBlock *> >(
+ DominatorTreeBase<GraphTraits<Inverse<BasicBlock *> >::NodeType> &DT
+ LLVM_COMMA Function &F));
+#undef LLVM_COMMA
// dominates - Return true if Def dominates a use in User. This performs
// the special checks necessary if Def and User are in the same basic block.
@@ -210,8 +191,7 @@ bool DominatorTree::dominates(const BasicBlockEdge &BBE,
return true;
}
-bool DominatorTree::dominates(const BasicBlockEdge &BBE,
- const Use &U) const {
+bool DominatorTree::dominates(const BasicBlockEdge &BBE, const Use &U) const {
// Assert that we have a single edge. We could handle them by simply
// returning false, but since isSingleEdge is linear on the number of
// edges, the callers can normally handle them more efficiently.
@@ -234,8 +214,7 @@ bool DominatorTree::dominates(const BasicBlockEdge &BBE,
return dominates(BBE, UseBB);
}
-bool DominatorTree::dominates(const Instruction *Def,
- const Use &U) const {
+bool DominatorTree::dominates(const Instruction *Def, const Use &U) const {
Instruction *UserInst = cast<Instruction>(U.getUser());
const BasicBlock *DefBB = Def->getParent();
@@ -300,3 +279,44 @@ bool DominatorTree::isReachableFromEntry(const Use &U) const {
// Everything else uses their operands in their own block.
return isReachableFromEntry(I->getParent());
}
+
+void DominatorTree::verifyDomTree() const {
+ if (!VerifyDomInfo)
+ return;
+
+ Function &F = *getRoot()->getParent();
+
+ DominatorTree OtherDT;
+ OtherDT.recalculate(F);
+ if (compare(OtherDT)) {
+ errs() << "DominatorTree is not up to date!\nComputed:\n";
+ print(errs());
+ errs() << "\nActual:\n";
+ OtherDT.print(errs());
+ abort();
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// DominatorTreeWrapperPass Implementation
+//===----------------------------------------------------------------------===//
+//
+// The implementation details of the wrapper pass that holds a DominatorTree.
+//
+//===----------------------------------------------------------------------===//
+
+char DominatorTreeWrapperPass::ID = 0;
+INITIALIZE_PASS(DominatorTreeWrapperPass, "domtree",
+ "Dominator Tree Construction", true, true)
+
+bool DominatorTreeWrapperPass::runOnFunction(Function &F) {
+ DT.recalculate(F);
+ return false;
+}
+
+void DominatorTreeWrapperPass::verifyAnalysis() const { DT.verifyDomTree(); }
+
+void DominatorTreeWrapperPass::print(raw_ostream &OS, const Module *) const {
+ DT.print(OS);
+}
+
diff --git a/lib/IR/Function.cpp b/lib/IR/Function.cpp
index e8a2402..c2ea0e1 100644
--- a/lib/IR/Function.cpp
+++ b/lib/IR/Function.cpp
@@ -18,13 +18,13 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/CodeGen/ValueTypes.h"
+#include "llvm/IR/CallSite.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/InstIterator.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LeakDetector.h"
#include "llvm/IR/Module.h"
-#include "llvm/Support/CallSite.h"
-#include "llvm/Support/InstIterator.h"
-#include "llvm/Support/LeakDetector.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/RWMutex.h"
#include "llvm/Support/StringPool.h"
@@ -84,6 +84,21 @@ bool Argument::hasByValAttr() const {
hasAttribute(getArgNo()+1, Attribute::ByVal);
}
+/// \brief Return true if this argument has the inalloca attribute on it in
+/// its containing function.
+bool Argument::hasInAllocaAttr() const {
+ if (!getType()->isPointerTy()) return false;
+ return getParent()->getAttributes().
+ hasAttribute(getArgNo()+1, Attribute::InAlloca);
+}
+
+bool Argument::hasByValOrInAllocaAttr() const {
+ if (!getType()->isPointerTy()) return false;
+ AttributeSet Attrs = getParent()->getAttributes();
+ return Attrs.hasAttribute(getArgNo() + 1, Attribute::ByVal) ||
+ Attrs.hasAttribute(getArgNo() + 1, Attribute::InAlloca);
+}
+
unsigned Argument::getParamAlignment() const {
assert(getType()->isPointerTy() && "Only pointers have alignments");
return getParent()->getParamAlignment(getArgNo()+1);
@@ -451,11 +466,12 @@ enum IIT_Info {
IIT_STRUCT3 = 20,
IIT_STRUCT4 = 21,
IIT_STRUCT5 = 22,
- IIT_EXTEND_VEC_ARG = 23,
- IIT_TRUNC_VEC_ARG = 24,
+ IIT_EXTEND_ARG = 23,
+ IIT_TRUNC_ARG = 24,
IIT_ANYPTR = 25,
IIT_V1 = 26,
- IIT_VARARG = 27
+ IIT_VARARG = 27,
+ IIT_HALF_VEC_ARG = 28
};
@@ -541,15 +557,21 @@ static void DecodeIITType(unsigned &NextElt, ArrayRef<unsigned char> Infos,
OutputTable.push_back(IITDescriptor::get(IITDescriptor::Argument, ArgInfo));
return;
}
- case IIT_EXTEND_VEC_ARG: {
+ case IIT_EXTEND_ARG: {
unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
- OutputTable.push_back(IITDescriptor::get(IITDescriptor::ExtendVecArgument,
+ OutputTable.push_back(IITDescriptor::get(IITDescriptor::ExtendArgument,
ArgInfo));
return;
}
- case IIT_TRUNC_VEC_ARG: {
+ case IIT_TRUNC_ARG: {
unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
- OutputTable.push_back(IITDescriptor::get(IITDescriptor::TruncVecArgument,
+ OutputTable.push_back(IITDescriptor::get(IITDescriptor::TruncArgument,
+ ArgInfo));
+ return;
+ }
+ case IIT_HALF_VEC_ARG: {
+ unsigned ArgInfo = (NextElt == Infos.size() ? 0 : Infos[NextElt++]);
+ OutputTable.push_back(IITDescriptor::get(IITDescriptor::HalfVecArgument,
ArgInfo));
return;
}
@@ -641,12 +663,24 @@ static Type *DecodeFixedType(ArrayRef<Intrinsic::IITDescriptor> &Infos,
case IITDescriptor::Argument:
return Tys[D.getArgumentNumber()];
- case IITDescriptor::ExtendVecArgument:
- return VectorType::getExtendedElementVectorType(cast<VectorType>(
- Tys[D.getArgumentNumber()]));
+ case IITDescriptor::ExtendArgument: {
+ Type *Ty = Tys[D.getArgumentNumber()];
+ if (VectorType *VTy = dyn_cast<VectorType>(Ty))
+ return VectorType::getExtendedElementVectorType(VTy);
- case IITDescriptor::TruncVecArgument:
- return VectorType::getTruncatedElementVectorType(cast<VectorType>(
+ return IntegerType::get(Context, 2 * cast<IntegerType>(Ty)->getBitWidth());
+ }
+ case IITDescriptor::TruncArgument: {
+ Type *Ty = Tys[D.getArgumentNumber()];
+ if (VectorType *VTy = dyn_cast<VectorType>(Ty))
+ return VectorType::getTruncatedElementVectorType(VTy);
+
+ IntegerType *ITy = cast<IntegerType>(Ty);
+ assert(ITy->getBitWidth() % 2 == 0);
+ return IntegerType::get(Context, ITy->getBitWidth() / 2);
+ }
+ case IITDescriptor::HalfVecArgument:
+ return VectorType::getHalfElementsVectorType(cast<VectorType>(
Tys[D.getArgumentNumber()]));
}
llvm_unreachable("unhandled");
@@ -696,15 +730,15 @@ Function *Intrinsic::getDeclaration(Module *M, ID id, ArrayRef<Type*> Tys) {
/// hasAddressTaken - returns true if there are any uses of this function
/// other than direct calls or invokes to it.
bool Function::hasAddressTaken(const User* *PutOffender) const {
- for (Value::const_use_iterator I = use_begin(), E = use_end(); I != E; ++I) {
- const User *U = *I;
- if (isa<BlockAddress>(U))
+ for (const Use &U : uses()) {
+ const User *FU = U.getUser();
+ if (isa<BlockAddress>(FU))
continue;
- if (!isa<CallInst>(U) && !isa<InvokeInst>(U))
- return PutOffender ? (*PutOffender = U, true) : true;
- ImmutableCallSite CS(cast<Instruction>(U));
- if (!CS.isCallee(I))
- return PutOffender ? (*PutOffender = U, true) : true;
+ if (!isa<CallInst>(FU) && !isa<InvokeInst>(FU))
+ return PutOffender ? (*PutOffender = FU, true) : true;
+ ImmutableCallSite CS(cast<Instruction>(FU));
+ if (!CS.isCallee(&U))
+ return PutOffender ? (*PutOffender = FU, true) : true;
}
return false;
}
@@ -716,8 +750,8 @@ bool Function::isDefTriviallyDead() const {
return false;
// Check if the function is used by anything other than a blockaddress.
- for (Value::const_use_iterator I = use_begin(), E = use_end(); I != E; ++I)
- if (!isa<BlockAddress>(*I))
+ for (const User *U : users())
+ if (!isa<BlockAddress>(U))
return false;
return true;
@@ -728,10 +762,8 @@ bool Function::isDefTriviallyDead() const {
bool Function::callsFunctionThatReturnsTwice() const {
for (const_inst_iterator
I = inst_begin(this), E = inst_end(this); I != E; ++I) {
- const CallInst* callInst = dyn_cast<CallInst>(&*I);
- if (!callInst)
- continue;
- if (callInst->canReturnTwice())
+ ImmutableCallSite CS(&*I);
+ if (CS && CS.hasFnAttr(Attribute::ReturnsTwice))
return true;
}
diff --git a/lib/IR/GCOV.cpp b/lib/IR/GCOV.cpp
index f0f8c7d..f69bdc4 100644
--- a/lib/IR/GCOV.cpp
+++ b/lib/IR/GCOV.cpp
@@ -1,4 +1,4 @@
-//===- GCOVr.cpp - LLVM coverage tool -------------------------------------===//
+//===- GCOV.cpp - LLVM coverage tool --------------------------------------===//
//
// The LLVM Compiler Infrastructure
//
@@ -12,13 +12,15 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Support/Debug.h"
#include "llvm/Support/GCOV.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MemoryObject.h"
+#include "llvm/Support/Path.h"
#include "llvm/Support/system_error.h"
+#include <algorithm>
using namespace llvm;
//===----------------------------------------------------------------------===//
@@ -29,63 +31,73 @@ GCOVFile::~GCOVFile() {
DeleteContainerPointers(Functions);
}
-/// isGCDAFile - Return true if Format identifies a .gcda file.
-static bool isGCDAFile(GCOV::GCOVFormat Format) {
- return Format == GCOV::GCDA_402 || Format == GCOV::GCDA_404;
-}
+/// readGCNO - Read GCNO buffer.
+bool GCOVFile::readGCNO(GCOVBuffer &Buffer) {
+ if (!Buffer.readGCNOFormat()) return false;
+ if (!Buffer.readGCOVVersion(Version)) return false;
+
+ if (!Buffer.readInt(Checksum)) return false;
+ while (true) {
+ if (!Buffer.readFunctionTag()) break;
+ GCOVFunction *GFun = new GCOVFunction(*this);
+ if (!GFun->readGCNO(Buffer, Version))
+ return false;
+ Functions.push_back(GFun);
+ }
-/// isGCNOFile - Return true if Format identifies a .gcno file.
-static bool isGCNOFile(GCOV::GCOVFormat Format) {
- return Format == GCOV::GCNO_402 || Format == GCOV::GCNO_404;
+ GCNOInitialized = true;
+ return true;
}
-/// read - Read GCOV buffer.
-bool GCOVFile::read(GCOVBuffer &Buffer) {
- GCOV::GCOVFormat Format = Buffer.readGCOVFormat();
- if (Format == GCOV::InvalidGCOV)
+/// readGCDA - Read GCDA buffer. It is required that readGCDA() can only be
+/// called after readGCNO().
+bool GCOVFile::readGCDA(GCOVBuffer &Buffer) {
+ assert(GCNOInitialized && "readGCDA() can only be called after readGCNO()");
+ if (!Buffer.readGCDAFormat()) return false;
+ GCOV::GCOVVersion GCDAVersion;
+ if (!Buffer.readGCOVVersion(GCDAVersion)) return false;
+ if (Version != GCDAVersion) {
+ errs() << "GCOV versions do not match.\n";
return false;
+ }
- if (isGCNOFile(Format)) {
- while (true) {
- if (!Buffer.readFunctionTag()) break;
- GCOVFunction *GFun = new GCOVFunction();
- if (!GFun->read(Buffer, Format))
- return false;
- Functions.push_back(GFun);
- }
+ uint32_t GCDAChecksum;
+ if (!Buffer.readInt(GCDAChecksum)) return false;
+ if (Checksum != GCDAChecksum) {
+ errs() << "File checksums do not match: " << Checksum << " != "
+ << GCDAChecksum << ".\n";
+ return false;
}
- 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;
+ 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]->readGCDA(Buffer, Version))
+ 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 to dbgs() for debugging purposes.
-void GCOVFile::dump() {
- for (SmallVectorImpl<GCOVFunction *>::iterator I = Functions.begin(),
+void GCOVFile::dump() const {
+ for (SmallVectorImpl<GCOVFunction *>::const_iterator I = Functions.begin(),
E = Functions.end(); I != E; ++I)
(*I)->dump();
}
@@ -106,54 +118,27 @@ void GCOVFile::collectLineCounts(FileInfo &FI) {
/// ~GCOVFunction - Delete GCOVFunction and its content.
GCOVFunction::~GCOVFunction() {
DeleteContainerPointers(Blocks);
+ DeleteContainerPointers(Edges);
}
-/// 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) {
+/// readGCNO - Read a function from the GCNO buffer. Return false if an error
+/// occurs.
+bool GCOVFunction::readGCNO(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
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)
- if (!Buff.readInt(Dummy)) return false; // Checksum #2
-
- if (!Buff.readString(Name)) return false;
-
- if (Format == GCOV::GCNO_402 || Format == GCOV::GCNO_404)
- if (!Buff.readString(Filename)) return false;
-
- if (Format == GCOV::GCDA_402 || Format == GCOV::GCDA_404) {
- if (!Buff.readArcTag()) {
- errs() << "Arc tag not found.\n";
+ if (!Buff.readInt(Checksum)) return false;
+ if (Version != GCOV::V402) {
+ uint32_t CfgChecksum;
+ if (!Buff.readInt(CfgChecksum)) return false;
+ if (Parent.getChecksum() != CfgChecksum) {
+ errs() << "File checksums do not match: " << Parent.getChecksum()
+ << " != " << CfgChecksum << " in (" << Name << ").\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;
}
-
+ if (!Buff.readString(Name)) return false;
+ if (!Buff.readString(Filename)) return false;
if (!Buff.readInt(LineNumber)) return false;
// read blocks.
@@ -176,13 +161,17 @@ bool GCOVFunction::read(GCOVBuffer &Buff, GCOV::GCOVFormat Format) {
uint32_t BlockNo;
if (!Buff.readInt(BlockNo)) return false;
if (BlockNo >= BlockCount) {
- errs() << "Unexpected block number.\n";
+ errs() << "Unexpected block number: " << BlockNo << " (in " << Name
+ << ").\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);
+ GCOVEdge *Edge = new GCOVEdge(Blocks[BlockNo], Blocks[Dst]);
+ Edges.push_back(Edge);
+ Blocks[BlockNo]->addDstEdge(Edge);
+ Blocks[Dst]->addSrcEdge(Edge);
if (!Buff.readInt(Dummy)) return false; // Edge flag
}
}
@@ -195,7 +184,8 @@ bool GCOVFunction::read(GCOVBuffer &Buff, GCOV::GCOVFormat Format) {
uint32_t BlockNo;
if (!Buff.readInt(BlockNo)) return false;
if (BlockNo >= BlockCount) {
- errs() << "Unexpected block number.\n";
+ errs() << "Unexpected block number: " << BlockNo << " (in " << Name
+ << ").\n";
return false;
}
GCOVBlock *Block = Blocks[BlockNo];
@@ -203,8 +193,9 @@ bool GCOVFunction::read(GCOVBuffer &Buff, GCOV::GCOVFormat Format) {
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";
+ if (Filename != F) {
+ errs() << "Multiple sources for a single basic block: " << Filename
+ << " != " << F << " (in " << Name << ").\n";
return false;
}
if (Buff.getCursor() == (EndPos - 4)) break;
@@ -220,10 +211,96 @@ bool GCOVFunction::read(GCOVBuffer &Buff, GCOV::GCOVFormat Format) {
return true;
}
+/// readGCDA - Read a function from the GCDA buffer. Return false if an error
+/// occurs.
+bool GCOVFunction::readGCDA(GCOVBuffer &Buff, GCOV::GCOVVersion Version) {
+ uint32_t Dummy;
+ if (!Buff.readInt(Dummy)) return false; // Function header length
+
+ uint32_t GCDAIdent;
+ if (!Buff.readInt(GCDAIdent)) return false;
+ if (Ident != GCDAIdent) {
+ errs() << "Function identifiers do not match: " << Ident << " != "
+ << GCDAIdent << " (in " << Name << ").\n";
+ return false;
+ }
+
+ uint32_t GCDAChecksum;
+ if (!Buff.readInt(GCDAChecksum)) return false;
+ if (Checksum != GCDAChecksum) {
+ errs() << "Function checksums do not match: " << Checksum << " != "
+ << GCDAChecksum << " (in " << Name << ").\n";
+ return false;
+ }
+
+ uint32_t CfgChecksum;
+ if (Version != GCOV::V402) {
+ if (!Buff.readInt(CfgChecksum)) return false;
+ if (Parent.getChecksum() != CfgChecksum) {
+ errs() << "File checksums do not match: " << Parent.getChecksum()
+ << " != " << CfgChecksum << " (in " << Name << ").\n";
+ return false;
+ }
+ }
+
+ StringRef GCDAName;
+ if (!Buff.readString(GCDAName)) return false;
+ if (Name != GCDAName) {
+ errs() << "Function names do not match: " << Name << " != " << GCDAName
+ << ".\n";
+ return false;
+ }
+
+ if (!Buff.readArcTag()) {
+ errs() << "Arc tag not found (in " << Name << ").\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 BlockNo = 0; Count > 0; ++BlockNo) {
+ // The last block is always reserved for exit block
+ if (BlockNo >= Blocks.size()-1) {
+ errs() << "Unexpected number of edges (in " << Name << ").\n";
+ return false;
+ }
+ GCOVBlock &Block = *Blocks[BlockNo];
+ for (size_t EdgeNo = 0, End = Block.getNumDstEdges(); EdgeNo < End;
+ ++EdgeNo) {
+ if (Count == 0) {
+ errs() << "Unexpected number of edges (in " << Name << ").\n";
+ return false;
+ }
+ uint64_t ArcCount;
+ if (!Buff.readInt64(ArcCount)) return false;
+ Block.addCount(EdgeNo, ArcCount);
+ --Count;
+ }
+ Block.sortDstEdges();
+ }
+ return true;
+}
+
+/// getEntryCount - Get the number of times the function was called by
+/// retrieving the entry block's count.
+uint64_t GCOVFunction::getEntryCount() const {
+ return Blocks.front()->getCount();
+}
+
+/// getExitCount - Get the number of times the function returned by retrieving
+/// the exit block's count.
+uint64_t GCOVFunction::getExitCount() const {
+ return Blocks.back()->getCount();
+}
+
/// dump - Dump GCOVFunction content to dbgs() for debugging purposes.
-void GCOVFunction::dump() {
+void GCOVFunction::dump() const {
dbgs() << "===== " << Name << " @ " << Filename << ":" << LineNumber << "\n";
- for (SmallVectorImpl<GCOVBlock *>::iterator I = Blocks.begin(),
+ for (SmallVectorImpl<GCOVBlock *>::const_iterator I = Blocks.begin(),
E = Blocks.end(); I != E; ++I)
(*I)->dump();
}
@@ -231,9 +308,15 @@ void GCOVFunction::dump() {
/// collectLineCounts - Collect line counts. This must be used after
/// reading .gcno and .gcda files.
void GCOVFunction::collectLineCounts(FileInfo &FI) {
+ // If the line number is zero, this is a function that doesn't actually appear
+ // in the source file, so there isn't anything we can do with it.
+ if (LineNumber == 0)
+ return;
+
for (SmallVectorImpl<GCOVBlock *>::iterator I = Blocks.begin(),
E = Blocks.end(); I != E; ++I)
(*I)->collectLineCounts(FI);
+ FI.addFunctionLine(Filename, LineNumber, this);
}
//===----------------------------------------------------------------------===//
@@ -241,31 +324,60 @@ void GCOVFunction::collectLineCounts(FileInfo &FI) {
/// ~GCOVBlock - Delete GCOVBlock and its content.
GCOVBlock::~GCOVBlock() {
- Edges.clear();
+ SrcEdges.clear();
+ DstEdges.clear();
Lines.clear();
}
+/// addCount - Add to block counter while storing the edge count. If the
+/// destination has no outgoing edges, also update that block's count too.
+void GCOVBlock::addCount(size_t DstEdgeNo, uint64_t N) {
+ assert(DstEdgeNo < DstEdges.size()); // up to caller to ensure EdgeNo is valid
+ DstEdges[DstEdgeNo]->Count = N;
+ Counter += N;
+ if (!DstEdges[DstEdgeNo]->Dst->getNumDstEdges())
+ DstEdges[DstEdgeNo]->Dst->Counter += N;
+}
+
+/// sortDstEdges - Sort destination edges by block number, nop if already
+/// sorted. This is required for printing branch info in the correct order.
+void GCOVBlock::sortDstEdges() {
+ if (!DstEdgesAreSorted) {
+ SortDstEdgesFunctor SortEdges;
+ std::stable_sort(DstEdges.begin(), DstEdges.end(), SortEdges);
+ }
+}
+
/// collectLineCounts - Collect line counts. This must be used after
/// reading .gcno and .gcda files.
void GCOVBlock::collectLineCounts(FileInfo &FI) {
for (SmallVectorImpl<uint32_t>::iterator I = Lines.begin(),
E = Lines.end(); I != E; ++I)
- FI.addLineCount(Parent.getFilename(), *I, Counter);
+ FI.addBlockLine(Parent.getFilename(), *I, this);
}
/// dump - Dump GCOVBlock content to dbgs() for debugging purposes.
-void GCOVBlock::dump() {
+void GCOVBlock::dump() const {
dbgs() << "Block : " << Number << " Counter : " << Counter << "\n";
- if (!Edges.empty()) {
- dbgs() << "\tEdges : ";
- for (SmallVectorImpl<uint32_t>::iterator I = Edges.begin(), E = Edges.end();
- I != E; ++I)
- dbgs() << (*I) << ",";
+ if (!SrcEdges.empty()) {
+ dbgs() << "\tSource Edges : ";
+ for (EdgeIterator I = SrcEdges.begin(), E = SrcEdges.end(); I != E; ++I) {
+ const GCOVEdge *Edge = *I;
+ dbgs() << Edge->Src->Number << " (" << Edge->Count << "), ";
+ }
+ dbgs() << "\n";
+ }
+ if (!DstEdges.empty()) {
+ dbgs() << "\tDestination Edges : ";
+ for (EdgeIterator I = DstEdges.begin(), E = DstEdges.end(); I != E; ++I) {
+ const GCOVEdge *Edge = *I;
+ dbgs() << Edge->Dst->Number << " (" << Edge->Count << "), ";
+ }
dbgs() << "\n";
}
if (!Lines.empty()) {
dbgs() << "\tLines : ";
- for (SmallVectorImpl<uint32_t>::iterator I = Lines.begin(),
+ for (SmallVectorImpl<uint32_t>::const_iterator I = Lines.begin(),
E = Lines.end(); I != E; ++I)
dbgs() << (*I) << ",";
dbgs() << "\n";
@@ -275,40 +387,335 @@ void GCOVBlock::dump() {
//===----------------------------------------------------------------------===//
// FileInfo implementation.
+// Safe integer division, returns 0 if numerator is 0.
+static uint32_t safeDiv(uint64_t Numerator, uint64_t Divisor) {
+ if (!Numerator)
+ return 0;
+ return Numerator/Divisor;
+}
+
+// This custom division function mimics gcov's branch ouputs:
+// - Round to closest whole number
+// - Only output 0% or 100% if it's exactly that value
+static uint32_t branchDiv(uint64_t Numerator, uint64_t Divisor) {
+ if (!Numerator)
+ return 0;
+ if (Numerator == Divisor)
+ return 100;
+
+ uint8_t Res = (Numerator*100+Divisor/2) / Divisor;
+ if (Res == 0)
+ return 1;
+ if (Res == 100)
+ return 99;
+ return Res;
+}
+
+struct formatBranchInfo {
+ formatBranchInfo(const GCOVOptions &Options, uint64_t Count,
+ uint64_t Total) :
+ Options(Options), Count(Count), Total(Total) {}
+
+ void print(raw_ostream &OS) const {
+ if (!Total)
+ OS << "never executed";
+ else if (Options.BranchCount)
+ OS << "taken " << Count;
+ else
+ OS << "taken " << branchDiv(Count, Total) << "%";
+ }
+
+ const GCOVOptions &Options;
+ uint64_t Count;
+ uint64_t Total;
+};
+
+static raw_ostream &operator<<(raw_ostream &OS, const formatBranchInfo &FBI) {
+ FBI.print(OS);
+ return OS;
+}
+
+/// Convert a path to a gcov filename. If PreservePaths is true, this
+/// translates "/" to "#", ".." to "^", and drops ".", to match gcov.
+static std::string mangleCoveragePath(StringRef Filename, bool PreservePaths) {
+ if (!PreservePaths)
+ return (sys::path::filename(Filename) + ".gcov").str();
+
+ // This behaviour is defined by gcov in terms of text replacements, so it's
+ // not likely to do anything useful on filesystems with different textual
+ // conventions.
+ llvm::SmallString<256> Result("");
+ StringRef::iterator I, S, E;
+ for (I = S = Filename.begin(), E = Filename.end(); I != E; ++I) {
+ if (*I != '/')
+ continue;
+
+ if (I - S == 1 && *S == '.') {
+ // ".", the current directory, is skipped.
+ } else if (I - S == 2 && *S == '.' && *(S + 1) == '.') {
+ // "..", the parent directory, is replaced with "^".
+ Result.append("^#");
+ } else {
+ if (S < I)
+ // Leave other components intact,
+ Result.append(S, I);
+ // And separate with "#".
+ Result.push_back('#');
+ }
+ S = I + 1;
+ }
+
+ if (S < I)
+ Result.append(S, I);
+ Result.append(".gcov");
+ return Result.str();
+}
+
/// print - Print source files with collected line count information.
-void FileInfo::print(raw_fd_ostream &OS, StringRef gcnoFile,
- StringRef gcdaFile) {
- for (StringMap<LineCounts>::iterator I = LineInfo.begin(), E = LineInfo.end();
- I != E; ++I) {
+void FileInfo::print(StringRef GCNOFile, StringRef GCDAFile) {
+ for (StringMap<LineData>::const_iterator I = LineInfo.begin(),
+ E = LineInfo.end(); I != E; ++I) {
StringRef Filename = I->first();
- 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;
+ std::unique_ptr<MemoryBuffer> Buff;
if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
errs() << Filename << ": " << ec.message() << "\n";
return;
}
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 {
+
+ std::string CoveragePath = mangleCoveragePath(Filename,
+ Options.PreservePaths);
+ std::string ErrorInfo;
+ raw_fd_ostream OS(CoveragePath.c_str(), ErrorInfo, sys::fs::F_Text);
+ if (!ErrorInfo.empty())
+ errs() << ErrorInfo << "\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";
+
+ const LineData &Line = I->second;
+ GCOVCoverage FileCoverage(Filename);
+ for (uint32_t LineIndex = 0; !AllLines.empty(); ++LineIndex) {
+ if (Options.BranchInfo) {
+ FunctionLines::const_iterator FuncsIt = Line.Functions.find(LineIndex);
+ if (FuncsIt != Line.Functions.end())
+ printFunctionSummary(OS, FuncsIt->second);
+ }
+
+ BlockLines::const_iterator BlocksIt = Line.Blocks.find(LineIndex);
+ if (BlocksIt == Line.Blocks.end()) {
+ // No basic blocks are on this line. Not an executable line of code.
OS << " -:";
+ std::pair<StringRef, StringRef> P = AllLines.split('\n');
+ OS << format("%5u:", LineIndex+1) << P.first << "\n";
+ AllLines = P.second;
+ } else {
+ const BlockVector &Blocks = BlocksIt->second;
+
+ // Add up the block counts to form line counts.
+ DenseMap<const GCOVFunction *, bool> LineExecs;
+ uint64_t LineCount = 0;
+ for (BlockVector::const_iterator I = Blocks.begin(), E = Blocks.end();
+ I != E; ++I) {
+ const GCOVBlock *Block = *I;
+ if (Options.AllBlocks) {
+ // Only take the highest block count for that line.
+ uint64_t BlockCount = Block->getCount();
+ LineCount = LineCount > BlockCount ? LineCount : BlockCount;
+ } else {
+ // Sum up all of the block counts.
+ LineCount += Block->getCount();
+ }
+
+ if (Options.FuncCoverage) {
+ // This is a slightly convoluted way to most accurately gather line
+ // statistics for functions. Basically what is happening is that we
+ // don't want to count a single line with multiple blocks more than
+ // once. However, we also don't simply want to give the total line
+ // count to every function that starts on the line. Thus, what is
+ // happening here are two things:
+ // 1) Ensure that the number of logical lines is only incremented
+ // once per function.
+ // 2) If there are multiple blocks on the same line, ensure that the
+ // number of lines executed is incremented as long as at least
+ // one of the blocks are executed.
+ const GCOVFunction *Function = &Block->getParent();
+ if (FuncCoverages.find(Function) == FuncCoverages.end()) {
+ std::pair<const GCOVFunction *, GCOVCoverage>
+ KeyValue(Function, GCOVCoverage(Function->getName()));
+ FuncCoverages.insert(KeyValue);
+ }
+ GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second;
+
+ if (LineExecs.find(Function) == LineExecs.end()) {
+ if (Block->getCount()) {
+ ++FuncCoverage.LinesExec;
+ LineExecs[Function] = true;
+ } else {
+ LineExecs[Function] = false;
+ }
+ ++FuncCoverage.LogicalLines;
+ } else if (!LineExecs[Function] && Block->getCount()) {
+ ++FuncCoverage.LinesExec;
+ LineExecs[Function] = true;
+ }
+ }
+ }
+
+ if (LineCount == 0)
+ OS << " #####:";
+ else {
+ OS << format("%9" PRIu64 ":", LineCount);
+ ++FileCoverage.LinesExec;
+ }
+ ++FileCoverage.LogicalLines;
+
+ std::pair<StringRef, StringRef> P = AllLines.split('\n');
+ OS << format("%5u:", LineIndex+1) << P.first << "\n";
+ AllLines = P.second;
+
+ uint32_t BlockNo = 0;
+ uint32_t EdgeNo = 0;
+ for (BlockVector::const_iterator I = Blocks.begin(), E = Blocks.end();
+ I != E; ++I) {
+ const GCOVBlock *Block = *I;
+
+ // Only print block and branch information at the end of the block.
+ if (Block->getLastLine() != LineIndex+1)
+ continue;
+ if (Options.AllBlocks)
+ printBlockInfo(OS, *Block, LineIndex, BlockNo);
+ if (Options.BranchInfo) {
+ size_t NumEdges = Block->getNumDstEdges();
+ if (NumEdges > 1)
+ printBranchInfo(OS, *Block, FileCoverage, EdgeNo);
+ else if (Options.UncondBranch && NumEdges == 1)
+ printUncondBranchInfo(OS, EdgeNo, (*Block->dst_begin())->Count);
+ }
+ }
}
- std::pair<StringRef, StringRef> P = AllLines.split('\n');
- if (AllLines != P.first)
- OS << format("%5u:", i+1) << P.first;
- OS << "\n";
- AllLines = P.second;
- ++i;
}
+ FileCoverages.push_back(std::make_pair(CoveragePath, FileCoverage));
+ }
+
+ // FIXME: There is no way to detect calls given current instrumentation.
+ if (Options.FuncCoverage)
+ printFuncCoverage();
+ printFileCoverage();
+}
+
+/// printFunctionSummary - Print function and block summary.
+void FileInfo::printFunctionSummary(raw_fd_ostream &OS,
+ const FunctionVector &Funcs) const {
+ for (FunctionVector::const_iterator I = Funcs.begin(), E = Funcs.end();
+ I != E; ++I) {
+ const GCOVFunction *Func = *I;
+ uint64_t EntryCount = Func->getEntryCount();
+ uint32_t BlocksExec = 0;
+ for (GCOVFunction::BlockIterator I = Func->block_begin(),
+ E = Func->block_end(); I != E; ++I) {
+ const GCOVBlock *Block = *I;
+ if (Block->getNumDstEdges() && Block->getCount())
+ ++BlocksExec;
+ }
+
+ OS << "function " << Func->getName() << " called " << EntryCount
+ << " returned " << safeDiv(Func->getExitCount()*100, EntryCount)
+ << "% blocks executed "
+ << safeDiv(BlocksExec*100, Func->getNumBlocks()-1) << "%\n";
+ }
+}
+
+/// printBlockInfo - Output counts for each block.
+void FileInfo::printBlockInfo(raw_fd_ostream &OS, const GCOVBlock &Block,
+ uint32_t LineIndex, uint32_t &BlockNo) const {
+ if (Block.getCount() == 0)
+ OS << " $$$$$:";
+ else
+ OS << format("%9" PRIu64 ":", Block.getCount());
+ OS << format("%5u-block %2u\n", LineIndex+1, BlockNo++);
+}
+
+/// printBranchInfo - Print conditional branch probabilities.
+void FileInfo::printBranchInfo(raw_fd_ostream &OS, const GCOVBlock &Block,
+ GCOVCoverage &Coverage, uint32_t &EdgeNo) {
+ SmallVector<uint64_t, 16> BranchCounts;
+ uint64_t TotalCounts = 0;
+ for (GCOVBlock::EdgeIterator I = Block.dst_begin(), E = Block.dst_end();
+ I != E; ++I) {
+ const GCOVEdge *Edge = *I;
+ BranchCounts.push_back(Edge->Count);
+ TotalCounts += Edge->Count;
+ if (Block.getCount()) ++Coverage.BranchesExec;
+ if (Edge->Count) ++Coverage.BranchesTaken;
+ ++Coverage.Branches;
+
+ if (Options.FuncCoverage) {
+ const GCOVFunction *Function = &Block.getParent();
+ GCOVCoverage &FuncCoverage = FuncCoverages.find(Function)->second;
+ if (Block.getCount()) ++FuncCoverage.BranchesExec;
+ if (Edge->Count) ++FuncCoverage.BranchesTaken;
+ ++FuncCoverage.Branches;
+ }
+ }
+
+ for (SmallVectorImpl<uint64_t>::const_iterator I = BranchCounts.begin(),
+ E = BranchCounts.end(); I != E; ++I) {
+ OS << format("branch %2u ", EdgeNo++)
+ << formatBranchInfo(Options, *I, TotalCounts) << "\n";
+ }
+}
+
+/// printUncondBranchInfo - Print unconditional branch probabilities.
+void FileInfo::printUncondBranchInfo(raw_fd_ostream &OS, uint32_t &EdgeNo,
+ uint64_t Count) const {
+ OS << format("unconditional %2u ", EdgeNo++)
+ << formatBranchInfo(Options, Count, Count) << "\n";
+}
+
+// printCoverage - Print generic coverage info used by both printFuncCoverage
+// and printFileCoverage.
+void FileInfo::printCoverage(const GCOVCoverage &Coverage) const {
+ outs() << format("Lines executed:%.2f%% of %u\n",
+ double(Coverage.LinesExec)*100/Coverage.LogicalLines,
+ Coverage.LogicalLines);
+ if (Options.BranchInfo) {
+ if (Coverage.Branches) {
+ outs() << format("Branches executed:%.2f%% of %u\n",
+ double(Coverage.BranchesExec)*100/Coverage.Branches,
+ Coverage.Branches);
+ outs() << format("Taken at least once:%.2f%% of %u\n",
+ double(Coverage.BranchesTaken)*100/Coverage.Branches,
+ Coverage.Branches);
+ } else {
+ outs() << "No branches\n";
+ }
+ outs() << "No calls\n"; // to be consistent with gcov
+ }
+}
+
+// printFuncCoverage - Print per-function coverage info.
+void FileInfo::printFuncCoverage() const {
+ for (FuncCoverageMap::const_iterator I = FuncCoverages.begin(),
+ E = FuncCoverages.end(); I != E; ++I) {
+ const GCOVCoverage &Coverage = I->second;
+ outs() << "Function '" << Coverage.Name << "'\n";
+ printCoverage(Coverage);
+ outs() << "\n";
+ }
+}
+
+// printFileCoverage - Print per-file coverage info.
+void FileInfo::printFileCoverage() const {
+ for (FileCoverageList::const_iterator I = FileCoverages.begin(),
+ E = FileCoverages.end(); I != E; ++I) {
+ const std::string &Filename = I->first;
+ const GCOVCoverage &Coverage = I->second;
+ outs() << "File '" << Coverage.Name << "'\n";
+ printCoverage(Coverage);
+ outs() << Coverage.Name << ":creating '" << Filename << "'\n\n";
}
}
diff --git a/lib/IR/GVMaterializer.cpp b/lib/IR/GVMaterializer.cpp
index f77a9c9..706926d 100644
--- a/lib/IR/GVMaterializer.cpp
+++ b/lib/IR/GVMaterializer.cpp
@@ -12,7 +12,7 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/GVMaterializer.h"
+#include "llvm/IR/GVMaterializer.h"
using namespace llvm;
GVMaterializer::~GVMaterializer() {}
diff --git a/lib/IR/Globals.cpp b/lib/IR/Globals.cpp
index da3b02a..f338dd7 100644
--- a/lib/IR/Globals.cpp
+++ b/lib/IR/Globals.cpp
@@ -18,9 +18,9 @@
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalVariable.h"
+#include "llvm/IR/LeakDetector.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/LeakDetector.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
@@ -40,6 +40,10 @@ void GlobalValue::Dematerialize() {
getParent()->Dematerialize(this);
}
+const DataLayout *GlobalValue::getDataLayout() const {
+ return getParent()->getDataLayout();
+}
+
/// Override destroyConstant to make sure it doesn't get called on
/// GlobalValue's because they shouldn't be treated like other constants.
void GlobalValue::destroyConstant() {
@@ -53,9 +57,12 @@ void GlobalValue::copyAttributesFrom(const GlobalValue *Src) {
setSection(Src->getSection());
setVisibility(Src->getVisibility());
setUnnamedAddr(Src->hasUnnamedAddr());
+ setDLLStorageClass(Src->getDLLStorageClass());
}
void GlobalValue::setAlignment(unsigned Align) {
+ assert((!isa<GlobalAlias>(this) || !Align) &&
+ "GlobalAlias should not have an alignment!");
assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
assert(Align <= MaximumAlignment &&
"Alignment is greater than MaximumAlignment!");
@@ -184,7 +191,7 @@ void GlobalVariable::copyAttributesFrom(const GlobalValue *Src) {
assert(isa<GlobalVariable>(Src) && "Expected a GlobalVariable!");
GlobalValue::copyAttributesFrom(Src);
const GlobalVariable *SrcVar = cast<GlobalVariable>(Src);
- setThreadLocal(SrcVar->isThreadLocal());
+ setThreadLocalMode(SrcVar->getThreadLocalMode());
}
@@ -229,41 +236,35 @@ void GlobalAlias::setAliasee(Constant *Aliasee) {
setOperand(0, Aliasee);
}
-GlobalValue *GlobalAlias::getAliasedGlobal() {
- Constant *C = getAliasee();
- if (C == 0) return 0;
-
+static GlobalValue *getAliaseeGV(GlobalAlias *GA) {
+ Constant *C = GA->getAliasee();
+ assert(C && "Must alias something");
+
if (GlobalValue *GV = dyn_cast<GlobalValue>(C))
return GV;
ConstantExpr *CE = cast<ConstantExpr>(C);
- assert((CE->getOpcode() == Instruction::BitCast ||
+ assert((CE->getOpcode() == Instruction::BitCast ||
+ CE->getOpcode() == Instruction::AddrSpaceCast ||
CE->getOpcode() == Instruction::GetElementPtr) &&
"Unsupported aliasee");
-
+
return cast<GlobalValue>(CE->getOperand(0));
}
-GlobalValue *GlobalAlias::resolveAliasedGlobal(bool stopOnWeak) {
+GlobalValue *GlobalAlias::getAliasedGlobal() {
SmallPtrSet<GlobalValue*, 3> Visited;
- // Check if we need to stop early.
- if (stopOnWeak && mayBeOverridden())
- return this;
-
- GlobalValue *GV = getAliasedGlobal();
- Visited.insert(GV);
-
- // Iterate over aliasing chain, stopping on weak alias if necessary.
- while (GlobalAlias *GA = dyn_cast<GlobalAlias>(GV)) {
- if (stopOnWeak && GA->mayBeOverridden())
- break;
-
- GV = GA->getAliasedGlobal();
+ GlobalAlias *GA = this;
+ for (;;) {
+ GlobalValue *GV = getAliaseeGV(GA);
if (!Visited.insert(GV))
return 0;
- }
- return GV;
+ // Iterate over aliasing chain.
+ GA = dyn_cast<GlobalAlias>(GV);
+ if (!GA)
+ return GV;
+ }
}
diff --git a/lib/IR/IRPrintingPasses.cpp b/lib/IR/IRPrintingPasses.cpp
new file mode 100644
index 0000000..099c27c
--- /dev/null
+++ b/lib/IR/IRPrintingPasses.cpp
@@ -0,0 +1,127 @@
+//===--- IRPrintingPasses.cpp - Module and Function printing passes -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// PrintModulePass and PrintFunctionPass implementations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/IRPrintingPasses.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/Module.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Pass.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+PrintModulePass::PrintModulePass() : OS(dbgs()) {}
+PrintModulePass::PrintModulePass(raw_ostream &OS, const std::string &Banner)
+ : OS(OS), Banner(Banner) {}
+
+PreservedAnalyses PrintModulePass::run(Module *M) {
+ OS << Banner << *M;
+ return PreservedAnalyses::all();
+}
+
+PrintFunctionPass::PrintFunctionPass() : OS(dbgs()) {}
+PrintFunctionPass::PrintFunctionPass(raw_ostream &OS, const std::string &Banner)
+ : OS(OS), Banner(Banner) {}
+
+PreservedAnalyses PrintFunctionPass::run(Function *F) {
+ OS << Banner << static_cast<Value &>(*F);
+ return PreservedAnalyses::all();
+}
+
+namespace {
+
+class PrintModulePassWrapper : public ModulePass {
+ PrintModulePass P;
+
+public:
+ static char ID;
+ PrintModulePassWrapper() : ModulePass(ID) {}
+ PrintModulePassWrapper(raw_ostream &OS, const std::string &Banner)
+ : ModulePass(ID), P(OS, Banner) {}
+
+ bool runOnModule(Module &M) override {
+ P.run(&M);
+ return false;
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ }
+};
+
+class PrintFunctionPassWrapper : public FunctionPass {
+ PrintFunctionPass P;
+
+public:
+ static char ID;
+ PrintFunctionPassWrapper() : FunctionPass(ID) {}
+ PrintFunctionPassWrapper(raw_ostream &OS, const std::string &Banner)
+ : FunctionPass(ID), P(OS, Banner) {}
+
+ // This pass just prints a banner followed by the function as it's processed.
+ bool runOnFunction(Function &F) override {
+ P.run(&F);
+ return false;
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ }
+};
+
+class PrintBasicBlockPass : public BasicBlockPass {
+ raw_ostream &Out;
+ std::string Banner;
+
+public:
+ static char ID;
+ PrintBasicBlockPass() : BasicBlockPass(ID), Out(dbgs()) {}
+ PrintBasicBlockPass(raw_ostream &Out, const std::string &Banner)
+ : BasicBlockPass(ID), Out(Out), Banner(Banner) {}
+
+ bool runOnBasicBlock(BasicBlock &BB) override {
+ Out << Banner << BB;
+ return false;
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override{
+ AU.setPreservesAll();
+ }
+};
+
+}
+
+char PrintModulePassWrapper::ID = 0;
+INITIALIZE_PASS(PrintModulePassWrapper, "print-module",
+ "Print module to stderr", false, false)
+char PrintFunctionPassWrapper::ID = 0;
+INITIALIZE_PASS(PrintFunctionPassWrapper, "print-function",
+ "Print function to stderr", false, false)
+char PrintBasicBlockPass::ID = 0;
+INITIALIZE_PASS(PrintBasicBlockPass, "print-bb", "Print BB to stderr", false,
+ false)
+
+ModulePass *llvm::createPrintModulePass(llvm::raw_ostream &OS,
+ const std::string &Banner) {
+ return new PrintModulePassWrapper(OS, Banner);
+}
+
+FunctionPass *llvm::createPrintFunctionPass(llvm::raw_ostream &OS,
+ const std::string &Banner) {
+ return new PrintFunctionPassWrapper(OS, Banner);
+}
+
+BasicBlockPass *llvm::createPrintBasicBlockPass(llvm::raw_ostream &OS,
+ const std::string &Banner) {
+ return new PrintBasicBlockPass(OS, Banner);
+}
diff --git a/lib/IR/InlineAsm.cpp b/lib/IR/InlineAsm.cpp
index 9f2a9fe..62d191d 100644
--- a/lib/IR/InlineAsm.cpp
+++ b/lib/IR/InlineAsm.cpp
@@ -64,16 +64,6 @@ InlineAsm::ConstraintInfo::ConstraintInfo() :
currentAlternativeIndex(0) {
}
-/// Copy constructor.
-InlineAsm::ConstraintInfo::ConstraintInfo(const ConstraintInfo &other) :
- Type(other.Type), isEarlyClobber(other.isEarlyClobber),
- MatchingInput(other.MatchingInput), isCommutative(other.isCommutative),
- isIndirect(other.isIndirect), Codes(other.Codes),
- isMultipleAlternative(other.isMultipleAlternative),
- multipleAlternatives(other.multipleAlternatives),
- currentAlternativeIndex(other.currentAlternativeIndex) {
-}
-
/// Parse - Analyze the specified string (e.g. "==&{eax}") and fill in the
/// fields in this structure. If the constraint string is not understood,
/// return true, otherwise return false.
diff --git a/lib/IR/Instruction.cpp b/lib/IR/Instruction.cpp
index a7773c4..d31a92e 100644
--- a/lib/IR/Instruction.cpp
+++ b/lib/IR/Instruction.cpp
@@ -12,13 +12,13 @@
//===----------------------------------------------------------------------===//
#include "llvm/IR/Instruction.h"
+#include "llvm/IR/CallSite.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LeakDetector.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/Type.h"
-#include "llvm/Support/CallSite.h"
-#include "llvm/Support/LeakDetector.h"
using namespace llvm;
Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps,
@@ -35,6 +35,10 @@ Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps,
}
}
+const DataLayout *Instruction::getDataLayout() const {
+ return getParent()->getDataLayout();
+}
+
Instruction::Instruction(Type *ty, unsigned it, Use *Ops, unsigned NumOps,
BasicBlock *InsertAtEnd)
: User(ty, Value::InstructionVal + it, Ops, NumOps), Parent(0) {
@@ -277,9 +281,8 @@ bool Instruction::isIdenticalToWhenDefined(const Instruction *I) const {
// We have two instructions of identical opcode and #operands. Check to see
// if all operands are the same.
- for (unsigned i = 0, e = getNumOperands(); i != e; ++i)
- if (getOperand(i) != I->getOperand(i))
- return false;
+ if (!std::equal(op_begin(), op_end(), I->op_begin()))
+ return false;
// Check special state that is a part of some instructions.
if (const LoadInst *LI = dyn_cast<LoadInst>(this))
@@ -310,7 +313,10 @@ bool Instruction::isIdenticalToWhenDefined(const Instruction *I) const {
FI->getSynchScope() == cast<FenceInst>(FI)->getSynchScope();
if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(this))
return CXI->isVolatile() == cast<AtomicCmpXchgInst>(I)->isVolatile() &&
- CXI->getOrdering() == cast<AtomicCmpXchgInst>(I)->getOrdering() &&
+ CXI->getSuccessOrdering() ==
+ cast<AtomicCmpXchgInst>(I)->getSuccessOrdering() &&
+ CXI->getFailureOrdering() ==
+ cast<AtomicCmpXchgInst>(I)->getFailureOrdering() &&
CXI->getSynchScope() == cast<AtomicCmpXchgInst>(I)->getSynchScope();
if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(this))
return RMWI->getOperation() == cast<AtomicRMWInst>(I)->getOperation() &&
@@ -319,11 +325,8 @@ bool Instruction::isIdenticalToWhenDefined(const Instruction *I) const {
RMWI->getSynchScope() == cast<AtomicRMWInst>(I)->getSynchScope();
if (const PHINode *thisPHI = dyn_cast<PHINode>(this)) {
const PHINode *otherPHI = cast<PHINode>(I);
- for (unsigned i = 0, e = thisPHI->getNumOperands(); i != e; ++i) {
- if (thisPHI->getIncomingBlock(i) != otherPHI->getIncomingBlock(i))
- return false;
- }
- return true;
+ return std::equal(thisPHI->block_begin(), thisPHI->block_end(),
+ otherPHI->block_begin());
}
return true;
}
@@ -384,7 +387,10 @@ bool Instruction::isSameOperationAs(const Instruction *I,
FI->getSynchScope() == cast<FenceInst>(I)->getSynchScope();
if (const AtomicCmpXchgInst *CXI = dyn_cast<AtomicCmpXchgInst>(this))
return CXI->isVolatile() == cast<AtomicCmpXchgInst>(I)->isVolatile() &&
- CXI->getOrdering() == cast<AtomicCmpXchgInst>(I)->getOrdering() &&
+ CXI->getSuccessOrdering() ==
+ cast<AtomicCmpXchgInst>(I)->getSuccessOrdering() &&
+ CXI->getFailureOrdering() ==
+ cast<AtomicCmpXchgInst>(I)->getFailureOrdering() &&
CXI->getSynchScope() == cast<AtomicCmpXchgInst>(I)->getSynchScope();
if (const AtomicRMWInst *RMWI = dyn_cast<AtomicRMWInst>(this))
return RMWI->getOperation() == cast<AtomicRMWInst>(I)->getOperation() &&
@@ -399,18 +405,18 @@ bool Instruction::isSameOperationAs(const Instruction *I,
/// specified block. Note that PHI nodes are considered to evaluate their
/// operands in the corresponding predecessor block.
bool Instruction::isUsedOutsideOfBlock(const BasicBlock *BB) const {
- for (const_use_iterator UI = use_begin(), E = use_end(); UI != E; ++UI) {
+ for (const Use &U : uses()) {
// PHI nodes uses values in the corresponding predecessor block. For other
// instructions, just check to see whether the parent of the use matches up.
- const User *U = *UI;
- const PHINode *PN = dyn_cast<PHINode>(U);
+ const Instruction *I = cast<Instruction>(U.getUser());
+ const PHINode *PN = dyn_cast<PHINode>(I);
if (PN == 0) {
- if (cast<Instruction>(U)->getParent() != BB)
+ if (I->getParent() != BB)
return true;
continue;
}
- if (PN->getIncomingBlock(UI) != BB)
+ if (PN->getIncomingBlock(U) != BB)
return true;
}
return false;
@@ -548,8 +554,8 @@ Instruction *Instruction::clone() const {
// new one.
SmallVector<std::pair<unsigned, MDNode*>, 4> TheMDs;
getAllMetadataOtherThanDebugLoc(TheMDs);
- for (unsigned i = 0, e = TheMDs.size(); i != e; ++i)
- New->setMetadata(TheMDs[i].first, TheMDs[i].second);
+ for (const auto &MD : TheMDs)
+ New->setMetadata(MD.first, MD.second);
New->setDebugLoc(getDebugLoc());
return New;
diff --git a/lib/IR/Instructions.cpp b/lib/IR/Instructions.cpp
index 8a6b77b..3aa8413 100644
--- a/lib/IR/Instructions.cpp
+++ b/lib/IR/Instructions.cpp
@@ -14,14 +14,14 @@
#include "llvm/IR/Instructions.h"
#include "LLVMContextImpl.h"
+#include "llvm/IR/CallSite.h"
+#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
-#include "llvm/Support/CallSite.h"
-#include "llvm/Support/ConstantRange.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MathExtras.h"
using namespace llvm;
@@ -893,7 +893,8 @@ void AllocaInst::setAlignment(unsigned Align) {
assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!");
assert(Align <= MaximumAlignment &&
"Alignment is greater than MaximumAlignment!");
- setInstructionSubclassData(Log2_32(Align) + 1);
+ setInstructionSubclassData((getSubclassDataFromInstruction() & ~31) |
+ (Log2_32(Align) + 1));
assert(getAlignment() == Align && "Alignment representation error!");
}
@@ -916,7 +917,7 @@ bool AllocaInst::isStaticAlloca() const {
// Must be in the entry block.
const BasicBlock *Parent = getParent();
- return Parent == &Parent->getParent()->front();
+ return Parent == &Parent->getParent()->front() && !isUsedWithInAlloca();
}
//===----------------------------------------------------------------------===//
@@ -1083,7 +1084,7 @@ void StoreInst::AssertOK() {
cast<PointerType>(getOperand(1)->getType())->getElementType()
&& "Ptr must be a pointer to Val type!");
assert(!(isAtomic() && getAlignment() == 0) &&
- "Alignment required for atomic load");
+ "Alignment required for atomic store");
}
@@ -1215,12 +1216,14 @@ void StoreInst::setAlignment(unsigned Align) {
//===----------------------------------------------------------------------===//
void AtomicCmpXchgInst::Init(Value *Ptr, Value *Cmp, Value *NewVal,
- AtomicOrdering Ordering,
+ AtomicOrdering SuccessOrdering,
+ AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope) {
Op<0>() = Ptr;
Op<1>() = Cmp;
Op<2>() = NewVal;
- setOrdering(Ordering);
+ setSuccessOrdering(SuccessOrdering);
+ setFailureOrdering(FailureOrdering);
setSynchScope(SynchScope);
assert(getOperand(0) && getOperand(1) && getOperand(2) &&
@@ -1233,30 +1236,38 @@ void AtomicCmpXchgInst::Init(Value *Ptr, Value *Cmp, Value *NewVal,
assert(getOperand(2)->getType() ==
cast<PointerType>(getOperand(0)->getType())->getElementType()
&& "Ptr must be a pointer to NewVal type!");
- assert(Ordering != NotAtomic &&
+ assert(SuccessOrdering != NotAtomic &&
+ "AtomicCmpXchg instructions must be atomic!");
+ assert(FailureOrdering != NotAtomic &&
"AtomicCmpXchg instructions must be atomic!");
+ assert(SuccessOrdering >= FailureOrdering &&
+ "AtomicCmpXchg success ordering must be at least as strong as fail");
+ assert(FailureOrdering != Release && FailureOrdering != AcquireRelease &&
+ "AtomicCmpXchg failure ordering cannot include release semantics");
}
AtomicCmpXchgInst::AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal,
- AtomicOrdering Ordering,
+ AtomicOrdering SuccessOrdering,
+ AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope,
Instruction *InsertBefore)
: Instruction(Cmp->getType(), AtomicCmpXchg,
OperandTraits<AtomicCmpXchgInst>::op_begin(this),
OperandTraits<AtomicCmpXchgInst>::operands(this),
InsertBefore) {
- Init(Ptr, Cmp, NewVal, Ordering, SynchScope);
+ Init(Ptr, Cmp, NewVal, SuccessOrdering, FailureOrdering, SynchScope);
}
AtomicCmpXchgInst::AtomicCmpXchgInst(Value *Ptr, Value *Cmp, Value *NewVal,
- AtomicOrdering Ordering,
+ AtomicOrdering SuccessOrdering,
+ AtomicOrdering FailureOrdering,
SynchronizationScope SynchScope,
BasicBlock *InsertAtEnd)
: Instruction(Cmp->getType(), AtomicCmpXchg,
OperandTraits<AtomicCmpXchgInst>::op_begin(this),
OperandTraits<AtomicCmpXchgInst>::operands(this),
InsertAtEnd) {
- Init(Ptr, Cmp, NewVal, Ordering, SynchScope);
+ Init(Ptr, Cmp, NewVal, SuccessOrdering, FailureOrdering, SynchScope);
}
//===----------------------------------------------------------------------===//
@@ -1577,11 +1588,11 @@ bool ShuffleVectorInst::isValidOperands(const Value *V1, const Value *V2,
if (const ConstantVector *MV = dyn_cast<ConstantVector>(Mask)) {
unsigned V1Size = cast<VectorType>(V1->getType())->getNumElements();
- for (unsigned i = 0, e = MV->getNumOperands(); i != e; ++i) {
- if (ConstantInt *CI = dyn_cast<ConstantInt>(MV->getOperand(i))) {
+ for (Value *Op : MV->operands()) {
+ if (ConstantInt *CI = dyn_cast<ConstantInt>(Op)) {
if (CI->uge(V1Size*2))
return false;
- } else if (!isa<UndefValue>(MV->getOperand(i))) {
+ } else if (!isa<UndefValue>(Op)) {
return false;
}
}
@@ -1701,8 +1712,7 @@ ExtractValueInst::ExtractValueInst(const ExtractValueInst &EVI)
//
Type *ExtractValueInst::getIndexedType(Type *Agg,
ArrayRef<unsigned> Idxs) {
- for (unsigned CurIdx = 0; CurIdx != Idxs.size(); ++CurIdx) {
- unsigned Index = Idxs[CurIdx];
+ for (unsigned Index : Idxs) {
// We can't use CompositeType::indexValid(Index) here.
// indexValid() always returns true for arrays because getelementptr allows
// out-of-bounds indices. Since we don't allow those for extractvalue and
@@ -2114,8 +2124,27 @@ bool CastInst::isNoopCast(Type *IntPtrTy) const {
return isNoopCast(getOpcode(), getOperand(0)->getType(), getType(), IntPtrTy);
}
-/// This function determines if a pair of casts can be eliminated and what
-/// opcode should be used in the elimination. This assumes that there are two
+bool CastInst::isNoopCast(const DataLayout *DL) const {
+ if (!DL) {
+ // Assume maximum pointer size.
+ return isNoopCast(Type::getInt64Ty(getContext()));
+ }
+
+ Type *PtrOpTy = 0;
+ if (getOpcode() == Instruction::PtrToInt)
+ PtrOpTy = getOperand(0)->getType();
+ else if (getOpcode() == Instruction::IntToPtr)
+ PtrOpTy = getType();
+
+ Type *IntPtrTy = PtrOpTy
+ ? DL->getIntPtrType(PtrOpTy)
+ : DL->getIntPtrType(getContext(), 0);
+
+ return isNoopCast(getOpcode(), getOperand(0)->getType(), getType(), IntPtrTy);
+}
+
+/// This function determines if a pair of casts can be eliminated and what
+/// opcode should be used in the elimination. This assumes that there are two
/// instructions like this:
/// * %F = firstOpcode SrcTy %x to MidTy
/// * %S = secondOpcode MidTy %F to DstTy
@@ -2206,7 +2235,7 @@ unsigned CastInst::isEliminableCastPair(
case 3:
// 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.
+ // non-vector type.
if (!SrcTy->isVectorTy() && DstTy->isIntegerTy())
return firstOp;
return 0;
@@ -2817,30 +2846,55 @@ CastInst::castIsValid(Instruction::CastOps op, Value *S, Type *DstTy) {
return false;
return SrcTy->getScalarType()->isIntegerTy() &&
DstTy->getScalarType()->isPointerTy();
- case Instruction::BitCast:
+ case Instruction::BitCast: {
+ PointerType *SrcPtrTy = dyn_cast<PointerType>(SrcTy->getScalarType());
+ PointerType *DstPtrTy = dyn_cast<PointerType>(DstTy->getScalarType());
+
// BitCast implies a no-op cast of type only. No bits change.
// However, you can't cast pointers to anything but pointers.
- if (SrcTy->isPtrOrPtrVectorTy() != DstTy->isPtrOrPtrVectorTy())
+ if (!SrcPtrTy != !DstPtrTy)
return false;
- // For non pointer cases, the cast is okay if the source and destination bit
+ // For non-pointer cases, the cast is okay if the source and destination bit
// widths are identical.
- if (!SrcTy->isPtrOrPtrVectorTy())
+ if (!SrcPtrTy)
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());
+ // If both are pointers then the address spaces must match.
+ if (SrcPtrTy->getAddressSpace() != DstPtrTy->getAddressSpace())
+ return false;
+
+ // A vector of pointers must have the same number of elements.
+ if (VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy)) {
+ if (VectorType *DstVecTy = dyn_cast<VectorType>(DstTy))
+ return (SrcVecTy->getNumElements() == DstVecTy->getNumElements());
+
+ return false;
+ }
+
+ return true;
+ }
+ case Instruction::AddrSpaceCast: {
+ PointerType *SrcPtrTy = dyn_cast<PointerType>(SrcTy->getScalarType());
+ if (!SrcPtrTy)
+ return false;
+
+ PointerType *DstPtrTy = dyn_cast<PointerType>(DstTy->getScalarType());
+ if (!DstPtrTy)
+ return false;
+
+ if (SrcPtrTy->getAddressSpace() == DstPtrTy->getAddressSpace())
+ return false;
+
+ if (VectorType *SrcVecTy = dyn_cast<VectorType>(SrcTy)) {
+ if (VectorType *DstVecTy = dyn_cast<VectorType>(DstTy))
+ return (SrcVecTy->getNumElements() == DstVecTy->getNumElements());
+
+ return false;
+ }
+
+ return true;
+ }
}
}
@@ -3552,7 +3606,8 @@ StoreInst *StoreInst::clone_impl() const {
AtomicCmpXchgInst *AtomicCmpXchgInst::clone_impl() const {
AtomicCmpXchgInst *Result =
new AtomicCmpXchgInst(getOperand(0), getOperand(1), getOperand(2),
- getOrdering(), getSynchScope());
+ getSuccessOrdering(), getFailureOrdering(),
+ getSynchScope());
Result->setVolatile(isVolatile());
return Result;
}
diff --git a/lib/IR/IntrinsicInst.cpp b/lib/IR/IntrinsicInst.cpp
index 51f88d2..554f2be 100644
--- a/lib/IR/IntrinsicInst.cpp
+++ b/lib/IR/IntrinsicInst.cpp
@@ -1,4 +1,4 @@
-//===-- InstrinsicInst.cpp - Intrinsic Instruction Wrappers -----*- C++ -*-===//
+//===-- InstrinsicInst.cpp - Intrinsic Instruction Wrappers ---------------===//
//
// The LLVM Compiler Infrastructure
//
diff --git a/lib/IR/LLVMContext.cpp b/lib/IR/LLVMContext.cpp
index 883bb98..1bfc515 100644
--- a/lib/IR/LLVMContext.cpp
+++ b/lib/IR/LLVMContext.cpp
@@ -15,6 +15,8 @@
#include "llvm/IR/LLVMContext.h"
#include "LLVMContextImpl.h"
#include "llvm/IR/Constants.h"
+#include "llvm/IR/DiagnosticInfo.h"
+#include "llvm/IR/DiagnosticPrinter.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Metadata.h"
#include "llvm/Support/ManagedStatic.h"
@@ -98,31 +100,59 @@ void *LLVMContext::getInlineAsmDiagnosticContext() const {
return pImpl->InlineAsmDiagContext;
}
+void LLVMContext::setDiagnosticHandler(DiagnosticHandlerTy DiagnosticHandler,
+ void *DiagnosticContext) {
+ pImpl->DiagnosticHandler = DiagnosticHandler;
+ pImpl->DiagnosticContext = DiagnosticContext;
+}
+
+LLVMContext::DiagnosticHandlerTy LLVMContext::getDiagnosticHandler() const {
+ return pImpl->DiagnosticHandler;
+}
+
+void *LLVMContext::getDiagnosticContext() const {
+ return pImpl->DiagnosticContext;
+}
+
void LLVMContext::emitError(const Twine &ErrorStr) {
- emitError(0U, ErrorStr);
+ diagnose(DiagnosticInfoInlineAsm(ErrorStr));
}
void LLVMContext::emitError(const Instruction *I, const Twine &ErrorStr) {
- unsigned LocCookie = 0;
- if (const MDNode *SrcLoc = I->getMetadata("srcloc")) {
- if (SrcLoc->getNumOperands() != 0)
- if (const ConstantInt *CI = dyn_cast<ConstantInt>(SrcLoc->getOperand(0)))
- LocCookie = CI->getZExtValue();
- }
- return emitError(LocCookie, ErrorStr);
+ assert (I && "Invalid instruction");
+ diagnose(DiagnosticInfoInlineAsm(*I, ErrorStr));
}
-void LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) {
- // If there is no error handler installed, just print the error and exit.
- if (pImpl->InlineAsmDiagHandler == 0) {
- errs() << "error: " << ErrorStr << "\n";
+void LLVMContext::diagnose(const DiagnosticInfo &DI) {
+ // If there is a report handler, use it.
+ if (pImpl->DiagnosticHandler != 0) {
+ pImpl->DiagnosticHandler(DI, pImpl->DiagnosticContext);
+ return;
+ }
+ // Otherwise, print the message with a prefix based on the severity.
+ std::string MsgStorage;
+ raw_string_ostream Stream(MsgStorage);
+ DiagnosticPrinterRawOStream DP(Stream);
+ DI.print(DP);
+ Stream.flush();
+ switch (DI.getSeverity()) {
+ case DS_Error:
+ errs() << "error: " << MsgStorage << "\n";
exit(1);
+ case DS_Warning:
+ errs() << "warning: " << MsgStorage << "\n";
+ break;
+ case DS_Remark:
+ errs() << "remark: " << MsgStorage << "\n";
+ break;
+ case DS_Note:
+ errs() << "note: " << MsgStorage << "\n";
+ break;
}
+}
- // If we do have an error handler, we can report the error and keep going.
- SMDiagnostic Diag("", SourceMgr::DK_Error, ErrorStr.str());
-
- pImpl->InlineAsmDiagHandler(Diag, pImpl->InlineAsmDiagContext, LocCookie);
+void LLVMContext::emitError(unsigned LocCookie, const Twine &ErrorStr) {
+ diagnose(DiagnosticInfoInlineAsm(LocCookie, ErrorStr));
}
//===----------------------------------------------------------------------===//
diff --git a/lib/IR/LLVMContextImpl.cpp b/lib/IR/LLVMContextImpl.cpp
index 6a6a4d6..ebff9d3 100644
--- a/lib/IR/LLVMContextImpl.cpp
+++ b/lib/IR/LLVMContextImpl.cpp
@@ -37,6 +37,8 @@ LLVMContextImpl::LLVMContextImpl(LLVMContext &C)
Int64Ty(C, 64) {
InlineAsmDiagHandler = 0;
InlineAsmDiagContext = 0;
+ DiagnosticHandler = 0;
+ DiagnosticContext = 0;
NamedStructTypesUniqueID = 0;
}
diff --git a/lib/IR/LLVMContextImpl.h b/lib/IR/LLVMContextImpl.h
index 407b985..dc77d29 100644
--- a/lib/IR/LLVMContextImpl.h
+++ b/lib/IR/LLVMContextImpl.h
@@ -30,7 +30,7 @@
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
-#include "llvm/Support/ValueHandle.h"
+#include "llvm/IR/ValueHandle.h"
#include <vector>
namespace llvm {
@@ -225,9 +225,9 @@ public:
MDNode *get() const {
return cast_or_null<MDNode>(getValPtr());
}
-
- virtual void deleted();
- virtual void allUsesReplacedWith(Value *VNew);
+
+ void deleted() override;
+ void allUsesReplacedWith(Value *VNew) override;
};
class LLVMContextImpl {
@@ -238,9 +238,12 @@ public:
LLVMContext::InlineAsmDiagHandlerTy InlineAsmDiagHandler;
void *InlineAsmDiagContext;
-
- typedef DenseMap<DenseMapAPIntKeyInfo::KeyTy, ConstantInt*,
- DenseMapAPIntKeyInfo> IntMapTy;
+
+ LLVMContext::DiagnosticHandlerTy DiagnosticHandler;
+ void *DiagnosticContext;
+
+ typedef DenseMap<DenseMapAPIntKeyInfo::KeyTy, ConstantInt *,
+ DenseMapAPIntKeyInfo> IntMapTy;
IntMapTy IntConstants;
typedef DenseMap<DenseMapAPFloatKeyInfo::KeyTy, ConstantFP*,
@@ -278,8 +281,8 @@ public:
StringMap<ConstantDataSequential*> CDSConstants;
-
- DenseMap<std::pair<Function*, BasicBlock*> , BlockAddress*> BlockAddresses;
+ DenseMap<std::pair<const Function *, const BasicBlock *>, BlockAddress *>
+ BlockAddresses;
ConstantUniqueMap<ExprMapKeyType, const ExprMapKeyType&, Type, ConstantExpr>
ExprConstants;
@@ -349,7 +352,12 @@ public:
/// for an index. The ValueHandle ensures that ScopeINlinedAtIdx stays up
/// to date.
std::vector<std::pair<DebugRecVH, DebugRecVH> > ScopeInlinedAtRecords;
-
+
+ /// DiscriminatorTable - This table maps file:line locations to an
+ /// integer representing the next DWARF path discriminator to assign to
+ /// instructions in different blocks at the same location.
+ DenseMap<std::pair<const char *, unsigned>, unsigned> DiscriminatorTable;
+
/// IntrinsicIDCache - Cache of intrinsic name (string) to numeric ID mappings
/// requested in this context
typedef DenseMap<const Function*, unsigned> IntrinsicIDCacheTy;
diff --git a/lib/IR/LeakDetector.cpp b/lib/IR/LeakDetector.cpp
index 835e5e6..6f71627 100644
--- a/lib/IR/LeakDetector.cpp
+++ b/lib/IR/LeakDetector.cpp
@@ -11,7 +11,7 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Support/LeakDetector.h"
+#include "llvm/IR/LeakDetector.h"
#include "LLVMContextImpl.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/IR/Value.h"
diff --git a/lib/IR/LegacyPassManager.cpp b/lib/IR/LegacyPassManager.cpp
index a431d82..7c5cc68 100644
--- a/lib/IR/LegacyPassManager.cpp
+++ b/lib/IR/LegacyPassManager.cpp
@@ -12,17 +12,16 @@
//===----------------------------------------------------------------------===//
-#include "llvm/Assembly/PrintModulePass.h"
-#include "llvm/Assembly/Writer.h"
+#include "llvm/IR/IRPrintingPasses.h"
#include "llvm/IR/LegacyPassManager.h"
-#include "llvm/IR/Module.h"
#include "llvm/IR/LegacyPassManagers.h"
+#include "llvm/IR/LegacyPassNameParser.h"
+#include "llvm/IR/Module.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>
@@ -144,7 +143,7 @@ void PassManagerPrettyStackEntry::print(raw_ostream &OS) const {
OS << "value";
OS << " '";
- WriteAsOperand(OS, V, /*PrintTy=*/false, M);
+ V->printAsOperand(OS, /*PrintTy=*/false, M);
OS << "'\n";
}
@@ -165,28 +164,28 @@ public:
/// 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);
+ bool runOnFunction(Function &F) override;
/// Pass Manager itself does not invalidate any analysis info.
- void getAnalysisUsage(AnalysisUsage &Info) const {
+ void getAnalysisUsage(AnalysisUsage &Info) const override {
Info.setPreservesAll();
}
- bool doInitialization(Module &M);
+ bool doInitialization(Module &M) override;
bool doInitialization(Function &F);
- bool doFinalization(Module &M);
+ bool doFinalization(Module &M) override;
bool doFinalization(Function &F);
- virtual PMDataManager *getAsPMDataManager() { return this; }
- virtual Pass *getAsPass() { return this; }
+ PMDataManager *getAsPMDataManager() override { return this; }
+ Pass *getAsPass() override { return this; }
- virtual const char *getPassName() const {
+ const char *getPassName() const override {
return "BasicBlock Pass Manager";
}
// Print passes managed by this manager
- void dumpPassStructure(unsigned Offset) {
- llvm::dbgs().indent(Offset*2) << "BasicBlockPass Manager\n";
+ void dumpPassStructure(unsigned Offset) override {
+ dbgs().indent(Offset*2) << "BasicBlockPass Manager\n";
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
BasicBlockPass *BP = getContainedPass(Index);
BP->dumpPassStructure(Offset + 1);
@@ -200,7 +199,7 @@ public:
return BP;
}
- virtual PassManagerType getPassManagerType() const {
+ PassManagerType getPassManagerType() const override {
return PMT_BasicBlockPassManager;
}
};
@@ -235,8 +234,9 @@ public:
}
/// createPrinterPass - Get a function printer pass.
- Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const {
- return createPrintFunctionPass(Banner, &O);
+ Pass *createPrinterPass(raw_ostream &O,
+ const std::string &Banner) const override {
+ return createPrintFunctionPass(O, Banner);
}
// Prepare for running an on the fly pass, freeing memory if needed
@@ -249,21 +249,21 @@ public:
/// doInitialization - Run all of the initializers for the function passes.
///
- bool doInitialization(Module &M);
+ bool doInitialization(Module &M) override;
/// doFinalization - Run all of the finalizers for the function passes.
///
- bool doFinalization(Module &M);
+ bool doFinalization(Module &M) override;
- virtual PMDataManager *getAsPMDataManager() { return this; }
- virtual Pass *getAsPass() { return this; }
- virtual PassManagerType getTopLevelPassManagerType() {
+ PMDataManager *getAsPMDataManager() override { return this; }
+ Pass *getAsPass() override { return this; }
+ PassManagerType getTopLevelPassManagerType() override {
return PMT_FunctionPassManager;
}
/// Pass Manager itself does not invalidate any analysis info.
- void getAnalysisUsage(AnalysisUsage &Info) const {
+ void getAnalysisUsage(AnalysisUsage &Info) const override {
Info.setPreservesAll();
}
@@ -304,8 +304,9 @@ public:
}
/// createPrinterPass - Get a module printer pass.
- Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const {
- return createPrintModulePass(&O, false, Banner);
+ Pass *createPrinterPass(raw_ostream &O,
+ const std::string &Banner) const override {
+ return createPrintModulePass(O, Banner);
}
/// run - Execute all of the passes scheduled for execution. Keep track of
@@ -324,30 +325,30 @@ public:
bool doFinalization();
/// Pass Manager itself does not invalidate any analysis info.
- void getAnalysisUsage(AnalysisUsage &Info) const {
+ void getAnalysisUsage(AnalysisUsage &Info) const override {
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);
+ void addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) override;
/// 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);
+ Pass* getOnTheFlyPass(Pass *MP, AnalysisID PI, Function &F) override;
- virtual const char *getPassName() const {
+ const char *getPassName() const override {
return "Module Pass Manager";
}
- virtual PMDataManager *getAsPMDataManager() { return this; }
- virtual Pass *getAsPass() { return this; }
+ PMDataManager *getAsPMDataManager() override { return this; }
+ Pass *getAsPass() override { return this; }
// Print passes managed by this manager
- void dumpPassStructure(unsigned Offset) {
- llvm::dbgs().indent(Offset*2) << "ModulePass Manager\n";
+ void dumpPassStructure(unsigned Offset) override {
+ dbgs().indent(Offset*2) << "ModulePass Manager\n";
for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) {
ModulePass *MP = getContainedPass(Index);
MP->dumpPassStructure(Offset + 1);
@@ -364,7 +365,7 @@ public:
return static_cast<ModulePass *>(PassVector[N]);
}
- virtual PassManagerType getPassManagerType() const {
+ PassManagerType getPassManagerType() const override {
return PMT_ModulePassManager;
}
@@ -404,8 +405,9 @@ public:
}
/// createPrinterPass - Get a module printer pass.
- Pass *createPrinterPass(raw_ostream &O, const std::string &Banner) const {
- return createPrintModulePass(&O, false, Banner);
+ Pass *createPrinterPass(raw_ostream &O,
+ const std::string &Banner) const override {
+ return createPrintModulePass(O, Banner);
}
/// run - Execute all of the passes scheduled for execution. Keep track of
@@ -424,13 +426,13 @@ public:
bool doFinalization();
/// Pass Manager itself does not invalidate any analysis info.
- void getAnalysisUsage(AnalysisUsage &Info) const {
+ void getAnalysisUsage(AnalysisUsage &Info) const override {
Info.setPreservesAll();
}
- virtual PMDataManager *getAsPMDataManager() { return this; }
- virtual Pass *getAsPass() { return this; }
- virtual PassManagerType getTopLevelPassManagerType() {
+ PMDataManager *getAsPMDataManager() override { return this; }
+ Pass *getAsPass() override { return this; }
+ PassManagerType getTopLevelPassManagerType() override {
return PMT_ModulePassManager;
}
@@ -475,7 +477,7 @@ public:
}
// createTheTimeInfo - This method either initializes the TheTimeInfo pointer
- // to a non null value (if the -time-passes option is enabled) or it leaves it
+ // 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();
@@ -1133,7 +1135,7 @@ void PMDataManager::dumpLastUses(Pass *P, unsigned Offset) const{
for (SmallVectorImpl<Pass *>::iterator I = LUses.begin(),
E = LUses.end(); I != E; ++I) {
- llvm::dbgs() << "--" << std::string(Offset*2, ' ');
+ dbgs() << "--" << std::string(Offset*2, ' ');
(*I)->dumpPassStructure(0);
}
}
@@ -1755,7 +1757,7 @@ 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
+// 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;
diff --git a/lib/IR/Mangler.cpp b/lib/IR/Mangler.cpp
new file mode 100644
index 0000000..d82388f
--- /dev/null
+++ b/lib/IR/Mangler.cpp
@@ -0,0 +1,144 @@
+//===-- Mangler.cpp - Self-contained c/asm llvm name mangler --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Unified name mangler for assembly backends.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/IR/Mangler.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Function.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+static void getNameWithPrefixx(raw_ostream &OS, const Twine &GVName,
+ Mangler::ManglerPrefixTy PrefixTy,
+ const DataLayout &DL, bool UseAt) {
+ SmallString<256> TmpData;
+ StringRef Name = GVName.toStringRef(TmpData);
+ assert(!Name.empty() && "getNameWithPrefix requires non-empty name");
+
+ if (PrefixTy == Mangler::Private)
+ OS << DL.getPrivateGlobalPrefix();
+ else if (PrefixTy == Mangler::LinkerPrivate)
+ OS << DL.getLinkerPrivateGlobalPrefix();
+
+ if (UseAt) {
+ OS << '@';
+ } else {
+ char Prefix = DL.getGlobalPrefix();
+ if (Prefix != '\0')
+ OS << Prefix;
+ }
+
+ // If this is a simple string that doesn't need escaping, just append it.
+ OS << Name;
+}
+
+void Mangler::getNameWithPrefix(raw_ostream &OS, const Twine &GVName,
+ ManglerPrefixTy PrefixTy) const {
+ return getNameWithPrefixx(OS, GVName, PrefixTy, *DL, false);
+}
+
+void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,
+ const Twine &GVName,
+ ManglerPrefixTy PrefixTy) const {
+ raw_svector_ostream OS(OutName);
+ return getNameWithPrefix(OS, GVName, PrefixTy);
+}
+
+/// AddFastCallStdCallSuffix - Microsoft fastcall and stdcall functions require
+/// a suffix on their name indicating the number of words of arguments they
+/// take.
+static void AddFastCallStdCallSuffix(raw_ostream &OS, const Function *F,
+ const DataLayout &TD) {
+ // Calculate arguments size total.
+ unsigned ArgWords = 0;
+ for (Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
+ AI != AE; ++AI) {
+ Type *Ty = AI->getType();
+ // 'Dereference' type in case of byval or inalloca parameter attribute.
+ if (AI->hasByValOrInAllocaAttr())
+ Ty = cast<PointerType>(Ty)->getElementType();
+ // Size should be aligned to DWORD boundary
+ ArgWords += ((TD.getTypeAllocSize(Ty) + 3)/4)*4;
+ }
+
+ OS << '@' << ArgWords;
+}
+
+void Mangler::getNameWithPrefix(raw_ostream &OS, const GlobalValue *GV,
+ bool CannotUsePrivateLabel) const {
+ ManglerPrefixTy PrefixTy = Mangler::Default;
+ if (GV->hasPrivateLinkage()) {
+ if (CannotUsePrivateLabel)
+ PrefixTy = Mangler::LinkerPrivate;
+ else
+ PrefixTy = Mangler::Private;
+ }
+
+ if (!GV->hasName()) {
+ // Get the ID for the global, assigning a new one if we haven't got one
+ // already.
+ unsigned &ID = AnonGlobalIDs[GV];
+ if (ID == 0)
+ ID = NextAnonGlobalID++;
+
+ // Must mangle the global into a unique ID.
+ getNameWithPrefix(OS, "__unnamed_" + Twine(ID), PrefixTy);
+ return;
+ }
+
+ StringRef Name = GV->getName();
+
+ // No need to do anything special if the global has the special "do not
+ // mangle" flag in the name.
+ if (Name[0] == '\1') {
+ OS << Name.substr(1);
+ return;
+ }
+
+ bool UseAt = false;
+ const Function *MSFunc = NULL;
+ CallingConv::ID CC;
+ if (DL->hasMicrosoftFastStdCallMangling()) {
+ if ((MSFunc = dyn_cast<Function>(GV))) {
+ CC = MSFunc->getCallingConv();
+ // fastcall functions need to start with @ instead of _.
+ if (CC == CallingConv::X86_FastCall)
+ UseAt = true;
+ }
+ }
+
+ getNameWithPrefixx(OS, Name, PrefixTy, *DL, UseAt);
+
+ if (!MSFunc)
+ return;
+
+ // If we are supposed to add a microsoft-style suffix for stdcall/fastcall,
+ // add it.
+ // fastcall and stdcall functions usually need @42 at the end to specify
+ // the argument info.
+ FunctionType *FT = MSFunc->getFunctionType();
+ if ((CC == CallingConv::X86_FastCall || CC == CallingConv::X86_StdCall) &&
+ // "Pure" variadic functions do not receive @0 suffix.
+ (!FT->isVarArg() || FT->getNumParams() == 0 ||
+ (FT->getNumParams() == 1 && MSFunc->hasStructRetAttr())))
+ AddFastCallStdCallSuffix(OS, MSFunc, *DL);
+}
+
+void Mangler::getNameWithPrefix(SmallVectorImpl<char> &OutName,
+ const GlobalValue *GV,
+ bool CannotUsePrivateLabel) const {
+ raw_svector_ostream OS(OutName);
+ getNameWithPrefix(OS, GV, CannotUsePrivateLabel);
+}
diff --git a/lib/IR/Metadata.cpp b/lib/IR/Metadata.cpp
index a32d25c..ba39334 100644
--- a/lib/IR/Metadata.cpp
+++ b/lib/IR/Metadata.cpp
@@ -16,14 +16,15 @@
#include "SymbolTableListTraitsImpl.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringMap.h"
+#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/LLVMContext.h"
+#include "llvm/IR/LeakDetector.h"
#include "llvm/IR/Module.h"
-#include "llvm/Support/ConstantRange.h"
-#include "llvm/Support/LeakDetector.h"
-#include "llvm/Support/ValueHandle.h"
+#include "llvm/IR/ValueHandle.h"
using namespace llvm;
//===----------------------------------------------------------------------===//
@@ -77,8 +78,8 @@ public:
/// the list.
void setAsFirstOperand(unsigned V) { this->setValPtrInt(V); }
- virtual void deleted();
- virtual void allUsesReplacedWith(Value *NV);
+ void deleted() override;
+ void allUsesReplacedWith(Value *NV) override;
};
} // end namespace llvm.
@@ -223,8 +224,8 @@ MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef<Value*> Vals,
// Note that if the operands are later nulled out, the node will be
// removed from the uniquing map.
FoldingSetNodeID ID;
- for (unsigned i = 0; i != Vals.size(); ++i)
- ID.AddPointer(Vals[i]);
+ for (Value *V : Vals)
+ ID.AddPointer(V);
void *InsertPoint;
MDNode *N = pImpl->MDNodeSet.FindNodeOrInsertPos(ID, InsertPoint);
@@ -235,8 +236,7 @@ MDNode *MDNode::getMDNode(LLVMContext &Context, ArrayRef<Value*> Vals,
bool isFunctionLocal = false;
switch (FL) {
case FL_Unknown:
- for (unsigned i = 0; i != Vals.size(); ++i) {
- Value *V = Vals[i];
+ for (Value *V : Vals) {
if (!V) continue;
if (isFunctionLocalValue(V)) {
isFunctionLocal = true;
@@ -583,6 +583,50 @@ MDNode *Instruction::getMetadataImpl(StringRef Kind) const {
return getMetadataImpl(getContext().getMDKindID(Kind));
}
+void Instruction::dropUnknownMetadata(ArrayRef<unsigned> KnownIDs) {
+ SmallSet<unsigned, 5> KnownSet;
+ KnownSet.insert(KnownIDs.begin(), KnownIDs.end());
+
+ // Drop debug if needed
+ if (KnownSet.erase(LLVMContext::MD_dbg))
+ DbgLoc = DebugLoc();
+
+ if (!hasMetadataHashEntry())
+ return; // Nothing to remove!
+
+ DenseMap<const Instruction *, LLVMContextImpl::MDMapTy> &MetadataStore =
+ getContext().pImpl->MetadataStore;
+
+ if (KnownSet.empty()) {
+ // Just drop our entry at the store.
+ MetadataStore.erase(this);
+ setHasMetadataHashEntry(false);
+ return;
+ }
+
+ LLVMContextImpl::MDMapTy &Info = MetadataStore[this];
+ unsigned I;
+ unsigned E;
+ // Walk the array and drop any metadata we don't know.
+ for (I = 0, E = Info.size(); I != E;) {
+ if (KnownSet.count(Info[I].first)) {
+ ++I;
+ continue;
+ }
+
+ Info[I] = Info.back();
+ Info.pop_back();
+ --E;
+ }
+ assert(E == Info.size());
+
+ if (E == 0) {
+ // Drop our entry at the store.
+ MetadataStore.erase(this);
+ setHasMetadataHashEntry(false);
+ }
+}
+
/// setMetadata - Set the metadata of of the specified kind to the specified
/// node. This updates/replaces metadata if already present, or removes it if
/// Node is null.
@@ -604,9 +648,9 @@ void Instruction::setMetadata(unsigned KindID, MDNode *Node) {
setHasMetadataHashEntry(true);
} else {
// Handle replacement of an existing value.
- for (unsigned i = 0, e = Info.size(); i != e; ++i)
- if (Info[i].first == KindID) {
- Info[i].second = Node;
+ for (auto &P : Info)
+ if (P.first == KindID) {
+ P.second = Node;
return;
}
}
@@ -652,10 +696,9 @@ MDNode *Instruction::getMetadataImpl(unsigned KindID) const {
LLVMContextImpl::MDMapTy &Info = getContext().pImpl->MetadataStore[this];
assert(!Info.empty() && "bit out of sync with hash table");
- for (LLVMContextImpl::MDMapTy::iterator I = Info.begin(), E = Info.end();
- I != E; ++I)
- if (I->first == KindID)
- return I->second;
+ for (const auto &I : Info)
+ if (I.first == KindID)
+ return I.second;
return 0;
}
diff --git a/lib/IR/Module.cpp b/lib/IR/Module.cpp
index 4f240c7..1accd47 100644
--- a/lib/IR/Module.cpp
+++ b/lib/IR/Module.cpp
@@ -17,12 +17,12 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/GVMaterializer.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/GVMaterializer.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/LLVMContext.h"
-#include "llvm/Support/LeakDetector.h"
+#include "llvm/IR/LeakDetector.h"
#include <algorithm>
#include <cstdarg>
#include <cstdlib>
@@ -42,8 +42,8 @@ template class llvm::SymbolTableListTraits<GlobalAlias, Module>;
// Primitive Module methods.
//
-Module::Module(StringRef MID, LLVMContext& C)
- : Context(C), Materializer(NULL), ModuleID(MID) {
+Module::Module(StringRef MID, LLVMContext &C)
+ : Context(C), Materializer(), ModuleID(MID), DL("") {
ValSymTab = new ValueSymbolTable();
NamedMDSymTab = new StringMap<NamedMDNode *>();
Context.addModule(this);
@@ -60,51 +60,6 @@ Module::~Module() {
delete static_cast<StringMap<NamedMDNode *> *>(NamedMDSymTab);
}
-/// Target endian information.
-Module::Endianness Module::getEndianness() const {
- StringRef temp = DataLayout;
- Module::Endianness ret = AnyEndianness;
-
- while (!temp.empty()) {
- std::pair<StringRef, StringRef> P = getToken(temp, "-");
-
- StringRef token = P.first;
- temp = P.second;
-
- if (token[0] == 'e') {
- ret = LittleEndian;
- } else if (token[0] == 'E') {
- ret = BigEndian;
- }
- }
-
- return ret;
-}
-
-/// Target Pointer Size information.
-Module::PointerSize Module::getPointerSize() const {
- StringRef temp = DataLayout;
- Module::PointerSize ret = AnyPointerSize;
-
- while (!temp.empty()) {
- std::pair<StringRef, StringRef> TmpP = getToken(temp, "-");
- temp = TmpP.second;
- TmpP = getToken(TmpP.first, ":");
- StringRef token = TmpP.second, signalToken = TmpP.first;
-
- if (signalToken[0] == 'p') {
- int size = 0;
- getToken(token, ":").first.getAsInteger(10, size);
- if (size == 32)
- ret = Pointer32;
- else if (size == 64)
- ret = Pointer64;
- }
- }
-
- return ret;
-}
-
/// getNamedValue - Return the first global value in the module with
/// the specified name, of arbitrary type. This method returns null
/// if a global with the specified name is not found.
@@ -149,16 +104,6 @@ Constant *Module::getOrInsertFunction(StringRef Name,
return New; // Return the new prototype.
}
- // Okay, the function exists. Does it have externally visible linkage?
- if (F->hasLocalLinkage()) {
- // Clear the function's name.
- F->setName("");
- // Retry, now there won't be a conflict.
- Constant *NewF = getOrInsertFunction(Name, Ty);
- F->setName(Name);
- return NewF;
- }
-
// If the function exists but has the wrong type, return a bitcast to the
// right type.
if (F->getType() != PointerType::getUnqual(Ty))
@@ -316,8 +261,7 @@ getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const {
const NamedMDNode *ModFlags = getModuleFlagsMetadata();
if (!ModFlags) return;
- for (unsigned i = 0, e = ModFlags->getNumOperands(); i != e; ++i) {
- MDNode *Flag = ModFlags->getOperand(i);
+ for (const MDNode *Flag : ModFlags->operands()) {
if (Flag->getNumOperands() >= 3 && isa<ConstantInt>(Flag->getOperand(0)) &&
isa<MDString>(Flag->getOperand(1))) {
// Check the operands of the MDNode before accessing the operands.
@@ -336,8 +280,7 @@ getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const {
Value *Module::getModuleFlag(StringRef Key) const {
SmallVector<Module::ModuleFlagEntry, 8> ModuleFlags;
getModuleFlagsMetadata(ModuleFlags);
- for (unsigned I = 0, E = ModuleFlags.size(); I < E; ++I) {
- const ModuleFlagEntry &MFE = ModuleFlags[I];
+ for (const ModuleFlagEntry &MFE : ModuleFlags) {
if (Key == MFE.Key->getString())
return MFE.Val;
}
@@ -383,6 +326,34 @@ void Module::addModuleFlag(MDNode *Node) {
getOrInsertModuleFlagsMetadata()->addOperand(Node);
}
+void Module::setDataLayout(StringRef Desc) {
+ DL.reset(Desc);
+
+ if (Desc.empty()) {
+ DataLayoutStr = "";
+ } else {
+ DataLayoutStr = DL.getStringRepresentation();
+ // DataLayoutStr is now equivalent to Desc, but since the representation
+ // is not unique, they may not be identical.
+ }
+}
+
+void Module::setDataLayout(const DataLayout *Other) {
+ if (!Other) {
+ DataLayoutStr = "";
+ DL.reset("");
+ } else {
+ DL = *Other;
+ DataLayoutStr = DL.getStringRepresentation();
+ }
+}
+
+const DataLayout *Module::getDataLayout() const {
+ if (DataLayoutStr.empty())
+ return 0;
+ return &DL;
+}
+
//===----------------------------------------------------------------------===//
// Methods to control the materialization of GlobalValues in the Module.
//
@@ -422,22 +393,18 @@ void Module::Dematerialize(GlobalValue *GV) {
return Materializer->Dematerialize(GV);
}
-bool Module::MaterializeAll(std::string *ErrInfo) {
+error_code Module::materializeAll() {
if (!Materializer)
- return false;
- error_code EC = Materializer->MaterializeModule(this);
- if (!EC)
- return false;
- if (ErrInfo)
- *ErrInfo = EC.message();
- return true;
+ return error_code::success();
+ return Materializer->MaterializeModule(this);
}
-bool Module::MaterializeAllPermanently(std::string *ErrInfo) {
- if (MaterializeAll(ErrInfo))
- return true;
+error_code Module::materializeAllPermanently() {
+ if (error_code EC = materializeAll())
+ return EC;
+
Materializer.reset();
- return false;
+ return error_code::success();
}
//===----------------------------------------------------------------------===//
diff --git a/lib/IR/Pass.cpp b/lib/IR/Pass.cpp
index 7fc4828..e16c5b7 100644
--- a/lib/IR/Pass.cpp
+++ b/lib/IR/Pass.cpp
@@ -14,10 +14,11 @@
//===----------------------------------------------------------------------===//
#include "llvm/Pass.h"
-#include "llvm/Assembly/PrintModulePass.h"
+#include "llvm/IR/Function.h"
+#include "llvm/IR/IRPrintingPasses.h"
+#include "llvm/IR/LegacyPassNameParser.h"
#include "llvm/PassRegistry.h"
#include "llvm/Support/Debug.h"
-#include "llvm/Support/PassNameParser.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
@@ -35,7 +36,7 @@ ModulePass::~ModulePass() { }
Pass *ModulePass::createPrinterPass(raw_ostream &O,
const std::string &Banner) const {
- return createPrintModulePass(&O, false, Banner);
+ return createPrintModulePass(O, Banner);
}
PassManagerType ModulePass::getPotentialPassManagerType() const {
@@ -130,20 +131,29 @@ void ImmutablePass::initializePass() {
Pass *FunctionPass::createPrinterPass(raw_ostream &O,
const std::string &Banner) const {
- return createPrintFunctionPass(Banner, &O);
+ return createPrintFunctionPass(O, Banner);
}
PassManagerType FunctionPass::getPotentialPassManagerType() const {
return PMT_FunctionPassManager;
}
+bool FunctionPass::skipOptnoneFunction(const Function &F) const {
+ if (F.hasFnAttribute(Attribute::OptimizeNone)) {
+ DEBUG(dbgs() << "Skipping pass '" << getPassName()
+ << "' on function " << F.getName() << "\n");
+ return true;
+ }
+ return false;
+}
+
//===----------------------------------------------------------------------===//
// BasicBlockPass Implementation
//
Pass *BasicBlockPass::createPrinterPass(raw_ostream &O,
const std::string &Banner) const {
- return createPrintBasicBlockPass(&O, false, Banner);
+ return createPrintBasicBlockPass(O, Banner);
}
bool BasicBlockPass::doInitialization(Function &) {
@@ -156,6 +166,18 @@ bool BasicBlockPass::doFinalization(Function &) {
return false;
}
+bool BasicBlockPass::skipOptnoneFunction(const BasicBlock &BB) const {
+ const Function *F = BB.getParent();
+ if (F && F->hasFnAttribute(Attribute::OptimizeNone)) {
+ // Report this only once per function.
+ if (&BB == &F->getEntryBlock())
+ DEBUG(dbgs() << "Skipping pass '" << getPassName()
+ << "' on function " << F->getName() << "\n");
+ return true;
+ }
+ return false;
+}
+
PassManagerType BasicBlockPass::getPotentialPassManagerType() const {
return PMT_BasicBlockPassManager;
}
@@ -230,7 +252,7 @@ namespace {
VectorType &CFGOnlyList;
GetCFGOnlyPasses(VectorType &L) : CFGOnlyList(L) {}
- void passEnumerate(const PassInfo *P) {
+ void passEnumerate(const PassInfo *P) override {
if (P->isCFGOnlyPass())
CFGOnlyList.push_back(P->getTypeInfo());
}
diff --git a/lib/IR/PassManager.cpp b/lib/IR/PassManager.cpp
index 966af7d..ea15455 100644
--- a/lib/IR/PassManager.cpp
+++ b/lib/IR/PassManager.cpp
@@ -1,4 +1,4 @@
-//===- PassManager.h - Infrastructure for managing & running IR passes ----===//
+//===- PassManager.cpp - Infrastructure for managing & running IR passes --===//
//
// The LLVM Compiler Infrastructure
//
@@ -7,147 +7,138 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/IR/PassManager.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/PassManager.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
using namespace llvm;
-void ModulePassManager::run() {
- for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx)
- if (Passes[Idx]->run(M))
- if (AM) AM->invalidateAll(M);
-}
+static cl::opt<bool>
+DebugPM("debug-pass-manager", cl::Hidden,
+ cl::desc("Print pass management debugging information"));
+
+PreservedAnalyses ModulePassManager::run(Module *M, ModuleAnalysisManager *AM) {
+ PreservedAnalyses PA = PreservedAnalyses::all();
+
+ if (DebugPM)
+ dbgs() << "Starting module pass manager run.\n";
-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);
- }
- return Changed;
+ for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) {
+ if (DebugPM)
+ dbgs() << "Running module pass: " << Passes[Idx]->name() << "\n";
+
+ PreservedAnalyses PassPA = Passes[Idx]->run(M, AM);
+ if (AM)
+ AM->invalidate(M, PassPA);
+ PA.intersect(std::move(PassPA));
+ }
+
+ if (DebugPM)
+ dbgs() << "Finished module pass manager run.\n";
+
+ return PA;
}
-void AnalysisManager::invalidateAll(Function *F) {
- assert(F->getParent() == M && "Invalidating a function from another module!");
+ModuleAnalysisManager::ResultConceptT &
+ModuleAnalysisManager::getResultImpl(void *PassID, Module *M) {
+ ModuleAnalysisResultMapT::iterator RI;
+ bool Inserted;
+ std::tie(RI, Inserted) = ModuleAnalysisResults.insert(std::make_pair(
+ PassID, std::unique_ptr<detail::AnalysisResultConcept<Module *>>()));
- // 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);
+ // If we don't have a cached result for this module, look up the pass and run
+ // it to produce a result, which we then add to the cache.
+ if (Inserted)
+ RI->second = std::move(lookupPass(PassID).run(M, this));
- // 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 {
- ++I;
- }
- while (!InvalidatedPassIDs.empty())
- FunctionAnalysisResults.erase(
- std::make_pair(InvalidatedPassIDs.pop_back_val(), F));
+ return *RI->second;
}
-void AnalysisManager::invalidateAll(Module *M) {
- // First invalidate any module results we still have laying about.
+ModuleAnalysisManager::ResultConceptT *
+ModuleAnalysisManager::getCachedResultImpl(void *PassID, Module *M) const {
+ ModuleAnalysisResultMapT::const_iterator RI =
+ ModuleAnalysisResults.find(PassID);
+ return RI == ModuleAnalysisResults.end() ? 0 : &*RI->second;
+}
+
+void ModuleAnalysisManager::invalidateImpl(void *PassID, Module *M) {
+ ModuleAnalysisResults.erase(PassID);
+}
+
+void ModuleAnalysisManager::invalidateImpl(Module *M,
+ const PreservedAnalyses &PA) {
// 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))
+ if (I->second->invalidate(M, PA))
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;
- }
- while (!InvalidatedPassIDs.empty())
- FunctionAnalysisResults.erase(
- std::make_pair(InvalidatedPassIDs.pop_back_val(), F));
- }
}
-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> >()));
+PreservedAnalyses FunctionPassManager::run(Function *F,
+ FunctionAnalysisManager *AM) {
+ PreservedAnalyses PA = PreservedAnalyses::all();
- 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);
+ if (DebugPM)
+ dbgs() << "Starting function pass manager run.\n";
+
+ for (unsigned Idx = 0, Size = Passes.size(); Idx != Size; ++Idx) {
+ if (DebugPM)
+ dbgs() << "Running function pass: " << Passes[Idx]->name() << "\n";
+
+ PreservedAnalyses PassPA = Passes[Idx]->run(F, AM);
+ if (AM)
+ AM->invalidate(F, PassPA);
+ PA.intersect(std::move(PassPA));
}
- return *RI->second;
+ if (DebugPM)
+ dbgs() << "Finished function pass manager run.\n";
+
+ return PA;
}
-const AnalysisManager::AnalysisResultConcept<Function> &
-AnalysisManager::getResultImpl(void *PassID, Function *F) {
- assert(F->getParent() == M && "Analyzing a function from another module!");
+bool FunctionAnalysisManager::empty() const {
+ assert(FunctionAnalysisResults.empty() ==
+ FunctionAnalysisResultLists.empty() &&
+ "The storage and index of analysis results disagree on how many there "
+ "are!");
+ return FunctionAnalysisResults.empty();
+}
+void FunctionAnalysisManager::clear() {
+ FunctionAnalysisResults.clear();
+ FunctionAnalysisResultLists.clear();
+}
+
+FunctionAnalysisManager::ResultConceptT &
+FunctionAnalysisManager::getResultImpl(void *PassID, Function *F) {
FunctionAnalysisResultMapT::iterator RI;
bool Inserted;
- llvm::tie(RI, Inserted) = FunctionAnalysisResults.insert(std::make_pair(
+ std::tie(RI, Inserted) = FunctionAnalysisResults.insert(std::make_pair(
std::make_pair(PassID, F), FunctionAnalysisResultListT::iterator()));
+ // If we don't have a cached result for this function, look up the pass and
+ // run it to produce a result, which we then add to the cache.
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());
+ ResultList.emplace_back(PassID, lookupPass(PassID).run(F, this));
+ RI->second = std::prev(ResultList.end());
}
return *RI->second->second;
}
-void AnalysisManager::invalidateImpl(void *PassID, Module *M) {
- assert(M == this->M && "Invalidating a pass over a different module!");
- ModuleAnalysisResults.erase(PassID);
+FunctionAnalysisManager::ResultConceptT *
+FunctionAnalysisManager::getCachedResultImpl(void *PassID, Function *F) const {
+ FunctionAnalysisResultMapT::const_iterator RI =
+ FunctionAnalysisResults.find(std::make_pair(PassID, F));
+ return RI == FunctionAnalysisResults.end() ? 0 : &*RI->second->second;
}
-void AnalysisManager::invalidateImpl(void *PassID, Function *F) {
- assert(F->getParent() == M &&
- "Invalidating a pass over a function from another module!");
-
+void FunctionAnalysisManager::invalidateImpl(void *PassID, Function *F) {
FunctionAnalysisResultMapT::iterator RI =
FunctionAnalysisResults.find(std::make_pair(PassID, F));
if (RI == FunctionAnalysisResults.end())
@@ -155,3 +146,52 @@ void AnalysisManager::invalidateImpl(void *PassID, Function *F) {
FunctionAnalysisResultLists[F].erase(RI->second);
}
+
+void FunctionAnalysisManager::invalidateImpl(Function *F,
+ const PreservedAnalyses &PA) {
+ // 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, PA)) {
+ InvalidatedPassIDs.push_back(I->first);
+ I = ResultsList.erase(I);
+ } else {
+ ++I;
+ }
+ while (!InvalidatedPassIDs.empty())
+ FunctionAnalysisResults.erase(
+ std::make_pair(InvalidatedPassIDs.pop_back_val(), F));
+}
+
+char FunctionAnalysisManagerModuleProxy::PassID;
+
+FunctionAnalysisManagerModuleProxy::Result
+FunctionAnalysisManagerModuleProxy::run(Module *M) {
+ assert(FAM->empty() && "Function analyses ran prior to the module proxy!");
+ return Result(*FAM);
+}
+
+FunctionAnalysisManagerModuleProxy::Result::~Result() {
+ // Clear out the analysis manager if we're being destroyed -- it means we
+ // didn't even see an invalidate call when we got invalidated.
+ FAM->clear();
+}
+
+bool FunctionAnalysisManagerModuleProxy::Result::invalidate(
+ Module *M, const PreservedAnalyses &PA) {
+ // If this proxy isn't marked as preserved, then we can't even invalidate
+ // individual function analyses, there may be an invalid set of Function
+ // objects in the cache making it impossible to incrementally preserve them.
+ // Just clear the entire manager.
+ if (!PA.preserved(ID()))
+ FAM->clear();
+
+ // Return false to indicate that this result is still a valid proxy.
+ return false;
+}
+
+char ModuleAnalysisManagerFunctionProxy::PassID;
diff --git a/lib/IR/PassRegistry.cpp b/lib/IR/PassRegistry.cpp
index d3b2f1f..74dc0f1 100644
--- a/lib/IR/PassRegistry.cpp
+++ b/lib/IR/PassRegistry.cpp
@@ -179,6 +179,8 @@ void PassRegistry::registerAnalysisGroup(const void *InterfaceID,
assert(ImplementationInfo->getNormalCtor() &&
"Cannot specify pass as default if it does not have a default ctor");
InterfaceInfo->setNormalCtor(ImplementationInfo->getNormalCtor());
+ InterfaceInfo->setTargetMachineCtor(
+ ImplementationInfo->getTargetMachineCtor());
}
}
diff --git a/lib/IR/PrintModulePass.cpp b/lib/IR/PrintModulePass.cpp
deleted file mode 100644
index 5026bc2..0000000
--- a/lib/IR/PrintModulePass.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-//===--- IR/PrintModulePass.cpp - Module/Function Printer -----------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// PrintModulePass and PrintFunctionPass implementations.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/Assembly/PrintModulePass.h"
-#include "llvm/IR/Function.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/raw_ostream.h"
-using namespace llvm;
-
-namespace {
-
- class PrintModulePass : public ModulePass {
- std::string Banner;
- raw_ostream *Out; // raw_ostream to print on
- bool DeleteStream; // Delete the ostream in our dtor?
- public:
- static char ID;
- PrintModulePass() : ModulePass(ID), Out(&dbgs()),
- DeleteStream(false) {}
- PrintModulePass(const std::string &B, raw_ostream *o, bool DS)
- : ModulePass(ID), Banner(B), Out(o), DeleteStream(DS) {}
-
- ~PrintModulePass() {
- if (DeleteStream) delete Out;
- }
-
- bool runOnModule(Module &M) {
- (*Out) << Banner << M;
- return false;
- }
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- }
- };
-
- class PrintFunctionPass : public FunctionPass {
- std::string Banner; // String to print before each function
- raw_ostream *Out; // raw_ostream to print on
- bool DeleteStream; // Delete the ostream in our dtor?
- public:
- static char ID;
- PrintFunctionPass() : FunctionPass(ID), Banner(""), Out(&dbgs()),
- DeleteStream(false) {}
- PrintFunctionPass(const std::string &B, raw_ostream *o, bool DS)
- : FunctionPass(ID), Banner(B), Out(o), DeleteStream(DS) {}
-
- ~PrintFunctionPass() {
- if (DeleteStream) delete Out;
- }
-
- // runOnFunction - This pass just prints a banner followed by the
- // function as it's processed.
- //
- bool runOnFunction(Function &F) {
- (*Out) << Banner << static_cast<Value&>(F);
- return false;
- }
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- }
- };
-
- class PrintBasicBlockPass : public BasicBlockPass {
- std::string Banner;
- raw_ostream *Out; // raw_ostream to print on
- bool DeleteStream; // Delete the ostream in our dtor?
- public:
- static char ID;
- PrintBasicBlockPass() : BasicBlockPass(ID), Out(&dbgs()),
- DeleteStream(false) {}
- PrintBasicBlockPass(const std::string &B, raw_ostream *o, bool DS)
- : BasicBlockPass(ID), Banner(B), Out(o), DeleteStream(DS) {}
-
- ~PrintBasicBlockPass() {
- if (DeleteStream) delete Out;
- }
-
- bool runOnBasicBlock(BasicBlock &BB) {
- (*Out) << Banner << BB;
- return false;
- }
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- }
- };
-}
-
-char PrintModulePass::ID = 0;
-INITIALIZE_PASS(PrintModulePass, "print-module",
- "Print module to stderr", false, false)
-char PrintFunctionPass::ID = 0;
-INITIALIZE_PASS(PrintFunctionPass, "print-function",
- "Print function to stderr", false, false)
-char PrintBasicBlockPass::ID = 0;
-INITIALIZE_PASS(PrintBasicBlockPass, "print-bb",
- "Print BB to stderr", false, false)
-
-/// createPrintModulePass - Create and return a pass that writes the
-/// module to the specified raw_ostream.
-ModulePass *llvm::createPrintModulePass(llvm::raw_ostream *OS,
- bool DeleteStream,
- const std::string &Banner) {
- return new PrintModulePass(Banner, OS, DeleteStream);
-}
-
-/// createPrintFunctionPass - Create and return a pass that prints
-/// functions to the specified raw_ostream as they are processed.
-FunctionPass *llvm::createPrintFunctionPass(const std::string &Banner,
- llvm::raw_ostream *OS,
- bool DeleteStream) {
- return new PrintFunctionPass(Banner, OS, DeleteStream);
-}
-
-/// createPrintBasicBlockPass - Create and return a pass that writes the
-/// BB to the specified raw_ostream.
-BasicBlockPass *llvm::createPrintBasicBlockPass(llvm::raw_ostream *OS,
- bool DeleteStream,
- const std::string &Banner) {
- return new PrintBasicBlockPass(Banner, OS, DeleteStream);
-}
-
diff --git a/lib/IR/Type.cpp b/lib/IR/Type.cpp
index 432cbc9..b02509f 100644
--- a/lib/IR/Type.cpp
+++ b/lib/IR/Type.cpp
@@ -132,7 +132,7 @@ unsigned Type::getPrimitiveSizeInBits() const {
/// getScalarSizeInBits - If this is a vector type, return the
/// getPrimitiveSizeInBits value for the element type. Otherwise return the
/// getPrimitiveSizeInBits value for this type.
-unsigned Type::getScalarSizeInBits() {
+unsigned Type::getScalarSizeInBits() const {
return getScalarType()->getPrimitiveSizeInBits();
}
@@ -155,20 +155,14 @@ int Type::getFPMantissaWidth() const {
/// isSizedDerivedType - Derived types like structures and arrays are sized
/// iff all of the members of the type are sized as well. Since asking for
/// their size is relatively uncommon, move this operation out of line.
-bool Type::isSizedDerivedType() const {
- if (this->isIntegerTy())
- return true;
-
+bool Type::isSizedDerivedType(SmallPtrSet<const Type*, 4> *Visited) const {
if (const ArrayType *ATy = dyn_cast<ArrayType>(this))
- return ATy->getElementType()->isSized();
+ return ATy->getElementType()->isSized(Visited);
if (const VectorType *VTy = dyn_cast<VectorType>(this))
- return VTy->getElementType()->isSized();
-
- if (!this->isStructTy())
- return false;
+ return VTy->getElementType()->isSized(Visited);
- return cast<StructType>(this)->isSized();
+ return cast<StructType>(this)->isSized(Visited);
}
//===----------------------------------------------------------------------===//
@@ -556,17 +550,20 @@ StructType *StructType::create(StringRef Name, Type *type, ...) {
return llvm::StructType::create(Ctx, StructFields, Name);
}
-bool StructType::isSized() const {
+bool StructType::isSized(SmallPtrSet<const Type*, 4> *Visited) const {
if ((getSubclassData() & SCDB_IsSized) != 0)
return true;
if (isOpaque())
return false;
+ if (Visited && !Visited->insert(this))
+ return false;
+
// Okay, our struct is sized if all of the elements are, but if one of the
// elements is opaque, the struct isn't sized *yet*, but may become sized in
// the future, so just bail out without caching.
for (element_iterator I = element_begin(), E = element_end(); I != E; ++I)
- if (!(*I)->isSized())
+ if (!(*I)->isSized(Visited))
return false;
// Here we cheat a bit and cast away const-ness. The goal is to memoize when
diff --git a/lib/IR/Use.cpp b/lib/IR/Use.cpp
index 1d343e8..60a0c56 100644
--- a/lib/IR/Use.cpp
+++ b/lib/IR/Use.cpp
@@ -6,111 +6,76 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file implements the algorithm for finding the User of a Use.
-//
-//===----------------------------------------------------------------------===//
+#include "llvm/IR/Use.h"
+#include "llvm/IR/User.h"
#include "llvm/IR/Value.h"
#include <new>
namespace llvm {
-//===----------------------------------------------------------------------===//
-// Use swap Implementation
-//===----------------------------------------------------------------------===//
-
void Use::swap(Use &RHS) {
- Value *V1(Val);
- Value *V2(RHS.Val);
- if (V1 != V2) {
- if (V1) {
- removeFromList();
- }
-
- if (V2) {
- RHS.removeFromList();
- Val = V2;
- V2->addUse(*this);
- } else {
- Val = 0;
- }
+ if (Val == RHS.Val)
+ return;
+
+ if (Val)
+ removeFromList();
+
+ Value *OldVal = Val;
+ if (RHS.Val) {
+ RHS.removeFromList();
+ Val = RHS.Val;
+ Val->addUse(*this);
+ } else {
+ Val = 0;
+ }
- if (V1) {
- RHS.Val = V1;
- V1->addUse(RHS);
- } else {
- RHS.Val = 0;
- }
+ if (OldVal) {
+ RHS.Val = OldVal;
+ RHS.Val->addUse(RHS);
+ } else {
+ RHS.Val = 0;
}
}
-//===----------------------------------------------------------------------===//
-// Use getImpliedUser Implementation
-//===----------------------------------------------------------------------===//
-
-const Use *Use::getImpliedUser() const {
- const Use *Current = this;
-
- while (true) {
- unsigned Tag = (Current++)->Prev.getInt();
- switch (Tag) {
- case zeroDigitTag:
- case oneDigitTag:
- continue;
-
- case stopTag: {
- ++Current;
- ptrdiff_t Offset = 1;
- while (true) {
- unsigned Tag = Current->Prev.getInt();
- switch (Tag) {
- case zeroDigitTag:
- case oneDigitTag:
- ++Current;
- Offset = (Offset << 1) + Tag;
- continue;
- default:
- return Current + Offset;
- }
- }
- }
-
- case fullStopTag:
- return Current;
- }
- }
+User *Use::getUser() const {
+ const Use *End = getImpliedUser();
+ const UserRef *ref = reinterpret_cast<const UserRef *>(End);
+ return ref->getInt() ? ref->getPointer()
+ : reinterpret_cast<User *>(const_cast<Use *>(End));
}
-//===----------------------------------------------------------------------===//
-// Use initTags Implementation
-//===----------------------------------------------------------------------===//
+unsigned Use::getOperandNo() const {
+ return this - getUser()->op_begin();
+}
-Use *Use::initTags(Use * const Start, Use *Stop) {
+// Sets up the waymarking algoritm's tags for a series of Uses. See the
+// algorithm details here:
+//
+// http://www.llvm.org/docs/ProgrammersManual.html#UserLayout
+//
+Use *Use::initTags(Use *const Start, Use *Stop) {
ptrdiff_t Done = 0;
while (Done < 20) {
if (Start == Stop--)
return Start;
- static const PrevPtrTag tags[20] = { fullStopTag, oneDigitTag, stopTag,
- oneDigitTag, oneDigitTag, stopTag,
- zeroDigitTag, oneDigitTag, oneDigitTag,
- stopTag, zeroDigitTag, oneDigitTag,
- zeroDigitTag, oneDigitTag, stopTag,
- oneDigitTag, oneDigitTag, oneDigitTag,
- oneDigitTag, stopTag
- };
- new(Stop) Use(tags[Done++]);
+ static const PrevPtrTag tags[20] = {
+ fullStopTag, oneDigitTag, stopTag, oneDigitTag, oneDigitTag,
+ stopTag, zeroDigitTag, oneDigitTag, oneDigitTag, stopTag,
+ zeroDigitTag, oneDigitTag, zeroDigitTag, oneDigitTag, stopTag,
+ oneDigitTag, oneDigitTag, oneDigitTag, oneDigitTag, stopTag};
+ new (Stop) Use(tags[Done++]);
}
ptrdiff_t Count = Done;
while (Start != Stop) {
--Stop;
if (!Count) {
- new(Stop) Use(stopTag);
+ new (Stop) Use(stopTag);
++Done;
Count = Done;
} else {
- new(Stop) Use(PrevPtrTag(Count & 1));
+ new (Stop) Use(PrevPtrTag(Count & 1));
Count >>= 1;
++Done;
}
@@ -119,10 +84,6 @@ Use *Use::initTags(Use * const Start, Use *Stop) {
return Start;
}
-//===----------------------------------------------------------------------===//
-// Use zap Implementation
-//===----------------------------------------------------------------------===//
-
void Use::zap(Use *Start, const Use *Stop, bool del) {
while (Start != Stop)
(--Stop)->~Use();
@@ -130,16 +91,37 @@ void Use::zap(Use *Start, const Use *Stop, bool del) {
::operator delete(Start);
}
-//===----------------------------------------------------------------------===//
-// Use getUser Implementation
-//===----------------------------------------------------------------------===//
+const Use *Use::getImpliedUser() const {
+ const Use *Current = this;
-User *Use::getUser() const {
- const Use *End = getImpliedUser();
- const UserRef *ref = reinterpret_cast<const UserRef*>(End);
- return ref->getInt()
- ? ref->getPointer()
- : reinterpret_cast<User*>(const_cast<Use*>(End));
+ while (true) {
+ unsigned Tag = (Current++)->Prev.getInt();
+ switch (Tag) {
+ case zeroDigitTag:
+ case oneDigitTag:
+ continue;
+
+ case stopTag: {
+ ++Current;
+ ptrdiff_t Offset = 1;
+ while (true) {
+ unsigned Tag = Current->Prev.getInt();
+ switch (Tag) {
+ case zeroDigitTag:
+ case oneDigitTag:
+ ++Current;
+ Offset = (Offset << 1) + Tag;
+ continue;
+ default:
+ return Current + Offset;
+ }
+ }
+ }
+
+ case fullStopTag:
+ return Current;
+ }
+ }
}
} // End llvm namespace
diff --git a/lib/IR/Value.cpp b/lib/IR/Value.cpp
index 62a3b31..97a562e 100644
--- a/lib/IR/Value.cpp
+++ b/lib/IR/Value.cpp
@@ -18,17 +18,17 @@
#include "llvm/IR/Constant.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/GetElementPtrTypeIterator.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/LeakDetector.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
+#include "llvm/IR/ValueHandle.h"
#include "llvm/IR/ValueSymbolTable.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/GetElementPtrTypeIterator.h"
-#include "llvm/Support/LeakDetector.h"
#include "llvm/Support/ManagedStatic.h"
-#include "llvm/Support/ValueHandle.h"
#include <algorithm>
using namespace llvm;
@@ -119,7 +119,7 @@ bool Value::isUsedInBasicBlock(const BasicBlock *BB) const {
// Scan both lists simultaneously until one is exhausted. This limits the
// search to the shorter list.
BasicBlock::const_iterator BI = BB->begin(), BE = BB->end();
- const_use_iterator UI = use_begin(), UE = use_end();
+ const_user_iterator UI = user_begin(), UE = user_end();
for (; BI != BE && UI != UE; ++BI, ++UI) {
// Scan basic block: Check if this Value is used by the instruction at BI.
if (std::find(BI->op_begin(), BI->op_end(), this) != BI->op_end())
@@ -182,6 +182,8 @@ void Value::setName(const Twine &NewName) {
SmallString<256> NameData;
StringRef NameRef = NewName.toStringRef(NameData);
+ assert(NameRef.find_first_of(0) == StringRef::npos &&
+ "Null bytes are not allowed in names");
// Name isn't changing?
if (getName() == NameRef)
diff --git a/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp
index da6b573..089ad1c 100644
--- a/lib/IR/Verifier.cpp
+++ b/lib/IR/Verifier.cpp
@@ -45,31 +45,30 @@
//
//===----------------------------------------------------------------------===//
-#include "llvm/Analysis/Verifier.h"
+#include "llvm/IR/Verifier.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringExtras.h"
-#include "llvm/Analysis/Dominators.h"
-#include "llvm/Assembly/Writer.h"
-#include "llvm/DebugInfo.h"
+#include "llvm/IR/CFG.h"
+#include "llvm/IR/CallSite.h"
#include "llvm/IR/CallingConv.h"
+#include "llvm/IR/ConstantRange.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
+#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/Dominators.h"
#include "llvm/IR/InlineAsm.h"
+#include "llvm/IR/InstVisitor.h"
#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Metadata.h"
#include "llvm/IR/Module.h"
-#include "llvm/InstVisitor.h"
+#include "llvm/IR/PassManager.h"
#include "llvm/Pass.h"
-#include "llvm/PassManager.h"
-#include "llvm/Support/CFG.h"
-#include "llvm/Support/CallSite.h"
#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/ConstantRange.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
@@ -80,325 +79,258 @@ using namespace llvm;
static cl::opt<bool> DisableDebugInfoVerifier("disable-debug-info-verifier",
cl::init(true));
-namespace { // Anonymous namespace for class
- struct PreVerifier : public FunctionPass {
- static char ID; // Pass ID, replacement for typeid
-
- PreVerifier() : FunctionPass(ID) {
- initializePreVerifierPass(*PassRegistry::getPassRegistry());
- }
-
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- }
-
- // Check that the prerequisites for successful DominatorTree construction
- // are satisfied.
- bool runOnFunction(Function &F) {
- bool Broken = false;
-
- for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) {
- if (I->empty() || !I->back().isTerminator()) {
- dbgs() << "Basic Block in function '" << F.getName()
- << "' does not have terminator!\n";
- WriteAsOperand(dbgs(), I, true);
- dbgs() << "\n";
- Broken = true;
- }
- }
-
- if (Broken)
- report_fatal_error("Broken module, no Basic Block terminator!");
-
- return false;
- }
- };
-}
-
-char PreVerifier::ID = 0;
-INITIALIZE_PASS(PreVerifier, "preverify", "Preliminary module verification",
- false, false)
-static char &PreVerifyID = PreVerifier::ID;
-
namespace {
- struct Verifier : public FunctionPass, public InstVisitor<Verifier> {
- static char ID; // Pass ID, replacement for typeid
- bool Broken; // Is this module found to be broken?
- VerifierFailureAction action;
- // What to do if verification fails.
- Module *Mod; // Module we are verifying right now
- LLVMContext *Context; // Context within which we are verifying
- DominatorTree *DT; // Dominator Tree, caution can be null!
- const DataLayout *DL;
-
- std::string Messages;
- raw_string_ostream MessagesStr;
-
- /// InstInThisBlock - when verifying a basic block, keep track of all of the
- /// instructions we have seen so far. This allows us to do efficient
- /// dominance checks for the case when an instruction has an operand that is
- /// an instruction in the same block.
- SmallPtrSet<Instruction*, 16> InstsInThisBlock;
-
- /// MDNodes - keep track of the metadata nodes that have been checked
- /// already.
- SmallPtrSet<MDNode *, 32> MDNodes;
-
- /// PersonalityFn - The personality function referenced by the
- /// LandingPadInsts. All LandingPadInsts within the same function must use
- /// the same personality function.
- const Value *PersonalityFn;
-
- /// Finder keeps track of all debug info MDNodes in a Module.
- DebugInfoFinder Finder;
-
- Verifier()
- : FunctionPass(ID), Broken(false),
- action(AbortProcessAction), Mod(0), Context(0), DT(0), DL(0),
- MessagesStr(Messages), PersonalityFn(0) {
- initializeVerifierPass(*PassRegistry::getPassRegistry());
+class Verifier : public InstVisitor<Verifier> {
+ friend class InstVisitor<Verifier>;
+
+ raw_ostream &OS;
+ const Module *M;
+ LLVMContext *Context;
+ const DataLayout *DL;
+ DominatorTree DT;
+
+ /// \brief When verifying a basic block, keep track of all of the
+ /// instructions we have seen so far.
+ ///
+ /// This allows us to do efficient dominance checks for the case when an
+ /// instruction has an operand that is an instruction in the same block.
+ SmallPtrSet<Instruction *, 16> InstsInThisBlock;
+
+ /// \brief Keep track of the metadata nodes that have been checked already.
+ SmallPtrSet<MDNode *, 32> MDNodes;
+
+ /// \brief The personality function referenced by the LandingPadInsts.
+ /// All LandingPadInsts within the same function must use the same
+ /// personality function.
+ const Value *PersonalityFn;
+
+ /// \brief Finder keeps track of all debug info MDNodes in a Module.
+ DebugInfoFinder Finder;
+
+ /// \brief Track the brokenness of the module while recursively visiting.
+ bool Broken;
+
+public:
+ explicit Verifier(raw_ostream &OS = dbgs())
+ : OS(OS), M(0), Context(0), DL(0), PersonalityFn(0), Broken(false) {}
+
+ bool verify(const Function &F) {
+ M = F.getParent();
+ Context = &M->getContext();
+
+ // First ensure the function is well-enough formed to compute dominance
+ // information.
+ if (F.empty()) {
+ OS << "Function '" << F.getName()
+ << "' does not contain an entry block!\n";
+ return false;
}
- explicit Verifier(VerifierFailureAction ctn)
- : FunctionPass(ID), Broken(false), action(ctn), Mod(0),
- Context(0), DT(0), DL(0), MessagesStr(Messages), PersonalityFn(0) {
- initializeVerifierPass(*PassRegistry::getPassRegistry());
+ for (Function::const_iterator I = F.begin(), E = F.end(); I != E; ++I) {
+ if (I->empty() || !I->back().isTerminator()) {
+ OS << "Basic Block in function '" << F.getName()
+ << "' does not have terminator!\n";
+ I->printAsOperand(OS, true);
+ OS << "\n";
+ return false;
+ }
}
- bool doInitialization(Module &M) {
- Mod = &M;
- Context = &M.getContext();
+ // Now directly compute a dominance tree. We don't rely on the pass
+ // manager to provide this as it isolates us from a potentially
+ // out-of-date dominator tree and makes it significantly more complex to
+ // run this code outside of a pass manager.
+ // FIXME: It's really gross that we have to cast away constness here.
+ DT.recalculate(const_cast<Function &>(F));
- DL = getAnalysisIfAvailable<DataLayout>();
-
- // 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();
- }
+ Finder.reset();
+ Broken = false;
+ // FIXME: We strip const here because the inst visitor strips const.
+ visit(const_cast<Function &>(F));
+ InstsInThisBlock.clear();
+ PersonalityFn = 0;
- bool runOnFunction(Function &F) {
- // Get dominator information if we are being run by PassManager
- DT = &getAnalysis<DominatorTree>();
+ if (!DisableDebugInfoVerifier)
+ // Verify Debug Info.
+ verifyDebugInfo();
- Mod = F.getParent();
- if (!Context) Context = &F.getContext();
+ return !Broken;
+ }
- Finder.reset();
- visit(F);
- InstsInThisBlock.clear();
- PersonalityFn = 0;
+ bool verify(const Module &M) {
+ this->M = &M;
+ Context = &M.getContext();
+ Finder.reset();
+ Broken = false;
- if (!DisableDebugInfoVerifier)
- // Verify Debug Info.
- verifyDebugInfo();
+ // Scan through, checking all of the external function's linkage now...
+ for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I) {
+ visitGlobalValue(*I);
- // 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();
+ // Check to make sure function prototypes are okay.
+ if (I->isDeclaration())
+ visitFunction(*I);
}
- bool doFinalization(Module &M) {
- // Scan through, checking all of the external function's linkage now...
- for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
- visitGlobalValue(*I);
-
- // Check to make sure function prototypes are okay.
- if (I->isDeclaration()) visitFunction(*I);
- }
-
- for (Module::global_iterator I = M.global_begin(), E = M.global_end();
- I != E; ++I)
- visitGlobalVariable(*I);
-
- for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end();
- I != E; ++I)
- visitGlobalAlias(*I);
-
- for (Module::named_metadata_iterator I = M.named_metadata_begin(),
- E = M.named_metadata_end(); I != E; ++I)
- visitNamedMDNode(*I);
+ for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
+ I != E; ++I)
+ visitGlobalVariable(*I);
- visitModuleFlags(M);
- visitModuleIdents(M);
+ for (Module::const_alias_iterator I = M.alias_begin(), E = M.alias_end();
+ I != E; ++I)
+ visitGlobalAlias(*I);
- if (!DisableDebugInfoVerifier) {
- Finder.reset();
- Finder.processModule(M);
- // Verify Debug Info.
- verifyDebugInfo();
- }
-
- // If the module is broken, abort at this time.
- return abortIfBroken();
- }
+ for (Module::const_named_metadata_iterator I = M.named_metadata_begin(),
+ E = M.named_metadata_end();
+ I != E; ++I)
+ visitNamedMDNode(*I);
- virtual void getAnalysisUsage(AnalysisUsage &AU) const {
- AU.setPreservesAll();
- AU.addRequiredID(PreVerifyID);
- AU.addRequired<DominatorTree>();
- }
+ visitModuleFlags(M);
+ visitModuleIdents(M);
- /// abortIfBroken - If the module is broken and we are supposed to abort on
- /// this condition, do so.
- ///
- bool abortIfBroken() {
- if (!Broken) return false;
- MessagesStr << "Broken module found, ";
- switch (action) {
- case AbortProcessAction:
- MessagesStr << "compilation aborted!\n";
- dbgs() << MessagesStr.str();
- // Client should choose different reaction if abort is not desired
- abort();
- case PrintMessageAction:
- MessagesStr << "verification continues.\n";
- dbgs() << MessagesStr.str();
- return false;
- case ReturnStatusAction:
- MessagesStr << "compilation terminated.\n";
- return true;
- }
- llvm_unreachable("Invalid action");
+ if (!DisableDebugInfoVerifier) {
+ Finder.reset();
+ Finder.processModule(M);
+ // Verify Debug Info.
+ verifyDebugInfo();
}
+ return !Broken;
+ }
- // Verification methods...
- void visitGlobalValue(GlobalValue &GV);
- void visitGlobalVariable(GlobalVariable &GV);
- 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);
- void visitFunction(Function &F);
- void visitBasicBlock(BasicBlock &BB);
- using InstVisitor<Verifier>::visit;
-
- void visit(Instruction &I);
-
- void visitTruncInst(TruncInst &I);
- void visitZExtInst(ZExtInst &I);
- void visitSExtInst(SExtInst &I);
- void visitFPTruncInst(FPTruncInst &I);
- void visitFPExtInst(FPExtInst &I);
- void visitFPToUIInst(FPToUIInst &I);
- void visitFPToSIInst(FPToSIInst &I);
- void visitUIToFPInst(UIToFPInst &I);
- void visitSIToFPInst(SIToFPInst &I);
- 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);
- void visitFCmpInst(FCmpInst &FC);
- void visitExtractElementInst(ExtractElementInst &EI);
- void visitInsertElementInst(InsertElementInst &EI);
- void visitShuffleVectorInst(ShuffleVectorInst &EI);
- void visitVAArgInst(VAArgInst &VAA) { visitInstruction(VAA); }
- void visitCallInst(CallInst &CI);
- void visitInvokeInst(InvokeInst &II);
- void visitGetElementPtrInst(GetElementPtrInst &GEP);
- void visitLoadInst(LoadInst &LI);
- void visitStoreInst(StoreInst &SI);
- void verifyDominatesUse(Instruction &I, unsigned i);
- void visitInstruction(Instruction &I);
- void visitTerminatorInst(TerminatorInst &I);
- void visitBranchInst(BranchInst &BI);
- void visitReturnInst(ReturnInst &RI);
- void visitSwitchInst(SwitchInst &SI);
- void visitIndirectBrInst(IndirectBrInst &BI);
- void visitSelectInst(SelectInst &SI);
- void visitUserOp1(Instruction &I);
- void visitUserOp2(Instruction &I) { visitUserOp1(I); }
- void visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI);
- void visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI);
- void visitAtomicRMWInst(AtomicRMWInst &RMWI);
- void visitFenceInst(FenceInst &FI);
- void visitAllocaInst(AllocaInst &AI);
- void visitExtractValueInst(ExtractValueInst &EVI);
- void visitInsertValueInst(InsertValueInst &IVI);
- void visitLandingPadInst(LandingPadInst &LPI);
-
- void VerifyCallSite(CallSite CS);
- bool PerformTypeCheck(Intrinsic::ID ID, Function *F, Type *Ty,
- int VT, unsigned ArgNo, std::string &Suffix);
- 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);
- void VerifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty,
- bool isReturnValue, const Value *V);
- void VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs,
- const Value *V);
-
- void VerifyBitcastType(const Value *V, Type *DestTy, Type *SrcTy);
- void VerifyConstantExprBitcastType(const ConstantExpr *CE);
-
- void verifyDebugInfo();
-
- void WriteValue(const Value *V) {
- if (!V) return;
- if (isa<Instruction>(V)) {
- MessagesStr << *V << '\n';
- } else {
- WriteAsOperand(MessagesStr, V, true, Mod);
- MessagesStr << '\n';
- }
- }
-
- void WriteType(Type *T) {
- if (!T) return;
- MessagesStr << ' ' << *T;
+private:
+ // Verification methods...
+ void visitGlobalValue(const GlobalValue &GV);
+ void visitGlobalVariable(const GlobalVariable &GV);
+ void visitGlobalAlias(const GlobalAlias &GA);
+ void visitNamedMDNode(const NamedMDNode &NMD);
+ void visitMDNode(MDNode &MD, Function *F);
+ void visitModuleIdents(const Module &M);
+ void visitModuleFlags(const Module &M);
+ void visitModuleFlag(const MDNode *Op,
+ DenseMap<const MDString *, const MDNode *> &SeenIDs,
+ SmallVectorImpl<const MDNode *> &Requirements);
+ void visitFunction(const Function &F);
+ void visitBasicBlock(BasicBlock &BB);
+
+ // InstVisitor overrides...
+ using InstVisitor<Verifier>::visit;
+ void visit(Instruction &I);
+
+ void visitTruncInst(TruncInst &I);
+ void visitZExtInst(ZExtInst &I);
+ void visitSExtInst(SExtInst &I);
+ void visitFPTruncInst(FPTruncInst &I);
+ void visitFPExtInst(FPExtInst &I);
+ void visitFPToUIInst(FPToUIInst &I);
+ void visitFPToSIInst(FPToSIInst &I);
+ void visitUIToFPInst(UIToFPInst &I);
+ void visitSIToFPInst(SIToFPInst &I);
+ 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);
+ void visitFCmpInst(FCmpInst &FC);
+ void visitExtractElementInst(ExtractElementInst &EI);
+ void visitInsertElementInst(InsertElementInst &EI);
+ void visitShuffleVectorInst(ShuffleVectorInst &EI);
+ void visitVAArgInst(VAArgInst &VAA) { visitInstruction(VAA); }
+ void visitCallInst(CallInst &CI);
+ void visitInvokeInst(InvokeInst &II);
+ void visitGetElementPtrInst(GetElementPtrInst &GEP);
+ void visitLoadInst(LoadInst &LI);
+ void visitStoreInst(StoreInst &SI);
+ void verifyDominatesUse(Instruction &I, unsigned i);
+ void visitInstruction(Instruction &I);
+ void visitTerminatorInst(TerminatorInst &I);
+ void visitBranchInst(BranchInst &BI);
+ void visitReturnInst(ReturnInst &RI);
+ void visitSwitchInst(SwitchInst &SI);
+ void visitIndirectBrInst(IndirectBrInst &BI);
+ void visitSelectInst(SelectInst &SI);
+ void visitUserOp1(Instruction &I);
+ void visitUserOp2(Instruction &I) { visitUserOp1(I); }
+ void visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI);
+ void visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI);
+ void visitAtomicRMWInst(AtomicRMWInst &RMWI);
+ void visitFenceInst(FenceInst &FI);
+ void visitAllocaInst(AllocaInst &AI);
+ void visitExtractValueInst(ExtractValueInst &EVI);
+ void visitInsertValueInst(InsertValueInst &IVI);
+ void visitLandingPadInst(LandingPadInst &LPI);
+
+ void VerifyCallSite(CallSite CS);
+ bool PerformTypeCheck(Intrinsic::ID ID, Function *F, Type *Ty, int VT,
+ unsigned ArgNo, std::string &Suffix);
+ 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);
+ void VerifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty,
+ bool isReturnValue, const Value *V);
+ void VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs,
+ const Value *V);
+
+ void VerifyBitcastType(const Value *V, Type *DestTy, Type *SrcTy);
+ void VerifyConstantExprBitcastType(const ConstantExpr *CE);
+
+ void verifyDebugInfo();
+
+ void WriteValue(const Value *V) {
+ if (!V)
+ return;
+ if (isa<Instruction>(V)) {
+ OS << *V << '\n';
+ } else {
+ V->printAsOperand(OS, true, M);
+ OS << '\n';
}
+ }
+ void WriteType(Type *T) {
+ if (!T)
+ return;
+ OS << ' ' << *T;
+ }
- // CheckFailed - A check failed, so print out the condition and the message
- // that failed. This provides a nice place to put a breakpoint if you want
- // to see why something is not correct.
- void CheckFailed(const Twine &Message,
- const Value *V1 = 0, const Value *V2 = 0,
- const Value *V3 = 0, const Value *V4 = 0) {
- MessagesStr << Message.str() << "\n";
- WriteValue(V1);
- WriteValue(V2);
- WriteValue(V3);
- WriteValue(V4);
- Broken = true;
- }
+ // CheckFailed - A check failed, so print out the condition and the message
+ // that failed. This provides a nice place to put a breakpoint if you want
+ // to see why something is not correct.
+ void CheckFailed(const Twine &Message, const Value *V1 = 0,
+ const Value *V2 = 0, const Value *V3 = 0,
+ const Value *V4 = 0) {
+ OS << Message.str() << "\n";
+ WriteValue(V1);
+ WriteValue(V2);
+ WriteValue(V3);
+ WriteValue(V4);
+ Broken = true;
+ }
- void CheckFailed(const Twine &Message, const Value *V1,
- Type *T2, const Value *V3 = 0) {
- MessagesStr << Message.str() << "\n";
- WriteValue(V1);
- WriteType(T2);
- WriteValue(V3);
- Broken = true;
- }
+ void CheckFailed(const Twine &Message, const Value *V1, Type *T2,
+ const Value *V3 = 0) {
+ OS << Message.str() << "\n";
+ WriteValue(V1);
+ WriteType(T2);
+ WriteValue(V3);
+ Broken = true;
+ }
- void CheckFailed(const Twine &Message, Type *T1,
- Type *T2 = 0, Type *T3 = 0) {
- MessagesStr << Message.str() << "\n";
- WriteType(T1);
- WriteType(T2);
- WriteType(T3);
- Broken = true;
- }
- };
+ void CheckFailed(const Twine &Message, Type *T1, Type *T2 = 0, Type *T3 = 0) {
+ OS << Message.str() << "\n";
+ WriteType(T1);
+ WriteType(T2);
+ WriteType(T3);
+ Broken = true;
+ }
+};
} // End anonymous namespace
-char Verifier::ID = 0;
-INITIALIZE_PASS_BEGIN(Verifier, "verify", "Module Verifier", false, false)
-INITIALIZE_PASS_DEPENDENCY(PreVerifier)
-INITIALIZE_PASS_DEPENDENCY(DominatorTree)
-INITIALIZE_PASS_END(Verifier, "verify", "Module Verifier", false, false)
-
// Assert - We know that cond should be true, if not print an error message.
#define Assert(C, M) \
do { if (!(C)) { CheckFailed(M); return; } } while (0)
@@ -418,31 +350,27 @@ void Verifier::visit(Instruction &I) {
}
-void Verifier::visitGlobalValue(GlobalValue &GV) {
+void Verifier::visitGlobalValue(const GlobalValue &GV) {
Assert1(!GV.isDeclaration() ||
GV.isMaterializable() ||
GV.hasExternalLinkage() ||
- GV.hasDLLImportLinkage() ||
GV.hasExternalWeakLinkage() ||
(isa<GlobalAlias>(GV) &&
(GV.hasLocalLinkage() || GV.hasWeakLinkage())),
- "Global is external, but doesn't have external or dllimport or weak linkage!",
+ "Global is external, but doesn't have external or weak linkage!",
&GV);
- Assert1(!GV.hasDLLImportLinkage() || GV.isDeclaration(),
- "Global is marked as dllimport, but not external", &GV);
-
Assert1(!GV.hasAppendingLinkage() || isa<GlobalVariable>(GV),
"Only global variables can have appending linkage!", &GV);
if (GV.hasAppendingLinkage()) {
- GlobalVariable *GVar = dyn_cast<GlobalVariable>(&GV);
+ const GlobalVariable *GVar = dyn_cast<GlobalVariable>(&GV);
Assert1(GVar && GVar->getType()->getElementType()->isArrayTy(),
"Only global arrays can have appending linkage!", GVar);
}
}
-void Verifier::visitGlobalVariable(GlobalVariable &GV) {
+void Verifier::visitGlobalVariable(const GlobalVariable &GV) {
if (GV.hasInitializer()) {
Assert1(GV.getInitializer()->getType() == GV.getType()->getElementType(),
"Global variable initializer type does not match global "
@@ -457,8 +385,7 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) {
&GV);
}
} else {
- Assert1(GV.hasExternalLinkage() || GV.hasDLLImportLinkage() ||
- GV.hasExternalWeakLinkage(),
+ Assert1(GV.hasExternalLinkage() || GV.hasExternalWeakLinkage(),
"invalid linkage type for global declaration", &GV);
}
@@ -488,8 +415,8 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) {
PointerType *PTy = dyn_cast<PointerType>(ATy->getElementType());
Assert1(PTy, "wrong type for intrinsic global variable", &GV);
if (GV.hasInitializer()) {
- Constant *Init = GV.getInitializer();
- ConstantArray *InitArray = dyn_cast<ConstantArray>(Init);
+ const Constant *Init = GV.getInitializer();
+ const ConstantArray *InitArray = dyn_cast<ConstantArray>(Init);
Assert1(InitArray, "wrong initalizer for intrinsic global variable",
Init);
for (unsigned i = 0, e = InitArray->getNumOperands(); i != e; ++i) {
@@ -503,6 +430,11 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) {
}
}
+ Assert1(!GV.hasDLLImportStorageClass() ||
+ (GV.isDeclaration() && GV.hasExternalLinkage()) ||
+ GV.hasAvailableExternallyLinkage(),
+ "Global is marked as dllimport, but not external", &GV);
+
if (!GV.hasInitializer()) {
visitGlobalValue(GV);
return;
@@ -533,7 +465,7 @@ void Verifier::visitGlobalVariable(GlobalVariable &GV) {
visitGlobalValue(GV);
}
-void Verifier::visitGlobalAlias(GlobalAlias &GA) {
+void Verifier::visitGlobalAlias(const GlobalAlias &GA) {
Assert1(!GA.getName().empty(),
"Alias name cannot be empty!", &GA);
Assert1(GlobalAlias::isValidLinkage(GA.getLinkage()),
@@ -543,20 +475,25 @@ void Verifier::visitGlobalAlias(GlobalAlias &GA) {
Assert1(GA.getType() == GA.getAliasee()->getType(),
"Alias and aliasee types should match!", &GA);
Assert1(!GA.hasUnnamedAddr(), "Alias cannot have unnamed_addr!", &GA);
+ Assert1(!GA.hasSection(), "Alias cannot have a section!", &GA);
+ Assert1(!GA.getAlignment(), "Alias connot have an alignment", &GA);
+
+ const Constant *Aliasee = GA.getAliasee();
+ const GlobalValue *GV = dyn_cast<GlobalValue>(Aliasee);
- Constant *Aliasee = GA.getAliasee();
+ if (!GV) {
+ const ConstantExpr *CE = dyn_cast<ConstantExpr>(Aliasee);
+ if (CE && (CE->getOpcode() == Instruction::BitCast ||
+ CE->getOpcode() == Instruction::AddrSpaceCast ||
+ CE->getOpcode() == Instruction::GetElementPtr))
+ GV = dyn_cast<GlobalValue>(CE->getOperand(0));
- if (!isa<GlobalValue>(Aliasee)) {
- ConstantExpr *CE = dyn_cast<ConstantExpr>(Aliasee);
- Assert1(CE &&
- (CE->getOpcode() == Instruction::BitCast ||
- CE->getOpcode() == Instruction::GetElementPtr) &&
- isa<GlobalValue>(CE->getOperand(0)),
- "Aliasee should be either GlobalValue or bitcast of GlobalValue",
+ Assert1(GV, "Aliasee should be either GlobalValue, bitcast or "
+ "addrspacecast of GlobalValue",
&GA);
if (CE->getOpcode() == Instruction::BitCast) {
- unsigned SrcAS = CE->getOperand(0)->getType()->getPointerAddressSpace();
+ unsigned SrcAS = GV->getType()->getPointerAddressSpace();
unsigned DstAS = CE->getType()->getPointerAddressSpace();
Assert1(SrcAS == DstAS,
@@ -564,15 +501,20 @@ void Verifier::visitGlobalAlias(GlobalAlias &GA) {
&GA);
}
}
+ Assert1(!GV->isDeclaration(), "Alias must point to a definition", &GA);
+ if (const GlobalAlias *GAAliasee = dyn_cast<GlobalAlias>(GV)) {
+ Assert1(!GAAliasee->mayBeOverridden(), "Alias cannot point to a weak alias",
+ &GA);
+ }
- const GlobalValue* Resolved = GA.resolveAliasedGlobal(/*stopOnWeak*/ false);
- Assert1(Resolved,
- "Aliasing chain should end with function or global variable", &GA);
+ const GlobalValue *AG = GA.getAliasedGlobal();
+ Assert1(AG, "Aliasing chain should end with function or global variable",
+ &GA);
visitGlobalValue(GA);
}
-void Verifier::visitNamedMDNode(NamedMDNode &NMD) {
+void Verifier::visitNamedMDNode(const NamedMDNode &NMD) {
for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i) {
MDNode *MD = NMD.getOperand(i);
if (!MD)
@@ -620,7 +562,7 @@ void Verifier::visitMDNode(MDNode &MD, Function *F) {
}
}
-void Verifier::visitModuleIdents(Module &M) {
+void Verifier::visitModuleIdents(const Module &M) {
const NamedMDNode *Idents = M.getNamedMetadata("llvm.ident");
if (!Idents)
return;
@@ -638,24 +580,24 @@ void Verifier::visitModuleIdents(Module &M) {
}
}
-void Verifier::visitModuleFlags(Module &M) {
+void Verifier::visitModuleFlags(const Module &M) {
const NamedMDNode *Flags = M.getModuleFlagsMetadata();
if (!Flags) return;
// Scan each flag, and track the flags and requirements.
- DenseMap<MDString*, MDNode*> SeenIDs;
- SmallVector<MDNode*, 16> Requirements;
+ DenseMap<const MDString*, const MDNode*> SeenIDs;
+ SmallVector<const MDNode*, 16> Requirements;
for (unsigned I = 0, E = Flags->getNumOperands(); I != E; ++I) {
visitModuleFlag(Flags->getOperand(I), SeenIDs, Requirements);
}
// Validate that the requirements in the module are valid.
for (unsigned I = 0, E = Requirements.size(); I != E; ++I) {
- MDNode *Requirement = Requirements[I];
- MDString *Flag = cast<MDString>(Requirement->getOperand(0));
- Value *ReqValue = Requirement->getOperand(1);
+ const MDNode *Requirement = Requirements[I];
+ const MDString *Flag = cast<MDString>(Requirement->getOperand(0));
+ const Value *ReqValue = Requirement->getOperand(1);
- MDNode *Op = SeenIDs.lookup(Flag);
+ const MDNode *Op = SeenIDs.lookup(Flag);
if (!Op) {
CheckFailed("invalid requirement on flag, flag is not present in module",
Flag);
@@ -671,8 +613,10 @@ void Verifier::visitModuleFlags(Module &M) {
}
}
-void Verifier::visitModuleFlag(MDNode *Op, DenseMap<MDString*, MDNode*>&SeenIDs,
- SmallVectorImpl<MDNode*> &Requirements) {
+void
+Verifier::visitModuleFlag(const MDNode *Op,
+ DenseMap<const MDString *, const MDNode *> &SeenIDs,
+ SmallVectorImpl<const MDNode *> &Requirements) {
// Each module flag should have three arguments, the merge behavior (a
// constant int), the flag ID (an MDString), and the value.
Assert1(Op->getNumOperands() == 3,
@@ -813,26 +757,25 @@ void Verifier::VerifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty,
!Attrs.hasAttribute(Idx, Attribute::Nest) &&
!Attrs.hasAttribute(Idx, Attribute::StructRet) &&
!Attrs.hasAttribute(Idx, Attribute::NoCapture) &&
- !Attrs.hasAttribute(Idx, Attribute::Returned),
- "Attribute 'byval', 'nest', 'sret', 'nocapture', and 'returned' "
- "do not apply to return values!", V);
-
- // Check for mutually incompatible attributes.
- Assert1(!((Attrs.hasAttribute(Idx, Attribute::ByVal) &&
- Attrs.hasAttribute(Idx, Attribute::Nest)) ||
- (Attrs.hasAttribute(Idx, Attribute::ByVal) &&
- Attrs.hasAttribute(Idx, Attribute::StructRet)) ||
- (Attrs.hasAttribute(Idx, Attribute::Nest) &&
- Attrs.hasAttribute(Idx, Attribute::StructRet))), "Attributes "
- "'byval, nest, and sret' are incompatible!", V);
-
- Assert1(!((Attrs.hasAttribute(Idx, Attribute::ByVal) &&
- Attrs.hasAttribute(Idx, Attribute::Nest)) ||
- (Attrs.hasAttribute(Idx, Attribute::ByVal) &&
- Attrs.hasAttribute(Idx, Attribute::InReg)) ||
- (Attrs.hasAttribute(Idx, Attribute::Nest) &&
- Attrs.hasAttribute(Idx, Attribute::InReg))), "Attributes "
- "'byval, nest, and inreg' are incompatible!", V);
+ !Attrs.hasAttribute(Idx, Attribute::Returned) &&
+ !Attrs.hasAttribute(Idx, Attribute::InAlloca),
+ "Attributes 'byval', 'inalloca', 'nest', 'sret', 'nocapture', and "
+ "'returned' do not apply to return values!", V);
+
+ // Check for mutually incompatible attributes. Only inreg is compatible with
+ // sret.
+ unsigned AttrCount = 0;
+ AttrCount += Attrs.hasAttribute(Idx, Attribute::ByVal);
+ AttrCount += Attrs.hasAttribute(Idx, Attribute::InAlloca);
+ AttrCount += Attrs.hasAttribute(Idx, Attribute::StructRet) ||
+ Attrs.hasAttribute(Idx, Attribute::InReg);
+ AttrCount += Attrs.hasAttribute(Idx, Attribute::Nest);
+ Assert1(AttrCount <= 1, "Attributes 'byval', 'inalloca', 'inreg', 'nest', "
+ "and 'sret' are incompatible!", V);
+
+ Assert1(!(Attrs.hasAttribute(Idx, Attribute::InAlloca) &&
+ Attrs.hasAttribute(Idx, Attribute::ReadOnly)), "Attributes "
+ "'inalloca and readonly' are incompatible!", V);
Assert1(!(Attrs.hasAttribute(Idx, Attribute::StructRet) &&
Attrs.hasAttribute(Idx, Attribute::Returned)), "Attributes "
@@ -855,14 +798,18 @@ void Verifier::VerifyParameterAttrs(AttributeSet Attrs, unsigned Idx, Type *Ty,
"Wrong types for attribute: " +
AttributeFuncs::typeIncompatible(Ty, Idx).getAsString(Idx), V);
- if (PointerType *PTy = dyn_cast<PointerType>(Ty))
- Assert1(!Attrs.hasAttribute(Idx, Attribute::ByVal) ||
- PTy->getElementType()->isSized(),
- "Attribute 'byval' does not support unsized types!", V);
- else
+ if (PointerType *PTy = dyn_cast<PointerType>(Ty)) {
+ if (!PTy->getElementType()->isSized()) {
+ Assert1(!Attrs.hasAttribute(Idx, Attribute::ByVal) &&
+ !Attrs.hasAttribute(Idx, Attribute::InAlloca),
+ "Attributes 'byval' and 'inalloca' do not support unsized types!",
+ V);
+ }
+ } else {
Assert1(!Attrs.hasAttribute(Idx, Attribute::ByVal),
"Attribute 'byval' only applies to parameters with pointer type!",
V);
+ }
}
// VerifyFunctionAttrs - Check parameter attributes against a function type.
@@ -906,6 +853,11 @@ void Verifier::VerifyFunctionAttrs(FunctionType *FT, AttributeSet Attrs,
if (Attrs.hasAttribute(Idx, Attribute::StructRet))
Assert1(Idx == 1, "Attribute sret is not on first parameter!", V);
+
+ if (Attrs.hasAttribute(Idx, Attribute::InAlloca)) {
+ Assert1(Idx == FT->getNumParams(),
+ "inalloca isn't on the last parameter!", V);
+ }
}
if (!Attrs.hasAttributes(AttributeSet::FunctionIndex))
@@ -1001,7 +953,7 @@ bool Verifier::VerifyAttributeCount(AttributeSet Attrs, unsigned Params) {
// visitFunction - Verify that a function is ok.
//
-void Verifier::visitFunction(Function &F) {
+void Verifier::visitFunction(const Function &F) {
// Check function arguments.
FunctionType *FT = F.getFunctionType();
unsigned NumArgs = F.arg_size();
@@ -1059,8 +1011,8 @@ void Verifier::visitFunction(Function &F) {
// Check that the argument values match the function type for this function...
unsigned i = 0;
- for (Function::arg_iterator I = F.arg_begin(), E = F.arg_end();
- I != E; ++I, ++i) {
+ for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E;
+ ++I, ++i) {
Assert2(I->getType() == FT->getParamType(i),
"Argument value does not match function argument type!",
I, FT->getParamType(i));
@@ -1074,8 +1026,7 @@ void Verifier::visitFunction(Function &F) {
if (F.isMaterializable()) {
// Function has a body somewhere we can't see.
} else if (F.isDeclaration()) {
- Assert1(F.hasExternalLinkage() || F.hasDLLImportLinkage() ||
- F.hasExternalWeakLinkage(),
+ Assert1(F.hasExternalLinkage() || F.hasExternalWeakLinkage(),
"invalid linkage type for function declaration", &F);
} else {
// Verify that this function (which has a body) is not named "llvm.*". It
@@ -1083,13 +1034,13 @@ void Verifier::visitFunction(Function &F) {
Assert1(!isLLVMdotName, "llvm intrinsics cannot be defined!", &F);
// Check the entry node
- BasicBlock *Entry = &F.getEntryBlock();
+ const BasicBlock *Entry = &F.getEntryBlock();
Assert1(pred_begin(Entry) == pred_end(Entry),
"Entry block to function must not have predecessors!", Entry);
// The address of the entry block cannot be taken, unless it is dead.
if (Entry->hasAddressTaken()) {
- Assert1(!BlockAddress::get(Entry)->isConstantUsed(),
+ Assert1(!BlockAddress::lookup(Entry)->isConstantUsed(),
"blockaddress may not be used with the entry block!", Entry);
}
}
@@ -1101,6 +1052,11 @@ void Verifier::visitFunction(Function &F) {
if (F.hasAddressTaken(&U))
Assert1(0, "Invalid user of intrinsic instruction!", U);
}
+
+ Assert1(!F.hasDLLImportStorageClass() ||
+ (F.isDeclaration() && F.hasExternalLinkage()) ||
+ F.hasAvailableExternallyLinkage(),
+ "Function is marked as dllimport, but not external.", &F);
}
// verifyBasicBlock - Verify that a basic block is well formed...
@@ -1566,6 +1522,10 @@ void Verifier::VerifyCallSite(CallSite CS) {
Assert1(!Attrs.hasAttribute(Idx, Attribute::StructRet),
"Attribute 'sret' cannot be used for vararg call arguments!", I);
+
+ if (Attrs.hasAttribute(Idx, Attribute::InAlloca))
+ Assert1(Idx == CS.arg_size(), "inalloca isn't on the last argument!",
+ I);
}
}
@@ -1861,22 +1821,37 @@ void Verifier::visitStoreInst(StoreInst &SI) {
}
void Verifier::visitAllocaInst(AllocaInst &AI) {
+ SmallPtrSet<const Type*, 4> Visited;
PointerType *PTy = AI.getType();
Assert1(PTy->getAddressSpace() == 0,
"Allocation instruction pointer not in the generic address space!",
&AI);
- Assert1(PTy->getElementType()->isSized(), "Cannot allocate unsized type",
+ Assert1(PTy->getElementType()->isSized(&Visited), "Cannot allocate unsized type",
&AI);
Assert1(AI.getArraySize()->getType()->isIntegerTy(),
"Alloca array size must have integer type", &AI);
+
visitInstruction(AI);
}
void Verifier::visitAtomicCmpXchgInst(AtomicCmpXchgInst &CXI) {
- Assert1(CXI.getOrdering() != NotAtomic,
+
+ // FIXME: more conditions???
+ Assert1(CXI.getSuccessOrdering() != NotAtomic,
"cmpxchg instructions must be atomic.", &CXI);
- Assert1(CXI.getOrdering() != Unordered,
+ Assert1(CXI.getFailureOrdering() != NotAtomic,
+ "cmpxchg instructions must be atomic.", &CXI);
+ Assert1(CXI.getSuccessOrdering() != Unordered,
+ "cmpxchg instructions cannot be unordered.", &CXI);
+ Assert1(CXI.getFailureOrdering() != Unordered,
"cmpxchg instructions cannot be unordered.", &CXI);
+ Assert1(CXI.getSuccessOrdering() >= CXI.getFailureOrdering(),
+ "cmpxchg instructions be at least as constrained on success as fail",
+ &CXI);
+ Assert1(CXI.getFailureOrdering() != Release &&
+ CXI.getFailureOrdering() != AcquireRelease,
+ "cmpxchg failure ordering cannot include release semantics", &CXI);
+
PointerType *PTy = dyn_cast<PointerType>(CXI.getOperand(0)->getType());
Assert1(PTy, "First cmpxchg operand must be a pointer.", &CXI);
Type *ElTy = PTy->getElementType();
@@ -2007,7 +1982,7 @@ void Verifier::verifyDominatesUse(Instruction &I, unsigned i) {
}
const Use &U = I.getOperandUse(i);
- Assert2(InstsInThisBlock.count(Op) || DT->dominates(Op, U),
+ Assert2(InstsInThisBlock.count(Op) || DT.dominates(Op, U),
"Instruction does not dominate all uses!", Op, &I);
}
@@ -2018,10 +1993,10 @@ void Verifier::visitInstruction(Instruction &I) {
Assert1(BB, "Instruction not embedded in basic block!", &I);
if (!isa<PHINode>(I)) { // Check that non-phi nodes are not self referential
- for (Value::use_iterator UI = I.use_begin(), UE = I.use_end();
- UI != UE; ++UI)
- Assert1(*UI != (User*)&I || !DT->isReachableFromEntry(BB),
+ for (User *U : I.users()) {
+ Assert1(U != (User*)&I || !DT.isReachableFromEntry(BB),
"Only PHI nodes may reference their own value!", &I);
+ }
}
// Check that void typed values don't have names
@@ -2043,13 +2018,12 @@ void Verifier::visitInstruction(Instruction &I) {
// Check that all uses of the instruction, if they are instructions
// themselves, actually have parent basic blocks. If the use is not an
// instruction, it is an error!
- for (User::use_iterator UI = I.use_begin(), UE = I.use_end();
- UI != UE; ++UI) {
- if (Instruction *Used = dyn_cast<Instruction>(*UI))
+ for (Use &U : I.uses()) {
+ if (Instruction *Used = dyn_cast<Instruction>(U.getUser()))
Assert2(Used->getParent() != 0, "Instruction referencing instruction not"
" embedded in a basic block!", &I, Used);
else {
- CheckFailed("Use of instruction is not an instruction!", *UI);
+ CheckFailed("Use of instruction is not an instruction!", U);
return;
}
}
@@ -2071,7 +2045,7 @@ void Verifier::visitInstruction(Instruction &I) {
Assert1(!F->isIntrinsic() || isa<CallInst>(I) ||
F->getIntrinsicID() == Intrinsic::donothing,
"Cannot invoke an intrinsinc other than donothing", &I);
- Assert1(F->getParent() == Mod, "Referencing function in another module!",
+ Assert1(F->getParent() == M, "Referencing function in another module!",
&I);
} else if (BasicBlock *OpBB = dyn_cast<BasicBlock>(I.getOperand(i))) {
Assert1(OpBB->getParent() == BB->getParent(),
@@ -2080,7 +2054,7 @@ void Verifier::visitInstruction(Instruction &I) {
Assert1(OpArg->getParent() == BB->getParent(),
"Referring to an argument in another function!", &I);
} else if (GlobalValue *GV = dyn_cast<GlobalValue>(I.getOperand(i))) {
- Assert1(GV->getParent() == Mod, "Referencing global in another module!",
+ Assert1(GV->getParent() == M, "Referencing global in another module!",
&I);
} else if (isa<Instruction>(I.getOperand(i))) {
verifyDominatesUse(I, i);
@@ -2131,7 +2105,7 @@ void Verifier::visitInstruction(Instruction &I) {
if (!DisableDebugInfoVerifier) {
MD = I.getMetadata(LLVMContext::MD_dbg);
- Finder.processLocation(*Mod, DILocation(MD));
+ Finder.processLocation(*M, DILocation(MD));
}
InstsInThisBlock.insert(&I);
@@ -2202,18 +2176,41 @@ bool Verifier::VerifyIntrinsicType(Type *Ty,
}
llvm_unreachable("all argument kinds not covered");
- case IITDescriptor::ExtendVecArgument:
+ case IITDescriptor::ExtendArgument: {
// This may only be used when referring to a previous vector argument.
- return D.getArgumentNumber() >= ArgTys.size() ||
- !isa<VectorType>(ArgTys[D.getArgumentNumber()]) ||
- VectorType::getExtendedElementVectorType(
- cast<VectorType>(ArgTys[D.getArgumentNumber()])) != Ty;
+ if (D.getArgumentNumber() >= ArgTys.size())
+ return true;
+
+ Type *NewTy = ArgTys[D.getArgumentNumber()];
+ if (VectorType *VTy = dyn_cast<VectorType>(NewTy))
+ NewTy = VectorType::getExtendedElementVectorType(VTy);
+ else if (IntegerType *ITy = dyn_cast<IntegerType>(NewTy))
+ NewTy = IntegerType::get(ITy->getContext(), 2 * ITy->getBitWidth());
+ else
+ return true;
+
+ return Ty != NewTy;
+ }
+ case IITDescriptor::TruncArgument: {
+ // This may only be used when referring to a previous vector argument.
+ if (D.getArgumentNumber() >= ArgTys.size())
+ return true;
- case IITDescriptor::TruncVecArgument:
+ Type *NewTy = ArgTys[D.getArgumentNumber()];
+ if (VectorType *VTy = dyn_cast<VectorType>(NewTy))
+ NewTy = VectorType::getTruncatedElementVectorType(VTy);
+ else if (IntegerType *ITy = dyn_cast<IntegerType>(NewTy))
+ NewTy = IntegerType::get(ITy->getContext(), ITy->getBitWidth() / 2);
+ else
+ return true;
+
+ return Ty != NewTy;
+ }
+ case IITDescriptor::HalfVecArgument:
// This may only be used when referring to a previous vector argument.
return D.getArgumentNumber() >= ArgTys.size() ||
!isa<VectorType>(ArgTys[D.getArgumentNumber()]) ||
- VectorType::getTruncatedElementVectorType(
+ VectorType::getHalfElementsVectorType(
cast<VectorType>(ArgTys[D.getArgumentNumber()])) != Ty;
}
llvm_unreachable("unhandled");
@@ -2284,8 +2281,10 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
// know they are legal for the intrinsic!) get the intrinsic name through the
// usual means. This allows us to verify the mangling of argument types into
// the name.
- Assert1(Intrinsic::getName(ID, ArgTys) == IF->getName(),
- "Intrinsic name not mangled correctly for type arguments!", IF);
+ const std::string ExpectedName = Intrinsic::getName(ID, ArgTys);
+ Assert1(ExpectedName == IF->getName(),
+ "Intrinsic name not mangled correctly for type arguments! "
+ "Should be: " + ExpectedName, IF);
// If the intrinsic takes MDNode arguments, verify that they are either global
// or are local to *this* function.
@@ -2309,13 +2308,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(*Mod, cast<DbgDeclareInst>(&CI));
+ Finder.processDeclare(*M, 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(*Mod, cast<DbgValueInst>(&CI));
+ Finder.processValue(*M, cast<DbgValueInst>(&CI));
}
break;
}
@@ -2383,22 +2382,21 @@ void Verifier::visitIntrinsicFunctionCall(Intrinsic::ID ID, CallInst &CI) {
void Verifier::verifyDebugInfo() {
// Verify Debug Info.
if (!DisableDebugInfoVerifier) {
- 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);
- for (DebugInfoFinder::iterator I = Finder.subprogram_begin(),
- E = Finder.subprogram_end(); I != E; ++I)
- Assert1(DISubprogram(*I).Verify(), "DISubprogram does not Verify!", *I);
- for (DebugInfoFinder::iterator I = Finder.global_variable_begin(),
- E = Finder.global_variable_end(); I != E; ++I)
- Assert1(DIGlobalVariable(*I).Verify(),
- "DIGlobalVariable does not Verify!", *I);
- for (DebugInfoFinder::iterator I = Finder.type_begin(),
- E = Finder.type_end(); I != E; ++I)
- Assert1(DIType(*I).Verify(), "DIType does not Verify!", *I);
- for (DebugInfoFinder::iterator I = Finder.scope_begin(),
- E = Finder.scope_end(); I != E; ++I)
- Assert1(DIScope(*I).Verify(), "DIScope does not Verify!", *I);
+ for (DICompileUnit CU : Finder.compile_units()) {
+ Assert1(CU.Verify(), "DICompileUnit does not Verify!", CU);
+ }
+ for (DISubprogram S : Finder.subprograms()) {
+ Assert1(S.Verify(), "DISubprogram does not Verify!", S);
+ }
+ for (DIGlobalVariable GV : Finder.global_variables()) {
+ Assert1(GV.Verify(), "DIGlobalVariable does not Verify!", GV);
+ }
+ for (DIType T : Finder.types()) {
+ Assert1(T.Verify(), "DIType does not Verify!", T);
+ }
+ for (DIScope S : Finder.scopes()) {
+ Assert1(S.Verify(), "DIScope does not Verify!", S);
+ }
}
}
@@ -2406,37 +2404,84 @@ void Verifier::verifyDebugInfo() {
// Implement the public interfaces to this file...
//===----------------------------------------------------------------------===//
-FunctionPass *llvm::createVerifierPass(VerifierFailureAction action) {
- return new Verifier(action);
+bool llvm::verifyFunction(const Function &f, raw_ostream *OS) {
+ Function &F = const_cast<Function &>(f);
+ assert(!F.isDeclaration() && "Cannot verify external functions");
+
+ raw_null_ostream NullStr;
+ Verifier V(OS ? *OS : NullStr);
+
+ // Note that this function's return value is inverted from what you would
+ // expect of a function called "verify".
+ return !V.verify(F);
}
+bool llvm::verifyModule(const Module &M, raw_ostream *OS) {
+ raw_null_ostream NullStr;
+ Verifier V(OS ? *OS : NullStr);
-/// verifyFunction - Check a function for errors, printing messages on stderr.
-/// Return true if the function is corrupt.
-///
-bool llvm::verifyFunction(const Function &f, VerifierFailureAction action) {
- Function &F = const_cast<Function&>(f);
- assert(!F.isDeclaration() && "Cannot verify external functions");
+ bool Broken = false;
+ for (Module::const_iterator I = M.begin(), E = M.end(); I != E; ++I)
+ if (!I->isDeclaration())
+ Broken |= !V.verify(*I);
- FunctionPassManager FPM(F.getParent());
- Verifier *V = new Verifier(action);
- FPM.add(V);
- FPM.doInitialization();
- FPM.run(F);
- return V->Broken;
+ // Note that this function's return value is inverted from what you would
+ // expect of a function called "verify".
+ return !V.verify(M) || Broken;
}
-/// verifyModule - Check a module for errors, printing messages on stderr.
-/// Return true if the module is corrupt.
-///
-bool llvm::verifyModule(const Module &M, VerifierFailureAction action,
- std::string *ErrorInfo) {
- PassManager PM;
- Verifier *V = new Verifier(action);
- PM.add(V);
- PM.run(const_cast<Module&>(M));
-
- if (ErrorInfo && V->Broken)
- *ErrorInfo = V->MessagesStr.str();
- return V->Broken;
+namespace {
+struct VerifierLegacyPass : public FunctionPass {
+ static char ID;
+
+ Verifier V;
+ bool FatalErrors;
+
+ VerifierLegacyPass() : FunctionPass(ID), FatalErrors(true) {
+ initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry());
+ }
+ explicit VerifierLegacyPass(bool FatalErrors)
+ : FunctionPass(ID), V(dbgs()), FatalErrors(FatalErrors) {
+ initializeVerifierLegacyPassPass(*PassRegistry::getPassRegistry());
+ }
+
+ bool runOnFunction(Function &F) override {
+ if (!V.verify(F) && FatalErrors)
+ report_fatal_error("Broken function found, compilation aborted!");
+
+ return false;
+ }
+
+ bool doFinalization(Module &M) override {
+ if (!V.verify(M) && FatalErrors)
+ report_fatal_error("Broken module found, compilation aborted!");
+
+ return false;
+ }
+
+ void getAnalysisUsage(AnalysisUsage &AU) const override {
+ AU.setPreservesAll();
+ }
+};
+}
+
+char VerifierLegacyPass::ID = 0;
+INITIALIZE_PASS(VerifierLegacyPass, "verify", "Module Verifier", false, false)
+
+FunctionPass *llvm::createVerifierPass(bool FatalErrors) {
+ return new VerifierLegacyPass(FatalErrors);
+}
+
+PreservedAnalyses VerifierPass::run(Module *M) {
+ if (verifyModule(*M, &dbgs()) && FatalErrors)
+ report_fatal_error("Broken module found, compilation aborted!");
+
+ return PreservedAnalyses::all();
+}
+
+PreservedAnalyses VerifierPass::run(Function *F) {
+ if (verifyFunction(*F, &dbgs()) && FatalErrors)
+ report_fatal_error("Broken function found, compilation aborted!");
+
+ return PreservedAnalyses::all();
}