diff options
author | Pirama Arumuga Nainar <pirama@google.com> | 2015-05-06 11:46:36 -0700 |
---|---|---|
committer | Pirama Arumuga Nainar <pirama@google.com> | 2015-05-18 10:52:30 -0700 |
commit | 2c3e0051c31c3f5b2328b447eadf1cf9c4427442 (patch) | |
tree | c0104029af14e9f47c2ef58ca60e6137691f3c9b /include | |
parent | e1bc145815f4334641be19f1c45ecf85d25b6e5a (diff) | |
download | external_llvm-2c3e0051c31c3f5b2328b447eadf1cf9c4427442.zip external_llvm-2c3e0051c31c3f5b2328b447eadf1cf9c4427442.tar.gz external_llvm-2c3e0051c31c3f5b2328b447eadf1cf9c4427442.tar.bz2 |
Update aosp/master LLVM for rebase to r235153
Change-Id: I9bf53792f9fc30570e81a8d80d296c681d005ea7
(cherry picked from commit 0c7f116bb6950ef819323d855415b2f2b0aad987)
Diffstat (limited to 'include')
171 files changed, 3831 insertions, 3157 deletions
diff --git a/include/llvm-c/Core.h b/include/llvm-c/Core.h index 8873fdb..effbd15 100644 --- a/include/llvm-c/Core.h +++ b/include/llvm-c/Core.h @@ -169,6 +169,7 @@ typedef enum { LLVMNonNullAttribute = 1ULL << 37, LLVMJumpTableAttribute = 1ULL << 38, LLVMDereferenceableAttribute = 1ULL << 39, + LLVMDereferenceableOrNullAttribute = 1ULL << 40, */ } LLVMAttribute; diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index 8c65f70..9c2365a 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -100,16 +100,18 @@ public: } const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + unsigned NumEntries = getNumEntries(); for (BucketT *P = getBuckets(), *E = getBucketsEnd(); P != E; ++P) { if (!KeyInfoT::isEqual(P->getFirst(), EmptyKey)) { if (!KeyInfoT::isEqual(P->getFirst(), TombstoneKey)) { P->getSecond().~ValueT(); - decrementNumEntries(); + --NumEntries; } P->getFirst() = EmptyKey; } } - assert(getNumEntries() == 0 && "Node count imbalance!"); + assert(NumEntries == 0 && "Node count imbalance!"); + setNumEntries(0); setNumTombstones(0); } @@ -257,7 +259,7 @@ public: const void *getPointerIntoBucketsArray() const { return getBuckets(); } protected: - DenseMapBase() {} + DenseMapBase() = default; void destroyAll() { if (getNumBuckets() == 0) // Nothing to do. @@ -341,11 +343,6 @@ protected: } } - void swap(DenseMapBase& RHS) { - std::swap(getNumEntries(), RHS.getNumEntries()); - std::swap(getNumTombstones(), RHS.getNumTombstones()); - } - static unsigned getHashValue(const KeyT &Val) { return KeyInfoT::getHashValue(Val); } @@ -589,6 +586,8 @@ public: } void swap(DenseMap& RHS) { + this->incrementEpoch(); + RHS.incrementEpoch(); std::swap(Buckets, RHS.Buckets); std::swap(NumEntries, RHS.NumEntries); std::swap(NumTombstones, RHS.NumTombstones); diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h index 5186333..e9668c4 100644 --- a/include/llvm/ADT/DepthFirstIterator.h +++ b/include/llvm/ADT/DepthFirstIterator.h @@ -209,7 +209,7 @@ df_iterator<T> df_end(const T& G) { // Provide an accessor method to use them in range-based patterns. template <class T> iterator_range<df_iterator<T>> depth_first(const T& G) { - return iterator_range<df_iterator<T>>(df_begin(G), df_end(G)); + return make_range(df_begin(G), df_end(G)); } // Provide global definitions of external depth first iterators... @@ -232,8 +232,7 @@ df_ext_iterator<T, SetTy> df_ext_end(const T& G, SetTy &S) { template <class T, class SetTy> iterator_range<df_ext_iterator<T, SetTy>> depth_first_ext(const T& G, SetTy &S) { - return iterator_range<df_ext_iterator<T, SetTy>>(df_ext_begin(G, S), - df_ext_end(G, S)); + return make_range(df_ext_begin(G, S), df_ext_end(G, S)); } @@ -259,7 +258,7 @@ idf_iterator<T> idf_end(const T& G){ // Provide an accessor method to use them in range-based patterns. template <class T> iterator_range<idf_iterator<T>> inverse_depth_first(const T& G) { - return iterator_range<idf_iterator<T>>(idf_begin(G), idf_end(G)); + return make_range(idf_begin(G), idf_end(G)); } // Provide global definitions of external inverse depth first iterators... @@ -284,8 +283,7 @@ idf_ext_iterator<T, SetTy> idf_ext_end(const T& G, SetTy &S) { template <class T, class SetTy> iterator_range<idf_ext_iterator<T, SetTy>> inverse_depth_first_ext(const T& G, SetTy &S) { - return iterator_range<idf_ext_iterator<T, SetTy>>(idf_ext_begin(G, S), - idf_ext_end(G, S)); + return make_range(idf_ext_begin(G, S), idf_ext_end(G, S)); } } // End llvm namespace diff --git a/include/llvm/ADT/EpochTracker.h b/include/llvm/ADT/EpochTracker.h index d593073..582d581 100644 --- a/include/llvm/ADT/EpochTracker.h +++ b/include/llvm/ADT/EpochTracker.h @@ -30,7 +30,7 @@ public: class HandleBase { public: - HandleBase() {} + HandleBase() = default; explicit HandleBase(const DebugEpochBase *) {} bool isHandleInSync() const { return true; } const void *getEpochAddress() const { return nullptr; } diff --git a/include/llvm/ADT/Hashing.h b/include/llvm/ADT/Hashing.h index a1e7864..77e6d77 100644 --- a/include/llvm/ADT/Hashing.h +++ b/include/llvm/ADT/Hashing.h @@ -75,7 +75,7 @@ class hash_code { public: /// \brief Default construct a hash_code. /// Note that this leaves the value uninitialized. - hash_code() {} + hash_code() = default; /// \brief Form a hash code directly from a numerical value. hash_code(size_t value) : value(value) {} diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h index fa337e9..759a2db 100644 --- a/include/llvm/ADT/PostOrderIterator.h +++ b/include/llvm/ADT/PostOrderIterator.h @@ -18,6 +18,7 @@ #include "llvm/ADT/GraphTraits.h" #include "llvm/ADT/SmallPtrSet.h" +#include "llvm/ADT/iterator_range.h" #include <set> #include <vector> @@ -174,9 +175,13 @@ public: // Provide global constructors that automatically figure out correct types... // template <class T> -po_iterator<T> po_begin(T G) { return po_iterator<T>::begin(G); } +po_iterator<T> po_begin(const T &G) { return po_iterator<T>::begin(G); } template <class T> -po_iterator<T> po_end (T G) { return po_iterator<T>::end(G); } +po_iterator<T> po_end (const T &G) { return po_iterator<T>::end(G); } + +template <class T> iterator_range<po_iterator<T>> post_order(const T &G) { + return make_range(po_begin(G), po_end(G)); +} // Provide global definitions of external postorder iterators... template<class T, class SetType=std::set<typename GraphTraits<T>::NodeType*> > @@ -195,6 +200,11 @@ po_ext_iterator<T, SetType> po_ext_end(T G, SetType &S) { return po_ext_iterator<T, SetType>::end(G, S); } +template <class T, class SetType> +iterator_range<po_ext_iterator<T, SetType>> post_order_ext(const T &G, SetType &S) { + return make_range(po_ext_begin(G, S), po_ext_end(G, S)); +} + // Provide global definitions of inverse post order iterators... template <class T, class SetType = std::set<typename GraphTraits<T>::NodeType*>, @@ -205,15 +215,20 @@ struct ipo_iterator : public po_iterator<Inverse<T>, SetType, External > { }; template <class T> -ipo_iterator<T> ipo_begin(T G, bool Reverse = false) { +ipo_iterator<T> ipo_begin(const T &G, bool Reverse = false) { return ipo_iterator<T>::begin(G, Reverse); } template <class T> -ipo_iterator<T> ipo_end(T G){ +ipo_iterator<T> ipo_end(const T &G){ return ipo_iterator<T>::end(G); } +template <class T> +iterator_range<ipo_iterator<T>> inverse_post_order(const T &G, bool Reverse = false) { + return make_range(ipo_begin(G, Reverse), ipo_end(G)); +} + // Provide global definitions of external inverse postorder iterators... template <class T, class SetType = std::set<typename GraphTraits<T>::NodeType*> > @@ -225,15 +240,21 @@ struct ipo_ext_iterator : public ipo_iterator<T, SetType, true> { }; template <class T, class SetType> -ipo_ext_iterator<T, SetType> ipo_ext_begin(T G, SetType &S) { +ipo_ext_iterator<T, SetType> ipo_ext_begin(const T &G, SetType &S) { return ipo_ext_iterator<T, SetType>::begin(G, S); } template <class T, class SetType> -ipo_ext_iterator<T, SetType> ipo_ext_end(T G, SetType &S) { +ipo_ext_iterator<T, SetType> ipo_ext_end(const T &G, SetType &S) { return ipo_ext_iterator<T, SetType>::end(G, S); } +template <class T, class SetType> +iterator_range<ipo_ext_iterator<T, SetType>> +inverse_post_order_ext(const T &G, SetType &S) { + return make_range(ipo_ext_begin(G, S), ipo_ext_end(G, S)); +} + //===--------------------------------------------------------------------===// // Reverse Post Order CFG iterator code //===--------------------------------------------------------------------===// diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h index 51bb18d..fbe5b65 100644 --- a/include/llvm/ADT/Twine.h +++ b/include/llvm/ADT/Twine.h @@ -430,7 +430,7 @@ namespace llvm { /// Return the twine contents as a std::string. std::string str() const; - /// Write the concatenated string into the given SmallString or SmallVector. + /// Append the concatenated string into the given SmallString or SmallVector. void toVector(SmallVectorImpl<char> &Out) const; /// This returns the twine as a single StringRef. This method is only valid diff --git a/include/llvm/ADT/iterator.h b/include/llvm/ADT/iterator.h index e2c9e5e..54a288d 100644 --- a/include/llvm/ADT/iterator.h +++ b/include/llvm/ADT/iterator.h @@ -150,7 +150,7 @@ class iterator_adaptor_base protected: WrappedIteratorT I; - iterator_adaptor_base() {} + iterator_adaptor_base() = default; template <typename U> explicit iterator_adaptor_base( @@ -231,7 +231,7 @@ struct pointee_iterator pointee_iterator<WrappedIteratorT>, WrappedIteratorT, typename std::iterator_traits<WrappedIteratorT>::iterator_category, T> { - pointee_iterator() {} + pointee_iterator() = default; template <typename U> pointee_iterator(U &&u) : pointee_iterator::iterator_adaptor_base(std::forward<U &&>(u)) {} diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h index 43bcc34..6999bd1 100644 --- a/include/llvm/Analysis/AliasAnalysis.h +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -145,6 +145,19 @@ public: Location getLocation(const AtomicRMWInst *RMWI); static Location getLocationForSource(const MemTransferInst *MTI); static Location getLocationForDest(const MemIntrinsic *MI); + Location getLocation(const Instruction *Inst) { + if (auto *I = dyn_cast<LoadInst>(Inst)) + return getLocation(I); + else if (auto *I = dyn_cast<StoreInst>(Inst)) + return getLocation(I); + else if (auto *I = dyn_cast<VAArgInst>(Inst)) + return getLocation(I); + else if (auto *I = dyn_cast<AtomicCmpXchgInst>(Inst)) + return getLocation(I); + else if (auto *I = dyn_cast<AtomicRMWInst>(Inst)) + return getLocation(I); + llvm_unreachable("unsupported memory instruction"); + } /// Alias analysis result - Either we know for sure that it does not alias, we /// know for sure it must alias, or we don't know anything: The two pointers @@ -352,6 +365,24 @@ public: return (MRB & ModRef) && (MRB & ArgumentPointees); } + /// getModRefInfo - Return information about whether or not an + /// instruction may read or write memory (without regard to a + /// specific location) + ModRefResult getModRefInfo(const Instruction *I) { + if (auto CS = ImmutableCallSite(I)) { + auto MRB = getModRefBehavior(CS); + if (MRB & ModRef) + return ModRef; + else if (MRB & Ref) + return Ref; + else if (MRB & Mod) + return Mod; + return NoModRef; + } + + return getModRefInfo(I, Location()); + } + /// getModRefInfo - Return information about whether or not an instruction may /// read or write the specified memory location. An instruction /// that doesn't read or write memory may be trivially LICM'd for example. @@ -472,6 +503,10 @@ public: ModRefResult getModRefInfo(const VAArgInst* I, const Value* P, uint64_t Size){ return getModRefInfo(I, Location(P, Size)); } + /// getModRefInfo - Return information about whether a call and an instruction + /// may refer to the same memory locations. + ModRefResult getModRefInfo(Instruction *I, + ImmutableCallSite Call); /// getModRefInfo - Return information about whether two call sites may refer /// to the same set of memory locations. See diff --git a/include/llvm/Analysis/AssumptionCache.h b/include/llvm/Analysis/AssumptionCache.h index fc1393f..1f00b69 100644 --- a/include/llvm/Analysis/AssumptionCache.h +++ b/include/llvm/Analysis/AssumptionCache.h @@ -165,7 +165,7 @@ public: AssumptionCache &getAssumptionCache(Function &F); AssumptionCacheTracker(); - ~AssumptionCacheTracker(); + ~AssumptionCacheTracker() override; void releaseMemory() override { AssumptionCaches.shrink_and_clear(); } diff --git a/include/llvm/Analysis/BlockFrequencyInfo.h b/include/llvm/Analysis/BlockFrequencyInfo.h index 3289a28..f27c32d 100644 --- a/include/llvm/Analysis/BlockFrequencyInfo.h +++ b/include/llvm/Analysis/BlockFrequencyInfo.h @@ -34,7 +34,7 @@ public: BlockFrequencyInfo(); - ~BlockFrequencyInfo(); + ~BlockFrequencyInfo() override; void getAnalysisUsage(AnalysisUsage &AU) const override; diff --git a/include/llvm/Analysis/BlockFrequencyInfoImpl.h b/include/llvm/Analysis/BlockFrequencyInfoImpl.h index 57b5154..9acc863 100644 --- a/include/llvm/Analysis/BlockFrequencyInfoImpl.h +++ b/include/llvm/Analysis/BlockFrequencyInfoImpl.h @@ -718,9 +718,6 @@ void IrreducibleGraph::addEdges(const BlockNode &Node, /// /// It has some known flaws. /// -/// - Loop scale is limited to 4096 per loop (2^12) to avoid exhausting -/// BlockFrequency's 64-bit integer precision. -/// /// - The model of irreducible control flow is a rough approximation. /// /// Modelling irreducible control flow exactly involves setting up and diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h index 64d288a..14b8822 100644 --- a/include/llvm/Analysis/CallGraph.h +++ b/include/llvm/Analysis/CallGraph.h @@ -318,7 +318,7 @@ public: static char ID; // Class identification, replacement for typeinfo CallGraphWrapperPass(); - virtual ~CallGraphWrapperPass(); + ~CallGraphWrapperPass() override; /// \brief The internal \c CallGraph around which the rest of this interface /// is wrapped. diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h index ce0b899..0b3b2ea 100644 --- a/include/llvm/Analysis/DependenceAnalysis.h +++ b/include/llvm/Analysis/DependenceAnalysis.h @@ -219,7 +219,7 @@ namespace llvm { public: FullDependence(Instruction *Src, Instruction *Dst, bool LoopIndependent, unsigned Levels); - ~FullDependence() { delete[] DV; } + ~FullDependence() override { delete[] DV; } /// isLoopIndependent - Returns true if this is a loop-independent /// dependence. diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h index fdee9f8..79ed74d 100644 --- a/include/llvm/Analysis/InlineCost.h +++ b/include/llvm/Analysis/InlineCost.h @@ -107,7 +107,7 @@ public: static char ID; InlineCostAnalysis(); - ~InlineCostAnalysis(); + ~InlineCostAnalysis() override; // Pass interface implementation. void getAnalysisUsage(AnalysisUsage &AU) const override; diff --git a/include/llvm/Analysis/JumpInstrTableInfo.h b/include/llvm/Analysis/JumpInstrTableInfo.h index 591e794..b6dad47 100644 --- a/include/llvm/Analysis/JumpInstrTableInfo.h +++ b/include/llvm/Analysis/JumpInstrTableInfo.h @@ -39,7 +39,7 @@ public: /// The default byte alignment for jump tables is 16, which is large but /// usually safe. JumpInstrTableInfo(uint64_t ByteAlign = 16); - virtual ~JumpInstrTableInfo(); + ~JumpInstrTableInfo() override; const char *getPassName() const override { return "Jump-Instruction Table Info"; } diff --git a/include/llvm/Analysis/LazyValueInfo.h b/include/llvm/Analysis/LazyValueInfo.h index 8e5bbfb..1051cff 100644 --- a/include/llvm/Analysis/LazyValueInfo.h +++ b/include/llvm/Analysis/LazyValueInfo.h @@ -39,7 +39,7 @@ public: LazyValueInfo() : FunctionPass(ID), PImpl(nullptr) { initializeLazyValueInfoPass(*PassRegistry::getPassRegistry()); } - ~LazyValueInfo() { assert(!PImpl && "releaseMemory not called"); } + ~LazyValueInfo() override { assert(!PImpl && "releaseMemory not called"); } /// This is used to return true/false/dunno results. enum Tristate { diff --git a/include/llvm/Analysis/LibCallAliasAnalysis.h b/include/llvm/Analysis/LibCallAliasAnalysis.h index 49e0dc8..df95e0e 100644 --- a/include/llvm/Analysis/LibCallAliasAnalysis.h +++ b/include/llvm/Analysis/LibCallAliasAnalysis.h @@ -36,8 +36,8 @@ namespace llvm { : FunctionPass(ID), LCI(LC) { initializeLibCallAliasAnalysisPass(*PassRegistry::getPassRegistry()); } - ~LibCallAliasAnalysis(); - + ~LibCallAliasAnalysis() override; + ModRefResult getModRefInfo(ImmutableCallSite CS, const Location &Loc) override; diff --git a/include/llvm/Analysis/LoopAccessAnalysis.h b/include/llvm/Analysis/LoopAccessAnalysis.h index 0a9dc07..a4393bb 100644 --- a/include/llvm/Analysis/LoopAccessAnalysis.h +++ b/include/llvm/Analysis/LoopAccessAnalysis.h @@ -339,6 +339,10 @@ public: bool needsChecking(unsigned I, unsigned J, const SmallVectorImpl<int> *PtrPartition) const; + /// \brief Return true if any pointer requires run-time checking according + /// to needsChecking. + bool needsAnyChecking(const SmallVectorImpl<int> *PtrPartition) const; + /// \brief Print the list run-time memory checks necessary. /// /// If \p PtrPartition is set, it contains the partition number for @@ -428,6 +432,13 @@ public: /// Only used in DEBUG build but we don't want NDEBUG-dependent ABI. unsigned NumSymbolicStrides; + /// \brief Checks existence of store to invariant address inside loop. + /// If the loop has any store to invariant address, then it returns true, + /// else returns false. + bool hasStoreToLoopInvariantAddress() const { + return StoreToLoopInvariantAddress; + } + private: /// \brief Analyze the loop. Substitute symbolic strides using Strides. void analyzeLoop(const ValueToValueMap &Strides); @@ -465,6 +476,10 @@ private: /// \brief Cache the result of analyzeLoop. bool CanVecMem; + /// \brief Indicator for storing to uniform addresses. + /// If a loop has write to a loop invariant address then it should be true. + bool StoreToLoopInvariantAddress; + /// \brief The diagnostics report generated for the analysis. E.g. why we /// couldn't analyze the loop. Optional<LoopAccessReport> Report; diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h index 85c2da7..f3d85e6 100644 --- a/include/llvm/Analysis/LoopInfo.h +++ b/include/llvm/Analysis/LoopInfo.h @@ -464,23 +464,20 @@ public: /// cannot find a terminating instruction with location information, /// it returns an unknown location. DebugLoc getStartLoc() const { - DebugLoc StartLoc; BasicBlock *HeadBB; // Try the pre-header first. - if ((HeadBB = getLoopPreheader()) != nullptr) { - StartLoc = HeadBB->getTerminator()->getDebugLoc(); - if (!StartLoc.isUnknown()) - return StartLoc; - } + if ((HeadBB = getLoopPreheader()) != nullptr) + if (DebugLoc DL = HeadBB->getTerminator()->getDebugLoc()) + return DL; // If we have no pre-header or there are no instructions with debug // info in it, try the header. HeadBB = getHeader(); if (HeadBB) - StartLoc = HeadBB->getTerminator()->getDebugLoc(); + return HeadBB->getTerminator()->getDebugLoc(); - return StartLoc; + return DebugLoc(); } private: diff --git a/include/llvm/Analysis/LoopInfoImpl.h b/include/llvm/Analysis/LoopInfoImpl.h index 7cc4a77..0490bb1 100644 --- a/include/llvm/Analysis/LoopInfoImpl.h +++ b/include/llvm/Analysis/LoopInfoImpl.h @@ -409,9 +409,6 @@ class PopulateLoopsDFS { typedef typename BlockTraits::ChildIteratorType SuccIterTy; LoopInfoBase<BlockT, LoopT> *LI; - DenseSet<const BlockT *> VisitedBlocks; - std::vector<std::pair<BlockT*, SuccIterTy> > DFSStack; - public: PopulateLoopsDFS(LoopInfoBase<BlockT, LoopT> *li): LI(li) {} @@ -420,36 +417,13 @@ public: protected: void insertIntoLoop(BlockT *Block); - - BlockT *dfsSource() { return DFSStack.back().first; } - SuccIterTy &dfsSucc() { return DFSStack.back().second; } - SuccIterTy dfsSuccEnd() { return BlockTraits::child_end(dfsSource()); } - - void pushBlock(BlockT *Block) { - DFSStack.push_back(std::make_pair(Block, BlockTraits::child_begin(Block))); - } }; /// Top-level driver for the forward DFS within the loop. template<class BlockT, class LoopT> void PopulateLoopsDFS<BlockT, LoopT>::traverse(BlockT *EntryBlock) { - pushBlock(EntryBlock); - VisitedBlocks.insert(EntryBlock); - while (!DFSStack.empty()) { - // Traverse the leftmost path as far as possible. - while (dfsSucc() != dfsSuccEnd()) { - BlockT *BB = *dfsSucc(); - ++dfsSucc(); - if (!VisitedBlocks.insert(BB).second) - continue; - - // Push the next DFS successor onto the stack. - pushBlock(BB); - } - // Visit the top of the stack in postorder and backtrack. - insertIntoLoop(dfsSource()); - DFSStack.pop_back(); - } + for (BlockT *BB : post_order(EntryBlock)) + insertIntoLoop(BB); } /// Add a single Block to its ancestor loops in PostOrder. If the block is a @@ -498,10 +472,9 @@ Analyze(DominatorTreeBase<BlockT> &DomTree) { // Postorder traversal of the dominator tree. DomTreeNodeBase<BlockT>* DomRoot = DomTree.getRootNode(); - for (po_iterator<DomTreeNodeBase<BlockT>*> DomIter = po_begin(DomRoot), - DomEnd = po_end(DomRoot); DomIter != DomEnd; ++DomIter) { + for (auto DomNode : post_order(DomRoot)) { - BlockT *Header = DomIter->getBlock(); + BlockT *Header = DomNode->getBlock(); SmallVector<BlockT *, 4> Backedges; // Check each predecessor of the potential loop header. diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h index abc2b90..c8453e9 100644 --- a/include/llvm/Analysis/MemoryDependenceAnalysis.h +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -329,7 +329,7 @@ namespace llvm { public: MemoryDependenceAnalysis(); - ~MemoryDependenceAnalysis(); + ~MemoryDependenceAnalysis() override; static char ID; /// Pass Implementation stuff. This doesn't do any analysis eagerly. diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h index 8d11e80..d112ab1 100644 --- a/include/llvm/Analysis/Passes.h +++ b/include/llvm/Analysis/Passes.h @@ -138,6 +138,13 @@ namespace llvm { //===--------------------------------------------------------------------===// // + // createDivergenceAnalysisPass - This pass determines which branches in a GPU + // program are divergent. + // + FunctionPass *createDivergenceAnalysisPass(); + + //===--------------------------------------------------------------------===// + // // Minor pass prototypes, allowing us to expose them through bugpoint and // analyze. FunctionPass *createInstCountPass(); diff --git a/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h index 72cd357..0f7e2b8 100644 --- a/include/llvm/Analysis/PostDominators.h +++ b/include/llvm/Analysis/PostDominators.h @@ -30,7 +30,7 @@ struct PostDominatorTree : public FunctionPass { DT = new DominatorTreeBase<BasicBlock>(true); } - ~PostDominatorTree(); + ~PostDominatorTree() override; bool runOnFunction(Function &F) override; diff --git a/include/llvm/Analysis/RegionInfo.h b/include/llvm/Analysis/RegionInfo.h index 1c7f4d3..7ceb086 100644 --- a/include/llvm/Analysis/RegionInfo.h +++ b/include/llvm/Analysis/RegionInfo.h @@ -820,8 +820,6 @@ public: inline RegionNode(Region *Parent, BasicBlock *Entry, bool isSubRegion = false) : RegionNodeBase<RegionTraits<Function>>(Parent, Entry, isSubRegion) {} - ~RegionNode() {} - bool operator==(const Region &RN) const { return this == reinterpret_cast<const RegionNode *>(&RN); } @@ -842,7 +840,7 @@ class RegionInfo : public RegionInfoBase<RegionTraits<Function>> { public: explicit RegionInfo(); - virtual ~RegionInfo(); + ~RegionInfo() override; // updateStatistics - Update statistic about created regions. void updateStatistics(Region *R) final; @@ -858,7 +856,7 @@ public: static char ID; explicit RegionInfoPass(); - ~RegionInfoPass(); + ~RegionInfoPass() override; RegionInfo &getRegionInfo() { return RI; } diff --git a/include/llvm/Analysis/RegionInfoImpl.h b/include/llvm/Analysis/RegionInfoImpl.h index b0dc263..b31eefc 100644 --- a/include/llvm/Analysis/RegionInfoImpl.h +++ b/include/llvm/Analysis/RegionInfoImpl.h @@ -487,7 +487,7 @@ void RegionBase<Tr>::print(raw_ostream &OS, bool print_tree, unsigned level, OS.indent(level * 2 + 2); if (Style == PrintBB) { - for (const auto &BB : blocks()) + for (const auto *BB : blocks()) OS << BB->getName() << ", "; // TODO: remove the last "," } else if (Style == PrintRN) { for (const_element_iterator I = element_begin(), E = element_end(); @@ -714,10 +714,8 @@ void RegionInfoBase<Tr>::scanForRegions(FuncT &F, BBtoBBMap *ShortCut) { // regions from the bottom of the dominance tree. If the small regions are // detected first, detection of bigger regions is faster, as we can jump // over the small regions. - for (po_iterator<DomTreeNodeT *> FI = po_begin(N), FE = po_end(N); FI != FE; - ++FI) { - findRegionsWithEntry(FI->getBlock(), ShortCut); - } + for (auto DomNode : post_order(N)) + findRegionsWithEntry(DomNode->getBlock(), ShortCut); } template <class Tr> diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index 4360414..1240b85 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -256,6 +256,10 @@ namespace llvm { /// Mark predicate values currently being processed by isImpliedCond. DenseSet<Value*> PendingLoopPredicates; + /// Set to true by isLoopBackedgeGuardedByCond when we're walking the set of + /// conditions dominating the backedge of a loop. + bool WalkingBEDominatingConds; + /// ExitLimit - Information about the number of loop iterations for which a /// loop exit's branch condition evaluates to the not-taken path. This is a /// temporary pair of exact and max expressions that are eventually diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h index b0b0946..8ec2078 100644 --- a/include/llvm/Analysis/ScalarEvolutionExpander.h +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -28,7 +28,7 @@ namespace llvm { /// all materialized values are safe to speculate. bool isSafeToExpand(const SCEV *S, ScalarEvolution &SE); - /// SCEVExpander - This class uses information about analyze scalars to + /// This class uses information about analyze scalars to /// rewrite expressions in canonical form. /// /// Clients should create an instance of this class when rewriting is needed, @@ -48,37 +48,36 @@ namespace llvm { std::set<AssertingVH<Value> > InsertedValues; std::set<AssertingVH<Value> > InsertedPostIncValues; - /// RelevantLoops - A memoization of the "relevant" loop for a given SCEV. + /// A memoization of the "relevant" loop for a given SCEV. DenseMap<const SCEV *, const Loop *> RelevantLoops; - /// PostIncLoops - Addrecs referring to any of the given loops are expanded + /// \brief Addrecs referring to any of the given loops are expanded /// in post-inc mode. For example, expanding {1,+,1}<L> in post-inc mode /// returns the add instruction that adds one to the phi for {0,+,1}<L>, /// as opposed to a new phi starting at 1. This is only supported in /// non-canonical mode. PostIncLoopSet PostIncLoops; - /// IVIncInsertPos - When this is non-null, addrecs expanded in the - /// loop it indicates should be inserted with increments at - /// IVIncInsertPos. + /// \brief When this is non-null, addrecs expanded in the loop it indicates + /// should be inserted with increments at IVIncInsertPos. const Loop *IVIncInsertLoop; - /// IVIncInsertPos - When expanding addrecs in the IVIncInsertLoop loop, - /// insert the IV increment at this position. + /// \brief When expanding addrecs in the IVIncInsertLoop loop, insert the IV + /// increment at this position. Instruction *IVIncInsertPos; - /// Phis that complete an IV chain. Reuse + /// \brief Phis that complete an IV chain. Reuse std::set<AssertingVH<PHINode> > ChainedPhis; - /// CanonicalMode - When true, expressions are expanded in "canonical" - /// form. In particular, addrecs are expanded as arithmetic based on - /// a canonical induction variable. When false, expression are expanded - /// in a more literal form. + /// \brief When true, expressions are expanded in "canonical" form. In + /// particular, addrecs are expanded as arithmetic based on a canonical + /// induction variable. When false, expression are expanded in a more + /// literal form. bool CanonicalMode; - /// When invoked from LSR, the expander is in "strength reduction" mode. The - /// only difference is that phi's are only reused if they are already in - /// "expanded" form. + /// \brief When invoked from LSR, the expander is in "strength reduction" + /// mode. The only difference is that phi's are only reused if they are + /// already in "expanded" form. bool LSRMode; typedef IRBuilder<true, TargetFolder> BuilderType; @@ -91,7 +90,7 @@ namespace llvm { friend struct SCEVVisitor<SCEVExpander, Value*>; public: - /// SCEVExpander - Construct a SCEVExpander in "canonical" mode. + /// \brief Construct a SCEVExpander in "canonical" mode. explicit SCEVExpander(ScalarEvolution &se, const DataLayout &DL, const char *name) : SE(se), DL(DL), IVName(name), IVIncInsertLoop(nullptr), @@ -106,7 +105,7 @@ namespace llvm { void setDebugType(const char* s) { DebugType = s; } #endif - /// clear - Erase the contents of the InsertedExpressions map so that users + /// \brief Erase the contents of the InsertedExpressions map so that users /// trying to expand the same expression into multiple BasicBlocks or /// different places within the same BasicBlock can do so. void clear() { @@ -116,31 +115,38 @@ namespace llvm { ChainedPhis.clear(); } - /// getOrInsertCanonicalInductionVariable - This method returns the - /// canonical induction variable of the specified type for the specified - /// loop (inserting one if there is none). A canonical induction variable - /// starts at zero and steps by one on each iteration. + /// \brief Return true for expressions that may incur non-trivial cost to + /// evaluate at runtime. + bool isHighCostExpansion(const SCEV *Expr, Loop *L) { + SmallPtrSet<const SCEV *, 8> Processed; + return isHighCostExpansionHelper(Expr, L, Processed); + } + + /// \brief This method returns the canonical induction variable of the + /// specified type for the specified loop (inserting one if there is none). + /// A canonical induction variable starts at zero and steps by one on each + /// iteration. PHINode *getOrInsertCanonicalInductionVariable(const Loop *L, Type *Ty); - /// getIVIncOperand - Return the induction variable increment's IV operand. + /// \brief Return the induction variable increment's IV operand. Instruction *getIVIncOperand(Instruction *IncV, Instruction *InsertPos, bool allowScale); - /// hoistIVInc - Utility for hoisting an IV increment. + /// \brief Utility for hoisting an IV increment. bool hoistIVInc(Instruction *IncV, Instruction *InsertPos); - /// replaceCongruentIVs - replace congruent phis with their most canonical + /// \brief replace congruent phis with their most canonical /// representative. Return the number of phis eliminated. unsigned replaceCongruentIVs(Loop *L, const DominatorTree *DT, SmallVectorImpl<WeakVH> &DeadInsts, const TargetTransformInfo *TTI = nullptr); - /// expandCodeFor - Insert code to directly compute the specified SCEV - /// expression into the program. The inserted code is inserted into the - /// specified block. + /// \brief Insert code to directly compute the specified SCEV expression + /// into the program. The inserted code is inserted into the specified + /// block. Value *expandCodeFor(const SCEV *SH, Type *Ty, Instruction *I); - /// setIVIncInsertPos - Set the current IV increment loop and position. + /// \brief Set the current IV increment loop and position. void setIVIncInsertPos(const Loop *L, Instruction *Pos) { assert(!CanonicalMode && "IV increment positions are not supported in CanonicalMode"); @@ -148,16 +154,15 @@ namespace llvm { IVIncInsertPos = Pos; } - /// setPostInc - Enable post-inc expansion for addrecs referring to the - /// given loops. Post-inc expansion is only supported in non-canonical - /// mode. + /// \brief Enable post-inc expansion for addrecs referring to the given + /// loops. Post-inc expansion is only supported in non-canonical mode. void setPostInc(const PostIncLoopSet &L) { assert(!CanonicalMode && "Post-inc expansion is not supported in CanonicalMode"); PostIncLoops = L; } - /// clearPostInc - Disable all post-inc expansion. + /// \brief Disable all post-inc expansion. void clearPostInc() { PostIncLoops.clear(); @@ -166,23 +171,22 @@ namespace llvm { InsertedPostIncValues.clear(); } - /// disableCanonicalMode - Disable the behavior of expanding expressions in - /// canonical form rather than in a more literal form. Non-canonical mode - /// is useful for late optimization passes. + /// \brief Disable the behavior of expanding expressions in canonical form + /// rather than in a more literal form. Non-canonical mode is useful for + /// late optimization passes. void disableCanonicalMode() { CanonicalMode = false; } void enableLSRMode() { LSRMode = true; } - /// clearInsertPoint - Clear the current insertion point. This is useful - /// if the instruction that had been serving as the insertion point may - /// have been deleted. + /// \brief Clear the current insertion point. This is useful if the + /// instruction that had been serving as the insertion point may have been + /// deleted. void clearInsertPoint() { Builder.ClearInsertionPoint(); } - /// isInsertedInstruction - Return true if the specified instruction was - /// inserted by the code rewriter. If so, the client should not modify the - /// instruction. + /// \brief Return true if the specified instruction was inserted by the code + /// rewriter. If so, the client should not modify the instruction. bool isInsertedInstruction(Instruction *I) const { return InsertedValues.count(I) || InsertedPostIncValues.count(I); } @@ -192,24 +196,27 @@ namespace llvm { private: LLVMContext &getContext() const { return SE.getContext(); } - /// InsertBinop - Insert the specified binary operator, doing a small amount + /// \brief Recursive helper function for isHighCostExpansion. + bool isHighCostExpansionHelper(const SCEV *S, Loop *L, + SmallPtrSetImpl<const SCEV *> &Processed); + + /// \brief Insert the specified binary operator, doing a small amount /// of work to avoid inserting an obviously redundant operation. Value *InsertBinop(Instruction::BinaryOps Opcode, Value *LHS, Value *RHS); - /// ReuseOrCreateCast - Arange for there to be a cast of V to Ty at IP, - /// reusing an existing cast if a suitable one exists, moving an existing - /// cast if a suitable one exists but isn't in the right place, or - /// or creating a new one. + /// \brief Arrange for there to be a cast of V to Ty at IP, reusing an + /// existing cast if a suitable one exists, moving an existing cast if a + /// suitable one exists but isn't in the right place, or or creating a new + /// one. Value *ReuseOrCreateCast(Value *V, Type *Ty, Instruction::CastOps Op, BasicBlock::iterator IP); - /// InsertNoopCastOfTo - Insert a cast of V to the specified type, - /// which must be possible with a noop cast, doing what we can to - /// share the casts. + /// \brief Insert a cast of V to the specified type, which must be possible + /// with a noop cast, doing what we can to share the casts. Value *InsertNoopCastOfTo(Value *V, Type *Ty); - /// expandAddToGEP - Expand a SCEVAddExpr with a pointer type into a GEP + /// \brief Expand a SCEVAddExpr with a pointer type into a GEP /// instead of using ptrtoint+arithmetic+inttoptr. Value *expandAddToGEP(const SCEV *const *op_begin, const SCEV *const *op_end, @@ -217,13 +224,13 @@ namespace llvm { Value *expand(const SCEV *S); - /// expandCodeFor - Insert code to directly compute the specified SCEV - /// expression into the program. The inserted code is inserted into the - /// SCEVExpander's current insertion point. If a type is specified, the - /// result will be expanded to have that type, with a cast if necessary. + /// \brief Insert code to directly compute the specified SCEV expression + /// into the program. The inserted code is inserted into the SCEVExpander's + /// current insertion point. If a type is specified, the result will be + /// expanded to have that type, with a cast if necessary. Value *expandCodeFor(const SCEV *SH, Type *Ty = nullptr); - /// getRelevantLoop - Determine the most "relevant" loop for the given SCEV. + /// \brief Determine the most "relevant" loop for the given SCEV. const Loop *getRelevantLoop(const SCEV *); Value *visitConstant(const SCEVConstant *S) { diff --git a/include/llvm/Analysis/TargetFolder.h b/include/llvm/Analysis/TargetFolder.h index f691296..12bf9fe 100644 --- a/include/llvm/Analysis/TargetFolder.h +++ b/include/llvm/Analysis/TargetFolder.h @@ -130,34 +130,35 @@ public: // Memory Instructions //===--------------------------------------------------------------------===// - Constant *CreateGetElementPtr(Constant *C, + Constant *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return Fold(ConstantExpr::getGetElementPtr(C, IdxList)); + return Fold(ConstantExpr::getGetElementPtr(Ty, C, IdxList)); } - Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return Fold(ConstantExpr::getGetElementPtr(C, Idx)); + return Fold(ConstantExpr::getGetElementPtr(Ty, C, Idx)); } - Constant *CreateGetElementPtr(Constant *C, + Constant *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return Fold(ConstantExpr::getGetElementPtr(C, IdxList)); + return Fold(ConstantExpr::getGetElementPtr(Ty, C, IdxList)); } - Constant *CreateInBoundsGetElementPtr(Constant *C, + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList)); + return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList)); } - Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, + Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return Fold(ConstantExpr::getInBoundsGetElementPtr(C, Idx)); + return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx)); } - Constant *CreateInBoundsGetElementPtr(Constant *C, + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return Fold(ConstantExpr::getInBoundsGetElementPtr(C, IdxList)); + return Fold(ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList)); } //===--------------------------------------------------------------------===// diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index fdb2010..f4195fb 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -190,12 +190,21 @@ public: /// comments for a detailed explanation of the cost values. unsigned getUserCost(const User *U) const; - /// \brief hasBranchDivergence - Return true if branch divergence exists. + /// \brief Return true if branch divergence exists. + /// /// Branch divergence has a significantly negative impact on GPU performance /// when threads in the same wavefront take different paths due to conditional /// branches. bool hasBranchDivergence() const; + /// \brief Returns whether V is a source of divergence. + /// + /// This function provides the target-dependent information for + /// the target-independent DivergenceAnalysis. DivergenceAnalysis first + /// builds the dependency graph, and then runs the reachability algorithm + /// starting with the sources of divergence. + bool isSourceOfDivergence(const Value *V) const; + /// \brief Test whether calls to a function lower to actual program function /// calls. /// @@ -252,6 +261,9 @@ public: /// loop body even when the number of loop iterations is not known at /// compile time). bool Runtime; + /// Allow emitting expensive instructions (such as divisions) when computing + /// the trip count of a loop for runtime unrolling. + bool AllowExpensiveTripCount; }; /// \brief Get target-customized preferences for the generic loop unrolling @@ -520,6 +532,7 @@ public: ArrayRef<const Value *> Arguments) = 0; virtual unsigned getUserCost(const User *U) = 0; virtual bool hasBranchDivergence() = 0; + virtual bool isSourceOfDivergence(const Value *V) = 0; virtual bool isLoweredToCall(const Function *F) = 0; virtual void getUnrollingPreferences(Loop *L, UnrollingPreferences &UP) = 0; virtual bool isLegalAddImmediate(int64_t Imm) = 0; @@ -619,6 +632,9 @@ public: } unsigned getUserCost(const User *U) override { return Impl.getUserCost(U); } bool hasBranchDivergence() override { return Impl.hasBranchDivergence(); } + bool isSourceOfDivergence(const Value *V) override { + return Impl.isSourceOfDivergence(V); + } bool isLoweredToCall(const Function *F) override { return Impl.isLoweredToCall(F); } diff --git a/include/llvm/Analysis/TargetTransformInfoImpl.h b/include/llvm/Analysis/TargetTransformInfoImpl.h index f4bf07f..b00de77 100644 --- a/include/llvm/Analysis/TargetTransformInfoImpl.h +++ b/include/llvm/Analysis/TargetTransformInfoImpl.h @@ -164,6 +164,8 @@ public: bool hasBranchDivergence() { return false; } + bool isSourceOfDivergence(const Value *V) { return false; } + bool isLoweredToCall(const Function *F) { // FIXME: These should almost certainly not be handled here, and instead // handled with the help of TLI or the target itself. This was largely @@ -408,7 +410,7 @@ public: ->getGEPCost(GEP->getPointerOperand(), Indices); } - if (ImmutableCallSite CS = U) { + if (auto CS = ImmutableCallSite(U)) { const Function *F = CS.getCalledFunction(); if (!F) { // Just use the called value type. diff --git a/include/llvm/Bitcode/BitCodes.h b/include/llvm/Bitcode/BitCodes.h index 3f7a77d..96c4201 100644 --- a/include/llvm/Bitcode/BitCodes.h +++ b/include/llvm/Bitcode/BitCodes.h @@ -164,8 +164,8 @@ template <> struct isPodLike<BitCodeAbbrevOp> { static const bool value=true; }; /// specialized format instead of the fully-general, fully-vbr, format. class BitCodeAbbrev : public RefCountedBase<BitCodeAbbrev> { SmallVector<BitCodeAbbrevOp, 32> OperandList; - ~BitCodeAbbrev() {} // Only RefCountedBase is allowed to delete. + ~BitCodeAbbrev() = default; friend class RefCountedBase<BitCodeAbbrev>; public: diff --git a/include/llvm/Bitcode/BitcodeWriterPass.h b/include/llvm/Bitcode/BitcodeWriterPass.h index 8fe9b7e..ae915c6 100644 --- a/include/llvm/Bitcode/BitcodeWriterPass.h +++ b/include/llvm/Bitcode/BitcodeWriterPass.h @@ -26,7 +26,11 @@ class PreservedAnalyses; /// \brief Create and return a pass that writes the module to the specified /// ostream. Note that this pass is designed for use with the legacy pass /// manager. -ModulePass *createBitcodeWriterPass(raw_ostream &Str); +/// +/// If \c ShouldPreserveUseListOrder, encode use-list order so it can be +/// reproduced when deserialized. +ModulePass *createBitcodeWriterPass(raw_ostream &Str, + bool ShouldPreserveUseListOrder = false); /// \brief Pass for writing a module of IR out to a bitcode file. /// @@ -34,10 +38,16 @@ ModulePass *createBitcodeWriterPass(raw_ostream &Str); /// a pass for the legacy pass manager, use the function above. class BitcodeWriterPass { raw_ostream &OS; + bool ShouldPreserveUseListOrder; public: /// \brief Construct a bitcode writer pass around a particular output stream. - explicit BitcodeWriterPass(raw_ostream &OS) : OS(OS) {} + /// + /// If \c ShouldPreserveUseListOrder, encode use-list order so it can be + /// reproduced when deserialized. + explicit BitcodeWriterPass(raw_ostream &OS, + bool ShouldPreserveUseListOrder = false) + : OS(OS), ShouldPreserveUseListOrder(ShouldPreserveUseListOrder) {} /// \brief Run the bitcode writer pass, and output the module to the selected /// output stream. diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index d842167..e450db0 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -397,7 +397,8 @@ namespace bitc { ATTR_KIND_IN_ALLOCA = 38, ATTR_KIND_NON_NULL = 39, ATTR_KIND_JUMP_TABLE = 40, - ATTR_KIND_DEREFERENCEABLE = 41 + ATTR_KIND_DEREFERENCEABLE = 41, + ATTR_KIND_DEREFERENCEABLE_OR_NULL = 42 }; enum ComdatSelectionKindCodes { diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h index 254949d..9d30098 100644 --- a/include/llvm/Bitcode/ReaderWriter.h +++ b/include/llvm/Bitcode/ReaderWriter.h @@ -56,11 +56,16 @@ namespace llvm { parseBitcodeFile(MemoryBufferRef Buffer, LLVMContext &Context, DiagnosticHandlerFunction DiagnosticHandler = nullptr); - /// WriteBitcodeToFile - Write the specified module to the specified - /// raw output stream. For streams where it matters, the given stream - /// should be in "binary" mode. - void WriteBitcodeToFile(const Module *M, raw_ostream &Out); - + /// \brief Write the specified module to the specified raw output stream. + /// + /// For streams where it matters, the given stream should be in "binary" + /// mode. + /// + /// If \c ShouldPreserveUseListOrder, encode the use-list order for each \a + /// Value in \c M. These will be reconstructed exactly when \a M is + /// deserialized. + void WriteBitcodeToFile(const Module *M, raw_ostream &Out, + bool ShouldPreserveUseListOrder = false); /// isBitcodeWrapper - Return true if the given bytes are the magic bytes /// for an LLVM IR bitcode wrapper. diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index d364012..11f98ca 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -140,7 +140,7 @@ protected: explicit AsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer); public: - virtual ~AsmPrinter(); + ~AsmPrinter() override; DwarfDebug *getDwarfDebug() { return DD; } DwarfDebug *getDwarfDebug() const { return DD; } diff --git a/include/llvm/CodeGen/BasicTTIImpl.h b/include/llvm/CodeGen/BasicTTIImpl.h index e1e5112..c5efef3 100644 --- a/include/llvm/CodeGen/BasicTTIImpl.h +++ b/include/llvm/CodeGen/BasicTTIImpl.h @@ -114,6 +114,8 @@ public: bool hasBranchDivergence() { return false; } + bool isSourceOfDivergence(const Value *V) { return false; } + bool isLegalAddImmediate(int64_t imm) { return getTLI()->isLegalAddImmediate(imm); } diff --git a/include/llvm/CodeGen/GCStrategy.h b/include/llvm/CodeGen/GCStrategy.h index 869f888..a1b8e89 100644 --- a/include/llvm/CodeGen/GCStrategy.h +++ b/include/llvm/CodeGen/GCStrategy.h @@ -60,11 +60,11 @@ namespace llvm { namespace GC { -/// PointKind - The type of a collector-safe point. +/// PointKind - Used to indicate whether the address of the call instruction +/// or the address after the call instruction is listed in the stackmap. For +/// most runtimes, PostCall safepoints are appropriate. /// enum PointKind { - Loop, ///< Instr is a loop (backwards branch). - Return, ///< Instr is a return instruction. PreCall, ///< Instr is a call instruction. PostCall ///< Instr is the return address of a call. }; diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index b3a8405..aa217d5 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -23,7 +23,7 @@ #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/IR/DebugLoc.h" -#include "llvm/IR/Metadata.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/ValueHandle.h" #include <unordered_map> #include <utility> @@ -45,7 +45,8 @@ typedef std::pair<const MachineInstr *, const MachineInstr *> InsnRange; class LexicalScope { public: - LexicalScope(LexicalScope *P, const MDNode *D, const MDNode *I, bool A) + LexicalScope(LexicalScope *P, const MDLocalScope *D, const MDLocation *I, + bool A) : Parent(P), Desc(D), InlinedAtLocation(I), AbstractScope(A), LastInsn(nullptr), FirstInsn(nullptr), DFSIn(0), DFSOut(0) { assert((!D || D->isResolved()) && "Expected resolved node"); @@ -57,8 +58,8 @@ public: // Accessors. LexicalScope *getParent() const { return Parent; } const MDNode *getDesc() const { return Desc; } - const MDNode *getInlinedAt() const { return InlinedAtLocation; } - const MDNode *getScopeNode() const { return Desc; } + const MDLocation *getInlinedAt() const { return InlinedAtLocation; } + const MDLocalScope *getScopeNode() const { return Desc; } bool isAbstractScope() const { return AbstractScope; } SmallVectorImpl<LexicalScope *> &getChildren() { return Children; } SmallVectorImpl<InsnRange> &getRanges() { return Ranges; } @@ -118,8 +119,8 @@ public: private: LexicalScope *Parent; // Parent to this scope. - const MDNode *Desc; // Debug info descriptor. - const MDNode *InlinedAtLocation; // Location at which this + const MDLocalScope *Desc; // Debug info descriptor. + const MDLocation *InlinedAtLocation; // Location at which this // scope is inlined. bool AbstractScope; // Abstract Scope SmallVector<LexicalScope *, 4> Children; // Scopes defined in scope. @@ -158,16 +159,16 @@ public: /// getMachineBasicBlocks - Populate given set using machine basic blocks /// which have machine instructions that belong to lexical scope identified by /// DebugLoc. - void getMachineBasicBlocks(DebugLoc DL, + void getMachineBasicBlocks(const MDLocation *DL, SmallPtrSetImpl<const MachineBasicBlock *> &MBBs); /// dominates - Return true if DebugLoc's lexical scope dominates at least one /// machine instruction's lexical scope in a given machine basic block. - bool dominates(DebugLoc DL, MachineBasicBlock *MBB); + bool dominates(const MDLocation *DL, MachineBasicBlock *MBB); /// findLexicalScope - Find lexical scope, either regular or inlined, for the /// given DebugLoc. Return NULL if not found. - LexicalScope *findLexicalScope(DebugLoc DL); + LexicalScope *findLexicalScope(const MDLocation *DL); /// getAbstractScopesList - Return a reference to list of abstract scopes. ArrayRef<LexicalScope *> getAbstractScopesList() const { @@ -175,19 +176,19 @@ public: } /// findAbstractScope - Find an abstract scope or return null. - LexicalScope *findAbstractScope(const MDNode *N) { + LexicalScope *findAbstractScope(const MDLocalScope *N) { auto I = AbstractScopeMap.find(N); return I != AbstractScopeMap.end() ? &I->second : nullptr; } /// findInlinedScope - Find an inlined scope for the given scope/inlined-at. - LexicalScope *findInlinedScope(const MDNode *N, const MDNode *IA) { + LexicalScope *findInlinedScope(const MDLocalScope *N, const MDLocation *IA) { auto I = InlinedLexicalScopeMap.find(std::make_pair(N, IA)); return I != InlinedLexicalScopeMap.end() ? &I->second : nullptr; } /// findLexicalScope - Find regular lexical scope or return null. - LexicalScope *findLexicalScope(const MDNode *N) { + LexicalScope *findLexicalScope(const MDLocalScope *N) { auto I = LexicalScopeMap.find(N); return I != LexicalScopeMap.end() ? &I->second : nullptr; } @@ -196,18 +197,24 @@ public: void dump(); /// getOrCreateAbstractScope - Find or create an abstract lexical scope. - LexicalScope *getOrCreateAbstractScope(const MDNode *N); + LexicalScope *getOrCreateAbstractScope(const MDLocalScope *Scope); private: - /// getOrCreateLexicalScope - Find lexical scope for the given DebugLoc. If + /// getOrCreateLexicalScope - Find lexical scope for the given Scope/IA. If /// not available then create new lexical scope. - LexicalScope *getOrCreateLexicalScope(DebugLoc DL); + LexicalScope *getOrCreateLexicalScope(const MDLocalScope *Scope, + const MDLocation *IA = nullptr); + LexicalScope *getOrCreateLexicalScope(const MDLocation *DL) { + return DL ? getOrCreateLexicalScope(DL->getScope(), DL->getInlinedAt()) + : nullptr; + } /// getOrCreateRegularScope - Find or create a regular lexical scope. - LexicalScope *getOrCreateRegularScope(MDNode *Scope); + LexicalScope *getOrCreateRegularScope(const MDLocalScope *Scope); /// getOrCreateInlinedScope - Find or create an inlined lexical scope. - LexicalScope *getOrCreateInlinedScope(MDNode *Scope, MDNode *InlinedAt); + LexicalScope *getOrCreateInlinedScope(const MDLocalScope *Scope, + const MDLocation *InlinedAt); /// extractLexicalScopes - Extract instruction ranges for each lexical scopes /// for the given machine function. @@ -223,17 +230,18 @@ private: /// LexicalScopeMap - Tracks the scopes in the current function. // Use an unordered_map to ensure value pointer validity over insertion. - std::unordered_map<const MDNode *, LexicalScope> LexicalScopeMap; + std::unordered_map<const MDLocalScope *, LexicalScope> LexicalScopeMap; /// InlinedLexicalScopeMap - Tracks inlined function scopes in current /// function. - std::unordered_map<std::pair<const MDNode *, const MDNode *>, LexicalScope, - pair_hash<const MDNode *, const MDNode *>> - InlinedLexicalScopeMap; + std::unordered_map<std::pair<const MDLocalScope *, const MDLocation *>, + LexicalScope, + pair_hash<const MDLocalScope *, const MDLocation *>> + InlinedLexicalScopeMap; /// AbstractScopeMap - These scopes are not included LexicalScopeMap. // Use an unordered_map to ensure value pointer validity over insertion. - std::unordered_map<const MDNode *, LexicalScope> AbstractScopeMap; + std::unordered_map<const MDLocalScope *, LexicalScope> AbstractScopeMap; /// AbstractScopesList - Tracks abstract scopes constructed while processing /// a function. diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index dc52c0a..9673f80 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -100,7 +100,7 @@ extern cl::opt<bool> UseSegmentSetForPhysRegs; public: static char ID; // Pass identification, replacement for typeid LiveIntervals(); - virtual ~LiveIntervals(); + ~LiveIntervals() override; // Calculate the spill weight to assign to a single instruction. static float getSpillWeight(bool isDef, bool isUse, diff --git a/include/llvm/CodeGen/LiveRangeEdit.h b/include/llvm/CodeGen/LiveRangeEdit.h index 44c3c4e..de855f2 100644 --- a/include/llvm/CodeGen/LiveRangeEdit.h +++ b/include/llvm/CodeGen/LiveRangeEdit.h @@ -122,7 +122,7 @@ public: MRI.setDelegate(this); } - ~LiveRangeEdit() { MRI.resetDelegate(this); } + ~LiveRangeEdit() override { MRI.resetDelegate(this); } LiveInterval &getParent() const { assert(Parent && "No parent LiveInterval"); diff --git a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h index 1aef689..feb394e 100644 --- a/include/llvm/CodeGen/MachineBlockFrequencyInfo.h +++ b/include/llvm/CodeGen/MachineBlockFrequencyInfo.h @@ -35,7 +35,7 @@ public: MachineBlockFrequencyInfo(); - ~MachineBlockFrequencyInfo(); + ~MachineBlockFrequencyInfo() override; void getAnalysisUsage(AnalysisUsage &AU) const override; diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h index 19f4e2d..4428fa6 100644 --- a/include/llvm/CodeGen/MachineDominators.h +++ b/include/llvm/CodeGen/MachineDominators.h @@ -72,7 +72,7 @@ public: MachineDominatorTree(); - ~MachineDominatorTree(); + ~MachineDominatorTree() override; DominatorTreeBase<MachineBasicBlock> &getBase() { applySplitCriticalEdges(); diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index 6677360..1e7fee6 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -516,10 +516,6 @@ public: /// on the stack. Returns an index with a negative value. int CreateFixedSpillStackObject(uint64_t Size, int64_t SPOffset); - /// Allocates memory at a fixed, target-specific offset from the frame - /// pointer. Marks the function as having its frame address taken. - int CreateFrameAllocation(uint64_t Size); - /// isFixedObjectIndex - Returns true if the specified index corresponds to a /// fixed stack object. bool isFixedObjectIndex(int ObjectIdx) const { diff --git a/include/llvm/CodeGen/MachineFunctionAnalysis.h b/include/llvm/CodeGen/MachineFunctionAnalysis.h index 36f1c66..023eeb1 100644 --- a/include/llvm/CodeGen/MachineFunctionAnalysis.h +++ b/include/llvm/CodeGen/MachineFunctionAnalysis.h @@ -31,7 +31,7 @@ private: public: static char ID; explicit MachineFunctionAnalysis(const TargetMachine &tm); - ~MachineFunctionAnalysis(); + ~MachineFunctionAnalysis() override; MachineFunction &getMF() const { return *MF; } diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 333dcdb..9097150 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -248,9 +248,7 @@ public: /// this DBG_VALUE instruction. DIVariable getDebugVariable() const { assert(isDebugValue() && "not a DBG_VALUE"); - DIVariable Var(getOperand(2).getMetadata()); - assert(Var.Verify() && "not a DIVariable"); - return Var; + return cast<MDLocalVariable>(getOperand(2).getMetadata()); } /// \brief Return the complex address expression referenced by diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index e6cb494..0574ebc 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -174,7 +174,8 @@ public: const MachineInstrBuilder &addMetadata(const MDNode *MD) const { MI->addOperand(*MF, MachineOperand::CreateMetadata(MD)); - assert((MI->isDebugValue() ? MI->getDebugVariable().Verify() : true) && + assert((MI->isDebugValue() ? static_cast<bool>(MI->getDebugVariable()) + : true) && "first MDNode argument of a DBG_VALUE not a DIVariable"); return *this; } @@ -355,8 +356,10 @@ inline MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID, bool IsIndirect, unsigned Reg, unsigned Offset, const MDNode *Variable, const MDNode *Expr) { - assert(DIVariable(Variable).Verify() && "not a DIVariable"); - assert(DIExpression(Expr)->isValid() && "not a DIExpression"); + assert(isa<MDLocalVariable>(Variable) && "not a DIVariable"); + assert(cast<MDExpression>(Expr)->isValid() && "not a DIExpression"); + assert(cast<MDLocalVariable>(Variable)->isValidLocationForIntrinsic(DL) && + "Expected inlined-at fields to agree"); if (IsIndirect) return BuildMI(MF, DL, MCID) .addReg(Reg, RegState::Debug) @@ -382,8 +385,8 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, const MCInstrDesc &MCID, bool IsIndirect, unsigned Reg, unsigned Offset, const MDNode *Variable, const MDNode *Expr) { - assert(DIVariable(Variable).Verify() && "not a DIVariable"); - assert(DIExpression(Expr)->isValid() && "not a DIExpression"); + assert(isa<MDLocalVariable>(Variable) && "not a DIVariable"); + assert(cast<MDExpression>(Expr)->isValid() && "not a DIExpression"); MachineFunction &MF = *BB.getParent(); MachineInstr *MI = BuildMI(MF, DL, MCID, IsIndirect, Reg, Offset, Variable, Expr); diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index f171df2..3965b1d 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -58,22 +58,25 @@ class MachineFunction; class Module; class PointerType; class StructType; +struct WinEHFuncInfo; //===----------------------------------------------------------------------===// /// LandingPadInfo - This structure is used to retain landing pad info for /// the current function. /// struct LandingPadInfo { - MachineBasicBlock *LandingPadBlock; // Landing pad block. - SmallVector<MCSymbol*, 1> BeginLabels; // Labels prior to invoke. - SmallVector<MCSymbol*, 1> EndLabels; // Labels after invoke. - SmallVector<MCSymbol*, 1> ClauseLabels; // Labels for each clause. - MCSymbol *LandingPadLabel; // Label at beginning of landing pad. - const Function *Personality; // Personality function. - std::vector<int> TypeIds; // List of type ids (filters negative) + MachineBasicBlock *LandingPadBlock; // Landing pad block. + SmallVector<MCSymbol *, 1> BeginLabels; // Labels prior to invoke. + SmallVector<MCSymbol *, 1> EndLabels; // Labels after invoke. + SmallVector<MCSymbol *, 1> ClauseLabels; // Labels for each clause. + MCSymbol *LandingPadLabel; // Label at beginning of landing pad. + const Function *Personality; // Personality function. + std::vector<int> TypeIds; // List of type ids (filters negative). + int WinEHState; // WinEH specific state number. explicit LandingPadInfo(MachineBasicBlock *MBB) - : LandingPadBlock(MBB), LandingPadLabel(nullptr), Personality(nullptr) {} + : LandingPadBlock(MBB), LandingPadLabel(nullptr), Personality(nullptr), + WinEHState(-1) {} }; //===----------------------------------------------------------------------===// @@ -88,7 +91,10 @@ public: virtual ~MachineModuleInfoImpl(); typedef std::vector<std::pair<MCSymbol*, StubValueTy> > SymbolListTy; protected: - static SymbolListTy GetSortedStubs(const DenseMap<MCSymbol*, StubValueTy>&); + + /// Return the entries from a DenseMap in a deterministic sorted orer. + /// Clears the map. + static SymbolListTy getSortedStubs(DenseMap<MCSymbol*, StubValueTy>&); }; //===----------------------------------------------------------------------===// @@ -172,16 +178,19 @@ class MachineModuleInfo : public ImmutablePass { EHPersonality PersonalityTypeCache; + DenseMap<const Function *, std::unique_ptr<WinEHFuncInfo>> FuncInfoMap; + public: static char ID; // Pass identification, replacement for typeid struct VariableDbgInfo { - TrackingMDNodeRef Var; - TrackingMDNodeRef Expr; + const MDLocalVariable *Var; + const MDExpression *Expr; unsigned Slot; - DebugLoc Loc; + const MDLocation *Loc; - VariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot, DebugLoc Loc) + VariableDbgInfo(const MDLocalVariable *Var, const MDExpression *Expr, + unsigned Slot, const MDLocation *Loc) : Var(Var), Expr(Expr), Slot(Slot), Loc(Loc) {} }; typedef SmallVector<VariableDbgInfo, 4> VariableDbgInfoMapTy; @@ -191,7 +200,7 @@ public: // Real constructor. MachineModuleInfo(const MCAsmInfo &MAI, const MCRegisterInfo &MRI, const MCObjectFileInfo *MOFI); - ~MachineModuleInfo(); + ~MachineModuleInfo() override; // Initialization and Finalization bool doInitialization(Module &) override; @@ -207,6 +216,12 @@ public: void setModule(const Module *M) { TheModule = M; } const Module *getModule() const { return TheModule; } + const Function *getWinEHParent(const Function *F) const; + WinEHFuncInfo &getWinEHFuncInfo(const Function *F); + bool hasWinEHFuncInfo(const Function *F) const { + return FuncInfoMap.count(getWinEHParent(F)) > 0; + } + /// getInfo - Keep track of various per-function pieces of information for /// backends that would like to do so. /// @@ -304,6 +319,8 @@ public: void addPersonality(MachineBasicBlock *LandingPad, const Function *Personality); + void addWinEHState(MachineBasicBlock *LandingPad, int State); + /// getPersonalityIndex - Get index of the current personality function inside /// Personalitites array unsigned getPersonalityIndex() const; @@ -421,8 +438,8 @@ public: /// setVariableDbgInfo - Collect information used to emit debugging /// information of a variable. - void setVariableDbgInfo(MDNode *Var, MDNode *Expr, unsigned Slot, - DebugLoc Loc) { + void setVariableDbgInfo(const MDLocalVariable *Var, const MDExpression *Expr, + unsigned Slot, const MDLocation *Loc) { VariableDbgInfos.emplace_back(Var, Expr, Slot, Loc); } diff --git a/include/llvm/CodeGen/MachineModuleInfoImpls.h b/include/llvm/CodeGen/MachineModuleInfoImpls.h index 7afc7eb..a67f9b5 100644 --- a/include/llvm/CodeGen/MachineModuleInfoImpls.h +++ b/include/llvm/CodeGen/MachineModuleInfoImpls.h @@ -58,14 +58,14 @@ namespace llvm { } /// Accessor methods to return the set of stubs in sorted order. - SymbolListTy GetFnStubList() const { - return GetSortedStubs(FnStubs); + SymbolListTy GetFnStubList() { + return getSortedStubs(FnStubs); } - SymbolListTy GetGVStubList() const { - return GetSortedStubs(GVStubs); + SymbolListTy GetGVStubList() { + return getSortedStubs(GVStubs); } - SymbolListTy GetHiddenGVStubList() const { - return GetSortedStubs(HiddenGVStubs); + SymbolListTy GetHiddenGVStubList() { + return getSortedStubs(HiddenGVStubs); } }; @@ -87,8 +87,8 @@ namespace llvm { /// Accessor methods to return the set of stubs in sorted order. - SymbolListTy GetGVStubList() const { - return GetSortedStubs(GVStubs); + SymbolListTy GetGVStubList() { + return getSortedStubs(GVStubs); } }; diff --git a/include/llvm/CodeGen/MachinePassRegistry.h b/include/llvm/CodeGen/MachinePassRegistry.h index 57d1a6d..6731983 100644 --- a/include/llvm/CodeGen/MachinePassRegistry.h +++ b/include/llvm/CodeGen/MachinePassRegistry.h @@ -124,7 +124,7 @@ class RegisterPassParser : public MachinePassRegistryListener, public: RegisterPassParser(cl::Option &O) : cl::parser<typename RegistryClass::FunctionPassCtor>(O) {} - ~RegisterPassParser() { RegistryClass::setListener(nullptr); } + ~RegisterPassParser() override { RegistryClass::setListener(nullptr); } void initialize() { cl::parser<typename RegistryClass::FunctionPassCtor>::initialize(); diff --git a/include/llvm/CodeGen/MachinePostDominators.h b/include/llvm/CodeGen/MachinePostDominators.h index aab5c40..70bdb19 100644 --- a/include/llvm/CodeGen/MachinePostDominators.h +++ b/include/llvm/CodeGen/MachinePostDominators.h @@ -33,7 +33,7 @@ public: MachinePostDominatorTree(); - ~MachinePostDominatorTree(); + ~MachinePostDominatorTree() override; FunctionPass *createMachinePostDominatorTreePass(); diff --git a/include/llvm/CodeGen/MachineRegionInfo.h b/include/llvm/CodeGen/MachineRegionInfo.h index 43499db..cf49c29 100644 --- a/include/llvm/CodeGen/MachineRegionInfo.h +++ b/include/llvm/CodeGen/MachineRegionInfo.h @@ -57,8 +57,6 @@ public: } - ~MachineRegionNode() { } - bool operator==(const MachineRegion &RN) const { return this == reinterpret_cast<const MachineRegionNode*>(&RN); } @@ -80,7 +78,7 @@ class MachineRegionInfo : public RegionInfoBase<RegionTraits<MachineFunction>> { public: explicit MachineRegionInfo(); - virtual ~MachineRegionInfo(); + ~MachineRegionInfo() override; // updateStatistics - Update statistic about created regions. void updateStatistics(MachineRegion *R) final; @@ -98,7 +96,7 @@ public: static char ID; explicit MachineRegionInfoPass(); - ~MachineRegionInfoPass(); + ~MachineRegionInfoPass() override; MachineRegionInfo &getRegionInfo() { return RI; diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 001d09f..e5b837a 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -620,22 +620,25 @@ public: /// setRegAllocationHint - Specify a register allocation hint for the /// specified virtual register. - void setRegAllocationHint(unsigned Reg, unsigned Type, unsigned PrefReg) { - RegAllocHints[Reg].first = Type; - RegAllocHints[Reg].second = PrefReg; + void setRegAllocationHint(unsigned VReg, unsigned Type, unsigned PrefReg) { + assert(TargetRegisterInfo::isVirtualRegister(VReg)); + RegAllocHints[VReg].first = Type; + RegAllocHints[VReg].second = PrefReg; } /// getRegAllocationHint - Return the register allocation hint for the /// specified virtual register. std::pair<unsigned, unsigned> - getRegAllocationHint(unsigned Reg) const { - return RegAllocHints[Reg]; + getRegAllocationHint(unsigned VReg) const { + assert(TargetRegisterInfo::isVirtualRegister(VReg)); + return RegAllocHints[VReg]; } /// getSimpleHint - Return the preferred register allocation hint, or 0 if a /// standard simple hint (Type == 0) is not set. - unsigned getSimpleHint(unsigned Reg) const { - std::pair<unsigned, unsigned> Hint = getRegAllocationHint(Reg); + unsigned getSimpleHint(unsigned VReg) const { + assert(TargetRegisterInfo::isVirtualRegister(VReg)); + std::pair<unsigned, unsigned> Hint = getRegAllocationHint(VReg); return Hint.first ? 0 : Hint.second; } diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index a319401..e80e14e 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -385,7 +385,7 @@ public: ShouldTrackPressure(false), RPTracker(RegPressure), TopRPTracker(TopPressure), BotRPTracker(BotPressure) {} - virtual ~ScheduleDAGMILive(); + ~ScheduleDAGMILive() override; /// Return true if this DAG supports VReg liveness and RegPressure. bool hasVRegLiveness() const override { return true; } @@ -909,7 +909,7 @@ public: PostGenericScheduler(const MachineSchedContext *C): GenericSchedulerBase(C), Top(SchedBoundary::TopQID, "TopQ") {} - virtual ~PostGenericScheduler() {} + ~PostGenericScheduler() override {} void initPolicy(MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End, diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 48e1f21..2505c04 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -125,7 +125,7 @@ public: // Dummy constructor. TargetPassConfig(); - virtual ~TargetPassConfig(); + ~TargetPassConfig() override; static char ID; diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h index cc9e000..fcb6fee 100644 --- a/include/llvm/CodeGen/RegisterPressure.h +++ b/include/llvm/CodeGen/RegisterPressure.h @@ -35,21 +35,6 @@ struct RegisterPressure { SmallVector<unsigned,8> LiveInRegs; SmallVector<unsigned,8> LiveOutRegs; - /// Increase register pressure for each pressure set impacted by this register - /// class. Normally called by RegPressureTracker, but may be called manually - /// to account for live through (global liveness). - /// - /// \param Reg is either a virtual register number or register unit number. - void increase(unsigned Reg, const TargetRegisterInfo *TRI, - const MachineRegisterInfo *MRI); - - /// Decrease register pressure for each pressure set impacted by this register - /// class. This is only useful to account for spilling or rematerialization. - /// - /// \param Reg is either a virtual register number or register unit number. - void decrease(unsigned Reg, const TargetRegisterInfo *TRI, - const MachineRegisterInfo *MRI); - void dump(const TargetRegisterInfo *TRI) const; }; diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h index 00dd8f9..1196783 100644 --- a/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -158,7 +158,7 @@ namespace llvm { bool RemoveKillFlags = false, LiveIntervals *LIS = nullptr); - virtual ~ScheduleDAGInstrs() {} + ~ScheduleDAGInstrs() override {} bool isPostRA() const { return IsPostRA; } diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index dc1c80d..582febd 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -41,14 +41,16 @@ class TargetSelectionDAGInfo; class SDVTListNode : public FoldingSetNode { friend struct FoldingSetTrait<SDVTListNode>; - /// FastID - A reference to an Interned FoldingSetNodeID for this node. + /// A reference to an Interned FoldingSetNodeID for this node. /// The Allocator in SelectionDAG holds the data. /// SDVTList contains all types which are frequently accessed in SelectionDAG. - /// The size of this list is not expected big so it won't introduce memory penalty. + /// The size of this list is not expected to be big so it won't introduce + /// a memory penalty. FoldingSetNodeIDRef FastID; const EVT *VTs; unsigned int NumVTs; - /// The hash value for SDVTList is fixed so cache it to avoid hash calculation + /// The hash value for SDVTList is fixed, so cache it to avoid + /// hash calculation. unsigned HashValue; public: SDVTListNode(const FoldingSetNodeIDRef ID, const EVT *VT, unsigned int Num) : @@ -61,8 +63,8 @@ public: } }; -// Specialize FoldingSetTrait for SDVTListNode -// To avoid computing temp FoldingSetNodeID and hash value. +/// Specialize FoldingSetTrait for SDVTListNode +/// to avoid computing temp FoldingSetNodeID and hash value. template<> struct FoldingSetTrait<SDVTListNode> : DefaultFoldingSetTrait<SDVTListNode> { static void Profile(const SDVTListNode &X, FoldingSetNodeID& ID) { ID = X.FastID; @@ -98,7 +100,7 @@ private: static void createNode(const SDNode &); }; -/// SDDbgInfo - Keeps track of dbg_value information through SDISel. We do +/// Keeps track of dbg_value information through SDISel. We do /// not build SDNodes for these so as not to perturb the generated code; /// instead the info is kept off to the side in this structure. Each SDNode may /// have one or more associated dbg_value entries. This information is kept in @@ -159,10 +161,10 @@ public: class SelectionDAG; void checkForCycles(const SelectionDAG *DAG, bool force = false); -/// SelectionDAG class - This is used to represent a portion of an LLVM function -/// in a low-level Data Dependence DAG representation suitable for instruction -/// selection. This DAG is constructed as the first step of instruction -/// selection in order to allow implementation of machine specific optimizations +/// This is used to represent a portion of an LLVM function in a low-level +/// Data Dependence DAG representation suitable for instruction selection. +/// This DAG is constructed as the first step of instruction selection in order +/// to allow implementation of machine specific optimizations /// and code simplifications. /// /// The representation used by the SelectionDAG is a target-independent @@ -178,40 +180,39 @@ class SelectionDAG { LLVMContext *Context; CodeGenOpt::Level OptLevel; - /// EntryNode - The starting token. + /// The starting token. SDNode EntryNode; - /// Root - The root of the entire DAG. + /// The root of the entire DAG. SDValue Root; - /// AllNodes - A linked list of nodes in the current DAG. + /// A linked list of nodes in the current DAG. ilist<SDNode> AllNodes; - /// NodeAllocatorType - The AllocatorType for allocating SDNodes. We use + /// The AllocatorType for allocating SDNodes. We use /// pool allocation with recycling. typedef RecyclingAllocator<BumpPtrAllocator, SDNode, sizeof(LargestSDNode), AlignOf<MostAlignedSDNode>::Alignment> NodeAllocatorType; - /// NodeAllocator - Pool allocation for nodes. + /// Pool allocation for nodes. NodeAllocatorType NodeAllocator; - /// CSEMap - This structure is used to memoize nodes, automatically performing + /// This structure is used to memoize nodes, automatically performing /// CSE with existing nodes when a duplicate is requested. FoldingSet<SDNode> CSEMap; - /// OperandAllocator - Pool allocation for machine-opcode SDNode operands. + /// Pool allocation for machine-opcode SDNode operands. BumpPtrAllocator OperandAllocator; - /// Allocator - Pool allocation for misc. objects that are created once per - /// SelectionDAG. + /// Pool allocation for misc. objects that are created once per SelectionDAG. BumpPtrAllocator Allocator; - /// DbgInfo - Tracks dbg_value information through SDISel. + /// Tracks dbg_value information through SDISel. SDDbgInfo *DbgInfo; public: - /// DAGUpdateListener - Clients of various APIs that cause global effects on + /// Clients of various APIs that cause global effects on /// the DAG can optionally implement this interface. This allows the clients /// to handle the various sorts of updates that happen. /// @@ -232,15 +233,15 @@ public: DAG.UpdateListeners = Next; } - /// NodeDeleted - The node N that was deleted and, if E is not null, an + /// The node N that was deleted and, if E is not null, an /// equivalent node E that replaced it. virtual void NodeDeleted(SDNode *N, SDNode *E); - /// NodeUpdated - The node N that was updated. + /// The node N that was updated. virtual void NodeUpdated(SDNode *N); }; - /// NewNodesMustHaveLegalTypes - When true, additional steps are taken to + /// When true, additional steps are taken to /// ensure that getConstant() and similar functions return DAG nodes that /// have legal types. This is important after type legalization since /// any illegally typed nodes generated after this point will not experience @@ -251,13 +252,12 @@ private: /// DAGUpdateListener is a friend so it can manipulate the listener stack. friend struct DAGUpdateListener; - /// UpdateListeners - Linked list of registered DAGUpdateListener instances. + /// Linked list of registered DAGUpdateListener instances. /// This stack is maintained by DAGUpdateListener RAII. DAGUpdateListener *UpdateListeners; - /// setGraphColorHelper - Implementation of setSubgraphColor. + /// Implementation of setSubgraphColor. /// Return whether we had to truncate the search. - /// bool setSubgraphColorHelper(SDNode *N, const char *Color, DenseSet<SDNode *> &visited, int level, bool &printed); @@ -269,14 +269,11 @@ public: explicit SelectionDAG(const TargetMachine &TM, llvm::CodeGenOpt::Level); ~SelectionDAG(); - /// init - Prepare this SelectionDAG to process code in the given - /// MachineFunction. - /// + /// Prepare this SelectionDAG to process code in the given MachineFunction. void init(MachineFunction &mf); - /// clear - Clear state and free memory necessary to make this + /// Clear state and free memory necessary to make this /// SelectionDAG ready to process a new block. - /// void clear(); MachineFunction &getMachineFunction() const { return *MF; } @@ -286,8 +283,7 @@ public: const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return *TSI; } LLVMContext *getContext() const {return Context; } - /// viewGraph - Pop up a GraphViz/gv window with the DAG rendered using 'dot'. - /// + /// Pop up a GraphViz/gv window with the DAG rendered using 'dot'. void viewGraph(const std::string &Title); void viewGraph(); @@ -295,24 +291,21 @@ public: std::map<const SDNode *, std::string> NodeGraphAttrs; #endif - /// clearGraphAttrs - Clear all previously defined node graph attributes. + /// Clear all previously defined node graph attributes. /// Intended to be used from a debugging tool (eg. gdb). void clearGraphAttrs(); - /// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".) - /// + /// Set graph attributes for a node. (eg. "color=red".) void setGraphAttrs(const SDNode *N, const char *Attrs); - /// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".) + /// Get graph attributes for a node. (eg. "color=red".) /// Used from getNodeAttributes. const std::string getGraphAttrs(const SDNode *N) const; - /// setGraphColor - Convenience for setting node color attribute. - /// + /// Convenience for setting node color attribute. void setGraphColor(const SDNode *N, const char *Color); - /// setGraphColor - Convenience for setting subgraph color attribute. - /// + /// Convenience for setting subgraph color attribute. void setSubgraphColor(SDNode *N, const char *Color); typedef ilist<SDNode>::const_iterator allnodes_const_iterator; @@ -325,17 +318,15 @@ public: return AllNodes.size(); } - /// getRoot - Return the root tag of the SelectionDAG. - /// + /// Return the root tag of the SelectionDAG. const SDValue &getRoot() const { return Root; } - /// getEntryNode - Return the token chain corresponding to the entry of the - /// function. + /// Return the token chain corresponding to the entry of the function. SDValue getEntryNode() const { return SDValue(const_cast<SDNode *>(&EntryNode), 0); } - /// setRoot - Set the current root tag of the SelectionDAG. + /// Set the current root tag of the SelectionDAG. /// const SDValue &setRoot(SDValue N) { assert((!N.getNode() || N.getValueType() == MVT::Other) && @@ -348,22 +339,22 @@ public: return Root; } - /// Combine - This iterates over the nodes in the SelectionDAG, folding + /// This iterates over the nodes in the SelectionDAG, folding /// certain types of nodes together, or eliminating superfluous nodes. The /// Level argument controls whether Combine is allowed to produce nodes and /// types that are illegal on the target. void Combine(CombineLevel Level, AliasAnalysis &AA, CodeGenOpt::Level OptLevel); - /// LegalizeTypes - This transforms the SelectionDAG into a SelectionDAG that - /// only uses types natively supported by the target. Returns "true" if it - /// made any changes. + /// This transforms the SelectionDAG into a SelectionDAG that + /// only uses types natively supported by the target. + /// Returns "true" if it made any changes. /// /// Note that this is an involved process that may invalidate pointers into /// the graph. bool LegalizeTypes(); - /// Legalize - This transforms the SelectionDAG into a SelectionDAG that is + /// This transforms the SelectionDAG into a SelectionDAG that is /// compatible with the target instruction selector, as indicated by the /// TargetLowering object. /// @@ -392,7 +383,7 @@ public: /// UpdatedNodes with any new nodes replacing those originally in the DAG. bool LegalizeOp(SDNode *N, SmallSetVector<SDNode *, 16> &UpdatedNodes); - /// LegalizeVectors - This transforms the SelectionDAG into a SelectionDAG + /// This transforms the SelectionDAG into a SelectionDAG /// that only uses vector math operations supported by the target. This is /// necessary as a separate step from Legalize because unrolling a vector /// operation can introduce illegal types, which requires running @@ -405,16 +396,14 @@ public: /// the graph. bool LegalizeVectors(); - /// RemoveDeadNodes - This method deletes all unreachable nodes in the - /// SelectionDAG. + /// This method deletes all unreachable nodes in the SelectionDAG. void RemoveDeadNodes(); - /// DeleteNode - Remove the specified node from the system. This node must + /// Remove the specified node from the system. This node must /// have no referrers. void DeleteNode(SDNode *N); - /// getVTList - Return an SDVTList that represents the list of values - /// specified. + /// Return an SDVTList that represents the list of values specified. SDVTList getVTList(EVT VT); SDVTList getVTList(EVT VT1, EVT VT2); SDVTList getVTList(EVT VT1, EVT VT2, EVT VT3); @@ -561,10 +550,9 @@ public: SDValue STy, SDValue Rnd, SDValue Sat, ISD::CvtCode Code); - /// getVectorShuffle - Return an ISD::VECTOR_SHUFFLE node. The number of - /// elements in VT, which must be a vector type, must match the number of - /// mask elements NumElts. A integer mask element equal to -1 is treated as - /// undefined. + /// Return an ISD::VECTOR_SHUFFLE node. The number of elements in VT, + /// which must be a vector type, must match the number of mask elements + /// NumElts. An integer mask element equal to -1 is treated as undefined. SDValue getVectorShuffle(EVT VT, SDLoc dl, SDValue N1, SDValue N2, const int *MaskElts); SDValue getVectorShuffle(EVT VT, SDLoc dl, SDValue N1, SDValue N2, @@ -580,63 +568,62 @@ public: /// Example: shuffle A, B, <0,5,2,7> -> shuffle B, A, <4,1,6,3> SDValue getCommutedVectorShuffle(const ShuffleVectorSDNode &SV); - /// getAnyExtOrTrunc - Convert Op, which must be of integer type, to the + /// Convert Op, which must be of integer type, to the /// integer type VT, by either any-extending or truncating it. SDValue getAnyExtOrTrunc(SDValue Op, SDLoc DL, EVT VT); - /// getSExtOrTrunc - Convert Op, which must be of integer type, to the + /// Convert Op, which must be of integer type, to the /// integer type VT, by either sign-extending or truncating it. SDValue getSExtOrTrunc(SDValue Op, SDLoc DL, EVT VT); - /// getZExtOrTrunc - Convert Op, which must be of integer type, to the + /// Convert Op, which must be of integer type, to the /// integer type VT, by either zero-extending or truncating it. SDValue getZExtOrTrunc(SDValue Op, SDLoc DL, EVT VT); - /// getZeroExtendInReg - Return the expression required to zero extend the Op + /// Return the expression required to zero extend the Op /// value assuming it was the smaller SrcTy value. SDValue getZeroExtendInReg(SDValue Op, SDLoc DL, EVT SrcTy); - /// getAnyExtendVectorInReg - Return an operation which will any-extend the - /// low lanes of the operand into the specified vector type. For example, + /// Return an operation which will any-extend the low lanes of the operand + /// into the specified vector type. For example, /// this can convert a v16i8 into a v4i32 by any-extending the low four /// lanes of the operand from i8 to i32. SDValue getAnyExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT); - /// getSignExtendVectorInReg - Return an operation which will sign extend the - /// low lanes of the operand into the specified vector type. For example, + /// Return an operation which will sign extend the low lanes of the operand + /// into the specified vector type. For example, /// this can convert a v16i8 into a v4i32 by sign extending the low four /// lanes of the operand from i8 to i32. SDValue getSignExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT); - /// getZeroExtendVectorInReg - Return an operation which will zero extend the - /// low lanes of the operand into the specified vector type. For example, + /// Return an operation which will zero extend the low lanes of the operand + /// into the specified vector type. For example, /// this can convert a v16i8 into a v4i32 by zero extending the low four /// lanes of the operand from i8 to i32. SDValue getZeroExtendVectorInReg(SDValue Op, SDLoc DL, EVT VT); - /// getBoolExtOrTrunc - Convert Op, which must be of integer type, to the - /// integer type VT, by using an extension appropriate for the target's + /// Convert Op, which must be of integer type, to the integer type VT, + /// by using an extension appropriate for the target's /// BooleanContent for type OpVT or truncating it. SDValue getBoolExtOrTrunc(SDValue Op, SDLoc SL, EVT VT, EVT OpVT); - /// getNOT - Create a bitwise NOT operation as (XOR Val, -1). + /// Create a bitwise NOT operation as (XOR Val, -1). SDValue getNOT(SDLoc DL, SDValue Val, EVT VT); /// \brief Create a logical NOT operation as (XOR Val, BooleanOne). SDValue getLogicalNOT(SDLoc DL, SDValue Val, EVT VT); - /// getCALLSEQ_START - Return a new CALLSEQ_START node, which always must have - /// a glue result (to ensure it's not CSE'd). CALLSEQ_START does not have a - /// useful SDLoc. + /// Return a new CALLSEQ_START node, which always must have a glue result + /// (to ensure it's not CSE'd). CALLSEQ_START does not have a useful SDLoc. SDValue getCALLSEQ_START(SDValue Chain, SDValue Op, SDLoc DL) { SDVTList VTs = getVTList(MVT::Other, MVT::Glue); SDValue Ops[] = { Chain, Op }; return getNode(ISD::CALLSEQ_START, DL, VTs, Ops); } - /// getCALLSEQ_END - Return a new CALLSEQ_END node, which always must have a - /// glue result (to ensure it's not CSE'd). CALLSEQ_END does not have - /// a useful SDLoc. + /// Return a new CALLSEQ_END node, which always must have a + /// glue result (to ensure it's not CSE'd). + /// CALLSEQ_END does not have a useful SDLoc. SDValue getCALLSEQ_END(SDValue Chain, SDValue Op1, SDValue Op2, SDValue InGlue, SDLoc DL) { SDVTList NodeTys = getVTList(MVT::Other, MVT::Glue); @@ -649,18 +636,17 @@ public: return getNode(ISD::CALLSEQ_END, DL, NodeTys, Ops); } - /// getUNDEF - Return an UNDEF node. UNDEF does not have a useful SDLoc. + /// Return an UNDEF node. UNDEF does not have a useful SDLoc. SDValue getUNDEF(EVT VT) { return getNode(ISD::UNDEF, SDLoc(), VT); } - /// getGLOBAL_OFFSET_TABLE - Return a GLOBAL_OFFSET_TABLE node. This does - /// not have a useful SDLoc. + /// Return a GLOBAL_OFFSET_TABLE node. This does not have a useful SDLoc. SDValue getGLOBAL_OFFSET_TABLE(EVT VT) { return getNode(ISD::GLOBAL_OFFSET_TABLE, SDLoc(), VT); } - /// getNode - Gets or creates the specified node. + /// Gets or creates the specified node. /// SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT); SDValue getNode(unsigned Opcode, SDLoc DL, EVT VT, SDValue N); @@ -692,27 +678,26 @@ public: SDValue N1, SDValue N2, SDValue N3, SDValue N4, SDValue N5); - /// getStackArgumentTokenFactor - Compute a TokenFactor to force all - /// the incoming stack arguments to be loaded from the stack. This is - /// used in tail call lowering to protect stack arguments from being - /// clobbered. + /// Compute a TokenFactor to force all the incoming stack arguments to be + /// loaded from the stack. This is used in tail call lowering to protect + /// stack arguments from being clobbered. SDValue getStackArgumentTokenFactor(SDValue Chain); SDValue getMemcpy(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool isVol, bool AlwaysInline, - MachinePointerInfo DstPtrInfo, + bool isTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo); SDValue getMemmove(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src, - SDValue Size, unsigned Align, bool isVol, + SDValue Size, unsigned Align, bool isVol, bool isTailCall, MachinePointerInfo DstPtrInfo, MachinePointerInfo SrcPtrInfo); SDValue getMemset(SDValue Chain, SDLoc dl, SDValue Dst, SDValue Src, - SDValue Size, unsigned Align, bool isVol, + SDValue Size, unsigned Align, bool isVol, bool isTailCall, MachinePointerInfo DstPtrInfo); - /// getSetCC - Helper function to make it easier to build SetCC's if you just + /// Helper function to make it easier to build SetCC's if you just /// have an ISD::CondCode instead of an SDValue. /// SDValue getSetCC(SDLoc DL, EVT VT, SDValue LHS, SDValue RHS, @@ -726,8 +711,8 @@ public: return getNode(ISD::SETCC, DL, VT, LHS, RHS, getCondCode(Cond)); } - // getSelect - Helper function to make it easier to build Select's if you just - // have operands and don't want to check for vector. + /// Helper function to make it easier to build Select's if you just + /// have operands and don't want to check for vector. SDValue getSelect(SDLoc DL, EVT VT, SDValue Cond, SDValue LHS, SDValue RHS) { assert(LHS.getValueType() == RHS.getValueType() && @@ -738,7 +723,7 @@ public: Cond, LHS, RHS); } - /// getSelectCC - Helper function to make it easier to build SelectCC's if you + /// Helper function to make it easier to build SelectCC's if you /// just have an ISD::CondCode instead of an SDValue. /// SDValue getSelectCC(SDLoc DL, SDValue LHS, SDValue RHS, @@ -747,12 +732,12 @@ public: LHS, RHS, True, False, getCondCode(Cond)); } - /// getVAArg - VAArg produces a result and token chain, and takes a pointer + /// VAArg produces a result and token chain, and takes a pointer /// and a source value as input. SDValue getVAArg(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, SDValue SV, unsigned Align); - /// getAtomicCmpSwap - Gets a node for an atomic cmpxchg op. There are two + /// Gets a node for an atomic cmpxchg op. There are two /// valid Opcodes. ISD::ATOMIC_CMO_SWAP produces the value loaded and a /// chain result. ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS produces the value loaded, /// a success flag (initially i1), and a chain. @@ -769,7 +754,7 @@ public: AtomicOrdering FailureOrdering, SynchronizationScope SynchScope); - /// getAtomic - Gets a node for an atomic op, produces result (if relevant) + /// Gets a node for an atomic op, produces result (if relevant) /// and chain and takes 2 operands. SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDValue Chain, SDValue Ptr, SDValue Val, const Value *PtrVal, @@ -780,15 +765,15 @@ public: AtomicOrdering Ordering, SynchronizationScope SynchScope); - /// getAtomic - Gets a node for an atomic op, produces result and chain and + /// Gets a node for an atomic op, produces result and chain and /// takes 1 operand. SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, EVT VT, SDValue Chain, SDValue Ptr, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope); - /// getAtomic - Gets a node for an atomic op, produces result and chain and - /// takes N operands. + /// Gets a node for an atomic op, produces result and chain and takes N + /// operands. SDValue getAtomic(unsigned Opcode, SDLoc dl, EVT MemVT, SDVTList VTList, ArrayRef<SDValue> Ops, MachineMemOperand *MMO, AtomicOrdering SuccessOrdering, @@ -798,7 +783,7 @@ public: ArrayRef<SDValue> Ops, MachineMemOperand *MMO, AtomicOrdering Ordering, SynchronizationScope SynchScope); - /// getMemIntrinsicNode - Creates a MemIntrinsicNode that may produce a + /// Creates a MemIntrinsicNode that may produce a /// result and takes a list of operands. Opcode may be INTRINSIC_VOID, /// INTRINSIC_W_CHAIN, or a target-specific opcode with a value not /// less than FIRST_TARGET_MEMORY_OPCODE. @@ -813,10 +798,10 @@ public: ArrayRef<SDValue> Ops, EVT MemVT, MachineMemOperand *MMO); - /// getMergeValues - Create a MERGE_VALUES node from the given operands. + /// Create a MERGE_VALUES node from the given operands. SDValue getMergeValues(ArrayRef<SDValue> Ops, SDLoc dl); - /// getLoad - Loads are not normal binary operators: their result type is not + /// Loads are not normal binary operators: their result type is not /// determined by their operands, and they produce a value AND a token chain. /// SDValue getLoad(EVT VT, SDLoc dl, SDValue Chain, SDValue Ptr, @@ -848,8 +833,7 @@ public: SDValue Chain, SDValue Ptr, SDValue Offset, EVT MemVT, MachineMemOperand *MMO); - /// getStore - Helper function to build ISD::STORE nodes. - /// + /// Helper function to build ISD::STORE nodes. SDValue getStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, MachinePointerInfo PtrInfo, bool isVolatile, bool isNonTemporal, unsigned Alignment, @@ -872,21 +856,21 @@ public: SDValue getMaskedStore(SDValue Chain, SDLoc dl, SDValue Val, SDValue Ptr, SDValue Mask, EVT MemVT, MachineMemOperand *MMO, bool IsTrunc); - /// getSrcValue - Construct a node to track a Value* through the backend. + /// Construct a node to track a Value* through the backend. SDValue getSrcValue(const Value *v); - /// getMDNode - Return an MDNodeSDNode which holds an MDNode. + /// Return an MDNodeSDNode which holds an MDNode. SDValue getMDNode(const MDNode *MD); - /// getAddrSpaceCast - Return an AddrSpaceCastSDNode. + /// Return an AddrSpaceCastSDNode. SDValue getAddrSpaceCast(SDLoc dl, EVT VT, SDValue Ptr, unsigned SrcAS, unsigned DestAS); - /// getShiftAmountOperand - Return the specified value casted to + /// Return the specified value casted to /// the target's desired shift amount type. SDValue getShiftAmountOperand(EVT LHSTy, SDValue Op); - /// UpdateNodeOperands - *Mutate* the specified node in-place to have the + /// *Mutate* the specified node in-place to have the /// specified operands. If the resultant node already exists in the DAG, /// this does not modify the specified node, instead it returns the node that /// already exists. If the resultant node does not exist in the DAG, the @@ -902,7 +886,7 @@ public: SDValue Op3, SDValue Op4, SDValue Op5); SDNode *UpdateNodeOperands(SDNode *N, ArrayRef<SDValue> Ops); - /// SelectNodeTo - These are used for target selectors to *mutate* the + /// These are used for target selectors to *mutate* the /// specified node to have the specified return type, Target opcode, and /// operands. Note that target opcodes are stored as /// ~TargetOpcode in the node opcode field. The resultant node is returned. @@ -932,12 +916,12 @@ public: SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, SDVTList VTs, ArrayRef<SDValue> Ops); - /// MorphNodeTo - This *mutates* the specified node to have the specified + /// This *mutates* the specified node to have the specified /// return type, opcode, and operands. SDNode *MorphNodeTo(SDNode *N, unsigned Opc, SDVTList VTs, ArrayRef<SDValue> Ops); - /// getMachineNode - These are used for target selectors to create a new node + /// These are used for target selectors to create a new node /// with specified return type(s), MachineInstr opcode, and operands. /// /// Note that getMachineNode returns the resultant node. If there is already @@ -976,25 +960,20 @@ public: MachineSDNode *getMachineNode(unsigned Opcode, SDLoc dl, SDVTList VTs, ArrayRef<SDValue> Ops); - /// getTargetExtractSubreg - A convenience function for creating - /// TargetInstrInfo::EXTRACT_SUBREG nodes. + /// A convenience function for creating TargetInstrInfo::EXTRACT_SUBREG nodes. SDValue getTargetExtractSubreg(int SRIdx, SDLoc DL, EVT VT, SDValue Operand); - /// getTargetInsertSubreg - A convenience function for creating - /// TargetInstrInfo::INSERT_SUBREG nodes. + /// A convenience function for creating TargetInstrInfo::INSERT_SUBREG nodes. SDValue getTargetInsertSubreg(int SRIdx, SDLoc DL, EVT VT, SDValue Operand, SDValue Subreg); - /// getNodeIfExists - Get the specified node if it's already available, or - /// else return NULL. + /// Get the specified node if it's already available, or else return NULL. SDNode *getNodeIfExists(unsigned Opcode, SDVTList VTs, ArrayRef<SDValue> Ops, bool nuw = false, bool nsw = false, bool exact = false); - /// getDbgValue - Creates a SDDbgValue node. - /// - /// SDNode + /// Creates a SDDbgValue node. SDDbgValue *getDbgValue(MDNode *Var, MDNode *Expr, SDNode *N, unsigned R, bool IsIndirect, uint64_t Off, DebugLoc DL, unsigned O); @@ -1007,16 +986,16 @@ public: SDDbgValue *getFrameIndexDbgValue(MDNode *Var, MDNode *Expr, unsigned FI, uint64_t Off, DebugLoc DL, unsigned O); - /// RemoveDeadNode - Remove the specified node from the system. If any of its + /// Remove the specified node from the system. If any of its /// operands then becomes dead, remove them as well. Inform UpdateListener /// for each node deleted. void RemoveDeadNode(SDNode *N); - /// RemoveDeadNodes - This method deletes the unreachable nodes in the + /// This method deletes the unreachable nodes in the /// given list, and any nodes that become unreachable as a result. void RemoveDeadNodes(SmallVectorImpl<SDNode *> &DeadNodes); - /// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead. + /// Modify anything using 'From' to use 'To' instead. /// This can cause recursive merging of nodes in the DAG. Use the first /// version if 'From' is known to have a single result, use the second /// if you have two nodes with identical results (or if 'To' has a superset @@ -1035,30 +1014,29 @@ public: void ReplaceAllUsesWith(SDNode *From, SDNode *To); void ReplaceAllUsesWith(SDNode *From, const SDValue *To); - /// ReplaceAllUsesOfValueWith - Replace any uses of From with To, leaving + /// Replace any uses of From with To, leaving /// uses of other values produced by From.Val alone. void ReplaceAllUsesOfValueWith(SDValue From, SDValue To); - /// ReplaceAllUsesOfValuesWith - Like ReplaceAllUsesOfValueWith, but - /// for multiple values at once. This correctly handles the case where + /// Like ReplaceAllUsesOfValueWith, but for multiple values at once. + /// This correctly handles the case where /// there is an overlap between the From values and the To values. void ReplaceAllUsesOfValuesWith(const SDValue *From, const SDValue *To, unsigned Num); - /// AssignTopologicalOrder - Topological-sort the AllNodes list and a + /// Topological-sort the AllNodes list and a /// assign a unique node id for each node in the DAG based on their /// topological order. Returns the number of nodes. unsigned AssignTopologicalOrder(); - /// RepositionNode - Move node N in the AllNodes list to be immediately + /// Move node N in the AllNodes list to be immediately /// before the given iterator Position. This may be used to update the /// topological ordering when the list of nodes is modified. void RepositionNode(allnodes_iterator Position, SDNode *N) { AllNodes.insert(Position, AllNodes.remove(N)); } - /// isCommutativeBinOp - Returns true if the opcode is a commutative binary - /// operation. + /// Returns true if the opcode is a commutative binary operation. static bool isCommutativeBinOp(unsigned Opcode) { // FIXME: This should get its info from the td file, so that we can include // target info. @@ -1099,19 +1077,19 @@ public: } } - /// AddDbgValue - Add a dbg_value SDNode. If SD is non-null that means the + /// Add a dbg_value SDNode. If SD is non-null that means the /// value is produced by SD. void AddDbgValue(SDDbgValue *DB, SDNode *SD, bool isParameter); - /// GetDbgValues - Get the debug values which reference the given SDNode. + /// Get the debug values which reference the given SDNode. ArrayRef<SDDbgValue*> GetDbgValues(const SDNode* SD) { return DbgInfo->getSDDbgValues(SD); } - /// TransferDbgValues - Transfer SDDbgValues. + /// Transfer SDDbgValues. void TransferDbgValues(SDValue From, SDValue To); - /// hasDebugValues - Return true if there are any SDDbgValue nodes associated + /// Return true if there are any SDDbgValue nodes associated /// with this SelectionDAG. bool hasDebugValues() const { return !DbgInfo->empty(); } @@ -1126,28 +1104,27 @@ public: void dump() const; - /// CreateStackTemporary - Create a stack temporary, suitable for holding the + /// Create a stack temporary, suitable for holding the /// specified value type. If minAlign is specified, the slot size will have /// at least that alignment. SDValue CreateStackTemporary(EVT VT, unsigned minAlign = 1); - /// CreateStackTemporary - Create a stack temporary suitable for holding + /// Create a stack temporary suitable for holding /// either of the specified value types. SDValue CreateStackTemporary(EVT VT1, EVT VT2); - /// FoldConstantArithmetic - SDValue FoldConstantArithmetic(unsigned Opcode, EVT VT, SDNode *Cst1, SDNode *Cst2); - /// FoldSetCC - Constant fold a setcc to true or false. + /// Constant fold a setcc to true or false. SDValue FoldSetCC(EVT VT, SDValue N1, SDValue N2, ISD::CondCode Cond, SDLoc dl); - /// SignBitIsZero - Return true if the sign bit of Op is known to be zero. We - /// use this predicate to simplify operations downstream. + /// Return true if the sign bit of Op is known to be zero. + /// We use this predicate to simplify operations downstream. bool SignBitIsZero(SDValue Op, unsigned Depth = 0) const; - /// MaskedValueIsZero - Return true if 'Op & Mask' is known to be zero. We + /// Return true if 'Op & Mask' is known to be zero. We /// use this predicate to simplify operations downstream. Op and Mask are /// known to be the same type. bool MaskedValueIsZero(SDValue Op, const APInt &Mask, unsigned Depth = 0) @@ -1160,7 +1137,7 @@ public: void computeKnownBits(SDValue Op, APInt &KnownZero, APInt &KnownOne, unsigned Depth = 0) const; - /// ComputeNumSignBits - Return the number of times the sign bit of the + /// Return the number of times the sign bit of the /// register is replicated into the other bits. We know that at least 1 bit /// is always equal to the sign bit (itself), but other cases can give us /// information. For example, immediately after an "SRA X, 2", we know that @@ -1169,26 +1146,26 @@ public: /// class to allow target nodes to be understood. unsigned ComputeNumSignBits(SDValue Op, unsigned Depth = 0) const; - /// isBaseWithConstantOffset - Return true if the specified operand is an + /// Return true if the specified operand is an /// ISD::ADD with a ConstantSDNode on the right-hand side, or if it is an /// ISD::OR with a ConstantSDNode that is guaranteed to have the same /// semantics as an ADD. This handles the equivalence: /// X|Cst == X+Cst iff X&Cst = 0. bool isBaseWithConstantOffset(SDValue Op) const; - /// isKnownNeverNan - Test whether the given SDValue is known to never be NaN. + /// Test whether the given SDValue is known to never be NaN. bool isKnownNeverNaN(SDValue Op) const; - /// isKnownNeverZero - Test whether the given SDValue is known to never be + /// Test whether the given SDValue is known to never be /// positive or negative Zero. bool isKnownNeverZero(SDValue Op) const; - /// isEqualTo - Test whether two SDValues are known to compare equal. This + /// Test whether two SDValues are known to compare equal. This /// is true if they are the same value, or if one is negative zero and the /// other positive zero. bool isEqualTo(SDValue A, SDValue B) const; - /// UnrollVectorOp - Utility function used by legalize and lowering to + /// Utility function used by legalize and lowering to /// "unroll" a vector operation by splitting out the scalars and operating /// on each element individually. If the ResNE is 0, fully unroll the vector /// op. If ResNE is less than the width of the vector op, unroll up to ResNE. @@ -1196,43 +1173,40 @@ public: /// vector op and fill the end of the resulting vector with UNDEFS. SDValue UnrollVectorOp(SDNode *N, unsigned ResNE = 0); - /// isConsecutiveLoad - Return true if LD is loading 'Bytes' bytes from a - /// location that is 'Dist' units away from the location that the 'Base' load - /// is loading from. + /// Return true if LD is loading 'Bytes' bytes from a location that is 'Dist' + /// units away from the location that the 'Base' load is loading from. bool isConsecutiveLoad(LoadSDNode *LD, LoadSDNode *Base, unsigned Bytes, int Dist) const; - /// InferPtrAlignment - Infer alignment of a load / store address. Return 0 if + /// Infer alignment of a load / store address. Return 0 if /// it cannot be inferred. unsigned InferPtrAlignment(SDValue Ptr) const; - /// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a type + /// Compute the VTs needed for the low/hi parts of a type /// which is split (or expanded) into two not necessarily identical pieces. std::pair<EVT, EVT> GetSplitDestVTs(const EVT &VT) const; - /// SplitVector - Split the vector with EXTRACT_SUBVECTOR using the provides + /// Split the vector with EXTRACT_SUBVECTOR using the provides /// VTs and return the low/high part. std::pair<SDValue, SDValue> SplitVector(const SDValue &N, const SDLoc &DL, const EVT &LoVT, const EVT &HiVT); - /// SplitVector - Split the vector with EXTRACT_SUBVECTOR and return the - /// low/high part. + /// Split the vector with EXTRACT_SUBVECTOR and return the low/high part. std::pair<SDValue, SDValue> SplitVector(const SDValue &N, const SDLoc &DL) { EVT LoVT, HiVT; std::tie(LoVT, HiVT) = GetSplitDestVTs(N.getValueType()); return SplitVector(N, DL, LoVT, HiVT); } - /// SplitVectorOperand - Split the node's operand with EXTRACT_SUBVECTOR and + /// Split the node's operand with EXTRACT_SUBVECTOR and /// return the low/high part. std::pair<SDValue, SDValue> SplitVectorOperand(const SDNode *N, unsigned OpNo) { return SplitVector(N->getOperand(OpNo), SDLoc(N)); } - /// ExtractVectorElements - Append the extracted elements from Start to Count - /// out of the vector Op in Args. If Count is 0, all of the elements will be - /// extracted. + /// Append the extracted elements from Start to Count out of the vector Op + /// in Args. If Count is 0, all of the elements will be extracted. void ExtractVectorElements(SDValue Op, SmallVectorImpl<SDValue> &Args, unsigned Start = 0, unsigned Count = 0); @@ -1258,10 +1232,10 @@ private: SDValue N1, SDValue N2, bool nuw, bool nsw, bool exact); - /// VTList - List of non-single value types. + /// List of non-single value types. FoldingSet<SDVTListNode> VTListMap; - /// CondCodeNodes - Maps to auto-CSE operations. + /// Maps to auto-CSE operations. std::vector<CondCodeSDNode*> CondCodeNodes; std::vector<SDNode*> ValueTypeNodes; diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index 7acdfc7..a874375 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -58,7 +58,7 @@ public: explicit SelectionDAGISel(TargetMachine &tm, CodeGenOpt::Level OL = CodeGenOpt::Default); - virtual ~SelectionDAGISel(); + ~SelectionDAGISel() override; const TargetLowering *getTargetLowering() const { return TLI; } diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 2b3e08c..66f060c 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -50,23 +50,6 @@ template <typename T> struct DenseMapInfo; template <typename T> struct simplify_type; template <typename T> struct ilist_traits; -/// Returns true if the opcode is a binary operation with flags. -static bool isBinOpWithFlags(unsigned Opcode) { - switch (Opcode) { - case ISD::SDIV: - case ISD::UDIV: - case ISD::SRA: - case ISD::SRL: - case ISD::MUL: - case ISD::ADD: - case ISD::SUB: - case ISD::SHL: - return true; - default: - return false; - } -} - void checkForCycles(const SDNode *N, const SelectionDAG *DAG = nullptr, bool force = false); @@ -967,6 +950,23 @@ public: } }; +/// Returns true if the opcode is a binary operation with flags. +static bool isBinOpWithFlags(unsigned Opcode) { + switch (Opcode) { + case ISD::SDIV: + case ISD::UDIV: + case ISD::SRA: + case ISD::SRL: + case ISD::MUL: + case ISD::ADD: + case ISD::SUB: + case ISD::SHL: + return true; + default: + return false; + } +} + /// This class is an extension of BinarySDNode /// used from those opcodes that have associated extra flags. class BinaryWithFlagsSDNode : public BinarySDNode { diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 75920a3..a868cbd 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -34,11 +34,12 @@ namespace llvm { class TargetLoweringObjectFileELF : public TargetLoweringObjectFile { bool UseInitArray; + mutable unsigned NextUniqueID = 0; public: TargetLoweringObjectFileELF() : UseInitArray(false) {} - virtual ~TargetLoweringObjectFileELF() {} + ~TargetLoweringObjectFileELF() override {} void emitPersonalityValue(MCStreamer &Streamer, const TargetMachine &TM, const MCSymbol *Sym) const override; @@ -87,7 +88,7 @@ public: class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile { public: - virtual ~TargetLoweringObjectFileMachO() {} + ~TargetLoweringObjectFileMachO() override {} TargetLoweringObjectFileMachO(); /// Extract the dependent library name from a linker option string. Returns @@ -135,7 +136,7 @@ public: class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile { public: - virtual ~TargetLoweringObjectFileCOFF() {} + ~TargetLoweringObjectFileCOFF() override {} const MCSection * getExplicitSectionGlobal(const GlobalValue *GV, diff --git a/include/llvm/CodeGen/WinEHFuncInfo.h b/include/llvm/CodeGen/WinEHFuncInfo.h new file mode 100644 index 0000000..5fc2b12 --- /dev/null +++ b/include/llvm/CodeGen/WinEHFuncInfo.h @@ -0,0 +1,153 @@ +//===-- llvm/CodeGen/WinEHFuncInfo.h ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Data structures and associated state for Windows exception handling schemes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_WINEHFUNCINFO_H +#define LLVM_CODEGEN_WINEHFUNCINFO_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/TinyPtrVector.h" +#include "llvm/ADT/DenseMap.h" + +namespace llvm { +class BasicBlock; +class Constant; +class Function; +class GlobalValue; +class IntrinsicInst; +class LandingPadInst; +class MCSymbol; +class Value; + +enum ActionType { Catch, Cleanup }; + +class ActionHandler { +public: + ActionHandler(BasicBlock *BB, ActionType Type) + : StartBB(BB), Type(Type), EHState(-1), HandlerBlockOrFunc(nullptr) {} + + ActionType getType() const { return Type; } + BasicBlock *getStartBlock() const { return StartBB; } + + bool hasBeenProcessed() { return HandlerBlockOrFunc != nullptr; } + + void setHandlerBlockOrFunc(Constant *F) { HandlerBlockOrFunc = F; } + Constant *getHandlerBlockOrFunc() { return HandlerBlockOrFunc; } + + void setEHState(int State) { EHState = State; } + int getEHState() const { return EHState; } + +private: + BasicBlock *StartBB; + ActionType Type; + int EHState; + + // Can be either a BlockAddress or a Function depending on the EH personality. + Constant *HandlerBlockOrFunc; +}; + +class CatchHandler : public ActionHandler { +public: + CatchHandler(BasicBlock *BB, Constant *Selector, BasicBlock *NextBB) + : ActionHandler(BB, ActionType::Catch), Selector(Selector), + NextBB(NextBB), ExceptionObjectVar(nullptr), + ExceptionObjectIndex(-1) {} + + // Method for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ActionHandler *H) { + return H->getType() == ActionType::Catch; + } + + Constant *getSelector() const { return Selector; } + BasicBlock *getNextBB() const { return NextBB; } + + const Value *getExceptionVar() { return ExceptionObjectVar; } + TinyPtrVector<BasicBlock *> &getReturnTargets() { return ReturnTargets; } + + void setExceptionVar(const Value *Val) { ExceptionObjectVar = Val; } + void setExceptionVarIndex(int Index) { ExceptionObjectIndex = Index; } + int getExceptionVarIndex() const { return ExceptionObjectIndex; } + void setReturnTargets(TinyPtrVector<BasicBlock *> &Targets) { + ReturnTargets = Targets; + } + +private: + Constant *Selector; + BasicBlock *NextBB; + // While catch handlers are being outlined the ExceptionObjectVar field will + // be populated with the instruction in the parent frame that corresponds + // to the exception object (or nullptr if the catch does not use an + // exception object) and the ExceptionObjectIndex field will be -1. + // When the parseEHActions function is called to populate a vector of + // instances of this class, the ExceptionObjectVar field will be nullptr + // and the ExceptionObjectIndex will be the index of the exception object in + // the parent function's frameescape block. + const Value *ExceptionObjectVar; + int ExceptionObjectIndex; + TinyPtrVector<BasicBlock *> ReturnTargets; +}; + +class CleanupHandler : public ActionHandler { +public: + CleanupHandler(BasicBlock *BB) : ActionHandler(BB, ActionType::Cleanup) {} + + // Method for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ActionHandler *H) { + return H->getType() == ActionType::Cleanup; + } +}; + +void parseEHActions(const IntrinsicInst *II, + SmallVectorImpl<ActionHandler *> &Actions); + + +// The following structs respresent the .xdata for functions using C++ +// exceptions on Windows. + +struct WinEHUnwindMapEntry { + int ToState; + Function *Cleanup; +}; + +struct WinEHHandlerType { + int Adjectives; + GlobalVariable *TypeDescriptor; + int CatchObjRecoverIdx; + Function *Handler; +}; + +struct WinEHTryBlockMapEntry { + int TryLow; + int TryHigh; + SmallVector<WinEHHandlerType, 1> HandlerArray; +}; + +struct WinEHFuncInfo { + DenseMap<const LandingPadInst *, int> LandingPadStateMap; + DenseMap<const Function *, int> CatchHandlerParentFrameObjIdx; + DenseMap<const Function *, int> CatchHandlerParentFrameObjOffset; + DenseMap<const Function *, int> CatchHandlerMaxState; + SmallVector<WinEHUnwindMapEntry, 4> UnwindMap; + SmallVector<WinEHTryBlockMapEntry, 4> TryBlockMap; + SmallVector<std::pair<MCSymbol *, int>, 4> IPToStateList; + int UnwindHelpFrameIdx; + int UnwindHelpFrameOffset; + + unsigned NumIPToStateFuncsVisited; + + WinEHFuncInfo() + : UnwindHelpFrameIdx(INT_MAX), UnwindHelpFrameOffset(-1), + NumIPToStateFuncsVisited(0) {} +}; + +} +#endif // LLVM_CODEGEN_WINEHFUNCINFO_H diff --git a/include/llvm/DebugInfo/DWARF/DWARFUnit.h b/include/llvm/DebugInfo/DWARF/DWARFUnit.h index 29fa4a3..2b377a9 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFUnit.h +++ b/include/llvm/DebugInfo/DWARF/DWARFUnit.h @@ -46,7 +46,7 @@ protected: const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, bool isLittleEndian) = 0; - ~DWARFUnitSectionBase() {} + ~DWARFUnitSectionBase() = default; }; /// Concrete instance of DWARFUnitSection, specialized for one Unit type. diff --git a/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h b/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h index 96ce12f..b5fa8c3 100644 --- a/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h +++ b/include/llvm/DebugInfo/PDB/ConcreteSymbolEnumerator.h @@ -22,7 +22,7 @@ public: ConcreteSymbolEnumerator(std::unique_ptr<IPDBEnumSymbols> SymbolEnumerator) : Enumerator(std::move(SymbolEnumerator)) {} - virtual ~ConcreteSymbolEnumerator() {} + ~ConcreteSymbolEnumerator() override {} uint32_t getChildCount() const override { return Enumerator->getChildCount(); diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h index abdaa0c..4b2add8 100644 --- a/include/llvm/ExecutionEngine/ExecutionEngine.h +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -15,6 +15,7 @@ #ifndef LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H #define LLVM_EXECUTIONENGINE_EXECUTIONENGINE_H +#include "RuntimeDyld.h" #include "llvm-c/ExecutionEngine.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -42,6 +43,7 @@ class GlobalVariable; class GlobalValue; class JITEventListener; class MachineCodeInfo; +class MCJITMemoryManager; class MutexGuard; class ObjectCache; class RTDyldMemoryManager; @@ -57,46 +59,34 @@ namespace object { /// table. Access to this class should be serialized under a mutex. class ExecutionEngineState { public: - struct AddressMapConfig : public ValueMapConfig<const GlobalValue*> { - typedef ExecutionEngineState *ExtraData; - static sys::Mutex *getMutex(ExecutionEngineState *EES); - static void onDelete(ExecutionEngineState *EES, const GlobalValue *Old); - static void onRAUW(ExecutionEngineState *, const GlobalValue *, - const GlobalValue *); - }; - - typedef ValueMap<const GlobalValue *, void *, AddressMapConfig> - GlobalAddressMapTy; + typedef StringMap<uint64_t> GlobalAddressMapTy; private: - ExecutionEngine &EE; - /// GlobalAddressMap - A mapping between LLVM global values and their - /// actualized version... + /// GlobalAddressMap - A mapping between LLVM global symbol names values and + /// their actualized version... GlobalAddressMapTy GlobalAddressMap; /// GlobalAddressReverseMap - This is the reverse mapping of GlobalAddressMap, /// used to convert raw addresses into the LLVM global value that is emitted /// at the address. This map is not computed unless getGlobalValueAtAddress /// is called at some point. - std::map<void *, AssertingVH<const GlobalValue> > GlobalAddressReverseMap; + std::map<uint64_t, std::string> GlobalAddressReverseMap; public: - ExecutionEngineState(ExecutionEngine &EE); GlobalAddressMapTy &getGlobalAddressMap() { return GlobalAddressMap; } - std::map<void*, AssertingVH<const GlobalValue> > & - getGlobalAddressReverseMap() { + std::map<uint64_t, std::string> &getGlobalAddressReverseMap() { return GlobalAddressReverseMap; } /// \brief Erase an entry from the mapping table. /// /// \returns The address that \p ToUnmap was happed to. - void *RemoveMapping(const GlobalValue *ToUnmap); + uint64_t RemoveMapping(StringRef Name); }; /// \brief Abstract interface for implementation execution of LLVM modules, @@ -139,15 +129,17 @@ protected: virtual char *getMemoryForGV(const GlobalVariable *GV); static ExecutionEngine *(*MCJITCtor)( - std::unique_ptr<Module> M, - std::string *ErrorStr, - std::unique_ptr<RTDyldMemoryManager> MCJMM, - std::unique_ptr<TargetMachine> TM); + std::unique_ptr<Module> M, + std::string *ErrorStr, + std::shared_ptr<MCJITMemoryManager> MM, + std::shared_ptr<RuntimeDyld::SymbolResolver> SR, + std::unique_ptr<TargetMachine> TM); static ExecutionEngine *(*OrcMCJITReplacementCtor)( - std::string *ErrorStr, - std::unique_ptr<RTDyldMemoryManager> OrcJMM, - std::unique_ptr<TargetMachine> TM); + std::string *ErrorStr, + std::shared_ptr<MCJITMemoryManager> MM, + std::shared_ptr<RuntimeDyld::SymbolResolver> SR, + std::unique_ptr<TargetMachine> TM); static ExecutionEngine *(*InterpCtor)(std::unique_ptr<Module> M, std::string *ErrorStr); @@ -157,6 +149,9 @@ protected: /// abort. void *(*LazyFunctionCreator)(const std::string &); + /// getMangledName - Get mangled name. + std::string getMangledName(const GlobalValue *GV); + public: /// lock - This lock protects the ExecutionEngine and MCJIT classes. It must /// be held while changing the internal state of any of those classes. @@ -228,7 +223,8 @@ public: /// Map the address of a JIT section as returned from the memory manager /// to the address in the target process as the running code will see it. /// This is the address which will be used for relocation resolution. - virtual void mapSectionAddress(const void *LocalAddress, uint64_t TargetAddress) { + virtual void mapSectionAddress(const void *LocalAddress, + uint64_t TargetAddress) { llvm_unreachable("Re-mapping of section addresses not supported with this " "EE!"); } @@ -286,6 +282,7 @@ public: /// existing data in memory. Mappings are automatically removed when their /// GlobalValue is destroyed. void addGlobalMapping(const GlobalValue *GV, void *Addr); + void addGlobalMapping(StringRef Name, uint64_t Addr); /// clearAllGlobalMappings - Clear all global mappings and start over again, /// for use in dynamic compilation scenarios to move globals. @@ -299,14 +296,17 @@ public: /// address. This updates both maps as required. If "Addr" is null, the /// entry for the global is removed from the mappings. This returns the old /// value of the pointer, or null if it was not in the map. - void *updateGlobalMapping(const GlobalValue *GV, void *Addr); + uint64_t updateGlobalMapping(const GlobalValue *GV, void *Addr); + uint64_t updateGlobalMapping(StringRef Name, uint64_t Addr); + + /// getAddressToGlobalIfAvailable - This returns the address of the specified + /// global symbol. + uint64_t getAddressToGlobalIfAvailable(StringRef S); /// getPointerToGlobalIfAvailable - This returns the address of the specified /// global value if it is has already been codegen'd, otherwise it returns /// null. - /// - /// This function is deprecated for the MCJIT execution engine. It doesn't - /// seem to be needed in that case, but an equivalent can be added if it is. + void *getPointerToGlobalIfAvailable(StringRef S); void *getPointerToGlobalIfAvailable(const GlobalValue *GV); /// getPointerToGlobal - This returns the address of the specified global @@ -470,7 +470,7 @@ public: } protected: - ExecutionEngine() : EEState(*this) {} + ExecutionEngine() {} explicit ExecutionEngine(std::unique_ptr<Module> M); void emitGlobals(); @@ -500,7 +500,8 @@ private: EngineKind::Kind WhichEngine; std::string *ErrorStr; CodeGenOpt::Level OptLevel; - std::unique_ptr<RTDyldMemoryManager> MCJMM; + std::shared_ptr<MCJITMemoryManager> MemMgr; + std::shared_ptr<RuntimeDyld::SymbolResolver> Resolver; TargetOptions Options; Reloc::Model RelocModel; CodeModel::Model CMModel; @@ -535,6 +536,12 @@ public: /// memory manager. This option defaults to NULL. EngineBuilder &setMCJITMemoryManager(std::unique_ptr<RTDyldMemoryManager> mcjmm); + EngineBuilder& + setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM); + + EngineBuilder& + setSymbolResolver(std::unique_ptr<RuntimeDyld::SymbolResolver> SR); + /// setErrorStr - Set the error string to write to on error. This option /// defaults to NULL. EngineBuilder &setErrorStr(std::string *e) { diff --git a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h index 77b0c48..30f7f1c 100644 --- a/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h +++ b/include/llvm/ExecutionEngine/Orc/CompileOnDemandLayer.h @@ -16,7 +16,7 @@ #define LLVM_EXECUTIONENGINE_ORC_COMPILEONDEMANDLAYER_H #include "IndirectionUtils.h" -#include "LookasideRTDyldMM.h" +#include "LambdaResolver.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include <list> @@ -36,7 +36,7 @@ namespace orc { /// compiled only when it is first called. template <typename BaseLayerT, typename CompileCallbackMgrT> class CompileOnDemandLayer { -public: +private: /// @brief Lookup helper that provides compatibility with the classic /// static-compilation symbol resolution process. /// @@ -64,6 +64,8 @@ public: /// @brief Construct a scoped lookup. CODScopedLookup(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {} + virtual ~CODScopedLookup() {} + /// @brief Start a new context for a single logical module. LMHandle createLogicalModule() { Handles.push_back(SiblingHandlesList()); @@ -92,6 +94,10 @@ public: return nullptr; } + /// @brief Find an external symbol (via the user supplied SymbolResolver). + virtual RuntimeDyld::SymbolInfo + externalLookup(const std::string &Name) const = 0; + private: JITSymbol findSymbolIn(LMHandle LMH, const std::string &Name) { @@ -105,7 +111,29 @@ public: PseudoDylibModuleSetHandlesList Handles; }; -private: + template <typename ResolverPtrT> + class CODScopedLookupImpl : public CODScopedLookup { + public: + CODScopedLookupImpl(BaseLayerT &BaseLayer, ResolverPtrT Resolver) + : CODScopedLookup(BaseLayer), Resolver(std::move(Resolver)) {} + + RuntimeDyld::SymbolInfo + externalLookup(const std::string &Name) const override { + return Resolver->findSymbol(Name); + } + + private: + ResolverPtrT Resolver; + }; + + template <typename ResolverPtrT> + static std::shared_ptr<CODScopedLookup> + createCODScopedLookup(BaseLayerT &BaseLayer, + ResolverPtrT Resolver) { + typedef CODScopedLookupImpl<ResolverPtrT> Impl; + return std::make_shared<Impl>(BaseLayer, std::move(Resolver)); + } + typedef typename BaseLayerT::ModuleSetHandleT BaseLayerModuleSetHandleT; typedef std::vector<BaseLayerModuleSetHandleT> BaseLayerModuleSetHandleListT; @@ -138,36 +166,31 @@ public: /// @brief Handle to a set of loaded modules. typedef typename ModuleSetInfoListT::iterator ModuleSetHandleT; - // @brief Fallback lookup functor. - typedef std::function<uint64_t(const std::string &)> LookupFtor; - /// @brief Construct a compile-on-demand layer instance. CompileOnDemandLayer(BaseLayerT &BaseLayer, CompileCallbackMgrT &CallbackMgr) : BaseLayer(BaseLayer), CompileCallbackMgr(CallbackMgr) {} /// @brief Add a module to the compile-on-demand layer. - template <typename ModuleSetT> + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> ModuleSetHandleT addModuleSet(ModuleSetT Ms, - LookupFtor FallbackLookup = nullptr) { + MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { - // If the user didn't supply a fallback lookup then just use - // getSymbolAddress. - if (!FallbackLookup) - FallbackLookup = [=](const std::string &Name) { - return findSymbol(Name, true).getAddress(); - }; + assert(MemMgr == nullptr && + "User supplied memory managers not supported with COD yet."); // Create a lookup context and ModuleSetInfo for this module set. // For the purposes of symbol resolution the set Ms will be treated as if // the modules it contained had been linked together as a dylib. - auto DylibLookup = std::make_shared<CODScopedLookup>(BaseLayer); + auto DylibLookup = createCODScopedLookup(BaseLayer, std::move(Resolver)); ModuleSetHandleT H = ModuleSetInfos.insert(ModuleSetInfos.end(), ModuleSetInfo(DylibLookup)); ModuleSetInfo &MSI = ModuleSetInfos.back(); // Process each of the modules in this module set. for (auto &M : Ms) - partitionAndAdd(*M, MSI, FallbackLookup); + partitionAndAdd(*M, MSI); return H; } @@ -203,8 +226,7 @@ public: private: - void partitionAndAdd(Module &M, ModuleSetInfo &MSI, - LookupFtor FallbackLookup) { + void partitionAndAdd(Module &M, ModuleSetInfo &MSI) { const char *AddrSuffix = "$orc_addr"; const char *BodySuffix = "$orc_body"; @@ -224,8 +246,7 @@ private: auto FunctionModules = std::move(PartitionedModule.Functions); // Emit the commons stright away. - auto CommonHandle = addModule(std::move(CommonsModule), MSI, LogicalModule, - FallbackLookup); + auto CommonHandle = addModule(std::move(CommonsModule), MSI, LogicalModule); BaseLayer.emitAndFinalize(CommonHandle); // Map of definition names to callback-info data structures. We'll use @@ -255,10 +276,12 @@ private: Function *Proto = StubsModule->getFunction(Name); assert(Proto && "Failed to clone function decl into stubs module."); auto CallbackInfo = - CompileCallbackMgr.getCompileCallback(*Proto->getFunctionType()); + CompileCallbackMgr.getCompileCallback(Proto->getContext()); GlobalVariable *FunctionBodyPointer = - createImplPointer(*Proto, Name + AddrSuffix, - CallbackInfo.getAddress()); + createImplPointer(*Proto->getType(), *Proto->getParent(), + Name + AddrSuffix, + createIRTypedAddress(*Proto->getFunctionType(), + CallbackInfo.getAddress())); makeStub(*Proto, *FunctionBodyPointer); F.setName(Name + BodySuffix); @@ -268,7 +291,7 @@ private: NewStubInfos.push_back(StubInfos.insert(StubInfos.begin(), KV)); } - auto H = addModule(std::move(SubM), MSI, LogicalModule, FallbackLookup); + auto H = addModule(std::move(SubM), MSI, LogicalModule); // Set the compile actions for this module: for (auto &KVPair : NewStubInfos) { @@ -286,7 +309,7 @@ private: // Ok - we've processed all the partitioned modules. Now add the // stubs/globals module and set the update actions. auto StubsH = - addModule(std::move(StubsModule), MSI, LogicalModule, FallbackLookup); + addModule(std::move(StubsModule), MSI, LogicalModule); for (auto &KVPair : StubInfos) { std::string AddrName = Mangle(KVPair.first + AddrSuffix, @@ -304,8 +327,7 @@ private: BaseLayerModuleSetHandleT addModule( std::unique_ptr<Module> M, ModuleSetInfo &MSI, - typename CODScopedLookup::LMHandle LogicalModule, - LookupFtor FallbackLookup) { + typename CODScopedLookup::LMHandle LogicalModule) { // Add this module to the JIT with a memory manager that uses the // DylibLookup to resolve symbols. @@ -313,19 +335,25 @@ private: MSet.push_back(std::move(M)); auto DylibLookup = MSI.Lookup; - auto MM = - createLookasideRTDyldMM<SectionMemoryManager>( + auto Resolver = + createLambdaResolver( [=](const std::string &Name) { if (auto Symbol = DylibLookup->findSymbol(LogicalModule, Name)) - return Symbol.getAddress(); - return FallbackLookup(Name); + return RuntimeDyld::SymbolInfo(Symbol.getAddress(), + Symbol.getFlags()); + return DylibLookup->externalLookup(Name); }, - [=](const std::string &Name) { - return DylibLookup->findSymbol(LogicalModule, Name).getAddress(); + [=](const std::string &Name) -> RuntimeDyld::SymbolInfo { + if (auto Symbol = DylibLookup->findSymbol(LogicalModule, Name)) + return RuntimeDyld::SymbolInfo(Symbol.getAddress(), + Symbol.getFlags()); + return nullptr; }); BaseLayerModuleSetHandleT H = - BaseLayer.addModuleSet(std::move(MSet), std::move(MM)); + BaseLayer.addModuleSet(std::move(MSet), + make_unique<SectionMemoryManager>(), + std::move(Resolver)); // Add this module to the logical module lookup. DylibLookup->addToLogicalModule(LogicalModule, H); MSI.BaseLayerModuleSetHandles.push_back(H); diff --git a/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h b/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h new file mode 100644 index 0000000..c10508c --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/ExecutionUtils.h @@ -0,0 +1,182 @@ +//===-- ExecutionUtils.h - Utilities for executing code in Orc --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Contains utilities for executing code in Orc. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H +#define LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H + +#include "JITSymbol.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include <vector> + +namespace llvm { + +class ConstantArray; +class GlobalVariable; +class Function; +class Module; +class Value; + +namespace orc { + +/// @brief This iterator provides a convenient way to iterate over the elements +/// of an llvm.global_ctors/llvm.global_dtors instance. +/// +/// The easiest way to get hold of instances of this class is to use the +/// getConstructors/getDestructors functions. +class CtorDtorIterator { +public: + + /// @brief Accessor for an element of the global_ctors/global_dtors array. + /// + /// This class provides a read-only view of the element with any casts on + /// the function stripped away. + struct Element { + Element(unsigned Priority, const Function *Func, const Value *Data) + : Priority(Priority), Func(Func), Data(Data) {} + + unsigned Priority; + const Function *Func; + const Value *Data; + }; + + /// @brief Construct an iterator instance. If End is true then this iterator + /// acts as the end of the range, otherwise it is the beginning. + CtorDtorIterator(const GlobalVariable *GV, bool End); + + /// @brief Test iterators for equality. + bool operator==(const CtorDtorIterator &Other) const; + + /// @brief Test iterators for inequality. + bool operator!=(const CtorDtorIterator &Other) const; + + /// @brief Pre-increment iterator. + CtorDtorIterator& operator++(); + + /// @brief Post-increment iterator. + CtorDtorIterator operator++(int); + + /// @brief Dereference iterator. The resulting value provides a read-only view + /// of this element of the global_ctors/global_dtors list. + Element operator*() const; + +private: + const ConstantArray *InitList; + unsigned I; +}; + +/// @brief Create an iterator range over the entries of the llvm.global_ctors +/// array. +iterator_range<CtorDtorIterator> getConstructors(const Module &M); + +/// @brief Create an iterator range over the entries of the llvm.global_ctors +/// array. +iterator_range<CtorDtorIterator> getDestructors(const Module &M); + +/// @brief Convenience class for recording constructor/destructor names for +/// later execution. +template <typename JITLayerT> +class CtorDtorRunner { +public: + + /// @brief Construct a CtorDtorRunner for the given range using the given + /// name mangling function. + CtorDtorRunner(std::vector<std::string> CtorDtorNames, + typename JITLayerT::ModuleSetHandleT H) + : CtorDtorNames(std::move(CtorDtorNames)), H(H) {} + + /// @brief Run the recorded constructors/destructors through the given JIT + /// layer. + bool runViaLayer(JITLayerT &JITLayer) const { + typedef void (*CtorDtorTy)(); + + bool Error = false; + for (const auto &CtorDtorName : CtorDtorNames) + if (auto CtorDtorSym = JITLayer.findSymbolIn(H, CtorDtorName, false)) { + CtorDtorTy CtorDtor = + reinterpret_cast<CtorDtorTy>( + static_cast<uintptr_t>(CtorDtorSym.getAddress())); + CtorDtor(); + } else + Error = true; + return !Error; + } + +private: + std::vector<std::string> CtorDtorNames; + typename JITLayerT::ModuleSetHandleT H; +}; + +/// @brief Support class for static dtor execution. For hosted (in-process) JITs +/// only! +/// +/// If a __cxa_atexit function isn't found C++ programs that use static +/// destructors will fail to link. However, we don't want to use the host +/// process's __cxa_atexit, because it will schedule JIT'd destructors to run +/// after the JIT has been torn down, which is no good. This class makes it easy +/// to override __cxa_atexit (and the related __dso_handle). +/// +/// To use, clients should manually call searchOverrides from their symbol +/// resolver. This should generally be done after attempting symbol resolution +/// inside the JIT, but before searching the host process's symbol table. When +/// the client determines that destructors should be run (generally at JIT +/// teardown or after a return from main), the runDestructors method should be +/// called. +class LocalCXXRuntimeOverrides { +public: + + /// Create a runtime-overrides class. + template <typename MangleFtorT> + LocalCXXRuntimeOverrides(const MangleFtorT &Mangle) { + addOverride(Mangle("__dso_handle"), toTargetAddress(&DSOHandleOverride)); + addOverride(Mangle("__cxa_atexit"), toTargetAddress(&CXAAtExitOverride)); + } + + /// Search overrided symbols. + RuntimeDyld::SymbolInfo searchOverrides(const std::string &Name) { + auto I = CXXRuntimeOverrides.find(Name); + if (I != CXXRuntimeOverrides.end()) + return RuntimeDyld::SymbolInfo(I->second, JITSymbolFlags::Exported); + return nullptr; + } + + /// Run any destructors recorded by the overriden __cxa_atexit function + /// (CXAAtExitOverride). + void runDestructors(); + +private: + + template <typename PtrTy> + TargetAddress toTargetAddress(PtrTy* P) { + return static_cast<TargetAddress>(reinterpret_cast<uintptr_t>(P)); + } + + void addOverride(const std::string &Name, TargetAddress Addr) { + CXXRuntimeOverrides.insert(std::make_pair(Name, Addr)); + } + + StringMap<TargetAddress> CXXRuntimeOverrides; + + typedef void (*DestructorPtr)(void*); + typedef std::pair<DestructorPtr, void*> CXXDestructorDataPair; + typedef std::vector<CXXDestructorDataPair> CXXDestructorDataPairList; + CXXDestructorDataPairList DSOHandleOverride; + static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg, + void *DSOHandle); +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H diff --git a/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h index 6a47622..6379022 100644 --- a/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h +++ b/include/llvm/ExecutionEngine/Orc/IRCompileLayer.h @@ -52,14 +52,16 @@ public: /// @brief Set an ObjectCache to query before compiling. void setObjectCache(ObjectCache *NewCache) { ObjCache = NewCache; } - /// @brief Compile each module in the given module set, then then add the - /// resulting set of objects to the base layer, along with the memory - // manager MM. + /// @brief Compile each module in the given module set, then add the resulting + /// set of objects to the base layer along with the memory manager and + /// symbol resolver. /// /// @return A handle for the added modules. - template <typename ModuleSetT> + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> ModuleSetHandleT addModuleSet(ModuleSetT Ms, - std::unique_ptr<RTDyldMemoryManager> MM) { + MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { OwningObjectVec Objects; OwningBufferVec Buffers; @@ -81,7 +83,7 @@ public: } ModuleSetHandleT H = - BaseLayer.addObjectSet(Objects, std::move(MM)); + BaseLayer.addObjectSet(Objects, std::move(MemMgr), std::move(Resolver)); BaseLayer.takeOwnershipOfBuffers(H, std::move(Buffers)); diff --git a/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h b/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h new file mode 100644 index 0000000..4dabb9a --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/IRTransformLayer.h @@ -0,0 +1,101 @@ +//===----- IRTransformLayer.h - Run all IR through a functor ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Run all IR passed in through a user supplied functor. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H +#define LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H + +#include "JITSymbol.h" + +namespace llvm { +namespace orc { + +/// @brief IR mutating layer. +/// +/// This layer accepts sets of LLVM IR Modules (via addModuleSet). It +/// immediately applies the user supplied functor to each module, then adds +/// the set of transformed modules to the layer below. +template <typename BaseLayerT, typename TransformFtor> +class IRTransformLayer { +public: + /// @brief Handle to a set of added modules. + typedef typename BaseLayerT::ModuleSetHandleT ModuleSetHandleT; + + /// @brief Construct an IRTransformLayer with the given BaseLayer + IRTransformLayer(BaseLayerT &BaseLayer, + TransformFtor Transform = TransformFtor()) + : BaseLayer(BaseLayer), Transform(std::move(Transform)) {} + + /// @brief Apply the transform functor to each module in the module set, then + /// add the resulting set of modules to the base layer, along with the + /// memory manager and symbol resolver. + /// + /// @return A handle for the added modules. + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> + ModuleSetHandleT addModuleSet(ModuleSetT Ms, + MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { + + for (auto I = Ms.begin(), E = Ms.end(); I != E; ++I) + *I = Transform(std::move(*I)); + + return BaseLayer.addModuleSet(std::move(Ms), std::move(MemMgr), + std::move(Resolver)); + } + + /// @brief Remove the module set associated with the handle H. + void removeModuleSet(ModuleSetHandleT H) { BaseLayer.removeModuleSet(H); } + + /// @brief Search for the given named symbol. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it exists. + JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) { + return BaseLayer.findSymbol(Name, ExportedSymbolsOnly); + } + + /// @brief Get the address of the given symbol in the context of the set of + /// modules represented by the handle H. This call is forwarded to the + /// base layer's implementation. + /// @param H The handle for the module set to search in. + /// @param Name The name of the symbol to search for. + /// @param ExportedSymbolsOnly If true, search only for exported symbols. + /// @return A handle for the given named symbol, if it is found in the + /// given module set. + JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name, + bool ExportedSymbolsOnly) { + return BaseLayer.findSymbolIn(H, Name, ExportedSymbolsOnly); + } + + /// @brief Immediately emit and finalize the module set represented by the + /// given handle. + /// @param H Handle for module set to emit/finalize. + void emitAndFinalize(ModuleSetHandleT H) { + BaseLayer.emitAndFinalize(H); + } + + /// @brief Access the transform functor directly. + TransformFtor& getTransform() { return Transform; } + + /// @brief Access the mumate functor directly. + const TransformFtor& getTransform() const { return Transform; } + +private: + BaseLayerT &BaseLayer; + TransformFtor Transform; +}; + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_IRTRANSFORMLAYER_H diff --git a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h index 8ce1d4d..7b4f611 100644 --- a/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h +++ b/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h @@ -16,6 +16,7 @@ #include "JITSymbol.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" @@ -37,11 +38,11 @@ public: /// the compile and update actions for the callback. class CompileCallbackInfo { public: - CompileCallbackInfo(Constant *Addr, CompileFtor &Compile, + CompileCallbackInfo(TargetAddress Addr, CompileFtor &Compile, UpdateFtor &Update) : Addr(Addr), Compile(Compile), Update(Update) {} - Constant* getAddress() const { return Addr; } + TargetAddress getAddress() const { return Addr; } void setCompileAction(CompileFtor Compile) { this->Compile = std::move(Compile); } @@ -49,7 +50,7 @@ public: this->Update = std::move(Update); } private: - Constant *Addr; + TargetAddress Addr; CompileFtor &Compile; UpdateFtor &Update; }; @@ -94,7 +95,7 @@ public: } /// @brief Get/create a compile callback with the given signature. - virtual CompileCallbackInfo getCompileCallback(FunctionType &FT) = 0; + virtual CompileCallbackInfo getCompileCallback(LLVMContext &Context) = 0; protected: @@ -125,27 +126,23 @@ public: /// there is no existing callback trampoline. /// (Trampolines are allocated in blocks for /// efficiency.) - JITCompileCallbackManager(JITLayerT &JIT, LLVMContext &Context, + JITCompileCallbackManager(JITLayerT &JIT, RuntimeDyld::MemoryManager &MemMgr, + LLVMContext &Context, TargetAddress ErrorHandlerAddress, unsigned NumTrampolinesPerBlock) : JITCompileCallbackManagerBase(ErrorHandlerAddress, NumTrampolinesPerBlock), - JIT(JIT) { + JIT(JIT), MemMgr(MemMgr) { emitResolverBlock(Context); } /// @brief Get/create a compile callback with the given signature. - CompileCallbackInfo getCompileCallback(FunctionType &FT) final { - TargetAddress TrampolineAddr = getAvailableTrampolineAddr(FT.getContext()); + CompileCallbackInfo getCompileCallback(LLVMContext &Context) final { + TargetAddress TrampolineAddr = getAvailableTrampolineAddr(Context); auto &CallbackHandler = this->ActiveTrampolines[TrampolineAddr]; - Constant *AddrIntVal = - ConstantInt::get(Type::getInt64Ty(FT.getContext()), TrampolineAddr); - Constant *AddrPtrVal = - ConstantExpr::getCast(Instruction::IntToPtr, AddrIntVal, - PointerType::get(&FT, 0)); - return CompileCallbackInfo(AddrPtrVal, CallbackHandler.Compile, + return CompileCallbackInfo(TrampolineAddr, CallbackHandler.Compile, CallbackHandler.Update); } @@ -162,7 +159,9 @@ private: std::unique_ptr<Module> M(new Module("resolver_block_module", Context)); TargetT::insertResolverBlock(*M, *this); - auto H = JIT.addModuleSet(SingletonSet(std::move(M)), nullptr); + auto H = JIT.addModuleSet(SingletonSet(std::move(M)), &MemMgr, + static_cast<RuntimeDyld::SymbolResolver*>( + nullptr)); JIT.emitAndFinalize(H); auto ResolverBlockSymbol = JIT.findSymbolIn(H, TargetT::ResolverBlockName, false); @@ -187,7 +186,9 @@ private: TargetT::insertCompileCallbackTrampolines(*M, ResolverBlockAddr, this->NumTrampolinesPerBlock, this->ActiveTrampolines.size()); - auto H = JIT.addModuleSet(SingletonSet(std::move(M)), nullptr); + auto H = JIT.addModuleSet(SingletonSet(std::move(M)), &MemMgr, + static_cast<RuntimeDyld::SymbolResolver*>( + nullptr)); JIT.emitAndFinalize(H); for (unsigned I = 0; I < this->NumTrampolinesPerBlock; ++I) { std::string Name = GetLabelName(I); @@ -198,10 +199,11 @@ private: } JITLayerT &JIT; + RuntimeDyld::MemoryManager &MemMgr; TargetAddress ResolverBlockAddr; }; -/// @brief Get an update functor for updating the value of a named function +/// @brief Get an update functor that updates the value of a named function /// pointer. template <typename JITLayerT> JITCompileCallbackManagerBase::UpdateFtor @@ -217,13 +219,26 @@ getLocalFPUpdater(JITLayerT &JIT, typename JITLayerT::ModuleSetHandleT H, }; } -GlobalVariable* createImplPointer(Function &F, const Twine &Name, - Constant *Initializer); +/// @brief Build a function pointer of FunctionType with the given constant +/// address. +/// +/// Usage example: Turn a trampoline address into a function pointer constant +/// for use in a stub. +Constant* createIRTypedAddress(FunctionType &FT, TargetAddress Addr); +/// @brief Create a function pointer with the given type, name, and initializer +/// in the given Module. +GlobalVariable* createImplPointer(PointerType &PT, Module &M, + const Twine &Name, Constant *Initializer); + +/// @brief Turn a function declaration into a stub function that makes an +/// indirect call using the given function pointer. void makeStub(Function &F, GlobalVariable &ImplPointer); typedef std::map<Module*, DenseSet<const GlobalValue*>> ModulePartitionMap; +/// @brief Extract subsections of a Module into the given Module according to +/// the given ModulePartitionMap. void partition(Module &M, const ModulePartitionMap &PMap); /// @brief Struct for trivial "complete" partitioning of a module. @@ -239,6 +254,7 @@ public: Functions(std::move(S.Functions)) {} }; +/// @brief Extract every function in M into a separate module. FullyPartitionedModule fullyPartition(Module &M); } // End namespace orc. diff --git a/include/llvm/ExecutionEngine/Orc/JITSymbol.h b/include/llvm/ExecutionEngine/Orc/JITSymbol.h index 7c3ad56..422a376 100644 --- a/include/llvm/ExecutionEngine/Orc/JITSymbol.h +++ b/include/llvm/ExecutionEngine/Orc/JITSymbol.h @@ -27,7 +27,7 @@ typedef uint64_t TargetAddress; /// @brief Represents a symbol in the JIT. class JITSymbol : public JITSymbolBase { -public: +public: typedef std::function<TargetAddress()> GetAddressFtor; diff --git a/include/llvm/ExecutionEngine/Orc/LambdaResolver.h b/include/llvm/ExecutionEngine/Orc/LambdaResolver.h new file mode 100644 index 0000000..faa2365 --- /dev/null +++ b/include/llvm/ExecutionEngine/Orc/LambdaResolver.h @@ -0,0 +1,62 @@ +//===-- LambdaResolverMM - Redirect symbol lookup via a functor -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Defines a RuntimeDyld::SymbolResolver subclass that uses a user-supplied +// functor for symbol resolution. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H +#define LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include <memory> +#include <vector> + +namespace llvm { +namespace orc { + +template <typename ExternalLookupFtorT, typename DylibLookupFtorT> +class LambdaResolver : public RuntimeDyld::SymbolResolver { +public: + + LambdaResolver(ExternalLookupFtorT ExternalLookupFtor, + DylibLookupFtorT DylibLookupFtor) + : ExternalLookupFtor(ExternalLookupFtor), + DylibLookupFtor(DylibLookupFtor) {} + + RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) final { + return ExternalLookupFtor(Name); + } + + RuntimeDyld::SymbolInfo + findSymbolInLogicalDylib(const std::string &Name) final { + return DylibLookupFtor(Name); + } + +private: + ExternalLookupFtorT ExternalLookupFtor; + DylibLookupFtorT DylibLookupFtor; +}; + +template <typename ExternalLookupFtorT, + typename DylibLookupFtorT> +std::unique_ptr<LambdaResolver<ExternalLookupFtorT, DylibLookupFtorT>> +createLambdaResolver(ExternalLookupFtorT ExternalLookupFtor, + DylibLookupFtorT DylibLookupFtor) { + typedef LambdaResolver<ExternalLookupFtorT, DylibLookupFtorT> LR; + return make_unique<LR>(std::move(ExternalLookupFtor), + std::move(DylibLookupFtor)); +} + +} // End namespace orc. +} // End namespace llvm. + +#endif // LLVM_EXECUTIONENGINE_ORC_LAMBDARESOLVER_H diff --git a/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h index ac5fccf..71c83f7 100644 --- a/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h +++ b/include/llvm/ExecutionEngine/Orc/LazyEmittingLayer.h @@ -15,11 +15,11 @@ #define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H #include "JITSymbol.h" -#include "LookasideRTDyldMM.h" #include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/IR/GlobalValue.h" #include "llvm/IR/Mangler.h" #include "llvm/IR/Module.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringMap.h" #include <list> @@ -94,10 +94,11 @@ private: BaseLayer.emitAndFinalize(Handle); } - template <typename ModuleSetT> + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> static std::unique_ptr<EmissionDeferredSet> - create(BaseLayerT &B, ModuleSetT Ms, - std::unique_ptr<RTDyldMemoryManager> MM); + create(BaseLayerT &B, ModuleSetT Ms, MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver); protected: virtual const GlobalValue* searchGVs(StringRef Name, @@ -109,12 +110,15 @@ private: BaseLayerHandleT Handle; }; - template <typename ModuleSetT> + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> class EmissionDeferredSetImpl : public EmissionDeferredSet { public: EmissionDeferredSetImpl(ModuleSetT Ms, - std::unique_ptr<RTDyldMemoryManager> MM) - : Ms(std::move(Ms)), MM(std::move(MM)) {} + MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) + : Ms(std::move(Ms)), MemMgr(std::move(MemMgr)), + Resolver(std::move(Resolver)) {} protected: @@ -145,7 +149,8 @@ private: // We don't need the mangled names set any more: Once we've emitted this // to the base layer we'll just look for symbols there. MangledSymbols.reset(); - return BaseLayer.addModuleSet(std::move(Ms), std::move(MM)); + return BaseLayer.addModuleSet(std::move(Ms), std::move(MemMgr), + std::move(Resolver)); } private: @@ -206,7 +211,8 @@ private: } ModuleSetT Ms; - std::unique_ptr<RTDyldMemoryManager> MM; + MemoryManagerPtrT MemMgr; + SymbolResolverPtrT Resolver; mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols; }; @@ -223,12 +229,15 @@ public: LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {} /// @brief Add the given set of modules to the lazy emitting layer. - template <typename ModuleSetT> + template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> ModuleSetHandleT addModuleSet(ModuleSetT Ms, - std::unique_ptr<RTDyldMemoryManager> MM) { + MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { return ModuleSetList.insert( ModuleSetList.end(), - EmissionDeferredSet::create(BaseLayer, std::move(Ms), std::move(MM))); + EmissionDeferredSet::create(BaseLayer, std::move(Ms), std::move(MemMgr), + std::move(Resolver))); } /// @brief Remove the module set represented by the given handle. @@ -277,12 +286,16 @@ public: }; template <typename BaseLayerT> -template <typename ModuleSetT> +template <typename ModuleSetT, typename MemoryManagerPtrT, + typename SymbolResolverPtrT> std::unique_ptr<typename LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet> LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet::create( - BaseLayerT &B, ModuleSetT Ms, std::unique_ptr<RTDyldMemoryManager> MM) { - return llvm::make_unique<EmissionDeferredSetImpl<ModuleSetT>>(std::move(Ms), - std::move(MM)); + BaseLayerT &B, ModuleSetT Ms, MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { + typedef EmissionDeferredSetImpl<ModuleSetT, MemoryManagerPtrT, SymbolResolverPtrT> + EDS; + return llvm::make_unique<EDS>(std::move(Ms), std::move(MemMgr), + std::move(Resolver)); } } // End namespace orc. diff --git a/include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h b/include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h deleted file mode 100644 index 4456404..0000000 --- a/include/llvm/ExecutionEngine/Orc/LookasideRTDyldMM.h +++ /dev/null @@ -1,92 +0,0 @@ -//===- LookasideRTDyldMM - Redirect symbol lookup via a functor -*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Defines an adapter for RuntimeDyldMM that allows lookups for external -// symbols to go via a functor. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_EXECUTIONENGINE_ORC_LOOKASIDERTDYLDMM_H -#define LLVM_EXECUTIONENGINE_ORC_LOOKASIDERTDYLDMM_H - -#include "llvm/ADT/STLExtras.h" -#include <memory> -#include <vector> - -namespace llvm { -namespace orc { - -/// @brief Defines an adapter for RuntimeDyldMM that allows lookups for external -/// symbols to go via a functor, before falling back to the lookup logic -/// provided by the underlying RuntimeDyldMM instance. -/// -/// This class is useful for redirecting symbol lookup back to various layers -/// of a JIT component stack, e.g. to enable lazy module emission. -/// -template <typename BaseRTDyldMM, typename ExternalLookupFtor, - typename DylibLookupFtor> -class LookasideRTDyldMM : public BaseRTDyldMM { -public: - /// @brief Create a LookasideRTDyldMM intance. - LookasideRTDyldMM(ExternalLookupFtor ExternalLookup, - DylibLookupFtor DylibLookup) - : ExternalLookup(std::move(ExternalLookup)), - DylibLookup(std::move(DylibLookup)) {} - - /// @brief Look up the given symbol address, first via the functor this - /// instance was created with, then (if the symbol isn't found) - /// via the underlying RuntimeDyldMM. - uint64_t getSymbolAddress(const std::string &Name) override { - if (uint64_t Addr = ExternalLookup(Name)) - return Addr; - return BaseRTDyldMM::getSymbolAddress(Name); - } - - uint64_t getSymbolAddressInLogicalDylib(const std::string &Name) override { - if (uint64_t Addr = DylibLookup(Name)) - return Addr; - return BaseRTDyldMM::getSymbolAddressInLogicalDylib(Name); - }; - - /// @brief Get a reference to the ExternalLookup functor. - ExternalLookupFtor &getExternalLookup() { return ExternalLookup; } - - /// @brief Get a const-reference to the ExternalLookup functor. - const ExternalLookupFtor &getExternalLookup() const { return ExternalLookup; } - - /// @brief Get a reference to the DylibLookup functor. - DylibLookupFtor &getDylibLookup() { return DylibLookup; } - - /// @brief Get a const-reference to the DylibLookup functor. - const DylibLookupFtor &getDylibLookup() const { return DylibLookup; } - -private: - ExternalLookupFtor ExternalLookup; - DylibLookupFtor DylibLookup; -}; - -/// @brief Create a LookasideRTDyldMM from a base memory manager type, an -/// external lookup functor, and a dylib lookup functor. -template <typename BaseRTDyldMM, typename ExternalLookupFtor, - typename DylibLookupFtor> -std::unique_ptr< - LookasideRTDyldMM<BaseRTDyldMM, ExternalLookupFtor, DylibLookupFtor>> -createLookasideRTDyldMM(ExternalLookupFtor &&ExternalLookup, - DylibLookupFtor &&DylibLookup) { - typedef LookasideRTDyldMM<BaseRTDyldMM, ExternalLookupFtor, DylibLookupFtor> - ThisLookasideMM; - return llvm::make_unique<ThisLookasideMM>( - std::forward<ExternalLookupFtor>(ExternalLookup), - std::forward<DylibLookupFtor>(DylibLookup)); -} - -} // End namespace orc. -} // End namespace llvm. - -#endif // LLVM_EXECUTIONENGINE_ORC_LOOKASIDERTDYLDMM_H diff --git a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h index 9838991..f3094da 100644 --- a/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h +++ b/include/llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h @@ -15,7 +15,7 @@ #define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H #include "JITSymbol.h" -#include "LookasideRTDyldMM.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ExecutionEngine/ExecutionEngine.h" #include "llvm/ExecutionEngine/SectionMemoryManager.h" #include <list> @@ -38,13 +38,12 @@ protected: LinkedObjectSet(const LinkedObjectSet&) = delete; void operator=(const LinkedObjectSet&) = delete; public: - LinkedObjectSet(std::unique_ptr<RTDyldMemoryManager> MM) - : MM(std::move(MM)), RTDyld(llvm::make_unique<RuntimeDyld>(&*this->MM)), + LinkedObjectSet(RuntimeDyld::MemoryManager &MemMgr, + RuntimeDyld::SymbolResolver &Resolver) + : RTDyld(llvm::make_unique<RuntimeDyld>(MemMgr, Resolver)), State(Raw) {} - // MSVC 2012 cannot infer a move constructor, so write it out longhand. - LinkedObjectSet(LinkedObjectSet &&O) - : MM(std::move(O.MM)), RTDyld(std::move(O.RTDyld)), State(O.State) {} + virtual ~LinkedObjectSet() {} std::unique_ptr<RuntimeDyld::LoadedObjectInfo> addObject(const object::ObjectFile &Obj) { @@ -57,14 +56,7 @@ protected: bool NeedsFinalization() const { return (State == Raw); } - void Finalize() { - State = Finalizing; - RTDyld->resolveRelocations(); - RTDyld->registerEHFrames(); - MM->finalizeMemory(); - OwnedBuffers.clear(); - State = Finalized; - } + virtual void Finalize() = 0; void mapSectionAddress(const void *LocalAddress, TargetAddress TargetAddr) { assert((State != Finalized) && @@ -76,8 +68,7 @@ protected: OwnedBuffers.push_back(std::move(B)); } - private: - std::unique_ptr<RTDyldMemoryManager> MM; + protected: std::unique_ptr<RuntimeDyld> RTDyld; enum { Raw, Finalizing, Finalized } State; @@ -87,7 +78,7 @@ protected: std::vector<std::unique_ptr<MemoryBuffer>> OwnedBuffers; }; - typedef std::list<LinkedObjectSet> LinkedObjectSetListT; + typedef std::list<std::unique_ptr<LinkedObjectSet>> LinkedObjectSetListT; public: /// @brief Handle to a set of loaded objects. @@ -99,7 +90,7 @@ public: template <typename OwningMBSet> void takeOwnershipOfBuffers(ObjSetHandleT H, OwningMBSet MBs) { for (auto &MB : MBs) - H->takeOwnershipOfBuffer(std::move(MB)); + (*H)->takeOwnershipOfBuffer(std::move(MB)); } }; @@ -120,6 +111,37 @@ public: /// symbols. template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded> class ObjectLinkingLayer : public ObjectLinkingLayerBase { +private: + + template <typename MemoryManagerPtrT, typename SymbolResolverPtrT> + class ConcreteLinkedObjectSet : public LinkedObjectSet { + public: + ConcreteLinkedObjectSet(MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) + : LinkedObjectSet(*MemMgr, *Resolver), MemMgr(std::move(MemMgr)), + Resolver(std::move(Resolver)) { } + + void Finalize() override { + State = Finalizing; + RTDyld->resolveRelocations(); + RTDyld->registerEHFrames(); + MemMgr->finalizeMemory(); + OwnedBuffers.clear(); + State = Finalized; + } + + private: + MemoryManagerPtrT MemMgr; + SymbolResolverPtrT Resolver; + }; + + template <typename MemoryManagerPtrT, typename SymbolResolverPtrT> + std::unique_ptr<LinkedObjectSet> + createLinkedObjectSet(MemoryManagerPtrT MemMgr, SymbolResolverPtrT Resolver) { + typedef ConcreteLinkedObjectSet<MemoryManagerPtrT, SymbolResolverPtrT> LOS; + return llvm::make_unique<LOS>(std::move(MemMgr), std::move(Resolver)); + } + public: /// @brief LoadedObjectInfo list. Contains a list of owning pointers to @@ -127,21 +149,16 @@ public: typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>> LoadedObjInfoList; - /// @brief Functor to create RTDyldMemoryManager instances. - typedef std::function<std::unique_ptr<RTDyldMemoryManager>()> CreateRTDyldMMFtor; - /// @brief Functor for receiving finalization notifications. typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor; /// @brief Construct an ObjectLinkingLayer with the given NotifyLoaded, - /// NotifyFinalized and CreateMemoryManager functors. + /// and NotifyFinalized functors. ObjectLinkingLayer( - CreateRTDyldMMFtor CreateMemoryManager = CreateRTDyldMMFtor(), NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(), NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor()) : NotifyLoaded(std::move(NotifyLoaded)), - NotifyFinalized(std::move(NotifyFinalized)), - CreateMemoryManager(std::move(CreateMemoryManager)) {} + NotifyFinalized(std::move(NotifyFinalized)) {} /// @brief Add a set of objects (or archives) that will be treated as a unit /// for the purposes of symbol lookup and memory management. @@ -154,19 +171,18 @@ public: /// This version of this method allows the client to pass in an /// RTDyldMemoryManager instance that will be used to allocate memory and look /// up external symbol addresses for the given objects. - template <typename ObjSetT> + template <typename ObjSetT, + typename MemoryManagerPtrT, + typename SymbolResolverPtrT> ObjSetHandleT addObjectSet(const ObjSetT &Objects, - std::unique_ptr<RTDyldMemoryManager> MM) { - - if (!MM) { - assert(CreateMemoryManager && - "No memory manager or memory manager creator provided."); - MM = CreateMemoryManager(); - } - - ObjSetHandleT Handle = LinkedObjSetList.insert( - LinkedObjSetList.end(), LinkedObjectSet(std::move(MM))); - LinkedObjectSet &LOS = *Handle; + MemoryManagerPtrT MemMgr, + SymbolResolverPtrT Resolver) { + ObjSetHandleT Handle = + LinkedObjSetList.insert( + LinkedObjSetList.end(), + createLinkedObjectSet(std::move(MemMgr), std::move(Resolver))); + + LinkedObjectSet &LOS = **Handle; LoadedObjInfoList LoadedObjInfos; for (auto &Obj : Objects) @@ -212,11 +228,11 @@ public: /// given object set. JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name, bool ExportedSymbolsOnly) { - if (auto Sym = H->getSymbol(Name)) { + if (auto Sym = (*H)->getSymbol(Name)) { if (Sym.isExported() || !ExportedSymbolsOnly) { auto Addr = Sym.getAddress(); auto Flags = Sym.getFlags(); - if (!H->NeedsFinalization()) { + if (!(*H)->NeedsFinalization()) { // If this instance has already been finalized then we can just return // the address. return JITSymbol(Addr, Flags); @@ -225,10 +241,10 @@ public: // it. The functor still needs to double-check whether finalization is // required, in case someone else finalizes this set before the // functor is called. - auto GetAddress = + auto GetAddress = [this, Addr, H]() { - if (H->NeedsFinalization()) { - H->Finalize(); + if ((*H)->NeedsFinalization()) { + (*H)->Finalize(); if (NotifyFinalized) NotifyFinalized(H); } @@ -244,14 +260,14 @@ public: /// @brief Map section addresses for the objects associated with the handle H. void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress, TargetAddress TargetAddr) { - H->mapSectionAddress(LocalAddress, TargetAddr); + (*H)->mapSectionAddress(LocalAddress, TargetAddr); } /// @brief Immediately emit and finalize the object set represented by the /// given handle. /// @param H Handle for object set to emit/finalize. void emitAndFinalize(ObjSetHandleT H) { - H->Finalize(); + (*H)->Finalize(); if (NotifyFinalized) NotifyFinalized(H); } @@ -260,7 +276,6 @@ private: LinkedObjectSetListT LinkedObjSetList; NotifyLoadedFtor NotifyLoaded; NotifyFinalizedFtor NotifyFinalized; - CreateRTDyldMMFtor CreateMemoryManager; }; } // End namespace orc. diff --git a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h index 792a499..207bad0 100644 --- a/include/llvm/ExecutionEngine/RTDyldMemoryManager.h +++ b/include/llvm/ExecutionEngine/RTDyldMemoryManager.h @@ -14,6 +14,7 @@ #ifndef LLVM_EXECUTIONENGINE_RTDYLDMEMORYMANAGER_H #define LLVM_EXECUTIONENGINE_RTDYLDMEMORYMANAGER_H +#include "RuntimeDyld.h" #include "llvm-c/ExecutionEngine.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/CBindingWrapping.h" @@ -27,89 +28,91 @@ class ExecutionEngine; class ObjectFile; } +class MCJITMemoryManager : public RuntimeDyld::MemoryManager { +public: + /// This method is called after an object has been loaded into memory but + /// before relocations are applied to the loaded sections. The object load + /// may have been initiated by MCJIT to resolve an external symbol for another + /// object that is being finalized. In that case, the object about which + /// the memory manager is being notified will be finalized immediately after + /// the memory manager returns from this call. + /// + /// Memory managers which are preparing code for execution in an external + /// address space can use this call to remap the section addresses for the + /// newly loaded object. + virtual void notifyObjectLoaded(ExecutionEngine *EE, + const object::ObjectFile &) {} +}; + // RuntimeDyld clients often want to handle the memory management of // what gets placed where. For JIT clients, this is the subset of // JITMemoryManager required for dynamic loading of binaries. // // FIXME: As the RuntimeDyld fills out, additional routines will be needed // for the varying types of objects to be allocated. -class RTDyldMemoryManager { +class RTDyldMemoryManager : public MCJITMemoryManager, + public RuntimeDyld::SymbolResolver { RTDyldMemoryManager(const RTDyldMemoryManager&) = delete; void operator=(const RTDyldMemoryManager&) = delete; public: RTDyldMemoryManager() {} - virtual ~RTDyldMemoryManager(); - - /// Allocate a memory block of (at least) the given size suitable for - /// executable code. The SectionID is a unique identifier assigned by the JIT - /// engine, and optionally recorded by the memory manager to access a loaded - /// section. - virtual uint8_t *allocateCodeSection( - uintptr_t Size, unsigned Alignment, unsigned SectionID, - StringRef SectionName) = 0; - - /// Allocate a memory block of (at least) the given size suitable for data. - /// The SectionID is a unique identifier assigned by the JIT engine, and - /// optionally recorded by the memory manager to access a loaded section. - virtual uint8_t *allocateDataSection( - uintptr_t Size, unsigned Alignment, unsigned SectionID, - StringRef SectionName, bool IsReadOnly) = 0; - - /// Inform the memory manager about the total amount of memory required to - /// allocate all sections to be loaded: - /// \p CodeSize - the total size of all code sections - /// \p DataSizeRO - the total size of all read-only data sections - /// \p DataSizeRW - the total size of all read-write data sections - /// - /// Note that by default the callback is disabled. To enable it - /// redefine the method needsToReserveAllocationSpace to return true. - virtual void reserveAllocationSpace( - uintptr_t CodeSize, uintptr_t DataSizeRO, uintptr_t DataSizeRW) { } - - /// Override to return true to enable the reserveAllocationSpace callback. - virtual bool needsToReserveAllocationSpace() { return false; } - - /// Register the EH frames with the runtime so that c++ exceptions work. - /// - /// \p Addr parameter provides the local address of the EH frame section - /// data, while \p LoadAddr provides the address of the data in the target - /// address space. If the section has not been remapped (which will usually - /// be the case for local execution) these two values will be the same. - virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size); + ~RTDyldMemoryManager() override; - virtual void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size); + void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override; + void deregisterEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override; /// This method returns the address of the specified function or variable in /// the current process. static uint64_t getSymbolAddressInProcess(const std::string &Name); + /// Legacy symbol lookup - DEPRECATED! Please override findSymbol instead. + /// /// This method returns the address of the specified function or variable. /// It is used to resolve symbols during module linking. virtual uint64_t getSymbolAddress(const std::string &Name) { return getSymbolAddressInProcess(Name); } - /// This method returns the address of the specified symbol if it exists - /// within the logical dynamic library represented by this - /// RTDyldMemoryManager. Unlike getSymbolAddress, queries through this - /// interface should return addresses for hidden symbols. + /// This method returns a RuntimeDyld::SymbolInfo for the specified function + /// or variable. It is used to resolve symbols during module linking. + /// + /// By default this falls back on the legacy lookup method: + /// 'getSymbolAddress'. The address returned by getSymbolAddress is treated as + /// a strong, exported symbol, consistent with historical treatment by + /// RuntimeDyld. /// - /// This is of particular importance for the Orc JIT APIs, which support lazy - /// compilation by breaking up modules: Each of those broken out modules - /// must be able to resolve hidden symbols provided by the others. Clients - /// writing memory managers for MCJIT can usually ignore this method. + /// Clients writing custom RTDyldMemoryManagers are encouraged to override + /// this method and return a SymbolInfo with the flags set correctly. This is + /// necessary for RuntimeDyld to correctly handle weak and non-exported symbols. + RuntimeDyld::SymbolInfo findSymbol(const std::string &Name) override { + return RuntimeDyld::SymbolInfo(getSymbolAddress(Name), + JITSymbolFlags::Exported); + } + + /// Legacy symbol lookup -- DEPRECATED! Please override + /// findSymbolInLogicalDylib instead. /// - /// This method will be queried by RuntimeDyld when checking for previous - /// definitions of common symbols. It will *not* be queried by default when - /// resolving external symbols (this minimises the link-time overhead for - /// MCJIT clients who don't care about Orc features). If you are writing a - /// RTDyldMemoryManager for Orc and want "external" symbol resolution to - /// search the logical dylib, you should override your getSymbolAddress - /// method call this method directly. + /// Default to treating all modules as separate. virtual uint64_t getSymbolAddressInLogicalDylib(const std::string &Name) { return 0; } + /// Default to treating all modules as separate. + /// + /// By default this falls back on the legacy lookup method: + /// 'getSymbolAddressInLogicalDylib'. The address returned by + /// getSymbolAddressInLogicalDylib is treated as a strong, exported symbol, + /// consistent with historical treatment by RuntimeDyld. + /// + /// Clients writing custom RTDyldMemoryManagers are encouraged to override + /// this method and return a SymbolInfo with the flags set correctly. This is + /// necessary for RuntimeDyld to correctly handle weak and non-exported symbols. + RuntimeDyld::SymbolInfo + findSymbolInLogicalDylib(const std::string &Name) override { + return RuntimeDyld::SymbolInfo(getSymbolAddressInLogicalDylib(Name), + JITSymbolFlags::Exported); + } + /// This method returns the address of the specified function. As such it is /// only useful for resolving library symbols, not code generated symbols. /// @@ -121,30 +124,6 @@ public: /// MCJIT or RuntimeDyld. Use getSymbolAddress instead. virtual void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true); - - /// This method is called after an object has been loaded into memory but - /// before relocations are applied to the loaded sections. The object load - /// may have been initiated by MCJIT to resolve an external symbol for another - /// object that is being finalized. In that case, the object about which - /// the memory manager is being notified will be finalized immediately after - /// the memory manager returns from this call. - /// - /// Memory managers which are preparing code for execution in an external - /// address space can use this call to remap the section addresses for the - /// newly loaded object. - virtual void notifyObjectLoaded(ExecutionEngine *EE, - const object::ObjectFile &) {} - - /// This method is called when object loading is complete and section page - /// permissions can be applied. It is up to the memory manager implementation - /// to decide whether or not to act on this method. The memory manager will - /// typically allocate all sections as read-write and then apply specific - /// permissions when this method is called. Code sections cannot be executed - /// until this function has been called. In addition, any cache coherency - /// operations needed to reliably use the memory are also performed. - /// - /// Returns true if an error occurred, false otherwise. - virtual bool finalizeMemory(std::string *ErrMsg = nullptr) = 0; }; // Create wrappers for C Binding types (see CBindingWrapping.h). @@ -153,4 +132,5 @@ DEFINE_SIMPLE_CONVERSION_FUNCTIONS( } // namespace llvm + #endif diff --git a/include/llvm/ExecutionEngine/RuntimeDyld.h b/include/llvm/ExecutionEngine/RuntimeDyld.h index fe0ccda..5723f05 100644 --- a/include/llvm/ExecutionEngine/RuntimeDyld.h +++ b/include/llvm/ExecutionEngine/RuntimeDyld.h @@ -16,7 +16,6 @@ #include "JITSymbolFlags.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/Support/Memory.h" #include <memory> @@ -29,19 +28,13 @@ namespace object { class RuntimeDyldImpl; class RuntimeDyldCheckerImpl; - + class RuntimeDyld { friend class RuntimeDyldCheckerImpl; RuntimeDyld(const RuntimeDyld &) = delete; void operator=(const RuntimeDyld &) = delete; - // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public - // interface. - std::unique_ptr<RuntimeDyldImpl> Dyld; - RTDyldMemoryManager *MM; - bool ProcessAllSections; - RuntimeDyldCheckerImpl *Checker; protected: // Change the address associated with a section when resolving relocations. // Any relocations already associated with the symbol will be re-resolved. @@ -82,7 +75,101 @@ public: unsigned BeginIdx, EndIdx; }; - RuntimeDyld(RTDyldMemoryManager *); + /// \brief Memory Management. + class MemoryManager { + public: + virtual ~MemoryManager() {}; + + /// Allocate a memory block of (at least) the given size suitable for + /// executable code. The SectionID is a unique identifier assigned by the + /// RuntimeDyld instance, and optionally recorded by the memory manager to + /// access a loaded section. + virtual uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + StringRef SectionName) = 0; + + /// Allocate a memory block of (at least) the given size suitable for data. + /// The SectionID is a unique identifier assigned by the JIT engine, and + /// optionally recorded by the memory manager to access a loaded section. + virtual uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, + unsigned SectionID, + StringRef SectionName, + bool IsReadOnly) = 0; + + /// Inform the memory manager about the total amount of memory required to + /// allocate all sections to be loaded: + /// \p CodeSize - the total size of all code sections + /// \p DataSizeRO - the total size of all read-only data sections + /// \p DataSizeRW - the total size of all read-write data sections + /// + /// Note that by default the callback is disabled. To enable it + /// redefine the method needsToReserveAllocationSpace to return true. + virtual void reserveAllocationSpace(uintptr_t CodeSize, + uintptr_t DataSizeRO, + uintptr_t DataSizeRW) {} + + /// Override to return true to enable the reserveAllocationSpace callback. + virtual bool needsToReserveAllocationSpace() { return false; } + + /// Register the EH frames with the runtime so that c++ exceptions work. + /// + /// \p Addr parameter provides the local address of the EH frame section + /// data, while \p LoadAddr provides the address of the data in the target + /// address space. If the section has not been remapped (which will usually + /// be the case for local execution) these two values will be the same. + virtual void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, + size_t Size) = 0; + virtual void deregisterEHFrames(uint8_t *addr, uint64_t LoadAddr, + size_t Size) = 0; + + /// This method is called when object loading is complete and section page + /// permissions can be applied. It is up to the memory manager implementation + /// to decide whether or not to act on this method. The memory manager will + /// typically allocate all sections as read-write and then apply specific + /// permissions when this method is called. Code sections cannot be executed + /// until this function has been called. In addition, any cache coherency + /// operations needed to reliably use the memory are also performed. + /// + /// Returns true if an error occurred, false otherwise. + virtual bool finalizeMemory(std::string *ErrMsg = nullptr) = 0; + + private: + virtual void anchor(); + }; + + /// \brief Symbol resolution. + class SymbolResolver { + public: + virtual ~SymbolResolver() {}; + + /// This method returns the address of the specified function or variable. + /// It is used to resolve symbols during module linking. + virtual SymbolInfo findSymbol(const std::string &Name) = 0; + + /// This method returns the address of the specified symbol if it exists + /// within the logical dynamic library represented by this + /// RTDyldMemoryManager. Unlike getSymbolAddress, queries through this + /// interface should return addresses for hidden symbols. + /// + /// This is of particular importance for the Orc JIT APIs, which support lazy + /// compilation by breaking up modules: Each of those broken out modules + /// must be able to resolve hidden symbols provided by the others. Clients + /// writing memory managers for MCJIT can usually ignore this method. + /// + /// This method will be queried by RuntimeDyld when checking for previous + /// definitions of common symbols. It will *not* be queried by default when + /// resolving external symbols (this minimises the link-time overhead for + /// MCJIT clients who don't care about Orc features). If you are writing a + /// RTDyldMemoryManager for Orc and want "external" symbol resolution to + /// search the logical dylib, you should override your getSymbolAddress + /// method call this method directly. + virtual SymbolInfo findSymbolInLogicalDylib(const std::string &Name) = 0; + private: + virtual void anchor(); + }; + + /// \brief Construct a RuntimeDyld instance. + RuntimeDyld(MemoryManager &MemMgr, SymbolResolver &Resolver); ~RuntimeDyld(); /// Add the referenced object file to the list of objects to be loaded and @@ -131,6 +218,15 @@ public: assert(!Dyld && "setProcessAllSections must be called before loadObject."); this->ProcessAllSections = ProcessAllSections; } + +private: + // RuntimeDyldImpl is the actual class. RuntimeDyld is just the public + // interface. + std::unique_ptr<RuntimeDyldImpl> Dyld; + MemoryManager &MemMgr; + SymbolResolver &Resolver; + bool ProcessAllSections; + RuntimeDyldCheckerImpl *Checker; }; } // end namespace llvm diff --git a/include/llvm/ExecutionEngine/SectionMemoryManager.h b/include/llvm/ExecutionEngine/SectionMemoryManager.h index b825aff..0b0dcb0 100644 --- a/include/llvm/ExecutionEngine/SectionMemoryManager.h +++ b/include/llvm/ExecutionEngine/SectionMemoryManager.h @@ -16,7 +16,7 @@ #define LLVM_EXECUTIONENGINE_SECTIONMEMORYMANAGER_H #include "llvm/ADT/SmallVector.h" -#include "llvm/ExecutionEngine/RuntimeDyld.h" +#include "llvm/ExecutionEngine/RTDyldMemoryManager.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/Memory.h" @@ -40,7 +40,7 @@ class SectionMemoryManager : public RTDyldMemoryManager { public: SectionMemoryManager() { } - virtual ~SectionMemoryManager(); + ~SectionMemoryManager() override; /// \brief Allocates a memory block of (at least) the given size suitable for /// executable code. diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 443892b..d0d1b5e 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -89,6 +89,7 @@ public: ///< often, so lazy binding isn't worthwhile NonNull, ///< Pointer is known to be not null Dereferenceable, ///< Pointer is known to be dereferenceable + DereferenceableOrNull, ///< Pointer is either null or dereferenceable NoRedZone, ///< Disable redzone NoReturn, ///< Mark the function as not returning NoUnwind, ///< Function doesn't unwind stack @@ -136,6 +137,8 @@ public: static Attribute getWithStackAlignment(LLVMContext &Context, uint64_t Align); static Attribute getWithDereferenceableBytes(LLVMContext &Context, uint64_t Bytes); + static Attribute getWithDereferenceableOrNullBytes(LLVMContext &Context, + uint64_t Bytes); //===--------------------------------------------------------------------===// // Attribute Accessors @@ -185,6 +188,10 @@ public: /// dereferenceable attribute (or zero if unknown). uint64_t getDereferenceableBytes() const; + /// \brief Returns the number of dereferenceable_or_null bytes from the + /// dereferenceable_or_null attribute (or zero if unknown). + uint64_t getDereferenceableOrNullBytes() const; + /// \brief The Attribute is converted to a string of equivalent mnemonic. This /// is, presumably, for writing out the mnemonics for the assembly writer. std::string getAsString(bool InAttrGrp = false) const; @@ -287,6 +294,12 @@ public: AttributeSet addDereferenceableAttr(LLVMContext &C, unsigned Index, uint64_t Bytes) const; + /// \brief Add the dereferenceable_or_null attribute to the attribute set at + /// the given index. Since attribute sets are immutable, this returns a new + /// set. + AttributeSet addDereferenceableOrNullAttr(LLVMContext &C, unsigned Index, + uint64_t Bytes) const; + //===--------------------------------------------------------------------===// // AttributeSet Accessors //===--------------------------------------------------------------------===// @@ -331,6 +344,10 @@ public: /// \brief Get the number of dereferenceable bytes (or zero if unknown). uint64_t getDereferenceableBytes(unsigned Index) const; + /// \brief Get the number of dereferenceable_or_null bytes (or zero if + /// unknown). + uint64_t getDereferenceableOrNullBytes(unsigned Index) const; + /// \brief Return the attributes at the index as a string. std::string getAsString(unsigned Index, bool InAttrGrp = false) const; @@ -411,6 +428,7 @@ class AttrBuilder { uint64_t Alignment; uint64_t StackAlignment; uint64_t DerefBytes; + uint64_t DerefOrNullBytes; public: AttrBuilder() : Attrs(0), Alignment(0), StackAlignment(0), DerefBytes(0) {} explicit AttrBuilder(uint64_t Val) @@ -476,6 +494,10 @@ public: /// attribute exists (zero is returned otherwise). uint64_t getDereferenceableBytes() const { return DerefBytes; } + /// \brief Retrieve the number of dereferenceable_or_null bytes, if the + /// dereferenceable_or_null attribute exists (zero is returned otherwise). + uint64_t getDereferenceableOrNullBytes() const { return DerefOrNullBytes; } + /// \brief This turns an int alignment (which must be a power of 2) into the /// form used internally in Attribute. AttrBuilder &addAlignmentAttr(unsigned Align); @@ -488,6 +510,10 @@ public: /// internally in Attribute. AttrBuilder &addDereferenceableAttr(uint64_t Bytes); + /// \brief This turns the number of dereferenceable_or_null bytes into the + /// form used internally in Attribute. + AttrBuilder &addDereferenceableOrNullAttr(uint64_t Bytes); + /// \brief Return true if the builder contains no target-independent /// attributes. bool empty() const { return Attrs.none(); } diff --git a/include/llvm/IR/BasicBlock.h b/include/llvm/IR/BasicBlock.h index 8f5cdeb..a71946e 100644 --- a/include/llvm/IR/BasicBlock.h +++ b/include/llvm/IR/BasicBlock.h @@ -28,33 +28,25 @@ class LandingPadInst; class TerminatorInst; class LLVMContext; class BlockAddress; +class Function; -template<> struct ilist_traits<Instruction> - : public SymbolTableListTraits<Instruction, BasicBlock> { +// Traits for intrusive list of basic blocks... +template<> struct ilist_traits<BasicBlock> + : public SymbolTableListTraits<BasicBlock, Function> { - /// \brief Return a node that marks the end of a list. - /// - /// The sentinel is relative to this instance, so we use a non-static - /// method. - Instruction *createSentinel() const { - // Since i(p)lists always publicly derive from their corresponding traits, - // placing a data member in this class will augment the i(p)list. But since - // the NodeTy is expected to be publicly derive from ilist_node<NodeTy>, - // there is a legal viable downcast from it to NodeTy. We use this trick to - // superimpose an i(p)list with a "ghostly" NodeTy, which becomes the - // sentinel. Dereferencing the sentinel is forbidden (save the - // ilist_node<NodeTy>), so no one will ever notice the superposition. - return static_cast<Instruction*>(&Sentinel); - } - static void destroySentinel(Instruction*) {} + BasicBlock *createSentinel() const; + static void destroySentinel(BasicBlock*) {} + + BasicBlock *provideInitialHead() const { return createSentinel(); } + BasicBlock *ensureHead(BasicBlock*) const { return createSentinel(); } + static void noteHead(BasicBlock*, BasicBlock*) {} - Instruction *provideInitialHead() const { return createSentinel(); } - Instruction *ensureHead(Instruction*) const { return createSentinel(); } - static void noteHead(Instruction*, Instruction*) {} + static ValueSymbolTable *getSymTab(Function *ItemParent); private: - mutable ilist_half_node<Instruction> Sentinel; + mutable ilist_half_node<BasicBlock> Sentinel; }; + /// \brief LLVM Basic Block Representation /// /// This represents a single basic block in LLVM. A basic block is simply a @@ -113,7 +105,7 @@ public: BasicBlock *InsertBefore = nullptr) { return new BasicBlock(Context, Name, Parent, InsertBefore); } - ~BasicBlock(); + ~BasicBlock() override; /// \brief Return the enclosing method, or null if none. const Function *getParent() const { return Parent; } @@ -176,7 +168,9 @@ public: void removeFromParent(); /// \brief Unlink 'this' from the containing function and delete it. - void eraseFromParent(); + /// + // \returns an iterator pointing to the element after the erased one. + iplist<BasicBlock>::iterator eraseFromParent(); /// \brief Unlink this basic block from its current function and insert it /// into the function that \p MovePos lives in, right before \p MovePos. @@ -332,6 +326,12 @@ private: } }; +// createSentinel is used to get hold of the node that marks the end of the +// list... (same trick used here as in ilist_traits<Instruction>) +inline BasicBlock *ilist_traits<BasicBlock>::createSentinel() const { + return static_cast<BasicBlock*>(&Sentinel); +} + // Create wrappers for C Binding types (see CBindingWrapping.h). DEFINE_SIMPLE_CONVERSION_FUNCTIONS(BasicBlock, LLVMBasicBlockRef) diff --git a/include/llvm/IR/CallSite.h b/include/llvm/IR/CallSite.h index 9c87936..ebace33 100644 --- a/include/llvm/IR/CallSite.h +++ b/include/llvm/IR/CallSite.h @@ -46,12 +46,13 @@ template <typename FunTy = const Function, class CallSiteBase { protected: PointerIntPair<InstrTy*, 1, bool> I; -public: + CallSiteBase() : I(nullptr, false) {} CallSiteBase(CallTy *CI) : I(CI, true) { assert(CI); } CallSiteBase(InvokeTy *II) : I(II, false) { assert(II); } - CallSiteBase(ValTy *II) { *this = get(II); } -protected: + explicit CallSiteBase(ValTy *II) { *this = get(II); } + +private: /// CallSiteBase::get - This static method is sort of like a constructor. It /// will create an appropriate call site for a Call or Invoke instruction, but /// it can also create a null initialized CallSiteBase object for something @@ -349,15 +350,13 @@ private: class CallSite : public CallSiteBase<Function, Value, User, Instruction, CallInst, InvokeInst, User::op_iterator> { - typedef CallSiteBase<Function, Value, User, Instruction, - CallInst, InvokeInst, User::op_iterator> Base; public: CallSite() {} - CallSite(Base B) : Base(B) {} - CallSite(Value* V) : Base(V) {} - CallSite(CallInst *CI) : Base(CI) {} - CallSite(InvokeInst *II) : Base(II) {} - CallSite(Instruction *II) : Base(II) {} + CallSite(CallSiteBase B) : CallSiteBase(B) {} + CallSite(CallInst *CI) : CallSiteBase(CI) {} + CallSite(InvokeInst *II) : CallSiteBase(II) {} + explicit CallSite(Instruction *II) : CallSiteBase(II) {} + explicit CallSite(Value *V) : CallSiteBase(V) {} bool operator==(const CallSite &CS) const { return I == CS.I; } bool operator!=(const CallSite &CS) const { return I != CS.I; } @@ -371,13 +370,13 @@ private: /// ImmutableCallSite - establish a view to a call site for examination class ImmutableCallSite : public CallSiteBase<> { - typedef CallSiteBase<> Base; public: - ImmutableCallSite(const Value* V) : Base(V) {} - ImmutableCallSite(const CallInst *CI) : Base(CI) {} - ImmutableCallSite(const InvokeInst *II) : Base(II) {} - ImmutableCallSite(const Instruction *II) : Base(II) {} - ImmutableCallSite(CallSite CS) : Base(CS.getInstruction()) {} + ImmutableCallSite() {} + ImmutableCallSite(const CallInst *CI) : CallSiteBase(CI) {} + ImmutableCallSite(const InvokeInst *II) : CallSiteBase(II) {} + explicit ImmutableCallSite(const Instruction *II) : CallSiteBase(II) {} + explicit ImmutableCallSite(const Value *V) : CallSiteBase(V) {} + ImmutableCallSite(CallSite CS) : CallSiteBase(CS.getInstruction()) {} }; } // End llvm namespace diff --git a/include/llvm/IR/ConstantFolder.h b/include/llvm/IR/ConstantFolder.h index e271a14..fb6ca3b 100644 --- a/include/llvm/IR/ConstantFolder.h +++ b/include/llvm/IR/ConstantFolder.h @@ -118,34 +118,35 @@ public: // Memory Instructions //===--------------------------------------------------------------------===// - Constant *CreateGetElementPtr(Constant *C, + Constant *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getGetElementPtr(C, IdxList); + return ConstantExpr::getGetElementPtr(Ty, C, IdxList); } - Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return ConstantExpr::getGetElementPtr(C, Idx); + return ConstantExpr::getGetElementPtr(Ty, C, Idx); } - Constant *CreateGetElementPtr(Constant *C, + Constant *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return ConstantExpr::getGetElementPtr(C, IdxList); + return ConstantExpr::getGetElementPtr(Ty, C, IdxList); } - Constant *CreateInBoundsGetElementPtr(Constant *C, + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList); } - Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, + Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return ConstantExpr::getInBoundsGetElementPtr(C, Idx); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx); } - Constant *CreateInBoundsGetElementPtr(Constant *C, + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList); } //===--------------------------------------------------------------------===// diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 59be653..70437e6 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -547,7 +547,7 @@ class ConstantDataSequential : public Constant { protected: explicit ConstantDataSequential(Type *ty, ValueTy VT, const char *Data) : Constant(ty, VT, nullptr, 0), DataElements(Data), Next(nullptr) {} - ~ConstantDataSequential() { delete Next; } + ~ConstantDataSequential() override { delete Next; } static Constant *getImpl(StringRef Bytes, Type *Ty); @@ -1057,41 +1057,43 @@ public: /// all elements must be Constant's. /// /// \param OnlyIfReducedTy see \a getWithOperands() docs. - static Constant *getGetElementPtr(Constant *C, ArrayRef<Constant *> IdxList, + static Constant *getGetElementPtr(Type *Ty, Constant *C, + ArrayRef<Constant *> IdxList, bool InBounds = false, Type *OnlyIfReducedTy = nullptr) { return getGetElementPtr( - C, makeArrayRef((Value * const *)IdxList.data(), IdxList.size()), + Ty, C, makeArrayRef((Value * const *)IdxList.data(), IdxList.size()), InBounds, OnlyIfReducedTy); } - static Constant *getGetElementPtr(Constant *C, Constant *Idx, + static Constant *getGetElementPtr(Type *Ty, Constant *C, Constant *Idx, bool InBounds = false, Type *OnlyIfReducedTy = nullptr) { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return getGetElementPtr(C, cast<Value>(Idx), InBounds, OnlyIfReducedTy); + return getGetElementPtr(Ty, C, cast<Value>(Idx), InBounds, OnlyIfReducedTy); } - static Constant *getGetElementPtr(Constant *C, ArrayRef<Value *> IdxList, + static Constant *getGetElementPtr(Type *Ty, Constant *C, + ArrayRef<Value *> IdxList, bool InBounds = false, Type *OnlyIfReducedTy = nullptr); /// Create an "inbounds" getelementptr. See the documentation for the /// "inbounds" flag in LangRef.html for details. - static Constant *getInBoundsGetElementPtr(Constant *C, + static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) { - return getGetElementPtr(C, IdxList, true); + return getGetElementPtr(Ty, C, IdxList, true); } - static Constant *getInBoundsGetElementPtr(Constant *C, + static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C, Constant *Idx) { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return getGetElementPtr(C, Idx, true); + return getGetElementPtr(Ty, C, Idx, true); } - static Constant *getInBoundsGetElementPtr(Constant *C, + static Constant *getInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) { - return getGetElementPtr(C, IdxList, true); + return getGetElementPtr(Ty, C, IdxList, true); } static Constant *getExtractElement(Constant *Vec, Constant *Idx, diff --git a/include/llvm/IR/DIBuilder.h b/include/llvm/IR/DIBuilder.h index 97a7b83..db87654 100644 --- a/include/llvm/IR/DIBuilder.h +++ b/include/llvm/IR/DIBuilder.h @@ -30,38 +30,17 @@ namespace llvm { class Value; class Constant; class LLVMContext; - class MDNode; class StringRef; - class DIBasicType; - class DICompileUnit; - class DICompositeType; - class DIDerivedType; - class DIDescriptor; - class DIFile; - class DIEnumerator; - class DIType; - class DIGlobalVariable; - class DIImportedEntity; - class DINameSpace; - class DIVariable; - class DISubrange; - class DILexicalBlockFile; - class DILexicalBlock; - class DIScope; - class DISubprogram; - class DITemplateTypeParameter; - class DITemplateValueParameter; - class DIObjCProperty; class DIBuilder { Module &M; LLVMContext &VMContext; - MDNode *TempEnumTypes; - MDNode *TempRetainTypes; - MDNode *TempSubprograms; - MDNode *TempGVs; - MDNode *TempImportedModules; + TempMDTuple TempEnumTypes; + TempMDTuple TempRetainTypes; + TempMDTuple TempSubprograms; + TempMDTuple TempGVs; + TempMDTuple TempImportedModules; Function *DeclareFn; // llvm.dbg.declare Function *ValueFn; // llvm.dbg.value @@ -125,26 +104,25 @@ namespace llvm { /// source location information in the back end /// without actually changing the output (e.g., /// when using optimization remarks). - DICompileUnit createCompileUnit(unsigned Lang, StringRef File, - StringRef Dir, StringRef Producer, - bool isOptimized, StringRef Flags, - unsigned RV, - StringRef SplitName = StringRef(), - DebugEmissionKind Kind = FullDebug, - bool EmitDebugInfo = true); + MDCompileUnit *createCompileUnit(unsigned Lang, StringRef File, + StringRef Dir, StringRef Producer, + bool isOptimized, StringRef Flags, + unsigned RV, StringRef SplitName = "", + DebugEmissionKind Kind = FullDebug, + bool EmitDebugInfo = true); /// createFile - Create a file descriptor to hold debugging information /// for a file. - DIFile createFile(StringRef Filename, StringRef Directory); + MDFile *createFile(StringRef Filename, StringRef Directory); /// createEnumerator - Create a single enumerator value. - DIEnumerator createEnumerator(StringRef Name, int64_t Val); + MDEnumerator *createEnumerator(StringRef Name, int64_t Val); /// \brief Create a DWARF unspecified type. - DIBasicType createUnspecifiedType(StringRef Name); + MDBasicType *createUnspecifiedType(StringRef Name); /// \brief Create C++11 nullptr type. - DIBasicType createNullPtrType(); + MDBasicType *createNullPtrType(); /// createBasicType - Create debugging information entry for a basic /// type. @@ -152,36 +130,36 @@ namespace llvm { /// @param SizeInBits Size of the type. /// @param AlignInBits Type alignment. /// @param Encoding DWARF encoding code, e.g. dwarf::DW_ATE_float. - DIBasicType createBasicType(StringRef Name, uint64_t SizeInBits, - uint64_t AlignInBits, unsigned Encoding); + MDBasicType *createBasicType(StringRef Name, uint64_t SizeInBits, + uint64_t AlignInBits, unsigned Encoding); /// createQualifiedType - Create debugging information entry for a qualified /// type, e.g. 'const int'. /// @param Tag Tag identifing type, e.g. dwarf::TAG_volatile_type /// @param FromTy Base Type. - DIDerivedType createQualifiedType(unsigned Tag, DIType FromTy); + MDDerivedType *createQualifiedType(unsigned Tag, MDType *FromTy); /// createPointerType - Create debugging information entry for a pointer. /// @param PointeeTy Type pointed by this pointer. /// @param SizeInBits Size. /// @param AlignInBits Alignment. (optional) /// @param Name Pointer type name. (optional) - DIDerivedType - createPointerType(DIType PointeeTy, uint64_t SizeInBits, - uint64_t AlignInBits = 0, StringRef Name = StringRef()); + MDDerivedType *createPointerType(MDType *PointeeTy, uint64_t SizeInBits, + uint64_t AlignInBits = 0, + StringRef Name = ""); /// \brief Create debugging information entry for a pointer to member. /// @param PointeeTy Type pointed to by this pointer. /// @param SizeInBits Size. /// @param AlignInBits Alignment. (optional) /// @param Class Type for which this pointer points to members of. - DIDerivedType createMemberPointerType(DIType PointeeTy, DIType Class, - uint64_t SizeInBits, - uint64_t AlignInBits = 0); + MDDerivedType *createMemberPointerType(MDType *PointeeTy, MDType *Class, + uint64_t SizeInBits, + uint64_t AlignInBits = 0); /// createReferenceType - Create debugging information entry for a c++ /// style reference or rvalue reference type. - DIDerivedType createReferenceType(unsigned Tag, DIType RTy); + MDDerivedType *createReferenceType(unsigned Tag, MDType *RTy); /// createTypedef - Create debugging information entry for a typedef. /// @param Ty Original type. @@ -189,11 +167,11 @@ namespace llvm { /// @param File File where this type is defined. /// @param LineNo Line number. /// @param Context The surrounding context for the typedef. - DIDerivedType createTypedef(DIType Ty, StringRef Name, DIFile File, - unsigned LineNo, DIDescriptor Context); + MDDerivedType *createTypedef(MDType *Ty, StringRef Name, MDFile *File, + unsigned LineNo, MDScope *Context); /// createFriend - Create debugging information entry for a 'friend'. - DIDerivedType createFriend(DIType Ty, DIType FriendTy); + MDDerivedType *createFriend(MDType *Ty, MDType *FriendTy); /// createInheritance - Create debugging information entry to establish /// inheritance relationship between two types. @@ -202,8 +180,8 @@ namespace llvm { /// @param BaseOffset Base offset. /// @param Flags Flags to describe inheritance attribute, /// e.g. private - DIDerivedType createInheritance(DIType Ty, DIType BaseTy, - uint64_t BaseOffset, unsigned Flags); + MDDerivedType *createInheritance(MDType *Ty, MDType *BaseTy, + uint64_t BaseOffset, unsigned Flags); /// createMemberType - Create debugging information entry for a member. /// @param Scope Member scope. @@ -215,10 +193,11 @@ namespace llvm { /// @param OffsetInBits Member offset. /// @param Flags Flags to encode member attribute, e.g. private /// @param Ty Parent type. - DIDerivedType - createMemberType(DIDescriptor Scope, StringRef Name, DIFile File, - unsigned LineNo, uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, DIType Ty); + MDDerivedType *createMemberType(MDScope *Scope, StringRef Name, + MDFile *File, unsigned LineNo, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + MDType *Ty); /// createStaticMemberType - Create debugging information entry for a /// C++ static data member. @@ -229,10 +208,10 @@ namespace llvm { /// @param Ty Type of the static member. /// @param Flags Flags to encode member attribute, e.g. private. /// @param Val Const initializer of the member. - DIDerivedType createStaticMemberType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNo, - DIType Ty, unsigned Flags, - llvm::Constant *Val); + MDDerivedType *createStaticMemberType(MDScope *Scope, StringRef Name, + MDFile *File, unsigned LineNo, + MDType *Ty, unsigned Flags, + llvm::Constant *Val); /// createObjCIVar - Create debugging information entry for Objective-C /// instance variable. @@ -245,11 +224,10 @@ namespace llvm { /// @param Flags Flags to encode member attribute, e.g. private /// @param Ty Parent type. /// @param PropertyNode Property associated with this ivar. - DIDerivedType createObjCIVar(StringRef Name, DIFile File, - unsigned LineNo, uint64_t SizeInBits, - uint64_t AlignInBits, uint64_t OffsetInBits, - unsigned Flags, DIType Ty, - MDNode *PropertyNode); + MDDerivedType *createObjCIVar(StringRef Name, MDFile *File, unsigned LineNo, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + MDType *Ty, MDNode *PropertyNode); /// createObjCProperty - Create debugging information entry for Objective-C /// property. @@ -260,12 +238,11 @@ namespace llvm { /// @param SetterName Name of the Objective C property setter selector. /// @param PropertyAttributes Objective C property attributes. /// @param Ty Type. - DIObjCProperty createObjCProperty(StringRef Name, - DIFile File, unsigned LineNumber, - StringRef GetterName, - StringRef SetterName, - unsigned PropertyAttributes, - DIType Ty); + MDObjCProperty *createObjCProperty(StringRef Name, MDFile *File, + unsigned LineNumber, + StringRef GetterName, + StringRef SetterName, + unsigned PropertyAttributes, MDType *Ty); /// createClassType - Create debugging information entry for a class. /// @param Scope Scope in which this class is defined. @@ -283,14 +260,14 @@ namespace llvm { /// for more info. /// @param TemplateParms Template type parameters. /// @param UniqueIdentifier A unique identifier for the class. - DICompositeType createClassType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, - DIType DerivedFrom, DIArray Elements, - DIType VTableHolder = DIType(), - MDNode *TemplateParms = nullptr, - StringRef UniqueIdentifier = StringRef()); + MDCompositeType *createClassType(MDScope *Scope, StringRef Name, + MDFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + uint64_t OffsetInBits, unsigned Flags, + MDType *DerivedFrom, DIArray Elements, + MDType *VTableHolder = nullptr, + MDNode *TemplateParms = nullptr, + StringRef UniqueIdentifier = ""); /// createStructType - Create debugging information entry for a struct. /// @param Scope Scope in which this struct is defined. @@ -303,13 +280,11 @@ namespace llvm { /// @param Elements Struct elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. /// @param UniqueIdentifier A unique identifier for the struct. - DICompositeType createStructType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, - unsigned Flags, DIType DerivedFrom, - DIArray Elements, unsigned RunTimeLang = 0, - DIType VTableHolder = DIType(), - StringRef UniqueIdentifier = StringRef()); + MDCompositeType *createStructType( + MDScope *Scope, StringRef Name, MDFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, + MDType *DerivedFrom, DIArray Elements, unsigned RunTimeLang = 0, + MDType *VTableHolder = nullptr, StringRef UniqueIdentifier = ""); /// createUnionType - Create debugging information entry for an union. /// @param Scope Scope in which this union is defined. @@ -322,19 +297,20 @@ namespace llvm { /// @param Elements Union elements. /// @param RunTimeLang Optional parameter, Objective-C runtime version. /// @param UniqueIdentifier A unique identifier for the union. - DICompositeType createUnionType( - DIDescriptor Scope, StringRef Name, DIFile File, unsigned LineNumber, - uint64_t SizeInBits, uint64_t AlignInBits, unsigned Flags, - DIArray Elements, unsigned RunTimeLang = 0, - StringRef UniqueIdentifier = StringRef()); + MDCompositeType *createUnionType(MDScope *Scope, StringRef Name, + MDFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, + unsigned Flags, DIArray Elements, + unsigned RunTimeLang = 0, + StringRef UniqueIdentifier = ""); /// createTemplateTypeParameter - Create debugging information for template /// type parameter. /// @param Scope Scope in which this type is defined. /// @param Name Type parameter name. /// @param Ty Parameter type. - DITemplateTypeParameter - createTemplateTypeParameter(DIDescriptor Scope, StringRef Name, DIType Ty); + MDTemplateTypeParameter * + createTemplateTypeParameter(MDScope *Scope, StringRef Name, MDType *Ty); /// createTemplateValueParameter - Create debugging information for template /// value parameter. @@ -342,46 +318,46 @@ namespace llvm { /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val Constant parameter value. - DITemplateValueParameter createTemplateValueParameter(DIDescriptor Scope, - StringRef Name, - DIType Ty, - Constant *Val); + MDTemplateValueParameter *createTemplateValueParameter(MDScope *Scope, + StringRef Name, + MDType *Ty, + Constant *Val); /// \brief Create debugging information for a template template parameter. /// @param Scope Scope in which this type is defined. /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val The fully qualified name of the template. - DITemplateValueParameter createTemplateTemplateParameter(DIDescriptor Scope, - StringRef Name, - DIType Ty, - StringRef Val); + MDTemplateValueParameter *createTemplateTemplateParameter(MDScope *Scope, + StringRef Name, + MDType *Ty, + StringRef Val); /// \brief Create debugging information for a template parameter pack. /// @param Scope Scope in which this type is defined. /// @param Name Value parameter name. /// @param Ty Parameter type. /// @param Val An array of types in the pack. - DITemplateValueParameter createTemplateParameterPack(DIDescriptor Scope, - StringRef Name, - DIType Ty, - DIArray Val); + MDTemplateValueParameter *createTemplateParameterPack(MDScope *Scope, + StringRef Name, + MDType *Ty, + DIArray Val); /// createArrayType - Create debugging information entry for an array. /// @param Size Array size. /// @param AlignInBits Alignment. /// @param Ty Element type. /// @param Subscripts Subscripts. - DICompositeType createArrayType(uint64_t Size, uint64_t AlignInBits, - DIType Ty, DIArray Subscripts); + MDCompositeType *createArrayType(uint64_t Size, uint64_t AlignInBits, + MDType *Ty, DIArray Subscripts); /// createVectorType - Create debugging information entry for a vector type. /// @param Size Array size. /// @param AlignInBits Alignment. /// @param Ty Element type. /// @param Subscripts Subscripts. - DICompositeType createVectorType(uint64_t Size, uint64_t AlignInBits, - DIType Ty, DIArray Subscripts); + MDCompositeType *createVectorType(uint64_t Size, uint64_t AlignInBits, + MDType *Ty, DIArray Subscripts); /// createEnumerationType - Create debugging information entry for an /// enumeration. @@ -394,10 +370,10 @@ namespace llvm { /// @param Elements Enumeration elements. /// @param UnderlyingType Underlying type of a C++11/ObjC fixed enum. /// @param UniqueIdentifier A unique identifier for the enum. - DICompositeType createEnumerationType(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNumber, uint64_t SizeInBits, - uint64_t AlignInBits, DIArray Elements, DIType UnderlyingType, - StringRef UniqueIdentifier = StringRef()); + MDCompositeType *createEnumerationType( + MDScope *Scope, StringRef Name, MDFile *File, unsigned LineNumber, + uint64_t SizeInBits, uint64_t AlignInBits, DIArray Elements, + MDType *UnderlyingType, StringRef UniqueIdentifier = ""); /// createSubroutineType - Create subroutine type. /// @param File File in which this subroutine is defined. @@ -405,39 +381,39 @@ namespace llvm { /// includes return type at 0th index. /// @param Flags E.g.: LValueReference. /// These flags are used to emit dwarf attributes. - DISubroutineType createSubroutineType(DIFile File, - DITypeArray ParameterTypes, - unsigned Flags = 0); + MDSubroutineType *createSubroutineType(MDFile *File, + DITypeArray ParameterTypes, + unsigned Flags = 0); - /// createArtificialType - Create a new DIType with "artificial" flag set. - DIType createArtificialType(DIType Ty); + /// createArtificialType - Create a new MDType* with "artificial" flag set. + MDType *createArtificialType(MDType *Ty); - /// createObjectPointerType - Create a new DIType with the "object pointer" + /// createObjectPointerType - Create a new MDType* with the "object pointer" /// flag set. - DIType createObjectPointerType(DIType Ty); + MDType *createObjectPointerType(MDType *Ty); /// \brief Create a permanent forward-declared type. - DICompositeType createForwardDecl(unsigned Tag, StringRef Name, - DIDescriptor Scope, DIFile F, - unsigned Line, unsigned RuntimeLang = 0, - uint64_t SizeInBits = 0, - uint64_t AlignInBits = 0, - StringRef UniqueIdentifier = StringRef()); + MDCompositeType *createForwardDecl(unsigned Tag, StringRef Name, + MDScope *Scope, MDFile *F, unsigned Line, + unsigned RuntimeLang = 0, + uint64_t SizeInBits = 0, + uint64_t AlignInBits = 0, + StringRef UniqueIdentifier = ""); /// \brief Create a temporary forward-declared type. - DICompositeType createReplaceableCompositeType( - unsigned Tag, StringRef Name, DIDescriptor Scope, DIFile F, - unsigned Line, unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, - uint64_t AlignInBits = 0, unsigned Flags = DIDescriptor::FlagFwdDecl, - StringRef UniqueIdentifier = StringRef()); + MDCompositeType *createReplaceableCompositeType( + unsigned Tag, StringRef Name, MDScope *Scope, MDFile *F, unsigned Line, + unsigned RuntimeLang = 0, uint64_t SizeInBits = 0, + uint64_t AlignInBits = 0, unsigned Flags = DebugNode::FlagFwdDecl, + StringRef UniqueIdentifier = ""); - /// retainType - Retain DIType in a module even if it is not referenced + /// retainType - Retain MDType* in a module even if it is not referenced /// through debug info anchors. - void retainType(DIType T); + void retainType(MDType *T); /// createUnspecifiedParameter - Create unspecified parameter type /// for a subroutine type. - DIBasicType createUnspecifiedParameter(); + MDBasicType *createUnspecifiedParameter(); /// getOrCreateArray - Get a DIArray, create one if required. DIArray getOrCreateArray(ArrayRef<Metadata *> Elements); @@ -447,8 +423,7 @@ namespace llvm { /// getOrCreateSubrange - Create a descriptor for a value range. This /// implicitly uniques the values returned. - DISubrange getOrCreateSubrange(int64_t Lo, int64_t Count); - + MDSubrange *getOrCreateSubrange(int64_t Lo, int64_t Count); /// createGlobalVariable - Create a new descriptor for the specified /// variable. @@ -462,19 +437,19 @@ namespace llvm { /// externally visible or not. /// @param Val llvm::Value of the variable. /// @param Decl Reference to the corresponding declaration. - DIGlobalVariable createGlobalVariable(DIDescriptor Context, StringRef Name, - StringRef LinkageName, DIFile File, - unsigned LineNo, DITypeRef Ty, - bool isLocalToUnit, - llvm::Constant *Val, - MDNode *Decl = nullptr); + MDGlobalVariable *createGlobalVariable(MDScope *Context, StringRef Name, + StringRef LinkageName, MDFile *File, + unsigned LineNo, MDType *Ty, + bool isLocalToUnit, + llvm::Constant *Val, + MDNode *Decl = nullptr); /// createTempGlobalVariableFwdDecl - Identical to createGlobalVariable /// except that the resulting DbgNode is temporary and meant to be RAUWed. - DIGlobalVariable createTempGlobalVariableFwdDecl( - DIDescriptor Context, StringRef Name, StringRef LinkageName, - DIFile File, unsigned LineNo, DITypeRef Ty, bool isLocalToUnit, - llvm::Constant *Val, MDNode *Decl = nullptr); + MDGlobalVariable *createTempGlobalVariableFwdDecl( + MDScope *Context, StringRef Name, StringRef LinkageName, MDFile *File, + unsigned LineNo, MDType *Ty, bool isLocalToUnit, llvm::Constant *Val, + MDNode *Decl = nullptr); /// createLocalVariable - Create a new descriptor for the specified /// local variable. @@ -490,29 +465,29 @@ namespace llvm { /// @param Flags Flags, e.g. artificial variable. /// @param ArgNo If this variable is an argument then this argument's /// number. 1 indicates 1st argument. - DIVariable createLocalVariable(unsigned Tag, DIDescriptor Scope, - StringRef Name, - DIFile File, unsigned LineNo, - DITypeRef Ty, bool AlwaysPreserve = false, - unsigned Flags = 0, - unsigned ArgNo = 0); + MDLocalVariable *createLocalVariable(unsigned Tag, MDScope *Scope, + StringRef Name, MDFile *File, + unsigned LineNo, MDType *Ty, + bool AlwaysPreserve = false, + unsigned Flags = 0, + unsigned ArgNo = 0); /// createExpression - Create a new descriptor for the specified /// variable which has a complex address expression for its address. /// @param Addr An array of complex address operations. - DIExpression createExpression(ArrayRef<uint64_t> Addr = None); - DIExpression createExpression(ArrayRef<int64_t> Addr); + MDExpression *createExpression(ArrayRef<uint64_t> Addr = None); + MDExpression *createExpression(ArrayRef<int64_t> Addr); /// createBitPieceExpression - Create a descriptor to describe one part /// of aggregate variable that is fragmented across multiple Values. /// /// @param OffsetInBits Offset of the piece in bits. /// @param SizeInBits Size of the piece in bits. - DIExpression createBitPieceExpression(unsigned OffsetInBits, - unsigned SizeInBits); + MDExpression *createBitPieceExpression(unsigned OffsetInBits, + unsigned SizeInBits); /// createFunction - Create a new descriptor for the specified subprogram. - /// See comments in DISubprogram for descriptions of these fields. + /// See comments in MDSubprogram* for descriptions of these fields. /// @param Scope Function scope. /// @param Name Function name. /// @param LinkageName Mangled function name. @@ -527,49 +502,35 @@ namespace llvm { /// @param isOptimized True if optimization is ON. /// @param Fn llvm::Function pointer. /// @param TParam Function template parameters. - DISubprogram createFunction(DIDescriptor Scope, StringRef Name, - StringRef LinkageName, - DIFile File, unsigned LineNo, - DICompositeType Ty, bool isLocalToUnit, - bool isDefinition, - unsigned ScopeLine, - unsigned Flags = 0, - bool isOptimized = false, - Function *Fn = nullptr, - MDNode *TParam = nullptr, - MDNode *Decl = nullptr); + MDSubprogram * + createFunction(MDScope *Scope, StringRef Name, StringRef LinkageName, + MDFile *File, unsigned LineNo, MDSubroutineType *Ty, + bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, + unsigned Flags = 0, bool isOptimized = false, + Function *Fn = nullptr, MDNode *TParam = nullptr, + MDNode *Decl = nullptr); /// createTempFunctionFwdDecl - Identical to createFunction, /// except that the resulting DbgNode is meant to be RAUWed. - DISubprogram createTempFunctionFwdDecl(DIDescriptor Scope, StringRef Name, - StringRef LinkageName, - DIFile File, unsigned LineNo, - DICompositeType Ty, bool isLocalToUnit, - bool isDefinition, - unsigned ScopeLine, - unsigned Flags = 0, - bool isOptimized = false, - Function *Fn = nullptr, - MDNode *TParam = nullptr, - MDNode *Decl = nullptr); - + MDSubprogram *createTempFunctionFwdDecl( + MDScope *Scope, StringRef Name, StringRef LinkageName, MDFile *File, + unsigned LineNo, MDSubroutineType *Ty, bool isLocalToUnit, + bool isDefinition, unsigned ScopeLine, unsigned Flags = 0, + bool isOptimized = false, Function *Fn = nullptr, + MDNode *TParam = nullptr, MDNode *Decl = nullptr); /// FIXME: this is added for dragonegg. Once we update dragonegg /// to call resolve function, this will be removed. - DISubprogram createFunction(DIScopeRef Scope, StringRef Name, - StringRef LinkageName, - DIFile File, unsigned LineNo, - DICompositeType Ty, bool isLocalToUnit, - bool isDefinition, - unsigned ScopeLine, - unsigned Flags = 0, - bool isOptimized = false, - Function *Fn = nullptr, - MDNode *TParam = nullptr, - MDNode *Decl = nullptr); + MDSubprogram * + createFunction(DIScopeRef Scope, StringRef Name, StringRef LinkageName, + MDFile *File, unsigned LineNo, MDSubroutineType *Ty, + bool isLocalToUnit, bool isDefinition, unsigned ScopeLine, + unsigned Flags = 0, bool isOptimized = false, + Function *Fn = nullptr, MDNode *TParam = nullptr, + MDNode *Decl = nullptr); /// createMethod - Create a new descriptor for the specified C++ method. - /// See comments in DISubprogram for descriptions of these fields. + /// See comments in MDSubprogram* for descriptions of these fields. /// @param Scope Function scope. /// @param Name Function name. /// @param LinkageName Mangled function name. @@ -587,17 +548,13 @@ namespace llvm { /// @param isOptimized True if optimization is ON. /// @param Fn llvm::Function pointer. /// @param TParam Function template parameters. - DISubprogram createMethod(DIDescriptor Scope, StringRef Name, - StringRef LinkageName, - DIFile File, unsigned LineNo, - DICompositeType Ty, bool isLocalToUnit, - bool isDefinition, - unsigned Virtuality = 0, unsigned VTableIndex = 0, - DIType VTableHolder = DIType(), - unsigned Flags = 0, - bool isOptimized = false, - Function *Fn = nullptr, - MDNode *TParam = nullptr); + MDSubprogram * + createMethod(MDScope *Scope, StringRef Name, StringRef LinkageName, + MDFile *File, unsigned LineNo, MDSubroutineType *Ty, + bool isLocalToUnit, bool isDefinition, unsigned Virtuality = 0, + unsigned VTableIndex = 0, MDType *VTableHolder = nullptr, + unsigned Flags = 0, bool isOptimized = false, + Function *Fn = nullptr, MDNode *TParam = nullptr); /// createNameSpace - This creates new descriptor for a namespace /// with the specified parent scope. @@ -605,9 +562,8 @@ namespace llvm { /// @param Name Name of this namespace /// @param File Source file /// @param LineNo Line number - DINameSpace createNameSpace(DIDescriptor Scope, StringRef Name, - DIFile File, unsigned LineNo); - + MDNamespace *createNameSpace(MDScope *Scope, StringRef Name, MDFile *File, + unsigned LineNo); /// createLexicalBlockFile - This creates a descriptor for a lexical /// block with a new file attached. This merely extends the existing @@ -615,8 +571,8 @@ namespace llvm { /// @param Scope Lexical block. /// @param File Source file. /// @param Discriminator DWARF path discriminator value. - DILexicalBlockFile createLexicalBlockFile(DIDescriptor Scope, DIFile File, - unsigned Discriminator = 0); + MDLexicalBlockFile *createLexicalBlockFile(MDScope *Scope, MDFile *File, + unsigned Discriminator = 0); /// createLexicalBlock - This creates a descriptor for a lexical block /// with the specified parent context. @@ -624,60 +580,63 @@ namespace llvm { /// @param File Source file. /// @param Line Line number. /// @param Col Column number. - DILexicalBlock createLexicalBlock(DIDescriptor Scope, DIFile File, - unsigned Line, unsigned Col); + MDLexicalBlock *createLexicalBlock(MDScope *Scope, MDFile *File, + unsigned Line, unsigned Col); /// \brief Create a descriptor for an imported module. /// @param Context The scope this module is imported into /// @param NS The namespace being imported here /// @param Line Line number - DIImportedEntity createImportedModule(DIScope Context, DINameSpace NS, - unsigned Line); + MDImportedEntity *createImportedModule(MDScope *Context, MDNamespace *NS, + unsigned Line); /// \brief Create a descriptor for an imported module. /// @param Context The scope this module is imported into /// @param NS An aliased namespace /// @param Line Line number - DIImportedEntity createImportedModule(DIScope Context, DIImportedEntity NS, - unsigned Line); + MDImportedEntity *createImportedModule(MDScope *Context, + MDImportedEntity *NS, unsigned Line); /// \brief Create a descriptor for an imported function. /// @param Context The scope this module is imported into /// @param Decl The declaration (or definition) of a function, type, or /// variable /// @param Line Line number - DIImportedEntity createImportedDeclaration(DIScope Context, DIDescriptor Decl, - unsigned Line, - StringRef Name = StringRef()); - DIImportedEntity createImportedDeclaration(DIScope Context, - DIImportedEntity NS, - unsigned Line, - StringRef Name = StringRef()); + MDImportedEntity *createImportedDeclaration(MDScope *Context, + DebugNode *Decl, unsigned Line, + StringRef Name = ""); /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable /// @param VarInfo Variable's debug info descriptor. /// @param Expr A complex location expression. + /// @param DL Debug info location. /// @param InsertAtEnd Location for the new intrinsic. - Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, - DIExpression Expr, BasicBlock *InsertAtEnd); + Instruction *insertDeclare(llvm::Value *Storage, MDLocalVariable *VarInfo, + MDExpression *Expr, const MDLocation *DL, + BasicBlock *InsertAtEnd); /// insertDeclare - Insert a new llvm.dbg.declare intrinsic call. /// @param Storage llvm::Value of the variable /// @param VarInfo Variable's debug info descriptor. /// @param Expr A complex location expression. + /// @param DL Debug info location. /// @param InsertBefore Location for the new intrinsic. - Instruction *insertDeclare(llvm::Value *Storage, DIVariable VarInfo, - DIExpression Expr, Instruction *InsertBefore); + Instruction *insertDeclare(llvm::Value *Storage, MDLocalVariable *VarInfo, + MDExpression *Expr, const MDLocation *DL, + Instruction *InsertBefore); /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. /// @param Val llvm::Value of the variable /// @param Offset Offset /// @param VarInfo Variable's debug info descriptor. /// @param Expr A complex location expression. + /// @param DL Debug info location. /// @param InsertAtEnd Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, - DIVariable VarInfo, DIExpression Expr, + MDLocalVariable *VarInfo, + MDExpression *Expr, + const MDLocation *DL, BasicBlock *InsertAtEnd); /// insertDbgValueIntrinsic - Insert a new llvm.dbg.value intrinsic call. @@ -685,24 +644,45 @@ namespace llvm { /// @param Offset Offset /// @param VarInfo Variable's debug info descriptor. /// @param Expr A complex location expression. + /// @param DL Debug info location. /// @param InsertBefore Location for the new intrinsic. Instruction *insertDbgValueIntrinsic(llvm::Value *Val, uint64_t Offset, - DIVariable VarInfo, DIExpression Expr, + MDLocalVariable *VarInfo, + MDExpression *Expr, + const MDLocation *DL, Instruction *InsertBefore); /// \brief Replace the vtable holder in the given composite type. /// /// If this creates a self reference, it may orphan some unresolved cycles /// in the operands of \c T, so \a DIBuilder needs to track that. - void replaceVTableHolder(DICompositeType &T, DICompositeType VTableHolder); + void replaceVTableHolder(MDCompositeType *&T, + MDCompositeType *VTableHolder); /// \brief Replace arrays on a composite type. /// /// If \c T is resolved, but the arrays aren't -- which can happen if \c T /// has a self-reference -- \a DIBuilder needs to track the array to /// resolve cycles. - void replaceArrays(DICompositeType &T, DIArray Elements, + void replaceArrays(MDCompositeType *&T, DIArray Elements, DIArray TParems = DIArray()); + + /// \brief Replace a temporary node. + /// + /// Call \a MDNode::replaceAllUsesWith() on \c N, replacing it with \c + /// Replacement. + /// + /// If \c Replacement is the same as \c N.get(), instead call \a + /// MDNode::replaceWithUniqued(). In this case, the uniqued node could + /// have a different address, so we return the final address. + template <class NodeTy> + NodeTy *replaceTemporary(TempMDNode &&N, NodeTy *Replacement) { + if (N.get() == Replacement) + return cast<NodeTy>(MDNode::replaceWithUniqued(std::move(N))); + + N->replaceAllUsesWith(Replacement); + return Replacement; + } }; } // end namespace llvm diff --git a/include/llvm/IR/DebugInfo.h b/include/llvm/IR/DebugInfo.h index 0163c05..18b0c72 100644 --- a/include/llvm/IR/DebugInfo.h +++ b/include/llvm/IR/DebugInfo.h @@ -58,1292 +58,365 @@ class DIObjCProperty; /// \brief Maps from type identifier to the actual MDNode. typedef DenseMap<const MDString *, MDNode *> DITypeIdentifierMap; -class DIHeaderFieldIterator - : public std::iterator<std::input_iterator_tag, StringRef, std::ptrdiff_t, - const StringRef *, StringRef> { - StringRef Header; - StringRef Current; +class DIDescriptor { + MDNode *N; public: - DIHeaderFieldIterator() {} - explicit DIHeaderFieldIterator(StringRef Header) - : Header(Header), Current(Header.slice(0, Header.find('\0'))) {} - StringRef operator*() const { return Current; } - const StringRef *operator->() const { return &Current; } - DIHeaderFieldIterator &operator++() { - increment(); - return *this; - } - DIHeaderFieldIterator operator++(int) { - DIHeaderFieldIterator X(*this); - increment(); - return X; - } - bool operator==(const DIHeaderFieldIterator &X) const { - return Current.data() == X.Current.data(); - } - bool operator!=(const DIHeaderFieldIterator &X) const { - return !(*this == X); - } + DIDescriptor(const MDNode *N = nullptr) : N(const_cast<MDNode *>(N)) {} - StringRef getHeader() const { return Header; } - StringRef getCurrent() const { return Current; } - StringRef getPrefix() const { - if (Current.begin() == Header.begin()) - return StringRef(); - return Header.slice(0, Current.begin() - Header.begin() - 1); - } - StringRef getSuffix() const { - if (Current.end() == Header.end()) - return StringRef(); - return Header.slice(Current.end() - Header.begin() + 1, StringRef::npos); - } - - /// \brief Get the current field as a number. - /// - /// Convert the current field into a number. Return \c 0 on error. - template <class T> T getNumber() const { - T Int; - if (getCurrent().getAsInteger(0, Int)) - return 0; - return Int; - } - -private: - void increment() { - assert(Current.data() != nullptr && "Cannot increment past the end"); - StringRef Suffix = getSuffix(); - Current = Suffix.slice(0, Suffix.find('\0')); - } + operator MDNode *() const { return N; } + MDNode *operator->() const { return N; } + MDNode &operator*() const { return *N; } }; -/// \brief A thin wraper around MDNode to access encoded debug info. -/// -/// This should not be stored in a container, because the underlying MDNode may -/// change in certain situations. -class DIDescriptor { - // Befriends DIRef so DIRef can befriend the protected member - // function: getFieldAs<DIRef>. - template <typename T> friend class DIRef; +#define DECLARE_SIMPLIFY_DESCRIPTOR(DESC) \ + class DESC; \ + template <> struct simplify_type<const DESC>; \ + template <> struct simplify_type<DESC>; +DECLARE_SIMPLIFY_DESCRIPTOR(DIDescriptor) +DECLARE_SIMPLIFY_DESCRIPTOR(DISubrange) +DECLARE_SIMPLIFY_DESCRIPTOR(DIEnumerator) +DECLARE_SIMPLIFY_DESCRIPTOR(DIScope) +DECLARE_SIMPLIFY_DESCRIPTOR(DIType) +DECLARE_SIMPLIFY_DESCRIPTOR(DIBasicType) +DECLARE_SIMPLIFY_DESCRIPTOR(DIDerivedType) +DECLARE_SIMPLIFY_DESCRIPTOR(DICompositeType) +DECLARE_SIMPLIFY_DESCRIPTOR(DISubroutineType) +DECLARE_SIMPLIFY_DESCRIPTOR(DIFile) +DECLARE_SIMPLIFY_DESCRIPTOR(DICompileUnit) +DECLARE_SIMPLIFY_DESCRIPTOR(DISubprogram) +DECLARE_SIMPLIFY_DESCRIPTOR(DILexicalBlock) +DECLARE_SIMPLIFY_DESCRIPTOR(DILexicalBlockFile) +DECLARE_SIMPLIFY_DESCRIPTOR(DINameSpace) +DECLARE_SIMPLIFY_DESCRIPTOR(DITemplateTypeParameter) +DECLARE_SIMPLIFY_DESCRIPTOR(DITemplateValueParameter) +DECLARE_SIMPLIFY_DESCRIPTOR(DIGlobalVariable) +DECLARE_SIMPLIFY_DESCRIPTOR(DIVariable) +DECLARE_SIMPLIFY_DESCRIPTOR(DIExpression) +DECLARE_SIMPLIFY_DESCRIPTOR(DILocation) +DECLARE_SIMPLIFY_DESCRIPTOR(DIObjCProperty) +DECLARE_SIMPLIFY_DESCRIPTOR(DIImportedEntity) +#undef DECLARE_SIMPLIFY_DESCRIPTOR + +typedef DebugNodeArray DIArray; +typedef MDTypeRefArray DITypeArray; +typedef DebugNodeRef DIDescriptorRef; +typedef MDScopeRef DIScopeRef; +typedef MDTypeRef DITypeRef; + +class DISubrange { + MDSubrange *N; public: - /// \brief Accessibility flags. - /// - /// The three accessibility flags are mutually exclusive and rolled together - /// in the first two bits. - enum { -#define HANDLE_DI_FLAG(ID, NAME) Flag##NAME = ID, -#include "llvm/IR/DebugInfoFlags.def" - FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic - }; - - static unsigned getFlag(StringRef Flag); - static const char *getFlagString(unsigned Flag); - - /// \brief Split up a flags bitfield. - /// - /// Split \c Flags into \c SplitFlags, a vector of its components. Returns - /// any remaining (unrecognized) bits. - static unsigned splitFlags(unsigned Flags, - SmallVectorImpl<unsigned> &SplitFlags); - -protected: - const MDNode *DbgNode; - - StringRef getStringField(unsigned Elt) const; - unsigned getUnsignedField(unsigned Elt) const { - return (unsigned)getUInt64Field(Elt); - } - uint64_t getUInt64Field(unsigned Elt) const; - int64_t getInt64Field(unsigned Elt) const; - DIDescriptor getDescriptorField(unsigned Elt) const; + DISubrange(const MDSubrange *N = nullptr) : N(const_cast<MDSubrange *>(N)) {} - template <typename DescTy> DescTy getFieldAs(unsigned Elt) const { - return DescTy(getDescriptorField(Elt)); - } + operator MDSubrange *() const { return N; } + MDSubrange *operator->() const { return N; } + MDSubrange &operator*() const { return *N; } +}; - GlobalVariable *getGlobalVariableField(unsigned Elt) const; - Constant *getConstantField(unsigned Elt) const; - Function *getFunctionField(unsigned Elt) const; +class DIEnumerator { + MDEnumerator *N; public: - explicit DIDescriptor(const MDNode *N = nullptr) : DbgNode(N) {} - - bool Verify() const; - - MDNode *get() const { return const_cast<MDNode *>(DbgNode); } - operator MDNode *() const { return get(); } - MDNode *operator->() const { return get(); } - MDNode &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - // An explicit operator bool so that we can do testing of DI values - // easily. - // FIXME: This operator bool isn't actually protecting anything at the - // moment due to the conversion operator above making DIDescriptor nodes - // implicitly convertable to bool. - explicit operator bool() const { return DbgNode != nullptr; } - - bool operator==(DIDescriptor Other) const { return DbgNode == Other.DbgNode; } - bool operator!=(DIDescriptor Other) const { return !operator==(Other); } - - StringRef getHeader() const { return getStringField(0); } - - size_t getNumHeaderFields() const { - return std::distance(DIHeaderFieldIterator(getHeader()), - DIHeaderFieldIterator()); - } - - DIHeaderFieldIterator header_begin() const { - return DIHeaderFieldIterator(getHeader()); - } - DIHeaderFieldIterator header_end() const { return DIHeaderFieldIterator(); } - - DIHeaderFieldIterator getHeaderIterator(unsigned Index) const { - // Since callers expect an empty string for out-of-range accesses, we can't - // use std::advance() here. - for (auto I = header_begin(), E = header_end(); I != E; ++I, --Index) - if (!Index) - return I; - return header_end(); - } - - StringRef getHeaderField(unsigned Index) const { - return *getHeaderIterator(Index); - } - - template <class T> T getHeaderFieldAs(unsigned Index) const { - return getHeaderIterator(Index).getNumber<T>(); - } - - uint16_t getTag() const { - if (auto *N = dyn_cast_or_null<DebugNode>(get())) - return N->getTag(); - return 0; - } + DIEnumerator(const MDEnumerator *N = nullptr) + : N(const_cast<MDEnumerator *>(N)) {} - bool isDerivedType() const { return get() && isa<MDDerivedTypeBase>(get()); } - bool isCompositeType() const { - return get() && isa<MDCompositeTypeBase>(get()); - } - bool isSubroutineType() const { - return get() && isa<MDSubroutineType>(get()); - } - bool isBasicType() const { return get() && isa<MDBasicType>(get()); } - bool isVariable() const { return get() && isa<MDLocalVariable>(get()); } - bool isSubprogram() const { return get() && isa<MDSubprogram>(get()); } - bool isGlobalVariable() const { - return get() && isa<MDGlobalVariable>(get()); - } - bool isScope() const { return get() && isa<MDScope>(get()); } - bool isFile() const { return get() && isa<MDFile>(get()); } - bool isCompileUnit() const { return get() && isa<MDCompileUnit>(get()); } - bool isNameSpace() const{ return get() && isa<MDNamespace>(get()); } - bool isLexicalBlockFile() const { - return get() && isa<MDLexicalBlockFile>(get()); - } - bool isLexicalBlock() const { - return get() && isa<MDLexicalBlockBase>(get()); - } - bool isSubrange() const { return get() && isa<MDSubrange>(get()); } - bool isEnumerator() const { return get() && isa<MDEnumerator>(get()); } - bool isType() const { return get() && isa<MDType>(get()); } - bool isTemplateTypeParameter() const { - return get() && isa<MDTemplateTypeParameter>(get()); - } - bool isTemplateValueParameter() const { - return get() && isa<MDTemplateValueParameter>(get()); - } - bool isObjCProperty() const { return get() && isa<MDObjCProperty>(get()); } - bool isImportedEntity() const { - return get() && isa<MDImportedEntity>(get()); - } - bool isExpression() const { return get() && isa<MDExpression>(get()); } - - void print(raw_ostream &OS) const; - void dump() const; - - /// \brief Replace all uses of debug info referenced by this descriptor. - void replaceAllUsesWith(LLVMContext &VMContext, DIDescriptor D); - void replaceAllUsesWith(MDNode *D); + operator MDEnumerator *() const { return N; } + MDEnumerator *operator->() const { return N; } + MDEnumerator &operator*() const { return *N; } }; -#define RETURN_FROM_RAW(VALID, UNUSED) \ - do { \ - auto *N = get(); \ - assert(N && "Expected non-null in accessor"); \ - return VALID; \ - } while (false) -#define RETURN_DESCRIPTOR_FROM_RAW(DESC, VALID) \ - do { \ - auto *N = get(); \ - assert(N && "Expected non-null in accessor"); \ - return DESC(dyn_cast_or_null<MDNode>(VALID)); \ - } while (false) -#define RETURN_REF_FROM_RAW(REF, VALID) \ - do { \ - auto *N = get(); \ - assert(N && "Expected non-null in accessor"); \ - return REF::get(VALID); \ - } while (false) - -/// \brief This is used to represent ranges, for array bounds. -class DISubrange : public DIDescriptor { -public: - explicit DISubrange(const MDNode *N = nullptr) : DIDescriptor(N) {} - DISubrange(const MDSubrange *N) : DIDescriptor(N) {} - - MDSubrange *get() const { - return cast_or_null<MDSubrange>(DIDescriptor::get()); - } - operator MDSubrange *() const { return get(); } - MDSubrange *operator->() const { return get(); } - MDSubrange &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - int64_t getLo() const { RETURN_FROM_RAW(N->getLo(), 0); } - int64_t getCount() const { RETURN_FROM_RAW(N->getCount(), 0); } - bool Verify() const; -}; +class DIScope { + MDScope *N; -/// \brief This descriptor holds an array of nodes with type T. -template <typename T> class DITypedArray : public DIDescriptor { public: - explicit DITypedArray(const MDNode *N = nullptr) : DIDescriptor(N) {} - unsigned getNumElements() const { - return DbgNode ? DbgNode->getNumOperands() : 0; - } - T getElement(unsigned Idx) const { return getFieldAs<T>(Idx); } + DIScope(const MDScope *N = nullptr) : N(const_cast<MDScope *>(N)) {} + + operator DIDescriptor() const { return N; } + operator MDScope *() const { return N; } + MDScope *operator->() const { return N; } + MDScope &operator*() const { return *N; } }; -typedef DITypedArray<DIDescriptor> DIArray; +class DIType { + MDType *N; -/// \brief A wrapper for an enumerator (e.g. X and Y in 'enum {X,Y}'). -/// -/// FIXME: it seems strange that this doesn't have either a reference to the -/// type/precision or a file/line pair for location info. -class DIEnumerator : public DIDescriptor { public: - explicit DIEnumerator(const MDNode *N = nullptr) : DIDescriptor(N) {} - DIEnumerator(const MDEnumerator *N) : DIDescriptor(N) {} - - MDEnumerator *get() const { - return cast_or_null<MDEnumerator>(DIDescriptor::get()); - } - operator MDEnumerator *() const { return get(); } - MDEnumerator *operator->() const { return get(); } - MDEnumerator &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } + DIType(const MDType *N = nullptr) : N(const_cast<MDType *>(N)) {} - StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } - int64_t getEnumValue() const { RETURN_FROM_RAW(N->getValue(), 0); } - bool Verify() const; + operator DIDescriptor() const { return N; } + operator DIScope() const { return N; } + operator MDType *() const { return N; } + MDType *operator->() const { return N; } + MDType &operator*() const { return *N; } }; -template <typename T> class DIRef; -typedef DIRef<DIDescriptor> DIDescriptorRef; -typedef DIRef<DIScope> DIScopeRef; -typedef DIRef<DIType> DITypeRef; -typedef DITypedArray<DITypeRef> DITypeArray; +class DIBasicType { + MDBasicType *N; -/// \brief A base class for various scopes. -/// -/// Although, implementation-wise, DIScope is the parent class of most -/// other DIxxx classes, including DIType and its descendants, most of -/// DIScope's descendants are not a substitutable subtype of -/// DIScope. The DIDescriptor::isScope() method only is true for -/// DIScopes that are scopes in the strict lexical scope sense -/// (DICompileUnit, DISubprogram, etc.), but not for, e.g., a DIType. -class DIScope : public DIDescriptor { public: - explicit DIScope(const MDNode *N = nullptr) : DIDescriptor(N) {} - DIScope(const MDScope *N) : DIDescriptor(N) {} - - MDScope *get() const { return cast_or_null<MDScope>(DIDescriptor::get()); } - operator MDScope *() const { return get(); } - MDScope *operator->() const { return get(); } - MDScope &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - /// \brief Get the parent scope. - /// - /// Gets the parent scope for this scope node or returns a default - /// constructed scope. - DIScopeRef getContext() const; - /// \brief Get the scope name. - /// - /// If the scope node has a name, return that, else return an empty string. - StringRef getName() const; - StringRef getFilename() const; - StringRef getDirectory() const; - - /// \brief Generate a reference to this DIScope. - /// - /// Uses the type identifier instead of the actual MDNode if possible, to - /// help type uniquing. - DIScopeRef getRef() const; + DIBasicType(const MDBasicType *N = nullptr) + : N(const_cast<MDBasicType *>(N)) {} + + operator DIDescriptor() const { return N; } + operator DIType() const { return N; } + operator MDBasicType *() const { return N; } + MDBasicType *operator->() const { return N; } + MDBasicType &operator*() const { return *N; } }; -/// \brief Represents reference to a DIDescriptor. -/// -/// Abstracts over direct and identifier-based metadata references. -template <typename T> class DIRef { - template <typename DescTy> - friend DescTy DIDescriptor::getFieldAs(unsigned Elt) const; - friend DIScopeRef DIScope::getContext() const; - friend DIScopeRef DIScope::getRef() const; - friend class DIType; - - /// \brief Val can be either a MDNode or a MDString. - /// - /// In the latter, MDString specifies the type identifier. - const Metadata *Val; - explicit DIRef(const Metadata *V); +class DIDerivedType { + MDDerivedTypeBase *N; public: - T resolve(const DITypeIdentifierMap &Map) const; - StringRef getName() const; - operator Metadata *() const { return const_cast<Metadata *>(Val); } - - static DIRef get(const Metadata *MD) { return DIRef(MD); } + DIDerivedType(const MDDerivedTypeBase *N = nullptr) + : N(const_cast<MDDerivedTypeBase *>(N)) {} + + operator DIDescriptor() const { return N; } + operator DIType() const { return N; } + operator MDDerivedTypeBase *() const { return N; } + MDDerivedTypeBase *operator->() const { return N; } + MDDerivedTypeBase &operator*() const { return *N; } }; -template <typename T> -T DIRef<T>::resolve(const DITypeIdentifierMap &Map) const { - if (!Val) - return T(); - - if (const MDNode *MD = dyn_cast<MDNode>(Val)) - return T(MD); - - const MDString *MS = cast<MDString>(Val); - // Find the corresponding MDNode. - DITypeIdentifierMap::const_iterator Iter = Map.find(MS); - assert(Iter != Map.end() && "Identifier not in the type map?"); - assert(DIDescriptor(Iter->second).isType() && - "MDNode in DITypeIdentifierMap should be a DIType."); - return T(Iter->second); -} - -template <typename T> StringRef DIRef<T>::getName() const { - if (!Val) - return StringRef(); - - if (const MDNode *MD = dyn_cast<MDNode>(Val)) - return T(MD).getName(); - - const MDString *MS = cast<MDString>(Val); - return MS->getString(); -} - -/// \brief Handle fields that are references to DIDescriptors. -template <> -DIDescriptorRef DIDescriptor::getFieldAs<DIDescriptorRef>(unsigned Elt) const; -/// \brief Specialize DIRef constructor for DIDescriptorRef. -template <> DIRef<DIDescriptor>::DIRef(const Metadata *V); - -/// \brief Handle fields that are references to DIScopes. -template <> DIScopeRef DIDescriptor::getFieldAs<DIScopeRef>(unsigned Elt) const; -/// \brief Specialize DIRef constructor for DIScopeRef. -template <> DIRef<DIScope>::DIRef(const Metadata *V); - -/// \brief Handle fields that are references to DITypes. -template <> DITypeRef DIDescriptor::getFieldAs<DITypeRef>(unsigned Elt) const; -/// \brief Specialize DIRef constructor for DITypeRef. -template <> DIRef<DIType>::DIRef(const Metadata *V); - -/// \brief This is a wrapper for a type. -/// -/// FIXME: Types should be factored much better so that CV qualifiers and -/// others do not require a huge and empty descriptor full of zeros. -class DIType : public DIScope { -public: - explicit DIType(const MDNode *N = nullptr) : DIScope(N) {} - DIType(const MDType *N) : DIScope(N) {} - - MDType *get() const { return cast_or_null<MDType>(DIDescriptor::get()); } - operator MDType *() const { return get(); } - MDType *operator->() const { return get(); } - MDType &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - operator DITypeRef() const { - assert(isType() && - "constructing DITypeRef from an MDNode that is not a type"); - return DITypeRef(&*getRef()); - } - - bool Verify() const; +class DICompositeType { + MDCompositeTypeBase *N; - DIScopeRef getContext() const { - RETURN_REF_FROM_RAW(DIScopeRef, N->getScope()); - } - StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } - unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } - uint64_t getSizeInBits() const { RETURN_FROM_RAW(N->getSizeInBits(), 0); } - uint64_t getAlignInBits() const { RETURN_FROM_RAW(N->getAlignInBits(), 0); } - // FIXME: Offset is only used for DW_TAG_member nodes. Making every type - // carry this is just plain insane. - uint64_t getOffsetInBits() const { RETURN_FROM_RAW(N->getOffsetInBits(), 0); } - unsigned getFlags() const { RETURN_FROM_RAW(N->getFlags(), 0); } - bool isPrivate() const { - return (getFlags() & FlagAccessibility) == FlagPrivate; - } - bool isProtected() const { - return (getFlags() & FlagAccessibility) == FlagProtected; - } - bool isPublic() const { - return (getFlags() & FlagAccessibility) == FlagPublic; - } - bool isForwardDecl() const { return (getFlags() & FlagFwdDecl) != 0; } - bool isAppleBlockExtension() const { - return (getFlags() & FlagAppleBlock) != 0; - } - bool isBlockByrefStruct() const { - return (getFlags() & FlagBlockByrefStruct) != 0; - } - bool isVirtual() const { return (getFlags() & FlagVirtual) != 0; } - bool isArtificial() const { return (getFlags() & FlagArtificial) != 0; } - bool isObjectPointer() const { return (getFlags() & FlagObjectPointer) != 0; } - bool isObjcClassComplete() const { - return (getFlags() & FlagObjcClassComplete) != 0; - } - bool isVector() const { return (getFlags() & FlagVector) != 0; } - bool isStaticMember() const { return (getFlags() & FlagStaticMember) != 0; } - bool isLValueReference() const { - return (getFlags() & FlagLValueReference) != 0; - } - bool isRValueReference() const { - return (getFlags() & FlagRValueReference) != 0; - } - bool isValid() const { return DbgNode && isType(); } -}; - -/// \brief A basic type, like 'int' or 'float'. -class DIBasicType : public DIType { public: - explicit DIBasicType(const MDNode *N = nullptr) : DIType(N) {} - DIBasicType(const MDBasicType *N) : DIType(N) {} - - MDBasicType *get() const { - return cast_or_null<MDBasicType>(DIDescriptor::get()); - } - operator MDBasicType *() const { return get(); } - MDBasicType *operator->() const { return get(); } - MDBasicType &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - unsigned getEncoding() const { RETURN_FROM_RAW(N->getEncoding(), 0); } - - bool Verify() const; + DICompositeType(const MDCompositeTypeBase *N = nullptr) + : N(const_cast<MDCompositeTypeBase *>(N)) {} + + operator DIDescriptor() const { return N; } + operator DIType() const { return N; } + operator MDCompositeTypeBase *() const { return N; } + MDCompositeTypeBase *operator->() const { return N; } + MDCompositeTypeBase &operator*() const { return *N; } }; -/// \brief A simple derived type -/// -/// Like a const qualified type, a typedef, a pointer or reference, et cetera. -/// Or, a data member of a class/struct/union. -class DIDerivedType : public DIType { -public: - explicit DIDerivedType(const MDNode *N = nullptr) : DIType(N) {} - DIDerivedType(const MDDerivedTypeBase *N) : DIType(N) {} - - MDDerivedTypeBase *get() const { - return cast_or_null<MDDerivedTypeBase>(DIDescriptor::get()); - } - operator MDDerivedTypeBase *() const { return get(); } - MDDerivedTypeBase *operator->() const { return get(); } - MDDerivedTypeBase &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - DITypeRef getTypeDerivedFrom() const { - RETURN_REF_FROM_RAW(DITypeRef, N->getBaseType()); - } - - /// \brief Return property node, if this ivar is associated with one. - MDNode *getObjCProperty() const { - if (auto *N = dyn_cast<MDDerivedType>(get())) - return dyn_cast_or_null<MDNode>(N->getExtraData()); - return nullptr; - } +class DISubroutineType { + MDSubroutineType *N; - DITypeRef getClassType() const { - assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); - if (auto *N = dyn_cast<MDDerivedType>(get())) - return DITypeRef::get(N->getExtraData()); - return DITypeRef::get(nullptr); - } - - Constant *getConstant() const { - assert((getTag() == dwarf::DW_TAG_member) && isStaticMember()); - if (auto *N = dyn_cast<MDDerivedType>(get())) - if (auto *C = dyn_cast_or_null<ConstantAsMetadata>(N->getExtraData())) - return C->getValue(); - - return nullptr; - } - - bool Verify() const; +public: + DISubroutineType(const MDSubroutineType *N = nullptr) + : N(const_cast<MDSubroutineType *>(N)) {} + + operator DIDescriptor() const { return N; } + operator DIType() const { return N; } + operator DICompositeType() const { return N; } + operator MDSubroutineType *() const { return N; } + MDSubroutineType *operator->() const { return N; } + MDSubroutineType &operator*() const { return *N; } }; -/// \brief Types that refer to multiple other types. -/// -/// This descriptor holds a type that can refer to multiple other types, like a -/// function or struct. -/// -/// DICompositeType is derived from DIDerivedType because some -/// composite types (such as enums) can be derived from basic types -// FIXME: Make this derive from DIType directly & just store the -// base type in a single DIType field. -class DICompositeType : public DIDerivedType { - friend class DIBuilder; - - /// \brief Set the array of member DITypes. - void setArraysHelper(MDNode *Elements, MDNode *TParams); +class DIFile { + MDFile *N; public: - explicit DICompositeType(const MDNode *N = nullptr) : DIDerivedType(N) {} - DICompositeType(const MDCompositeTypeBase *N) : DIDerivedType(N) {} + DIFile(const MDFile *N = nullptr) : N(const_cast<MDFile *>(N)) {} - MDCompositeTypeBase *get() const { - return cast_or_null<MDCompositeTypeBase>(DIDescriptor::get()); - } - operator MDCompositeTypeBase *() const { return get(); } - MDCompositeTypeBase *operator->() const { return get(); } - MDCompositeTypeBase &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - DIArray getElements() const { - assert(!isSubroutineType() && "no elements for DISubroutineType"); - RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getElements()); - } + operator DIDescriptor() const { return N; } + operator DIScope() const { return N; } + operator MDFile *() const { return N; } + MDFile *operator->() const { return N; } + MDFile &operator*() const { return *N; } +}; -private: - template <typename T> - void setArrays(DITypedArray<T> Elements, DIArray TParams = DIArray()) { - assert( - (!TParams || DbgNode->getNumOperands() == 8) && - "If you're setting the template parameters this should include a slot " - "for that!"); - setArraysHelper(Elements, TParams); - } +class DICompileUnit { + MDCompileUnit *N; public: - unsigned getRunTimeLang() const { RETURN_FROM_RAW(N->getRuntimeLang(), 0); } - DITypeRef getContainingType() const { - RETURN_REF_FROM_RAW(DITypeRef, N->getVTableHolder()); - } + DICompileUnit(const MDCompileUnit *N = nullptr) + : N(const_cast<MDCompileUnit *>(N)) {} + + operator DIDescriptor() const { return N; } + operator DIScope() const { return N; } + operator MDCompileUnit *() const { return N; } + MDCompileUnit *operator->() const { return N; } + MDCompileUnit &operator*() const { return *N; } +}; -private: - /// \brief Set the containing type. - void setContainingType(DICompositeType ContainingType); +class DISubprogram { + MDSubprogram *N; public: - DIArray getTemplateParams() const { - RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getTemplateParams()); - } - MDString *getIdentifier() const { - RETURN_FROM_RAW(N->getRawIdentifier(), nullptr); - } - - bool Verify() const; + DISubprogram(const MDSubprogram *N = nullptr) + : N(const_cast<MDSubprogram *>(N)) {} + + operator DIDescriptor() const { return N; } + operator DIScope() const { return N; } + operator MDSubprogram *() const { return N; } + MDSubprogram *operator->() const { return N; } + MDSubprogram &operator*() const { return *N; } }; -class DISubroutineType : public DICompositeType { -public: - explicit DISubroutineType(const MDNode *N = nullptr) : DICompositeType(N) {} - DISubroutineType(const MDSubroutineType *N) : DICompositeType(N) {} +class DILexicalBlock { + MDLexicalBlockBase *N; - MDSubroutineType *get() const { - return cast_or_null<MDSubroutineType>(DIDescriptor::get()); - } - operator MDSubroutineType *() const { return get(); } - MDSubroutineType *operator->() const { return get(); } - MDSubroutineType &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - DITypedArray<DITypeRef> getTypeArray() const { - RETURN_DESCRIPTOR_FROM_RAW(DITypedArray<DITypeRef>, N->getTypeArray()); - } -}; - -/// \brief This is a wrapper for a file. -class DIFile : public DIScope { public: - explicit DIFile(const MDNode *N = nullptr) : DIScope(N) {} - DIFile(const MDFile *N) : DIScope(N) {} - - MDFile *get() const { return cast_or_null<MDFile>(DIDescriptor::get()); } - operator MDFile *() const { return get(); } - MDFile *operator->() const { return get(); } - MDFile &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } + DILexicalBlock(const MDLexicalBlockBase *N = nullptr) + : N(const_cast<MDLexicalBlockBase *>(N)) {} - /// \brief Retrieve the MDNode for the directory/file pair. - MDNode *getFileNode() const { return get(); } - bool Verify() const; + operator DIDescriptor() const { return N; } + operator MDLexicalBlockBase *() const { return N; } + MDLexicalBlockBase *operator->() const { return N; } + MDLexicalBlockBase &operator*() const { return *N; } }; -/// \brief A wrapper for a compile unit. -class DICompileUnit : public DIScope { -public: - explicit DICompileUnit(const MDNode *N = nullptr) : DIScope(N) {} - DICompileUnit(const MDCompileUnit *N) : DIScope(N) {} - - MDCompileUnit *get() const { - return cast_or_null<MDCompileUnit>(DIDescriptor::get()); - } - operator MDCompileUnit *() const { return get(); } - MDCompileUnit *operator->() const { return get(); } - MDCompileUnit &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - dwarf::SourceLanguage getLanguage() const { - RETURN_FROM_RAW(static_cast<dwarf::SourceLanguage>(N->getSourceLanguage()), - static_cast<dwarf::SourceLanguage>(0)); - } - StringRef getProducer() const { RETURN_FROM_RAW(N->getProducer(), ""); } - bool isOptimized() const { RETURN_FROM_RAW(N->isOptimized(), false); } - StringRef getFlags() const { RETURN_FROM_RAW(N->getFlags(), ""); } - unsigned getRunTimeVersion() const { - RETURN_FROM_RAW(N->getRuntimeVersion(), 0); - } +class DILexicalBlockFile { + MDLexicalBlockFile *N; - DIArray getEnumTypes() const { - RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getEnumTypes()); - } - DIArray getRetainedTypes() const { - RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getRetainedTypes()); - } - DIArray getSubprograms() const { - RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getSubprograms()); - } - DIArray getGlobalVariables() const { - RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getGlobalVariables()); - } - DIArray getImportedEntities() const { - RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getImportedEntities()); - } - - void replaceSubprograms(DIArray Subprograms); - void replaceGlobalVariables(DIArray GlobalVariables); - - StringRef getSplitDebugFilename() const { - RETURN_FROM_RAW(N->getSplitDebugFilename(), ""); - } - unsigned getEmissionKind() const { RETURN_FROM_RAW(N->getEmissionKind(), 0); } - - bool Verify() const; -}; - -/// \brief This is a wrapper for a subprogram (e.g. a function). -class DISubprogram : public DIScope { public: - explicit DISubprogram(const MDNode *N = nullptr) : DIScope(N) {} - DISubprogram(const MDSubprogram *N) : DIScope(N) {} - - MDSubprogram *get() const { - return cast_or_null<MDSubprogram>(DIDescriptor::get()); - } - operator MDSubprogram *() const { return get(); } - MDSubprogram *operator->() const { return get(); } - MDSubprogram &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } - StringRef getDisplayName() const { RETURN_FROM_RAW(N->getDisplayName(), ""); } - StringRef getLinkageName() const { RETURN_FROM_RAW(N->getLinkageName(), ""); } - unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } - - /// \brief Check if this is local (like 'static' in C). - unsigned isLocalToUnit() const { RETURN_FROM_RAW(N->isLocalToUnit(), 0); } - unsigned isDefinition() const { RETURN_FROM_RAW(N->isDefinition(), 0); } - - unsigned getVirtuality() const { RETURN_FROM_RAW(N->getVirtuality(), 0); } - unsigned getVirtualIndex() const { RETURN_FROM_RAW(N->getVirtualIndex(), 0); } - - unsigned getFlags() const { RETURN_FROM_RAW(N->getFlags(), 0); } - - unsigned isOptimized() const { RETURN_FROM_RAW(N->isOptimized(), 0); } - - /// \brief Get the beginning of the scope of the function (not the name). - unsigned getScopeLineNumber() const { RETURN_FROM_RAW(N->getScopeLine(), 0); } - - DIScopeRef getContext() const { - RETURN_REF_FROM_RAW(DIScopeRef, N->getScope()); - } - DISubroutineType getType() const { - RETURN_DESCRIPTOR_FROM_RAW(DISubroutineType, N->getType()); - } - - DITypeRef getContainingType() const { - RETURN_REF_FROM_RAW(DITypeRef, N->getContainingType()); - } - - bool Verify() const; - - /// \brief Check if this provides debugging information for the function F. - bool describes(const Function *F); - - Function *getFunction() const; - - void replaceFunction(Function *F) { - if (auto *N = get()) - N->replaceFunction(F); - } - DIArray getTemplateParams() const { - RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getTemplateParams()); - } - DISubprogram getFunctionDeclaration() const { - RETURN_DESCRIPTOR_FROM_RAW(DISubprogram, N->getDeclaration()); - } - MDNode *getVariablesNodes() const { return getVariables(); } - DIArray getVariables() const { - RETURN_DESCRIPTOR_FROM_RAW(DIArray, N->getVariables()); - } - - unsigned isArtificial() const { return (getFlags() & FlagArtificial) != 0; } - /// \brief Check for the "private" access specifier. - bool isPrivate() const { - return (getFlags() & FlagAccessibility) == FlagPrivate; - } - /// \brief Check for the "protected" access specifier. - bool isProtected() const { - return (getFlags() & FlagAccessibility) == FlagProtected; - } - /// \brief Check for the "public" access specifier. - bool isPublic() const { - return (getFlags() & FlagAccessibility) == FlagPublic; - } - /// \brief Check for "explicit". - bool isExplicit() const { return (getFlags() & FlagExplicit) != 0; } - /// \brief Check if this is prototyped. - bool isPrototyped() const { return (getFlags() & FlagPrototyped) != 0; } - - /// \brief Check if this is reference-qualified. - /// - /// Return true if this subprogram is a C++11 reference-qualified non-static - /// member function (void foo() &). - unsigned isLValueReference() const { - return (getFlags() & FlagLValueReference) != 0; - } + DILexicalBlockFile(const MDLexicalBlockFile *N = nullptr) + : N(const_cast<MDLexicalBlockFile *>(N)) {} - /// \brief Check if this is rvalue-reference-qualified. - /// - /// Return true if this subprogram is a C++11 rvalue-reference-qualified - /// non-static member function (void foo() &&). - unsigned isRValueReference() const { - return (getFlags() & FlagRValueReference) != 0; - } + operator DIDescriptor() const { return N; } + operator MDLexicalBlockFile *() const { return N; } + MDLexicalBlockFile *operator->() const { return N; } + MDLexicalBlockFile &operator*() const { return *N; } }; -/// \brief This is a wrapper for a lexical block. -class DILexicalBlock : public DIScope { -public: - explicit DILexicalBlock(const MDNode *N = nullptr) : DIScope(N) {} - DILexicalBlock(const MDLexicalBlock *N) : DIScope(N) {} +class DINameSpace { + MDNamespace *N; - MDLexicalBlockBase *get() const { - return cast_or_null<MDLexicalBlockBase>(DIDescriptor::get()); - } - operator MDLexicalBlockBase *() const { return get(); } - MDLexicalBlockBase *operator->() const { return get(); } - MDLexicalBlockBase &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - DIScope getContext() const { - RETURN_DESCRIPTOR_FROM_RAW(DIScope, N->getScope()); - } - unsigned getLineNumber() const { - if (auto *N = dyn_cast<MDLexicalBlock>(get())) - return N->getLine(); - return 0; - } - unsigned getColumnNumber() const { - if (auto *N = dyn_cast<MDLexicalBlock>(get())) - return N->getColumn(); - return 0; - } - bool Verify() const; -}; - -/// \brief This is a wrapper for a lexical block with a filename change. -class DILexicalBlockFile : public DIScope { public: - explicit DILexicalBlockFile(const MDNode *N = nullptr) : DIScope(N) {} - DILexicalBlockFile(const MDLexicalBlockFile *N) : DIScope(N) {} - - MDLexicalBlockFile *get() const { - return cast_or_null<MDLexicalBlockFile>(DIDescriptor::get()); - } - operator MDLexicalBlockFile *() const { return get(); } - MDLexicalBlockFile *operator->() const { return get(); } - MDLexicalBlockFile &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - DIScope getContext() const { - // FIXME: This logic is horrible. getScope() returns a DILexicalBlock, but - // then we check if it's a subprogram? WHAT?!? - if (getScope().isSubprogram()) - return getScope(); - return getScope().getContext(); - } - unsigned getLineNumber() const { return getScope().getLineNumber(); } - unsigned getColumnNumber() const { return getScope().getColumnNumber(); } - DILexicalBlock getScope() const { - RETURN_DESCRIPTOR_FROM_RAW(DILexicalBlock, N->getScope()); - } - unsigned getDiscriminator() const { - RETURN_FROM_RAW(N->getDiscriminator(), 0); - } - bool Verify() const; + DINameSpace(const MDNamespace *N = nullptr) + : N(const_cast<MDNamespace *>(N)) {} + + operator DIDescriptor() const { return N; } + operator DIScope() const { return N; } + operator MDNamespace *() const { return N; } + MDNamespace *operator->() const { return N; } + MDNamespace &operator*() const { return *N; } }; -/// \brief A wrapper for a C++ style name space. -class DINameSpace : public DIScope { -public: - explicit DINameSpace(const MDNode *N = nullptr) : DIScope(N) {} - DINameSpace(const MDNamespace *N) : DIScope(N) {} - - MDNamespace *get() const { - return cast_or_null<MDNamespace>(DIDescriptor::get()); - } - operator MDNamespace *() const { return get(); } - MDNamespace *operator->() const { return get(); } - MDNamespace &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } - unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } - DIScope getContext() const { - RETURN_DESCRIPTOR_FROM_RAW(DIScope, N->getScope()); - } - bool Verify() const; -}; +class DITemplateTypeParameter { + MDTemplateTypeParameter *N; -/// \brief This is a wrapper for template type parameter. -class DITemplateTypeParameter : public DIDescriptor { public: - explicit DITemplateTypeParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} - DITemplateTypeParameter(const MDTemplateTypeParameter *N) : DIDescriptor(N) {} + DITemplateTypeParameter(const MDTemplateTypeParameter *N = nullptr) + : N(const_cast<MDTemplateTypeParameter *>(N)) {} - MDTemplateTypeParameter *get() const { - return cast_or_null<MDTemplateTypeParameter>(DIDescriptor::get()); - } - operator MDTemplateTypeParameter *() const { return get(); } - MDTemplateTypeParameter *operator->() const { return get(); } - MDTemplateTypeParameter &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } - - DITypeRef getType() const { RETURN_REF_FROM_RAW(DITypeRef, N->getType()); } - bool Verify() const; + operator MDTemplateTypeParameter *() const { return N; } + MDTemplateTypeParameter *operator->() const { return N; } + MDTemplateTypeParameter &operator*() const { return *N; } }; -/// \brief This is a wrapper for template value parameter. -class DITemplateValueParameter : public DIDescriptor { -public: - explicit DITemplateValueParameter(const MDNode *N = nullptr) - : DIDescriptor(N) {} - DITemplateValueParameter(const MDTemplateValueParameter *N) - : DIDescriptor(N) {} +class DITemplateValueParameter { + MDTemplateValueParameter *N; - MDTemplateValueParameter *get() const { - return cast_or_null<MDTemplateValueParameter>(DIDescriptor::get()); - } - operator MDTemplateValueParameter *() const { return get(); } - MDTemplateValueParameter *operator->() const { return get(); } - MDTemplateValueParameter &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } +public: + DITemplateValueParameter(const MDTemplateValueParameter *N = nullptr) + : N(const_cast<MDTemplateValueParameter *>(N)) {} - StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } - DITypeRef getType() const { RETURN_REF_FROM_RAW(DITypeRef, N->getType()); } - Metadata *getValue() const { RETURN_FROM_RAW(N->getValue(), nullptr); } - bool Verify() const; + operator MDTemplateValueParameter *() const { return N; } + MDTemplateValueParameter *operator->() const { return N; } + MDTemplateValueParameter &operator*() const { return *N; } }; -/// \brief This is a wrapper for a global variable. -class DIGlobalVariable : public DIDescriptor { - DIFile getFile() const { RETURN_DESCRIPTOR_FROM_RAW(DIFile, N->getFile()); } +class DIGlobalVariable { + MDGlobalVariable *N; public: - explicit DIGlobalVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} - DIGlobalVariable(const MDGlobalVariable *N) : DIDescriptor(N) {} + DIGlobalVariable(const MDGlobalVariable *N = nullptr) + : N(const_cast<MDGlobalVariable *>(N)) {} - MDGlobalVariable *get() const { - return cast_or_null<MDGlobalVariable>(DIDescriptor::get()); - } - operator MDGlobalVariable *() const { return get(); } - MDGlobalVariable *operator->() const { return get(); } - MDGlobalVariable &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } - StringRef getDisplayName() const { RETURN_FROM_RAW(N->getDisplayName(), ""); } - StringRef getLinkageName() const { RETURN_FROM_RAW(N->getLinkageName(), ""); } - unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } - unsigned isLocalToUnit() const { RETURN_FROM_RAW(N->isLocalToUnit(), 0); } - unsigned isDefinition() const { RETURN_FROM_RAW(N->isDefinition(), 0); } - - DIScope getContext() const { - RETURN_DESCRIPTOR_FROM_RAW(DIScope, N->getScope()); - } - StringRef getFilename() const { return getFile().getFilename(); } - StringRef getDirectory() const { return getFile().getDirectory(); } - DITypeRef getType() const { RETURN_REF_FROM_RAW(DITypeRef, N->getType()); } - - GlobalVariable *getGlobal() const; - Constant *getConstant() const { - if (auto *N = get()) - if (auto *C = dyn_cast_or_null<ConstantAsMetadata>(N->getVariable())) - return C->getValue(); - return nullptr; - } - DIDerivedType getStaticDataMemberDeclaration() const { - RETURN_DESCRIPTOR_FROM_RAW(DIDerivedType, - N->getStaticDataMemberDeclaration()); - } - - bool Verify() const; + operator DIDescriptor() const { return N; } + operator MDGlobalVariable *() const { return N; } + MDGlobalVariable *operator->() const { return N; } + MDGlobalVariable &operator*() const { return *N; } }; -/// \brief This is a wrapper for a variable (e.g. parameter, local, global etc). -class DIVariable : public DIDescriptor { - unsigned getFlags() const { RETURN_FROM_RAW(N->getFlags(), 0); } +class DIVariable { + MDLocalVariable *N; public: - explicit DIVariable(const MDNode *N = nullptr) : DIDescriptor(N) {} - DIVariable(const MDLocalVariable *N) : DIDescriptor(N) {} + DIVariable(const MDLocalVariable *N = nullptr) + : N(const_cast<MDLocalVariable *>(N)) {} - MDLocalVariable *get() const { - return cast_or_null<MDLocalVariable>(DIDescriptor::get()); - } - operator MDLocalVariable *() const { return get(); } - MDLocalVariable *operator->() const { return get(); } - MDLocalVariable &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } - unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } - unsigned getArgNumber() const { RETURN_FROM_RAW(N->getArg(), 0); } - - DIScope getContext() const { - RETURN_DESCRIPTOR_FROM_RAW(DIScope, N->getScope()); - } - DIFile getFile() const { RETURN_DESCRIPTOR_FROM_RAW(DIFile, N->getFile()); } - DITypeRef getType() const { RETURN_REF_FROM_RAW(DITypeRef, N->getType()); } - - /// \brief Return true if this variable is marked as "artificial". - bool isArtificial() const { - return (getFlags() & FlagArtificial) != 0; - } - - bool isObjectPointer() const { - return (getFlags() & FlagObjectPointer) != 0; - } - - /// \brief If this variable is inlined then return inline location. - MDNode *getInlinedAt() const { - RETURN_DESCRIPTOR_FROM_RAW(DIDescriptor, N->getInlinedAt()); - } - - bool Verify() const; - - /// \brief Check if this is a "__block" variable (Apple Blocks). - bool isBlockByrefVariable(const DITypeIdentifierMap &Map) const { - return (getType().resolve(Map)).isBlockByrefStruct(); - } - - /// \brief Check if this is an inlined function argument. - bool isInlinedFnArgument(const Function *CurFn); - - /// \brief Return the size reported by the variable's type. - unsigned getSizeInBits(const DITypeIdentifierMap &Map); - - void printExtendedName(raw_ostream &OS) const; + operator MDLocalVariable *() const { return N; } + MDLocalVariable *operator->() const { return N; } + MDLocalVariable &operator*() const { return *N; } }; -/// \brief A complex location expression in postfix notation. -/// -/// This is (almost) a DWARF expression that modifies the location of a -/// variable or (or the location of a single piece of a variable). -/// -/// FIXME: Instead of DW_OP_plus taking an argument, this should use DW_OP_const -/// and have DW_OP_plus consume the topmost elements on the stack. -class DIExpression : public DIDescriptor { -public: - explicit DIExpression(const MDNode *N = nullptr) : DIDescriptor(N) {} - DIExpression(const MDExpression *N) : DIDescriptor(N) {} - - MDExpression *get() const { - return cast_or_null<MDExpression>(DIDescriptor::get()); - } - operator MDExpression *() const { return get(); } - MDExpression *operator->() const { return get(); } - MDExpression &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - // Don't call this. Call isValid() directly. - bool Verify() const = delete; - - /// \brief Return the number of elements in the complex expression. - unsigned getNumElements() const { return get()->getNumElements(); } - - /// \brief return the Idx'th complex address element. - uint64_t getElement(unsigned I) const { return get()->getElement(I); } - - /// \brief Return whether this is a piece of an aggregate variable. - bool isBitPiece() const; - /// \brief Return the offset of this piece in bits. - uint64_t getBitPieceOffset() const; - /// \brief Return the size of this piece in bits. - uint64_t getBitPieceSize() const; - - class iterator; - /// \brief A lightweight wrapper around an element of a DIExpression. - class Operand { - friend class iterator; - MDExpression::element_iterator I; - Operand() {} - Operand(MDExpression::element_iterator I) : I(I) {} - public: - /// \brief Operands such as DW_OP_piece have explicit (non-stack) arguments. - /// Argument 0 is the operand itself. - uint64_t getArg(unsigned N) const { - MDExpression::element_iterator In = I; - std::advance(In, N); - return *In; - } - operator uint64_t () const { return *I; } - /// \brief Returns underlying MDExpression::element_iterator. - const MDExpression::element_iterator &getBase() const { return I; } - /// \brief Returns the next operand. - iterator getNext() const; - }; - - /// \brief An iterator for DIExpression elements. - class iterator : public std::iterator<std::input_iterator_tag, StringRef, - unsigned, const Operand*, Operand> { - friend class Operand; - MDExpression::element_iterator I; - Operand Tmp; - - public: - iterator(MDExpression::element_iterator I) : I(I) {} - const Operand &operator*() { return Tmp = Operand(I); } - const Operand *operator->() { return &(Tmp = Operand(I)); } - iterator &operator++() { - increment(); - return *this; - } - iterator operator++(int) { - iterator X(*this); - increment(); - return X; - } - bool operator==(const iterator &X) const { return I == X.I; } - bool operator!=(const iterator &X) const { return !(*this == X); } - - private: - void increment() { - switch (**this) { - case dwarf::DW_OP_bit_piece: std::advance(I, 3); break; - case dwarf::DW_OP_plus: std::advance(I, 2); break; - case dwarf::DW_OP_deref: std::advance(I, 1); break; - default: - llvm_unreachable("unsupported operand"); - } - } - }; - - iterator begin() const { return get()->elements_begin(); } - iterator end() const { return get()->elements_end(); } -}; +class DIExpression { + MDExpression *N; -/// \brief This object holds location information. -/// -/// This object is not associated with any DWARF tag. -class DILocation : public DIDescriptor { public: - explicit DILocation(const MDNode *N) : DIDescriptor(N) {} - - MDLocation *get() const { - return cast_or_null<MDLocation>(DIDescriptor::get()); - } - operator MDLocation *() const { return get(); } - MDLocation *operator->() const { return get(); } - MDLocation &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } - - unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } - unsigned getColumnNumber() const { RETURN_FROM_RAW(N->getColumn(), 0); } - DIScope getScope() const { - RETURN_DESCRIPTOR_FROM_RAW(DIScope, N->getScope()); - } - DILocation getOrigLocation() const { - RETURN_DESCRIPTOR_FROM_RAW(DILocation, N->getInlinedAt()); - } - StringRef getFilename() const { return getScope().getFilename(); } - StringRef getDirectory() const { return getScope().getDirectory(); } - bool Verify() const; - bool atSameLineAs(const DILocation &Other) const { - return (getLineNumber() == Other.getLineNumber() && - getFilename() == Other.getFilename()); - } - /// \brief Get the DWAF discriminator. - /// - /// DWARF discriminators are used to distinguish identical file locations for - /// instructions that are on different basic blocks. If two instructions are - /// inside the same lexical block and are in different basic blocks, we - /// create a new lexical block with identical location as the original but - /// with a different discriminator value - /// (lib/Transforms/Util/AddDiscriminators.cpp for details). - unsigned getDiscriminator() const { - // Since discriminators are associated with lexical blocks, make - // sure this location is a lexical block before retrieving its - // value. - return getScope().isLexicalBlockFile() - ? DILexicalBlockFile( - cast<MDNode>(cast<MDLocation>(DbgNode)->getScope())) - .getDiscriminator() - : 0; - } + DIExpression(const MDExpression *N = nullptr) + : N(const_cast<MDExpression *>(N)) {} - /// \brief Generate a new discriminator value for this location. - unsigned computeNewDiscriminator(LLVMContext &Ctx); - - /// \brief Return a copy of this location with a different scope. - DILocation copyWithNewScope(LLVMContext &Ctx, DILexicalBlockFile NewScope); + operator MDExpression *() const { return N; } + MDExpression *operator->() const { return N; } + MDExpression &operator*() const { return *N; } }; -class DIObjCProperty : public DIDescriptor { +class DILocation { + MDLocation *N; + public: - explicit DIObjCProperty(const MDNode *N) : DIDescriptor(N) {} - DIObjCProperty(const MDObjCProperty *N) : DIDescriptor(N) {} + DILocation(const MDLocation *N = nullptr) : N(const_cast<MDLocation *>(N)) {} - MDObjCProperty *get() const { - return cast_or_null<MDObjCProperty>(DIDescriptor::get()); - } - operator MDObjCProperty *() const { return get(); } - MDObjCProperty *operator->() const { return get(); } - MDObjCProperty &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } + operator MDLocation *() const { return N; } + MDLocation *operator->() const { return N; } + MDLocation &operator*() const { return *N; } +}; - StringRef getObjCPropertyName() const { RETURN_FROM_RAW(N->getName(), ""); } - DIFile getFile() const { RETURN_DESCRIPTOR_FROM_RAW(DIFile, N->getFile()); } - unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } +class DIObjCProperty { + MDObjCProperty *N; - StringRef getObjCPropertyGetterName() const { - RETURN_FROM_RAW(N->getGetterName(), ""); - } - StringRef getObjCPropertySetterName() const { - RETURN_FROM_RAW(N->getSetterName(), ""); - } - unsigned getAttributes() const { RETURN_FROM_RAW(N->getAttributes(), 0); } - bool isReadOnlyObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readonly) != 0; - } - bool isReadWriteObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_readwrite) != 0; - } - bool isAssignObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_assign) != 0; - } - bool isRetainObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_retain) != 0; - } - bool isCopyObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_copy) != 0; - } - bool isNonAtomicObjCProperty() const { - return (getAttributes() & dwarf::DW_APPLE_PROPERTY_nonatomic) != 0; - } - - /// \brief Get the type. - /// - /// \note Objective-C doesn't have an ODR, so there is no benefit in storing - /// the type as a DITypeRef here. - DIType getType() const { RETURN_DESCRIPTOR_FROM_RAW(DIType, N->getType()); } +public: + DIObjCProperty(const MDObjCProperty *N = nullptr) + : N(const_cast<MDObjCProperty *>(N)) {} - bool Verify() const; + operator MDObjCProperty *() const { return N; } + MDObjCProperty *operator->() const { return N; } + MDObjCProperty &operator*() const { return *N; } }; -/// \brief An imported module (C++ using directive or similar). -class DIImportedEntity : public DIDescriptor { -public: - DIImportedEntity() = default; - explicit DIImportedEntity(const MDNode *N) : DIDescriptor(N) {} - DIImportedEntity(const MDImportedEntity *N) : DIDescriptor(N) {} +class DIImportedEntity { + MDImportedEntity *N; - MDImportedEntity *get() const { - return cast_or_null<MDImportedEntity>(DIDescriptor::get()); - } - operator MDImportedEntity *() const { return get(); } - MDImportedEntity *operator->() const { return get(); } - MDImportedEntity &operator*() const { - assert(get() && "Expected valid pointer"); - return *get(); - } +public: + DIImportedEntity(const MDImportedEntity *N = nullptr) + : N(const_cast<MDImportedEntity *>(N)) {} - DIScope getContext() const { - RETURN_DESCRIPTOR_FROM_RAW(DIScope, N->getScope()); - } - DIDescriptorRef getEntity() const { - RETURN_REF_FROM_RAW(DIDescriptorRef, N->getEntity()); - } - unsigned getLineNumber() const { RETURN_FROM_RAW(N->getLine(), 0); } - StringRef getName() const { RETURN_FROM_RAW(N->getName(), ""); } - bool Verify() const; + operator DIDescriptor() const { return N; } + operator MDImportedEntity *() const { return N; } + MDImportedEntity *operator->() const { return N; } + MDImportedEntity &operator*() const { return *N; } }; -#undef RETURN_FROM_RAW -#undef RETURN_DESCRIPTOR_FROM_RAW -#undef RETURN_REF_FROM_RAW +#define SIMPLIFY_DESCRIPTOR(DESC) \ + template <> struct simplify_type<const DESC> { \ + typedef Metadata *SimpleType; \ + static SimpleType getSimplifiedValue(const DESC &DI) { return DI; } \ + }; \ + template <> struct simplify_type<DESC> : simplify_type<const DESC> {}; +SIMPLIFY_DESCRIPTOR(DIDescriptor) +SIMPLIFY_DESCRIPTOR(DISubrange) +SIMPLIFY_DESCRIPTOR(DIEnumerator) +SIMPLIFY_DESCRIPTOR(DIScope) +SIMPLIFY_DESCRIPTOR(DIType) +SIMPLIFY_DESCRIPTOR(DIBasicType) +SIMPLIFY_DESCRIPTOR(DIDerivedType) +SIMPLIFY_DESCRIPTOR(DICompositeType) +SIMPLIFY_DESCRIPTOR(DISubroutineType) +SIMPLIFY_DESCRIPTOR(DIFile) +SIMPLIFY_DESCRIPTOR(DICompileUnit) +SIMPLIFY_DESCRIPTOR(DISubprogram) +SIMPLIFY_DESCRIPTOR(DILexicalBlock) +SIMPLIFY_DESCRIPTOR(DILexicalBlockFile) +SIMPLIFY_DESCRIPTOR(DINameSpace) +SIMPLIFY_DESCRIPTOR(DITemplateTypeParameter) +SIMPLIFY_DESCRIPTOR(DITemplateValueParameter) +SIMPLIFY_DESCRIPTOR(DIGlobalVariable) +SIMPLIFY_DESCRIPTOR(DIVariable) +SIMPLIFY_DESCRIPTOR(DIExpression) +SIMPLIFY_DESCRIPTOR(DILocation) +SIMPLIFY_DESCRIPTOR(DIObjCProperty) +SIMPLIFY_DESCRIPTOR(DIImportedEntity) +#undef SIMPLIFY_DESCRIPTOR /// \brief Find subprogram that is enclosing this scope. DISubprogram getDISubprogram(const MDNode *Scope); @@ -1356,16 +429,6 @@ DISubprogram getDISubprogram(const Function *F); /// \brief Find underlying composite type. DICompositeType getDICompositeType(DIType T); -/// \brief Create a new inlined variable based on current variable. -/// -/// @param DV Current Variable. -/// @param InlinedScope Location at current variable is inlined. -DIVariable createInlinedVariable(MDNode *DV, MDNode *InlinedScope, - LLVMContext &VMContext); - -/// \brief Remove inlined scope from the variable. -DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext); - /// \brief Generate map by visiting all retained types. DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes); @@ -1375,6 +438,7 @@ DITypeIdentifierMap generateDITypeIdentifierMap(const NamedMDNode *CU_Nodes); /// metadata for debugging. We also remove debug locations for instructions. /// Return true if module is modified. bool StripDebugInfo(Module &M); +bool stripDebugInfo(Function &F); /// \brief Return Debug Info Metadata Version by checking module flags. unsigned getDebugMetadataVersionFromModule(const Module &M); diff --git a/include/llvm/IR/DebugInfoMetadata.h b/include/llvm/IR/DebugInfoMetadata.h index d7563fc..62373c4 100644 --- a/include/llvm/IR/DebugInfoMetadata.h +++ b/include/llvm/IR/DebugInfoMetadata.h @@ -41,6 +41,101 @@ namespace llvm { +/// \brief Pointer union between a subclass of DebugNode and MDString. +/// +/// \a MDCompositeType can be referenced via an \a MDString unique identifier. +/// This class allows some type safety in the face of that, requiring either a +/// node of a particular type or an \a MDString. +template <class T> class TypedDebugNodeRef { + const Metadata *MD = nullptr; + +public: + TypedDebugNodeRef() = default; + TypedDebugNodeRef(std::nullptr_t) {} + + /// \brief Construct from a raw pointer. + explicit TypedDebugNodeRef(const Metadata *MD) : MD(MD) { + assert((!MD || isa<MDString>(MD) || isa<T>(MD)) && "Expected valid ref"); + } + + template <class U> + TypedDebugNodeRef( + const TypedDebugNodeRef<U> &X, + typename std::enable_if<std::is_convertible<U *, T *>::value>::type * = + nullptr) + : MD(X) {} + + operator Metadata *() const { return const_cast<Metadata *>(MD); } + + bool operator==(const TypedDebugNodeRef<T> &X) const { return MD == X.MD; }; + bool operator!=(const TypedDebugNodeRef<T> &X) const { return MD != X.MD; }; + + /// \brief Create a reference. + /// + /// Get a reference to \c N, using an \a MDString reference if available. + static TypedDebugNodeRef get(const T *N); + + template <class MapTy> T *resolve(const MapTy &Map) const { + if (!MD) + return nullptr; + + if (auto *Typed = dyn_cast<T>(MD)) + return const_cast<T *>(Typed); + + auto *S = cast<MDString>(MD); + auto I = Map.find(S); + assert(I != Map.end() && "Missing identifier in type map"); + return cast<T>(I->second); + } +}; + +typedef TypedDebugNodeRef<DebugNode> DebugNodeRef; +typedef TypedDebugNodeRef<MDScope> MDScopeRef; +typedef TypedDebugNodeRef<MDType> MDTypeRef; + +class MDTypeRefArray { + const MDTuple *N = nullptr; + +public: + MDTypeRefArray(const MDTuple *N) : N(N) {} + + explicit operator bool() const { return get(); } + explicit operator MDTuple *() const { return get(); } + + MDTuple *get() const { return const_cast<MDTuple *>(N); } + MDTuple *operator->() const { return get(); } + MDTuple &operator*() const { return *get(); } + + // FIXME: Fix callers and remove condition on N. + unsigned size() const { return N ? N->getNumOperands() : 0u; } + MDTypeRef operator[](unsigned I) const { return MDTypeRef(N->getOperand(I)); } + + class iterator : std::iterator<std::input_iterator_tag, MDTypeRef, + std::ptrdiff_t, void, MDTypeRef> { + MDNode::op_iterator I = nullptr; + + public: + iterator() = default; + explicit iterator(MDNode::op_iterator I) : I(I) {} + MDTypeRef operator*() const { return MDTypeRef(*I); } + iterator &operator++() { + ++I; + return *this; + } + iterator operator++(int) { + iterator Temp(*this); + ++I; + return Temp; + } + bool operator==(const iterator &X) const { return I == X.I; } + bool operator!=(const iterator &X) const { return I != X.I; } + }; + + // FIXME: Fix callers and remove condition on N. + iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); } + iterator end() const { return N ? iterator(N->op_end()) : iterator(); } +}; + /// \brief Tagged DWARF-like metadata node. /// /// A metadata node with a DWARF tag (i.e., a constant named \c DW_TAG_*, @@ -57,7 +152,7 @@ protected: assert(Tag < 1u << 16); SubclassData16 = Tag; } - ~DebugNode() {} + ~DebugNode() = default; template <class Ty> Ty *getOperandAs(unsigned I) const { return cast_or_null<Ty>(getOperand(I)); @@ -78,6 +173,28 @@ protected: public: unsigned getTag() const { return SubclassData16; } + /// \brief Debug info flags. + /// + /// The three accessibility flags are mutually exclusive and rolled together + /// in the first two bits. + enum DIFlags { +#define HANDLE_DI_FLAG(ID, NAME) Flag##NAME = ID, +#include "llvm/IR/DebugInfoFlags.def" + FlagAccessibility = FlagPrivate | FlagProtected | FlagPublic + }; + + static unsigned getFlag(StringRef Flag); + static const char *getFlagString(unsigned Flag); + + /// \brief Split up a flags bitfield. + /// + /// Split \c Flags into \c SplitFlags, a vector of its components. Returns + /// any remaining (unrecognized) bits. + static unsigned splitFlags(unsigned Flags, + SmallVectorImpl<unsigned> &SplitFlags); + + DebugNodeRef getRef() const { return DebugNodeRef::get(this); } + static bool classof(const Metadata *MD) { switch (MD->getMetadataID()) { default: @@ -106,6 +223,18 @@ public: } }; +template <class T> +struct simplify_type<const TypedDebugNodeRef<T>> { + typedef Metadata *SimpleType; + static SimpleType getSimplifiedValue(const TypedDebugNodeRef<T> &MD) { + return MD; + } +}; + +template <class T> +struct simplify_type<TypedDebugNodeRef<T>> + : simplify_type<const TypedDebugNodeRef<T>> {}; + /// \brief Generic tagged DWARF-like metadata node. /// /// An un-specialized DWARF-like metadata node. The first operand is a @@ -192,27 +321,30 @@ class MDSubrange : public DebugNode { friend class MDNode; int64_t Count; - int64_t Lo; + int64_t LowerBound; - MDSubrange(LLVMContext &C, StorageType Storage, int64_t Count, int64_t Lo) + MDSubrange(LLVMContext &C, StorageType Storage, int64_t Count, + int64_t LowerBound) : DebugNode(C, MDSubrangeKind, Storage, dwarf::DW_TAG_subrange_type, None), - Count(Count), Lo(Lo) {} - ~MDSubrange() {} + Count(Count), LowerBound(LowerBound) {} + ~MDSubrange() = default; - static MDSubrange *getImpl(LLVMContext &Context, int64_t Count, int64_t Lo, - StorageType Storage, bool ShouldCreate = true); + static MDSubrange *getImpl(LLVMContext &Context, int64_t Count, + int64_t LowerBound, StorageType Storage, + bool ShouldCreate = true); TempMDSubrange cloneImpl() const { - return getTemporary(getContext(), getCount(), getLo()); + return getTemporary(getContext(), getCount(), getLowerBound()); } public: - DEFINE_MDNODE_GET(MDSubrange, (int64_t Count, int64_t Lo = 0), (Count, Lo)) + DEFINE_MDNODE_GET(MDSubrange, (int64_t Count, int64_t LowerBound = 0), + (Count, LowerBound)) TempMDSubrange clone() const { return cloneImpl(); } - int64_t getLo() const { return Lo; } + int64_t getLowerBound() const { return LowerBound; } int64_t getCount() const { return Count; } static bool classof(const Metadata *MD) { @@ -234,7 +366,7 @@ class MDEnumerator : public DebugNode { ArrayRef<Metadata *> Ops) : DebugNode(C, MDEnumeratorKind, Storage, dwarf::DW_TAG_enumerator, Ops), Value(Value) {} - ~MDEnumerator() {} + ~MDEnumerator() = default; static MDEnumerator *getImpl(LLVMContext &Context, int64_t Value, StringRef Name, StorageType Storage, @@ -279,20 +411,30 @@ protected: MDScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, ArrayRef<Metadata *> Ops) : DebugNode(C, ID, Storage, Tag, Ops) {} - ~MDScope() {} + ~MDScope() = default; public: - /// \brief Return the underlying file. + MDFile *getFile() const { return cast_or_null<MDFile>(getRawFile()); } + + inline StringRef getFilename() const; + inline StringRef getDirectory() const; + + StringRef getName() const; + MDScopeRef getScope() const; + + /// \brief Return the raw underlying file. /// /// An \a MDFile is an \a MDScope, but it doesn't point at a separate file /// (it\em is the file). If \c this is an \a MDFile, we need to return \c /// this. Otherwise, return the first operand, which is where all other /// subclasses store their file pointer. - Metadata *getFile() const { + Metadata *getRawFile() const { return isa<MDFile>(this) ? const_cast<MDScope *>(this) : static_cast<Metadata *>(getOperand(0)); } + MDScopeRef getRef() const { return MDScopeRef::get(this); } + static bool classof(const Metadata *MD) { switch (MD->getMetadataID()) { default: @@ -322,7 +464,7 @@ class MDFile : public MDScope { MDFile(LLVMContext &C, StorageType Storage, ArrayRef<Metadata *> Ops) : MDScope(C, MDFileKind, Storage, dwarf::DW_TAG_file_type, Ops) {} - ~MDFile() {} + ~MDFile() = default; static MDFile *getImpl(LLVMContext &Context, StringRef Filename, StringRef Directory, StorageType Storage, @@ -358,6 +500,18 @@ public: } }; +StringRef MDScope::getFilename() const { + if (auto *F = getFile()) + return F->getFilename(); + return ""; +} + +StringRef MDScope::getDirectory() const { + if (auto *F = getFile()) + return F->getDirectory(); + return ""; +} + /// \brief Base class for types. /// /// TODO: Remove the hardcoded name and context, since many types don't use @@ -377,7 +531,7 @@ protected: : MDScope(C, ID, Storage, Tag, Ops), Line(Line), Flags(Flags), SizeInBits(SizeInBits), AlignInBits(AlignInBits), OffsetInBits(OffsetInBits) {} - ~MDType() {} + ~MDType() = default; public: TempMDType clone() const { @@ -390,9 +544,11 @@ public: uint64_t getOffsetInBits() const { return OffsetInBits; } unsigned getFlags() const { return Flags; } - Metadata *getScope() const { return getOperand(1); } + MDScopeRef getScope() const { return MDScopeRef(getRawScope()); } StringRef getName() const { return getStringOperand(2); } + + Metadata *getRawScope() const { return getOperand(1); } MDString *getRawName() const { return getOperandAs<MDString>(2); } void setFlags(unsigned NewFlags) { @@ -400,6 +556,31 @@ public: Flags = NewFlags; } + bool isPrivate() const { + return (getFlags() & FlagAccessibility) == FlagPrivate; + } + bool isProtected() const { + return (getFlags() & FlagAccessibility) == FlagProtected; + } + bool isPublic() const { + return (getFlags() & FlagAccessibility) == FlagPublic; + } + bool isForwardDecl() const { return getFlags() & FlagFwdDecl; } + bool isAppleBlockExtension() const { return getFlags() & FlagAppleBlock; } + bool isBlockByrefStruct() const { return getFlags() & FlagBlockByrefStruct; } + bool isVirtual() const { return getFlags() & FlagVirtual; } + bool isArtificial() const { return getFlags() & FlagArtificial; } + bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } + bool isObjcClassComplete() const { + return getFlags() & FlagObjcClassComplete; + } + bool isVector() const { return getFlags() & FlagVector; } + bool isStaticMember() const { return getFlags() & FlagStaticMember; } + bool isLValueReference() const { return getFlags() & FlagLValueReference; } + bool isRValueReference() const { return getFlags() & FlagRValueReference; } + + MDTypeRef getRef() const { return MDTypeRef::get(this); } + static bool classof(const Metadata *MD) { switch (MD->getMetadataID()) { default: @@ -413,7 +594,7 @@ public: } }; -/// \brief Basic type. +/// \brief Basic type, like 'int' or 'float'. /// /// TODO: Split out DW_TAG_unspecified_type. /// TODO: Drop unused accessors. @@ -429,7 +610,7 @@ class MDBasicType : public MDType { : MDType(C, MDBasicTypeKind, Storage, Tag, 0, SizeInBits, AlignInBits, 0, 0, Ops), Encoding(Encoding) {} - ~MDBasicType() {} + ~MDBasicType() = default; static MDBasicType *getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, uint64_t SizeInBits, @@ -480,10 +661,11 @@ protected: ArrayRef<Metadata *> Ops) : MDType(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags, Ops) {} - ~MDDerivedTypeBase() {} + ~MDDerivedTypeBase() = default; public: - Metadata *getBaseType() const { return getOperand(3); } + MDTypeRef getBaseType() const { return MDTypeRef(getRawBaseType()); } + Metadata *getRawBaseType() const { return getOperand(3); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDDerivedTypeKind || @@ -507,11 +689,11 @@ class MDDerivedType : public MDDerivedTypeBase { uint64_t OffsetInBits, unsigned Flags, ArrayRef<Metadata *> Ops) : MDDerivedTypeBase(C, MDDerivedTypeKind, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags, Ops) {} - ~MDDerivedType() {} + ~MDDerivedType() = default; static MDDerivedType *getImpl(LLVMContext &Context, unsigned Tag, - StringRef Name, Metadata *File, unsigned Line, - Metadata *Scope, Metadata *BaseType, + StringRef Name, MDFile *File, unsigned Line, + MDScopeRef Scope, MDTypeRef BaseType, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, unsigned Flags, Metadata *ExtraData, StorageType Storage, @@ -545,11 +727,10 @@ public: (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, ExtraData)) DEFINE_MDNODE_GET(MDDerivedType, - (unsigned Tag, StringRef Name, Metadata *File, - unsigned Line, Metadata *Scope, Metadata *BaseType, - uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, - Metadata *ExtraData = nullptr), + (unsigned Tag, StringRef Name, MDFile *File, unsigned Line, + MDScopeRef Scope, MDTypeRef BaseType, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, Metadata *ExtraData = nullptr), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, ExtraData)) @@ -562,7 +743,25 @@ public: /// /// TODO: Separate out types that need this extra operand: pointer-to-member /// types and member fields (static members and ivars). - Metadata *getExtraData() const { return getOperand(4); } + Metadata *getExtraData() const { return getRawExtraData(); } + Metadata *getRawExtraData() const { return getOperand(4); } + + /// \brief Get casted version of extra data. + /// @{ + MDTypeRef getClassType() const { + assert(getTag() == dwarf::DW_TAG_ptr_to_member_type); + return MDTypeRef(getExtraData()); + } + MDObjCProperty *getObjCProperty() const { + return dyn_cast_or_null<MDObjCProperty>(getExtraData()); + } + Constant *getConstant() const { + assert(getTag() == dwarf::DW_TAG_member && isStaticMember()); + if (auto *C = cast_or_null<ConstantAsMetadata>(getExtraData())) + return C->getValue(); + return nullptr; + } + /// @} static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDDerivedTypeKind; @@ -584,15 +783,28 @@ protected: : MDDerivedTypeBase(C, ID, Storage, Tag, Line, SizeInBits, AlignInBits, OffsetInBits, Flags, Ops), RuntimeLang(RuntimeLang) {} - ~MDCompositeTypeBase() {} + ~MDCompositeTypeBase() = default; public: - Metadata *getElements() const { return getOperand(4); } - Metadata *getVTableHolder() const { return getOperand(5); } - Metadata *getTemplateParams() const { return getOperand(6); } + /// \brief Get the elements of the composite type. + /// + /// \note Calling this is only valid for \a MDCompositeType. This assertion + /// can be removed once \a MDSubroutineType has been separated from + /// "composite types". + DebugNodeArray getElements() const { + assert(!isa<MDSubroutineType>(this) && "no elements for DISubroutineType"); + return cast_or_null<MDTuple>(getRawElements()); + } + MDTypeRef getVTableHolder() const { return MDTypeRef(getRawVTableHolder()); } + MDTemplateParameterArray getTemplateParams() const { + return cast_or_null<MDTuple>(getRawTemplateParams()); + } StringRef getIdentifier() const { return getStringOperand(7); } unsigned getRuntimeLang() const { return RuntimeLang; } + Metadata *getRawElements() const { return getOperand(4); } + Metadata *getRawVTableHolder() const { return getOperand(5); } + Metadata *getRawTemplateParams() const { return getOperand(6); } MDString *getRawIdentifier() const { return getOperandAs<MDString>(7); } /// \brief Replace operands. @@ -601,20 +813,19 @@ public: /// this will be RAUW'ed and deleted. Use a \a TrackingMDRef to keep track /// of its movement if necessary. /// @{ - void replaceElements(MDTuple *Elements) { + void replaceElements(DebugNodeArray Elements) { #ifndef NDEBUG - if (auto *Old = cast_or_null<MDTuple>(getElements())) - for (const auto &Op : Old->operands()) - assert(std::find(Elements->op_begin(), Elements->op_end(), Op) && - "Lost a member during member list replacement"); + for (DebugNode *Op : getElements()) + assert(std::find(Elements->op_begin(), Elements->op_end(), Op) && + "Lost a member during member list replacement"); #endif - replaceOperandWith(4, Elements); + replaceOperandWith(4, Elements.get()); } - void replaceVTableHolder(Metadata *VTableHolder) { + void replaceVTableHolder(MDTypeRef VTableHolder) { replaceOperandWith(5, VTableHolder); } - void replaceTemplateParams(MDTuple *TemplateParams) { - replaceOperandWith(6, TemplateParams); + void replaceTemplateParams(MDTemplateParameterArray TemplateParams) { + replaceOperandWith(6, TemplateParams.get()); } /// @} @@ -639,20 +850,20 @@ class MDCompositeType : public MDCompositeTypeBase { : MDCompositeTypeBase(C, MDCompositeTypeKind, Storage, Tag, Line, RuntimeLang, SizeInBits, AlignInBits, OffsetInBits, Flags, Ops) {} - ~MDCompositeType() {} + ~MDCompositeType() = default; static MDCompositeType * getImpl(LLVMContext &Context, unsigned Tag, StringRef Name, Metadata *File, - unsigned Line, Metadata *Scope, Metadata *BaseType, + unsigned Line, MDScopeRef Scope, MDTypeRef BaseType, uint64_t SizeInBits, uint64_t AlignInBits, uint64_t OffsetInBits, - uint64_t Flags, Metadata *Elements, unsigned RuntimeLang, - Metadata *VTableHolder, Metadata *TemplateParams, + uint64_t Flags, DebugNodeArray Elements, unsigned RuntimeLang, + MDTypeRef VTableHolder, MDTemplateParameterArray TemplateParams, StringRef Identifier, StorageType Storage, bool ShouldCreate = true) { - return getImpl(Context, Tag, getCanonicalMDString(Context, Name), File, - Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, - Flags, Elements, RuntimeLang, VTableHolder, TemplateParams, - getCanonicalMDString(Context, Identifier), Storage, - ShouldCreate); + return getImpl( + Context, Tag, getCanonicalMDString(Context, Name), File, Line, Scope, + BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements.get(), + RuntimeLang, VTableHolder, TemplateParams.get(), + getCanonicalMDString(Context, Identifier), Storage, ShouldCreate); } static MDCompositeType * getImpl(LLVMContext &Context, unsigned Tag, MDString *Name, Metadata *File, @@ -672,12 +883,12 @@ class MDCompositeType : public MDCompositeTypeBase { public: DEFINE_MDNODE_GET(MDCompositeType, - (unsigned Tag, StringRef Name, Metadata *File, - unsigned Line, Metadata *Scope, Metadata *BaseType, - uint64_t SizeInBits, uint64_t AlignInBits, - uint64_t OffsetInBits, unsigned Flags, Metadata *Elements, - unsigned RuntimeLang, Metadata *VTableHolder, - Metadata *TemplateParams = nullptr, + (unsigned Tag, StringRef Name, MDFile *File, unsigned Line, + MDScopeRef Scope, MDTypeRef BaseType, uint64_t SizeInBits, + uint64_t AlignInBits, uint64_t OffsetInBits, + unsigned Flags, DebugNodeArray Elements, + unsigned RuntimeLang, MDTypeRef VTableHolder, + MDTemplateParameterArray TemplateParams = nullptr, StringRef Identifier = ""), (Tag, Name, File, Line, Scope, BaseType, SizeInBits, AlignInBits, OffsetInBits, Flags, Elements, RuntimeLang, @@ -701,6 +912,14 @@ public: } }; +template <class T> TypedDebugNodeRef<T> TypedDebugNodeRef<T>::get(const T *N) { + if (N) + if (auto *Composite = dyn_cast<MDCompositeType>(N)) + if (auto *S = Composite->getRawIdentifier()) + return TypedDebugNodeRef<T>(S); + return TypedDebugNodeRef<T>(N); +} + /// \brief Type array for a subprogram. /// /// TODO: Detach from CompositeType, and fold the array of types in directly @@ -714,9 +933,15 @@ class MDSubroutineType : public MDCompositeTypeBase { : MDCompositeTypeBase(C, MDSubroutineTypeKind, Storage, dwarf::DW_TAG_subroutine_type, 0, 0, 0, 0, 0, Flags, Ops) {} - ~MDSubroutineType() {} + ~MDSubroutineType() = default; static MDSubroutineType *getImpl(LLVMContext &Context, unsigned Flags, + MDTypeRefArray TypeArray, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, Flags, TypeArray.get(), Storage, ShouldCreate); + } + static MDSubroutineType *getImpl(LLVMContext &Context, unsigned Flags, Metadata *TypeArray, StorageType Storage, bool ShouldCreate = true); @@ -725,12 +950,18 @@ class MDSubroutineType : public MDCompositeTypeBase { } public: + DEFINE_MDNODE_GET(MDSubroutineType, + (unsigned Flags, MDTypeRefArray TypeArray), + (Flags, TypeArray)) DEFINE_MDNODE_GET(MDSubroutineType, (unsigned Flags, Metadata *TypeArray), (Flags, TypeArray)) TempMDSubroutineType clone() const { return cloneImpl(); } - Metadata *getTypeArray() const { return getElements(); } + MDTypeRefArray getTypeArray() const { + return cast_or_null<MDTuple>(getRawTypeArray()); + } + Metadata *getRawTypeArray() const { return getRawElements(); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDSubroutineTypeKind; @@ -753,22 +984,23 @@ class MDCompileUnit : public MDScope { : MDScope(C, MDCompileUnitKind, Storage, dwarf::DW_TAG_compile_unit, Ops), SourceLanguage(SourceLanguage), IsOptimized(IsOptimized), RuntimeVersion(RuntimeVersion), EmissionKind(EmissionKind) {} - ~MDCompileUnit() {} + ~MDCompileUnit() = default; static MDCompileUnit * - getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, + getImpl(LLVMContext &Context, unsigned SourceLanguage, MDFile *File, StringRef Producer, bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, StringRef SplitDebugFilename, - unsigned EmissionKind, Metadata *EnumTypes, Metadata *RetainedTypes, - Metadata *Subprograms, Metadata *GlobalVariables, - Metadata *ImportedEntities, StorageType Storage, + unsigned EmissionKind, MDCompositeTypeArray EnumTypes, + MDTypeArray RetainedTypes, MDSubprogramArray Subprograms, + MDGlobalVariableArray GlobalVariables, + MDImportedEntityArray ImportedEntities, StorageType Storage, bool ShouldCreate = true) { - return getImpl(Context, SourceLanguage, File, - getCanonicalMDString(Context, Producer), IsOptimized, - getCanonicalMDString(Context, Flags), RuntimeVersion, - getCanonicalMDString(Context, SplitDebugFilename), - EmissionKind, EnumTypes, RetainedTypes, Subprograms, - GlobalVariables, ImportedEntities, Storage, ShouldCreate); + return getImpl( + Context, SourceLanguage, File, getCanonicalMDString(Context, Producer), + IsOptimized, getCanonicalMDString(Context, Flags), RuntimeVersion, + getCanonicalMDString(Context, SplitDebugFilename), EmissionKind, + EnumTypes.get(), RetainedTypes.get(), Subprograms.get(), + GlobalVariables.get(), ImportedEntities.get(), Storage, ShouldCreate); } static MDCompileUnit * getImpl(LLVMContext &Context, unsigned SourceLanguage, Metadata *File, @@ -789,12 +1021,13 @@ class MDCompileUnit : public MDScope { public: DEFINE_MDNODE_GET(MDCompileUnit, - (unsigned SourceLanguage, Metadata *File, - StringRef Producer, bool IsOptimized, StringRef Flags, - unsigned RuntimeVersion, StringRef SplitDebugFilename, - unsigned EmissionKind, Metadata *EnumTypes, - Metadata *RetainedTypes, Metadata *Subprograms, - Metadata *GlobalVariables, Metadata *ImportedEntities), + (unsigned SourceLanguage, MDFile *File, StringRef Producer, + bool IsOptimized, StringRef Flags, unsigned RuntimeVersion, + StringRef SplitDebugFilename, unsigned EmissionKind, + MDCompositeTypeArray EnumTypes, MDTypeArray RetainedTypes, + MDSubprogramArray Subprograms, + MDGlobalVariableArray GlobalVariables, + MDImportedEntityArray ImportedEntities), (SourceLanguage, File, Producer, IsOptimized, Flags, RuntimeVersion, SplitDebugFilename, EmissionKind, EnumTypes, RetainedTypes, Subprograms, GlobalVariables, @@ -820,17 +1053,32 @@ public: StringRef getProducer() const { return getStringOperand(1); } StringRef getFlags() const { return getStringOperand(2); } StringRef getSplitDebugFilename() const { return getStringOperand(3); } - Metadata *getEnumTypes() const { return getOperand(4); } - Metadata *getRetainedTypes() const { return getOperand(5); } - Metadata *getSubprograms() const { return getOperand(6); } - Metadata *getGlobalVariables() const { return getOperand(7); } - Metadata *getImportedEntities() const { return getOperand(8); } + MDCompositeTypeArray getEnumTypes() const { + return cast_or_null<MDTuple>(getRawEnumTypes()); + } + MDTypeArray getRetainedTypes() const { + return cast_or_null<MDTuple>(getRawRetainedTypes()); + } + MDSubprogramArray getSubprograms() const { + return cast_or_null<MDTuple>(getRawSubprograms()); + } + MDGlobalVariableArray getGlobalVariables() const { + return cast_or_null<MDTuple>(getRawGlobalVariables()); + } + MDImportedEntityArray getImportedEntities() const { + return cast_or_null<MDTuple>(getRawImportedEntities()); + } MDString *getRawProducer() const { return getOperandAs<MDString>(1); } MDString *getRawFlags() const { return getOperandAs<MDString>(2); } MDString *getRawSplitDebugFilename() const { return getOperandAs<MDString>(3); } + Metadata *getRawEnumTypes() const { return getOperand(4); } + Metadata *getRawRetainedTypes() const { return getOperand(5); } + Metadata *getRawSubprograms() const { return getOperand(6); } + Metadata *getRawGlobalVariables() const { return getOperand(7); } + Metadata *getRawImportedEntities() const { return getOperand(8); } /// \brief Replace arrays. /// @@ -838,8 +1086,12 @@ public: /// deleted on a uniquing collision. In practice, uniquing collisions on \a /// MDCompileUnit should be fairly rare. /// @{ - void replaceSubprograms(MDTuple *N) { replaceOperandWith(6, N); } - void replaceGlobalVariables(MDTuple *N) { replaceOperandWith(7, N); } + void replaceSubprograms(MDSubprogramArray N) { + replaceOperandWith(6, N.get()); + } + void replaceGlobalVariables(MDGlobalVariableArray N) { + replaceOperandWith(7, N.get()); + } /// @} static bool classof(const Metadata *MD) { @@ -857,9 +1109,15 @@ protected: MDLocalScope(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, ArrayRef<Metadata *> Ops) : MDScope(C, ID, Storage, Tag, Ops) {} - ~MDLocalScope() {} + ~MDLocalScope() = default; public: + /// \brief Get the subprogram for this scope. + /// + /// Return this if it's an \a MDSubprogram; otherwise, look up the scope + /// chain. + MDSubprogram *getSubprogram() const; + static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDSubprogramKind || MD->getMetadataID() == MDLexicalBlockKind || @@ -914,12 +1172,58 @@ public: unsigned getLine() const { return SubclassData32; } unsigned getColumn() const { return SubclassData16; } MDLocalScope *getScope() const { - return cast_or_null<MDLocalScope>(getRawScope()); + return cast<MDLocalScope>(getRawScope()); } MDLocation *getInlinedAt() const { return cast_or_null<MDLocation>(getRawInlinedAt()); } + MDFile *getFile() const { return getScope()->getFile(); } + StringRef getFilename() const { return getScope()->getFilename(); } + StringRef getDirectory() const { return getScope()->getDirectory(); } + + /// \brief Get the scope where this is inlined. + /// + /// Walk through \a getInlinedAt() and return \a getScope() from the deepest + /// location. + MDLocalScope *getInlinedAtScope() const { + if (auto *IA = getInlinedAt()) + return IA->getInlinedAtScope(); + return getScope(); + } + + /// \brief Check whether this can be discriminated from another location. + /// + /// Check \c this can be discriminated from \c RHS in a linetable entry. + /// Scope and inlined-at chains are not recorded in the linetable, so they + /// cannot be used to distinguish basic blocks. + /// + /// The current implementation is weaker than it should be, since it just + /// checks filename and line. + /// + /// FIXME: Add a check for getDiscriminator(). + /// FIXME: Add a check for getColumn(). + /// FIXME: Change the getFilename() check to getFile() (or add one for + /// getDirectory()). + bool canDiscriminate(const MDLocation &RHS) const { + return getFilename() != RHS.getFilename() || getLine() != RHS.getLine(); + } + + /// \brief Get the DWARF discriminator. + /// + /// DWARF discriminators distinguish identical file locations between + /// instructions that are on different basic blocks. + inline unsigned getDiscriminator() const; + + /// \brief Compute new discriminator in the given context. + /// + /// This modifies the \a LLVMContext that \c this is in to increment the next + /// discriminator for \c this's line/filename combination. + /// + /// FIXME: Delete this. See comments in implementation and at the only call + /// site in \a AddDiscriminators::runOnFunction(). + unsigned computeNewDiscriminator() const; + Metadata *getRawScope() const { return getOperand(0); } Metadata *getRawInlinedAt() const { if (getNumOperands() == 2) @@ -958,21 +1262,23 @@ class MDSubprogram : public MDLocalScope { Line(Line), ScopeLine(ScopeLine), Virtuality(Virtuality), VirtualIndex(VirtualIndex), Flags(Flags), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition), IsOptimized(IsOptimized) {} - ~MDSubprogram() {} + ~MDSubprogram() = default; static MDSubprogram * - getImpl(LLVMContext &Context, Metadata *Scope, StringRef Name, - StringRef LinkageName, Metadata *File, unsigned Line, Metadata *Type, - bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, - Metadata *ContainingType, unsigned Virtuality, unsigned VirtualIndex, - unsigned Flags, bool IsOptimized, Metadata *Function, - Metadata *TemplateParams, Metadata *Declaration, Metadata *Variables, + getImpl(LLVMContext &Context, MDScopeRef Scope, StringRef Name, + StringRef LinkageName, MDFile *File, unsigned Line, + MDSubroutineType *Type, bool IsLocalToUnit, bool IsDefinition, + unsigned ScopeLine, MDTypeRef ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Constant *Function, MDTemplateParameterArray TemplateParams, + MDSubprogram *Declaration, MDLocalVariableArray Variables, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, LinkageName), File, Line, Type, IsLocalToUnit, IsDefinition, ScopeLine, ContainingType, - Virtuality, VirtualIndex, Flags, IsOptimized, Function, - TemplateParams, Declaration, Variables, Storage, + Virtuality, VirtualIndex, Flags, IsOptimized, + Function ? ConstantAsMetadata::get(Function) : nullptr, + TemplateParams.get(), Declaration, Variables.get(), Storage, ShouldCreate); } static MDSubprogram * @@ -989,22 +1295,25 @@ class MDSubprogram : public MDLocalScope { getFile(), getLine(), getType(), isLocalToUnit(), isDefinition(), getScopeLine(), getContainingType(), getVirtuality(), getVirtualIndex(), getFlags(), - isOptimized(), getFunction(), getTemplateParams(), - getDeclaration(), getVariables()); + isOptimized(), getFunctionConstant(), + getTemplateParams(), getDeclaration(), getVariables()); } public: - DEFINE_MDNODE_GET( - MDSubprogram, - (Metadata * Scope, StringRef Name, StringRef LinkageName, Metadata *File, - unsigned Line, Metadata *Type, bool IsLocalToUnit, bool IsDefinition, - unsigned ScopeLine, Metadata *ContainingType, unsigned Virtuality, - unsigned VirtualIndex, unsigned Flags, bool IsOptimized, - Metadata *Function = nullptr, Metadata *TemplateParams = nullptr, - Metadata *Declaration = nullptr, Metadata *Variables = nullptr), - (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, - ScopeLine, ContainingType, Virtuality, VirtualIndex, Flags, IsOptimized, - Function, TemplateParams, Declaration, Variables)) + DEFINE_MDNODE_GET(MDSubprogram, + (MDScopeRef Scope, StringRef Name, StringRef LinkageName, + MDFile *File, unsigned Line, MDSubroutineType *Type, + bool IsLocalToUnit, bool IsDefinition, unsigned ScopeLine, + MDTypeRef ContainingType, unsigned Virtuality, + unsigned VirtualIndex, unsigned Flags, bool IsOptimized, + Constant *Function = nullptr, + MDTemplateParameterArray TemplateParams = nullptr, + MDSubprogram *Declaration = nullptr, + MDLocalVariableArray Variables = nullptr), + (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, + IsDefinition, ScopeLine, ContainingType, Virtuality, + VirtualIndex, Flags, IsOptimized, Function, TemplateParams, + Declaration, Variables)) DEFINE_MDNODE_GET( MDSubprogram, (Metadata * Scope, MDString *Name, MDString *LinkageName, Metadata *File, @@ -1029,7 +1338,36 @@ public: bool isDefinition() const { return IsDefinition; } bool isOptimized() const { return IsOptimized; } - Metadata *getScope() const { return getOperand(1); } + unsigned isArtificial() const { return getFlags() & FlagArtificial; } + bool isPrivate() const { + return (getFlags() & FlagAccessibility) == FlagPrivate; + } + bool isProtected() const { + return (getFlags() & FlagAccessibility) == FlagProtected; + } + bool isPublic() const { + return (getFlags() & FlagAccessibility) == FlagPublic; + } + bool isExplicit() const { return getFlags() & FlagExplicit; } + bool isPrototyped() const { return getFlags() & FlagPrototyped; } + + /// \brief Check if this is reference-qualified. + /// + /// Return true if this subprogram is a C++11 reference-qualified non-static + /// member function (void foo() &). + unsigned isLValueReference() const { + return getFlags() & FlagLValueReference; + } + + /// \brief Check if this is rvalue-reference-qualified. + /// + /// Return true if this subprogram is a C++11 rvalue-reference-qualified + /// non-static member function (void foo() &&). + unsigned isRValueReference() const { + return getFlags() & FlagRValueReference; + } + + MDScopeRef getScope() const { return MDScopeRef(getRawScope()); } StringRef getName() const { return getStringOperand(2); } StringRef getDisplayName() const { return getStringOperand(3); } @@ -1038,13 +1376,42 @@ public: MDString *getRawName() const { return getOperandAs<MDString>(2); } MDString *getRawLinkageName() const { return getOperandAs<MDString>(4); } - Metadata *getType() const { return getOperand(5); } - Metadata *getContainingType() const { return getOperand(6); } + MDSubroutineType *getType() const { + return cast_or_null<MDSubroutineType>(getRawType()); + } + MDTypeRef getContainingType() const { + return MDTypeRef(getRawContainingType()); + } - Metadata *getFunction() const { return getOperand(7); } - Metadata *getTemplateParams() const { return getOperand(8); } - Metadata *getDeclaration() const { return getOperand(9); } - Metadata *getVariables() const { return getOperand(10); } + Constant *getFunctionConstant() const { + if (auto *C = cast_or_null<ConstantAsMetadata>(getRawFunction())) + return C->getValue(); + return nullptr; + } + MDTemplateParameterArray getTemplateParams() const { + return cast_or_null<MDTuple>(getRawTemplateParams()); + } + MDSubprogram *getDeclaration() const { + return cast_or_null<MDSubprogram>(getRawDeclaration()); + } + MDLocalVariableArray getVariables() const { + return cast_or_null<MDTuple>(getRawVariables()); + } + + Metadata *getRawScope() const { return getOperand(1); } + Metadata *getRawType() const { return getOperand(5); } + Metadata *getRawContainingType() const { return getOperand(6); } + Metadata *getRawFunction() const { return getOperand(7); } + Metadata *getRawTemplateParams() const { return getOperand(8); } + Metadata *getRawDeclaration() const { return getOperand(9); } + Metadata *getRawVariables() const { return getOperand(10); } + + /// \brief Get a pointer to the function this subprogram describes. + /// + /// This dyn_casts \a getFunctionConstant() to \a Function. + /// + /// FIXME: Should this be looking through bitcasts? + Function *getFunction() const; /// \brief Replace the function. /// @@ -1057,6 +1424,11 @@ public: void replaceFunction(std::nullptr_t) { replaceOperandWith(7, nullptr); } /// @} + /// \brief Check if this subprogram decribes the given function. + /// + /// FIXME: Should this be looking through bitcasts? + bool describes(const Function *F) const; + static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDSubprogramKind; } @@ -1067,11 +1439,20 @@ protected: MDLexicalBlockBase(LLVMContext &C, unsigned ID, StorageType Storage, ArrayRef<Metadata *> Ops) : MDLocalScope(C, ID, Storage, dwarf::DW_TAG_lexical_block, Ops) {} - ~MDLexicalBlockBase() {} + ~MDLexicalBlockBase() = default; public: - Metadata *getScope() const { return getOperand(1); } + MDLocalScope *getScope() const { return cast<MDLocalScope>(getRawScope()); } + Metadata *getRawScope() const { return getOperand(1); } + + /// \brief Forwarding accessors to LexicalBlock. + /// + /// TODO: Remove these and update code to use \a MDLexicalBlock directly. + /// @{ + inline unsigned getLine() const; + inline unsigned getColumn() const; + /// @} static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDLexicalBlockKind || MD->getMetadataID() == MDLexicalBlockFileKind; @@ -1089,7 +1470,16 @@ class MDLexicalBlock : public MDLexicalBlockBase { unsigned Column, ArrayRef<Metadata *> Ops) : MDLexicalBlockBase(C, MDLexicalBlockKind, Storage, Ops), Line(Line), Column(Column) {} - ~MDLexicalBlock() {} + ~MDLexicalBlock() = default; + + static MDLexicalBlock *getImpl(LLVMContext &Context, MDLocalScope *Scope, + MDFile *File, unsigned Line, unsigned Column, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, static_cast<Metadata *>(Scope), + static_cast<Metadata *>(File), Line, Column, Storage, + ShouldCreate); + } static MDLexicalBlock *getImpl(LLVMContext &Context, Metadata *Scope, Metadata *File, unsigned Line, unsigned Column, @@ -1101,6 +1491,9 @@ class MDLexicalBlock : public MDLexicalBlockBase { } public: + DEFINE_MDNODE_GET(MDLexicalBlock, (MDLocalScope * Scope, MDFile *File, + unsigned Line, unsigned Column), + (Scope, File, Line, Column)) DEFINE_MDNODE_GET(MDLexicalBlock, (Metadata * Scope, Metadata *File, unsigned Line, unsigned Column), (Scope, File, Line, Column)) @@ -1115,6 +1508,18 @@ public: } }; +unsigned MDLexicalBlockBase::getLine() const { + if (auto *N = dyn_cast<MDLexicalBlock>(this)) + return N->getLine(); + return 0; +} + +unsigned MDLexicalBlockBase::getColumn() const { + if (auto *N = dyn_cast<MDLexicalBlock>(this)) + return N->getColumn(); + return 0; +} + class MDLexicalBlockFile : public MDLexicalBlockBase { friend class LLVMContextImpl; friend class MDNode; @@ -1125,7 +1530,16 @@ class MDLexicalBlockFile : public MDLexicalBlockBase { unsigned Discriminator, ArrayRef<Metadata *> Ops) : MDLexicalBlockBase(C, MDLexicalBlockFileKind, Storage, Ops), Discriminator(Discriminator) {} - ~MDLexicalBlockFile() {} + ~MDLexicalBlockFile() = default; + + static MDLexicalBlockFile *getImpl(LLVMContext &Context, MDLocalScope *Scope, + MDFile *File, unsigned Discriminator, + StorageType Storage, + bool ShouldCreate = true) { + return getImpl(Context, static_cast<Metadata *>(Scope), + static_cast<Metadata *>(File), Discriminator, Storage, + ShouldCreate); + } static MDLexicalBlockFile *getImpl(LLVMContext &Context, Metadata *Scope, Metadata *File, unsigned Discriminator, @@ -1138,12 +1552,19 @@ class MDLexicalBlockFile : public MDLexicalBlockBase { } public: + DEFINE_MDNODE_GET(MDLexicalBlockFile, (MDLocalScope * Scope, MDFile *File, + unsigned Discriminator), + (Scope, File, Discriminator)) DEFINE_MDNODE_GET(MDLexicalBlockFile, (Metadata * Scope, Metadata *File, unsigned Discriminator), (Scope, File, Discriminator)) TempMDLexicalBlockFile clone() const { return cloneImpl(); } + // TODO: Remove these once they're gone from MDLexicalBlockBase. + unsigned getLine() const = delete; + unsigned getColumn() const = delete; + unsigned getDiscriminator() const { return Discriminator; } static bool classof(const Metadata *MD) { @@ -1151,6 +1572,12 @@ public: } }; +unsigned MDLocation::getDiscriminator() const { + if (auto *F = dyn_cast<MDLexicalBlockFile>(getScope())) + return F->getDiscriminator(); + return 0; +} + class MDNamespace : public MDScope { friend class LLVMContextImpl; friend class MDNode; @@ -1162,10 +1589,10 @@ class MDNamespace : public MDScope { : MDScope(Context, MDNamespaceKind, Storage, dwarf::DW_TAG_namespace, Ops), Line(Line) {} - ~MDNamespace() {} + ~MDNamespace() = default; - static MDNamespace *getImpl(LLVMContext &Context, Metadata *Scope, - Metadata *File, StringRef Name, unsigned Line, + static MDNamespace *getImpl(LLVMContext &Context, MDScope *Scope, + MDFile *File, StringRef Name, unsigned Line, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, File, getCanonicalMDString(Context, Name), Line, Storage, ShouldCreate); @@ -1180,8 +1607,8 @@ class MDNamespace : public MDScope { } public: - DEFINE_MDNODE_GET(MDNamespace, (Metadata * Scope, Metadata *File, - StringRef Name, unsigned Line), + DEFINE_MDNODE_GET(MDNamespace, (MDScope * Scope, MDFile *File, StringRef Name, + unsigned Line), (Scope, File, Name, Line)) DEFINE_MDNODE_GET(MDNamespace, (Metadata * Scope, Metadata *File, MDString *Name, unsigned Line), @@ -1190,9 +1617,10 @@ public: TempMDNamespace clone() const { return cloneImpl(); } unsigned getLine() const { return Line; } - Metadata *getScope() const { return getOperand(1); } + MDScope *getScope() const { return cast_or_null<MDScope>(getRawScope()); } StringRef getName() const { return getStringOperand(2); } + Metadata *getRawScope() const { return getOperand(1); } MDString *getRawName() const { return getOperandAs<MDString>(2); } static bool classof(const Metadata *MD) { @@ -1206,13 +1634,14 @@ protected: MDTemplateParameter(LLVMContext &Context, unsigned ID, StorageType Storage, unsigned Tag, ArrayRef<Metadata *> Ops) : DebugNode(Context, ID, Storage, Tag, Ops) {} - ~MDTemplateParameter() {} + ~MDTemplateParameter() = default; public: StringRef getName() const { return getStringOperand(0); } - Metadata *getType() const { return getOperand(1); } + MDTypeRef getType() const { return MDTypeRef(getRawType()); } MDString *getRawName() const { return getOperandAs<MDString>(0); } + Metadata *getRawType() const { return getOperand(1); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDTemplateTypeParameterKind || @@ -1228,10 +1657,10 @@ class MDTemplateTypeParameter : public MDTemplateParameter { ArrayRef<Metadata *> Ops) : MDTemplateParameter(Context, MDTemplateTypeParameterKind, Storage, dwarf::DW_TAG_template_type_parameter, Ops) {} - ~MDTemplateTypeParameter() {} + ~MDTemplateTypeParameter() = default; static MDTemplateTypeParameter *getImpl(LLVMContext &Context, StringRef Name, - Metadata *Type, StorageType Storage, + MDTypeRef Type, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, getCanonicalMDString(Context, Name), Type, Storage, ShouldCreate); @@ -1245,7 +1674,7 @@ class MDTemplateTypeParameter : public MDTemplateParameter { } public: - DEFINE_MDNODE_GET(MDTemplateTypeParameter, (StringRef Name, Metadata *Type), + DEFINE_MDNODE_GET(MDTemplateTypeParameter, (StringRef Name, MDTypeRef Type), (Name, Type)) DEFINE_MDNODE_GET(MDTemplateTypeParameter, (MDString * Name, Metadata *Type), (Name, Type)) @@ -1265,10 +1694,10 @@ class MDTemplateValueParameter : public MDTemplateParameter { unsigned Tag, ArrayRef<Metadata *> Ops) : MDTemplateParameter(Context, MDTemplateValueParameterKind, Storage, Tag, Ops) {} - ~MDTemplateValueParameter() {} + ~MDTemplateValueParameter() = default; static MDTemplateValueParameter *getImpl(LLVMContext &Context, unsigned Tag, - StringRef Name, Metadata *Type, + StringRef Name, MDTypeRef Type, Metadata *Value, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, getCanonicalMDString(Context, Name), Type, @@ -1286,7 +1715,7 @@ class MDTemplateValueParameter : public MDTemplateParameter { public: DEFINE_MDNODE_GET(MDTemplateValueParameter, (unsigned Tag, StringRef Name, - Metadata *Type, Metadata *Value), + MDTypeRef Type, Metadata *Value), (Tag, Name, Type, Value)) DEFINE_MDNODE_GET(MDTemplateValueParameter, (unsigned Tag, MDString *Name, Metadata *Type, Metadata *Value), @@ -1311,16 +1740,30 @@ protected: MDVariable(LLVMContext &C, unsigned ID, StorageType Storage, unsigned Tag, unsigned Line, ArrayRef<Metadata *> Ops) : DebugNode(C, ID, Storage, Tag, Ops), Line(Line) {} - ~MDVariable() {} + ~MDVariable() = default; public: unsigned getLine() const { return Line; } - Metadata *getScope() const { return getOperand(0); } + MDScope *getScope() const { return cast_or_null<MDScope>(getRawScope()); } StringRef getName() const { return getStringOperand(1); } - Metadata *getFile() const { return getOperand(2); } - Metadata *getType() const { return getOperand(3); } + MDFile *getFile() const { return cast_or_null<MDFile>(getRawFile()); } + MDTypeRef getType() const { return MDTypeRef(getRawType()); } + + StringRef getFilename() const { + if (auto *F = getFile()) + return F->getFilename(); + return ""; + } + StringRef getDirectory() const { + if (auto *F = getFile()) + return F->getDirectory(); + return ""; + } + Metadata *getRawScope() const { return getOperand(0); } MDString *getRawName() const { return getOperandAs<MDString>(1); } + Metadata *getRawFile() const { return getOperand(2); } + Metadata *getRawType() const { return getOperand(3); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDLocalVariableKind || @@ -1344,17 +1787,18 @@ class MDGlobalVariable : public MDVariable { : MDVariable(C, MDGlobalVariableKind, Storage, dwarf::DW_TAG_variable, Line, Ops), IsLocalToUnit(IsLocalToUnit), IsDefinition(IsDefinition) {} - ~MDGlobalVariable() {} + ~MDGlobalVariable() = default; static MDGlobalVariable * - getImpl(LLVMContext &Context, Metadata *Scope, StringRef Name, - StringRef LinkageName, Metadata *File, unsigned Line, Metadata *Type, - bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, - Metadata *StaticDataMemberDeclaration, StorageType Storage, + getImpl(LLVMContext &Context, MDScope *Scope, StringRef Name, + StringRef LinkageName, MDFile *File, unsigned Line, MDTypeRef Type, + bool IsLocalToUnit, bool IsDefinition, Constant *Variable, + MDDerivedType *StaticDataMemberDeclaration, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Scope, getCanonicalMDString(Context, Name), getCanonicalMDString(Context, LinkageName), File, Line, Type, - IsLocalToUnit, IsDefinition, Variable, + IsLocalToUnit, IsDefinition, + Variable ? ConstantAsMetadata::get(Variable) : nullptr, StaticDataMemberDeclaration, Storage, ShouldCreate); } static MDGlobalVariable * @@ -1373,10 +1817,10 @@ class MDGlobalVariable : public MDVariable { public: DEFINE_MDNODE_GET(MDGlobalVariable, - (Metadata * Scope, StringRef Name, StringRef LinkageName, - Metadata *File, unsigned Line, Metadata *Type, - bool IsLocalToUnit, bool IsDefinition, Metadata *Variable, - Metadata *StaticDataMemberDeclaration), + (MDScope * Scope, StringRef Name, StringRef LinkageName, + MDFile *File, unsigned Line, MDTypeRef Type, + bool IsLocalToUnit, bool IsDefinition, Constant *Variable, + MDDerivedType *StaticDataMemberDeclaration), (Scope, Name, LinkageName, File, Line, Type, IsLocalToUnit, IsDefinition, Variable, StaticDataMemberDeclaration)) DEFINE_MDNODE_GET(MDGlobalVariable, @@ -1393,10 +1837,18 @@ public: bool isDefinition() const { return IsDefinition; } StringRef getDisplayName() const { return getStringOperand(4); } StringRef getLinkageName() const { return getStringOperand(5); } - Metadata *getVariable() const { return getOperand(6); } - Metadata *getStaticDataMemberDeclaration() const { return getOperand(7); } + Constant *getVariable() const { + if (auto *C = cast_or_null<ConstantAsMetadata>(getRawVariable())) + return dyn_cast<Constant>(C->getValue()); + return nullptr; + } + MDDerivedType *getStaticDataMemberDeclaration() const { + return cast_or_null<MDDerivedType>(getRawStaticDataMemberDeclaration()); + } MDString *getRawLinkageName() const { return getOperandAs<MDString>(5); } + Metadata *getRawVariable() const { return getOperand(6); } + Metadata *getRawStaticDataMemberDeclaration() const { return getOperand(7); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDGlobalVariableKind; @@ -1420,62 +1872,61 @@ class MDLocalVariable : public MDVariable { ArrayRef<Metadata *> Ops) : MDVariable(C, MDLocalVariableKind, Storage, Tag, Line, Ops), Arg(Arg), Flags(Flags) {} - ~MDLocalVariable() {} + ~MDLocalVariable() = default; static MDLocalVariable *getImpl(LLVMContext &Context, unsigned Tag, - Metadata *Scope, StringRef Name, - Metadata *File, unsigned Line, Metadata *Type, - unsigned Arg, unsigned Flags, - Metadata *InlinedAt, StorageType Storage, + MDScope *Scope, StringRef Name, MDFile *File, + unsigned Line, MDTypeRef Type, unsigned Arg, + unsigned Flags, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, Tag, Scope, getCanonicalMDString(Context, Name), - File, Line, Type, Arg, Flags, InlinedAt, Storage, - ShouldCreate); + File, Line, Type, Arg, Flags, Storage, ShouldCreate); } - static MDLocalVariable *getImpl(LLVMContext &Context, unsigned Tag, - Metadata *Scope, MDString *Name, - Metadata *File, unsigned Line, Metadata *Type, - unsigned Arg, unsigned Flags, - Metadata *InlinedAt, StorageType Storage, - bool ShouldCreate = true); + static MDLocalVariable * + getImpl(LLVMContext &Context, unsigned Tag, Metadata *Scope, MDString *Name, + Metadata *File, unsigned Line, Metadata *Type, unsigned Arg, + unsigned Flags, StorageType Storage, bool ShouldCreate = true); TempMDLocalVariable cloneImpl() const { return getTemporary(getContext(), getTag(), getScope(), getName(), - getFile(), getLine(), getType(), getArg(), getFlags(), - getInlinedAt()); + getFile(), getLine(), getType(), getArg(), getFlags()); } public: DEFINE_MDNODE_GET(MDLocalVariable, - (unsigned Tag, Metadata *Scope, StringRef Name, - Metadata *File, unsigned Line, Metadata *Type, - unsigned Arg, unsigned Flags, - Metadata *InlinedAt = nullptr), - (Tag, Scope, Name, File, Line, Type, Arg, Flags, InlinedAt)) + (unsigned Tag, MDLocalScope *Scope, StringRef Name, + MDFile *File, unsigned Line, MDTypeRef Type, unsigned Arg, + unsigned Flags), + (Tag, Scope, Name, File, Line, Type, Arg, Flags)) DEFINE_MDNODE_GET(MDLocalVariable, (unsigned Tag, Metadata *Scope, MDString *Name, Metadata *File, unsigned Line, Metadata *Type, - unsigned Arg, unsigned Flags, - Metadata *InlinedAt = nullptr), - (Tag, Scope, Name, File, Line, Type, Arg, Flags, InlinedAt)) + unsigned Arg, unsigned Flags), + (Tag, Scope, Name, File, Line, Type, Arg, Flags)) TempMDLocalVariable clone() const { return cloneImpl(); } + /// \brief Get the local scope for this variable. + /// + /// Variables must be defined in a local scope. + MDLocalScope *getScope() const { + return cast<MDLocalScope>(MDVariable::getScope()); + } + unsigned getArg() const { return Arg; } unsigned getFlags() const { return Flags; } - Metadata *getInlinedAt() const { return getOperand(4); } - /// \brief Get an inlined version of this variable. + bool isArtificial() const { return getFlags() & FlagArtificial; } + bool isObjectPointer() const { return getFlags() & FlagObjectPointer; } + + /// \brief Check that a location is valid for this variable. /// - /// Returns a version of this with \a getAlinedAt() set to \c InlinedAt. - MDLocalVariable *withInline(MDLocation *InlinedAt) const { - if (InlinedAt == getInlinedAt()) - return const_cast<MDLocalVariable *>(this); - auto Temp = clone(); - Temp->replaceOperandWith(4, InlinedAt); - return replaceWithUniqued(std::move(Temp)); + /// Check that \c DL exists, is in the same subprogram, and has the same + /// inlined-at location as \c this. (Otherwise, it's not a valid attachemnt + /// to a \a DbgInfoIntrinsic.) + bool isValidLocationForIntrinsic(const MDLocation *DL) const { + return DL && getScope()->getSubprogram() == DL->getScope()->getSubprogram(); } - MDLocalVariable *withoutInline() const { return withInline(nullptr); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDLocalVariableKind; @@ -1484,6 +1935,12 @@ public: /// \brief DWARF expression. /// +/// This is (almost) a DWARF expression that modifies the location of a +/// variable or (or the location of a single piece of a variable). +/// +/// FIXME: Instead of DW_OP_plus taking an argument, this should use DW_OP_const +/// and have DW_OP_plus consume the topmost elements on the stack. +/// /// TODO: Co-allocate the expression elements. /// TODO: Separate from MDNode, or otherwise drop Distinct and Temporary /// storage types. @@ -1496,7 +1953,7 @@ class MDExpression : public MDNode { MDExpression(LLVMContext &C, StorageType Storage, ArrayRef<uint64_t> Elements) : MDNode(C, MDExpressionKind, Storage, None), Elements(Elements.begin(), Elements.end()) {} - ~MDExpression() {} + ~MDExpression() = default; static MDExpression *getImpl(LLVMContext &Context, ArrayRef<uint64_t> Elements, StorageType Storage, @@ -1519,6 +1976,15 @@ public: return Elements[I]; } + /// \brief Return whether this is a piece of an aggregate variable. + bool isBitPiece() const; + + /// \brief Return the offset of this piece in bits. + uint64_t getBitPieceOffset() const; + + /// \brief Return the size of this piece in bits. + uint64_t getBitPieceSize() const; + typedef ArrayRef<uint64_t>::iterator element_iterator; element_iterator elements_begin() const { return getElements().begin(); } element_iterator elements_end() const { return getElements().end(); } @@ -1573,6 +2039,13 @@ public: return T; } + /// \brief Get the next iterator. + /// + /// \a std::next() doesn't work because this is technically an + /// input_iterator, but it's a perfectly valid operation. This is an + /// accessor to provide the same functionality. + expr_op_iterator getNext() const { return ++expr_op_iterator(*this); } + bool operator==(const expr_op_iterator &X) const { return getBase() == X.getBase(); } @@ -1619,12 +2092,12 @@ class MDObjCProperty : public DebugNode { : DebugNode(C, MDObjCPropertyKind, Storage, dwarf::DW_TAG_APPLE_property, Ops), Line(Line), Attributes(Attributes) {} - ~MDObjCProperty() {} + ~MDObjCProperty() = default; static MDObjCProperty * - getImpl(LLVMContext &Context, StringRef Name, Metadata *File, unsigned Line, + getImpl(LLVMContext &Context, StringRef Name, MDFile *File, unsigned Line, StringRef GetterName, StringRef SetterName, unsigned Attributes, - Metadata *Type, StorageType Storage, bool ShouldCreate = true) { + MDType *Type, StorageType Storage, bool ShouldCreate = true) { return getImpl(Context, getCanonicalMDString(Context, Name), File, Line, getCanonicalMDString(Context, GetterName), getCanonicalMDString(Context, SetterName), Attributes, Type, @@ -1644,9 +2117,9 @@ class MDObjCProperty : public DebugNode { public: DEFINE_MDNODE_GET(MDObjCProperty, - (StringRef Name, Metadata *File, unsigned Line, + (StringRef Name, MDFile *File, unsigned Line, StringRef GetterName, StringRef SetterName, - unsigned Attributes, Metadata *Type), + unsigned Attributes, MDType *Type), (Name, File, Line, GetterName, SetterName, Attributes, Type)) DEFINE_MDNODE_GET(MDObjCProperty, @@ -1661,20 +2134,39 @@ public: unsigned getLine() const { return Line; } unsigned getAttributes() const { return Attributes; } StringRef getName() const { return getStringOperand(0); } - Metadata *getFile() const { return getOperand(1); } + MDFile *getFile() const { return cast_or_null<MDFile>(getRawFile()); } StringRef getGetterName() const { return getStringOperand(2); } StringRef getSetterName() const { return getStringOperand(3); } - Metadata *getType() const { return getOperand(4); } + + /// \brief Get the type. + /// + /// \note Objective-C doesn't have an ODR, so there is no benefit in storing + /// the type as a DITypeRef here. + MDType *getType() const { return cast_or_null<MDType>(getRawType()); } + + StringRef getFilename() const { + if (auto *F = getFile()) + return F->getFilename(); + return ""; + } + StringRef getDirectory() const { + if (auto *F = getFile()) + return F->getDirectory(); + return ""; + } MDString *getRawName() const { return getOperandAs<MDString>(0); } + Metadata *getRawFile() const { return getOperand(1); } MDString *getRawGetterName() const { return getOperandAs<MDString>(2); } MDString *getRawSetterName() const { return getOperandAs<MDString>(3); } + Metadata *getRawType() const { return getOperand(4); } static bool classof(const Metadata *MD) { return MD->getMetadataID() == MDObjCPropertyKind; } }; +/// \brief An imported module (C++ using directive or similar). class MDImportedEntity : public DebugNode { friend class LLVMContextImpl; friend class MDNode; @@ -1684,10 +2176,10 @@ class MDImportedEntity : public DebugNode { MDImportedEntity(LLVMContext &C, StorageType Storage, unsigned Tag, unsigned Line, ArrayRef<Metadata *> Ops) : DebugNode(C, MDImportedEntityKind, Storage, Tag, Ops), Line(Line) {} - ~MDImportedEntity() {} + ~MDImportedEntity() = default; static MDImportedEntity *getImpl(LLVMContext &Context, unsigned Tag, - Metadata *Scope, Metadata *Entity, + MDScope *Scope, DebugNodeRef Entity, unsigned Line, StringRef Name, StorageType Storage, bool ShouldCreate = true) { @@ -1707,7 +2199,7 @@ class MDImportedEntity : public DebugNode { public: DEFINE_MDNODE_GET(MDImportedEntity, - (unsigned Tag, Metadata *Scope, Metadata *Entity, + (unsigned Tag, MDScope *Scope, DebugNodeRef Entity, unsigned Line, StringRef Name = ""), (Tag, Scope, Entity, Line, Name)) DEFINE_MDNODE_GET(MDImportedEntity, @@ -1718,10 +2210,12 @@ public: TempMDImportedEntity clone() const { return cloneImpl(); } unsigned getLine() const { return Line; } - Metadata *getScope() const { return getOperand(0); } - Metadata *getEntity() const { return getOperand(1); } + MDScope *getScope() const { return cast_or_null<MDScope>(getRawScope()); } + DebugNodeRef getEntity() const { return DebugNodeRef(getRawEntity()); } StringRef getName() const { return getStringOperand(2); } + Metadata *getRawScope() const { return getOperand(0); } + Metadata *getRawEntity() const { return getOperand(1); } MDString *getRawName() const { return getOperandAs<MDString>(2); } static bool classof(const Metadata *MD) { diff --git a/include/llvm/IR/DebugLoc.h b/include/llvm/IR/DebugLoc.h index c29d5bf..f88a7b1 100644 --- a/include/llvm/IR/DebugLoc.h +++ b/include/llvm/IR/DebugLoc.h @@ -22,11 +22,15 @@ namespace llvm { class LLVMContext; class raw_ostream; - class MDNode; - - /// DebugLoc - Debug location id. This is carried by Instruction, SDNode, - /// and MachineInstr to compactly encode file/line/scope information for an - /// operation. + class MDLocation; + + /// \brief A debug info location. + /// + /// This class is a wrapper around a tracking reference to an \a MDLocation + /// pointer. + /// + /// To avoid extra includes, \a DebugLoc doubles the \a MDLocation API with a + /// one based on relatively opaque \a MDNode pointers. class DebugLoc { TrackingMDNodeRef Loc; @@ -43,64 +47,76 @@ namespace llvm { return *this; } + /// \brief Construct from an \a MDLocation. + DebugLoc(const MDLocation *L); + + /// \brief Construct from an \a MDNode. + /// + /// Note: if \c N is not an \a MDLocation, a verifier check will fail, and + /// accessors will crash. However, construction from other nodes is + /// supported in order to handle forward references when reading textual + /// IR. + explicit DebugLoc(const MDNode *N); + + /// \brief Get the underlying \a MDLocation. + /// + /// \pre !*this or \c isa<MDLocation>(getAsMDNode()). + /// @{ + MDLocation *get() const; + operator MDLocation *() const { return get(); } + MDLocation *operator->() const { return get(); } + MDLocation &operator*() const { return *get(); } + /// @} + + /// \brief Check for null. + /// + /// Check for null in a way that is safe with broken debug info. Unlike + /// the conversion to \c MDLocation, this doesn't require that \c Loc is of + /// the right type. Important for cases like \a llvm::StripDebugInfo() and + /// \a Instruction::hasMetadata(). + explicit operator bool() const { return Loc; } + /// \brief Check whether this has a trivial destructor. bool hasTrivialDestructor() const { return Loc.hasTrivialDestructor(); } - /// get - Get a new DebugLoc that corresponds to the specified line/col - /// scope/inline location. - static DebugLoc get(unsigned Line, unsigned Col, MDNode *Scope, - MDNode *InlinedAt = nullptr); - - /// getFromDILocation - Translate the DILocation quad into a DebugLoc. - static DebugLoc getFromDILocation(MDNode *N); - - /// getFromDILexicalBlock - Translate the DILexicalBlock into a DebugLoc. - static DebugLoc getFromDILexicalBlock(MDNode *N); - - /// isUnknown - Return true if this is an unknown location. - bool isUnknown() const { return !Loc; } + /// \brief Create a new DebugLoc. + /// + /// Create a new DebugLoc at the specified line/col and scope/inline. This + /// forwards to \a MDLocation::get(). + /// + /// If \c !Scope, returns a default-constructed \a DebugLoc. + /// + /// FIXME: Remove this. Users should use MDLocation::get(). + static DebugLoc get(unsigned Line, unsigned Col, const MDNode *Scope, + const MDNode *InlinedAt = nullptr); unsigned getLine() const; unsigned getCol() const; - - /// getScope - This returns the scope pointer for this DebugLoc, or null if - /// invalid. MDNode *getScope() const; - MDNode *getScope(const LLVMContext &) const { return getScope(); } - - /// getInlinedAt - This returns the InlinedAt pointer for this DebugLoc, or - /// null if invalid or not present. - MDNode *getInlinedAt() const; - MDNode *getInlinedAt(const LLVMContext &) const { return getInlinedAt(); } - - /// getScopeAndInlinedAt - Return both the Scope and the InlinedAt values. - void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA) const; - void getScopeAndInlinedAt(MDNode *&Scope, MDNode *&IA, - const LLVMContext &) const { - return getScopeAndInlinedAt(Scope, IA); - } - - /// getScopeNode - Get MDNode for DebugLoc's scope, or null if invalid. - MDNode *getScopeNode() const; - MDNode *getScopeNode(const LLVMContext &) const { return getScopeNode(); } - - // getFnDebugLoc - Walk up the scope chain of given debug loc and find line - // number info for the function. + MDLocation *getInlinedAt() const; + + /// \brief Get the fully inlined-at scope for a DebugLoc. + /// + /// Gets the inlined-at scope for a DebugLoc. + MDNode *getInlinedAtScope() const; + + /// \brief Find the debug info location for the start of the function. + /// + /// Walk up the scope chain of given debug loc and find line number info + /// for the function. + /// + /// FIXME: Remove this. Users should use MDLocation/MDLocalScope API to + /// find the subprogram, and then MDLocation::get(). DebugLoc getFnDebugLoc() const; - DebugLoc getFnDebugLoc(const LLVMContext &) const { - return getFnDebugLoc(); - } - /// getAsMDNode - This method converts the compressed DebugLoc node into a - /// DILocation compatible MDNode. - MDNode *getAsMDNode() const; - MDNode *getAsMDNode(LLVMContext &) const { return getAsMDNode(); } + /// \brief Return \c this as a bar \a MDNode. + MDNode *getAsMDNode() const { return Loc; } bool operator==(const DebugLoc &DL) const { return Loc == DL.Loc; } - bool operator!=(const DebugLoc &DL) const { return !(*this == DL); } + bool operator!=(const DebugLoc &DL) const { return Loc != DL.Loc; } void dump() const; - void dump(const LLVMContext &) const { dump(); } + /// \brief prints source location /path/to/file.exe:line:col @[inlined at] void print(raw_ostream &OS) const; }; diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index 0cd5afb..a5eed9b 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -31,26 +31,6 @@ namespace llvm { class FunctionType; class LLVMContext; -// Traits for intrusive list of basic blocks... -template<> struct ilist_traits<BasicBlock> - : public SymbolTableListTraits<BasicBlock, Function> { - - // createSentinel is used to get hold of the node that marks the end of the - // list... (same trick used here as in ilist_traits<Instruction>) - BasicBlock *createSentinel() const { - return static_cast<BasicBlock*>(&Sentinel); - } - static void destroySentinel(BasicBlock*) {} - - BasicBlock *provideInitialHead() const { return createSentinel(); } - BasicBlock *ensureHead(BasicBlock*) const { return createSentinel(); } - static void noteHead(BasicBlock*, BasicBlock*) {} - - static ValueSymbolTable *getSymTab(Function *ItemParent); -private: - mutable ilist_half_node<BasicBlock> Sentinel; -}; - template<> struct ilist_traits<Argument> : public SymbolTableListTraits<Argument, Function> { @@ -86,6 +66,7 @@ private: mutable ArgumentListType ArgumentList; ///< The formal arguments ValueSymbolTable *SymTab; ///< Symbol table of args/instructions AttributeSet AttributeSets; ///< Parameter attributes + FunctionType *Ty; /* * Value::SubclassData @@ -133,7 +114,7 @@ public: return new(0) Function(Ty, Linkage, N, M); } - ~Function(); + ~Function() override; Type *getReturnType() const; // Return the type of the ret val FunctionType *getFunctionType() const; // Return the FunctionType for me @@ -242,6 +223,10 @@ public: /// @brief adds the dereferenceable attribute to the list of attributes. void addDereferenceableAttr(unsigned i, uint64_t Bytes); + /// @brief adds the dereferenceable_or_null attribute to the list of + /// attributes. + void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes); + /// @brief Extract the alignment for a call or parameter (0=unknown). unsigned getParamAlignment(unsigned i) const { return AttributeSets.getParamAlignment(i); @@ -472,6 +457,10 @@ public: Constant *getPrologueData() const; void setPrologueData(Constant *PrologueData); + /// Print the function to an output stream with an optional + /// AssemblyAnnotationWriter. + void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW = nullptr) const; + /// viewCFG - This function is meant for use from the debugger. You can just /// say 'call F->viewCFG()' and a ghostview window should pop up from the /// program, displaying the CFG of the current function with the code for each diff --git a/include/llvm/IR/GVMaterializer.h b/include/llvm/IR/GVMaterializer.h index ae2f2e1..779f2e0 100644 --- a/include/llvm/IR/GVMaterializer.h +++ b/include/llvm/IR/GVMaterializer.h @@ -54,6 +54,7 @@ public: virtual std::error_code MaterializeModule(Module *M) = 0; virtual std::error_code materializeMetadata() = 0; + virtual void setStripDebugInfo() = 0; virtual std::vector<StructType *> getIdentifiedStructTypes() const = 0; }; diff --git a/include/llvm/IR/GlobalObject.h b/include/llvm/IR/GlobalObject.h index 50deb08..f055241 100644 --- a/include/llvm/IR/GlobalObject.h +++ b/include/llvm/IR/GlobalObject.h @@ -27,7 +27,7 @@ class GlobalObject : public GlobalValue { GlobalObject(const GlobalObject &) = delete; protected: - GlobalObject(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, + GlobalObject(PointerType *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, LinkageTypes Linkage, const Twine &Name) : GlobalValue(Ty, VTy, Ops, NumOps, Linkage, Name), ObjComdat(nullptr) { setGlobalValueSubClassData(0); diff --git a/include/llvm/IR/GlobalValue.h b/include/llvm/IR/GlobalValue.h index 002e5e7..aeaaef4 100644 --- a/include/llvm/IR/GlobalValue.h +++ b/include/llvm/IR/GlobalValue.h @@ -61,7 +61,7 @@ public: }; protected: - GlobalValue(Type *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, + GlobalValue(PointerType *Ty, ValueTy VTy, Use *Ops, unsigned NumOps, LinkageTypes Linkage, const Twine &Name) : Constant(Ty, VTy, Ops, NumOps), Linkage(Linkage), Visibility(DefaultVisibility), UnnamedAddr(0), @@ -104,7 +104,7 @@ public: LocalExecTLSModel }; - ~GlobalValue() { + ~GlobalValue() override { removeDeadConstantUsers(); // remove any dead constants using this. } @@ -165,9 +165,9 @@ public: const char *getSection() const; /// Global values are always pointers. - inline PointerType *getType() const { - return cast<PointerType>(User::getType()); - } + PointerType *getType() const { return cast<PointerType>(User::getType()); } + + Type *getValueType() const { return getType()->getElementType(); } static LinkageTypes getLinkOnceLinkage(bool ODR) { return ODR ? LinkOnceODRLinkage : LinkOnceAnyLinkage; @@ -343,11 +343,11 @@ public: virtual void eraseFromParent() = 0; /// Get the module that this global value is contained inside of... - inline Module *getParent() { return Parent; } - inline const Module *getParent() const { return Parent; } + Module *getParent() { return Parent; } + const Module *getParent() const { return Parent; } // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const Value *V) { + static bool classof(const Value *V) { return V->getValueID() == Value::FunctionVal || V->getValueID() == Value::GlobalVariableVal || V->getValueID() == Value::GlobalAliasVal; diff --git a/include/llvm/IR/GlobalVariable.h b/include/llvm/IR/GlobalVariable.h index d7b81a2..9f57705 100644 --- a/include/llvm/IR/GlobalVariable.h +++ b/include/llvm/IR/GlobalVariable.h @@ -66,7 +66,7 @@ public: ThreadLocalMode = NotThreadLocal, unsigned AddressSpace = 0, bool isExternallyInitialized = false); - ~GlobalVariable() { + ~GlobalVariable() override { NumOperands = 1; // FIXME: needed by operator delete } diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index 617e2bc..9c4ba07 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -21,6 +21,7 @@ #include "llvm/IR/BasicBlock.h" #include "llvm/IR/ConstantFolder.h" #include "llvm/IR/DataLayout.h" +#include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Operator.h" @@ -123,7 +124,7 @@ public: /// \brief If this builder has a current debug location, set it on the /// specified instruction. void SetInstDebugLocation(Instruction *I) const { - if (!CurDbgLocation.isUnknown()) + if (CurDbgLocation) I->setDebugLoc(CurDbgLocation); } @@ -243,7 +244,7 @@ public: /// filled in with the null terminated string value specified. The new global /// variable will be marked mergable with any others of the same contents. If /// Name is specified, it is the name of the global variable created. - Value *CreateGlobalString(StringRef Str, const Twine &Name = ""); + GlobalVariable *CreateGlobalString(StringRef Str, const Twine &Name = ""); /// \brief Get a constant value representing either true or false. ConstantInt *getInt1(bool V) { @@ -1028,12 +1029,16 @@ public: if (!isa<Constant>(IdxList[i])) break; if (i == e) - return Insert(Folder.CreateGetElementPtr(PC, IdxList), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, IdxList), Name); } return Insert(GetElementPtrInst::Create(Ty, Ptr, IdxList), Name); } Value *CreateInBoundsGEP(Value *Ptr, ArrayRef<Value *> IdxList, const Twine &Name = "") { + return CreateInBoundsGEP(nullptr, Ptr, IdxList, Name); + } + Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, ArrayRef<Value *> IdxList, + const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) { // Every index must be constant. size_t i, e; @@ -1041,68 +1046,77 @@ public: if (!isa<Constant>(IdxList[i])) break; if (i == e) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, IdxList), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, IdxList), + Name); } - return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, IdxList), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, IdxList), Name); } Value *CreateGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { + return CreateGEP(nullptr, Ptr, Idx, Name); + } + Value *CreateGEP(Type *Ty, Value *Ptr, Value *Idx, const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Insert(Folder.CreateGetElementPtr(PC, IC), Name); - return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idx), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, IC), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name); } - Value *CreateInBoundsGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { + Value *CreateInBoundsGEP(Type *Ty, Value *Ptr, Value *Idx, + const Twine &Name = "") { if (Constant *PC = dyn_cast<Constant>(Ptr)) if (Constant *IC = dyn_cast<Constant>(Idx)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, IC), Name); - return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idx), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, IC), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name); } Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { + return CreateConstGEP1_32(nullptr, Ptr, Idx0, Name); + } + Value *CreateConstGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, + const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, Idx), Name); - return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idx), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, Idx), Name); } - Value *CreateConstInBoundsGEP1_32(Value *Ptr, unsigned Idx0, + Value *CreateConstInBoundsGEP1_32(Type *Ty, Value *Ptr, unsigned Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, Idx), Name); - return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idx), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idx), Name); } - Value *CreateConstGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, - const Twine &Name = "") { + Value *CreateConstGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, unsigned Idx1, + const Twine &Name = "") { Value *Idxs[] = { ConstantInt::get(Type::getInt32Ty(Context), Idx0), ConstantInt::get(Type::getInt32Ty(Context), Idx1) }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateGetElementPtr(Ty, PC, Idxs), Name); - return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idxs), Name); + return Insert(GetElementPtrInst::Create(Ty, Ptr, Idxs), Name); } - Value *CreateConstInBoundsGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, - const Twine &Name = "") { + Value *CreateConstInBoundsGEP2_32(Type *Ty, Value *Ptr, unsigned Idx0, + unsigned Idx1, const Twine &Name = "") { Value *Idxs[] = { ConstantInt::get(Type::getInt32Ty(Context), Idx0), ConstantInt::get(Type::getInt32Ty(Context), Idx1) }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(Ty, PC, Idxs), Name); - return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idxs), Name); + return Insert(GetElementPtrInst::CreateInBounds(Ty, Ptr, Idxs), Name); } Value *CreateConstGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateGetElementPtr(nullptr, PC, Idx), Name); return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idx), Name); } @@ -1111,7 +1125,7 @@ public: Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(nullptr, PC, Idx), Name); return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idx), Name); } @@ -1123,7 +1137,7 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateGetElementPtr(nullptr, PC, Idxs), Name); return Insert(GetElementPtrInst::Create(nullptr, Ptr, Idxs), Name); } @@ -1135,21 +1149,23 @@ public: }; if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name); + return Insert(Folder.CreateInBoundsGetElementPtr(nullptr, PC, Idxs), + Name); return Insert(GetElementPtrInst::CreateInBounds(nullptr, Ptr, Idxs), Name); } - Value *CreateStructGEP(Value *Ptr, unsigned Idx, const Twine &Name = "") { - return CreateConstInBoundsGEP2_32(Ptr, 0, Idx, Name); + Value *CreateStructGEP(Type *Ty, Value *Ptr, unsigned Idx, + const Twine &Name = "") { + return CreateConstInBoundsGEP2_32(Ty, Ptr, 0, Idx, Name); } /// \brief Same as CreateGlobalString, but return a pointer with "i8*" type /// instead of a pointer to array of i8. Value *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "") { - Value *gv = CreateGlobalString(Str, Name); + GlobalVariable *gv = CreateGlobalString(Str, Name); Value *zero = ConstantInt::get(Type::getInt32Ty(Context), 0); Value *Args[] = { zero, zero }; - return CreateInBoundsGEP(gv, Args, Name); + return CreateInBoundsGEP(gv->getValueType(), gv, Args, Name); } //===--------------------------------------------------------------------===// diff --git a/include/llvm/IR/IRPrintingPasses.h b/include/llvm/IR/IRPrintingPasses.h index 7f2027b..5f1d56f 100644 --- a/include/llvm/IR/IRPrintingPasses.h +++ b/include/llvm/IR/IRPrintingPasses.h @@ -34,7 +34,8 @@ class raw_ostream; /// \brief Create and return a pass that writes the module to the specified /// \c raw_ostream. ModulePass *createPrintModulePass(raw_ostream &OS, - const std::string &Banner = ""); + const std::string &Banner = "", + bool ShouldPreserveUseListOrder = false); /// \brief Create and return a pass that prints functions to the specified /// \c raw_ostream as they are processed. @@ -53,10 +54,12 @@ BasicBlockPass *createPrintBasicBlockPass(raw_ostream &OS, class PrintModulePass { raw_ostream &OS; std::string Banner; + bool ShouldPreserveUseListOrder; public: PrintModulePass(); - PrintModulePass(raw_ostream &OS, const std::string &Banner = ""); + PrintModulePass(raw_ostream &OS, const std::string &Banner = "", + bool ShouldPreserveUseListOrder = false); PreservedAnalyses run(Module &M); diff --git a/include/llvm/IR/InlineAsm.h b/include/llvm/IR/InlineAsm.h index 6ae4122..c8f25e7 100644 --- a/include/llvm/IR/InlineAsm.h +++ b/include/llvm/IR/InlineAsm.h @@ -51,7 +51,7 @@ private: InlineAsm(PointerType *Ty, const std::string &AsmString, const std::string &Constraints, bool hasSideEffects, bool isAlignStack, AsmDialect asmDialect); - virtual ~InlineAsm(); + ~InlineAsm() override; /// When the ConstantUniqueMap merges two types and makes two InlineAsms /// identical, it destroys one of them with this method. diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index 3a33f43..108b9eb 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -44,7 +44,7 @@ protected: : Instruction(Ty, iType, Ops, NumOps, InsertAtEnd) {} // Out of line virtual method, so the vtable, etc has a home. - ~TerminatorInst(); + ~TerminatorInst() override; /// Virtual methods - Terminators should overload these and provide inline /// overrides of non-V methods. @@ -102,7 +102,7 @@ public: } // Out of line virtual method, so the vtable, etc has a home. - ~UnaryInstruction(); + ~UnaryInstruction() override; /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); diff --git a/include/llvm/IR/Instruction.h b/include/llvm/IR/Instruction.h index dc96b57..9dd16fd 100644 --- a/include/llvm/IR/Instruction.h +++ b/include/llvm/IR/Instruction.h @@ -18,6 +18,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ilist_node.h" #include "llvm/IR/DebugLoc.h" +#include "llvm/IR/SymbolTableListTraits.h" #include "llvm/IR/User.h" namespace llvm { @@ -25,10 +26,27 @@ namespace llvm { class FastMathFlags; class LLVMContext; class MDNode; +class BasicBlock; struct AAMDNodes; -template<typename ValueSubClass, typename ItemParentClass> - class SymbolTableListTraits; +template <> +struct ilist_traits<Instruction> + : public SymbolTableListTraits<Instruction, BasicBlock> { + + /// \brief Return a node that marks the end of a list. + /// + /// The sentinel is relative to this instance, so we use a non-static + /// method. + Instruction *createSentinel() const; + static void destroySentinel(Instruction *) {} + + Instruction *provideInitialHead() const { return createSentinel(); } + Instruction *ensureHead(Instruction *) const { return createSentinel(); } + static void noteHead(Instruction *, Instruction *) {} + +private: + mutable ilist_half_node<Instruction> Sentinel; +}; class Instruction : public User, public ilist_node<Instruction> { void operator=(const Instruction &) = delete; @@ -44,7 +62,7 @@ class Instruction : public User, public ilist_node<Instruction> { }; public: // Out of line virtual method, so the vtable, etc has a home. - ~Instruction(); + ~Instruction() override; /// user_back - Specialize the methods defined in Value, as we know that an /// instruction can only be used by other instructions. @@ -69,7 +87,8 @@ public: /// eraseFromParent - This method unlinks 'this' from the containing basic /// block and deletes it. /// - void eraseFromParent(); + /// \returns an iterator pointing to the element after the erased one + iplist<Instruction>::iterator eraseFromParent(); /// insertBefore - Insert an unlinked instructions into a basic block /// immediately before the specified instruction. @@ -134,9 +153,7 @@ public: /// hasMetadata() - Return true if this instruction has any metadata attached /// to it. - bool hasMetadata() const { - return !DbgLoc.isUnknown() || hasMetadataHashEntry(); - } + bool hasMetadata() const { return DbgLoc || hasMetadataHashEntry(); } /// hasMetadataOtherThanDebugLoc - Return true if this instruction has /// metadata attached to it other than a debug location. @@ -495,6 +512,17 @@ protected: }; +inline Instruction *ilist_traits<Instruction>::createSentinel() const { + // Since i(p)lists always publicly derive from their corresponding traits, + // placing a data member in this class will augment the i(p)list. But since + // the NodeTy is expected to be publicly derive from ilist_node<NodeTy>, + // there is a legal viable downcast from it to NodeTy. We use this trick to + // superimpose an i(p)list with a "ghostly" NodeTy, which becomes the + // sentinel. Dereferencing the sentinel is forbidden (save the + // ilist_node<NodeTy>), so no one will ever notice the superposition. + return static_cast<Instruction *>(&Sentinel); +} + // Instruction* is only 4-byte aligned. template<> class PointerLikeTypeTraits<Instruction*> { diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 52fa360..1f2ca30 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -91,7 +91,7 @@ public: const Twine &Name, BasicBlock *InsertAtEnd); // Out of line virtual method, so the vtable, etc. has a home. - virtual ~AllocaInst(); + ~AllocaInst() override; /// isArrayAllocation - Return true if there is an allocation size parameter /// to the allocation instruction that is not 1. @@ -180,7 +180,12 @@ public: unsigned Align, Instruction *InsertBefore = nullptr); LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, BasicBlock *InsertAtEnd); - LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, + LoadInst(Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, + AtomicOrdering Order, SynchronizationScope SynchScope = CrossThread, + Instruction *InsertBefore = nullptr) + : LoadInst(cast<PointerType>(Ptr->getType())->getElementType(), Ptr, + NameStr, isVolatile, Align, Order, SynchScope, InsertBefore) {} + LoadInst(Type *Ty, Value *Ptr, const Twine &NameStr, bool isVolatile, unsigned Align, AtomicOrdering Order, SynchronizationScope SynchScope = CrossThread, Instruction *InsertBefore = nullptr); @@ -882,9 +887,9 @@ public: /// Null is returned if the indices are invalid for the specified /// pointer type. /// - static Type *getIndexedType(Type *Ptr, ArrayRef<Value *> IdxList); - static Type *getIndexedType(Type *Ptr, ArrayRef<Constant *> IdxList); - static Type *getIndexedType(Type *Ptr, ArrayRef<uint64_t> IdxList); + static Type *getIndexedType(Type *Ty, ArrayRef<Value *> IdxList); + static Type *getIndexedType(Type *Ty, ArrayRef<Constant *> IdxList); + static Type *getIndexedType(Type *Ty, ArrayRef<uint64_t> IdxList); inline op_iterator idx_begin() { return op_begin()+1; } inline const_op_iterator idx_begin() const { return op_begin()+1; } @@ -915,9 +920,12 @@ public: /// GetGEPReturnType - Returns the pointer type returned by the GEP /// instruction, which may be a vector of pointers. static Type *getGEPReturnType(Value *Ptr, ArrayRef<Value *> IdxList) { - Type *PtrTy = PointerType::get(checkGEPType( - getIndexedType(Ptr->getType(), IdxList)), - Ptr->getType()->getPointerAddressSpace()); + Type *PtrTy = + PointerType::get(checkGEPType(getIndexedType( + cast<PointerType>(Ptr->getType()->getScalarType()) + ->getElementType(), + IdxList)), + Ptr->getType()->getPointerAddressSpace()); // Vector GEP if (Ptr->getType()->isVectorTy()) { unsigned NumElem = cast<VectorType>(Ptr->getType())->getNumElements(); @@ -1327,7 +1335,11 @@ public: static Instruction* CreateFree(Value* Source, Instruction *InsertBefore); static Instruction* CreateFree(Value* Source, BasicBlock *InsertAtEnd); - ~CallInst(); + ~CallInst() override; + + Type *getFunctionType() const { + return cast<PointerType>(getCalledValue()->getType())->getElementType(); + } // Note that 'musttail' implies 'tail'. enum TailCallKind { TCK_None = 0, TCK_Tail = 1, TCK_MustTail = 2 }; @@ -1404,6 +1416,10 @@ public: /// \brief adds the dereferenceable attribute to the list of attributes. void addDereferenceableAttr(unsigned i, uint64_t Bytes); + /// \brief adds the dereferenceable_or_null attribute to the list of + /// attributes. + void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes); + /// \brief Determine whether this call has the given attribute. bool hasFnAttr(Attribute::AttrKind A) const { assert(A != Attribute::NoBuiltin && @@ -2167,7 +2183,7 @@ public: const Twine &NameStr, BasicBlock *InsertAtEnd) { return new PHINode(Ty, NumReservedValues, NameStr, InsertAtEnd); } - ~PHINode(); + ~PHINode() override; /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2358,7 +2374,7 @@ public: static LandingPadInst *Create(Type *RetTy, Value *PersonalityFn, unsigned NumReservedClauses, const Twine &NameStr, BasicBlock *InsertAtEnd); - ~LandingPadInst(); + ~LandingPadInst() override; /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2460,7 +2476,7 @@ public: static ReturnInst* Create(LLVMContext &C, BasicBlock *InsertAtEnd) { return new(0) ReturnInst(C, InsertAtEnd); } - virtual ~ReturnInst(); + ~ReturnInst() override; /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2757,7 +2773,7 @@ public: return new SwitchInst(Value, Default, NumCases, InsertAtEnd); } - ~SwitchInst(); + ~SwitchInst() override; /// Provide fast operand accessors DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -2943,7 +2959,7 @@ public: BasicBlock *InsertAtEnd) { return new IndirectBrInst(Address, NumDests, InsertAtEnd); } - ~IndirectBrInst(); + ~IndirectBrInst() override; /// Provide fast operand accessors. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -3093,9 +3109,13 @@ public: /// removeAttribute - removes the attribute from the list of attributes. void removeAttribute(unsigned i, Attribute attr); - /// \brief removes the dereferenceable attribute to the list of attributes. + /// \brief adds the dereferenceable attribute to the list of attributes. void addDereferenceableAttr(unsigned i, uint64_t Bytes); + /// \brief adds the dereferenceable_or_null attribute to the list of + /// attributes. + void addDereferenceableOrNullAttr(unsigned i, uint64_t Bytes); + /// \brief Determine whether this call has the given attribute. bool hasFnAttr(Attribute::AttrKind A) const { assert(A != Attribute::NoBuiltin && diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index da9d8cb..4052a31 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -421,10 +421,6 @@ def int_eh_endcatch : Intrinsic<[], []>; // Represents the list of actions to take when an exception is thrown. def int_eh_actions : Intrinsic<[llvm_ptr_ty], [llvm_vararg_ty], []>; -// Designates the provided static alloca as the unwind help object. Required -// for WinEH. -def int_eh_unwindhelp : Intrinsic<[], [llvm_ptr_ty], []>; - // __builtin_unwind_init is an undocumented GCC intrinsic that causes all // callee-saved registers to be saved and restored (regardless of whether they // are used) in the calling function. It is used by libgcc_eh. @@ -630,3 +626,4 @@ include "llvm/IR/IntrinsicsNVVM.td" include "llvm/IR/IntrinsicsMips.td" include "llvm/IR/IntrinsicsR600.td" include "llvm/IR/IntrinsicsBPF.td" +include "llvm/IR/IntrinsicsSystemZ.td" diff --git a/include/llvm/IR/IntrinsicsBPF.td b/include/llvm/IR/IntrinsicsBPF.td index 6b5110b..94eca8e 100644 --- a/include/llvm/IR/IntrinsicsBPF.td +++ b/include/llvm/IR/IntrinsicsBPF.td @@ -19,4 +19,6 @@ let TargetPrefix = "bpf" in { // All intrinsics start with "llvm.bpf." Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; def int_bpf_load_word : GCCBuiltin<"__builtin_bpf_load_word">, Intrinsic<[llvm_i64_ty], [llvm_ptr_ty, llvm_i64_ty], [IntrReadMem]>; + def int_bpf_pseudo : GCCBuiltin<"__builtin_bpf_pseudo">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty]>; } diff --git a/include/llvm/IR/IntrinsicsPowerPC.td b/include/llvm/IR/IntrinsicsPowerPC.td index 95fc3e5..74c0172 100644 --- a/include/llvm/IR/IntrinsicsPowerPC.td +++ b/include/llvm/IR/IntrinsicsPowerPC.td @@ -37,6 +37,25 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". // generated by the PowerPC backend! def int_ppc_mtctr : Intrinsic<[], [llvm_anyint_ty], []>; def int_ppc_is_decremented_ctr_nonzero : Intrinsic<[llvm_i1_ty], [], []>; + + // Intrinsics for [double]word extended forms of divide instructions + def int_ppc_divwe : GCCBuiltin<"__builtin_divwe">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_divweu : GCCBuiltin<"__builtin_divweu">, + Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_divde : GCCBuiltin<"__builtin_divde">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; + def int_ppc_divdeu : GCCBuiltin<"__builtin_divdeu">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; + + // Bit permute doubleword + def int_ppc_bpermd : GCCBuiltin<"__builtin_bpermd">, + Intrinsic<[llvm_i64_ty], [llvm_i64_ty, llvm_i64_ty], + [IntrNoMem]>; } @@ -563,11 +582,12 @@ let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". Intrinsic<[llvm_v16i8_ty], [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], [IntrNoMem]>; -// These need diagnostics for invalid arguments so don't inherit from GCCBuiltin def int_ppc_altivec_crypto_vshasigmad : + GCCBuiltin<"__builtin_altivec_crypto_vshasigmad">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; def int_ppc_altivec_crypto_vshasigmaw : + GCCBuiltin<"__builtin_altivec_crypto_vshasigmaw">, Intrinsic<[llvm_v4i32_ty], [llvm_v4i32_ty, llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; } @@ -801,20 +821,20 @@ let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". -def int_ppc_tbegin : +def int_ppc_tbegin : GCCBuiltin<"__builtin_tbegin">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; -def int_ppc_tend : +def int_ppc_tend : GCCBuiltin<"__builtin_tend">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; def int_ppc_tabort : GCCBuiltin<"__builtin_tabort">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; -def int_ppc_tabortwc : +def int_ppc_tabortwc : GCCBuiltin<"__builtin_tabortwc">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; -def int_ppc_tabortwci : +def int_ppc_tabortwci : GCCBuiltin<"__builtin_tabortwci">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; -def int_ppc_tabortdc : +def int_ppc_tabortdc : GCCBuiltin<"__builtin_tabortdc">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; -def int_ppc_tabortdci : +def int_ppc_tabortdci : GCCBuiltin<"__builtin_tabortdci">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, llvm_i32_ty], []>; def int_ppc_tcheck : GCCBuiltin<"__builtin_tcheck">, @@ -823,7 +843,7 @@ def int_ppc_treclaim : GCCBuiltin<"__builtin_treclaim">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; def int_ppc_trechkpt : GCCBuiltin<"__builtin_trechkpt">, Intrinsic<[llvm_i32_ty], [], []>; -def int_ppc_tsr : +def int_ppc_tsr : GCCBuiltin<"__builtin_tsr">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty], []>; def int_ppc_get_texasr : GCCBuiltin<"__builtin_get_texasr">, diff --git a/include/llvm/IR/IntrinsicsSystemZ.td b/include/llvm/IR/IntrinsicsSystemZ.td new file mode 100644 index 0000000..6883db3 --- /dev/null +++ b/include/llvm/IR/IntrinsicsSystemZ.td @@ -0,0 +1,46 @@ +//===- IntrinsicsSystemZ.td - Defines SystemZ intrinsics ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the SystemZ-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// +// Transactional-execution intrinsics +// +//===----------------------------------------------------------------------===// + +let TargetPrefix = "s390" in { + def int_s390_tbegin : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty, llvm_i32_ty], + [IntrNoDuplicate]>; + + def int_s390_tbegin_nofloat : Intrinsic<[llvm_i32_ty], + [llvm_ptr_ty, llvm_i32_ty], + [IntrNoDuplicate]>; + + def int_s390_tbeginc : Intrinsic<[], [llvm_ptr_ty, llvm_i32_ty], + [IntrNoDuplicate]>; + + def int_s390_tabort : Intrinsic<[], [llvm_i64_ty], + [IntrNoReturn, Throws]>; + + def int_s390_tend : GCCBuiltin<"__builtin_tend">, + Intrinsic<[llvm_i32_ty], []>; + + def int_s390_etnd : GCCBuiltin<"__builtin_tx_nesting_depth">, + Intrinsic<[llvm_i32_ty], [], [IntrNoMem]>; + + def int_s390_ntstg : Intrinsic<[], [llvm_i64_ty, llvm_ptr64_ty], + [IntrReadWriteArgMem]>; + + def int_s390_ppa_txassist : GCCBuiltin<"__builtin_tx_assist">, + Intrinsic<[], [llvm_i32_ty]>; +} + diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 39b8e3b..49231d8 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -1408,12 +1408,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw256">, Intrinsic<[llvm_v4i64_ty], [llvm_v32i8_ty, llvm_v32i8_ty], [IntrNoMem, Commutative]>; - def int_x86_avx512_mask_pmulu_dq_512 : GCCBuiltin<"__builtin_ia32_pmuludq512_mask">, - Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pmul_dq_512 : GCCBuiltin<"__builtin_ia32_pmuldq512_mask">, - Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; } // Vector min, max @@ -3093,7 +3087,27 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". Intrinsic<[llvm_v8i64_ty], [llvm_v8i32_ty], [IntrNoMem]>; } - +//Bitwise Ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_avx512_mask_pand_d_512 : GCCBuiltin<"__builtin_ia32_pandd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pand_q_512 : GCCBuiltin<"__builtin_ia32_pandq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_d_512 : GCCBuiltin<"__builtin_ia32_pord512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_por_q_512 : GCCBuiltin<"__builtin_ia32_porq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_d_512 : GCCBuiltin<"__builtin_ia32_pxord512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pxor_q_512 : GCCBuiltin<"__builtin_ia32_pxorq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; +} // Arithmetic ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". @@ -3222,6 +3236,27 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". [IntrNoMem]>; } +// Integer arithmetic ops +let TargetPrefix = "x86" in { + def int_x86_avx512_mask_padd_d_512 : GCCBuiltin<"__builtin_ia32_paddd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_padd_q_512 : GCCBuiltin<"__builtin_ia32_paddq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_d_512 : GCCBuiltin<"__builtin_ia32_psubd512_mask">, + Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v16i32_ty, llvm_i16_ty], [IntrNoMem]>; + def int_x86_avx512_mask_psub_q_512 : GCCBuiltin<"__builtin_ia32_psubq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmulu_dq_512 : GCCBuiltin<"__builtin_ia32_pmuludq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_avx512_mask_pmul_dq_512 : GCCBuiltin<"__builtin_ia32_pmuldq512_mask">, + Intrinsic<[llvm_v8i64_ty], [llvm_v16i32_ty, llvm_v16i32_ty, + llvm_v8i64_ty, llvm_i8_ty], [IntrNoMem]>; +} // Gather and Scatter ops let TargetPrefix = "x86" in { def int_x86_avx512_gather_dpd_512 : GCCBuiltin<"__builtin_ia32_gathersiv8df">, @@ -3813,14 +3848,6 @@ let TargetPrefix = "x86" in { def int_x86_avx512_mask_cmp_pd_512 : GCCBuiltin<"__builtin_ia32_cmppd512_mask">, Intrinsic<[llvm_i8_ty], [llvm_v8f64_ty, llvm_v8f64_ty, llvm_i8_ty, llvm_i8_ty, llvm_i32_ty], [IntrNoMem]>; - def int_x86_avx512_mask_pand_d_512 : GCCBuiltin<"__builtin_ia32_pandd512_mask">, - Intrinsic<[llvm_v16i32_ty], [llvm_v16i32_ty, llvm_v16i32_ty, - llvm_v16i32_ty, llvm_i16_ty], - [IntrNoMem]>; - def int_x86_avx512_mask_pand_q_512 : GCCBuiltin<"__builtin_ia32_pandq512_mask">, - Intrinsic<[llvm_v8i64_ty], [llvm_v8i64_ty, llvm_v8i64_ty, - llvm_v8i64_ty, llvm_i8_ty], - [IntrNoMem]>; def int_x86_avx512_movntdqa : GCCBuiltin<"__builtin_ia32_movntdqa512">, Intrinsic<[llvm_v8i64_ty], [llvm_ptr_ty], [IntrReadMem]>; } diff --git a/include/llvm/IR/LegacyPassManager.h b/include/llvm/IR/LegacyPassManager.h index 6c04e9d..5257a0e 100644 --- a/include/llvm/IR/LegacyPassManager.h +++ b/include/llvm/IR/LegacyPassManager.h @@ -50,7 +50,7 @@ class PassManager : public PassManagerBase { public: PassManager(); - ~PassManager(); + ~PassManager() override; void add(Pass *P) override; @@ -70,7 +70,7 @@ public: /// FunctionPassManager ctor - This initializes the pass manager. It needs, /// but does not take ownership of, the specified Module. explicit FunctionPassManager(Module *M); - ~FunctionPassManager(); + ~FunctionPassManager() override; void add(Pass *P) override; diff --git a/include/llvm/IR/LegacyPassNameParser.h b/include/llvm/IR/LegacyPassNameParser.h index 52db1c3..39ae80d 100644 --- a/include/llvm/IR/LegacyPassNameParser.h +++ b/include/llvm/IR/LegacyPassNameParser.h @@ -43,7 +43,7 @@ class PassNameParser : public PassRegistrationListener, public cl::parser<const PassInfo*> { public: PassNameParser(cl::Option &O); - virtual ~PassNameParser(); + ~PassNameParser() override; void initialize() { cl::parser<const PassInfo*>::initialize(); diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index a31bdbf..03e70fe 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -89,7 +89,7 @@ protected: Metadata(unsigned ID, StorageType Storage) : SubclassID(ID), Storage(Storage), SubclassData16(0), SubclassData32(0) { } - ~Metadata() {} + ~Metadata() = default; /// \brief Default handling of a changed operand, which asserts. /// @@ -164,7 +164,7 @@ class MetadataAsValue : public Value { Metadata *MD; MetadataAsValue(Type *Ty, Metadata *MD); - ~MetadataAsValue(); + ~MetadataAsValue() override; /// \brief Drop use of metadata (during teardown). void dropUse() { MD = nullptr; } @@ -253,7 +253,7 @@ protected: : Metadata(ID, Uniqued), ReplaceableMetadataImpl(V->getContext()), V(V) { assert(V && "Expected valid value"); } - ~ValueAsMetadata() {} + ~ValueAsMetadata() = default; public: static ValueAsMetadata *get(Value *V); @@ -754,13 +754,18 @@ protected: MDNode(LLVMContext &Context, unsigned ID, StorageType Storage, ArrayRef<Metadata *> Ops1, ArrayRef<Metadata *> Ops2 = None); - ~MDNode() {} + ~MDNode() = default; void dropAllReferences(); MDOperand *mutable_begin() { return mutable_end() - NumOperands; } MDOperand *mutable_end() { return reinterpret_cast<MDOperand *>(this); } + typedef iterator_range<MDOperand *> mutable_op_range; + mutable_op_range mutable_operands() { + return mutable_op_range(mutable_begin(), mutable_end()); + } + public: static inline MDTuple *get(LLVMContext &Context, ArrayRef<Metadata *> MDs); static inline MDTuple *getIfExists(LLVMContext &Context, @@ -1028,6 +1033,78 @@ void TempMDNodeDeleter::operator()(MDNode *Node) const { MDNode::deleteTemporary(Node); } +/// \brief Typed iterator through MDNode operands. +/// +/// An iterator that transforms an \a MDNode::iterator into an iterator over a +/// particular Metadata subclass. +template <class T> +class TypedMDOperandIterator + : std::iterator<std::input_iterator_tag, T *, std::ptrdiff_t, void, T *> { + MDNode::op_iterator I = nullptr; + +public: + TypedMDOperandIterator() = default; + explicit TypedMDOperandIterator(MDNode::op_iterator I) : I(I) {} + T *operator*() const { return cast_or_null<T>(*I); } + TypedMDOperandIterator &operator++() { + ++I; + return *this; + } + TypedMDOperandIterator operator++(int) { + TypedMDOperandIterator Temp(*this); + ++I; + return Temp; + } + bool operator==(const TypedMDOperandIterator &X) const { return I == X.I; } + bool operator!=(const TypedMDOperandIterator &X) const { return I != X.I; } +}; + +/// \brief Typed, array-like tuple of metadata. +/// +/// This is a wrapper for \a MDTuple that makes it act like an array holding a +/// particular type of metadata. +template <class T> class MDTupleTypedArrayWrapper { + const MDTuple *N = nullptr; + +public: + MDTupleTypedArrayWrapper() = default; + MDTupleTypedArrayWrapper(const MDTuple *N) : N(N) {} + + template <class U> + MDTupleTypedArrayWrapper( + const MDTupleTypedArrayWrapper<U> &Other, + typename std::enable_if<std::is_convertible<U *, T *>::value>::type * = + nullptr) + : N(Other.get()) {} + + template <class U> + explicit MDTupleTypedArrayWrapper( + const MDTupleTypedArrayWrapper<U> &Other, + typename std::enable_if<!std::is_convertible<U *, T *>::value>::type * = + nullptr) + : N(Other.get()) {} + + explicit operator bool() const { return get(); } + explicit operator MDTuple *() const { return get(); } + + MDTuple *get() const { return const_cast<MDTuple *>(N); } + MDTuple *operator->() const { return get(); } + MDTuple &operator*() const { return *get(); } + + // FIXME: Fix callers and remove condition on N. + unsigned size() const { return N ? N->getNumOperands() : 0u; } + T *operator[](unsigned I) const { return cast_or_null<T>(N->getOperand(I)); } + + // FIXME: Fix callers and remove condition on N. + typedef TypedMDOperandIterator<T> iterator; + iterator begin() const { return N ? iterator(N->op_begin()) : iterator(); } + iterator end() const { return N ? iterator(N->op_end()) : iterator(); } +}; + +#define HANDLE_METADATA(CLASS) \ + typedef MDTupleTypedArrayWrapper<CLASS> CLASS##Array; +#include "llvm/IR/Metadata.def" + //===----------------------------------------------------------------------===// /// \brief A tuple of MDNodes. /// diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index ac60c8e..dbaf322 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -642,8 +642,11 @@ public: /// @{ /// Print the module to an output stream with an optional - /// AssemblyAnnotationWriter. - void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW) const; + /// AssemblyAnnotationWriter. If \c ShouldPreserveUseListOrder, then include + /// uselistorder directives so that use-lists can be recreated when reading + /// the assembly. + void print(raw_ostream &OS, AssemblyAnnotationWriter *AAW, + bool ShouldPreserveUseListOrder = false) const; /// Dump the module to stderr (for debugging). void dump() const; diff --git a/include/llvm/IR/NoFolder.h b/include/llvm/IR/NoFolder.h index ab7bed6..61f4817 100644 --- a/include/llvm/IR/NoFolder.h +++ b/include/llvm/IR/NoFolder.h @@ -177,34 +177,35 @@ public: // Memory Instructions //===--------------------------------------------------------------------===// - Constant *CreateGetElementPtr(Constant *C, + Constant *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getGetElementPtr(C, IdxList); + return ConstantExpr::getGetElementPtr(Ty, C, IdxList); } - Constant *CreateGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateGetElementPtr(Type *Ty, Constant *C, Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return ConstantExpr::getGetElementPtr(C, Idx); + return ConstantExpr::getGetElementPtr(Ty, C, Idx); } - Instruction *CreateGetElementPtr(Constant *C, + Instruction *CreateGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return GetElementPtrInst::Create(nullptr, C, IdxList); + return GetElementPtrInst::Create(Ty, C, IdxList); } - Constant *CreateInBoundsGetElementPtr(Constant *C, + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Constant *> IdxList) const { - return ConstantExpr::getInBoundsGetElementPtr(C, IdxList); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, IdxList); } - Constant *CreateInBoundsGetElementPtr(Constant *C, Constant *Idx) const { + Constant *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, + Constant *Idx) const { // This form of the function only exists to avoid ambiguous overload // warnings about whether to convert Idx to ArrayRef<Constant *> or // ArrayRef<Value *>. - return ConstantExpr::getInBoundsGetElementPtr(C, Idx); + return ConstantExpr::getInBoundsGetElementPtr(Ty, C, Idx); } - Instruction *CreateInBoundsGetElementPtr(Constant *C, + Instruction *CreateInBoundsGetElementPtr(Type *Ty, Constant *C, ArrayRef<Value *> IdxList) const { - return GetElementPtrInst::CreateInBounds(nullptr, C, IdxList); + return GetElementPtrInst::CreateInBounds(Ty, C, IdxList); } //===--------------------------------------------------------------------===// diff --git a/include/llvm/IR/Operator.h b/include/llvm/IR/Operator.h index c87f89c..8c3afdd 100644 --- a/include/llvm/IR/Operator.h +++ b/include/llvm/IR/Operator.h @@ -42,7 +42,7 @@ protected: // NOTE: Cannot use = delete because it's not legal to delete // an overridden method that's not deleted in the base class. Cannot leave // this unimplemented because that leads to an ODR-violation. - ~Operator(); + ~Operator() override; public: /// Return the opcode for this Instruction or ConstantExpr. @@ -181,17 +181,17 @@ public: { } /// Whether any flag is set - bool any() { return Flags != 0; } + bool any() const { return Flags != 0; } /// Set all the flags to false void clear() { Flags = 0; } /// Flag queries - bool noNaNs() { return 0 != (Flags & NoNaNs); } - bool noInfs() { return 0 != (Flags & NoInfs); } - bool noSignedZeros() { return 0 != (Flags & NoSignedZeros); } - bool allowReciprocal() { return 0 != (Flags & AllowReciprocal); } - bool unsafeAlgebra() { return 0 != (Flags & UnsafeAlgebra); } + bool noNaNs() const { return 0 != (Flags & NoNaNs); } + bool noInfs() const { return 0 != (Flags & NoInfs); } + bool noSignedZeros() const { return 0 != (Flags & NoSignedZeros); } + bool allowReciprocal() const { return 0 != (Flags & AllowReciprocal); } + bool unsafeAlgebra() const { return 0 != (Flags & UnsafeAlgebra); } /// Flag setters void setNoNaNs() { Flags |= NoNaNs; } diff --git a/include/llvm/IR/PatternMatch.h b/include/llvm/IR/PatternMatch.h index f94e105..41154e6 100644 --- a/include/llvm/IR/PatternMatch.h +++ b/include/llvm/IR/PatternMatch.h @@ -295,6 +295,9 @@ template <typename Class> struct bind_ty { /// \brief Match a value, capturing it if we match. inline bind_ty<Value> m_Value(Value *&V) { return V; } +/// \brief Match an instruction, capturing it if we match. +inline bind_ty<Instruction> m_Instruction(Instruction *&I) { return I; } + /// \brief Match a binary operator, capturing it if we match. inline bind_ty<BinaryOperator> m_BinOp(BinaryOperator *&I) { return I; } @@ -1103,6 +1106,52 @@ m_UnordFMax(const LHS &L, const RHS &R) { return MaxMin_match<FCmpInst, LHS, RHS, ufmax_pred_ty>(L, R); } +//===----------------------------------------------------------------------===// +// Matchers for overflow check patterns: e.g. (a + b) u< a +// + +template <typename LHS_t, typename RHS_t, typename Sum_t> +struct UAddWithOverflow_match { + LHS_t L; + RHS_t R; + Sum_t S; + + UAddWithOverflow_match(const LHS_t &L, const RHS_t &R, const Sum_t &S) + : L(L), R(R), S(S) {} + + template <typename OpTy> bool match(OpTy *V) { + Value *ICmpLHS, *ICmpRHS; + ICmpInst::Predicate Pred; + if (!m_ICmp(Pred, m_Value(ICmpLHS), m_Value(ICmpRHS)).match(V)) + return false; + + Value *AddLHS, *AddRHS; + auto AddExpr = m_Add(m_Value(AddLHS), m_Value(AddRHS)); + + // (a + b) u< a, (a + b) u< b + if (Pred == ICmpInst::ICMP_ULT) + if (AddExpr.match(ICmpLHS) && (ICmpRHS == AddLHS || ICmpRHS == AddRHS)) + return L.match(AddLHS) && R.match(AddRHS) && S.match(ICmpLHS); + + // a >u (a + b), b >u (a + b) + if (Pred == ICmpInst::ICMP_UGT) + if (AddExpr.match(ICmpRHS) && (ICmpLHS == AddLHS || ICmpLHS == AddRHS)) + return L.match(AddLHS) && R.match(AddRHS) && S.match(ICmpRHS); + + return false; + } +}; + +/// \brief Match an icmp instruction checking for unsigned overflow on addition. +/// +/// S is matched to the addition whose result is being checked for overflow, and +/// L and R are matched to the LHS and RHS of S. +template <typename LHS_t, typename RHS_t, typename Sum_t> +UAddWithOverflow_match<LHS_t, RHS_t, Sum_t> +m_UAddWithOverflow(const LHS_t &L, const RHS_t &R, const Sum_t &S) { + return UAddWithOverflow_match<LHS_t, RHS_t, Sum_t>(L, R, S); +} + /// \brief Match an 'unordered' floating point minimum function. /// Floating point has one special value 'NaN'. Therefore, there is no total /// order. However, if we can ignore the 'NaN' value (for example, because of a diff --git a/include/llvm/IR/Type.h b/include/llvm/IR/Type.h index c2073c7..09b6388 100644 --- a/include/llvm/IR/Type.h +++ b/include/llvm/IR/Type.h @@ -91,8 +91,8 @@ protected: NumContainedTys(0), ContainedTys(nullptr) { setTypeID(tid); } - ~Type() {} - + ~Type() = default; + void setTypeID(TypeID ID) { IDAndSubclassData = (ID & 0xFF) | (IDAndSubclassData & 0xFFFFFF00); assert(getTypeID() == ID && "TypeID data too large for field"); diff --git a/include/llvm/IR/UseListOrder.h b/include/llvm/IR/UseListOrder.h index 7d8205d..b7c2418 100644 --- a/include/llvm/IR/UseListOrder.h +++ b/include/llvm/IR/UseListOrder.h @@ -51,12 +51,6 @@ private: typedef std::vector<UseListOrder> UseListOrderStack; -/// \brief Whether to preserve use-list ordering. -bool shouldPreserveBitcodeUseListOrder(); -bool shouldPreserveAssemblyUseListOrder(); -void setPreserveBitcodeUseListOrder(bool ShouldPreserve); -void setPreserveAssemblyUseListOrder(bool ShouldPreserve); - } // end namespace llvm #endif diff --git a/include/llvm/IR/User.h b/include/llvm/IR/User.h index d39378d..4559005 100644 --- a/include/llvm/IR/User.h +++ b/include/llvm/IR/User.h @@ -60,9 +60,7 @@ protected: NumOperands = 0; } public: - ~User() { - Use::zap(OperandList, OperandList + NumOperands); - } + ~User() override { Use::zap(OperandList, OperandList + NumOperands); } /// \brief Free memory allocated for User and Use objects. void operator delete(void *Usr); /// \brief Placement delete - required by std, but never called. diff --git a/include/llvm/IR/ValueMap.h b/include/llvm/IR/ValueMap.h index 08d6d17..4d00b63 100644 --- a/include/llvm/IR/ValueMap.h +++ b/include/llvm/IR/ValueMap.h @@ -99,8 +99,6 @@ public: explicit ValueMap(const ExtraData &Data, unsigned NumInitBuckets = 64) : Map(NumInitBuckets), Data(Data) {} - ~ValueMap() {} - bool hasMD() const { return MDMap; } MDMapT &MD() { if (!MDMap) @@ -149,9 +147,14 @@ public: // If the key is already in the map, it returns false and doesn't update the // value. std::pair<iterator, bool> insert(const std::pair<KeyT, ValueT> &KV) { - std::pair<typename MapT::iterator, bool> map_result= - Map.insert(std::make_pair(Wrap(KV.first), KV.second)); - return std::make_pair(iterator(map_result.first), map_result.second); + auto MapResult = Map.insert(std::make_pair(Wrap(KV.first), KV.second)); + return std::make_pair(iterator(MapResult.first), MapResult.second); + } + + std::pair<iterator, bool> insert(std::pair<KeyT, ValueT> &&KV) { + auto MapResult = + Map.insert(std::make_pair(Wrap(KV.first), std::move(KV.second))); + return std::make_pair(iterator(MapResult.first), MapResult.second); } /// insert - Range insertion of pairs. @@ -258,9 +261,9 @@ public: // I could == Copy.Map->Map.end() if the onRAUW callback already // removed the old mapping. if (I != Copy.Map->Map.end()) { - ValueT Target(I->second); + ValueT Target(std::move(I->second)); Copy.Map->Map.erase(I); // Definitely destroys *this. - Copy.Map->insert(std::make_pair(typed_new_key, Target)); + Copy.Map->insert(std::make_pair(typed_new_key, std::move(Target))); } } } diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 1d428b0..490d814 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -110,6 +110,7 @@ void initializeDeadInstEliminationPass(PassRegistry&); void initializeDeadMachineInstructionElimPass(PassRegistry&); void initializeDelinearizationPass(PassRegistry &); void initializeDependenceAnalysisPass(PassRegistry&); +void initializeDivergenceAnalysisPass(PassRegistry&); void initializeDomOnlyPrinterPass(PassRegistry&); void initializeDomOnlyViewerPass(PassRegistry&); void initializeDomPrinterPass(PassRegistry&); @@ -205,6 +206,7 @@ void initializeMergedLoadStoreMotionPass(PassRegistry &); void initializeMetaRenamerPass(PassRegistry&); void initializeMergeFunctionsPass(PassRegistry&); void initializeModuleDebugInfoPrinterPass(PassRegistry&); +void initializeNaryReassociatePass(PassRegistry&); void initializeNoAAPass(PassRegistry&); void initializeObjCARCAliasAnalysisPass(PassRegistry&); void initializeObjCARCAPElimPass(PassRegistry&); @@ -294,6 +296,7 @@ void initializeWinEHPreparePass(PassRegistry&); void initializePlaceBackedgeSafepointsImplPass(PassRegistry&); void initializePlaceSafepointsPass(PassRegistry&); void initializeDwarfEHPreparePass(PassRegistry&); +void initializeFloat2IntPass(PassRegistry&); } #endif diff --git a/include/llvm/LTO/LTOCodeGenerator.h b/include/llvm/LTO/LTOCodeGenerator.h index 820d6d5..a4aace4 100644 --- a/include/llvm/LTO/LTOCodeGenerator.h +++ b/include/llvm/LTO/LTOCodeGenerator.h @@ -53,6 +53,7 @@ namespace llvm { class TargetLibraryInfo; class TargetMachine; class raw_ostream; + class raw_pwrite_stream; //===----------------------------------------------------------------------===// /// C++ class which implements the opaque lto_code_gen_t type. @@ -137,7 +138,7 @@ struct LTOCodeGenerator { private: void initializeLTOPasses(); - bool compileOptimized(raw_ostream &out, std::string &errMsg); + bool compileOptimized(raw_pwrite_stream &out, std::string &errMsg); bool compileOptimizedToFile(const char **name, std::string &errMsg); void applyScopeRestrictions(); void applyRestriction(GlobalValue &GV, ArrayRef<StringRef> Libcalls, diff --git a/include/llvm/LineEditor/LineEditor.h b/include/llvm/LineEditor/LineEditor.h index 1a9a691..bb106f8 100644 --- a/include/llvm/LineEditor/LineEditor.h +++ b/include/llvm/LineEditor/LineEditor.h @@ -119,7 +119,7 @@ private: }; struct ListCompleterConcept : CompleterConcept { - ~ListCompleterConcept(); + ~ListCompleterConcept() override; CompletionAction complete(StringRef Buffer, size_t Pos) const override; static std::string getCommonPrefix(const std::vector<Completion> &Comps); virtual std::vector<Completion> getCompletions(StringRef Buffer, diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index 391267c..bee39b1 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -15,6 +15,7 @@ #ifndef LLVM_LINKALLPASSES_H #define LLVM_LINKALLPASSES_H +#include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasSetTracker.h" #include "llvm/Analysis/CallPrinter.h" #include "llvm/Analysis/DomPrinter.h" @@ -35,6 +36,7 @@ #include "llvm/Transforms/Utils/SymbolRewriter.h" #include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" #include "llvm/Transforms/Vectorize.h" +#include "llvm/Support/Valgrind.h" #include <cstdlib> namespace { @@ -74,6 +76,7 @@ namespace { (void) llvm::createDeadInstEliminationPass(); (void) llvm::createDeadStoreEliminationPass(); (void) llvm::createDependenceAnalysisPass(); + (void) llvm::createDivergenceAnalysisPass(); (void) llvm::createDomOnlyPrinterPass(); (void) llvm::createDomPrinterPass(); (void) llvm::createDomOnlyViewerPass(); @@ -106,6 +109,7 @@ namespace { (void) llvm::createLowerExpectIntrinsicPass(); (void) llvm::createLowerInvokePass(); (void) llvm::createLowerSwitchPass(); + (void) llvm::createNaryReassociatePass(); (void) llvm::createNoAAPass(); (void) llvm::createObjCARCAliasAnalysisPass(); (void) llvm::createObjCARCAPElimPass(); @@ -169,6 +173,7 @@ namespace { (void) llvm::createRewriteSymbolsPass(); (void) llvm::createStraightLineStrengthReducePass(); (void) llvm::createMemDerefPrinter(); + (void) llvm::createFloat2IntPass(); (void)new llvm::IntervalPartition(); (void)new llvm::ScalarEvolution(); @@ -177,6 +182,8 @@ namespace { ((llvm::RegionPass*)nullptr)->runOnRegion((llvm::Region*)nullptr, RGM); llvm::AliasSetTracker X(*(llvm::AliasAnalysis*)nullptr); X.add(nullptr, 0, llvm::AAMDNodes()); // for -print-alias-sets + (void) llvm::AreStatisticsEnabled(); + (void) llvm::sys::RunningOnValgrind(); } } ForcePassLinking; // Force link by creating a global definition. } diff --git a/include/llvm/MC/ConstantPools.h b/include/llvm/MC/ConstantPools.h index 1fc0332..ee7022b 100644 --- a/include/llvm/MC/ConstantPools.h +++ b/include/llvm/MC/ConstantPools.h @@ -77,9 +77,6 @@ class AssemblerConstantPools { ConstantPoolMapTy ConstantPools; public: - AssemblerConstantPools() {} - ~AssemblerConstantPools() {} - void emitAll(MCStreamer &Streamer); void emitForCurrentSection(MCStreamer &Streamer); const MCExpr *addEntry(MCStreamer &Streamer, const MCExpr *Expr, diff --git a/include/llvm/MC/MCAsmBackend.h b/include/llvm/MC/MCAsmBackend.h index 56da95d..ff77dc9 100644 --- a/include/llvm/MC/MCAsmBackend.h +++ b/include/llvm/MC/MCAsmBackend.h @@ -30,7 +30,7 @@ class MCSection; class MCValue; class raw_ostream; -/// MCAsmBackend - Generic interface to target specific assembler backends. +/// Generic interface to target specific assembler backends. class MCAsmBackend { MCAsmBackend(const MCAsmBackend &) = delete; void operator=(const MCAsmBackend &) = delete; @@ -46,42 +46,42 @@ public: /// lifetime management virtual void reset() {} - /// createObjectWriter - Create a new MCObjectWriter instance for use by the - /// assembler backend to emit the final object file. - virtual MCObjectWriter *createObjectWriter(raw_ostream &OS) const = 0; + /// Create a new MCObjectWriter instance for use by the assembler backend to + /// emit the final object file. + virtual MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const = 0; - /// createELFObjectTargetWriter - Create a new ELFObjectTargetWriter to enable - /// non-standard ELFObjectWriters. + /// Create a new ELFObjectTargetWriter to enable non-standard + /// ELFObjectWriters. virtual MCELFObjectTargetWriter *createELFObjectTargetWriter() const { llvm_unreachable("createELFObjectTargetWriter is not supported by asm " "backend"); } - /// hasDataInCodeSupport - Check whether this target implements data-in-code - /// markers. If not, data region directives will be ignored. + /// Check whether this target implements data-in-code markers. If not, data + /// region directives will be ignored. bool hasDataInCodeSupport() const { return HasDataInCodeSupport; } /// @name Target Fixup Interfaces /// @{ - /// getNumFixupKinds - Get the number of target specific fixup kinds. + /// Get the number of target specific fixup kinds. virtual unsigned getNumFixupKinds() const = 0; - /// getFixupKindInfo - Get information on a fixup kind. + /// Get information on a fixup kind. virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const; - /// processFixupValue - Target hook to adjust the literal value of a fixup - /// if necessary. IsResolved signals whether the caller believes a relocation - /// is needed; the target can modify the value. The default does nothing. + /// Target hook to adjust the literal value of a fixup if necessary. + /// IsResolved signals whether the caller believes a relocation is needed; the + /// target can modify the value. The default does nothing. virtual void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFixup &Fixup, const MCFragment *DF, const MCValue &Target, uint64_t &Value, bool &IsResolved) {} - /// applyFixup - Apply the \p Value for given \p Fixup into the provided - /// data fragment, at the offset specified by the fixup and following the - /// fixup kind as appropriate. + /// Apply the \p Value for given \p Fixup into the provided data fragment, at + /// the offset specified by the fixup and following the fixup kind as + /// appropriate. virtual void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, uint64_t Value, bool IsPCRel) const = 0; @@ -90,20 +90,18 @@ public: /// @name Target Relaxation Interfaces /// @{ - /// mayNeedRelaxation - Check whether the given instruction may need - /// relaxation. + /// Check whether the given instruction may need relaxation. /// /// \param Inst - The instruction to test. virtual bool mayNeedRelaxation(const MCInst &Inst) const = 0; - /// fixupNeedsRelaxation - Target specific predicate for whether a given - /// fixup requires the associated instruction to be relaxed. + /// Target specific predicate for whether a given fixup requires the + /// associated instruction to be relaxed. virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const = 0; - /// RelaxInstruction - Relax the instruction in the given fragment to the next - /// wider instruction. + /// Relax the instruction in the given fragment to the next wider instruction. /// /// \param Inst The instruction to relax, which may be the same as the /// output. @@ -112,22 +110,19 @@ public: /// @} - /// getMinimumNopSize - Returns the minimum size of a nop in bytes on this - /// target. The assembler will use this to emit excess padding in situations - /// where the padding required for simple alignment would be less than the - /// minimum nop size. + /// Returns the minimum size of a nop in bytes on this target. The assembler + /// will use this to emit excess padding in situations where the padding + /// required for simple alignment would be less than the minimum nop size. /// virtual unsigned getMinimumNopSize() const { return 1; } - /// writeNopData - Write an (optimal) nop sequence of Count bytes to the given - /// output. If the target cannot generate such a sequence, it should return an - /// error. + /// Write an (optimal) nop sequence of Count bytes to the given output. If the + /// target cannot generate such a sequence, it should return an error. /// /// \return - True on success. virtual bool writeNopData(uint64_t Count, MCObjectWriter *OW) const = 0; - /// handleAssemblerFlag - Handle any target-specific assembler flags. - /// By default, do nothing. + /// Handle any target-specific assembler flags. By default, do nothing. virtual void handleAssemblerFlag(MCAssemblerFlag Flag) {} /// \brief Generate the compact unwind encoding for the CFI instructions. diff --git a/include/llvm/MC/MCAsmInfoELF.h b/include/llvm/MC/MCAsmInfoELF.h index 7bd2460..afd4933 100644 --- a/include/llvm/MC/MCAsmInfoELF.h +++ b/include/llvm/MC/MCAsmInfoELF.h @@ -15,8 +15,7 @@ namespace llvm { class MCAsmInfoELF : public MCAsmInfo { virtual void anchor(); - const MCSection * - getNonexecutableStackSection(MCContext &Ctx) const override final; + const MCSection *getNonexecutableStackSection(MCContext &Ctx) const final; protected: MCAsmInfoELF(); diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h index 4d1590a..8b012be 100644 --- a/include/llvm/MC/MCAsmLayout.h +++ b/include/llvm/MC/MCAsmLayout.h @@ -50,11 +50,6 @@ private: /// \brief Is the layout for this fragment valid? bool isFragmentValid(const MCFragment *F) const; - /// \brief Compute the amount of padding required before this fragment to - /// obey bundling restrictions. - uint64_t computeBundlePadding(const MCFragment *F, - uint64_t FOffset, uint64_t FSize); - public: MCAsmLayout(MCAssembler &Assembler); diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index 9a85293..b8e9227 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -143,7 +143,7 @@ public: : MCFragment(FType, SD), BundlePadding(0) { } - virtual ~MCEncodedFragment(); + ~MCEncodedFragment() override; virtual SmallVectorImpl<char> &getContents() = 0; virtual const SmallVectorImpl<char> &getContents() const = 0; @@ -182,7 +182,7 @@ public: { } - virtual ~MCEncodedFragmentWithFixups(); + ~MCEncodedFragmentWithFixups() override; typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator; typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator; @@ -1245,11 +1245,23 @@ public: FileNames.push_back(FileName); } + /// \brief Write the necessary bundle padding to the given object writer. + /// Expects a fragment \p F containing instructions and its size \p FSize. + void writeFragmentPadding(const MCFragment &F, uint64_t FSize, + MCObjectWriter *OW) const; + /// @} void dump(); }; +/// \brief Compute the amount of padding required before the fragment \p F to +/// obey bundling restrictions, where \p FOffset is the fragment's offset in +/// its section and \p FSize is the fragment's size. +uint64_t computeBundlePadding(const MCAssembler &Assembler, + const MCFragment *F, + uint64_t FOffset, uint64_t FSize); + } // end namespace llvm #endif diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index 064f471..bf473cc 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -162,12 +162,44 @@ namespace llvm { /// The Compile Unit ID that we are currently processing. unsigned DwarfCompileUnitID; - typedef std::pair<std::string, std::string> SectionGroupPair; - typedef std::tuple<std::string, std::string, int> SectionGroupTriple; + struct ELFSectionKey { + std::string SectionName; + StringRef GroupName; + unsigned UniqueID; + ELFSectionKey(StringRef SectionName, StringRef GroupName, + unsigned UniqueID) + : SectionName(SectionName), GroupName(GroupName), UniqueID(UniqueID) { + } + bool operator<(const ELFSectionKey &Other) const { + if (SectionName != Other.SectionName) + return SectionName < Other.SectionName; + if (GroupName != Other.GroupName) + return GroupName < Other.GroupName; + return UniqueID < Other.UniqueID; + } + }; + + struct COFFSectionKey { + std::string SectionName; + StringRef GroupName; + int SelectionKey; + COFFSectionKey(StringRef SectionName, StringRef GroupName, + int SelectionKey) + : SectionName(SectionName), GroupName(GroupName), + SelectionKey(SelectionKey) {} + bool operator<(const COFFSectionKey &Other) const { + if (SectionName != Other.SectionName) + return SectionName < Other.SectionName; + if (GroupName != Other.GroupName) + return GroupName < Other.GroupName; + return SelectionKey < Other.SelectionKey; + } + }; StringMap<const MCSectionMachO*> MachOUniquingMap; - std::map<SectionGroupPair, const MCSectionELF *> ELFUniquingMap; - std::map<SectionGroupTriple, const MCSectionCOFF *> COFFUniquingMap; + std::map<ELFSectionKey, const MCSectionELF *> ELFUniquingMap; + std::map<COFFSectionKey, const MCSectionCOFF *> COFFUniquingMap; + StringMap<bool> ELFRelSecNames; /// Do automatic reset in destructor bool AutoReset; @@ -231,8 +263,14 @@ namespace llvm { MCSymbol *getOrCreateSectionSymbol(const MCSectionELF &Section); + /// Gets a symbol that will be defined to the final stack offset of a local + /// variable after codegen. + /// + /// @param Idx - The index of a local variable passed to @llvm.frameescape. MCSymbol *getOrCreateFrameAllocSymbol(StringRef FuncName, unsigned Idx); + MCSymbol *getOrCreateParentFrameOffsetSymbol(StringRef FuncName); + /// Get the symbol for \p Name, or null. MCSymbol *LookupSymbol(const Twine &Name) const; @@ -265,18 +303,52 @@ namespace llvm { } const MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags) { + return getELFSection(Section, Type, Flags, nullptr); + } + + const MCSectionELF *getELFSection(StringRef Section, unsigned Type, unsigned Flags, - const char *BeginSymName = nullptr); + const char *BeginSymName) { + return getELFSection(Section, Type, Flags, 0, "", BeginSymName); + } + + const MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + StringRef Group) { + return getELFSection(Section, Type, Flags, EntrySize, Group, nullptr); + } const MCSectionELF *getELFSection(StringRef Section, unsigned Type, unsigned Flags, unsigned EntrySize, StringRef Group, - const char *BeginSymName = nullptr); + const char *BeginSymName) { + return getELFSection(Section, Type, Flags, EntrySize, Group, ~0, + BeginSymName); + } + + const MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + StringRef Group, unsigned UniqueID) { + return getELFSection(Section, Type, Flags, EntrySize, Group, UniqueID, + nullptr); + } + + const MCSectionELF *getELFSection(StringRef Section, unsigned Type, + unsigned Flags, unsigned EntrySize, + StringRef Group, unsigned UniqueID, + const char *BeginSymName); const MCSectionELF *getELFSection(StringRef Section, unsigned Type, unsigned Flags, unsigned EntrySize, - StringRef Group, bool Unique, - const char *BeginSymName = nullptr); + const MCSymbol *Group, unsigned UniqueID, + const char *BeginSymName, + const MCSectionELF *Associated); + + const MCSectionELF *createELFRelSection(StringRef Name, unsigned Type, + unsigned Flags, unsigned EntrySize, + const MCSymbol *Group, + const MCSectionELF *Associated); void renameELFSection(const MCSectionELF *Section, StringRef Name); diff --git a/include/llvm/MC/MCELFObjectWriter.h b/include/llvm/MC/MCELFObjectWriter.h index 7493507..e9fef76 100644 --- a/include/llvm/MC/MCELFObjectWriter.h +++ b/include/llvm/MC/MCELFObjectWriter.h @@ -24,6 +24,18 @@ class MCSectionData; class MCSymbol; class MCSymbolData; class MCValue; +class raw_pwrite_stream; + +struct ELFRelocationEntry { + uint64_t Offset; // Where is the relocation. + const MCSymbol *Symbol; // The symbol to relocate with. + unsigned Type; // The type of the relocation. + uint64_t Addend; // The addend to use. + + ELFRelocationEntry(uint64_t Offset, const MCSymbol *Symbol, unsigned Type, + uint64_t Addend) + : Offset(Offset), Symbol(Symbol), Type(Type), Addend(Addend) {} +}; class MCELFObjectTargetWriter { const uint8_t OSABI; @@ -61,6 +73,9 @@ public: virtual bool needsRelocateWithSymbol(const MCSymbolData &SD, unsigned Type) const; + virtual void sortRelocs(const MCAssembler &Asm, + std::vector<ELFRelocationEntry> &Relocs); + /// @name Accessors /// @{ uint8_t getOSABI() const { return OSABI; } @@ -116,7 +131,8 @@ public: /// \param OS - The stream to write to. /// \returns The constructed object writer. MCObjectWriter *createELFObjectWriter(MCELFObjectTargetWriter *MOTW, - raw_ostream &OS, bool IsLittleEndian); + raw_pwrite_stream &OS, + bool IsLittleEndian); } // End llvm namespace #endif diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h index ab6c5e3..ace4ee3 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -29,23 +29,18 @@ class raw_ostream; class MCELFStreamer : public MCObjectStreamer { public: - MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, + MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_pwrite_stream &OS, MCCodeEmitter *Emitter) - : MCObjectStreamer(Context, TAB, OS, Emitter), - SeenIdent(false) {} + : MCObjectStreamer(Context, TAB, OS, Emitter), SeenIdent(false) {} - MCELFStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, - MCCodeEmitter *Emitter, MCAssembler *Assembler) - : MCObjectStreamer(Context, TAB, OS, Emitter, Assembler), - SeenIdent(false) {} - - virtual ~MCELFStreamer(); + ~MCELFStreamer() override; /// state management void reset() override { + SeenIdent = false; LocalCommons.clear(); BindingExplicitlySet.clear(); - SeenIdent = false; + BundleGroups.clear(); MCObjectStreamer::reset(); } @@ -100,6 +95,9 @@ private: void fixSymbolsInTLSFixups(const MCExpr *expr); + /// \brief Merge the content of the fragment \p EF into the fragment \p DF. + void mergeFragment(MCDataFragment *, MCEncodedFragmentWithFixups *); + bool SeenIdent; struct LocalCommon { @@ -111,11 +109,16 @@ private: std::vector<LocalCommon> LocalCommons; SmallPtrSet<MCSymbol *, 16> BindingExplicitlySet; + + /// BundleGroups - The stack of fragments holding the bundle-locked + /// instructions. + llvm::SmallVector<MCDataFragment *, 4> BundleGroups; }; MCELFStreamer *createARMELFStreamer(MCContext &Context, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *Emitter, - bool RelaxAll, bool IsThumb); + raw_pwrite_stream &OS, + MCCodeEmitter *Emitter, bool RelaxAll, + bool IsThumb); } // end namespace llvm diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h index dce3a06..4181d00 100644 --- a/include/llvm/MC/MCInstPrinter.h +++ b/include/llvm/MC/MCInstPrinter.h @@ -19,6 +19,7 @@ class raw_ostream; class MCAsmInfo; class MCInstrInfo; class MCRegisterInfo; +class MCSubtargetInfo; class StringRef; namespace HexStyle { @@ -40,9 +41,6 @@ protected: const MCInstrInfo &MII; const MCRegisterInfo &MRI; - /// The current set of available features. - uint64_t AvailableFeatures; - /// True if we are printing marked up assembly. bool UseMarkup; @@ -58,7 +56,7 @@ public: MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii, const MCRegisterInfo &mri) : CommentStream(nullptr), MAI(mai), MII(mii), MRI(mri), - AvailableFeatures(0), UseMarkup(0), PrintImmHex(0), + UseMarkup(0), PrintImmHex(0), PrintHexStyle(HexStyle::C) {} virtual ~MCInstPrinter(); @@ -69,7 +67,7 @@ public: /// printInst - Print the specified MCInst to the specified raw_ostream. /// virtual void printInst(const MCInst *MI, raw_ostream &OS, - StringRef Annot) = 0; + StringRef Annot, const MCSubtargetInfo &STI) = 0; /// getOpcodeName - Return the name of the specified opcode enum (e.g. /// "MOV32ri") or empty if we can't resolve it. @@ -78,9 +76,6 @@ public: /// printRegName - Print the assembler register name. virtual void printRegName(raw_ostream &OS, unsigned RegNo) const; - uint64_t getAvailableFeatures() const { return AvailableFeatures; } - void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; } - bool getUseMarkup() const { return UseMarkup; } void setUseMarkup(bool Value) { UseMarkup = Value; } diff --git a/include/llvm/MC/MCLinkerOptimizationHint.h b/include/llvm/MC/MCLinkerOptimizationHint.h index 890d638..c96d578 100644 --- a/include/llvm/MC/MCLinkerOptimizationHint.h +++ b/include/llvm/MC/MCLinkerOptimizationHint.h @@ -141,7 +141,7 @@ public: public: raw_counting_ostream() : Count(0) {} - ~raw_counting_ostream() { flush(); } + ~raw_counting_ostream() override { flush(); } }; raw_counting_ostream OutStream; diff --git a/include/llvm/MC/MCMachObjectWriter.h b/include/llvm/MC/MCMachObjectWriter.h index 514700b..bfe5d36 100644 --- a/include/llvm/MC/MCMachObjectWriter.h +++ b/include/llvm/MC/MCMachObjectWriter.h @@ -119,7 +119,7 @@ class MachObjectWriter : public MCObjectWriter { MachSymbolData *findSymbolData(const MCSymbol &Sym); public: - MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &OS, + MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_pwrite_stream &OS, bool IsLittleEndian) : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {} @@ -257,13 +257,12 @@ public: void computeSectionAddresses(const MCAssembler &Asm, const MCAsmLayout &Layout); - void markAbsoluteVariableSymbols(MCAssembler &Asm, - const MCAsmLayout &Layout); void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) override; bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, const MCSymbolData &DataA, + const MCSymbolData *DataB, const MCFragment &FB, bool InSet, bool IsPCRel) const override; @@ -280,7 +279,8 @@ public: /// \param OS - The stream to write to. /// \returns The constructed object writer. MCObjectWriter *createMachObjectWriter(MCMachObjectTargetWriter *MOTW, - raw_ostream &OS, bool IsLittleEndian); + raw_pwrite_stream &OS, + bool IsLittleEndian); } // End llvm namespace diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index 2420072..6666a50 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -24,6 +24,7 @@ class MCFragment; class MCDataFragment; class MCAsmBackend; class raw_ostream; +class raw_pwrite_stream; /// \brief Streaming object file generation interface. /// @@ -44,16 +45,10 @@ class MCObjectStreamer : public MCStreamer { void EmitCFIStartProcImpl(MCDwarfFrameInfo &Frame) override; void EmitCFIEndProcImpl(MCDwarfFrameInfo &Frame) override; - // If any labels have been emitted but not assigned fragments, ensure that - // they get assigned, either to F if possible or to a new data fragment. - void flushPendingLabels(MCFragment *F); - protected: - MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, + MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_pwrite_stream &OS, MCCodeEmitter *Emitter); - MCObjectStreamer(MCContext &Context, MCAsmBackend &TAB, raw_ostream &OS, - MCCodeEmitter *Emitter, MCAssembler *Assembler); - ~MCObjectStreamer(); + ~MCObjectStreamer() override; public: /// state management @@ -87,6 +82,12 @@ protected: bool changeSectionImpl(const MCSection *Section, const MCExpr *Subsection); + /// If any labels have been emitted but not assigned fragments, ensure that + /// they get assigned, either to F if possible or to a new data fragment. + /// Optionally, it is also possible to provide an offset \p FOffset, which + /// will be used as a symbol offset within the fragment. + void flushPendingLabels(MCFragment *F, uint64_t FOffset = 0); + public: void visitUsedSymbol(const MCSymbol &Sym) override; diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index fcfa968..f8e2821 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -13,6 +13,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/EndianStream.h" #include "llvm/Support/raw_ostream.h" #include <cassert> @@ -41,12 +42,12 @@ class MCObjectWriter { void operator=(const MCObjectWriter &) = delete; protected: - raw_ostream &OS; + raw_pwrite_stream &OS; unsigned IsLittleEndian : 1; protected: // Can only create subclasses. - MCObjectWriter(raw_ostream &OS, bool IsLittleEndian) + MCObjectWriter(raw_pwrite_stream &OS, bool IsLittleEndian) : OS(OS), IsLittleEndian(IsLittleEndian) {} public: @@ -91,12 +92,12 @@ public: const MCSymbolRefExpr *B, bool InSet) const; - virtual bool - IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, - const MCSymbolData &DataA, - const MCFragment &FB, - bool InSet, - bool IsPCRel) const; + virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, + const MCSymbolData &DataA, + const MCSymbolData *DataB, + const MCFragment &FB, + bool InSet, + bool IsPCRel) const; /// \brief True if this symbol (which is a variable) is weak. This is not /// just STB_WEAK, but more generally whether or not we can evaluate @@ -120,33 +121,27 @@ public: } void WriteLE16(uint16_t Value) { - Write8(uint8_t(Value >> 0)); - Write8(uint8_t(Value >> 8)); + support::endian::Writer<support::little>(OS).write(Value); } void WriteLE32(uint32_t Value) { - WriteLE16(uint16_t(Value >> 0)); - WriteLE16(uint16_t(Value >> 16)); + support::endian::Writer<support::little>(OS).write(Value); } void WriteLE64(uint64_t Value) { - WriteLE32(uint32_t(Value >> 0)); - WriteLE32(uint32_t(Value >> 32)); + support::endian::Writer<support::little>(OS).write(Value); } void WriteBE16(uint16_t Value) { - Write8(uint8_t(Value >> 8)); - Write8(uint8_t(Value >> 0)); + support::endian::Writer<support::big>(OS).write(Value); } void WriteBE32(uint32_t Value) { - WriteBE16(uint16_t(Value >> 16)); - WriteBE16(uint16_t(Value >> 0)); + support::endian::Writer<support::big>(OS).write(Value); } void WriteBE64(uint64_t Value) { - WriteBE32(uint32_t(Value >> 32)); - WriteBE32(uint32_t(Value >> 0)); + support::endian::Writer<support::big>(OS).write(Value); } void Write16(uint16_t Value) { diff --git a/include/llvm/MC/MCParser/AsmLexer.h b/include/llvm/MC/MCParser/AsmLexer.h index 2f681d6..62d39b2 100644 --- a/include/llvm/MC/MCParser/AsmLexer.h +++ b/include/llvm/MC/MCParser/AsmLexer.h @@ -40,7 +40,7 @@ protected: public: AsmLexer(const MCAsmInfo &MAI); - ~AsmLexer(); + ~AsmLexer() override; void setBuffer(StringRef Buf, const char *ptr = nullptr); diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h index b6ec1d8..237f6d3 100644 --- a/include/llvm/MC/MCSectionCOFF.h +++ b/include/llvm/MC/MCSectionCOFF.h @@ -53,7 +53,7 @@ class MCSymbol; assert ((Characteristics & 0x00F00000) == 0 && "alignment must not be set upon section creation"); } - ~MCSectionCOFF(); + ~MCSectionCOFF() override; public: /// ShouldOmitSectionDirective - Decides whether a '.section' directive diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h index 434a5b6..9efe102 100644 --- a/include/llvm/MC/MCSectionELF.h +++ b/include/llvm/MC/MCSectionELF.h @@ -39,7 +39,7 @@ class MCSectionELF : public MCSection { /// below. unsigned Flags; - bool Unique; + unsigned UniqueID; /// EntrySize - The size of each entry in this section. This size only /// makes sense for sections that contain fixed-sized entries. If a @@ -48,14 +48,18 @@ class MCSectionELF : public MCSection { const MCSymbol *Group; + /// Depending on the type of the section this is sh_link or sh_info. + const MCSectionELF *Associated; + private: friend class MCContext; MCSectionELF(StringRef Section, unsigned type, unsigned flags, SectionKind K, - unsigned entrySize, const MCSymbol *group, bool Unique, - MCSymbol *Begin) + unsigned entrySize, const MCSymbol *group, unsigned UniqueID, + MCSymbol *Begin, const MCSectionELF *Associated) : MCSection(SV_ELF, K, Begin), SectionName(Section), Type(type), - Flags(flags), Unique(Unique), EntrySize(entrySize), Group(group) {} - ~MCSectionELF(); + Flags(flags), UniqueID(UniqueID), EntrySize(entrySize), Group(group), + Associated(Associated) {} + ~MCSectionELF() override; void setSectionName(StringRef Name) { SectionName = Name; } @@ -76,6 +80,11 @@ public: bool UseCodeAlign() const override; bool isVirtualSection() const override; + bool isUnique() const { return UniqueID != ~0U; } + unsigned getUniqueID() const { return UniqueID; } + + const MCSectionELF *getAssociatedSection() const { return Associated; } + static bool classof(const MCSection *S) { return S->getVariant() == SV_ELF; } diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index df7610b..ad2bbcf 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -90,7 +90,7 @@ public: class AArch64TargetStreamer : public MCTargetStreamer { public: AArch64TargetStreamer(MCStreamer &S); - ~AArch64TargetStreamer(); + ~AArch64TargetStreamer() override; void finish() override; @@ -115,7 +115,7 @@ private: class ARMTargetStreamer : public MCTargetStreamer { public: ARMTargetStreamer(MCStreamer &S); - ~ARMTargetStreamer(); + ~ARMTargetStreamer() override; virtual void emitFnStart(); virtual void emitFnEnd(); @@ -746,7 +746,8 @@ MCStreamer *createNullStreamer(MCContext &Ctx); /// /// \param ShowInst - Whether to show the MCInst representation inline with /// the assembly. -MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, +MCStreamer *createAsmStreamer(MCContext &Ctx, + std::unique_ptr<formatted_raw_ostream> OS, bool isVerboseAsm, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst); diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h index 53443b0..e4bdfda 100644 --- a/include/llvm/MC/MCSymbol.h +++ b/include/llvm/MC/MCSymbol.h @@ -15,6 +15,7 @@ #define LLVM_MC_MCSYMBOL_H #include "llvm/ADT/StringRef.h" +#include "llvm/MC/MCExpr.h" #include "llvm/Support/Compiler.h" namespace llvm { @@ -42,8 +43,9 @@ namespace llvm { /// Section - The section the symbol is defined in. This is null for /// undefined symbols, and the special AbsolutePseudoSection value for - /// absolute symbols. - const MCSection *Section; + /// absolute symbols. If this is a variable symbol, this caches the + /// variable value's section. + mutable const MCSection *Section; /// Value - If non-null, the value for a variable symbol. const MCExpr *Value; @@ -68,6 +70,12 @@ namespace llvm { MCSymbol(const MCSymbol&) = delete; void operator=(const MCSymbol&) = delete; + const MCSection *getSectionPtr() const { + if (Section || !Value) + return Section; + return Section = Value->FindAssociatedSection(); + } + public: /// getName - Get the symbol name. StringRef getName() const { return Name; } @@ -103,7 +111,7 @@ namespace llvm { /// /// Defined symbols are either absolute or in some section. bool isDefined() const { - return Section != nullptr; + return getSectionPtr() != nullptr; } /// isInSection - Check if this symbol is defined in some section (i.e., it @@ -119,27 +127,27 @@ namespace llvm { /// isAbsolute - Check if this is an absolute symbol. bool isAbsolute() const { - return Section == AbsolutePseudoSection; + return getSectionPtr() == AbsolutePseudoSection; } /// getSection - Get the section associated with a defined, non-absolute /// symbol. const MCSection &getSection() const { assert(isInSection() && "Invalid accessor!"); - return *Section; + return *getSectionPtr(); } /// setSection - Mark the symbol as defined in the section \p S. - void setSection(const MCSection &S) { Section = &S; } + void setSection(const MCSection &S) { + assert(!isVariable() && "Cannot set section of variable"); + Section = &S; + } /// setUndefined - Mark the symbol as undefined. void setUndefined() { Section = nullptr; } - /// setAbsolute - Mark the symbol as absolute. - void setAbsolute() { Section = AbsolutePseudoSection; } - /// @} /// @name Variable Symbols /// @{ diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index 8412b1d..36db391 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -75,8 +75,6 @@ struct ParseInstructionInfo { ParseInstructionInfo() : AsmRewrites(nullptr) {} ParseInstructionInfo(SmallVectorImpl<AsmRewrite> *rewrites) : AsmRewrites(rewrites) {} - - ~ParseInstructionInfo() {} }; /// MCTargetAsmParser - Generic interface to target specific assembly parsers. @@ -110,7 +108,7 @@ protected: // Can only create subclasses. MCTargetOptions MCOptions; public: - virtual ~MCTargetAsmParser(); + ~MCTargetAsmParser() override; uint64_t getAvailableFeatures() const { return AvailableFeatures; } void setAvailableFeatures(uint64_t Value) { AvailableFeatures = Value; } diff --git a/include/llvm/MC/MCWinCOFFObjectWriter.h b/include/llvm/MC/MCWinCOFFObjectWriter.h index 956e436..e2e95c7 100644 --- a/include/llvm/MC/MCWinCOFFObjectWriter.h +++ b/include/llvm/MC/MCWinCOFFObjectWriter.h @@ -16,6 +16,7 @@ class MCFixup; class MCObjectWriter; class MCValue; class raw_ostream; +class raw_pwrite_stream; class MCWinCOFFObjectTargetWriter { virtual void anchor(); @@ -40,7 +41,7 @@ class raw_ostream; /// \param OS - The stream to write to. /// \returns The constructed object writer. MCObjectWriter *createWinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW, - raw_ostream &OS); + raw_pwrite_stream &OS); } // End llvm namespace #endif diff --git a/include/llvm/MC/MCWinCOFFStreamer.h b/include/llvm/MC/MCWinCOFFStreamer.h index 57a75ce..b3fee81 100644 --- a/include/llvm/MC/MCWinCOFFStreamer.h +++ b/include/llvm/MC/MCWinCOFFStreamer.h @@ -24,11 +24,12 @@ class MCSubtargetInfo; class MCSymbol; class StringRef; class raw_ostream; +class raw_pwrite_stream; class MCWinCOFFStreamer : public MCObjectStreamer { public: MCWinCOFFStreamer(MCContext &Context, MCAsmBackend &MAB, MCCodeEmitter &CE, - raw_ostream &OS); + raw_pwrite_stream &OS); /// state management void reset() override { diff --git a/include/llvm/MC/SubtargetFeature.h b/include/llvm/MC/SubtargetFeature.h index bfecb8b..6f195d7 100644 --- a/include/llvm/MC/SubtargetFeature.h +++ b/include/llvm/MC/SubtargetFeature.h @@ -78,7 +78,7 @@ public: std::string getString() const; /// Adding Features. - void AddFeature(StringRef String); + void AddFeature(StringRef String, bool Enable = true); /// ToggleFeature - Toggle a feature and returns the newly updated feature /// bits. diff --git a/include/llvm/Object/IRObjectFile.h b/include/llvm/Object/IRObjectFile.h index 74f4666..ef65528 100644 --- a/include/llvm/Object/IRObjectFile.h +++ b/include/llvm/Object/IRObjectFile.h @@ -31,7 +31,7 @@ class IRObjectFile : public SymbolicFile { public: IRObjectFile(MemoryBufferRef Object, std::unique_ptr<Module> M); - ~IRObjectFile(); + ~IRObjectFile() override; void moveSymbolNext(DataRefImpl &Symb) const override; std::error_code printSymbolName(raw_ostream &OS, DataRefImpl Symb) const override; diff --git a/include/llvm/Object/SymbolicFile.h b/include/llvm/Object/SymbolicFile.h index b6a8b4d..114b229 100644 --- a/include/llvm/Object/SymbolicFile.h +++ b/include/llvm/Object/SymbolicFile.h @@ -118,7 +118,7 @@ const uint64_t UnknownAddressOrSize = ~0ULL; class SymbolicFile : public Binary { public: - virtual ~SymbolicFile(); + ~SymbolicFile() override; SymbolicFile(unsigned int Type, MemoryBufferRef Source); // virtual interface. diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h index 9a09309..23b0451 100644 --- a/include/llvm/Option/ArgList.h +++ b/include/llvm/Option/ArgList.h @@ -320,7 +320,7 @@ private: public: InputArgList(const char* const *ArgBegin, const char* const *ArgEnd); - ~InputArgList(); + ~InputArgList() override; const char *getArgString(unsigned Index) const override { return ArgStrings[Index]; @@ -355,7 +355,7 @@ class DerivedArgList : public ArgList { public: /// Construct a new derived arg list from \p BaseArgs. DerivedArgList(const InputArgList &BaseArgs); - ~DerivedArgList(); + ~DerivedArgList() override; const char *getArgString(unsigned Index) const override { return BaseArgs.getArgString(Index); diff --git a/include/llvm/Pass.h b/include/llvm/Pass.h index 6e92d96..3c4d838 100644 --- a/include/llvm/Pass.h +++ b/include/llvm/Pass.h @@ -250,7 +250,7 @@ public: explicit ModulePass(char &pid) : Pass(PT_Module, pid) {} // Force out-of-line virtual method. - virtual ~ModulePass(); + ~ModulePass() override; }; @@ -279,7 +279,7 @@ public: : ModulePass(pid) {} // Force out-of-line virtual method. - virtual ~ImmutablePass(); + ~ImmutablePass() override; }; //===----------------------------------------------------------------------===// diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h index de31771..94cf3e8 100644 --- a/include/llvm/Support/Allocator.h +++ b/include/llvm/Support/Allocator.h @@ -203,7 +203,8 @@ public: } /// \brief Allocate space at the specified alignment. - LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, size_t Alignment) { + LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void * + Allocate(size_t Size, size_t Alignment) { assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead."); // Keep track of how many bytes we've allocated. diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index f7de840..c81fbaf 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -72,20 +72,20 @@ #define LLVM_NOEXCEPT #endif -/// \brief Does the compiler support r-value reference *this? +/// \brief Does the compiler support ref-qualifiers for *this? /// -/// Sadly, this is separate from just r-value reference support because GCC -/// implemented this later than everything else. +/// Sadly, this is separate from just rvalue reference support because GCC +/// and MSVC implemented this later than everything else. #if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1) #define LLVM_HAS_RVALUE_REFERENCE_THIS 1 #else #define LLVM_HAS_RVALUE_REFERENCE_THIS 0 #endif -/// Expands to '&' if r-value references are supported. +/// Expands to '&' if ref-qualifiers for *this are supported. /// -/// This can be used to provide l-value/r-value overrides of member functions. -/// The r-value override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS +/// This can be used to provide lvalue/rvalue overrides of member functions. +/// The rvalue override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS #if LLVM_HAS_RVALUE_REFERENCE_THIS #define LLVM_LVALUE_FUNCTION & #else @@ -223,6 +223,16 @@ #define LLVM_ATTRIBUTE_RETURNS_NONNULL #endif +/// \macro LLVM_ATTRIBUTE_RETURNS_NOALIAS Used to mark a function as returning a +/// pointer that does not alias any other valid pointer. +#ifdef __GNUC__ +#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __declspec(restrict) +#else +#define LLVM_ATTRIBUTE_RETURNS_NOALIAS +#endif + /// LLVM_EXTENSION - Support compilers where we have a keyword to suppress /// pedantic diagnostics. #ifdef __GNUC__ @@ -281,6 +291,37 @@ # define LLVM_ASSUME_ALIGNED(p, a) (p) #endif +/// \macro LLVM_ALIGNAS +/// \brief Used to specify a minimum alignment for a structure or variable. The +/// alignment must be a constant integer. Use LLVM_PTR_SIZE to compute +/// alignments in terms of the size of a pointer. +/// +/// Note that __declspec(align) has special quirks, it's not legal to pass a +/// structure with __declspec(align) as a formal parameter. +#ifdef _MSC_VER +# define LLVM_ALIGNAS(x) __declspec(align(x)) +#elif __GNUC__ && !__has_feature(cxx_alignas) && !LLVM_GNUC_PREREQ(4, 8, 0) +# define LLVM_ALIGNAS(x) __attribute__((aligned(x))) +#else +# define LLVM_ALIGNAS(x) alignas(x) +#endif + +/// \macro LLVM_PTR_SIZE +/// \brief A constant integer equivalent to the value of sizeof(void*). +/// Generally used in combination with LLVM_ALIGNAS or when doing computation in +/// the preprocessor. +#ifdef __SIZEOF_POINTER__ +# define LLVM_PTR_SIZE __SIZEOF_POINTER__ +#elif defined(_WIN64) +# define LLVM_PTR_SIZE 8 +#elif defined(_WIN32) +# define LLVM_PTR_SIZE 4 +#elif defined(_MSC_VER) +# error "could not determine LLVM_PTR_SIZE as a constant int for MSVC" +#else +# define LLVM_PTR_SIZE sizeof(void *) +#endif + /// \macro LLVM_FUNCTION_NAME /// \brief Expands to __func__ on compilers which support it. Otherwise, /// expands to a compiler-dependent replacement. diff --git a/include/llvm/Support/ELFRelocs/Mips.def b/include/llvm/Support/ELFRelocs/Mips.def index dc57346..0e6de3b 100644 --- a/include/llvm/Support/ELFRelocs/Mips.def +++ b/include/llvm/Support/ELFRelocs/Mips.def @@ -110,3 +110,4 @@ ELF_RELOC(R_MICROMIPS_GPREL7_S2, 172) ELF_RELOC(R_MICROMIPS_PC23_S2, 173) ELF_RELOC(R_MIPS_NUM, 218) ELF_RELOC(R_MIPS_PC32, 248) +ELF_RELOC(R_MIPS_EH, 249) diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index b3b44c4..a736c32 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -120,7 +120,7 @@ class UniqueID { uint64_t File; public: - UniqueID() {} + UniqueID() = default; UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {} bool operator==(const UniqueID &Other) const { return Device == Other.Device && File == Other.File; diff --git a/include/llvm/Support/FormattedStream.h b/include/llvm/Support/FormattedStream.h index 8137daa..4a135cd 100644 --- a/include/llvm/Support/FormattedStream.h +++ b/include/llvm/Support/FormattedStream.h @@ -25,27 +25,11 @@ namespace llvm { /// boundaries and querying the number of lines written to the stream. /// class formatted_raw_ostream : public raw_ostream { -public: - /// DELETE_STREAM - Tell the destructor to delete the held stream. - /// - static const bool DELETE_STREAM = true; - - /// PRESERVE_STREAM - Tell the destructor to not delete the held - /// stream. - /// - static const bool PRESERVE_STREAM = false; - -private: /// TheStream - The real stream we output to. We set it to be /// unbuffered, since we're already doing our own buffering. /// raw_ostream *TheStream; - /// DeleteStream - Do we need to delete TheStream in the - /// destructor? - /// - bool DeleteStream; - /// Position - The current output column and line of the data that's /// been flushed and the portion of the buffer that's been /// scanned. The line and column scheme is zero-based. @@ -73,6 +57,24 @@ private: /// void ComputePosition(const char *Ptr, size_t size); + void setStream(raw_ostream &Stream) { + releaseStream(); + + TheStream = &Stream; + + // This formatted_raw_ostream inherits from raw_ostream, so it'll do its + // own buffering, and it doesn't need or want TheStream to do another + // layer of buffering underneath. Resize the buffer to what TheStream + // had been using, and tell TheStream not to do its own buffering. + if (size_t BufferSize = TheStream->GetBufferSize()) + SetBufferSize(BufferSize); + else + SetUnbuffered(); + TheStream->SetUnbuffered(); + + Scanned = nullptr; + } + public: /// formatted_raw_ostream - Open the specified file for /// writing. If an error occurs, information about the error is @@ -84,39 +86,19 @@ public: /// so it doesn't want another layer of buffering to be happening /// underneath it. /// - formatted_raw_ostream(raw_ostream &Stream, bool Delete = false) - : raw_ostream(), TheStream(nullptr), DeleteStream(false), Position(0, 0) { - setStream(Stream, Delete); + formatted_raw_ostream(raw_ostream &Stream) + : TheStream(nullptr), Position(0, 0) { + setStream(Stream); } - explicit formatted_raw_ostream() - : raw_ostream(), TheStream(nullptr), DeleteStream(false), Position(0, 0) { + explicit formatted_raw_ostream() : TheStream(nullptr), Position(0, 0) { Scanned = nullptr; } - ~formatted_raw_ostream() { + ~formatted_raw_ostream() override { flush(); releaseStream(); } - void setStream(raw_ostream &Stream, bool Delete = false) { - releaseStream(); - - TheStream = &Stream; - DeleteStream = Delete; - - // This formatted_raw_ostream inherits from raw_ostream, so it'll do its - // own buffering, and it doesn't need or want TheStream to do another - // layer of buffering underneath. Resize the buffer to what TheStream - // had been using, and tell TheStream not to do its own buffering. - if (size_t BufferSize = TheStream->GetBufferSize()) - SetBufferSize(BufferSize); - else - SetUnbuffered(); - TheStream->SetUnbuffered(); - - Scanned = nullptr; - } - /// PadToColumn - Align the output to some column number. If the current /// column is already equal to or more than NewCol, PadToColumn inserts one /// space. @@ -151,13 +133,11 @@ public: private: void releaseStream() { - // Delete the stream if needed. Otherwise, transfer the buffer - // settings from this raw_ostream back to the underlying stream. + // Transfer the buffer settings from this raw_ostream back to the underlying + // stream. if (!TheStream) return; - if (DeleteStream) - delete TheStream; - else if (size_t BufferSize = GetBufferSize()) + if (size_t BufferSize = GetBufferSize()) TheStream->SetBufferSize(BufferSize); else TheStream->SetUnbuffered(); diff --git a/include/llvm/Support/GenericDomTree.h b/include/llvm/Support/GenericDomTree.h index 0998eb9..63678bb 100644 --- a/include/llvm/Support/GenericDomTree.h +++ b/include/llvm/Support/GenericDomTree.h @@ -243,6 +243,8 @@ protected: this->Roots.clear(); Vertex.clear(); RootNode = nullptr; + DFSInfoValid = false; + SlowQueries = 0; } // NewBB is split and now it has one successor. Update dominator tree to @@ -637,9 +639,38 @@ protected: friend void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType> &DT, FuncT &F); + + DomTreeNodeBase<NodeT> *getNodeForBlock(NodeT *BB) { + if (DomTreeNodeBase<NodeT> *Node = getNode(BB)) + return Node; + + // Haven't calculated this node yet? Get or calculate the node for the + // immediate dominator. + NodeT *IDom = getIDom(BB); + + assert(IDom || this->DomTreeNodes[nullptr]); + DomTreeNodeBase<NodeT> *IDomNode = getNodeForBlock(IDom); + + // Add a new tree node for this NodeT, and link it as a child of + // IDomNode + return (this->DomTreeNodes[BB] = IDomNode->addChild( + llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))).get(); + } + + NodeT *getIDom(NodeT *BB) const { return IDoms.lookup(BB); } + + void addRoot(NodeT *BB) { this->Roots.push_back(BB); } + +public: /// updateDFSNumbers - Assign In and Out numbers to the nodes while walking /// dominator tree in dfs order. void updateDFSNumbers() const { + + if (DFSInfoValid) { + SlowQueries = 0; + return; + } + unsigned DFSNum = 0; SmallVector<std::pair<const DomTreeNodeBase<NodeT> *, @@ -682,28 +713,6 @@ protected: DFSInfoValid = true; } - DomTreeNodeBase<NodeT> *getNodeForBlock(NodeT *BB) { - if (DomTreeNodeBase<NodeT> *Node = getNode(BB)) - return Node; - - // Haven't calculated this node yet? Get or calculate the node for the - // immediate dominator. - NodeT *IDom = getIDom(BB); - - assert(IDom || this->DomTreeNodes[nullptr]); - DomTreeNodeBase<NodeT> *IDomNode = getNodeForBlock(IDom); - - // Add a new tree node for this NodeT, and link it as a child of - // IDomNode - return (this->DomTreeNodes[BB] = IDomNode->addChild( - llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))).get(); - } - - NodeT *getIDom(NodeT *BB) const { return IDoms.lookup(BB); } - - void addRoot(NodeT *BB) { this->Roots.push_back(BB); } - -public: /// recalculate - compute a dominator tree for the given function template <class FT> void recalculate(FT &F) { typedef GraphTraits<FT *> TraitsTy; diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index 388d82c..7edc2ac 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -318,31 +318,31 @@ inline bool isIntN(unsigned N, int64_t x) { return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); } -/// isMask_32 - This function returns true if the argument is a sequence of ones -/// starting at the least significant bit with the remainder zero (32 bit -/// version). Ex. isMask_32(0x0000FFFFU) == true. +/// isMask_32 - This function returns true if the argument is a non-empty +/// sequence of ones starting at the least significant bit with the remainder +/// zero (32 bit version). Ex. isMask_32(0x0000FFFFU) == true. inline bool isMask_32(uint32_t Value) { return Value && ((Value + 1) & Value) == 0; } -/// isMask_64 - This function returns true if the argument is a sequence of ones -/// starting at the least significant bit with the remainder zero (64 bit -/// version). +/// isMask_64 - This function returns true if the argument is a non-empty +/// sequence of ones starting at the least significant bit with the remainder +/// zero (64 bit version). inline bool isMask_64(uint64_t Value) { return Value && ((Value + 1) & Value) == 0; } /// isShiftedMask_32 - This function returns true if the argument contains a -/// sequence of ones with the remainder zero (32 bit version.) +/// non-empty sequence of ones with the remainder zero (32 bit version.) /// Ex. isShiftedMask_32(0x0000FF00U) == true. inline bool isShiftedMask_32(uint32_t Value) { - return isMask_32((Value - 1) | Value); + return Value && isMask_32((Value - 1) | Value); } /// isShiftedMask_64 - This function returns true if the argument contains a -/// sequence of ones with the remainder zero (64 bit version.) +/// non-empty sequence of ones with the remainder zero (64 bit version.) inline bool isShiftedMask_64(uint64_t Value) { - return isMask_64((Value - 1) | Value); + return Value && isMask_64((Value - 1) | Value); } /// isPowerOf2_32 - This function returns true if the argument is a power of diff --git a/include/llvm/Support/OnDiskHashTable.h b/include/llvm/Support/OnDiskHashTable.h index 52f133c..0f097f2 100644 --- a/include/llvm/Support/OnDiskHashTable.h +++ b/include/llvm/Support/OnDiskHashTable.h @@ -75,13 +75,10 @@ template <typename Info> class OnDiskChainedHashTableGenerator { llvm::SpecificBumpPtrAllocator<Item> BA; /// \brief A linked list of values in a particular hash bucket. - class Bucket { - public: + struct Bucket { offset_type Off; - Item *Head; unsigned Length; - - Bucket() {} + Item *Head; }; Bucket *Buckets; diff --git a/include/llvm/Support/Options.h b/include/llvm/Support/Options.h index 4fd1bff..2742d39 100644 --- a/include/llvm/Support/Options.h +++ b/include/llvm/Support/Options.h @@ -61,7 +61,7 @@ char OptionKey<ValT, Base, Mem>::ID = 0; /// The OptionRegistry is responsible for managing lifetimes of the options and /// provides interfaces for option registration and reading values from options. /// This object is a singleton, only one instance should ever exist so that all -/// options are registered in teh same place. +/// options are registered in the same place. class OptionRegistry { private: DenseMap<void *, cl::Option *> Options; diff --git a/include/llvm/Support/Signals.h b/include/llvm/Support/Signals.h index a067b13..7e165d7 100644 --- a/include/llvm/Support/Signals.h +++ b/include/llvm/Support/Signals.h @@ -39,7 +39,7 @@ namespace sys { /// When an error signal (such as SIBABRT or SIGSEGV) is delivered to the /// process, print a stack trace and then exit. /// @brief Print a stack trace if a fatal signal occurs. - void PrintStackTraceOnErrorSignal(); + void PrintStackTraceOnErrorSignal(bool DisableCrashReporting = false); /// Disable all system dialog boxes that appear when the process crashes. void DisableSystemDialogsOnCrash(); diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index ba6bbde..a4bf51f 100644 --- a/include/llvm/Support/TargetRegistry.h +++ b/include/llvm/Support/TargetRegistry.h @@ -22,6 +22,7 @@ #include "llvm-c/Disassembler.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/CodeGen.h" +#include "llvm/Support/FormattedStream.h" #include <cassert> #include <memory> #include <string> @@ -49,20 +50,22 @@ namespace llvm { class TargetMachine; class TargetOptions; class raw_ostream; + class raw_pwrite_stream; class formatted_raw_ostream; MCStreamer *createNullStreamer(MCContext &Ctx); - MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, + MCStreamer *createAsmStreamer(MCContext &Ctx, + std::unique_ptr<formatted_raw_ostream> OS, bool isVerboseAsm, bool useDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst); /// Takes ownership of \p TAB and \p CE. MCStreamer *createELFStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE, + raw_pwrite_stream &OS, MCCodeEmitter *CE, bool RelaxAll); MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, MCCodeEmitter *CE, + raw_pwrite_stream &OS, MCCodeEmitter *CE, bool RelaxAll, bool DWARFMustBeAtTheEnd, bool LabelSections = false); @@ -124,24 +127,24 @@ namespace llvm { typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T, const MCSubtargetInfo &STI, MCContext &Ctx); - typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Target &T, + typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Triple &T, unsigned SyntaxVariant, const MCAsmInfo &MAI, const MCInstrInfo &MII, - const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI); + const MCRegisterInfo &MRI); typedef MCCodeEmitter *(*MCCodeEmitterCtorTy)(const MCInstrInfo &II, const MCRegisterInfo &MRI, MCContext &Ctx); typedef MCStreamer *(*ELFStreamerCtorTy)(const Triple &T, MCContext &Ctx, - MCAsmBackend &TAB, raw_ostream &OS, + MCAsmBackend &TAB, + raw_pwrite_stream &OS, MCCodeEmitter *Emitter, bool RelaxAll); typedef MCStreamer *(*MachOStreamerCtorTy)( - MCContext &Ctx, MCAsmBackend &TAB, raw_ostream &OS, + MCContext &Ctx, MCAsmBackend &TAB, raw_pwrite_stream &OS, MCCodeEmitter *Emitter, bool RelaxAll, bool DWARFMustBeAtTheEnd); typedef MCStreamer *(*COFFStreamerCtorTy)(MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &OS, + raw_pwrite_stream &OS, MCCodeEmitter *Emitter, bool RelaxAll); typedef MCTargetStreamer *(*NullTargetStreamerCtorTy)(MCStreamer &S); @@ -409,14 +412,13 @@ namespace llvm { return MCDisassemblerCtorFn(*this, STI, Ctx); } - MCInstPrinter *createMCInstPrinter(unsigned SyntaxVariant, + MCInstPrinter *createMCInstPrinter(const Triple &T, unsigned SyntaxVariant, const MCAsmInfo &MAI, const MCInstrInfo &MII, - const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI) const { + const MCRegisterInfo &MRI) const { if (!MCInstPrinterCtorFn) return nullptr; - return MCInstPrinterCtorFn(*this, SyntaxVariant, MAI, MII, MRI, STI); + return MCInstPrinterCtorFn(T, SyntaxVariant, MAI, MII, MRI); } @@ -438,7 +440,7 @@ namespace llvm { /// \param Emitter The target independent assembler object.Takes ownership. /// \param RelaxAll Relax all fixups? MCStreamer *createMCObjectStreamer(const Triple &T, MCContext &Ctx, - MCAsmBackend &TAB, raw_ostream &OS, + MCAsmBackend &TAB, raw_pwrite_stream &OS, MCCodeEmitter *Emitter, const MCSubtargetInfo &STI, bool RelaxAll, @@ -471,14 +473,16 @@ namespace llvm { return S; } - MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, + MCStreamer *createAsmStreamer(MCContext &Ctx, + std::unique_ptr<formatted_raw_ostream> OS, bool IsVerboseAsm, bool UseDwarfDirectory, MCInstPrinter *InstPrint, MCCodeEmitter *CE, MCAsmBackend *TAB, bool ShowInst) const { - MCStreamer *S = - llvm::createAsmStreamer(Ctx, OS, IsVerboseAsm, UseDwarfDirectory, - InstPrint, CE, TAB, ShowInst); - createAsmTargetStreamer(*S, OS, InstPrint, IsVerboseAsm); + formatted_raw_ostream &OSRef = *OS; + MCStreamer *S = llvm::createAsmStreamer(Ctx, std::move(OS), IsVerboseAsm, + UseDwarfDirectory, InstPrint, CE, + TAB, ShowInst); + createAsmTargetStreamer(*S, OSRef, InstPrint, IsVerboseAsm); return S; } diff --git a/include/llvm/Support/ToolOutputFile.h b/include/llvm/Support/ToolOutputFile.h index d98e7bb..1be26c2 100644 --- a/include/llvm/Support/ToolOutputFile.h +++ b/include/llvm/Support/ToolOutputFile.h @@ -18,16 +18,16 @@ namespace llvm { -/// tool_output_file - This class contains a raw_fd_ostream and adds a -/// few extra features commonly needed for compiler-like tool output files: +/// This class contains a raw_fd_ostream and adds a few extra features commonly +/// needed for compiler-like tool output files: /// - The file is automatically deleted if the process is killed. /// - The file is automatically deleted when the tool_output_file /// object is destroyed unless the client calls keep(). class tool_output_file { - /// Installer - This class is declared before the raw_fd_ostream so that - /// it is constructed before the raw_fd_ostream is constructed and - /// destructed after the raw_fd_ostream is destructed. It installs - /// cleanups in its constructor and uninstalls them in its destructor. + /// This class is declared before the raw_fd_ostream so that it is constructed + /// before the raw_fd_ostream is constructed and destructed after the + /// raw_fd_ostream is destructed. It installs cleanups in its constructor and + /// uninstalls them in its destructor. class CleanupInstaller { /// The name of the file. std::string Filename; @@ -39,8 +39,7 @@ class tool_output_file { ~CleanupInstaller(); } Installer; - /// OS - The contained stream. This is intentionally declared after - /// Installer. + /// The contained stream. This is intentionally declared after Installer. raw_fd_ostream OS; public: @@ -51,11 +50,11 @@ public: tool_output_file(StringRef Filename, int FD); - /// os - Return the contained raw_fd_ostream. + /// Return the contained raw_fd_ostream. raw_fd_ostream &os() { return OS; } - /// keep - Indicate that the tool's job wrt this output file has been - /// successful and the file should not be deleted. + /// Indicate that the tool's job wrt this output file has been successful and + /// the file should not be deleted. void keep() { Installer.Keep = true; } }; diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index 78829f8..672cf30 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -888,7 +888,7 @@ public: void *Ctxt = nullptr, SourceMgr::DiagHandlerTy DiagHandler = nullptr, void *DiagHandlerCtxt = nullptr); - ~Input(); + ~Input() override; // Check if there was an syntax or semantic error during parsing. std::error_code error(); @@ -955,7 +955,7 @@ private: }; class MapHNode : public HNode { - virtual void anchor(); + void anchor() override; public: MapHNode(Node *n) : HNode(n) { } @@ -974,7 +974,7 @@ private: }; class SequenceHNode : public HNode { - virtual void anchor(); + void anchor() override; public: SequenceHNode(Node *n) : HNode(n) { } @@ -1020,7 +1020,7 @@ private: class Output : public IO { public: Output(llvm::raw_ostream &, void *Ctxt=nullptr); - virtual ~Output(); + ~Output() override; bool outputting() override; bool mapTag(StringRef, bool) override; diff --git a/include/llvm/Support/circular_raw_ostream.h b/include/llvm/Support/circular_raw_ostream.h index ee7b89f..19f9c2c 100644 --- a/include/llvm/Support/circular_raw_ostream.h +++ b/include/llvm/Support/circular_raw_ostream.h @@ -107,30 +107,17 @@ namespace llvm /// management of it, etc. /// circular_raw_ostream(raw_ostream &Stream, const char *Header, - size_t BuffSize = 0, bool Owns = REFERENCE_ONLY) - : raw_ostream(/*unbuffered*/true), - TheStream(nullptr), - OwnsStream(Owns), - BufferSize(BuffSize), - BufferArray(nullptr), - Filled(false), - Banner(Header) { + size_t BuffSize = 0, bool Owns = REFERENCE_ONLY) + : raw_ostream(/*unbuffered*/ true), TheStream(nullptr), + OwnsStream(Owns), BufferSize(BuffSize), BufferArray(nullptr), + Filled(false), Banner(Header) { if (BufferSize != 0) BufferArray = new char[BufferSize]; Cur = BufferArray; setStream(Stream, Owns); } - explicit circular_raw_ostream() - : raw_ostream(/*unbuffered*/true), - TheStream(nullptr), - OwnsStream(REFERENCE_ONLY), - BufferArray(nullptr), - Filled(false), - Banner("") { - Cur = BufferArray; - } - ~circular_raw_ostream() { + ~circular_raw_ostream() override { flush(); flushBufferWithBanner(); releaseStream(); diff --git a/include/llvm/Support/raw_os_ostream.h b/include/llvm/Support/raw_os_ostream.h index 04cf3b6..a983aeb 100644 --- a/include/llvm/Support/raw_os_ostream.h +++ b/include/llvm/Support/raw_os_ostream.h @@ -34,7 +34,7 @@ class raw_os_ostream : public raw_ostream { public: raw_os_ostream(std::ostream &O) : OS(O) {} - ~raw_os_ostream(); + ~raw_os_ostream() override; }; } // end llvm namespace diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index 12783c7..338f0f4 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -20,21 +20,20 @@ #include <system_error> namespace llvm { - class format_object_base; - class FormattedString; - class FormattedNumber; - template <typename T> - class SmallVectorImpl; - - namespace sys { - namespace fs { - enum OpenFlags : unsigned; - } - } - -/// raw_ostream - This class implements an extremely fast bulk output stream -/// that can *only* output to a stream. It does not support seeking, reopening, -/// rewinding, line buffered disciplines etc. It is a simple buffer that outputs +class format_object_base; +class FormattedString; +class FormattedNumber; +template <typename T> class SmallVectorImpl; + +namespace sys { +namespace fs { +enum OpenFlags : unsigned; +} +} + +/// This class implements an extremely fast bulk output stream that can *only* +/// output to a stream. It does not support seeking, reopening, rewinding, line +/// buffered disciplines etc. It is a simple buffer that outputs /// a chunk at a time. class raw_ostream { private: @@ -81,8 +80,8 @@ public: SAVEDCOLOR }; - explicit raw_ostream(bool unbuffered=false) - : BufferMode(unbuffered ? Unbuffered : InternalBuffer) { + explicit raw_ostream(bool unbuffered = false) + : BufferMode(unbuffered ? Unbuffered : InternalBuffer) { // Start out ready to flush. OutBufStart = OutBufEnd = OutBufCur = nullptr; } @@ -96,12 +95,11 @@ public: // Configuration Interface //===--------------------------------------------------------------------===// - /// SetBuffered - Set the stream to be buffered, with an automatically - /// determined buffer size. + /// Set the stream to be buffered, with an automatically determined buffer + /// size. void SetBuffered(); - /// SetBufferSize - Set the stream to be buffered, using the - /// specified buffer size. + /// Set the stream to be buffered, using the specified buffer size. void SetBufferSize(size_t Size) { flush(); SetBufferAndMode(new char[Size], Size, InternalBuffer); @@ -117,10 +115,9 @@ public: return OutBufEnd - OutBufStart; } - /// SetUnbuffered - Set the stream to be unbuffered. When - /// unbuffered, the stream will flush after every write. This routine - /// will also flush the buffer immediately when the stream is being - /// set to unbuffered. + /// Set the stream to be unbuffered. When unbuffered, the stream will flush + /// after every write. This routine will also flush the buffer immediately + /// when the stream is being set to unbuffered. void SetUnbuffered() { flush(); SetBufferAndMode(nullptr, 0, Unbuffered); @@ -204,11 +201,11 @@ public: raw_ostream &operator<<(double N); - /// write_hex - Output \p N in hexadecimal, without any prefix or padding. + /// Output \p N in hexadecimal, without any prefix or padding. raw_ostream &write_hex(unsigned long long N); - /// write_escaped - Output \p Str, turning '\\', '\t', '\n', '"', and - /// anything that doesn't satisfy std::isprint into an escape sequence. + /// Output \p Str, turning '\\', '\t', '\n', '"', and anything that doesn't + /// satisfy std::isprint into an escape sequence. raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false); raw_ostream &write(unsigned char C); @@ -263,8 +260,8 @@ public: //===--------------------------------------------------------------------===// private: - /// write_impl - The is the piece of the class that is implemented - /// by subclasses. This writes the \p Size bytes starting at + /// The is the piece of the class that is implemented by subclasses. This + /// writes the \p Size bytes starting at /// \p Ptr to the underlying stream. /// /// This function is guaranteed to only be called at a point at which it is @@ -281,51 +278,58 @@ private: // An out of line virtual method to provide a home for the class vtable. virtual void handle(); - /// current_pos - Return the current position within the stream, not - /// counting the bytes currently in the buffer. + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. virtual uint64_t current_pos() const = 0; protected: - /// SetBuffer - Use the provided buffer as the raw_ostream buffer. This is - /// intended for use only by subclasses which can arrange for the output to go - /// directly into the desired output buffer, instead of being copied on each - /// flush. + /// Use the provided buffer as the raw_ostream buffer. This is intended for + /// use only by subclasses which can arrange for the output to go directly + /// into the desired output buffer, instead of being copied on each flush. void SetBuffer(char *BufferStart, size_t Size) { SetBufferAndMode(BufferStart, Size, ExternalBuffer); } - /// preferred_buffer_size - Return an efficient buffer size for the - /// underlying output mechanism. + /// Return an efficient buffer size for the underlying output mechanism. virtual size_t preferred_buffer_size() const; - /// getBufferStart - Return the beginning of the current stream buffer, or 0 - /// if the stream is unbuffered. + /// Return the beginning of the current stream buffer, or 0 if the stream is + /// unbuffered. const char *getBufferStart() const { return OutBufStart; } //===--------------------------------------------------------------------===// // Private Interface //===--------------------------------------------------------------------===// private: - /// SetBufferAndMode - Install the given buffer and mode. + /// Install the given buffer and mode. void SetBufferAndMode(char *BufferStart, size_t Size, BufferKind Mode); - /// flush_nonempty - Flush the current buffer, which is known to be - /// non-empty. This outputs the currently buffered data and resets - /// the buffer to empty. + /// Flush the current buffer, which is known to be non-empty. This outputs the + /// currently buffered data and resets the buffer to empty. void flush_nonempty(); - /// copy_to_buffer - Copy data into the buffer. Size must not be - /// greater than the number of unused bytes in the buffer. + /// Copy data into the buffer. Size must not be greater than the number of + /// unused bytes in the buffer. void copy_to_buffer(const char *Ptr, size_t Size); }; +/// An abstract base class for streams implementations that also support a +/// pwrite operation. This is usefull for code that can mostly stream out data, +/// but needs to patch in a header that needs to know the output size. +class raw_pwrite_stream : public raw_ostream { +public: + explicit raw_pwrite_stream(bool Unbuffered = false) + : raw_ostream(Unbuffered) {} + virtual void pwrite(const char *Ptr, size_t Size, uint64_t Offset) = 0; +}; + //===----------------------------------------------------------------------===// // File Output Streams //===----------------------------------------------------------------------===// -/// raw_fd_ostream - A raw_ostream that writes to a file descriptor. +/// A raw_ostream that writes to a file descriptor. /// -class raw_fd_ostream : public raw_ostream { +class raw_fd_ostream : public raw_pwrite_stream { int FD; bool ShouldClose; @@ -339,18 +343,19 @@ class raw_fd_ostream : public raw_ostream { uint64_t pos; - /// write_impl - See raw_ostream::write_impl. + bool SupportsSeeking; + + /// See raw_ostream::write_impl. void write_impl(const char *Ptr, size_t Size) override; - /// current_pos - Return the current position within the stream, not - /// counting the bytes currently in the buffer. + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. uint64_t current_pos() const override { return pos; } - /// preferred_buffer_size - Determine an efficient buffer size. + /// Determine an efficient buffer size. size_t preferred_buffer_size() const override; - /// error_detected - Set the flag indicating that an output error has - /// been encountered. + /// Set the flag indicating that an output error has been encountered. void error_detected() { Error = true; } public: @@ -367,22 +372,26 @@ public: raw_fd_ostream(StringRef Filename, std::error_code &EC, sys::fs::OpenFlags Flags); - /// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If - /// ShouldClose is true, this closes the file when the stream is destroyed. + /// FD is the file descriptor that this writes to. If ShouldClose is true, + /// this closes the file when the stream is destroyed. raw_fd_ostream(int fd, bool shouldClose, bool unbuffered=false); - ~raw_fd_ostream(); + ~raw_fd_ostream() override; - /// close - Manually flush the stream and close the file. - /// Note that this does not call fsync. + /// Manually flush the stream and close the file. Note that this does not call + /// fsync. void close(); - /// seek - Flushes the stream and repositions the underlying file descriptor - /// position to the offset specified from the beginning of the file. + bool supportsSeeking() { return SupportsSeeking; } + + /// Flushes the stream and repositions the underlying file descriptor position + /// to the offset specified from the beginning of the file. uint64_t seek(uint64_t off); - /// SetUseAtomicWrite - Set the stream to attempt to use atomic writes for - /// individual output routines where possible. + void pwrite(const char *Ptr, size_t Size, uint64_t Offset) override; + + /// Set the stream to attempt to use atomic writes for individual output + /// routines where possible. /// /// Note that because raw_ostream's are typically buffered, this flag is only /// sensible when used on unbuffered streams which will flush their output @@ -401,18 +410,18 @@ public: bool has_colors() const override; - /// has_error - Return the value of the flag in this raw_fd_ostream indicating - /// whether an output error has been encountered. + /// Return the value of the flag in this raw_fd_ostream indicating whether an + /// output error has been encountered. /// This doesn't implicitly flush any pending output. Also, it doesn't /// guarantee to detect all errors unless the stream has been closed. bool has_error() const { return Error; } - /// clear_error - Set the flag read by has_error() to false. If the error - /// flag is set at the time when this raw_ostream's destructor is called, - /// report_fatal_error is called to report the error. Use clear_error() - /// after handling the error to avoid this behavior. + /// Set the flag read by has_error() to false. If the error flag is set at the + /// time when this raw_ostream's destructor is called, report_fatal_error is + /// called to report the error. Use clear_error() after handling the error to + /// avoid this behavior. /// /// "Errors should never pass silently. /// Unless explicitly silenced." @@ -423,87 +432,105 @@ public: } }; -/// outs() - This returns a reference to a raw_ostream for standard output. -/// Use it like: outs() << "foo" << "bar"; +/// This returns a reference to a raw_ostream for standard output. Use it like: +/// outs() << "foo" << "bar"; raw_ostream &outs(); -/// errs() - This returns a reference to a raw_ostream for standard error. -/// Use it like: errs() << "foo" << "bar"; +/// This returns a reference to a raw_ostream for standard error. Use it like: +/// errs() << "foo" << "bar"; raw_ostream &errs(); -/// nulls() - This returns a reference to a raw_ostream which simply discards -/// output. +/// This returns a reference to a raw_ostream which simply discards output. raw_ostream &nulls(); //===----------------------------------------------------------------------===// // Output Stream Adaptors //===----------------------------------------------------------------------===// -/// raw_string_ostream - A raw_ostream that writes to an std::string. This is a -/// simple adaptor class. This class does not encounter output errors. +/// A raw_ostream that writes to an std::string. This is a simple adaptor +/// class. This class does not encounter output errors. class raw_string_ostream : public raw_ostream { std::string &OS; - /// write_impl - See raw_ostream::write_impl. + /// See raw_ostream::write_impl. void write_impl(const char *Ptr, size_t Size) override; - /// current_pos - Return the current position within the stream, not - /// counting the bytes currently in the buffer. + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. uint64_t current_pos() const override { return OS.size(); } public: explicit raw_string_ostream(std::string &O) : OS(O) {} - ~raw_string_ostream(); + ~raw_string_ostream() override; - /// str - Flushes the stream contents to the target string and returns - /// the string's reference. + /// Flushes the stream contents to the target string and returns the string's + /// reference. std::string& str() { flush(); return OS; } }; -/// raw_svector_ostream - A raw_ostream that writes to an SmallVector or -/// SmallString. This is a simple adaptor class. This class does not -/// encounter output errors. -class raw_svector_ostream : public raw_ostream { +/// A raw_ostream that writes to an SmallVector or SmallString. This is a +/// simple adaptor class. This class does not encounter output errors. +class raw_svector_ostream : public raw_pwrite_stream { SmallVectorImpl<char> &OS; - /// write_impl - See raw_ostream::write_impl. + /// See raw_ostream::write_impl. void write_impl(const char *Ptr, size_t Size) override; - /// current_pos - Return the current position within the stream, not - /// counting the bytes currently in the buffer. + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. uint64_t current_pos() const override; + +protected: + // Like the regular constructor, but doesn't call init. + explicit raw_svector_ostream(SmallVectorImpl<char> &O, unsigned); + void init(); + public: /// Construct a new raw_svector_ostream. /// /// \param O The vector to write to; this should generally have at least 128 /// bytes free to avoid any extraneous memory overhead. explicit raw_svector_ostream(SmallVectorImpl<char> &O); - ~raw_svector_ostream(); + ~raw_svector_ostream() override; - /// resync - This is called when the SmallVector we're appending to is changed - /// outside of the raw_svector_ostream's control. It is only safe to do this - /// if the raw_svector_ostream has previously been flushed. + void pwrite(const char *Ptr, size_t Size, uint64_t Offset) override; + + /// This is called when the SmallVector we're appending to is changed outside + /// of the raw_svector_ostream's control. It is only safe to do this if the + /// raw_svector_ostream has previously been flushed. void resync(); - /// str - Flushes the stream contents to the target vector and return a - /// StringRef for the vector contents. + /// Flushes the stream contents to the target vector and return a StringRef + /// for the vector contents. StringRef str(); }; -/// raw_null_ostream - A raw_ostream that discards all output. -class raw_null_ostream : public raw_ostream { - /// write_impl - See raw_ostream::write_impl. +/// A raw_ostream that discards all output. +class raw_null_ostream : public raw_pwrite_stream { + /// See raw_ostream::write_impl. void write_impl(const char *Ptr, size_t size) override; - /// current_pos - Return the current position within the stream, not - /// counting the bytes currently in the buffer. + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. uint64_t current_pos() const override; public: explicit raw_null_ostream() {} - ~raw_null_ostream(); + ~raw_null_ostream() override; + void pwrite(const char *Ptr, size_t Size, uint64_t Offset) override; +}; + +class buffer_ostream : public raw_svector_ostream { + raw_ostream &OS; + SmallVector<char, 0> Buffer; + +public: + buffer_ostream(raw_ostream &OS) : raw_svector_ostream(Buffer, 0), OS(OS) { + init(); + } + ~buffer_ostream() { OS << str(); } }; } // end llvm namespace diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index 5233493..e746e7d 100644 --- a/include/llvm/TableGen/Record.h +++ b/include/llvm/TableGen/Record.h @@ -1442,8 +1442,6 @@ public: TheInit(O.TheInit), IsAnonymous(O.IsAnonymous), ResolveFirst(O.ResolveFirst) { } - ~Record() {} - static unsigned getNewUID() { return LastID++; } unsigned getID() const { return ID; } diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index 6c970d0..1ff8db8 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -207,6 +207,12 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment, // The function should return 0 to select the default order defined by // MemberList, 1 to select the first AltOrders entry and so on. code AltOrderSelect = [{}]; + + // Specify allocation priority for register allocators using a greedy + // heuristic. Classes with higher priority values are assigned first. This is + // useful as it is sometimes beneficial to assign registers to highly + // constrained classes first. The value has to be in the range [0,63]. + int AllocationPriority = 0; } // The memberList in a RegisterClass is a dag of set operations. TableGen @@ -1015,6 +1021,11 @@ class AsmWriter { // name. string AsmWriterClassName = "InstPrinter"; + // PassSubtarget - Determines whether MCSubtargetInfo should be passed to + // the various print methods. + // FIXME: Remove after all ports are updated. + int PassSubtarget = 0; + // Variant - AsmWriters can be of multiple different variants. Variants are // used to support targets that need to emit assembly code in ways that are // mostly the same for different targets, but have minor differences in diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index 87aba9f..2a1ce04 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -48,6 +48,7 @@ class TargetSubtargetInfo; class TargetTransformInfo; class formatted_raw_ostream; class raw_ostream; +class raw_pwrite_stream; class TargetLoweringObjectFile; // The old pass manager infrastructure is hidden in a legacy namespace now. @@ -58,9 +59,9 @@ using legacy::PassManagerBase; //===----------------------------------------------------------------------===// /// -/// TargetMachine - Primary interface to the complete machine description for -/// the target machine. All target-specific information should be accessible -/// through this interface. +/// Primary interface to the complete machine description for the target +/// machine. All target-specific information should be accessible through this +/// interface. /// class TargetMachine { TargetMachine(const TargetMachine &) = delete; @@ -70,25 +71,25 @@ protected: // Can only create subclasses. StringRef TargetTriple, StringRef CPU, StringRef FS, const TargetOptions &Options); - /// TheTarget - The Target that this machine was created for. + /// The Target that this machine was created for. const Target &TheTarget; - /// DataLayout - For ABI type size and alignment. + /// For ABI type size and alignment. const DataLayout DL; - /// TargetTriple, TargetCPU, TargetFS - Triple string, CPU name, and target - /// feature strings the TargetMachine instance is created with. + /// Triple string, CPU name, and target feature strings the TargetMachine + /// instance is created with. std::string TargetTriple; std::string TargetCPU; std::string TargetFS; - /// CodeGenInfo - Low level target information such as relocation model. - /// Non-const to allow resetting optimization level per-function. + /// Low level target information such as relocation model. Non-const to + /// allow resetting optimization level per-function. MCCodeGenInfo *CodeGenInfo; - /// AsmInfo - Contains target specific asm information. - /// + /// Contains target specific asm information. const MCAsmInfo *AsmInfo; + const MCRegisterInfo *MRI; const MCInstrInfo *MII; const MCSubtargetInfo *STI; @@ -106,8 +107,8 @@ public: StringRef getTargetCPU() const { return TargetCPU; } StringRef getTargetFeatureString() const { return TargetFS; } - /// getSubtargetImpl - virtual method implemented by subclasses that returns - /// a reference to that target's TargetSubtargetInfo-derived member variable. + /// Virtual method implemented by subclasses that returns a reference to that + /// target's TargetSubtargetInfo-derived member variable. virtual const TargetSubtargetInfo *getSubtargetImpl(const Function &) const { return nullptr; } @@ -115,15 +116,15 @@ public: return nullptr; } - /// getSubtarget - This method returns a pointer to the specified type of + /// This method returns a pointer to the specified type of /// TargetSubtargetInfo. In debug builds, it verifies that the object being /// returned is of the correct type. template <typename STC> const STC &getSubtarget(const Function &F) const { return *static_cast<const STC*>(getSubtargetImpl(F)); } - /// getDataLayout - This method returns a pointer to the DataLayout for - /// the target. It should be unchanging for every subtarget. + /// This method returns a pointer to the DataLayout for the target. It should + /// be unchanging for every subtarget. const DataLayout *getDataLayout() const { return &DL; } /// \brief Reset the target options based on the function's attributes. @@ -131,16 +132,14 @@ public: // from TargetMachine. void resetTargetOptions(const Function &F) const; - /// getMCAsmInfo - Return target specific asm information. - /// + /// Return target specific asm information. const MCAsmInfo *getMCAsmInfo() const { return AsmInfo; } + const MCRegisterInfo *getMCRegisterInfo() const { return MRI; } const MCInstrInfo *getMCInstrInfo() const { return MII; } const MCSubtargetInfo *getMCSubtargetInfo() const { return STI; } - /// getIntrinsicInfo - If intrinsic information is available, return it. If - /// not, return null. - /// + /// If intrinsic information is available, return it. If not, return null. virtual const TargetIntrinsicInfo *getIntrinsicInfo() const { return nullptr; } @@ -148,20 +147,18 @@ public: bool requiresStructuredCFG() const { return RequireStructuredCFG; } void setRequiresStructuredCFG(bool Value) { RequireStructuredCFG = Value; } - /// getRelocationModel - Returns the code generation relocation model. The - /// choices are static, PIC, and dynamic-no-pic, and target default. + /// Returns the code generation relocation model. The choices are static, PIC, + /// and dynamic-no-pic, and target default. Reloc::Model getRelocationModel() const; - /// getCodeModel - Returns the code model. The choices are small, kernel, - /// medium, large, and target default. + /// Returns the code model. The choices are small, kernel, medium, large, and + /// target default. CodeModel::Model getCodeModel() const; - /// getTLSModel - Returns the TLS model which should be used for the given - /// global variable. + /// Returns the TLS model which should be used for the given global variable. TLSModel::Model getTLSModel(const GlobalValue *GV) const; - /// getOptLevel - Returns the optimization level: None, Less, - /// Default, or Aggressive. + /// Returns the optimization level: None, Less, Default, or Aggressive. CodeGenOpt::Level getOptLevel() const; /// \brief Overrides the optimization level. @@ -198,21 +195,20 @@ public: /// uses this to answer queries about the IR. virtual TargetIRAnalysis getTargetIRAnalysis(); - /// CodeGenFileType - These enums are meant to be passed into - /// addPassesToEmitFile to indicate what type of file to emit, and returned by - /// it to indicate what type of file could actually be made. + /// These enums are meant to be passed into addPassesToEmitFile to indicate + /// what type of file to emit, and returned by it to indicate what type of + /// file could actually be made. enum CodeGenFileType { CGFT_AssemblyFile, CGFT_ObjectFile, CGFT_Null // Do not emit any output. }; - /// addPassesToEmitFile - Add passes to the specified pass manager to get the - /// specified file emitted. Typically this will involve several steps of code - /// generation. This method should return true if emission of this file type - /// is not supported, or false on success. - virtual bool addPassesToEmitFile(PassManagerBase &, - formatted_raw_ostream &, + /// Add passes to the specified pass manager to get the specified file + /// emitted. Typically this will involve several steps of code generation. + /// This method should return true if emission of this file type is not + /// supported, or false on success. + virtual bool addPassesToEmitFile(PassManagerBase &, raw_pwrite_stream &, CodeGenFileType, bool /*DisableVerify*/ = true, AnalysisID /*StartAfter*/ = nullptr, @@ -220,14 +216,13 @@ public: return true; } - /// addPassesToEmitMC - Add passes to the specified pass manager to get - /// machine code emitted with the MCJIT. This method returns true if machine - /// code is not supported. It fills the MCContext Ctx pointer which can be - /// used to build custom MCStreamer. + /// Add passes to the specified pass manager to get machine code emitted with + /// the MCJIT. This method returns true if machine code is not supported. It + /// fills the MCContext Ctx pointer which can be used to build custom + /// MCStreamer. /// - virtual bool addPassesToEmitMC(PassManagerBase &, - MCContext *&, - raw_ostream &, + virtual bool addPassesToEmitMC(PassManagerBase &, MCContext *&, + raw_pwrite_stream &, bool /*DisableVerify*/ = true) { return true; } @@ -237,8 +232,8 @@ public: MCSymbol *getSymbol(const GlobalValue *GV, Mangler &Mang) const; }; -/// LLVMTargetMachine - This class describes a target machine that is -/// implemented with the LLVM target-independent code generator. +/// This class describes a target machine that is implemented with the LLVM +/// target-independent code generator. /// class LLVMTargetMachine : public TargetMachine { protected: // Can only create subclasses. @@ -255,25 +250,24 @@ public: /// generator to answer queries about the IR. TargetIRAnalysis getTargetIRAnalysis() override; - /// createPassConfig - Create a pass configuration object to be used by - /// addPassToEmitX methods for generating a pipeline of CodeGen passes. + /// Create a pass configuration object to be used by addPassToEmitX methods + /// for generating a pipeline of CodeGen passes. virtual TargetPassConfig *createPassConfig(PassManagerBase &PM); - /// addPassesToEmitFile - Add passes to the specified pass manager to get the - /// specified file emitted. Typically this will involve several steps of code - /// generation. - bool addPassesToEmitFile(PassManagerBase &PM, formatted_raw_ostream &Out, + /// Add passes to the specified pass manager to get the specified file + /// emitted. Typically this will involve several steps of code generation. + bool addPassesToEmitFile(PassManagerBase &PM, raw_pwrite_stream &Out, CodeGenFileType FileType, bool DisableVerify = true, AnalysisID StartAfter = nullptr, AnalysisID StopAfter = nullptr) override; - /// addPassesToEmitMC - Add passes to the specified pass manager to get - /// machine code emitted with the MCJIT. This method returns true if machine - /// code is not supported. It fills the MCContext Ctx pointer which can be - /// used to build custom MCStreamer. - /// + /// Add passes to the specified pass manager to get machine code emitted with + /// the MCJIT. This method returns true if machine code is not supported. It + /// fills the MCContext Ctx pointer which can be used to build custom + /// MCStreamer. bool addPassesToEmitMC(PassManagerBase &PM, MCContext *&Ctx, - raw_ostream &OS, bool DisableVerify = true) override; + raw_pwrite_stream &OS, + bool DisableVerify = true) override; }; } // End llvm namespace diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index f447fd6..d41ca99 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -212,9 +212,9 @@ namespace llvm { /// FloatABIType - This setting is set by -float-abi=xxx option is specfied /// on the command line. This setting may either be Default, Soft, or Hard. /// Default selects the target's default behavior. Soft selects the ABI for - /// UseSoftFloat, but does not indicate that FP hardware may not be used. - /// Such a combination is unfortunately popular (e.g. arm-apple-darwin). - /// Hard presumes that the normal FP ABI is used. + /// software floating point, but does not indicate that FP hardware may not + /// be used. Such a combination is unfortunately popular (e.g. + /// arm-apple-darwin). Hard presumes that the normal FP ABI is used. FloatABI::ABIType FloatABIType; /// AllowFPOpFusion - This flag is set by the -fuse-fp-ops=xxx option. diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 4184052..121b8a2 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -46,6 +46,9 @@ public: const uint32_t *SubClassMask; const uint16_t *SuperRegIndices; const unsigned LaneMask; + /// Classes with a higher priority value are assigned first by register + /// allocators using a greedy heuristic. The value is in the range [0,63]. + const uint8_t AllocationPriority; /// Whether the class supports two (or more) disjunct subregister indices. const bool HasDisjunctSubRegs; const sc_iterator SuperClasses; diff --git a/include/llvm/Target/TargetSubtargetInfo.h b/include/llvm/Target/TargetSubtargetInfo.h index bb5409b6..0f42790 100644 --- a/include/llvm/Target/TargetSubtargetInfo.h +++ b/include/llvm/Target/TargetSubtargetInfo.h @@ -42,15 +42,17 @@ template <typename T> class SmallVectorImpl; /// be exposed through a TargetSubtargetInfo-derived class. /// class TargetSubtargetInfo : public MCSubtargetInfo { - TargetSubtargetInfo(const TargetSubtargetInfo&) = delete; - void operator=(const TargetSubtargetInfo&) = delete; + TargetSubtargetInfo(const TargetSubtargetInfo &) = delete; + void operator=(const TargetSubtargetInfo &) = delete; + protected: // Can only create subclasses... TargetSubtargetInfo(); + public: // AntiDepBreakMode - Type of anti-dependence breaking that should // be performed before post-RA scheduling. typedef enum { ANTIDEP_NONE, ANTIDEP_CRITICAL, ANTIDEP_ALL } AntiDepBreakMode; - typedef SmallVectorImpl<const TargetRegisterClass*> RegClassVector; + typedef SmallVectorImpl<const TargetRegisterClass *> RegClassVector; virtual ~TargetSubtargetInfo(); @@ -89,8 +91,9 @@ public: /// MCSchedClassDesc with the isVariant property. This may return the ID of /// another variant SchedClass, but repeated invocation must quickly terminate /// in a nonvariant SchedClass. - virtual unsigned resolveSchedClass(unsigned SchedClass, const MachineInstr *MI, - const TargetSchedModel* SchedModel) const { + virtual unsigned resolveSchedClass(unsigned SchedClass, + const MachineInstr *MI, + const TargetSchedModel *SchedModel) const { return 0; } @@ -128,20 +131,16 @@ public: /// scheduling heuristics (no custom MachineSchedStrategy) to make /// changes to the generic scheduling policy. virtual void overrideSchedPolicy(MachineSchedPolicy &Policy, - MachineInstr *begin, - MachineInstr *end, + MachineInstr *begin, MachineInstr *end, unsigned NumRegionInstrs) const {} // \brief Perform target specific adjustments to the latency of a schedule // dependency. - virtual void adjustSchedDependency(SUnit *def, SUnit *use, - SDep& dep) const { } + virtual void adjustSchedDependency(SUnit *def, SUnit *use, SDep &dep) const {} // For use with PostRAScheduling: get the anti-dependence breaking that should // be performed before post-RA scheduling. - virtual AntiDepBreakMode getAntiDepBreakMode() const { - return ANTIDEP_NONE; - } + virtual AntiDepBreakMode getAntiDepBreakMode() const { return ANTIDEP_NONE; } // For use with PostRAScheduling: in CriticalPathRCs, return any register // classes that should only be considered for anti-dependence breaking if they @@ -177,9 +176,7 @@ public: } /// Enable tracking of subregister liveness in register allocator. - virtual bool enableSubRegLiveness() const { - return false; - } + virtual bool enableSubRegLiveness() const { return false; } }; } // End llvm namespace diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h index 2d754d0..925ebda 100644 --- a/include/llvm/Transforms/Scalar.h +++ b/include/llvm/Transforms/Scalar.h @@ -427,6 +427,11 @@ createSeparateConstOffsetFromGEPPass(const TargetMachine *TM = nullptr, // BasicBlockPass *createLoadCombinePass(); +//===----------------------------------------------------------------------===// +// +// StraightLineStrengthReduce - This pass strength-reduces some certain +// instruction patterns in straight-line code. +// FunctionPass *createStraightLineStrengthReducePass(); //===----------------------------------------------------------------------===// @@ -446,6 +451,18 @@ ModulePass *createPlaceSafepointsPass(); // FunctionPass *createRewriteStatepointsForGCPass(); +//===----------------------------------------------------------------------===// +// +// Float2Int - Demote floats to ints where possible. +// +FunctionPass *createFloat2IntPass(); + +//===----------------------------------------------------------------------===// +// +// NaryReassociate - Simplify n-ary operations by reassociation. +// +FunctionPass *createNaryReassociatePass(); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/LoopUtils.h b/include/llvm/Transforms/Utils/LoopUtils.h index 2eb2555..e8f3172 100644 --- a/include/llvm/Transforms/Utils/LoopUtils.h +++ b/include/llvm/Transforms/Utils/LoopUtils.h @@ -122,6 +122,10 @@ bool promoteLoopAccessesToScalars(AliasSet &, SmallVectorImpl<BasicBlock*> &, /// Updates safety information in LICMSafetyInfo argument. void computeLICMSafetyInfo(LICMSafetyInfo *, Loop *); +/// \brief Checks if the given PHINode in a loop header is an induction +/// variable. Returns true if this is an induction PHI along with the step +/// value. +bool isInductionPHI(PHINode *, ScalarEvolution *, ConstantInt *&); } #endif diff --git a/include/llvm/Transforms/Utils/ModuleUtils.h b/include/llvm/Transforms/Utils/ModuleUtils.h index 16904f1..907563e 100644 --- a/include/llvm/Transforms/Utils/ModuleUtils.h +++ b/include/llvm/Transforms/Utils/ModuleUtils.h @@ -20,6 +20,7 @@ class Module; class Function; class GlobalValue; class GlobalVariable; +class Constant; template <class PtrType> class SmallPtrSetImpl; /// Append F to the list of global ctors of module M with the given Priority. @@ -36,6 +37,12 @@ void appendToGlobalDtors(Module &M, Function *F, int Priority); GlobalVariable *collectUsedGlobalVariables(Module &M, SmallPtrSetImpl<GlobalValue *> &Set, bool CompilerUsed); + +// Validate the result of Module::getOrInsertFunction called for an interface +// function of given sanitizer. If the instrumented module defines a function +// with the same name, their prototypes must match, otherwise +// getOrInsertFunction returns a bitcast. +Function *checkSanitizerInterfaceFunction(Constant *FuncOrBitcast); } // End llvm namespace #endif // LLVM_TRANSFORMS_UTILS_MODULEUTILS_H diff --git a/include/llvm/Transforms/Utils/SymbolRewriter.h b/include/llvm/Transforms/Utils/SymbolRewriter.h index 48dea04..5ccee98 100644 --- a/include/llvm/Transforms/Utils/SymbolRewriter.h +++ b/include/llvm/Transforms/Utils/SymbolRewriter.h @@ -90,9 +90,6 @@ typedef iplist<RewriteDescriptor> RewriteDescriptorList; class RewriteMapParser { public: - RewriteMapParser() {} - ~RewriteMapParser() {} - bool parse(const std::string &MapFile, RewriteDescriptorList *Descriptors); private: diff --git a/include/llvm/Transforms/Utils/UnrollLoop.h b/include/llvm/Transforms/Utils/UnrollLoop.h index 04d9ee1..7f2cf8d 100644 --- a/include/llvm/Transforms/Utils/UnrollLoop.h +++ b/include/llvm/Transforms/Utils/UnrollLoop.h @@ -28,11 +28,13 @@ class MDNode; class Pass; bool UnrollLoop(Loop *L, unsigned Count, unsigned TripCount, bool AllowRuntime, - unsigned TripMultiple, LoopInfo *LI, Pass *PP, - LPPassManager *LPM, AssumptionCache *AC); + bool AllowExpensiveTripCount, unsigned TripMultiple, + LoopInfo *LI, Pass *PP, LPPassManager *LPM, + AssumptionCache *AC); -bool UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo *LI, - LPPassManager* LPM); +bool UnrollRuntimeLoopProlog(Loop *L, unsigned Count, + bool AllowExpensiveTripCount, LoopInfo *LI, + LPPassManager *LPM); MDNode *GetUnrollMetadata(MDNode *LoopID, StringRef Name); } |