diff options
Diffstat (limited to 'include/llvm')
158 files changed, 3661 insertions, 3510 deletions
diff --git a/include/llvm/ADT/APFloat.h b/include/llvm/ADT/APFloat.h index ffd8975..43a7866 100644 --- a/include/llvm/ADT/APFloat.h +++ b/include/llvm/ADT/APFloat.h @@ -21,9 +21,6 @@ namespace llvm { -/// A signed type to represent a floating point numbers unbiased exponent. -typedef signed short exponent_t; - struct fltSemantics; class APSInt; class StringRef; @@ -120,11 +117,14 @@ enum lostFraction { // Example of truncated bits: /// New formats: x87 in single and double precision mode (IEEE apart from /// extended exponent range) (hard). /// -/// New operations: sqrt, IEEE remainder, C90 fmod, nextafter, nexttoward. +/// New operations: sqrt, IEEE remainder, C90 fmod, nexttoward. /// class APFloat { public: + /// A signed type to represent a floating point numbers unbiased exponent. + typedef signed short ExponentType; + /// \name Floating Point Semantics. /// @{ @@ -191,7 +191,6 @@ public: APFloat(const fltSemantics &); // Default construct to 0.0 APFloat(const fltSemantics &, StringRef); APFloat(const fltSemantics &, integerPart); - APFloat(const fltSemantics &, fltCategory, bool negative); APFloat(const fltSemantics &, uninitializedTag); APFloat(const fltSemantics &, const APInt &); explicit APFloat(double d); @@ -211,14 +210,18 @@ public: /// /// \param Negative True iff the number should be negative. static APFloat getZero(const fltSemantics &Sem, bool Negative = false) { - return APFloat(Sem, fcZero, Negative); + APFloat Val(Sem, uninitialized); + Val.makeZero(Negative); + return Val; } /// Factory for Positive and Negative Infinity. /// /// \param Negative True iff the number should be negative. static APFloat getInf(const fltSemantics &Sem, bool Negative = false) { - return APFloat(Sem, fcInfinity, Negative); + APFloat Val(Sem, uninitialized); + Val.makeInf(Negative); + return Val; } /// Factory for QNaN values. @@ -300,6 +303,8 @@ public: /// IEEE-754R 5.3.1: nextUp/nextDown. opStatus next(bool nextDown); + /// @} + /// \name Sign operations. /// @{ @@ -359,10 +364,7 @@ public: /// /// This implies that the current value of the float is not zero, subnormal, /// infinite, or NaN following the definition of normality from IEEE-754R. - /// - /// The current implementation of isNormal() differs from this by treating - /// subnormal values as normal values. - bool isIEEENormal() const { return !isDenormal() && isNormal(); } + bool isNormal() const { return !isDenormal() && isFiniteNonZero(); } /// Returns true if and only if the current value is zero, subnormal, or /// normal. @@ -394,10 +396,18 @@ public: fltCategory getCategory() const { return category; } const fltSemantics &getSemantics() const { return *semantics; } bool isNonZero() const { return category != fcZero; } - bool isNormal() const { return category == fcNormal; } + bool isFiniteNonZero() const { return isFinite() && !isZero(); } bool isPosZero() const { return isZero() && !isNegative(); } bool isNegZero() const { return isZero() && isNegative(); } + /// Returns true if and only if the number has the smallest possible non-zero + /// magnitude in the current semantics. + bool isSmallest() const; + + /// Returns true if and only if the number has the largest possible finite + /// magnitude in the current semantics. + bool isLargest() const; + /// @} APFloat &operator=(const APFloat &); @@ -491,24 +501,15 @@ private: void makeNaN(bool SNaN = false, bool Neg = false, const APInt *fill = 0); static APFloat makeNaN(const fltSemantics &Sem, bool SNaN, bool Negative, const APInt *fill); - - /// @} - - /// \name Special value queries only useful internally to APFloat - /// @{ - - /// Returns true if and only if the number has the smallest possible non-zero - /// magnitude in the current semantics. - bool isSmallest() const; - /// Returns true if and only if the number has the largest possible finite - /// magnitude in the current semantics. - bool isLargest() const; + void makeInf(bool Neg = false); + void makeZero(bool Neg = false); /// @} /// \name Miscellany /// @{ + bool convertFromStringSpecials(StringRef str); opStatus normalize(roundingMode, lostFraction); opStatus addOrSubtract(const APFloat &, roundingMode, bool subtract); cmpResult compareAbsoluteValue(const APFloat &) const; @@ -557,7 +558,7 @@ private: } significand; /// The signed unbiased exponent of the value. - exponent_t exponent; + ExponentType exponent; /// What kind of floating point number this is. /// diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h index e5797b8..625a6db 100644 --- a/include/llvm/ADT/APInt.h +++ b/include/llvm/ADT/APInt.h @@ -337,13 +337,17 @@ public: /// \brief Determine if all bits are set /// /// This checks to see if the value has all bits of the APInt are set or not. - bool isAllOnesValue() const { return countPopulation() == BitWidth; } + bool isAllOnesValue() const { + if (isSingleWord()) + return VAL == ~integerPart(0) >> (APINT_BITS_PER_WORD - BitWidth); + return countPopulationSlowCase() == BitWidth; + } /// \brief Determine if this is the largest unsigned value. /// /// This checks to see if the value of this APInt is the maximum unsigned /// value for the APInt's bit width. - bool isMaxValue() const { return countPopulation() == BitWidth; } + bool isMaxValue() const { return isAllOnesValue(); } /// \brief Determine if this is the largest signed value. /// diff --git a/include/llvm/ADT/IntervalMap.h b/include/llvm/ADT/IntervalMap.h index 44a61ff..1ca3288 100644 --- a/include/llvm/ADT/IntervalMap.h +++ b/include/llvm/ADT/IntervalMap.h @@ -612,7 +612,7 @@ public: /// insertFrom - Add mapping of [a;b] to y if possible, coalescing as much as /// possible. This may cause the node to grow by 1, or it may cause the node /// to shrink because of coalescing. -/// @param i Starting index = insertFrom(0, size, a) +/// @param Pos Starting index = insertFrom(0, size, a) /// @param Size Number of elements in node. /// @param a Interval start. /// @param b Interval stop. @@ -1956,7 +1956,7 @@ iterator::eraseNode(unsigned Level) { /// overflow - Distribute entries of the current node evenly among /// its siblings and ensure that the current node is not full. /// This may require allocating a new node. -/// @param NodeT The type of node at Level (Leaf or Branch). +/// @tparam NodeT The type of node at Level (Leaf or Branch). /// @param Level path index of the overflowing node. /// @return True when the tree height was changed. template <typename KeyT, typename ValT, unsigned N, typename Traits> diff --git a/include/llvm/ADT/NullablePtr.h b/include/llvm/ADT/NullablePtr.h deleted file mode 100644 index 8ddfd5d..0000000 --- a/include/llvm/ADT/NullablePtr.h +++ /dev/null @@ -1,52 +0,0 @@ -//===- llvm/ADT/NullablePtr.h - A pointer that allows null ------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines and implements the NullablePtr class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_ADT_NULLABLEPTR_H -#define LLVM_ADT_NULLABLEPTR_H - -#include <cassert> -#include <cstddef> - -namespace llvm { -/// NullablePtr pointer wrapper - NullablePtr is used for APIs where a -/// potentially-null pointer gets passed around that must be explicitly handled -/// in lots of places. By putting a wrapper around the null pointer, it makes -/// it more likely that the null pointer case will be handled correctly. -template<class T> -class NullablePtr { - T *Ptr; -public: - NullablePtr(T *P = 0) : Ptr(P) {} - - bool isNull() const { return Ptr == 0; } - bool isNonNull() const { return Ptr != 0; } - - /// get - Return the pointer if it is non-null. - const T *get() const { - assert(Ptr && "Pointer wasn't checked for null!"); - return Ptr; - } - - /// get - Return the pointer if it is non-null. - T *get() { - assert(Ptr && "Pointer wasn't checked for null!"); - return Ptr; - } - - T *getPtrOrNull() { return Ptr; } - const T *getPtrOrNull() const { return Ptr; } -}; - -} // end namespace llvm - -#endif diff --git a/include/llvm/ADT/SmallBitVector.h b/include/llvm/ADT/SmallBitVector.h index fe9bef9..86949b2 100644 --- a/include/llvm/ADT/SmallBitVector.h +++ b/include/llvm/ADT/SmallBitVector.h @@ -426,6 +426,40 @@ public: return *this; } + /// reset - Reset bits that are set in RHS. Same as *this &= ~RHS. + SmallBitVector &reset(const SmallBitVector &RHS) { + if (isSmall() && RHS.isSmall()) + setSmallBits(getSmallBits() & ~RHS.getSmallBits()); + else if (!isSmall() && !RHS.isSmall()) + getPointer()->reset(*RHS.getPointer()); + else + for (unsigned i = 0, e = std::min(size(), RHS.size()); i != e; ++i) + if (RHS.test(i)) + reset(i); + + return *this; + } + + /// test - Check if (This - RHS) is zero. + /// This is the same as reset(RHS) and any(). + bool test(const SmallBitVector &RHS) const { + if (isSmall() && RHS.isSmall()) + return (getSmallBits() & ~RHS.getSmallBits()) != 0; + if (!isSmall() && !RHS.isSmall()) + return getPointer()->test(*RHS.getPointer()); + + unsigned i, e; + for (i = 0, e = std::min(size(), RHS.size()); i != e; ++i) + if (test(i) && !RHS.test(i)) + return true; + + for (e = size(); i != e; ++i) + if (test(i)) + return true; + + return false; + } + SmallBitVector &operator|=(const SmallBitVector &RHS) { resize(std::max(size(), RHS.size())); if (isSmall()) diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index d013d05..3e1e24c 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -19,7 +19,7 @@ #include <utility> namespace llvm { - template<typename T> + template <typename T> class SmallVectorImpl; class APInt; class hash_code; @@ -548,6 +548,10 @@ namespace llvm { template <typename T> struct isPodLike; template <> struct isPodLike<StringRef> { static const bool value = true; }; + /// Construct a string ref from a boolean. + inline StringRef toStringRef(bool B) { + return StringRef(B ? "true" : "false"); + } } #endif diff --git a/include/llvm/ADT/Triple.h b/include/llvm/ADT/Triple.h index 41e463d..8d968e8 100644 --- a/include/llvm/ADT/Triple.h +++ b/include/llvm/ADT/Triple.h @@ -55,6 +55,7 @@ public: msp430, // MSP430: msp430 ppc, // PPC: powerpc ppc64, // PPC64: powerpc64, ppu + ppc64le, // PPC64LE: powerpc64le r600, // R600: AMD GPUs HD2XXX - HD6XXX sparc, // Sparc: sparc sparcv9, // Sparcv9: Sparcv9 @@ -64,7 +65,6 @@ public: x86, // X86: i[3-9]86 x86_64, // X86-64: amd64, x86_64 xcore, // XCore: xcore - mblaze, // MBlaze: mblaze nvptx, // NVPTX: 32-bit nvptx64, // NVPTX: 64-bit le32, // le32: generic little-endian 32-bit CPU (PNaCl / Emscripten) @@ -81,7 +81,8 @@ public: BGP, BGQ, Freescale, - IBM + IBM, + NVIDIA }; enum OSType { UnknownOS, @@ -107,7 +108,9 @@ public: NaCl, // Native Client CNK, // BG/P Compute-Node Kernel Bitrig, - AIX + AIX, + CUDA, // NVIDIA CUDA + NVCL // NVIDIA OpenCL }; enum EnvironmentType { UnknownEnvironment, diff --git a/include/llvm/Analysis/BlockFrequencyImpl.h b/include/llvm/Analysis/BlockFrequencyImpl.h index b3e2d18..5e14d6f 100644 --- a/include/llvm/Analysis/BlockFrequencyImpl.h +++ b/include/llvm/Analysis/BlockFrequencyImpl.h @@ -1,4 +1,4 @@ -//===---- BlockFrequencyImpl.h - Machine Block Frequency Implementation ---===// +//===-- BlockFrequencyImpl.h - Block Frequency Implementation --*- C++ -*--===// // // The LLVM Compiler Infrastructure // @@ -33,7 +33,7 @@ class BlockFrequencyInfo; class MachineBlockFrequencyInfo; /// BlockFrequencyImpl implements block frequency algorithm for IR and -/// Machine Instructions. Algorithm starts with value 1024 (START_FREQ) +/// Machine Instructions. Algorithm starts with value ENTRY_FREQ /// for the entry block and then propagates frequencies using branch weights /// from (Machine)BranchProbabilityInfo. LoopInfo is not required because /// algorithm can find "backedges" by itself. @@ -85,31 +85,16 @@ class BlockFrequencyImpl { << " --> " << Freqs[BB] << "\n"); } - /// divBlockFreq - Divide BB block frequency by PROB. If Prob = 0 do nothing. - /// - void divBlockFreq(BlockT *BB, BranchProbability Prob) { - uint64_t N = Prob.getNumerator(); - assert(N && "Illegal division by zero!"); - uint64_t D = Prob.getDenominator(); - uint64_t Freq = (Freqs[BB].getFrequency() * D) / N; - - // Should we assert it? - if (Freq > UINT32_MAX) - Freq = UINT32_MAX; - - Freqs[BB] = BlockFrequency(Freq); - DEBUG(dbgs() << "Frequency(" << getBlockName(BB) << ") /= (" << Prob - << ") --> " << Freqs[BB] << "\n"); - } - // All blocks in postorder. std::vector<BlockT *> POT; // Map Block -> Position in reverse-postorder list. DenseMap<BlockT *, unsigned> RPO; - // Cycle Probability for each bloch. - DenseMap<BlockT *, uint32_t> CycleProb; + // For each loop header, record the per-iteration probability of exiting the + // loop. This is the reciprocal of the expected number of loop iterations. + typedef DenseMap<BlockT*, BranchProbability> LoopExitProbMap; + LoopExitProbMap LoopExitProb; // (reverse-)postorder traversal iterators. typedef typename std::vector<BlockT *>::iterator pot_iterator; @@ -123,7 +108,7 @@ class BlockFrequencyImpl { rpot_iterator rpot_at(BlockT *BB) { rpot_iterator I = rpot_begin(); - unsigned idx = RPO[BB]; + unsigned idx = RPO.lookup(BB); assert(idx); std::advance(I, idx - 1); @@ -131,22 +116,14 @@ class BlockFrequencyImpl { return I; } - - /// isReachable - Returns if BB block is reachable from the entry. - /// - bool isReachable(BlockT *BB) { - return RPO.count(BB); - } - - /// isBackedge - Return if edge Src -> Dst is a backedge. + /// isBackedge - Return if edge Src -> Dst is a reachable backedge. /// bool isBackedge(BlockT *Src, BlockT *Dst) { - assert(isReachable(Src)); - assert(isReachable(Dst)); - - unsigned a = RPO[Src]; - unsigned b = RPO[Dst]; - + unsigned a = RPO.lookup(Src); + if (!a) + return false; + unsigned b = RPO.lookup(Dst); + assert(b && "Destination block should be reachable"); return a >= b; } @@ -196,7 +173,7 @@ class BlockFrequencyImpl { PI != PE; ++PI) { BlockT *Pred = *PI; - if (isReachable(Pred) && isBackedge(Pred, BB)) { + if (isBackedge(Pred, BB)) { isLoopHead = true; } else if (BlocksInLoop.count(Pred)) { incBlockFreq(BB, getEdgeFreq(Pred, BB)); @@ -211,10 +188,13 @@ class BlockFrequencyImpl { if (!isLoopHead) return; - assert(EntryFreq >= CycleProb[BB]); - uint32_t CProb = CycleProb[BB]; - uint32_t Numerator = EntryFreq - CProb ? EntryFreq - CProb : 1; - divBlockFreq(BB, BranchProbability(Numerator, EntryFreq)); + // This block is a loop header, so boost its frequency by the expected + // number of loop iterations. The loop blocks will be revisited so they all + // get this boost. + typename LoopExitProbMap::const_iterator I = LoopExitProb.find(BB); + assert(I != LoopExitProb.end() && "Loop header missing from table"); + Freqs[BB] /= I->second; + DEBUG(dbgs() << "Loop header scaled to " << Freqs[BB] << ".\n"); } /// doLoop - Propagate block frequency down through the loop. @@ -234,24 +214,50 @@ class BlockFrequencyImpl { } // Compute loop's cyclic probability using backedges probabilities. + BlockFrequency BackFreq; for (typename GT::ChildIteratorType PI = GraphTraits< Inverse<BlockT *> >::child_begin(Head), PE = GraphTraits< Inverse<BlockT *> >::child_end(Head); PI != PE; ++PI) { BlockT *Pred = *PI; assert(Pred); - if (isReachable(Pred) && isBackedge(Pred, Head)) { - uint64_t N = getEdgeFreq(Pred, Head).getFrequency(); - uint64_t D = getBlockFreq(Head).getFrequency(); - assert(N <= EntryFreq && "Backedge frequency must be <= EntryFreq!"); - uint64_t Res = (N * EntryFreq) / D; - - assert(Res <= UINT32_MAX); - CycleProb[Head] += (uint32_t) Res; - DEBUG(dbgs() << " CycleProb[" << getBlockName(Head) << "] += " << Res - << " --> " << CycleProb[Head] << "\n"); - } + if (isBackedge(Pred, Head)) + BackFreq += getEdgeFreq(Pred, Head); + } + + // The cyclic probability is freq(BackEdges) / freq(Head), where freq(Head) + // only counts edges entering the loop, not the loop backedges. + // The probability of leaving the loop on each iteration is: + // + // ExitProb = 1 - CyclicProb + // + // The Expected number of loop iterations is: + // + // Iterations = 1 / ExitProb + // + uint64_t D = std::max(getBlockFreq(Head).getFrequency(), UINT64_C(1)); + uint64_t N = std::max(BackFreq.getFrequency(), UINT64_C(1)); + if (N < D) + N = D - N; + else + // We'd expect N < D, but rounding and saturation means that can't be + // guaranteed. + N = 1; + + // Now ExitProb = N / D, make sure it fits in an i32/i32 fraction. + assert(N <= D); + if (D > UINT32_MAX) { + unsigned Shift = 32 - countLeadingZeros(D); + D >>= Shift; + N >>= Shift; + if (N == 0) + N = 1; } + BranchProbability LEP = BranchProbability(N, D); + LoopExitProb.insert(std::make_pair(Head, LEP)); + DEBUG(dbgs() << "LoopExitProb[" << getBlockName(Head) << "] = " << LEP + << " from 1 - " << BackFreq << " / " << getBlockFreq(Head) + << ".\n"); } friend class BlockFrequencyInfo; @@ -266,7 +272,7 @@ class BlockFrequencyImpl { // Clear everything. RPO.clear(); POT.clear(); - CycleProb.clear(); + LoopExitProb.clear(); Freqs.clear(); BlockT *EntryBlock = fn->begin(); @@ -292,8 +298,7 @@ class BlockFrequencyImpl { PI != PE; ++PI) { BlockT *Pred = *PI; - if (isReachable(Pred) && isBackedge(Pred, BB) - && (!LastTail || RPO[Pred] > RPO[LastTail])) + if (isBackedge(Pred, BB) && (!LastTail || RPO[Pred] > RPO[LastTail])) LastTail = Pred; } diff --git a/include/llvm/Analysis/BlockFrequencyInfo.h b/include/llvm/Analysis/BlockFrequencyInfo.h index fcab906..64bd15c 100644 --- a/include/llvm/Analysis/BlockFrequencyInfo.h +++ b/include/llvm/Analysis/BlockFrequencyInfo.h @@ -1,4 +1,4 @@ -//========-------- BlockFrequencyInfo.h - Block Frequency Analysis -------========// +//===------- BlockFrequencyInfo.h - Block Frequency Analysis --*- C++ -*---===// // // The LLVM Compiler Infrastructure // @@ -43,10 +43,10 @@ public: void print(raw_ostream &O, const Module *M) const; /// getblockFreq - Return block frequency. Return 0 if we don't have the - /// information. Please note that initial frequency is equal to 1024. It means - /// that we should not rely on the value itself, but only on the comparison to - /// the other block frequencies. We do this to avoid using of floating points. - /// + /// information. Please note that initial frequency is equal to ENTRY_FREQ. It + /// means that we should not rely on the value itself, but only on the + /// comparison to the other block frequencies. We do this to avoid using of + /// floating points. BlockFrequency getBlockFreq(const BasicBlock *BB) const; }; diff --git a/include/llvm/Analysis/CFG.h b/include/llvm/Analysis/CFG.h new file mode 100644 index 0000000..08fdc26 --- /dev/null +++ b/include/llvm/Analysis/CFG.h @@ -0,0 +1,69 @@ +//===-- Analysis/CFG.h - BasicBlock Analyses --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of functions performs analyses on basic blocks, and instructions +// contained within basic blocks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CFG_H +#define LLVM_ANALYSIS_CFG_H + +#include "llvm/IR/BasicBlock.h" +#include "llvm/Support/CFG.h" + +namespace llvm { + +class BasicBlock; +class DominatorTree; +class Function; +class Instruction; +class LoopInfo; +class TerminatorInst; + +/// Analyze the specified function to find all of the loop backedges in the +/// function and return them. This is a relatively cheap (compared to +/// computing dominators and loop info) analysis. +/// +/// The output is added to Result, as pairs of <from,to> edge info. +void FindFunctionBackedges( + const Function &F, + SmallVectorImpl<std::pair<const BasicBlock *, const BasicBlock *> > & + Result); + +/// Search for the specified successor of basic block BB and return its position +/// in the terminator instruction's list of successors. It is an error to call +/// this with a block that is not a successor. +unsigned GetSuccessorNumber(BasicBlock *BB, BasicBlock *Succ); + +/// Return true if the specified edge is a critical edge. Critical edges are +/// edges from a block with multiple successors to a block with multiple +/// predecessors. +/// +bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum, + bool AllowIdenticalEdges = false); + +/// Determine whether there is a path from From to To within a single function. +/// Returns false only if we can prove that once 'From' has been executed then +/// 'To' can not be executed. Conservatively returns true. +/// +/// This function is linear with respect to the number of blocks in the CFG, +/// walking down successors from From to reach To, with a fixed threshold. +/// Using DT or LI allows us to answer more quickly. LI reduces the cost of +/// an entire loop of any number of blocsk to be the same as the cost of a +/// single block. DT reduces the cost by allowing the search to terminate when +/// we find a block that dominates the block containing 'To'. DT is most useful +/// on branchy code but not loops, and LI is most useful on code with loops but +/// does not help on branchy code outside loops. +bool isPotentiallyReachable(const Instruction *From, const Instruction *To, + DominatorTree *DT = 0, LoopInfo *LI = 0); + +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/DependenceAnalysis.h b/include/llvm/Analysis/DependenceAnalysis.h index a78ac59..8fce2f6 100644 --- a/include/llvm/Analysis/DependenceAnalysis.h +++ b/include/llvm/Analysis/DependenceAnalysis.h @@ -61,11 +61,20 @@ namespace llvm { /// cases (for output, flow, and anti dependences), the dependence implies /// an ordering, where the source must precede the destination; in contrast, /// input dependences are unordered. + /// + /// When a dependence graph is built, each Dependence will be a member of + /// the set of predecessor edges for its destination instruction and a set + /// if successor edges for its source instruction. These sets are represented + /// as singly-linked lists, with the "next" fields stored in the dependence + /// itelf. class Dependence { public: Dependence(Instruction *Source, Instruction *Destination) : - Src(Source), Dst(Destination) {} + Src(Source), + Dst(Destination), + NextPredecessor(NULL), + NextSuccessor(NULL) {} virtual ~Dependence() {} /// Dependence::DVEntry - Each level in the distance/direction vector @@ -164,11 +173,36 @@ namespace llvm { /// variable associated with the loop at this level. virtual bool isScalar(unsigned Level) const; + /// getNextPredecessor - Returns the value of the NextPredecessor + /// field. + const Dependence *getNextPredecessor() const { + return NextPredecessor; + } + + /// getNextSuccessor - Returns the value of the NextSuccessor + /// field. + const Dependence *getNextSuccessor() const { + return NextSuccessor; + } + + /// setNextPredecessor - Sets the value of the NextPredecessor + /// field. + void setNextPredecessor(const Dependence *pred) { + NextPredecessor = pred; + } + + /// setNextSuccessor - Sets the value of the NextSuccessor + /// field. + void setNextSuccessor(const Dependence *succ) { + NextSuccessor = succ; + } + /// dump - For debugging purposes, dumps a dependence to OS. /// void dump(raw_ostream &OS) const; private: Instruction *Src, *Dst; + const Dependence *NextPredecessor, *NextSuccessor; friend class DependenceAnalysis; }; @@ -815,7 +849,7 @@ namespace llvm { bool propagate(const SCEV *&Src, const SCEV *&Dst, SmallBitVector &Loops, - SmallVector<Constraint, 4> &Constraints, + SmallVectorImpl<Constraint> &Constraints, bool &Consistent); /// propagateDistance - Attempt to propagate a distance diff --git a/include/llvm/Analysis/InstructionSimplify.h b/include/llvm/Analysis/InstructionSimplify.h index d760a4c..775d0df 100644 --- a/include/llvm/Analysis/InstructionSimplify.h +++ b/include/llvm/Analysis/InstructionSimplify.h @@ -1,4 +1,4 @@ -//===-- InstructionSimplify.h - Fold instructions into simpler forms ------===// +//===-- InstructionSimplify.h - Fold instrs into simpler forms --*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/llvm/Analysis/MemoryBuiltins.h b/include/llvm/Analysis/MemoryBuiltins.h index 4883383..0d1ae8c 100644 --- a/include/llvm/Analysis/MemoryBuiltins.h +++ b/include/llvm/Analysis/MemoryBuiltins.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // // This family of functions identifies calls to builtin functions that allocate -// or free memory. +// or free memory. // //===----------------------------------------------------------------------===// @@ -78,7 +78,7 @@ static inline CallInst *extractMallocCall(Value *I, return const_cast<CallInst*>(extractMallocCall((const Value*)I, TLI)); } -/// isArrayMalloc - Returns the corresponding CallInst if the instruction +/// isArrayMalloc - Returns the corresponding CallInst if the instruction /// is a call to malloc whose array size can be determined and the array size /// is not constant 1. Otherwise, return NULL. const CallInst *isArrayMalloc(const Value *I, const DataLayout *TD, @@ -98,7 +98,7 @@ PointerType *getMallocType(const CallInst *CI, const TargetLibraryInfo *TLI); /// >1: Unique PointerType cannot be determined, return NULL. Type *getMallocAllocatedType(const CallInst *CI, const TargetLibraryInfo *TLI); -/// getMallocArraySize - Returns the array size of a malloc call. If the +/// getMallocArraySize - Returns the array size of a malloc call. If the /// argument passed to malloc is a multiple of the size of the malloced type, /// then return that multiple. For non-array mallocs, the multiple is /// constant 1. Otherwise, return NULL for mallocs whose array size cannot be @@ -127,12 +127,12 @@ static inline CallInst *extractCallocCall(Value *I, /// isFreeCall - Returns non-null if the value is a call to the builtin free() const CallInst *isFreeCall(const Value *I, const TargetLibraryInfo *TLI); - + static inline CallInst *isFreeCall(Value *I, const TargetLibraryInfo *TLI) { return const_cast<CallInst*>(isFreeCall((const Value*)I, TLI)); } - + //===----------------------------------------------------------------------===// // Utility functions to compute size of objects. // @@ -150,7 +150,7 @@ bool getObjectSize(const Value *Ptr, uint64_t &Size, const DataLayout *TD, typedef std::pair<APInt, APInt> SizeOffsetType; -/// \brief Evaluate the size and offset of an object ponted by a Value* +/// \brief Evaluate the size and offset of an object pointed to by a Value* /// statically. Fails if size or offset are not known at compile time. class ObjectSizeOffsetVisitor : public InstVisitor<ObjectSizeOffsetVisitor, SizeOffsetType> { @@ -206,7 +206,7 @@ public: typedef std::pair<Value*, Value*> SizeOffsetEvalType; -/// \brief Evaluate the size and offset of an object ponted by a Value*. +/// \brief Evaluate the size and offset of an object pointed to by a Value*. /// May create code to compute the result at run-time. class ObjectSizeOffsetEvaluator : public InstVisitor<ObjectSizeOffsetEvaluator, SizeOffsetEvalType> { diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h index 349447f..3817e41 100644 --- a/include/llvm/Analysis/ScalarEvolution.h +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -545,6 +545,10 @@ namespace llvm { /// forgetMemoizedResults - Drop memoized information computed for S. void forgetMemoizedResults(const SCEV *S); + /// Return false iff given SCEV contains a SCEVUnknown with NULL value- + /// pointer. + bool checkValidity(const SCEV *S) const; + public: static char ID; // Pass identification, replacement for typeid ScalarEvolution(); diff --git a/include/llvm/Analysis/TargetTransformInfo.h b/include/llvm/Analysis/TargetTransformInfo.h index eb29e34..21a3a12 100644 --- a/include/llvm/Analysis/TargetTransformInfo.h +++ b/include/llvm/Analysis/TargetTransformInfo.h @@ -171,6 +171,12 @@ public: /// comments for a detailed explanation of the cost values. virtual unsigned getUserCost(const User *U) const; + /// \brief hasBranchDivergence - 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. + virtual bool hasBranchDivergence() const; + /// \brief Test whether calls to a function lower to actual program function /// calls. /// @@ -339,7 +345,11 @@ public: /// merged into the instruction indexing mode. Some targets might want to /// distinguish between address computation for memory operations on vector /// types and scalar types. Such targets should override this function. - virtual unsigned getAddressComputationCost(Type *Ty) const; + /// The 'IsComplex' parameter is a hint that the address computation is likely + /// to involve multiple instructions and as such unlikely to be merged into + /// the address indexing mode. + virtual unsigned getAddressComputationCost(Type *Ty, + bool IsComplex = false) const; /// @} diff --git a/include/llvm/AutoUpgrade.h b/include/llvm/AutoUpgrade.h index e13c4c1..ca3446e 100644 --- a/include/llvm/AutoUpgrade.h +++ b/include/llvm/AutoUpgrade.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// These functions are implemented by lib/VMCore/AutoUpgrade.cpp. +// These functions are implemented by lib/IR/AutoUpgrade.cpp. // //===----------------------------------------------------------------------===// @@ -20,19 +20,19 @@ namespace llvm { class Function; class CallInst; - /// This is a more granular function that simply checks an intrinsic function + /// This is a more granular function that simply checks an intrinsic function /// for upgrading, and returns true if it requires upgrading. It may return /// null in NewFn if the all calls to the original intrinsic function /// should be transformed to non-function-call instructions. bool UpgradeIntrinsicFunction(Function *F, Function *&NewFn); - /// This is the complement to the above, replacing a specific call to an + /// This is the complement to the above, replacing a specific call to an /// intrinsic function with a call to the specified new function. void UpgradeIntrinsicCall(CallInst *CI, Function *NewFn); - - /// This is an auto-upgrade hook for any old intrinsic function syntaxes - /// which need to have both the function updated as well as all calls updated - /// to the new function. This should only be run in a post-processing fashion + + /// This is an auto-upgrade hook for any old intrinsic function syntaxes + /// which need to have both the function updated as well as all calls updated + /// to the new function. This should only be run in a post-processing fashion /// so that it can update all calls to the old function. void UpgradeCallsToIntrinsic(Function* F); diff --git a/include/llvm/Bitcode/Archive.h b/include/llvm/Bitcode/Archive.h deleted file mode 100644 index d27f690..0000000 --- a/include/llvm/Bitcode/Archive.h +++ /dev/null @@ -1,539 +0,0 @@ -//===-- llvm/Bitcode/Archive.h - LLVM Bitcode Archive -----------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This header file declares the Archive and ArchiveMember classes that provide -// manipulation of LLVM Archive files. The implementation is provided by the -// lib/Bitcode/Archive library. This library is used to read and write -// archive (*.a) files that contain LLVM bitcode files (or others). -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_BITCODE_ARCHIVE_H -#define LLVM_BITCODE_ARCHIVE_H - -#include "llvm/ADT/ilist.h" -#include "llvm/ADT/ilist_node.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/PathV1.h" -#include <map> -#include <set> - -namespace llvm { - class MemoryBuffer; - -// Forward declare classes -class Module; // From VMCore -class Archive; // Declared below -class ArchiveMemberHeader; // Internal implementation class -class LLVMContext; // Global data - -/// This class is the main class manipulated by users of the Archive class. It -/// holds information about one member of the Archive. It is also the element -/// stored by the Archive's ilist, the Archive's main abstraction. Because of -/// the special requirements of archive files, users are not permitted to -/// construct ArchiveMember instances. You should obtain them from the methods -/// of the Archive class instead. -/// @brief This class represents a single archive member. -class ArchiveMember : public ilist_node<ArchiveMember> { - /// @name Types - /// @{ - public: - /// These flags are used internally by the archive member to specify various - /// characteristics of the member. The various "is" methods below provide - /// access to the flags. The flags are not user settable. - enum Flags { - SVR4SymbolTableFlag = 1, ///< Member is a SVR4 symbol table - BSD4SymbolTableFlag = 2, ///< Member is a BSD4 symbol table - LLVMSymbolTableFlag = 4, ///< Member is an LLVM symbol table - BitcodeFlag = 8, ///< Member is bitcode - HasPathFlag = 16, ///< Member has a full or partial path - HasLongFilenameFlag = 32, ///< Member uses the long filename syntax - StringTableFlag = 64 ///< Member is an ar(1) format string table - }; - - /// @} - /// @name Accessors - /// @{ - public: - /// @returns the parent Archive instance - /// @brief Get the archive associated with this member - Archive* getArchive() const { return parent; } - - /// @returns the path to the Archive's file - /// @brief Get the path to the archive member - const sys::Path& getPath() const { return path; } - - /// The "user" is the owner of the file per Unix security. This may not - /// have any applicability on non-Unix systems but is a required component - /// of the "ar" file format. - /// @brief Get the user associated with this archive member. - unsigned getUser() const { return info.getUser(); } - - /// The "group" is the owning group of the file per Unix security. This - /// may not have any applicability on non-Unix systems but is a required - /// component of the "ar" file format. - /// @brief Get the group associated with this archive member. - unsigned getGroup() const { return info.getGroup(); } - - /// The "mode" specifies the access permissions for the file per Unix - /// security. This may not have any applicability on non-Unix systems but is - /// a required component of the "ar" file format. - /// @brief Get the permission mode associated with this archive member. - unsigned getMode() const { return info.getMode(); } - - /// This method returns the time at which the archive member was last - /// modified when it was not in the archive. - /// @brief Get the time of last modification of the archive member. - sys::TimeValue getModTime() const { return info.getTimestamp(); } - - /// @returns the size of the archive member in bytes. - /// @brief Get the size of the archive member. - uint64_t getSize() const { return info.getSize(); } - - /// This method returns the total size of the archive member as it - /// appears on disk. This includes the file content, the header, the - /// long file name if any, and the padding. - /// @brief Get total on-disk member size. - unsigned getMemberSize() const; - - /// This method will return a pointer to the in-memory content of the - /// archive member, if it is available. If the data has not been loaded - /// into memory, the return value will be null. - /// @returns a pointer to the member's data. - /// @brief Get the data content of the archive member - const char* getData() const { return data; } - - /// @returns true iff the member is a SVR4 (non-LLVM) symbol table - /// @brief Determine if this member is a SVR4 symbol table. - bool isSVR4SymbolTable() const { return flags&SVR4SymbolTableFlag; } - - /// @returns true iff the member is a BSD4.4 (non-LLVM) symbol table - /// @brief Determine if this member is a BSD4.4 symbol table. - bool isBSD4SymbolTable() const { return flags&BSD4SymbolTableFlag; } - - /// @returns true iff the archive member is the LLVM symbol table - /// @brief Determine if this member is the LLVM symbol table. - bool isLLVMSymbolTable() const { return flags&LLVMSymbolTableFlag; } - - /// @returns true iff the archive member is the ar(1) string table - /// @brief Determine if this member is the ar(1) string table. - bool isStringTable() const { return flags&StringTableFlag; } - - /// @returns true iff the archive member is a bitcode file. - /// @brief Determine if this member is a bitcode file. - bool isBitcode() const { return flags&BitcodeFlag; } - - /// @returns true iff the file name contains a path (directory) component. - /// @brief Determine if the member has a path - bool hasPath() const { return flags&HasPathFlag; } - - /// Long filenames are an artifact of the ar(1) file format which allows - /// up to sixteen characters in its header and doesn't allow a path - /// separator character (/). To avoid this, a "long format" member name is - /// allowed that doesn't have this restriction. This method determines if - /// that "long format" is used for this member. - /// @returns true iff the file name uses the long form - /// @brief Determine if the member has a long file name - bool hasLongFilename() const { return flags&HasLongFilenameFlag; } - - /// This method returns the status info (like Unix stat(2)) for the archive - /// member. The status info provides the file's size, permissions, and - /// modification time. The contents of the Path::StatusInfo structure, other - /// than the size and modification time, may not have utility on non-Unix - /// systems. - /// @returns the status info for the archive member - /// @brief Obtain the status info for the archive member - const sys::FileStatus &getFileStatus() const { return info; } - - /// This method causes the archive member to be replaced with the contents - /// of the file specified by \p File. The contents of \p this will be - /// updated to reflect the new data from \p File. The \p File must exist and - /// be readable on entry to this method. - /// @returns true if an error occurred, false otherwise - /// @brief Replace contents of archive member with a new file. - bool replaceWith(const sys::Path &aFile, std::string* ErrMsg); - - /// @} - /// @name Data - /// @{ - private: - Archive* parent; ///< Pointer to parent archive - sys::PathWithStatus path; ///< Path of file containing the member - sys::FileStatus info; ///< Status info (size,mode,date) - unsigned flags; ///< Flags about the archive member - const char* data; ///< Data for the member - - /// @} - /// @name Constructors - /// @{ - public: - /// The default constructor is only used by the Archive's iplist when it - /// constructs the list's sentry node. - ArchiveMember(); - - private: - /// Used internally by the Archive class to construct an ArchiveMember. - /// The contents of the ArchiveMember are filled out by the Archive class. - explicit ArchiveMember(Archive *PAR); - - // So Archive can construct an ArchiveMember - friend class llvm::Archive; - /// @} -}; - -/// This class defines the interface to LLVM Archive files. The Archive class -/// presents the archive file as an ilist of ArchiveMember objects. The members -/// can be rearranged in any fashion either by directly editing the ilist or by -/// using editing methods on the Archive class (recommended). The Archive -/// class also provides several ways of accessing the archive file for various -/// purposes such as editing and linking. Full symbol table support is provided -/// for loading only those files that resolve symbols. Note that read -/// performance of this library is _crucial_ for performance of JIT type -/// applications and the linkers. Consequently, the implementation of the class -/// is optimized for reading. -class Archive { - - /// @name Types - /// @{ - public: - /// This is the ilist type over which users may iterate to examine - /// the contents of the archive - /// @brief The ilist type of ArchiveMembers that Archive contains. - typedef iplist<ArchiveMember> MembersList; - - /// @brief Forward mutable iterator over ArchiveMember - typedef MembersList::iterator iterator; - - /// @brief Forward immutable iterator over ArchiveMember - typedef MembersList::const_iterator const_iterator; - - /// @brief Reverse mutable iterator over ArchiveMember - typedef std::reverse_iterator<iterator> reverse_iterator; - - /// @brief Reverse immutable iterator over ArchiveMember - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; - - /// @brief The in-memory version of the symbol table - typedef std::map<std::string,unsigned> SymTabType; - - /// @} - /// @name ilist accessor methods - /// @{ - public: - inline iterator begin() { return members.begin(); } - inline const_iterator begin() const { return members.begin(); } - inline iterator end () { return members.end(); } - inline const_iterator end () const { return members.end(); } - - inline reverse_iterator rbegin() { return members.rbegin(); } - inline const_reverse_iterator rbegin() const { return members.rbegin(); } - inline reverse_iterator rend () { return members.rend(); } - inline const_reverse_iterator rend () const { return members.rend(); } - - inline size_t size() const { return members.size(); } - inline bool empty() const { return members.empty(); } - inline const ArchiveMember& front() const { return members.front(); } - inline ArchiveMember& front() { return members.front(); } - inline const ArchiveMember& back() const { return members.back(); } - inline ArchiveMember& back() { return members.back(); } - - /// @} - /// @name ilist mutator methods - /// @{ - public: - /// This method splices a \p src member from an archive (possibly \p this), - /// to a position just before the member given by \p dest in \p this. When - /// the archive is written, \p src will be written in its new location. - /// @brief Move a member to a new location - inline void splice(iterator dest, Archive& arch, iterator src) - { return members.splice(dest,arch.members,src); } - - /// This method erases a \p target member from the archive. When the - /// archive is written, it will no longer contain \p target. The associated - /// ArchiveMember is deleted. - /// @brief Erase a member. - inline iterator erase(iterator target) { return members.erase(target); } - - /// @} - /// @name Constructors - /// @{ - public: - /// Create an empty archive file and associate it with the \p Filename. This - /// method does not actually create the archive disk file. It creates an - /// empty Archive object. If the writeToDisk method is called, the archive - /// file \p Filename will be created at that point, with whatever content - /// the returned Archive object has at that time. - /// @returns An Archive* that represents the new archive file. - /// @brief Create an empty Archive. - static Archive* CreateEmpty( - const sys::Path& Filename,///< Name of the archive to (eventually) create. - LLVMContext& C ///< Context to use for global information - ); - - /// Open an existing archive and load its contents in preparation for - /// editing. After this call, the member ilist is completely populated based - /// on the contents of the archive file. You should use this form of open if - /// you intend to modify the archive or traverse its contents (e.g. for - /// printing). - /// @brief Open and load an archive file - static Archive* OpenAndLoad( - const sys::Path& filePath, ///< The file path to open and load - LLVMContext& C, ///< The context to use for global information - std::string* ErrorMessage ///< An optional error string - ); - - /// This method opens an existing archive file from \p Filename and reads in - /// its symbol table without reading in any of the archive's members. This - /// reduces both I/O and cpu time in opening the archive if it is to be used - /// solely for symbol lookup (e.g. during linking). The \p Filename must - /// exist and be an archive file or an error will be returned. This form - /// of opening the archive is intended for read-only operations that need to - /// locate members via the symbol table for link editing. Since the archve - /// members are not read by this method, the archive will appear empty upon - /// return. If editing operations are performed on the archive, they will - /// completely replace the contents of the archive! It is recommended that - /// if this form of opening the archive is used that only the symbol table - /// lookup methods (getSymbolTable, findModuleDefiningSymbol, and - /// findModulesDefiningSymbols) be used. - /// @returns an Archive* that represents the archive file, or null on error. - /// @brief Open an existing archive and load its symbols. - static Archive* OpenAndLoadSymbols( - const sys::Path& Filename, ///< Name of the archive file to open - LLVMContext& C, ///< The context to use for global info - std::string* ErrorMessage=0 ///< An optional error string - ); - - /// This destructor cleans up the Archive object, releases all memory, and - /// closes files. It does nothing with the archive file on disk. If you - /// haven't used the writeToDisk method by the time the destructor is - /// called, all changes to the archive will be lost. - /// @brief Destruct in-memory archive - ~Archive(); - - /// @} - /// @name Accessors - /// @{ - public: - /// @returns the path to the archive file. - /// @brief Get the archive path. - const sys::Path& getPath() { return archPath; } - - /// This method is provided so that editing methods can be invoked directly - /// on the Archive's iplist of ArchiveMember. However, it is recommended - /// that the usual STL style iterator interface be used instead. - /// @returns the iplist of ArchiveMember - /// @brief Get the iplist of the members - MembersList& getMembers() { return members; } - - /// This method allows direct query of the Archive's symbol table. The - /// symbol table is a std::map of std::string (the symbol) to unsigned (the - /// file offset). Note that for efficiency reasons, the offset stored in - /// the symbol table is not the actual offset. It is the offset from the - /// beginning of the first "real" file member (after the symbol table). Use - /// the getFirstFileOffset() to obtain that offset and add this value to the - /// offset in the symbol table to obtain the real file offset. Note that - /// there is purposefully no interface provided by Archive to look up - /// members by their offset. Use the findModulesDefiningSymbols and - /// findModuleDefiningSymbol methods instead. - /// @returns the Archive's symbol table. - /// @brief Get the archive's symbol table - const SymTabType& getSymbolTable() { return symTab; } - - /// This method returns the offset in the archive file to the first "real" - /// file member. Archive files, on disk, have a signature and might have a - /// symbol table that precedes the first actual file member. This method - /// allows you to determine what the size of those fields are. - /// @returns the offset to the first "real" file member in the archive. - /// @brief Get the offset to the first "real" file member in the archive. - unsigned getFirstFileOffset() { return firstFileOffset; } - - /// This method will scan the archive for bitcode modules, interpret them - /// and return a vector of the instantiated modules in \p Modules. If an - /// error occurs, this method will return true. If \p ErrMessage is not null - /// and an error occurs, \p *ErrMessage will be set to a string explaining - /// the error that occurred. - /// @returns true if an error occurred - /// @brief Instantiate all the bitcode modules located in the archive - bool getAllModules(std::vector<Module*>& Modules, std::string* ErrMessage); - - /// This accessor looks up the \p symbol in the archive's symbol table and - /// returns the associated module that defines that symbol. This method can - /// be called as many times as necessary. This is handy for linking the - /// archive into another module based on unresolved symbols. Note that the - /// Module returned by this accessor should not be deleted by the caller. It - /// is managed internally by the Archive class. It is possible that multiple - /// calls to this accessor will return the same Module instance because the - /// associated module defines multiple symbols. - /// @returns The Module* found or null if the archive does not contain a - /// module that defines the \p symbol. - /// @brief Look up a module by symbol name. - Module* findModuleDefiningSymbol( - const std::string& symbol, ///< Symbol to be sought - std::string* ErrMessage ///< Error message storage, if non-zero - ); - - /// This method is similar to findModuleDefiningSymbol but allows lookup of - /// more than one symbol at a time. If \p symbols contains a list of - /// undefined symbols in some module, then calling this method is like - /// making one complete pass through the archive to resolve symbols but is - /// more efficient than looking at the individual members. Note that on - /// exit, the symbols resolved by this method will be removed from \p - /// symbols to ensure they are not re-searched on a subsequent call. If - /// you need to retain the list of symbols, make a copy. - /// @brief Look up multiple symbols in the archive. - bool findModulesDefiningSymbols( - std::set<std::string>& symbols, ///< Symbols to be sought - SmallVectorImpl<Module*>& modules, ///< The modules matching \p symbols - std::string* ErrMessage ///< Error msg storage, if non-zero - ); - - /// This method determines whether the archive is a properly formed llvm - /// bitcode archive. It first makes sure the symbol table has been loaded - /// and has a non-zero size. If it does, then it is an archive. If not, - /// then it tries to load all the bitcode modules of the archive. Finally, - /// it returns whether it was successful. - /// @returns true if the archive is a proper llvm bitcode archive - /// @brief Determine whether the archive is a proper llvm bitcode archive. - bool isBitcodeArchive(); - - /// @} - /// @name Mutators - /// @{ - public: - /// This method is the only way to get the archive written to disk. It - /// creates or overwrites the file specified when \p this was created - /// or opened. The arguments provide options for writing the archive. If - /// \p CreateSymbolTable is true, the archive is scanned for bitcode files - /// and a symbol table of the externally visible function and global - /// variable names is created. If \p TruncateNames is true, the names of the - /// archive members will have their path component stripped and the file - /// name will be truncated at 15 characters. If \p Compress is specified, - /// all archive members will be compressed before being written. If - /// \p PrintSymTab is true, the symbol table will be printed to std::cout. - /// @returns true if an error occurred, \p error set to error message; - /// returns false if the writing succeeded. - /// @brief Write (possibly modified) archive contents to disk - bool writeToDisk( - bool CreateSymbolTable=false, ///< Create Symbol table - bool TruncateNames=false, ///< Truncate the filename to 15 chars - std::string* ErrMessage=0 ///< If non-null, where error msg is set - ); - - /// This method adds a new file to the archive. The \p filename is examined - /// to determine just enough information to create an ArchiveMember object - /// which is then inserted into the Archive object's ilist at the location - /// given by \p where. - /// @returns true if an error occurred, false otherwise - /// @brief Add a file to the archive. - bool addFileBefore( - const sys::Path& filename, ///< The file to be added - iterator where, ///< Insertion point - std::string* ErrMsg ///< Optional error message location - ); - - /// @} - /// @name Implementation - /// @{ - protected: - /// @brief Construct an Archive for \p filename and optionally map it - /// into memory. - explicit Archive(const sys::Path& filename, LLVMContext& C); - - /// @param data The symbol table data to be parsed - /// @param len The length of the symbol table data - /// @param error Set to address of a std::string to get error messages - /// @returns false on error - /// @brief Parse the symbol table at \p data. - bool parseSymbolTable(const void* data,unsigned len,std::string* error); - - /// @returns A fully populated ArchiveMember or 0 if an error occurred. - /// @brief Parse the header of a member starting at \p At - ArchiveMember* parseMemberHeader( - const char*&At, ///< The pointer to the location we're parsing - const char*End, ///< The pointer to the end of the archive - std::string* error ///< Optional error message catcher - ); - - /// @param ErrMessage Set to address of a std::string to get error messages - /// @returns false on error - /// @brief Check that the archive signature is correct - bool checkSignature(std::string* ErrMessage); - - /// @param ErrMessage Set to address of a std::string to get error messages - /// @returns false on error - /// @brief Load the entire archive. - bool loadArchive(std::string* ErrMessage); - - /// @param ErrMessage Set to address of a std::string to get error messages - /// @returns false on error - /// @brief Load just the symbol table. - bool loadSymbolTable(std::string* ErrMessage); - - /// @brief Write the symbol table to an ofstream. - void writeSymbolTable(std::ofstream& ARFile); - - /// Writes one ArchiveMember to an ofstream. If an error occurs, returns - /// false, otherwise true. If an error occurs and error is non-null then - /// it will be set to an error message. - /// @returns false if writing member succeeded, - /// returns true if writing member failed, \p error set to error message. - bool writeMember( - const ArchiveMember& member, ///< The member to be written - std::ofstream& ARFile, ///< The file to write member onto - bool CreateSymbolTable, ///< Should symbol table be created? - bool TruncateNames, ///< Should names be truncated to 11 chars? - std::string* ErrMessage ///< If non-null, place were error msg is set - ); - - /// @brief Fill in an ArchiveMemberHeader from ArchiveMember. - bool fillHeader(const ArchiveMember&mbr, - ArchiveMemberHeader& hdr,int sz, bool TruncateNames) const; - - /// @brief Maps archive into memory - bool mapToMemory(std::string* ErrMsg); - - /// @brief Frees all the members and unmaps the archive file. - void cleanUpMemory(); - - /// This type is used to keep track of bitcode modules loaded from the - /// symbol table. It maps the file offset to a pair that consists of the - /// associated ArchiveMember and the Module. - /// @brief Module mapping type - typedef std::map<unsigned,std::pair<Module*,ArchiveMember*> > - ModuleMap; - - - /// @} - /// @name Data - /// @{ - protected: - sys::Path archPath; ///< Path to the archive file we read/write - MembersList members; ///< The ilist of ArchiveMember - MemoryBuffer *mapfile; ///< Raw Archive contents mapped into memory - const char* base; ///< Base of the memory mapped file data - SymTabType symTab; ///< The symbol table - std::string strtab; ///< The string table for long file names - unsigned symTabSize; ///< Size in bytes of symbol table - unsigned firstFileOffset; ///< Offset to first normal file. - ModuleMap modules; ///< The modules loaded via symbol lookup. - ArchiveMember* foreignST; ///< This holds the foreign symbol table. - LLVMContext& Context; ///< This holds global data. - /// @} - /// @name Hidden - /// @{ - private: - Archive() LLVM_DELETED_FUNCTION; - Archive(const Archive&) LLVM_DELETED_FUNCTION; - Archive& operator=(const Archive&) LLVM_DELETED_FUNCTION; - /// @} -}; - -} // End llvm namespace - -#endif diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h index f9690d5..463e3b9 100644 --- a/include/llvm/Bitcode/LLVMBitCodes.h +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -330,6 +330,47 @@ namespace bitc { enum UseListCodes { USELIST_CODE_ENTRY = 1 // USELIST_CODE_ENTRY: TBD. }; + + enum AttributeKindCodes { + // = 0 is unused + ATTR_KIND_ALIGNMENT = 1, + ATTR_KIND_ALWAYS_INLINE = 2, + ATTR_KIND_BY_VAL = 3, + ATTR_KIND_INLINE_HINT = 4, + ATTR_KIND_IN_REG = 5, + ATTR_KIND_MIN_SIZE = 6, + ATTR_KIND_NAKED = 7, + ATTR_KIND_NEST = 8, + ATTR_KIND_NO_ALIAS = 9, + ATTR_KIND_NO_BUILTIN = 10, + ATTR_KIND_NO_CAPTURE = 11, + ATTR_KIND_NO_DUPLICATE = 12, + ATTR_KIND_NO_IMPLICIT_FLOAT = 13, + ATTR_KIND_NO_INLINE = 14, + ATTR_KIND_NON_LAZY_BIND = 15, + ATTR_KIND_NO_RED_ZONE = 16, + ATTR_KIND_NO_RETURN = 17, + ATTR_KIND_NO_UNWIND = 18, + ATTR_KIND_OPTIMIZE_FOR_SIZE = 19, + ATTR_KIND_READ_NONE = 20, + ATTR_KIND_READ_ONLY = 21, + ATTR_KIND_RETURNED = 22, + ATTR_KIND_RETURNS_TWICE = 23, + ATTR_KIND_S_EXT = 24, + ATTR_KIND_STACK_ALIGNMENT = 25, + ATTR_KIND_STACK_PROTECT = 26, + ATTR_KIND_STACK_PROTECT_REQ = 27, + ATTR_KIND_STACK_PROTECT_STRONG = 28, + ATTR_KIND_STRUCT_RET = 29, + ATTR_KIND_SANITIZE_ADDRESS = 30, + ATTR_KIND_SANITIZE_THREAD = 31, + ATTR_KIND_SANITIZE_MEMORY = 32, + ATTR_KIND_UW_TABLE = 33, + ATTR_KIND_Z_EXT = 34, + ATTR_KIND_BUILTIN = 35, + ATTR_KIND_COLD = 36 + }; + } // End bitc namespace } // End llvm namespace diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index 5973255..677331b 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -121,6 +121,8 @@ namespace llvm { public: virtual ~AsmPrinter(); + const DwarfDebug *getDwarfDebug() const { return DD; } + /// isVerbose - Return true if assembly output should contain comments. /// bool isVerbose() const { return VerboseAsm; } @@ -233,8 +235,8 @@ namespace llvm { /// it if appropriate. void EmitBasicBlockStart(const MachineBasicBlock *MBB) const; - /// EmitGlobalConstant - Print a general LLVM constant to the .s file. - void EmitGlobalConstant(const Constant *CV, unsigned AddrSpace = 0); + /// \brief Print a general LLVM constant to the .s file. + void EmitGlobalConstant(const Constant *CV); //===------------------------------------------------------------------===// @@ -371,10 +373,10 @@ namespace llvm { //===------------------------------------------------------------------===// /// EmitSLEB128 - emit the specified signed leb128 value. - void EmitSLEB128(int Value, const char *Desc = 0) const; + void EmitSLEB128(int64_t Value, const char *Desc = 0) const; /// EmitULEB128 - emit the specified unsigned leb128 value. - void EmitULEB128(unsigned Value, const char *Desc = 0, + void EmitULEB128(uint64_t Value, const char *Desc = 0, unsigned PadTo = 0) const; /// EmitCFAByte - Emit a .byte 42 directive for a DW_CFA_xxx value. @@ -402,16 +404,13 @@ namespace llvm { void EmitSectionOffset(const MCSymbol *Label, const MCSymbol *SectionLabel) const; - /// getDebugValueLocation - Get location information encoded by DBG_VALUE - /// operands. - virtual MachineLocation getDebugValueLocation(const MachineInstr *MI) const; - /// getISAEncoding - Get the value for DW_AT_APPLE_isa. Zero if no isa /// encoding specified. virtual unsigned getISAEncoding() { return 0; } /// EmitDwarfRegOp - Emit dwarf register operation. - virtual void EmitDwarfRegOp(const MachineLocation &MLoc) const; + virtual void EmitDwarfRegOp(const MachineLocation &MLoc, + bool Indirect) const; //===------------------------------------------------------------------===// // Dwarf Lowering Routines diff --git a/include/llvm/CodeGen/CalcSpillWeights.h b/include/llvm/CodeGen/CalcSpillWeights.h index 9cd2dec..c8ec764 100644 --- a/include/llvm/CodeGen/CalcSpillWeights.h +++ b/include/llvm/CodeGen/CalcSpillWeights.h @@ -18,6 +18,7 @@ namespace llvm { class LiveInterval; class LiveIntervals; + class MachineBlockFrequencyInfo; class MachineLoopInfo; /// normalizeSpillWeight - The spill weight of a live interval is computed as: @@ -43,11 +44,13 @@ namespace llvm { MachineFunction &MF; LiveIntervals &LIS; const MachineLoopInfo &Loops; + const MachineBlockFrequencyInfo &MBFI; DenseMap<unsigned, float> Hint; public: VirtRegAuxInfo(MachineFunction &mf, LiveIntervals &lis, - const MachineLoopInfo &loops) : - MF(mf), LIS(lis), Loops(loops) {} + const MachineLoopInfo &loops, + const MachineBlockFrequencyInfo &mbfi) + : MF(mf), LIS(lis), Loops(loops), MBFI(mbfi) {} /// CalculateWeightAndHint - (re)compute li's spill weight and allocation /// hint. diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h index fa9d60f..a18f433 100644 --- a/include/llvm/CodeGen/CallingConvLower.h +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -158,7 +158,7 @@ private: MachineFunction &MF; const TargetMachine &TM; const TargetRegisterInfo &TRI; - SmallVector<CCValAssign, 16> &Locs; + SmallVectorImpl<CCValAssign> &Locs; LLVMContext &Context; unsigned StackOffset; @@ -219,7 +219,7 @@ protected: public: CCState(CallingConv::ID CC, bool isVarArg, MachineFunction &MF, - const TargetMachine &TM, SmallVector<CCValAssign, 16> &locs, + const TargetMachine &TM, SmallVectorImpl<CCValAssign> &locs, LLVMContext &C); void addLoc(const CCValAssign &V) { diff --git a/include/llvm/CodeGen/CommandFlags.h b/include/llvm/CodeGen/CommandFlags.h index 9a27661..0c21e76 100644 --- a/include/llvm/CodeGen/CommandFlags.h +++ b/include/llvm/CodeGen/CommandFlags.h @@ -110,11 +110,6 @@ DisableFPElim("disable-fp-elim", cl::init(false)); cl::opt<bool> -DisableFPElimNonLeaf("disable-non-leaf-fp-elim", - cl::desc("Disable frame pointer elimination optimization for non-leaf funcs"), - cl::init(false)); - -cl::opt<bool> EnableUnsafeFPMath("enable-unsafe-fp-math", cl::desc("Enable optimizations that may decrease FP precision"), cl::init(false)); @@ -186,11 +181,6 @@ OverrideStackAlignment("stack-alignment", cl::desc("Override default stack alignment"), cl::init(0)); -cl::opt<bool> -EnableRealignStack("realign-stack", - cl::desc("Realign stack if needed"), - cl::init(true)); - cl::opt<std::string> TrapFuncName("trap-func", cl::Hidden, cl::desc("Emit a call to trap function rather than a trap instruction"), @@ -220,8 +210,4 @@ cl::opt<std::string> StartAfter("start-after", cl::value_desc("pass-name"), cl::init("")); -cl::opt<unsigned> -SSPBufferSize("stack-protector-buffer-size", cl::init(8), - cl::desc("Lower bound for a buffer to be considered for " - "stack protection")); #endif diff --git a/include/llvm/CodeGen/FastISel.h b/include/llvm/CodeGen/FastISel.h index 471e9bf..0063474 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -1,4 +1,4 @@ -//===-- FastISel.h - Definition of the FastISel class ---------------------===// +//===-- FastISel.h - Definition of the FastISel class ---*- C++ -*---------===// // // The LLVM Compiler Infrastructure // @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the FastISel class. -// +/// +/// \file +/// This file defines the FastISel class. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CODEGEN_FASTISEL_H @@ -26,7 +27,6 @@ class ConstantFP; class FunctionLoweringInfo; class Instruction; class LoadInst; -class MachineBasicBlock; class MachineConstantPool; class MachineFunction; class MachineInstr; @@ -42,9 +42,8 @@ class TargetRegisterInfo; class User; class Value; -/// FastISel - This is a fast-path instruction selection class that -/// generates poor code and doesn't support illegal types or non-trivial -/// lowering, but runs quickly. +/// This is a fast-path instruction selection class that generates poor code and +/// doesn't support illegal types or non-trivial lowering, but runs quickly. class FastISel { protected: DenseMap<const Value *, unsigned> LocalValueMap; @@ -60,99 +59,92 @@ protected: const TargetRegisterInfo &TRI; const TargetLibraryInfo *LibInfo; - /// The position of the last instruction for materializing constants - /// for use in the current block. It resets to EmitStartPt when it - /// makes sense (for example, it's usually profitable to avoid function - /// calls between the definition and the use) + /// The position of the last instruction for materializing constants for use + /// in the current block. It resets to EmitStartPt when it makes sense (for + /// example, it's usually profitable to avoid function calls between the + /// definition and the use) MachineInstr *LastLocalValue; - /// The top most instruction in the current block that is allowed for - /// emitting local variables. LastLocalValue resets to EmitStartPt when - /// it makes sense (for example, on function calls) + /// The top most instruction in the current block that is allowed for emitting + /// local variables. LastLocalValue resets to EmitStartPt when it makes sense + /// (for example, on function calls) MachineInstr *EmitStartPt; public: - /// getLastLocalValue - Return the position of the last instruction - /// emitted for materializing constants for use in the current block. + /// Return the position of the last instruction emitted for materializing + /// constants for use in the current block. MachineInstr *getLastLocalValue() { return LastLocalValue; } - /// setLastLocalValue - Update the position of the last instruction - /// emitted for materializing constants for use in the current block. + /// Update the position of the last instruction emitted for materializing + /// constants for use in the current block. void setLastLocalValue(MachineInstr *I) { EmitStartPt = I; LastLocalValue = I; } - /// startNewBlock - Set the current block to which generated machine - /// instructions will be appended, and clear the local CSE map. - /// + /// Set the current block to which generated machine instructions will be + /// appended, and clear the local CSE map. void startNewBlock(); - /// getCurDebugLoc() - Return current debug location information. + /// Return current debug location information. DebugLoc getCurDebugLoc() const { return DL; } - /// LowerArguments - Do "fast" instruction selection for function arguments - /// and append machine instructions to the current block. Return true if - /// it is successful. + /// Do "fast" instruction selection for function arguments and append machine + /// instructions to the current block. Return true if it is successful. bool LowerArguments(); - /// SelectInstruction - Do "fast" instruction selection for the given - /// LLVM IR instruction, and append generated machine instructions to - /// the current block. Return true if selection was successful. - /// + /// Do "fast" instruction selection for the given LLVM IR instruction, and + /// append generated machine instructions to the current block. Return true if + /// selection was successful. bool SelectInstruction(const Instruction *I); - /// SelectOperator - Do "fast" instruction selection for the given - /// LLVM IR operator (Instruction or ConstantExpr), and append - /// generated machine instructions to the current block. Return true - /// if selection was successful. - /// + /// Do "fast" instruction selection for the given LLVM IR operator + /// (Instruction or ConstantExpr), and append generated machine instructions + /// to the current block. Return true if selection was successful. bool SelectOperator(const User *I, unsigned Opcode); - /// getRegForValue - Create a virtual register and arrange for it to - /// be assigned the value for the given LLVM value. + /// Create a virtual register and arrange for it to be assigned the value for + /// the given LLVM value. unsigned getRegForValue(const Value *V); - /// lookUpRegForValue - Look up the value to see if its value is already - /// cached in a register. It may be defined by instructions across blocks or - /// defined locally. + /// Look up the value to see if its value is already cached in a register. It + /// may be defined by instructions across blocks or defined locally. unsigned lookUpRegForValue(const Value *V); - /// getRegForGEPIndex - This is a wrapper around getRegForValue that also - /// takes care of truncating or sign-extending the given getelementptr - /// index value. + /// This is a wrapper around getRegForValue that also takes care of truncating + /// or sign-extending the given getelementptr index value. std::pair<unsigned, bool> getRegForGEPIndex(const Value *V); - /// \brief We're checking to see if we can fold \p LI into \p FoldInst. - /// Note that we could have a sequence where multiple LLVM IR instructions - /// are folded into the same machineinstr. For example we could have: + /// \brief We're checking to see if we can fold \p LI into \p FoldInst. Note + /// that we could have a sequence where multiple LLVM IR instructions are + /// folded into the same machineinstr. For example we could have: + /// /// A: x = load i32 *P /// B: y = icmp A, 42 /// C: br y, ... /// - /// In this scenario, \p LI is "A", and \p FoldInst is "C". We know - /// about "B" (and any other folded instructions) because it is between - /// A and C. + /// In this scenario, \p LI is "A", and \p FoldInst is "C". We know about "B" + /// (and any other folded instructions) because it is between A and C. /// /// If we succeed folding, return true. - /// bool tryToFoldLoad(const LoadInst *LI, const Instruction *FoldInst); - /// \brief The specified machine instr operand is a vreg, and that - /// vreg is being provided by the specified load instruction. If possible, - /// try to fold the load as an operand to the instruction, returning true if + /// \brief The specified machine instr operand is a vreg, and that vreg is + /// being provided by the specified load instruction. If possible, try to + /// fold the load as an operand to the instruction, returning true if /// possible. + /// /// This method should be implemented by targets. virtual bool tryToFoldLoadIntoMI(MachineInstr * /*MI*/, unsigned /*OpNo*/, const LoadInst * /*LI*/) { return false; } - /// recomputeInsertPt - Reset InsertPt to prepare for inserting instructions - /// into the current block. + /// Reset InsertPt to prepare for inserting instructions into the current + /// block. void recomputeInsertPt(); - /// removeDeadCode - Remove all dead instructions between the I and E. + /// Remove all dead instructions between the I and E. void removeDeadCode(MachineBasicBlock::iterator I, MachineBasicBlock::iterator E); @@ -161,11 +153,11 @@ public: DebugLoc DL; }; - /// enterLocalValueArea - Prepare InsertPt to begin inserting instructions - /// into the local value area and return the old insert position. + /// Prepare InsertPt to begin inserting instructions into the local value area + /// and return the old insert position. SavePoint enterLocalValueArea(); - /// leaveLocalValueArea - Reset InsertPt to the given old insert position. + /// Reset InsertPt to the given old insert position. void leaveLocalValueArea(SavePoint Old); virtual ~FastISel(); @@ -174,69 +166,59 @@ protected: explicit FastISel(FunctionLoweringInfo &funcInfo, const TargetLibraryInfo *libInfo); - /// TargetSelectInstruction - This method is called by target-independent - /// code when the normal FastISel process fails to select an instruction. - /// This gives targets a chance to emit code for anything that doesn't - /// fit into FastISel's framework. It returns true if it was successful. - /// + /// This method is called by target-independent code when the normal FastISel + /// process fails to select an instruction. This gives targets a chance to + /// emit code for anything that doesn't fit into FastISel's framework. It + /// returns true if it was successful. virtual bool TargetSelectInstruction(const Instruction *I) = 0; - /// FastLowerArguments - This method is called by target-independent code to - /// do target specific argument lowering. It returns true if it was - /// successful. + /// This method is called by target-independent code to do target specific + /// argument lowering. It returns true if it was successful. virtual bool FastLowerArguments(); - /// FastEmit_r - This method is called by target-independent code - /// to request that an instruction with the given type and opcode - /// be emitted. + /// This method is called by target-independent code to request that an + /// instruction with the given type and opcode be emitted. virtual unsigned FastEmit_(MVT VT, MVT RetVT, unsigned Opcode); - /// FastEmit_r - This method is called by target-independent code - /// to request that an instruction with the given type, opcode, and - /// register operand be emitted. - /// + /// This method is called by target-independent code to request that an + /// instruction with the given type, opcode, and register operand be emitted. virtual unsigned FastEmit_r(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, bool Op0IsKill); - /// FastEmit_rr - This method is called by target-independent code - /// to request that an instruction with the given type, opcode, and - /// register operands be emitted. - /// + /// This method is called by target-independent code to request that an + /// instruction with the given type, opcode, and register operands be emitted. virtual unsigned FastEmit_rr(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill); - /// FastEmit_ri - This method is called by target-independent code - /// to request that an instruction with the given type, opcode, and - /// register and immediate operands be emitted. - /// + /// This method is called by target-independent code to request that an + /// instruction with the given type, opcode, and register and immediate + /// operands be emitted. virtual unsigned FastEmit_ri(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, bool Op0IsKill, uint64_t Imm); - /// FastEmit_rf - This method is called by target-independent code - /// to request that an instruction with the given type, opcode, and - /// register and floating-point immediate operands be emitted. - /// + /// This method is called by target-independent code to request that an + /// instruction with the given type, opcode, and register and floating-point + /// immediate operands be emitted. virtual unsigned FastEmit_rf(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0, bool Op0IsKill, const ConstantFP *FPImm); - /// FastEmit_rri - This method is called by target-independent code - /// to request that an instruction with the given type, opcode, and - /// register and immediate operands be emitted. - /// + /// This method is called by target-independent code to request that an + /// instruction with the given type, opcode, and register and immediate + /// operands be emitted. virtual unsigned FastEmit_rri(MVT VT, MVT RetVT, unsigned Opcode, @@ -244,142 +226,130 @@ protected: unsigned Op1, bool Op1IsKill, uint64_t Imm); - /// FastEmit_ri_ - This method is a wrapper of FastEmit_ri. It first tries - /// to emit an instruction with an immediate operand using FastEmit_ri. - /// If that fails, it materializes the immediate into a register and try - /// FastEmit_rr instead. + /// \brief This method is a wrapper of FastEmit_ri. + /// + /// It first tries to emit an instruction with an immediate operand using + /// FastEmit_ri. If that fails, it materializes the immediate into a register + /// and try FastEmit_rr instead. unsigned FastEmit_ri_(MVT VT, unsigned Opcode, unsigned Op0, bool Op0IsKill, uint64_t Imm, MVT ImmType); - /// FastEmit_i - This method is called by target-independent code - /// to request that an instruction with the given type, opcode, and - /// immediate operand be emitted. + /// This method is called by target-independent code to request that an + /// instruction with the given type, opcode, and immediate operand be emitted. virtual unsigned FastEmit_i(MVT VT, MVT RetVT, unsigned Opcode, uint64_t Imm); - /// FastEmit_f - This method is called by target-independent code - /// to request that an instruction with the given type, opcode, and - /// floating-point immediate operand be emitted. + /// This method is called by target-independent code to request that an + /// instruction with the given type, opcode, and floating-point immediate + /// operand be emitted. virtual unsigned FastEmit_f(MVT VT, MVT RetVT, unsigned Opcode, const ConstantFP *FPImm); - /// FastEmitInst_ - Emit a MachineInstr with no operands and a - /// result register in the given register class. - /// + /// Emit a MachineInstr with no operands and a result register in the given + /// register class. unsigned FastEmitInst_(unsigned MachineInstOpcode, const TargetRegisterClass *RC); - /// FastEmitInst_r - Emit a MachineInstr with one register operand - /// and a result register in the given register class. - /// + /// Emit a MachineInstr with one register operand and a result register in the + /// given register class. unsigned FastEmitInst_r(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill); - /// FastEmitInst_rr - Emit a MachineInstr with two register operands - /// and a result register in the given register class. - /// + /// Emit a MachineInstr with two register operands and a result register in + /// the given register class. unsigned FastEmitInst_rr(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill); - /// FastEmitInst_rrr - Emit a MachineInstr with three register operands - /// and a result register in the given register class. - /// + /// Emit a MachineInstr with three register operands and a result register in + /// the given register class. unsigned FastEmitInst_rrr(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill, unsigned Op2, bool Op2IsKill); - /// FastEmitInst_ri - Emit a MachineInstr with a register operand, - /// an immediate, and a result register in the given register class. - /// + /// Emit a MachineInstr with a register operand, an immediate, and a result + /// register in the given register class. unsigned FastEmitInst_ri(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, uint64_t Imm); - /// FastEmitInst_rii - Emit a MachineInstr with one register operand - /// and two immediate operands. - /// + /// Emit a MachineInstr with one register operand and two immediate operands. unsigned FastEmitInst_rii(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, uint64_t Imm1, uint64_t Imm2); - /// FastEmitInst_rf - Emit a MachineInstr with two register operands - /// and a result register in the given register class. - /// + /// Emit a MachineInstr with two register operands and a result register in + /// the given register class. unsigned FastEmitInst_rf(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, const ConstantFP *FPImm); - /// FastEmitInst_rri - Emit a MachineInstr with two register operands, - /// an immediate, and a result register in the given register class. - /// + /// Emit a MachineInstr with two register operands, an immediate, and a result + /// register in the given register class. unsigned FastEmitInst_rri(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill, uint64_t Imm); - /// FastEmitInst_rrii - Emit a MachineInstr with two register operands, - /// two immediates operands, and a result register in the given register - /// class. + /// Emit a MachineInstr with two register operands, two immediates operands, + /// and a result register in the given register class. unsigned FastEmitInst_rrii(unsigned MachineInstOpcode, const TargetRegisterClass *RC, unsigned Op0, bool Op0IsKill, unsigned Op1, bool Op1IsKill, uint64_t Imm1, uint64_t Imm2); - /// FastEmitInst_i - Emit a MachineInstr with a single immediate - /// operand, and a result register in the given register class. + /// Emit a MachineInstr with a single immediate operand, and a result register + /// in the given register class. unsigned FastEmitInst_i(unsigned MachineInstrOpcode, const TargetRegisterClass *RC, uint64_t Imm); - /// FastEmitInst_ii - Emit a MachineInstr with a two immediate operands. + /// Emit a MachineInstr with a two immediate operands. unsigned FastEmitInst_ii(unsigned MachineInstrOpcode, const TargetRegisterClass *RC, uint64_t Imm1, uint64_t Imm2); - /// FastEmitInst_extractsubreg - Emit a MachineInstr for an extract_subreg - /// from a specified index of a superregister to a specified type. + /// Emit a MachineInstr for an extract_subreg from a specified index of a + /// superregister to a specified type. unsigned FastEmitInst_extractsubreg(MVT RetVT, unsigned Op0, bool Op0IsKill, uint32_t Idx); - /// FastEmitZExtFromI1 - Emit MachineInstrs to compute the value of Op - /// with all but the least significant bit set to zero. + /// Emit MachineInstrs to compute the value of Op with all but the least + /// significant bit set to zero. unsigned FastEmitZExtFromI1(MVT VT, unsigned Op0, bool Op0IsKill); - /// FastEmitBranch - Emit an unconditional branch to the given block, - /// unless it is the immediate (fall-through) successor, and update - /// the CFG. + /// Emit an unconditional branch to the given block, unless it is the + /// immediate (fall-through) successor, and update the CFG. void FastEmitBranch(MachineBasicBlock *MBB, DebugLoc DL); void UpdateValueMap(const Value* I, unsigned Reg, unsigned NumRegs = 1); unsigned createResultReg(const TargetRegisterClass *RC); - /// TargetMaterializeConstant - Emit a constant in a register using - /// target-specific logic, such as constant pool loads. + /// Emit a constant in a register using target-specific logic, such as + /// constant pool loads. virtual unsigned TargetMaterializeConstant(const Constant* C) { return 0; } - /// TargetMaterializeAlloca - Emit an alloca address in a register using - /// target-specific logic. + /// Emit an alloca address in a register using target-specific logic. virtual unsigned TargetMaterializeAlloca(const AllocaInst* C) { return 0; } @@ -405,25 +375,26 @@ private: bool SelectInsertValue(const User *I); - /// HandlePHINodesInSuccessorBlocks - Handle PHI nodes in successor blocks. + /// \brief Handle PHI nodes in successor blocks. + /// /// Emit code to ensure constants are copied into registers when needed. /// Remember the virtual registers that need to be added to the Machine PHI - /// nodes as input. We cannot just directly add them, because expansion - /// might result in multiple MBB's for one BB. As such, the start of the - /// BB might correspond to a different MBB than the end. + /// nodes as input. We cannot just directly add them, because expansion might + /// result in multiple MBB's for one BB. As such, the start of the BB might + /// correspond to a different MBB than the end. bool HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB); - /// materializeRegForValue - Helper for getRegForVale. This function is - /// called when the value isn't already available in a register and must - /// be materialized with new instructions. + /// Helper for getRegForVale. This function is called when the value isn't + /// already available in a register and must be materialized with new + /// instructions. unsigned materializeRegForValue(const Value *V, MVT VT); - /// flushLocalValueMap - clears LocalValueMap and moves the area for the - /// new local variables to the beginning of the block. It helps to avoid - /// spilling cached variables across heavy instructions like calls. + /// Clears LocalValueMap and moves the area for the new local variables to the + /// beginning of the block. It helps to avoid spilling cached variables across + /// heavy instructions like calls. void flushLocalValueMap(); - /// hasTrivialKill - Test whether the given value has exactly one use. + /// Test whether the given value has exactly one use. bool hasTrivialKill(const Value *V) const; }; diff --git a/include/llvm/CodeGen/FunctionLoweringInfo.h b/include/llvm/CodeGen/FunctionLoweringInfo.h index 206fef7..50d320f 100644 --- a/include/llvm/CodeGen/FunctionLoweringInfo.h +++ b/include/llvm/CodeGen/FunctionLoweringInfo.h @@ -50,7 +50,6 @@ class Value; /// class FunctionLoweringInfo { const TargetMachine &TM; - const TargetLowering *TLI; public: const Function *Fn; MachineFunction *MF; @@ -116,7 +115,12 @@ public: /// there's no other convenient place for it to live right now. std::vector<std::pair<MachineInstr*, unsigned> > PHINodesToUpdate; - explicit FunctionLoweringInfo(const TargetMachine &TM); + /// If the current MBB is a landing pad, the exception pointer and exception + /// selector registers are copied into these virtual registers by + /// SelectionDAGISel::PrepareEHLandingPad(). + unsigned ExceptionPointerVirtReg, ExceptionSelectorVirtReg; + + explicit FunctionLoweringInfo(const TargetMachine &TM) : TM(TM) {} /// set - Initialize this FunctionLoweringInfo with the given Function /// and its associated MachineFunction. diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index 0fd211b..9466b90 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -77,18 +77,6 @@ namespace ISD { /// adjustment during unwind. FRAME_TO_ARGS_OFFSET, - /// RESULT, OUTCHAIN = EXCEPTIONADDR(INCHAIN) - This node represents the - /// address of the exception block on entry to an landing pad block. - EXCEPTIONADDR, - - /// RESULT, OUTCHAIN = LSDAADDR(INCHAIN) - This node represents the - /// address of the Language Specific Data Area for the enclosing function. - LSDAADDR, - - /// RESULT, OUTCHAIN = EHSELECTION(INCHAIN, EXCEPTION) - This node - /// represents the selection index of the exception thrown. - EHSELECTION, - /// OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER) - This node represents /// 'eh_return' gcc dwarf builtin, which is used to return from /// exception. The general meaning is: adjust stack by OFFSET and pass @@ -647,7 +635,7 @@ namespace ISD { /// which do not reference a specific memory location should be less than /// this value. Those that do must not be less than this value, and can /// be used with SelectionDAG::getMemIntrinsicNode. - static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+150; + static const int FIRST_TARGET_MEMORY_OPCODE = BUILTIN_OP_END+180; //===--------------------------------------------------------------------===// /// MemIndexedMode enum - This enum defines the load / store indexed diff --git a/include/llvm/CodeGen/LexicalScopes.h b/include/llvm/CodeGen/LexicalScopes.h index ff65db4..26563a6 100644 --- a/include/llvm/CodeGen/LexicalScopes.h +++ b/include/llvm/CodeGen/LexicalScopes.h @@ -141,8 +141,8 @@ private: DenseMap<const MDNode *, LexicalScope *> AbstractScopeMap; /// AbstractScopesList - Tracks abstract scopes constructed while processing - /// a function. - SmallVector<LexicalScope *, 4>AbstractScopesList; + /// a function. + SmallVector<LexicalScope *, 4> AbstractScopesList; /// CurrentFnLexicalScope - Top level scope for the current function. /// @@ -166,13 +166,13 @@ public: virtual ~LexicalScope() {} // Accessors. - LexicalScope *getParent() const { return Parent; } - const MDNode *getDesc() const { return Desc; } - const MDNode *getInlinedAt() const { return InlinedAtLocation; } - const MDNode *getScopeNode() const { return Desc; } - bool isAbstractScope() const { return AbstractScope; } - SmallVector<LexicalScope *, 4> &getChildren() { return Children; } - SmallVector<InsnRange, 4> &getRanges() { return Ranges; } + LexicalScope *getParent() const { return Parent; } + const MDNode *getDesc() const { return Desc; } + const MDNode *getInlinedAt() const { return InlinedAtLocation; } + const MDNode *getScopeNode() const { return Desc; } + bool isAbstractScope() const { return AbstractScope; } + SmallVectorImpl<LexicalScope *> &getChildren() { return Children; } + SmallVectorImpl<InsnRange> &getRanges() { return Ranges; } /// addChild - Add a child scope. void addChild(LexicalScope *S) { Children.push_back(S); } diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index cb09a49..efad0c6 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -389,7 +389,7 @@ namespace llvm { void join(LiveInterval &Other, const int *ValNoAssignments, const int *RHSValNoAssignments, - SmallVector<VNInfo*, 16> &NewVNInfo, + SmallVectorImpl<VNInfo *> &NewVNInfo, MachineRegisterInfo *MRI); /// isInOneLiveRange - Return true if the range specified is entirely in the diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index 7d72f37..ffb07a5 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -35,6 +35,7 @@ namespace llvm { class AliasAnalysis; class BitVector; + class BlockFrequency; class LiveRangeCalc; class LiveVariables; class MachineDominatorTree; @@ -99,7 +100,7 @@ namespace llvm { virtual ~LiveIntervals(); // Calculate the spill weight to assign to a single instruction. - static float getSpillWeight(bool isDef, bool isUse, unsigned loopDepth); + static float getSpillWeight(bool isDef, bool isUse, BlockFrequency freq); LiveInterval &getInterval(unsigned Reg) { LiveInterval *LI = VirtRegIntervals[Reg]; diff --git a/include/llvm/CodeGen/LiveRangeEdit.h b/include/llvm/CodeGen/LiveRangeEdit.h index e59276f..a8749da 100644 --- a/include/llvm/CodeGen/LiveRangeEdit.h +++ b/include/llvm/CodeGen/LiveRangeEdit.h @@ -19,6 +19,7 @@ #define LLVM_CODEGEN_LIVERANGEEDIT_H #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/CodeGen/LiveInterval.h" #include "llvm/Target/TargetMachine.h" @@ -27,6 +28,7 @@ namespace llvm { class AliasAnalysis; class LiveIntervals; +class MachineBlockFrequencyInfo; class MachineLoopInfo; class MachineRegisterInfo; class VirtRegMap; @@ -89,6 +91,12 @@ private: /// a load, eliminate the register by folding the def into the use. bool foldAsLoad(LiveInterval *LI, SmallVectorImpl<MachineInstr*> &Dead); + typedef SetVector<LiveInterval*, + SmallVector<LiveInterval*, 8>, + SmallPtrSet<LiveInterval*, 8> > ToShrinkSet; + /// Helper for eliminateDeadDefs. + void eliminateDeadDef(MachineInstr *MI, ToShrinkSet &ToShrink); + public: /// Create a LiveRangeEdit for breaking down parent into smaller pieces. /// @param parent The register being spilled or split. @@ -201,7 +209,8 @@ public: /// calculateRegClassAndHint - Recompute register class and hint for each new /// register. void calculateRegClassAndHint(MachineFunction&, - const MachineLoopInfo&); + const MachineLoopInfo&, + const MachineBlockFrequencyInfo&); }; } diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h index 6628fd2..dc735f7 100644 --- a/include/llvm/CodeGen/LiveVariables.h +++ b/include/llvm/CodeGen/LiveVariables.h @@ -157,8 +157,8 @@ private: // Intermediate data structures void HandlePhysRegUse(unsigned Reg, MachineInstr *MI); void HandlePhysRegDef(unsigned Reg, MachineInstr *MI, - SmallVector<unsigned, 4> &Defs); - void UpdatePhysRegDefs(MachineInstr *MI, SmallVector<unsigned, 4> &Defs); + SmallVectorImpl<unsigned> &Defs); + void UpdatePhysRegDefs(MachineInstr *MI, SmallVectorImpl<unsigned> &Defs); /// FindLastRefOrPartRef - Return the last reference or partial reference of /// the specified register. diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h index 0f2f874..d6f5883 100644 --- a/include/llvm/CodeGen/MachineBasicBlock.h +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -296,6 +296,11 @@ public: /// is an error to add the same register to the same set more than once. void addLiveIn(unsigned Reg) { LiveIns.push_back(Reg); } + /// Add PhysReg as live in to this block, and ensure that there is a copy of + /// PhysReg to a virtual register of class RC. Return the virtual register + /// that is a copy of the live in PhysReg. + unsigned addLiveIn(unsigned PhysReg, const TargetRegisterClass *RC); + /// removeLiveIn - Remove the specified register from the live in set. /// void removeLiveIn(unsigned Reg); diff --git a/include/llvm/CodeGen/MachineConstantPool.h b/include/llvm/CodeGen/MachineConstantPool.h index 8ed215d..912ce89 100644 --- a/include/llvm/CodeGen/MachineConstantPool.h +++ b/include/llvm/CodeGen/MachineConstantPool.h @@ -132,15 +132,17 @@ public: /// address of the function constant pool values. /// @brief The machine constant pool. class MachineConstantPool { - const DataLayout *TD; ///< The machine's DataLayout. - unsigned PoolAlignment; ///< The alignment for the pool. + const TargetMachine &TM; ///< The target machine. + unsigned PoolAlignment; ///< The alignment for the pool. std::vector<MachineConstantPoolEntry> Constants; ///< The pool of constants. /// MachineConstantPoolValues that use an existing MachineConstantPoolEntry. DenseSet<MachineConstantPoolValue*> MachineCPVsSharingEntries; + + const DataLayout *getDataLayout() const; public: /// @brief The only constructor. - explicit MachineConstantPool(const DataLayout *td) - : TD(td), PoolAlignment(1) {} + explicit MachineConstantPool(const TargetMachine &TM) + : TM(TM), PoolAlignment(1) {} ~MachineConstantPool(); /// getConstantPoolAlignment - Return the alignment required by diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index cdec7e6..022634d 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -27,6 +27,7 @@ class Type; class MachineFunction; class MachineBasicBlock; class TargetFrameLowering; +class TargetMachine; class BitVector; class Value; class AllocaInst; @@ -119,6 +120,8 @@ class MachineFrameInfo { isSpillSlot(isSS), MayNeedSP(NSP), Alloca(Val), PreAllocated(false) {} }; + const TargetMachine &TM; + /// Objects - The list of stack objects allocated... /// std::vector<StackObject> Objects; @@ -201,10 +204,6 @@ class MachineFrameInfo { /// CSIValid - Has CSInfo been set yet? bool CSIValid; - /// TargetFrameLowering - Target information about frame layout. - /// - const TargetFrameLowering &TFI; - /// LocalFrameObjects - References to frame indices which are mapped /// into the local frame allocation block. <FrameIdx, LocalOffset> SmallVector<std::pair<int, int64_t>, 32> LocalFrameObjects; @@ -223,9 +222,11 @@ class MachineFrameInfo { /// Whether the "realign-stack" option is on. bool RealignOption; + + const TargetFrameLowering *getFrameLowering() const; public: - explicit MachineFrameInfo(const TargetFrameLowering &tfi, bool RealignOpt) - : TFI(tfi), RealignOption(RealignOpt) { + explicit MachineFrameInfo(const TargetMachine &TM, bool RealignOpt) + : TM(TM), RealignOption(RealignOpt) { StackSize = NumFixedObjects = OffsetAdjustment = MaxAlignment = 0; HasVarSizedObjects = false; FrameAddressTaken = false; diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index 195cce7..cf5e7e2 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -908,11 +908,6 @@ public: bool isSafeToMove(const TargetInstrInfo *TII, AliasAnalysis *AA, bool &SawStore) const; - /// isSafeToReMat - Return true if it's safe to rematerialize the specified - /// instruction which defined the specified register instead of copying it. - bool isSafeToReMat(const TargetInstrInfo *TII, AliasAnalysis *AA, - unsigned DstReg) const; - /// hasOrderedMemoryRef - Return true if this instruction may have an ordered /// or volatile memory reference, or if the information describing the memory /// reference is not available. Return false if it is known to have no diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h index 92c8da9..df01371 100644 --- a/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -335,6 +335,51 @@ inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, return BuildMI(*BB, BB->end(), DL, MCID, DestReg); } +/// BuildMI - This version of the builder builds a DBG_VALUE intrinsic +/// for either a value in a register or a register-indirect+offset +/// address. The convention is that a DBG_VALUE is indirect iff the +/// second operand is an immediate. +/// +inline MachineInstrBuilder BuildMI(MachineFunction &MF, + DebugLoc DL, + const MCInstrDesc &MCID, + bool IsIndirect, + unsigned Reg, + unsigned Offset, + const MDNode *MD) { + if (IsIndirect) + return BuildMI(MF, DL, MCID) + .addReg(Reg, RegState::Debug) + .addImm(Offset) + .addMetadata(MD); + else { + assert(Offset == 0 && "A direct address cannot have an offset."); + return BuildMI(MF, DL, MCID) + .addReg(Reg, RegState::Debug) + .addReg(0U, RegState::Debug) + .addMetadata(MD); + } +} + +/// BuildMI - This version of the builder builds a DBG_VALUE intrinsic +/// for either a value in a register or a register-indirect+offset +/// address and inserts it at position I. +/// +inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, + DebugLoc DL, + const MCInstrDesc &MCID, + bool IsIndirect, + unsigned Reg, + unsigned Offset, + const MDNode *MD) { + MachineFunction &MF = *BB.getParent(); + MachineInstr *MI = BuildMI(MF, DL, MCID, IsIndirect, Reg, Offset, MD); + BB.insert(I, MI); + return MachineInstrBuilder(MF, MI); +} + + inline unsigned getDefRegState(bool B) { return B ? RegState::Define : 0; } diff --git a/include/llvm/CodeGen/MachineOperand.h b/include/llvm/CodeGen/MachineOperand.h index 414770b..57b28fe 100644 --- a/include/llvm/CodeGen/MachineOperand.h +++ b/include/llvm/CodeGen/MachineOperand.h @@ -391,7 +391,7 @@ public: } void setIsDebug(bool Val = true) { - assert(isReg() && IsDef && "Wrong MachineOperand accessor"); + assert(isReg() && !IsDef && "Wrong MachineOperand accessor"); IsDebug = Val; } diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index 24ba7bb..7a6dcd0 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -17,6 +17,7 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/IndexedMap.h" #include "llvm/CodeGen/MachineInstrBundle.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/Target/TargetRegisterInfo.h" #include <vector> @@ -26,7 +27,7 @@ namespace llvm { /// registers, including vreg register classes, use/def chains for registers, /// etc. class MachineRegisterInfo { - const TargetRegisterInfo *const TRI; + const TargetMachine &TM; /// IsSSA - True when the machine function is in SSA form and virtual /// registers have a single def. @@ -108,9 +109,13 @@ class MachineRegisterInfo { MachineRegisterInfo(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; void operator=(const MachineRegisterInfo&) LLVM_DELETED_FUNCTION; public: - explicit MachineRegisterInfo(const TargetRegisterInfo &TRI); + explicit MachineRegisterInfo(const TargetMachine &TM); ~MachineRegisterInfo(); + const TargetRegisterInfo *getTargetRegisterInfo() const { + return TM.getRegisterInfo(); + } + //===--------------------------------------------------------------------===// // Function State //===--------------------------------------------------------------------===// @@ -377,7 +382,8 @@ public: bool isPhysRegUsed(unsigned Reg) const { if (UsedPhysRegMask.test(Reg)) return true; - for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) + for (MCRegUnitIterator Units(Reg, getTargetRegisterInfo()); + Units.isValid(); ++Units) if (UsedRegUnits.test(*Units)) return true; return false; @@ -392,7 +398,8 @@ public: /// setPhysRegUsed - Mark the specified register used in this function. /// This should only be called during and after register allocation. void setPhysRegUsed(unsigned Reg) { - for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) + for (MCRegUnitIterator Units(Reg, getTargetRegisterInfo()); + Units.isValid(); ++Units) UsedRegUnits.set(*Units); } @@ -406,7 +413,8 @@ public: /// This should only be called during and after register allocation. void setPhysRegUnused(unsigned Reg) { UsedPhysRegMask.reset(Reg); - for (MCRegUnitIterator Units(Reg, TRI); Units.isValid(); ++Units) + for (MCRegUnitIterator Units(Reg, getTargetRegisterInfo()); + Units.isValid(); ++Units) UsedRegUnits.reset(*Units); } @@ -466,7 +474,8 @@ public: /// register, so a register allocator needs to track its liveness and /// availability. bool isAllocatable(unsigned PhysReg) const { - return TRI->isInAllocatableClass(PhysReg) && !isReserved(PhysReg); + return getTargetRegisterInfo()->isInAllocatableClass(PhysReg) && + !isReserved(PhysReg); } //===--------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/MachineScheduler.h b/include/llvm/CodeGen/MachineScheduler.h index 769e4b4..d110ea1 100644 --- a/include/llvm/CodeGen/MachineScheduler.h +++ b/include/llvm/CodeGen/MachineScheduler.h @@ -30,7 +30,6 @@ #include "llvm/CodeGen/MachinePassRegistry.h" #include "llvm/CodeGen/RegisterPressure.h" #include "llvm/CodeGen/ScheduleDAGInstrs.h" -#include "llvm/Target/TargetInstrInfo.h" namespace llvm { diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h index 7ec90ae..9b6f61e 100644 --- a/include/llvm/CodeGen/Passes.h +++ b/include/llvm/CodeGen/Passes.h @@ -308,7 +308,8 @@ protected: AnalysisID addPass(AnalysisID PassID); /// Add a pass to the PassManager if that pass is supposed to be run, as - /// determined by the StartAfter and StopAfter options. + /// determined by the StartAfter and StopAfter options. Takes ownership of the + /// pass. void addPass(Pass *P); /// addMachinePasses helper to create the target-selected or overriden @@ -329,7 +330,7 @@ namespace llvm { /// This pass implements the target transform info analysis using the target /// independent information available to the LLVM code generator. ImmutablePass * - createBasicTargetTransformInfoPass(const TargetLoweringBase *TLI); + createBasicTargetTransformInfoPass(const TargetMachine *TM); /// createUnreachableBlockEliminationPass - The LLVM code generator does not /// work well with unreachable basic blocks (what live ranges make sense for a @@ -518,7 +519,7 @@ namespace llvm { /// createStackProtectorPass - This pass adds stack protectors to functions. /// - FunctionPass *createStackProtectorPass(const TargetLoweringBase *tli); + FunctionPass *createStackProtectorPass(const TargetMachine *TM); /// createMachineVerifierPass - This pass verifies cenerated machine code /// instructions for correctness. @@ -527,12 +528,12 @@ namespace llvm { /// createDwarfEHPass - This pass mulches exception handling code into a form /// adapted to code generation. Required if using dwarf exception handling. - FunctionPass *createDwarfEHPass(const TargetLoweringBase *tli); + FunctionPass *createDwarfEHPass(const TargetMachine *TM); /// createSjLjEHPreparePass - This pass adapts exception handling code to use /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control flow. /// - FunctionPass *createSjLjEHPreparePass(const TargetLoweringBase *tli); + FunctionPass *createSjLjEHPreparePass(const TargetMachine *TM); /// LocalStackSlotAllocation - This pass assigns local frame indices to stack /// slots relative to one another and allocates base registers to access them diff --git a/include/llvm/CodeGen/RegAllocPBQP.h b/include/llvm/CodeGen/RegAllocPBQP.h index 8b8e3d9..6f2d139 100644 --- a/include/llvm/CodeGen/RegAllocPBQP.h +++ b/include/llvm/CodeGen/RegAllocPBQP.h @@ -26,8 +26,8 @@ namespace llvm { class LiveIntervals; + class MachineBlockFrequencyInfo; class MachineFunction; - class MachineLoopInfo; class TargetRegisterInfo; template<class T> class OwningPtr; @@ -125,7 +125,7 @@ namespace llvm { /// Build a PBQP instance to represent the register allocation problem for /// the given MachineFunction. virtual PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis, - const MachineLoopInfo *loopInfo, + const MachineBlockFrequencyInfo *mbfi, const RegSet &vregs); private: @@ -144,7 +144,7 @@ namespace llvm { /// Build a PBQP instance to represent the register allocation problem for /// the given MachineFunction. virtual PBQPRAProblem *build(MachineFunction *mf, const LiveIntervals *lis, - const MachineLoopInfo *loopInfo, + const MachineBlockFrequencyInfo *mbfi, const RegSet &vregs); private: diff --git a/include/llvm/CodeGen/RegisterClassInfo.h b/include/llvm/CodeGen/RegisterClassInfo.h index 3ad22e6..9ec12bd 100644 --- a/include/llvm/CodeGen/RegisterClassInfo.h +++ b/include/llvm/CodeGen/RegisterClassInfo.h @@ -62,6 +62,8 @@ class RegisterClassInfo { // Reserved registers in the current MF. BitVector Reserved; + OwningArrayPtr<unsigned> PSetLimits; + // Compute all information about RC. void compute(const TargetRegisterClass *RC) const; @@ -126,8 +128,19 @@ public: unsigned getLastCostChange(const TargetRegisterClass *RC) { return get(RC).LastCostChange; } + + /// Get the register unit limit for the given pressure set index. + /// + /// RegisterClassInfo adjusts this limit for reserved registers. + unsigned getRegPressureSetLimit(unsigned Idx) const { + if (!PSetLimits[Idx]) + PSetLimits[Idx] = computePSetLimit(Idx); + return PSetLimits[Idx]; + } + +protected: + unsigned computePSetLimit(unsigned Idx) const; }; } // end namespace llvm #endif - diff --git a/include/llvm/CodeGen/RegisterPressure.h b/include/llvm/CodeGen/RegisterPressure.h index 2670180..8a0a8f3 100644 --- a/include/llvm/CodeGen/RegisterPressure.h +++ b/include/llvm/CodeGen/RegisterPressure.h @@ -99,6 +99,10 @@ struct PressureElement { PressureElement(unsigned id, int inc): PSetID(id), UnitIncrease(inc) {} bool isValid() const { return PSetID != ~0U; } + + // If signed PSetID is negative, it is invalid; convert it to INT_MAX to give + // it lowest priority. + int PSetRank() const { return PSetID & INT_MAX; } }; /// Store the effects of a change in pressure on things that MI scheduler cares @@ -183,6 +187,9 @@ class RegPressureTracker { /// or RegisterPressure. If requireIntervals is false, LIS are ignored. bool RequireIntervals; + /// True if UntiedDefs will be populated. + bool TrackUntiedDefs; + /// Register pressure corresponds to liveness before this instruction /// iterator. It may point to the end of the block or a DebugValue rather than /// an instruction. @@ -194,16 +201,24 @@ class RegPressureTracker { /// Set of live registers. LiveRegSet LiveRegs; + /// Set of vreg defs that start a live range. + SparseSet<unsigned, VirtReg2IndexFunctor> UntiedDefs; + /// Live-through pressure. + std::vector<unsigned> LiveThruPressure; + public: RegPressureTracker(IntervalPressure &rp) : - MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(true) {} + MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(true), + TrackUntiedDefs(false) {} RegPressureTracker(RegionPressure &rp) : - MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(false) {} + MF(0), TRI(0), RCI(0), LIS(0), MBB(0), P(rp), RequireIntervals(false), + TrackUntiedDefs(false) {} void init(const MachineFunction *mf, const RegisterClassInfo *rci, const LiveIntervals *lis, const MachineBasicBlock *mbb, - MachineBasicBlock::const_iterator pos); + MachineBasicBlock::const_iterator pos, + bool ShouldTrackUntiedDefs = false); /// Force liveness of virtual registers or physical register /// units. Particularly useful to initialize the livein/out state of the @@ -232,6 +247,17 @@ public: /// Finalize the region boundaries and recored live ins and live outs. void closeRegion(); + /// Initialize the LiveThru pressure set based on the untied defs found in + /// RPTracker. + void initLiveThru(const RegPressureTracker &RPTracker); + + /// Copy an existing live thru pressure result. + void initLiveThru(ArrayRef<unsigned> PressureSet) { + LiveThruPressure.assign(PressureSet.begin(), PressureSet.end()); + } + + ArrayRef<unsigned> getLiveThru() const { return LiveThruPressure; } + /// Get the resulting register pressure over the traversed region. /// This result is complete if either advance() or recede() has returned true, /// or if closeRegion() was explicitly invoked. @@ -304,6 +330,10 @@ public: return getDownwardPressure(MI, PressureResult, MaxPressureResult); } + bool hasUntiedDef(unsigned VirtReg) const { + return UntiedDefs.count(VirtReg); + } + void dump() const; protected: @@ -315,6 +345,11 @@ protected: void bumpUpwardPressure(const MachineInstr *MI); void bumpDownwardPressure(const MachineInstr *MI); }; + +#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) +void dumpRegSetPressure(ArrayRef<unsigned> SetPressure, + const TargetRegisterInfo *TRI); +#endif } // end namespace llvm #endif diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h index 95bf291..28ebe53 100644 --- a/include/llvm/CodeGen/RegisterScavenging.h +++ b/include/llvm/CodeGen/RegisterScavenging.h @@ -131,7 +131,7 @@ public: /// Query whether a frame index is a scavenging frame index. bool isScavengingFrameIndex(int FI) const { - for (SmallVector<ScavengedInfo, 2>::const_iterator I = Scavenged.begin(), + for (SmallVectorImpl<ScavengedInfo>::const_iterator I = Scavenged.begin(), IE = Scavenged.end(); I != IE; ++I) if (I->FrameIndex == FI) return true; @@ -141,7 +141,7 @@ public: /// Get an array of scavenging frame indices. void getScavengingFrameIndices(SmallVectorImpl<int> &A) const { - for (SmallVector<ScavengedInfo, 2>::const_iterator I = Scavenged.begin(), + for (SmallVectorImpl<ScavengedInfo>::const_iterator I = Scavenged.begin(), IE = Scavenged.end(); I != IE; ++I) if (I->FrameIndex >= 0) A.push_back(I->FrameIndex); diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 7cff27e..371ac6c 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -90,11 +90,6 @@ namespace llvm { /// the value of the Latency field of the predecessor, however advanced /// models may provide additional information about specific edges. unsigned Latency; - /// Record MinLatency seperately from "expected" Latency. - /// - /// FIXME: this field is not packed on LP64. Convert to 16-bit DAG edge - /// latency after introducing saturating truncation. - unsigned MinLatency; public: /// SDep - Construct a null SDep. This is only for use by container @@ -120,10 +115,9 @@ namespace llvm { Latency = 1; break; } - MinLatency = Latency; } SDep(SUnit *S, OrderKind kind) - : Dep(S, Order), Contents(), Latency(0), MinLatency(0) { + : Dep(S, Order), Contents(), Latency(0) { Contents.OrdKind = kind; } @@ -142,8 +136,7 @@ namespace llvm { } bool operator==(const SDep &Other) const { - return overlaps(Other) - && Latency == Other.Latency && MinLatency == Other.MinLatency; + return overlaps(Other) && Latency == Other.Latency; } bool operator!=(const SDep &Other) const { @@ -163,18 +156,6 @@ namespace llvm { Latency = Lat; } - /// getMinLatency - Return the minimum latency for this edge. Minimum - /// latency is used for scheduling groups, while normal (expected) latency - /// is for instruction cost and critical path. - unsigned getMinLatency() const { - return MinLatency; - } - - /// setMinLatency - Set the minimum latency for this edge. - void setMinLatency(unsigned Lat) { - MinLatency = Lat; - } - //// getSUnit - Return the SUnit to which this edge points. SUnit *getSUnit() const { return Dep.getPointer(); @@ -282,10 +263,10 @@ namespace llvm { SmallVector<SDep, 4> Preds; // All sunit predecessors. SmallVector<SDep, 4> Succs; // All sunit successors. - typedef SmallVector<SDep, 4>::iterator pred_iterator; - typedef SmallVector<SDep, 4>::iterator succ_iterator; - typedef SmallVector<SDep, 4>::const_iterator const_pred_iterator; - typedef SmallVector<SDep, 4>::const_iterator const_succ_iterator; + typedef SmallVectorImpl<SDep>::iterator pred_iterator; + typedef SmallVectorImpl<SDep>::iterator succ_iterator; + typedef SmallVectorImpl<SDep>::const_iterator const_pred_iterator; + typedef SmallVectorImpl<SDep>::const_iterator const_succ_iterator; unsigned NodeNum; // Entry # of node in the node vector. unsigned NodeQueueId; // Queue id of node. diff --git a/include/llvm/CodeGen/ScheduleDAGInstrs.h b/include/llvm/CodeGen/ScheduleDAGInstrs.h index 990cac6..9ab1013 100644 --- a/include/llvm/CodeGen/ScheduleDAGInstrs.h +++ b/include/llvm/CodeGen/ScheduleDAGInstrs.h @@ -158,7 +158,7 @@ namespace llvm { /// \brief Resolve and cache a resolved scheduling class for an SUnit. const MCSchedClassDesc *getSchedClass(SUnit *SU) const { - if (!SU->SchedClass) + if (!SU->SchedClass && SchedModel.hasInstrSchedModel()) SU->SchedClass = SchedModel.resolveSchedClass(SU->getInstr()); return SU->SchedClass; } diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index 487ab28..79e533e 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -72,7 +72,8 @@ private: class SDDbgInfo { SmallVector<SDDbgValue*, 32> DbgValues; SmallVector<SDDbgValue*, 32> ByvalParmDbgValues; - DenseMap<const SDNode*, SmallVector<SDDbgValue*, 2> > DbgValMap; + typedef DenseMap<const SDNode*, SmallVector<SDDbgValue*, 2> > DbgValMapType; + DbgValMapType DbgValMap; void operator=(const SDDbgInfo&) LLVM_DELETED_FUNCTION; SDDbgInfo(const SDDbgInfo&) LLVM_DELETED_FUNCTION; @@ -98,14 +99,13 @@ public: } ArrayRef<SDDbgValue*> getSDDbgValues(const SDNode *Node) { - DenseMap<const SDNode*, SmallVector<SDDbgValue*, 2> >::iterator I = - DbgValMap.find(Node); + DbgValMapType::iterator I = DbgValMap.find(Node); if (I != DbgValMap.end()) return I->second; return ArrayRef<SDDbgValue*>(); } - typedef SmallVector<SDDbgValue*,32>::iterator DbgIterator; + typedef SmallVectorImpl<SDDbgValue*>::iterator DbgIterator; DbgIterator DbgBegin() { return DbgValues.begin(); } DbgIterator DbgEnd() { return DbgValues.end(); } DbgIterator ByvalParmDbgBegin() { return ByvalParmDbgValues.begin(); } @@ -129,7 +129,6 @@ void checkForCycles(const SelectionDAG *DAG); /// class SelectionDAG { const TargetMachine &TM; - const TargetLowering &TLI; const TargetSelectionDAGInfo &TSI; const TargetTransformInfo *TTI; MachineFunction *MF; @@ -232,7 +231,9 @@ public: MachineFunction &getMachineFunction() const { return *MF; } const TargetMachine &getTarget() const { return TM; } - const TargetLowering &getTargetLoweringInfo() const { return TLI; } + const TargetLowering &getTargetLoweringInfo() const { + return *TM.getTargetLowering(); + } const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return TSI; } const TargetTransformInfo *getTargetTransformInfo() const { return TTI; } LLVMContext *getContext() const {return Context; } @@ -609,9 +610,23 @@ public: "Cannot compare scalars to vectors"); assert(LHS.getValueType().isVector() == VT.isVector() && "Cannot compare scalars to vectors"); + assert(Cond != ISD::SETCC_INVALID && + "Cannot create a setCC of an invalid node."); 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. + SDValue getSelect(SDLoc DL, EVT VT, SDValue Cond, + SDValue LHS, SDValue RHS) { + assert(LHS.getValueType() == RHS.getValueType() && + "Cannot use select on differing types"); + assert(VT.isVector() == LHS.getValueType().isVector() && + "Cannot mix vectors and scalars"); + return getNode(Cond.getValueType().isVector() ? ISD::VSELECT : ISD::SELECT, DL, VT, + Cond, LHS, RHS); + } + /// getSelectCC - Helper function to make it easier to build SelectCC's if you /// just have an ISD::CondCode instead of an SDValue. /// diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h index 37bbc1f..3d55d3a 100644 --- a/include/llvm/CodeGen/SelectionDAGISel.h +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -30,7 +30,6 @@ namespace llvm { class MachineInstr; class TargetLowering; class TargetLibraryInfo; - class TargetInstrInfo; class TargetTransformInfo; class FunctionLoweringInfo; class ScheduleHazardRecognizer; @@ -42,8 +41,7 @@ namespace llvm { /// pattern-matching instruction selectors. class SelectionDAGISel : public MachineFunctionPass { public: - const TargetMachine &TM; - const TargetLowering *TLI; + TargetMachine &TM; const TargetLibraryInfo *LibInfo; const TargetTransformInfo *TTI; FunctionLoweringInfo *FuncInfo; @@ -56,11 +54,13 @@ public: CodeGenOpt::Level OptLevel; static char ID; - explicit SelectionDAGISel(const TargetMachine &tm, + explicit SelectionDAGISel(TargetMachine &tm, CodeGenOpt::Level OL = CodeGenOpt::Default); virtual ~SelectionDAGISel(); - const TargetLowering *getTargetLowering() { return TLI; } + const TargetLowering *getTargetLowering() const { + return TM.getTargetLowering(); + } virtual void getAnalysisUsage(AnalysisUsage &AU) const; diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 0f45dc8..987f290 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -539,7 +539,7 @@ public: /// NOTE: This is still very expensive. Use carefully. bool hasPredecessorHelper(const SDNode *N, SmallPtrSet<const SDNode *, 32> &Visited, - SmallVector<const SDNode *, 16> &Worklist) const; + SmallVectorImpl<const SDNode *> &Worklist) const; /// getNumOperands - Return the number of values used by this operation. /// @@ -1181,7 +1181,8 @@ class ShuffleVectorSDNode : public SDNode { const int *Mask; protected: friend class SelectionDAG; - ShuffleVectorSDNode(EVT VT, unsigned Order, DebugLoc dl, SDValue N1, SDValue N2, const int *M) + ShuffleVectorSDNode(EVT VT, unsigned Order, DebugLoc dl, SDValue N1, + SDValue N2, const int *M) : SDNode(ISD::VECTOR_SHUFFLE, Order, dl, getSDVTList(VT)), Mask(M) { InitOperands(Ops, N1, N2); } @@ -1195,16 +1196,16 @@ public: assert(Idx < getValueType(0).getVectorNumElements() && "Idx out of range!"); return Mask[Idx]; } - + bool isSplat() const { return isSplatMask(Mask, getValueType(0)); } - int getSplatIndex() const { + int getSplatIndex() const { assert(isSplat() && "Cannot get splat index for non-splat!"); EVT VT = getValueType(0); for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) { - if (Mask[i] != -1) + if (Mask[i] >= 0) return Mask[i]; } - return -1; + llvm_unreachable("Splat with all undef indices?"); } static bool isSplatMask(const int *Mask, EVT VT); @@ -1212,7 +1213,7 @@ public: return N->getOpcode() == ISD::VECTOR_SHUFFLE; } }; - + class ConstantSDNode : public SDNode { const ConstantInt *Value; friend class SelectionDAG; diff --git a/include/llvm/CodeGen/SlotIndexes.h b/include/llvm/CodeGen/SlotIndexes.h index 676cdaf..984796a 100644 --- a/include/llvm/CodeGen/SlotIndexes.h +++ b/include/llvm/CodeGen/SlotIndexes.h @@ -59,7 +59,7 @@ namespace llvm { // poisoned, so that dangling SlotIndex access can be reliably detected. void setPoison() { intptr_t tmp = reinterpret_cast<intptr_t>(mi); - assert(((tmp & 0x1) == 0x0) && "Pointer already poisoned?"); + assert(((tmp & 0x1) == 0x0) && "Pointer already poisoned?"); tmp |= 0x1; mi = reinterpret_cast<MachineInstr*>(tmp); } @@ -218,6 +218,13 @@ namespace llvm { return other.getIndex() - getIndex(); } + /// Return the scaled distance from this index to the given one, where all + /// slots on the same instruction have zero distance. + int getInstrDistance(SlotIndex other) const { + return (other.listEntry()->getIndex() - listEntry()->getIndex()) + / Slot_Count; + } + /// isBlock - Returns true if this is a block boundary slot. bool isBlock() const { return getSlot() == Slot_Block; } @@ -672,7 +679,7 @@ namespace llvm { /// performance. Any remaining SlotIndex objects that point to the same /// index are left 'dangling' (much the same as a dangling pointer to a /// freed object) and should not be accessed, except to destruct them. - /// + /// /// Like dangling pointers, access to dangling SlotIndexes can cause /// painful-to-track-down bugs, especially if the memory for the index /// previously pointed to has been re-used. To detect dangling SlotIndex diff --git a/include/llvm/CodeGen/TargetSchedule.h b/include/llvm/CodeGen/TargetSchedule.h index 3e22252..f2adcf8 100644 --- a/include/llvm/CodeGen/TargetSchedule.h +++ b/include/llvm/CodeGen/TargetSchedule.h @@ -84,9 +84,6 @@ public: /// \brief Maximum number of micro-ops that may be scheduled per cycle. unsigned getIssueWidth() const { return SchedModel.IssueWidth; } - /// \brief Number of cycles the OOO processor is expected to hide. - unsigned getILPWindow() const { return SchedModel.ILPWindow; } - /// \brief Return the number of issue slots required for this MI. unsigned getNumMicroOps(const MachineInstr *MI, const MCSchedClassDesc *SC = 0) const; @@ -131,18 +128,23 @@ public: return ResourceLCM; } + /// \brief Number of micro-ops that may be buffered for OOO execution. + unsigned getMicroOpBufferSize() const { return SchedModel.MicroOpBufferSize; } + + /// \brief Number of resource units that may be buffered for OOO execution. + /// \return The buffer size in resource units or -1 for unlimited. + int getResourceBufferSize(unsigned PIdx) const { + return SchedModel.getProcResource(PIdx)->BufferSize; + } + /// \brief Compute operand latency based on the available machine model. /// - /// Computes and return the latency of the given data dependent def and use + /// Compute and return the latency of the given data dependent def and use /// when the operand indices are already known. UseMI may be NULL for an /// unknown user. - /// - /// FindMin may be set to get the minimum vs. expected latency. Minimum - /// latency is used for scheduling groups, while expected latency is for - /// instruction cost and critical path. unsigned computeOperandLatency(const MachineInstr *DefMI, unsigned DefOperIdx, - const MachineInstr *UseMI, unsigned UseOperIdx, - bool FindMin) const; + const MachineInstr *UseMI, unsigned UseOperIdx) + const; /// \brief Compute the instruction latency based on the available machine /// model. @@ -157,12 +159,6 @@ public: /// This is typically one cycle. unsigned computeOutputLatency(const MachineInstr *DefMI, unsigned DefIdx, const MachineInstr *DepMI) const; - -private: - /// getDefLatency is a helper for computeOperandLatency. Return the - /// instruction's latency if operand lookup is not required. - /// Otherwise return -1. - int getDefLatency(const MachineInstr *DefMI, bool FindMin) const; }; } // namespace llvm diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h index ec48b67..b7b3d73 100644 --- a/include/llvm/CodeGen/ValueTypes.h +++ b/include/llvm/CodeGen/ValueTypes.h @@ -343,6 +343,10 @@ namespace llvm { unsigned getSizeInBits() const { switch (SimpleTy) { + default: + llvm_unreachable("getSizeInBits called on extended MVT."); + case Other: + llvm_unreachable("Value type is non-standard value, Other."); case iPTR: llvm_unreachable("Value type size is target-dependent. Ask TLI."); case iPTRAny: @@ -352,8 +356,6 @@ namespace llvm { llvm_unreachable("Value type is overloaded."); case Metadata: llvm_unreachable("Value type is metadata."); - default: - llvm_unreachable("getSizeInBits called on extended MVT."); case i1 : return 1; case v2i1: return 2; case v4i1: return 4; diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index d27fcde..4b0aa4b 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -33,27 +33,6 @@ /* Define to 1 if you have the `arc4random' function. */ #cmakedefine HAVE_ARC4RANDOM -/* Define to 1 if you have the `argz_append' function. */ -#cmakedefine HAVE_ARGZ_APPEND ${HAVE_ARGZ_APPEND} - -/* Define to 1 if you have the `argz_create_sep' function. */ -#cmakedefine HAVE_ARGZ_CREATE_SEP ${HAVE_ARGZ_CREATE_SEP} - -/* Define to 1 if you have the <argz.h> header file. */ -#cmakedefine HAVE_ARGZ_H ${HAVE_ARGZ_H} - -/* Define to 1 if you have the `argz_insert' function. */ -#cmakedefine HAVE_ARGZ_INSERT ${HAVE_ARGZ_INSERT} - -/* Define to 1 if you have the `argz_next' function. */ -#cmakedefine HAVE_ARGZ_NEXT ${HAVE_ARGZ_NEXT} - -/* Define to 1 if you have the `argz_stringify' function. */ -#cmakedefine HAVE_ARGZ_STRINGIFY ${HAVE_ARGZ_STRINGIFY} - -/* Define to 1 if you have the <assert.h> header file. */ -#cmakedefine HAVE_ASSERT_H ${HAVE_ASSERT_H} - /* Define to 1 if you have the `backtrace' function. */ #cmakedefine HAVE_BACKTRACE ${HAVE_BACKTRACE} @@ -69,6 +48,12 @@ /* Define to 1 if you have the `closedir' function. */ #cmakedefine HAVE_CLOSEDIR ${HAVE_CLOSEDIR} +/* Define if curses provides the has_color() function on this platform. */ +#cmakedefine HAVE_CURSES + +/* Define to 1 if you have the <curses.h> header file. */ +#cmakedefine HAVE_CURSES_H + /* Define to 1 if you have the <cxxabi.h> header file. */ #cmakedefine HAVE_CXXABI_H ${HAVE_CXXABI_H} @@ -78,9 +63,6 @@ /* can use __crashreporter_info__ */ #undef HAVE_CRASHREPORTER_INFO -/* Define to 1 if you have the <ctype.h> header file. */ -#cmakedefine HAVE_CTYPE_H ${HAVE_CTYPE_H} - /* Define to 1 if you have the declaration of `strerror_s', and to 0 if you don't. */ #cmakedefine01 HAVE_DECL_STRERROR_S @@ -92,9 +74,6 @@ /* Define if you have the GNU dld library. */ #undef HAVE_DLD -/* Define to 1 if you have the <dld.h> header file. */ -#cmakedefine HAVE_DLD_H ${HAVE_DLD_H} - /* Define to 1 if you have the `dlerror' function. */ #cmakedefine HAVE_DLERROR ${HAVE_DLERROR} @@ -104,9 +83,6 @@ /* Define if dlopen() is available on this platform. */ #cmakedefine HAVE_DLOPEN ${HAVE_DLOPEN} -/* Define to 1 if you have the <dl.h> header file. */ -#cmakedefine HAVE_DL_H ${HAVE_DL_H} - /* Define if the dot program is available */ #cmakedefine HAVE_DOT ${HAVE_DOT} @@ -119,9 +95,6 @@ /* Define to 1 if you have the <errno.h> header file. */ #cmakedefine HAVE_ERRNO_H ${HAVE_ERRNO_H} -/* Define to 1 if the system has the type `error_t'. */ -#cmakedefine HAVE_ERROR_T ${HAVE_ERROR_T} - /* Define to 1 if you have the <execinfo.h> header file. */ #cmakedefine HAVE_EXECINFO_H ${HAVE_EXECINFO_H} @@ -170,6 +143,12 @@ /* Define to 1 if you have the `fmodf' function. */ #cmakedefine HAVE_FMODF ${HAVE_FMODF} +/* Define to 1 if you have the `futimes' function. */ +#cmakedefine HAVE_FUTIMES ${HAVE_FUTIMES} + +/* Define to 1 if you have the `futimens' function */ +#cmakedefine HAVE_FUTIMENS ${HAVE_FUTIMENS} + /* Define to 1 if you have the `getcwd' function. */ #cmakedefine HAVE_GETCWD ${HAVE_GETCWD} @@ -191,9 +170,6 @@ /* Define if the gv program is available */ #cmakedefine HAVE_GV ${HAVE_GV} -/* Define to 1 if you have the `index' function. */ -#cmakedefine HAVE_INDEX ${HAVE_INDEX} - /* Define to 1 if the system has the type `int64_t'. */ #cmakedefine HAVE_INT64_T ${HAVE_INT64_T} @@ -239,12 +215,9 @@ /* Define to 1 if you have the <limits.h> header file. */ #cmakedefine HAVE_LIMITS_H ${HAVE_LIMITS_H} -/* Define if you can use -Wl,-export-dynamic. */ +/* Define if you can use -rdynamic. */ #define HAVE_LINK_EXPORT_DYNAMIC 1 -/* Define to 1 if you have the <link.h> header file. */ -#cmakedefine HAVE_LINK_H ${HAVE_LINK_H} - /* Define if you can use -Wl,-R. to pass -R. to the linker, in order to add the current directory to the dynamic linker search path. */ #undef HAVE_LINK_R @@ -270,15 +243,6 @@ /* Define to 1 if you have the `malloc_zone_statistics' function. */ #cmakedefine HAVE_MALLOC_ZONE_STATISTICS ${HAVE_MALLOC_ZONE_STATISTICS} -/* Define to 1 if you have the `memcpy' function. */ -#cmakedefine HAVE_MEMCPY ${HAVE_MEMCPY} - -/* Define to 1 if you have the `memmove' function. */ -#cmakedefine HAVE_MEMMOVE ${HAVE_MEMMOVE} - -/* Define to 1 if you have the <memory.h> header file. */ -#cmakedefine HAVE_MEMORY_H ${HAVE_MEMORY_H} - /* Define to 1 if you have the `mkdtemp' function. */ #cmakedefine HAVE_MKDTEMP ${HAVE_MKDTEMP} @@ -298,6 +262,18 @@ /* Define if mmap() can map files into memory */ #undef HAVE_MMAP_FILE +/* Define to 1 if you have the <ncursesw/curses.h> header file. */ +#cmakedefine HAVE_NCURSESW_CURSES_H + +/* Define to 1 if you have the <ncursesw.h> header file. */ +#cmakedefine HAVE_NCURSESW_H + +/* Define to 1 if you have the <ncurses/curses.h> header file. */ +#cmakedefine HAVE_NCURSES_CURSES_H + +/* Define to 1 if you have the <ncurses.h> header file. */ +#cmakedefine HAVE_NCURSES_H + /* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */ #cmakedefine HAVE_NDIR_H ${HAVE_NDIR_H} @@ -346,9 +322,6 @@ /* Define to 1 if you have the `realpath' function. */ #undef HAVE_REALPATH -/* Define to 1 if you have the `rindex' function. */ -#cmakedefine HAVE_RINDEX ${HAVE_RINDEX} - /* Define to 1 if you have the `rintf' function. */ #undef HAVE_RINTF @@ -367,9 +340,6 @@ /* Define to 1 if you have the `setjmp' function. */ #cmakedefine HAVE_SETJMP ${HAVE_SETJMP} -/* Define to 1 if you have the <setjmp.h> header file. */ -#cmakedefine HAVE_SETJMP_H ${HAVE_SETJMP_H} - /* Define to 1 if you have the `setrlimit' function. */ #cmakedefine HAVE_SETRLIMIT ${HAVE_SETRLIMIT} @@ -388,24 +358,12 @@ /* Define to 1 if you have the <stdint.h> header file. */ #cmakedefine HAVE_STDINT_H ${HAVE_STDINT_H} -/* Define to 1 if you have the <stdio.h> header file. */ -#cmakedefine HAVE_STDIO_H ${HAVE_STDIO_H} - -/* Define to 1 if you have the <stdlib.h> header file. */ -#cmakedefine HAVE_STDLIB_H ${HAVE_STDLIB_H} - /* Set to 1 if the std::isinf function is found in <cmath> */ #undef HAVE_STD_ISINF_IN_CMATH /* Set to 1 if the std::isnan function is found in <cmath> */ #undef HAVE_STD_ISNAN_IN_CMATH -/* Define to 1 if you have the `strchr' function. */ -#cmakedefine HAVE_STRCHR ${HAVE_STRCHR} - -/* Define to 1 if you have the `strcmp' function. */ -#cmakedefine HAVE_STRCMP ${HAVE_STRCMP} - /* Define to 1 if you have the `strdup' function. */ #cmakedefine HAVE_STRDUP ${HAVE_STRDUP} @@ -415,15 +373,6 @@ /* Define to 1 if you have the `strerror_r' function. */ #cmakedefine HAVE_STRERROR_R ${HAVE_STRERROR_R} -/* Define to 1 if you have the <strings.h> header file. */ -#cmakedefine HAVE_STRINGS_H ${HAVE_STRINGS_H} - -/* Define to 1 if you have the <string.h> header file. */ -#cmakedefine HAVE_STRING_H ${HAVE_STRING_H} - -/* Define to 1 if you have the `strrchr' function. */ -#cmakedefine HAVE_STRRCHR ${HAVE_STRRCHR} - /* Define to 1 if you have the `strtof' function. */ #cmakedefine HAVE_STRTOF ${HAVE_STRTOF} @@ -440,9 +389,6 @@ */ #cmakedefine HAVE_SYS_DIR_H ${HAVE_SYS_DIR_H} -/* Define to 1 if you have the <sys/dl.h> header file. */ -#cmakedefine HAVE_SYS_DL_H ${HAVE_SYS_DL_H} - /* Define to 1 if you have the <sys/ioctl.h> header file. */ #cmakedefine HAVE_SYS_IOCTL_H ${HAVE_SYS_IOCTL_H} @@ -495,14 +441,11 @@ /* Define to 1 if you have the <valgrind/valgrind.h> header file. */ #cmakedefine HAVE_VALGRIND_VALGRIND_H ${HAVE_VALGRIND_VALGRIND_H} -/* Define to 1 if you have the <windows.h> header file. */ -#cmakedefine HAVE_WINDOWS_H ${HAVE_WINDOWS_H} - /* Define to 1 if you have the `writev' function. */ #cmakedefine HAVE_WRITEV ${HAVE_WRITEV} /* Define if the xdot.py program is available */ -#cmakedefine HAVE_XDOT_PY ${HAVE_XDOT_PY} +#cmakedefine HAVE_XDOT ${HAVE_XDOT} /* Define to 1 if you have the <zlib.h> header file. */ #cmakedefine HAVE_ZLIB_H ${HAVE_ZLIB_H} @@ -651,8 +594,8 @@ /* Define to path to twopi program if found or 'echo twopi' otherwise */ #cmakedefine LLVM_PATH_TWOPI "${LLVM_PATH_TWOPI}" -/* Define to path to xdot.py program if found or 'echo xdot.py' otherwise */ -#cmakedefine LLVM_PATH_XDOT_PY "${LLVM_PATH_XDOT_PY}" +/* Define to path to xdot.py program if found or 'echo xdot' otherwise */ +#cmakedefine LLVM_PATH_XDOT "${LLVM_PATH_XDOT}" /* Installation prefix directory */ #cmakedefine LLVM_PREFIX "${LLVM_PREFIX}" @@ -728,9 +671,6 @@ /* Define to empty if `const' does not conform to ANSI C. */ #undef const -/* Define to a type to use for `error_t' if it is not otherwise available. */ -#cmakedefine error_t ${error_t} - /* Define to `int' if <sys/types.h> does not define. */ #undef pid_t diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index c3860b6..7bb1caa 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -51,15 +51,9 @@ /* Define to 1 if you have the `argz_stringify' function. */ #undef HAVE_ARGZ_STRINGIFY -/* Define to 1 if you have the <assert.h> header file. */ -#undef HAVE_ASSERT_H - /* Define to 1 if you have the `backtrace' function. */ #undef HAVE_BACKTRACE -/* Define to 1 if you have the `bcopy' function. */ -#undef HAVE_BCOPY - /* Define to 1 if you have the `ceilf' function. */ #undef HAVE_CEILF @@ -75,8 +69,11 @@ /* can use __crashreporter_info__ */ #undef HAVE_CRASHREPORTER_INFO -/* Define to 1 if you have the <ctype.h> header file. */ -#undef HAVE_CTYPE_H +/* Define if curses provides the has_color() function on this platform. */ +#undef HAVE_CURSES + +/* Define to 1 if you have the <curses.h> header file. */ +#undef HAVE_CURSES_H /* Define to 1 if you have the <cxxabi.h> header file. */ #undef HAVE_CXXABI_H @@ -100,9 +97,6 @@ /* Define if you have the GNU dld library. */ #undef HAVE_DLD -/* Define to 1 if you have the <dld.h> header file. */ -#undef HAVE_DLD_H - /* Define to 1 if you have the `dlerror' function. */ #undef HAVE_DLERROR @@ -112,9 +106,6 @@ /* Define if dlopen() is available on this platform. */ #undef HAVE_DLOPEN -/* Define to 1 if you have the <dl.h> header file. */ -#undef HAVE_DL_H - /* Define if the dot program is available */ #undef HAVE_DOT @@ -166,6 +157,12 @@ /* Define to 1 if you have the `fmodf' function. */ #undef HAVE_FMODF +/* Define to 1 if you have the `futimens' function. */ +#undef HAVE_FUTIMENS + +/* Define to 1 if you have the `futimes' function. */ +#undef HAVE_FUTIMES + /* Define to 1 if you have the `getcwd' function. */ #undef HAVE_GETCWD @@ -187,9 +184,6 @@ /* Define if the gv program is available */ #undef HAVE_GV -/* Define to 1 if you have the `index' function. */ -#undef HAVE_INDEX - /* Define to 1 if the system has the type `int64_t'. */ #undef HAVE_INT64_T @@ -232,10 +226,7 @@ /* Define to 1 if you have the `z' library (-lz). */ #undef HAVE_LIBZ -/* Define to 1 if you have the <limits.h> header file. */ -#undef HAVE_LIMITS_H - -/* Define if you can use -Wl,-export-dynamic. */ +/* Define if you can use -rdynamic. */ #undef HAVE_LINK_EXPORT_DYNAMIC /* Define to 1 if you have the <link.h> header file. */ @@ -275,12 +266,6 @@ /* Define to 1 if you have the `malloc_zone_statistics' function. */ #undef HAVE_MALLOC_ZONE_STATISTICS -/* Define to 1 if you have the `memcpy' function. */ -#undef HAVE_MEMCPY - -/* Define to 1 if you have the `memmove' function. */ -#undef HAVE_MEMMOVE - /* Define to 1 if you have the <memory.h> header file. */ #undef HAVE_MEMORY_H @@ -303,6 +288,18 @@ /* Define if mmap() can map files into memory */ #undef HAVE_MMAP_FILE +/* Define to 1 if you have the <ncursesw/curses.h> header file. */ +#undef HAVE_NCURSESW_CURSES_H + +/* Define to 1 if you have the <ncursesw.h> header file. */ +#undef HAVE_NCURSESW_H + +/* Define to 1 if you have the <ncurses/curses.h> header file. */ +#undef HAVE_NCURSES_CURSES_H + +/* Define to 1 if you have the <ncurses.h> header file. */ +#undef HAVE_NCURSES_H + /* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */ #undef HAVE_NDIR_H @@ -351,9 +348,6 @@ /* Define to 1 if you have the `realpath' function. */ #undef HAVE_REALPATH -/* Define to 1 if you have the `rindex' function. */ -#undef HAVE_RINDEX - /* Define to 1 if you have the `rintf' function. */ #undef HAVE_RINTF @@ -393,9 +387,6 @@ /* Define to 1 if you have the <stdint.h> header file. */ #undef HAVE_STDINT_H -/* Define to 1 if you have the <stdio.h> header file. */ -#undef HAVE_STDIO_H - /* Define to 1 if you have the <stdlib.h> header file. */ #undef HAVE_STDLIB_H @@ -405,15 +396,6 @@ /* Set to 1 if the std::isnan function is found in <cmath> */ #undef HAVE_STD_ISNAN_IN_CMATH -/* Define to 1 if you have the `strchr' function. */ -#undef HAVE_STRCHR - -/* Define to 1 if you have the `strcmp' function. */ -#undef HAVE_STRCMP - -/* Define to 1 if you have the `strdup' function. */ -#undef HAVE_STRDUP - /* Define to 1 if you have the `strerror' function. */ #undef HAVE_STRERROR @@ -426,9 +408,6 @@ /* Define to 1 if you have the <string.h> header file. */ #undef HAVE_STRING_H -/* Define to 1 if you have the `strrchr' function. */ -#undef HAVE_STRRCHR - /* Define to 1 if you have the `strtof' function. */ #undef HAVE_STRTOF @@ -445,9 +424,6 @@ */ #undef HAVE_SYS_DIR_H -/* Define to 1 if you have the <sys/dl.h> header file. */ -#undef HAVE_SYS_DL_H - /* Define to 1 if you have the <sys/ioctl.h> header file. */ #undef HAVE_SYS_IOCTL_H @@ -500,14 +476,11 @@ /* Define to 1 if you have the <valgrind/valgrind.h> header file. */ #undef HAVE_VALGRIND_VALGRIND_H -/* Define to 1 if you have the <windows.h> header file. */ -#undef HAVE_WINDOWS_H - /* Define to 1 if you have the `writev' function. */ #undef HAVE_WRITEV -/* Define if the xdot.py program is available */ -#undef HAVE_XDOT_PY +/* Define if the xdot program is available */ +#undef HAVE_XDOT /* Define to 1 if you have the <zlib.h> header file. */ #undef HAVE_ZLIB_H @@ -656,8 +629,8 @@ /* Define to path to twopi program if found or 'echo twopi' otherwise */ #undef LLVM_PATH_TWOPI -/* Define to path to xdot.py program if found or 'echo xdot.py' otherwise */ -#undef LLVM_PATH_XDOT_PY +/* Define to path to xdot program if found or 'echo xdot' otherwise */ +#undef LLVM_PATH_XDOT /* Installation prefix directory */ #undef LLVM_PREFIX diff --git a/include/llvm/DIBuilder.h b/include/llvm/DIBuilder.h index 2440064..a15d619 100644 --- a/include/llvm/DIBuilder.h +++ b/include/llvm/DIBuilder.h @@ -29,6 +29,7 @@ namespace llvm { class MDNode; class StringRef; class DIBasicType; + class DICompileUnit; class DICompositeType; class DIDerivedType; class DIDescriptor; @@ -53,7 +54,6 @@ namespace llvm { private: Module &M; LLVMContext & VMContext; - MDNode *TheCU; MDNode *TempEnumTypes; MDNode *TempRetainTypes; @@ -70,12 +70,17 @@ namespace llvm { SmallVector<Value *, 4> AllGVs; SmallVector<Value *, 4> AllImportedModules; + DITemplateValueParameter + createTemplateValueParameter(unsigned Tag, DIDescriptor Scope, + StringRef Name, DIType Ty, Value *Val, + MDNode *File = 0, unsigned LineNo = 0, + unsigned ColumnNo = 0); + DIBuilder(const DIBuilder &) LLVM_DELETED_FUNCTION; void operator=(const DIBuilder &) LLVM_DELETED_FUNCTION; public: explicit DIBuilder(Module &M); - const MDNode *getCU() { return TheCU; } enum ComplexAddrKind { OpPlus=1, OpDeref }; /// finalize - Construct any deferred debug info descriptors. @@ -97,20 +102,24 @@ namespace llvm { /// Objective-C. /// @param SplitName The name of the file that we'll split debug info out /// into. - void createCompileUnit(unsigned Lang, StringRef File, StringRef Dir, - StringRef Producer, bool isOptimized, - StringRef Flags, unsigned RV, - StringRef SplitName = StringRef()); + DICompileUnit createCompileUnit(unsigned Lang, StringRef File, + StringRef Dir, StringRef Producer, + bool isOptimized, StringRef Flags, + unsigned RV, + StringRef SplitName = StringRef()); /// createFile - Create a file descriptor to hold debugging information /// for a file. DIFile createFile(StringRef Filename, StringRef Directory); /// createEnumerator - Create a single enumerator value. - DIEnumerator createEnumerator(StringRef Name, uint64_t Val); + DIEnumerator createEnumerator(StringRef Name, int64_t Val); + + /// \brief Create a DWARF unspecified type. + DIBasicType createUnspecifiedType(StringRef Name); - /// createNullPtrType - Create C++0x nullptr type. - DIBasicType createNullPtrType(StringRef Name); + /// \brief Create C++11 nullptr type. + DIBasicType createNullPtrType(); /// createBasicType - Create debugging information entry for a basic /// type. @@ -337,6 +346,32 @@ namespace llvm { DIType Ty, Value *Val, MDNode *File = 0, unsigned LineNo = 0, unsigned ColumnNo = 0); + /// \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. + /// @param File File where this type parameter is defined. + /// @param LineNo Line number. + /// @param ColumnNo Column Number. + DITemplateValueParameter + createTemplateTemplateParameter(DIDescriptor Scope, StringRef Name, + DIType Ty, StringRef Val, MDNode *File = 0, + unsigned LineNo = 0, unsigned ColumnNo = 0); + + /// \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. + /// @param File File where this type parameter is defined. + /// @param LineNo Line number. + /// @param ColumnNo Column Number. + DITemplateValueParameter + createTemplateParameterPack(DIDescriptor Scope, StringRef Name, + DIType Ty, DIArray Val, MDNode *File = 0, + unsigned LineNo = 0, unsigned ColumnNo = 0); + /// createArrayType - Create debugging information entry for an array. /// @param Size Array size. /// @param AlignInBits Alignment. diff --git a/include/llvm/DebugInfo.h b/include/llvm/DebugInfo.h index 61d0681..f7e6434 100644 --- a/include/llvm/DebugInfo.h +++ b/include/llvm/DebugInfo.h @@ -31,6 +31,7 @@ namespace llvm { class Type; class Value; class DbgDeclareInst; + class DbgValueInst; class Instruction; class MDNode; class NamedMDNode; @@ -63,7 +64,8 @@ namespace llvm { FlagObjcClassComplete = 1 << 9, FlagObjectPointer = 1 << 10, FlagVector = 1 << 11, - FlagStaticMember = 1 << 12 + FlagStaticMember = 1 << 12, + FlagIndirectVariable = 1 << 13 }; protected: const MDNode *DbgNode; @@ -87,20 +89,27 @@ namespace llvm { void replaceFunctionField(unsigned Elt, Function *F); public: - explicit DIDescriptor() : DbgNode(0) {} - explicit DIDescriptor(const MDNode *N) : DbgNode(N) {} - explicit DIDescriptor(const DIFile F); - explicit DIDescriptor(const DISubprogram F); - explicit DIDescriptor(const DILexicalBlockFile F); - explicit DIDescriptor(const DILexicalBlock F); - explicit DIDescriptor(const DIVariable F); - explicit DIDescriptor(const DIType F); + explicit DIDescriptor(const MDNode *N = 0) : DbgNode(N) {} bool Verify() const; operator MDNode *() const { return const_cast<MDNode*>(DbgNode); } MDNode *operator ->() const { return const_cast<MDNode*>(DbgNode); } + // 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. + LLVM_EXPLICIT operator bool() const { return DbgNode != 0; } + + bool operator==(DIDescriptor Other) const { + return DbgNode == Other.DbgNode; + } + bool operator!=(DIDescriptor Other) const { + return !operator==(Other); + } + unsigned getTag() const { return getUnsignedField(0) & ~LLVMDebugVersionMask; } @@ -120,7 +129,6 @@ namespace llvm { bool isSubrange() const; bool isEnumerator() const; bool isType() const; - bool isGlobal() const; bool isUnspecifiedParameter() const; bool isTemplateTypeParameter() const; bool isTemplateValueParameter() const; @@ -149,8 +157,7 @@ namespace llvm { /// DIArray - This descriptor holds an array of descriptors. class DIArray : public DIDescriptor { public: - explicit DIArray(const MDNode *N = 0) - : DIDescriptor(N) {} + explicit DIArray(const MDNode *N = 0) : DIDescriptor(N) {} unsigned getNumElements() const; DIDescriptor getElement(unsigned Idx) const { @@ -158,59 +165,6 @@ namespace llvm { } }; - /// DIScope - A base class for various scopes. - class DIScope : public DIDescriptor { - protected: - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DIScope(const MDNode *N = 0) : DIDescriptor (N) {} - - /// Set the filename by allocating a new string MDNode for - /// it and attaching it to the underlying node. - void setFilename(StringRef Name, LLVMContext &Context); - StringRef getFilename() const; - StringRef getDirectory() const; - }; - - /// DIFile - This is a wrapper for a file. - class DIFile : public DIScope { - friend class DIDescriptor; - public: - explicit DIFile(const MDNode *N = 0) : DIScope(N) { - if (DbgNode && !isFile()) - DbgNode = 0; - } - MDNode *getFileNode() const; - bool Verify() const; - }; - - /// DICompileUnit - A wrapper for a compile unit. - class DICompileUnit : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DICompileUnit(const MDNode *N = 0) : DIScope(N) {} - - unsigned getLanguage() const { return getUnsignedField(2); } - StringRef getProducer() const { return getStringField(3); } - - bool isOptimized() const { return getUnsignedField(4) != 0; } - StringRef getFlags() const { return getStringField(5); } - unsigned getRunTimeVersion() const { return getUnsignedField(6); } - - DIArray getEnumTypes() const; - DIArray getRetainedTypes() const; - DIArray getSubprograms() const; - DIArray getGlobalVariables() const; - DIArray getImportedEntities() const; - - StringRef getSplitDebugFilename() const { return getStringField(12); } - - /// Verify - Verify that a compile unit is well formed. - bool Verify() const; - }; - /// DIEnumerator - 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. @@ -221,10 +175,25 @@ namespace llvm { explicit DIEnumerator(const MDNode *N = 0) : DIDescriptor(N) {} StringRef getName() const { return getStringField(1); } - uint64_t getEnumValue() const { return getUInt64Field(2); } + int64_t getEnumValue() const { return getInt64Field(2); } bool Verify() const; }; + /// DIScope - A base class for various scopes. + class DIScope : public DIDescriptor { + protected: + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + public: + explicit DIScope(const MDNode *N = 0) : DIDescriptor (N) {} + + /// Gets the parent scope for this scope node or returns a + /// default constructed scope. + DIScope getContext() const; + StringRef getFilename() const; + StringRef getDirectory() const; + }; + /// DIType - 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. @@ -232,14 +201,12 @@ namespace llvm { protected: friend class DIDescriptor; void printInternal(raw_ostream &OS) const; - // This ctor is used when the Tag has already been validated by a derived - // ctor. - DIType(const MDNode *N, bool, bool) : DIScope(N) {} + public: + DIType(const MDNode *N = 0) : DIScope(N) {} + /// Verify - Verify that a type descriptor is well formed. bool Verify() const; - explicit DIType(const MDNode *N); - explicit DIType() {} DIScope getContext() const { return getFieldAs<DIScope>(2); } StringRef getName() const { return getStringField(3); } @@ -314,12 +281,9 @@ namespace llvm { class DIDerivedType : public DIType { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; - protected: - explicit DIDerivedType(const MDNode *N, bool, bool) - : DIType(N, true, true) {} + public: - explicit DIDerivedType(const MDNode *N = 0) - : DIType(N, true, true) {} + explicit DIDerivedType(const MDNode *N = 0) : DIType(N) {} DIType getTypeDerivedFrom() const { return getFieldAs<DIType>(9); } @@ -355,11 +319,7 @@ namespace llvm { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; public: - explicit DICompositeType(const MDNode *N = 0) - : DIDerivedType(N, true, true) { - if (N && !isCompositeType()) - DbgNode = 0; - } + explicit DICompositeType(const MDNode *N = 0) : DIDerivedType(N) {} DIArray getTypeArray() const { return getFieldAs<DIArray>(10); } void setTypeArray(DIArray Elements, DIArray TParams = DIArray()); @@ -374,42 +334,38 @@ namespace llvm { bool Verify() const; }; - /// DITemplateTypeParameter - This is a wrapper for template type parameter. - class DITemplateTypeParameter : public DIDescriptor { + /// DIFile - This is a wrapper for a file. + class DIFile : public DIScope { + friend class DIDescriptor; public: - explicit DITemplateTypeParameter(const MDNode *N = 0) : DIDescriptor(N) {} - - DIScope getContext() const { return getFieldAs<DIScope>(1); } - StringRef getName() const { return getStringField(2); } - DIType getType() const { return getFieldAs<DIType>(3); } - StringRef getFilename() const { - return getFieldAs<DIFile>(4).getFilename(); - } - StringRef getDirectory() const { - return getFieldAs<DIFile>(4).getDirectory(); - } - unsigned getLineNumber() const { return getUnsignedField(5); } - unsigned getColumnNumber() const { return getUnsignedField(6); } + explicit DIFile(const MDNode *N = 0) : DIScope(N) {} + MDNode *getFileNode() const; bool Verify() const; }; - /// DITemplateValueParameter - This is a wrapper for template value parameter. - class DITemplateValueParameter : public DIDescriptor { + /// DICompileUnit - A wrapper for a compile unit. + class DICompileUnit : public DIScope { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; public: - explicit DITemplateValueParameter(const MDNode *N = 0) : DIDescriptor(N) {} + explicit DICompileUnit(const MDNode *N = 0) : DIScope(N) {} - DIScope getContext() const { return getFieldAs<DIScope>(1); } - StringRef getName() const { return getStringField(2); } - DIType getType() const { return getFieldAs<DIType>(3); } - Value *getValue() const; - StringRef getFilename() const { - return getFieldAs<DIFile>(5).getFilename(); - } - StringRef getDirectory() const { - return getFieldAs<DIFile>(5).getDirectory(); - } - unsigned getLineNumber() const { return getUnsignedField(6); } - unsigned getColumnNumber() const { return getUnsignedField(7); } + unsigned getLanguage() const { return getUnsignedField(2); } + StringRef getProducer() const { return getStringField(3); } + + bool isOptimized() const { return getUnsignedField(4) != 0; } + StringRef getFlags() const { return getStringField(5); } + unsigned getRunTimeVersion() const { return getUnsignedField(6); } + + DIArray getEnumTypes() const; + DIArray getRetainedTypes() const; + DIArray getSubprograms() const; + DIArray getGlobalVariables() const; + DIArray getImportedEntities() const; + + StringRef getSplitDebugFilename() const { return getStringField(12); } + + /// Verify - Verify that a compile unit is well formed. bool Verify() const; }; @@ -489,6 +445,83 @@ namespace llvm { unsigned getScopeLineNumber() const { return getUnsignedField(19); } }; + /// DILexicalBlock - This is a wrapper for a lexical block. + class DILexicalBlock : public DIScope { + public: + explicit DILexicalBlock(const MDNode *N = 0) : DIScope(N) {} + DIScope getContext() const { return getFieldAs<DIScope>(2); } + unsigned getLineNumber() const { return getUnsignedField(3); } + unsigned getColumnNumber() const { return getUnsignedField(4); } + bool Verify() const; + }; + + /// DILexicalBlockFile - This is a wrapper for a lexical block with + /// a filename change. + class DILexicalBlockFile : public DIScope { + public: + explicit DILexicalBlockFile(const MDNode *N = 0) : DIScope(N) {} + DIScope getContext() const { + if (getScope().isSubprogram()) + return getScope(); + return getScope().getContext(); + } + unsigned getLineNumber() const { return getScope().getLineNumber(); } + unsigned getColumnNumber() const { return getScope().getColumnNumber(); } + DILexicalBlock getScope() const { return getFieldAs<DILexicalBlock>(2); } + bool Verify() const; + }; + + /// DINameSpace - A wrapper for a C++ style name space. + class DINameSpace : public DIScope { + friend class DIDescriptor; + void printInternal(raw_ostream &OS) const; + public: + explicit DINameSpace(const MDNode *N = 0) : DIScope(N) {} + DIScope getContext() const { return getFieldAs<DIScope>(2); } + StringRef getName() const { return getStringField(3); } + unsigned getLineNumber() const { return getUnsignedField(4); } + bool Verify() const; + }; + + /// DITemplateTypeParameter - This is a wrapper for template type parameter. + class DITemplateTypeParameter : public DIDescriptor { + public: + explicit DITemplateTypeParameter(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScope getContext() const { return getFieldAs<DIScope>(1); } + StringRef getName() const { return getStringField(2); } + DIType getType() const { return getFieldAs<DIType>(3); } + StringRef getFilename() const { + return getFieldAs<DIFile>(4).getFilename(); + } + StringRef getDirectory() const { + return getFieldAs<DIFile>(4).getDirectory(); + } + unsigned getLineNumber() const { return getUnsignedField(5); } + unsigned getColumnNumber() const { return getUnsignedField(6); } + bool Verify() const; + }; + + /// DITemplateValueParameter - This is a wrapper for template value parameter. + class DITemplateValueParameter : public DIDescriptor { + public: + explicit DITemplateValueParameter(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScope getContext() const { return getFieldAs<DIScope>(1); } + StringRef getName() const { return getStringField(2); } + DIType getType() const { return getFieldAs<DIType>(3); } + Value *getValue() const; + StringRef getFilename() const { + return getFieldAs<DIFile>(5).getFilename(); + } + StringRef getDirectory() const { + return getFieldAs<DIFile>(5).getDirectory(); + } + unsigned getLineNumber() const { return getUnsignedField(6); } + unsigned getColumnNumber() const { return getUnsignedField(7); } + bool Verify() const; + }; + /// DIGlobalVariable - This is a wrapper for a global variable. class DIGlobalVariable : public DIDescriptor { friend class DIDescriptor; @@ -529,8 +562,7 @@ namespace llvm { friend class DIDescriptor; void printInternal(raw_ostream &OS) const; public: - explicit DIVariable(const MDNode *N = 0) - : DIDescriptor(N) {} + explicit DIVariable(const MDNode *N = 0) : DIDescriptor(N) {} DIScope getContext() const { return getFieldAs<DIScope>(1); } StringRef getName() const { return getStringField(2); } @@ -553,6 +585,11 @@ namespace llvm { return (getUnsignedField(6) & FlagObjectPointer) != 0; } + /// \brief Return true if this variable is represented as a pointer. + bool isIndirect() const { + return (getUnsignedField(6) & FlagIndirectVariable) != 0; + } + /// getInlinedAt - If this variable is inlined then return inline location. MDNode *getInlinedAt() const; @@ -583,40 +620,6 @@ namespace llvm { void printExtendedName(raw_ostream &OS) const; }; - /// DILexicalBlock - This is a wrapper for a lexical block. - class DILexicalBlock : public DIScope { - public: - explicit DILexicalBlock(const MDNode *N = 0) : DIScope(N) {} - DIScope getContext() const { return getFieldAs<DIScope>(2); } - unsigned getLineNumber() const { return getUnsignedField(3); } - unsigned getColumnNumber() const { return getUnsignedField(4); } - bool Verify() const; - }; - - /// DILexicalBlockFile - This is a wrapper for a lexical block with - /// a filename change. - class DILexicalBlockFile : public DIScope { - public: - explicit DILexicalBlockFile(const MDNode *N = 0) : DIScope(N) {} - DIScope getContext() const { if (getScope().isSubprogram()) return getScope(); return getScope().getContext(); } - unsigned getLineNumber() const { return getScope().getLineNumber(); } - unsigned getColumnNumber() const { return getScope().getColumnNumber(); } - DILexicalBlock getScope() const { return getFieldAs<DILexicalBlock>(2); } - bool Verify() const; - }; - - /// DINameSpace - A wrapper for a C++ style name space. - class DINameSpace : public DIScope { - friend class DIDescriptor; - void printInternal(raw_ostream &OS) const; - public: - explicit DINameSpace(const MDNode *N = 0) : DIScope(N) {} - DIScope getContext() const { return getFieldAs<DIScope>(2); } - StringRef getName() const { return getStringField(3); } - unsigned getLineNumber() const { return getUnsignedField(4); } - bool Verify() const; - }; - /// DILocation - This object holds location information. This object /// is not associated with any DWARF tag. class DILocation : public DIDescriptor { @@ -714,12 +717,27 @@ namespace llvm { /// cleanseInlinedVariable - Remove inlined scope from the variable. DIVariable cleanseInlinedVariable(MDNode *DV, LLVMContext &VMContext); + /// DebugInfoFinder tries to list all debug info MDNodes used in a module. To + /// list debug info MDNodes used by an instruction, DebugInfoFinder uses + /// processDeclare, processValue and processLocation to handle DbgDeclareInst, + /// DbgValueInst and DbgLoc attached to instructions. processModule will go + /// through all DICompileUnits in llvm.dbg.cu and list debug info MDNodes + /// used by the CUs. class DebugInfoFinder { public: /// processModule - Process entire module and collect debug info /// anchors. void processModule(const Module &M); + /// processDeclare - Process DbgDeclareInst. + void processDeclare(const DbgDeclareInst *DDI); + /// Process DbgValueInst. + void processValue(const DbgValueInst *DVI); + /// processLocation - Process DILocation. + void processLocation(DILocation Loc); + + /// Clear all lists. + void reset(); private: /// processType - Process DIType. void processType(DIType DT); @@ -730,11 +748,7 @@ namespace llvm { /// processSubprogram - Process DISubprogram. void processSubprogram(DISubprogram SP); - /// processDeclare - Process DbgDeclareInst. - void processDeclare(const DbgDeclareInst *DDI); - - /// processLocation - Process DILocation. - void processLocation(DILocation Loc); + void processScope(DIScope Scope); /// addCompileUnit - Add compile unit into CUs. bool addCompileUnit(DICompileUnit CU); @@ -748,8 +762,10 @@ namespace llvm { /// addType - Add type into Tys. bool addType(DIType DT); + bool addScope(DIScope Scope); + public: - typedef SmallVector<MDNode *, 8>::const_iterator iterator; + typedef SmallVectorImpl<MDNode *>::const_iterator iterator; iterator compile_unit_begin() const { return CUs.begin(); } iterator compile_unit_end() const { return CUs.end(); } iterator subprogram_begin() const { return SPs.begin(); } @@ -758,17 +774,21 @@ namespace llvm { iterator global_variable_end() const { return GVs.end(); } iterator type_begin() const { return TYs.begin(); } iterator type_end() const { return TYs.end(); } + iterator scope_begin() const { return Scopes.begin(); } + iterator scope_end() const { return Scopes.end(); } unsigned compile_unit_count() const { return CUs.size(); } unsigned global_variable_count() const { return GVs.size(); } unsigned subprogram_count() const { return SPs.size(); } unsigned type_count() const { return TYs.size(); } + unsigned scope_count() const { return Scopes.size(); } private: SmallVector<MDNode *, 8> CUs; // Compile Units SmallVector<MDNode *, 8> SPs; // Subprograms SmallVector<MDNode *, 8> GVs; // Global Variables; SmallVector<MDNode *, 8> TYs; // Types + SmallVector<MDNode *, 8> Scopes; // Scopes SmallPtrSet<MDNode *, 64> NodesSeen; }; } // end namespace llvm diff --git a/include/llvm/DebugInfo/DIContext.h b/include/llvm/DebugInfo/DIContext.h index 8fcd9e0..4bb7c77 100644 --- a/include/llvm/DebugInfo/DIContext.h +++ b/include/llvm/DebugInfo/DIContext.h @@ -21,6 +21,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Object/RelocVisitor.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/DataTypes.h" namespace llvm { @@ -105,6 +106,7 @@ enum DIDumpType { DIDT_Info, DIDT_InfoDwo, DIDT_Line, + DIDT_Loc, DIDT_Ranges, DIDT_Pubnames, DIDT_Str, @@ -121,6 +123,12 @@ typedef DenseMap<uint64_t, std::pair<uint8_t, int64_t> > RelocAddrMap; class DIContext { public: + enum DIContextKind { + CK_DWARF + }; + DIContextKind getKind() const { return Kind; } + + DIContext(DIContextKind K) : Kind(K) {} virtual ~DIContext(); /// getDWARFContext - get a context for binary DWARF data. @@ -134,6 +142,8 @@ public: uint64_t Size, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; virtual DIInliningInfo getInliningInfoForAddress(uint64_t Address, DILineInfoSpecifier Specifier = DILineInfoSpecifier()) = 0; +private: + const DIContextKind Kind; }; } diff --git a/include/llvm/ExecutionEngine/ObjectCache.h b/include/llvm/ExecutionEngine/ObjectCache.h index 0bee861..aa200fb 100644 --- a/include/llvm/ExecutionEngine/ObjectCache.h +++ b/include/llvm/ExecutionEngine/ObjectCache.h @@ -30,23 +30,9 @@ public: /// getObjectCopy - Returns a pointer to a newly allocated MemoryBuffer that /// contains the object which corresponds with Module M, or 0 if an object is - /// not available. The caller owns the MemoryBuffer returned by this function. - MemoryBuffer* getObjectCopy(const Module* M) { - const MemoryBuffer* Obj = getObject(M); - if (Obj) - return MemoryBuffer::getMemBufferCopy(Obj->getBuffer()); - else - return 0; - } - -protected: - /// getObject - Returns a pointer to a MemoryBuffer that contains an object - /// that corresponds with Module M, or 0 if an object is not available. - /// The pointer returned by this function is not suitable for loading because - /// the memory is read-only and owned by the ObjectCache. To retrieve an - /// owning pointer to a MemoryBuffer (which is suitable for calling - /// RuntimeDyld::loadObject() with) use getObjectCopy() instead. - virtual const MemoryBuffer* getObject(const Module* M) = 0; + /// not available. The caller owns both the MemoryBuffer returned by this + /// and the memory it references. + virtual MemoryBuffer* getObject(const Module* M) = 0; }; } diff --git a/include/llvm/IR/Argument.h b/include/llvm/IR/Argument.h index 40d61ff..eb6ed46 100644 --- a/include/llvm/IR/Argument.h +++ b/include/llvm/IR/Argument.h @@ -82,6 +82,11 @@ public: /// its containing function. bool hasReturnedAttr() const; + /// \brief Return true if this argument has the readonly or readnone attribute + /// on it in its containing function. + bool onlyReadsMemory() const; + + /// \brief Add a Attribute to an argument. void addAttr(AttributeSet AS); diff --git a/include/llvm/IR/Attributes.h b/include/llvm/IR/Attributes.h index 0d14709..2183758 100644 --- a/include/llvm/IR/Attributes.h +++ b/include/llvm/IR/Attributes.h @@ -67,6 +67,8 @@ public: ///< stored as log2 of alignment with +1 bias ///< 0 means unaligned (different from align(1)) AlwaysInline, ///< inline=always + Builtin, ///< Callee is recognized as a builtin, despite + ///< nobuiltin attribute on its declaration. ByVal, ///< Pass structure by value Cold, ///< Marks function as being in a cold path. InlineHint, ///< Source said inlining was desirable @@ -248,6 +250,8 @@ public: /// attribute sets are immutable, this returns a new set. AttributeSet addAttribute(LLVMContext &C, unsigned Index, StringRef Kind) const; + AttributeSet addAttribute(LLVMContext &C, unsigned Index, + StringRef Kind, StringRef Value) const; /// \brief Add attributes to the attribute set at the given index. Since /// attribute sets are immutable, this returns a new set. diff --git a/include/llvm/IR/CallingConv.h b/include/llvm/IR/CallingConv.h index 6f3ab20..585fc5e 100644 --- a/include/llvm/IR/CallingConv.h +++ b/include/llvm/IR/CallingConv.h @@ -93,13 +93,6 @@ namespace CallingConv { /// Passes all arguments in register or parameter space. PTX_Device = 72, - /// MBLAZE_INTR - Calling convention used for MBlaze interrupt routines. - MBLAZE_INTR = 73, - - /// MBLAZE_INTR - Calling convention used for MBlaze interrupt support - /// routines (i.e. GCC's save_volatiles attribute). - MBLAZE_SVOL = 74, - /// SPIR_FUNC - Calling convention for SPIR non-kernel device functions. /// No lowering or expansion of arguments. /// Structures are passed as a pointer to a struct with the byval attribute. @@ -119,8 +112,17 @@ namespace CallingConv { SPIR_KERNEL = 76, /// Intel_OCL_BI - Calling conventions for Intel OpenCL built-ins - Intel_OCL_BI = 77 + Intel_OCL_BI = 77, + + /// \brief The C convention as specified in the x86-64 supplement to the + /// System V ABI, used on most non-Windows systems. + X86_64_SysV = 78, + /// \brief The C convention as implemented on Windows/x86-64. This + /// convention differs from the more common \c X86_64_SysV convention + /// in a number of ways, most notably in that XMM registers used to pass + /// arguments are shadowed by GPRs, and vice versa. + X86_64_Win64 = 79 }; } // End CallingConv namespace diff --git a/include/llvm/IR/Constants.h b/include/llvm/IR/Constants.h index 2f29f54..99aed0d 100644 --- a/include/llvm/IR/Constants.h +++ b/include/llvm/IR/Constants.h @@ -112,7 +112,6 @@ public: /// Return the constant as a 64-bit unsigned integer value after it /// has been zero extended as appropriate for the type of this constant. Note /// that this method can assert if the value does not fit in 64 bits. - /// @deprecated /// @brief Return the zero extended value. inline uint64_t getZExtValue() const { return Val.getZExtValue(); @@ -121,7 +120,6 @@ public: /// Return the constant as a 64-bit integer value after it has been sign /// extended as appropriate for the type of this constant. Note that /// this method can assert if the value does not fit in 64 bits. - /// @deprecated /// @brief Return the sign extended value. inline int64_t getSExtValue() const { return Val.getSExtValue(); diff --git a/include/llvm/IR/DataLayout.h b/include/llvm/IR/DataLayout.h index b0def6b..269edeb 100644 --- a/include/llvm/IR/DataLayout.h +++ b/include/llvm/IR/DataLayout.h @@ -237,13 +237,14 @@ public: /// Layout pointer alignment /// FIXME: The defaults need to be removed once all of /// the backends/clients are updated. - unsigned getPointerABIAlignment(unsigned AS = 0) const { + unsigned getPointerABIAlignment(unsigned AS = 0) const { DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS); if (val == Pointers.end()) { val = Pointers.find(0); } return val->second.ABIAlign; } + /// Return target's alignment for stack-based pointers /// FIXME: The defaults need to be removed once all of /// the backends/clients are updated. @@ -257,7 +258,7 @@ public: /// Layout pointer size /// FIXME: The defaults need to be removed once all of /// the backends/clients are updated. - unsigned getPointerSize(unsigned AS = 0) const { + unsigned getPointerSize(unsigned AS = 0) const { DenseMap<unsigned, PointerAlignElem>::const_iterator val = Pointers.find(AS); if (val == Pointers.end()) { val = Pointers.find(0); @@ -267,9 +268,21 @@ public: /// Layout pointer size, in bits /// FIXME: The defaults need to be removed once all of /// the backends/clients are updated. - unsigned getPointerSizeInBits(unsigned AS = 0) const { + unsigned getPointerSizeInBits(unsigned AS = 0) const { return getPointerSize(AS) * 8; } + + /// Layout pointer size, in bits, based on the type. If this function is + /// called with a pointer type, then the type size of the pointer is returned. + /// If this function is called with a vector of pointers, then the type size + /// of the pointer is returned. This should only be called with a pointer or + /// vector of pointers. + unsigned getPointerTypeSizeInBits(Type *) const; + + unsigned getPointerTypeSize(Type *Ty) const { + return getPointerTypeSizeInBits(Ty) / 8; + } + /// Size examples: /// /// Type SizeInBits StoreSizeInBits AllocSizeInBits[*] diff --git a/include/llvm/IR/Function.h b/include/llvm/IR/Function.h index f97929f..0e51c6f 100644 --- a/include/llvm/IR/Function.h +++ b/include/llvm/IR/Function.h @@ -166,30 +166,37 @@ public: (static_cast<unsigned>(CC) << 1)); } - /// getAttributes - Return the attribute list for this Function. - /// + /// @brief Return the attribute list for this Function. AttributeSet getAttributes() const { return AttributeSets; } - /// setAttributes - Set the attribute list for this Function. - /// + /// @brief Set the attribute list for this Function. void setAttributes(AttributeSet attrs) { AttributeSets = attrs; } - /// addFnAttr - Add function attributes to this function. - /// + /// @brief Add function attributes to this function. void addFnAttr(Attribute::AttrKind N) { setAttributes(AttributeSets.addAttribute(getContext(), AttributeSet::FunctionIndex, N)); } - /// addFnAttr - Add function attributes to this function. - /// + /// @brief Remove function attributes from this function. + void removeFnAttr(Attribute::AttrKind N) { + setAttributes(AttributeSets.removeAttribute( + getContext(), AttributeSet::FunctionIndex, N)); + } + + /// @brief Add function attributes to this function. void addFnAttr(StringRef Kind) { setAttributes( AttributeSets.addAttribute(getContext(), AttributeSet::FunctionIndex, Kind)); } + void addFnAttr(StringRef Kind, StringRef Value) { + setAttributes( + AttributeSets.addAttribute(getContext(), + AttributeSet::FunctionIndex, Kind, Value)); + } - /// \brief Return true if the function has the attribute. + /// @brief Return true if the function has the attribute. bool hasFnAttribute(Attribute::AttrKind Kind) const { return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind); } @@ -197,6 +204,14 @@ public: return AttributeSets.hasAttribute(AttributeSet::FunctionIndex, Kind); } + /// @brief Return the attribute for the given attribute kind. + Attribute getFnAttribute(Attribute::AttrKind Kind) const { + return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind); + } + Attribute getFnAttribute(StringRef Kind) const { + return AttributeSets.getAttribute(AttributeSet::FunctionIndex, Kind); + } + /// hasGC/getGC/setGC/clearGC - The name of the garbage collection algorithm /// to use during code generation. bool hasGC() const; @@ -303,6 +318,21 @@ public: addAttribute(n, Attribute::NoCapture); } + bool doesNotAccessMemory(unsigned n) const { + return AttributeSets.hasAttribute(n, Attribute::ReadNone); + } + void setDoesNotAccessMemory(unsigned n) { + addAttribute(n, Attribute::ReadNone); + } + + bool onlyReadsMemory(unsigned n) const { + return doesNotAccessMemory(n) || + AttributeSets.hasAttribute(n, Attribute::ReadOnly); + } + void setOnlyReadsMemory(unsigned n) { + addAttribute(n, Attribute::ReadOnly); + } + /// copyAttributesFrom - copy all additional attributes (those not needed to /// create a Function) from the Function Src to this one. void copyAttributesFrom(const GlobalValue *Src); diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index f11d3b4..e396e71 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -49,10 +49,6 @@ protected: class IRBuilderBase { DebugLoc CurDbgLocation; protected: - /// Save the current debug location here while we are suppressing - /// line table entries. - llvm::DebugLoc SavedDbgLocation; - BasicBlock *BB; BasicBlock::iterator InsertPt; LLVMContext &Context; @@ -71,6 +67,7 @@ public: /// inserted into a block. void ClearInsertionPoint() { BB = 0; + InsertPt = 0; } BasicBlock *GetInsertBlock() const { return BB; } @@ -89,6 +86,7 @@ public: void SetInsertPoint(Instruction *I) { BB = I->getParent(); InsertPt = I; + assert(I != BB->end() && "Can't read debug loc from end()"); SetCurrentDebugLocation(I->getDebugLoc()); } @@ -117,23 +115,6 @@ public: CurDbgLocation = L; } - /// \brief Temporarily suppress DebugLocations from being attached - /// to emitted instructions, until the next call to - /// SetCurrentDebugLocation() or EnableDebugLocations(). Use this - /// if you want an instruction to be counted towards the prologue or - /// if there is no useful source location. - void DisableDebugLocations() { - llvm::DebugLoc Empty; - SavedDbgLocation = getCurrentDebugLocation(); - SetCurrentDebugLocation(Empty); - } - - /// \brief Restore the previously saved DebugLocation. - void EnableDebugLocations() { - assert(CurDbgLocation.isUnknown()); - SetCurrentDebugLocation(SavedDbgLocation); - } - /// \brief Get location information used by debugging information. DebugLoc getCurrentDebugLocation() const { return CurDbgLocation; } @@ -290,7 +271,7 @@ public: } /// \brief Fetch the type representing a pointer to an integer value. - IntegerType* getIntPtrTy(DataLayout *DL, unsigned AddrSpace = 0) { + IntegerType* getIntPtrTy(const DataLayout *DL, unsigned AddrSpace = 0) { return DL->getIntPtrType(Context, AddrSpace); } diff --git a/include/llvm/IR/InstrTypes.h b/include/llvm/IR/InstrTypes.h index f50c28a..e12bb03 100644 --- a/include/llvm/IR/InstrTypes.h +++ b/include/llvm/IR/InstrTypes.h @@ -531,6 +531,12 @@ public: Type *DestTy ///< The Type to which the value should be cast. ); + /// @brief Check whether a bitcast between these types is valid + static bool isBitCastable( + Type *SrcTy, ///< The Type from which the value should be cast. + Type *DestTy ///< The Type to which the value should be cast. + ); + /// Returns the opcode necessary to cast Val into Ty using usual casting /// rules. /// @brief Infer the opcode for cast operand and type @@ -698,7 +704,7 @@ public: /// @brief Create a CmpInst static CmpInst *Create(OtherOps Op, unsigned short predicate, Value *S1, Value *S2, const Twine &Name, BasicBlock *InsertAtEnd); - + /// @brief Get the opcode casted to the right type OtherOps getOpcode() const { return static_cast<OtherOps>(Instruction::getOpcode()); @@ -715,15 +721,15 @@ public: static bool isFPPredicate(Predicate P) { return P >= FIRST_FCMP_PREDICATE && P <= LAST_FCMP_PREDICATE; } - + static bool isIntPredicate(Predicate P) { return P >= FIRST_ICMP_PREDICATE && P <= LAST_ICMP_PREDICATE; } - + bool isFPPredicate() const { return isFPPredicate(getPredicate()); } bool isIntPredicate() const { return isIntPredicate(getPredicate()); } - - + + /// For example, EQ -> NE, UGT -> ULE, SLT -> SGE, /// OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc. /// @returns the inverse predicate for the instruction's current predicate. @@ -821,7 +827,7 @@ public: static inline bool classof(const Value *V) { return isa<Instruction>(V) && classof(cast<Instruction>(V)); } - + /// @brief Create a result type for fcmp/icmp static Type* makeCmpResultType(Type* opnd_type) { if (VectorType* vt = dyn_cast<VectorType>(opnd_type)) { diff --git a/include/llvm/IR/Instructions.h b/include/llvm/IR/Instructions.h index 7e29699..e05c3a8 100644 --- a/include/llvm/IR/Instructions.h +++ b/include/llvm/IR/Instructions.h @@ -1278,7 +1278,11 @@ public: void removeAttribute(unsigned i, Attribute attr); /// \brief Determine whether this call has the given attribute. - bool hasFnAttr(Attribute::AttrKind A) const; + bool hasFnAttr(Attribute::AttrKind A) const { + assert(A != Attribute::NoBuiltin && + "Use CallInst::isNoBuiltin() to check for Attribute::NoBuiltin"); + return hasFnAttrImpl(A); + } /// \brief Determine whether the call or the callee has the given attributes. bool paramHasAttr(unsigned i, Attribute::AttrKind A) const; @@ -1288,6 +1292,13 @@ public: return AttributeList.getParamAlignment(i); } + /// \brief Return true if the call should not be treated as a call to a + /// builtin. + bool isNoBuiltin() const { + return hasFnAttrImpl(Attribute::NoBuiltin) && + !hasFnAttrImpl(Attribute::Builtin); + } + /// \brief Return true if the call should not be inlined. bool isNoInline() const { return hasFnAttr(Attribute::NoInline); } void setIsNoInline() { @@ -1378,6 +1389,9 @@ public: return isa<Instruction>(V) && classof(cast<Instruction>(V)); } private: + + bool hasFnAttrImpl(Attribute::AttrKind A) const; + // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. void setInstructionSubclassData(unsigned short D) { @@ -2609,7 +2623,6 @@ public: } /// addCase - Add an entry to the switch instruction... - /// @deprecated /// Note: /// This action invalidates case_end(). Old case_end() iterator will /// point to the added case. @@ -2695,7 +2708,6 @@ public: } /// Resolves case value for current case. - /// @deprecated ConstantIntTy *getCaseValue() { assert(Index < SI->getNumCases() && "Index out the number of cases."); IntegersSubsetRef CaseRanges = *SubsetIt; @@ -2799,7 +2811,6 @@ public: CaseIt(const ParentTy& Src) : ParentTy(Src) {} /// Sets the new value for current case. - /// @deprecated. void setValue(ConstantInt *V) { assert(Index < SI->getNumCases() && "Index out the number of cases."); IntegersSubsetToBB Mapping; @@ -3024,7 +3035,11 @@ public: void removeAttribute(unsigned i, Attribute attr); /// \brief Determine whether this call has the NoAlias attribute. - bool hasFnAttr(Attribute::AttrKind A) const; + bool hasFnAttr(Attribute::AttrKind A) const { + assert(A != Attribute::NoBuiltin && + "Use CallInst::isNoBuiltin() to check for Attribute::NoBuiltin"); + return hasFnAttrImpl(A); + } /// \brief Determine whether the call or the callee has the given attributes. bool paramHasAttr(unsigned i, Attribute::AttrKind A) const; @@ -3034,6 +3049,15 @@ public: return AttributeList.getParamAlignment(i); } + /// \brief Return true if the call should not be treated as a call to a + /// builtin. + bool isNoBuiltin() const { + // We assert in hasFnAttr if one passes in Attribute::NoBuiltin, so we have + // to check it by hand. + return hasFnAttrImpl(Attribute::NoBuiltin) && + !hasFnAttrImpl(Attribute::Builtin); + } + /// \brief Return true if the call should not be inlined. bool isNoInline() const { return hasFnAttr(Attribute::NoInline); } void setIsNoInline() { @@ -3140,6 +3164,8 @@ private: virtual unsigned getNumSuccessorsV() const; virtual void setSuccessorV(unsigned idx, BasicBlock *B); + bool hasFnAttrImpl(Attribute::AttrKind A) const; + // Shadow Instruction::setInstructionSubclassData with a private forwarding // method so that subclasses cannot accidentally use it. void setInstructionSubclassData(unsigned short D) { diff --git a/include/llvm/IR/Intrinsics.td b/include/llvm/IR/Intrinsics.td index e252664..1a849c4 100644 --- a/include/llvm/IR/Intrinsics.td +++ b/include/llvm/IR/Intrinsics.td @@ -55,6 +55,18 @@ class NoCapture<int argNo> : IntrinsicProperty { int ArgNo = argNo; } +// ReadOnly - The specified argument pointer is not written to through the +// pointer by the intrinsic. +class ReadOnly<int argNo> : IntrinsicProperty { + int ArgNo = argNo; +} + +// ReadNone - The specified argument pointer is not dereferenced by the +// intrinsic. +class ReadNone<int argNo> : IntrinsicProperty { + int ArgNo = argNo; +} + def IntrNoReturn : IntrinsicProperty; //===----------------------------------------------------------------------===// @@ -253,11 +265,13 @@ def int_stackprotector : Intrinsic<[], [llvm_ptr_ty, llvm_ptrptr_ty], []>; def int_memcpy : Intrinsic<[], [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i32_ty, llvm_i1_ty], - [IntrReadWriteArgMem, NoCapture<0>, NoCapture<1>]>; + [IntrReadWriteArgMem, NoCapture<0>, NoCapture<1>, + ReadOnly<1>]>; def int_memmove : Intrinsic<[], [llvm_anyptr_ty, llvm_anyptr_ty, llvm_anyint_ty, llvm_i32_ty, llvm_i1_ty], - [IntrReadWriteArgMem, NoCapture<0>, NoCapture<1>]>; + [IntrReadWriteArgMem, NoCapture<0>, NoCapture<1>, + ReadOnly<1>]>; def int_memset : Intrinsic<[], [llvm_anyptr_ty, llvm_i8_ty, llvm_anyint_ty, llvm_i32_ty, llvm_i1_ty], @@ -347,6 +361,9 @@ def int_eh_typeid_for : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty], [IntrNoMem]>; def int_eh_return_i32 : Intrinsic<[], [llvm_i32_ty, llvm_ptr_ty]>; def int_eh_return_i64 : Intrinsic<[], [llvm_i64_ty, 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. def int_eh_unwind_init: Intrinsic<[]>, GCCBuiltin<"__builtin_unwind_init">; @@ -477,6 +494,7 @@ def int_convertuu : Intrinsic<[llvm_anyint_ty], include "llvm/IR/IntrinsicsPowerPC.td" include "llvm/IR/IntrinsicsX86.td" include "llvm/IR/IntrinsicsARM.td" +include "llvm/IR/IntrinsicsAArch64.td" include "llvm/IR/IntrinsicsXCore.td" include "llvm/IR/IntrinsicsHexagon.td" include "llvm/IR/IntrinsicsNVVM.td" diff --git a/include/llvm/IR/IntrinsicsAArch64.td b/include/llvm/IR/IntrinsicsAArch64.td new file mode 100644 index 0000000..d7b1947 --- /dev/null +++ b/include/llvm/IR/IntrinsicsAArch64.td @@ -0,0 +1,41 @@ +//===- IntrinsicsAArch64.td - Defines AArch64 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 AArch64-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Advanced SIMD (NEON) + +let TargetPrefix = "aarch64" in { // All intrinsics start with "llvm.aarch64.". + +// Vector Absolute Compare (Floating Point) +def int_aarch64_neon_vacgeq : Intrinsic<[llvm_v2i64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; +def int_aarch64_neon_vacgtq : Intrinsic<[llvm_v2i64_ty], + [llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + +// Vector maxNum (Floating Point) +def int_aarch64_neon_vmaxnm : Neon_2Arg_Intrinsic; + +// Vector minNum (Floating Point) +def int_aarch64_neon_vminnm : Neon_2Arg_Intrinsic; + +// Vector Pairwise maxNum (Floating Point) +def int_aarch64_neon_vpmaxnm : Neon_2Arg_Intrinsic; + +// Vector Pairwise minNum (Floating Point) +def int_aarch64_neon_vpminnm : Neon_2Arg_Intrinsic; + +// Vector Multiply Extended (Floating Point) +def int_aarch64_neon_vmulx : Neon_2Arg_Intrinsic; +} diff --git a/include/llvm/IR/IntrinsicsARM.td b/include/llvm/IR/IntrinsicsARM.td index 93b1ae1..3c5d5ff 100644 --- a/include/llvm/IR/IntrinsicsARM.td +++ b/include/llvm/IR/IntrinsicsARM.td @@ -34,12 +34,15 @@ def int_arm_usat : GCCBuiltin<"__builtin_arm_usat">, Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; //===----------------------------------------------------------------------===// -// Load and Store exclusive doubleword +// Load, Store and Clear exclusive + +def int_arm_ldrex : Intrinsic<[llvm_i32_ty], [llvm_anyptr_ty]>; +def int_arm_strex : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_anyptr_ty]>; +def int_arm_clrex : Intrinsic<[]>; def int_arm_strexd : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty, - llvm_ptr_ty], [IntrReadWriteArgMem]>; -def int_arm_ldrexd : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_ptr_ty], - [IntrReadArgMem]>; + llvm_ptr_ty]>; +def int_arm_ldrexd : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_ptr_ty]>; //===----------------------------------------------------------------------===// // VFP @@ -124,6 +127,8 @@ class Neon_CvtFxToFP_Intrinsic : Intrinsic<[llvm_anyfloat_ty], [llvm_anyint_ty, llvm_i32_ty], [IntrNoMem]>; class Neon_CvtFPToFx_Intrinsic : Intrinsic<[llvm_anyint_ty], [llvm_anyfloat_ty, llvm_i32_ty], [IntrNoMem]>; +class Neon_CvtFPtoInt_1Arg_Intrinsic + : Intrinsic<[llvm_anyvector_ty], [llvm_anyvector_ty], [IntrNoMem]>; // The table operands for VTBL and VTBX consist of 1 to 4 v8i8 vectors. // Besides the table, VTBL has one other v8i8 argument and VTBX has two. @@ -177,10 +182,12 @@ let Properties = [IntrNoMem, Commutative] in { // Vector Maximum. def int_arm_neon_vmaxs : Neon_2Arg_Intrinsic; def int_arm_neon_vmaxu : Neon_2Arg_Intrinsic; + def int_arm_neon_vmaxnm : Neon_2Arg_Intrinsic; // Vector Minimum. def int_arm_neon_vmins : Neon_2Arg_Intrinsic; def int_arm_neon_vminu : Neon_2Arg_Intrinsic; + def int_arm_neon_vminnm : Neon_2Arg_Intrinsic; // Vector Reciprocal Step. def int_arm_neon_vrecps : Neon_2Arg_Intrinsic; @@ -314,6 +321,16 @@ def int_arm_neon_vrecpe : Neon_1Arg_Intrinsic; // Vector Reciprocal Square Root Estimate. def int_arm_neon_vrsqrte : Neon_1Arg_Intrinsic; +// Vector Conversions Between Floating-point and Integer +def int_arm_neon_vcvtau : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtas : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtnu : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtns : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtpu : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtps : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtmu : Neon_CvtFPtoInt_1Arg_Intrinsic; +def int_arm_neon_vcvtms : Neon_CvtFPtoInt_1Arg_Intrinsic; + // Vector Conversions Between Floating-point and Fixed-point. def int_arm_neon_vcvtfp2fxs : Neon_CvtFPToFx_Intrinsic; def int_arm_neon_vcvtfp2fxu : Neon_CvtFPToFx_Intrinsic; @@ -347,6 +364,14 @@ def int_arm_neon_vtbx2 : Neon_Tbl4Arg_Intrinsic; def int_arm_neon_vtbx3 : Neon_Tbl5Arg_Intrinsic; def int_arm_neon_vtbx4 : Neon_Tbl6Arg_Intrinsic; +// Vector Rounding +def int_arm_neon_vrintn : Neon_1Arg_Intrinsic; +def int_arm_neon_vrintx : Neon_1Arg_Intrinsic; +def int_arm_neon_vrinta : Neon_1Arg_Intrinsic; +def int_arm_neon_vrintz : Neon_1Arg_Intrinsic; +def int_arm_neon_vrintm : Neon_1Arg_Intrinsic; +def int_arm_neon_vrintp : Neon_1Arg_Intrinsic; + // De-interleaving vector loads from N-element structures. // Source operands are the address and alignment. def int_arm_neon_vld1 : Intrinsic<[llvm_anyvector_ty], diff --git a/include/llvm/IR/IntrinsicsNVVM.td b/include/llvm/IR/IntrinsicsNVVM.td index c248517..a372c22 100644 --- a/include/llvm/IR/IntrinsicsNVVM.td +++ b/include/llvm/IR/IntrinsicsNVVM.td @@ -861,8 +861,6 @@ def int_nvvm_ptr_gen_to_param: Intrinsic<[llvm_anyptr_ty], // Move intrinsics, used in nvvm internally -def int_nvvm_move_i8 : Intrinsic<[llvm_i8_ty], [llvm_i8_ty], [IntrNoMem], - "llvm.nvvm.move.i8">; def int_nvvm_move_i16 : Intrinsic<[llvm_i16_ty], [llvm_i16_ty], [IntrNoMem], "llvm.nvvm.move.i16">; def int_nvvm_move_i32 : Intrinsic<[llvm_i32_ty], [llvm_i32_ty], [IntrNoMem], diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 69e0ab4..c7675c2 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -2578,3 +2578,42 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_xtest : GCCBuiltin<"__builtin_ia32_xtest">, Intrinsic<[llvm_i32_ty], [], []>; } +// AVX-512 + +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + // Mask instructions + // 16-bit mask + def int_x86_kadd_v16i1 : GCCBuiltin<"__builtin_ia32_kaddw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + [IntrNoMem]>; + def int_x86_kand_v16i1 : GCCBuiltin<"__builtin_ia32_kandw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + [IntrNoMem]>; + def int_x86_kandn_v16i1 : GCCBuiltin<"__builtin_ia32_kandnw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + [IntrNoMem]>; + def int_x86_knot_v16i1 : GCCBuiltin<"__builtin_ia32_knotw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty], [IntrNoMem]>; + def int_x86_kor_v16i1 : GCCBuiltin<"__builtin_ia32_korw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + [IntrNoMem]>; + def int_x86_kxor_v16i1 : GCCBuiltin<"__builtin_ia32_kxorw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + [IntrNoMem]>; + def int_x86_kxnor_v16i1 : GCCBuiltin<"__builtin_ia32_kxnorw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v16i1_ty, llvm_v16i1_ty], + [IntrNoMem]>; + def int_x86_mask2int_v16i1 : GCCBuiltin<"__builtin_ia32_mask2intw">, + Intrinsic<[llvm_i32_ty], [llvm_v16i1_ty], [IntrNoMem]>; + def int_x86_int2mask_v16i1 : GCCBuiltin<"__builtin_ia32_int2maskw">, + Intrinsic<[llvm_v16i1_ty], [llvm_i32_ty], [IntrNoMem]>; + def int_x86_kunpck_v16i1 : GCCBuiltin<"__builtin_ia32_kunpckbw">, + Intrinsic<[llvm_v16i1_ty], [llvm_v8i1_ty, llvm_v8i1_ty], + [IntrNoMem]>; + def int_x86_avx512_kortestz : GCCBuiltin<"__builtin_ia32_kortestz">, + Intrinsic<[llvm_i32_ty], [llvm_i16_ty, llvm_i16_ty], + [IntrNoMem]>; + def int_x86_avx512_kortestc : GCCBuiltin<"__builtin_ia32_kortestc">, + Intrinsic<[llvm_i32_ty], [llvm_i16_ty, llvm_i16_ty], + [IntrNoMem]>; +} diff --git a/include/llvm/IR/IntrinsicsXCore.td b/include/llvm/IR/IntrinsicsXCore.td index a481313..bf345d4 100644 --- a/include/llvm/IR/IntrinsicsXCore.td +++ b/include/llvm/IR/IntrinsicsXCore.td @@ -13,7 +13,8 @@ let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". // Miscellaneous instructions. - def int_xcore_bitrev : Intrinsic<[llvm_i32_ty],[llvm_i32_ty],[IntrNoMem]>; + def int_xcore_bitrev : Intrinsic<[llvm_i32_ty],[llvm_i32_ty],[IntrNoMem]>, + GCCBuiltin<"__builtin_bitrev">; def int_xcore_crc8 : Intrinsic<[llvm_i32_ty, llvm_i32_ty], [llvm_i32_ty,llvm_i32_ty,llvm_i32_ty], [IntrNoMem]>; @@ -24,9 +25,12 @@ let TargetPrefix = "xcore" in { // All intrinsics start with "llvm.xcore.". [IntrNoMem]>; def int_xcore_zext : Intrinsic<[llvm_i32_ty], [llvm_i32_ty, llvm_i32_ty], [IntrNoMem]>; - def int_xcore_getid : Intrinsic<[llvm_i32_ty],[],[IntrNoMem]>; - def int_xcore_getps : Intrinsic<[llvm_i32_ty],[llvm_i32_ty]>; - def int_xcore_setps : Intrinsic<[],[llvm_i32_ty, llvm_i32_ty]>; + def int_xcore_getid : Intrinsic<[llvm_i32_ty],[],[IntrNoMem]>, + GCCBuiltin<"__builtin_getid">; + def int_xcore_getps : Intrinsic<[llvm_i32_ty],[llvm_i32_ty]>, + GCCBuiltin<"__builtin_getps">; + def int_xcore_setps : Intrinsic<[],[llvm_i32_ty, llvm_i32_ty]>, + GCCBuiltin<"__builtin_setps">; def int_xcore_geted : Intrinsic<[llvm_i32_ty],[]>; def int_xcore_getet : Intrinsic<[llvm_i32_ty],[]>; def int_xcore_setsr : Intrinsic<[],[llvm_i32_ty]>; diff --git a/include/llvm/IR/Metadata.h b/include/llvm/IR/Metadata.h index 8c2cfac..acd84d7 100644 --- a/include/llvm/IR/Metadata.h +++ b/include/llvm/IR/Metadata.h @@ -22,11 +22,8 @@ #include "llvm/IR/Value.h" namespace llvm { -class Constant; -class Instruction; class LLVMContext; class Module; -template <typename T> class SmallVectorImpl; template<typename ValueSubClass, typename ItemParentClass> class SymbolTableListTraits; @@ -139,7 +136,7 @@ public: void replaceOperandWith(unsigned i, Value *NewVal); /// getOperand - Return specified operand. - Value *getOperand(unsigned i) const; + Value *getOperand(unsigned i) const LLVM_READONLY; /// getNumOperands - Return number of MDNode operands. unsigned getNumOperands() const { return NumOperands; } diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index d414405..3dbc5ff 100644 --- a/include/llvm/IR/Module.h +++ b/include/llvm/IR/Module.h @@ -352,15 +352,22 @@ public: /// symbol table. If it does not exist, return null. If AllowInternal is set /// to true, this function will return types that have InternalLinkage. By /// default, these types are not returned. - GlobalVariable *getGlobalVariable(StringRef Name, - bool AllowInternal = false) const; + const GlobalVariable *getGlobalVariable(StringRef Name, + bool AllowInternal = false) const { + return const_cast<Module *>(this)->getGlobalVariable(Name, AllowInternal); + } + + GlobalVariable *getGlobalVariable(StringRef Name, bool AllowInternal = false); /// getNamedGlobal - Return the global variable in the module with the /// specified name, of arbitrary type. This method returns null if a global /// with the specified name is not found. - GlobalVariable *getNamedGlobal(StringRef Name) const { + GlobalVariable *getNamedGlobal(StringRef Name) { return getGlobalVariable(Name, true); } + const GlobalVariable *getNamedGlobal(StringRef Name) const { + return const_cast<Module *>(this)->getNamedGlobal(Name); + } /// getOrInsertGlobal - Look up the specified global in the module symbol /// table. @@ -405,6 +412,10 @@ public: /// getModuleFlagsMetadata - Returns the module flags in the provided vector. void getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const; + /// Return the corresponding value if Key appears in module flags, otherwise + /// return null. + Value *getModuleFlag(StringRef Key) const; + /// getModuleFlagsMetadata - Returns the NamedMDNode in the module that /// represents module-level flags. This method returns null if there are no /// module-level flags. diff --git a/include/llvm/IR/TypeBuilder.h b/include/llvm/IR/TypeBuilder.h index 80c60a0..5a29e1e 100644 --- a/include/llvm/IR/TypeBuilder.h +++ b/include/llvm/IR/TypeBuilder.h @@ -17,7 +17,7 @@ #include "llvm/IR/DerivedTypes.h" #include "llvm/IR/LLVMContext.h" -#include <limits.h> +#include <climits> namespace llvm { diff --git a/include/llvm/InitializePasses.h b/include/llvm/InitializePasses.h index 072c2e4..d7d18d0 100644 --- a/include/llvm/InitializePasses.h +++ b/include/llvm/InitializePasses.h @@ -87,6 +87,8 @@ void initializeCFGOnlyPrinterPass(PassRegistry&); void initializeCFGOnlyViewerPass(PassRegistry&); void initializeCFGPrinterPass(PassRegistry&); void initializeCFGSimplifyPassPass(PassRegistry&); +void initializeFlattenCFGPassPass(PassRegistry&); +void initializeStructurizeCFGPass(PassRegistry&); void initializeCFGViewerPass(PassRegistry&); void initializeCalculateSpillWeightsPass(PassRegistry&); void initializeCallGraphAnalysisGroup(PassRegistry&); @@ -239,7 +241,6 @@ void initializeScalarEvolutionAliasAnalysisPass(PassRegistry&); void initializeScalarEvolutionPass(PassRegistry&); void initializeSimpleInlinerPass(PassRegistry&); void initializeRegisterCoalescerPass(PassRegistry&); -void initializeSimplifyLibCallsPass(PassRegistry&); void initializeSingleLoopExtractorPass(PassRegistry&); void initializeSinkingPass(PassRegistry&); void initializeSlotIndexesPass(PassRegistry&); diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index ca1c139..ec39829 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -62,6 +62,7 @@ namespace { (void) llvm::createCallGraphPrinterPass(); (void) llvm::createCallGraphViewerPass(); (void) llvm::createCFGSimplificationPass(); + (void) llvm::createStructurizeCFGPass(); (void) llvm::createConstantMergePass(); (void) llvm::createConstantPropagationPass(); (void) llvm::createCostModelAnalysisPass(); @@ -129,7 +130,6 @@ namespace { (void) llvm::createRegionViewerPass(); (void) llvm::createSCCPPass(); (void) llvm::createScalarReplAggregatesPass(); - (void) llvm::createSimplifyLibCallsPass(); (void) llvm::createSingleLoopExtractorPass(); (void) llvm::createStripSymbolsPass(); (void) llvm::createStripNonDebugSymbolsPass(); diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index 781a9d0..e83b624 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -200,13 +200,6 @@ namespace llvm { /// on Mips or .gprel32 on Alpha. const char *GPRel32Directive; // Defaults to NULL. - /// getDataASDirective - Return the directive that should be used to emit - /// data of the specified size to the specified numeric address space. - virtual const char *getDataASDirective(unsigned Size, unsigned AS) const { - assert(AS != 0 && "Don't know the directives for default addr space"); - return 0; - } - /// SunStyleELFSectionSwitchSyntax - This is true if this target uses "Sun /// Style" syntax for section switching ("#alloc,#write" etc) instead of the /// normal ELF syntax (,"a,w") in .section directives. @@ -344,8 +337,8 @@ namespace llvm { virtual ~MCAsmInfo(); // FIXME: move these methods to DwarfPrinter when the JIT stops using them. - static unsigned getSLEB128Size(int Value); - static unsigned getULEB128Size(unsigned Value); + static unsigned getSLEB128Size(int64_t Value); + static unsigned getULEB128Size(uint64_t Value); /// getPointerSize - Get the pointer size in bytes. unsigned getPointerSize() const { @@ -372,17 +365,17 @@ namespace llvm { // Data directive accessors. // - const char *getData8bitsDirective(unsigned AS = 0) const { - return AS == 0 ? Data8bitsDirective : getDataASDirective(8, AS); + const char *getData8bitsDirective() const { + return Data8bitsDirective; } - const char *getData16bitsDirective(unsigned AS = 0) const { - return AS == 0 ? Data16bitsDirective : getDataASDirective(16, AS); + const char *getData16bitsDirective() const { + return Data16bitsDirective; } - const char *getData32bitsDirective(unsigned AS = 0) const { - return AS == 0 ? Data32bitsDirective : getDataASDirective(32, AS); + const char *getData32bitsDirective() const { + return Data32bitsDirective; } - const char *getData64bitsDirective(unsigned AS = 0) const { - return AS == 0 ? Data64bitsDirective : getDataASDirective(64, AS); + const char *getData64bitsDirective() const { + return Data64bitsDirective; } const char *getGPRel64Directive() const { return GPRel64Directive; } const char *getGPRel32Directive() const { return GPRel32Directive; } diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index 0db3dee..c012ed0 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -11,6 +11,7 @@ #define LLVM_MC_MCCONTEXT_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/MC/MCDwarf.h" @@ -37,6 +38,7 @@ namespace llvm { class Twine; class MCSectionMachO; class MCSectionELF; + class MCSectionCOFF; /// MCContext - Context object for machine code objects. This class owns all /// of the sections that it creates. @@ -51,10 +53,10 @@ namespace llvm { const SourceMgr *SrcMgr; /// The MCAsmInfo for this target. - const MCAsmInfo &MAI; + const MCAsmInfo *MAI; /// The MCRegisterInfo for this target. - const MCRegisterInfo &MRI; + const MCRegisterInfo *MRI; /// The MCObjectFileInfo for this target. const MCObjectFileInfo *MOFI; @@ -97,7 +99,7 @@ namespace llvm { bool SecureLogUsed; /// The compilation directory to use for DW_AT_comp_dir. - std::string CompilationDir; + SmallString<128> CompilationDir; /// The main file name if passed in explicitly. std::string MainFileName; @@ -163,16 +165,16 @@ namespace llvm { MCSymbol *CreateSymbol(StringRef Name); public: - explicit MCContext(const MCAsmInfo &MAI, const MCRegisterInfo &MRI, + explicit MCContext(const MCAsmInfo *MAI, const MCRegisterInfo *MRI, const MCObjectFileInfo *MOFI, const SourceMgr *Mgr = 0, bool DoAutoReset = true); ~MCContext(); const SourceMgr *getSourceManager() const { return SrcMgr; } - const MCAsmInfo &getAsmInfo() const { return MAI; } + const MCAsmInfo *getAsmInfo() const { return MAI; } - const MCRegisterInfo &getRegisterInfo() const { return MRI; } + const MCRegisterInfo *getRegisterInfo() const { return MRI; } const MCObjectFileInfo *getObjectFileInfo() const { return MOFI; } @@ -254,14 +256,12 @@ namespace llvm { const MCSectionELF *CreateELFGroupSection(); - const MCSection *getCOFFSection(StringRef Section, unsigned Characteristics, - int Selection, SectionKind Kind); - - const MCSection *getCOFFSection(StringRef Section, unsigned Characteristics, - SectionKind Kind) { - return getCOFFSection (Section, Characteristics, 0, Kind); - } + const MCSectionCOFF *getCOFFSection(StringRef Section, + unsigned Characteristics, + SectionKind Kind, int Selection = 0, + const MCSectionCOFF *Assoc = 0); + const MCSectionCOFF *getCOFFSection(StringRef Section); /// @} @@ -272,7 +272,7 @@ namespace llvm { /// This can be overridden by clients which want to control the reported /// compilation directory and have it be something other than the current /// working directory. - const std::string &getCompilationDir() const { return CompilationDir; } + StringRef getCompilationDir() const { return CompilationDir; } /// \brief Set the compilation directory for DW_AT_comp_dir /// Override the default (CWD) compilation directory. diff --git a/include/llvm/MC/MCELFStreamer.h b/include/llvm/MC/MCELFStreamer.h index 55c05b0..7565c15 100644 --- a/include/llvm/MC/MCELFStreamer.h +++ b/include/llvm/MC/MCELFStreamer.h @@ -77,8 +77,7 @@ public: uint64_t Size = 0, unsigned ByteAlignment = 0); virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment = 0); - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, - unsigned AddrSpace); + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size); virtual void EmitFileDirective(StringRef Filename); diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index d851f64..5d55974 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -171,24 +171,56 @@ public: VK_ARM_TARGET2, VK_ARM_PREL31, - VK_PPC_TOC, // TOC base - VK_PPC_TOC_ENTRY, // TOC entry - VK_PPC_ADDR16_HA, // symbol@ha - VK_PPC_ADDR16_LO, // symbol@l - VK_PPC_TPREL16_HA, // symbol@tprel@ha - VK_PPC_TPREL16_LO, // symbol@tprel@l - VK_PPC_DTPREL16_HA, // symbol@dtprel@ha - VK_PPC_DTPREL16_LO, // symbol@dtprel@l - VK_PPC_TOC16_HA, // symbol@toc@ha - VK_PPC_TOC16_LO, // symbol@toc@l - VK_PPC_GOT_TPREL16_HA, // symbol@got@tprel@ha - VK_PPC_GOT_TPREL16_LO, // symbol@got@tprel@l + VK_PPC_LO, // symbol@l + VK_PPC_HI, // symbol@h + VK_PPC_HA, // symbol@ha + VK_PPC_HIGHER, // symbol@higher + VK_PPC_HIGHERA, // symbol@highera + VK_PPC_HIGHEST, // symbol@highest + VK_PPC_HIGHESTA, // symbol@highesta + VK_PPC_GOT_LO, // symbol@got@l + VK_PPC_GOT_HI, // symbol@got@h + VK_PPC_GOT_HA, // symbol@got@ha + VK_PPC_TOCBASE, // symbol@tocbase + VK_PPC_TOC, // symbol@toc + VK_PPC_TOC_LO, // symbol@toc@l + VK_PPC_TOC_HI, // symbol@toc@h + VK_PPC_TOC_HA, // symbol@toc@ha + VK_PPC_DTPMOD, // symbol@dtpmod + VK_PPC_TPREL, // symbol@tprel + VK_PPC_TPREL_LO, // symbol@tprel@l + VK_PPC_TPREL_HI, // symbol@tprel@h + VK_PPC_TPREL_HA, // symbol@tprel@ha + VK_PPC_TPREL_HIGHER, // symbol@tprel@higher + VK_PPC_TPREL_HIGHERA, // symbol@tprel@highera + VK_PPC_TPREL_HIGHEST, // symbol@tprel@highest + VK_PPC_TPREL_HIGHESTA, // symbol@tprel@highesta + VK_PPC_DTPREL, // symbol@dtprel + VK_PPC_DTPREL_LO, // symbol@dtprel@l + VK_PPC_DTPREL_HI, // symbol@dtprel@h + VK_PPC_DTPREL_HA, // symbol@dtprel@ha + VK_PPC_DTPREL_HIGHER, // symbol@dtprel@higher + VK_PPC_DTPREL_HIGHERA, // symbol@dtprel@highera + VK_PPC_DTPREL_HIGHEST, // symbol@dtprel@highest + VK_PPC_DTPREL_HIGHESTA,// symbol@dtprel@highesta + VK_PPC_GOT_TPREL, // symbol@got@tprel + VK_PPC_GOT_TPREL_LO, // symbol@got@tprel@l + VK_PPC_GOT_TPREL_HI, // symbol@got@tprel@h + VK_PPC_GOT_TPREL_HA, // symbol@got@tprel@ha + VK_PPC_GOT_DTPREL, // symbol@got@dtprel + VK_PPC_GOT_DTPREL_LO, // symbol@got@dtprel@l + VK_PPC_GOT_DTPREL_HI, // symbol@got@dtprel@h + VK_PPC_GOT_DTPREL_HA, // symbol@got@dtprel@ha VK_PPC_TLS, // symbol@tls - VK_PPC_GOT_TLSGD16_HA, // symbol@got@tlsgd@ha - VK_PPC_GOT_TLSGD16_LO, // symbol@got@tlsgd@l + VK_PPC_GOT_TLSGD, // symbol@got@tlsgd + VK_PPC_GOT_TLSGD_LO, // symbol@got@tlsgd@l + VK_PPC_GOT_TLSGD_HI, // symbol@got@tlsgd@h + VK_PPC_GOT_TLSGD_HA, // symbol@got@tlsgd@ha VK_PPC_TLSGD, // symbol@tlsgd - VK_PPC_GOT_TLSLD16_HA, // symbol@got@tlsld@ha - VK_PPC_GOT_TLSLD16_LO, // symbol@got@tlsld@l + VK_PPC_GOT_TLSLD, // symbol@got@tlsld + VK_PPC_GOT_TLSLD_LO, // symbol@got@tlsld@l + VK_PPC_GOT_TLSLD_HI, // symbol@got@tlsld@h + VK_PPC_GOT_TLSLD_HA, // symbol@got@tlsld@ha VK_PPC_TLSLD, // symbol@tlsld VK_Mips_GPREL, diff --git a/include/llvm/MC/MCInstPrinter.h b/include/llvm/MC/MCInstPrinter.h index a18cbd9..cb7225f 100644 --- a/include/llvm/MC/MCInstPrinter.h +++ b/include/llvm/MC/MCInstPrinter.h @@ -21,6 +21,13 @@ class MCInstrInfo; class MCRegisterInfo; class StringRef; +namespace HexStyle { + enum Style { + C, ///< 0xff + Asm ///< 0ffh + }; +} + /// MCInstPrinter - This is an instance of a target assembly language printer /// that converts an MCInst to valid target assembly syntax. class MCInstPrinter { @@ -42,13 +49,16 @@ protected: /// True if we are printing immediates as hex. bool PrintImmHex; + /// Which style to use for printing hexadecimal values. + HexStyle::Style PrintHexStyle; + /// Utility function for printing annotations. void printAnnotation(raw_ostream &OS, StringRef Annot); public: MCInstPrinter(const MCAsmInfo &mai, const MCInstrInfo &mii, const MCRegisterInfo &mri) : CommentStream(0), MAI(mai), MII(mii), MRI(mri), AvailableFeatures(0), - UseMarkup(0), PrintImmHex(0) {} + UseMarkup(0), PrintImmHex(0), PrintHexStyle(HexStyle::C) {} virtual ~MCInstPrinter(); @@ -80,8 +90,16 @@ public: bool getPrintImmHex() const { return PrintImmHex; } void setPrintImmHex(bool Value) { PrintImmHex = Value; } + HexStyle::Style getPrintHexStyleHex() const { return PrintHexStyle; } + void setPrintImmHex(HexStyle::Style Value) { PrintHexStyle = Value; } + /// Utility function to print immediates in decimal or hex. - format_object1<int64_t> formatImm(const int64_t Value) const; + format_object1<int64_t> formatImm(const int64_t Value) const { return PrintImmHex ? formatHex(Value) : formatDec(Value); } + + /// Utility functions to print decimal/hexadecimal values. + format_object1<int64_t> formatDec(const int64_t Value) const; + format_object1<int64_t> formatHex(const int64_t Value) const; + format_object1<uint64_t> formatHex(const uint64_t Value) const; }; } // namespace llvm diff --git a/include/llvm/MC/MCInstrDesc.h b/include/llvm/MC/MCInstrDesc.h index 9b5415a..310f706 100644 --- a/include/llvm/MC/MCInstrDesc.h +++ b/include/llvm/MC/MCInstrDesc.h @@ -268,8 +268,20 @@ public: if (isBranch() || isCall() || isReturn() || isIndirectBranch()) return true; unsigned PC = RI.getProgramCounter(); - if (PC == 0) return false; - return hasDefOfPhysReg(MI, PC, RI); + if (PC == 0) + return false; + if (hasDefOfPhysReg(MI, PC, RI)) + return true; + // A variadic instruction may define PC in the variable operand list. + // There's currently no indication of which entries in a variable + // list are defs and which are uses. While that's the case, this function + // needs to assume they're defs in order to be conservatively correct. + for (int i = NumOperands, e = MI.getNumOperands(); i != e; ++i) { + if (MI.getOperand(i).isReg() && + RI.isSubRegisterEq(PC, MI.getOperand(i).getReg())) + return true; + } + return false; } /// \brief Return true if this instruction has a predicate operand diff --git a/include/llvm/MC/MCInstrItineraries.h b/include/llvm/MC/MCInstrItineraries.h index 65d1559..c4f9e1c 100644 --- a/include/llvm/MC/MCInstrItineraries.h +++ b/include/llvm/MC/MCInstrItineraries.h @@ -157,17 +157,12 @@ public: /// class. The latency is the maximum completion time for any stage /// in the itinerary. /// - /// InstrStages override the itinerary's MinLatency property. In fact, if the - /// stage latencies, which may be zero, are less than MinLatency, - /// getStageLatency returns a value less than MinLatency. - /// - /// If no stages exist, MinLatency is used. If MinLatency is invalid (<0), - /// then it defaults to one cycle. + /// If no stages exist, it defaults to one cycle. unsigned getStageLatency(unsigned ItinClassIndx) const { // If the target doesn't provide itinerary information, use a simple // non-zero default value for all instructions. if (isEmpty()) - return SchedModel->MinLatency < 0 ? 1 : SchedModel->MinLatency; + return 1; // Calculate the maximum completion time for any stage. unsigned Latency = 0, StartCycle = 0; @@ -176,7 +171,6 @@ public: Latency = std::max(Latency, StartCycle + IS->getCycles()); StartCycle += IS->getNextCycles(); } - return Latency; } diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index 22a2839..0affeee 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -78,8 +78,7 @@ public: virtual void EmitLabel(MCSymbol *Symbol); virtual void EmitDebugLabel(MCSymbol *Symbol); virtual void EmitAssignment(MCSymbol *Symbol, const MCExpr *Value); - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, - unsigned AddrSpace); + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size); virtual void EmitULEB128Value(const MCExpr *Value); virtual void EmitSLEB128Value(const MCExpr *Value); virtual void EmitWeakReference(MCSymbol *Alias, const MCSymbol *Symbol); @@ -94,7 +93,7 @@ public: virtual void EmitBundleAlignMode(unsigned AlignPow2); virtual void EmitBundleLock(bool AlignToEnd); virtual void EmitBundleUnlock(); - virtual void EmitBytes(StringRef Data, unsigned AddrSpace = 0); + virtual void EmitBytes(StringRef Data); virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0, unsigned ValueSize = 1, @@ -102,6 +101,10 @@ public: virtual void EmitCodeAlignment(unsigned ByteAlignment, unsigned MaxBytesToEmit = 0); virtual bool EmitValueToOffset(const MCExpr *Offset, unsigned char Value); + virtual void EmitDwarfLocDirective(unsigned FileNo, unsigned Line, + unsigned Column, unsigned Flags, + unsigned Isa, unsigned Discriminator, + StringRef FileName); virtual void EmitDwarfAdvanceLineAddr(int64_t LineDelta, const MCSymbol *LastLabel, const MCSymbol *Label, @@ -110,8 +113,8 @@ public: const MCSymbol *Label); virtual void EmitGPRel32Value(const MCExpr *Value); virtual void EmitGPRel64Value(const MCExpr *Value); - virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, - unsigned AddrSpace = 0); + virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue); + virtual void EmitZeros(uint64_t NumBytes); virtual void FinishImpl(); /// @} diff --git a/include/llvm/MC/MCSchedule.h b/include/llvm/MC/MCSchedule.h index defa299..673cdf6 100644 --- a/include/llvm/MC/MCSchedule.h +++ b/include/llvm/MC/MCSchedule.h @@ -30,15 +30,18 @@ struct MCProcResourceDesc { unsigned NumUnits; // Number of resource of this kind unsigned SuperIdx; // Index of the resources kind that contains this kind. - // Buffered resources may be consumed at some indeterminate cycle after - // dispatch (e.g. for instructions that may issue out-of-order). Unbuffered - // resources always consume their resource some fixed number of cycles after - // dispatch (e.g. for instruction interlocking that may stall the pipeline). - bool IsBuffered; + // Number of resources that may be buffered. + // + // Buffered resources (BufferSize > 0 || BufferSize == -1) may be consumed at + // some indeterminate cycle after dispatch (e.g. for instructions that may + // issue out-of-order). Unbuffered resources (BufferSize == 0) always consume + // their resource some fixed number of cycles after dispatch (e.g. for + // instruction interlocking that may stall the pipeline). + int BufferSize; bool operator==(const MCProcResourceDesc &Other) const { return NumUnits == Other.NumUnits && SuperIdx == Other.SuperIdx - && IsBuffered == Other.IsBuffered; + && BufferSize == Other.BufferSize; } }; @@ -134,28 +137,22 @@ public: unsigned IssueWidth; static const unsigned DefaultIssueWidth = 1; - // MinLatency is the minimum latency between a register write - // followed by a data dependent read. This determines which - // instructions may be scheduled in the same per-cycle group. This - // is distinct from *expected* latency, which determines the likely - // critical path but does not guarantee a pipeline - // hazard. MinLatency can always be overridden by the number of - // InstrStage cycles. + // MicroOpBufferSize is the number of micro-ops that the processor may buffer + // for out-of-order execution. // - // (-1) Standard in-order processor. - // Use InstrItinerary OperandCycles as MinLatency. - // If no OperandCycles exist, then use the cycle of the last InstrStage. + // "0" means operations that are not ready in this cycle are not considered + // for scheduling (they go in the pending queue). Latency is paramount. This + // may be more efficient if many instructions are pending in a schedule. // - // (0) Out-of-order processor, or in-order with bundled dependencies. - // RAW dependencies may be dispatched in the same cycle. - // Optional InstrItinerary OperandCycles provides expected latency. + // "1" means all instructions are considered for scheduling regardless of + // whether they are ready in this cycle. Latency still causes issue stalls, + // but we balance those stalls against other heuristics. // - // (>0) In-order processor with variable latencies. - // Use the greater of this value or the cycle of the last InstrStage. - // Optional InstrItinerary OperandCycles provides expected latency. - // TODO: can't yet specify both min and expected latency per operand. - int MinLatency; - static const int DefaultMinLatency = -1; + // "> 1" means the processor is out-of-order. This is a machine independent + // estimate of highly machine specific characteristics such are the register + // renaming pool and reorder buffer. + unsigned MicroOpBufferSize; + static const unsigned DefaultMicroOpBufferSize = 0; // LoadLatency is the expected latency of load instructions. // @@ -172,16 +169,6 @@ public: unsigned HighLatency; static const unsigned DefaultHighLatency = 10; - // ILPWindow is the number of cycles that the scheduler effectively ignores - // before attempting to hide latency. This should be zero for in-order cpus to - // always hide expected latency. For out-of-order cpus, it may be tweaked as - // desired to roughly approximate instruction buffers. The actual threshold is - // not very important for an OOO processor, as long as it isn't too high. A - // nonzero value helps avoid rescheduling to hide latency when its is fairly - // obviously useless and makes register pressure heuristics more effective. - unsigned ILPWindow; - static const unsigned DefaultILPWindow = 0; - // MispredictPenalty is the typical number of extra cycles the processor // takes to recover from a branch misprediction. unsigned MispredictPenalty; @@ -203,10 +190,9 @@ public: // initialized in this default ctor because some clients directly instantiate // MCSchedModel instead of using a generated itinerary. MCSchedModel(): IssueWidth(DefaultIssueWidth), - MinLatency(DefaultMinLatency), + MicroOpBufferSize(DefaultMicroOpBufferSize), LoadLatency(DefaultLoadLatency), HighLatency(DefaultHighLatency), - ILPWindow(DefaultILPWindow), MispredictPenalty(DefaultMispredictPenalty), ProcID(0), ProcResourceTable(0), SchedClassTable(0), NumProcResourceKinds(0), NumSchedClasses(0), @@ -216,12 +202,12 @@ public: } // Table-gen driven ctor. - MCSchedModel(unsigned iw, int ml, unsigned ll, unsigned hl, unsigned ilp, + MCSchedModel(unsigned iw, int mbs, unsigned ll, unsigned hl, unsigned mp, unsigned pi, const MCProcResourceDesc *pr, const MCSchedClassDesc *sc, unsigned npr, unsigned nsc, const InstrItinerary *ii): - IssueWidth(iw), MinLatency(ml), LoadLatency(ll), HighLatency(hl), - ILPWindow(ilp), MispredictPenalty(mp), ProcID(pi), ProcResourceTable(pr), + IssueWidth(iw), MicroOpBufferSize(mbs), LoadLatency(ll), HighLatency(hl), + MispredictPenalty(mp), ProcID(pi), ProcResourceTable(pr), SchedClassTable(sc), NumProcResourceKinds(npr), NumSchedClasses(nsc), InstrItineraries(ii) {} diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h index 50e33a5..754e829 100644 --- a/include/llvm/MC/MCSectionCOFF.h +++ b/include/llvm/MC/MCSectionCOFF.h @@ -25,22 +25,33 @@ namespace llvm { // The memory for this string is stored in the same MCContext as *this. StringRef SectionName; + // FIXME: The following fields should not be mutable, but are for now so + // the asm parser can honor the .linkonce directive. + /// Characteristics - This is the Characteristics field of a section, - // drawn from the enums below. - unsigned Characteristics; + /// drawn from the enums below. + mutable unsigned Characteristics; /// Selection - This is the Selection field for the section symbol, if /// it is a COMDAT section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0 - int Selection; + mutable int Selection; + + /// Assoc - This is name of the associated section, if it is a COMDAT + /// section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0 with an + /// associative Selection (IMAGE_COMDAT_SELECT_ASSOCIATIVE). + mutable const MCSectionCOFF *Assoc; private: friend class MCContext; MCSectionCOFF(StringRef Section, unsigned Characteristics, - int Selection, SectionKind K) + int Selection, const MCSectionCOFF *Assoc, SectionKind K) : MCSection(SV_COFF, K), SectionName(Section), - Characteristics(Characteristics), Selection (Selection) { + Characteristics(Characteristics), Selection(Selection), Assoc(Assoc) { assert ((Characteristics & 0x00F00000) == 0 && "alignment must not be set upon section creation"); + assert ((Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) == + (Assoc != 0) && + "associative COMDAT section must have an associated section"); } ~MCSectionCOFF(); @@ -57,7 +68,10 @@ namespace llvm { return SectionName.str() + "_end"; } unsigned getCharacteristics() const { return Characteristics; } - int getSelection () const { return Selection; } + int getSelection() const { return Selection; } + const MCSectionCOFF *getAssocSection() const { return Assoc; } + + void setSelection(int Selection, const MCSectionCOFF *Assoc = 0) const; virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS, diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 2cab481..970c4ed 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -407,7 +407,7 @@ namespace llvm { /// /// This is used to implement assembler directives such as .byte, .ascii, /// etc. - virtual void EmitBytes(StringRef Data, unsigned AddrSpace = 0) = 0; + virtual void EmitBytes(StringRef Data) = 0; /// EmitValue - Emit the expression @p Value into the output as a native /// integer of the given @p Size bytes. @@ -418,22 +418,19 @@ namespace llvm { /// @param Value - The value to emit. /// @param Size - The size of the integer (in bytes) to emit. This must /// match a native machine width. - virtual void EmitValueImpl(const MCExpr *Value, unsigned Size, - unsigned AddrSpace) = 0; + virtual void EmitValueImpl(const MCExpr *Value, unsigned Size) = 0; - void EmitValue(const MCExpr *Value, unsigned Size, unsigned AddrSpace = 0); + void EmitValue(const MCExpr *Value, unsigned Size); /// EmitIntValue - Special case of EmitValue that avoids the client having /// to pass in a MCExpr for constant integers. - virtual void EmitIntValue(uint64_t Value, unsigned Size, - unsigned AddrSpace = 0); + virtual void EmitIntValue(uint64_t Value, unsigned Size); /// EmitAbsValue - Emit the Value, but try to avoid relocations. On MachO /// this is done by producing /// foo = value /// .long foo - void EmitAbsValue(const MCExpr *Value, unsigned Size, - unsigned AddrSpace = 0); + void EmitAbsValue(const MCExpr *Value, unsigned Size); virtual void EmitULEB128Value(const MCExpr *Value) = 0; @@ -441,17 +438,15 @@ namespace llvm { /// EmitULEB128Value - Special case of EmitULEB128Value that avoids the /// client having to pass in a MCExpr for constant integers. - void EmitULEB128IntValue(uint64_t Value, unsigned Padding = 0, - unsigned AddrSpace = 0); + void EmitULEB128IntValue(uint64_t Value, unsigned Padding = 0); /// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the /// client having to pass in a MCExpr for constant integers. - void EmitSLEB128IntValue(int64_t Value, unsigned AddrSpace = 0); + void EmitSLEB128IntValue(int64_t Value); /// EmitSymbolValue - Special case of EmitValue that avoids the client /// having to pass in a MCExpr for MCSymbols. - void EmitSymbolValue(const MCSymbol *Sym, unsigned Size, - unsigned AddrSpace = 0); + void EmitSymbolValue(const MCSymbol *Sym, unsigned Size); /// EmitGPRel64Value - Emit the expression @p Value into the output as a /// gprel64 (64-bit GP relative) value. @@ -469,14 +464,11 @@ namespace llvm { /// EmitFill - Emit NumBytes bytes worth of the value specified by /// FillValue. This implements directives such as '.space'. - virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue, - unsigned AddrSpace = 0); + virtual void EmitFill(uint64_t NumBytes, uint8_t FillValue); - /// EmitZeros - Emit NumBytes worth of zeros. This is a convenience - /// function that just wraps EmitFill. - void EmitZeros(uint64_t NumBytes, unsigned AddrSpace = 0) { - EmitFill(NumBytes, 0, AddrSpace); - } + /// \brief Emit NumBytes worth of zeros. + /// This function properly handles data in virtual sections. + virtual void EmitZeros(uint64_t NumBytes); /// EmitValueToAlignment - Emit some number of copies of @p Value until /// the byte alignment @p ByteAlignment is reached. diff --git a/include/llvm/MC/MCTargetAsmParser.h b/include/llvm/MC/MCTargetAsmParser.h index 6e878df..ebcbd5b 100644 --- a/include/llvm/MC/MCTargetAsmParser.h +++ b/include/llvm/MC/MCTargetAsmParser.h @@ -143,7 +143,7 @@ public: /// mnemonicIsValid - This returns true if this is a valid mnemonic and false /// otherwise. - virtual bool mnemonicIsValid(StringRef Mnemonic) = 0; + virtual bool mnemonicIsValid(StringRef Mnemonic, unsigned VariantID) = 0; /// MatchAndEmitInstruction - Recognize a series of operands of a parsed /// instruction as an actual MCInst and emit it to the specified MCStreamer. diff --git a/include/llvm/Object/Archive.h b/include/llvm/Object/Archive.h index e2478f6..1cba519 100644 --- a/include/llvm/Object/Archive.h +++ b/include/llvm/Object/Archive.h @@ -14,12 +14,10 @@ #ifndef LLVM_OBJECT_ARCHIVE_H #define LLVM_OBJECT_ARCHIVE_H -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" #include "llvm/Object/Binary.h" -#include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/MemoryBuffer.h" namespace llvm { @@ -33,33 +31,17 @@ struct ArchiveMemberHeader { char Size[10]; ///< Size of data, not including header or padding. char Terminator[2]; - ///! Get the name without looking up long names. - llvm::StringRef getName() const { - char EndCond; - if (Name[0] == '/' || Name[0] == '#') - EndCond = ' '; - else - EndCond = '/'; - llvm::StringRef::size_type end = - llvm::StringRef(Name, sizeof(Name)).find(EndCond); - if (end == llvm::StringRef::npos) - end = sizeof(Name); - assert(end <= sizeof(Name) && end > 0); - // Don't include the EndCond if there is one. - return llvm::StringRef(Name, end); - } + /// Get the name without looking up long names. + llvm::StringRef getName() const; - uint64_t getSize() const { - uint64_t ret; - if (llvm::StringRef(Size, sizeof(Size)).rtrim(" ").getAsInteger(10, ret)) - llvm_unreachable("Size is not an integer."); - return ret; - } -}; + /// Members are not larger than 4GB. + uint32_t getSize() const; -static const ArchiveMemberHeader *ToHeader(const char *base) { - return reinterpret_cast<const ArchiveMemberHeader *>(base); -} + sys::fs::perms getAccessMode() const; + sys::TimeValue getLastModified() const; + unsigned getUID() const; + unsigned getGID() const; +}; class Archive : public Binary { virtual void anchor(); @@ -71,53 +53,34 @@ public: /// \brief Offset from Data to the start of the file. uint16_t StartOfFile; - public: - Child(const Archive *p, StringRef d) : Parent(p), Data(d) { - if (!p || d.empty()) - return; - // Setup StartOfFile and PaddingBytes. - StartOfFile = sizeof(ArchiveMemberHeader); - // Don't include attached name. - StringRef Name = ToHeader(Data.data())->getName(); - if (Name.startswith("#1/")) { - uint64_t NameSize; - if (Name.substr(3).rtrim(" ").getAsInteger(10, NameSize)) - llvm_unreachable("Long name length is not an integer"); - StartOfFile += NameSize; - } + const ArchiveMemberHeader *getHeader() const { + return reinterpret_cast<const ArchiveMemberHeader *>(Data.data()); } + public: + Child(const Archive *Parent, const char *Start); + bool operator ==(const Child &other) const { - return (Parent == other.Parent) && (Data.begin() == other.Data.begin()); + assert(Parent == other.Parent); + return Data.begin() == other.Data.begin(); } bool operator <(const Child &other) const { return Data.begin() < other.Data.begin(); } - Child getNext() const { - size_t SpaceToSkip = Data.size(); - // If it's odd, add 1 to make it even. - if (SpaceToSkip & 1) - ++SpaceToSkip; - - const char *NextLoc = Data.data() + SpaceToSkip; - - // Check to see if this is past the end of the archive. - if (NextLoc >= Parent->Data->getBufferEnd()) - return Child(Parent, StringRef(0, 0)); - - size_t NextSize = - sizeof(ArchiveMemberHeader) + ToHeader(NextLoc)->getSize(); - - return Child(Parent, StringRef(NextLoc, NextSize)); - } + Child getNext() const; error_code getName(StringRef &Result) const; - int getLastModified() const; - int getUID() const; - int getGID() const; - int getAccessMode() const; + StringRef getRawName() const { return getHeader()->getName(); } + sys::TimeValue getLastModified() const { + return getHeader()->getLastModified(); + } + unsigned getUID() const { return getHeader()->getUID(); } + unsigned getGID() const { return getHeader()->getGID(); } + sys::fs::perms getAccessMode() const { + return getHeader()->getAccessMode(); + } /// \return the size of the archive member without the header or padding. uint64_t getSize() const { return Data.size() - StartOfFile; } @@ -126,16 +89,7 @@ public: } error_code getMemoryBuffer(OwningPtr<MemoryBuffer> &Result, - bool FullPath = false) const { - StringRef Name; - if (error_code ec = getName(Name)) - return ec; - SmallString<128> Path; - Result.reset(MemoryBuffer::getMemBuffer( - getBuffer(), FullPath ? (Twine(Parent->getFileName()) + "(" + Name + - ")").toStringRef(Path) : Name, false)); - return error_code::success(); - } + bool FullPath = false) const; error_code getAsBinary(OwningPtr<Binary> &Result) const; }; @@ -143,7 +97,7 @@ public: class child_iterator { Child child; public: - child_iterator() : child(Child(0, StringRef())) {} + child_iterator() : child(Child(0, 0)) {} child_iterator(const Child &c) : child(c) {} const Child* operator->() const { return &child; @@ -220,7 +174,7 @@ public: return Format; } - child_iterator begin_children(bool skip_internal = true) const; + child_iterator begin_children(bool SkipInternal = true) const; child_iterator end_children() const; symbol_iterator begin_symbols() const; @@ -234,9 +188,12 @@ public: // check if a symbol is in the archive child_iterator findSym(StringRef name) const; + bool hasSymbolTable() const; + private: child_iterator SymbolTable; child_iterator StringTable; + child_iterator FirstRegular; Kind Format; }; diff --git a/include/llvm/Object/Binary.h b/include/llvm/Object/Binary.h index 78fcf6f..a3f5625 100644 --- a/include/llvm/Object/Binary.h +++ b/include/llvm/Object/Binary.h @@ -38,6 +38,7 @@ protected: enum { ID_Archive, + ID_MachOUniversalBinary, // Object and children. ID_StartObjects, ID_COFF, @@ -87,6 +88,10 @@ public: return TypeID == ID_Archive; } + bool isMachOUniversalBinary() const { + return TypeID == ID_MachOUniversalBinary; + } + bool isELF() const { return TypeID >= ID_ELF32L && TypeID <= ID_ELF64B; } diff --git a/include/llvm/Object/COFF.h b/include/llvm/Object/COFF.h index 209aa76..2190067 100644 --- a/include/llvm/Object/COFF.h +++ b/include/llvm/Object/COFF.h @@ -129,6 +129,14 @@ struct data_directory { support::ulittle32_t Size; }; +struct import_directory_table_entry { + support::ulittle32_t ImportLookupTableRVA; + support::ulittle32_t TimeDateStamp; + support::ulittle32_t ForwarderChain; + support::ulittle32_t NameRVA; + support::ulittle32_t ImportAddressTableRVA; +}; + struct coff_symbol { struct StringTableOffset { support::ulittle32_t Zeroes; @@ -188,7 +196,9 @@ struct coff_aux_section_definition { class COFFObjectFile : public ObjectFile { private: - const coff_file_header *Header; + const coff_file_header *COFFHeader; + const pe32_header *PE32Header; + const data_directory *DataDirectory; const coff_section *SectionTable; const coff_symbol *SymbolTable; const char *StringTable; @@ -272,6 +282,9 @@ public: virtual StringRef getLoadName() const; error_code getHeader(const coff_file_header *&Res) const; + error_code getCOFFHeader(const coff_file_header *&Res) const; + error_code getPE32Header(const pe32_header *&Res) const; + error_code getDataDirectory(uint32_t index, const data_directory *&Res) const; error_code getSection(int32_t index, const coff_section *&Res) const; error_code getSymbol(uint32_t index, const coff_symbol *&Res) const; template <typename T> diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index eb8e22e..2063809 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -1234,7 +1234,8 @@ error_code ELFObjectFile<ELFT>::getSymbolFlags(DataRefImpl Symb, Result |= SymbolRef::SF_Absolute; if (symb->getType() == ELF::STT_FILE || - symb->getType() == ELF::STT_SECTION) + symb->getType() == ELF::STT_SECTION || + Symb == begin_symbols()->getRawDataRefImpl()) Result |= SymbolRef::SF_FormatSpecific; if (getSymbolTableIndex(symb) == ELF::SHN_UNDEF) @@ -1667,6 +1668,8 @@ StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_PC16); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_CALL16); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_GPREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_UNUSED1); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_UNUSED2); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SHIFT5); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_SHIFT6); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_MIPS_64); @@ -2030,9 +2033,45 @@ StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14_BRTAKEN); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL14_BRNTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT16_HA); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TLS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPMOD32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_HI); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TPREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_DTPREL32); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSGD16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TLSLD16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_TPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_GOT_DTPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TLSGD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_TLSLD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC_REL16_HA); default: break; } break; @@ -2052,32 +2091,74 @@ StringRef ELFObjectFile<ELFT>::getRelocationTypeName(uint32_t Type) const { LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14_BRTAKEN); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL14_BRNTAKEN); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_HA); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL32); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHER); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHERA); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHEST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_HIGHESTA); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL64); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_HI); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_HA); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_DS); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_ADDR16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT16_LO_DS); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_DS); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TOC16_LO_DS); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPMOD64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HI); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HI); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL64); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_HI); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSGD16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_HI); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TLSLD16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_DS); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_HI); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_TPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_GOT_DTPREL16_HA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHER); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHERA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHEST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TPREL16_HIGHESTA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_LO_DS); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHER); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHERA); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHEST); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_DTPREL16_HIGHESTA); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSGD); LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_TLSLD); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16_LO); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16_HI); + LLVM_ELF_SWITCH_RELOC_TYPE_NAME(R_PPC64_REL16_HA); default: break; } break; @@ -2272,7 +2353,16 @@ error_code ELFObjectFile<ELFT>::getRelocationValueString( res = "Unknown"; } break; - case ELF::EM_AARCH64: + case ELF::EM_AARCH64: { + std::string fmtbuf; + raw_string_ostream fmt(fmtbuf); + fmt << symname; + if (addend != 0) + fmt << (addend < 0 ? "" : "+") << addend; + fmt.flush(); + Result.append(fmtbuf.begin(), fmtbuf.end()); + break; + } case ELF::EM_ARM: case ELF::EM_HEXAGON: res = symname; @@ -2708,7 +2798,8 @@ unsigned ELFObjectFile<ELFT>::getArch() const { return (ELFT::TargetEndianness == support::little) ? Triple::mipsel : Triple::mips; case ELF::EM_PPC64: - return Triple::ppc64; + return (ELFT::TargetEndianness == support::little) ? + Triple::ppc64le : Triple::ppc64; case ELF::EM_S390: return Triple::systemz; default: diff --git a/include/llvm/Object/ELFYAML.h b/include/llvm/Object/ELFYAML.h index 029a8ab..fca965f 100644 --- a/include/llvm/Object/ELFYAML.h +++ b/include/llvm/Object/ELFYAML.h @@ -36,23 +36,59 @@ LLVM_YAML_STRONG_TYPEDEF(uint16_t, ELF_ET) LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_EM) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFCLASS) LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFDATA) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_ELFOSABI) +LLVM_YAML_STRONG_TYPEDEF(uint32_t, ELF_SHT) +// Just use 64, since it can hold 32-bit values too. +LLVM_YAML_STRONG_TYPEDEF(uint64_t, ELF_SHF) +LLVM_YAML_STRONG_TYPEDEF(uint8_t, ELF_STT) // For now, hardcode 64 bits everywhere that 32 or 64 would be needed // since 64-bit can hold 32-bit values too. struct FileHeader { ELF_ELFCLASS Class; ELF_ELFDATA Data; + ELF_ELFOSABI OSABI; ELF_ET Type; ELF_EM Machine; llvm::yaml::Hex64 Entry; }; +struct Symbol { + StringRef Name; + ELF_STT Type; + StringRef Section; + llvm::yaml::Hex64 Value; + llvm::yaml::Hex64 Size; +}; +struct LocalGlobalWeakSymbols { + std::vector<Symbol> Local; + std::vector<Symbol> Global; + std::vector<Symbol> Weak; +}; +struct Section { + StringRef Name; + ELF_SHT Type; + ELF_SHF Flags; + llvm::yaml::Hex64 Address; + object::yaml::BinaryRef Content; + StringRef Link; + llvm::yaml::Hex64 AddressAlign; +}; struct Object { FileHeader Header; + std::vector<Section> Sections; + // Although in reality the symbols reside in a section, it is a lot + // cleaner and nicer if we read them from the YAML as a separate + // top-level key, which automatically ensures that invariants like there + // being a single SHT_SYMTAB section are upheld. + LocalGlobalWeakSymbols Symbols; }; } // end namespace ELFYAML } // end namespace llvm +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Section) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::ELFYAML::Symbol) + namespace llvm { namespace yaml { @@ -77,11 +113,46 @@ struct ScalarEnumerationTraits<ELFYAML::ELF_ELFDATA> { }; template <> +struct ScalarEnumerationTraits<ELFYAML::ELF_ELFOSABI> { + static void enumeration(IO &IO, ELFYAML::ELF_ELFOSABI &Value); +}; + +template <> +struct ScalarEnumerationTraits<ELFYAML::ELF_SHT> { + static void enumeration(IO &IO, ELFYAML::ELF_SHT &Value); +}; + +template <> +struct ScalarBitSetTraits<ELFYAML::ELF_SHF> { + static void bitset(IO &IO, ELFYAML::ELF_SHF &Value); +}; + +template <> +struct ScalarEnumerationTraits<ELFYAML::ELF_STT> { + static void enumeration(IO &IO, ELFYAML::ELF_STT &Value); +}; + +template <> struct MappingTraits<ELFYAML::FileHeader> { static void mapping(IO &IO, ELFYAML::FileHeader &FileHdr); }; template <> +struct MappingTraits<ELFYAML::Symbol> { + static void mapping(IO &IO, ELFYAML::Symbol &Symbol); +}; + +template <> +struct MappingTraits<ELFYAML::LocalGlobalWeakSymbols> { + static void mapping(IO &IO, ELFYAML::LocalGlobalWeakSymbols &Symbols); +}; + +template <> +struct MappingTraits<ELFYAML::Section> { + static void mapping(IO &IO, ELFYAML::Section &Section); +}; + +template <> struct MappingTraits<ELFYAML::Object> { static void mapping(IO &IO, ELFYAML::Object &Object); }; diff --git a/include/llvm/Object/Error.h b/include/llvm/Object/Error.h index fbaf71c..8b0570b 100644 --- a/include/llvm/Object/Error.h +++ b/include/llvm/Object/Error.h @@ -22,17 +22,17 @@ namespace object { const error_category &object_category(); struct object_error { -enum _ { - success = 0, - invalid_file_type, - parse_failed, - unexpected_eof -}; - _ v_; - - object_error(_ v) : v_(v) {} - explicit object_error(int v) : v_(_(v)) {} - operator int() const {return v_;} + enum Impl { + success = 0, + arch_not_found, + invalid_file_type, + parse_failed, + unexpected_eof + }; + Impl V; + + object_error(Impl V) : V(V) {} + operator Impl() const { return V; } }; inline error_code make_error_code(object_error e) { @@ -43,7 +43,8 @@ inline error_code make_error_code(object_error e) { template <> struct is_error_code_enum<object::object_error> : true_type { }; -template <> struct is_error_code_enum<object::object_error::_> : true_type { }; +template <> struct is_error_code_enum<object::object_error::Impl> : true_type { +}; } // end namespace llvm. diff --git a/include/llvm/Object/MachO.h b/include/llvm/Object/MachO.h index 1b9faaa..50435d6 100644 --- a/include/llvm/Object/MachO.h +++ b/include/llvm/Object/MachO.h @@ -17,6 +17,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/Triple.h" #include "llvm/Object/MachOFormat.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Support/MachO.h" @@ -196,6 +197,8 @@ public: bool is64Bit() const; void ReadULEB128s(uint64_t Index, SmallVectorImpl<uint64_t> &Out) const; + static Triple::ArchType getArch(uint32_t CPUType); + static bool classof(const Binary *v) { return v->isMachO(); } diff --git a/include/llvm/Object/MachOFormat.h b/include/llvm/Object/MachOFormat.h index ffca391..96ee8a7 100644 --- a/include/llvm/Object/MachOFormat.h +++ b/include/llvm/Object/MachOFormat.h @@ -95,6 +95,8 @@ namespace macho { enum StructureSizes { Header32Size = 28, Header64Size = 32, + FatHeaderSize = 8, + FatArchHeaderSize = 20, SegmentLoadCommand32Size = 56, SegmentLoadCommand64Size = 72, Section32Size = 68, @@ -130,6 +132,22 @@ namespace macho { uint32_t Reserved; }; + /// \brief Header for universal object files. + struct FatHeader { + uint32_t Magic; + uint32_t NumFatArch; + }; + + /// \brief Header for a single-architecture object file in a + /// universal binary. + struct FatArchHeader { + uint32_t CPUType; + uint32_t CPUSubtype; + uint32_t Offset; + uint32_t Size; + uint32_t Align; + }; + // See <mach-o/loader.h>. enum HeaderFileType { HFT_Object = 0x1 diff --git a/include/llvm/Object/MachOUniversal.h b/include/llvm/Object/MachOUniversal.h new file mode 100644 index 0000000..5743282 --- /dev/null +++ b/include/llvm/Object/MachOUniversal.h @@ -0,0 +1,102 @@ +//===- MachOUniversal.h - Mach-O universal binaries -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares Mach-O fat/universal binaries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MACHOUNIVERSAL_H +#define LLVM_OBJECT_MACHOUNIVERSAL_H + +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/MachOFormat.h" + +namespace llvm { +namespace object { + +class ObjectFile; + +class MachOUniversalBinary : public Binary { + virtual void anchor(); + + uint32_t NumberOfObjects; +public: + class ObjectForArch { + const MachOUniversalBinary *Parent; + /// \brief Index of object in the universal binary. + uint32_t Index; + /// \brief Descriptor of the object. + macho::FatArchHeader Header; + + public: + ObjectForArch(const MachOUniversalBinary *Parent, uint32_t Index); + + void clear() { + Parent = 0; + Index = 0; + } + + bool operator==(const ObjectForArch &Other) const { + return (Parent == Other.Parent) && (Index == Other.Index); + } + + ObjectForArch getNext() const { return ObjectForArch(Parent, Index + 1); } + uint32_t getCPUType() const { return Header.CPUType; } + + error_code getAsObjectFile(OwningPtr<ObjectFile> &Result) const; + }; + + class object_iterator { + ObjectForArch Obj; + public: + object_iterator(const ObjectForArch &Obj) : Obj(Obj) {} + const ObjectForArch* operator->() const { + return &Obj; + } + + bool operator==(const object_iterator &Other) const { + return Obj == Other.Obj; + } + bool operator!=(const object_iterator &Other) const { + return !(*this == Other); + } + + object_iterator& operator++() { // Preincrement + Obj = Obj.getNext(); + return *this; + } + }; + + MachOUniversalBinary(MemoryBuffer *Source, error_code &ec); + + object_iterator begin_objects() const { + return ObjectForArch(this, 0); + } + object_iterator end_objects() const { + return ObjectForArch(0, 0); + } + + uint32_t getNumberOfObjects() const { return NumberOfObjects; } + + // Cast methods. + static inline bool classof(Binary const *V) { + return V->isMachOUniversalBinary(); + } + + error_code getObjectForArch(Triple::ArchType Arch, + OwningPtr<ObjectFile> &Result) const; +}; + +} +} + +#endif diff --git a/include/llvm/Object/RelocVisitor.h b/include/llvm/Object/RelocVisitor.h index 52e4d6f..b1eb4e6 100644 --- a/include/llvm/Object/RelocVisitor.h +++ b/include/llvm/Object/RelocVisitor.h @@ -81,6 +81,8 @@ public: switch (RelocType) { case llvm::ELF::R_PPC64_ADDR32: return visitELF_PPC64_ADDR32(R, Value); + case llvm::ELF::R_PPC64_ADDR64: + return visitELF_PPC64_ADDR64(R, Value); default: HasError = true; return RelocToApply(); @@ -217,6 +219,10 @@ private: uint32_t Res = (Value + Addend) & 0xFFFFFFFF; return RelocToApply(Res, 4); } + RelocToApply visitELF_PPC64_ADDR64(RelocationRef R, uint64_t Value) { + int64_t Addend = getAddend64BE(R); + return RelocToApply(Value + Addend, 8); + } /// PPC32 ELF RelocToApply visitELF_PPC_ADDR32(RelocationRef R, uint64_t Value) { diff --git a/include/llvm/Option/ArgList.h b/include/llvm/Option/ArgList.h index d3accfe..06ba679 100644 --- a/include/llvm/Option/ArgList.h +++ b/include/llvm/Option/ArgList.h @@ -222,8 +222,17 @@ public: /// negation are present, the last one wins. bool hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default=true) const; + /// hasFlag - Given an option \p Pos, an alias \p PosAlias and its negative + /// form \p Neg, return true if the option or its alias is present, false if + /// the negation is present, and \p Default if none of the options are + /// given. If multiple options are present, the last one wins. + bool hasFlag(OptSpecifier Pos, OptSpecifier PosAlias, OptSpecifier Neg, + bool Default = true) const; + /// AddLastArg - Render only the last argument match \p Id0, if present. void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const; + void AddLastArg(ArgStringList &Output, OptSpecifier Id0, + OptSpecifier Id1) const; /// AddAllArgs - Render all arguments matching the given ids. void AddAllArgs(ArgStringList &Output, OptSpecifier Id0, diff --git a/include/llvm/Option/OptParser.td b/include/llvm/Option/OptParser.td index e781fa0..32cc2c0 100644 --- a/include/llvm/Option/OptParser.td +++ b/include/llvm/Option/OptParser.td @@ -14,10 +14,10 @@ // Define the kinds of options. -class OptionKind<string name, int predecence = 0, bit sentinel = 0> { +class OptionKind<string name, int precedence = 0, bit sentinel = 0> { string Name = name; // The kind precedence, kinds with lower precedence are matched first. - int Precedence = predecence; + int Precedence = precedence; // Indicate a sentinel option. bit Sentinel = sentinel; } @@ -89,6 +89,7 @@ class Option<list<string> prefixes, string name, OptionKind kind> { list<OptionFlag> Flags = []; OptionGroup Group = ?; Option Alias = ?; + list<string> AliasArgs = []; } // Helpers for defining options. @@ -113,6 +114,7 @@ class JoinedAndSeparate<list<string> prefixes, string name> // Mix-ins for adding optional attributes. class Alias<Option alias> { Option Alias = alias; } +class AliasArgs<list<string> aliasargs> { list<string> AliasArgs = aliasargs; } class EnumName<string name> { string EnumName = name; } class Flags<list<OptionFlag> flags> { list<OptionFlag> Flags = flags; } class Group<OptionGroup group> { OptionGroup Group = group; } diff --git a/include/llvm/Option/OptTable.h b/include/llvm/Option/OptTable.h index a93acbf..a5b59ce 100644 --- a/include/llvm/Option/OptTable.h +++ b/include/llvm/Option/OptTable.h @@ -44,6 +44,7 @@ public: unsigned short Flags; unsigned short GroupID; unsigned short AliasID; + const char *AliasArgs; }; private: @@ -99,9 +100,6 @@ public: return getInfo(id).GroupID; } - /// \brief Should the help for the given option be hidden by default. - bool isOptionHelpHidden(OptSpecifier id) const; - /// \brief Get the help text to use to describe this option. const char *getOptionHelpText(OptSpecifier id) const { return getInfo(id).HelpText; @@ -119,11 +117,17 @@ public: /// \param [in,out] Index - The current parsing position in the argument /// string list; on return this will be the index of the next argument /// string to parse. + /// \param [in] FlagsToInclude - Only parse options with any of these flags. + /// Zero is the default which includes all flags. + /// \param [in] FlagsToExclude - Don't parse options with this flag. Zero + /// is the default and means exclude nothing. /// /// \return The parsed argument, or 0 if the argument is missing values /// (in which case Index still points at the conceptual next argument string /// to parse). - Arg *ParseOneArg(const ArgList &Args, unsigned &Index) const; + Arg *ParseOneArg(const ArgList &Args, unsigned &Index, + unsigned FlagsToInclude = 0, + unsigned FlagsToExclude = 0) const; /// \brief Parse an list of arguments into an InputArgList. /// @@ -139,19 +143,31 @@ public: /// \param MissingArgIndex - On error, the index of the option which could /// not be parsed. /// \param MissingArgCount - On error, the number of missing options. + /// \param FlagsToInclude - Only parse options with any of these flags. + /// Zero is the default which includes all flags. + /// \param FlagsToExclude - Don't parse options with this flag. Zero + /// is the default and means exclude nothing. /// \return An InputArgList; on error this will contain all the options /// which could be parsed. InputArgList *ParseArgs(const char* const *ArgBegin, const char* const *ArgEnd, unsigned &MissingArgIndex, - unsigned &MissingArgCount) const; + unsigned &MissingArgCount, + unsigned FlagsToInclude = 0, + unsigned FlagsToExclude = 0) const; /// \brief Render the help text for an option table. /// /// \param OS - The stream to write the help text to. /// \param Name - The name to use in the usage line. /// \param Title - The title to use in the usage line. - /// \param ShowHidden - Whether help-hidden arguments should be shown. + /// \param FlagsToInclude - If non-zero, only include options with any + /// of these flags set. + /// \param FlagsToExclude - Exclude options with any of these flags set. + void PrintHelp(raw_ostream &OS, const char *Name, + const char *Title, unsigned FlagsToInclude, + unsigned FlagsToExclude) const; + void PrintHelp(raw_ostream &OS, const char *Name, const char *Title, bool ShowHidden = false) const; }; diff --git a/include/llvm/Option/Option.h b/include/llvm/Option/Option.h index 4861b59..47fd817 100644 --- a/include/llvm/Option/Option.h +++ b/include/llvm/Option/Option.h @@ -103,6 +103,16 @@ public: return Owner->getOption(Info->AliasID); } + /// \brief Get the alias arguments as a \0 separated list. + /// E.g. ["foo", "bar"] would be returned as "foo\0bar\0". + const char *getAliasArgs() const { + assert(Info && "Must have a valid info!"); + assert((!Info->AliasArgs || Info->AliasArgs[0] != 0) && + "AliasArgs should be either 0 or non-empty."); + + return Info->AliasArgs; + } + /// \brief Get the default prefix for this option. StringRef getPrefix() const { const char *Prefix = *Info->Prefixes; diff --git a/include/llvm/Support/BlockFrequency.h b/include/llvm/Support/BlockFrequency.h index 839cf93..666b3c8 100644 --- a/include/llvm/Support/BlockFrequency.h +++ b/include/llvm/Support/BlockFrequency.h @@ -25,17 +25,35 @@ class BranchProbability; class BlockFrequency { uint64_t Frequency; - static const int64_t ENTRY_FREQ = 1024; + static const int64_t ENTRY_FREQ = 1 << 14; + + // Scale frequency by N/D, saturating on overflow. + void scale(uint32_t N, uint32_t D); public: BlockFrequency(uint64_t Freq = 0) : Frequency(Freq) { } + /// \brief Returns the frequency of the entry block of the function. static uint64_t getEntryFrequency() { return ENTRY_FREQ; } + + /// \brief Returns the maximum possible frequency, the saturation value. + static uint64_t getMaxFrequency() { return -1ULL; } + + /// \brief Returns the frequency as a fixpoint number scaled by the entry + /// frequency. uint64_t getFrequency() const { return Frequency; } + /// \brief Multiplies with a branch probability. The computation will never + /// overflow. BlockFrequency &operator*=(const BranchProbability &Prob); const BlockFrequency operator*(const BranchProbability &Prob) const; + /// \brief Divide by a non-zero branch probability using saturating + /// arithmetic. + BlockFrequency &operator/=(const BranchProbability &Prob); + BlockFrequency operator/(const BranchProbability &Prob) const; + + /// \brief Adds another block frequency using saturating arithmetic. BlockFrequency &operator+=(const BlockFrequency &Freq); const BlockFrequency operator+(const BlockFrequency &Freq) const; diff --git a/include/llvm/Support/CFG.h b/include/llvm/Support/CFG.h index 71a83e9..74ec726 100644 --- a/include/llvm/Support/CFG.h +++ b/include/llvm/Support/CFG.h @@ -328,7 +328,7 @@ template <> struct GraphTraits<Function*> : public GraphTraits<BasicBlock*> { typedef Function::iterator nodes_iterator; static nodes_iterator nodes_begin(Function *F) { return F->begin(); } static nodes_iterator nodes_end (Function *F) { return F->end(); } - static unsigned size (Function *F) { return F->size(); } + static size_t size (Function *F) { return F->size(); } }; template <> struct GraphTraits<const Function*> : public GraphTraits<const BasicBlock*> { @@ -338,7 +338,7 @@ template <> struct GraphTraits<const Function*> : typedef Function::const_iterator nodes_iterator; static nodes_iterator nodes_begin(const Function *F) { return F->begin(); } static nodes_iterator nodes_end (const Function *F) { return F->end(); } - static unsigned size (const Function *F) { return F->size(); } + static size_t size (const Function *F) { return F->size(); } }; diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index d348b76..a39a3f9 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -488,6 +488,24 @@ namespace COFF { uint32_t Size; }; + enum DataDirectoryIndex { + EXPORT_TABLE = 0, + IMPORT_TABLE, + RESOURCE_TABLE, + EXCEPTION_TABLE, + CERTIFICATE_TABLE, + BASE_RELOCATION_TABLE, + DEBUG, + ARCHITECTURE, + GLOBAL_PTR, + TLS_TABLE, + LOAD_CONFIG_TABLE, + BOUND_IMPORT, + IAT, + DELAY_IMPORT_DESCRIPTOR, + CLR_RUNTIME_HEADER + }; + enum WindowsSubsystem { IMAGE_SUBSYSTEM_UNKNOWN = 0, ///< An unknown subsystem. IMAGE_SUBSYSTEM_NATIVE = 1, ///< Device drivers and native Windows processes diff --git a/include/llvm/Support/CallSite.h b/include/llvm/Support/CallSite.h index d80d9d8..2a1c5ca 100644 --- a/include/llvm/Support/CallSite.h +++ b/include/llvm/Support/CallSite.h @@ -198,6 +198,12 @@ public: CALLSITE_DELEGATE_GETTER(getParamAlignment(i)); } + /// \brief Return true if the call should not be treated as a call to a + /// builtin. + bool isNoBuiltin() const { + CALLSITE_DELEGATE_GETTER(isNoBuiltin()); + } + /// @brief Return true if the call should not be inlined. bool isNoInline() const { CALLSITE_DELEGATE_GETTER(isNoInline()); @@ -251,6 +257,15 @@ public: return paramHasAttr(ArgNo + 1, Attribute::ByVal); } + bool doesNotAccessMemory(unsigned ArgNo) const { + return paramHasAttr(ArgNo + 1, Attribute::ReadNone); + } + + bool onlyReadsMemory(unsigned ArgNo) const { + return paramHasAttr(ArgNo + 1, Attribute::ReadOnly) || + paramHasAttr(ArgNo + 1, Attribute::ReadNone); + } + /// hasArgument - Returns true if this CallSite passes the given Value* as an /// argument to the called function. bool hasArgument(const Value *Arg) const { diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h index 0d2d6c9..d70acbf 100644 --- a/include/llvm/Support/Casting.h +++ b/include/llvm/Support/Casting.h @@ -206,7 +206,10 @@ template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy> { } }; - +template <class X> struct is_simple_type { + static const bool value = + is_same<X, typename simplify_type<X>::SimpleType>::value; +}; // cast<X> - Return the argument parameter cast to the specified type. This // casting operator asserts that the type is correct, so it does not return null @@ -216,10 +219,12 @@ template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy> { // cast<Instruction>(myVal)->getParent() // template <class X, class Y> -inline typename cast_retty<X, const Y>::ret_type cast(const Y &Val) { +inline typename enable_if_c<!is_simple_type<Y>::value, + typename cast_retty<X, const Y>::ret_type>::type +cast(const Y &Val) { assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); - return cast_convert_val<X, const Y, - typename simplify_type<const Y>::SimpleType>::doit(Val); + return cast_convert_val< + X, const Y, typename simplify_type<const Y>::SimpleType>::doit(Val); } template <class X, class Y> @@ -230,10 +235,7 @@ inline typename cast_retty<X, Y>::ret_type cast(Y &Val) { } template <class X, class Y> -inline typename enable_if< - is_same<Y, typename simplify_type<Y>::SimpleType>, - typename cast_retty<X, Y*>::ret_type ->::type cast(Y *Val) { +inline typename cast_retty<X, Y *>::ret_type cast(Y *Val) { assert(isa<X>(Val) && "cast<Ty>() argument of incompatible type!"); return cast_convert_val<X, Y*, typename simplify_type<Y*>::SimpleType>::doit(Val); @@ -259,7 +261,9 @@ inline typename cast_retty<X, Y*>::ret_type cast_or_null(Y *Val) { // template <class X, class Y> -inline typename cast_retty<X, const Y>::ret_type dyn_cast(const Y &Val) { +inline typename enable_if_c<!is_simple_type<Y>::value, + typename cast_retty<X, const Y>::ret_type>::type +dyn_cast(const Y &Val) { return isa<X>(Val) ? cast<X>(Val) : 0; } @@ -269,10 +273,7 @@ inline typename cast_retty<X, Y>::ret_type dyn_cast(Y &Val) { } template <class X, class Y> -inline typename enable_if< - is_same<Y, typename simplify_type<Y>::SimpleType>, - typename cast_retty<X, Y*>::ret_type ->::type dyn_cast(Y *Val) { +inline typename cast_retty<X, Y *>::ret_type dyn_cast(Y *Val) { return isa<X>(Val) ? cast<X>(Val) : 0; } diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index 531760b..c0bfbae 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -1745,6 +1745,59 @@ void PrintHelpMessage(bool Hidden=false, bool Categorized=false); /// llvm::cl::ParseCommandLineOptions(). void getRegisteredOptions(StringMap<Option*> &Map); +//===----------------------------------------------------------------------===// +// Standalone command line processing utilities. +// + +/// \brief Saves strings in the inheritor's stable storage and returns a stable +/// raw character pointer. +class StringSaver { +public: + virtual const char *SaveString(const char *Str) = 0; + virtual ~StringSaver() {}; // Pacify -Wnon-virtual-dtor. +}; + +/// \brief Tokenizes a command line that can contain escapes and quotes. +// +/// The quoting rules match those used by GCC and other tools that use +/// libiberty's buildargv() or expandargv() utilities, and do not match bash. +/// They differ from buildargv() on treatment of backslashes that do not escape +/// a special character to make it possible to accept most Windows file paths. +/// +/// \param [in] Source The string to be split on whitespace with quotes. +/// \param [in] Saver Delegates back to the caller for saving parsed strings. +/// \param [out] NewArgv All parsed strings are appended to NewArgv. +void TokenizeGNUCommandLine(StringRef Source, StringSaver &Saver, + SmallVectorImpl<const char *> &NewArgv); + +/// \brief Tokenizes a Windows command line which may contain quotes and escaped +/// quotes. +/// +/// See MSDN docs for CommandLineToArgvW for information on the quoting rules. +/// http://msdn.microsoft.com/en-us/library/windows/desktop/17w5ykft(v=vs.85).aspx +/// +/// \param [in] Source The string to be split on whitespace with quotes. +/// \param [in] Saver Delegates back to the caller for saving parsed strings. +/// \param [out] NewArgv All parsed strings are appended to NewArgv. +void TokenizeWindowsCommandLine(StringRef Source, StringSaver &Saver, + SmallVectorImpl<const char *> &NewArgv); + +/// \brief String tokenization function type. Should be compatible with either +/// Windows or Unix command line tokenizers. +typedef void (*TokenizerCallback)(StringRef Source, StringSaver &Saver, + SmallVectorImpl<const char *> &NewArgv); + +/// \brief Expand response files on a command line recursively using the given +/// StringSaver and tokenization strategy. Argv should contain the command line +/// before expansion and will be modified in place. +/// +/// \param [in] Saver Delegates back to the caller for saving parsed strings. +/// \param [in] Tokenizer Tokenization strategy. Typically Unix or Windows. +/// \param [in,out] Argv Command line into which to expand response files. +/// \return true if all @files were expanded successfully or there were none. +bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, + SmallVectorImpl<const char *> &Argv); + } // End namespace cl } // End namespace llvm diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index 13d057b..feac934 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -21,6 +21,25 @@ # define __has_feature(x) 0 #endif +#ifndef __has_attribute +# define __has_attribute(x) 0 +#endif + +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif + +/// \macro __GNUC_PREREQ +/// \brief Defines __GNUC_PREREQ if glibc's features.h isn't available. +#ifndef __GNUC_PREREQ +# if defined(__GNUC__) && defined(__GNUC_MINOR__) +# define __GNUC_PREREQ(maj, min) \ + ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min)) +# else +# define __GNUC_PREREQ(maj, min) 0 +# endif +#endif + /// \brief Does the compiler support r-value references? /// This implies that <utility> provides the one-argument std::move; it /// does not imply the existence of any other C++ library features. @@ -146,13 +165,15 @@ /// into a shared library, then the class should be private to the library and /// not accessible from outside it. Can also be used to mark variables and /// functions, making them private to any shared library they are linked into. -#if (__GNUC__ >= 4) && !defined(__MINGW32__) && !defined(__CYGWIN__) +/// On PE/COFF targets, library visibility is the default, so this isn't needed. +#if (__has_attribute(visibility) || __GNUC_PREREQ(4, 0)) && \ + !defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32) #define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden"))) #else #define LLVM_LIBRARY_VISIBILITY #endif -#if (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#if __has_attribute(used) || __GNUC_PREREQ(3, 1) #define LLVM_ATTRIBUTE_USED __attribute__((__used__)) #else #define LLVM_ATTRIBUTE_USED @@ -166,31 +187,37 @@ // more portable solution: // (void)unused_var_name; // Prefer cast-to-void wherever it is sufficient. -#if (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) +#if __has_attribute(unused) || __GNUC_PREREQ(3, 1) #define LLVM_ATTRIBUTE_UNUSED __attribute__((__unused__)) #else #define LLVM_ATTRIBUTE_UNUSED #endif -#if (__GNUC__ >= 4) && !defined(__MINGW32__) && !defined(__CYGWIN__) +// FIXME: Provide this for PE/COFF targets. +#if (__has_attribute(weak) || __GNUC_PREREQ(4, 0)) && \ + (!defined(__MINGW32__) && !defined(__CYGWIN__) && !defined(LLVM_ON_WIN32)) #define LLVM_ATTRIBUTE_WEAK __attribute__((__weak__)) #else #define LLVM_ATTRIBUTE_WEAK #endif -#ifdef __GNUC__ // aka 'CONST' but following LLVM Conventions. +// Prior to clang 3.2, clang did not accept any spelling of +// __has_attribute(const), so assume it is supported. +#if defined(__clang__) || defined(__GNUC__) +// aka 'CONST' but following LLVM Conventions. #define LLVM_READNONE __attribute__((__const__)) #else #define LLVM_READNONE #endif -#ifdef __GNUC__ // aka 'PURE' but following LLVM Conventions. +#if __has_attribute(pure) || defined(__GNUC__) +// aka 'PURE' but following LLVM Conventions. #define LLVM_READONLY __attribute__((__pure__)) #else #define LLVM_READONLY #endif -#if (__GNUC__ >= 4) +#if __has_builtin(__builtin_expect) || __GNUC_PREREQ(4, 0) #define LLVM_LIKELY(EXPR) __builtin_expect((bool)(EXPR), true) #define LLVM_UNLIKELY(EXPR) __builtin_expect((bool)(EXPR), false) #else @@ -213,7 +240,7 @@ /// LLVM_ATTRIBUTE_NOINLINE - On compilers where we have a directive to do so, /// mark a method "not for inlining". -#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +#if __has_attribute(noinline) || __GNUC_PREREQ(3, 4) #define LLVM_ATTRIBUTE_NOINLINE __attribute__((noinline)) #elif defined(_MSC_VER) #define LLVM_ATTRIBUTE_NOINLINE __declspec(noinline) @@ -225,7 +252,7 @@ /// so, mark a method "always inline" because it is performance sensitive. GCC /// 3.4 supported this but is buggy in various cases and produces unimplemented /// errors, just use it in GCC 4.0 and later. -#if __GNUC__ > 3 +#if __has_attribute(always_inline) || __GNUC_PREREQ(4, 0) #define LLVM_ATTRIBUTE_ALWAYS_INLINE inline __attribute__((always_inline)) #elif defined(_MSC_VER) #define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline @@ -267,8 +294,7 @@ /// LLVM_BUILTIN_UNREACHABLE - On compilers which support it, expands /// to an expression which states that it is undefined behavior for the /// compiler to reach this point. Otherwise is not defined. -#if defined(__clang__) || (__GNUC__ > 4) \ - || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5) +#if __has_builtin(__builtin_unreachable) || __GNUC_PREREQ(4, 5) # define LLVM_BUILTIN_UNREACHABLE __builtin_unreachable() #elif defined(_MSC_VER) # define LLVM_BUILTIN_UNREACHABLE __assume(false) @@ -276,8 +302,7 @@ /// LLVM_BUILTIN_TRAP - On compilers which support it, expands to an expression /// which causes the program to exit abnormally. -#if defined(__clang__) || (__GNUC__ > 4) \ - || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) +#if __has_builtin(__builtin_trap) || __GNUC_PREREQ(4, 3) # define LLVM_BUILTIN_TRAP __builtin_trap() #else # define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0 @@ -285,11 +310,10 @@ /// \macro LLVM_ASSUME_ALIGNED /// \brief Returns a pointer with an assumed alignment. -#if !defined(__clang__) && ((__GNUC__ > 4) \ - || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) -// FIXME: Enable on clang when it supports it. +#if __has_builtin(__builtin_assume_aligned) && __GNUC_PREREQ(4, 7) # define LLVM_ASSUME_ALIGNED(p, a) __builtin_assume_aligned(p, a) #elif defined(LLVM_BUILTIN_UNREACHABLE) +// As of today, clang does not support __builtin_assume_aligned. # define LLVM_ASSUME_ALIGNED(p, a) \ (((uintptr_t(p) % (a)) == 0) ? (p) : (LLVM_BUILTIN_UNREACHABLE, (p))) #else diff --git a/include/llvm/Support/ConstantRange.h b/include/llvm/Support/ConstantRange.h index 0f29256..f757c6e 100644 --- a/include/llvm/Support/ConstantRange.h +++ b/include/llvm/Support/ConstantRange.h @@ -42,6 +42,14 @@ namespace llvm { class ConstantRange { APInt Lower, Upper; +#if LLVM_HAS_RVALUE_REFERENCES + // If we have move semantics, pass APInts by value and move them into place. + typedef APInt APIntMoveTy; +#else + // Otherwise pass by const ref to save one copy. + typedef const APInt &APIntMoveTy; +#endif + public: /// Initialize a full (the default) or empty set for the specified bit width. /// @@ -49,12 +57,12 @@ public: /// Initialize a range to hold the single specified value. /// - ConstantRange(const APInt &Value); + ConstantRange(APIntMoveTy Value); /// @brief Initialize a range of values explicitly. This will assert out if /// Lower==Upper and Lower != Min or Max value for its type. It will also /// assert out if the two APInt's are not the same bit width. - ConstantRange(const APInt &Lower, const APInt &Upper); + ConstantRange(APIntMoveTy Lower, APIntMoveTy Upper); /// makeICmpRegion - Produce the smallest range that contains all values that /// might satisfy the comparison specified by Pred when compared to any value diff --git a/include/llvm/Support/ConvertUTF.h b/include/llvm/Support/ConvertUTF.h index 1eae6d6..2820366 100644 --- a/include/llvm/Support/ConvertUTF.h +++ b/include/llvm/Support/ConvertUTF.h @@ -87,8 +87,8 @@ ------------------------------------------------------------------------ */ -#ifndef CLANG_BASIC_CONVERTUTF_H -#define CLANG_BASIC_CONVERTUTF_H +#ifndef LLVM_SUPPORT_CONVERTUTF_H +#define LLVM_SUPPORT_CONVERTUTF_H /* --------------------------------------------------------------------- The following 4 definitions are compiler-specific. @@ -112,6 +112,9 @@ typedef unsigned char Boolean; /* 0 or 1 */ #define UNI_MAX_UTF8_BYTES_PER_CODE_POINT 4 +#define UNI_UTF16_BYTE_ORDER_MARK_NATIVE 0xFEFF +#define UNI_UTF16_BYTE_ORDER_MARK_SWAPPED 0xFFFE + typedef enum { conversionOK, /* conversion successful */ sourceExhausted, /* partial character in source, but hit end */ @@ -165,6 +168,7 @@ unsigned getNumBytesForUTF8(UTF8 firstByte); /*************************************************************************/ /* Below are LLVM-specific wrappers of the functions above. */ +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" namespace llvm { @@ -219,6 +223,22 @@ static inline ConversionResult convertUTF8Sequence(const UTF8 **source, return sourceExhausted; return ConvertUTF8toUTF32(source, *source + size, &target, target + 1, flags); } + +/** + * Returns true if a blob of text starts with a UTF-16 big or little endian byte + * order mark. + */ +bool hasUTF16ByteOrderMark(ArrayRef<char> SrcBytes); + +/** + * Converts a stream of raw bytes assumed to be UTF16 into a UTF8 std::string. + * + * \param [in] SrcBytes A buffer of what is assumed to be UTF-16 encoded text. + * \param [out] Out Converted UTF-8 is stored here on success. + * \returns true on success + */ +bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out); + } /* end namespace llvm */ #endif diff --git a/include/llvm/Support/DataTypes.h.cmake b/include/llvm/Support/DataTypes.h.cmake index 7484abd..a26070c 100644 --- a/include/llvm/Support/DataTypes.h.cmake +++ b/include/llvm/Support/DataTypes.h.cmake @@ -26,7 +26,6 @@ #ifndef SUPPORT_DATATYPES_H #define SUPPORT_DATATYPES_H -#cmakedefine HAVE_SYS_TYPES_H ${HAVE_SYS_TYPES_H} #cmakedefine HAVE_INTTYPES_H ${HAVE_INTTYPES_H} #cmakedefine HAVE_STDINT_H ${HAVE_STDINT_H} #cmakedefine HAVE_UINT64_T ${HAVE_UINT64_T} @@ -54,9 +53,7 @@ #endif /* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */ -#ifdef HAVE_SYS_TYPES_H #include <sys/types.h> -#endif #ifdef HAVE_INTTYPES_H #include <inttypes.h> @@ -101,7 +98,11 @@ typedef short int16_t; typedef unsigned short uint16_t; typedef signed char int8_t; typedef unsigned char uint8_t; -typedef signed int ssize_t; +#if defined(_WIN64) + typedef signed __int64 ssize_t; +#else + typedef signed int ssize_t; +#endif #ifndef INT8_MAX # define INT8_MAX 127 #endif diff --git a/include/llvm/Support/DataTypes.h.in b/include/llvm/Support/DataTypes.h.in index b9fb48a..7fc9b72 100644 --- a/include/llvm/Support/DataTypes.h.in +++ b/include/llvm/Support/DataTypes.h.in @@ -26,7 +26,6 @@ #ifndef SUPPORT_DATATYPES_H #define SUPPORT_DATATYPES_H -#undef HAVE_SYS_TYPES_H #undef HAVE_INTTYPES_H #undef HAVE_STDINT_H #undef HAVE_UINT64_T @@ -54,9 +53,7 @@ #endif /* Note that <inttypes.h> includes <stdint.h>, if this is a C99 system. */ -#ifdef HAVE_SYS_TYPES_H #include <sys/types.h> -#endif #ifdef HAVE_INTTYPES_H #include <inttypes.h> @@ -98,7 +95,12 @@ typedef short int16_t; typedef unsigned short uint16_t; typedef signed char int8_t; typedef unsigned char uint8_t; -typedef signed int ssize_t; +#if defined(_WIN64) + typedef signed __int64 ssize_t; +#else + typedef signed int ssize_t; +#endif + #ifndef INT8_MAX # define INT8_MAX 127 #endif diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h index b52914f..d0e2322 100644 --- a/include/llvm/Support/Dwarf.h +++ b/include/llvm/Support/Dwarf.h @@ -272,6 +272,8 @@ enum dwarf_constants { DW_AT_GNU_vector = 0x2107, DW_AT_GNU_template_name = 0x2110, + DW_AT_GNU_odr_signature = 0x210f, + // Extensions for Fission proposal. DW_AT_GNU_dwo_name = 0x2130, DW_AT_GNU_dwo_id = 0x2131, diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index ac11f0a..54da31c 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -276,7 +276,6 @@ enum { EM_STM8 = 186, // STMicroeletronics STM8 8-bit microcontroller EM_TILE64 = 187, // Tilera TILE64 multicore architecture family EM_TILEPRO = 188, // Tilera TILEPro multicore architecture family - EM_MICROBLAZE = 189, // Xilinx MicroBlaze 32-bit RISC soft processor core EM_CUDA = 190, // NVIDIA CUDA architecture EM_TILEGX = 191, // Tilera TILE-Gx multicore architecture family EM_CLOUDSHIELD = 192, // CloudShield architecture family @@ -287,8 +286,7 @@ enum { EM_RL78 = 197, // Renesas RL78 family EM_VIDEOCORE5 = 198, // Broadcom VideoCore V processor EM_78KOR = 199, // Renesas 78KOR family - EM_56800EX = 200, // Freescale 56800EX Digital Signal Controller (DSC) - EM_MBLAZE = 47787 // Xilinx MicroBlaze + EM_56800EX = 200 // Freescale 56800EX Digital Signal Controller (DSC) }; // Object file classes. @@ -418,32 +416,6 @@ enum { R_386_NUM = 43 }; -// MBlaze relocations. -enum { - R_MICROBLAZE_NONE = 0, - R_MICROBLAZE_32 = 1, - R_MICROBLAZE_32_PCREL = 2, - R_MICROBLAZE_64_PCREL = 3, - R_MICROBLAZE_32_PCREL_LO = 4, - R_MICROBLAZE_64 = 5, - R_MICROBLAZE_32_LO = 6, - R_MICROBLAZE_SRO32 = 7, - R_MICROBLAZE_SRW32 = 8, - R_MICROBLAZE_64_NONE = 9, - R_MICROBLAZE_32_SYM_OP_SYM = 10, - R_MICROBLAZE_GNU_VTINHERIT = 11, - R_MICROBLAZE_GNU_VTENTRY = 12, - R_MICROBLAZE_GOTPC_64 = 13, - R_MICROBLAZE_GOT_64 = 14, - R_MICROBLAZE_PLT_64 = 15, - R_MICROBLAZE_REL = 16, - R_MICROBLAZE_JUMP_SLOT = 17, - R_MICROBLAZE_GLOB_DAT = 18, - R_MICROBLAZE_GOTOFF_64 = 19, - R_MICROBLAZE_GOTOFF_32 = 20, - R_MICROBLAZE_COPY = 21 -}; - // ELF Relocation types for PPC32 enum { R_PPC_NONE = 0, /* No relocation. */ @@ -460,9 +432,45 @@ enum { R_PPC_REL14 = 11, R_PPC_REL14_BRTAKEN = 12, R_PPC_REL14_BRNTAKEN = 13, + R_PPC_GOT16 = 14, + R_PPC_GOT16_LO = 15, + R_PPC_GOT16_HI = 16, + R_PPC_GOT16_HA = 17, R_PPC_REL32 = 26, + R_PPC_TLS = 67, + R_PPC_DTPMOD32 = 68, + R_PPC_TPREL16 = 69, R_PPC_TPREL16_LO = 70, - R_PPC_TPREL16_HA = 72 + R_PPC_TPREL16_HI = 71, + R_PPC_TPREL16_HA = 72, + R_PPC_TPREL32 = 73, + R_PPC_DTPREL16 = 74, + R_PPC_DTPREL16_LO = 75, + R_PPC_DTPREL16_HI = 76, + R_PPC_DTPREL16_HA = 77, + R_PPC_DTPREL32 = 78, + R_PPC_GOT_TLSGD16 = 79, + R_PPC_GOT_TLSGD16_LO = 80, + R_PPC_GOT_TLSGD16_HI = 81, + R_PPC_GOT_TLSGD16_HA = 82, + R_PPC_GOT_TLSLD16 = 83, + R_PPC_GOT_TLSLD16_LO = 84, + R_PPC_GOT_TLSLD16_HI = 85, + R_PPC_GOT_TLSLD16_HA = 86, + R_PPC_GOT_TPREL16 = 87, + R_PPC_GOT_TPREL16_LO = 88, + R_PPC_GOT_TPREL16_HI = 89, + R_PPC_GOT_TPREL16_HA = 90, + R_PPC_GOT_DTPREL16 = 91, + R_PPC_GOT_DTPREL16_LO = 92, + R_PPC_GOT_DTPREL16_HI = 93, + R_PPC_GOT_DTPREL16_HA = 94, + R_PPC_TLSGD = 95, + R_PPC_TLSLD = 96, + R_PPC_REL16 = 249, + R_PPC_REL16_LO = 250, + R_PPC_REL16_HI = 251, + R_PPC_REL16_HA = 252 }; // ELF Relocation types for PPC64 @@ -481,32 +489,74 @@ enum { R_PPC64_REL14 = 11, R_PPC64_REL14_BRTAKEN = 12, R_PPC64_REL14_BRNTAKEN = 13, + R_PPC64_GOT16 = 14, + R_PPC64_GOT16_LO = 15, + R_PPC64_GOT16_HI = 16, + R_PPC64_GOT16_HA = 17, R_PPC64_REL32 = 26, R_PPC64_ADDR64 = 38, R_PPC64_ADDR16_HIGHER = 39, + R_PPC64_ADDR16_HIGHERA = 40, R_PPC64_ADDR16_HIGHEST = 41, + R_PPC64_ADDR16_HIGHESTA = 42, R_PPC64_REL64 = 44, R_PPC64_TOC16 = 47, R_PPC64_TOC16_LO = 48, + R_PPC64_TOC16_HI = 49, R_PPC64_TOC16_HA = 50, R_PPC64_TOC = 51, R_PPC64_ADDR16_DS = 56, R_PPC64_ADDR16_LO_DS = 57, + R_PPC64_GOT16_DS = 58, + R_PPC64_GOT16_LO_DS = 59, R_PPC64_TOC16_DS = 63, R_PPC64_TOC16_LO_DS = 64, R_PPC64_TLS = 67, + R_PPC64_DTPMOD64 = 68, + R_PPC64_TPREL16 = 69, R_PPC64_TPREL16_LO = 70, + R_PPC64_TPREL16_HI = 71, R_PPC64_TPREL16_HA = 72, + R_PPC64_TPREL64 = 73, + R_PPC64_DTPREL16 = 74, R_PPC64_DTPREL16_LO = 75, + R_PPC64_DTPREL16_HI = 76, R_PPC64_DTPREL16_HA = 77, + R_PPC64_DTPREL64 = 78, + R_PPC64_GOT_TLSGD16 = 79, R_PPC64_GOT_TLSGD16_LO = 80, + R_PPC64_GOT_TLSGD16_HI = 81, R_PPC64_GOT_TLSGD16_HA = 82, + R_PPC64_GOT_TLSLD16 = 83, R_PPC64_GOT_TLSLD16_LO = 84, + R_PPC64_GOT_TLSLD16_HI = 85, R_PPC64_GOT_TLSLD16_HA = 86, + R_PPC64_GOT_TPREL16_DS = 87, R_PPC64_GOT_TPREL16_LO_DS = 88, + R_PPC64_GOT_TPREL16_HI = 89, R_PPC64_GOT_TPREL16_HA = 90, + R_PPC64_GOT_DTPREL16_DS = 91, + R_PPC64_GOT_DTPREL16_LO_DS = 92, + R_PPC64_GOT_DTPREL16_HI = 93, + R_PPC64_GOT_DTPREL16_HA = 94, + R_PPC64_TPREL16_DS = 95, + R_PPC64_TPREL16_LO_DS = 96, + R_PPC64_TPREL16_HIGHER = 97, + R_PPC64_TPREL16_HIGHERA = 98, + R_PPC64_TPREL16_HIGHEST = 99, + R_PPC64_TPREL16_HIGHESTA = 100, + R_PPC64_DTPREL16_DS = 101, + R_PPC64_DTPREL16_LO_DS = 102, + R_PPC64_DTPREL16_HIGHER = 103, + R_PPC64_DTPREL16_HIGHERA = 104, + R_PPC64_DTPREL16_HIGHEST = 105, + R_PPC64_DTPREL16_HIGHESTA = 106, R_PPC64_TLSGD = 107, - R_PPC64_TLSLD = 108 + R_PPC64_TLSLD = 108, + R_PPC64_REL16 = 249, + R_PPC64_REL16_LO = 250, + R_PPC64_REL16_HI = 251, + R_PPC64_REL16_HA = 252 }; // ELF Relocation types for AArch64 @@ -790,6 +840,8 @@ enum { R_MIPS_PC16 = 10, R_MIPS_CALL16 = 11, R_MIPS_GPREL32 = 12, + R_MIPS_UNUSED1 = 13, + R_MIPS_UNUSED2 = 14, R_MIPS_SHIFT5 = 16, R_MIPS_SHIFT6 = 17, R_MIPS_64 = 18, diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index 570b34b..c130b47 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -33,6 +33,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/TimeValue.h" #include "llvm/Support/system_error.h" #include <ctime> #include <iterator> @@ -72,22 +73,6 @@ private: int v_; }; -/// copy_option - An "enum class" enumeration of copy semantics for copy -/// operations. -struct copy_option { - enum _ { - fail_if_exists, - overwrite_if_exists - }; - - copy_option(_ v) : v_(v) {} - explicit copy_option(int v) : v_(_(v)) {} - operator int() const {return v_;} - -private: - int v_; -}; - /// space_info - Self explanatory. struct space_info { uint64_t capacity; @@ -95,30 +80,28 @@ struct space_info { uint64_t available; }; - enum perms { - no_perms = 0, - owner_read = 0400, - owner_write = 0200, - owner_exe = 0100, - owner_all = owner_read | owner_write | owner_exe, - group_read = 040, - group_write = 020, - group_exe = 010, - group_all = group_read | group_write | group_exe, - others_read = 04, - others_write = 02, - others_exe = 01, - others_all = others_read | others_write | others_exe, - all_all = owner_all | group_all | others_all, - set_uid_on_exe = 04000, - set_gid_on_exe = 02000, - sticky_bit = 01000, - perms_mask = all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit, - perms_not_known = 0xFFFF, - add_perms = 0x1000, - remove_perms = 0x2000, - symlink_perms = 0x4000 + no_perms = 0, + owner_read = 0400, + owner_write = 0200, + owner_exe = 0100, + owner_all = owner_read | owner_write | owner_exe, + group_read = 040, + group_write = 020, + group_exe = 010, + group_all = group_read | group_write | group_exe, + others_read = 04, + others_write = 02, + others_exe = 01, + others_all = others_read | others_write | others_exe, + all_read = owner_read | group_read | others_read, + all_write = owner_write | group_write | others_write, + all_exe = owner_exe | group_exe | others_exe, + all_all = owner_all | group_all | others_all, + set_uid_on_exe = 04000, + set_gid_on_exe = 02000, + sticky_bit = 01000, + perms_not_known = 0xFFFF }; // Helper functions so that you can use & and | to manipulate perms bits: @@ -142,8 +125,25 @@ inline perms operator~(perms x) { return static_cast<perms>(~static_cast<unsigned short>(x)); } +class UniqueID { + uint64_t Device; + uint64_t File; + +public: + UniqueID() {} + UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {} + bool operator==(const UniqueID &Other) const { + return Device == Other.Device && File == Other.File; + } + bool operator!=(const UniqueID &Other) const { return !(*this == Other); } + bool operator<(const UniqueID &Other) const { + return Device < Other.Device || + (Device == Other.Device && File < Other.File); + } + uint64_t getDevice() const { return Device; } + uint64_t getFile() const { return File; } +}; - /// file_status - Represents the result of a call to stat and friends. It has /// a platform specific member to store the result. class file_status @@ -151,6 +151,10 @@ class file_status #if defined(LLVM_ON_UNIX) dev_t fs_st_dev; ino_t fs_st_ino; + time_t fs_st_mtime; + uid_t fs_st_uid; + gid_t fs_st_gid; + off_t fs_st_size; #elif defined (LLVM_ON_WIN32) uint32_t LastWriteTimeHigh; uint32_t LastWriteTimeLow; @@ -161,18 +165,51 @@ class file_status uint32_t FileIndexLow; #endif friend bool equivalent(file_status A, file_status B); - friend error_code status(const Twine &path, file_status &result); file_type Type; perms Perms; public: - explicit file_status(file_type v=file_type::status_error, - perms prms=perms_not_known) - : Type(v), Perms(prms) {} + file_status() : Type(file_type::status_error) {} + file_status(file_type Type) : Type(Type) {} + + #if defined(LLVM_ON_UNIX) + file_status(file_type Type, perms Perms, dev_t Dev, ino_t Ino, time_t MTime, + uid_t UID, gid_t GID, off_t Size) + : fs_st_dev(Dev), fs_st_ino(Ino), fs_st_mtime(MTime), fs_st_uid(UID), + fs_st_gid(GID), fs_st_size(Size), Type(Type), Perms(Perms) {} + #elif defined(LLVM_ON_WIN32) + file_status(file_type Type, uint32_t LastWriteTimeHigh, + uint32_t LastWriteTimeLow, uint32_t VolumeSerialNumber, + uint32_t FileSizeHigh, uint32_t FileSizeLow, + uint32_t FileIndexHigh, uint32_t FileIndexLow) + : LastWriteTimeHigh(LastWriteTimeHigh), + LastWriteTimeLow(LastWriteTimeLow), + VolumeSerialNumber(VolumeSerialNumber), FileSizeHigh(FileSizeHigh), + FileSizeLow(FileSizeLow), FileIndexHigh(FileIndexHigh), + FileIndexLow(FileIndexLow), Type(Type), Perms(perms_not_known) {} + #endif // getters file_type type() const { return Type; } perms permissions() const { return Perms; } - + TimeValue getLastModificationTime() const; + UniqueID getUniqueID() const; + + #if defined(LLVM_ON_UNIX) + uint32_t getUser() const { return fs_st_uid; } + uint32_t getGroup() const { return fs_st_gid; } + uint64_t getSize() const { return fs_st_size; } + #elif defined (LLVM_ON_WIN32) + uint32_t getUser() const { + return 9999; // Not applicable to Windows, so... + } + uint32_t getGroup() const { + return 9999; // Not applicable to Windows, so... + } + uint64_t getSize() const { + return (uint64_t(FileSizeHigh) << 32) + FileSizeLow; + } + #endif + // setters void type(file_type v) { Type = v; } void permissions(perms p) { Perms = p; } @@ -199,6 +236,7 @@ struct file_magic { macho_bundle, ///< Mach-O Bundle file macho_dynamically_linked_shared_lib_stub, ///< Mach-O Shared lib stub macho_dsym_companion, ///< Mach-O dSYM companion file + macho_universal_binary, ///< Mach-O universal binary coff_object, ///< COFF object file pecoff_executable ///< PECOFF executable file }; @@ -232,18 +270,6 @@ private: /// platform specific error_code. error_code make_absolute(SmallVectorImpl<char> &path); -/// @brief Copy the file at \a from to the path \a to. -/// -/// @param from The path to copy the file from. -/// @param to The path to copy the file to. -/// @param copt Behavior if \a to already exists. -/// @returns errc::success if the file has been successfully copied. -/// errc::file_exists if \a to already exists and \a copt == -/// copy_option::fail_if_exists. Otherwise a platform specific -/// error_code. -error_code copy_file(const Twine &from, const Twine &to, - copy_option copt = copy_option::fail_if_exists); - /// @brief Create all the non-existent directories in path. /// /// @param path Directories to create. @@ -252,6 +278,13 @@ error_code copy_file(const Twine &from, const Twine &to, /// otherwise a platform specific error_code. error_code create_directories(const Twine &path, bool &existed); +/// @brief Convenience function for clients that don't need to know if the +/// directory existed or not. +inline error_code create_directories(const Twine &Path) { + bool Existed; + return create_directories(Path, Existed); +} + /// @brief Create the directory in path. /// /// @param path Directory to create. @@ -260,6 +293,13 @@ error_code create_directories(const Twine &path, bool &existed); /// otherwise a platform specific error_code. error_code create_directory(const Twine &path, bool &existed); +/// @brief Convenience function for clients that don't need to know if the +/// directory existed or not. +inline error_code create_directory(const Twine &Path) { + bool Existed; + return create_directory(Path, Existed); +} + /// @brief Create a hard link from \a from to \a to. /// /// @param to The path to hard link to. @@ -292,6 +332,13 @@ error_code current_path(SmallVectorImpl<char> &result); /// successfully set, otherwise a platform specific error_code. error_code remove(const Twine &path, bool &existed); +/// @brief Convenience function for clients that don't need to know if the file +/// existed or not. +inline error_code remove(const Twine &Path) { + bool Existed; + return remove(Path, Existed); +} + /// @brief Recursively remove all files below \a path, then \a path. Files are /// removed as if by POSIX remove(). /// @@ -301,6 +348,13 @@ error_code remove(const Twine &path, bool &existed); /// successfully set, otherwise a platform specific error_code. error_code remove_all(const Twine &path, uint32_t &num_removed); +/// @brief Convenience function for clients that don't need to know how many +/// files were removed. +inline error_code remove_all(const Twine &Path) { + uint32_t Removed; + return remove_all(Path, Removed); +} + /// @brief Rename \a from to \a to. Files are renamed as if by POSIX rename(). /// /// @param from The path to rename from. @@ -342,6 +396,18 @@ inline bool exists(const Twine &path) { return !exists(path, result) && result; } +/// @brief Can we execute this file? +/// +/// @param Path Input path. +/// @returns True if we can execute it, false otherwise. +bool can_execute(const Twine &Path); + +/// @brief Can we write this file? +/// +/// @param Path Input path. +/// @returns True if we can write to it, false otherwise. +bool can_write(const Twine &Path); + /// @brief Do file_status's represent the same thing? /// /// @param A Input file_status. @@ -372,14 +438,6 @@ inline bool equivalent(const Twine &A, const Twine &B) { return !equivalent(A, B, result) && result; } -/// @brief Get file size. -/// -/// @param path Input path. -/// @param result Set to the size of the file in \a path. -/// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code file_size(const Twine &path, uint64_t &result); - /// @brief Does status represent a directory? /// /// @param status A file_status previously returned from status. @@ -395,6 +453,13 @@ bool is_directory(file_status status); /// platform specific error_code. error_code is_directory(const Twine &path, bool &result); +/// @brief Simpler version of is_directory for clients that don't need to +/// differentiate between an error and false. +inline bool is_directory(const Twine &Path) { + bool Result; + return !is_directory(Path, Result) && Result; +} + /// @brief Does status represent a regular file? /// /// @param status A file_status previously returned from status. @@ -410,6 +475,15 @@ bool is_regular_file(file_status status); /// platform specific error_code. error_code is_regular_file(const Twine &path, bool &result); +/// @brief Simpler version of is_regular_file for clients that don't need to +/// differentiate between an error and false. +inline bool is_regular_file(const Twine &Path) { + bool Result; + if (is_regular_file(Path, Result)) + return false; + return Result; +} + /// @brief Does this status represent something that exists but is not a /// directory, regular file, or symlink? /// @@ -451,12 +525,25 @@ error_code is_symlink(const Twine &path, bool &result); /// platform specific error_code. error_code status(const Twine &path, file_status &result); -/// @brief Modifies permission bits on a file +/// @brief A version for when a file descriptor is already available. +error_code status(int FD, file_status &Result); + +/// @brief Get file size. /// -/// @param path Input path. -/// @returns errc::success if permissions have been changed, otherwise a +/// @param Path Input path. +/// @param Result Set to the size of the file in \a Path. +/// @returns errc::success if result has been successfully set, otherwise a /// platform specific error_code. -error_code permissions(const Twine &path, perms prms); +inline error_code file_size(const Twine &Path, uint64_t &Result) { + file_status Status; + error_code EC = status(Path, Status); + if (EC) + return EC; + Result = Status.getSize(); + return error_code::success(); +} + +error_code setLastModificationAndAccessTime(int FD, TimeValue Time); /// @brief Is status available? /// @@ -472,28 +559,84 @@ bool status_known(file_status s); /// platform specific error_code. error_code status_known(const Twine &path, bool &result); -/// @brief Generate a unique path and open it as a file. +/// @brief Create a uniquely named file. /// /// Generates a unique path suitable for a temporary file and then opens it as a /// file. The name is based on \a model with '%' replaced by a random char in /// [0-9a-f]. If \a model is not an absolute path, a suitable temporary /// directory will be prepended. /// +/// Example: clang-%%-%%-%%-%%-%%.s => clang-a0-b1-c2-d3-e4.s +/// /// This is an atomic operation. Either the file is created and opened, or the /// file system is left untouched. /// -/// clang-%%-%%-%%-%%-%%.s => /tmp/clang-a0-b1-c2-d3-e4.s +/// The intendend use is for files that are to be kept, possibly after +/// renaming them. For example, when running 'clang -c foo.o', the file can +/// be first created as foo-abc123.o and then renamed. /// -/// @param model Name to base unique path off of. -/// @param result_fd Set to the opened file's file descriptor. -/// @param result_path Set to the opened file's absolute path. -/// @param makeAbsolute If true and \a model is not an absolute path, a temp -/// directory will be prepended. -/// @returns errc::success if result_{fd,path} have been successfully set, +/// @param Model Name to base unique path off of. +/// @param ResultFD Set to the opened file's file descriptor. +/// @param ResultPath Set to the opened file's absolute path. +/// @returns errc::success if Result{FD,Path} have been successfully set, /// otherwise a platform specific error_code. -error_code unique_file(const Twine &model, int &result_fd, - SmallVectorImpl<char> &result_path, - bool makeAbsolute = true, unsigned mode = 0600); +error_code createUniqueFile(const Twine &Model, int &ResultFD, + SmallVectorImpl<char> &ResultPath, + unsigned Mode = all_read | all_write); + +/// @brief Simpler version for clients that don't want an open file. +error_code createUniqueFile(const Twine &Model, + SmallVectorImpl<char> &ResultPath); + +/// @brief Create a file in the system temporary directory. +/// +/// The filename is of the form prefix-random_chars.suffix. Since the directory +/// is not know to the caller, Prefix and Suffix cannot have path separators. +/// The files are created with mode 0600. +/// +/// This should be used for things like a temporary .s that is removed after +/// running the assembler. +error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, + int &ResultFD, + SmallVectorImpl<char> &ResultPath); + +/// @brief Simpler version for clients that don't want an open file. +error_code createTemporaryFile(const Twine &Prefix, StringRef Suffix, + SmallVectorImpl<char> &ResultPath); + +error_code createUniqueDirectory(const Twine &Prefix, + SmallVectorImpl<char> &ResultPath); + +enum OpenFlags { + F_None = 0, + + /// F_Excl - When opening a file, this flag makes raw_fd_ostream + /// report an error if the file already exists. + F_Excl = 1, + + /// F_Append - When opening a file, if it already exists append to the + /// existing file instead of returning an error. This may not be specified + /// with F_Excl. + F_Append = 2, + + /// F_Binary - The file should be opened in binary mode on platforms that + /// make this distinction. + F_Binary = 4 +}; + +inline OpenFlags operator|(OpenFlags A, OpenFlags B) { + return OpenFlags(unsigned(A) | unsigned(B)); +} + +inline OpenFlags &operator|=(OpenFlags &A, OpenFlags B) { + A = A | B; + return A; +} + +error_code openFileForWrite(const Twine &Name, int &ResultFD, OpenFlags Flags, + unsigned Mode = 0666); + +error_code openFileForRead(const Twine &Name, int &ResultFD); /// @brief Canonicalize path. /// @@ -538,43 +681,7 @@ file_magic identify_magic(StringRef magic); /// platform specific error_code. error_code identify_magic(const Twine &path, file_magic &result); -/// @brief Get library paths the system linker uses. -/// -/// @param result Set to the list of system library paths. -/// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code GetSystemLibraryPaths(SmallVectorImpl<std::string> &result); - -/// @brief Get bitcode library paths the system linker uses -/// + LLVM_LIB_SEARCH_PATH + LLVM_LIBDIR. -/// -/// @param result Set to the list of bitcode library paths. -/// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code GetBitcodeLibraryPaths(SmallVectorImpl<std::string> &result); - -/// @brief Find a library. -/// -/// Find the path to a library using its short name. Use the system -/// dependent library paths to locate the library. -/// -/// c => /usr/lib/libc.so -/// -/// @param short_name Library name one would give to the system linker. -/// @param result Set to the absolute path \a short_name represents. -/// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code FindLibrary(const Twine &short_name, SmallVectorImpl<char> &result); - -/// @brief Get absolute path of main executable. -/// -/// @param argv0 The program name as it was spelled on the command line. -/// @param MainAddr Address of some symbol in the executable (not in a library). -/// @param result Set to the absolute path of the current executable. -/// @returns errc::success if result has been successfully set, otherwise a -/// platform specific error_code. -error_code GetMainExecutable(const char *argv0, void *MainAddr, - SmallVectorImpl<char> &result); +error_code getUniqueID(const Twine Path, UniqueID &Result); /// This class represents a memory mapped file. It is based on /// boost::iostreams::mapped_file. @@ -648,7 +755,7 @@ public: char *data() const; /// Get a const view of the data. Modifying this memory has undefined - /// behaivor. + /// behavior. const char *const_data() const; /// \returns The minimum alignment offset must be. @@ -679,7 +786,10 @@ error_code map_file_pages(const Twine &path, off_t file_offset, size_t size, /// platform specific error_code. error_code unmap_file_pages(void *base, size_t size); - +/// Return the path to the main executable, given the value of argv[0] from +/// program startup and the address of main itself. In extremis, this function +/// may fail and return an empty path. +std::string getMainExecutable(const char *argv0, void *MainExecAddr); /// @} /// @name Iterators diff --git a/include/llvm/Support/FileUtilities.h b/include/llvm/Support/FileUtilities.h index c6feb9f..79c59e4 100644 --- a/include/llvm/Support/FileUtilities.h +++ b/include/llvm/Support/FileUtilities.h @@ -17,7 +17,6 @@ #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" -#include "llvm/Support/PathV1.h" namespace llvm { @@ -28,8 +27,8 @@ namespace llvm { /// option, it will set the string to an error message if an error occurs, or /// if the files are different. /// - int DiffFilesWithTolerance(const sys::PathWithStatus &FileA, - const sys::PathWithStatus &FileB, + int DiffFilesWithTolerance(StringRef FileA, + StringRef FileB, double AbsTol, double RelTol, std::string *Error = 0); diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h index e867fae..62547dd 100644 --- a/include/llvm/Support/GraphWriter.h +++ b/include/llvm/Support/GraphWriter.h @@ -26,7 +26,6 @@ #include "llvm/ADT/GraphTraits.h" #include "llvm/Support/DOTGraphTraits.h" #include "llvm/Support/Path.h" -#include "llvm/Support/PathV1.h" #include "llvm/Support/raw_ostream.h" #include <cassert> #include <vector> @@ -51,7 +50,8 @@ namespace GraphProgram { }; } -void DisplayGraph(const sys::Path& Filename, bool wait=true, GraphProgram::Name program = GraphProgram::DOT); +void DisplayGraph(StringRef Filename, bool wait = true, + GraphProgram::Name program = GraphProgram::DOT); template<typename GraphType> class GraphWriter { @@ -319,34 +319,23 @@ raw_ostream &WriteGraph(raw_ostream &O, const GraphType &G, return O; } -template<typename GraphType> -sys::Path WriteGraph(const GraphType &G, const Twine &Name, - bool ShortNames = false, const Twine &Title = "") { - std::string ErrMsg; - sys::Path Filename = sys::Path::GetTemporaryDirectory(&ErrMsg); - if (Filename.isEmpty()) { - errs() << "Error: " << ErrMsg << "\n"; - return Filename; - } - Filename.appendComponent((Name + ".dot").str()); - if (Filename.makeUnique(true,&ErrMsg)) { - errs() << "Error: " << ErrMsg << "\n"; - return sys::Path(); - } +std::string createGraphFilename(const Twine &Name, int &FD); - errs() << "Writing '" << Filename.str() << "'... "; +template <typename GraphType> +std::string WriteGraph(const GraphType &G, const Twine &Name, + bool ShortNames = false, const Twine &Title = "") { + int FD; + std::string Filename = createGraphFilename(Name, FD); + raw_fd_ostream O(FD, /*shouldClose=*/ true); - std::string ErrorInfo; - raw_fd_ostream O(Filename.c_str(), ErrorInfo); - - if (ErrorInfo.empty()) { - llvm::WriteGraph(O, G, ShortNames, Title); - errs() << " done. \n"; - } else { - errs() << "error opening file '" << Filename.str() << "' for writing!\n"; - Filename.clear(); + if (FD == -1) { + errs() << "error opening file '" << Filename << "' for writing!\n"; + return ""; } + llvm::WriteGraph(O, G, ShortNames, Title); + errs() << " done. \n"; + return Filename; } @@ -357,9 +346,9 @@ template<typename GraphType> void ViewGraph(const GraphType &G, const Twine &Name, bool ShortNames = false, const Twine &Title = "", GraphProgram::Name Program = GraphProgram::DOT) { - sys::Path Filename = llvm::WriteGraph(G, Name, ShortNames, Title); + std::string Filename = llvm::WriteGraph(G, Name, ShortNames, Title); - if (Filename.isEmpty()) + if (Filename.empty()) return; DisplayGraph(Filename, true, Program); diff --git a/include/llvm/Support/IntegersSubset.h b/include/llvm/Support/IntegersSubset.h index ce34d78..64b79ee 100644 --- a/include/llvm/Support/IntegersSubset.h +++ b/include/llvm/Support/IntegersSubset.h @@ -361,7 +361,7 @@ public: FlatCollection.end(), CheckingVal) != FlatCollection.end(); - for (unsigned i = 0, e = getNumItems(); i < e; ++i) { + for (size_t i = 0, e = getNumItems(); i < e; ++i) { if (RangeLinks[i].first == RangeLinks[i].second) { if (*RangeLinks[i].first == CheckingVal) return true; @@ -382,7 +382,7 @@ public: } /// Return number of items (ranges) stored in set. - unsigned getNumItems() const { + size_t getNumItems() const { return RangeLinks.size(); } @@ -409,7 +409,7 @@ public: /// for range [<0>, <1>, <5>] the size will 3 unsigned getSize() const { APInt sz(((const APInt&)getItem(0).getLow()).getBitWidth(), 0); - for (unsigned i = 0, e = getNumItems(); i != e; ++i) { + for (size_t i = 0, e = getNumItems(); i != e; ++i) { const APInt Low = getItem(i).getLow(); const APInt High = getItem(i).getHigh(); APInt S = High - Low + 1; diff --git a/include/llvm/Support/LEB128.h b/include/llvm/Support/LEB128.h index 802b4f3..3d73792 100644 --- a/include/llvm/Support/LEB128.h +++ b/include/llvm/Support/LEB128.h @@ -20,7 +20,7 @@ namespace llvm { /// Utility function to encode a SLEB128 value to an output stream. -static inline void encodeSLEB128(int64_t Value, raw_ostream &OS) { +inline void encodeSLEB128(int64_t Value, raw_ostream &OS) { bool More; do { uint8_t Byte = Value & 0x7f; @@ -29,19 +29,19 @@ static inline void encodeSLEB128(int64_t Value, raw_ostream &OS) { More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) || ((Value == -1) && ((Byte & 0x40) != 0)))); if (More) - Byte |= 0x80; // Mark this byte that that more bytes will follow. + Byte |= 0x80; // Mark this byte to show that more bytes will follow. OS << char(Byte); } while (More); } /// Utility function to encode a ULEB128 value to an output stream. -static inline void encodeULEB128(uint64_t Value, raw_ostream &OS, - unsigned Padding = 0) { +inline void encodeULEB128(uint64_t Value, raw_ostream &OS, + unsigned Padding = 0) { do { uint8_t Byte = Value & 0x7f; Value >>= 7; if (Value != 0 || Padding != 0) - Byte |= 0x80; // Mark this byte that that more bytes will follow. + Byte |= 0x80; // Mark this byte to show that more bytes will follow. OS << char(Byte); } while (Value != 0); @@ -55,14 +55,14 @@ static inline void encodeULEB128(uint64_t Value, raw_ostream &OS, /// Utility function to encode a ULEB128 value to a buffer. Returns /// the length in bytes of the encoded value. -static inline unsigned encodeULEB128(uint64_t Value, uint8_t *p, - unsigned Padding = 0) { +inline unsigned encodeULEB128(uint64_t Value, uint8_t *p, + unsigned Padding = 0) { uint8_t *orig_p = p; do { uint8_t Byte = Value & 0x7f; Value >>= 7; if (Value != 0 || Padding != 0) - Byte |= 0x80; // Mark this byte that that more bytes will follow. + Byte |= 0x80; // Mark this byte to show that more bytes will follow. *p++ = Byte; } while (Value != 0); @@ -77,7 +77,7 @@ static inline unsigned encodeULEB128(uint64_t Value, uint8_t *p, /// Utility function to decode a ULEB128 value. -static inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = 0) { +inline uint64_t decodeULEB128(const uint8_t *p, unsigned *n = 0) { const uint8_t *orig_p = p; uint64_t Value = 0; unsigned Shift = 0; diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index a65bfbc..00c6ad7 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -45,7 +45,9 @@ enum ZeroBehavior { template <typename T> typename enable_if_c<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, std::size_t>::type -countTrailingZeros(T Val, ZeroBehavior /*ZB*/ = ZB_Width) { +countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { + (void)ZB; + if (!Val) return std::numeric_limits<T>::digits; if (Val & 0x1) @@ -78,7 +80,7 @@ inline std::size_t countTrailingZeros<uint32_t>(uint32_t Val, ZeroBehavior ZB) { if (ZB != ZB_Undefined && Val == 0) return 32; -#if __GNUC__ >= 4 +#if __has_builtin(__builtin_ctz) || __GNUC_PREREQ(4, 0) return __builtin_ctz(Val); #elif _MSC_VER unsigned long Index; @@ -93,7 +95,7 @@ inline std::size_t countTrailingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) { if (ZB != ZB_Undefined && Val == 0) return 64; -#if __GNUC__ >= 4 +#if __has_builtin(__builtin_ctzll) || __GNUC_PREREQ(4, 0) return __builtin_ctzll(Val); #elif _MSC_VER unsigned long Index; @@ -114,7 +116,9 @@ inline std::size_t countTrailingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) { template <typename T> typename enable_if_c<std::numeric_limits<T>::is_integer && !std::numeric_limits<T>::is_signed, std::size_t>::type -countLeadingZeros(T Val, ZeroBehavior /*ZB*/ = ZB_Width) { +countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { + (void)ZB; + if (!Val) return std::numeric_limits<T>::digits; @@ -142,7 +146,7 @@ inline std::size_t countLeadingZeros<uint32_t>(uint32_t Val, ZeroBehavior ZB) { if (ZB != ZB_Undefined && Val == 0) return 32; -#if __GNUC__ >= 4 +#if __has_builtin(__builtin_clz) || __GNUC_PREREQ(4, 0) return __builtin_clz(Val); #elif _MSC_VER unsigned long Index; @@ -157,7 +161,7 @@ inline std::size_t countLeadingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) { if (ZB != ZB_Undefined && Val == 0) return 64; -#if __GNUC__ >= 4 +#if __has_builtin(__builtin_clzll) || __GNUC_PREREQ(4, 0) return __builtin_clzll(Val); #elif _MSC_VER unsigned long Index; diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h index 0cce726..4f28da4 100644 --- a/include/llvm/Support/MemoryBuffer.h +++ b/include/llvm/Support/MemoryBuffer.h @@ -74,13 +74,18 @@ public: int64_t FileSize = -1, bool RequiresNullTerminator = true); - /// getOpenFile - Given an already-open file descriptor, read the file and - /// return a MemoryBuffer. + /// Given an already-open file descriptor, map some slice of it into a + /// MemoryBuffer. The slice is specified by an \p Offset and \p MapSize. + /// Since this is in the middle of a file, the buffer is not null terminated. + static error_code getOpenFileSlice(int FD, const char *Filename, + OwningPtr<MemoryBuffer> &Result, + uint64_t MapSize, int64_t Offset); + + /// Given an already-open file descriptor, read the file and return a + /// MemoryBuffer. static error_code getOpenFile(int FD, const char *Filename, - OwningPtr<MemoryBuffer> &result, - uint64_t FileSize = -1, - uint64_t MapSize = -1, - int64_t Offset = 0, + OwningPtr<MemoryBuffer> &Result, + uint64_t FileSize, bool RequiresNullTerminator = true); /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note @@ -119,11 +124,7 @@ public: static error_code getFileOrSTDIN(StringRef Filename, OwningPtr<MemoryBuffer> &result, int64_t FileSize = -1); - static error_code getFileOrSTDIN(const char *Filename, - OwningPtr<MemoryBuffer> &result, - int64_t FileSize = -1); - - + //===--------------------------------------------------------------------===// // Provided for performance analysis. //===--------------------------------------------------------------------===// diff --git a/include/llvm/Support/Path.h b/include/llvm/Support/Path.h index a70498a..f9a65e5 100644 --- a/include/llvm/Support/Path.h +++ b/include/llvm/Support/Path.h @@ -111,6 +111,7 @@ inline reverse_iterator rend(StringRef path) { /// @code /// directory/filename.cpp => directory/ /// directory/ => directory +/// filename.cpp => <empty> /// / => / /// @endcode /// diff --git a/include/llvm/Support/PathV1.h b/include/llvm/Support/PathV1.h deleted file mode 100644 index eaf2550..0000000 --- a/include/llvm/Support/PathV1.h +++ /dev/null @@ -1,557 +0,0 @@ -//===- llvm/Support/PathV1.h - Path Operating System Concept ----*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file declares the llvm::sys::Path class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_PATHV1_H -#define LLVM_SUPPORT_PATHV1_H - -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/TimeValue.h" -#include <set> -#include <string> -#include <vector> - -#define LLVM_PATH_DEPRECATED_MSG(replacement) \ - "PathV1 has been deprecated and will be removed as soon as all LLVM and" \ - " Clang clients have been moved over to PathV2. Please use `" #replacement \ - "` from PathV2 instead." - -namespace llvm { -namespace sys { - - /// This structure provides basic file system information about a file. It - /// is patterned after the stat(2) Unix operating system call but made - /// platform independent and eliminates many of the unix-specific fields. - /// However, to support llvm-ar, the mode, user, and group fields are - /// retained. These pertain to unix security and may not have a meaningful - /// value on non-Unix platforms. However, the other fields should - /// always be applicable on all platforms. The structure is filled in by - /// the PathWithStatus class. - /// @brief File status structure - class FileStatus { - public: - uint64_t fileSize; ///< Size of the file in bytes - TimeValue modTime; ///< Time of file's modification - uint32_t mode; ///< Mode of the file, if applicable - uint32_t user; ///< User ID of owner, if applicable - uint32_t group; ///< Group ID of owner, if applicable - uint64_t uniqueID; ///< A number to uniquely ID this file - bool isDir : 1; ///< True if this is a directory. - bool isFile : 1; ///< True if this is a file. - - FileStatus() : fileSize(0), modTime(0,0), mode(0777), user(999), - group(999), uniqueID(0), isDir(false), isFile(false) { } - - TimeValue getTimestamp() const { return modTime; } - uint64_t getSize() const { return fileSize; } - uint32_t getMode() const { return mode; } - uint32_t getUser() const { return user; } - uint32_t getGroup() const { return group; } - uint64_t getUniqueID() const { return uniqueID; } - }; - - /// This class provides an abstraction for the path to a file or directory - /// in the operating system's filesystem and provides various basic operations - /// on it. Note that this class only represents the name of a path to a file - /// or directory which may or may not be valid for a given machine's file - /// system. The class is patterned after the java.io.File class with various - /// extensions and several omissions (not relevant to LLVM). A Path object - /// ensures that the path it encapsulates is syntactically valid for the - /// operating system it is running on but does not ensure correctness for - /// any particular file system. That is, a syntactically valid path might - /// specify path components that do not exist in the file system and using - /// such a Path to act on the file system could produce errors. There is one - /// invalid Path value which is permitted: the empty path. The class should - /// never allow a syntactically invalid non-empty path name to be assigned. - /// Empty paths are required in order to indicate an error result in some - /// situations. If the path is empty, the isValid operation will return - /// false. All operations will fail if isValid is false. Operations that - /// change the path will either return false if it would cause a syntactically - /// invalid path name (in which case the Path object is left unchanged) or - /// throw an std::string exception indicating the error. The methods are - /// grouped into four basic categories: Path Accessors (provide information - /// about the path without accessing disk), Disk Accessors (provide - /// information about the underlying file or directory), Path Mutators - /// (change the path information, not the disk), and Disk Mutators (change - /// the disk file/directory referenced by the path). The Disk Mutator methods - /// all have the word "disk" embedded in their method name to reinforce the - /// notion that the operation modifies the file system. - /// @since 1.4 - /// @brief An abstraction for operating system paths. - class Path { - /// @name Constructors - /// @{ - public: - /// Construct a path to a unique temporary directory that is created in - /// a "standard" place for the operating system. The directory is - /// guaranteed to be created on exit from this function. If the directory - /// cannot be created, the function will throw an exception. - /// @returns an invalid path (empty) on error - /// @param ErrMsg Optional place for an error message if an error occurs - /// @brief Construct a path to an new, unique, existing temporary - /// directory. - static Path GetTemporaryDirectory(std::string* ErrMsg = 0); - - /// Construct a path to the current directory for the current process. - /// @returns The current working directory. - /// @brief Returns the current working directory. - static Path GetCurrentDirectory(); - - /// Return the suffix commonly used on file names that contain an - /// executable. - /// @returns The executable file suffix for the current platform. - /// @brief Return the executable file suffix. - static StringRef GetEXESuffix(); - - /// GetMainExecutable - Return the path to the main executable, given the - /// value of argv[0] from program startup and the address of main itself. - /// In extremis, this function may fail and return an empty path. - static Path GetMainExecutable(const char *argv0, void *MainAddr); - - /// This is one of the very few ways in which a path can be constructed - /// with a syntactically invalid name. The only *legal* invalid name is an - /// empty one. Other invalid names are not permitted. Empty paths are - /// provided so that they can be used to indicate null or error results in - /// other lib/System functionality. - /// @brief Construct an empty (and invalid) path. - Path() : path() {} - Path(const Path &that) : path(that.path) {} - - /// This constructor will accept a char* or std::string as a path. No - /// checking is done on this path to determine if it is valid. To - /// determine validity of the path, use the isValid method. - /// @param p The path to assign. - /// @brief Construct a Path from a string. - explicit Path(StringRef p); - - /// This constructor will accept a character range as a path. No checking - /// is done on this path to determine if it is valid. To determine - /// validity of the path, use the isValid method. - /// @param StrStart A pointer to the first character of the path name - /// @param StrLen The length of the path name at StrStart - /// @brief Construct a Path from a string. - Path(const char *StrStart, unsigned StrLen); - - /// @} - /// @name Operators - /// @{ - public: - /// Makes a copy of \p that to \p this. - /// @returns \p this - /// @brief Assignment Operator - Path &operator=(const Path &that) { - path = that.path; - return *this; - } - - /// Makes a copy of \p that to \p this. - /// @param that A StringRef denoting the path - /// @returns \p this - /// @brief Assignment Operator - Path &operator=(StringRef that); - - /// Compares \p this Path with \p that Path for equality. - /// @returns true if \p this and \p that refer to the same thing. - /// @brief Equality Operator - bool operator==(const Path &that) const; - - /// Compares \p this Path with \p that Path for inequality. - /// @returns true if \p this and \p that refer to different things. - /// @brief Inequality Operator - bool operator!=(const Path &that) const { return !(*this == that); } - - /// Determines if \p this Path is less than \p that Path. This is required - /// so that Path objects can be placed into ordered collections (e.g. - /// std::map). The comparison is done lexicographically as defined by - /// the std::string::compare method. - /// @returns true if \p this path is lexicographically less than \p that. - /// @brief Less Than Operator - bool operator<(const Path& that) const; - - /// @} - /// @name Path Accessors - /// @{ - public: - /// This function will use an operating system specific algorithm to - /// determine if the current value of \p this is a syntactically valid - /// path name for the operating system. The path name does not need to - /// exist, validity is simply syntactical. Empty paths are always invalid. - /// @returns true iff the path name is syntactically legal for the - /// host operating system. - /// @brief Determine if a path is syntactically valid or not. - bool isValid() const; - - /// This function determines if the contents of the path name are empty. - /// That is, the path name has a zero length. This does NOT determine if - /// if the file is empty. To get the length of the file itself, Use the - /// PathWithStatus::getFileStatus() method and then the getSize() method - /// on the returned FileStatus object. - /// @returns true iff the path is empty. - /// @brief Determines if the path name is empty (invalid). - bool isEmpty() const { return path.empty(); } - - - - /// Obtain a 'C' string for the path name. - /// @returns a 'C' string containing the path name. - /// @brief Returns the path as a C string. - const char *c_str() const { return path.c_str(); } - const std::string &str() const { return path; } - - - /// size - Return the length in bytes of this path name. - size_t size() const { return path.size(); } - - /// empty - Returns true if the path is empty. - unsigned empty() const { return path.empty(); } - - /// @} - /// @name Disk Accessors - /// @{ - public: - /// This function determines if the path name in the object references an - /// archive file by looking at its magic number. - /// @returns true if the file starts with the magic number for an archive - /// file. - /// @brief Determine if the path references an archive file. - bool isArchive() const; - - /// This function determines if the path name in the object references a - /// native Dynamic Library (shared library, shared object) by looking at - /// the file's magic number. The Path object must reference a file, not a - /// directory. - /// @returns true if the file starts with the magic number for a native - /// shared library. - /// @brief Determine if the path references a dynamic library. - bool isDynamicLibrary() const; - - /// This function determines if the path name in the object references a - /// native object file by looking at it's magic number. The term object - /// file is defined as "an organized collection of separate, named - /// sequences of binary data." This covers the obvious file formats such - /// as COFF and ELF, but it also includes llvm ir bitcode, archives, - /// libraries, etc... - /// @returns true if the file starts with the magic number for an object - /// file. - /// @brief Determine if the path references an object file. - bool isObjectFile() const; - - /// This function determines if the path name references an existing file - /// or directory in the file system. - /// @returns true if the pathname references an existing file or - /// directory. - /// @brief Determines if the path is a file or directory in - /// the file system. - LLVM_ATTRIBUTE_DEPRECATED(bool exists() const, - LLVM_PATH_DEPRECATED_MSG(fs::exists)); - - /// This function determines if the path name references an - /// existing directory. - /// @returns true if the pathname references an existing directory. - /// @brief Determines if the path is a directory in the file system. - LLVM_ATTRIBUTE_DEPRECATED(bool isDirectory() const, - LLVM_PATH_DEPRECATED_MSG(fs::is_directory)); - - /// This function determines if the path name references an - /// existing symbolic link. - /// @returns true if the pathname references an existing symlink. - /// @brief Determines if the path is a symlink in the file system. - LLVM_ATTRIBUTE_DEPRECATED(bool isSymLink() const, - LLVM_PATH_DEPRECATED_MSG(fs::is_symlink)); - - /// This function determines if the path name references a readable file - /// or directory in the file system. This function checks for - /// the existence and readability (by the current program) of the file - /// or directory. - /// @returns true if the pathname references a readable file. - /// @brief Determines if the path is a readable file or directory - /// in the file system. - bool canRead() const; - - /// This function determines if the path name references a writable file - /// or directory in the file system. This function checks for the - /// existence and writability (by the current program) of the file or - /// directory. - /// @returns true if the pathname references a writable file. - /// @brief Determines if the path is a writable file or directory - /// in the file system. - bool canWrite() const; - - /// This function checks that what we're trying to work only on a regular - /// file. Check for things like /dev/null, any block special file, or - /// other things that aren't "regular" regular files. - /// @returns true if the file is S_ISREG. - /// @brief Determines if the file is a regular file - bool isRegularFile() const; - - /// This function determines if the path name references an executable - /// file in the file system. This function checks for the existence and - /// executability (by the current program) of the file. - /// @returns true if the pathname references an executable file. - /// @brief Determines if the path is an executable file in the file - /// system. - bool canExecute() const; - - /// This function builds a list of paths that are the names of the - /// files and directories in a directory. - /// @returns true if an error occurs, true otherwise - /// @brief Build a list of directory's contents. - bool getDirectoryContents( - std::set<Path> &paths, ///< The resulting list of file & directory names - std::string* ErrMsg ///< Optional place to return an error message. - ) const; - - /// @} - /// @name Path Mutators - /// @{ - public: - /// The path name is cleared and becomes empty. This is an invalid - /// path name but is the *only* invalid path name. This is provided - /// so that path objects can be used to indicate the lack of a - /// valid path being found. - /// @brief Make the path empty. - void clear() { path.clear(); } - - /// This method sets the Path object to \p unverified_path. This can fail - /// if the \p unverified_path does not pass the syntactic checks of the - /// isValid() method. If verification fails, the Path object remains - /// unchanged and false is returned. Otherwise true is returned and the - /// Path object takes on the path value of \p unverified_path - /// @returns true if the path was set, false otherwise. - /// @param unverified_path The path to be set in Path object. - /// @brief Set a full path from a StringRef - bool set(StringRef unverified_path); - - /// One path component is removed from the Path. If only one component is - /// present in the path, the Path object becomes empty. If the Path object - /// is empty, no change is made. - /// @returns false if the path component could not be removed. - /// @brief Removes the last directory component of the Path. - bool eraseComponent(); - - /// The \p component is added to the end of the Path if it is a legal - /// name for the operating system. A directory separator will be added if - /// needed. - /// @returns false if the path component could not be added. - /// @brief Appends one path component to the Path. - bool appendComponent(StringRef component); - - /// A period and the \p suffix are appended to the end of the pathname. - /// When the \p suffix is empty, no action is performed. - /// @brief Adds a period and the \p suffix to the end of the pathname. - void appendSuffix(StringRef suffix); - - /// The suffix of the filename is erased. The suffix begins with and - /// includes the last . character in the filename after the last directory - /// separator and extends until the end of the name. If no . character is - /// after the last directory separator, then the file name is left - /// unchanged (i.e. it was already without a suffix) but the function - /// returns false. - /// @returns false if there was no suffix to remove, true otherwise. - /// @brief Remove the suffix from a path name. - bool eraseSuffix(); - - /// The current Path name is made unique in the file system. Upon return, - /// the Path will have been changed to make a unique file in the file - /// system or it will not have been changed if the current path name is - /// already unique. - /// @throws std::string if an unrecoverable error occurs. - /// @brief Make the current path name unique in the file system. - bool makeUnique( bool reuse_current /*= true*/, std::string* ErrMsg ); - - /// The current Path name is made absolute by prepending the - /// current working directory if necessary. - LLVM_ATTRIBUTE_DEPRECATED( - void makeAbsolute(), - LLVM_PATH_DEPRECATED_MSG(fs::make_absolute)); - - /// @} - /// @name Disk Mutators - /// @{ - public: - /// This method attempts to make the file referenced by the Path object - /// available for reading so that the canRead() method will return true. - /// @brief Make the file readable; - bool makeReadableOnDisk(std::string* ErrMsg = 0); - - /// This method attempts to make the file referenced by the Path object - /// available for writing so that the canWrite() method will return true. - /// @brief Make the file writable; - bool makeWriteableOnDisk(std::string* ErrMsg = 0); - - /// This method allows the last modified time stamp and permission bits - /// to be set on the disk object referenced by the Path. - /// @throws std::string if an error occurs. - /// @returns true on error. - /// @brief Set the status information. - bool setStatusInfoOnDisk(const FileStatus &SI, - std::string *ErrStr = 0) const; - - /// This method attempts to create a directory in the file system with the - /// same name as the Path object. The \p create_parents parameter controls - /// whether intermediate directories are created or not. if \p - /// create_parents is true, then an attempt will be made to create all - /// intermediate directories, as needed. If \p create_parents is false, - /// then only the final directory component of the Path name will be - /// created. The created directory will have no entries. - /// @returns true if the directory could not be created, false otherwise - /// @brief Create the directory this Path refers to. - bool createDirectoryOnDisk( - bool create_parents = false, ///< Determines whether non-existent - ///< directory components other than the last one (the "parents") - ///< are created or not. - std::string* ErrMsg = 0 ///< Optional place to put error messages. - ); - - /// This is like createFile except that it creates a temporary file. A - /// unique temporary file name is generated based on the contents of - /// \p this before the call. The new name is assigned to \p this and the - /// file is created. Note that this will both change the Path object - /// *and* create the corresponding file. This function will ensure that - /// the newly generated temporary file name is unique in the file system. - /// @returns true if the file couldn't be created, false otherwise. - /// @brief Create a unique temporary file - bool createTemporaryFileOnDisk( - bool reuse_current = false, ///< When set to true, this parameter - ///< indicates that if the current file name does not exist then - ///< it will be used without modification. - std::string* ErrMsg = 0 ///< Optional place to put error messages - ); - - /// This method renames the file referenced by \p this as \p newName. The - /// file referenced by \p this must exist. The file referenced by - /// \p newName does not need to exist. - /// @returns true on error, false otherwise - /// @brief Rename one file as another. - bool renamePathOnDisk(const Path& newName, std::string* ErrMsg); - - /// This method attempts to destroy the file or directory named by the - /// last component of the Path. If the Path refers to a directory and the - /// \p destroy_contents is false, an attempt will be made to remove just - /// the directory (the final Path component). If \p destroy_contents is - /// true, an attempt will be made to remove the entire contents of the - /// directory, recursively. If the Path refers to a file, the - /// \p destroy_contents parameter is ignored. - /// @param destroy_contents Indicates whether the contents of a destroyed - /// @param Err An optional string to receive an error message. - /// directory should also be destroyed (recursively). - /// @returns false if the file/directory was destroyed, true on error. - /// @brief Removes the file or directory from the filesystem. - bool eraseFromDisk(bool destroy_contents = false, - std::string *Err = 0) const; - - /// @} - /// @name Data - /// @{ - protected: - // Our win32 implementation relies on this string being mutable. - mutable std::string path; ///< Storage for the path name. - - - /// @} - }; - - /// This class is identical to Path class except it allows you to obtain the - /// file status of the Path as well. The reason for the distinction is one of - /// efficiency. First, the file status requires additional space and the space - /// is incorporated directly into PathWithStatus without an additional malloc. - /// Second, obtaining status information is an expensive operation on most - /// operating systems so we want to be careful and explicit about where we - /// allow this operation in LLVM. - /// @brief Path with file status class. - class PathWithStatus : public Path { - /// @name Constructors - /// @{ - public: - /// @brief Default constructor - PathWithStatus() : Path(), status(), fsIsValid(false) {} - - /// @brief Copy constructor - PathWithStatus(const PathWithStatus &that) - : Path(static_cast<const Path&>(that)), status(that.status), - fsIsValid(that.fsIsValid) {} - - /// This constructor allows construction from a Path object - /// @brief Path constructor - PathWithStatus(const Path &other) - : Path(other), status(), fsIsValid(false) {} - - /// This constructor will accept a char* or std::string as a path. No - /// checking is done on this path to determine if it is valid. To - /// determine validity of the path, use the isValid method. - /// @brief Construct a Path from a string. - explicit PathWithStatus( - StringRef p ///< The path to assign. - ) : Path(p), status(), fsIsValid(false) {} - - /// This constructor will accept a character range as a path. No checking - /// is done on this path to determine if it is valid. To determine - /// validity of the path, use the isValid method. - /// @brief Construct a Path from a string. - explicit PathWithStatus( - const char *StrStart, ///< Pointer to the first character of the path - unsigned StrLen ///< Length of the path. - ) : Path(StrStart, StrLen), status(), fsIsValid(false) {} - - /// Makes a copy of \p that to \p this. - /// @returns \p this - /// @brief Assignment Operator - PathWithStatus &operator=(const PathWithStatus &that) { - static_cast<Path&>(*this) = static_cast<const Path&>(that); - status = that.status; - fsIsValid = that.fsIsValid; - return *this; - } - - /// Makes a copy of \p that to \p this. - /// @returns \p this - /// @brief Assignment Operator - PathWithStatus &operator=(const Path &that) { - static_cast<Path&>(*this) = static_cast<const Path&>(that); - fsIsValid = false; - return *this; - } - - /// @} - /// @name Methods - /// @{ - public: - /// This function returns status information about the file. The type of - /// path (file or directory) is updated to reflect the actual contents - /// of the file system. - /// @returns 0 on failure, with Error explaining why (if non-zero), - /// otherwise returns a pointer to a FileStatus structure on success. - /// @brief Get file status. - const FileStatus *getFileStatus( - bool forceUpdate = false, ///< Force an update from the file system - std::string *Error = 0 ///< Optional place to return an error msg. - ) const; - - /// @} - /// @name Data - /// @{ - private: - mutable FileStatus status; ///< Status information. - mutable bool fsIsValid; ///< Whether we've obtained it or not - - /// @} - }; - - /// This is the OS-specific path separator: a colon on Unix or a semicolon - /// on Windows. - extern const char PathSeparator; -} - -} - -#endif diff --git a/include/llvm/Support/PatternMatch.h b/include/llvm/Support/PatternMatch.h index 95d9d78..b1732b2 100644 --- a/include/llvm/Support/PatternMatch.h +++ b/include/llvm/Support/PatternMatch.h @@ -696,10 +696,17 @@ m_ZExt(const OpTy &Op) { /// m_UIToFP template<typename OpTy> inline CastClass_match<OpTy, Instruction::UIToFP> -m_UIToFp(const OpTy &Op) { +m_UIToFP(const OpTy &Op) { return CastClass_match<OpTy, Instruction::UIToFP>(Op); } +/// m_SIToFP +template<typename OpTy> +inline CastClass_match<OpTy, Instruction::SIToFP> +m_SIToFP(const OpTy &Op) { + return CastClass_match<OpTy, Instruction::SIToFP>(Op); +} + //===----------------------------------------------------------------------===// // Matchers for unary operators // diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h index 08a64de..5134351 100644 --- a/include/llvm/Support/Program.h +++ b/include/llvm/Support/Program.h @@ -16,132 +16,81 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Path.h" -#include "llvm/Support/PathV1.h" +#include "llvm/Support/system_error.h" namespace llvm { class error_code; namespace sys { - // TODO: Add operations to communicate with the process, redirect its I/O, - // etc. - - /// This class provides an abstraction for programs that are executable by the - /// operating system. It provides a platform generic way to find executable - /// programs from the path and to execute them in various ways. The sys::Path - /// class is used to specify the location of the Program. - /// @since 1.4 - /// @brief An abstraction for finding and executing programs. - class Program { - /// Opaque handle for target specific data. - void *Data_; - - // Noncopyable. - Program(const Program& other) LLVM_DELETED_FUNCTION; - Program& operator=(const Program& other) LLVM_DELETED_FUNCTION; - - /// @name Methods - /// @{ - - Program(); - ~Program(); + /// This is the OS-specific separator for PATH like environment variables: + // a colon on Unix or a semicolon on Windows. +#if defined(LLVM_ON_UNIX) + const char EnvPathSeparator = ':'; +#elif defined (LLVM_ON_WIN32) + const char EnvPathSeparator = ';'; +#endif - /// This function executes the program using the \p arguments provided. The - /// invoked program will inherit the stdin, stdout, and stderr file - /// descriptors, the environment and other configuration settings of the - /// invoking program. If Path::executable() does not return true when this - /// function is called then a std::string is thrown. - /// @returns false in case of error, true otherwise. - /// @see FindProgramByName - /// @brief Executes the program with the given set of \p args. - bool Execute - ( const Path& path, ///< sys::Path object providing the path of the - ///< program to be executed. It is presumed this is the result of - ///< the FindProgramByName method. - const char** args, ///< A vector of strings that are passed to the + /// This static constructor (factory) will attempt to locate a program in + /// the operating system's file system using some pre-determined set of + /// locations to search (e.g. the PATH on Unix). Paths with slashes are + /// returned unmodified. + /// @returns A Path object initialized to the path of the program or a + /// Path object that is empty (invalid) if the program could not be found. + /// @brief Construct a Program by finding it by name. + std::string FindProgramByName(const std::string& name); + + // These functions change the specified standard stream (stdin, stdout, or + // stderr) to binary mode. They return errc::success if the specified stream + // was changed. Otherwise a platform dependent error is returned. + error_code ChangeStdinToBinary(); + error_code ChangeStdoutToBinary(); + error_code ChangeStderrToBinary(); + + /// This function executes the program using the arguments provided. The + /// invoked program will inherit the stdin, stdout, and stderr file + /// descriptors, the environment and other configuration settings of the + /// invoking program. + /// This function waits the program to finish. + /// @returns an integer result code indicating the status of the program. + /// A zero or positive value indicates the result code of the program. + /// -1 indicates failure to execute + /// -2 indicates a crash during execution or timeout + int ExecuteAndWait( + StringRef Program, ///< Path of the program to be executed. It is + /// presumed this is the result of the FindProgramByName method. + const char **args, ///< A vector of strings that are passed to the ///< program. The first element should be the name of the program. ///< The list *must* be terminated by a null char* entry. - const char ** env = 0, ///< An optional vector of strings to use for + const char **env = 0, ///< An optional vector of strings to use for ///< the program's environment. If not provided, the current program's ///< environment will be used. - const sys::Path** redirects = 0, ///< An optional array of pointers to - ///< Paths. If the array is null, no redirection is done. The array - ///< should have a size of at least three. If the pointer in the array - ///< are not null, then the inferior process's stdin(0), stdout(1), - ///< and stderr(2) will be redirected to the corresponding Paths. - ///< When an empty Path is passed in, the corresponding file + const StringRef **redirects = 0, ///< An optional array of pointers to + ///< paths. If the array is null, no redirection is done. The array + ///< should have a size of at least three. The inferior process's + ///< stdin(0), stdout(1), and stderr(2) will be redirected to the + ///< corresponding paths. + ///< When an empty path is passed in, the corresponding file ///< descriptor will be disconnected (ie, /dev/null'd) in a portable ///< way. + unsigned secondsToWait = 0, ///< If non-zero, this specifies the amount + ///< of time to wait for the child process to exit. If the time + ///< expires, the child is killed and this call returns. If zero, + ///< this function will wait until the child finishes or forever if + ///< it doesn't. unsigned memoryLimit = 0, ///< If non-zero, this specifies max. amount ///< of memory can be allocated by process. If memory usage will be ///< higher limit, the child is killed and this call returns. If zero ///< - no memory limit. - std::string* ErrMsg = 0 ///< If non-zero, provides a pointer to a string + std::string *ErrMsg = 0, ///< If non-zero, provides a pointer to a string ///< instance in which error messages will be returned. If the string ///< is non-empty upon return an error occurred while invoking the ///< program. - ); - - /// This function waits for the program to exit. This function will block - /// the current program until the invoked program exits. - /// @returns an integer result code indicating the status of the program. - /// A zero or positive value indicates the result code of the program. - /// -1 indicates failure to execute - /// -2 indicates a crash during execution or timeout - /// @see Execute - /// @brief Waits for the program to exit. - int Wait - ( const Path& path, ///< The path to the child process executable. - unsigned secondsToWait, ///< If non-zero, this specifies the amount - ///< of time to wait for the child process to exit. If the time - ///< expires, the child is killed and this call returns. If zero, - ///< this function will wait until the child finishes or forever if - ///< it doesn't. - std::string* ErrMsg ///< If non-zero, provides a pointer to a string - ///< instance in which error messages will be returned. If the string - ///< is non-empty upon return an error occurred while waiting. - ); - - public: - /// This static constructor (factory) will attempt to locate a program in - /// the operating system's file system using some pre-determined set of - /// locations to search (e.g. the PATH on Unix). Paths with slashes are - /// returned unmodified. - /// @returns A Path object initialized to the path of the program or a - /// Path object that is empty (invalid) if the program could not be found. - /// @brief Construct a Program by finding it by name. - static Path FindProgramByName(const std::string& name); - - // These methods change the specified standard stream (stdin, stdout, or - // stderr) to binary mode. They return errc::success if the specified stream - // was changed. Otherwise a platform dependent error is returned. - static error_code ChangeStdinToBinary(); - static error_code ChangeStdoutToBinary(); - static error_code ChangeStderrToBinary(); - - /// A convenience function equivalent to Program prg; prg.Execute(..); - /// prg.Wait(..); - /// @see Execute, Wait - static int ExecuteAndWait(const Path& path, - const char** args, - const char ** env = 0, - const sys::Path** redirects = 0, - unsigned secondsToWait = 0, - unsigned memoryLimit = 0, - std::string* ErrMsg = 0, - bool *ExecutionFailed = 0); - - /// A convenience function equivalent to Program prg; prg.Execute(..); - /// @see Execute - static void ExecuteNoWait(const Path& path, - const char** args, - const char ** env = 0, - const sys::Path** redirects = 0, - unsigned memoryLimit = 0, - std::string* ErrMsg = 0); - - /// @} + bool *ExecutionFailed = 0); - }; + /// Similar to ExecuteAndWait, but return immediately. + void ExecuteNoWait(StringRef Program, const char **args, const char **env = 0, + const StringRef **redirects = 0, unsigned memoryLimit = 0, + std::string *ErrMsg = 0); // Return true if the given arguments fit within system-specific // argument length limits. diff --git a/include/llvm/Support/Regex.h b/include/llvm/Support/Regex.h index 82df2c6..3d071be 100644 --- a/include/llvm/Support/Regex.h +++ b/include/llvm/Support/Regex.h @@ -77,6 +77,10 @@ namespace llvm { /// string. std::string sub(StringRef Repl, StringRef String, std::string *Error = 0); + /// \brief If this function returns true, ^Str$ is an extended regular + /// expression that matches Str and only Str. + static bool isLiteralERE(StringRef Str); + private: struct llvm_regex *preg; int error; diff --git a/include/llvm/Support/Registry.h b/include/llvm/Support/Registry.h index 29eafb6..073becd 100644 --- a/include/llvm/Support/Registry.h +++ b/include/llvm/Support/Registry.h @@ -14,6 +14,8 @@ #ifndef LLVM_SUPPORT_REGISTRY_H #define LLVM_SUPPORT_REGISTRY_H +#include "llvm/Support/Compiler.h" + namespace llvm { /// A simple registry entry which provides only a name, description, and /// no-argument constructor. diff --git a/include/llvm/Support/Signals.h b/include/llvm/Support/Signals.h index c0a489a..58ed175 100644 --- a/include/llvm/Support/Signals.h +++ b/include/llvm/Support/Signals.h @@ -16,7 +16,6 @@ #define LLVM_SUPPORT_SIGNALS_H #include "llvm/Support/Path.h" -#include "llvm/Support/PathV1.h" #include <cstdio> namespace llvm { @@ -29,11 +28,11 @@ namespace sys { /// This function registers signal handlers to ensure that if a signal gets /// delivered that the named file is removed. /// @brief Remove a file if a fatal signal occurs. - bool RemoveFileOnSignal(const Path &Filename, std::string* ErrMsg = 0); + bool RemoveFileOnSignal(StringRef Filename, std::string* ErrMsg = 0); /// This function removes a file from the list of files to be removed on /// signal delivery. - void DontRemoveFileOnSignal(const Path &Filename); + void DontRemoveFileOnSignal(StringRef Filename); /// When an error signal (such as SIBABRT or SIGSEGV) is delivered to the /// process, print a stack trace and then exit. diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index d67914a..5b33d42 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -39,7 +39,7 @@ public: DK_Warning, DK_Note }; - + /// DiagHandlerTy - Clients that want to handle their own diagnostics in a /// custom way can register a function pointer+context as a diagnostic /// handler. It gets called each time PrintMessage is invoked. @@ -98,7 +98,7 @@ public: return Buffers[i].Buffer; } - unsigned getNumBuffers() const { + size_t getNumBuffers() const { return Buffers.size(); } @@ -109,20 +109,20 @@ public: /// AddNewSourceBuffer - Add a new source buffer to this source manager. This /// takes ownership of the memory buffer. - unsigned AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) { + size_t AddNewSourceBuffer(MemoryBuffer *F, SMLoc IncludeLoc) { SrcBuffer NB; NB.Buffer = F; NB.IncludeLoc = IncludeLoc; Buffers.push_back(NB); - return Buffers.size()-1; + return Buffers.size() - 1; } /// AddIncludeFile - Search for a file with the specified name in the current /// directory or in one of the IncludeDirs. If no file is found, this returns /// ~0, otherwise it returns the buffer ID of the stacked file. /// The full path to the included file can be found in IncludedFile. - unsigned AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, - std::string &IncludedFile); + size_t AddIncludeFile(const std::string &Filename, SMLoc IncludeLoc, + std::string &IncludedFile); /// FindBufferContainingLoc - Return the ID of the buffer containing the /// specified location, returning -1 if not found. @@ -221,7 +221,7 @@ public: SMDiagnostic(StringRef filename, SourceMgr::DiagKind Knd, StringRef Msg) : SM(0), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), Message(Msg) {} - + // Diagnostic with a location. SMDiagnostic(const SourceMgr &sm, SMLoc L, StringRef FN, int Line, int Col, SourceMgr::DiagKind Kind, diff --git a/include/llvm/Support/SystemUtils.h b/include/llvm/Support/SystemUtils.h index 399aee5..d2d08b2 100644 --- a/include/llvm/Support/SystemUtils.h +++ b/include/llvm/Support/SystemUtils.h @@ -19,7 +19,6 @@ namespace llvm { class raw_ostream; - namespace sys { class Path; } /// Determine if the raw_ostream provided is connected to a terminal. If so, /// generate a warning message to errs() advising against display of bitcode @@ -30,15 +29,6 @@ bool CheckBitcodeOutputToConsole( bool print_warning = true ///< Control whether warnings are printed ); -/// PrependMainExecutablePath - Prepend the path to the program being executed -/// to \p ExeName, given the value of argv[0] and the address of main() -/// itself. This allows us to find another LLVM tool if it is built in the same -/// directory. An empty string is returned on error; note that this function -/// just mainpulates the path and doesn't check for executability. -/// @brief Find a named executable. -sys::Path PrependMainExecutablePath(const std::string &ExeName, - const char *Argv0, void *MainAddr); - } // End llvm namespace #endif diff --git a/include/llvm/Support/TimeValue.h b/include/llvm/Support/TimeValue.h index 4b48b84..2785408 100644 --- a/include/llvm/Support/TimeValue.h +++ b/include/llvm/Support/TimeValue.h @@ -253,9 +253,10 @@ namespace sys { /// Converts the TimeValue into the corresponding number of "ticks" for /// Win32 platforms, correcting for the difference in Win32 zero time. - /// @brief Convert to windows time (seconds since 12:00:00a Jan 1, 1601) + /// @brief Convert to Win32's FILETIME + /// (100ns intervals since 00:00:00 Jan 1, 1601 UTC) uint64_t toWin32Time() const { - uint64_t result = seconds_ - Win32ZeroTimeSeconds; + uint64_t result = (uint64_t)10000000 * (seconds_ - Win32ZeroTimeSeconds); result += nanos_ / NANOSECONDS_PER_WIN32_TICK; return result; } diff --git a/include/llvm/Support/ToolOutputFile.h b/include/llvm/Support/ToolOutputFile.h index b3b7c57..a2191ad 100644 --- a/include/llvm/Support/ToolOutputFile.h +++ b/include/llvm/Support/ToolOutputFile.h @@ -47,7 +47,9 @@ public: /// tool_output_file - This constructor's arguments are passed to /// to raw_fd_ostream's constructor. tool_output_file(const char *filename, std::string &ErrorInfo, - unsigned Flags = 0); + sys::fs::OpenFlags Flags = sys::fs::F_None); + + tool_output_file(const char *Filename, int FD); /// os - Return the contained raw_fd_ostream. raw_fd_ostream &os() { return OS; } diff --git a/include/llvm/Support/UnicodeCharRanges.h b/include/llvm/Support/UnicodeCharRanges.h new file mode 100644 index 0000000..4a4d988 --- /dev/null +++ b/include/llvm/Support/UnicodeCharRanges.h @@ -0,0 +1,98 @@ +//===--- UnicodeCharRanges.h - Types and functions for character ranges ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_SUPPORT_UNICODECHARRANGES_H +#define LLVM_SUPPORT_UNICODECHARRANGES_H + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/Mutex.h" +#include "llvm/Support/MutexGuard.h" +#include "llvm/Support/raw_ostream.h" + +namespace { + +struct UnicodeCharRange { + uint32_t Lower; + uint32_t Upper; +}; +typedef llvm::ArrayRef<UnicodeCharRange> UnicodeCharSet; + +/// Returns true if each of the ranges in \p CharSet is a proper closed range +/// [min, max], and if the ranges themselves are ordered and non-overlapping. +static inline bool isValidCharSet(UnicodeCharSet CharSet) { +#ifndef NDEBUG + static llvm::SmallPtrSet<const UnicodeCharRange *, 16> Validated; + static llvm::sys::Mutex ValidationMutex; + + // Check the validation cache. + { + llvm::MutexGuard Guard(ValidationMutex); + if (Validated.count(CharSet.data())) + return true; + } + + // Walk through the ranges. + uint32_t Prev = 0; + for (UnicodeCharSet::iterator I = CharSet.begin(), E = CharSet.end(); + I != E; ++I) { + if (I != CharSet.begin() && Prev >= I->Lower) { + DEBUG(llvm::dbgs() << "Upper bound 0x"); + DEBUG(llvm::dbgs().write_hex(Prev)); + DEBUG(llvm::dbgs() << " should be less than succeeding lower bound 0x"); + DEBUG(llvm::dbgs().write_hex(I->Lower) << "\n"); + return false; + } + if (I->Upper < I->Lower) { + DEBUG(llvm::dbgs() << "Upper bound 0x"); + DEBUG(llvm::dbgs().write_hex(I->Lower)); + DEBUG(llvm::dbgs() << " should not be less than lower bound 0x"); + DEBUG(llvm::dbgs().write_hex(I->Upper) << "\n"); + return false; + } + Prev = I->Upper; + } + + // Update the validation cache. + { + llvm::MutexGuard Guard(ValidationMutex); + Validated.insert(CharSet.data()); + } +#endif + return true; +} + +} // namespace + + +/// Returns true if the Unicode code point \p C is within the set of +/// characters specified by \p CharSet. +LLVM_READONLY static inline bool isCharInSet(uint32_t C, + UnicodeCharSet CharSet) { + assert(isValidCharSet(CharSet)); + + size_t LowPoint = 0; + size_t HighPoint = CharSet.size(); + + // Binary search the set of char ranges. + while (HighPoint != LowPoint) { + size_t MidPoint = (HighPoint + LowPoint) / 2; + if (C < CharSet[MidPoint].Lower) + HighPoint = MidPoint; + else if (C > CharSet[MidPoint].Upper) + LowPoint = MidPoint + 1; + else + return true; + } + + return false; +} + +#endif // LLVM_SUPPORT_UNICODECHARRANGES_H diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index 801868f..0f57f44 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -14,7 +14,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseMapInfo.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringExtras.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/ADT/Twine.h" @@ -760,15 +760,7 @@ private: } static inline bool classof(const MapHNode *) { return true; } - struct StrMappingInfo { - static StringRef getEmptyKey() { return StringRef(); } - static StringRef getTombstoneKey() { return StringRef(" ", 0); } - static unsigned getHashValue(StringRef const val) { - return llvm::HashString(val); } - static bool isEqual(StringRef const lhs, - StringRef const rhs) { return lhs.equals(rhs); } - }; - typedef llvm::DenseMap<StringRef, HNode*, StrMappingInfo> NameToNode; + typedef llvm::StringMap<HNode*> NameToNode; bool isValidKey(StringRef key); diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index d2b4a2a..ec7e06b 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -17,6 +17,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/FileSystem.h" namespace llvm { class format_object_base; @@ -335,22 +336,6 @@ class raw_fd_ostream : public raw_ostream { void error_detected() { Error = true; } public: - - enum { - /// F_Excl - When opening a file, this flag makes raw_fd_ostream - /// report an error if the file already exists. - F_Excl = 1, - - /// F_Append - When opening a file, if it already exists append to the - /// existing file instead of returning an error. This may not be specified - /// with F_Excl. - F_Append = 2, - - /// F_Binary - The file should be opened in binary mode on platforms that - /// make this distinction. - F_Binary = 4 - }; - /// raw_fd_ostream - Open the specified file for writing. If an error occurs, /// information about the error is put into ErrorInfo, and the stream should /// be immediately destroyed; the string will be empty if no error occurred. @@ -362,7 +347,7 @@ public: /// file descriptor when it is done (this is necessary to detect /// output errors). raw_fd_ostream(const char *Filename, std::string &ErrorInfo, - unsigned Flags = 0); + sys::fs::OpenFlags Flags = sys::fs::F_None); /// 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. diff --git a/include/llvm/TableGen/Record.h b/include/llvm/TableGen/Record.h index 76ee69d..e17cddd 100644 --- a/include/llvm/TableGen/Record.h +++ b/include/llvm/TableGen/Record.h @@ -1731,6 +1731,86 @@ struct LessRecordFieldName { } }; +struct LessRecordRegister { + static size_t min(size_t a, size_t b) { return a < b ? a : b; } + static bool ascii_isdigit(char x) { return x >= '0' && x <= '9'; } + + struct RecordParts { + SmallVector<std::pair< bool, StringRef>, 4> Parts; + + RecordParts(StringRef Rec) { + if (Rec.empty()) + return; + + size_t Len = 0; + const char *Start = Rec.data(); + const char *Curr = Start; + bool isDigitPart = ascii_isdigit(Curr[0]); + for (size_t I = 0, E = Rec.size(); I != E; ++I, ++Len) { + bool isDigit = ascii_isdigit(Curr[I]); + if (isDigit != isDigitPart) { + Parts.push_back(std::make_pair(isDigitPart, StringRef(Start, Len))); + Len = 0; + Start = &Curr[I]; + isDigitPart = ascii_isdigit(Curr[I]); + } + } + // Push the last part. + Parts.push_back(std::make_pair(isDigitPart, StringRef(Start, Len))); + } + + size_t size() { return Parts.size(); } + + std::pair<bool, StringRef> getPart(size_t i) { + assert (i < Parts.size() && "Invalid idx!"); + return Parts[i]; + } + }; + + bool operator()(const Record *Rec1, const Record *Rec2) const { + RecordParts LHSParts(StringRef(Rec1->getName())); + RecordParts RHSParts(StringRef(Rec2->getName())); + + size_t LHSNumParts = LHSParts.size(); + size_t RHSNumParts = RHSParts.size(); + assert (LHSNumParts && RHSNumParts && "Expected at least one part!"); + + if (LHSNumParts != RHSNumParts) + return LHSNumParts < RHSNumParts; + + // We expect the registers to be of the form [_a-zA-z]+([0-9]*[_a-zA-Z]*)*. + for (size_t I = 0, E = LHSNumParts; I < E; I+=2) { + std::pair<bool, StringRef> LHSPart = LHSParts.getPart(I); + std::pair<bool, StringRef> RHSPart = RHSParts.getPart(I); + // Expect even part to always be alpha. + assert (LHSPart.first == false && RHSPart.first == false && + "Expected both parts to be alpha."); + if (int Res = LHSPart.second.compare(RHSPart.second)) + return Res < 0; + } + for (size_t I = 1, E = LHSNumParts; I < E; I+=2) { + std::pair<bool, StringRef> LHSPart = LHSParts.getPart(I); + std::pair<bool, StringRef> RHSPart = RHSParts.getPart(I); + // Expect odd part to always be numeric. + assert (LHSPart.first == true && RHSPart.first == true && + "Expected both parts to be numeric."); + if (LHSPart.second.size() != RHSPart.second.size()) + return LHSPart.second.size() < RHSPart.second.size(); + + unsigned LHSVal, RHSVal; + + bool LHSFailed = LHSPart.second.getAsInteger(10, LHSVal); (void)LHSFailed; + assert(!LHSFailed && "Unable to convert LHS to integer."); + bool RHSFailed = RHSPart.second.getAsInteger(10, RHSVal); (void)RHSFailed; + assert(!RHSFailed && "Unable to convert RHS to integer."); + + if (LHSVal != RHSVal) + return LHSVal < RHSVal; + } + return LHSNumParts < RHSNumParts; + } +}; + raw_ostream &operator<<(raw_ostream &OS, const RecordKeeper &RK); /// QualifyName - Return an Init with a qualifier prefix referring diff --git a/include/llvm/Target/Mangler.h b/include/llvm/Target/Mangler.h index 986244f..e925cd5 100644 --- a/include/llvm/Target/Mangler.h +++ b/include/llvm/Target/Mangler.h @@ -59,13 +59,14 @@ public: /// and the specified global variable's name. If the global variable doesn't /// have a name, this fills in a unique name for the global. void getNameWithPrefix(SmallVectorImpl<char> &OutName, const GlobalValue *GV, - bool isImplicitlyPrivate); + bool isImplicitlyPrivate, bool UseGlobalPrefix = true); /// getNameWithPrefix - Fill OutName with the name of the appropriate prefix /// and the specified name as the global variable name. GVName must not be /// empty. void getNameWithPrefix(SmallVectorImpl<char> &OutName, const Twine &GVName, - ManglerPrefixTy PrefixTy = Mangler::Default); + ManglerPrefixTy PrefixTy = Mangler::Default, + bool UseGlobalPrefix = true); }; } // End llvm namespace diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index a9644d4..89ca529 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -445,6 +445,11 @@ class Instruction { string TwoOperandAliasConstraint = ""; ///@} + + /// UseNamedOperandTable - If set, the operand indices of this instruction + /// can be queried via the getNamedOperandIdx() function which is generated + /// by TableGen. + bit UseNamedOperandTable = 0; } /// PseudoInstExpansion - Expansion information for a pseudo-instruction. @@ -813,6 +818,9 @@ class AsmParser { // ShouldEmitMatchRegisterName - Set to false if the target needs a hand // written register name matcher bit ShouldEmitMatchRegisterName = 1; + + /// Does the instruction mnemonic allow '.' + bit MnemonicContainsDot = 0; } def DefaultAsmParser : AsmParser; diff --git a/include/llvm/Target/TargetFrameLowering.h b/include/llvm/Target/TargetFrameLowering.h index d5f30f4..a60147f 100644 --- a/include/llvm/Target/TargetFrameLowering.h +++ b/include/llvm/Target/TargetFrameLowering.h @@ -88,6 +88,11 @@ public: /// int getOffsetOfLocalArea() const { return LocalAreaOffset; } + /// isFPCloseToIncomingSP - Return true if the frame pointer is close to + /// the incoming stack pointer, false if it is close to the post-prologue + /// stack pointer. + virtual bool isFPCloseToIncomingSP() const { return true; } + /// getCalleeSavedSpillSlots - This method returns a pointer to an array of /// pairs, that contains an entry for each callee saved register that must be /// spilled to a particular stack location if it is spilled. diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index d49ce1c..f746daf 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -173,6 +173,14 @@ public: const MachineMemOperand *&MMO, int &FrameIndex) const; + /// isStackSlotCopy - Return true if the specified machine instruction + /// is a copy of one stack slot to another and has no other effect. + /// Provide the identity of the two frame indices. + virtual bool isStackSlotCopy(const MachineInstr *MI, int &DestFrameIndex, + int &SrcFrameIndex) const { + return false; + } + /// reMaterialize - Re-issue the specified 'original' instruction at the /// specific location targeting a new destination register. /// The register in Orig->getOperand(0).getReg() will be substituted by @@ -505,22 +513,6 @@ public: return false; } - /// emitFrameIndexDebugValue - Emit a target-dependent form of - /// DBG_VALUE encoding the address of a frame index. Addresses would - /// normally be lowered the same way as other addresses on the target, - /// e.g. in load instructions. For targets that do not support this - /// the debug info is simply lost. - /// If you add this for a target you should handle this DBG_VALUE in the - /// target-specific AsmPrinter code as well; you will probably get invalid - /// assembly output if you don't. - virtual MachineInstr *emitFrameIndexDebugValue(MachineFunction &MF, - int FrameIx, - uint64_t Offset, - const MDNode *MDPtr, - DebugLoc dl) const { - return 0; - } - /// foldMemoryOperand - Attempt to fold a load or store of the specified stack /// slot into the specified machine instruction for the specified operand(s). /// If this is possible, a new instruction is returned with the specified @@ -817,12 +809,10 @@ public: /// computeOperandLatency - Compute and return the latency of the given data /// dependent def and use when the operand indices are already known. - /// - /// FindMin may be set to get the minimum vs. expected latency. unsigned computeOperandLatency(const InstrItineraryData *ItinData, const MachineInstr *DefMI, unsigned DefIdx, - const MachineInstr *UseMI, unsigned UseIdx, - bool FindMin = false) const; + const MachineInstr *UseMI, unsigned UseIdx) + const; /// getInstrLatency - Compute the instruction latency of a given instruction. /// If the instruction has higher cost when predicated, it's returned via @@ -839,7 +829,7 @@ public: const MachineInstr *DefMI) const; int computeDefOperandLatency(const InstrItineraryData *ItinData, - const MachineInstr *DefMI, bool FindMin) const; + const MachineInstr *DefMI) const; /// isHighLatencyDef - Return true if this opcode has high latency to its /// result. diff --git a/include/llvm/Target/TargetLibraryInfo.h b/include/llvm/Target/TargetLibraryInfo.h index 4b9c044..8c1f223 100644 --- a/include/llvm/Target/TargetLibraryInfo.h +++ b/include/llvm/Target/TargetLibraryInfo.h @@ -24,8 +24,12 @@ namespace llvm { under_IO_putc, /// void operator delete[](void*); ZdaPv, + /// void operator delete[](void*, nothrow); + ZdaPvRKSt9nothrow_t, /// void operator delete(void*); ZdlPv, + /// void operator delete(void*, nothrow); + ZdlPvRKSt9nothrow_t, /// void *new[](unsigned int); Znaj, /// void *new[](unsigned int, nothrow); @@ -308,6 +312,8 @@ namespace llvm { getpwnam, /// char *gets(char *s); gets, + /// int gettimeofday(struct timeval *tp, void *tzp); + gettimeofday, /// uint32_t htonl(uint32_t hostlong); htonl, /// uint16_t htons(uint16_t hostshort); diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 9483282..c3fa3cc 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -6,17 +6,18 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file describes how to lower LLVM code to machine code. This has two -// main components: -// -// 1. Which ValueTypes are natively supported by the target. -// 2. Which operations are supported for supported ValueTypes. -// 3. Cost thresholds for alternative implementations of certain operations. -// -// In addition it has a few other components, like information about FP -// immediates. -// +/// +/// \file +/// This file describes how to lower LLVM code to machine code. This has two +/// main components: +/// +/// 1. Which ValueTypes are natively supported by the target. +/// 2. Which operations are supported for supported ValueTypes. +/// 3. Cost thresholds for alternative implementations of certain operations. +/// +/// In addition it has a few other components, like information about FP +/// immediates. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_TARGET_TARGETLOWERING_H @@ -67,15 +68,15 @@ namespace llvm { }; } -/// TargetLoweringBase - This base class for TargetLowering contains the -/// SelectionDAG-independent parts that can be used from the rest of CodeGen. +/// This base class for TargetLowering contains the SelectionDAG-independent +/// parts that can be used from the rest of CodeGen. class TargetLoweringBase { TargetLoweringBase(const TargetLoweringBase&) LLVM_DELETED_FUNCTION; void operator=(const TargetLoweringBase&) LLVM_DELETED_FUNCTION; public: - /// LegalizeAction - This enum indicates whether operations are valid for a - /// target, and if not, what action should be used to make them valid. + /// This enum indicates whether operations are valid for a target, and if not, + /// what action should be used to make them valid. enum LegalizeAction { Legal, // The target natively supports this operation. Promote, // This operation should be executed in a larger type. @@ -83,8 +84,8 @@ public: Custom // Use the LowerOperation hook to implement custom lowering. }; - /// LegalizeTypeAction - This enum indicates whether a types are legal for a - /// target, and if not, what action should be used to make them valid. + /// This enum indicates whether a types are legal for a target, and if not, + /// what action should be used to make them valid. enum LegalizeTypeAction { TypeLegal, // The target natively supports this type. TypePromoteInteger, // Replace this integer with a larger one. @@ -100,12 +101,14 @@ public: /// in order to type-legalize it. typedef std::pair<LegalizeTypeAction, EVT> LegalizeKind; - enum BooleanContent { // How the target represents true/false values. + /// Enum that describes how the target represents true/false values. + enum BooleanContent { UndefinedBooleanContent, // Only bit 0 counts, the rest can hold garbage. ZeroOrOneBooleanContent, // All bits zero except for bit 0. ZeroOrNegativeOneBooleanContent // All bits equal to bit 0. }; + /// Enum that describes what type of support for selects the target has. enum SelectSupportKind { ScalarValSelect, // The target supports scalar selects (ex: cmov). ScalarCondVectorVal, // The target supports selects with a scalar condition @@ -153,112 +156,118 @@ public: EVT getShiftAmountTy(EVT LHSTy) const; - /// isSelectExpensive - Return true if the select operation is expensive for - /// this target. + /// Returns the type to be used for the index operand of: + /// ISD::INSERT_VECTOR_ELT, ISD::EXTRACT_VECTOR_ELT, + /// ISD::INSERT_SUBVECTOR, and ISD::EXTRACT_SUBVECTOR + virtual MVT getVectorIdxTy() const { + return getPointerTy(); + } + + /// Return true if the select operation is expensive for this target. bool isSelectExpensive() const { return SelectIsExpensive; } virtual bool isSelectSupported(SelectSupportKind /*kind*/) const { return true; } - /// shouldSplitVectorElementType - Return true if a vector of the given type - /// should be split (TypeSplitVector) instead of promoted - /// (TypePromoteInteger) during type legalization. + /// Return true if a vector of the given type should be split + /// (TypeSplitVector) instead of promoted (TypePromoteInteger) during type + /// legalization. virtual bool shouldSplitVectorElementType(EVT /*VT*/) const { return false; } - /// isIntDivCheap() - Return true if integer divide is usually cheaper than - /// a sequence of several shifts, adds, and multiplies for this target. + /// Return true if integer divide is usually cheaper than a sequence of + /// several shifts, adds, and multiplies for this target. bool isIntDivCheap() const { return IntDivIsCheap; } - /// isSlowDivBypassed - Returns true if target has indicated at least one - /// type should be bypassed. + /// Returns true if target has indicated at least one type should be bypassed. bool isSlowDivBypassed() const { return !BypassSlowDivWidths.empty(); } - /// getBypassSlowDivTypes - Returns map of slow types for division or - /// remainder with corresponding fast types + /// Returns map of slow types for division or remainder with corresponding + /// fast types const DenseMap<unsigned int, unsigned int> &getBypassSlowDivWidths() const { return BypassSlowDivWidths; } - /// isPow2DivCheap() - Return true if pow2 div is cheaper than a chain of - /// srl/add/sra. + /// Return true if pow2 div is cheaper than a chain of srl/add/sra. bool isPow2DivCheap() const { return Pow2DivIsCheap; } - /// isJumpExpensive() - Return true if Flow Control is an expensive operation - /// that should be avoided. + /// Return true if Flow Control is an expensive operation that should be + /// avoided. bool isJumpExpensive() const { return JumpIsExpensive; } - /// isPredictableSelectExpensive - Return true if selects are only cheaper - /// than branches if the branch is unlikely to be predicted right. + /// Return true if selects are only cheaper than branches if the branch is + /// unlikely to be predicted right. bool isPredictableSelectExpensive() const { return PredictableSelectIsExpensive; } - /// getSetCCResultType - Return the ValueType of the result of SETCC - /// operations. Also used to obtain the target's preferred type for - /// the condition operand of SELECT and BRCOND nodes. In the case of - /// BRCOND the argument passed is MVT::Other since there are no other - /// operands to get a type hint from. + /// Return the ValueType of the result of SETCC operations. Also used to + /// obtain the target's preferred type for the condition operand of SELECT and + /// BRCOND nodes. In the case of BRCOND the argument passed is MVT::Other + /// since there are no other operands to get a type hint from. virtual EVT getSetCCResultType(LLVMContext &Context, EVT VT) const; - /// getCmpLibcallReturnType - Return the ValueType for comparison - /// libcalls. Comparions libcalls include floating point comparion calls, - /// and Ordered/Unordered check calls on floating point numbers. + /// Return the ValueType for comparison libcalls. Comparions libcalls include + /// floating point comparion calls, and Ordered/Unordered check calls on + /// floating point numbers. virtual MVT::SimpleValueType getCmpLibcallReturnType() const; - /// getBooleanContents - For targets without i1 registers, this gives the - /// nature of the high-bits of boolean values held in types wider than i1. + /// For targets without i1 registers, this gives the nature of the high-bits + /// of boolean values held in types wider than i1. + /// /// "Boolean values" are special true/false values produced by nodes like /// SETCC and consumed (as the condition) by nodes like SELECT and BRCOND. - /// Not to be confused with general values promoted from i1. - /// Some cpus distinguish between vectors of boolean and scalars; the isVec - /// parameter selects between the two kinds. For example on X86 a scalar - /// boolean should be zero extended from i1, while the elements of a vector - /// of booleans should be sign extended from i1. + /// Not to be confused with general values promoted from i1. Some cpus + /// distinguish between vectors of boolean and scalars; the isVec parameter + /// selects between the two kinds. For example on X86 a scalar boolean should + /// be zero extended from i1, while the elements of a vector of booleans + /// should be sign extended from i1. BooleanContent getBooleanContents(bool isVec) const { return isVec ? BooleanVectorContents : BooleanContents; } - /// getSchedulingPreference - Return target scheduling preference. + /// Return target scheduling preference. Sched::Preference getSchedulingPreference() const { return SchedPreferenceInfo; } - /// getSchedulingPreference - Some scheduler, e.g. hybrid, can switch to - /// different scheduling heuristics for different nodes. This function returns - /// the preference (or none) for the given node. + /// Some scheduler, e.g. hybrid, can switch to different scheduling heuristics + /// for different nodes. This function returns the preference (or none) for + /// the given node. virtual Sched::Preference getSchedulingPreference(SDNode *) const { return Sched::None; } - /// getRegClassFor - Return the register class that should be used for the - /// specified value type. + /// Return the register class that should be used for the specified value + /// type. virtual const TargetRegisterClass *getRegClassFor(MVT VT) const { const TargetRegisterClass *RC = RegClassForVT[VT.SimpleTy]; assert(RC && "This value type is not natively supported!"); return RC; } - /// getRepRegClassFor - Return the 'representative' register class for the - /// specified value type. The 'representative' register class is the largest - /// legal super-reg register class for the register class of the value type. - /// For example, on i386 the rep register class for i8, i16, and i32 are GR32; - /// while the rep register class is GR64 on x86_64. + /// Return the 'representative' register class for the specified value + /// type. + /// + /// The 'representative' register class is the largest legal super-reg + /// register class for the register class of the value type. For example, on + /// i386 the rep register class for i8, i16, and i32 are GR32; while the rep + /// register class is GR64 on x86_64. virtual const TargetRegisterClass *getRepRegClassFor(MVT VT) const { const TargetRegisterClass *RC = RepRegClassForVT[VT.SimpleTy]; return RC; } - /// getRepRegClassCostFor - Return the cost of the 'representative' register - /// class for the specified value type. + /// Return the cost of the 'representative' register class for the specified + /// value type. virtual uint8_t getRepRegClassCostFor(MVT VT) const { return RepRegClassCostForVT[VT.SimpleTy]; } - /// isTypeLegal - Return true if the target has native support for the - /// specified value type. This means that it has a register that directly - /// holds it without promotions or expansions. + /// Return true if the target has native support for the specified value type. + /// This means that it has a register that directly holds it without + /// promotions or expansions. bool isTypeLegal(EVT VT) const { assert(!VT.isSimple() || (unsigned)VT.getSimpleVT().SimpleTy < array_lengthof(RegClassForVT)); @@ -289,10 +298,10 @@ public: return ValueTypeActions; } - /// getTypeAction - Return how we should legalize values of this type, either - /// it is already legal (return 'Legal') or we need to promote it to a larger - /// type (return 'Promote'), or we need to expand it into multiple registers - /// of smaller integer type (return 'Expand'). 'Custom' is not an option. + /// Return how we should legalize values of this type, either it is already + /// legal (return 'Legal') or we need to promote it to a larger type (return + /// 'Promote'), or we need to expand it into multiple registers of smaller + /// integer type (return 'Expand'). 'Custom' is not an option. LegalizeTypeAction getTypeAction(LLVMContext &Context, EVT VT) const { return getTypeConversion(Context, VT).first; } @@ -300,20 +309,20 @@ public: return ValueTypeActions.getTypeAction(VT); } - /// getTypeToTransformTo - For types supported by the target, this is an - /// identity function. For types that must be promoted to larger types, this - /// returns the larger type to promote to. For integer types that are larger - /// than the largest integer register, this contains one step in the expansion - /// to get to the smaller register. For illegal floating point types, this - /// returns the integer type to transform to. + /// For types supported by the target, this is an identity function. For + /// types that must be promoted to larger types, this returns the larger type + /// to promote to. For integer types that are larger than the largest integer + /// register, this contains one step in the expansion to get to the smaller + /// register. For illegal floating point types, this returns the integer type + /// to transform to. EVT getTypeToTransformTo(LLVMContext &Context, EVT VT) const { return getTypeConversion(Context, VT).second; } - /// getTypeToExpandTo - For types supported by the target, this is an - /// identity function. For types that must be expanded (i.e. integer types - /// that are larger than the largest integer register or illegal floating - /// point types), this returns the largest legal type it will be expanded to. + /// For types supported by the target, this is an identity function. For + /// types that must be expanded (i.e. integer types that are larger than the + /// largest integer register or illegal floating point types), this returns + /// the largest legal type it will be expanded to. EVT getTypeToExpandTo(LLVMContext &Context, EVT VT) const { assert(!VT.isVector()); while (true) { @@ -329,24 +338,19 @@ public: } } - /// getVectorTypeBreakdown - Vector types are broken down into some number of - /// legal first class types. For example, EVT::v8f32 maps to 2 EVT::v4f32 - /// with Altivec or SSE1, or 8 promoted EVT::f64 values with the X86 FP stack. - /// Similarly, EVT::v2i64 turns into 4 EVT::i32 values with both PPC and X86. + /// Vector types are broken down into some number of legal first class types. + /// For example, EVT::v8f32 maps to 2 EVT::v4f32 with Altivec or SSE1, or 8 + /// promoted EVT::f64 values with the X86 FP stack. Similarly, EVT::v2i64 + /// turns into 4 EVT::i32 values with both PPC and X86. /// /// This method returns the number of registers needed, and the VT for each /// register. It also returns the VT and quantity of the intermediate values /// before they are promoted/expanded. - /// unsigned getVectorTypeBreakdown(LLVMContext &Context, EVT VT, EVT &IntermediateVT, unsigned &NumIntermediates, MVT &RegisterVT) const; - /// getTgtMemIntrinsic: Given an intrinsic, checks if on the target the - /// intrinsic will need to map to a MemIntrinsicNode (touches memory). If - /// this is the case, it returns true and store the intrinsic - /// information into the IntrinsicInfo that was passed to the function. struct IntrinsicInfo { unsigned opc; // target opcode EVT memVT; // memory VT @@ -358,45 +362,48 @@ public: bool writeMem; // writes memory? }; + /// Given an intrinsic, checks if on the target the intrinsic will need to map + /// to a MemIntrinsicNode (touches memory). If this is the case, it returns + /// true and store the intrinsic information into the IntrinsicInfo that was + /// passed to the function. virtual bool getTgtMemIntrinsic(IntrinsicInfo &, const CallInst &, unsigned /*Intrinsic*/) const { return false; } - /// isFPImmLegal - Returns true if the target can instruction select the - /// specified FP immediate natively. If false, the legalizer will materialize - /// the FP immediate as a load from a constant pool. + /// Returns true if the target can instruction select the specified FP + /// immediate natively. If false, the legalizer will materialize the FP + /// immediate as a load from a constant pool. virtual bool isFPImmLegal(const APFloat &/*Imm*/, EVT /*VT*/) const { return false; } - /// isShuffleMaskLegal - Targets can use this to indicate that they only - /// support *some* VECTOR_SHUFFLE operations, those with specific masks. - /// By default, if a target supports the VECTOR_SHUFFLE node, all mask values - /// are assumed to be legal. + /// Targets can use this to indicate that they only support *some* + /// VECTOR_SHUFFLE operations, those with specific masks. By default, if a + /// target supports the VECTOR_SHUFFLE node, all mask values are assumed to be + /// legal. virtual bool isShuffleMaskLegal(const SmallVectorImpl<int> &/*Mask*/, EVT /*VT*/) const { return true; } - /// canOpTrap - Returns true if the operation can trap for the value type. + /// Returns true if the operation can trap for the value type. + /// /// VT must be a legal type. By default, we optimistically assume most /// operations don't trap except for divide and remainder. virtual bool canOpTrap(unsigned Op, EVT VT) const; - /// isVectorClearMaskLegal - Similar to isShuffleMaskLegal. This is - /// used by Targets can use this to indicate if there is a suitable - /// VECTOR_SHUFFLE that can be used to replace a VAND with a constant - /// pool entry. + /// Similar to isShuffleMaskLegal. This is used by Targets can use this to + /// indicate if there is a suitable VECTOR_SHUFFLE that can be used to replace + /// a VAND with a constant pool entry. virtual bool isVectorClearMaskLegal(const SmallVectorImpl<int> &/*Mask*/, EVT /*VT*/) const { return false; } - /// getOperationAction - Return how this operation should be treated: either - /// it is legal, needs to be promoted to a larger size, needs to be - /// expanded to some other code sequence, or the target has a custom expander - /// for it. + /// Return how this operation should be treated: either it is legal, needs to + /// be promoted to a larger size, needs to be expanded to some other code + /// sequence, or the target has a custom expander for it. LegalizeAction getOperationAction(unsigned Op, EVT VT) const { if (VT.isExtended()) return Expand; // If a target-specific SDNode requires legalization, require the target @@ -406,59 +413,55 @@ public: return (LegalizeAction)OpActions[I][Op]; } - /// isOperationLegalOrCustom - Return true if the specified operation is - /// legal on this target or can be made legal with custom lowering. This - /// is used to help guide high-level lowering decisions. + /// Return true if the specified operation is legal on this target or can be + /// made legal with custom lowering. This is used to help guide high-level + /// lowering decisions. bool isOperationLegalOrCustom(unsigned Op, EVT VT) const { return (VT == MVT::Other || isTypeLegal(VT)) && (getOperationAction(Op, VT) == Legal || getOperationAction(Op, VT) == Custom); } - /// isOperationLegalOrPromote - Return true if the specified operation is - /// legal on this target or can be made legal using promotion. This - /// is used to help guide high-level lowering decisions. + /// Return true if the specified operation is legal on this target or can be + /// made legal using promotion. This is used to help guide high-level lowering + /// decisions. bool isOperationLegalOrPromote(unsigned Op, EVT VT) const { return (VT == MVT::Other || isTypeLegal(VT)) && (getOperationAction(Op, VT) == Legal || getOperationAction(Op, VT) == Promote); } - /// isOperationExpand - Return true if the specified operation is illegal on - /// this target or unlikely to be made legal with custom lowering. This is - /// used to help guide high-level lowering decisions. + /// Return true if the specified operation is illegal on this target or + /// unlikely to be made legal with custom lowering. This is used to help guide + /// high-level lowering decisions. bool isOperationExpand(unsigned Op, EVT VT) const { return (!isTypeLegal(VT) || getOperationAction(Op, VT) == Expand); } - /// isOperationLegal - Return true if the specified operation is legal on this - /// target. + /// Return true if the specified operation is legal on this target. bool isOperationLegal(unsigned Op, EVT VT) const { return (VT == MVT::Other || isTypeLegal(VT)) && getOperationAction(Op, VT) == Legal; } - /// getLoadExtAction - Return how this load with extension should be treated: - /// either it is legal, needs to be promoted to a larger size, needs to be - /// expanded to some other code sequence, or the target has a custom expander - /// for it. + /// Return how this load with extension should be treated: either it is legal, + /// needs to be promoted to a larger size, needs to be expanded to some other + /// code sequence, or the target has a custom expander for it. LegalizeAction getLoadExtAction(unsigned ExtType, MVT VT) const { assert(ExtType < ISD::LAST_LOADEXT_TYPE && VT < MVT::LAST_VALUETYPE && "Table isn't big enough!"); return (LegalizeAction)LoadExtActions[VT.SimpleTy][ExtType]; } - /// isLoadExtLegal - Return true if the specified load with extension is legal - /// on this target. + /// Return true if the specified load with extension is legal on this target. bool isLoadExtLegal(unsigned ExtType, EVT VT) const { return VT.isSimple() && getLoadExtAction(ExtType, VT.getSimpleVT()) == Legal; } - /// getTruncStoreAction - Return how this store with truncation should be - /// treated: either it is legal, needs to be promoted to a larger size, needs - /// to be expanded to some other code sequence, or the target has a custom - /// expander for it. + /// Return how this store with truncation should be treated: either it is + /// legal, needs to be promoted to a larger size, needs to be expanded to some + /// other code sequence, or the target has a custom expander for it. LegalizeAction getTruncStoreAction(MVT ValVT, MVT MemVT) const { assert(ValVT < MVT::LAST_VALUETYPE && MemVT < MVT::LAST_VALUETYPE && "Table isn't big enough!"); @@ -466,17 +469,16 @@ public: [MemVT.SimpleTy]; } - /// isTruncStoreLegal - Return true if the specified store with truncation is - /// legal on this target. + /// Return true if the specified store with truncation is legal on this + /// target. bool isTruncStoreLegal(EVT ValVT, EVT MemVT) const { return isTypeLegal(ValVT) && MemVT.isSimple() && getTruncStoreAction(ValVT.getSimpleVT(), MemVT.getSimpleVT()) == Legal; } - /// getIndexedLoadAction - Return how the indexed load should be treated: - /// either it is legal, needs to be promoted to a larger size, needs to be - /// expanded to some other code sequence, or the target has a custom expander - /// for it. + /// Return how the indexed load should be treated: either it is legal, needs + /// to be promoted to a larger size, needs to be expanded to some other code + /// sequence, or the target has a custom expander for it. LegalizeAction getIndexedLoadAction(unsigned IdxMode, MVT VT) const { assert(IdxMode < ISD::LAST_INDEXED_MODE && VT < MVT::LAST_VALUETYPE && @@ -485,18 +487,16 @@ public: return (LegalizeAction)((IndexedModeActions[Ty][IdxMode] & 0xf0) >> 4); } - /// isIndexedLoadLegal - Return true if the specified indexed load is legal - /// on this target. + /// Return true if the specified indexed load is legal on this target. bool isIndexedLoadLegal(unsigned IdxMode, EVT VT) const { return VT.isSimple() && (getIndexedLoadAction(IdxMode, VT.getSimpleVT()) == Legal || getIndexedLoadAction(IdxMode, VT.getSimpleVT()) == Custom); } - /// getIndexedStoreAction - Return how the indexed store should be treated: - /// either it is legal, needs to be promoted to a larger size, needs to be - /// expanded to some other code sequence, or the target has a custom expander - /// for it. + /// Return how the indexed store should be treated: either it is legal, needs + /// to be promoted to a larger size, needs to be expanded to some other code + /// sequence, or the target has a custom expander for it. LegalizeAction getIndexedStoreAction(unsigned IdxMode, MVT VT) const { assert(IdxMode < ISD::LAST_INDEXED_MODE && VT < MVT::LAST_VALUETYPE && @@ -505,17 +505,16 @@ public: return (LegalizeAction)(IndexedModeActions[Ty][IdxMode] & 0x0f); } - /// isIndexedStoreLegal - Return true if the specified indexed load is legal - /// on this target. + /// Return true if the specified indexed load is legal on this target. bool isIndexedStoreLegal(unsigned IdxMode, EVT VT) const { return VT.isSimple() && (getIndexedStoreAction(IdxMode, VT.getSimpleVT()) == Legal || getIndexedStoreAction(IdxMode, VT.getSimpleVT()) == Custom); } - /// getCondCodeAction - Return how the condition code should be treated: - /// either it is legal, needs to be expanded to some other code sequence, - /// or the target has a custom expander for it. + /// Return how the condition code should be treated: either it is legal, needs + /// to be expanded to some other code sequence, or the target has a custom + /// expander for it. LegalizeAction getCondCodeAction(ISD::CondCode CC, MVT VT) const { assert((unsigned)CC < array_lengthof(CondCodeActions) && @@ -530,8 +529,7 @@ public: return Action; } - /// isCondCodeLegal - Return true if the specified condition code is legal - /// on this target. + /// Return true if the specified condition code is legal on this target. bool isCondCodeLegal(ISD::CondCode CC, MVT VT) const { return getCondCodeAction(CC, VT) == Legal || @@ -539,8 +537,8 @@ public: } - /// getTypeToPromoteTo - If the action for this operation is to promote, this - /// method returns the ValueType to promote to. + /// If the action for this operation is to promote, this method returns the + /// ValueType to promote to. MVT getTypeToPromoteTo(unsigned Op, MVT VT) const { assert(getOperationAction(Op, VT) == Promote && "This operation isn't promoted!"); @@ -564,10 +562,10 @@ public: return NVT; } - /// getValueType - Return the EVT corresponding to this LLVM type. - /// This is fixed by the LLVM operations except for the pointer size. If - /// AllowUnknown is true, this will return MVT::Other for types with no EVT - /// counterpart (e.g. structs), otherwise it will assert. + /// Return the EVT corresponding to this LLVM type. This is fixed by the LLVM + /// operations except for the pointer size. If AllowUnknown is true, this + /// will return MVT::Other for types with no EVT counterpart (e.g. structs), + /// otherwise it will assert. EVT getValueType(Type *Ty, bool AllowUnknown = false) const { // Lower scalar pointers to native pointer types. if (Ty->isPointerTy()) return PointerTy; @@ -589,20 +587,17 @@ public: return getValueType(Ty, AllowUnknown).getSimpleVT(); } - /// getByValTypeAlignment - Return the desired alignment for ByVal aggregate - /// function arguments in the caller parameter area. This is the actual - /// alignment, not its logarithm. + /// Return the desired alignment for ByVal aggregate function arguments in the + /// caller parameter area. This is the actual alignment, not its logarithm. virtual unsigned getByValTypeAlignment(Type *Ty) const; - /// getRegisterType - Return the type of registers that this ValueType will - /// eventually require. + /// Return the type of registers that this ValueType will eventually require. MVT getRegisterType(MVT VT) const { assert((unsigned)VT.SimpleTy < array_lengthof(RegisterTypeForVT)); return RegisterTypeForVT[VT.SimpleTy]; } - /// getRegisterType - Return the type of registers that this ValueType will - /// eventually require. + /// Return the type of registers that this ValueType will eventually require. MVT getRegisterType(LLVMContext &Context, EVT VT) const { if (VT.isSimple()) { assert((unsigned)VT.getSimpleVT().SimpleTy < @@ -623,12 +618,14 @@ public: llvm_unreachable("Unsupported extended type!"); } - /// getNumRegisters - Return the number of registers that this ValueType will - /// eventually require. This is one for any types promoted to live in larger - /// registers, but may be more than one for types (like i64) that are split - /// into pieces. For types like i140, which are first promoted then expanded, - /// it is the number of registers needed to hold all the bits of the original - /// type. For an i140 on a 32 bit machine this means 5 registers. + /// Return the number of registers that this ValueType will eventually + /// require. + /// + /// This is one for any types promoted to live in larger registers, but may be + /// more than one for types (like i64) that are split into pieces. For types + /// like i140, which are first promoted then expanded, it is the number of + /// registers needed to hold all the bits of the original type. For an i140 + /// on a 32 bit machine this means 5 registers. unsigned getNumRegisters(LLVMContext &Context, EVT VT) const { if (VT.isSimple()) { assert((unsigned)VT.getSimpleVT().SimpleTy < @@ -649,68 +646,72 @@ public: llvm_unreachable("Unsupported extended type!"); } - /// ShouldShrinkFPConstant - If true, then instruction selection should - /// seek to shrink the FP constant of the specified type to a smaller type - /// in order to save space and / or reduce runtime. + /// If true, then instruction selection should seek to shrink the FP constant + /// of the specified type to a smaller type in order to save space and / or + /// reduce runtime. virtual bool ShouldShrinkFPConstant(EVT) const { return true; } - /// hasTargetDAGCombine - If true, the target has custom DAG combine - /// transformations that it can perform for the specified node. + /// If true, the target has custom DAG combine transformations that it can + /// perform for the specified node. bool hasTargetDAGCombine(ISD::NodeType NT) const { assert(unsigned(NT >> 3) < array_lengthof(TargetDAGCombineArray)); return TargetDAGCombineArray[NT >> 3] & (1 << (NT&7)); } + /// \brief Get maximum # of store operations permitted for llvm.memset + /// /// This function returns the maximum number of store operations permitted /// to replace a call to llvm.memset. The value is set by the target at the /// performance threshold for such a replacement. If OptSize is true, /// return the limit for functions that have OptSize attribute. - /// @brief Get maximum # of store operations permitted for llvm.memset unsigned getMaxStoresPerMemset(bool OptSize) const { return OptSize ? MaxStoresPerMemsetOptSize : MaxStoresPerMemset; } + /// \brief Get maximum # of store operations permitted for llvm.memcpy + /// /// This function returns the maximum number of store operations permitted /// to replace a call to llvm.memcpy. The value is set by the target at the /// performance threshold for such a replacement. If OptSize is true, /// return the limit for functions that have OptSize attribute. - /// @brief Get maximum # of store operations permitted for llvm.memcpy unsigned getMaxStoresPerMemcpy(bool OptSize) const { return OptSize ? MaxStoresPerMemcpyOptSize : MaxStoresPerMemcpy; } + /// \brief Get maximum # of store operations permitted for llvm.memmove + /// /// This function returns the maximum number of store operations permitted /// to replace a call to llvm.memmove. The value is set by the target at the /// performance threshold for such a replacement. If OptSize is true, /// return the limit for functions that have OptSize attribute. - /// @brief Get maximum # of store operations permitted for llvm.memmove unsigned getMaxStoresPerMemmove(bool OptSize) const { return OptSize ? MaxStoresPerMemmoveOptSize : MaxStoresPerMemmove; } + /// \brief Determine if the target supports unaligned memory accesses. + /// /// This function returns true if the target allows unaligned memory accesses. /// of the specified type. If true, it also returns whether the unaligned /// memory access is "fast" in the second argument by reference. This is used, - /// for example, in situations where an array copy/move/set is converted to a + /// for example, in situations where an array copy/move/set is converted to a /// sequence of store operations. It's use helps to ensure that such - /// replacements don't generate code that causes an alignment error (trap) on + /// replacements don't generate code that causes an alignment error (trap) on /// the target machine. - /// @brief Determine if the target supports unaligned memory accesses. virtual bool allowsUnalignedMemoryAccesses(EVT, bool * /*Fast*/ = 0) const { return false; } - /// getOptimalMemOpType - Returns the target specific optimal type for load - /// and store operations as a result of memset, memcpy, and memmove - /// lowering. If DstAlign is zero that means it's safe to destination - /// alignment can satisfy any constraint. Similarly if SrcAlign is zero it - /// means there isn't a need to check it against alignment requirement, - /// probably because the source does not need to be loaded. If 'IsMemset' is - /// true, that means it's expanding a memset. If 'ZeroMemset' is true, that - /// means it's a memset of zero. 'MemcpyStrSrc' indicates whether the memcpy - /// source is constant so it does not need to be loaded. - /// It returns EVT::Other if the type should be determined using generic - /// target-independent logic. + /// Returns the target specific optimal type for load and store operations as + /// a result of memset, memcpy, and memmove lowering. + /// + /// If DstAlign is zero that means it's safe to destination alignment can + /// satisfy any constraint. Similarly if SrcAlign is zero it means there isn't + /// a need to check it against alignment requirement, probably because the + /// source does not need to be loaded. If 'IsMemset' is true, that means it's + /// expanding a memset. If 'ZeroMemset' is true, that means it's a memset of + /// zero. 'MemcpyStrSrc' indicates whether the memcpy source is constant so it + /// does not need to be loaded. It returns EVT::Other if the type should be + /// determined using generic target-independent logic. virtual EVT getOptimalMemOpType(uint64_t /*Size*/, unsigned /*DstAlign*/, unsigned /*SrcAlign*/, bool /*IsMemset*/, @@ -720,113 +721,102 @@ public: return MVT::Other; } - /// isSafeMemOpType - Returns true if it's safe to use load / store of the - /// specified type to expand memcpy / memset inline. This is mostly true - /// for all types except for some special cases. For example, on X86 - /// targets without SSE2 f64 load / store are done with fldl / fstpl which - /// also does type conversion. Note the specified type doesn't have to be - /// legal as the hook is used before type legalization. + /// Returns true if it's safe to use load / store of the specified type to + /// expand memcpy / memset inline. + /// + /// This is mostly true for all types except for some special cases. For + /// example, on X86 targets without SSE2 f64 load / store are done with fldl / + /// fstpl which also does type conversion. Note the specified type doesn't + /// have to be legal as the hook is used before type legalization. virtual bool isSafeMemOpType(MVT /*VT*/) const { return true; } - /// usesUnderscoreSetJmp - Determine if we should use _setjmp or setjmp - /// to implement llvm.setjmp. + /// Determine if we should use _setjmp or setjmp to implement llvm.setjmp. bool usesUnderscoreSetJmp() const { return UseUnderscoreSetJmp; } - /// usesUnderscoreLongJmp - Determine if we should use _longjmp or longjmp - /// to implement llvm.longjmp. + /// Determine if we should use _longjmp or longjmp to implement llvm.longjmp. bool usesUnderscoreLongJmp() const { return UseUnderscoreLongJmp; } - /// supportJumpTables - return whether the target can generate code for - /// jump tables. + /// Return whether the target can generate code for jump tables. bool supportJumpTables() const { return SupportJumpTables; } - /// getMinimumJumpTableEntries - return integer threshold on number of - /// blocks to use jump tables rather than if sequence. + /// Return integer threshold on number of blocks to use jump tables rather + /// than if sequence. int getMinimumJumpTableEntries() const { return MinimumJumpTableEntries; } - /// getStackPointerRegisterToSaveRestore - If a physical register, this - /// specifies the register that llvm.savestack/llvm.restorestack should save - /// and restore. + /// If a physical register, this specifies the register that + /// llvm.savestack/llvm.restorestack should save and restore. unsigned getStackPointerRegisterToSaveRestore() const { return StackPointerRegisterToSaveRestore; } - /// getExceptionPointerRegister - If a physical register, this returns - /// the register that receives the exception address on entry to a landing - /// pad. + /// If a physical register, this returns the register that receives the + /// exception address on entry to a landing pad. unsigned getExceptionPointerRegister() const { return ExceptionPointerRegister; } - /// getExceptionSelectorRegister - If a physical register, this returns - /// the register that receives the exception typeid on entry to a landing - /// pad. + /// If a physical register, this returns the register that receives the + /// exception typeid on entry to a landing pad. unsigned getExceptionSelectorRegister() const { return ExceptionSelectorRegister; } - /// getJumpBufSize - returns the target's jmp_buf size in bytes (if never - /// set, the default is 200) + /// Returns the target's jmp_buf size in bytes (if never set, the default is + /// 200) unsigned getJumpBufSize() const { return JumpBufSize; } - /// getJumpBufAlignment - returns the target's jmp_buf alignment in bytes - /// (if never set, the default is 0) + /// Returns the target's jmp_buf alignment in bytes (if never set, the default + /// is 0) unsigned getJumpBufAlignment() const { return JumpBufAlignment; } - /// getMinStackArgumentAlignment - return the minimum stack alignment of an - /// argument. + /// Return the minimum stack alignment of an argument. unsigned getMinStackArgumentAlignment() const { return MinStackArgumentAlignment; } - /// getMinFunctionAlignment - return the minimum function alignment. - /// + /// Return the minimum function alignment. unsigned getMinFunctionAlignment() const { return MinFunctionAlignment; } - /// getPrefFunctionAlignment - return the preferred function alignment. - /// + /// Return the preferred function alignment. unsigned getPrefFunctionAlignment() const { return PrefFunctionAlignment; } - /// getPrefLoopAlignment - return the preferred loop alignment. - /// + /// Return the preferred loop alignment. unsigned getPrefLoopAlignment() const { return PrefLoopAlignment; } - /// getInsertFencesFor - return whether the DAG builder should automatically - /// insert fences and reduce ordering for atomics. - /// + /// Return whether the DAG builder should automatically insert fences and + /// reduce ordering for atomics. bool getInsertFencesForAtomic() const { return InsertFencesForAtomic; } - /// getStackCookieLocation - Return true if the target stores stack - /// protector cookies at a fixed offset in some non-standard address - /// space, and populates the address space and offset as - /// appropriate. + /// Return true if the target stores stack protector cookies at a fixed offset + /// in some non-standard address space, and populates the address space and + /// offset as appropriate. virtual bool getStackCookieLocation(unsigned &/*AddressSpace*/, unsigned &/*Offset*/) const { return false; } - /// getMaximalGlobalOffset - Returns the maximal possible offset which can be - /// used for loads / stores from the global. + /// Returns the maximal possible offset which can be used for loads / stores + /// from the global. virtual unsigned getMaximalGlobalOffset() const { return 0; } @@ -852,106 +842,98 @@ public: virtual void resetOperationActions() {} protected: - /// setBooleanContents - Specify how the target extends the result of a - /// boolean value from i1 to a wider type. See getBooleanContents. + /// Specify how the target extends the result of a boolean value from i1 to a + /// wider type. See getBooleanContents. void setBooleanContents(BooleanContent Ty) { BooleanContents = Ty; } - /// setBooleanVectorContents - Specify how the target extends the result - /// of a vector boolean value from a vector of i1 to a wider type. See - /// getBooleanContents. + + /// Specify how the target extends the result of a vector boolean value from a + /// vector of i1 to a wider type. See getBooleanContents. void setBooleanVectorContents(BooleanContent Ty) { BooleanVectorContents = Ty; } - /// setSchedulingPreference - Specify the target scheduling preference. + /// Specify the target scheduling preference. void setSchedulingPreference(Sched::Preference Pref) { SchedPreferenceInfo = Pref; } - /// setUseUnderscoreSetJmp - Indicate whether this target prefers to - /// use _setjmp to implement llvm.setjmp or the non _ version. - /// Defaults to false. + /// Indicate whether this target prefers to use _setjmp to implement + /// llvm.setjmp or the non _ version. Defaults to false. void setUseUnderscoreSetJmp(bool Val) { UseUnderscoreSetJmp = Val; } - /// setUseUnderscoreLongJmp - Indicate whether this target prefers to - /// use _longjmp to implement llvm.longjmp or the non _ version. - /// Defaults to false. + /// Indicate whether this target prefers to use _longjmp to implement + /// llvm.longjmp or the non _ version. Defaults to false. void setUseUnderscoreLongJmp(bool Val) { UseUnderscoreLongJmp = Val; } - /// setSupportJumpTables - Indicate whether the target can generate code for - /// jump tables. + /// Indicate whether the target can generate code for jump tables. void setSupportJumpTables(bool Val) { SupportJumpTables = Val; } - /// setMinimumJumpTableEntries - Indicate the number of blocks to generate - /// jump tables rather than if sequence. + /// Indicate the number of blocks to generate jump tables rather than if + /// sequence. void setMinimumJumpTableEntries(int Val) { MinimumJumpTableEntries = Val; } - /// setStackPointerRegisterToSaveRestore - If set to a physical register, this - /// specifies the register that llvm.savestack/llvm.restorestack should save - /// and restore. + /// If set to a physical register, this specifies the register that + /// llvm.savestack/llvm.restorestack should save and restore. void setStackPointerRegisterToSaveRestore(unsigned R) { StackPointerRegisterToSaveRestore = R; } - /// setExceptionPointerRegister - If set to a physical register, this sets - /// the register that receives the exception address on entry to a landing - /// pad. + /// If set to a physical register, this sets the register that receives the + /// exception address on entry to a landing pad. void setExceptionPointerRegister(unsigned R) { ExceptionPointerRegister = R; } - /// setExceptionSelectorRegister - If set to a physical register, this sets - /// the register that receives the exception typeid on entry to a landing - /// pad. + /// If set to a physical register, this sets the register that receives the + /// exception typeid on entry to a landing pad. void setExceptionSelectorRegister(unsigned R) { ExceptionSelectorRegister = R; } - /// SelectIsExpensive - Tells the code generator not to expand operations - /// into sequences that use the select operations if possible. + /// Tells the code generator not to expand operations into sequences that use + /// the select operations if possible. void setSelectIsExpensive(bool isExpensive = true) { SelectIsExpensive = isExpensive; } - /// JumpIsExpensive - Tells the code generator not to expand sequence of - /// operations into a separate sequences that increases the amount of - /// flow control. + /// Tells the code generator not to expand sequence of operations into a + /// separate sequences that increases the amount of flow control. void setJumpIsExpensive(bool isExpensive = true) { JumpIsExpensive = isExpensive; } - /// setIntDivIsCheap - Tells the code generator that integer divide is - /// expensive, and if possible, should be replaced by an alternate sequence - /// of instructions not containing an integer divide. + /// Tells the code generator that integer divide is expensive, and if + /// possible, should be replaced by an alternate sequence of instructions not + /// containing an integer divide. void setIntDivIsCheap(bool isCheap = true) { IntDivIsCheap = isCheap; } - /// addBypassSlowDiv - Tells the code generator which bitwidths to bypass. + /// Tells the code generator which bitwidths to bypass. void addBypassSlowDiv(unsigned int SlowBitWidth, unsigned int FastBitWidth) { BypassSlowDivWidths[SlowBitWidth] = FastBitWidth; } - /// setPow2DivIsCheap - Tells the code generator that it shouldn't generate - /// srl/add/sra for a signed divide by power of two, and let the target handle - /// it. + /// Tells the code generator that it shouldn't generate srl/add/sra for a + /// signed divide by power of two, and let the target handle it. void setPow2DivIsCheap(bool isCheap = true) { Pow2DivIsCheap = isCheap; } - /// addRegisterClass - Add the specified register class as an available - /// regclass for the specified value type. This indicates the selector can - /// handle values of that class natively. + /// Add the specified register class as an available regclass for the + /// specified value type. This indicates the selector can handle values of + /// that class natively. void addRegisterClass(MVT VT, const TargetRegisterClass *RC) { assert((unsigned)VT.SimpleTy < array_lengthof(RegClassForVT)); AvailableRegClasses.push_back(std::make_pair(VT, RC)); RegClassForVT[VT.SimpleTy] = RC; } - /// clearRegisterClasses - Remove all register classes. + /// Remove all register classes. void clearRegisterClasses() { memset(RegClassForVT, 0,MVT::LAST_VALUETYPE * sizeof(TargetRegisterClass*)); @@ -962,25 +944,25 @@ protected: void clearOperationActions() { } - /// findRepresentativeClass - Return the largest legal super-reg register class - /// of the register class for the specified type and its associated "cost". + /// Return the largest legal super-reg register class of the register class + /// for the specified type and its associated "cost". virtual std::pair<const TargetRegisterClass*, uint8_t> findRepresentativeClass(MVT VT) const; - /// computeRegisterProperties - Once all of the register classes are added, - /// this allows us to compute derived properties we expose. + /// Once all of the register classes are added, this allows us to compute + /// derived properties we expose. void computeRegisterProperties(); - /// setOperationAction - Indicate that the specified operation does not work - /// with the specified type and indicate what to do about it. + /// Indicate that the specified operation does not work with the specified + /// type and indicate what to do about it. void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action) { assert(Op < array_lengthof(OpActions[0]) && "Table isn't big enough!"); OpActions[(unsigned)VT.SimpleTy][Op] = (uint8_t)Action; } - /// setLoadExtAction - Indicate that the specified load with extension does - /// not work with the specified type and indicate what to do about it. + /// Indicate that the specified load with extension does not work with the + /// specified type and indicate what to do about it. void setLoadExtAction(unsigned ExtType, MVT VT, LegalizeAction Action) { assert(ExtType < ISD::LAST_LOADEXT_TYPE && VT < MVT::LAST_VALUETYPE && @@ -988,8 +970,8 @@ protected: LoadExtActions[VT.SimpleTy][ExtType] = (uint8_t)Action; } - /// setTruncStoreAction - Indicate that the specified truncating store does - /// not work with the specified type and indicate what to do about it. + /// Indicate that the specified truncating store does not work with the + /// specified type and indicate what to do about it. void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action) { assert(ValVT < MVT::LAST_VALUETYPE && MemVT < MVT::LAST_VALUETYPE && @@ -997,9 +979,10 @@ protected: TruncStoreActions[ValVT.SimpleTy][MemVT.SimpleTy] = (uint8_t)Action; } - /// setIndexedLoadAction - Indicate that the specified indexed load does or - /// does not work with the specified type and indicate what to do abort - /// it. NOTE: All indexed mode loads are initialized to Expand in + /// Indicate that the specified indexed load does or does not work with the + /// specified type and indicate what to do abort it. + /// + /// NOTE: All indexed mode loads are initialized to Expand in /// TargetLowering.cpp void setIndexedLoadAction(unsigned IdxMode, MVT VT, LegalizeAction Action) { @@ -1010,9 +993,10 @@ protected: IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] |= ((uint8_t)Action) <<4; } - /// setIndexedStoreAction - Indicate that the specified indexed store does or - /// does not work with the specified type and indicate what to do about - /// it. NOTE: All indexed mode stores are initialized to Expand in + /// Indicate that the specified indexed store does or does not work with the + /// specified type and indicate what to do about it. + /// + /// NOTE: All indexed mode stores are initialized to Expand in /// TargetLowering.cpp void setIndexedStoreAction(unsigned IdxMode, MVT VT, LegalizeAction Action) { @@ -1023,8 +1007,8 @@ protected: IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] |= ((uint8_t)Action); } - /// setCondCodeAction - Indicate that the specified condition code is or isn't - /// supported on the target and indicate what to do about it. + /// Indicate that the specified condition code is or isn't supported on the + /// target and indicate what to do about it. void setCondCodeAction(ISD::CondCode CC, MVT VT, LegalizeAction Action) { assert(VT < MVT::LAST_VALUETYPE && @@ -1039,63 +1023,59 @@ protected: |= (uint64_t)Action << (VT.SimpleTy & 0x1F)*2; } - /// AddPromotedToType - If Opc/OrigVT is specified as being promoted, the - /// promotion code defaults to trying a larger integer/fp until it can find - /// one that works. If that default is insufficient, this method can be used - /// by the target to override the default. + /// If Opc/OrigVT is specified as being promoted, the promotion code defaults + /// to trying a larger integer/fp until it can find one that works. If that + /// default is insufficient, this method can be used by the target to override + /// the default. void AddPromotedToType(unsigned Opc, MVT OrigVT, MVT DestVT) { PromoteToType[std::make_pair(Opc, OrigVT.SimpleTy)] = DestVT.SimpleTy; } - /// setTargetDAGCombine - Targets should invoke this method for each target - /// independent node that they want to provide a custom DAG combiner for by - /// implementing the PerformDAGCombine virtual method. + /// Targets should invoke this method for each target independent node that + /// they want to provide a custom DAG combiner for by implementing the + /// PerformDAGCombine virtual method. void setTargetDAGCombine(ISD::NodeType NT) { assert(unsigned(NT >> 3) < array_lengthof(TargetDAGCombineArray)); TargetDAGCombineArray[NT >> 3] |= 1 << (NT&7); } - /// setJumpBufSize - Set the target's required jmp_buf buffer size (in - /// bytes); default is 200 + /// Set the target's required jmp_buf buffer size (in bytes); default is 200 void setJumpBufSize(unsigned Size) { JumpBufSize = Size; } - /// setJumpBufAlignment - Set the target's required jmp_buf buffer - /// alignment (in bytes); default is 0 + /// Set the target's required jmp_buf buffer alignment (in bytes); default is + /// 0 void setJumpBufAlignment(unsigned Align) { JumpBufAlignment = Align; } - /// setMinFunctionAlignment - Set the target's minimum function alignment (in - /// log2(bytes)) + /// Set the target's minimum function alignment (in log2(bytes)) void setMinFunctionAlignment(unsigned Align) { MinFunctionAlignment = Align; } - /// setPrefFunctionAlignment - Set the target's preferred function alignment. - /// This should be set if there is a performance benefit to - /// higher-than-minimum alignment (in log2(bytes)) + /// Set the target's preferred function alignment. This should be set if + /// there is a performance benefit to higher-than-minimum alignment (in + /// log2(bytes)) void setPrefFunctionAlignment(unsigned Align) { PrefFunctionAlignment = Align; } - /// setPrefLoopAlignment - Set the target's preferred loop alignment. Default - /// alignment is zero, it means the target does not care about loop alignment. - /// The alignment is specified in log2(bytes). + /// Set the target's preferred loop alignment. Default alignment is zero, it + /// means the target does not care about loop alignment. The alignment is + /// specified in log2(bytes). void setPrefLoopAlignment(unsigned Align) { PrefLoopAlignment = Align; } - /// setMinStackArgumentAlignment - Set the minimum stack alignment of an - /// argument (in log2(bytes)). + /// Set the minimum stack alignment of an argument (in log2(bytes)). void setMinStackArgumentAlignment(unsigned Align) { MinStackArgumentAlignment = Align; } - /// setInsertFencesForAtomic - Set if the DAG builder should - /// automatically insert fences and reduce the order of atomic memory - /// operations to Monotonic. + /// Set if the DAG builder should automatically insert fences and reduce the + /// order of atomic memory operations to Monotonic. void setInsertFencesForAtomic(bool fence) { InsertFencesForAtomic = fence; } @@ -1105,25 +1085,24 @@ public: // Addressing mode description hooks (used by LSR etc). // - /// GetAddrModeArguments - CodeGenPrepare sinks address calculations into the - /// same BB as Load/Store instructions reading the address. This allows as - /// much computation as possible to be done in the address mode for that - /// operand. This hook lets targets also pass back when this should be done - /// on intrinsics which load/store. + /// CodeGenPrepare sinks address calculations into the same BB as Load/Store + /// instructions reading the address. This allows as much computation as + /// possible to be done in the address mode for that operand. This hook lets + /// targets also pass back when this should be done on intrinsics which + /// load/store. virtual bool GetAddrModeArguments(IntrinsicInst * /*I*/, SmallVectorImpl<Value*> &/*Ops*/, Type *&/*AccessTy*/) const { return false; } - /// AddrMode - This represents an addressing mode of: + /// This represents an addressing mode of: /// BaseGV + BaseOffs + BaseReg + Scale*ScaleReg /// If BaseGV is null, there is no BaseGV. /// If BaseOffs is zero, there is no base offset. /// If HasBaseReg is false, there is no base register. /// If Scale is zero, there is no ScaleReg. Scale of 1 indicates a reg with /// no scale. - /// struct AddrMode { GlobalValue *BaseGV; int64_t BaseOffs; @@ -1132,16 +1111,17 @@ public: AddrMode() : BaseGV(0), BaseOffs(0), HasBaseReg(false), Scale(0) {} }; - /// isLegalAddressingMode - Return true if the addressing mode represented by - /// AM is legal for this target, for a load/store of the specified type. + /// Return true if the addressing mode represented by AM is legal for this + /// target, for a load/store of the specified type. + /// /// The type may be VoidTy, in which case only return true if the addressing - /// mode is legal for a load/store of any legal type. - /// TODO: Handle pre/postinc as well. + /// mode is legal for a load/store of any legal type. TODO: Handle + /// pre/postinc as well. virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const; - /// \brief Return the cost of the scaling factor used in the addressing - /// mode represented by AM for this target, for a load/store - /// of the specified type. + /// \brief Return the cost of the scaling factor used in the addressing mode + /// represented by AM for this target, for a load/store of the specified type. + /// /// If the AM is supported, the return value must be >= 0. /// If the AM is not supported, it returns a negative value. /// TODO: Handle pre/postinc as well. @@ -1151,41 +1131,48 @@ public: return -1; } - /// isLegalICmpImmediate - Return true if the specified immediate is legal - /// icmp immediate, that is the target has icmp instructions which can compare - /// a register against the immediate without having to materialize the - /// immediate into a register. + /// Return true if the specified immediate is legal icmp immediate, that is + /// the target has icmp instructions which can compare a register against the + /// immediate without having to materialize the immediate into a register. virtual bool isLegalICmpImmediate(int64_t) const { return true; } - /// isLegalAddImmediate - Return true if the specified immediate is legal - /// add immediate, that is the target has add instructions which can add - /// a register with the immediate without having to materialize the - /// immediate into a register. + /// Return true if the specified immediate is legal add immediate, that is the + /// target has add instructions which can add a register with the immediate + /// without having to materialize the immediate into a register. virtual bool isLegalAddImmediate(int64_t) const { return true; } - /// isTruncateFree - Return true if it's free to truncate a value of - /// type Ty1 to type Ty2. e.g. On x86 it's free to truncate a i32 value in - /// register EAX to i16 by referencing its sub-register AX. + /// Return true if it's free to truncate a value of type Ty1 to type + /// Ty2. e.g. On x86 it's free to truncate a i32 value in register EAX to i16 + /// by referencing its sub-register AX. virtual bool isTruncateFree(Type * /*Ty1*/, Type * /*Ty2*/) const { return false; } + /// Return true if a truncation from Ty1 to Ty2 is permitted when deciding + /// whether a call is in tail position. Typically this means that both results + /// would be assigned to the same register or stack slot, but it could mean + /// the target performs adequate checks of its own before proceeding with the + /// tail call. + virtual bool allowTruncateForTailCall(Type * /*Ty1*/, Type * /*Ty2*/) const { + return false; + } + virtual bool isTruncateFree(EVT /*VT1*/, EVT /*VT2*/) const { return false; } - /// isZExtFree - Return true if any actual instruction that defines a - /// value of type Ty1 implicitly zero-extends the value to Ty2 in the result - /// register. This does not necessarily include registers defined in - /// unknown ways, such as incoming arguments, or copies from unknown - /// virtual registers. Also, if isTruncateFree(Ty2, Ty1) is true, this - /// does not necessarily apply to truncate instructions. e.g. on x86-64, - /// all instructions that define 32-bit values implicit zero-extend the - /// result out to 64 bits. + /// Return true if any actual instruction that defines a value of type Ty1 + /// implicitly zero-extends the value to Ty2 in the result register. + /// + /// This does not necessarily include registers defined in unknown ways, such + /// as incoming arguments, or copies from unknown virtual registers. Also, if + /// isTruncateFree(Ty2, Ty1) is true, this does not necessarily apply to + /// truncate instructions. e.g. on x86-64, all instructions that define 32-bit + /// values implicit zero-extend the result out to 64 bits. virtual bool isZExtFree(Type * /*Ty1*/, Type * /*Ty2*/) const { return false; } @@ -1194,36 +1181,42 @@ public: return false; } - /// isZExtFree - Return true if zero-extending the specific node Val to type - /// VT2 is free (either because it's implicitly zero-extended such as ARM - /// ldrb / ldrh or because it's folded such as X86 zero-extending loads). + /// Return true if zero-extending the specific node Val to type VT2 is free + /// (either because it's implicitly zero-extended such as ARM ldrb / ldrh or + /// because it's folded such as X86 zero-extending loads). virtual bool isZExtFree(SDValue Val, EVT VT2) const { return isZExtFree(Val.getValueType(), VT2); } - /// isFNegFree - Return true if an fneg operation is free to the point where - /// it is never worthwhile to replace it with a bitwise operation. - virtual bool isFNegFree(EVT) const { + /// Return true if an fneg operation is free to the point where it is never + /// worthwhile to replace it with a bitwise operation. + virtual bool isFNegFree(EVT VT) const { + assert(VT.isFloatingPoint()); return false; } - /// isFAbsFree - Return true if an fneg operation is free to the point where - /// it is never worthwhile to replace it with a bitwise operation. - virtual bool isFAbsFree(EVT) const { + /// Return true if an fabs operation is free to the point where it is never + /// worthwhile to replace it with a bitwise operation. + virtual bool isFAbsFree(EVT VT) const { + assert(VT.isFloatingPoint()); return false; } - /// isFMAFasterThanMulAndAdd - Return true if an FMA operation is faster than - /// a pair of mul and add instructions. fmuladd intrinsics will be expanded to - /// FMAs when this method returns true (and FMAs are legal), otherwise fmuladd - /// is expanded to mul + add. - virtual bool isFMAFasterThanMulAndAdd(EVT) const { + /// Return true if an FMA operation is faster than a pair of fmul and fadd + /// instructions. fmuladd intrinsics will be expanded to FMAs when this method + /// returns true, otherwise fmuladd is expanded to fmul + fadd. + /// + /// NOTE: This may be called before legalization on types for which FMAs are + /// not legal, but should return true if those types will eventually legalize + /// to types that support FMAs. After legalization, it will only be called on + /// types that support FMAs (via Legal or Custom actions) + virtual bool isFMAFasterThanFMulAndFAdd(EVT) const { return false; } - /// isNarrowingProfitable - Return true if it's profitable to narrow - /// operations of type VT1 to VT2. e.g. on x86, it's profitable to narrow - /// from i32 to i8 but not from i32 to i16. + /// Return true if it's profitable to narrow operations of type VT1 to + /// VT2. e.g. on x86, it's profitable to narrow from i32 to i8 but not from + /// i32 to i16. virtual bool isNarrowingProfitable(EVT /*VT1*/, EVT /*VT2*/) const { return false; } @@ -1232,38 +1225,34 @@ public: // Runtime Library hooks // - /// setLibcallName - Rename the default libcall routine name for the specified - /// libcall. + /// Rename the default libcall routine name for the specified libcall. void setLibcallName(RTLIB::Libcall Call, const char *Name) { LibcallRoutineNames[Call] = Name; } - /// getLibcallName - Get the libcall routine name for the specified libcall. - /// + /// Get the libcall routine name for the specified libcall. const char *getLibcallName(RTLIB::Libcall Call) const { return LibcallRoutineNames[Call]; } - /// setCmpLibcallCC - Override the default CondCode to be used to test the - /// result of the comparison libcall against zero. + /// Override the default CondCode to be used to test the result of the + /// comparison libcall against zero. void setCmpLibcallCC(RTLIB::Libcall Call, ISD::CondCode CC) { CmpLibcallCCs[Call] = CC; } - /// getCmpLibcallCC - Get the CondCode that's to be used to test the result of - /// the comparison libcall against zero. + /// Get the CondCode that's to be used to test the result of the comparison + /// libcall against zero. ISD::CondCode getCmpLibcallCC(RTLIB::Libcall Call) const { return CmpLibcallCCs[Call]; } - /// setLibcallCallingConv - Set the CallingConv that should be used for the - /// specified libcall. + /// Set the CallingConv that should be used for the specified libcall. void setLibcallCallingConv(RTLIB::Libcall Call, CallingConv::ID CC) { LibcallCallingConvs[Call] = CC; } - /// getLibcallCallingConv - Get the CallingConv that should be used for the - /// specified libcall. + /// Get the CallingConv that should be used for the specified libcall. CallingConv::ID getLibcallCallingConv(RTLIB::Libcall Call) const { return LibcallCallingConvs[Call]; } @@ -1273,171 +1262,160 @@ private: const DataLayout *TD; const TargetLoweringObjectFile &TLOF; - /// PointerTy - The type to use for pointers for the default address space, - /// usually i32 or i64. - /// + /// The type to use for pointers for the default address space, usually i32 or + /// i64. MVT PointerTy; - /// IsLittleEndian - True if this is a little endian target. - /// + /// True if this is a little endian target. bool IsLittleEndian; - /// SelectIsExpensive - Tells the code generator not to expand operations - /// into sequences that use the select operations if possible. + /// Tells the code generator not to expand operations into sequences that use + /// the select operations if possible. bool SelectIsExpensive; - /// IntDivIsCheap - Tells the code generator not to expand integer divides by - /// constants into a sequence of muls, adds, and shifts. This is a hack until - /// a real cost model is in place. If we ever optimize for size, this will be - /// set to true unconditionally. + /// Tells the code generator not to expand integer divides by constants into a + /// sequence of muls, adds, and shifts. This is a hack until a real cost + /// model is in place. If we ever optimize for size, this will be set to true + /// unconditionally. bool IntDivIsCheap; - /// BypassSlowDivMap - Tells the code generator to bypass slow divide or - /// remainder instructions. For example, BypassSlowDivWidths[32,8] tells the - /// code generator to bypass 32-bit integer div/rem with an 8-bit unsigned - /// integer div/rem when the operands are positive and less than 256. + /// Tells the code generator to bypass slow divide or remainder + /// instructions. For example, BypassSlowDivWidths[32,8] tells the code + /// generator to bypass 32-bit integer div/rem with an 8-bit unsigned integer + /// div/rem when the operands are positive and less than 256. DenseMap <unsigned int, unsigned int> BypassSlowDivWidths; - /// Pow2DivIsCheap - Tells the code generator that it shouldn't generate - /// srl/add/sra for a signed divide by power of two, and let the target handle - /// it. + /// Tells the code generator that it shouldn't generate srl/add/sra for a + /// signed divide by power of two, and let the target handle it. bool Pow2DivIsCheap; - /// JumpIsExpensive - Tells the code generator that it shouldn't generate - /// extra flow control instructions and should attempt to combine flow - /// control instructions via predication. + /// Tells the code generator that it shouldn't generate extra flow control + /// instructions and should attempt to combine flow control instructions via + /// predication. bool JumpIsExpensive; - /// UseUnderscoreSetJmp - This target prefers to use _setjmp to implement - /// llvm.setjmp. Defaults to false. + /// This target prefers to use _setjmp to implement llvm.setjmp. + /// + /// Defaults to false. bool UseUnderscoreSetJmp; - /// UseUnderscoreLongJmp - This target prefers to use _longjmp to implement - /// llvm.longjmp. Defaults to false. + /// This target prefers to use _longjmp to implement llvm.longjmp. + /// + /// Defaults to false. bool UseUnderscoreLongJmp; - /// SupportJumpTables - Whether the target can generate code for jumptables. - /// If it's not true, then each jumptable must be lowered into if-then-else's. + /// Whether the target can generate code for jumptables. If it's not true, + /// then each jumptable must be lowered into if-then-else's. bool SupportJumpTables; - /// MinimumJumpTableEntries - Number of blocks threshold to use jump tables. + /// Number of blocks threshold to use jump tables. int MinimumJumpTableEntries; - /// BooleanContents - Information about the contents of the high-bits in - /// boolean values held in a type wider than i1. See getBooleanContents. + /// Information about the contents of the high-bits in boolean values held in + /// a type wider than i1. See getBooleanContents. BooleanContent BooleanContents; - /// BooleanVectorContents - Information about the contents of the high-bits - /// in boolean vector values when the element type is wider than i1. See - /// getBooleanContents. + + /// Information about the contents of the high-bits in boolean vector values + /// when the element type is wider than i1. See getBooleanContents. BooleanContent BooleanVectorContents; - /// SchedPreferenceInfo - The target scheduling preference: shortest possible - /// total cycles or lowest register usage. + /// The target scheduling preference: shortest possible total cycles or lowest + /// register usage. Sched::Preference SchedPreferenceInfo; - /// JumpBufSize - The size, in bytes, of the target's jmp_buf buffers + /// The size, in bytes, of the target's jmp_buf buffers unsigned JumpBufSize; - /// JumpBufAlignment - The alignment, in bytes, of the target's jmp_buf - /// buffers + /// The alignment, in bytes, of the target's jmp_buf buffers unsigned JumpBufAlignment; - /// MinStackArgumentAlignment - The minimum alignment that any argument - /// on the stack needs to have. - /// + /// The minimum alignment that any argument on the stack needs to have. unsigned MinStackArgumentAlignment; - /// MinFunctionAlignment - The minimum function alignment (used when - /// optimizing for size, and to prevent explicitly provided alignment - /// from leading to incorrect code). - /// + /// The minimum function alignment (used when optimizing for size, and to + /// prevent explicitly provided alignment from leading to incorrect code). unsigned MinFunctionAlignment; - /// PrefFunctionAlignment - The preferred function alignment (used when - /// alignment unspecified and optimizing for speed). - /// + /// The preferred function alignment (used when alignment unspecified and + /// optimizing for speed). unsigned PrefFunctionAlignment; - /// PrefLoopAlignment - The preferred loop alignment. - /// + /// The preferred loop alignment. unsigned PrefLoopAlignment; - /// InsertFencesForAtomic - Whether the DAG builder should automatically - /// insert fences and reduce ordering for atomics. (This will be set for - /// for most architectures with weak memory ordering.) + /// Whether the DAG builder should automatically insert fences and reduce + /// ordering for atomics. (This will be set for for most architectures with + /// weak memory ordering.) bool InsertFencesForAtomic; - /// StackPointerRegisterToSaveRestore - If set to a physical register, this - /// specifies the register that llvm.savestack/llvm.restorestack should save - /// and restore. + /// If set to a physical register, this specifies the register that + /// llvm.savestack/llvm.restorestack should save and restore. unsigned StackPointerRegisterToSaveRestore; - /// ExceptionPointerRegister - If set to a physical register, this specifies - /// the register that receives the exception address on entry to a landing - /// pad. + /// If set to a physical register, this specifies the register that receives + /// the exception address on entry to a landing pad. unsigned ExceptionPointerRegister; - /// ExceptionSelectorRegister - If set to a physical register, this specifies - /// the register that receives the exception typeid on entry to a landing - /// pad. + /// If set to a physical register, this specifies the register that receives + /// the exception typeid on entry to a landing pad. unsigned ExceptionSelectorRegister; - /// RegClassForVT - This indicates the default register class to use for - /// each ValueType the target supports natively. + /// This indicates the default register class to use for each ValueType the + /// target supports natively. const TargetRegisterClass *RegClassForVT[MVT::LAST_VALUETYPE]; unsigned char NumRegistersForVT[MVT::LAST_VALUETYPE]; MVT RegisterTypeForVT[MVT::LAST_VALUETYPE]; - /// RepRegClassForVT - This indicates the "representative" register class to - /// use for each ValueType the target supports natively. This information is - /// used by the scheduler to track register pressure. By default, the - /// representative register class is the largest legal super-reg register - /// class of the register class of the specified type. e.g. On x86, i8, i16, - /// and i32's representative class would be GR32. + /// This indicates the "representative" register class to use for each + /// ValueType the target supports natively. This information is used by the + /// scheduler to track register pressure. By default, the representative + /// register class is the largest legal super-reg register class of the + /// register class of the specified type. e.g. On x86, i8, i16, and i32's + /// representative class would be GR32. const TargetRegisterClass *RepRegClassForVT[MVT::LAST_VALUETYPE]; - /// RepRegClassCostForVT - This indicates the "cost" of the "representative" - /// register class for each ValueType. The cost is used by the scheduler to - /// approximate register pressure. + /// This indicates the "cost" of the "representative" register class for each + /// ValueType. The cost is used by the scheduler to approximate register + /// pressure. uint8_t RepRegClassCostForVT[MVT::LAST_VALUETYPE]; - /// TransformToType - For any value types we are promoting or expanding, this - /// contains the value type that we are changing to. For Expanded types, this - /// contains one step of the expand (e.g. i64 -> i32), even if there are - /// multiple steps required (e.g. i64 -> i16). For types natively supported - /// by the system, this holds the same type (e.g. i32 -> i32). + /// For any value types we are promoting or expanding, this contains the value + /// type that we are changing to. For Expanded types, this contains one step + /// of the expand (e.g. i64 -> i32), even if there are multiple steps required + /// (e.g. i64 -> i16). For types natively supported by the system, this holds + /// the same type (e.g. i32 -> i32). MVT TransformToType[MVT::LAST_VALUETYPE]; - /// OpActions - For each operation and each value type, keep a LegalizeAction - /// that indicates how instruction selection should deal with the operation. - /// Most operations are Legal (aka, supported natively by the target), but + /// For each operation and each value type, keep a LegalizeAction that + /// indicates how instruction selection should deal with the operation. Most + /// operations are Legal (aka, supported natively by the target), but /// operations that are not should be described. Note that operations on /// non-legal value types are not described here. uint8_t OpActions[MVT::LAST_VALUETYPE][ISD::BUILTIN_OP_END]; - /// LoadExtActions - For each load extension type and each value type, - /// keep a LegalizeAction that indicates how instruction selection should deal - /// with a load of a specific value type and extension type. + /// For each load extension type and each value type, keep a LegalizeAction + /// that indicates how instruction selection should deal with a load of a + /// specific value type and extension type. uint8_t LoadExtActions[MVT::LAST_VALUETYPE][ISD::LAST_LOADEXT_TYPE]; - /// TruncStoreActions - For each value type pair keep a LegalizeAction that - /// indicates whether a truncating store of a specific value type and - /// truncating type is legal. + /// For each value type pair keep a LegalizeAction that indicates whether a + /// truncating store of a specific value type and truncating type is legal. uint8_t TruncStoreActions[MVT::LAST_VALUETYPE][MVT::LAST_VALUETYPE]; - /// IndexedModeActions - For each indexed mode and each value type, - /// keep a pair of LegalizeAction that indicates how instruction - /// selection should deal with the load / store. The first dimension is the - /// value_type for the reference. The second dimension represents the various - /// modes for load store. + /// For each indexed mode and each value type, keep a pair of LegalizeAction + /// that indicates how instruction selection should deal with the load / + /// store. + /// + /// The first dimension is the value_type for the reference. The second + /// dimension represents the various modes for load store. uint8_t IndexedModeActions[MVT::LAST_VALUETYPE][ISD::LAST_INDEXED_MODE]; - /// CondCodeActions - For each condition code (ISD::CondCode) keep a - /// LegalizeAction that indicates how instruction selection should - /// deal with the condition code. - /// Because each CC action takes up 2 bits, we need to have the array size - /// be large enough to fit all of the value types. This can be done by - /// dividing the MVT::LAST_VALUETYPE by 32 and adding one. + /// For each condition code (ISD::CondCode) keep a LegalizeAction that + /// indicates how instruction selection should deal with the condition code. + /// + /// Because each CC action takes up 2 bits, we need to have the array size be + /// large enough to fit all of the value types. This can be done by dividing + /// the MVT::LAST_VALUETYPE by 32 and adding one. uint64_t CondCodeActions[ISD::SETCC_INVALID][(MVT::LAST_VALUETYPE / 32) + 1]; ValueTypeActionImpl ValueTypeActions; @@ -1573,34 +1551,34 @@ public: private: std::vector<std::pair<MVT, const TargetRegisterClass*> > AvailableRegClasses; - /// TargetDAGCombineArray - Targets can specify ISD nodes that they would - /// like PerformDAGCombine callbacks for by calling setTargetDAGCombine(), - /// which sets a bit in this array. + /// Targets can specify ISD nodes that they would like PerformDAGCombine + /// callbacks for by calling setTargetDAGCombine(), which sets a bit in this + /// array. unsigned char TargetDAGCombineArray[(ISD::BUILTIN_OP_END+CHAR_BIT-1)/CHAR_BIT]; - /// PromoteToType - For operations that must be promoted to a specific type, - /// this holds the destination type. This map should be sparse, so don't hold - /// it as an array. + /// For operations that must be promoted to a specific type, this holds the + /// destination type. This map should be sparse, so don't hold it as an + /// array. /// /// Targets add entries to this map with AddPromotedToType(..), clients access /// this with getTypeToPromoteTo(..). std::map<std::pair<unsigned, MVT::SimpleValueType>, MVT::SimpleValueType> PromoteToType; - /// LibcallRoutineNames - Stores the name each libcall. - /// + /// Stores the name each libcall. const char *LibcallRoutineNames[RTLIB::UNKNOWN_LIBCALL]; - /// CmpLibcallCCs - The ISD::CondCode that should be used to test the result - /// of each of the comparison libcall against zero. + /// The ISD::CondCode that should be used to test the result of each of the + /// comparison libcall against zero. ISD::CondCode CmpLibcallCCs[RTLIB::UNKNOWN_LIBCALL]; - /// LibcallCallingConvs - Stores the CallingConv that should be used for each - /// libcall. + /// Stores the CallingConv that should be used for each libcall. CallingConv::ID LibcallCallingConvs[RTLIB::UNKNOWN_LIBCALL]; protected: + /// \brief Specify maximum number of store instructions per memset call. + /// /// When lowering \@llvm.memset this field specifies the maximum number of /// store operations that may be substituted for the call to memset. Targets /// must set this value based on the cost threshold for that target. Targets @@ -1609,13 +1587,14 @@ protected: /// alignment restrictions. For example, storing 9 bytes on a 32-bit machine /// with 16-bit alignment would result in four 2-byte stores and one 1-byte /// store. This only applies to setting a constant array of a constant size. - /// @brief Specify maximum number of store instructions per memset call. unsigned MaxStoresPerMemset; /// Maximum number of stores operations that may be substituted for the call /// to memset, used for functions with OptSize attribute. unsigned MaxStoresPerMemsetOptSize; + /// \brief Specify maximum bytes of store instructions per memcpy call. + /// /// When lowering \@llvm.memcpy this field specifies the maximum number of /// store operations that may be substituted for a call to memcpy. Targets /// must set this value based on the cost threshold for that target. Targets @@ -1625,13 +1604,14 @@ protected: /// with 32-bit alignment would result in one 4-byte store, a one 2-byte store /// and one 1-byte store. This only applies to copying a constant array of /// constant size. - /// @brief Specify maximum bytes of store instructions per memcpy call. unsigned MaxStoresPerMemcpy; - /// Maximum number of store operations that may be substituted for a call - /// to memcpy, used for functions with OptSize attribute. + /// Maximum number of store operations that may be substituted for a call to + /// memcpy, used for functions with OptSize attribute. unsigned MaxStoresPerMemcpyOptSize; + /// \brief Specify maximum bytes of store instructions per memmove call. + /// /// When lowering \@llvm.memmove this field specifies the maximum number of /// store instructions that may be substituted for a call to memmove. Targets /// must set this value based on the cost threshold for that target. Targets @@ -1640,31 +1620,27 @@ protected: /// alignment restrictions. For example, moving 9 bytes on a 32-bit machine /// with 8-bit alignment would result in nine 1-byte stores. This only /// applies to copying a constant array of constant size. - /// @brief Specify maximum bytes of store instructions per memmove call. unsigned MaxStoresPerMemmove; - /// Maximum number of store instructions that may be substituted for a call - /// to memmove, used for functions with OpSize attribute. + /// Maximum number of store instructions that may be substituted for a call to + /// memmove, used for functions with OpSize attribute. unsigned MaxStoresPerMemmoveOptSize; - /// PredictableSelectIsExpensive - Tells the code generator that select is - /// more expensive than a branch if the branch is usually predicted right. + /// Tells the code generator that select is more expensive than a branch if + /// the branch is usually predicted right. bool PredictableSelectIsExpensive; protected: - /// isLegalRC - Return true if the value types that can be represented by the - /// specified register class are all legal. + /// Return true if the value types that can be represented by the specified + /// register class are all legal. bool isLegalRC(const TargetRegisterClass *RC) const; }; -//===----------------------------------------------------------------------===// -/// TargetLowering - This class defines information used to lower LLVM code to -/// legal SelectionDAG operators that the target instruction selector can accept -/// natively. +/// This class defines information used to lower LLVM code to legal SelectionDAG +/// operators that the target instruction selector can accept natively. /// /// This class also defines callbacks that targets must implement to lower /// target-specific constructs to SelectionDAG operators. -/// class TargetLowering : public TargetLoweringBase { TargetLowering(const TargetLowering&) LLVM_DELETED_FUNCTION; void operator=(const TargetLowering&) LLVM_DELETED_FUNCTION; @@ -1674,9 +1650,9 @@ public: explicit TargetLowering(const TargetMachine &TM, const TargetLoweringObjectFile *TLOF); - /// getPreIndexedAddressParts - returns true by value, base pointer and - /// offset pointer and addressing mode by reference if the node's address - /// can be legally represented as pre-indexed load / store address. + /// Returns true by value, base pointer and offset pointer and addressing mode + /// by reference if the node's address can be legally represented as + /// pre-indexed load / store address. virtual bool getPreIndexedAddressParts(SDNode * /*N*/, SDValue &/*Base*/, SDValue &/*Offset*/, ISD::MemIndexedMode &/*AM*/, @@ -1684,9 +1660,9 @@ public: return false; } - /// getPostIndexedAddressParts - returns true by value, base pointer and - /// offset pointer and addressing mode by reference if this node can be - /// combined with a load / store to form a post-indexed load / store. + /// Returns true by value, base pointer and offset pointer and addressing mode + /// by reference if this node can be combined with a load / store to form a + /// post-indexed load / store. virtual bool getPostIndexedAddressParts(SDNode * /*N*/, SDNode * /*Op*/, SDValue &/*Base*/, SDValue &/*Offset*/, ISD::MemIndexedMode &/*AM*/, @@ -1694,9 +1670,8 @@ public: return false; } - /// getJumpTableEncoding - Return the entry encoding for a jump table in the - /// current function. The returned value is a member of the - /// MachineJumpTableInfo::JTEntryKind enum. + /// Return the entry encoding for a jump table in the current function. The + /// returned value is a member of the MachineJumpTableInfo::JTEntryKind enum. virtual unsigned getJumpTableEncoding() const; virtual const MCExpr * @@ -1706,21 +1681,18 @@ public: llvm_unreachable("Need to implement this hook if target has custom JTIs"); } - /// getPICJumpTableRelocaBase - Returns relocation base for the given PIC - /// jumptable. + /// Returns relocation base for the given PIC jumptable. virtual SDValue getPICJumpTableRelocBase(SDValue Table, SelectionDAG &DAG) const; - /// getPICJumpTableRelocBaseExpr - This returns the relocation base for the - /// given PIC jumptable, the same as getPICJumpTableRelocBase, but as an - /// MCExpr. + /// This returns the relocation base for the given PIC jumptable, the same as + /// getPICJumpTableRelocBase, but as an MCExpr. virtual const MCExpr * getPICJumpTableRelocBaseExpr(const MachineFunction *MF, unsigned JTI, MCContext &Ctx) const; - /// isOffsetFoldingLegal - Return true if folding a constant offset - /// with the given GlobalAddress is legal. It is frequently not legal in - /// PIC relocation models. + /// Return true if folding a constant offset with the given GlobalAddress is + /// legal. It is frequently not legal in PIC relocation models. virtual bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const; bool isInTailCallPosition(SelectionDAG &DAG, SDNode *Node, @@ -1738,9 +1710,9 @@ public: // TargetLowering Optimization Methods // - /// TargetLoweringOpt - A convenience struct that encapsulates a DAG, and two - /// SDValues for returning information from TargetLowering to its clients - /// that want to combine + /// A convenience struct that encapsulates a DAG, and two SDValues for + /// returning information from TargetLowering to its clients that want to + /// combine. struct TargetLoweringOpt { SelectionDAG &DAG; bool LegalTys; @@ -1761,44 +1733,40 @@ public: return true; } - /// ShrinkDemandedConstant - Check to see if the specified operand of the - /// specified instruction is a constant integer. If so, check to see if - /// there are any bits set in the constant that are not demanded. If so, - /// shrink the constant and return true. + /// Check to see if the specified operand of the specified instruction is a + /// constant integer. If so, check to see if there are any bits set in the + /// constant that are not demanded. If so, shrink the constant and return + /// true. bool ShrinkDemandedConstant(SDValue Op, const APInt &Demanded); - /// ShrinkDemandedOp - Convert x+y to (VT)((SmallVT)x+(SmallVT)y) if the - /// casts are free. This uses isZExtFree and ZERO_EXTEND for the widening - /// cast, but it could be generalized for targets with other types of - /// implicit widening casts. + /// Convert x+y to (VT)((SmallVT)x+(SmallVT)y) if the casts are free. This + /// uses isZExtFree and ZERO_EXTEND for the widening cast, but it could be + /// generalized for targets with other types of implicit widening casts. bool ShrinkDemandedOp(SDValue Op, unsigned BitWidth, const APInt &Demanded, SDLoc dl); }; - /// SimplifyDemandedBits - Look at Op. At this point, we know that only the - /// DemandedMask bits of the result of Op are ever used downstream. If we can - /// use this information to simplify Op, create a new simplified DAG node and - /// return true, returning the original and new nodes in Old and New. - /// Otherwise, analyze the expression and return a mask of KnownOne and - /// KnownZero bits for the expression (used to simplify the caller). - /// The KnownZero/One bits may only be accurate for those bits in the - /// DemandedMask. + /// Look at Op. At this point, we know that only the DemandedMask bits of the + /// result of Op are ever used downstream. If we can use this information to + /// simplify Op, create a new simplified DAG node and return true, returning + /// the original and new nodes in Old and New. Otherwise, analyze the + /// expression and return a mask of KnownOne and KnownZero bits for the + /// expression (used to simplify the caller). The KnownZero/One bits may only + /// be accurate for those bits in the DemandedMask. bool SimplifyDemandedBits(SDValue Op, const APInt &DemandedMask, APInt &KnownZero, APInt &KnownOne, TargetLoweringOpt &TLO, unsigned Depth = 0) const; - /// computeMaskedBitsForTargetNode - Determine which of the bits specified in - /// Mask are known to be either zero or one and return them in the - /// KnownZero/KnownOne bitsets. + /// Determine which of the bits specified in Mask are known to be either zero + /// or one and return them in the KnownZero/KnownOne bitsets. virtual void computeMaskedBitsForTargetNode(const SDValue Op, APInt &KnownZero, APInt &KnownOne, const SelectionDAG &DAG, unsigned Depth = 0) const; - /// ComputeNumSignBitsForTargetNode - This method can be implemented by - /// targets that want to expose additional information about sign bits to the - /// DAG Combiner. + /// This method can be implemented by targets that want to expose additional + /// information about sign bits to the DAG Combiner. virtual unsigned ComputeNumSignBitsForTargetNode(SDValue Op, unsigned Depth = 0) const; @@ -1830,20 +1798,20 @@ public: void CommitTargetLoweringOpt(const TargetLoweringOpt &TLO); }; - /// SimplifySetCC - Try to simplify a setcc built with the specified operands - /// and cc. If it is unable to simplify it, return a null SDValue. + /// Try to simplify a setcc built with the specified operands and cc. If it is + /// unable to simplify it, return a null SDValue. SDValue SimplifySetCC(EVT VT, SDValue N0, SDValue N1, ISD::CondCode Cond, bool foldBooleans, DAGCombinerInfo &DCI, SDLoc dl) const; - /// isGAPlusOffset - Returns true (and the GlobalValue and the offset) if the - /// node is a GlobalAddress + offset. + /// Returns true (and the GlobalValue and the offset) if the node is a + /// GlobalAddress + offset. virtual bool isGAPlusOffset(SDNode *N, const GlobalValue* &GA, int64_t &Offset) const; - /// PerformDAGCombine - This method will be invoked for all target nodes and - /// for any target-independent nodes that the target has registered with - /// invoke it for. + /// This method will be invoked for all target nodes and for any + /// target-independent nodes that the target has registered with invoke it + /// for. /// /// The semantics are as follows: /// Return Value: @@ -1856,26 +1824,26 @@ public: /// virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; - /// isTypeDesirableForOp - Return true if the target has native support for - /// the specified value type and it is 'desirable' to use the type for the - /// given node type. e.g. On x86 i16 is legal, but undesirable since i16 - /// instruction encodings are longer and some i16 instructions are slow. + /// Return true if the target has native support for the specified value type + /// and it is 'desirable' to use the type for the given node type. e.g. On x86 + /// i16 is legal, but undesirable since i16 instruction encodings are longer + /// and some i16 instructions are slow. virtual bool isTypeDesirableForOp(unsigned /*Opc*/, EVT VT) const { // By default, assume all legal types are desirable. return isTypeLegal(VT); } - /// isDesirableToPromoteOp - Return true if it is profitable for dag combiner - /// to transform a floating point op of specified opcode to a equivalent op of - /// an integer type. e.g. f32 load -> i32 load can be profitable on ARM. + /// Return true if it is profitable for dag combiner to transform a floating + /// point op of specified opcode to a equivalent op of an integer + /// type. e.g. f32 load -> i32 load can be profitable on ARM. virtual bool isDesirableToTransformToIntegerOp(unsigned /*Opc*/, EVT /*VT*/) const { return false; } - /// IsDesirableToPromoteOp - This method query the target whether it is - /// beneficial for dag combiner to promote the specified node. If true, it - /// should return the desired promotion type by reference. + /// This method query the target whether it is beneficial for dag combiner to + /// promote the specified node. If true, it should return the desired + /// promotion type by reference. virtual bool IsDesirableToPromoteOp(SDValue /*Op*/, EVT &/*PVT*/) const { return false; } @@ -1885,11 +1853,10 @@ public: // the SelectionDAGBuilder code knows how to lower these. // - /// LowerFormalArguments - This hook must be implemented to lower the - /// incoming (formal) arguments, described by the Ins array, into the - /// specified DAG. The implementation should fill in the InVals array - /// with legal-type argument values, and return the resulting token - /// chain value. + /// This hook must be implemented to lower the incoming (formal) arguments, + /// described by the Ins array, into the specified DAG. The implementation + /// should fill in the InVals array with legal-type argument values, and + /// return the resulting token chain value. /// virtual SDValue LowerFormalArguments(SDValue /*Chain*/, CallingConv::ID /*CallConv*/, @@ -1918,10 +1885,10 @@ public: }; typedef std::vector<ArgListEntry> ArgListTy; - /// CallLoweringInfo - This structure contains all information that is - /// necessary for lowering calls. It is passed to TLI::LowerCallTo when the - /// SelectionDAG builder needs to lower a call, and targets will see this - /// struct in their LowerCall implementation. + /// This structure contains all information that is necessary for lowering + /// calls. It is passed to TLI::LowerCallTo when the SelectionDAG builder + /// needs to lower a call, and targets will see this struct in their LowerCall + /// implementation. struct CallLoweringInfo { SDValue Chain; Type *RetTy; @@ -1948,8 +1915,7 @@ public: SmallVector<ISD::InputArg, 32> Ins; - /// CallLoweringInfo - Constructs a call lowering context based on the - /// ImmutableCallSite \p cs. + /// Constructs a call lowering context based on the ImmutableCallSite \p cs. CallLoweringInfo(SDValue chain, Type *retTy, FunctionType *FTy, bool isTailCall, SDValue callee, ArgListTy &args, SelectionDAG &dag, SDLoc dl, @@ -1963,8 +1929,8 @@ public: CallConv(cs.getCallingConv()), Callee(callee), Args(args), DAG(dag), DL(dl), CS(&cs) {} - /// CallLoweringInfo - Constructs a call lowering context based on the - /// provided call information. + /// Constructs a call lowering context based on the provided call + /// information. CallLoweringInfo(SDValue chain, Type *retTy, bool retSExt, bool retZExt, bool isVarArg, bool isInReg, unsigned numFixedArgs, CallingConv::ID callConv, bool isTailCall, @@ -1977,32 +1943,29 @@ public: Args(args), DAG(dag), DL(dl), CS(NULL) {} }; - /// LowerCallTo - This function lowers an abstract call to a function into an - /// actual call. This returns a pair of operands. The first element is the - /// return value for the function (if RetTy is not VoidTy). The second - /// element is the outgoing token chain. It calls LowerCall to do the actual - /// lowering. + /// This function lowers an abstract call to a function into an actual call. + /// This returns a pair of operands. The first element is the return value + /// for the function (if RetTy is not VoidTy). The second element is the + /// outgoing token chain. It calls LowerCall to do the actual lowering. std::pair<SDValue, SDValue> LowerCallTo(CallLoweringInfo &CLI) const; - /// LowerCall - This hook must be implemented to lower calls into the - /// the specified DAG. The outgoing arguments to the call are described - /// by the Outs array, and the values to be returned by the call are - /// described by the Ins array. The implementation should fill in the - /// InVals array with legal-type return values from the call, and return - /// the resulting token chain value. + /// This hook must be implemented to lower calls into the the specified + /// DAG. The outgoing arguments to the call are described by the Outs array, + /// and the values to be returned by the call are described by the Ins + /// array. The implementation should fill in the InVals array with legal-type + /// return values from the call, and return the resulting token chain value. virtual SDValue LowerCall(CallLoweringInfo &/*CLI*/, SmallVectorImpl<SDValue> &/*InVals*/) const { llvm_unreachable("Not Implemented"); } - /// HandleByVal - Target-specific cleanup for formal ByVal parameters. + /// Target-specific cleanup for formal ByVal parameters. virtual void HandleByVal(CCState *, unsigned &, unsigned) const {} - /// CanLowerReturn - This hook should be implemented to check whether the - /// return values described by the Outs array can fit into the return - /// registers. If false is returned, an sret-demotion is performed. - /// + /// This hook should be implemented to check whether the return values + /// described by the Outs array can fit into the return registers. If false + /// is returned, an sret-demotion is performed. virtual bool CanLowerReturn(CallingConv::ID /*CallConv*/, MachineFunction &/*MF*/, bool /*isVarArg*/, const SmallVectorImpl<ISD::OutputArg> &/*Outs*/, @@ -2012,11 +1975,9 @@ public: return true; } - /// LowerReturn - This hook must be implemented to lower outgoing - /// return values, described by the Outs array, into the specified - /// DAG. The implementation should return the resulting token chain - /// value. - /// + /// This hook must be implemented to lower outgoing return values, described + /// by the Outs array, into the specified DAG. The implementation should + /// return the resulting token chain value. virtual SDValue LowerReturn(SDValue /*Chain*/, CallingConv::ID /*CallConv*/, bool /*isVarArg*/, @@ -2026,42 +1987,42 @@ public: llvm_unreachable("Not Implemented"); } - /// isUsedByReturnOnly - Return true if result of the specified node is used - /// by a return node only. It also compute and return the input chain for the - /// tail call. - /// This is used to determine whether it is possible - /// to codegen a libcall as tail call at legalization time. + /// Return true if result of the specified node is used by a return node + /// only. It also compute and return the input chain for the tail call. + /// + /// This is used to determine whether it is possible to codegen a libcall as + /// tail call at legalization time. virtual bool isUsedByReturnOnly(SDNode *, SDValue &/*Chain*/) const { return false; } - /// mayBeEmittedAsTailCall - Return true if the target may be able emit the - /// call instruction as a tail call. This is used by optimization passes to - /// determine if it's profitable to duplicate return instructions to enable - /// tailcall optimization. + /// Return true if the target may be able emit the call instruction as a tail + /// call. This is used by optimization passes to determine if it's profitable + /// to duplicate return instructions to enable tailcall optimization. virtual bool mayBeEmittedAsTailCall(CallInst *) const { return false; } - /// getTypeForExtArgOrReturn - Return the type that should be used to zero or - /// sign extend a zeroext/signext integer argument or return value. - /// FIXME: Most C calling convention requires the return type to be promoted, - /// but this is not true all the time, e.g. i1 on x86-64. It is also not - /// necessary for non-C calling conventions. The frontend should handle this - /// and include all of the necessary information. + /// Return the type that should be used to zero or sign extend a + /// zeroext/signext integer argument or return value. FIXME: Most C calling + /// convention requires the return type to be promoted, but this is not true + /// all the time, e.g. i1 on x86-64. It is also not necessary for non-C + /// calling conventions. The frontend should handle this and include all of + /// the necessary information. virtual MVT getTypeForExtArgOrReturn(MVT VT, ISD::NodeType /*ExtendKind*/) const { MVT MinVT = getRegisterType(MVT::i32); return VT.bitsLT(MinVT) ? MinVT : VT; } - /// LowerOperationWrapper - This callback is invoked by the type legalizer - /// to legalize nodes with an illegal operand type but legal result types. - /// It replaces the LowerOperation callback in the type Legalizer. - /// The reason we can not do away with LowerOperation entirely is that - /// LegalizeDAG isn't yet ready to use this callback. + /// This callback is invoked by the type legalizer to legalize nodes with an + /// illegal operand type but legal result types. It replaces the + /// LowerOperation callback in the type Legalizer. The reason we can not do + /// away with LowerOperation entirely is that LegalizeDAG isn't yet ready to + /// use this callback. + /// /// TODO: Consider merging with ReplaceNodeResults. - + /// /// The target places new result values for the node in Results (their number /// and types must exactly match those of the original return values of /// the node), or leaves Results empty, which indicates that the node is not @@ -2071,19 +2032,19 @@ public: SmallVectorImpl<SDValue> &Results, SelectionDAG &DAG) const; - /// LowerOperation - This callback is invoked for operations that are - /// unsupported by the target, which are registered to use 'custom' lowering, - /// and whose defined values are all legal. - /// If the target has no operations that require custom lowering, it need not - /// implement this. The default implementation of this aborts. + /// This callback is invoked for operations that are unsupported by the + /// target, which are registered to use 'custom' lowering, and whose defined + /// values are all legal. If the target has no operations that require custom + /// lowering, it need not implement this. The default implementation of this + /// aborts. virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const; - /// ReplaceNodeResults - This callback is invoked when a node result type is - /// illegal for the target, and the operation was registered to use 'custom' - /// lowering for that result type. The target places new result values for - /// the node in Results (their number and types must exactly match those of - /// the original return values of the node), or leaves Results empty, which - /// indicates that the node is not to be custom lowered after all. + /// This callback is invoked when a node result type is illegal for the + /// target, and the operation was registered to use 'custom' lowering for that + /// result type. The target places new result values for the node in Results + /// (their number and types must exactly match those of the original return + /// values of the node), or leaves Results empty, which indicates that the + /// node is not to be custom lowered after all. /// /// If the target has no operations that require custom lowering, it need not /// implement this. The default implementation aborts. @@ -2093,12 +2054,11 @@ public: llvm_unreachable("ReplaceNodeResults not implemented for this target!"); } - /// getTargetNodeName() - This method returns the name of a target specific - /// DAG node. + /// This method returns the name of a target specific DAG node. virtual const char *getTargetNodeName(unsigned Opcode) const; - /// createFastISel - This method returns a target specific FastISel object, - /// or null if the target does not support "fast" ISel. + /// This method returns a target specific FastISel object, or null if the + /// target does not support "fast" ISel. virtual FastISel *createFastISel(FunctionLoweringInfo &, const TargetLibraryInfo *) const { return 0; @@ -2108,10 +2068,10 @@ public: // Inline Asm Support hooks // - /// ExpandInlineAsm - This hook allows the target to expand an inline asm - /// call to be explicit llvm code if it wants to. This is useful for - /// turning simple inline asms into LLVM intrinsics, which gives the - /// compiler more information about the behavior of the code. + /// This hook allows the target to expand an inline asm call to be explicit + /// llvm code if it wants to. This is useful for turning simple inline asms + /// into LLVM intrinsics, which gives the compiler more information about the + /// behavior of the code. virtual bool ExpandInlineAsm(CallInst *) const { return false; } @@ -2140,32 +2100,31 @@ public: CW_Default = CW_Okay // Default or don't know type. }; - /// AsmOperandInfo - This contains information for each constraint that we are - /// lowering. + /// This contains information for each constraint that we are lowering. struct AsmOperandInfo : public InlineAsm::ConstraintInfo { - /// ConstraintCode - This contains the actual string for the code, like "m". - /// TargetLowering picks the 'best' code from ConstraintInfo::Codes that - /// most closely matches the operand. + /// This contains the actual string for the code, like "m". TargetLowering + /// picks the 'best' code from ConstraintInfo::Codes that most closely + /// matches the operand. std::string ConstraintCode; - /// ConstraintType - Information about the constraint code, e.g. Register, - /// RegisterClass, Memory, Other, Unknown. + /// Information about the constraint code, e.g. Register, RegisterClass, + /// Memory, Other, Unknown. TargetLowering::ConstraintType ConstraintType; - /// CallOperandval - If this is the result output operand or a - /// clobber, this is null, otherwise it is the incoming operand to the - /// CallInst. This gets modified as the asm is processed. + /// If this is the result output operand or a clobber, this is null, + /// otherwise it is the incoming operand to the CallInst. This gets + /// modified as the asm is processed. Value *CallOperandVal; - /// ConstraintVT - The ValueType for the operand value. + /// The ValueType for the operand value. MVT ConstraintVT; - /// isMatchingInputConstraint - Return true of this is an input operand that - /// is a matching constraint like "4". + /// Return true of this is an input operand that is a matching constraint + /// like "4". bool isMatchingInputConstraint() const; - /// getMatchedOperand - If this is an input matching constraint, this method - /// returns the output operand it matches. + /// If this is an input matching constraint, this method returns the output + /// operand it matches. unsigned getMatchedOperand() const; /// Copy constructor for copying from an AsmOperandInfo. @@ -2187,11 +2146,10 @@ public: typedef std::vector<AsmOperandInfo> AsmOperandInfoVector; - /// ParseConstraints - Split up the constraint string from the inline - /// assembly value into the specific constraints and their prefixes, - /// and also tie in the associated operand values. - /// If this returns an empty vector, and if the constraint string itself - /// isn't empty, there was an error parsing. + /// Split up the constraint string from the inline assembly value into the + /// specific constraints and their prefixes, and also tie in the associated + /// operand values. If this returns an empty vector, and if the constraint + /// string itself isn't empty, there was an error parsing. virtual AsmOperandInfoVector ParseConstraints(ImmutableCallSite CS) const; /// Examine constraint type and operand type and determine a weight value. @@ -2204,41 +2162,37 @@ public: virtual ConstraintWeight getSingleConstraintMatchWeight( AsmOperandInfo &info, const char *constraint) const; - /// ComputeConstraintToUse - Determines the constraint code and constraint - /// type to use for the specific AsmOperandInfo, setting - /// OpInfo.ConstraintCode and OpInfo.ConstraintType. If the actual operand - /// being passed in is available, it can be passed in as Op, otherwise an - /// empty SDValue can be passed. + /// Determines the constraint code and constraint type to use for the specific + /// AsmOperandInfo, setting OpInfo.ConstraintCode and OpInfo.ConstraintType. + /// If the actual operand being passed in is available, it can be passed in as + /// Op, otherwise an empty SDValue can be passed. virtual void ComputeConstraintToUse(AsmOperandInfo &OpInfo, SDValue Op, SelectionDAG *DAG = 0) const; - /// getConstraintType - Given a constraint, return the type of constraint it - /// is for this target. + /// Given a constraint, return the type of constraint it is for this target. virtual ConstraintType getConstraintType(const std::string &Constraint) const; - /// getRegForInlineAsmConstraint - Given a physical register constraint (e.g. - /// {edx}), return the register number and the register class for the - /// register. + /// Given a physical register constraint (e.g. {edx}), return the register + /// number and the register class for the register. /// /// Given a register class constraint, like 'r', if this corresponds directly /// to an LLVM register class, return a register of 0 and the register class /// pointer. /// - /// This should only be used for C_Register constraints. On error, - /// this returns a register number of 0 and a null register class pointer.. + /// This should only be used for C_Register constraints. On error, this + /// returns a register number of 0 and a null register class pointer.. virtual std::pair<unsigned, const TargetRegisterClass*> getRegForInlineAsmConstraint(const std::string &Constraint, - EVT VT) const; + MVT VT) const; - /// LowerXConstraint - try to replace an X constraint, which matches anything, - /// with another that has more specific requirements based on the type of the - /// corresponding operand. This returns null if there is no replacement to - /// make. + /// Try to replace an X constraint, which matches anything, with another that + /// has more specific requirements based on the type of the corresponding + /// operand. This returns null if there is no replacement to make. virtual const char *LowerXConstraint(EVT ConstraintVT) const; - /// LowerAsmOperandForConstraint - Lower the specified operand into the Ops - /// vector. If it is invalid, don't add anything to Ops. + /// Lower the specified operand into the Ops vector. If it is invalid, don't + /// add anything to Ops. virtual void LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, std::vector<SDValue> &Ops, SelectionDAG &DAG) const; @@ -2257,26 +2211,26 @@ public: // Instruction Emitting Hooks // - // EmitInstrWithCustomInserter - This method should be implemented by targets - // that mark instructions with the 'usesCustomInserter' flag. These - // instructions are special in various ways, which require special support to - // insert. The specified MachineInstr is created but not inserted into any - // basic blocks, and this method is called to expand it into a sequence of - // instructions, potentially also creating new basic blocks and control flow. + // This method should be implemented by targets that mark instructions with + // the 'usesCustomInserter' flag. These instructions are special in various + // ways, which require special support to insert. The specified MachineInstr + // is created but not inserted into any basic blocks, and this method is + // called to expand it into a sequence of instructions, potentially also + // creating new basic blocks and control flow. virtual MachineBasicBlock * EmitInstrWithCustomInserter(MachineInstr *MI, MachineBasicBlock *MBB) const; - /// AdjustInstrPostInstrSelection - This method should be implemented by - /// targets that mark instructions with the 'hasPostISelHook' flag. These - /// instructions must be adjusted after instruction selection by target hooks. - /// e.g. To fill in optional defs for ARM 's' setting instructions. + /// This method should be implemented by targets that mark instructions with + /// the 'hasPostISelHook' flag. These instructions must be adjusted after + /// instruction selection by target hooks. e.g. To fill in optional defs for + /// ARM 's' setting instructions. virtual void AdjustInstrPostInstrSelection(MachineInstr *MI, SDNode *Node) const; }; -/// GetReturnInfo - Given an LLVM IR type and return type attributes, -/// compute the return value EVTs and flags, and optionally also -/// the offsets, if the return value is being lowered to memory. +/// Given an LLVM IR type and return type attributes, compute the return value +/// EVTs and flags, and optionally also the offsets, if the return value is +/// being lowered to memory. void GetReturnInfo(Type* ReturnType, AttributeSet attr, SmallVectorImpl<ISD::OutputArg> &Outs, const TargetLowering &TLI); diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index 9958755..7f15b74 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -138,6 +138,10 @@ public: return StaticDtorSection; } + /// \brief Create a symbol reference to describe the given TLS variable when + /// emitting the address in debug info. + virtual const MCExpr *getDebugThreadLocalSymbol(const MCSymbol *Sym) const; + protected: virtual const MCSection * SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index 7f04119..fd7228a 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -102,11 +102,14 @@ public: void resetTargetOptions(const MachineFunction *MF) const; // Interfaces to the major aspects of target machine information: + // // -- Instruction opcode and operand information // -- Pipelines and scheduling information // -- Stack frame information // -- Selection DAG lowering information // + // N.B. These objects may change during compilation. It's not safe to cache + // them between functions. virtual const TargetInstrInfo *getInstrInfo() const { return 0; } virtual const TargetFrameLowering *getFrameLowering() const { return 0; } virtual const TargetLowering *getTargetLowering() const { return 0; } diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h index 31c4c75..d9c8651 100644 --- a/include/llvm/Target/TargetOptions.h +++ b/include/llvm/Target/TargetOptions.h @@ -42,13 +42,13 @@ namespace llvm { public: TargetOptions() : PrintMachineCode(false), NoFramePointerElim(false), - NoFramePointerElimNonLeaf(false), LessPreciseFPMADOption(false), + LessPreciseFPMADOption(false), UnsafeFPMath(false), NoInfsFPMath(false), NoNaNsFPMath(false), HonorSignDependentRoundingFPMathOption(false), UseSoftFloat(false), NoZerosInBSS(false), JITEmitDebugInfo(false), JITEmitDebugInfoToDisk(false), GuaranteedTailCallOpt(false), DisableTailCalls(false), - StackAlignmentOverride(0), RealignStack(true), SSPBufferSize(0), + StackAlignmentOverride(0), EnableFastISel(false), PositionIndependentExecutable(false), EnableSegmentedStacks(false), UseInitArray(false), TrapFuncName(""), FloatABIType(FloatABI::Default), AllowFPOpFusion(FPOpFusion::Standard) @@ -64,12 +64,6 @@ namespace llvm { /// elimination optimization, this option should disable it. unsigned NoFramePointerElim : 1; - /// NoFramePointerElimNonLeaf - This flag is enabled when the - /// -disable-non-leaf-fp-elim is specified on the command line. If the - /// target supports the frame pointer elimination optimization, this option - /// should disable it for non-leaf functions. - unsigned NoFramePointerElimNonLeaf : 1; - /// DisableFramePointerElim - This returns true if frame pointer elimination /// optimization should be disabled for the given machine function. bool DisableFramePointerElim(const MachineFunction &MF) const; @@ -147,14 +141,6 @@ namespace llvm { /// StackAlignmentOverride - Override default stack alignment for target. unsigned StackAlignmentOverride; - /// RealignStack - This flag indicates whether the stack should be - /// automatically realigned, if needed. - unsigned RealignStack : 1; - - /// SSPBufferSize - The minimum size of buffers that will receive stack - /// smashing protection when -fstack-protection is used. - unsigned SSPBufferSize; - /// EnableFastISel - This flag enables fast-path instruction selection /// which trades away generated code quality in favor of reducing /// compile time. @@ -203,9 +189,41 @@ namespace llvm { /// via the llvm.fma.* intrinsic) will always be honored, regardless of /// the value of this option. FPOpFusion::FPOpFusionMode AllowFPOpFusion; - - bool operator==(const TargetOptions &); }; + +// Comparison operators: + + +inline bool operator==(const TargetOptions &LHS, + const TargetOptions &RHS) { +#define ARE_EQUAL(X) LHS.X == RHS.X + return + ARE_EQUAL(UnsafeFPMath) && + ARE_EQUAL(NoInfsFPMath) && + ARE_EQUAL(NoNaNsFPMath) && + ARE_EQUAL(HonorSignDependentRoundingFPMathOption) && + ARE_EQUAL(UseSoftFloat) && + ARE_EQUAL(NoZerosInBSS) && + ARE_EQUAL(JITEmitDebugInfo) && + ARE_EQUAL(JITEmitDebugInfoToDisk) && + ARE_EQUAL(GuaranteedTailCallOpt) && + ARE_EQUAL(DisableTailCalls) && + ARE_EQUAL(StackAlignmentOverride) && + ARE_EQUAL(EnableFastISel) && + ARE_EQUAL(PositionIndependentExecutable) && + ARE_EQUAL(EnableSegmentedStacks) && + ARE_EQUAL(UseInitArray) && + ARE_EQUAL(TrapFuncName) && + ARE_EQUAL(FloatABIType) && + ARE_EQUAL(AllowFPOpFusion); +#undef ARE_EQUAL +} + +inline bool operator!=(const TargetOptions &LHS, + const TargetOptions &RHS) { + return !(LHS == RHS); +} + } // End llvm namespace #endif diff --git a/include/llvm/Target/TargetSchedule.td b/include/llvm/Target/TargetSchedule.td index 660d2c4..575cb83 100644 --- a/include/llvm/Target/TargetSchedule.td +++ b/include/llvm/Target/TargetSchedule.td @@ -72,11 +72,13 @@ def instregex; // // Target hooks allow subtargets to associate LoadLatency and // HighLatency with groups of opcodes. +// +// See MCSchedule.h for detailed comments. class SchedMachineModel { int IssueWidth = -1; // Max micro-ops that may be scheduled per cycle. int MinLatency = -1; // Determines which instrucions are allowed in a group. // (-1) inorder (0) ooo, (1): inorder +var latencies. - int ILPWindow = -1; // Cycles of latency likely hidden by hardware buffers. + int MicroOpBufferSize = -1; // Max micro-ops that can be buffered. int LoadLatency = -1; // Cycles for loads to access the cache. int HighLatency = -1; // Approximation of cycles for "high latency" ops. int MispredictPenalty = -1; // Extra cycles for a mispredicted branch. @@ -106,7 +108,7 @@ class ProcResourceKind; // out-of-order engine that the compiler attempts to conserve. // Buffered resources may be held for multiple clock cycles, but the // scheduler does not pin them to a particular clock cycle relative to -// instruction dispatch. Setting Buffered=0 changes this to an +// instruction dispatch. Setting BufferSize=0 changes this to an // in-order resource. In this case, the scheduler counts down from the // cycle that the instruction issues in-order, forcing an interlock // with subsequent instructions that require the same resource until @@ -119,7 +121,7 @@ class ProcResourceUnits<ProcResourceKind kind, int num> { ProcResourceKind Kind = kind; int NumUnits = num; ProcResourceKind Super = ?; - bit Buffered = 1; + int BufferSize = -1; SchedMachineModel SchedModel = ?; } @@ -136,6 +138,7 @@ class ProcResource<int num> : ProcResourceKind, class ProcResGroup<list<ProcResource> resources> : ProcResourceKind { list<ProcResource> Resources = resources; SchedMachineModel SchedModel = ?; + int BufferSize = -1; } // A target architecture may define SchedReadWrite types and associate diff --git a/include/llvm/Transforms/IPO/PassManagerBuilder.h b/include/llvm/Transforms/IPO/PassManagerBuilder.h index 563721e..75631b3 100644 --- a/include/llvm/Transforms/IPO/PassManagerBuilder.h +++ b/include/llvm/Transforms/IPO/PassManagerBuilder.h @@ -100,12 +100,12 @@ public: /// added to the per-module passes. Pass *Inliner; - bool DisableSimplifyLibCalls; bool DisableUnitAtATime; bool DisableUnrollLoops; bool BBVectorize; bool SLPVectorize; bool LoopVectorize; + bool LateVectorize; private: /// ExtensionList - This is list of all of the extensions that are registered. diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h index f2027ce..d1b6fe1 100644 --- a/include/llvm/Transforms/Instrumentation.h +++ b/include/llvm/Transforms/Instrumentation.h @@ -78,11 +78,36 @@ FunctionPass *createThreadSanitizerPass(StringRef BlacklistFile = StringRef()); // checking on loads, stores, and other memory intrinsics. FunctionPass *createBoundsCheckingPass(); -/// createDebugIRPass - Create and return a pass that modifies a module's -/// debug metadata to point back to IR instead of the original source file -ModulePass *createDebugIRPass(StringRef FilenamePostfix, - bool hideDebugIntrinsics = true, - bool hideDebugMetadata = true); +/// createDebugIRPass - Enable interactive stepping through LLVM IR in LLDB (or +/// GDB) and generate a file with the LLVM IR to be +/// displayed in the debugger. +/// +/// Existing debug metadata is preserved (but may be modified) in order to allow +/// accessing variables in the original source. The line table and file +/// information is modified to correspond to the lines in the LLVM IR. If +/// Filename and Directory are empty, a file name is generated based on existing +/// debug information. If no debug information is available, a temporary file +/// name is generated. +/// +/// @param HideDebugIntrinsics Omit debug intrinsics in emitted IR source file. +/// @param HideDebugMetadata Omit debug metadata in emitted IR source file. +/// @param Directory Embed this directory in the debug information. +/// @param Filename Embed this file name in the debug information. +ModulePass *createDebugIRPass(bool HideDebugIntrinsics, + bool HideDebugMetadata, + StringRef Directory = StringRef(), + StringRef Filename = StringRef()); + +/// createDebugIRPass - Enable interactive stepping through LLVM IR in LLDB +/// (or GDB) with an existing IR file on disk. When creating +/// a DebugIR pass with this function, no source file is +/// output to disk and the existing one is unmodified. Debug +/// metadata in the Module is created/updated to point to +/// the existing textual IR file on disk. +/// NOTE: If the IR file to be debugged is not on disk, use the version of this +/// function with parameters in order to generate the file that will be +/// seen by the debugger. +ModulePass *createDebugIRPass(); } // End llvm namespace diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h index e833aaa..037ab6b 100644 --- a/include/llvm/Transforms/Scalar.h +++ b/include/llvm/Transforms/Scalar.h @@ -23,6 +23,7 @@ class GetElementPtrInst; class PassInfo; class TerminatorInst; class TargetLowering; +class TargetMachine; //===----------------------------------------------------------------------===// // @@ -119,7 +120,7 @@ Pass *createLICMPass(); // Pass *createLoopStrengthReducePass(); -Pass *createGlobalMergePass(const TargetLowering *TLI = 0); +Pass *createGlobalMergePass(const TargetMachine *TM = 0); //===----------------------------------------------------------------------===// // @@ -199,6 +200,19 @@ FunctionPass *createCFGSimplificationPass(); //===----------------------------------------------------------------------===// // +// FlattenCFG - flatten CFG, reduce number of conditional branches by using +// parallel-and and parallel-or mode, etc... +// +FunctionPass *createFlattenCFGPass(); + +//===----------------------------------------------------------------------===// +// +// CFG Structurization - Remove irreducible control flow +// +Pass *createStructurizeCFGPass(); + +//===----------------------------------------------------------------------===// +// // BreakCriticalEdges - Break all of the critical edges in the CFG by inserting // a dummy basic block. This pass may be "required" by passes that cannot deal // with critical edges. For this usage, a pass must call: @@ -247,9 +261,8 @@ extern char &LowerSwitchID; // purpose "my LLVM-to-LLVM pass doesn't support the invoke instruction yet" // lowering pass. // -FunctionPass *createLowerInvokePass(const TargetLowering *TLI = 0); -FunctionPass *createLowerInvokePass(const TargetLowering *TLI, - bool useExpensiveEHSupport); +FunctionPass *createLowerInvokePass(const TargetMachine *TM = 0, + bool useExpensiveEHSupport = false); extern char &LowerInvokePassID; //===----------------------------------------------------------------------===// @@ -297,15 +310,9 @@ Pass *createLoopDeletionPass(); //===----------------------------------------------------------------------===// // -/// createSimplifyLibCallsPass - This pass optimizes specific calls to -/// specific well-known (library) functions. -FunctionPass *createSimplifyLibCallsPass(); - -//===----------------------------------------------------------------------===// -// // CodeGenPrepare - This pass prepares a function for instruction selection. // -FunctionPass *createCodeGenPreparePass(const TargetLowering *TLI = 0); +FunctionPass *createCodeGenPreparePass(const TargetMachine *TM = 0); //===----------------------------------------------------------------------===// // diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h index 8f1a6e2..65cafe2 100644 --- a/include/llvm/Transforms/Utils/BasicBlockUtils.h +++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -70,28 +70,6 @@ void ReplaceInstWithInst(BasicBlock::InstListType &BIL, // void ReplaceInstWithInst(Instruction *From, Instruction *To); -/// FindFunctionBackedges - Analyze the specified function to find all of the -/// loop backedges in the function and return them. This is a relatively cheap -/// (compared to computing dominators and loop info) analysis. -/// -/// The output is added to Result, as pairs of <from,to> edge info. -void FindFunctionBackedges(const Function &F, - SmallVectorImpl<std::pair<const BasicBlock*,const BasicBlock*> > &Result); - - -/// GetSuccessorNumber - Search for the specified successor of basic block BB -/// and return its position in the terminator instruction's list of -/// successors. It is an error to call this with a block that is not a -/// successor. -unsigned GetSuccessorNumber(BasicBlock *BB, BasicBlock *Succ); - -/// isCriticalEdge - Return true if the specified edge is a critical edge. -/// Critical edges are edges from a block with multiple successors to a block -/// with multiple predecessors. -/// -bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum, - bool AllowIdenticalEdges = false); - /// SplitCriticalEdge - If this edge is a critical edge, insert a new node to /// split the critical edge. This will update DominatorTree and /// DominatorFrontier information if it is available, thus calling this pass @@ -227,6 +205,15 @@ ReturnInst *FoldReturnIntoUncondBranch(ReturnInst *RI, BasicBlock *BB, TerminatorInst *SplitBlockAndInsertIfThen(Instruction *Cmp, bool Unreachable, MDNode *BranchWeights = 0); +/// +/// GetIfCondition - Check whether BB is the merge point of a if-region. +/// If so, return the boolean condition that determines which entry into +/// BB will be taken. Also, return by references the block that will be +/// entered from if the condition is true, and the block that will be +/// entered if the condition is false. + +Value *GetIfCondition(BasicBlock *BB, BasicBlock *&IfTrue, + BasicBlock *&IfFalse); } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/BlackList.h b/include/llvm/Transforms/Utils/BlackList.h deleted file mode 100644 index 316b364..0000000 --- a/include/llvm/Transforms/Utils/BlackList.h +++ /dev/null @@ -1,59 +0,0 @@ -//===-- BlackList.h - blacklist for sanitizers ------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -//===----------------------------------------------------------------------===// -// -// This is a utility class for instrumentation passes (like AddressSanitizer -// or ThreadSanitizer) to avoid instrumenting some functions or global -// variables based on a user-supplied blacklist. -// -// The blacklist disables instrumentation of various functions and global -// variables. Each line contains a prefix, followed by a wild card expression. -// Empty lines and lines starting with "#" are ignored. -// --- -// # Blacklisted items: -// fun:*_ZN4base6subtle* -// global:*global_with_bad_access_or_initialization* -// global-init:*global_with_initialization_issues* -// global-init-type:*Namespace::ClassName* -// src:file_with_tricky_code.cc -// global-init-src:ignore-global-initializers-issues.cc -// --- -// Note that the wild card is in fact an llvm::Regex, but * is automatically -// replaced with .* -// This is similar to the "ignore" feature of ThreadSanitizer. -// http://code.google.com/p/data-race-test/wiki/ThreadSanitizerIgnores -// -//===----------------------------------------------------------------------===// -// - -#include "llvm/ADT/StringMap.h" - -namespace llvm { -class Function; -class GlobalVariable; -class Module; -class Regex; -class StringRef; - -class BlackList { - public: - BlackList(const StringRef Path); - // Returns whether either this function or it's source file are blacklisted. - bool isIn(const Function &F) const; - // Returns whether either this global or it's source file are blacklisted. - bool isIn(const GlobalVariable &G) const; - // Returns whether this module is blacklisted by filename. - bool isIn(const Module &M) const; - // Returns whether a global should be excluded from initialization checking. - bool isInInit(const GlobalVariable &G) const; - private: - StringMap<Regex*> Entries; - - bool inSection(const StringRef Section, const StringRef Query) const; -}; - -} // namespace llvm diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h index 2678250..65755d0 100644 --- a/include/llvm/Transforms/Utils/Local.h +++ b/include/llvm/Transforms/Utils/Local.h @@ -39,9 +39,10 @@ class DataLayout; class TargetLibraryInfo; class TargetTransformInfo; class DIBuilder; +class AliasAnalysis; template<typename T> class SmallVectorImpl; - + //===----------------------------------------------------------------------===// // Local constant propagation. // @@ -79,7 +80,7 @@ bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, /// too, recursively. Return true if a change was made. bool RecursivelyDeleteDeadPHINode(PHINode *PN, const TargetLibraryInfo *TLI=0); - + /// SimplifyInstructionsInBlock - Scan the specified basic block and try to /// simplify any instructions in it and recursively delete dead instructions. /// @@ -87,7 +88,7 @@ bool RecursivelyDeleteDeadPHINode(PHINode *PN, const TargetLibraryInfo *TLI=0); /// instructions in other blocks as well in this block. bool SimplifyInstructionsInBlock(BasicBlock *BB, const DataLayout *TD = 0, const TargetLibraryInfo *TLI = 0); - + //===----------------------------------------------------------------------===// // Control Flow Graph Restructuring. // @@ -105,15 +106,15 @@ bool SimplifyInstructionsInBlock(BasicBlock *BB, const DataLayout *TD = 0, /// recursively fold the 'and' to 0. void RemovePredecessorAndSimplify(BasicBlock *BB, BasicBlock *Pred, DataLayout *TD = 0); - - + + /// MergeBasicBlockIntoOnlyPred - BB is a block with one predecessor and its /// predecessor is known to have one successor (BB!). Eliminate the edge /// between them, moving the instructions in the predecessor into BB. This /// deletes the predecessor block. /// void MergeBasicBlockIntoOnlyPred(BasicBlock *BB, Pass *P = 0); - + /// TryToSimplifyUncondBranchFromEmptyBlock - BB is known to contain an /// unconditional branch, and contains no instructions other than PHI nodes, @@ -138,6 +139,12 @@ bool EliminateDuplicatePHINodes(BasicBlock *BB); bool SimplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, const DataLayout *TD = 0); +/// FlatternCFG - This function is used to flatten a CFG. For +/// example, it uses parallel-and and parallel-or mode to collapse +// if-conditions and merge if-regions with identical statements. +/// +bool FlattenCFG(BasicBlock *BB, AliasAnalysis *AA = 0); + /// FoldBranchToCommonDest - If this basic block is ONLY a setcc and a branch, /// and if a predecessor branches to us and one of our successors, fold the /// setcc into the predecessor and use logical operations to pick the right @@ -156,7 +163,7 @@ AllocaInst *DemoteRegToStack(Instruction &X, /// DemotePHIToStack - This function takes a virtual register computed by a phi /// node and replaces it with a slot in the stack frame, allocated via alloca. -/// The phi node is deleted and it returns the pointer to the alloca inserted. +/// The phi node is deleted and it returns the pointer to the alloca inserted. AllocaInst *DemotePHIToStack(PHINode *P, Instruction *AllocaPoint = 0); /// getOrEnforceKnownAlignment - If the specified pointer has an alignment that @@ -179,18 +186,19 @@ static inline unsigned getKnownAlignment(Value *V, const DataLayout *TD = 0) { template<typename IRBuilderTy> Value *EmitGEPOffset(IRBuilderTy *Builder, const DataLayout &TD, User *GEP, bool NoAssumptions = false) { - gep_type_iterator GTI = gep_type_begin(GEP); - Type *IntPtrTy = TD.getIntPtrType(GEP->getContext()); + GEPOperator *GEPOp = cast<GEPOperator>(GEP); + Type *IntPtrTy = TD.getIntPtrType(GEP->getType()); Value *Result = Constant::getNullValue(IntPtrTy); // If the GEP is inbounds, we know that none of the addressing operations will // overflow in an unsigned sense. - bool isInBounds = cast<GEPOperator>(GEP)->isInBounds() && !NoAssumptions; + bool isInBounds = GEPOp->isInBounds() && !NoAssumptions; // Build a mask for high order bits. - unsigned IntPtrWidth = TD.getPointerSizeInBits(); - uint64_t PtrSizeMask = ~0ULL >> (64-IntPtrWidth); + unsigned IntPtrWidth = IntPtrTy->getScalarType()->getIntegerBitWidth(); + uint64_t PtrSizeMask = ~0ULL >> (64 - IntPtrWidth); + gep_type_iterator GTI = gep_type_begin(GEP); for (User::op_iterator i = GEP->op_begin() + 1, e = GEP->op_end(); i != e; ++i, ++GTI) { Value *Op = *i; diff --git a/include/llvm/Transforms/Utils/ModuleUtils.h b/include/llvm/Transforms/Utils/ModuleUtils.h index bb7fc06..98a19ed 100644 --- a/include/llvm/Transforms/Utils/ModuleUtils.h +++ b/include/llvm/Transforms/Utils/ModuleUtils.h @@ -18,6 +18,9 @@ namespace llvm { class Module; class Function; +class GlobalValue; +class GlobalVariable; +template <class PtrType, unsigned SmallSize> class SmallPtrSet; /// Append F to the list of global ctors of module M with the given Priority. /// This wraps the function in the appropriate structure and stores it along @@ -28,6 +31,11 @@ void appendToGlobalCtors(Module &M, Function *F, int Priority); /// Same as appendToGlobalCtors(), but for global dtors. void appendToGlobalDtors(Module &M, Function *F, int Priority); +/// \brief Given "llvm.used" or "llvm.compiler.used" as a global name, collect +/// the initializer elements of that global in Set and return the global itself. +GlobalVariable *collectUsedGlobalVariables(Module &M, + SmallPtrSet<GlobalValue *, 8> &Set, + bool CompilerUsed); } // End llvm namespace #endif // LLVM_TRANSFORMS_UTILS_MODULEUTILS_H diff --git a/include/llvm/Transforms/Utils/PromoteMemToReg.h b/include/llvm/Transforms/Utils/PromoteMemToReg.h index 52a6157..2f28f33 100644 --- a/include/llvm/Transforms/Utils/PromoteMemToReg.h +++ b/include/llvm/Transforms/Utils/PromoteMemToReg.h @@ -15,29 +15,34 @@ #ifndef LLVM_TRANSFORMS_UTILS_PROMOTEMEMTOREG_H #define LLVM_TRANSFORMS_UTILS_PROMOTEMEMTOREG_H -#include <vector> +#include "llvm/ADT/ArrayRef.h" namespace llvm { class AllocaInst; +class DataLayout; class DominatorTree; class AliasSetTracker; -/// isAllocaPromotable - Return true if this alloca is legal for promotion. -/// This is true if there are only loads and stores to the alloca... +/// \brief Return true if this alloca is legal for promotion. /// -bool isAllocaPromotable(const AllocaInst *AI); - -/// PromoteMemToReg - Promote the specified list of alloca instructions into -/// scalar registers, inserting PHI nodes as appropriate. This function makes -/// use of DominanceFrontier information. This function does not modify the CFG -/// of the function at all. All allocas must be from the same function. +/// This is true if there are only loads, stores, and lifetime markers +/// (transitively) using this alloca. This also enforces that there is only +/// ever one layer of bitcasts or GEPs between the alloca and the lifetime +/// markers. +bool isAllocaPromotable(const AllocaInst *AI, const DataLayout *DL); + +/// \brief Promote the specified list of alloca instructions into scalar +/// registers, inserting PHI nodes as appropriate. +/// +/// This function makes use of DominanceFrontier information. This function +/// does not modify the CFG of the function at all. All allocas must be from +/// the same function. /// /// If AST is specified, the specified tracker is updated to reflect changes /// made to the IR. -/// -void PromoteMemToReg(const std::vector<AllocaInst*> &Allocas, - DominatorTree &DT, AliasSetTracker *AST = 0); +void PromoteMemToReg(ArrayRef<AllocaInst *> Allocas, DominatorTree &DT, + const DataLayout *DL, AliasSetTracker *AST = 0); } // End llvm namespace diff --git a/include/llvm/Transforms/Utils/SSAUpdater.h b/include/llvm/Transforms/Utils/SSAUpdater.h index cd04893..0c0e5de 100644 --- a/include/llvm/Transforms/Utils/SSAUpdater.h +++ b/include/llvm/Transforms/Utils/SSAUpdater.h @@ -28,82 +28,90 @@ namespace llvm { class Use; class Value; -/// SSAUpdater - This class updates SSA form for a set of values defined in -/// multiple blocks. This is used when code duplication or another unstructured +/// \brief Helper class for SSA formation on a set of values defined in +/// multiple blocks. +/// +/// This is used when code duplication or another unstructured /// transformation wants to rewrite a set of uses of one value with uses of a /// set of values. class SSAUpdater { friend class SSAUpdaterTraits<SSAUpdater>; private: - /// AvailableVals - This keeps track of which value to use on a per-block - /// basis. When we insert PHI nodes, we keep track of them here. + /// This keeps track of which value to use on a per-block basis. When we + /// insert PHI nodes, we keep track of them here. //typedef DenseMap<BasicBlock*, Value*> AvailableValsTy; void *AV; /// ProtoType holds the type of the values being rewritten. Type *ProtoType; - // PHI nodes are given a name based on ProtoName. + /// PHI nodes are given a name based on ProtoName. std::string ProtoName; - /// InsertedPHIs - If this is non-null, the SSAUpdater adds all PHI nodes that - /// it creates to the vector. + /// If this is non-null, the SSAUpdater adds all PHI nodes that it creates to + /// the vector. SmallVectorImpl<PHINode*> *InsertedPHIs; public: - /// SSAUpdater constructor. If InsertedPHIs is specified, it will be filled + /// If InsertedPHIs is specified, it will be filled /// in with all PHI Nodes created by rewriting. explicit SSAUpdater(SmallVectorImpl<PHINode*> *InsertedPHIs = 0); ~SSAUpdater(); - /// Initialize - Reset this object to get ready for a new set of SSA - /// updates with type 'Ty'. PHI nodes get a name based on 'Name'. + /// \brief Reset this object to get ready for a new set of SSA updates with + /// type 'Ty'. + /// + /// PHI nodes get a name based on 'Name'. void Initialize(Type *Ty, StringRef Name); - /// AddAvailableValue - Indicate that a rewritten value is available at the - /// end of the specified block with the specified value. + /// \brief Indicate that a rewritten value is available in the specified block + /// with the specified value. void AddAvailableValue(BasicBlock *BB, Value *V); - /// HasValueForBlock - Return true if the SSAUpdater already has a value for - /// the specified block. + /// \brief Return true if the SSAUpdater already has a value for the specified + /// block. bool HasValueForBlock(BasicBlock *BB) const; - /// GetValueAtEndOfBlock - Construct SSA form, materializing a value that is - /// live at the end of the specified block. + /// \brief Construct SSA form, materializing a value that is live at the end + /// of the specified block. Value *GetValueAtEndOfBlock(BasicBlock *BB); - /// GetValueInMiddleOfBlock - Construct SSA form, materializing a value that - /// is live in the middle of the specified block. + /// \brief Construct SSA form, materializing a value that is live in the + /// middle of the specified block. /// - /// GetValueInMiddleOfBlock is the same as GetValueAtEndOfBlock except in one - /// important case: if there is a definition of the rewritten value after the - /// 'use' in BB. Consider code like this: + /// \c GetValueInMiddleOfBlock is the same as \c GetValueAtEndOfBlock except + /// in one important case: if there is a definition of the rewritten value + /// after the 'use' in BB. Consider code like this: /// + /// \code /// X1 = ... /// SomeBB: /// use(X) /// X2 = ... /// br Cond, SomeBB, OutBB + /// \endcode /// /// In this case, there are two values (X1 and X2) added to the AvailableVals /// set by the client of the rewriter, and those values are both live out of /// their respective blocks. However, the use of X happens in the *middle* of /// a block. Because of this, we need to insert a new PHI node in SomeBB to /// merge the appropriate values, and this value isn't live out of the block. - /// Value *GetValueInMiddleOfBlock(BasicBlock *BB); - /// RewriteUse - Rewrite a use of the symbolic value. This handles PHI nodes, - /// which use their value in the corresponding predecessor. Note that this - /// will not work if the use is supposed to be rewritten to a value defined in - /// the same block as the use, but above it. Any 'AddAvailableValue's added - /// for the use's block will be considered to be below it. + /// \brief Rewrite a use of the symbolic value. + /// + /// This handles PHI nodes, which use their value in the corresponding + /// predecessor. Note that this will not work if the use is supposed to be + /// rewritten to a value defined in the same block as the use, but above it. + /// Any 'AddAvailableValue's added for the use's block will be considered to + /// be below it. void RewriteUse(Use &U); - /// RewriteUseAfterInsertions - Rewrite a use, just like RewriteUse. However, - /// this version of the method can rewrite uses in the same block as a - /// definition, because it assumes that all uses of a value are below any + /// \brief Rewrite a use like \c RewriteUse but handling in-block definitions. + /// + /// This version of the method can rewrite uses in the same block as + /// a definition, because it assumes that all uses of a value are below any /// inserted values. void RewriteUseAfterInsertions(Use &U); @@ -113,15 +121,15 @@ private: void operator=(const SSAUpdater&) LLVM_DELETED_FUNCTION; SSAUpdater(const SSAUpdater&) LLVM_DELETED_FUNCTION; }; - -/// LoadAndStorePromoter - This little helper class provides a convenient way to -/// promote a collection of loads and stores into SSA Form using the SSAUpdater. + +/// \brief Helper class for promoting a collection of loads and stores into SSA +/// Form using the SSAUpdater. +/// /// This handles complexities that SSAUpdater doesn't, such as multiple loads /// and stores in one block. /// /// Clients of this class are expected to subclass this and implement the /// virtual methods. -/// class LoadAndStorePromoter { protected: SSAUpdater &SSA; @@ -130,34 +138,36 @@ public: SSAUpdater &S, StringRef Name = StringRef()); virtual ~LoadAndStorePromoter() {} - /// run - This does the promotion. Insts is a list of loads and stores to - /// promote, and Name is the basename for the PHIs to insert. After this is - /// complete, the loads and stores are removed from the code. + /// \brief This does the promotion. + /// + /// Insts is a list of loads and stores to promote, and Name is the basename + /// for the PHIs to insert. After this is complete, the loads and stores are + /// removed from the code. void run(const SmallVectorImpl<Instruction*> &Insts) const; - /// Return true if the specified instruction is in the Inst list (which was - /// passed into the run method). Clients should implement this with a more - /// efficient version if possible. + /// \brief Return true if the specified instruction is in the Inst list. + /// + /// The Insts list is the one passed into the constructor. Clients should + /// implement this with a more efficient version if possible. virtual bool isInstInList(Instruction *I, const SmallVectorImpl<Instruction*> &Insts) const; - /// doExtraRewritesBeforeFinalDeletion - This hook is invoked after all the - /// stores are found and inserted as available values, but + /// \brief This hook is invoked after all the stores are found and inserted as + /// available values. virtual void doExtraRewritesBeforeFinalDeletion() const { } - /// replaceLoadWithValue - Clients can choose to implement this to get - /// notified right before a load is RAUW'd another value. + /// \brief Clients can choose to implement this to get notified right before + /// a load is RAUW'd another value. virtual void replaceLoadWithValue(LoadInst *LI, Value *V) const { } - /// This is called before each instruction is deleted. + /// \brief Called before each instruction is deleted. virtual void instructionDeleted(Instruction *I) const { } - /// updateDebugInfo - This is called to update debug info associated with the - /// instruction. + /// \brief Called to update debug info associated with the instruction. virtual void updateDebugInfo(Instruction *I) const { } }; diff --git a/include/llvm/Transforms/Utils/SpecialCaseList.h b/include/llvm/Transforms/Utils/SpecialCaseList.h new file mode 100644 index 0000000..787ddb0 --- /dev/null +++ b/include/llvm/Transforms/Utils/SpecialCaseList.h @@ -0,0 +1,102 @@ +//===-- SpecialCaseList.h - special case list for sanitizers ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +//===----------------------------------------------------------------------===// +// +// This is a utility class for instrumentation passes (like AddressSanitizer +// or ThreadSanitizer) to avoid instrumenting some functions or global +// variables based on a user-supplied list. +// +// The list can also specify categories for specific globals, which can be used +// to instruct an instrumentation pass to treat certain functions or global +// variables in a specific way, such as by omitting certain aspects of +// instrumentation while keeping others, or informing the instrumentation pass +// that a specific uninstrumentable function has certain semantics, thus +// allowing the pass to instrument callers according to those semantics. +// +// For example, AddressSanitizer uses the "init" category for globals whose +// initializers should not be instrumented, but which in all other respects +// should be instrumented. +// +// Each line contains a prefix, followed by a colon and a wild card expression, +// followed optionally by an equals sign and an instrumentation-specific +// category. Empty lines and lines starting with "#" are ignored. +// --- +// # Blacklisted items: +// fun:*_ZN4base6subtle* +// global:*global_with_bad_access_or_initialization* +// global:*global_with_initialization_issues*=init +// type:*Namespace::ClassName*=init +// src:file_with_tricky_code.cc +// src:ignore-global-initializers-issues.cc=init +// +// # Functions with pure functional semantics: +// fun:cos=functional +// fun:sin=functional +// --- +// Note that the wild card is in fact an llvm::Regex, but * is automatically +// replaced with .* +// This is similar to the "ignore" feature of ThreadSanitizer. +// http://code.google.com/p/data-race-test/wiki/ThreadSanitizerIgnores +// +//===----------------------------------------------------------------------===// +// + +#include "llvm/ADT/StringMap.h" + +namespace llvm { +class Function; +class GlobalVariable; +class MemoryBuffer; +class Module; +class Regex; +class StringRef; + +class SpecialCaseList { + public: + SpecialCaseList(const StringRef Path); + SpecialCaseList(const MemoryBuffer *MB); + ~SpecialCaseList(); + + /// Returns whether either this function or its source file are listed in the + /// given category, which may be omitted to search the empty category. + bool isIn(const Function &F, const StringRef Category = StringRef()) const; + + /// Returns whether this global, its type or its source file are listed in the + /// given category, which may be omitted to search the empty category. + bool isIn(const GlobalVariable &G, + const StringRef Category = StringRef()) const; + + /// Returns whether this module is listed in the given category, which may be + /// omitted to search the empty category. + bool isIn(const Module &M, const StringRef Category = StringRef()) const; + + /// Returns whether either this function or its source file are listed in any + /// category. Category will contain the name of an arbitrary category in + /// which this function is listed. + bool findCategory(const Function &F, StringRef &Category) const; + + /// Returns whether this global, its type or its source file are listed in any + /// category. Category will contain the name of an arbitrary category in + /// which this global is listed. + bool findCategory(const GlobalVariable &G, StringRef &Category) const; + + /// Returns whether this module is listed in any category. Category will + /// contain the name of an arbitrary category in which this module is listed. + bool findCategory(const Module &M, StringRef &Category) const; + + private: + struct Entry; + StringMap<StringMap<Entry> > Entries; + + void init(const MemoryBuffer *MB); + bool findCategory(const StringRef Section, const StringRef Query, + StringRef &Category) const; + bool inSectionCategory(const StringRef Section, const StringRef Query, + const StringRef Category) const; +}; + +} // namespace llvm |