diff options
author | Stephen Hines <srhines@google.com> | 2014-04-23 16:57:46 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-04-24 15:53:16 -0700 |
commit | 36b56886974eae4f9c5ebc96befd3e7bfe5de338 (patch) | |
tree | e6cfb69fbbd937f450eeb83bfb83b9da3b01275a /lib/IR | |
parent | 69a8640022b04415ae9fac62f8ab090601d8f889 (diff) | |
download | external_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')
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(); } |