diff options
author | Dan Gohman <djg@cray.com> | 2007-07-18 16:29:46 +0000 |
---|---|---|
committer | Dan Gohman <djg@cray.com> | 2007-07-18 16:29:46 +0000 |
commit | f17a25c88b892d30c2b41ba7ecdfbdfb2b4be9cc (patch) | |
tree | ebb79ea1ee5e3bc1fdf38541a811a8b804f0679a /include | |
download | external_llvm-f17a25c88b892d30c2b41ba7ecdfbdfb2b4be9cc.zip external_llvm-f17a25c88b892d30c2b41ba7ecdfbdfb2b4be9cc.tar.gz external_llvm-f17a25c88b892d30c2b41ba7ecdfbdfb2b4be9cc.tar.bz2 |
It's not necessary to do rounding for alloca operations when the requested
alignment is equal to the stack alignment.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@40004 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
234 files changed, 50882 insertions, 0 deletions
diff --git a/include/llvm-c/LinkTimeOptimizer.h b/include/llvm-c/LinkTimeOptimizer.h new file mode 100644 index 0000000..6de33ca --- /dev/null +++ b/include/llvm-c/LinkTimeOptimizer.h @@ -0,0 +1,58 @@ +//===-- llvm/LinkTimeOptimizer.h - LTO Public C Interface -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chandler Carruth and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header provides a C API to use the LLVM link time optimization +// library. This is inteded to be used by linkers which are C-only in +// their implementation for performing LTO. +// +//===----------------------------------------------------------------------===// + +#ifndef __LTO_CAPI_H__ +#define __LTO_CAPI_H__ + +#ifdef __cplusplus +extern "C" { +#endif + + /// This provides a dummy type for pointers to the LTO object. + typedef void* llvm_lto_t; + + /// This provides a C-visible enumerator to manage status codes. + /// This should map exactly onto the C++ enumerator LTOStatus. + typedef enum llvm_lto_status { + LLVM_LTO_UNKNOWN, + LLVM_LTO_OPT_SUCCESS, + LLVM_LTO_READ_SUCCESS, + LLVM_LTO_READ_FAILURE, + LLVM_LTO_WRITE_FAILURE, + LLVM_LTO_NO_TARGET, + LLVM_LTO_NO_WORK, + LLVM_LTO_MODULE_MERGE_FAILURE, + LLVM_LTO_ASM_FAILURE, + + // Added C-specific error codes + LLVM_LTO_NULL_OBJECT + } llvm_lto_status_t; + + /// This provides C interface to initialize link time optimizer. This allows + /// linker to use dlopen() interface to dynamically load LinkTimeOptimizer. + /// extern "C" helps, because dlopen() interface uses name to find the symbol. + extern llvm_lto_t llvm_create_optimizer(void); + extern void llvm_destroy_optimizer(llvm_lto_t lto); + + extern llvm_lto_status_t llvm_read_object_file + (llvm_lto_t lto, const char* input_filename); + extern llvm_lto_status_t llvm_optimize_modules + (llvm_lto_t lto, const char* output_filename); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/llvm/ADT/APInt.h b/include/llvm/ADT/APInt.h new file mode 100644 index 0000000..535e5db --- /dev/null +++ b/include/llvm/ADT/APInt.h @@ -0,0 +1,1228 @@ +//===-- llvm/Support/APInt.h - For Arbitrary Precision Integer -*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Sheng Zhou and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a class to represent arbitrary precision integral +// constant values and operations on them. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_APINT_H +#define LLVM_APINT_H + +#include "llvm/Support/DataTypes.h" +#include <cassert> +#include <string> + +namespace llvm { + +//===----------------------------------------------------------------------===// +// APInt Class +//===----------------------------------------------------------------------===// + +/// APInt - This class represents arbitrary precision constant integral values. +/// It is a functional replacement for common case unsigned integer type like +/// "unsigned", "unsigned long" or "uint64_t", but also allows non-byte-width +/// integer sizes and large integer value types such as 3-bits, 15-bits, or more +/// than 64-bits of precision. APInt provides a variety of arithmetic operators +/// and methods to manipulate integer values of any bit-width. It supports both +/// the typical integer arithmetic and comparison operations as well as bitwise +/// manipulation. +/// +/// The class has several invariants worth noting: +/// * All bit, byte, and word positions are zero-based. +/// * Once the bit width is set, it doesn't change except by the Truncate, +/// SignExtend, or ZeroExtend operations. +/// * All binary operators must be on APInt instances of the same bit width. +/// Attempting to use these operators on instances with different bit +/// widths will yield an assertion. +/// * The value is stored canonically as an unsigned value. For operations +/// where it makes a difference, there are both signed and unsigned variants +/// of the operation. For example, sdiv and udiv. However, because the bit +/// widths must be the same, operations such as Mul and Add produce the same +/// results regardless of whether the values are interpreted as signed or +/// not. +/// * In general, the class tries to follow the style of computation that LLVM +/// uses in its IR. This simplifies its use for LLVM. +/// +/// @brief Class for arbitrary precision integers. +class APInt { + + uint32_t BitWidth; ///< The number of bits in this APInt. + + /// This union is used to store the integer value. When the + /// integer bit-width <= 64, it uses VAL, otherwise it uses pVal. + union { + uint64_t VAL; ///< Used to store the <= 64 bits integer value. + uint64_t *pVal; ///< Used to store the >64 bits integer value. + }; + + /// This enum is used to hold the constants we needed for APInt. + enum { + APINT_BITS_PER_WORD = sizeof(uint64_t) * 8, ///< Bits in a word + APINT_WORD_SIZE = sizeof(uint64_t) ///< Byte size of a word + }; + + /// This constructor is used only internally for speed of construction of + /// temporaries. It is unsafe for general use so it is not public. + /// @brief Fast internal constructor + APInt(uint64_t* val, uint32_t bits) : BitWidth(bits), pVal(val) { } + + /// @returns true if the number of bits <= 64, false otherwise. + /// @brief Determine if this APInt just has one word to store value. + inline bool isSingleWord() const { + return BitWidth <= APINT_BITS_PER_WORD; + } + + /// @returns the word position for the specified bit position. + /// @brief Determine which word a bit is in. + static inline uint32_t whichWord(uint32_t bitPosition) { + return bitPosition / APINT_BITS_PER_WORD; + } + + /// @returns the bit position in a word for the specified bit position + /// in the APInt. + /// @brief Determine which bit in a word a bit is in. + static inline uint32_t whichBit(uint32_t bitPosition) { + return bitPosition % APINT_BITS_PER_WORD; + } + + /// This method generates and returns a uint64_t (word) mask for a single + /// bit at a specific bit position. This is used to mask the bit in the + /// corresponding word. + /// @returns a uint64_t with only bit at "whichBit(bitPosition)" set + /// @brief Get a single bit mask. + static inline uint64_t maskBit(uint32_t bitPosition) { + return 1ULL << whichBit(bitPosition); + } + + /// This method is used internally to clear the to "N" bits in the high order + /// word that are not used by the APInt. This is needed after the most + /// significant word is assigned a value to ensure that those bits are + /// zero'd out. + /// @brief Clear unused high order bits + inline APInt& clearUnusedBits() { + // Compute how many bits are used in the final word + uint32_t wordBits = BitWidth % APINT_BITS_PER_WORD; + if (wordBits == 0) + // If all bits are used, we want to leave the value alone. This also + // avoids the undefined behavior of >> when the shfit is the same size as + // the word size (64). + return *this; + + // Mask out the hight bits. + uint64_t mask = ~uint64_t(0ULL) >> (APINT_BITS_PER_WORD - wordBits); + if (isSingleWord()) + VAL &= mask; + else + pVal[getNumWords() - 1] &= mask; + return *this; + } + + /// @returns the corresponding word for the specified bit position. + /// @brief Get the word corresponding to a bit position + inline uint64_t getWord(uint32_t bitPosition) const { + return isSingleWord() ? VAL : pVal[whichWord(bitPosition)]; + } + + /// This is used by the constructors that take string arguments. + /// @brief Convert a char array into an APInt + void fromString(uint32_t numBits, const char *strStart, uint32_t slen, + uint8_t radix); + + /// This is used by the toString method to divide by the radix. It simply + /// provides a more convenient form of divide for internal use since KnuthDiv + /// has specific constraints on its inputs. If those constraints are not met + /// then it provides a simpler form of divide. + /// @brief An internal division function for dividing APInts. + static void divide(const APInt LHS, uint32_t lhsWords, + const APInt &RHS, uint32_t rhsWords, + APInt *Quotient, APInt *Remainder); + +#ifndef NDEBUG + /// @brief debug method + void dump() const; +#endif + +public: + /// @name Constructors + /// @{ + /// If isSigned is true then val is treated as if it were a signed value + /// (i.e. as an int64_t) and the appropriate sign extension to the bit width + /// will be done. Otherwise, no sign extension occurs (high order bits beyond + /// the range of val are zero filled). + /// @param numBits the bit width of the constructed APInt + /// @param val the initial value of the APInt + /// @param isSigned how to treat signedness of val + /// @brief Create a new APInt of numBits width, initialized as val. + APInt(uint32_t numBits, uint64_t val, bool isSigned = false); + + /// Note that numWords can be smaller or larger than the corresponding bit + /// width but any extraneous bits will be dropped. + /// @param numBits the bit width of the constructed APInt + /// @param numWords the number of words in bigVal + /// @param bigVal a sequence of words to form the initial value of the APInt + /// @brief Construct an APInt of numBits width, initialized as bigVal[]. + APInt(uint32_t numBits, uint32_t numWords, uint64_t bigVal[]); + + /// This constructor interprets Val as a string in the given radix. The + /// interpretation stops when the first charater that is not suitable for the + /// radix is encountered. Acceptable radix values are 2, 8, 10 and 16. It is + /// an error for the value implied by the string to require more bits than + /// numBits. + /// @param numBits the bit width of the constructed APInt + /// @param val the string to be interpreted + /// @param radix the radix of Val to use for the intepretation + /// @brief Construct an APInt from a string representation. + APInt(uint32_t numBits, const std::string& val, uint8_t radix); + + /// This constructor interprets the slen characters starting at StrStart as + /// a string in the given radix. The interpretation stops when the first + /// character that is not suitable for the radix is encountered. Acceptable + /// radix values are 2, 8, 10 and 16. It is an error for the value implied by + /// the string to require more bits than numBits. + /// @param numBits the bit width of the constructed APInt + /// @param strStart the start of the string to be interpreted + /// @param slen the maximum number of characters to interpret + /// @brief Construct an APInt from a string representation. + APInt(uint32_t numBits, const char strStart[], uint32_t slen, uint8_t radix); + + /// Simply makes *this a copy of that. + /// @brief Copy Constructor. + APInt(const APInt& that); + + /// @brief Destructor. + ~APInt(); + + /// @} + /// @name Value Tests + /// @{ + /// This tests the high bit of this APInt to determine if it is set. + /// @returns true if this APInt is negative, false otherwise + /// @brief Determine sign of this APInt. + bool isNegative() const { + return (*this)[BitWidth - 1]; + } + + /// This tests the high bit of the APInt to determine if it is unset. + /// @brief Determine if this APInt Value is positive (not negative). + bool isPositive() const { + return !isNegative(); + } + + /// This tests if the value of this APInt is strictly positive (> 0). + /// @returns true if this APInt is Positive and not zero. + /// @brief Determine if this APInt Value is strictly positive. + inline bool isStrictlyPositive() const { + return isPositive() && (*this) != 0; + } + + /// This checks to see if the value has all bits of the APInt are set or not. + /// @brief Determine if all bits are set + inline bool isAllOnesValue() const { + return countPopulation() == BitWidth; + } + + /// This checks to see if the value of this APInt is the maximum unsigned + /// value for the APInt's bit width. + /// @brief Determine if this is the largest unsigned value. + bool isMaxValue() const { + return countPopulation() == BitWidth; + } + + /// This checks to see if the value of this APInt is the maximum signed + /// value for the APInt's bit width. + /// @brief Determine if this is the largest signed value. + bool isMaxSignedValue() const { + return BitWidth == 1 ? VAL == 0 : + !isNegative() && countPopulation() == BitWidth - 1; + } + + /// This checks to see if the value of this APInt is the minimum unsigned + /// value for the APInt's bit width. + /// @brief Determine if this is the smallest unsigned value. + bool isMinValue() const { + return countPopulation() == 0; + } + + /// This checks to see if the value of this APInt is the minimum signed + /// value for the APInt's bit width. + /// @brief Determine if this is the smallest signed value. + bool isMinSignedValue() const { + return BitWidth == 1 ? VAL == 1 : + isNegative() && countPopulation() == 1; + } + + /// @brief Check if this APInt has an N-bits integer value. + inline bool isIntN(uint32_t N) const { + assert(N && "N == 0 ???"); + if (isSingleWord()) { + return VAL == (VAL & (~0ULL >> (64 - N))); + } else { + APInt Tmp(N, getNumWords(), pVal); + return Tmp == (*this); + } + } + + /// @returns true if the argument APInt value is a power of two > 0. + bool isPowerOf2() const; + + /// isSignBit - Return true if this is the value returned by getSignBit. + bool isSignBit() const { return isMinSignedValue(); } + + /// This converts the APInt to a boolean value as a test against zero. + /// @brief Boolean conversion function. + inline bool getBoolValue() const { + return *this != 0; + } + + /// getLimitedValue - If this value is smaller than the specified limit, + /// return it, otherwise return the limit value. This causes the value + /// to saturate to the limit. + uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const { + return (getActiveBits() > 64 || getZExtValue() > Limit) ? + Limit : getZExtValue(); + } + + /// @} + /// @name Value Generators + /// @{ + /// @brief Gets maximum unsigned value of APInt for specific bit width. + static APInt getMaxValue(uint32_t numBits) { + return APInt(numBits, 0).set(); + } + + /// @brief Gets maximum signed value of APInt for a specific bit width. + static APInt getSignedMaxValue(uint32_t numBits) { + return APInt(numBits, 0).set().clear(numBits - 1); + } + + /// @brief Gets minimum unsigned value of APInt for a specific bit width. + static APInt getMinValue(uint32_t numBits) { + return APInt(numBits, 0); + } + + /// @brief Gets minimum signed value of APInt for a specific bit width. + static APInt getSignedMinValue(uint32_t numBits) { + return APInt(numBits, 0).set(numBits - 1); + } + + /// getSignBit - This is just a wrapper function of getSignedMinValue(), and + /// it helps code readability when we want to get a SignBit. + /// @brief Get the SignBit for a specific bit width. + inline static APInt getSignBit(uint32_t BitWidth) { + return getSignedMinValue(BitWidth); + } + + /// @returns the all-ones value for an APInt of the specified bit-width. + /// @brief Get the all-ones value. + static APInt getAllOnesValue(uint32_t numBits) { + return APInt(numBits, 0).set(); + } + + /// @returns the '0' value for an APInt of the specified bit-width. + /// @brief Get the '0' value. + static APInt getNullValue(uint32_t numBits) { + return APInt(numBits, 0); + } + + /// Get an APInt with the same BitWidth as this APInt, just zero mask + /// the low bits and right shift to the least significant bit. + /// @returns the high "numBits" bits of this APInt. + APInt getHiBits(uint32_t numBits) const; + + /// Get an APInt with the same BitWidth as this APInt, just zero mask + /// the high bits. + /// @returns the low "numBits" bits of this APInt. + APInt getLoBits(uint32_t numBits) const; + + /// Constructs an APInt value that has a contiguous range of bits set. The + /// bits from loBit to hiBit will be set. All other bits will be zero. For + /// example, with parameters(32, 15, 0) you would get 0x0000FFFF. If hiBit is + /// less than loBit then the set bits "wrap". For example, with + /// parameters (32, 3, 28), you would get 0xF000000F. + /// @param numBits the intended bit width of the result + /// @param loBit the index of the lowest bit set. + /// @param hiBit the index of the highest bit set. + /// @returns An APInt value with the requested bits set. + /// @brief Get a value with a block of bits set. + static APInt getBitsSet(uint32_t numBits, uint32_t loBit, uint32_t hiBit) { + assert(hiBit < numBits && "hiBit out of range"); + assert(loBit < numBits && "loBit out of range"); + if (hiBit < loBit) + return getLowBitsSet(numBits, hiBit+1) | + getHighBitsSet(numBits, numBits-loBit+1); + return getLowBitsSet(numBits, hiBit-loBit+1).shl(loBit); + } + + /// Constructs an APInt value that has the top hiBitsSet bits set. + /// @param numBits the bitwidth of the result + /// @param hiBitsSet the number of high-order bits set in the result. + /// @brief Get a value with high bits set + static APInt getHighBitsSet(uint32_t numBits, uint32_t hiBitsSet) { + assert(hiBitsSet <= numBits && "Too many bits to set!"); + // Handle a degenerate case, to avoid shifting by word size + if (hiBitsSet == 0) + return APInt(numBits, 0); + uint32_t shiftAmt = numBits - hiBitsSet; + // For small values, return quickly + if (numBits <= APINT_BITS_PER_WORD) + return APInt(numBits, ~0ULL << shiftAmt); + return (~APInt(numBits, 0)).shl(shiftAmt); + } + + /// Constructs an APInt value that has the bottom loBitsSet bits set. + /// @param numBits the bitwidth of the result + /// @param loBitsSet the number of low-order bits set in the result. + /// @brief Get a value with low bits set + static APInt getLowBitsSet(uint32_t numBits, uint32_t loBitsSet) { + assert(loBitsSet <= numBits && "Too many bits to set!"); + // Handle a degenerate case, to avoid shifting by word size + if (loBitsSet == 0) + return APInt(numBits, 0); + if (loBitsSet == APINT_BITS_PER_WORD) + return APInt(numBits, -1ULL); + // For small values, return quickly + if (numBits < APINT_BITS_PER_WORD) + return APInt(numBits, (1ULL << loBitsSet) - 1); + return (~APInt(numBits, 0)).lshr(numBits - loBitsSet); + } + + /// The hash value is computed as the sum of the words and the bit width. + /// @returns A hash value computed from the sum of the APInt words. + /// @brief Get a hash value based on this APInt + uint64_t getHashValue() const; + + /// This function returns a pointer to the internal storage of the APInt. + /// This is useful for writing out the APInt in binary form without any + /// conversions. + inline const uint64_t* getRawData() const { + if (isSingleWord()) + return &VAL; + return &pVal[0]; + } + + /// @} + /// @name Unary Operators + /// @{ + /// @returns a new APInt value representing *this incremented by one + /// @brief Postfix increment operator. + inline const APInt operator++(int) { + APInt API(*this); + ++(*this); + return API; + } + + /// @returns *this incremented by one + /// @brief Prefix increment operator. + APInt& operator++(); + + /// @returns a new APInt representing *this decremented by one. + /// @brief Postfix decrement operator. + inline const APInt operator--(int) { + APInt API(*this); + --(*this); + return API; + } + + /// @returns *this decremented by one. + /// @brief Prefix decrement operator. + APInt& operator--(); + + /// Performs a bitwise complement operation on this APInt. + /// @returns an APInt that is the bitwise complement of *this + /// @brief Unary bitwise complement operator. + APInt operator~() const; + + /// Negates *this using two's complement logic. + /// @returns An APInt value representing the negation of *this. + /// @brief Unary negation operator + inline APInt operator-() const { + return APInt(BitWidth, 0) - (*this); + } + + /// Performs logical negation operation on this APInt. + /// @returns true if *this is zero, false otherwise. + /// @brief Logical negation operator. + bool operator !() const; + + /// @} + /// @name Assignment Operators + /// @{ + /// @returns *this after assignment of RHS. + /// @brief Copy assignment operator. + APInt& operator=(const APInt& RHS); + + /// The RHS value is assigned to *this. If the significant bits in RHS exceed + /// the bit width, the excess bits are truncated. If the bit width is larger + /// than 64, the value is zero filled in the unspecified high order bits. + /// @returns *this after assignment of RHS value. + /// @brief Assignment operator. + APInt& operator=(uint64_t RHS); + + /// Performs a bitwise AND operation on this APInt and RHS. The result is + /// assigned to *this. + /// @returns *this after ANDing with RHS. + /// @brief Bitwise AND assignment operator. + APInt& operator&=(const APInt& RHS); + + /// Performs a bitwise OR operation on this APInt and RHS. The result is + /// assigned *this; + /// @returns *this after ORing with RHS. + /// @brief Bitwise OR assignment operator. + APInt& operator|=(const APInt& RHS); + + /// Performs a bitwise XOR operation on this APInt and RHS. The result is + /// assigned to *this. + /// @returns *this after XORing with RHS. + /// @brief Bitwise XOR assignment operator. + APInt& operator^=(const APInt& RHS); + + /// Multiplies this APInt by RHS and assigns the result to *this. + /// @returns *this + /// @brief Multiplication assignment operator. + APInt& operator*=(const APInt& RHS); + + /// Adds RHS to *this and assigns the result to *this. + /// @returns *this + /// @brief Addition assignment operator. + APInt& operator+=(const APInt& RHS); + + /// Subtracts RHS from *this and assigns the result to *this. + /// @returns *this + /// @brief Subtraction assignment operator. + APInt& operator-=(const APInt& RHS); + + /// Shifts *this left by shiftAmt and assigns the result to *this. + /// @returns *this after shifting left by shiftAmt + /// @brief Left-shift assignment function. + inline APInt& operator<<=(uint32_t shiftAmt) { + *this = shl(shiftAmt); + return *this; + } + + /// @} + /// @name Binary Operators + /// @{ + /// Performs a bitwise AND operation on *this and RHS. + /// @returns An APInt value representing the bitwise AND of *this and RHS. + /// @brief Bitwise AND operator. + APInt operator&(const APInt& RHS) const; + APInt And(const APInt& RHS) const { + return this->operator&(RHS); + } + + /// Performs a bitwise OR operation on *this and RHS. + /// @returns An APInt value representing the bitwise OR of *this and RHS. + /// @brief Bitwise OR operator. + APInt operator|(const APInt& RHS) const; + APInt Or(const APInt& RHS) const { + return this->operator|(RHS); + } + + /// Performs a bitwise XOR operation on *this and RHS. + /// @returns An APInt value representing the bitwise XOR of *this and RHS. + /// @brief Bitwise XOR operator. + APInt operator^(const APInt& RHS) const; + APInt Xor(const APInt& RHS) const { + return this->operator^(RHS); + } + + /// Multiplies this APInt by RHS and returns the result. + /// @brief Multiplication operator. + APInt operator*(const APInt& RHS) const; + + /// Adds RHS to this APInt and returns the result. + /// @brief Addition operator. + APInt operator+(const APInt& RHS) const; + APInt operator+(uint64_t RHS) const { + return (*this) + APInt(BitWidth, RHS); + } + + /// Subtracts RHS from this APInt and returns the result. + /// @brief Subtraction operator. + APInt operator-(const APInt& RHS) const; + APInt operator-(uint64_t RHS) const { + return (*this) - APInt(BitWidth, RHS); + } + + APInt operator<<(unsigned Bits) const { + return shl(Bits); + } + + /// Arithmetic right-shift this APInt by shiftAmt. + /// @brief Arithmetic right-shift function. + APInt ashr(uint32_t shiftAmt) const; + + /// Logical right-shift this APInt by shiftAmt. + /// @brief Logical right-shift function. + APInt lshr(uint32_t shiftAmt) const; + + /// Left-shift this APInt by shiftAmt. + /// @brief Left-shift function. + APInt shl(uint32_t shiftAmt) const; + + /// @brief Rotate left by rotateAmt. + APInt rotl(uint32_t rotateAmt) const; + + /// @brief Rotate right by rotateAmt. + APInt rotr(uint32_t rotateAmt) const; + + /// Perform an unsigned divide operation on this APInt by RHS. Both this and + /// RHS are treated as unsigned quantities for purposes of this division. + /// @returns a new APInt value containing the division result + /// @brief Unsigned division operation. + APInt udiv(const APInt& RHS) const; + + /// Signed divide this APInt by APInt RHS. + /// @brief Signed division function for APInt. + inline APInt sdiv(const APInt& RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return (-(*this)).udiv(-RHS); + else + return -((-(*this)).udiv(RHS)); + else if (RHS.isNegative()) + return -(this->udiv(-RHS)); + return this->udiv(RHS); + } + + /// Perform an unsigned remainder operation on this APInt with RHS being the + /// divisor. Both this and RHS are treated as unsigned quantities for purposes + /// of this operation. Note that this is a true remainder operation and not + /// a modulo operation because the sign follows the sign of the dividend + /// which is *this. + /// @returns a new APInt value containing the remainder result + /// @brief Unsigned remainder operation. + APInt urem(const APInt& RHS) const; + + /// Signed remainder operation on APInt. + /// @brief Function for signed remainder operation. + inline APInt srem(const APInt& RHS) const { + if (isNegative()) + if (RHS.isNegative()) + return -((-(*this)).urem(-RHS)); + else + return -((-(*this)).urem(RHS)); + else if (RHS.isNegative()) + return this->urem(-RHS); + return this->urem(RHS); + } + + /// Sometimes it is convenient to divide two APInt values and obtain both + /// the quotient and remainder. This function does both operations in the + /// same computation making it a little more efficient. + /// @brief Dual division/remainder interface. + static void udivrem(const APInt &LHS, const APInt &RHS, + APInt &Quotient, APInt &Remainder); + + static void sdivrem(const APInt &LHS, const APInt &RHS, + APInt &Quotient, APInt &Remainder) + { + if (LHS.isNegative()) { + if (RHS.isNegative()) + APInt::udivrem(-LHS, -RHS, Quotient, Remainder); + else + APInt::udivrem(-LHS, RHS, Quotient, Remainder); + Quotient = -Quotient; + Remainder = -Remainder; + } else if (RHS.isNegative()) { + APInt::udivrem(LHS, -RHS, Quotient, Remainder); + Quotient = -Quotient; + } else { + APInt::udivrem(LHS, RHS, Quotient, Remainder); + } + } + + /// @returns the bit value at bitPosition + /// @brief Array-indexing support. + bool operator[](uint32_t bitPosition) const; + + /// @} + /// @name Comparison Operators + /// @{ + /// Compares this APInt with RHS for the validity of the equality + /// relationship. + /// @brief Equality operator. + bool operator==(const APInt& RHS) const; + + /// Compares this APInt with a uint64_t for the validity of the equality + /// relationship. + /// @returns true if *this == Val + /// @brief Equality operator. + bool operator==(uint64_t Val) const; + + /// Compares this APInt with RHS for the validity of the equality + /// relationship. + /// @returns true if *this == Val + /// @brief Equality comparison. + bool eq(const APInt &RHS) const { + return (*this) == RHS; + } + + /// Compares this APInt with RHS for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality operator. + inline bool operator!=(const APInt& RHS) const { + return !((*this) == RHS); + } + + /// Compares this APInt with a uint64_t for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality operator. + inline bool operator!=(uint64_t Val) const { + return !((*this) == Val); + } + + /// Compares this APInt with RHS for the validity of the inequality + /// relationship. + /// @returns true if *this != Val + /// @brief Inequality comparison + bool ne(const APInt &RHS) const { + return !((*this) == RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered unsigned. + /// @brief Unsigned less than comparison + bool ult(const APInt& RHS) const; + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-than relationship. + /// @returns true if *this < RHS when both are considered signed. + /// @brief Signed less than comparison + bool slt(const APInt& RHS) const; + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered unsigned. + /// @brief Unsigned less or equal comparison + bool ule(const APInt& RHS) const { + return ult(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the less-or-equal relationship. + /// @returns true if *this <= RHS when both are considered signed. + /// @brief Signed less or equal comparison + bool sle(const APInt& RHS) const { + return slt(RHS) || eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered unsigned. + /// @brief Unsigned greather than comparison + bool ugt(const APInt& RHS) const { + return !ult(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// the validity of the greater-than relationship. + /// @returns true if *this > RHS when both are considered signed. + /// @brief Signed greather than comparison + bool sgt(const APInt& RHS) const { + return !slt(RHS) && !eq(RHS); + } + + /// Regards both *this and RHS as unsigned quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered unsigned. + /// @brief Unsigned greater or equal comparison + bool uge(const APInt& RHS) const { + return !ult(RHS); + } + + /// Regards both *this and RHS as signed quantities and compares them for + /// validity of the greater-or-equal relationship. + /// @returns true if *this >= RHS when both are considered signed. + /// @brief Signed greather or equal comparison + bool sge(const APInt& RHS) const { + return !slt(RHS); + } + + /// @} + /// @name Resizing Operators + /// @{ + /// Truncate the APInt to a specified width. It is an error to specify a width + /// that is greater than or equal to the current width. + /// @brief Truncate to new width. + APInt &trunc(uint32_t width); + + /// This operation sign extends the APInt to a new width. If the high order + /// bit is set, the fill on the left will be done with 1 bits, otherwise zero. + /// It is an error to specify a width that is less than or equal to the + /// current width. + /// @brief Sign extend to a new width. + APInt &sext(uint32_t width); + + /// This operation zero extends the APInt to a new width. The high order bits + /// are filled with 0 bits. It is an error to specify a width that is less + /// than or equal to the current width. + /// @brief Zero extend to a new width. + APInt &zext(uint32_t width); + + /// Make this APInt have the bit width given by \p width. The value is sign + /// extended, truncated, or left alone to make it that width. + /// @brief Sign extend or truncate to width + APInt &sextOrTrunc(uint32_t width); + + /// Make this APInt have the bit width given by \p width. The value is zero + /// extended, truncated, or left alone to make it that width. + /// @brief Zero extend or truncate to width + APInt &zextOrTrunc(uint32_t width); + + /// @} + /// @name Bit Manipulation Operators + /// @{ + /// @brief Set every bit to 1. + APInt& set(); + + /// Set the given bit to 1 whose position is given as "bitPosition". + /// @brief Set a given bit to 1. + APInt& set(uint32_t bitPosition); + + /// @brief Set every bit to 0. + APInt& clear(); + + /// Set the given bit to 0 whose position is given as "bitPosition". + /// @brief Set a given bit to 0. + APInt& clear(uint32_t bitPosition); + + /// @brief Toggle every bit to its opposite value. + APInt& flip(); + + /// Toggle a given bit to its opposite value whose position is given + /// as "bitPosition". + /// @brief Toggles a given bit to its opposite value. + APInt& flip(uint32_t bitPosition); + + /// @} + /// @name Value Characterization Functions + /// @{ + + /// @returns the total number of bits. + inline uint32_t getBitWidth() const { + return BitWidth; + } + + /// Here one word's bitwidth equals to that of uint64_t. + /// @returns the number of words to hold the integer value of this APInt. + /// @brief Get the number of words. + inline uint32_t getNumWords() const { + return (BitWidth + APINT_BITS_PER_WORD - 1) / APINT_BITS_PER_WORD; + } + + /// This function returns the number of active bits which is defined as the + /// bit width minus the number of leading zeros. This is used in several + /// computations to see how "wide" the value is. + /// @brief Compute the number of active bits in the value + inline uint32_t getActiveBits() const { + return BitWidth - countLeadingZeros(); + } + + /// This function returns the number of active words in the value of this + /// APInt. This is used in conjunction with getActiveData to extract the raw + /// value of the APInt. + inline uint32_t getActiveWords() const { + return whichWord(getActiveBits()-1) + 1; + } + + /// Computes the minimum bit width for this APInt while considering it to be + /// a signed (and probably negative) value. If the value is not negative, + /// this function returns the same value as getActiveBits(). Otherwise, it + /// returns the smallest bit width that will retain the negative value. For + /// example, -1 can be written as 0b1 or 0xFFFFFFFFFF. 0b1 is shorter and so + /// for -1, this function will always return 1. + /// @brief Get the minimum bit size for this signed APInt + inline uint32_t getMinSignedBits() const { + if (isNegative()) + return BitWidth - countLeadingOnes() + 1; + return getActiveBits(); + } + + /// This method attempts to return the value of this APInt as a zero extended + /// uint64_t. The bitwidth must be <= 64 or the value must fit within a + /// uint64_t. Otherwise an assertion will result. + /// @brief Get zero extended value + inline uint64_t getZExtValue() const { + if (isSingleWord()) + return VAL; + assert(getActiveBits() <= 64 && "Too many bits for uint64_t"); + return pVal[0]; + } + + /// This method attempts to return the value of this APInt as a sign extended + /// int64_t. The bit width must be <= 64 or the value must fit within an + /// int64_t. Otherwise an assertion will result. + /// @brief Get sign extended value + inline int64_t getSExtValue() const { + if (isSingleWord()) + return int64_t(VAL << (APINT_BITS_PER_WORD - BitWidth)) >> + (APINT_BITS_PER_WORD - BitWidth); + assert(getActiveBits() <= 64 && "Too many bits for int64_t"); + return int64_t(pVal[0]); + } + + /// This method determines how many bits are required to hold the APInt + /// equivalent of the string given by \p str of length \p slen. + /// @brief Get bits required for string value. + static uint32_t getBitsNeeded(const char* str, uint32_t slen, uint8_t radix); + + /// countLeadingZeros - This function is an APInt version of the + /// countLeadingZeros_{32,64} functions in MathExtras.h. It counts the number + /// of zeros from the most significant bit to the first one bit. + /// @returns getNumWords() * APINT_BITS_PER_WORD if the value is zero. + /// @returns the number of zeros from the most significant bit to the first + /// one bits. + /// @brief Count the number of leading one bits. + uint32_t countLeadingZeros() const; + + /// countLeadingOnes - This function counts the number of contiguous 1 bits + /// in the high order bits. The count stops when the first 0 bit is reached. + /// @returns 0 if the high order bit is not set + /// @returns the number of 1 bits from the most significant to the least + /// @brief Count the number of leading one bits. + uint32_t countLeadingOnes() const; + + /// countTrailingZeros - This function is an APInt version of the + /// countTrailingZoers_{32,64} functions in MathExtras.h. It counts + /// the number of zeros from the least significant bit to the first one bit. + /// @returns getNumWords() * APINT_BITS_PER_WORD if the value is zero. + /// @returns the number of zeros from the least significant bit to the first + /// one bit. + /// @brief Count the number of trailing zero bits. + uint32_t countTrailingZeros() const; + + /// countPopulation - This function is an APInt version of the + /// countPopulation_{32,64} functions in MathExtras.h. It counts the number + /// of 1 bits in the APInt value. + /// @returns 0 if the value is zero. + /// @returns the number of set bits. + /// @brief Count the number of bits set. + uint32_t countPopulation() const; + + /// @} + /// @name Conversion Functions + /// @{ + + /// This is used internally to convert an APInt to a string. + /// @brief Converts an APInt to a std::string + std::string toString(uint8_t radix, bool wantSigned) const; + + /// Considers the APInt to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + /// @returns a character interpretation of the APInt + /// @brief Convert unsigned APInt to string representation. + inline std::string toString(uint8_t radix = 10) const { + return toString(radix, false); + } + + /// Considers the APInt to be unsigned and converts it into a string in the + /// radix given. The radix can be 2, 8, 10 or 16. + /// @returns a character interpretation of the APInt + /// @brief Convert unsigned APInt to string representation. + inline std::string toStringSigned(uint8_t radix = 10) const { + return toString(radix, true); + } + + /// @returns a byte-swapped representation of this APInt Value. + APInt byteSwap() const; + + /// @brief Converts this APInt to a double value. + double roundToDouble(bool isSigned) const; + + /// @brief Converts this unsigned APInt to a double value. + double roundToDouble() const { + return roundToDouble(false); + } + + /// @brief Converts this signed APInt to a double value. + double signedRoundToDouble() const { + return roundToDouble(true); + } + + /// The conversion does not do a translation from integer to double, it just + /// re-interprets the bits as a double. Note that it is valid to do this on + /// any bit width. Exactly 64 bits will be translated. + /// @brief Converts APInt bits to a double + double bitsToDouble() const { + union { + uint64_t I; + double D; + } T; + T.I = (isSingleWord() ? VAL : pVal[0]); + return T.D; + } + + /// The conversion does not do a translation from integer to float, it just + /// re-interprets the bits as a float. Note that it is valid to do this on + /// any bit width. Exactly 32 bits will be translated. + /// @brief Converts APInt bits to a double + float bitsToFloat() const { + union { + uint32_t I; + float F; + } T; + T.I = uint32_t((isSingleWord() ? VAL : pVal[0])); + return T.F; + } + + /// The conversion does not do a translation from double to integer, it just + /// re-interprets the bits of the double. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a double to APInt bits. + APInt& doubleToBits(double V) { + union { + uint64_t I; + double D; + } T; + T.D = V; + if (isSingleWord()) + VAL = T.I; + else + pVal[0] = T.I; + return clearUnusedBits(); + } + + /// The conversion does not do a translation from float to integer, it just + /// re-interprets the bits of the float. Note that it is valid to do this on + /// any bit width but bits from V may get truncated. + /// @brief Converts a float to APInt bits. + APInt& floatToBits(float V) { + union { + uint32_t I; + float F; + } T; + T.F = V; + if (isSingleWord()) + VAL = T.I; + else + pVal[0] = T.I; + return clearUnusedBits(); + } + + /// @} + /// @name Mathematics Operations + /// @{ + + /// @returns the floor log base 2 of this APInt. + inline uint32_t logBase2() const { + return BitWidth - 1 - countLeadingZeros(); + } + + /// @returns the log base 2 of this APInt if its an exact power of two, -1 + /// otherwise + inline int32_t exactLogBase2() const { + if (!isPowerOf2()) + return -1; + return logBase2(); + } + + /// @brief Compute the square root + APInt sqrt() const; + + /// If *this is < 0 then return -(*this), otherwise *this; + /// @brief Get the absolute value; + APInt abs() const { + if (isNegative()) + return -(*this); + return *this; + } + /// @} +}; + +inline bool operator==(uint64_t V1, const APInt& V2) { + return V2 == V1; +} + +inline bool operator!=(uint64_t V1, const APInt& V2) { + return V2 != V1; +} + +namespace APIntOps { + +/// @brief Determine the smaller of two APInts considered to be signed. +inline APInt smin(const APInt &A, const APInt &B) { + return A.slt(B) ? A : B; +} + +/// @brief Determine the larger of two APInts considered to be signed. +inline APInt smax(const APInt &A, const APInt &B) { + return A.sgt(B) ? A : B; +} + +/// @brief Determine the smaller of two APInts considered to be signed. +inline APInt umin(const APInt &A, const APInt &B) { + return A.ult(B) ? A : B; +} + +/// @brief Determine the larger of two APInts considered to be unsigned. +inline APInt umax(const APInt &A, const APInt &B) { + return A.ugt(B) ? A : B; +} + +/// @brief Check if the specified APInt has a N-bits integer value. +inline bool isIntN(uint32_t N, const APInt& APIVal) { + return APIVal.isIntN(N); +} + +/// @returns true if the argument APInt value is a sequence of ones +/// starting at the least significant bit with the remainder zero. +inline bool isMask(uint32_t numBits, const APInt& APIVal) { + return APIVal.getBoolValue() && ((APIVal + APInt(numBits,1)) & APIVal) == 0; +} + +/// @returns true if the argument APInt value contains a sequence of ones +/// with the remainder zero. +inline bool isShiftedMask(uint32_t numBits, const APInt& APIVal) { + return isMask(numBits, (APIVal - APInt(numBits,1)) | APIVal); +} + +/// @returns a byte-swapped representation of the specified APInt Value. +inline APInt byteSwap(const APInt& APIVal) { + return APIVal.byteSwap(); +} + +/// @returns the floor log base 2 of the specified APInt value. +inline uint32_t logBase2(const APInt& APIVal) { + return APIVal.logBase2(); +} + +/// GreatestCommonDivisor - This function returns the greatest common +/// divisor of the two APInt values using Enclid's algorithm. +/// @returns the greatest common divisor of Val1 and Val2 +/// @brief Compute GCD of two APInt values. +APInt GreatestCommonDivisor(const APInt& Val1, const APInt& Val2); + +/// Treats the APInt as an unsigned value for conversion purposes. +/// @brief Converts the given APInt to a double value. +inline double RoundAPIntToDouble(const APInt& APIVal) { + return APIVal.roundToDouble(); +} + +/// Treats the APInt as a signed value for conversion purposes. +/// @brief Converts the given APInt to a double value. +inline double RoundSignedAPIntToDouble(const APInt& APIVal) { + return APIVal.signedRoundToDouble(); +} + +/// @brief Converts the given APInt to a float vlalue. +inline float RoundAPIntToFloat(const APInt& APIVal) { + return float(RoundAPIntToDouble(APIVal)); +} + +/// Treast the APInt as a signed value for conversion purposes. +/// @brief Converts the given APInt to a float value. +inline float RoundSignedAPIntToFloat(const APInt& APIVal) { + return float(APIVal.signedRoundToDouble()); +} + +/// RoundDoubleToAPInt - This function convert a double value to an APInt value. +/// @brief Converts the given double value into a APInt. +APInt RoundDoubleToAPInt(double Double, uint32_t width); + +/// RoundFloatToAPInt - Converts a float value into an APInt value. +/// @brief Converts a float value into a APInt. +inline APInt RoundFloatToAPInt(float Float, uint32_t width) { + return RoundDoubleToAPInt(double(Float), width); +} + +/// Arithmetic right-shift the APInt by shiftAmt. +/// @brief Arithmetic right-shift function. +inline APInt ashr(const APInt& LHS, uint32_t shiftAmt) { + return LHS.ashr(shiftAmt); +} + +/// Logical right-shift the APInt by shiftAmt. +/// @brief Logical right-shift function. +inline APInt lshr(const APInt& LHS, uint32_t shiftAmt) { + return LHS.lshr(shiftAmt); +} + +/// Left-shift the APInt by shiftAmt. +/// @brief Left-shift function. +inline APInt shl(const APInt& LHS, uint32_t shiftAmt) { + return LHS.shl(shiftAmt); +} + +/// Signed divide APInt LHS by APInt RHS. +/// @brief Signed division function for APInt. +inline APInt sdiv(const APInt& LHS, const APInt& RHS) { + return LHS.sdiv(RHS); +} + +/// Unsigned divide APInt LHS by APInt RHS. +/// @brief Unsigned division function for APInt. +inline APInt udiv(const APInt& LHS, const APInt& RHS) { + return LHS.udiv(RHS); +} + +/// Signed remainder operation on APInt. +/// @brief Function for signed remainder operation. +inline APInt srem(const APInt& LHS, const APInt& RHS) { + return LHS.srem(RHS); +} + +/// Unsigned remainder operation on APInt. +/// @brief Function for unsigned remainder operation. +inline APInt urem(const APInt& LHS, const APInt& RHS) { + return LHS.urem(RHS); +} + +/// Performs multiplication on APInt values. +/// @brief Function for multiplication operation. +inline APInt mul(const APInt& LHS, const APInt& RHS) { + return LHS * RHS; +} + +/// Performs addition on APInt values. +/// @brief Function for addition operation. +inline APInt add(const APInt& LHS, const APInt& RHS) { + return LHS + RHS; +} + +/// Performs subtraction on APInt values. +/// @brief Function for subtraction operation. +inline APInt sub(const APInt& LHS, const APInt& RHS) { + return LHS - RHS; +} + +/// Performs bitwise AND operation on APInt LHS and +/// APInt RHS. +/// @brief Bitwise AND function for APInt. +inline APInt And(const APInt& LHS, const APInt& RHS) { + return LHS & RHS; +} + +/// Performs bitwise OR operation on APInt LHS and APInt RHS. +/// @brief Bitwise OR function for APInt. +inline APInt Or(const APInt& LHS, const APInt& RHS) { + return LHS | RHS; +} + +/// Performs bitwise XOR operation on APInt. +/// @brief Bitwise XOR function for APInt. +inline APInt Xor(const APInt& LHS, const APInt& RHS) { + return LHS ^ RHS; +} + +/// Performs a bitwise complement operation on APInt. +/// @brief Bitwise complement function. +inline APInt Not(const APInt& APIVal) { + return ~APIVal; +} + +} // End of APIntOps namespace + +} // End of llvm namespace + +#endif diff --git a/include/llvm/ADT/APSInt.h b/include/llvm/ADT/APSInt.h new file mode 100644 index 0000000..4eb4be2 --- /dev/null +++ b/include/llvm/ADT/APSInt.h @@ -0,0 +1,110 @@ +//===-- llvm/Support/APSInt.h - Arbitrary Precision Signed Int -*- C++ -*--===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the APSInt class, which is a simple class that +// represents an arbitrary sized integer that knows its signedness. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_APSINT_H +#define LLVM_APSINT_H + +#include "llvm/ADT/APInt.h" + +namespace llvm { + + +class APSInt : public APInt { + bool IsUnsigned; +public: + /// APSInt ctor - Create an APSInt with the specified width, default to + /// unsigned. + explicit APSInt(unsigned BitWidth) : APInt(BitWidth, 0), IsUnsigned(true) {} + APSInt(const APInt &I) : APInt(I), IsUnsigned(true) {} + + APSInt &operator=(const APSInt &RHS) { + APInt::operator=(RHS); + IsUnsigned = RHS.IsUnsigned; + return *this; + } + + APSInt &operator=(const APInt &RHS) { + // Retain our current sign. + APInt::operator=(RHS); + return *this; + } + + APSInt &operator=(uint64_t RHS) { + // Retain our current sign. + APInt::operator=(RHS); + return *this; + } + + // Query sign information. + bool isSigned() const { return !IsUnsigned; } + bool isUnsigned() const { return IsUnsigned; } + void setIsUnsigned(bool Val) { IsUnsigned = Val; } + void setIsSigned(bool Val) { IsUnsigned = !Val; } + + + const APSInt &operator%=(const APSInt &RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + if (IsUnsigned) + *this = urem(RHS); + else + *this = srem(RHS); + return *this; + } + const APSInt &operator/=(const APSInt &RHS) { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + if (IsUnsigned) + *this = udiv(RHS); + else + *this = sdiv(RHS); + return *this; + } + APSInt operator%(const APSInt &RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? urem(RHS) : srem(RHS); + } + APSInt operator/(const APSInt &RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? udiv(RHS) : sdiv(RHS); + } + + const APSInt &operator>>=(unsigned Amt) { + *this = *this >> Amt; + return *this; + } + + APSInt operator>>(unsigned Amt) const { + return IsUnsigned ? lshr(Amt) : ashr(Amt); + } + + inline bool operator<(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? ult(RHS) : slt(RHS); + } + inline bool operator>(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? ugt(RHS) : sgt(RHS); + } + inline bool operator<=(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? ule(RHS) : sle(RHS); + } + inline bool operator>=(const APSInt& RHS) const { + assert(IsUnsigned == RHS.IsUnsigned && "Signedness mismatch!"); + return IsUnsigned ? uge(RHS) : sge(RHS); + } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/ADT/BitVector.h b/include/llvm/ADT/BitVector.h new file mode 100644 index 0000000..243a810 --- /dev/null +++ b/include/llvm/ADT/BitVector.h @@ -0,0 +1,369 @@ +//===- llvm/ADT/BitVector.h - Bit vectors -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Evan Cheng and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the BitVector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_BITVECTOR_H +#define LLVM_ADT_BITVECTOR_H + +#include "llvm/Support/MathExtras.h" +#include <algorithm> +#include <cstdlib> +#include <cassert> + +namespace llvm { + +class BitVector { + typedef unsigned long BitWord; + + enum { BITWORD_SIZE = sizeof(BitWord) * 8 }; + + BitWord *Bits; // Actual bits. + unsigned Size; // Size of bitvector in bits. + unsigned Capacity; // Size of allocated memory in BitWord. + +public: + // Encapsulation of a single bit. + class reference { + friend class BitVector; + + BitWord *WordRef; + unsigned BitPos; + + reference(); // Undefined + + public: + reference(BitVector &b, unsigned Idx) { + WordRef = &b.Bits[Idx / BITWORD_SIZE]; + BitPos = Idx % BITWORD_SIZE; + } + + ~reference() {} + + reference& operator=(bool t) { + if (t) + *WordRef |= 1L << BitPos; + else + *WordRef &= ~(1L << BitPos); + return *this; + } + + operator bool() const { + return (*WordRef) & (1L << BitPos); + } + }; + + + /// BitVector default ctor - Creates an empty bitvector. + BitVector() : Size(0), Capacity(0) { + Bits = NULL; + } + + /// BitVector ctor - Creates a bitvector of specified number of bits. All + /// bits are initialized to the specified value. + explicit BitVector(unsigned s, bool t = false) : Size(s) { + Capacity = NumBitWords(s); + Bits = new BitWord[Capacity]; + init_words(Bits, Capacity, t); + if (t) + clear_unused_bits(); + } + + /// BitVector copy ctor. + BitVector(const BitVector &RHS) : Size(RHS.size()) { + if (Size == 0) { + Bits = NULL; + Capacity = 0; + return; + } + + Capacity = NumBitWords(RHS.size()); + Bits = new BitWord[Capacity]; + std::copy(RHS.Bits, &RHS.Bits[Capacity], Bits); + } + + ~BitVector() { + delete[] Bits; + } + + /// size - Returns the number of bits in this bitvector. + unsigned size() const { return Size; } + + /// count - Returns the number of bits which are set. + unsigned count() const { + unsigned NumBits = 0; + for (unsigned i = 0; i < NumBitWords(size()); ++i) + if (sizeof(BitWord) == 4) + NumBits += CountPopulation_32(Bits[i]); + else if (sizeof(BitWord) == 8) + NumBits += CountPopulation_64(Bits[i]); + else + assert(0 && "Unsupported!"); + return NumBits; + } + + /// any - Returns true if any bit is set. + bool any() const { + for (unsigned i = 0; i < NumBitWords(size()); ++i) + if (Bits[i] != 0) + return true; + return false; + } + + /// none - Returns true if none of the bits are set. + bool none() const { + return !any(); + } + + /// find_first - Returns the index of the first set bit, -1 if none + /// of the bits are set. + int find_first() const { + for (unsigned i = 0; i < NumBitWords(size()); ++i) + if (Bits[i] != 0) { + if (sizeof(BitWord) == 4) + return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]); + else if (sizeof(BitWord) == 8) + return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + else + assert(0 && "Unsupported!"); + } + return -1; + } + + /// find_next - Returns the index of the next set bit following the + /// "Prev" bit. Returns -1 if the next set bit is not found. + int find_next(unsigned Prev) const { + ++Prev; + if (Prev >= Size) + return -1; + + unsigned WordPos = Prev / BITWORD_SIZE; + unsigned BitPos = Prev % BITWORD_SIZE; + BitWord Copy = Bits[WordPos]; + // Mask off previous bits. + Copy &= ~0L << BitPos; + + if (Copy != 0) { + if (sizeof(BitWord) == 4) + return WordPos * BITWORD_SIZE + CountTrailingZeros_32(Copy); + else if (sizeof(BitWord) == 8) + return WordPos * BITWORD_SIZE + CountTrailingZeros_64(Copy); + else + assert(0 && "Unsupported!"); + } + + // Check subsequent words. + for (unsigned i = WordPos+1; i < NumBitWords(size()); ++i) + if (Bits[i] != 0) { + if (sizeof(BitWord) == 4) + return i * BITWORD_SIZE + CountTrailingZeros_32(Bits[i]); + else if (sizeof(BitWord) == 8) + return i * BITWORD_SIZE + CountTrailingZeros_64(Bits[i]); + else + assert(0 && "Unsupported!"); + } + return -1; + } + + /// clear - Clear all bits. + void clear() { + Size = 0; + } + + /// resize - Grow or shrink the bitvector. + void resize(unsigned N, bool t = false) { + if (N > Capacity * BITWORD_SIZE) { + unsigned OldCapacity = Capacity; + grow(N); + init_words(&Bits[OldCapacity], (Capacity-OldCapacity), t); + } + + // If we previously had no size, initialize the low word + if (Size == 0) + for (unsigned i = 0; i < Capacity; ++i) + Bits[i] = 0 - (unsigned)t; + + Size = N; + clear_unused_bits(); + } + + void reserve(unsigned N) { + if (N > Capacity * BITWORD_SIZE) + grow(N); + } + + // Set, reset, flip + BitVector &set() { + init_words(Bits, Capacity, true); + clear_unused_bits(); + return *this; + } + + BitVector &set(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] |= 1L << (Idx % BITWORD_SIZE); + return *this; + } + + BitVector &reset() { + init_words(Bits, Capacity, false); + return *this; + } + + BitVector &reset(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] &= ~(1L << (Idx % BITWORD_SIZE)); + return *this; + } + + BitVector &flip() { + for (unsigned i = 0; i < NumBitWords(size()); ++i) + Bits[i] = ~Bits[i]; + clear_unused_bits(); + return *this; + } + + BitVector &flip(unsigned Idx) { + Bits[Idx / BITWORD_SIZE] ^= 1L << (Idx % BITWORD_SIZE); + return *this; + } + + // No argument flip. + BitVector operator~() const { + return BitVector(*this).flip(); + } + + // Indexing. + reference operator[](unsigned Idx) { + return reference(*this, Idx); + } + + bool operator[](unsigned Idx) const { + BitWord Mask = 1L << (Idx % BITWORD_SIZE); + return (Bits[Idx / BITWORD_SIZE] & Mask) != 0; + } + + bool test(unsigned Idx) const { + return (*this)[Idx]; + } + + // Comparison operators. + bool operator==(const BitVector &RHS) const { + if (Size != RHS.Size) + return false; + + for (unsigned i = 0; i < NumBitWords(size()); ++i) + if (Bits[i] != RHS.Bits[i]) + return false; + return true; + } + + bool operator!=(const BitVector &RHS) const { + return !(*this == RHS); + } + + // Intersection, union, disjoint union. + BitVector operator&=(const BitVector &RHS) { + assert(Size == RHS.Size && "Illegal operation!"); + for (unsigned i = 0; i < NumBitWords(size()); ++i) + Bits[i] &= RHS.Bits[i]; + return *this; + } + + BitVector operator|=(const BitVector &RHS) { + assert(Size == RHS.Size && "Illegal operation!"); + for (unsigned i = 0; i < NumBitWords(size()); ++i) + Bits[i] |= RHS.Bits[i]; + return *this; + } + + BitVector operator^=(const BitVector &RHS) { + assert(Size == RHS.Size && "Illegal operation!"); + for (unsigned i = 0; i < NumBitWords(size()); ++i) + Bits[i] ^= RHS.Bits[i]; + return *this; + } + + // Assignment operator. + const BitVector &operator=(const BitVector &RHS) { + if (this == &RHS) return *this; + + Size = RHS.size(); + unsigned RHSWords = NumBitWords(Size); + if (Size <= Capacity * BITWORD_SIZE) { + std::copy(RHS.Bits, &RHS.Bits[RHSWords], Bits); + clear_unused_bits(); + return *this; + } + + // Grow the bitvector to have enough elements. + Capacity = NumBitWords(Size); + BitWord *NewBits = new BitWord[Capacity]; + std::copy(RHS.Bits, &RHS.Bits[RHSWords], NewBits); + + // Destroy the old bits. + delete[] Bits; + Bits = NewBits; + + return *this; + } + +private: + unsigned NumBitWords(unsigned S) const { + return (S + BITWORD_SIZE-1) / BITWORD_SIZE; + } + + // Clear the unused top bits in the high word. + void clear_unused_bits() { + unsigned ExtraBits = Size % BITWORD_SIZE; + if (ExtraBits) { + unsigned index = Size / BITWORD_SIZE; + Bits[index] &= ~(~0L << ExtraBits); + } + } + + void grow(unsigned NewSize) { + unsigned OldCapacity = Capacity; + Capacity = NumBitWords(NewSize); + BitWord *NewBits = new BitWord[Capacity]; + + // Copy the old bits over. + if (OldCapacity != 0) + std::copy(Bits, &Bits[OldCapacity], NewBits); + + // Destroy the old bits. + delete[] Bits; + Bits = NewBits; + } + + void init_words(BitWord *B, unsigned NumWords, bool t) { + memset(B, 0 - (int)t, NumWords*sizeof(BitWord)); + } +}; + +inline BitVector operator&(const BitVector &LHS, const BitVector &RHS) { + BitVector Result(LHS); + Result &= RHS; + return Result; +} + +inline BitVector operator|(const BitVector &LHS, const BitVector &RHS) { + BitVector Result(LHS); + Result |= RHS; + return Result; +} + +inline BitVector operator^(const BitVector &LHS, const BitVector &RHS) { + BitVector Result(LHS); + Result ^= RHS; + return Result; +} + +} // End llvm namespace +#endif diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h new file mode 100644 index 0000000..83edd64 --- /dev/null +++ b/include/llvm/ADT/DenseMap.h @@ -0,0 +1,355 @@ +//===- llvm/ADT/DenseMap.h - Dense probed hash table ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the DenseMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DENSEMAP_H +#define LLVM_ADT_DENSEMAP_H + +#include "llvm/Support/DataTypes.h" +#include <cassert> +#include <utility> + +namespace llvm { + +template<typename T> +struct DenseMapKeyInfo { + //static inline T getEmptyKey(); + //static inline T getTombstoneKey(); + //static unsigned getHashValue(const T &Val); + //static bool isPod() +}; + +// Provide DenseMapKeyInfo for all pointers. +template<typename T> +struct DenseMapKeyInfo<T*> { + static inline T* getEmptyKey() { return (T*)-1; } + static inline T* getTombstoneKey() { return (T*)-2; } + static unsigned getHashValue(const T *PtrVal) { + return (unsigned)((uintptr_t)PtrVal >> 4) ^ + (unsigned)((uintptr_t)PtrVal >> 9); + } + static bool isPod() { return true; } +}; + +template<typename KeyT, typename ValueT, + typename KeyInfoT = DenseMapKeyInfo<KeyT> > +class DenseMapIterator; +template<typename KeyT, typename ValueT, + typename KeyInfoT = DenseMapKeyInfo<KeyT> > +class DenseMapConstIterator; + +template<typename KeyT, typename ValueT, + typename KeyInfoT = DenseMapKeyInfo<KeyT> > +class DenseMap { + typedef std::pair<KeyT, ValueT> BucketT; + unsigned NumBuckets; + BucketT *Buckets; + + unsigned NumEntries; + unsigned NumTombstones; + DenseMap(const DenseMap &); // not implemented. +public: + explicit DenseMap(unsigned NumInitBuckets = 64) { + init(NumInitBuckets); + } + ~DenseMap() { + const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) { + if (P->first != EmptyKey && P->first != TombstoneKey) + P->second.~ValueT(); + P->first.~KeyT(); + } + delete[] (char*)Buckets; + } + + typedef DenseMapIterator<KeyT, ValueT, KeyInfoT> iterator; + typedef DenseMapConstIterator<KeyT, ValueT, KeyInfoT> const_iterator; + inline iterator begin() { + return iterator(Buckets, Buckets+NumBuckets); + } + inline iterator end() { + return iterator(Buckets+NumBuckets, Buckets+NumBuckets); + } + inline const_iterator begin() const { + return const_iterator(Buckets, Buckets+NumBuckets); + } + inline const_iterator end() const { + return const_iterator(Buckets+NumBuckets, Buckets+NumBuckets); + } + + bool empty() const { return NumEntries == 0; } + unsigned size() const { return NumEntries; } + + void clear() { + const KeyT EmptyKey = getEmptyKey(), TombstoneKey = getTombstoneKey(); + for (BucketT *P = Buckets, *E = Buckets+NumBuckets; P != E; ++P) { + if (P->first != EmptyKey && P->first != TombstoneKey) { + P->first = EmptyKey; + P->second.~ValueT(); + --NumEntries; + } + } + assert(NumEntries == 0 && "Node count imbalance!"); + NumTombstones = 0; + } + + /// count - Return true if the specified key is in the map. + bool count(const KeyT &Val) const { + BucketT *TheBucket; + return LookupBucketFor(Val, TheBucket); + } + + iterator find(const KeyT &Val) { + BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return iterator(TheBucket, Buckets+NumBuckets); + return end(); + } + const_iterator find(const KeyT &Val) const { + BucketT *TheBucket; + if (LookupBucketFor(Val, TheBucket)) + return const_iterator(TheBucket, Buckets+NumBuckets); + return end(); + } + + bool insert(const std::pair<KeyT, ValueT> &KV) { + BucketT *TheBucket; + if (LookupBucketFor(KV.first, TheBucket)) + return false; // Already in map. + + // Otherwise, insert the new element. + InsertIntoBucket(KV.first, KV.second, TheBucket); + return true; + } + + bool erase(const KeyT &Val) { + BucketT *TheBucket; + if (!LookupBucketFor(Val, TheBucket)) + return false; // not in map. + + TheBucket->second.~ValueT(); + TheBucket->first = getTombstoneKey(); + --NumEntries; + ++NumTombstones; + return true; + } + bool erase(iterator I) { + BucketT *TheBucket = &*I; + TheBucket->second.~ValueT(); + TheBucket->first = getTombstoneKey(); + --NumEntries; + ++NumTombstones; + return true; + } + + ValueT &operator[](const KeyT &Key) { + BucketT *TheBucket; + if (LookupBucketFor(Key, TheBucket)) + return TheBucket->second; + + return InsertIntoBucket(Key, ValueT(), TheBucket)->second; + } + +private: + BucketT *InsertIntoBucket(const KeyT &Key, const ValueT &Value, + BucketT *TheBucket) { + // If the load of the hash table is more than 3/4, or if fewer than 1/8 of + // the buckets are empty (meaning that many are filled with tombstones), + // grow the table. + // + // The later case is tricky. For example, if we had one empty bucket with + // tons of tombstones, failing lookups (e.g. for insertion) would have to + // probe almost the entire table until it found the empty bucket. If the + // table completely filled with tombstones, no lookup would ever succeed, + // causing infinite loops in lookup. + if (NumEntries*4 >= NumBuckets*3 || + NumBuckets-(NumEntries+NumTombstones) < NumBuckets/8) { + this->grow(); + LookupBucketFor(Key, TheBucket); + } + ++NumEntries; + + // If we are writing over a tombstone, remember this. + if (TheBucket->first != getEmptyKey()) + --NumTombstones; + + TheBucket->first = Key; + new (&TheBucket->second) ValueT(Value); + return TheBucket; + } + + static unsigned getHashValue(const KeyT &Val) { + return KeyInfoT::getHashValue(Val); + } + static const KeyT getEmptyKey() { + return KeyInfoT::getEmptyKey(); + } + static const KeyT getTombstoneKey() { + return KeyInfoT::getTombstoneKey(); + } + + /// LookupBucketFor - Lookup the appropriate bucket for Val, returning it in + /// FoundBucket. If the bucket contains the key and a value, this returns + /// true, otherwise it returns a bucket with an empty marker or tombstone and + /// returns false. + bool LookupBucketFor(const KeyT &Val, BucketT *&FoundBucket) const { + unsigned BucketNo = getHashValue(Val); + unsigned ProbeAmt = 1; + BucketT *BucketsPtr = Buckets; + + // FoundTombstone - Keep track of whether we find a tombstone while probing. + BucketT *FoundTombstone = 0; + const KeyT EmptyKey = getEmptyKey(); + const KeyT TombstoneKey = getTombstoneKey(); + assert(Val != EmptyKey && Val != TombstoneKey && + "Empty/Tombstone value shouldn't be inserted into map!"); + + while (1) { + BucketT *ThisBucket = BucketsPtr + (BucketNo & (NumBuckets-1)); + // Found Val's bucket? If so, return it. + if (ThisBucket->first == Val) { + FoundBucket = ThisBucket; + return true; + } + + // If we found an empty bucket, the key doesn't exist in the set. + // Insert it and return the default value. + if (ThisBucket->first == EmptyKey) { + // If we've already seen a tombstone while probing, fill it in instead + // of the empty bucket we eventually probed to. + if (FoundTombstone) ThisBucket = FoundTombstone; + FoundBucket = FoundTombstone ? FoundTombstone : ThisBucket; + return false; + } + + // If this is a tombstone, remember it. If Val ends up not in the map, we + // prefer to return it than something that would require more probing. + if (ThisBucket->first == TombstoneKey && !FoundTombstone) + FoundTombstone = ThisBucket; // Remember the first tombstone found. + + // Otherwise, it's a hash collision or a tombstone, continue quadratic + // probing. + BucketNo += ProbeAmt++; + } + } + + void init(unsigned InitBuckets) { + NumEntries = 0; + NumTombstones = 0; + NumBuckets = InitBuckets; + assert(InitBuckets && (InitBuckets & InitBuckets-1) == 0 && + "# initial buckets must be a power of two!"); + Buckets = (BucketT*)new char[sizeof(BucketT)*InitBuckets]; + // Initialize all the keys to EmptyKey. + const KeyT EmptyKey = getEmptyKey(); + for (unsigned i = 0; i != InitBuckets; ++i) + new (&Buckets[i].first) KeyT(EmptyKey); + } + + void grow() { + unsigned OldNumBuckets = NumBuckets; + BucketT *OldBuckets = Buckets; + + // Double the number of buckets. + NumBuckets <<= 1; + NumTombstones = 0; + Buckets = (BucketT*)new char[sizeof(BucketT)*NumBuckets]; + + // Initialize all the keys to EmptyKey. + const KeyT EmptyKey = getEmptyKey(); + for (unsigned i = 0, e = NumBuckets; i != e; ++i) + new (&Buckets[i].first) KeyT(EmptyKey); + + // Insert all the old elements. + const KeyT TombstoneKey = getTombstoneKey(); + for (BucketT *B = OldBuckets, *E = OldBuckets+OldNumBuckets; B != E; ++B) { + if (B->first != EmptyKey && B->first != TombstoneKey) { + // Insert the key/value into the new table. + BucketT *DestBucket; + bool FoundVal = LookupBucketFor(B->first, DestBucket); + FoundVal = FoundVal; // silence warning. + assert(!FoundVal && "Key already in new map?"); + DestBucket->first = B->first; + new (&DestBucket->second) ValueT(B->second); + + // Free the value. + B->second.~ValueT(); + } + B->first.~KeyT(); + } + + // Free the old table. + delete[] (char*)OldBuckets; + } +}; + +template<typename KeyT, typename ValueT, typename KeyInfoT> +class DenseMapIterator { + typedef std::pair<KeyT, ValueT> BucketT; +protected: + const BucketT *Ptr, *End; +public: + DenseMapIterator(const BucketT *Pos, const BucketT *E) : Ptr(Pos), End(E) { + AdvancePastEmptyBuckets(); + } + + std::pair<KeyT, ValueT> &operator*() const { + return *const_cast<BucketT*>(Ptr); + } + std::pair<KeyT, ValueT> *operator->() const { + return const_cast<BucketT*>(Ptr); + } + + bool operator==(const DenseMapIterator &RHS) const { + return Ptr == RHS.Ptr; + } + bool operator!=(const DenseMapIterator &RHS) const { + return Ptr != RHS.Ptr; + } + + inline DenseMapIterator& operator++() { // Preincrement + ++Ptr; + AdvancePastEmptyBuckets(); + return *this; + } + DenseMapIterator operator++(int) { // Postincrement + DenseMapIterator tmp = *this; ++*this; return tmp; + } + +private: + void AdvancePastEmptyBuckets() { + const KeyT Empty = KeyInfoT::getEmptyKey(); + const KeyT Tombstone = KeyInfoT::getTombstoneKey(); + + while (Ptr != End && (Ptr->first == Empty || Ptr->first == Tombstone)) + ++Ptr; + } +}; + +template<typename KeyT, typename ValueT, typename KeyInfoT> +class DenseMapConstIterator : public DenseMapIterator<KeyT, ValueT, KeyInfoT> { +public: + DenseMapConstIterator(const std::pair<KeyT, ValueT> *Pos, + const std::pair<KeyT, ValueT> *E) + : DenseMapIterator<KeyT, ValueT, KeyInfoT>(Pos, E) { + } + const std::pair<KeyT, ValueT> &operator*() const { + return *this->Ptr; + } + const std::pair<KeyT, ValueT> *operator->() const { + return this->Ptr; + } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/ADT/DepthFirstIterator.h b/include/llvm/ADT/DepthFirstIterator.h new file mode 100644 index 0000000..0cdd79b --- /dev/null +++ b/include/llvm/ADT/DepthFirstIterator.h @@ -0,0 +1,232 @@ +//===- llvm/ADT/DepthFirstIterator.h - Depth First iterator -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file builds on the ADT/GraphTraits.h file to build generic depth +// first graph iterator. This file exposes the following functions/types: +// +// df_begin/df_end/df_iterator +// * Normal depth-first iteration - visit a node and then all of its children. +// +// idf_begin/idf_end/idf_iterator +// * Depth-first iteration on the 'inverse' graph. +// +// df_ext_begin/df_ext_end/df_ext_iterator +// * Normal depth-first iteration - visit a node and then all of its children. +// This iterator stores the 'visited' set in an external set, which allows +// it to be more efficient, and allows external clients to use the set for +// other purposes. +// +// idf_ext_begin/idf_ext_end/idf_ext_iterator +// * Depth-first iteration on the 'inverse' graph. +// This iterator stores the 'visited' set in an external set, which allows +// it to be more efficient, and allows external clients to use the set for +// other purposes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_DEPTHFIRSTITERATOR_H +#define LLVM_ADT_DEPTHFIRSTITERATOR_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/iterator" +#include "llvm/ADT/SmallPtrSet.h" +#include <vector> +#include <set> + +namespace llvm { + +// df_iterator_storage - A private class which is used to figure out where to +// store the visited set. +template<class SetType, bool External> // Non-external set +class df_iterator_storage { +public: + SetType Visited; +}; + +template<class SetType> +class df_iterator_storage<SetType, true> { +public: + df_iterator_storage(SetType &VSet) : Visited(VSet) {} + df_iterator_storage(const df_iterator_storage &S) : Visited(S.Visited) {} + SetType &Visited; +}; + + +// Generic Depth First Iterator +template<class GraphT, +class SetType = llvm::SmallPtrSet<typename GraphTraits<GraphT>::NodeType*, 8>, + bool ExtStorage = false, class GT = GraphTraits<GraphT> > +class df_iterator : public forward_iterator<typename GT::NodeType, ptrdiff_t>, + public df_iterator_storage<SetType, ExtStorage> { + typedef forward_iterator<typename GT::NodeType, ptrdiff_t> super; + + typedef typename GT::NodeType NodeType; + typedef typename GT::ChildIteratorType ChildItTy; + + // VisitStack - Used to maintain the ordering. Top = current block + // First element is node pointer, second is the 'next child' to visit + std::vector<std::pair<NodeType *, ChildItTy> > VisitStack; +private: + inline df_iterator(NodeType *Node) { + this->Visited.insert(Node); + VisitStack.push_back(std::make_pair(Node, GT::child_begin(Node))); + } + inline df_iterator() { /* End is when stack is empty */ } + + inline df_iterator(NodeType *Node, SetType &S) + : df_iterator_storage<SetType, ExtStorage>(S) { + if (!S.count(Node)) { + this->Visited.insert(Node); + VisitStack.push_back(std::make_pair(Node, GT::child_begin(Node))); + } + } + inline df_iterator(SetType &S) + : df_iterator_storage<SetType, ExtStorage>(S) { + // End is when stack is empty + } + +public: + typedef typename super::pointer pointer; + typedef df_iterator<GraphT, SetType, ExtStorage, GT> _Self; + + // Provide static begin and end methods as our public "constructors" + static inline _Self begin(GraphT G) { + return _Self(GT::getEntryNode(G)); + } + static inline _Self end(GraphT G) { return _Self(); } + + // Static begin and end methods as our public ctors for external iterators + static inline _Self begin(GraphT G, SetType &S) { + return _Self(GT::getEntryNode(G), S); + } + static inline _Self end(GraphT G, SetType &S) { return _Self(S); } + + inline bool operator==(const _Self& x) const { + return VisitStack.size() == x.VisitStack.size() && + VisitStack == x.VisitStack; + } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline pointer operator*() const { + return VisitStack.back().first; + } + + // This is a nonstandard operator-> that dereferences the pointer an extra + // time... so that you can actually call methods ON the Node, because + // the contained type is a pointer. This allows BBIt->getTerminator() f.e. + // + inline NodeType *operator->() const { return operator*(); } + + inline _Self& operator++() { // Preincrement + do { + std::pair<NodeType *, ChildItTy> &Top = VisitStack.back(); + NodeType *Node = Top.first; + ChildItTy &It = Top.second; + + while (It != GT::child_end(Node)) { + NodeType *Next = *It++; + if (!this->Visited.count(Next)) { // Has our next sibling been visited? + // No, do it now. + this->Visited.insert(Next); + VisitStack.push_back(std::make_pair(Next, GT::child_begin(Next))); + return *this; + } + } + + // Oops, ran out of successors... go up a level on the stack. + VisitStack.pop_back(); + } while (!VisitStack.empty()); + return *this; + } + + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + + // nodeVisited - return true if this iterator has already visited the + // specified node. This is public, and will probably be used to iterate over + // nodes that a depth first iteration did not find: ie unreachable nodes. + // + inline bool nodeVisited(NodeType *Node) const { + return this->Visited.count(Node) != 0; + } +}; + + +// Provide global constructors that automatically figure out correct types... +// +template <class T> +df_iterator<T> df_begin(T G) { + return df_iterator<T>::begin(G); +} + +template <class T> +df_iterator<T> df_end(T G) { + return df_iterator<T>::end(G); +} + +// Provide global definitions of external depth first iterators... +template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeType*> > +struct df_ext_iterator : public df_iterator<T, SetTy, true> { + df_ext_iterator(const df_iterator<T, SetTy, true> &V) + : df_iterator<T, SetTy, true>(V) {} +}; + +template <class T, class SetTy> +df_ext_iterator<T, SetTy> df_ext_begin(T G, SetTy &S) { + return df_ext_iterator<T, SetTy>::begin(G, S); +} + +template <class T, class SetTy> +df_ext_iterator<T, SetTy> df_ext_end(T G, SetTy &S) { + return df_ext_iterator<T, SetTy>::end(G, S); +} + + +// Provide global definitions of inverse depth first iterators... +template <class T, + class SetTy = llvm::SmallPtrSet<typename GraphTraits<T>::NodeType*, 8>, + bool External = false> +struct idf_iterator : public df_iterator<Inverse<T>, SetTy, External> { + idf_iterator(const df_iterator<Inverse<T>, SetTy, External> &V) + : df_iterator<Inverse<T>, SetTy, External>(V) {} +}; + +template <class T> +idf_iterator<T> idf_begin(T G) { + return idf_iterator<T>::begin(G); +} + +template <class T> +idf_iterator<T> idf_end(T G){ + return idf_iterator<T>::end(G); +} + +// Provide global definitions of external inverse depth first iterators... +template <class T, class SetTy = std::set<typename GraphTraits<T>::NodeType*> > +struct idf_ext_iterator : public idf_iterator<T, SetTy, true> { + idf_ext_iterator(const idf_iterator<T, SetTy, true> &V) + : idf_iterator<T, SetTy, true>(V) {} + idf_ext_iterator(const df_iterator<Inverse<T>, SetTy, true> &V) + : idf_iterator<T, SetTy, true>(V) {} +}; + +template <class T, class SetTy> +idf_ext_iterator<T, SetTy> idf_ext_begin(T G, SetTy &S) { + return idf_ext_iterator<T, SetTy>::begin(G, S); +} + +template <class T, class SetTy> +idf_ext_iterator<T, SetTy> idf_ext_end(T G, SetTy &S) { + return idf_ext_iterator<T, SetTy>::end(G, S); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/EquivalenceClasses.h b/include/llvm/ADT/EquivalenceClasses.h new file mode 100644 index 0000000..7d305cb --- /dev/null +++ b/include/llvm/ADT/EquivalenceClasses.h @@ -0,0 +1,279 @@ +//===-- llvm/ADT/EquivalenceClasses.h - Generic Equiv. Classes --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Generic implementation of equivalence classes through the use Tarjan's +// efficient union-find algorithm. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_EQUIVALENCECLASSES_H +#define LLVM_ADT_EQUIVALENCECLASSES_H + +#include "llvm/ADT/iterator" +#include "llvm/Support/DataTypes.h" +#include <set> + +namespace llvm { + +/// EquivalenceClasses - This represents a collection of equivalence classes and +/// supports three efficient operations: insert an element into a class of its +/// own, union two classes, and find the class for a given element. In +/// addition to these modification methods, it is possible to iterate over all +/// of the equivalence classes and all of the elements in a class. +/// +/// This implementation is an efficient implementation that only stores one copy +/// of the element being indexed per entry in the set, and allows any arbitrary +/// type to be indexed (as long as it can be ordered with operator<). +/// +/// Here is a simple example using integers: +/// +/// EquivalenceClasses<int> EC; +/// EC.unionSets(1, 2); // insert 1, 2 into the same set +/// EC.insert(4); EC.insert(5); // insert 4, 5 into own sets +/// EC.unionSets(5, 1); // merge the set for 1 with 5's set. +/// +/// for (EquivalenceClasses<int>::iterator I = EC.begin(), E = EC.end(); +/// I != E; ++I) { // Iterate over all of the equivalence sets. +/// if (!I->isLeader()) continue; // Ignore non-leader sets. +/// for (EquivalenceClasses<int>::member_iterator MI = EC.member_begin(I); +/// MI != EC.member_end(); ++MI) // Loop over members in this set. +/// cerr << *MI << " "; // Print member. +/// cerr << "\n"; // Finish set. +/// } +/// +/// This example prints: +/// 4 +/// 5 1 2 +/// +template <class ElemTy> +class EquivalenceClasses { + /// ECValue - The EquivalenceClasses data structure is just a set of these. + /// Each of these represents a relation for a value. First it stores the + /// value itself, which provides the ordering that the set queries. Next, it + /// provides a "next pointer", which is used to enumerate all of the elements + /// in the unioned set. Finally, it defines either a "end of list pointer" or + /// "leader pointer" depending on whether the value itself is a leader. A + /// "leader pointer" points to the node that is the leader for this element, + /// if the node is not a leader. A "end of list pointer" points to the last + /// node in the list of members of this list. Whether or not a node is a + /// leader is determined by a bit stolen from one of the pointers. + class ECValue { + friend class EquivalenceClasses; + mutable const ECValue *Leader, *Next; + ElemTy Data; + // ECValue ctor - Start out with EndOfList pointing to this node, Next is + // Null, isLeader = true. + ECValue(const ElemTy &Elt) + : Leader(this), Next((ECValue*)(intptr_t)1), Data(Elt) {} + + const ECValue *getLeader() const { + if (isLeader()) return this; + if (Leader->isLeader()) return Leader; + // Path compression. + return Leader = Leader->getLeader(); + } + const ECValue *getEndOfList() const { + assert(isLeader() && "Cannot get the end of a list for a non-leader!"); + return Leader; + } + + void setNext(const ECValue *NewNext) const { + assert(getNext() == 0 && "Already has a next pointer!"); + Next = (const ECValue*)((intptr_t)NewNext | (intptr_t)isLeader()); + } + public: + ECValue(const ECValue &RHS) : Leader(this), Next((ECValue*)(intptr_t)1), + Data(RHS.Data) { + // Only support copying of singleton nodes. + assert(RHS.isLeader() && RHS.getNext() == 0 && "Not a singleton!"); + } + + bool operator<(const ECValue &UFN) const { return Data < UFN.Data; } + + bool isLeader() const { return (intptr_t)Next & 1; } + const ElemTy &getData() const { return Data; } + + const ECValue *getNext() const { + return (ECValue*)((intptr_t)Next & ~(intptr_t)1); + } + + template<typename T> + bool operator<(const T &Val) const { return Data < Val; } + }; + + /// TheMapping - This implicitly provides a mapping from ElemTy values to the + /// ECValues, it just keeps the key as part of the value. + std::set<ECValue> TheMapping; + +public: + EquivalenceClasses() {} + EquivalenceClasses(const EquivalenceClasses &RHS) { + operator=(RHS); + } + + const EquivalenceClasses &operator=(const EquivalenceClasses &RHS) { + TheMapping.clear(); + for (iterator I = RHS.begin(), E = RHS.end(); I != E; ++I) + if (I->isLeader()) { + member_iterator MI = RHS.member_begin(I); + member_iterator LeaderIt = member_begin(insert(*MI)); + for (++MI; MI != member_end(); ++MI) + unionSets(LeaderIt, member_begin(insert(*MI))); + } + return *this; + } + + //===--------------------------------------------------------------------===// + // Inspection methods + // + + /// iterator* - Provides a way to iterate over all values in the set. + typedef typename std::set<ECValue>::const_iterator iterator; + iterator begin() const { return TheMapping.begin(); } + iterator end() const { return TheMapping.end(); } + + bool empty() const { return TheMapping.empty(); } + + /// member_* Iterate over the members of an equivalence class. + /// + class member_iterator; + member_iterator member_begin(iterator I) const { + // Only leaders provide anything to iterate over. + return member_iterator(I->isLeader() ? &*I : 0); + } + member_iterator member_end() const { + return member_iterator(0); + } + + /// findValue - Return an iterator to the specified value. If it does not + /// exist, end() is returned. + iterator findValue(const ElemTy &V) const { + return TheMapping.find(V); + } + + /// getLeaderValue - Return the leader for the specified value that is in the + /// set. It is an error to call this method for a value that is not yet in + /// the set. For that, call getOrInsertLeaderValue(V). + const ElemTy &getLeaderValue(const ElemTy &V) const { + member_iterator MI = findLeader(V); + assert(MI != member_end() && "Value is not in the set!"); + return *MI; + } + + /// getOrInsertLeaderValue - Return the leader for the specified value that is + /// in the set. If the member is not in the set, it is inserted, then + /// returned. + const ElemTy &getOrInsertLeaderValue(const ElemTy &V) const { + member_iterator MI = findLeader(insert(V)); + assert(MI != member_end() && "Value is not in the set!"); + return *MI; + } + + /// getNumClasses - Return the number of equivalence classes in this set. + /// Note that this is a linear time operation. + unsigned getNumClasses() const { + unsigned NC = 0; + for (iterator I = begin(), E = end(); I != E; ++I) + if (I->isLeader()) ++NC; + return NC; + } + + + //===--------------------------------------------------------------------===// + // Mutation methods + + /// insert - Insert a new value into the union/find set, ignoring the request + /// if the value already exists. + iterator insert(const ElemTy &Data) { + return TheMapping.insert(Data).first; + } + + /// findLeader - Given a value in the set, return a member iterator for the + /// equivalence class it is in. This does the path-compression part that + /// makes union-find "union findy". This returns an end iterator if the value + /// is not in the equivalence class. + /// + member_iterator findLeader(iterator I) const { + if (I == TheMapping.end()) return member_end(); + return member_iterator(I->getLeader()); + } + member_iterator findLeader(const ElemTy &V) const { + return findLeader(TheMapping.find(V)); + } + + + /// union - Merge the two equivalence sets for the specified values, inserting + /// them if they do not already exist in the equivalence set. + member_iterator unionSets(const ElemTy &V1, const ElemTy &V2) { + iterator V1I = insert(V1), V2I = insert(V2); + return unionSets(findLeader(V1I), findLeader(V2I)); + } + member_iterator unionSets(member_iterator L1, member_iterator L2) { + assert(L1 != member_end() && L2 != member_end() && "Illegal inputs!"); + if (L1 == L2) return L1; // Unifying the same two sets, noop. + + // Otherwise, this is a real union operation. Set the end of the L1 list to + // point to the L2 leader node. + const ECValue &L1LV = *L1.Node, &L2LV = *L2.Node; + L1LV.getEndOfList()->setNext(&L2LV); + + // Update L1LV's end of list pointer. + L1LV.Leader = L2LV.getEndOfList(); + + // Clear L2's leader flag: + L2LV.Next = L2LV.getNext(); + + // L2's leader is now L1. + L2LV.Leader = &L1LV; + return L1; + } + + class member_iterator : public forward_iterator<ElemTy, ptrdiff_t> { + typedef forward_iterator<const ElemTy, ptrdiff_t> super; + const ECValue *Node; + friend class EquivalenceClasses; + public: + typedef size_t size_type; + typedef typename super::pointer pointer; + typedef typename super::reference reference; + + explicit member_iterator() {} + explicit member_iterator(const ECValue *N) : Node(N) {} + member_iterator(const member_iterator &I) : Node(I.Node) {} + + reference operator*() const { + assert(Node != 0 && "Dereferencing end()!"); + return Node->getData(); + } + reference operator->() const { return operator*(); } + + member_iterator &operator++() { + assert(Node != 0 && "++'d off the end of the list!"); + Node = Node->getNext(); + return *this; + } + + member_iterator operator++(int) { // postincrement operators. + member_iterator tmp = *this; + ++*this; + return tmp; + } + + bool operator==(const member_iterator &RHS) const { + return Node == RHS.Node; + } + bool operator!=(const member_iterator &RHS) const { + return Node != RHS.Node; + } + }; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/FoldingSet.h b/include/llvm/ADT/FoldingSet.h new file mode 100644 index 0000000..e6ded76 --- /dev/null +++ b/include/llvm/ADT/FoldingSet.h @@ -0,0 +1,258 @@ +//===-- llvm/ADT/FoldingSet.h - Uniquing Hash Set ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by James M. Laskey and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a hash set that can be used to remove duplication of nodes +// in a graph. This code was originally created by Chris Lattner for use with +// SelectionDAGCSEMap, but was isolated to provide use across the llvm code set. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_FOLDINGSET_H +#define LLVM_ADT_FOLDINGSET_H + +#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/SmallVector.h" +#include <string> + +namespace llvm { + +/// This folding set used for two purposes: +/// 1. Given information about a node we want to create, look up the unique +/// instance of the node in the set. If the node already exists, return +/// it, otherwise return the bucket it should be inserted into. +/// 2. Given a node that has already been created, remove it from the set. +/// +/// This class is implemented as a single-link chained hash table, where the +/// "buckets" are actually the nodes themselves (the next pointer is in the +/// node). The last node points back to the bucket to simplified node removal. +/// +/// Any node that is to be included in the folding set must be a subclass of +/// FoldingSetNode. The node class must also define a Profile method used to +/// establish the unique bits of data for the node. The Profile method is +/// passed a FoldingSetNodeID object which is used to gather the bits. Just +/// call one of the Add* functions defined in the FoldingSetImpl::NodeID class. +/// NOTE: That the folding set does not own the nodes and it is the +/// responsibility of the user to dispose of the nodes. +/// +/// Eg. +/// class MyNode : public FoldingSetNode { +/// private: +/// std::string Name; +/// unsigned Value; +/// public: +/// MyNode(const char *N, unsigned V) : Name(N), Value(V) {} +/// ... +/// void Profile(FoldingSetNodeID &ID) { +/// ID.AddString(Name); +/// ID.AddInteger(Value); +/// } +/// ... +/// }; +/// +/// To define the folding set itself use the FoldingSet template; +/// +/// Eg. +/// FoldingSet<MyNode> MyFoldingSet; +/// +/// Four public methods are available to manipulate the folding set; +/// +/// 1) If you have an existing node that you want add to the set but unsure +/// that the node might already exist then call; +/// +/// MyNode *M = MyFoldingSet.GetOrInsertNode(N); +/// +/// If The result is equal to the input then the node has been inserted. +/// Otherwise, the result is the node existing in the folding set, and the +/// input can be discarded (use the result instead.) +/// +/// 2) If you are ready to construct a node but want to check if it already +/// exists, then call FindNodeOrInsertPos with a FoldingSetNodeID of the bits to +/// check; +/// +/// FoldingSetNodeID ID; +/// ID.AddString(Name); +/// ID.AddInteger(Value); +/// void *InsertPoint; +/// +/// MyNode *M = MyFoldingSet.FindNodeOrInsertPos(ID, InsertPoint); +/// +/// If found then M with be non-NULL, else InsertPoint will point to where it +/// should be inserted using InsertNode. +/// +/// 3) If you get a NULL result from FindNodeOrInsertPos then you can as a new +/// node with FindNodeOrInsertPos; +/// +/// InsertNode(N, InsertPoint); +/// +/// 4) Finally, if you want to remove a node from the folding set call; +/// +/// bool WasRemoved = RemoveNode(N); +/// +/// The result indicates whether the node existed in the folding set. + + +//===----------------------------------------------------------------------===// +/// FoldingSetImpl - Implements the folding set functionality. The main +/// structure is an array of buckets. Each bucket is indexed by the hash of +/// the nodes it contains. The bucket itself points to the nodes contained +/// in the bucket via a singly linked list. The last node in the list points +/// back to the bucket to facilitate node removal. +/// +class FoldingSetImpl { +private: + /// Buckets - Array of bucket chains. + /// + void **Buckets; + + /// NumBuckets - Length of the Buckets array. Always a power of 2. + /// + unsigned NumBuckets; + + /// NumNodes - Number of nodes in the folding set. Growth occurs when NumNodes + /// is greater than twice the number of buckets. + unsigned NumNodes; + +public: + FoldingSetImpl(unsigned Log2InitSize = 6); + virtual ~FoldingSetImpl(); + + // Forward declaration. + class Node; + + //===--------------------------------------------------------------------===// + /// NodeID - This class is used to gather all the unique data bits of a + /// node. When all the bits are gathered this class is used to produce a + /// hash value for the node. + /// + class NodeID { + /// Bits - Vector of all the data bits that make the node unique. + /// Use a SmallVector to avoid a heap allocation in the common case. + SmallVector<unsigned, 32> Bits; + + public: + NodeID() {} + + /// getRawData - Return the ith entry in the Bits data. + /// + unsigned getRawData(unsigned i) const { + return Bits[i]; + } + + /// Add* - Add various data types to Bit data. + /// + void AddPointer(const void *Ptr); + void AddInteger(signed I); + void AddInteger(unsigned I); + void AddInteger(uint64_t I); + void AddFloat(float F); + void AddDouble(double D); + void AddString(const std::string &String); + + /// ComputeHash - Compute a strong hash value for this NodeID, used to + /// lookup the node in the FoldingSetImpl. + unsigned ComputeHash() const; + + /// operator== - Used to compare two nodes to each other. + /// + bool operator==(const NodeID &RHS) const; + }; + + //===--------------------------------------------------------------------===// + /// Node - This class is used to maintain the singly linked bucket list in + /// a folding set. + /// + class Node { + private: + // NextInFoldingSetBucket - next link in the bucket list. + void *NextInFoldingSetBucket; + + public: + + Node() : NextInFoldingSetBucket(0) {} + + // Accessors + void *getNextInBucket() const { return NextInFoldingSetBucket; } + void SetNextInBucket(void *N) { NextInFoldingSetBucket = N; } + }; + + /// RemoveNode - Remove a node from the folding set, returning true if one + /// was removed or false if the node was not in the folding set. + bool RemoveNode(Node *N); + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' and return + /// it instead. + Node *GetOrInsertNode(Node *N); + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, + /// return it. If not, return the insertion token that will make insertion + /// faster. + Node *FindNodeOrInsertPos(const NodeID &ID, void *&InsertPos); + + /// InsertNode - Insert the specified node into the folding set, knowing that + /// it is not already in the folding set. InsertPos must be obtained from + /// FindNodeOrInsertPos. + void InsertNode(Node *N, void *InsertPos); + +private: + + /// GrowHashTable - Double the size of the hash table and rehash everything. + /// + void GrowHashTable(); + +protected: + + /// GetNodeProfile - Instantiations of the FoldingSet template implement + /// this function to gather data bits for the given node. + virtual void GetNodeProfile(NodeID &ID, Node *N) const = 0; +}; + +// Convenience types to hide the implementation of the folding set. +typedef FoldingSetImpl::Node FoldingSetNode; +typedef FoldingSetImpl::NodeID FoldingSetNodeID; + +//===----------------------------------------------------------------------===// +/// FoldingSet - This template class is used to instantiate a specialized +/// implementation of the folding set to the node class T. T must be a +/// subclass of FoldingSetNode and implement a Profile function. +/// +template<class T> class FoldingSet : public FoldingSetImpl { +private: + /// GetNodeProfile - Each instantiatation of the FoldingSet needs to provide a + /// way to convert nodes into a unique specifier. + virtual void GetNodeProfile(NodeID &ID, Node *N) const { + T *TN = static_cast<T *>(N); + TN->Profile(ID); + } + +public: + FoldingSet(unsigned Log2InitSize = 6) + : FoldingSetImpl(Log2InitSize) + {} + + /// GetOrInsertNode - If there is an existing simple Node exactly + /// equal to the specified node, return it. Otherwise, insert 'N' and + /// return it instead. + T *GetOrInsertNode(Node *N) { + return static_cast<T *>(FoldingSetImpl::GetOrInsertNode(N)); + } + + /// FindNodeOrInsertPos - Look up the node specified by ID. If it exists, + /// return it. If not, return the insertion token that will make insertion + /// faster. + T *FindNodeOrInsertPos(const FoldingSetNodeID &ID, void *&InsertPos) { + return static_cast<T *>(FoldingSetImpl::FindNodeOrInsertPos(ID, InsertPos)); + } +}; + +} // End of namespace llvm. + + +#endif + diff --git a/include/llvm/ADT/GraphTraits.h b/include/llvm/ADT/GraphTraits.h new file mode 100644 index 0000000..99a69b8 --- /dev/null +++ b/include/llvm/ADT/GraphTraits.h @@ -0,0 +1,83 @@ +//===-- llvm/ADT/GraphTraits.h - Graph traits template ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the little GraphTraits<X> template class that should be +// specialized by classes that want to be iteratable by generic graph iterators. +// +// This file also defines the marker class Inverse that is used to iterate over +// graphs in a graph defined, inverse ordering... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_GRAPHTRAITS_H +#define LLVM_ADT_GRAPHTRAITS_H + +namespace llvm { + +// GraphTraits - This class should be specialized by different graph types... +// which is why the default version is empty. +// +template<class GraphType> +struct GraphTraits { + // Elements to provide: + + // typedef NodeType - Type of Node in the graph + // typedef ChildIteratorType - Type used to iterate over children in graph + + // static NodeType *getEntryNode(GraphType *) + // Return the entry node of the graph + + // static ChildIteratorType child_begin(NodeType *) + // static ChildIteratorType child_end (NodeType *) + // Return iterators that point to the beginning and ending of the child + // node list for the specified node. + // + + + // typedef ...iterator nodes_iterator; + // static nodes_iterator nodes_begin(GraphType *G) + // static nodes_iterator nodes_end (GraphType *G) + // + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + + + // If anyone tries to use this class without having an appropriate + // specialization, make an error. If you get this error, it's because you + // need to include the appropriate specialization of GraphTraits<> for your + // graph, or you need to define it for a new graph type. Either that or + // your argument to XXX_begin(...) is unknown or needs to have the proper .h + // file #include'd. + // + typedef typename GraphType::UnknownGraphTypeError NodeType; +}; + + +// Inverse - This class is used as a little marker class to tell the graph +// iterator to iterate over the graph in a graph defined "Inverse" ordering. +// Not all graphs define an inverse ordering, and if they do, it depends on +// the graph exactly what that is. Here's an example of usage with the +// df_iterator: +// +// idf_iterator<Method*> I = idf_begin(M), E = idf_end(M); +// for (; I != E; ++I) { ... } +// +// Which is equivalent to: +// df_iterator<Inverse<Method*> > I = idf_begin(M), E = idf_end(M); +// for (; I != E; ++I) { ... } +// +template <class GraphType> +struct Inverse { + GraphType &Graph; + + inline Inverse(GraphType &G) : Graph(G) {} +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/HashExtras.h b/include/llvm/ADT/HashExtras.h new file mode 100644 index 0000000..9993248 --- /dev/null +++ b/include/llvm/ADT/HashExtras.h @@ -0,0 +1,41 @@ +//===-- llvm/ADT/HashExtras.h - Useful functions for STL hash ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains some templates that are useful if you are working with the +// STL Hashed containers. +// +// No library is required when using these functinons. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_HASHEXTRAS_H +#define LLVM_ADT_HASHEXTRAS_H + +#include "llvm/ADT/hash_map" +#include <string> + +// Cannot specialize hash template from outside of the std namespace. +namespace HASH_NAMESPACE { + +// Provide a hash function for arbitrary pointers... +template <class T> struct hash<T *> { + inline size_t operator()(const T *Val) const { + return reinterpret_cast<size_t>(Val); + } +}; + +template <> struct hash<std::string> { + size_t operator()(std::string const &str) const { + return hash<char const *>()(str.c_str()); + } +}; + +} // End namespace std + +#endif diff --git a/include/llvm/ADT/IndexedMap.h b/include/llvm/ADT/IndexedMap.h new file mode 100644 index 0000000..bc38fdd --- /dev/null +++ b/include/llvm/ADT/IndexedMap.h @@ -0,0 +1,75 @@ +//===- llvm/ADT/IndexedMap.h - An index map implementation ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements an indexed map. The index map template takes two +// types. The first is the mapped type and the second is a functor +// that maps its argument to a size_t. On instantiation a "null" value +// can be provided to be used as a "does not exist" indicator in the +// map. A member function grow() is provided that given the value of +// the maximally indexed key (the argument of the functor) makes sure +// the map has enough space for it. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_INDEXEDMAP_H +#define LLVM_ADT_INDEXEDMAP_H + +#include <functional> +#include <vector> +#include <cassert> + +namespace llvm { + + struct IdentityFunctor : std::unary_function<unsigned, unsigned> { + unsigned operator()(unsigned Index) const { + return Index; + } + }; + + template <typename T, typename ToIndexT = IdentityFunctor> + class IndexedMap { + typedef typename ToIndexT::argument_type IndexT; + typedef std::vector<T> StorageT; + StorageT storage_; + T nullVal_; + ToIndexT toIndex_; + + public: + IndexedMap() : nullVal_(T()) { } + + explicit IndexedMap(const T& val) : nullVal_(val) { } + + typename StorageT::reference operator[](IndexT n) { + assert(toIndex_(n) < storage_.size() && "index out of bounds!"); + return storage_[toIndex_(n)]; + } + + typename StorageT::const_reference operator[](IndexT n) const { + assert(toIndex_(n) < storage_.size() && "index out of bounds!"); + return storage_[toIndex_(n)]; + } + + void clear() { + storage_.clear(); + } + + void grow(IndexT n) { + unsigned NewSize = toIndex_(n) + 1; + if (NewSize > storage_.size()) + storage_.resize(NewSize, nullVal_); + } + + typename StorageT::size_type size() const { + return storage_.size(); + } + }; + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/PostOrderIterator.h b/include/llvm/ADT/PostOrderIterator.h new file mode 100644 index 0000000..16f0865 --- /dev/null +++ b/include/llvm/ADT/PostOrderIterator.h @@ -0,0 +1,230 @@ +//===- llvm/ADT/PostOrderIterator.h - PostOrder iterator --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file builds on the ADT/GraphTraits.h file to build a generic graph +// post order iterator. This should work over any graph type that has a +// GraphTraits specialization. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_POSTORDERITERATOR_H +#define LLVM_ADT_POSTORDERITERATOR_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/iterator" +#include <stack> +#include <set> +#include <vector> + +namespace llvm { + +template<class SetType, bool External> // Non-external set +class po_iterator_storage { +public: + SetType Visited; +}; + +template<class SetType> +class po_iterator_storage<SetType, true> { +public: + po_iterator_storage(SetType &VSet) : Visited(VSet) {} + po_iterator_storage(const po_iterator_storage &S) : Visited(S.Visited) {} + SetType &Visited; +}; + +template<class GraphT, + class SetType = std::set<typename GraphTraits<GraphT>::NodeType*>, + bool ExtStorage = false, + class GT = GraphTraits<GraphT> > +class po_iterator : public forward_iterator<typename GT::NodeType, ptrdiff_t>, + public po_iterator_storage<SetType, ExtStorage> { + typedef forward_iterator<typename GT::NodeType, ptrdiff_t> super; + typedef typename GT::NodeType NodeType; + typedef typename GT::ChildIteratorType ChildItTy; + + // VisitStack - Used to maintain the ordering. Top = current block + // First element is basic block pointer, second is the 'next child' to visit + std::stack<std::pair<NodeType *, ChildItTy> > VisitStack; + + void traverseChild() { + while (VisitStack.top().second != GT::child_end(VisitStack.top().first)) { + NodeType *BB = *VisitStack.top().second++; + if (!this->Visited.count(BB)) { // If the block is not visited... + this->Visited.insert(BB); + VisitStack.push(std::make_pair(BB, GT::child_begin(BB))); + } + } + } + + inline po_iterator(NodeType *BB) { + this->Visited.insert(BB); + VisitStack.push(std::make_pair(BB, GT::child_begin(BB))); + traverseChild(); + } + inline po_iterator() {} // End is when stack is empty. + + inline po_iterator(NodeType *BB, SetType &S) : + po_iterator_storage<SetType, ExtStorage>(&S) { + if(!S.count(BB)) { + this->Visited.insert(BB); + VisitStack.push(std::make_pair(BB, GT::child_begin(BB))); + traverseChild(); + } + } + + inline po_iterator(SetType &S) : + po_iterator_storage<SetType, ExtStorage>(&S) { + } // End is when stack is empty. +public: + typedef typename super::pointer pointer; + typedef po_iterator<GraphT, SetType, ExtStorage, GT> _Self; + + // Provide static "constructors"... + static inline _Self begin(GraphT G) { return _Self(GT::getEntryNode(G)); } + static inline _Self end (GraphT G) { return _Self(); } + + static inline _Self begin(GraphT G, SetType &S) { + return _Self(GT::getEntryNode(G), S); + } + static inline _Self end (GraphT G, SetType &S) { return _Self(S); } + + inline bool operator==(const _Self& x) const { + return VisitStack == x.VisitStack; + } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline pointer operator*() const { + return VisitStack.top().first; + } + + // This is a nonstandard operator-> that dereferences the pointer an extra + // time... so that you can actually call methods ON the BasicBlock, because + // the contained type is a pointer. This allows BBIt->getTerminator() f.e. + // + inline NodeType *operator->() const { return operator*(); } + + inline _Self& operator++() { // Preincrement + VisitStack.pop(); + if (!VisitStack.empty()) + traverseChild(); + return *this; + } + + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } +}; + +// Provide global constructors that automatically figure out correct types... +// +template <class T> +po_iterator<T> po_begin(T G) { return po_iterator<T>::begin(G); } +template <class T> +po_iterator<T> po_end (T G) { return po_iterator<T>::end(G); } + +// Provide global definitions of external postorder iterators... +template<class T, class SetType=std::set<typename GraphTraits<T>::NodeType*> > +struct po_ext_iterator : public po_iterator<T, SetType, true> { + po_ext_iterator(const po_iterator<T, SetType, true> &V) : + po_iterator<T, SetType, true>(V) {} +}; + +template<class T, class SetType> +po_ext_iterator<T, SetType> po_ext_begin(T G, SetType &S) { + return po_ext_iterator<T, SetType>::begin(G, S); +} + +template<class T, class SetType> +po_ext_iterator<T, SetType> po_ext_end(T G, SetType &S) { + return po_ext_iterator<T, SetType>::end(G, S); +} + +// Provide global definitions of inverse post order iterators... +template <class T, + class SetType = std::set<typename GraphTraits<T>::NoddeType*>, + bool External = false> +struct ipo_iterator : public po_iterator<Inverse<T>, SetType, External > { + ipo_iterator(const po_iterator<Inverse<T>, SetType, External> &V) : + po_iterator<Inverse<T>, SetType, External> (V) {} +}; + +template <class T> +ipo_iterator<T> ipo_begin(T G, bool Reverse = false) { + return ipo_iterator<T>::begin(G, Reverse); +} + +template <class T> +ipo_iterator<T> ipo_end(T G){ + return ipo_iterator<T>::end(G); +} + +//Provide global definitions of external inverse postorder iterators... +template <class T, class SetType = std::set<typename GraphTraits<T>::NodeType*> > +struct ipo_ext_iterator : public ipo_iterator<T, SetType, true> { + ipo_ext_iterator(const ipo_iterator<T, SetType, true> &V) : + ipo_iterator<T, SetType, true>(&V) {} + ipo_ext_iterator(const po_iterator<Inverse<T>, SetType, true> &V) : + ipo_iterator<T, SetType, true>(&V) {} +}; + +template <class T, class SetType> +ipo_ext_iterator<T, SetType> ipo_ext_begin(T G, SetType &S) { + return ipo_ext_iterator<T, SetType>::begin(G, S); +} + +template <class T, class SetType> +ipo_ext_iterator<T, SetType> ipo_ext_end(T G, SetType &S) { + return ipo_ext_iterator<T, SetType>::end(G, S); +} + +//===--------------------------------------------------------------------===// +// Reverse Post Order CFG iterator code +//===--------------------------------------------------------------------===// +// +// This is used to visit basic blocks in a method in reverse post order. This +// class is awkward to use because I don't know a good incremental algorithm to +// computer RPO from a graph. Because of this, the construction of the +// ReversePostOrderTraversal object is expensive (it must walk the entire graph +// with a postorder iterator to build the data structures). The moral of this +// story is: Don't create more ReversePostOrderTraversal classes than necessary. +// +// This class should be used like this: +// { +// ReversePostOrderTraversal<Function*> RPOT(FuncPtr); // Expensive to create +// for (rpo_iterator I = RPOT.begin(); I != RPOT.end(); ++I) { +// ... +// } +// for (rpo_iterator I = RPOT.begin(); I != RPOT.end(); ++I) { +// ... +// } +// } +// + +template<class GraphT, class GT = GraphTraits<GraphT> > +class ReversePostOrderTraversal { + typedef typename GT::NodeType NodeType; + std::vector<NodeType*> Blocks; // Block list in normal PO order + inline void Initialize(NodeType *BB) { + copy(po_begin(BB), po_end(BB), back_inserter(Blocks)); + } +public: + typedef typename std::vector<NodeType*>::reverse_iterator rpo_iterator; + + inline ReversePostOrderTraversal(GraphT G) { + Initialize(GT::getEntryNode(G)); + } + + // Because we want a reverse post order, use reverse iterators from the vector + inline rpo_iterator begin() { return Blocks.rbegin(); } + inline rpo_iterator end() { return Blocks.rend(); } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/SCCIterator.h b/include/llvm/ADT/SCCIterator.h new file mode 100644 index 0000000..6b1260d --- /dev/null +++ b/include/llvm/ADT/SCCIterator.h @@ -0,0 +1,199 @@ +//===-- Support/SCCIterator.h - Strongly Connected Comp. Iter. --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected +// components (SCCs) of a graph in O(N+E) time using Tarjan's DFS algorithm. +// +// The SCC iterator has the important property that if a node in SCC S1 has an +// edge to a node in SCC S2, then it visits S1 *after* S2. +// +// To visit S1 *before* S2, use the scc_iterator on the Inverse graph. +// (NOTE: This requires some simple wrappers and is not supported yet.) +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SCCITERATOR_H +#define LLVM_ADT_SCCITERATOR_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/iterator" +#include <vector> +#include <map> + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// +/// scc_iterator - Enumerate the SCCs of a directed graph, in +/// reverse topological order of the SCC DAG. +/// +template<class GraphT, class GT = GraphTraits<GraphT> > +class scc_iterator + : public forward_iterator<std::vector<typename GT::NodeType>, ptrdiff_t> { + typedef typename GT::NodeType NodeType; + typedef typename GT::ChildIteratorType ChildItTy; + typedef std::vector<NodeType*> SccTy; + typedef forward_iterator<SccTy, ptrdiff_t> super; + typedef typename super::reference reference; + typedef typename super::pointer pointer; + + // The visit counters used to detect when a complete SCC is on the stack. + // visitNum is the global counter. + // nodeVisitNumbers are per-node visit numbers, also used as DFS flags. + unsigned visitNum; + std::map<NodeType *, unsigned> nodeVisitNumbers; + + // SCCNodeStack - Stack holding nodes of the SCC. + std::vector<NodeType *> SCCNodeStack; + + // CurrentSCC - The current SCC, retrieved using operator*(). + SccTy CurrentSCC; + + // VisitStack - Used to maintain the ordering. Top = current block + // First element is basic block pointer, second is the 'next child' to visit + std::vector<std::pair<NodeType *, ChildItTy> > VisitStack; + + // MinVistNumStack - Stack holding the "min" values for each node in the DFS. + // This is used to track the minimum uplink values for all children of + // the corresponding node on the VisitStack. + std::vector<unsigned> MinVisitNumStack; + + // A single "visit" within the non-recursive DFS traversal. + void DFSVisitOne(NodeType* N) { + ++visitNum; // Global counter for the visit order + nodeVisitNumbers[N] = visitNum; + SCCNodeStack.push_back(N); + MinVisitNumStack.push_back(visitNum); + VisitStack.push_back(std::make_pair(N, GT::child_begin(N))); + //DOUT << "TarjanSCC: Node " << N << + // " : visitNum = " << visitNum << "\n"; + } + + // The stack-based DFS traversal; defined below. + void DFSVisitChildren() { + assert(!VisitStack.empty()); + while (VisitStack.back().second != GT::child_end(VisitStack.back().first)) { + // TOS has at least one more child so continue DFS + NodeType *childN = *VisitStack.back().second++; + if (!nodeVisitNumbers.count(childN)) { + // this node has never been seen + DFSVisitOne(childN); + } else { + unsigned childNum = nodeVisitNumbers[childN]; + if (MinVisitNumStack.back() > childNum) + MinVisitNumStack.back() = childNum; + } + } + } + + // Compute the next SCC using the DFS traversal. + void GetNextSCC() { + assert(VisitStack.size() == MinVisitNumStack.size()); + CurrentSCC.clear(); // Prepare to compute the next SCC + while (!VisitStack.empty()) { + DFSVisitChildren(); + assert(VisitStack.back().second ==GT::child_end(VisitStack.back().first)); + NodeType* visitingN = VisitStack.back().first; + unsigned minVisitNum = MinVisitNumStack.back(); + VisitStack.pop_back(); + MinVisitNumStack.pop_back(); + if (!MinVisitNumStack.empty() && MinVisitNumStack.back() > minVisitNum) + MinVisitNumStack.back() = minVisitNum; + + //DOUT << "TarjanSCC: Popped node " << visitingN << + // " : minVisitNum = " << minVisitNum << "; Node visit num = " << + // nodeVisitNumbers[visitingN] << "\n"; + + if (minVisitNum == nodeVisitNumbers[visitingN]) { + // A full SCC is on the SCCNodeStack! It includes all nodes below + // visitingN on the stack. Copy those nodes to CurrentSCC, + // reset their minVisit values, and return (this suspends + // the DFS traversal till the next ++). + do { + CurrentSCC.push_back(SCCNodeStack.back()); + SCCNodeStack.pop_back(); + nodeVisitNumbers[CurrentSCC.back()] = ~0U; + } while (CurrentSCC.back() != visitingN); + return; + } + } + } + + inline scc_iterator(NodeType *entryN) : visitNum(0) { + DFSVisitOne(entryN); + GetNextSCC(); + } + inline scc_iterator() { /* End is when DFS stack is empty */ } + +public: + typedef scc_iterator<GraphT, GT> _Self; + + // Provide static "constructors"... + static inline _Self begin(GraphT& G) { return _Self(GT::getEntryNode(G)); } + static inline _Self end (GraphT& G) { return _Self(); } + + // Direct loop termination test (I.fini() is more efficient than I == end()) + inline bool fini() const { + assert(!CurrentSCC.empty() || VisitStack.empty()); + return CurrentSCC.empty(); + } + + inline bool operator==(const _Self& x) const { + return VisitStack == x.VisitStack && CurrentSCC == x.CurrentSCC; + } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + // Iterator traversal: forward iteration only + inline _Self& operator++() { // Preincrement + GetNextSCC(); + return *this; + } + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + + // Retrieve a reference to the current SCC + inline const SccTy &operator*() const { + assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); + return CurrentSCC; + } + inline SccTy &operator*() { + assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); + return CurrentSCC; + } + + // hasLoop() -- Test if the current SCC has a loop. If it has more than one + // node, this is trivially true. If not, it may still contain a loop if the + // node has an edge back to itself. + bool hasLoop() const { + assert(!CurrentSCC.empty() && "Dereferencing END SCC iterator!"); + if (CurrentSCC.size() > 1) return true; + NodeType *N = CurrentSCC.front(); + for (ChildItTy CI = GT::child_begin(N), CE=GT::child_end(N); CI != CE; ++CI) + if (*CI == N) + return true; + return false; + } +}; + + +// Global constructor for the SCC iterator. +template <class T> +scc_iterator<T> scc_begin(T G) { + return scc_iterator<T>::begin(G); +} + +template <class T> +scc_iterator<T> scc_end(T G) { + return scc_iterator<T>::end(G); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/STLExtras.h b/include/llvm/ADT/STLExtras.h new file mode 100644 index 0000000..14137e3 --- /dev/null +++ b/include/llvm/ADT/STLExtras.h @@ -0,0 +1,204 @@ +//===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains some templates that are useful if you are working with the +// STL at all. +// +// No library is required when using these functinons. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STLEXTRAS_H +#define LLVM_ADT_STLEXTRAS_H + +#include <functional> +#include <utility> // for std::pair +#include "llvm/ADT/iterator" + +namespace llvm { + +//===----------------------------------------------------------------------===// +// Extra additions to <functional> +//===----------------------------------------------------------------------===// + +template<class Ty> +struct greater_ptr : public std::binary_function<Ty, Ty, bool> { + bool operator()(const Ty* left, const Ty* right) const { + return *right < *left; + } +}; + +// deleter - Very very very simple method that is used to invoke operator +// delete on something. It is used like this: +// +// for_each(V.begin(), B.end(), deleter<Interval>); +// +template <class T> +static inline void deleter(T *Ptr) { + delete Ptr; +} + + + +//===----------------------------------------------------------------------===// +// Extra additions to <iterator> +//===----------------------------------------------------------------------===// + +// mapped_iterator - This is a simple iterator adapter that causes a function to +// be dereferenced whenever operator* is invoked on the iterator. +// +template <class RootIt, class UnaryFunc> +class mapped_iterator { + RootIt current; + UnaryFunc Fn; +public: + typedef typename std::iterator_traits<RootIt>::iterator_category + iterator_category; + typedef typename std::iterator_traits<RootIt>::difference_type + difference_type; + typedef typename UnaryFunc::result_type value_type; + + typedef void pointer; + //typedef typename UnaryFunc::result_type *pointer; + typedef void reference; // Can't modify value returned by fn + + typedef RootIt iterator_type; + typedef mapped_iterator<RootIt, UnaryFunc> _Self; + + inline const RootIt &getCurrent() const { return current; } + + inline explicit mapped_iterator(const RootIt &I, UnaryFunc F) + : current(I), Fn(F) {} + inline mapped_iterator(const mapped_iterator &It) + : current(It.current), Fn(It.Fn) {} + + inline value_type operator*() const { // All this work to do this + return Fn(*current); // little change + } + + _Self& operator++() { ++current; return *this; } + _Self& operator--() { --current; return *this; } + _Self operator++(int) { _Self __tmp = *this; ++current; return __tmp; } + _Self operator--(int) { _Self __tmp = *this; --current; return __tmp; } + _Self operator+ (difference_type n) const { return _Self(current + n); } + _Self& operator+= (difference_type n) { current += n; return *this; } + _Self operator- (difference_type n) const { return _Self(current - n); } + _Self& operator-= (difference_type n) { current -= n; return *this; } + reference operator[](difference_type n) const { return *(*this + n); } + + inline bool operator!=(const _Self &X) const { return !operator==(X); } + inline bool operator==(const _Self &X) const { return current == X.current; } + inline bool operator< (const _Self &X) const { return current < X.current; } + + inline difference_type operator-(const _Self &X) const { + return current - X.current; + } +}; + +template <class _Iterator, class Func> +inline mapped_iterator<_Iterator, Func> +operator+(typename mapped_iterator<_Iterator, Func>::difference_type N, + const mapped_iterator<_Iterator, Func>& X) { + return mapped_iterator<_Iterator, Func>(X.getCurrent() - N); +} + + +// map_iterator - Provide a convenient way to create mapped_iterators, just like +// make_pair is useful for creating pairs... +// +template <class ItTy, class FuncTy> +inline mapped_iterator<ItTy, FuncTy> map_iterator(const ItTy &I, FuncTy F) { + return mapped_iterator<ItTy, FuncTy>(I, F); +} + + +// next/prior - These functions unlike std::advance do not modify the +// passed iterator but return a copy. +// +// next(myIt) returns copy of myIt incremented once +// next(myIt, n) returns copy of myIt incremented n times +// prior(myIt) returns copy of myIt decremented once +// prior(myIt, n) returns copy of myIt decremented n times + +template <typename ItTy, typename Dist> +inline ItTy next(ItTy it, Dist n) +{ + std::advance(it, n); + return it; +} + +template <typename ItTy> +inline ItTy next(ItTy it) +{ + std::advance(it, 1); + return it; +} + +template <typename ItTy, typename Dist> +inline ItTy prior(ItTy it, Dist n) +{ + std::advance(it, -n); + return it; +} + +template <typename ItTy> +inline ItTy prior(ItTy it) +{ + std::advance(it, -1); + return it; +} + +//===----------------------------------------------------------------------===// +// Extra additions to <utility> +//===----------------------------------------------------------------------===// + +// tie - this function ties two objects and returns a temporary object +// that is assignable from a std::pair. This can be used to make code +// more readable when using values returned from functions bundled in +// a std::pair. Since an example is worth 1000 words: +// +// typedef std::map<int, int> Int2IntMap; +// +// Int2IntMap myMap; +// Int2IntMap::iterator where; +// bool inserted; +// tie(where, inserted) = myMap.insert(std::make_pair(123,456)); +// +// if (inserted) +// // do stuff +// else +// // do other stuff + +namespace +{ + template <typename T1, typename T2> + struct tier { + typedef T1 &first_type; + typedef T2 &second_type; + + first_type first; + second_type second; + + tier(first_type f, second_type s) : first(f), second(s) { } + tier& operator=(const std::pair<T1, T2>& p) { + first = p.first; + second = p.second; + return *this; + } + }; +} + +template <typename T1, typename T2> +inline tier<T1, T2> tie(T1& f, T2& s) { + return tier<T1, T2>(f, s); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/SetOperations.h b/include/llvm/ADT/SetOperations.h new file mode 100644 index 0000000..c37d1e7 --- /dev/null +++ b/include/llvm/ADT/SetOperations.h @@ -0,0 +1,71 @@ +//===-- llvm/ADT/SetOperations.h - Generic Set Operations -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines generic set operations that may be used on set's of +// different types, and different element types. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SETOPERATIONS_H +#define LLVM_ADT_SETOPERATIONS_H + +namespace llvm { + +/// set_union(A, B) - Compute A := A u B, return whether A changed. +/// +template <class S1Ty, class S2Ty> +bool set_union(S1Ty &S1, const S2Ty &S2) { + bool Changed = false; + + for (typename S2Ty::const_iterator SI = S2.begin(), SE = S2.end(); + SI != SE; ++SI) + if (S1.insert(*SI).second) + Changed = true; + + return Changed; +} + +/// set_intersect(A, B) - Compute A := A ^ B +/// Identical to set_intersection, except that it works on set<>'s and +/// is nicer to use. Functionally, this iterates through S1, removing +/// elements that are not contained in S2. +/// +template <class S1Ty, class S2Ty> +void set_intersect(S1Ty &S1, const S2Ty &S2) { + for (typename S1Ty::iterator I = S1.begin(); I != S1.end();) { + const typename S1Ty::key_type &E = *I; + ++I; + if (!S2.count(E)) S1.erase(E); // Erase element if not in S2 + } +} + +/// set_difference(A, B) - Return A - B +/// +template <class S1Ty, class S2Ty> +S1Ty set_difference(const S1Ty &S1, const S2Ty &S2) { + S1Ty Result; + for (typename S1Ty::const_iterator SI = S1.begin(), SE = S1.end(); + SI != SE; ++SI) + if (!S2.count(*SI)) // if the element is not in set2 + Result.insert(*SI); + return Result; +} + +/// set_subtract(A, B) - Compute A := A - B +/// +template <class S1Ty, class S2Ty> +void set_subtract(S1Ty &S1, const S2Ty &S2) { + for (typename S2Ty::const_iterator SI = S2.begin(), SE = S2.end(); + SI != SE; ++SI) + S1.erase(*SI); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/SetVector.h b/include/llvm/ADT/SetVector.h new file mode 100644 index 0000000..7675534 --- /dev/null +++ b/include/llvm/ADT/SetVector.h @@ -0,0 +1,168 @@ +//===- llvm/ADT/SetVector.h - Set with insert order iteration ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a set that has insertion order iteration +// characteristics. This is useful for keeping a set of things that need to be +// visited later but in a deterministic order (insertion order). The interface +// is purposefully minimal. +// +// This file defines SetVector and SmallSetVector, which performs no allocations +// if the SetVector has less than a certain number of elements. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SETVECTOR_H +#define LLVM_ADT_SETVECTOR_H + +#include "llvm/ADT/SmallSet.h" +#include <vector> +#include <cassert> +#include <algorithm> + +namespace llvm { + +/// This adapter class provides a way to keep a set of things that also has the +/// property of a deterministic iteration order. The order of iteration is the +/// order of insertion. +/// @brief A vector that has set insertion semantics. +template <typename T, typename Vector = std::vector<T>, + typename Set = SmallSet<T, 16> > +class SetVector { +public: + typedef T value_type; + typedef T key_type; + typedef T& reference; + typedef const T& const_reference; + typedef Set set_type; + typedef Vector vector_type; + typedef typename vector_type::const_iterator iterator; + typedef typename vector_type::const_iterator const_iterator; + typedef typename vector_type::size_type size_type; + + /// @brief Construct an empty SetVector + SetVector() {} + + /// @brief Initialize a SetVector with a range of elements + template<typename It> + SetVector(It Start, It End) { + insert(Start, End); + } + + /// @brief Determine if the SetVector is empty or not. + bool empty() const { + return vector_.empty(); + } + + /// @brief Determine the number of elements in the SetVector. + size_type size() const { + return vector_.size(); + } + + /// @brief Get an iterator to the beginning of the SetVector. + iterator begin() { + return vector_.begin(); + } + + /// @brief Get a const_iterator to the beginning of the SetVector. + const_iterator begin() const { + return vector_.begin(); + } + + /// @brief Get an iterator to the end of the SetVector. + iterator end() { + return vector_.end(); + } + + /// @brief Get a const_iterator to the end of the SetVector. + const_iterator end() const { + return vector_.end(); + } + + /// @brief Return the last element of the SetVector. + const T &back() const { + assert(!empty() && "Cannot call back() on empty SetVector!"); + return vector_.back(); + } + + /// @brief Index into the SetVector. + const_reference operator[](size_type n) const { + assert(n < vector_.size() && "SetVector access out of range!"); + return vector_[n]; + } + + /// @returns true iff the element was inserted into the SetVector. + /// @brief Insert a new element into the SetVector. + bool insert(const value_type &X) { + bool result = set_.insert(X); + if (result) + vector_.push_back(X); + return result; + } + + /// @brief Insert a range of elements into the SetVector. + template<typename It> + void insert(It Start, It End) { + for (; Start != End; ++Start) + if (set_.insert(*Start)) + vector_.push_back(*Start); + } + + /// @brief Remove an item from the set vector. + void remove(const value_type& X) { + if (set_.erase(X)) { + typename vector_type::iterator I = + std::find(vector_.begin(), vector_.end(), X); + assert(I != vector_.end() && "Corrupted SetVector instances!"); + vector_.erase(I); + } + } + + + /// @returns 0 if the element is not in the SetVector, 1 if it is. + /// @brief Count the number of elements of a given key in the SetVector. + size_type count(const key_type &key) const { + return set_.count(key); + } + + /// @brief Completely clear the SetVector + void clear() { + set_.clear(); + vector_.clear(); + } + + /// @brief Remove the last element of the SetVector. + void pop_back() { + assert(!empty() && "Cannot remove an element from an empty SetVector!"); + set_.erase(back()); + vector_.pop_back(); + } + +private: + set_type set_; ///< The set. + vector_type vector_; ///< The vector. +}; + +/// SmallSetVector - A SetVector that performs no allocations if smaller than +/// a certain size. +template <typename T, unsigned N> +class SmallSetVector : public SetVector<T, SmallVector<T, N>, SmallSet<T, N> > { +public: + SmallSetVector() {} + + /// @brief Initialize a SmallSetVector with a range of elements + template<typename It> + SmallSetVector(It Start, It End) { + this->insert(Start, End); + } +}; + +} // End llvm namespace + +// vim: sw=2 ai +#endif diff --git a/include/llvm/ADT/SmallPtrSet.h b/include/llvm/ADT/SmallPtrSet.h new file mode 100644 index 0000000..27c8459 --- /dev/null +++ b/include/llvm/ADT/SmallPtrSet.h @@ -0,0 +1,250 @@ +//===- llvm/ADT/SmallPtrSet.h - 'Normally small' pointer set ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the SmallPtrSet class. See the doxygen comment for +// SmallPtrSetImpl for more details on the algorithm used. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLPTRSET_H +#define LLVM_ADT_SMALLPTRSET_H + +#include <cassert> +#include <cstring> +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +/// SmallPtrSetImpl - This is the common code shared among all the +/// SmallPtrSet<>'s, which is almost everything. SmallPtrSet has two modes, one +/// for small and one for large sets. +/// +/// Small sets use an array of pointers allocated in the SmallPtrSet object, +/// which is treated as a simple array of pointers. When a pointer is added to +/// the set, the array is scanned to see if the element already exists, if not +/// the element is 'pushed back' onto the array. If we run out of space in the +/// array, we grow into the 'large set' case. SmallSet should be used when the +/// sets are often small. In this case, no memory allocation is used, and only +/// light-weight and cache-efficient scanning is used. +/// +/// Large sets use a classic exponentially-probed hash table. Empty buckets are +/// represented with an illegal pointer value (-1) to allow null pointers to be +/// inserted. Tombstones are represented with another illegal pointer value +/// (-2), to allow deletion. The hash table is resized when the table is 3/4 or +/// more. When this happens, the table is doubled in size. +/// +class SmallPtrSetImpl { +protected: + /// CurArray - This is the current set of buckets. If it points to + /// SmallArray, then the set is in 'small mode'. + void **CurArray; + /// CurArraySize - The allocated size of CurArray, always a power of two. + /// Note that CurArray points to an array that has CurArraySize+1 elements in + /// it, so that the end iterator actually points to valid memory. + unsigned CurArraySize; + + // If small, this is # elts allocated consequtively + unsigned NumElements; + unsigned NumTombstones; + void *SmallArray[1]; // Must be last ivar. + + // Helper to copy construct a SmallPtrSet. + SmallPtrSetImpl(const SmallPtrSetImpl& that); +public: + SmallPtrSetImpl(unsigned SmallSize) { + assert(SmallSize && (SmallSize & (SmallSize-1)) == 0 && + "Initial size must be a power of two!"); + CurArray = &SmallArray[0]; + CurArraySize = SmallSize; + // The end pointer, always valid, is set to a valid element to help the + // iterator. + CurArray[SmallSize] = 0; + clear(); + } + ~SmallPtrSetImpl(); + + bool empty() const { return size() == 0; } + unsigned size() const { return NumElements; } + + static void *getTombstoneMarker() { return reinterpret_cast<void*>(-2); } + static void *getEmptyMarker() { + // Note that -1 is chosen to make clear() efficiently implementable with + // memset and because it's not a valid pointer value. + return reinterpret_cast<void*>(-1); + } + + void clear() { + // Fill the array with empty markers. + memset(CurArray, -1, CurArraySize*sizeof(void*)); + NumElements = 0; + NumTombstones = 0; + } + + /// insert - This returns true if the pointer was new to the set, false if it + /// was already in the set. + bool insert(void *Ptr); + + template <typename IterT> + void insert(IterT I, IterT E) { + for (; I != E; ++I) + insert((void*)*I); + } + + /// erase - If the set contains the specified pointer, remove it and return + /// true, otherwise return false. + bool erase(void *Ptr); + + bool count(void *Ptr) const { + if (isSmall()) { + // Linear search for the item. + for (void *const *APtr = SmallArray, *const *E = SmallArray+NumElements; + APtr != E; ++APtr) + if (*APtr == Ptr) + return true; + return false; + } + + // Big set case. + return *FindBucketFor(Ptr) == Ptr; + } + +private: + bool isSmall() const { return CurArray == &SmallArray[0]; } + + unsigned Hash(void *Ptr) const { + return ((uintptr_t)Ptr >> 4) & (CurArraySize-1); + } + void * const *FindBucketFor(void *Ptr) const; + + /// Grow - Allocate a larger backing store for the buckets and move it over. + void Grow(); + + void operator=(const SmallPtrSetImpl &RHS); // DO NOT IMPLEMENT. +protected: + void CopyFrom(const SmallPtrSetImpl &RHS); +}; + +/// SmallPtrSetIteratorImpl - This is the common base class shared between all +/// instances of SmallPtrSetIterator. +class SmallPtrSetIteratorImpl { +protected: + void *const *Bucket; +public: + SmallPtrSetIteratorImpl(void *const *BP) : Bucket(BP) { + AdvanceIfNotValid(); + } + + bool operator==(const SmallPtrSetIteratorImpl &RHS) const { + return Bucket == RHS.Bucket; + } + bool operator!=(const SmallPtrSetIteratorImpl &RHS) const { + return Bucket != RHS.Bucket; + } + +protected: + /// AdvanceIfNotValid - If the current bucket isn't valid, advance to a bucket + /// that is. This is guaranteed to stop because the end() bucket is marked + /// valid. + void AdvanceIfNotValid() { + while (*Bucket == SmallPtrSetImpl::getEmptyMarker() || + *Bucket == SmallPtrSetImpl::getTombstoneMarker()) + ++Bucket; + } +}; + +/// SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet. +template<typename PtrTy> +class SmallPtrSetIterator : public SmallPtrSetIteratorImpl { +public: + SmallPtrSetIterator(void *const *BP) : SmallPtrSetIteratorImpl(BP) {} + + // Most methods provided by baseclass. + + PtrTy operator*() const { + return static_cast<PtrTy>(*Bucket); + } + + inline SmallPtrSetIterator& operator++() { // Preincrement + ++Bucket; + AdvanceIfNotValid(); + return *this; + } + + SmallPtrSetIterator operator++(int) { // Postincrement + SmallPtrSetIterator tmp = *this; ++*this; return tmp; + } +}; + +/// NextPowerOfTwo - This is a helper template that rounds N up to the next +/// power of two. +template<unsigned N> +struct NextPowerOfTwo; + +/// NextPowerOfTwoH - If N is not a power of two, increase it. This is a helper +/// template used to implement NextPowerOfTwo. +template<unsigned N, bool isPowerTwo> +struct NextPowerOfTwoH { + enum { Val = N }; +}; +template<unsigned N> +struct NextPowerOfTwoH<N, false> { + enum { + // We could just use NextVal = N+1, but this converges faster. N|(N-1) sets + // the right-most zero bits to one all at once, e.g. 0b0011000 -> 0b0011111. + Val = NextPowerOfTwo<(N|(N-1)) + 1>::Val + }; +}; + +template<unsigned N> +struct NextPowerOfTwo { + enum { Val = NextPowerOfTwoH<N, (N&(N-1)) == 0>::Val }; +}; + + +/// SmallPtrSet - This class implements a set which is optimizer for holding +/// SmallSize or less elements. This internally rounds up SmallSize to the next +/// power of two if it is not already a power of two. See the comments above +/// SmallPtrSetImpl for details of the algorithm. +template<class PtrType, unsigned SmallSize> +class SmallPtrSet : public SmallPtrSetImpl { + // Make sure that SmallSize is a power of two, round up if not. + enum { SmallSizePowTwo = NextPowerOfTwo<SmallSize>::Val }; + void *SmallArray[SmallSizePowTwo]; +public: + SmallPtrSet() : SmallPtrSetImpl(NextPowerOfTwo<SmallSizePowTwo>::Val) {} + SmallPtrSet(const SmallPtrSet &that) : SmallPtrSetImpl(that) {} + + template<typename It> + SmallPtrSet(It I, It E) + : SmallPtrSetImpl(NextPowerOfTwo<SmallSizePowTwo>::Val) { + insert(I, E); + } + + typedef SmallPtrSetIterator<PtrType> iterator; + typedef SmallPtrSetIterator<PtrType> const_iterator; + inline iterator begin() const { + return iterator(CurArray); + } + inline iterator end() const { + return iterator(CurArray+CurArraySize); + } + + // Allow assignment from any smallptrset with the same element type even if it + // doesn't have the same smallsize. + const SmallPtrSet<PtrType, SmallSize>& + operator=(const SmallPtrSet<PtrType, SmallSize> &RHS) { + CopyFrom(RHS); + return *this; + } + +}; + +} + +#endif diff --git a/include/llvm/ADT/SmallSet.h b/include/llvm/ADT/SmallSet.h new file mode 100644 index 0000000..30e8ee5 --- /dev/null +++ b/include/llvm/ADT/SmallSet.h @@ -0,0 +1,112 @@ +//===- llvm/ADT/SmallSet.h - 'Normally small' sets --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the SmallSet class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLSET_H +#define LLVM_ADT_SMALLSET_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include <set> + +namespace llvm { + +/// SmallSet - This maintains a set of unique values, optimizing for the case +/// when the set is small (less than N). In this case, the set can be +/// maintained with no mallocs. If the set gets large, we expand to using an +/// std::set to maintain reasonable lookup times. +/// +/// Note that this set does not provide a way to iterate over members in the +/// set. +template <typename T, unsigned N> +class SmallSet { + /// Use a SmallVector to hold the elements here (even though it will never + /// reach it's 'large' stage) to avoid calling the default ctors of elements + /// we will never use. + SmallVector<T, N> Vector; + std::set<T> Set; + typedef typename SmallVector<T, N>::const_iterator VIterator; + typedef typename SmallVector<T, N>::iterator mutable_iterator; +public: + SmallSet() {} + + bool empty() const { return Vector.empty() && Set.empty(); } + unsigned size() const { + return isSmall() ? Vector.size() : Set.size(); + } + + /// count - Return true if the element is in the set. + bool count(const T &V) const { + if (isSmall()) { + // Since the collection is small, just do a linear search. + return vfind(V) != Vector.end(); + } else { + return Set.count(V); + } + } + + /// insert - Insert an element into the set if it isn't already there. + bool insert(const T &V) { + if (!isSmall()) + return Set.insert(V).second; + + VIterator I = vfind(V); + if (I != Vector.end()) // Don't reinsert if it already exists. + return false; + if (Vector.size() < N) { + Vector.push_back(V); + return true; + } + + // Otherwise, grow from vector to set. + while (!Vector.empty()) { + Set.insert(Vector.back()); + Vector.pop_back(); + } + Set.insert(V); + return true; + } + + bool erase(const T &V) { + if (!isSmall()) + return Set.erase(V); + for (mutable_iterator I = Vector.begin(), E = Vector.end(); I != E; ++I) + if (*I == V) { + Vector.erase(I); + return true; + } + return false; + } + + void clear() { + Vector.clear(); + Set.clear(); + } +private: + bool isSmall() const { return Set.empty(); } + + VIterator vfind(const T &V) const { + for (VIterator I = Vector.begin(), E = Vector.end(); I != E; ++I) + if (*I == V) + return I; + return Vector.end(); + } +}; + +/// If this set is of pointer values, transparently switch over to using +/// SmallPtrSet for performance. +template <typename PointeeType, unsigned N> +class SmallSet<PointeeType*, N> : public SmallPtrSet<PointeeType*, N> {}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/ADT/SmallString.h b/include/llvm/ADT/SmallString.h new file mode 100644 index 0000000..2818ebb --- /dev/null +++ b/include/llvm/ADT/SmallString.h @@ -0,0 +1,62 @@ +//===- llvm/ADT/SmallString.h - 'Normally small' strings --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the SmallString class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLSTRING_H +#define LLVM_ADT_SMALLSTRING_H + +#include "llvm/ADT/SmallVector.h" +#include <cstring> + +namespace llvm { + +/// SmallString - A SmallString is just a SmallVector with methods and accessors +/// that make it work better as a string (e.g. operator+ etc). +template<unsigned InternalLen> +class SmallString : public SmallVector<char, InternalLen> { +public: + // Default ctor - Initialize to empty. + SmallString() {} + + // Initialize with a range. + template<typename ItTy> + SmallString(ItTy S, ItTy E) : SmallVector<char, InternalLen>(S, E) {} + + // Copy ctor. + SmallString(const SmallString &RHS) : SmallVector<char, InternalLen>(RHS) {} + + + // Extra methods. + const char *c_str() const { + SmallString *This = const_cast<SmallString*>(this); + // Ensure that there is a \0 at the end of the string. + This->reserve(this->size()+1); + This->End[0] = 0; + return this->begin(); + } + + // Extra operators. + SmallString &operator+=(const char *RHS) { + this->append(RHS, RHS+strlen(RHS)); + return *this; + } + SmallString &operator+=(char C) { + this->push_back(C); + return *this; + } + +}; + + +} + +#endif diff --git a/include/llvm/ADT/SmallVector.h b/include/llvm/ADT/SmallVector.h new file mode 100644 index 0000000..876ca27 --- /dev/null +++ b/include/llvm/ADT/SmallVector.h @@ -0,0 +1,485 @@ +//===- llvm/ADT/SmallVector.h - 'Normally small' vectors --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the SmallVector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_SMALLVECTOR_H +#define LLVM_ADT_SMALLVECTOR_H + +#include <algorithm> +#include <iterator> +#include <memory> + +#ifdef _MSC_VER +namespace std { +#if _MSC_VER <= 1310 + // Work around flawed VC++ implementation of std::uninitialized_copy. Define + // additional overloads so that elements with pointer types are recognized as + // scalars and not objects, causing bizarre type conversion errors. + template<class T1, class T2> + inline _Scalar_ptr_iterator_tag _Ptr_cat(T1 **, T2 **) { + _Scalar_ptr_iterator_tag _Cat; + return _Cat; + } + + template<class T1, class T2> + inline _Scalar_ptr_iterator_tag _Ptr_cat(T1* const *, T2 **) { + _Scalar_ptr_iterator_tag _Cat; + return _Cat; + } +#else +// FIXME: It is not clear if the problem is fixed in VS 2005. What is clear +// is that the above hack won't work if it wasn't fixed. +#endif +} +#endif + +namespace llvm { + +/// SmallVectorImpl - This class consists of common code factored out of the +/// SmallVector class to reduce code duplication based on the SmallVector 'N' +/// template parameter. +template <typename T> +class SmallVectorImpl { +protected: + T *Begin, *End, *Capacity; + + // Allocate raw space for N elements of type T. If T has a ctor or dtor, we + // don't want it to be automatically run, so we need to represent the space as + // something else. An array of char would work great, but might not be + // aligned sufficiently. Instead, we either use GCC extensions, or some + // number of union instances for the space, which guarantee maximal alignment. +protected: +#ifdef __GNUC__ + typedef char U; + U FirstEl __attribute__((aligned)); +#else + union U { + double D; + long double LD; + long long L; + void *P; + } FirstEl; +#endif + // Space after 'FirstEl' is clobbered, do not add any instance vars after it. +public: + // Default ctor - Initialize to empty. + SmallVectorImpl(unsigned N) + : Begin((T*)&FirstEl), End((T*)&FirstEl), Capacity((T*)&FirstEl+N) { + } + + ~SmallVectorImpl() { + // Destroy the constructed elements in the vector. + destroy_range(Begin, End); + + // If this wasn't grown from the inline copy, deallocate the old space. + if (!isSmall()) + delete[] (char*)Begin; + } + + typedef size_t size_type; + typedef T* iterator; + typedef const T* const_iterator; + typedef T& reference; + typedef const T& const_reference; + + bool empty() const { return Begin == End; } + size_type size() const { return End-Begin; } + + iterator begin() { return Begin; } + const_iterator begin() const { return Begin; } + + iterator end() { return End; } + const_iterator end() const { return End; } + + reference operator[](unsigned idx) { + return Begin[idx]; + } + const_reference operator[](unsigned idx) const { + return Begin[idx]; + } + + reference front() { + return begin()[0]; + } + const_reference front() const { + return begin()[0]; + } + + reference back() { + return end()[-1]; + } + const_reference back() const { + return end()[-1]; + } + + void push_back(const_reference Elt) { + if (End < Capacity) { + Retry: + new (End) T(Elt); + ++End; + return; + } + grow(); + goto Retry; + } + + void pop_back() { + --End; + End->~T(); + } + + void clear() { + destroy_range(Begin, End); + End = Begin; + } + + void resize(unsigned N) { + if (N < size()) { + destroy_range(Begin+N, End); + End = Begin+N; + } else if (N > size()) { + if (unsigned(Capacity-Begin) < N) + grow(N); + construct_range(End, Begin+N, T()); + End = Begin+N; + } + } + + void resize(unsigned N, const T &NV) { + if (N < size()) { + destroy_range(Begin+N, End); + End = Begin+N; + } else if (N > size()) { + if (unsigned(Capacity-Begin) < N) + grow(N); + construct_range(End, Begin+N, NV); + End = Begin+N; + } + } + + void reserve(unsigned N) { + if (unsigned(Capacity-Begin) < N) + grow(N); + } + + void swap(SmallVectorImpl &RHS); + + /// append - Add the specified range to the end of the SmallVector. + /// + template<typename in_iter> + void append(in_iter in_start, in_iter in_end) { + unsigned NumInputs = std::distance(in_start, in_end); + // Grow allocated space if needed. + if (End+NumInputs > Capacity) + grow(size()+NumInputs); + + // Copy the new elements over. + std::uninitialized_copy(in_start, in_end, End); + End += NumInputs; + } + + void assign(unsigned NumElts, const T &Elt) { + clear(); + if (unsigned(Capacity-Begin) < NumElts) + grow(NumElts); + End = Begin+NumElts; + construct_range(Begin, End, Elt); + } + + void erase(iterator I) { + // Shift all elts down one. + std::copy(I+1, End, I); + // Drop the last elt. + pop_back(); + } + + void erase(iterator S, iterator E) { + // Shift all elts down. + iterator I = std::copy(E, End, S); + // Drop the last elts. + destroy_range(I, End); + End = I; + } + + iterator insert(iterator I, const T &Elt) { + if (I == End) { // Important special case for empty vector. + push_back(Elt); + return end()-1; + } + + if (End < Capacity) { + Retry: + new (End) T(back()); + ++End; + // Push everything else over. + std::copy_backward(I, End-1, End); + *I = Elt; + return I; + } + unsigned EltNo = I-Begin; + grow(); + I = Begin+EltNo; + goto Retry; + } + + template<typename ItTy> + iterator insert(iterator I, ItTy From, ItTy To) { + if (I == End) { // Important special case for empty vector. + append(From, To); + return end()-1; + } + + unsigned NumToInsert = std::distance(From, To); + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + unsigned InsertElt = I-begin(); + + // Ensure there is enough space. + reserve(size() + NumToInsert); + + // Uninvalidate the iterator. + I = begin()+InsertElt; + + // If we already have this many elements in the collection, append the + // dest elements at the end, then copy over the appropriate elements. Since + // we already reserved space, we know that this won't reallocate the vector. + if (size() >= NumToInsert) { + T *OldEnd = End; + append(End-NumToInsert, End); + + // Copy the existing elements that get replaced. + std::copy(I, OldEnd-NumToInsert, I+NumToInsert); + + std::copy(From, To, I); + return I; + } + + // Otherwise, we're inserting more elements than exist already, and we're + // not inserting at the end. + + // Copy over the elements that we're about to overwrite. + T *OldEnd = End; + End += NumToInsert; + unsigned NumOverwritten = OldEnd-I; + std::uninitialized_copy(I, OldEnd, End-NumOverwritten); + + // Replace the overwritten part. + std::copy(From, From+NumOverwritten, I); + + // Insert the non-overwritten middle part. + std::uninitialized_copy(From+NumOverwritten, To, OldEnd); + return I; + } + + const SmallVectorImpl &operator=(const SmallVectorImpl &RHS); + +private: + /// isSmall - Return true if this is a smallvector which has not had dynamic + /// memory allocated for it. + bool isSmall() const { + return (void*)Begin == (void*)&FirstEl; + } + + /// grow - double the size of the allocated memory, guaranteeing space for at + /// least one more element or MinSize if specified. + void grow(unsigned MinSize = 0); + + void construct_range(T *S, T *E, const T &Elt) { + for (; S != E; ++S) + new (S) T(Elt); + } + + void destroy_range(T *S, T *E) { + while (S != E) { + --E; + E->~T(); + } + } +}; + +// Define this out-of-line to dissuade the C++ compiler from inlining it. +template <typename T> +void SmallVectorImpl<T>::grow(unsigned MinSize) { + unsigned CurCapacity = unsigned(Capacity-Begin); + unsigned CurSize = unsigned(size()); + unsigned NewCapacity = 2*CurCapacity; + if (NewCapacity < MinSize) + NewCapacity = MinSize; + T *NewElts = reinterpret_cast<T*>(new char[NewCapacity*sizeof(T)]); + + // Copy the elements over. + std::uninitialized_copy(Begin, End, NewElts); + + // Destroy the original elements. + destroy_range(Begin, End); + + // If this wasn't grown from the inline copy, deallocate the old space. + if (!isSmall()) + delete[] (char*)Begin; + + Begin = NewElts; + End = NewElts+CurSize; + Capacity = Begin+NewCapacity; +} + +template <typename T> +void SmallVectorImpl<T>::swap(SmallVectorImpl<T> &RHS) { + if (this == &RHS) return; + + // We can only avoid copying elements if neither vector is small. + if (!isSmall() && !RHS.isSmall()) { + std::swap(Begin, RHS.Begin); + std::swap(End, RHS.End); + std::swap(Capacity, RHS.Capacity); + return; + } + if (Begin+RHS.size() > Capacity) + grow(RHS.size()); + if (RHS.begin()+size() > RHS.Capacity) + RHS.grow(size()); + + // Swap the shared elements. + unsigned NumShared = size(); + if (NumShared > RHS.size()) NumShared = RHS.size(); + for (unsigned i = 0; i != NumShared; ++i) + std::swap(Begin[i], RHS[i]); + + // Copy over the extra elts. + if (size() > RHS.size()) { + unsigned EltDiff = size() - RHS.size(); + std::uninitialized_copy(Begin+NumShared, End, RHS.End); + RHS.End += EltDiff; + destroy_range(Begin+NumShared, End); + End = Begin+NumShared; + } else if (RHS.size() > size()) { + unsigned EltDiff = RHS.size() - size(); + std::uninitialized_copy(RHS.Begin+NumShared, RHS.End, End); + End += EltDiff; + destroy_range(RHS.Begin+NumShared, RHS.End); + RHS.End = RHS.Begin+NumShared; + } +} + +template <typename T> +const SmallVectorImpl<T> & +SmallVectorImpl<T>::operator=(const SmallVectorImpl<T> &RHS) { + // Avoid self-assignment. + if (this == &RHS) return *this; + + // If we already have sufficient space, assign the common elements, then + // destroy any excess. + unsigned RHSSize = unsigned(RHS.size()); + unsigned CurSize = unsigned(size()); + if (CurSize >= RHSSize) { + // Assign common elements. + iterator NewEnd = std::copy(RHS.Begin, RHS.Begin+RHSSize, Begin); + + // Destroy excess elements. + destroy_range(NewEnd, End); + + // Trim. + End = NewEnd; + return *this; + } + + // If we have to grow to have enough elements, destroy the current elements. + // This allows us to avoid copying them during the grow. + if (unsigned(Capacity-Begin) < RHSSize) { + // Destroy current elements. + destroy_range(Begin, End); + End = Begin; + CurSize = 0; + grow(RHSSize); + } else if (CurSize) { + // Otherwise, use assignment for the already-constructed elements. + std::copy(RHS.Begin, RHS.Begin+CurSize, Begin); + } + + // Copy construct the new elements in place. + std::uninitialized_copy(RHS.Begin+CurSize, RHS.End, Begin+CurSize); + + // Set end. + End = Begin+RHSSize; + return *this; +} + +/// SmallVector - This is a 'vector' (really, a variable-sized array), optimized +/// for the case when the array is small. It contains some number of elements +/// in-place, which allows it to avoid heap allocation when the actual number of +/// elements is below that threshold. This allows normal "small" cases to be +/// fast without losing generality for large inputs. +/// +/// Note that this does not attempt to be exception safe. +/// +template <typename T, unsigned N> +class SmallVector : public SmallVectorImpl<T> { + /// InlineElts - These are 'N-1' elements that are stored inline in the body + /// of the vector. The extra '1' element is stored in SmallVectorImpl. + typedef typename SmallVectorImpl<T>::U U; + enum { + // MinUs - The number of U's require to cover N T's. + MinUs = (sizeof(T)*N+sizeof(U)-1)/sizeof(U), + + // NumInlineEltsElts - The number of elements actually in this array. There + // is already one in the parent class, and we have to round up to avoid + // having a zero-element array. + NumInlineEltsElts = (MinUs - 1) > 0 ? (MinUs - 1) : 1, + + // NumTsAvailable - The number of T's we actually have space for, which may + // be more than N due to rounding. + NumTsAvailable = (NumInlineEltsElts+1)*sizeof(U) / sizeof(T) + }; + U InlineElts[NumInlineEltsElts]; +public: + SmallVector() : SmallVectorImpl<T>(NumTsAvailable) { + } + + explicit SmallVector(unsigned Size, const T &Value = T()) + : SmallVectorImpl<T>(NumTsAvailable) { + this->reserve(Size); + while (Size--) + push_back(Value); + } + + template<typename ItTy> + SmallVector(ItTy S, ItTy E) : SmallVectorImpl<T>(NumTsAvailable) { + append(S, E); + } + + SmallVector(const SmallVector &RHS) : SmallVectorImpl<T>(NumTsAvailable) { + operator=(RHS); + } + + const SmallVector &operator=(const SmallVector &RHS) { + SmallVectorImpl<T>::operator=(RHS); + return *this; + } +}; + +} // End llvm namespace + +namespace std { + /// Implement std::swap in terms of SmallVector swap. + template<typename T> + inline void + swap(llvm::SmallVectorImpl<T> &LHS, llvm::SmallVectorImpl<T> &RHS) { + LHS.swap(RHS); + } + + /// Implement std::swap in terms of SmallVector swap. + template<typename T, unsigned N> + inline void + swap(llvm::SmallVector<T, N> &LHS, llvm::SmallVector<T, N> &RHS) { + LHS.swap(RHS); + } +} + +#endif diff --git a/include/llvm/ADT/Statistic.h b/include/llvm/ADT/Statistic.h new file mode 100644 index 0000000..ec4fdd6 --- /dev/null +++ b/include/llvm/ADT/Statistic.h @@ -0,0 +1,75 @@ +//===-- llvm/ADT/Statistic.h - Easy way to expose stats ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the 'Statistic' class, which is designed to be an easy way +// to expose various metrics from passes. These statistics are printed at the +// end of a run (from llvm_shutdown), when the -stats command line option is +// passed on the command line. +// +// This is useful for reporting information like the number of instructions +// simplified, optimized or removed by various transformations, like this: +// +// static Statistic NumInstsKilled("gcse", "Number of instructions killed"); +// +// Later, in the code: ++NumInstsKilled; +// +// NOTE: Statistics *must* be declared as global variables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STATISTIC_H +#define LLVM_ADT_STATISTIC_H + +namespace llvm { + +class Statistic { +public: + const char *Name; + const char *Desc; + unsigned Value : 31; + bool Initialized : 1; + + unsigned getValue() const { return Value; } + const char *getName() const { return Name; } + const char *getDesc() const { return Desc; } + + /// construct - This should only be called for non-global statistics. + void construct(const char *name, const char *desc) { + Name = name; Desc = desc; + Value = 0; Initialized = 0; + } + + // Allow use of this class as the value itself. + operator unsigned() const { return Value; } + const Statistic &operator=(unsigned Val) { Value = Val; return init(); } + const Statistic &operator++() { ++Value; return init(); } + unsigned operator++(int) { init(); return Value++; } + const Statistic &operator--() { --Value; return init(); } + unsigned operator--(int) { init(); return Value--; } + const Statistic &operator+=(const unsigned &V) { Value += V; return init(); } + const Statistic &operator-=(const unsigned &V) { Value -= V; return init(); } + const Statistic &operator*=(const unsigned &V) { Value *= V; return init(); } + const Statistic &operator/=(const unsigned &V) { Value /= V; return init(); } + +protected: + Statistic &init() { + if (!Initialized) RegisterStatistic(); + return *this; + } + void RegisterStatistic(); +}; + +// STATISTIC - A macro to make definition of statistics really simple. This +// automatically passes the DEBUG_TYPE of the file into the statistic. +#define STATISTIC(VARNAME, DESC) \ + static Statistic VARNAME = { DEBUG_TYPE, DESC, 0, 0 } + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/StringExtras.h b/include/llvm/ADT/StringExtras.h new file mode 100644 index 0000000..f0788a1 --- /dev/null +++ b/include/llvm/ADT/StringExtras.h @@ -0,0 +1,150 @@ +//===-- llvm/ADT/StringExtras.h - Useful string functions -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains some functions that are useful when dealing with strings. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGEXTRAS_H +#define LLVM_ADT_STRINGEXTRAS_H + +#include "llvm/Support/DataTypes.h" +#include <cctype> +#include <cstdio> +#include <string> +#include <vector> + +namespace llvm { + +static inline std::string utohexstr(uint64_t X) { + char Buffer[40]; + char *BufPtr = Buffer+39; + + *BufPtr = 0; // Null terminate buffer... + if (X == 0) *--BufPtr = '0'; // Handle special case... + + while (X) { + unsigned char Mod = static_cast<unsigned char>(X) & 15; + if (Mod < 10) + *--BufPtr = '0' + Mod; + else + *--BufPtr = 'A' + Mod-10; + X >>= 4; + } + return std::string(BufPtr); +} + +static inline std::string utostr_32(uint32_t X, bool isNeg = false) { + char Buffer[20]; + char *BufPtr = Buffer+19; + + *BufPtr = 0; // Null terminate buffer... + if (X == 0) *--BufPtr = '0'; // Handle special case... + + while (X) { + *--BufPtr = '0' + char(X % 10); + X /= 10; + } + + if (isNeg) *--BufPtr = '-'; // Add negative sign... + + return std::string(BufPtr); +} + +static inline std::string utostr(uint64_t X, bool isNeg = false) { + if (X == uint32_t(X)) + return utostr_32(uint32_t(X), isNeg); + + char Buffer[40]; + char *BufPtr = Buffer+39; + + *BufPtr = 0; // Null terminate buffer... + if (X == 0) *--BufPtr = '0'; // Handle special case... + + while (X) { + *--BufPtr = '0' + char(X % 10); + X /= 10; + } + + if (isNeg) *--BufPtr = '-'; // Add negative sign... + return std::string(BufPtr); +} + + +static inline std::string itostr(int64_t X) { + if (X < 0) + return utostr(static_cast<uint64_t>(-X), true); + else + return utostr(static_cast<uint64_t>(X)); +} + +static inline std::string ftostr(double V) { + char Buffer[200]; + sprintf(Buffer, "%20.6e", V); + char *B = Buffer; + while (*B == ' ') ++B; + return B; +} + +static inline std::string LowercaseString(const std::string &S) { + std::string result(S); + for (unsigned i = 0; i < S.length(); ++i) + if (isupper(result[i])) + result[i] = char(tolower(result[i])); + return result; +} + +/// StringsEqualNoCase - Return true if the two strings are equal, ignoring +/// case. +static inline bool StringsEqualNoCase(const std::string &LHS, + const std::string &RHS) { + if (LHS.size() != RHS.size()) return false; + for (unsigned i = 0, e = LHS.size(); i != e; ++i) + if (tolower(LHS[i]) != tolower(RHS[i])) return false; + return true; +} + +/// StringsEqualNoCase - Return true if the two strings are equal, ignoring +/// case. +static inline bool StringsEqualNoCase(const std::string &LHS, + const char *RHS) { + for (unsigned i = 0, e = LHS.size(); i != e; ++i) { + if (RHS[i] == 0) return false; // RHS too short. + if (tolower(LHS[i]) != tolower(RHS[i])) return false; + } + return RHS[LHS.size()] == 0; // Not too long? +} + +/// getToken - This function extracts one token from source, ignoring any +/// leading characters that appear in the Delimiters string, and ending the +/// token at any of the characters that appear in the Delimiters string. If +/// there are no tokens in the source string, an empty string is returned. +/// The Source source string is updated in place to remove the returned string +/// and any delimiter prefix from it. +std::string getToken(std::string &Source, + const char *Delimiters = " \t\n\v\f\r"); + +/// SplitString - Split up the specified string according to the specified +/// delimiters, appending the result fragments to the output list. +void SplitString(const std::string &Source, + std::vector<std::string> &OutFragments, + const char *Delimiters = " \t\n\v\f\r"); + +/// UnescapeString - Modify the argument string, turning two character sequences +/// like '\\' 'n' into '\n'. This handles: \e \a \b \f \n \r \t \v \' \\ and +/// \num (where num is a 1-3 byte octal value). +void UnescapeString(std::string &Str); + +/// EscapeString - Modify the argument string, turning '\\' and anything that +/// doesn't satisfy std::isprint into an escape sequence. +void EscapeString(std::string &Str); + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/StringMap.h b/include/llvm/ADT/StringMap.h new file mode 100644 index 0000000..cb1dd9f --- /dev/null +++ b/include/llvm/ADT/StringMap.h @@ -0,0 +1,346 @@ +//===--- StringMap.h - String Hash table map interface ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the StringMap class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_STRINGMAP_H +#define LLVM_ADT_STRINGMAP_H + +#include "llvm/Support/Allocator.h" +#include <cstring> + +namespace llvm { + template<typename ValueT> + class StringMapConstIterator; + template<typename ValueT> + class StringMapIterator; + + +/// StringMapEntryBase - Shared base class of StringMapEntry instances. +class StringMapEntryBase { + unsigned StrLen; +public: + StringMapEntryBase(unsigned Len) : StrLen(Len) {} + + unsigned getKeyLength() const { return StrLen; } +}; + +/// StringMapImpl - This is the base class of StringMap that is shared among +/// all of its instantiations. +class StringMapImpl { +public: + /// ItemBucket - The hash table consists of an array of these. If Item is + /// non-null, this is an extant entry, otherwise, it is a hole. + struct ItemBucket { + /// FullHashValue - This remembers the full hash value of the key for + /// easy scanning. + unsigned FullHashValue; + + /// Item - This is a pointer to the actual item object. + StringMapEntryBase *Item; + }; + +protected: + ItemBucket *TheTable; + unsigned NumBuckets; + unsigned NumItems; + unsigned NumTombstones; + unsigned ItemSize; +protected: + StringMapImpl(unsigned itemSize) : ItemSize(itemSize) { init(16); } + StringMapImpl(unsigned InitSize, unsigned ItemSize); + void RehashTable(); + + /// ShouldRehash - Return true if the table should be rehashed after a new + /// element was recently inserted. + bool ShouldRehash() const { + // If the hash table is now more than 3/4 full, or if fewer than 1/8 of + // the buckets are empty (meaning that many are filled with tombstones), + // grow the table. + return NumItems*4 > NumBuckets*3 || + NumBuckets-(NumItems+NumTombstones) < NumBuckets/8; + } + + /// LookupBucketFor - Look up the bucket that the specified string should end + /// up in. If it already exists as a key in the map, the Item pointer for the + /// specified bucket will be non-null. Otherwise, it will be null. In either + /// case, the FullHashValue field of the bucket will be set to the hash value + /// of the string. + unsigned LookupBucketFor(const char *KeyStart, const char *KeyEnd); + + /// FindKey - Look up the bucket that contains the specified key. If it exists + /// in the map, return the bucket number of the key. Otherwise return -1. + /// This does not modify the map. + int FindKey(const char *KeyStart, const char *KeyEnd) const; + + /// RemoveKey - Remove the specified StringMapEntry from the table, but do not + /// delete it. This aborts if the value isn't in the table. + void RemoveKey(StringMapEntryBase *V); + + /// RemoveKey - Remove the StringMapEntry for the specified key from the + /// table, returning it. If the key is not in the table, this returns null. + StringMapEntryBase *RemoveKey(const char *KeyStart, const char *KeyEnd); +private: + void init(unsigned Size); +public: + static StringMapEntryBase *getTombstoneVal() { + return (StringMapEntryBase*)-1; + } + + unsigned getNumBuckets() const { return NumBuckets; } + unsigned getNumItems() const { return NumItems; } + + bool empty() const { return NumItems == 0; } + unsigned size() const { return NumItems; } +}; + +/// StringMapEntry - This is used to represent one value that is inserted into +/// a StringMap. It contains the Value itself and the key: the string length +/// and data. +template<typename ValueTy> +class StringMapEntry : public StringMapEntryBase { + ValueTy Val; +public: + StringMapEntry(unsigned StrLen) + : StringMapEntryBase(StrLen), Val() {} + StringMapEntry(unsigned StrLen, const ValueTy &V) + : StringMapEntryBase(StrLen), Val(V) {} + + const ValueTy &getValue() const { return Val; } + ValueTy &getValue() { return Val; } + + void setValue(const ValueTy &V) { Val = V; } + + /// getKeyData - Return the start of the string data that is the key for this + /// value. The string data is always stored immediately after the + /// StringMapEntry object. + const char *getKeyData() const {return reinterpret_cast<const char*>(this+1);} + + /// Create - Create a StringMapEntry for the specified key and default + /// construct the value. + template<typename AllocatorTy> + static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd, + AllocatorTy &Allocator) { + unsigned KeyLength = KeyEnd-KeyStart; + + // Okay, the item doesn't already exist, and 'Bucket' is the bucket to fill + // in. Allocate a new item with space for the string at the end and a null + // terminator. + unsigned AllocSize = sizeof(StringMapEntry)+KeyLength+1; + +#ifdef __GNUC__ + unsigned Alignment = __alignof__(StringMapEntry); +#else + // FIXME: ugly. + unsigned Alignment = 8; +#endif + StringMapEntry *NewItem = + static_cast<StringMapEntry*>(Allocator.Allocate(AllocSize, Alignment)); + + // Default construct the value. + new (NewItem) StringMapEntry(KeyLength); + + // Copy the string information. + char *StrBuffer = const_cast<char*>(NewItem->getKeyData()); + memcpy(StrBuffer, KeyStart, KeyLength); + StrBuffer[KeyLength] = 0; // Null terminate for convenience of clients. + return NewItem; + } + + /// Create - Create a StringMapEntry with normal malloc/free. + static StringMapEntry *Create(const char *KeyStart, const char *KeyEnd) { + MallocAllocator A; + return Create(KeyStart, KeyEnd, A); + } + + /// Destroy - Destroy this StringMapEntry, releasing memory back to the + /// specified allocator. + template<typename AllocatorTy> + void Destroy(AllocatorTy &Allocator) { + // Free memory referenced by the item. + this->~StringMapEntry(); + Allocator.Deallocate(this); + } + + /// Destroy this object, releasing memory back to the malloc allocator. + void Destroy() { + MallocAllocator A; + Destroy(A); + } +}; + + +/// StringMap - This is an unconventional map that is specialized for handling +/// keys that are "strings", which are basically ranges of bytes. This does some +/// funky memory allocation and hashing things to make it extremely efficient, +/// storing the string data *after* the value in the map. +template<typename ValueTy, typename AllocatorTy = MallocAllocator> +class StringMap : public StringMapImpl { + AllocatorTy Allocator; + typedef StringMapEntry<ValueTy> MapEntryTy; +public: + StringMap() : StringMapImpl(sizeof(MapEntryTy)) {} + StringMap(unsigned InitialSize) + : StringMapImpl(InitialSize, sizeof(MapEntryTy)) {} + + AllocatorTy &getAllocator() { return Allocator; } + const AllocatorTy &getAllocator() const { return Allocator; } + + typedef StringMapConstIterator<ValueTy> const_iterator; + typedef StringMapIterator<ValueTy> iterator; + + iterator begin() { + return iterator(TheTable, NumBuckets == 0); + } + iterator end() { + return iterator(TheTable+NumBuckets, true); + } + const_iterator begin() const { + return const_iterator(TheTable, NumBuckets == 0); + } + const_iterator end() const { + return const_iterator(TheTable+NumBuckets, true); + } + + iterator find(const char *KeyStart, const char *KeyEnd) { + int Bucket = FindKey(KeyStart, KeyEnd); + if (Bucket == -1) return end(); + return iterator(TheTable+Bucket); + } + + const_iterator find(const char *KeyStart, const char *KeyEnd) const { + int Bucket = FindKey(KeyStart, KeyEnd); + if (Bucket == -1) return end(); + return const_iterator(TheTable+Bucket); + } + + /// insert - Insert the specified key/value pair into the map. If the key + /// already exists in the map, return false and ignore the request, otherwise + /// insert it and return true. + bool insert(MapEntryTy *KeyValue) { + unsigned BucketNo = + LookupBucketFor(KeyValue->getKeyData(), + KeyValue->getKeyData()+KeyValue->getKeyLength()); + ItemBucket &Bucket = TheTable[BucketNo]; + if (Bucket.Item && Bucket.Item != getTombstoneVal()) + return false; // Already exists in map. + + if (Bucket.Item == getTombstoneVal()) + --NumTombstones; + Bucket.Item = KeyValue; + ++NumItems; + + if (ShouldRehash()) + RehashTable(); + return true; + } + + /// GetOrCreateValue - Look up the specified key in the table. If a value + /// exists, return it. Otherwise, default construct a value, insert it, and + /// return. + StringMapEntry<ValueTy> &GetOrCreateValue(const char *KeyStart, + const char *KeyEnd) { + unsigned BucketNo = LookupBucketFor(KeyStart, KeyEnd); + ItemBucket &Bucket = TheTable[BucketNo]; + if (Bucket.Item && Bucket.Item != getTombstoneVal()) + return *static_cast<MapEntryTy*>(Bucket.Item); + + MapEntryTy *NewItem = MapEntryTy::Create(KeyStart, KeyEnd, Allocator); + + if (Bucket.Item == getTombstoneVal()) + --NumTombstones; + ++NumItems; + + // Fill in the bucket for the hash table. The FullHashValue was already + // filled in by LookupBucketFor. + Bucket.Item = NewItem; + + if (ShouldRehash()) + RehashTable(); + return *NewItem; + } + + /// remove - Remove the specified key/value pair from the map, but do not + /// erase it. This aborts if the key is not in the map. + void remove(MapEntryTy *KeyValue) { + RemoveKey(KeyValue); + } + + ~StringMap() { + for (ItemBucket *I = TheTable, *E = TheTable+NumBuckets; I != E; ++I) { + if (I->Item && I->Item != getTombstoneVal()) + static_cast<MapEntryTy*>(I->Item)->Destroy(Allocator); + } + free(TheTable); + } +}; + + +template<typename ValueTy> +class StringMapConstIterator { +protected: + StringMapImpl::ItemBucket *Ptr; +public: + StringMapConstIterator(StringMapImpl::ItemBucket *Bucket, + bool NoAdvance = false) + : Ptr(Bucket) { + if (!NoAdvance) AdvancePastEmptyBuckets(); + } + + const StringMapEntry<ValueTy> &operator*() const { + return *static_cast<StringMapEntry<ValueTy>*>(Ptr->Item); + } + const StringMapEntry<ValueTy> *operator->() const { + return static_cast<StringMapEntry<ValueTy>*>(Ptr->Item); + } + + bool operator==(const StringMapConstIterator &RHS) const { + return Ptr == RHS.Ptr; + } + bool operator!=(const StringMapConstIterator &RHS) const { + return Ptr != RHS.Ptr; + } + + inline StringMapConstIterator& operator++() { // Preincrement + ++Ptr; + AdvancePastEmptyBuckets(); + return *this; + } + StringMapConstIterator operator++(int) { // Postincrement + StringMapConstIterator tmp = *this; ++*this; return tmp; + } + +private: + void AdvancePastEmptyBuckets() { + while (Ptr->Item == 0 || Ptr->Item == StringMapImpl::getTombstoneVal()) + ++Ptr; + } +}; + +template<typename ValueTy> +class StringMapIterator : public StringMapConstIterator<ValueTy> { +public: + StringMapIterator(StringMapImpl::ItemBucket *Bucket, + bool NoAdvance = false) + : StringMapConstIterator<ValueTy>(Bucket, NoAdvance) { + } + StringMapEntry<ValueTy> &operator*() const { + return *static_cast<StringMapEntry<ValueTy>*>(this->Ptr->Item); + } + StringMapEntry<ValueTy> *operator->() const { + return static_cast<StringMapEntry<ValueTy>*>(this->Ptr->Item); + } +}; + +} + +#endif + diff --git a/include/llvm/ADT/Tree.h b/include/llvm/ADT/Tree.h new file mode 100644 index 0000000..835a001 --- /dev/null +++ b/include/llvm/ADT/Tree.h @@ -0,0 +1,62 @@ +//===- llvm/ADT/Tree.h - Generic n-way tree structure -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class defines a generic N way tree node structure. The tree structure +// is immutable after creation, but the payload contained within it is not. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_TREE_H +#define LLVM_ADT_TREE_H + +#include <vector> + +namespace llvm { + +template<class ConcreteTreeNode, class Payload> +class Tree { + std::vector<ConcreteTreeNode*> Children; // This nodes children, if any + ConcreteTreeNode *Parent; // Parent of this node... + Payload Data; // Data held in this node... + +protected: + void setChildren(const std::vector<ConcreteTreeNode*> &children) { + Children = children; + } +public: + inline Tree(ConcreteTreeNode *parent) : Parent(parent) {} + inline Tree(const std::vector<ConcreteTreeNode*> &children, + ConcreteTreeNode *par) : Children(children), Parent(par) {} + + inline Tree(const std::vector<ConcreteTreeNode*> &children, + ConcreteTreeNode *par, const Payload &data) + : Children(children), Parent(par), Data(data) {} + + // Tree dtor - Free all children + inline ~Tree() { + for (unsigned i = Children.size(); i > 0; --i) + delete Children[i-1]; + } + + // Tree manipulation/walking routines... + inline ConcreteTreeNode *getParent() const { return Parent; } + inline unsigned getNumChildren() const { return Children.size(); } + inline ConcreteTreeNode *getChild(unsigned i) const { + assert(i < Children.size() && "Tree::getChild with index out of range!"); + return Children[i]; + } + + // Payload access... + inline Payload &getTreeData() { return Data; } + inline const Payload &getTreeData() const { return Data; } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/UniqueVector.h b/include/llvm/ADT/UniqueVector.h new file mode 100644 index 0000000..f3fd7b1 --- /dev/null +++ b/include/llvm/ADT/UniqueVector.h @@ -0,0 +1,89 @@ +//===-- llvm/ADT/UniqueVector.h ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by James M. Laskey and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_UNIQUEVECTOR_H +#define LLVM_ADT_UNIQUEVECTOR_H + +#include <cassert> +#include <map> +#include <vector> + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// UniqueVector - This class produces a sequential ID number (base 1) for each +/// unique entry that is added. T is the type of entries in the vector. This +/// class should have an implementation of operator== and of operator<. +/// Entries can be fetched using operator[] with the entry ID. +template<class T> class UniqueVector { +private: + // Map - Used to handle the correspondence of entry to ID. + std::map<T, unsigned> Map; + + // Vector - ID ordered vector of entries. Entries can be indexed by ID - 1. + // + std::vector<T> Vector; + +public: + /// insert - Append entry to the vector if it doesn't already exist. Returns + /// the entry's index + 1 to be used as a unique ID. + unsigned insert(const T &Entry) { + // Check if the entry is already in the map. + unsigned &Val = Map[Entry]; + + // See if entry exists, if so return prior ID. + if (Val) return Val; + + // Compute ID for entry. + Val = Vector.size() + 1; + + // Insert in vector. + Vector.push_back(Entry); + return Val; + } + + /// idFor - return the ID for an existing entry. Returns 0 if the entry is + /// not found. + unsigned idFor(const T &Entry) const { + // Search for entry in the map. + typename std::map<T, unsigned>::const_iterator MI = Map.find(Entry); + + // See if entry exists, if so return ID. + if (MI != Map.end()) return MI->second; + + // No luck. + return 0; + } + + /// operator[] - Returns a reference to the entry with the specified ID. + /// + const T &operator[](unsigned ID) const { + assert(ID-1 < size() && "ID is 0 or out of range!"); + return Vector[ID - 1]; + } + + /// size - Returns the number of entries in the vector. + /// + size_t size() const { return Vector.size(); } + + /// empty - Returns true if the vector is empty. + /// + bool empty() const { return Vector.empty(); } + + /// reset - Clears all the entries. + /// + void reset() { + Map.clear(); + Vector.resize(0, 0); + } +}; + +} // End of namespace llvm + +#endif // LLVM_ADT_UNIQUEVECTOR_H diff --git a/include/llvm/ADT/VectorExtras.h b/include/llvm/ADT/VectorExtras.h new file mode 100644 index 0000000..bda2ae6 --- /dev/null +++ b/include/llvm/ADT/VectorExtras.h @@ -0,0 +1,41 @@ +//===-- llvm/ADT/VectorExtras.h - Helpers for std::vector -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains helper functions which are useful for working with the +// std::vector class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_VECTOREXTRAS_H +#define LLVM_ADT_VECTOREXTRAS_H + +#include <cstdarg> +#include <vector> + +namespace llvm { + +/// make_vector - Helper function which is useful for building temporary vectors +/// to pass into type construction of CallInst ctors. This turns a null +/// terminated list of pointers (or other value types) into a real live vector. +/// +template<typename T> +inline std::vector<T> make_vector(T A, ...) { + va_list Args; + va_start(Args, A); + std::vector<T> Result; + Result.push_back(A); + while (T Val = va_arg(Args, T)) + Result.push_back(Val); + va_end(Args); + return Result; +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/ADT/hash_map.in b/include/llvm/ADT/hash_map.in new file mode 100644 index 0000000..fe5c393 --- /dev/null +++ b/include/llvm/ADT/hash_map.in @@ -0,0 +1,150 @@ +//===-- llvm/ADT/hash_map - "Portable" wrapper around hash_map --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a wrapper around the mysterious <hash_map> header file +// that seems to move around between GCC releases into and out of namespaces at +// will. #including this header will cause hash_map to be available in the +// global namespace. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_HASH_MAP +#define LLVM_ADT_HASH_MAP + +// Compiler Support Matrix +// +// Version Namespace Header File +// 2.95.x :: hash_map +// 3.0.4 std ext/hash_map +// 3.1 __gnu_cxx ext/hash_map +// HP aCC6 std stdex/rw/hashm*ap.h +// MS VC++ stdext hash_map + +#undef HAVE_GNU_EXT_HASH_MAP +#undef HAVE_STD_EXT_HASH_MAP +#undef HAVE_GLOBAL_HASH_MAP +#undef HAVE_RW_STDEX_HASH_MAP_H + +#if HAVE_GNU_EXT_HASH_MAP +// This is for GCC-3.1+ which puts hash in ext/hash_map +# include <ext/hash_map> +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE __gnu_cxx +# endif + +// GCC 3.0.x puts hash_map in <ext/hash_map> and in the std namespace. +#elif HAVE_STD_EXT_HASH_MAP +# include <ext/hash_map> +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE std +# endif + +// Older compilers such as GCC before version 3.0 do not keep +// extensions in the `ext' directory, and ignore the `std' namespace. +#elif HAVE_GLOBAL_HASH_MAP +# include <hash_map> +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE std +# endif + +// HP aCC doesn't include an SGI-like hash_map. For this platform (or +// any others using Rogue Wave Software's Tools.h++ library), we wrap +// around them in std:: +#elif HAVE_RW_STDEX_HASH_MAP_H +# include <rw/stdex/hashmap.h> +# include <rw/stdex/hashmmap.h> +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE std +# endif + +// Support Microsoft VC++. +#elif defined(_MSC_VER) +# include <hash_map> +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE stdext + using std::_Distance; +# endif + +// Give a warning if we couldn't find it, instead of (or in addition to) +// randomly doing something dumb. +#else +# warning "Autoconfiguration failed to find the hash_map header file." +#endif + +// we wrap Rogue Wave Tools.h++ rw_hashmap into something SGI-looking, here: +#ifdef HAVE_RW_STDEX_HASH_MAP_H +namespace HASH_NAMESPACE { + +template <class DataType> struct hash { + unsigned int operator()(const unsigned int& x) const { + return x; + } +}; + +template <typename KeyType, + typename ValueType, + class _HashFcn = hash<KeyType>, + class _EqualKey = equal_to<KeyType>, + class _A = allocator <ValueType> > +class hash_map : public rw_hashmap<KeyType, ValueType, class _HashFcn, + class _EqualKey, class _A> { +}; + +template <typename KeyType, + typename ValueType, + class _HashFcn = hash<KeyType>, + class _EqualKey = equal_to<KeyType>, + class _A = allocator <ValueType> > +class hash_multimap : public rw_hashmultimap<KeyType, ValueType, class _HashFcn, + class _EqualKey, class _A> { +}; + +} // end HASH_NAMESPACE; +#endif + +// Include vector because ext/hash_map includes stl_vector.h and leaves +// out specializations like stl_bvector.h, causing link conflicts. +#include <vector> + +#ifdef _MSC_VER + +// GCC and VC++ have differing ways of implementing hash_maps. As it's not +// standardized, that's to be expected. This adapter class allows VC++ +// hash_map to use GCC's hash classes. +namespace stdext { + template<class Key> struct hash; + + // Provide a hash function for unsigned ints... + template<> struct hash<unsigned int> { + inline size_t operator()(unsigned int Val) const { + return Val; + } + }; + + template<class Key> class hash_compare<Key, std::less<Key> > { + std::less<Key> comp; + public: + enum { bucket_size = 4 }; + enum { min_buckets = 8 }; + hash_compare() {} + hash_compare(std::less<Key> pred) : comp(pred) {} + size_t operator()(const Key& key) const { return hash<Key>()(key); } + bool operator()(const Key& k1, const Key& k2) const { return comp(k1, k2); } + }; +} + +#endif + +using HASH_NAMESPACE::hash_map; +using HASH_NAMESPACE::hash_multimap; +using HASH_NAMESPACE::hash; + +#include "llvm/ADT/HashExtras.h" + +#endif diff --git a/include/llvm/ADT/hash_set.in b/include/llvm/ADT/hash_set.in new file mode 100644 index 0000000..aa27e5f --- /dev/null +++ b/include/llvm/ADT/hash_set.in @@ -0,0 +1,111 @@ +//===-- llvm/ADT/hash_set - "Portable" wrapper around hash_set --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// vim:ft=cpp +// +// This file provides a wrapper around the mysterious <hash_set> header file +// that seems to move around between GCC releases into and out of namespaces at +// will. #including this header will cause hash_set to be available in the +// global namespace. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_HASH_SET +#define LLVM_ADT_HASH_SET + +// Compiler Support Matrix +// +// Version Namespace Header File +// 2.95.x :: hash_set +// 3.0.4 std ext/hash_set +// 3.1 __gnu_cxx ext/hash_set +// HP aCC6 std stdex/rw/hashset.h +// MS VC++ stdext hash_set + +#undef HAVE_GNU_EXT_HASH_SET +#undef HAVE_STD_EXT_HASH_SET +#undef HAVE_GLOBAL_HASH_SET +#undef HAVE_RW_STDEX_HASH_SET_H + +// GCC versions 3.1 and later put hash_set in <ext/hash_set> and in +// the __gnu_cxx namespace. +#if HAVE_GNU_EXT_HASH_SET +# include <ext/hash_set> +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE __gnu_cxx +# endif + +// GCC 3.0.x puts hash_set in <ext/hash_set> and in the std namespace. +#elif HAVE_STD_EXT_HASH_SET +# include <ext/hash_set> +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE std +# endif + +// Older compilers such as GCC before version 3.0 do not keep +// extensions in the `ext' directory, and ignore the `std' namespace. +#elif HAVE_GLOBAL_HASH_SET +# include <hash_set> +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE std +# endif + +// HP aCC doesn't include an SGI-like hash_set. For this platform (or +// any others using Rogue Wave Software's Tools.h++ library), we wrap +// around them in std:: +#elif HAVE_RW_STDEX_HASH_SET_H +# include <rw/stdex/hashset.h> +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE std +# endif + +// Support Microsoft VC++. +#elif defined(_MSC_VER) +# include <hash_set> +# ifndef HASH_NAMESPACE +# define HASH_NAMESPACE stdext +# endif + +// Give a warning if we couldn't find it, instead of (or in addition to) +// randomly doing something dumb. +#else +# warning "Autoconfiguration failed to find the hash_set header file." +#endif + +// we wrap Rogue Wave Tools.h++ rw_hashset into something SGI-looking, here: +#ifdef HAVE_RW_STDEX_HASH_SET_H +namespace HASH_NAMESPACE { + +/* +template <class DataType> struct hash { + unsigned int operator()(const unsigned int& x) const { + return x; + } +}; +*/ + +template <typename ValueType, + class _HashFcn = hash<ValueType>, + class _EqualKey = equal_to<ValueType>, + class _A = allocator <ValueType> > +class hash_set : + public rw_hashset<ValueType, class _HashFcn, class _EqualKey, class _A> { +}; + +} // end HASH_NAMESPACE; +#endif + +using HASH_NAMESPACE::hash_set; + +// Include vector because ext/hash_set includes stl_vector.h and leaves +// out specializations like stl_bvector.h, causing link conflicts. +#include <vector> + +#include "llvm/ADT/HashExtras.h" + +#endif diff --git a/include/llvm/ADT/ilist b/include/llvm/ADT/ilist new file mode 100644 index 0000000..5ca8f45 --- /dev/null +++ b/include/llvm/ADT/ilist @@ -0,0 +1,586 @@ +//===-- llvm/ADT/ilist - Intrusive Linked List Template ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines classes to implement an intrusive doubly linked list class +// (i.e. each node of the list must contain a next and previous field for the +// list. +// +// The ilist_traits trait class is used to gain access to the next and previous +// fields of the node type that the list is instantiated with. If it is not +// specialized, the list defaults to using the getPrev(), getNext() method calls +// to get the next and previous pointers. +// +// The ilist class itself, should be a plug in replacement for list, assuming +// that the nodes contain next/prev pointers. This list replacement does not +// provides a constant time size() method, so be careful to use empty() when you +// really want to know if it's empty. +// +// The ilist class is implemented by allocating a 'tail' node when the list is +// created (using ilist_traits<>::createSentinel()). This tail node is +// absolutely required because the user must be able to compute end()-1. Because +// of this, users of the direct next/prev links will see an extra link on the +// end of the list, which should be ignored. +// +// Requirements for a user of this list: +// +// 1. The user must provide {g|s}et{Next|Prev} methods, or specialize +// ilist_traits to provide an alternate way of getting and setting next and +// prev links. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ILIST +#define LLVM_ADT_ILIST + +#include "llvm/ADT/iterator" +#include <cassert> + +namespace llvm { + +template<typename NodeTy, typename Traits> class iplist; +template<typename NodeTy> class ilist_iterator; + +// Template traits for intrusive list. By specializing this template class, you +// can change what next/prev fields are used to store the links... +template<typename NodeTy> +struct ilist_traits { + static NodeTy *getPrev(NodeTy *N) { return N->getPrev(); } + static NodeTy *getNext(NodeTy *N) { return N->getNext(); } + static const NodeTy *getPrev(const NodeTy *N) { return N->getPrev(); } + static const NodeTy *getNext(const NodeTy *N) { return N->getNext(); } + + static void setPrev(NodeTy *N, NodeTy *Prev) { N->setPrev(Prev); } + static void setNext(NodeTy *N, NodeTy *Next) { N->setNext(Next); } + + static NodeTy *createNode(const NodeTy &V) { return new NodeTy(V); } + + static NodeTy *createSentinel() { return new NodeTy(); } + static void destroySentinel(NodeTy *N) { delete N; } + + void addNodeToList(NodeTy *NTy) {} + void removeNodeFromList(NodeTy *NTy) {} + void transferNodesFromList(iplist<NodeTy, ilist_traits> &L2, + ilist_iterator<NodeTy> first, + ilist_iterator<NodeTy> last) {} +}; + +// Const traits are the same as nonconst traits... +template<typename Ty> +struct ilist_traits<const Ty> : public ilist_traits<Ty> {}; + + +//===----------------------------------------------------------------------===// +// ilist_iterator<Node> - Iterator for intrusive list. +// +template<typename NodeTy> +class ilist_iterator + : public bidirectional_iterator<NodeTy, ptrdiff_t> { + typedef ilist_traits<NodeTy> Traits; + typedef bidirectional_iterator<NodeTy, ptrdiff_t> super; + +public: + typedef size_t size_type; + typedef typename super::pointer pointer; + typedef typename super::reference reference; +private: + pointer NodePtr; +public: + + ilist_iterator(pointer NP) : NodePtr(NP) {} + ilist_iterator(reference NR) : NodePtr(&NR) {} + ilist_iterator() : NodePtr(0) {} + + // This is templated so that we can allow constructing a const iterator from + // a nonconst iterator... + template<class node_ty> + ilist_iterator(const ilist_iterator<node_ty> &RHS) + : NodePtr(RHS.getNodePtrUnchecked()) {} + + // This is templated so that we can allow assigning to a const iterator from + // a nonconst iterator... + template<class node_ty> + const ilist_iterator &operator=(const ilist_iterator<node_ty> &RHS) { + NodePtr = RHS.getNodePtrUnchecked(); + return *this; + } + + // Accessors... + operator pointer() const { + assert(Traits::getNext(NodePtr) != 0 && "Dereferencing end()!"); + return NodePtr; + } + + reference operator*() const { + assert(Traits::getNext(NodePtr) != 0 && "Dereferencing end()!"); + return *NodePtr; + } + pointer operator->() { return &operator*(); } + const pointer operator->() const { return &operator*(); } + + // Comparison operators + bool operator==(const ilist_iterator &RHS) const { + return NodePtr == RHS.NodePtr; + } + bool operator!=(const ilist_iterator &RHS) const { + return NodePtr != RHS.NodePtr; + } + + // Increment and decrement operators... + ilist_iterator &operator--() { // predecrement - Back up + NodePtr = Traits::getPrev(NodePtr); + assert(Traits::getNext(NodePtr) && "--'d off the beginning of an ilist!"); + return *this; + } + ilist_iterator &operator++() { // preincrement - Advance + NodePtr = Traits::getNext(NodePtr); + assert(NodePtr && "++'d off the end of an ilist!"); + return *this; + } + ilist_iterator operator--(int) { // postdecrement operators... + ilist_iterator tmp = *this; + --*this; + return tmp; + } + ilist_iterator operator++(int) { // postincrement operators... + ilist_iterator tmp = *this; + ++*this; + return tmp; + } + + // Internal interface, do not use... + pointer getNodePtrUnchecked() const { return NodePtr; } +}; + +// do not implement. this is to catch errors when people try to use +// them as random access iterators +template<typename T> +void operator-(int, ilist_iterator<T>); +template<typename T> +void operator-(ilist_iterator<T>,int); + +template<typename T> +void operator+(int, ilist_iterator<T>); +template<typename T> +void operator+(ilist_iterator<T>,int); + +// operator!=/operator== - Allow mixed comparisons without dereferencing +// the iterator, which could very likely be pointing to end(). +template<typename T> +bool operator!=(const T* LHS, const ilist_iterator<const T> &RHS) { + return LHS != RHS.getNodePtrUnchecked(); +} +template<typename T> +bool operator==(const T* LHS, const ilist_iterator<const T> &RHS) { + return LHS == RHS.getNodePtrUnchecked(); +} +template<typename T> +bool operator!=(T* LHS, const ilist_iterator<T> &RHS) { + return LHS != RHS.getNodePtrUnchecked(); +} +template<typename T> +bool operator==(T* LHS, const ilist_iterator<T> &RHS) { + return LHS == RHS.getNodePtrUnchecked(); +} + + +// Allow ilist_iterators to convert into pointers to a node automatically when +// used by the dyn_cast, cast, isa mechanisms... + +template<typename From> struct simplify_type; + +template<typename NodeTy> struct simplify_type<ilist_iterator<NodeTy> > { + typedef NodeTy* SimpleType; + + static SimpleType getSimplifiedValue(const ilist_iterator<NodeTy> &Node) { + return &*Node; + } +}; +template<typename NodeTy> struct simplify_type<const ilist_iterator<NodeTy> > { + typedef NodeTy* SimpleType; + + static SimpleType getSimplifiedValue(const ilist_iterator<NodeTy> &Node) { + return &*Node; + } +}; + + +//===----------------------------------------------------------------------===// +// +// iplist - The subset of list functionality that can safely be used on nodes of +// polymorphic types, i.e. a heterogenous list with a common base class that +// holds the next/prev pointers... +// +template<typename NodeTy, typename Traits=ilist_traits<NodeTy> > +class iplist : public Traits { + NodeTy *Head; + + // Use the prev node pointer of 'head' as the tail pointer. This is really a + // circularly linked list where we snip the 'next' link from the sentinel node + // back to the first node in the list (to preserve assertions about going off + // the end of the list). + NodeTy *getTail() { return getPrev(Head); } + const NodeTy *getTail() const { return getPrev(Head); } + void setTail(NodeTy *N) { setPrev(Head, N); } + + static bool op_less(NodeTy &L, NodeTy &R) { return L < R; } + static bool op_equal(NodeTy &L, NodeTy &R) { return L == R; } +public: + typedef NodeTy *pointer; + typedef const NodeTy *const_pointer; + typedef NodeTy &reference; + typedef const NodeTy &const_reference; + typedef NodeTy value_type; + typedef ilist_iterator<NodeTy> iterator; + typedef ilist_iterator<const NodeTy> const_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + + iplist() : Head(Traits::createSentinel()) { + setNext(Head, 0); + setTail(Head); + } + ~iplist() { clear(); Traits::destroySentinel(getTail()); } + + // Iterator creation methods. + iterator begin() { return iterator(Head); } + const_iterator begin() const { return const_iterator(Head); } + iterator end() { return iterator(getTail()); } + const_iterator end() const { return const_iterator(getTail()); } + + // reverse iterator creation methods. + reverse_iterator rbegin() { return reverse_iterator(end()); } + const_reverse_iterator rbegin() const{ return const_reverse_iterator(end()); } + reverse_iterator rend() { return reverse_iterator(begin()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } + + + // Miscellaneous inspection routines. + size_type max_size() const { return size_type(-1); } + bool empty() const { return Head == getTail(); } + + // Front and back accessor functions... + reference front() { + assert(!empty() && "Called front() on empty list!"); + return *Head; + } + const_reference front() const { + assert(!empty() && "Called front() on empty list!"); + return *Head; + } + reference back() { + assert(!empty() && "Called back() on empty list!"); + return *getPrev(getTail()); + } + const_reference back() const { + assert(!empty() && "Called back() on empty list!"); + return *getPrev(getTail()); + } + + void swap(iplist &RHS) { + abort(); // Swap does not use list traits callback correctly yet! + std::swap(Head, RHS.Head); + } + + iterator insert(iterator where, NodeTy *New) { + NodeTy *CurNode = where.getNodePtrUnchecked(), *PrevNode = getPrev(CurNode); + setNext(New, CurNode); + setPrev(New, PrevNode); + + if (CurNode != Head) // Is PrevNode off the beginning of the list? + setNext(PrevNode, New); + else + Head = New; + setPrev(CurNode, New); + + addNodeToList(New); // Notify traits that we added a node... + return New; + } + + NodeTy *remove(iterator &IT) { + assert(IT != end() && "Cannot remove end of list!"); + NodeTy *Node = &*IT; + NodeTy *NextNode = getNext(Node); + NodeTy *PrevNode = getPrev(Node); + + if (Node != Head) // Is PrevNode off the beginning of the list? + setNext(PrevNode, NextNode); + else + Head = NextNode; + setPrev(NextNode, PrevNode); + IT = NextNode; + removeNodeFromList(Node); // Notify traits that we removed a node... + return Node; + } + + NodeTy *remove(const iterator &IT) { + iterator MutIt = IT; + return remove(MutIt); + } + + // erase - remove a node from the controlled sequence... and delete it. + iterator erase(iterator where) { + delete remove(where); + return where; + } + + +private: + // transfer - The heart of the splice function. Move linked list nodes from + // [first, last) into position. + // + void transfer(iterator position, iplist &L2, iterator first, iterator last) { + assert(first != last && "Should be checked by callers"); + + if (position != last) { + // Note: we have to be careful about the case when we move the first node + // in the list. This node is the list sentinel node and we can't move it. + NodeTy *ThisSentinel = getTail(); + setTail(0); + NodeTy *L2Sentinel = L2.getTail(); + L2.setTail(0); + + // Remove [first, last) from its old position. + NodeTy *First = &*first, *Prev = getPrev(First); + NodeTy *Next = last.getNodePtrUnchecked(), *Last = getPrev(Next); + if (Prev) + setNext(Prev, Next); + else + L2.Head = Next; + setPrev(Next, Prev); + + // Splice [first, last) into its new position. + NodeTy *PosNext = position.getNodePtrUnchecked(); + NodeTy *PosPrev = getPrev(PosNext); + + // Fix head of list... + if (PosPrev) + setNext(PosPrev, First); + else + Head = First; + setPrev(First, PosPrev); + + // Fix end of list... + setNext(Last, PosNext); + setPrev(PosNext, Last); + + transferNodesFromList(L2, First, PosNext); + + // Now that everything is set, restore the pointers to the list sentinals. + L2.setTail(L2Sentinel); + setTail(ThisSentinel); + } + } + +public: + + //===----------------------------------------------------------------------=== + // Functionality derived from other functions defined above... + // + + size_type size() const { +#if __GNUC__ == 2 + // GCC 2.95 has a broken std::distance + size_type Result = 0; + std::distance(begin(), end(), Result); + return Result; +#else + return std::distance(begin(), end()); +#endif + } + + iterator erase(iterator first, iterator last) { + while (first != last) + first = erase(first); + return last; + } + + void clear() { erase(begin(), end()); } + + // Front and back inserters... + void push_front(NodeTy *val) { insert(begin(), val); } + void push_back(NodeTy *val) { insert(end(), val); } + void pop_front() { + assert(!empty() && "pop_front() on empty list!"); + erase(begin()); + } + void pop_back() { + assert(!empty() && "pop_back() on empty list!"); + iterator t = end(); erase(--t); + } + + // Special forms of insert... + template<class InIt> void insert(iterator where, InIt first, InIt last) { + for (; first != last; ++first) insert(where, *first); + } + + // Splice members - defined in terms of transfer... + void splice(iterator where, iplist &L2) { + if (!L2.empty()) + transfer(where, L2, L2.begin(), L2.end()); + } + void splice(iterator where, iplist &L2, iterator first) { + iterator last = first; ++last; + if (where == first || where == last) return; // No change + transfer(where, L2, first, last); + } + void splice(iterator where, iplist &L2, iterator first, iterator last) { + if (first != last) transfer(where, L2, first, last); + } + + + + //===----------------------------------------------------------------------=== + // High-Level Functionality that shouldn't really be here, but is part of list + // + + // These two functions are actually called remove/remove_if in list<>, but + // they actually do the job of erase, rename them accordingly. + // + void erase(const NodeTy &val) { + for (iterator I = begin(), E = end(); I != E; ) { + iterator next = I; ++next; + if (*I == val) erase(I); + I = next; + } + } + template<class Pr1> void erase_if(Pr1 pred) { + for (iterator I = begin(), E = end(); I != E; ) { + iterator next = I; ++next; + if (pred(*I)) erase(I); + I = next; + } + } + + template<class Pr2> void unique(Pr2 pred) { + if (empty()) return; + for (iterator I = begin(), E = end(), Next = begin(); ++Next != E;) { + if (pred(*I)) + erase(Next); + else + I = Next; + Next = I; + } + } + void unique() { unique(op_equal); } + + template<class Pr3> void merge(iplist &right, Pr3 pred) { + iterator first1 = begin(), last1 = end(); + iterator first2 = right.begin(), last2 = right.end(); + while (first1 != last1 && first2 != last2) + if (pred(*first2, *first1)) { + iterator next = first2; + transfer(first1, right, first2, ++next); + first2 = next; + } else { + ++first1; + } + if (first2 != last2) transfer(last1, right, first2, last2); + } + void merge(iplist &right) { return merge(right, op_less); } + + template<class Pr3> void sort(Pr3 pred); + void sort() { sort(op_less); } + void reverse(); +}; + + +template<typename NodeTy> +struct ilist : public iplist<NodeTy> { + typedef typename iplist<NodeTy>::size_type size_type; + typedef typename iplist<NodeTy>::iterator iterator; + + ilist() {} + ilist(const ilist &right) { + insert(this->begin(), right.begin(), right.end()); + } + explicit ilist(size_type count) { + insert(this->begin(), count, NodeTy()); + } + ilist(size_type count, const NodeTy &val) { + insert(this->begin(), count, val); + } + template<class InIt> ilist(InIt first, InIt last) { + insert(this->begin(), first, last); + } + + + // Forwarding functions: A workaround for GCC 2.95 which does not correctly + // support 'using' declarations to bring a hidden member into scope. + // + iterator insert(iterator a, NodeTy *b){ return iplist<NodeTy>::insert(a, b); } + void push_front(NodeTy *a) { iplist<NodeTy>::push_front(a); } + void push_back(NodeTy *a) { iplist<NodeTy>::push_back(a); } + + + // Main implementation here - Insert for a node passed by value... + iterator insert(iterator where, const NodeTy &val) { + return insert(where, createNode(val)); + } + + + // Front and back inserters... + void push_front(const NodeTy &val) { insert(this->begin(), val); } + void push_back(const NodeTy &val) { insert(this->end(), val); } + + // Special forms of insert... + template<class InIt> void insert(iterator where, InIt first, InIt last) { + for (; first != last; ++first) insert(where, *first); + } + void insert(iterator where, size_type count, const NodeTy &val) { + for (; count != 0; --count) insert(where, val); + } + + // Assign special forms... + void assign(size_type count, const NodeTy &val) { + iterator I = this->begin(); + for (; I != this->end() && count != 0; ++I, --count) + *I = val; + if (count != 0) + insert(this->end(), val, val); + else + erase(I, this->end()); + } + template<class InIt> void assign(InIt first1, InIt last1) { + iterator first2 = this->begin(), last2 = this->end(); + for ( ; first1 != last1 && first2 != last2; ++first1, ++first2) + *first1 = *first2; + if (first2 == last2) + erase(first1, last1); + else + insert(last1, first2, last2); + } + + + // Resize members... + void resize(size_type newsize, NodeTy val) { + iterator i = this->begin(); + size_type len = 0; + for ( ; i != this->end() && len < newsize; ++i, ++len) /* empty*/ ; + + if (len == newsize) + erase(i, this->end()); + else // i == end() + insert(this->end(), newsize - len, val); + } + void resize(size_type newsize) { resize(newsize, NodeTy()); } +}; + +} // End llvm namespace + +namespace std { + // Ensure that swap uses the fast list swap... + template<class Ty> + void swap(llvm::iplist<Ty> &Left, llvm::iplist<Ty> &Right) { + Left.swap(Right); + } +} // End 'std' extensions... + +#endif diff --git a/include/llvm/ADT/iterator.in b/include/llvm/ADT/iterator.in new file mode 100644 index 0000000..47f70d1 --- /dev/null +++ b/include/llvm/ADT/iterator.in @@ -0,0 +1,76 @@ +//===-- llvm/ADT/iterator - Portable wrapper around <iterator> --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a wrapper around the mysterious <iterator> header file. +// In GCC 2.95.3, the file defines a bidirectional_iterator class (and other +// friends), instead of the standard iterator class. In GCC 3.1, the +// bidirectional_iterator class got moved out and the new, standards compliant, +// iterator<> class was added. Because there is nothing that we can do to get +// correct behavior on both compilers, we have this header with #ifdef's. Gross +// huh? +// +// By #includ'ing this file, you get the contents of <iterator> plus the +// following classes in the global namespace: +// +// 1. bidirectional_iterator +// 2. forward_iterator +// +// The #if directives' expressions are filled in by Autoconf. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ADT_ITERATOR +#define LLVM_ADT_ITERATOR + +#include <iterator> + +#undef HAVE_BI_ITERATOR +#undef HAVE_STD_ITERATOR +#undef HAVE_FWD_ITERATOR + +#ifdef _MSC_VER +# define HAVE_BI_ITERATOR 0 +# define HAVE_STD_ITERATOR 1 +# define HAVE_FWD_ITERATOR 0 +#endif + +#if !HAVE_BI_ITERATOR +# if HAVE_STD_ITERATOR +/// If the bidirectional iterator is not defined, we attempt to define it in +/// terms of the C++ standard iterator. Otherwise, we import it with a "using" +/// statement. +/// +template<class Ty, class PtrDiffTy> +struct bidirectional_iterator + : public std::iterator<std::bidirectional_iterator_tag, Ty, PtrDiffTy> { +}; +# else +# error "Need to have standard iterator to define bidirectional iterator!" +# endif +#else +using std::bidirectional_iterator; +#endif + +#if !HAVE_FWD_ITERATOR +# if HAVE_STD_ITERATOR +/// If the forward iterator is not defined, attempt to define it in terms of +/// the C++ standard iterator. Otherwise, we import it with a "using" statement. +/// +template<class Ty, class PtrDiffTy> +struct forward_iterator + : public std::iterator<std::forward_iterator_tag, Ty, PtrDiffTy> { +}; +# else +# error "Need to have standard iterator to define forward iterator!" +# endif +#else +using std::forward_iterator; +#endif + +#endif diff --git a/include/llvm/AbstractTypeUser.h b/include/llvm/AbstractTypeUser.h new file mode 100644 index 0000000..2b643ab --- /dev/null +++ b/include/llvm/AbstractTypeUser.h @@ -0,0 +1,179 @@ +//===-- llvm/AbstractTypeUser.h - AbstractTypeUser Interface ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the AbstractTypeUser class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ABSTRACT_TYPE_USER_H +#define LLVM_ABSTRACT_TYPE_USER_H + +#if !defined(LLVM_TYPE_H) && !defined(LLVM_VALUE_H) +#error Do not include this file directly. Include Type.h instead. +#error Some versions of GCC (e.g. 3.4 and 4.1) can not handle the inlined method +#error PATypeHolder::dropRef() correctly otherwise. +#endif + +// This is the "master" include for <cassert> Whether this file needs it or not, +// it must always include <cassert> for the files which include +// llvm/AbstractTypeUser.h +// +// In this way, most every LLVM source file will have access to the assert() +// macro without having to #include <cassert> directly. +// +#include <cassert> + +namespace llvm { + +class Type; +class DerivedType; + +/// The AbstractTypeUser class is an interface to be implemented by classes who +/// could possibly use an abstract type. Abstract types are denoted by the +/// isAbstract flag set to true in the Type class. These are classes that +/// contain an Opaque type in their structure somewhere. +/// +/// Classes must implement this interface so that they may be notified when an +/// abstract type is resolved. Abstract types may be resolved into more +/// concrete types through: linking, parsing, and bitcode reading. When this +/// happens, all of the users of the type must be updated to reference the new, +/// more concrete type. They are notified through the AbstractTypeUser +/// interface. +/// +/// In addition to this, AbstractTypeUsers must keep the use list of the +/// potentially abstract type that they reference up-to-date. To do this in a +/// nice, transparent way, the PATypeHandle class is used to hold "Potentially +/// Abstract Types", and keep the use list of the abstract types up-to-date. +/// @brief LLVM Abstract Type User Representation +class AbstractTypeUser { +protected: + virtual ~AbstractTypeUser(); // Derive from me +public: + + /// refineAbstractType - The callback method invoked when an abstract type is + /// resolved to another type. An object must override this method to update + /// its internal state to reference NewType instead of OldType. + /// + virtual void refineAbstractType(const DerivedType *OldTy, + const Type *NewTy) = 0; + + /// The other case which AbstractTypeUsers must be aware of is when a type + /// makes the transition from being abstract (where it has clients on it's + /// AbstractTypeUsers list) to concrete (where it does not). This method + /// notifies ATU's when this occurs for a type. + /// + virtual void typeBecameConcrete(const DerivedType *AbsTy) = 0; + + // for debugging... + virtual void dump() const = 0; +}; + + +/// PATypeHandle - Handle to a Type subclass. This class is used to keep the +/// use list of abstract types up-to-date. +/// +class PATypeHandle { + const Type *Ty; + AbstractTypeUser * const User; + + // These functions are defined at the bottom of Type.h. See the comment there + // for justification. + void addUser(); + void removeUser(); +public: + // ctor - Add use to type if abstract. Note that Ty must not be null + inline PATypeHandle(const Type *ty, AbstractTypeUser *user) + : Ty(ty), User(user) { + addUser(); + } + + // ctor - Add use to type if abstract. + inline PATypeHandle(const PATypeHandle &T) : Ty(T.Ty), User(T.User) { + addUser(); + } + + // dtor - Remove reference to type... + inline ~PATypeHandle() { removeUser(); } + + // Automatic casting operator so that the handle may be used naturally + inline operator Type *() const { return const_cast<Type*>(Ty); } + inline Type *get() const { return const_cast<Type*>(Ty); } + + // operator= - Allow assignment to handle + inline Type *operator=(const Type *ty) { + if (Ty != ty) { // Ensure we don't accidentally drop last ref to Ty + removeUser(); + Ty = ty; + addUser(); + } + return get(); + } + + // operator= - Allow assignment to handle + inline const Type *operator=(const PATypeHandle &T) { + return operator=(T.Ty); + } + + inline bool operator==(const Type *ty) { + return Ty == ty; + } + + // operator-> - Allow user to dereference handle naturally... + inline const Type *operator->() const { return Ty; } +}; + + +/// PATypeHolder - Holder class for a potentially abstract type. This uses +/// efficient union-find techniques to handle dynamic type resolution. Unless +/// you need to do custom processing when types are resolved, you should always +/// use PATypeHolders in preference to PATypeHandles. +/// +class PATypeHolder { + mutable const Type *Ty; +public: + PATypeHolder(const Type *ty) : Ty(ty) { + addRef(); + } + PATypeHolder(const PATypeHolder &T) : Ty(T.Ty) { + addRef(); + } + + ~PATypeHolder() { dropRef(); } + + operator Type *() const { return get(); } + Type *get() const; + + // operator-> - Allow user to dereference handle naturally... + Type *operator->() const { return get(); } + + // operator= - Allow assignment to handle + Type *operator=(const Type *ty) { + if (Ty != ty) { // Don't accidentally drop last ref to Ty. + dropRef(); + Ty = ty; + addRef(); + } + return get(); + } + Type *operator=(const PATypeHolder &H) { + return operator=(H.Ty); + } + + /// getRawType - This should only be used to implement the vmcore library. + /// + const Type *getRawType() const { return Ty; } + +private: + void addRef(); + void dropRef(); +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/AliasAnalysis.h b/include/llvm/Analysis/AliasAnalysis.h new file mode 100644 index 0000000..1cd6afc --- /dev/null +++ b/include/llvm/Analysis/AliasAnalysis.h @@ -0,0 +1,332 @@ +//===- llvm/Analysis/AliasAnalysis.h - Alias Analysis Interface -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the generic AliasAnalysis interface, which is used as the +// common interface used by all clients of alias analysis information, and +// implemented by all alias analysis implementations. Mod/Ref information is +// also captured by this interface. +// +// Implementations of this interface must implement the various virtual methods, +// which automatically provides functionality for the entire suite of client +// APIs. +// +// This API represents memory as a (Pointer, Size) pair. The Pointer component +// specifies the base memory address of the region, the Size specifies how large +// of an area is being queried. If Size is 0, two pointers only alias if they +// are exactly equal. If size is greater than zero, but small, the two pointers +// alias if the areas pointed to overlap. If the size is very large (ie, ~0U), +// then the two pointers alias if they may be pointing to components of the same +// memory object. Pointers that point to two completely different objects in +// memory never alias, regardless of the value of the Size component. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_ALIAS_ANALYSIS_H +#define LLVM_ANALYSIS_ALIAS_ANALYSIS_H + +#include "llvm/Support/CallSite.h" +#include "llvm/System/IncludeFile.h" +#include <vector> + +namespace llvm { + +class LoadInst; +class StoreInst; +class VAArgInst; +class TargetData; +class Pass; +class AnalysisUsage; + +class AliasAnalysis { +protected: + const TargetData *TD; + AliasAnalysis *AA; // Previous Alias Analysis to chain to. + + /// InitializeAliasAnalysis - Subclasses must call this method to initialize + /// the AliasAnalysis interface before any other methods are called. This is + /// typically called by the run* methods of these subclasses. This may be + /// called multiple times. + /// + void InitializeAliasAnalysis(Pass *P); + + // getAnalysisUsage - All alias analysis implementations should invoke this + // directly (using AliasAnalysis::getAnalysisUsage(AU)) to make sure that + // TargetData is required by the pass. + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + +public: + static char ID; // Class identification, replacement for typeinfo + AliasAnalysis() : TD(0), AA(0) {} + virtual ~AliasAnalysis(); // We want to be subclassed + + /// getTargetData - Every alias analysis implementation depends on the size of + /// data items in the current Target. This provides a uniform way to handle + /// it. + /// + const TargetData &getTargetData() const { return *TD; } + + //===--------------------------------------------------------------------===// + /// Alias Queries... + /// + + /// Alias analysis result - Either we know for sure that it does not alias, we + /// know for sure it must alias, or we don't know anything: The two pointers + /// _might_ alias. This enum is designed so you can do things like: + /// if (AA.alias(P1, P2)) { ... } + /// to check to see if two pointers might alias. + /// + enum AliasResult { NoAlias = 0, MayAlias = 1, MustAlias = 2 }; + + /// alias - The main low level interface to the alias analysis implementation. + /// Returns a Result indicating whether the two pointers are aliased to each + /// other. This is the interface that must be implemented by specific alias + /// analysis implementations. + /// + virtual AliasResult alias(const Value *V1, unsigned V1Size, + const Value *V2, unsigned V2Size); + + /// getMustAliases - If there are any pointers known that must alias this + /// pointer, return them now. This allows alias-set based alias analyses to + /// perform a form a value numbering (which is exposed by load-vn). If an + /// alias analysis supports this, it should ADD any must aliased pointers to + /// the specified vector. + /// + virtual void getMustAliases(Value *P, std::vector<Value*> &RetVals); + + /// pointsToConstantMemory - If the specified pointer is known to point into + /// constant global memory, return true. This allows disambiguation of store + /// instructions from constant pointers. + /// + virtual bool pointsToConstantMemory(const Value *P); + + //===--------------------------------------------------------------------===// + /// Simple mod/ref information... + /// + + /// ModRefResult - Represent the result of a mod/ref query. Mod and Ref are + /// bits which may be or'd together. + /// + enum ModRefResult { NoModRef = 0, Ref = 1, Mod = 2, ModRef = 3 }; + + + /// ModRefBehavior - Summary of how a function affects memory in the program. + /// Loads from constant globals are not considered memory accesses for this + /// interface. Also, functions may freely modify stack space local to their + /// invocation without having to report it through these interfaces. + enum ModRefBehavior { + // DoesNotAccessMemory - This function does not perform any non-local loads + // or stores to memory. + // + // This property corresponds to the GCC 'const' attribute. + DoesNotAccessMemory, + + // AccessesArguments - This function accesses function arguments in + // non-volatile and well known ways, but does not access any other memory. + // + // Clients may call getArgumentAccesses to get specific information about + // how pointer arguments are used. + AccessesArguments, + + // AccessesArgumentsAndGlobals - This function has accesses function + // arguments and global variables in non-volatile and well-known ways, but + // does not access any other memory. + // + // Clients may call getArgumentAccesses to get specific information about + // how pointer arguments and globals are used. + AccessesArgumentsAndGlobals, + + // OnlyReadsMemory - This function does not perform any non-local stores or + // volatile loads, but may read from any memory location. + // + // This property corresponds to the GCC 'pure' attribute. + OnlyReadsMemory, + + // UnknownModRefBehavior - This indicates that the function could not be + // classified into one of the behaviors above. + UnknownModRefBehavior + }; + + /// PointerAccessInfo - This struct is used to return results for pointers, + /// globals, and the return value of a function. + struct PointerAccessInfo { + /// V - The value this record corresponds to. This may be an Argument for + /// the function, a GlobalVariable, or null, corresponding to the return + /// value for the function. + Value *V; + + /// ModRefInfo - Whether the pointer is loaded or stored to/from. + /// + ModRefResult ModRefInfo; + + /// AccessType - Specific fine-grained access information for the argument. + /// If none of these classifications is general enough, the + /// getModRefBehavior method should not return AccessesArguments*. If a + /// record is not returned for a particular argument, the argument is never + /// dead and never dereferenced. + enum AccessType { + /// ScalarAccess - The pointer is dereferenced. + /// + ScalarAccess, + + /// ArrayAccess - The pointer is indexed through as an array of elements. + /// + ArrayAccess, + + /// ElementAccess ?? P->F only? + + /// CallsThrough - Indirect calls are made through the specified function + /// pointer. + CallsThrough + }; + }; + + /// getModRefBehavior - Return the behavior of the specified function if + /// called from the specified call site. The call site may be null in which + /// case the most generic behavior of this function should be returned. + virtual ModRefBehavior getModRefBehavior(Function *F, CallSite CS, + std::vector<PointerAccessInfo> *Info = 0); + + /// doesNotAccessMemory - If the specified function is known to never read or + /// write memory, return true. If the function only reads from known-constant + /// memory, it is also legal to return true. Functions that unwind the stack + /// are not legal for this predicate. + /// + /// Many optimizations (such as CSE and LICM) can be performed on calls to it, + /// without worrying about aliasing properties, and many functions have this + /// property (e.g. 'sin' and 'cos'). + /// + /// This property corresponds to the GCC 'const' attribute. + /// + bool doesNotAccessMemory(Function *F) { + return getModRefBehavior(F, CallSite()) == DoesNotAccessMemory; + } + + /// onlyReadsMemory - If the specified function is known to only read from + /// non-volatile memory (or not access memory at all), return true. Functions + /// that unwind the stack are not legal for this predicate. + /// + /// This property allows many common optimizations to be performed in the + /// absence of interfering store instructions, such as CSE of strlen calls. + /// + /// This property corresponds to the GCC 'pure' attribute. + /// + bool onlyReadsMemory(Function *F) { + /// FIXME: If the analysis returns more precise info, we can reduce it to + /// this. + ModRefBehavior MRB = getModRefBehavior(F, CallSite()); + return MRB == DoesNotAccessMemory || MRB == OnlyReadsMemory; + } + + + /// getModRefInfo - Return information about whether or not an instruction may + /// read or write memory specified by the pointer operand. An instruction + /// that doesn't read or write memory may be trivially LICM'd for example. + + /// getModRefInfo (for call sites) - Return whether information about whether + /// a particular call site modifies or reads the memory specified by the + /// pointer. + /// + virtual ModRefResult getModRefInfo(CallSite CS, Value *P, unsigned Size); + + /// getModRefInfo - Return information about whether two call sites may refer + /// to the same set of memory locations. This function returns NoModRef if + /// the two calls refer to disjoint memory locations, Ref if CS1 reads memory + /// written by CS2, Mod if CS1 writes to memory read or written by CS2, or + /// ModRef if CS1 might read or write memory accessed by CS2. + /// + virtual ModRefResult getModRefInfo(CallSite CS1, CallSite CS2); + + /// hasNoModRefInfoForCalls - Return true if the analysis has no mod/ref + /// information for pairs of function calls (other than "pure" and "const" + /// functions). This can be used by clients to avoid many pointless queries. + /// Remember that if you override this and chain to another analysis, you must + /// make sure that it doesn't have mod/ref info either. + /// + virtual bool hasNoModRefInfoForCalls() const; + + /// Convenience functions... + ModRefResult getModRefInfo(LoadInst *L, Value *P, unsigned Size); + ModRefResult getModRefInfo(StoreInst *S, Value *P, unsigned Size); + ModRefResult getModRefInfo(CallInst *C, Value *P, unsigned Size) { + return getModRefInfo(CallSite(C), P, Size); + } + ModRefResult getModRefInfo(InvokeInst *I, Value *P, unsigned Size) { + return getModRefInfo(CallSite(I), P, Size); + } + ModRefResult getModRefInfo(VAArgInst* I, Value* P, unsigned Size) { + return AliasAnalysis::Mod; + } + ModRefResult getModRefInfo(Instruction *I, Value *P, unsigned Size) { + switch (I->getOpcode()) { + case Instruction::VAArg: return getModRefInfo((VAArgInst*)I, P, Size); + case Instruction::Load: return getModRefInfo((LoadInst*)I, P, Size); + case Instruction::Store: return getModRefInfo((StoreInst*)I, P, Size); + case Instruction::Call: return getModRefInfo((CallInst*)I, P, Size); + case Instruction::Invoke: return getModRefInfo((InvokeInst*)I, P, Size); + default: return NoModRef; + } + } + + //===--------------------------------------------------------------------===// + /// Higher level methods for querying mod/ref information. + /// + + /// canBasicBlockModify - Return true if it is possible for execution of the + /// specified basic block to modify the value pointed to by Ptr. + /// + bool canBasicBlockModify(const BasicBlock &BB, const Value *P, unsigned Size); + + /// canInstructionRangeModify - Return true if it is possible for the + /// execution of the specified instructions to modify the value pointed to by + /// Ptr. The instructions to consider are all of the instructions in the + /// range of [I1,I2] INCLUSIVE. I1 and I2 must be in the same basic block. + /// + bool canInstructionRangeModify(const Instruction &I1, const Instruction &I2, + const Value *Ptr, unsigned Size); + + //===--------------------------------------------------------------------===// + /// Methods that clients should call when they transform the program to allow + /// alias analyses to update their internal data structures. Note that these + /// methods may be called on any instruction, regardless of whether or not + /// they have pointer-analysis implications. + /// + + /// deleteValue - This method should be called whenever an LLVM Value is + /// deleted from the program, for example when an instruction is found to be + /// redundant and is eliminated. + /// + virtual void deleteValue(Value *V); + + /// copyValue - This method should be used whenever a preexisting value in the + /// program is copied or cloned, introducing a new value. Note that analysis + /// implementations should tolerate clients that use this method to introduce + /// the same value multiple times: if the analysis already knows about a + /// value, it should ignore the request. + /// + virtual void copyValue(Value *From, Value *To); + + /// replaceWithNewValue - This method is the obvious combination of the two + /// above, and it provided as a helper to simplify client code. + /// + void replaceWithNewValue(Value *Old, Value *New) { + copyValue(Old, New); + deleteValue(Old); + } +}; + +} // End llvm namespace + +// Because of the way .a files work, we must force the BasicAA implementation to +// be pulled in if the AliasAnalysis header is included. Otherwise we run +// the risk of AliasAnalysis being used, but the default implementation not +// being linked into the tool that uses it. +FORCE_DEFINING_FILE_TO_BE_LINKED(AliasAnalysis) +FORCE_DEFINING_FILE_TO_BE_LINKED(BasicAliasAnalysis) + +#endif diff --git a/include/llvm/Analysis/AliasSetTracker.h b/include/llvm/Analysis/AliasSetTracker.h new file mode 100644 index 0000000..cd6450f --- /dev/null +++ b/include/llvm/Analysis/AliasSetTracker.h @@ -0,0 +1,392 @@ +//===- llvm/Analysis/AliasSetTracker.h - Build Alias Sets -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines two classes: AliasSetTracker and AliasSet. These interface +// are used to classify a collection of pointer references into a maximal number +// of disjoint sets. Each AliasSet object constructed by the AliasSetTracker +// object refers to memory disjoint from the other sets. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_ALIASSETTRACKER_H +#define LLVM_ANALYSIS_ALIASSETTRACKER_H + +#include "llvm/Support/CallSite.h" +#include "llvm/Support/Streams.h" +#include "llvm/ADT/iterator" +#include "llvm/ADT/hash_map" +#include "llvm/ADT/ilist" + +namespace llvm { + +class AliasAnalysis; +class LoadInst; +class StoreInst; +class FreeInst; +class AliasSetTracker; +class AliasSet; + +class AliasSet { + friend class AliasSetTracker; + + class PointerRec; + typedef std::pair<Value* const, PointerRec> HashNodePair; + + class PointerRec { + HashNodePair **PrevInList, *NextInList; + AliasSet *AS; + unsigned Size; + public: + PointerRec() : PrevInList(0), NextInList(0), AS(0), Size(0) {} + + HashNodePair *getNext() const { return NextInList; } + bool hasAliasSet() const { return AS != 0; } + + HashNodePair** setPrevInList(HashNodePair **PIL) { + PrevInList = PIL; + return &NextInList; + } + + void updateSize(unsigned NewSize) { + if (NewSize > Size) Size = NewSize; + } + + unsigned getSize() const { return Size; } + + AliasSet *getAliasSet(AliasSetTracker &AST) { + assert(AS && "No AliasSet yet!"); + if (AS->Forward) { + AliasSet *OldAS = AS; + AS = OldAS->getForwardedTarget(AST); + AS->addRef(); + OldAS->dropRef(AST); + } + return AS; + } + + void setAliasSet(AliasSet *as) { + assert(AS == 0 && "Already have an alias set!"); + AS = as; + } + + void removeFromList() { + if (NextInList) NextInList->second.PrevInList = PrevInList; + *PrevInList = NextInList; + if (AS->PtrListEnd == &NextInList) { + AS->PtrListEnd = PrevInList; + assert(*AS->PtrListEnd == 0 && "List not terminated right!"); + } + } + }; + + HashNodePair *PtrList, **PtrListEnd; // Doubly linked list of nodes + AliasSet *Forward; // Forwarding pointer + AliasSet *Next, *Prev; // Doubly linked list of AliasSets + + std::vector<CallSite> CallSites; // All calls & invokes in this node + + // RefCount - Number of nodes pointing to this AliasSet plus the number of + // AliasSets forwarding to it. + unsigned RefCount : 28; + + /// AccessType - Keep track of whether this alias set merely refers to the + /// locations of memory, whether it modifies the memory, or whether it does + /// both. The lattice goes from "NoModRef" to either Refs or Mods, then to + /// ModRef as necessary. + /// + enum AccessType { + NoModRef = 0, Refs = 1, // Ref = bit 1 + Mods = 2, ModRef = 3 // Mod = bit 2 + }; + unsigned AccessTy : 2; + + /// AliasType - Keep track the relationships between the pointers in the set. + /// Lattice goes from MustAlias to MayAlias. + /// + enum AliasType { + MustAlias = 0, MayAlias = 1 + }; + unsigned AliasTy : 1; + + // Volatile - True if this alias set contains volatile loads or stores. + bool Volatile : 1; + + friend struct ilist_traits<AliasSet>; + AliasSet *getPrev() const { return Prev; } + AliasSet *getNext() const { return Next; } + void setPrev(AliasSet *P) { Prev = P; } + void setNext(AliasSet *N) { Next = N; } + + void addRef() { ++RefCount; } + void dropRef(AliasSetTracker &AST) { + assert(RefCount >= 1 && "Invalid reference count detected!"); + if (--RefCount == 0) + removeFromTracker(AST); + } + +public: + /// Accessors... + bool isRef() const { return AccessTy & Refs; } + bool isMod() const { return AccessTy & Mods; } + bool isMustAlias() const { return AliasTy == MustAlias; } + bool isMayAlias() const { return AliasTy == MayAlias; } + + // isVolatile - Return true if this alias set contains volatile loads or + // stores. + bool isVolatile() const { return Volatile; } + + /// isForwardingAliasSet - Return true if this alias set should be ignored as + /// part of the AliasSetTracker object. + bool isForwardingAliasSet() const { return Forward; } + + /// mergeSetIn - Merge the specified alias set into this alias set... + /// + void mergeSetIn(AliasSet &AS, AliasSetTracker &AST); + + // Alias Set iteration - Allow access to all of the pointer which are part of + // this alias set... + class iterator; + iterator begin() const { return iterator(PtrList); } + iterator end() const { return iterator(); } + bool empty() const { return PtrList == 0; } + + void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + void dump() const; + + /// Define an iterator for alias sets... this is just a forward iterator. + class iterator : public forward_iterator<HashNodePair, ptrdiff_t> { + HashNodePair *CurNode; + public: + iterator(HashNodePair *CN = 0) : CurNode(CN) {} + + bool operator==(const iterator& x) const { + return CurNode == x.CurNode; + } + bool operator!=(const iterator& x) const { return !operator==(x); } + + const iterator &operator=(const iterator &I) { + CurNode = I.CurNode; + return *this; + } + + value_type &operator*() const { + assert(CurNode && "Dereferencing AliasSet.end()!"); + return *CurNode; + } + value_type *operator->() const { return &operator*(); } + + Value *getPointer() const { return CurNode->first; } + unsigned getSize() const { return CurNode->second.getSize(); } + + iterator& operator++() { // Preincrement + assert(CurNode && "Advancing past AliasSet.end()!"); + CurNode = CurNode->second.getNext(); + return *this; + } + iterator operator++(int) { // Postincrement + iterator tmp = *this; ++*this; return tmp; + } + }; + +private: + // Can only be created by AliasSetTracker + AliasSet() : PtrList(0), PtrListEnd(&PtrList), Forward(0), RefCount(0), + AccessTy(NoModRef), AliasTy(MustAlias), Volatile(false) { + } + + AliasSet(const AliasSet &AS) { + assert(0 && "Copy ctor called!?!?!"); + abort(); + } + + HashNodePair *getSomePointer() const { + return PtrList; + } + + /// getForwardedTarget - Return the real alias set this represents. If this + /// has been merged with another set and is forwarding, return the ultimate + /// destination set. This also implements the union-find collapsing as well. + AliasSet *getForwardedTarget(AliasSetTracker &AST) { + if (!Forward) return this; + + AliasSet *Dest = Forward->getForwardedTarget(AST); + if (Dest != Forward) { + Dest->addRef(); + Forward->dropRef(AST); + Forward = Dest; + } + return Dest; + } + + void removeFromTracker(AliasSetTracker &AST); + + void addPointer(AliasSetTracker &AST, HashNodePair &Entry, unsigned Size, + bool KnownMustAlias = false); + void addCallSite(CallSite CS, AliasAnalysis &AA); + void removeCallSite(CallSite CS) { + for (unsigned i = 0, e = CallSites.size(); i != e; ++i) + if (CallSites[i].getInstruction() == CS.getInstruction()) { + CallSites[i] = CallSites.back(); + CallSites.pop_back(); + } + } + void setVolatile() { Volatile = true; } + + /// aliasesPointer - Return true if the specified pointer "may" (or must) + /// alias one of the members in the set. + /// + bool aliasesPointer(const Value *Ptr, unsigned Size, AliasAnalysis &AA) const; + bool aliasesCallSite(CallSite CS, AliasAnalysis &AA) const; +}; + +inline std::ostream& operator<<(std::ostream &OS, const AliasSet &AS) { + AS.print(OS); + return OS; +} + + +class AliasSetTracker { + AliasAnalysis &AA; + ilist<AliasSet> AliasSets; + + // Map from pointers to their node + hash_map<Value*, AliasSet::PointerRec> PointerMap; +public: + /// AliasSetTracker ctor - Create an empty collection of AliasSets, and use + /// the specified alias analysis object to disambiguate load and store + /// addresses. + AliasSetTracker(AliasAnalysis &aa) : AA(aa) {} + + /// add methods - These methods are used to add different types of + /// instructions to the alias sets. Adding a new instruction can result in + /// one of three actions happening: + /// + /// 1. If the instruction doesn't alias any other sets, create a new set. + /// 2. If the instruction aliases exactly one set, add it to the set + /// 3. If the instruction aliases multiple sets, merge the sets, and add + /// the instruction to the result. + /// + /// These methods return true if inserting the instruction resulted in the + /// addition of a new alias set (i.e., the pointer did not alias anything). + /// + bool add(Value *Ptr, unsigned Size); // Add a location + bool add(LoadInst *LI); + bool add(StoreInst *SI); + bool add(FreeInst *FI); + bool add(CallSite CS); // Call/Invoke instructions + bool add(CallInst *CI) { return add(CallSite(CI)); } + bool add(InvokeInst *II) { return add(CallSite(II)); } + bool add(Instruction *I); // Dispatch to one of the other add methods... + void add(BasicBlock &BB); // Add all instructions in basic block + void add(const AliasSetTracker &AST); // Add alias relations from another AST + + /// remove methods - These methods are used to remove all entries that might + /// be aliased by the specified instruction. These methods return true if any + /// alias sets were eliminated. + bool remove(Value *Ptr, unsigned Size); // Remove a location + bool remove(LoadInst *LI); + bool remove(StoreInst *SI); + bool remove(FreeInst *FI); + bool remove(CallSite CS); + bool remove(CallInst *CI) { return remove(CallSite(CI)); } + bool remove(InvokeInst *II) { return remove(CallSite(II)); } + bool remove(Instruction *I); + void remove(AliasSet &AS); + + void clear() { + PointerMap.clear(); + AliasSets.clear(); + } + + /// getAliasSets - Return the alias sets that are active. + /// + const ilist<AliasSet> &getAliasSets() const { return AliasSets; } + + /// getAliasSetForPointer - Return the alias set that the specified pointer + /// lives in. If the New argument is non-null, this method sets the value to + /// true if a new alias set is created to contain the pointer (because the + /// pointer didn't alias anything). + AliasSet &getAliasSetForPointer(Value *P, unsigned Size, bool *New = 0); + + /// getAliasSetForPointerIfExists - Return the alias set containing the + /// location specified if one exists, otherwise return null. + AliasSet *getAliasSetForPointerIfExists(Value *P, unsigned Size) { + return findAliasSetForPointer(P, Size); + } + + /// containsPointer - Return true if the specified location is represented by + /// this alias set, false otherwise. This does not modify the AST object or + /// alias sets. + bool containsPointer(Value *P, unsigned Size) const; + + /// getAliasAnalysis - Return the underlying alias analysis object used by + /// this tracker. + AliasAnalysis &getAliasAnalysis() const { return AA; } + + /// deleteValue method - This method is used to remove a pointer value from + /// the AliasSetTracker entirely. It should be used when an instruction is + /// deleted from the program to update the AST. If you don't use this, you + /// would have dangling pointers to deleted instructions. + /// + void deleteValue(Value *PtrVal); + + /// copyValue - This method should be used whenever a preexisting value in the + /// program is copied or cloned, introducing a new value. Note that it is ok + /// for clients that use this method to introduce the same value multiple + /// times: if the tracker already knows about a value, it will ignore the + /// request. + /// + void copyValue(Value *From, Value *To); + + + typedef ilist<AliasSet>::iterator iterator; + typedef ilist<AliasSet>::const_iterator const_iterator; + + const_iterator begin() const { return AliasSets.begin(); } + const_iterator end() const { return AliasSets.end(); } + + iterator begin() { return AliasSets.begin(); } + iterator end() { return AliasSets.end(); } + + void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + void dump() const; + +private: + friend class AliasSet; + void removeAliasSet(AliasSet *AS); + + AliasSet::HashNodePair &getEntryFor(Value *V) { + // Standard operator[], except that it returns the whole pair, not just + // ->second. + return *PointerMap.insert(AliasSet::HashNodePair(V, + AliasSet::PointerRec())).first; + } + + AliasSet &addPointer(Value *P, unsigned Size, AliasSet::AccessType E, + bool &NewSet) { + NewSet = false; + AliasSet &AS = getAliasSetForPointer(P, Size, &NewSet); + AS.AccessTy |= E; + return AS; + } + AliasSet *findAliasSetForPointer(const Value *Ptr, unsigned Size); + + AliasSet *findAliasSetForCallSite(CallSite CS); +}; + +inline std::ostream& operator<<(std::ostream &OS, const AliasSetTracker &AST) { + AST.print(OS); + return OS; +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/CFGPrinter.h b/include/llvm/Analysis/CFGPrinter.h new file mode 100644 index 0000000..3567db1 --- /dev/null +++ b/include/llvm/Analysis/CFGPrinter.h @@ -0,0 +1,24 @@ +//===-- CFGPrinter.h - CFG printer external interface ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines external functions that can be called to explicitly +// instantiate the CFG printer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CFGPRINTER_H +#define LLVM_ANALYSIS_CFGPRINTER_H + +namespace llvm { + class FunctionPass; + FunctionPass *createCFGPrinterPass (); + FunctionPass *createCFGOnlyPrinterPass (); +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/CallGraph.h b/include/llvm/Analysis/CallGraph.h new file mode 100644 index 0000000..4f4ce0e --- /dev/null +++ b/include/llvm/Analysis/CallGraph.h @@ -0,0 +1,315 @@ +//===- CallGraph.h - Build a Module's call graph ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This interface is used to build and manipulate a call graph, which is a very +// useful tool for interprocedural optimization. +// +// Every function in a module is represented as a node in the call graph. The +// callgraph node keeps track of which functions the are called by the function +// corresponding to the node. +// +// A call graph may contain nodes where the function that they correspond to is +// null. These 'external' nodes are used to represent control flow that is not +// represented (or analyzable) in the module. In particular, this analysis +// builds one external node such that: +// 1. All functions in the module without internal linkage will have edges +// from this external node, indicating that they could be called by +// functions outside of the module. +// 2. All functions whose address is used for something more than a direct +// call, for example being stored into a memory location will also have an +// edge from this external node. Since they may be called by an unknown +// caller later, they must be tracked as such. +// +// There is a second external node added for calls that leave this module. +// Functions have a call edge to the external node iff: +// 1. The function is external, reflecting the fact that they could call +// anything without internal linkage or that has its address taken. +// 2. The function contains an indirect function call. +// +// As an extension in the future, there may be multiple nodes with a null +// function. These will be used when we can prove (through pointer analysis) +// that an indirect call site can call only a specific set of functions. +// +// Because of these properties, the CallGraph captures a conservative superset +// of all of the caller-callee relationships, which is useful for +// transformations. +// +// The CallGraph class also attempts to figure out what the root of the +// CallGraph is, which it currently does by looking for a function named 'main'. +// If no function named 'main' is found, the external node is used as the entry +// node, reflecting the fact that any function without internal linkage could +// be called into (which is common for libraries). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CALLGRAPH_H +#define LLVM_ANALYSIS_CALLGRAPH_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Pass.h" +#include "llvm/Support/CallSite.h" + +namespace llvm { + +class Function; +class Module; +class CallGraphNode; + +//===----------------------------------------------------------------------===// +// CallGraph class definition +// +class CallGraph { +protected: + Module *Mod; // The module this call graph represents + + typedef std::map<const Function *, CallGraphNode *> FunctionMapTy; + FunctionMapTy FunctionMap; // Map from a function to its node + +public: + static char ID; // Class identification, replacement for typeinfo + //===--------------------------------------------------------------------- + // Accessors... + // + typedef FunctionMapTy::iterator iterator; + typedef FunctionMapTy::const_iterator const_iterator; + + /// getModule - Return the module the call graph corresponds to. + /// + Module &getModule() const { return *Mod; } + + inline iterator begin() { return FunctionMap.begin(); } + inline iterator end() { return FunctionMap.end(); } + inline const_iterator begin() const { return FunctionMap.begin(); } + inline const_iterator end() const { return FunctionMap.end(); } + + // Subscripting operators, return the call graph node for the provided + // function + inline const CallGraphNode *operator[](const Function *F) const { + const_iterator I = FunctionMap.find(F); + assert(I != FunctionMap.end() && "Function not in callgraph!"); + return I->second; + } + inline CallGraphNode *operator[](const Function *F) { + const_iterator I = FunctionMap.find(F); + assert(I != FunctionMap.end() && "Function not in callgraph!"); + return I->second; + } + + //Returns the CallGraphNode which is used to represent undetermined calls + // into the callgraph. Override this if you want behavioural inheritance. + virtual CallGraphNode* getExternalCallingNode() const { return 0; } + + //Return the root/main method in the module, or some other root node, such + // as the externalcallingnode. Overload these if you behavioural + // inheritance. + virtual CallGraphNode* getRoot() { return 0; } + virtual const CallGraphNode* getRoot() const { return 0; } + + //===--------------------------------------------------------------------- + // Functions to keep a call graph up to date with a function that has been + // modified. + // + + /// removeFunctionFromModule - Unlink the function from this module, returning + /// it. Because this removes the function from the module, the call graph + /// node is destroyed. This is only valid if the function does not call any + /// other functions (ie, there are no edges in it's CGN). The easiest way to + /// do this is to dropAllReferences before calling this. + /// + Function *removeFunctionFromModule(CallGraphNode *CGN); + Function *removeFunctionFromModule(Function *F) { + return removeFunctionFromModule((*this)[F]); + } + + /// changeFunction - This method changes the function associated with this + /// CallGraphNode, for use by transformations that need to change the + /// prototype of a Function (thus they must create a new Function and move the + /// old code over). + void changeFunction(Function *OldF, Function *NewF); + + /// getOrInsertFunction - This method is identical to calling operator[], but + /// it will insert a new CallGraphNode for the specified function if one does + /// not already exist. + CallGraphNode *getOrInsertFunction(const Function *F); + + //===--------------------------------------------------------------------- + // Pass infrastructure interface glue code... + // +protected: + CallGraph() {} + +public: + virtual ~CallGraph() { destroy(); } + + /// initialize - Call this method before calling other methods, + /// re/initializes the state of the CallGraph. + /// + void initialize(Module &M); + + virtual void print(std::ostream &o, const Module *M) const; + void print(std::ostream *o, const Module *M) const { if (o) print(*o, M); } + void dump() const; + + // stub - dummy function, just ignore it + static int stub; +protected: + + // destroy - Release memory for the call graph + virtual void destroy(); +}; + +//===----------------------------------------------------------------------===// +// CallGraphNode class definition +// +class CallGraphNode { + Function *F; + typedef std::pair<CallSite,CallGraphNode*> CallRecord; + std::vector<CallRecord> CalledFunctions; + + CallGraphNode(const CallGraphNode &); // Do not implement +public: + //===--------------------------------------------------------------------- + // Accessor methods... + // + + typedef std::vector<CallRecord>::iterator iterator; + typedef std::vector<CallRecord>::const_iterator const_iterator; + + // getFunction - Return the function that this call graph node represents... + Function *getFunction() const { return F; } + + inline iterator begin() { return CalledFunctions.begin(); } + inline iterator end() { return CalledFunctions.end(); } + inline const_iterator begin() const { return CalledFunctions.begin(); } + inline const_iterator end() const { return CalledFunctions.end(); } + inline unsigned size() const { return CalledFunctions.size(); } + + // Subscripting operator - Return the i'th called function... + // + CallGraphNode *operator[](unsigned i) const { + return CalledFunctions[i].second; + } + + /// dump - Print out this call graph node. + /// + void dump() const; + void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + + //===--------------------------------------------------------------------- + // Methods to keep a call graph up to date with a function that has been + // modified + // + + /// removeAllCalledFunctions - As the name implies, this removes all edges + /// from this CallGraphNode to any functions it calls. + void removeAllCalledFunctions() { + CalledFunctions.clear(); + } + + /// addCalledFunction add a function to the list of functions called by this + /// one. + void addCalledFunction(CallSite CS, CallGraphNode *M) { + CalledFunctions.push_back(std::make_pair(CS, M)); + } + + /// removeCallEdgeTo - This method removes a *single* edge to the specified + /// callee function. Note that this method takes linear time, so it should be + /// used sparingly. + void removeCallEdgeTo(CallGraphNode *Callee); + + /// removeAnyCallEdgeTo - This method removes any call edges from this node to + /// the specified callee function. This takes more time to execute than + /// removeCallEdgeTo, so it should not be used unless necessary. + void removeAnyCallEdgeTo(CallGraphNode *Callee); + + friend class CallGraph; + + // CallGraphNode ctor - Create a node for the specified function. + inline CallGraphNode(Function *f) : F(f) {} +}; + +//===----------------------------------------------------------------------===// +// GraphTraits specializations for call graphs so that they can be treated as +// graphs by the generic graph algorithms. +// + +// Provide graph traits for tranversing call graphs using standard graph +// traversals. +template <> struct GraphTraits<CallGraphNode*> { + typedef CallGraphNode NodeType; + + typedef std::pair<CallSite, CallGraphNode*> CGNPairTy; + typedef std::pointer_to_unary_function<CGNPairTy, CallGraphNode*> CGNDerefFun; + + static NodeType *getEntryNode(CallGraphNode *CGN) { return CGN; } + + typedef mapped_iterator<NodeType::iterator, CGNDerefFun> ChildIteratorType; + + static inline ChildIteratorType child_begin(NodeType *N) { + return map_iterator(N->begin(), CGNDerefFun(CGNDeref)); + } + static inline ChildIteratorType child_end (NodeType *N) { + return map_iterator(N->end(), CGNDerefFun(CGNDeref)); + } + + static CallGraphNode *CGNDeref(CGNPairTy P) { + return P.second; + } + +}; + +template <> struct GraphTraits<const CallGraphNode*> { + typedef const CallGraphNode NodeType; + typedef NodeType::const_iterator ChildIteratorType; + + static NodeType *getEntryNode(const CallGraphNode *CGN) { return CGN; } + static inline ChildIteratorType child_begin(NodeType *N) { return N->begin();} + static inline ChildIteratorType child_end (NodeType *N) { return N->end(); } +}; + +template<> struct GraphTraits<CallGraph*> : public GraphTraits<CallGraphNode*> { + static NodeType *getEntryNode(CallGraph *CGN) { + return CGN->getExternalCallingNode(); // Start at the external node! + } + typedef std::pair<const Function*, CallGraphNode*> PairTy; + typedef std::pointer_to_unary_function<PairTy, CallGraphNode&> DerefFun; + + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + typedef mapped_iterator<CallGraph::iterator, DerefFun> nodes_iterator; + static nodes_iterator nodes_begin(CallGraph *CG) { + return map_iterator(CG->begin(), DerefFun(CGdereference)); + } + static nodes_iterator nodes_end (CallGraph *CG) { + return map_iterator(CG->end(), DerefFun(CGdereference)); + } + + static CallGraphNode &CGdereference(PairTy P) { + return *P.second; + } +}; + +template<> struct GraphTraits<const CallGraph*> : + public GraphTraits<const CallGraphNode*> { + static NodeType *getEntryNode(const CallGraph *CGN) { + return CGN->getExternalCallingNode(); + } + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + typedef CallGraph::const_iterator nodes_iterator; + static nodes_iterator nodes_begin(const CallGraph *CG) { return CG->begin(); } + static nodes_iterator nodes_end (const CallGraph *CG) { return CG->end(); } +}; + +} // End llvm namespace + +// Make sure that any clients of this file link in CallGraph.cpp +FORCE_DEFINING_FILE_TO_BE_LINKED(CallGraph) + +#endif diff --git a/include/llvm/Analysis/ConstantFolding.h b/include/llvm/Analysis/ConstantFolding.h new file mode 100644 index 0000000..9c19f11 --- /dev/null +++ b/include/llvm/Analysis/ConstantFolding.h @@ -0,0 +1,61 @@ +//===-- ConstantFolding.h - Analyze constant folding possibilities --------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of functions determines the possibility of performing constant +// folding. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CONSTANTFOLDING_H +#define LLVM_ANALYSIS_CONSTANTFOLDING_H + +namespace llvm { + class Constant; + class ConstantExpr; + class Instruction; + class TargetData; + class Function; + +/// ConstantFoldInstruction - Attempt to constant fold the specified +/// instruction. If successful, the constant result is returned, if not, null +/// is returned. Note that this function can only fail when attempting to fold +/// instructions like loads and stores, which have no constant expression form. +/// +Constant *ConstantFoldInstruction(Instruction *I, const TargetData *TD = 0); + +/// ConstantFoldInstOperands - Attempt to constant fold an instruction with the +/// specified operands. If successful, the constant result is returned, if not, +/// null is returned. Note that this function can fail when attempting to +/// fold instructions like loads and stores, which have no constant expression +/// form. +/// +Constant *ConstantFoldInstOperands( + const Instruction *I, ///< The model instruction + Constant** Ops, ///< The array of constant operands to use. + unsigned NumOps, ///< The number of operands provided. + const TargetData *TD = 0 ///< Optional target information. +); + + +/// ConstantFoldLoadThroughGEPConstantExpr - Given a constant and a +/// getelementptr constantexpr, return the constant value being addressed by the +/// constant expression, or null if something is funny and we can't decide. +Constant *ConstantFoldLoadThroughGEPConstantExpr(Constant *C, ConstantExpr *CE); + +/// canConstantFoldCallTo - Return true if its even possible to fold a call to +/// the specified function. +bool canConstantFoldCallTo(Function *F); + +/// ConstantFoldCall - Attempt to constant fold a call to the specified function +/// with the specified arguments, returning null if unsuccessful. +Constant * +ConstantFoldCall(Function *F, Constant** Operands, unsigned NumOperands); +} + +#endif diff --git a/include/llvm/Analysis/ConstantsScanner.h b/include/llvm/Analysis/ConstantsScanner.h new file mode 100644 index 0000000..9ea9ed6 --- /dev/null +++ b/include/llvm/Analysis/ConstantsScanner.h @@ -0,0 +1,94 @@ +//==- llvm/Analysis/ConstantsScanner.h - Iterate over constants -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements an iterator to walk through the constants referenced by +// a method. This is used by the Bitcode & Assembly writers to build constant +// pools. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_CONSTANTSSCANNER_H +#define LLVM_ANALYSIS_CONSTANTSSCANNER_H + +#include "llvm/Support/InstIterator.h" +#include "llvm/Instruction.h" +#include "llvm/ADT/iterator" + +namespace llvm { + +class Constant; + +class constant_iterator : public forward_iterator<const Constant, ptrdiff_t> { + const_inst_iterator InstI; // Method instruction iterator + unsigned OpIdx; // Operand index + + typedef constant_iterator _Self; + + inline bool isAtConstant() const { + assert(!InstI.atEnd() && OpIdx < InstI->getNumOperands() && + "isAtConstant called with invalid arguments!"); + return isa<Constant>(InstI->getOperand(OpIdx)); + } + +public: + inline constant_iterator(const Function *F) : InstI(inst_begin(F)), OpIdx(0) { + // Advance to first constant... if we are not already at constant or end + if (InstI != inst_end(F) && // InstI is valid? + (InstI->getNumOperands() == 0 || !isAtConstant())) // Not at constant? + operator++(); + } + + inline constant_iterator(const Function *F, bool) // end ctor + : InstI(inst_end(F)), OpIdx(0) { + } + + inline bool operator==(const _Self& x) const { return OpIdx == x.OpIdx && + InstI == x.InstI; } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline pointer operator*() const { + assert(isAtConstant() && "Dereferenced an iterator at the end!"); + return cast<Constant>(InstI->getOperand(OpIdx)); + } + inline pointer operator->() const { return operator*(); } + + inline _Self& operator++() { // Preincrement implementation + ++OpIdx; + do { + unsigned NumOperands = InstI->getNumOperands(); + while (OpIdx < NumOperands && !isAtConstant()) { + ++OpIdx; + } + + if (OpIdx < NumOperands) return *this; // Found a constant! + ++InstI; + OpIdx = 0; + } while (!InstI.atEnd()); + + return *this; // At the end of the method + } + + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + + inline bool atEnd() const { return InstI.atEnd(); } +}; + +inline constant_iterator constant_begin(const Function *F) { + return constant_iterator(F); +} + +inline constant_iterator constant_end(const Function *F) { + return constant_iterator(F, true); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/Dominators.h b/include/llvm/Analysis/Dominators.h new file mode 100644 index 0000000..f0b4672 --- /dev/null +++ b/include/llvm/Analysis/Dominators.h @@ -0,0 +1,431 @@ +//===- llvm/Analysis/Dominators.h - Dominator Info Calculation --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the following classes: +// 1. DominatorTree: Represent dominators as an explicit tree structure. +// 2. DominanceFrontier: Calculate and hold the dominance frontier for a +// function. +// +// These data structures are listed in increasing order of complexity. It +// takes longer to calculate the dominator frontier, for example, than the +// DominatorTree mapping. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_DOMINATORS_H +#define LLVM_ANALYSIS_DOMINATORS_H + +#include "llvm/Pass.h" +#include <set> + +namespace llvm { + +class Instruction; + +template <typename GraphType> struct GraphTraits; + +//===----------------------------------------------------------------------===// +/// DominatorBase - Base class that other, more interesting dominator analyses +/// inherit from. +/// +class DominatorBase : public FunctionPass { +protected: + std::vector<BasicBlock*> Roots; + const bool IsPostDominators; + inline DominatorBase(intptr_t ID, bool isPostDom) : + FunctionPass(ID), Roots(), IsPostDominators(isPostDom) {} +public: + + /// getRoots - Return the root blocks of the current CFG. This may include + /// multiple blocks if we are computing post dominators. For forward + /// dominators, this will always be a single block (the entry node). + /// + inline const std::vector<BasicBlock*> &getRoots() const { return Roots; } + + /// isPostDominator - Returns true if analysis based of postdoms + /// + bool isPostDominator() const { return IsPostDominators; } +}; + + +//===----------------------------------------------------------------------===// +// DomTreeNode - Dominator Tree Node +class DominatorTreeBase; +class PostDominatorTree; +class DomTreeNode { + BasicBlock *TheBB; + DomTreeNode *IDom; + std::vector<DomTreeNode*> Children; + int DFSNumIn, DFSNumOut; + + friend class DominatorTreeBase; + friend class PostDominatorTree; +public: + typedef std::vector<DomTreeNode*>::iterator iterator; + typedef std::vector<DomTreeNode*>::const_iterator const_iterator; + + iterator begin() { return Children.begin(); } + iterator end() { return Children.end(); } + const_iterator begin() const { return Children.begin(); } + const_iterator end() const { return Children.end(); } + + inline BasicBlock *getBlock() const { return TheBB; } + inline DomTreeNode *getIDom() const { return IDom; } + inline const std::vector<DomTreeNode*> &getChildren() const { return Children; } + + inline DomTreeNode(BasicBlock *BB, DomTreeNode *iDom) + : TheBB(BB), IDom(iDom), DFSNumIn(-1), DFSNumOut(-1) { } + inline DomTreeNode *addChild(DomTreeNode *C) { Children.push_back(C); return C; } + void setIDom(DomTreeNode *NewIDom); + +private: + // Return true if this node is dominated by other. Use this only if DFS info is valid. + bool DominatedBy(const DomTreeNode *other) const { + return this->DFSNumIn >= other->DFSNumIn && + this->DFSNumOut <= other->DFSNumOut; + } + + /// assignDFSNumber - Assign In and Out numbers while walking dominator tree + /// in dfs order. + void assignDFSNumber(int num); +}; + +//===----------------------------------------------------------------------===// +/// DominatorTree - Calculate the immediate dominator tree for a function. +/// +class DominatorTreeBase : public DominatorBase { + +protected: + void reset(); + typedef std::map<BasicBlock*, DomTreeNode*> DomTreeNodeMapType; + DomTreeNodeMapType DomTreeNodes; + DomTreeNode *RootNode; + + bool DFSInfoValid; + unsigned int SlowQueries; + // Information record used during immediate dominators computation. + struct InfoRec { + unsigned Semi; + unsigned Size; + BasicBlock *Label, *Parent, *Child, *Ancestor; + + std::vector<BasicBlock*> Bucket; + + InfoRec() : Semi(0), Size(0), Label(0), Parent(0), Child(0), Ancestor(0){} + }; + + std::map<BasicBlock*, BasicBlock*> IDoms; + + // Vertex - Map the DFS number to the BasicBlock* + std::vector<BasicBlock*> Vertex; + + // Info - Collection of information used during the computation of idoms. + std::map<BasicBlock*, InfoRec> Info; + + void updateDFSNumbers(); + + public: + DominatorTreeBase(intptr_t ID, bool isPostDom) + : DominatorBase(ID, isPostDom), DFSInfoValid(false), SlowQueries(0) {} + ~DominatorTreeBase() { reset(); } + + virtual void releaseMemory() { reset(); } + + /// getNode - return the (Post)DominatorTree node for the specified basic + /// block. This is the same as using operator[] on this class. + /// + inline DomTreeNode *getNode(BasicBlock *BB) const { + DomTreeNodeMapType::const_iterator i = DomTreeNodes.find(BB); + return (i != DomTreeNodes.end()) ? i->second : 0; + } + + inline DomTreeNode *operator[](BasicBlock *BB) const { + return getNode(BB); + } + + /// getRootNode - This returns the entry node for the CFG of the function. If + /// this tree represents the post-dominance relations for a function, however, + /// this root may be a node with the block == NULL. This is the case when + /// there are multiple exit nodes from a particular function. Consumers of + /// post-dominance information must be capable of dealing with this + /// possibility. + /// + DomTreeNode *getRootNode() { return RootNode; } + const DomTreeNode *getRootNode() const { return RootNode; } + + /// properlyDominates - Returns true iff this dominates N and this != N. + /// Note that this is not a constant time operation! + /// + bool properlyDominates(const DomTreeNode *A, DomTreeNode *B) const { + if (A == 0 || B == 0) return false; + return dominatedBySlowTreeWalk(A, B); + } + + inline bool properlyDominates(BasicBlock *A, BasicBlock *B) { + return properlyDominates(getNode(A), getNode(B)); + } + + bool dominatedBySlowTreeWalk(const DomTreeNode *A, + const DomTreeNode *B) const { + const DomTreeNode *IDom; + if (A == 0 || B == 0) return false; + while ((IDom = B->getIDom()) != 0 && IDom != A && IDom != B) + B = IDom; // Walk up the tree + return IDom != 0; + } + + + /// isReachableFromEntry - Return true if A is dominated by the entry + /// block of the function containing it. + const bool isReachableFromEntry(BasicBlock* A); + + /// dominates - Returns true iff A dominates B. Note that this is not a + /// constant time operation! + /// + inline bool dominates(const DomTreeNode *A, DomTreeNode *B) { + if (B == A) + return true; // A node trivially dominates itself. + + if (A == 0 || B == 0) + return false; + + if (DFSInfoValid) + return B->DominatedBy(A); + + // If we end up with too many slow queries, just update the + // DFS numbers on the theory that we are going to keep querying. + SlowQueries++; + if (SlowQueries > 32) { + updateDFSNumbers(); + return B->DominatedBy(A); + } + + return dominatedBySlowTreeWalk(A, B); + } + + inline bool dominates(BasicBlock *A, BasicBlock *B) { + if (A == B) + return true; + + return dominates(getNode(A), getNode(B)); + } + + /// findNearestCommonDominator - Find nearest common dominator basic block + /// for basic block A and B. If there is no such block then return NULL. + BasicBlock *findNearestCommonDominator(BasicBlock *A, BasicBlock *B); + + // dominates - Return true if A dominates B. This performs the + // special checks necessary if A and B are in the same basic block. + bool dominates(Instruction *A, Instruction *B); + + //===--------------------------------------------------------------------===// + // API to update (Post)DominatorTree information based on modifications to + // the CFG... + + /// addNewBlock - Add a new node to the dominator tree information. This + /// creates a new node as a child of DomBB dominator node,linking it into + /// the children list of the immediate dominator. + DomTreeNode *addNewBlock(BasicBlock *BB, BasicBlock *DomBB) { + assert(getNode(BB) == 0 && "Block already in dominator tree!"); + DomTreeNode *IDomNode = getNode(DomBB); + assert(IDomNode && "Not immediate dominator specified for block!"); + DFSInfoValid = false; + return DomTreeNodes[BB] = + IDomNode->addChild(new DomTreeNode(BB, IDomNode)); + } + + /// changeImmediateDominator - This method is used to update the dominator + /// tree information when a node's immediate dominator changes. + /// + void changeImmediateDominator(DomTreeNode *N, DomTreeNode *NewIDom) { + assert(N && NewIDom && "Cannot change null node pointers!"); + DFSInfoValid = false; + N->setIDom(NewIDom); + } + + void changeImmediateDominator(BasicBlock *BB, BasicBlock *NewBB) { + changeImmediateDominator(getNode(BB), getNode(NewBB)); + } + + /// removeNode - Removes a node from the dominator tree. Block must not + /// dominate any other blocks. Invalidates any node pointing to removed + /// block. + void removeNode(BasicBlock *BB) { + assert(getNode(BB) && "Removing node that isn't in dominator tree."); + DomTreeNodes.erase(BB); + } + + /// print - Convert to human readable form + /// + virtual void print(std::ostream &OS, const Module* = 0) const; + void print(std::ostream *OS, const Module* M = 0) const { + if (OS) print(*OS, M); + } + virtual void dump(); +}; + +//===------------------------------------- +/// DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to +/// compute a normal dominator tree. +/// +class DominatorTree : public DominatorTreeBase { +public: + static char ID; // Pass ID, replacement for typeid + DominatorTree() : DominatorTreeBase((intptr_t)&ID, false) {} + + BasicBlock *getRoot() const { + assert(Roots.size() == 1 && "Should always have entry node!"); + return Roots[0]; + } + + virtual bool runOnFunction(Function &F); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + + /// splitBlock + /// BB is split and now it has one successor. Update dominator tree to + /// reflect this change. + void splitBlock(BasicBlock *BB); +private: + void calculate(Function& F); + DomTreeNode *getNodeForBlock(BasicBlock *BB); + unsigned DFSPass(BasicBlock *V, InfoRec &VInfo, unsigned N); + void Compress(BasicBlock *V); + BasicBlock *Eval(BasicBlock *v); + void Link(BasicBlock *V, BasicBlock *W, InfoRec &WInfo); + inline BasicBlock *getIDom(BasicBlock *BB) const { + std::map<BasicBlock*, BasicBlock*>::const_iterator I = IDoms.find(BB); + return I != IDoms.end() ? I->second : 0; + } +}; + +//===------------------------------------- +/// DominatorTree GraphTraits specialization so the DominatorTree can be +/// iterable by generic graph iterators. +/// +template <> struct GraphTraits<DomTreeNode*> { + typedef DomTreeNode NodeType; + typedef NodeType::iterator ChildIteratorType; + + static NodeType *getEntryNode(NodeType *N) { + return N; + } + static inline ChildIteratorType child_begin(NodeType* N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType* N) { + return N->end(); + } +}; + +template <> struct GraphTraits<DominatorTree*> + : public GraphTraits<DomTreeNode*> { + static NodeType *getEntryNode(DominatorTree *DT) { + return DT->getRootNode(); + } +}; + + +//===----------------------------------------------------------------------===// +/// DominanceFrontierBase - Common base class for computing forward and inverse +/// dominance frontiers for a function. +/// +class DominanceFrontierBase : public DominatorBase { +public: + typedef std::set<BasicBlock*> DomSetType; // Dom set for a bb + typedef std::map<BasicBlock*, DomSetType> DomSetMapType; // Dom set map +protected: + DomSetMapType Frontiers; +public: + DominanceFrontierBase(intptr_t ID, bool isPostDom) + : DominatorBase(ID, isPostDom) {} + + virtual void releaseMemory() { Frontiers.clear(); } + + // Accessor interface: + typedef DomSetMapType::iterator iterator; + typedef DomSetMapType::const_iterator const_iterator; + iterator begin() { return Frontiers.begin(); } + const_iterator begin() const { return Frontiers.begin(); } + iterator end() { return Frontiers.end(); } + const_iterator end() const { return Frontiers.end(); } + iterator find(BasicBlock *B) { return Frontiers.find(B); } + const_iterator find(BasicBlock *B) const { return Frontiers.find(B); } + + void addBasicBlock(BasicBlock *BB, const DomSetType &frontier) { + assert(find(BB) == end() && "Block already in DominanceFrontier!"); + Frontiers.insert(std::make_pair(BB, frontier)); + } + + void addToFrontier(iterator I, BasicBlock *Node) { + assert(I != end() && "BB is not in DominanceFrontier!"); + I->second.insert(Node); + } + + void removeFromFrontier(iterator I, BasicBlock *Node) { + assert(I != end() && "BB is not in DominanceFrontier!"); + assert(I->second.count(Node) && "Node is not in DominanceFrontier of BB"); + I->second.erase(Node); + } + + /// print - Convert to human readable form + /// + virtual void print(std::ostream &OS, const Module* = 0) const; + void print(std::ostream *OS, const Module* M = 0) const { + if (OS) print(*OS, M); + } + virtual void dump(); +}; + + +//===------------------------------------- +/// DominanceFrontier Class - Concrete subclass of DominanceFrontierBase that is +/// used to compute a forward dominator frontiers. +/// +class DominanceFrontier : public DominanceFrontierBase { +public: + static char ID; // Pass ID, replacement for typeid + DominanceFrontier() : + DominanceFrontierBase((intptr_t)& ID, false) {} + + BasicBlock *getRoot() const { + assert(Roots.size() == 1 && "Should always have entry node!"); + return Roots[0]; + } + + virtual bool runOnFunction(Function &) { + Frontiers.clear(); + DominatorTree &DT = getAnalysis<DominatorTree>(); + Roots = DT.getRoots(); + assert(Roots.size() == 1 && "Only one entry block for forward domfronts!"); + calculate(DT, DT[Roots[0]]); + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired<DominatorTree>(); + } + + /// splitBlock + /// BB is split and now it has one successor. Update dominace frontier to + /// reflect this change. + void splitBlock(BasicBlock *BB); + +private: + const DomSetType &calculate(const DominatorTree &DT, + const DomTreeNode *Node); +}; + + +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/FindUsedTypes.h b/include/llvm/Analysis/FindUsedTypes.h new file mode 100644 index 0000000..6cafc89 --- /dev/null +++ b/include/llvm/Analysis/FindUsedTypes.h @@ -0,0 +1,67 @@ +//===- llvm/Analysis/FindUsedTypes.h - Find all Types in use ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass is used to seek out all of the types in use by the program. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_FINDUSEDTYPES_H +#define LLVM_ANALYSIS_FINDUSEDTYPES_H + +#include "llvm/Pass.h" +#include <set> + +namespace llvm { + +class Type; + +class FindUsedTypes : public ModulePass { + std::set<const Type *> UsedTypes; +public: + static char ID; // Pass identification, replacement for typeid + FindUsedTypes() : ModulePass((intptr_t)&ID) {} + + /// getTypes - After the pass has been run, return the set containing all of + /// the types used in the module. + /// + const std::set<const Type *> &getTypes() const { return UsedTypes; } + + /// Print the types found in the module. If the optional Module parameter is + /// passed in, then the types are printed symbolically if possible, using the + /// symbol table from the module. + /// + void print(std::ostream &o, const Module *M) const; + void print(std::ostream *o, const Module *M) const { if (o) print(*o, M); } + +private: + /// IncorporateType - Incorporate one type and all of its subtypes into the + /// collection of used types. + /// + void IncorporateType(const Type *Ty); + + /// IncorporateValue - Incorporate all of the types used by this value. + /// + void IncorporateValue(const Value *V); + +public: + /// run - This incorporates all types used by the specified module + bool runOnModule(Module &M); + + /// getAnalysisUsage - We do not modify anything. + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } +}; + +} // End llvm namespace + +// Make sure that any clients of this file link in PostDominators.cpp +FORCE_DEFINING_FILE_TO_BE_LINKED(FindUsedTypes) + +#endif diff --git a/include/llvm/Analysis/Interval.h b/include/llvm/Analysis/Interval.h new file mode 100644 index 0000000..bed815a --- /dev/null +++ b/include/llvm/Analysis/Interval.h @@ -0,0 +1,154 @@ +//===- llvm/Analysis/Interval.h - Interval Class Declaration ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Interval class, which +// represents a set of CFG nodes and is a portion of an interval partition. +// +// Intervals have some interesting and useful properties, including the +// following: +// 1. The header node of an interval dominates all of the elements of the +// interval +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INTERVAL_H +#define LLVM_INTERVAL_H + +#include "llvm/ADT/GraphTraits.h" +#include <vector> +#include <iosfwd> + +namespace llvm { + +class BasicBlock; + +//===----------------------------------------------------------------------===// +// +/// Interval Class - An Interval is a set of nodes defined such that every node +/// in the interval has all of its predecessors in the interval (except for the +/// header) +/// +class Interval { + /// HeaderNode - The header BasicBlock, which dominates all BasicBlocks in this + /// interval. Also, any loops in this interval must go through the HeaderNode. + /// + BasicBlock *HeaderNode; +public: + typedef std::vector<BasicBlock*>::iterator succ_iterator; + typedef std::vector<BasicBlock*>::iterator pred_iterator; + typedef std::vector<BasicBlock*>::iterator node_iterator; + + inline Interval(BasicBlock *Header) : HeaderNode(Header) { + Nodes.push_back(Header); + } + + inline Interval(const Interval &I) // copy ctor + : HeaderNode(I.HeaderNode), Nodes(I.Nodes), Successors(I.Successors) {} + + inline BasicBlock *getHeaderNode() const { return HeaderNode; } + + /// Nodes - The basic blocks in this interval. + /// + std::vector<BasicBlock*> Nodes; + + /// Successors - List of BasicBlocks that are reachable directly from nodes in + /// this interval, but are not in the interval themselves. + /// These nodes necessarily must be header nodes for other intervals. + /// + std::vector<BasicBlock*> Successors; + + /// Predecessors - List of BasicBlocks that have this Interval's header block + /// as one of their successors. + /// + std::vector<BasicBlock*> Predecessors; + + /// contains - Find out if a basic block is in this interval + inline bool contains(BasicBlock *BB) const { + for (unsigned i = 0; i < Nodes.size(); ++i) + if (Nodes[i] == BB) return true; + return false; + // I don't want the dependency on <algorithm> + //return find(Nodes.begin(), Nodes.end(), BB) != Nodes.end(); + } + + /// isSuccessor - find out if a basic block is a successor of this Interval + inline bool isSuccessor(BasicBlock *BB) const { + for (unsigned i = 0; i < Successors.size(); ++i) + if (Successors[i] == BB) return true; + return false; + // I don't want the dependency on <algorithm> + //return find(Successors.begin(), Successors.end(), BB) != Successors.end(); + } + + /// Equality operator. It is only valid to compare two intervals from the + /// same partition, because of this, all we have to check is the header node + /// for equality. + /// + inline bool operator==(const Interval &I) const { + return HeaderNode == I.HeaderNode; + } + + /// isLoop - Find out if there is a back edge in this interval... + bool isLoop() const; + + /// print - Show contents in human readable format... + void print(std::ostream &O) const; + void print(std::ostream *O) const { if (O) print(*O); } +}; + +/// succ_begin/succ_end - define methods so that Intervals may be used +/// just like BasicBlocks can with the succ_* functions, and *::succ_iterator. +/// +inline Interval::succ_iterator succ_begin(Interval *I) { + return I->Successors.begin(); +} +inline Interval::succ_iterator succ_end(Interval *I) { + return I->Successors.end(); +} + +/// pred_begin/pred_end - define methods so that Intervals may be used +/// just like BasicBlocks can with the pred_* functions, and *::pred_iterator. +/// +inline Interval::pred_iterator pred_begin(Interval *I) { + return I->Predecessors.begin(); +} +inline Interval::pred_iterator pred_end(Interval *I) { + return I->Predecessors.end(); +} + +template <> struct GraphTraits<Interval*> { + typedef Interval NodeType; + typedef Interval::succ_iterator ChildIteratorType; + + static NodeType *getEntryNode(Interval *I) { return I; } + + /// nodes_iterator/begin/end - Allow iteration over all nodes in the graph + static inline ChildIteratorType child_begin(NodeType *N) { + return succ_begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return succ_end(N); + } +}; + +template <> struct GraphTraits<Inverse<Interval*> > { + typedef Interval NodeType; + typedef Interval::pred_iterator ChildIteratorType; + static NodeType *getEntryNode(Inverse<Interval *> G) { return G.Graph; } + static inline ChildIteratorType child_begin(NodeType *N) { + return pred_begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return pred_end(N); + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/IntervalIterator.h b/include/llvm/Analysis/IntervalIterator.h new file mode 100644 index 0000000..dfa983c --- /dev/null +++ b/include/llvm/Analysis/IntervalIterator.h @@ -0,0 +1,258 @@ +//===- IntervalIterator.h - Interval Iterator Declaration -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an iterator that enumerates the intervals in a control flow +// graph of some sort. This iterator is parametric, allowing iterator over the +// following types of graphs: +// +// 1. A Function* object, composed of BasicBlock nodes. +// 2. An IntervalPartition& object, composed of Interval nodes. +// +// This iterator is defined to walk the control flow graph, returning intervals +// in depth first order. These intervals are completely filled in except for +// the predecessor fields (the successor information is filled in however). +// +// By default, the intervals created by this iterator are deleted after they +// are no longer any use to the iterator. This behavior can be changed by +// passing a false value into the intervals_begin() function. This causes the +// IOwnMem member to be set, and the intervals to not be deleted. +// +// It is only safe to use this if all of the intervals are deleted by the caller +// and all of the intervals are processed. However, the user of the iterator is +// not allowed to modify or delete the intervals until after the iterator has +// been used completely. The IntervalPartition class uses this functionality. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INTERVAL_ITERATOR_H +#define LLVM_INTERVAL_ITERATOR_H + +#include "llvm/Analysis/IntervalPartition.h" +#include "llvm/Function.h" +#include "llvm/Support/CFG.h" +#include <stack> +#include <set> +#include <algorithm> + +namespace llvm { + +// getNodeHeader - Given a source graph node and the source graph, return the +// BasicBlock that is the header node. This is the opposite of +// getSourceGraphNode. +// +inline BasicBlock *getNodeHeader(BasicBlock *BB) { return BB; } +inline BasicBlock *getNodeHeader(Interval *I) { return I->getHeaderNode(); } + +// getSourceGraphNode - Given a BasicBlock and the source graph, return the +// source graph node that corresponds to the BasicBlock. This is the opposite +// of getNodeHeader. +// +inline BasicBlock *getSourceGraphNode(Function *, BasicBlock *BB) { + return BB; +} +inline Interval *getSourceGraphNode(IntervalPartition *IP, BasicBlock *BB) { + return IP->getBlockInterval(BB); +} + +// addNodeToInterval - This method exists to assist the generic ProcessNode +// with the task of adding a node to the new interval, depending on the +// type of the source node. In the case of a CFG source graph (BasicBlock +// case), the BasicBlock itself is added to the interval. +// +inline void addNodeToInterval(Interval *Int, BasicBlock *BB) { + Int->Nodes.push_back(BB); +} + +// addNodeToInterval - This method exists to assist the generic ProcessNode +// with the task of adding a node to the new interval, depending on the +// type of the source node. In the case of a CFG source graph (BasicBlock +// case), the BasicBlock itself is added to the interval. In the case of +// an IntervalPartition source graph (Interval case), all of the member +// BasicBlocks are added to the interval. +// +inline void addNodeToInterval(Interval *Int, Interval *I) { + // Add all of the nodes in I as new nodes in Int. + copy(I->Nodes.begin(), I->Nodes.end(), back_inserter(Int->Nodes)); +} + + + + + +template<class NodeTy, class OrigContainer_t, class GT = GraphTraits<NodeTy*>, + class IGT = GraphTraits<Inverse<NodeTy*> > > +class IntervalIterator { + std::stack<std::pair<Interval*, typename Interval::succ_iterator> > IntStack; + std::set<BasicBlock*> Visited; + OrigContainer_t *OrigContainer; + bool IOwnMem; // If True, delete intervals when done with them + // See file header for conditions of use +public: + typedef IntervalIterator<NodeTy, OrigContainer_t> _Self; + typedef std::forward_iterator_tag iterator_category; + + IntervalIterator() {} // End iterator, empty stack + IntervalIterator(Function *M, bool OwnMemory) : IOwnMem(OwnMemory) { + OrigContainer = M; + if (!ProcessInterval(&M->front())) { + assert(0 && "ProcessInterval should never fail for first interval!"); + } + } + + IntervalIterator(IntervalPartition &IP, bool OwnMemory) : IOwnMem(OwnMemory) { + OrigContainer = &IP; + if (!ProcessInterval(IP.getRootInterval())) { + assert(0 && "ProcessInterval should never fail for first interval!"); + } + } + + inline ~IntervalIterator() { + if (IOwnMem) + while (!IntStack.empty()) { + delete operator*(); + IntStack.pop(); + } + } + + inline bool operator==(const _Self& x) const { return IntStack == x.IntStack;} + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline const Interval *operator*() const { return IntStack.top().first; } + inline Interval *operator*() { return IntStack.top().first; } + inline const Interval *operator->() const { return operator*(); } + inline Interval *operator->() { return operator*(); } + + _Self& operator++() { // Preincrement + assert(!IntStack.empty() && "Attempting to use interval iterator at end!"); + do { + // All of the intervals on the stack have been visited. Try visiting + // their successors now. + Interval::succ_iterator &SuccIt = IntStack.top().second, + EndIt = succ_end(IntStack.top().first); + while (SuccIt != EndIt) { // Loop over all interval succs + bool Done = ProcessInterval(getSourceGraphNode(OrigContainer, *SuccIt)); + ++SuccIt; // Increment iterator + if (Done) return *this; // Found a new interval! Use it! + } + + // Free interval memory... if necessary + if (IOwnMem) delete IntStack.top().first; + + // We ran out of successors for this interval... pop off the stack + IntStack.pop(); + } while (!IntStack.empty()); + + return *this; + } + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + +private: + // ProcessInterval - This method is used during the construction of the + // interval graph. It walks through the source graph, recursively creating + // an interval per invokation until the entire graph is covered. This uses + // the ProcessNode method to add all of the nodes to the interval. + // + // This method is templated because it may operate on two different source + // graphs: a basic block graph, or a preexisting interval graph. + // + bool ProcessInterval(NodeTy *Node) { + BasicBlock *Header = getNodeHeader(Node); + if (Visited.count(Header)) return false; + + Interval *Int = new Interval(Header); + Visited.insert(Header); // The header has now been visited! + + // Check all of our successors to see if they are in the interval... + for (typename GT::ChildIteratorType I = GT::child_begin(Node), + E = GT::child_end(Node); I != E; ++I) + ProcessNode(Int, getSourceGraphNode(OrigContainer, *I)); + + IntStack.push(std::make_pair(Int, succ_begin(Int))); + return true; + } + + // ProcessNode - This method is called by ProcessInterval to add nodes to the + // interval being constructed, and it is also called recursively as it walks + // the source graph. A node is added to the current interval only if all of + // its predecessors are already in the graph. This also takes care of keeping + // the successor set of an interval up to date. + // + // This method is templated because it may operate on two different source + // graphs: a basic block graph, or a preexisting interval graph. + // + void ProcessNode(Interval *Int, NodeTy *Node) { + assert(Int && "Null interval == bad!"); + assert(Node && "Null Node == bad!"); + + BasicBlock *NodeHeader = getNodeHeader(Node); + + if (Visited.count(NodeHeader)) { // Node already been visited? + if (Int->contains(NodeHeader)) { // Already in this interval... + return; + } else { // In other interval, add as successor + if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set + Int->Successors.push_back(NodeHeader); + } + } else { // Otherwise, not in interval yet + for (typename IGT::ChildIteratorType I = IGT::child_begin(Node), + E = IGT::child_end(Node); I != E; ++I) { + if (!Int->contains(*I)) { // If pred not in interval, we can't be + if (!Int->isSuccessor(NodeHeader)) // Add only if not already in set + Int->Successors.push_back(NodeHeader); + return; // See you later + } + } + + // If we get here, then all of the predecessors of BB are in the interval + // already. In this case, we must add BB to the interval! + addNodeToInterval(Int, Node); + Visited.insert(NodeHeader); // The node has now been visited! + + if (Int->isSuccessor(NodeHeader)) { + // If we were in the successor list from before... remove from succ list + Int->Successors.erase(std::remove(Int->Successors.begin(), + Int->Successors.end(), NodeHeader), + Int->Successors.end()); + } + + // Now that we have discovered that Node is in the interval, perhaps some + // of its successors are as well? + for (typename GT::ChildIteratorType It = GT::child_begin(Node), + End = GT::child_end(Node); It != End; ++It) + ProcessNode(Int, getSourceGraphNode(OrigContainer, *It)); + } + } +}; + +typedef IntervalIterator<BasicBlock, Function> function_interval_iterator; +typedef IntervalIterator<Interval, IntervalPartition> interval_part_interval_iterator; + + +inline function_interval_iterator intervals_begin(Function *F, + bool DeleteInts = true) { + return function_interval_iterator(F, DeleteInts); +} +inline function_interval_iterator intervals_end(Function *) { + return function_interval_iterator(); +} + +inline interval_part_interval_iterator + intervals_begin(IntervalPartition &IP, bool DeleteIntervals = true) { + return interval_part_interval_iterator(IP, DeleteIntervals); +} + +inline interval_part_interval_iterator intervals_end(IntervalPartition &IP) { + return interval_part_interval_iterator(); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/IntervalPartition.h b/include/llvm/Analysis/IntervalPartition.h new file mode 100644 index 0000000..1f985e3 --- /dev/null +++ b/include/llvm/Analysis/IntervalPartition.h @@ -0,0 +1,114 @@ +//===- IntervalPartition.h - Interval partition Calculation -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the IntervalPartition class, which +// calculates and represents the interval partition of a function, or a +// preexisting interval partition. +// +// In this way, the interval partition may be used to reduce a flow graph down +// to its degenerate single node interval partition (unless it is irreducible). +// +// TODO: The IntervalPartition class should take a bool parameter that tells +// whether it should add the "tails" of an interval to an interval itself or if +// they should be represented as distinct intervals. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INTERVAL_PARTITION_H +#define LLVM_INTERVAL_PARTITION_H + +#include "llvm/Analysis/Interval.h" +#include "llvm/Pass.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +// +// IntervalPartition - This class builds and holds an "interval partition" for +// a function. This partition divides the control flow graph into a set of +// maximal intervals, as defined with the properties above. Intuitively, a +// BasicBlock is a (possibly nonexistent) loop with a "tail" of non looping +// nodes following it. +// +class IntervalPartition : public FunctionPass { + typedef std::map<BasicBlock*, Interval*> IntervalMapTy; + IntervalMapTy IntervalMap; + + typedef std::vector<Interval*> IntervalListTy; + Interval *RootInterval; + std::vector<Interval*> Intervals; + +public: + static char ID; // Pass identification, replacement for typeid + + IntervalPartition() : FunctionPass((intptr_t)&ID), RootInterval(0) {} + + // run - Calculate the interval partition for this function + virtual bool runOnFunction(Function &F); + + // IntervalPartition ctor - Build a reduced interval partition from an + // existing interval graph. This takes an additional boolean parameter to + // distinguish it from a copy constructor. Always pass in false for now. + // + IntervalPartition(IntervalPartition &I, bool); + + // Destructor - Free memory + ~IntervalPartition() { destroy(); } + + // print - Show contents in human readable format... + virtual void print(std::ostream &O, const Module* = 0) const; + void print(std::ostream *O, const Module* M = 0) const { + if (O) print(*O, M); + } + + // getRootInterval() - Return the root interval that contains the starting + // block of the function. + inline Interval *getRootInterval() { return RootInterval; } + + // isDegeneratePartition() - Returns true if the interval partition contains + // a single interval, and thus cannot be simplified anymore. + bool isDegeneratePartition() { return Intervals.size() == 1; } + + // TODO: isIrreducible - look for triangle graph. + + // getBlockInterval - Return the interval that a basic block exists in. + inline Interval *getBlockInterval(BasicBlock *BB) { + IntervalMapTy::iterator I = IntervalMap.find(BB); + return I != IntervalMap.end() ? I->second : 0; + } + + // getAnalysisUsage - Implement the Pass API + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + + // Interface to Intervals vector... + const std::vector<Interval*> &getIntervals() const { return Intervals; } + +private: + // destroy - Reset state back to before function was analyzed + void destroy(); + + // addIntervalToPartition - Add an interval to the internal list of intervals, + // and then add mappings from all of the basic blocks in the interval to the + // interval itself (in the IntervalMap). + // + void addIntervalToPartition(Interval *I); + + // updatePredecessors - Interval generation only sets the successor fields of + // the interval data structures. After interval generation is complete, + // run through all of the intervals and propagate successor info as + // predecessor info. + // + void updatePredecessors(Interval *Int); +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/LoadValueNumbering.h b/include/llvm/Analysis/LoadValueNumbering.h new file mode 100644 index 0000000..b924595 --- /dev/null +++ b/include/llvm/Analysis/LoadValueNumbering.h @@ -0,0 +1,35 @@ +//===- llvm/Analysis/LoadValueNumbering.h - Value # Load Insts --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a value numbering pass that value #'s load instructions. +// To do this, it finds lexically identical load instructions, and uses alias +// analysis to determine which loads are guaranteed to produce the same value. +// +// This pass builds off of another value numbering pass to implement value +// numbering for non-load instructions. It uses Alias Analysis so that it can +// disambiguate the load instructions. The more powerful these base analyses +// are, the more powerful the resultant analysis will be. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOAD_VALUE_NUMBERING_H +#define LLVM_ANALYSIS_LOAD_VALUE_NUMBERING_H + +namespace llvm { + +class FunctionPass; + +/// createLoadValueNumberingPass - Create and return a new pass that implements +/// the ValueNumbering interface. +/// +FunctionPass *createLoadValueNumberingPass(); + +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/LoopInfo.h b/include/llvm/Analysis/LoopInfo.h new file mode 100644 index 0000000..b332fd1 --- /dev/null +++ b/include/llvm/Analysis/LoopInfo.h @@ -0,0 +1,363 @@ +//===- llvm/Analysis/LoopInfo.h - Natural Loop Calculator -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the LoopInfo class that is used to identify natural loops +// and determine the loop depth of various nodes of the CFG. Note that natural +// loops may actually be several loops that share the same header node. +// +// This analysis calculates the nesting structure of loops in a function. For +// each natural loop identified, this analysis identifies natural loops +// contained entirely within the loop and the basic blocks the make up the loop. +// +// It can calculate on the fly various bits of information, for example: +// +// * whether there is a preheader for the loop +// * the number of back edges to the header +// * whether or not a particular block branches out of the loop +// * the successor blocks of the loop +// * the loop depth +// * the trip count +// * etc... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_LOOP_INFO_H +#define LLVM_ANALYSIS_LOOP_INFO_H + +#include "llvm/Pass.h" +#include "llvm/ADT/GraphTraits.h" + +namespace llvm { + +class DominatorTree; +class LoopInfo; +class PHINode; +class Instruction; + +//===----------------------------------------------------------------------===// +/// Loop class - Instances of this class are used to represent loops that are +/// detected in the flow graph +/// +class Loop { + Loop *ParentLoop; + std::vector<Loop*> SubLoops; // Loops contained entirely within this one + std::vector<BasicBlock*> Blocks; // First entry is the header node + + Loop(const Loop &); // DO NOT IMPLEMENT + const Loop &operator=(const Loop &); // DO NOT IMPLEMENT +public: + /// Loop ctor - This creates an empty loop. + Loop() : ParentLoop(0) {} + ~Loop() { + for (unsigned i = 0, e = SubLoops.size(); i != e; ++i) + delete SubLoops[i]; + } + + unsigned getLoopDepth() const { + unsigned D = 0; + for (const Loop *CurLoop = this; CurLoop; CurLoop = CurLoop->ParentLoop) + ++D; + return D; + } + BasicBlock *getHeader() const { return Blocks.front(); } + Loop *getParentLoop() const { return ParentLoop; } + + /// contains - Return true of the specified basic block is in this loop + /// + bool contains(const BasicBlock *BB) const; + + /// iterator/begin/end - Return the loops contained entirely within this loop. + /// + const std::vector<Loop*> &getSubLoops() const { return SubLoops; } + typedef std::vector<Loop*>::const_iterator iterator; + iterator begin() const { return SubLoops.begin(); } + iterator end() const { return SubLoops.end(); } + + /// getBlocks - Get a list of the basic blocks which make up this loop. + /// + const std::vector<BasicBlock*> &getBlocks() const { return Blocks; } + typedef std::vector<BasicBlock*>::const_iterator block_iterator; + block_iterator block_begin() const { return Blocks.begin(); } + block_iterator block_end() const { return Blocks.end(); } + + /// isLoopExit - True if terminator in the block can branch to another block + /// that is outside of the current loop. + /// + bool isLoopExit(const BasicBlock *BB) const; + + /// getNumBackEdges - Calculate the number of back edges to the loop header + /// + unsigned getNumBackEdges() const; + + /// isLoopInvariant - Return true if the specified value is loop invariant + /// + bool isLoopInvariant(Value *V) const; + + //===--------------------------------------------------------------------===// + // APIs for simple analysis of the loop. + // + // Note that all of these methods can fail on general loops (ie, there may not + // be a preheader, etc). For best success, the loop simplification and + // induction variable canonicalization pass should be used to normalize loops + // for easy analysis. These methods assume canonical loops. + + /// getExitingBlocks - Return all blocks inside the loop that have successors + /// outside of the loop. These are the blocks _inside of the current loop_ + /// which branch out. The returned list is always unique. + /// + void getExitingBlocks(std::vector<BasicBlock*> &Blocks) const; + + /// getExitBlocks - Return all of the successor blocks of this loop. These + /// are the blocks _outside of the current loop_ which are branched to. + /// + void getExitBlocks(std::vector<BasicBlock*> &Blocks) const; + + /// getUniqueExitBlocks - Return all unique successor blocks of this loop. + /// These are the blocks _outside of the current loop_ which are branched to. + /// This assumes that loop is in canonical form. + /// + void getUniqueExitBlocks(std::vector<BasicBlock*> &ExitBlocks) const; + + /// getLoopPreheader - If there is a preheader for this loop, return it. A + /// loop has a preheader if there is only one edge to the header of the loop + /// from outside of the loop. If this is the case, the block branching to the + /// header of the loop is the preheader node. + /// + /// This method returns null if there is no preheader for the loop. + /// + BasicBlock *getLoopPreheader() const; + + /// getLoopLatch - If there is a latch block for this loop, return it. A + /// latch block is the canonical backedge for a loop. A loop header in normal + /// form has two edges into it: one from a preheader and one from a latch + /// block. + BasicBlock *getLoopLatch() const; + + /// getCanonicalInductionVariable - Check to see if the loop has a canonical + /// induction variable: an integer recurrence that starts at 0 and increments + /// by one each time through the loop. If so, return the phi node that + /// corresponds to it. + /// + PHINode *getCanonicalInductionVariable() const; + + /// getCanonicalInductionVariableIncrement - Return the LLVM value that holds + /// the canonical induction variable value for the "next" iteration of the + /// loop. This always succeeds if getCanonicalInductionVariable succeeds. + /// + Instruction *getCanonicalInductionVariableIncrement() const; + + /// getTripCount - Return a loop-invariant LLVM value indicating the number of + /// times the loop will be executed. Note that this means that the backedge + /// of the loop executes N-1 times. If the trip-count cannot be determined, + /// this returns null. + /// + Value *getTripCount() const; + + /// isLCSSAForm - Return true if the Loop is in LCSSA form + bool isLCSSAForm() const; + + //===--------------------------------------------------------------------===// + // APIs for updating loop information after changing the CFG + // + + /// addBasicBlockToLoop - This method is used by other analyses to update loop + /// information. NewBB is set to be a new member of the current loop. + /// Because of this, it is added as a member of all parent loops, and is added + /// to the specified LoopInfo object as being in the current basic block. It + /// is not valid to replace the loop header with this method. + /// + void addBasicBlockToLoop(BasicBlock *NewBB, LoopInfo &LI); + + /// replaceChildLoopWith - This is used when splitting loops up. It replaces + /// the OldChild entry in our children list with NewChild, and updates the + /// parent pointer of OldChild to be null and the NewChild to be this loop. + /// This updates the loop depth of the new child. + void replaceChildLoopWith(Loop *OldChild, Loop *NewChild); + + /// addChildLoop - Add the specified loop to be a child of this loop. This + /// updates the loop depth of the new child. + /// + void addChildLoop(Loop *NewChild); + + /// removeChildLoop - This removes the specified child from being a subloop of + /// this loop. The loop is not deleted, as it will presumably be inserted + /// into another loop. + Loop *removeChildLoop(iterator OldChild); + + /// addBlockEntry - This adds a basic block directly to the basic block list. + /// This should only be used by transformations that create new loops. Other + /// transformations should use addBasicBlockToLoop. + void addBlockEntry(BasicBlock *BB) { + Blocks.push_back(BB); + } + + /// moveToHeader - This method is used to move BB (which must be part of this + /// loop) to be the loop header of the loop (the block that dominates all + /// others). + void moveToHeader(BasicBlock *BB) { + if (Blocks[0] == BB) return; + for (unsigned i = 0; ; ++i) { + assert(i != Blocks.size() && "Loop does not contain BB!"); + if (Blocks[i] == BB) { + Blocks[i] = Blocks[0]; + Blocks[0] = BB; + return; + } + } + } + + /// removeBlockFromLoop - This removes the specified basic block from the + /// current loop, updating the Blocks as appropriate. This does not update + /// the mapping in the LoopInfo class. + void removeBlockFromLoop(BasicBlock *BB); + + void print(std::ostream &O, unsigned Depth = 0) const; + void print(std::ostream *O, unsigned Depth = 0) const { + if (O) print(*O, Depth); + } + void dump() const; +private: + friend class LoopInfo; + Loop(BasicBlock *BB) : ParentLoop(0) { + Blocks.push_back(BB); + } +}; + + + +//===----------------------------------------------------------------------===// +/// LoopInfo - This class builds and contains all of the top level loop +/// structures in the specified function. +/// +class LoopInfo : public FunctionPass { + // BBMap - Mapping of basic blocks to the inner most loop they occur in + std::map<BasicBlock*, Loop*> BBMap; + std::vector<Loop*> TopLevelLoops; + friend class Loop; +public: + static char ID; // Pass identification, replacement for typeid + + LoopInfo() : FunctionPass((intptr_t)&ID) {} + ~LoopInfo() { releaseMemory(); } + + /// iterator/begin/end - The interface to the top-level loops in the current + /// function. + /// + typedef std::vector<Loop*>::const_iterator iterator; + iterator begin() const { return TopLevelLoops.begin(); } + iterator end() const { return TopLevelLoops.end(); } + + /// getLoopFor - Return the inner most loop that BB lives in. If a basic + /// block is in no loop (for example the entry node), null is returned. + /// + Loop *getLoopFor(const BasicBlock *BB) const { + std::map<BasicBlock *, Loop*>::const_iterator I= + BBMap.find(const_cast<BasicBlock*>(BB)); + return I != BBMap.end() ? I->second : 0; + } + + /// operator[] - same as getLoopFor... + /// + const Loop *operator[](const BasicBlock *BB) const { + return getLoopFor(BB); + } + + /// getLoopDepth - Return the loop nesting level of the specified block... + /// + unsigned getLoopDepth(const BasicBlock *BB) const { + const Loop *L = getLoopFor(BB); + return L ? L->getLoopDepth() : 0; + } + + // isLoopHeader - True if the block is a loop header node + bool isLoopHeader(BasicBlock *BB) const { + const Loop *L = getLoopFor(BB); + return L && L->getHeader() == BB; + } + + /// runOnFunction - Calculate the natural loop information. + /// + virtual bool runOnFunction(Function &F); + + virtual void releaseMemory(); + + void print(std::ostream &O, const Module* = 0) const; + void print(std::ostream *O, const Module* M = 0) const { + if (O) print(*O, M); + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + /// removeLoop - This removes the specified top-level loop from this loop info + /// object. The loop is not deleted, as it will presumably be inserted into + /// another loop. + Loop *removeLoop(iterator I); + + /// changeLoopFor - Change the top-level loop that contains BB to the + /// specified loop. This should be used by transformations that restructure + /// the loop hierarchy tree. + void changeLoopFor(BasicBlock *BB, Loop *L); + + /// changeTopLevelLoop - Replace the specified loop in the top-level loops + /// list with the indicated loop. + void changeTopLevelLoop(Loop *OldLoop, Loop *NewLoop); + + /// addTopLevelLoop - This adds the specified loop to the collection of + /// top-level loops. + void addTopLevelLoop(Loop *New) { + assert(New->getParentLoop() == 0 && "Loop already in subloop!"); + TopLevelLoops.push_back(New); + } + + /// removeBlock - This method completely removes BB from all data structures, + /// including all of the Loop objects it is nested in and our mapping from + /// BasicBlocks to loops. + void removeBlock(BasicBlock *BB); + +private: + void Calculate(DominatorTree &DT); + Loop *ConsiderForLoop(BasicBlock *BB, DominatorTree &DT); + void MoveSiblingLoopInto(Loop *NewChild, Loop *NewParent); + void InsertLoopInto(Loop *L, Loop *Parent); +}; + + +// Allow clients to walk the list of nested loops... +template <> struct GraphTraits<const Loop*> { + typedef const Loop NodeType; + typedef std::vector<Loop*>::const_iterator ChildIteratorType; + + static NodeType *getEntryNode(const Loop *L) { return L; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->end(); + } +}; + +template <> struct GraphTraits<Loop*> { + typedef Loop NodeType; + typedef std::vector<Loop*>::const_iterator ChildIteratorType; + + static NodeType *getEntryNode(Loop *L) { return L; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->end(); + } +}; + +} // End llvm namespace + +// Make sure that any clients of this file link in LoopInfo.cpp +FORCE_DEFINING_FILE_TO_BE_LINKED(LoopInfo) + +#endif diff --git a/include/llvm/Analysis/LoopPass.h b/include/llvm/Analysis/LoopPass.h new file mode 100644 index 0000000..08c2bcb --- /dev/null +++ b/include/llvm/Analysis/LoopPass.h @@ -0,0 +1,132 @@ +//===- LoopPass.h - LoopPass class ----------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Devang Patel and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines LoopPass class. All loop optimization +// and transformation passes are derived from LoopPass. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LOOP_PASS_H +#define LLVM_LOOP_PASS_H + +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/Pass.h" +#include "llvm/PassManagers.h" +#include "llvm/Function.h" + +namespace llvm { + +class LPPassManager; +class Loop; +class Function; + +class LoopPass : public Pass { + + public: + explicit LoopPass(intptr_t pid) : Pass(pid) {} + + // runOnLoop - This method should be implemented by the subclass to perform + // whatever action is necessary for the specfied Loop. + virtual bool runOnLoop (Loop *L, LPPassManager &LPM) = 0; + virtual bool runOnFunctionBody (Function &F, LPPassManager &LPM) { + return false; + } + + // Initialization and finalization hooks. + virtual bool doInitialization(Loop *L, LPPassManager &LPM) { + return false; + } + + // Finalization hook does not supply Loop because at this time + // loop nest is completely different. + virtual bool doFinalization() { return false; } + + // Check if this pass is suitable for the current LPPassManager, if + // available. This pass P is not suitable for a LPPassManager if P + // is not preserving higher level analysis info used by other + // LPPassManager passes. In such case, pop LPPassManager from the + // stack. This will force assignPassManager() to create new + // LPPassManger as expected. + void preparePassManager(PMStack &PMS); + + /// Assign pass manager to manager this pass + virtual void assignPassManager(PMStack &PMS, + PassManagerType PMT = PMT_LoopPassManager); + + /// Return what kind of Pass Manager can manage this pass. + virtual PassManagerType getPotentialPassManagerType() const { + return PMT_LoopPassManager; + } +}; + +class LPPassManager : public FunctionPass, public PMDataManager { + +public: + static char ID; + LPPassManager(int Depth); + + /// run - Execute all of the passes scheduled for execution. Keep track of + /// whether any of the passes modifies the module, and if so, return true. + bool runOnFunction(Function &F); + + /// Pass Manager itself does not invalidate any analysis info. + // LPPassManager needs LoopInfo. + void getAnalysisUsage(AnalysisUsage &Info) const; + + virtual const char *getPassName() const { + return "Loop Pass Manager"; + } + + // Print passes managed by this manager + void dumpPassStructure(unsigned Offset) { + llvm::cerr << std::string(Offset*2, ' ') << "Loop Pass Manager\n"; + for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { + Pass *P = getContainedPass(Index); + P->dumpPassStructure(Offset + 1); + dumpLastUses(P, Offset+1); + } + } + + Pass *getContainedPass(unsigned N) { + assert ( N < PassVector.size() && "Pass number out of range!"); + Pass *FP = static_cast<Pass *>(PassVector[N]); + return FP; + } + + virtual PassManagerType getPassManagerType() const { + return PMT_LoopPassManager; + } + +public: + // Delete loop from the loop queue and loop nest (LoopInfo). + void deleteLoopFromQueue(Loop *L); + + // Inset loop into the loop nest(LoopInfo) and loop queue(LQ). + void insertLoop(Loop *L, Loop *ParentLoop); + + // Reoptimize this loop. LPPassManager will re-insert this loop into the + // queue. This allows LoopPass to change loop nest for the loop. This + // utility may send LPPassManager into infinite loops so use caution. + void redoLoop(Loop *L); + +private: + /// verifyLoopInfo - Verify loop nest. + void verifyLoopInfo(); + +private: + std::deque<Loop *> LQ; + bool skipThisLoop; + bool redoThisLoop; + LoopInfo *LI; + Loop *CurrentLoop; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/MemoryDependenceAnalysis.h b/include/llvm/Analysis/MemoryDependenceAnalysis.h new file mode 100644 index 0000000..014922e --- /dev/null +++ b/include/llvm/Analysis/MemoryDependenceAnalysis.h @@ -0,0 +1,75 @@ +//===- llvm/Analysis/MemoryDependenceAnalysis.h - Memory Deps --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the Owen Anderson and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an analysis that determines, for a given memory operation, +// what preceding memory operations it depends on. It builds on alias analysis +// information, and tries to provide a lazy, caching interface to a common kind +// of alias information query. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_MEMORY_DEPENDENCE_H +#define LLVM_ANALYSIS_MEMORY_DEPENDENCE_H + +#include "llvm/Pass.h" +#include "llvm/Support/CallSite.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/Support/Compiler.h" +#include <map> + +namespace llvm { + +class Function; +class FunctionPass; +class Instruction; + +class MemoryDependenceAnalysis : public FunctionPass { + private: + + DenseMap<Instruction*, std::pair<Instruction*, bool> > depGraphLocal; + std::multimap<Instruction*, Instruction*> reverseDep; + + Instruction* getCallSiteDependency(CallSite C, Instruction* start, + bool local = true); + public: + + static Instruction* NonLocal; + static Instruction* None; + + static char ID; // Class identification, replacement for typeinfo + MemoryDependenceAnalysis() : FunctionPass((intptr_t)&ID) {} + + /// Pass Implementation stuff. This doesn't do any analysis. + /// + bool runOnFunction(Function &) {return false; } + + /// Clean up memory in between runs + void releaseMemory() { + depGraphLocal.clear(); + reverseDep.clear(); + } + + /// getAnalysisUsage - Does not modify anything. It uses Value Numbering + /// and Alias Analysis. + /// + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + /// getDependency - Return the instruction on which a memory operation + /// depends, starting with start. + Instruction* getDependency(Instruction* query, Instruction* start = 0, + bool local = true); + + /// removeInstruction - Remove an instruction from the dependence analysis, + /// updating the dependence of instructions that previously depended on it. + void removeInstruction(Instruction* rem); + }; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h new file mode 100644 index 0000000..854128e --- /dev/null +++ b/include/llvm/Analysis/Passes.h @@ -0,0 +1,117 @@ +//===-- llvm/Analysis/Passes.h - Constructors for analyses ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file defines prototypes for accessor functions that expose passes +// in the analysis libraries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_PASSES_H +#define LLVM_ANALYSIS_PASSES_H + +namespace llvm { + class FunctionPass; + class ImmutablePass; + class ModulePass; + class Pass; + + //===--------------------------------------------------------------------===// + // + // createGlobalsModRefPass - This pass provides alias and mod/ref info for + // global values that do not have their addresses taken. + // + Pass *createGlobalsModRefPass(); + + //===--------------------------------------------------------------------===// + // + // createAliasDebugger - This pass helps debug clients of AA + // + Pass *createAliasDebugger(); + + //===--------------------------------------------------------------------===// + // + // createAliasAnalysisCounterPass - This pass counts alias queries and how the + // alias analysis implementation responds. + // + ModulePass *createAliasAnalysisCounterPass(); + + //===--------------------------------------------------------------------===// + // + // createAAEvalPass - This pass implements a simple N^2 alias analysis + // accuracy evaluator. + // + FunctionPass *createAAEvalPass(); + + //===--------------------------------------------------------------------===// + // + // createNoAAPass - This pass implements a "I don't know" alias analysis. + // + ImmutablePass *createNoAAPass(); + + //===--------------------------------------------------------------------===// + // + // createBasicAliasAnalysisPass - This pass implements the default alias + // analysis. + // + ImmutablePass *createBasicAliasAnalysisPass(); + + //===--------------------------------------------------------------------===// + // + // createAndersensPass - This pass implements Andersen's interprocedural alias + // analysis. + // + ModulePass *createAndersensPass(); + + //===--------------------------------------------------------------------===// + // + // createBasicVNPass - This pass walks SSA def-use chains to trivially + // identify lexically identical expressions. + // + ImmutablePass *createBasicVNPass(); + + //===--------------------------------------------------------------------===// + // + // createProfileLoaderPass - This pass loads information from a profile dump + // file. + // + ModulePass *createProfileLoaderPass(); + + //===--------------------------------------------------------------------===// + // + // createNoProfileInfoPass - This pass implements the default "no profile". + // + ImmutablePass *createNoProfileInfoPass(); + + //===--------------------------------------------------------------------===// + // + // createDSAAPass - This pass implements simple context sensitive alias + // analysis. + // + ModulePass *createDSAAPass(); + + //===--------------------------------------------------------------------===// + // + // createDSOptPass - This pass uses DSA to do a series of simple + // optimizations. + // + ModulePass *createDSOptPass(); + + //===--------------------------------------------------------------------===// + // + // createSteensgaardPass - This pass uses the data structure graphs to do a + // simple context insensitive alias analysis. + // + ModulePass *createSteensgaardPass(); + + // Minor pass prototypes, allowing us to expose them through bugpoint and + // analyze. + FunctionPass *createInstCountPass(); +} + +#endif diff --git a/include/llvm/Analysis/PostDominators.h b/include/llvm/Analysis/PostDominators.h new file mode 100644 index 0000000..091925e --- /dev/null +++ b/include/llvm/Analysis/PostDominators.h @@ -0,0 +1,86 @@ +//=- llvm/Analysis/PostDominators.h - Post Dominator Calculation-*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes interfaces to post dominance information. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_POST_DOMINATORS_H +#define LLVM_ANALYSIS_POST_DOMINATORS_H + +#include "llvm/Analysis/Dominators.h" + +namespace llvm { + +/// PostDominatorTree Class - Concrete subclass of DominatorTree that is used to +/// compute the a post-dominator tree. +/// +struct PostDominatorTree : public DominatorTreeBase { + static char ID; // Pass identification, replacement for typeid + + PostDominatorTree() : + DominatorTreeBase((intptr_t)&ID, true) {} + + virtual bool runOnFunction(Function &F) { + reset(); // Reset from the last time we were run... + calculate(F); + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } +private: + void calculate(Function &F); + DomTreeNode *getNodeForBlock(BasicBlock *BB); + unsigned DFSPass(BasicBlock *V, InfoRec &VInfo,unsigned N); + void Compress(BasicBlock *V, InfoRec &VInfo); + BasicBlock *Eval(BasicBlock *V); + void Link(BasicBlock *V, BasicBlock *W, InfoRec &WInfo); + + inline BasicBlock *getIDom(BasicBlock *BB) const { + std::map<BasicBlock*, BasicBlock*>::const_iterator I = IDoms.find(BB); + return I != IDoms.end() ? I->second : 0; + } +}; + + +/// PostDominanceFrontier Class - Concrete subclass of DominanceFrontier that is +/// used to compute the a post-dominance frontier. +/// +struct PostDominanceFrontier : public DominanceFrontierBase { + static char ID; + PostDominanceFrontier() + : DominanceFrontierBase((intptr_t) &ID, true) {} + + virtual bool runOnFunction(Function &) { + Frontiers.clear(); + PostDominatorTree &DT = getAnalysis<PostDominatorTree>(); + Roots = DT.getRoots(); + if (const DomTreeNode *Root = DT.getRootNode()) + calculate(DT, Root); + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + AU.addRequired<PostDominatorTree>(); + } + +private: + const DomSetType &calculate(const PostDominatorTree &DT, + const DomTreeNode *Node); +}; + +} // End llvm namespace + +// Make sure that any clients of this file link in PostDominators.cpp +FORCE_DEFINING_FILE_TO_BE_LINKED(PostDominanceFrontier) + +#endif diff --git a/include/llvm/Analysis/ProfileInfo.h b/include/llvm/Analysis/ProfileInfo.h new file mode 100644 index 0000000..74e3bc2 --- /dev/null +++ b/include/llvm/Analysis/ProfileInfo.h @@ -0,0 +1,67 @@ +//===- llvm/Analysis/ProfileInfo.h - Profile Info Interface -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the generic ProfileInfo interface, which is used as the +// common interface used by all clients of profiling information, and +// implemented either by making static guestimations, or by actually reading in +// profiling information gathered by running the program. +// +// Note that to be useful, all profile-based optimizations should preserve +// ProfileInfo, which requires that they notify it when changes to the CFG are +// made. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_PROFILEINFO_H +#define LLVM_ANALYSIS_PROFILEINFO_H + +#include <string> +#include <map> + +namespace llvm { + class BasicBlock; + class Pass; + + /// ProfileInfo Class - This class holds and maintains edge profiling + /// information for some unit of code. + class ProfileInfo { + protected: + // EdgeCounts - Count the number of times a transition between two blocks is + // executed. As a special case, we also hold an edge from the null + // BasicBlock to the entry block to indicate how many times the function was + // entered. + std::map<std::pair<BasicBlock*, BasicBlock*>, unsigned> EdgeCounts; + public: + static char ID; // Class identification, replacement for typeinfo + virtual ~ProfileInfo(); // We want to be subclassed + + //===------------------------------------------------------------------===// + /// Profile Information Queries + /// + unsigned getExecutionCount(BasicBlock *BB) const; + + unsigned getEdgeWeight(BasicBlock *Src, BasicBlock *Dest) const { + std::map<std::pair<BasicBlock*, BasicBlock*>, unsigned>::const_iterator I= + EdgeCounts.find(std::make_pair(Src, Dest)); + return I != EdgeCounts.end() ? I->second : 0; + } + + //===------------------------------------------------------------------===// + /// Analysis Update Methods + /// + + }; + + /// createProfileLoaderPass - This function returns a Pass that loads the + /// profiling information for the module from the specified filename, making + /// it available to the optimizers. + Pass *createProfileLoaderPass(const std::string &Filename); +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/ProfileInfoLoader.h b/include/llvm/Analysis/ProfileInfoLoader.h new file mode 100644 index 0000000..6c3c41d --- /dev/null +++ b/include/llvm/Analysis/ProfileInfoLoader.h @@ -0,0 +1,89 @@ +//===- ProfileInfoLoader.h - Load & convert profile information -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The ProfileInfoLoader class is used to load and represent profiling +// information read in from the dump file. If conversions between formats are +// needed, it can also do this. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_PROFILEINFOLOADER_H +#define LLVM_ANALYSIS_PROFILEINFOLOADER_H + +#include <vector> +#include <string> +#include <utility> + +namespace llvm { + +class Module; +class Function; +class BasicBlock; + +class ProfileInfoLoader { + Module &M; + std::vector<std::string> CommandLines; + std::vector<unsigned> FunctionCounts; + std::vector<unsigned> BlockCounts; + std::vector<unsigned> EdgeCounts; + std::vector<unsigned> BBTrace; +public: + // ProfileInfoLoader ctor - Read the specified profiling data file, exiting + // the program if the file is invalid or broken. + ProfileInfoLoader(const char *ToolName, const std::string &Filename, + Module &M); + + unsigned getNumExecutions() const { return CommandLines.size(); } + const std::string &getExecution(unsigned i) const { return CommandLines[i]; } + + // getFunctionCounts - This method is used by consumers of function counting + // information. If we do not directly have function count information, we + // compute it from other, more refined, types of profile information. + // + void getFunctionCounts(std::vector<std::pair<Function*, unsigned> > &Counts); + + // hasAccurateBlockCounts - Return true if we can synthesize accurate block + // frequency information from whatever we have. + // + bool hasAccurateBlockCounts() const { + return !BlockCounts.empty() || !EdgeCounts.empty(); + } + + // hasAccurateEdgeCounts - Return true if we can synthesize accurate edge + // frequency information from whatever we have. + // + bool hasAccurateEdgeCounts() const { + return !EdgeCounts.empty(); + } + + // getBlockCounts - This method is used by consumers of block counting + // information. If we do not directly have block count information, we + // compute it from other, more refined, types of profile information. + // + void getBlockCounts(std::vector<std::pair<BasicBlock*, unsigned> > &Counts); + + // getEdgeCounts - This method is used by consumers of edge counting + // information. If we do not directly have edge count information, we compute + // it from other, more refined, types of profile information. + // + // Edges are represented as a pair, where the first element is the basic block + // and the second element is the successor number. + // + typedef std::pair<BasicBlock*, unsigned> Edge; + void getEdgeCounts(std::vector<std::pair<Edge, unsigned> > &Counts); + + // getBBTrace - This method is used by consumers of basic-block trace + // information. + // + void getBBTrace(std::vector<BasicBlock *> &Trace); +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Analysis/ProfileInfoTypes.h b/include/llvm/Analysis/ProfileInfoTypes.h new file mode 100644 index 0000000..c662c3c --- /dev/null +++ b/include/llvm/Analysis/ProfileInfoTypes.h @@ -0,0 +1,28 @@ +/*===-- ProfileInfoTypes.h - Profiling info shared constants ------*- C -*-===*\ +|* +|* The LLVM Compiler Infrastructure +|* +|* This file was developed by the LLVM research group and is distributed under +|* the University of Illinois Open Source License. See LICENSE.TXT for details. +|* +|*===----------------------------------------------------------------------===*| +|* +|* This file defines constants shared by the various different profiling +|* runtime libraries and the LLVM C++ profile info loader. It must be a +|* C header because, at present, the profiling runtimes are written in C. +|* +\*===----------------------------------------------------------------------===*/ + +#ifndef LLVM_ANALYSIS_PROFILEINFOTYPES_H +#define LLVM_ANALYSIS_PROFILEINFOTYPES_H + +enum ProfilingType { + ArgumentInfo = 1, /* The command line argument block */ + FunctionInfo = 2, /* Function profiling information */ + BlockInfo = 3, /* Block profiling information */ + EdgeInfo = 4, /* Edge profiling information */ + PathInfo = 5, /* Path profiling information */ + BBTraceInfo = 6 /* Basic block trace information */ +}; + +#endif /* LLVM_ANALYSIS_PROFILEINFOTYPES_H */ diff --git a/include/llvm/Analysis/ScalarEvolution.h b/include/llvm/Analysis/ScalarEvolution.h new file mode 100644 index 0000000..b6a58fe --- /dev/null +++ b/include/llvm/Analysis/ScalarEvolution.h @@ -0,0 +1,250 @@ +//===- llvm/Analysis/ScalarEvolution.h - Scalar Evolution -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The ScalarEvolution class is an LLVM pass which can be used to analyze and +// catagorize scalar expressions in loops. It specializes in recognizing +// general induction variables, representing them with the abstract and opaque +// SCEV class. Given this analysis, trip counts of loops and other important +// properties can be obtained. +// +// This analysis is primarily useful for induction variable substitution and +// strength reduction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SCALAREVOLUTION_H +#define LLVM_ANALYSIS_SCALAREVOLUTION_H + +#include "llvm/Pass.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Streams.h" +#include <set> + +namespace llvm { + class Instruction; + class Type; + class ConstantRange; + class Loop; + class LoopInfo; + class SCEVHandle; + + /// SCEV - This class represent an analyzed expression in the program. These + /// are reference counted opaque objects that the client is not allowed to + /// do much with directly. + /// + class SCEV { + const unsigned SCEVType; // The SCEV baseclass this node corresponds to + mutable unsigned RefCount; + + friend class SCEVHandle; + void addRef() const { ++RefCount; } + void dropRef() const { + if (--RefCount == 0) + delete this; + } + + SCEV(const SCEV &); // DO NOT IMPLEMENT + void operator=(const SCEV &); // DO NOT IMPLEMENT + protected: + virtual ~SCEV(); + public: + explicit SCEV(unsigned SCEVTy) : SCEVType(SCEVTy), RefCount(0) {} + + /// getNegativeSCEV - Return the SCEV object corresponding to -V. + /// + static SCEVHandle getNegativeSCEV(const SCEVHandle &V); + + /// getMinusSCEV - Return LHS-RHS. + /// + static SCEVHandle getMinusSCEV(const SCEVHandle &LHS, + const SCEVHandle &RHS); + + + unsigned getSCEVType() const { return SCEVType; } + + /// getValueRange - Return the tightest constant bounds that this value is + /// known to have. This method is only valid on integer SCEV objects. + virtual ConstantRange getValueRange() const; + + /// isLoopInvariant - Return true if the value of this SCEV is unchanging in + /// the specified loop. + virtual bool isLoopInvariant(const Loop *L) const = 0; + + /// hasComputableLoopEvolution - Return true if this SCEV changes value in a + /// known way in the specified loop. This property being true implies that + /// the value is variant in the loop AND that we can emit an expression to + /// compute the value of the expression at any particular loop iteration. + virtual bool hasComputableLoopEvolution(const Loop *L) const = 0; + + /// getType - Return the LLVM type of this SCEV expression. + /// + virtual const Type *getType() const = 0; + + /// getBitWidth - Get the bit width of the type, if it has one, 0 otherwise. + /// + uint32_t getBitWidth() const; + + /// replaceSymbolicValuesWithConcrete - If this SCEV internally references + /// the symbolic value "Sym", construct and return a new SCEV that produces + /// the same value, but which uses the concrete value Conc instead of the + /// symbolic value. If this SCEV does not use the symbolic value, it + /// returns itself. + virtual SCEVHandle + replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym, + const SCEVHandle &Conc) const = 0; + + /// print - Print out the internal representation of this scalar to the + /// specified stream. This should really only be used for debugging + /// purposes. + virtual void print(std::ostream &OS) const = 0; + void print(std::ostream *OS) const { if (OS) print(*OS); } + + /// dump - This method is used for debugging. + /// + void dump() const; + }; + + inline std::ostream &operator<<(std::ostream &OS, const SCEV &S) { + S.print(OS); + return OS; + } + + /// SCEVCouldNotCompute - An object of this class is returned by queries that + /// could not be answered. For example, if you ask for the number of + /// iterations of a linked-list traversal loop, you will get one of these. + /// None of the standard SCEV operations are valid on this class, it is just a + /// marker. + struct SCEVCouldNotCompute : public SCEV { + SCEVCouldNotCompute(); + + // None of these methods are valid for this object. + virtual bool isLoopInvariant(const Loop *L) const; + virtual const Type *getType() const; + virtual bool hasComputableLoopEvolution(const Loop *L) const; + virtual void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + virtual SCEVHandle + replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym, + const SCEVHandle &Conc) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVCouldNotCompute *S) { return true; } + static bool classof(const SCEV *S); + }; + + /// SCEVHandle - This class is used to maintain the SCEV object's refcounts, + /// freeing the objects when the last reference is dropped. + class SCEVHandle { + SCEV *S; + SCEVHandle(); // DO NOT IMPLEMENT + public: + SCEVHandle(const SCEV *s) : S(const_cast<SCEV*>(s)) { + assert(S && "Cannot create a handle to a null SCEV!"); + S->addRef(); + } + SCEVHandle(const SCEVHandle &RHS) : S(RHS.S) { + S->addRef(); + } + ~SCEVHandle() { S->dropRef(); } + + operator SCEV*() const { return S; } + + SCEV &operator*() const { return *S; } + SCEV *operator->() const { return S; } + + bool operator==(SCEV *RHS) const { return S == RHS; } + bool operator!=(SCEV *RHS) const { return S != RHS; } + + const SCEVHandle &operator=(SCEV *RHS) { + if (S != RHS) { + S->dropRef(); + S = RHS; + S->addRef(); + } + return *this; + } + + const SCEVHandle &operator=(const SCEVHandle &RHS) { + if (S != RHS.S) { + S->dropRef(); + S = RHS.S; + S->addRef(); + } + return *this; + } + }; + + template<typename From> struct simplify_type; + template<> struct simplify_type<const SCEVHandle> { + typedef SCEV* SimpleType; + static SimpleType getSimplifiedValue(const SCEVHandle &Node) { + return Node; + } + }; + template<> struct simplify_type<SCEVHandle> + : public simplify_type<const SCEVHandle> {}; + + /// ScalarEvolution - This class is the main scalar evolution driver. Because + /// client code (intentionally) can't do much with the SCEV objects directly, + /// they must ask this class for services. + /// + class ScalarEvolution : public FunctionPass { + void *Impl; // ScalarEvolution uses the pimpl pattern + public: + static char ID; // Pass identification, replacement for typeid + ScalarEvolution() : FunctionPass((intptr_t)&ID), Impl(0) {} + + /// getSCEV - Return a SCEV expression handle for the full generality of the + /// specified expression. + SCEVHandle getSCEV(Value *V) const; + + /// hasSCEV - Return true if the SCEV for this value has already been + /// computed. + bool hasSCEV(Value *V) const; + + /// setSCEV - Insert the specified SCEV into the map of current SCEVs for + /// the specified value. + void setSCEV(Value *V, const SCEVHandle &H); + + /// getSCEVAtScope - Return a SCEV expression handle for the specified value + /// at the specified scope in the program. The L value specifies a loop + /// nest to evaluate the expression at, where null is the top-level or a + /// specified loop is immediately inside of the loop. + /// + /// This method can be used to compute the exit value for a variable defined + /// in a loop by querying what the value will hold in the parent loop. + /// + /// If this value is not computable at this scope, a SCEVCouldNotCompute + /// object is returned. + SCEVHandle getSCEVAtScope(Value *V, const Loop *L) const; + + /// getIterationCount - If the specified loop has a predictable iteration + /// count, return it, otherwise return a SCEVCouldNotCompute object. + SCEVHandle getIterationCount(const Loop *L) const; + + /// hasLoopInvariantIterationCount - Return true if the specified loop has + /// an analyzable loop-invariant iteration count. + bool hasLoopInvariantIterationCount(const Loop *L) const; + + /// deleteValueFromRecords - This method should be called by the + /// client before it removes a Value from the program, to make sure + /// that no dangling references are left around. + void deleteValueFromRecords(Value *V) const; + + virtual bool runOnFunction(Function &F); + virtual void releaseMemory(); + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void print(std::ostream &OS, const Module* = 0) const; + void print(std::ostream *OS, const Module* M = 0) const { + if (OS) print(*OS, M); + } + }; +} + +#endif diff --git a/include/llvm/Analysis/ScalarEvolutionExpander.h b/include/llvm/Analysis/ScalarEvolutionExpander.h new file mode 100644 index 0000000..a5cc713 --- /dev/null +++ b/include/llvm/Analysis/ScalarEvolutionExpander.h @@ -0,0 +1,153 @@ +//===---- llvm/Analysis/ScalarEvolutionExpander.h - SCEV Exprs --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the classes used to generate code from scalar expressions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SCALAREVOLUTION_EXPANDER_H +#define LLVM_ANALYSIS_SCALAREVOLUTION_EXPANDER_H + +#include "llvm/BasicBlock.h" +#include "llvm/Constants.h" +#include "llvm/Instructions.h" +#include "llvm/Type.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/Analysis/ScalarEvolutionExpressions.h" +#include "llvm/Support/CFG.h" + +namespace llvm { + /// SCEVExpander - This class uses information about analyze scalars to + /// rewrite expressions in canonical form. + /// + /// Clients should create an instance of this class when rewriting is needed, + /// and destroy it when finished to allow the release of the associated + /// memory. + struct SCEVExpander : public SCEVVisitor<SCEVExpander, Value*> { + ScalarEvolution &SE; + LoopInfo &LI; + std::map<SCEVHandle, Value*> InsertedExpressions; + std::set<Instruction*> InsertedInstructions; + + Instruction *InsertPt; + + friend struct SCEVVisitor<SCEVExpander, Value*>; + public: + SCEVExpander(ScalarEvolution &se, LoopInfo &li) : SE(se), LI(li) {} + + LoopInfo &getLoopInfo() const { return LI; } + + /// clear - Erase the contents of the InsertedExpressions map so that users + /// trying to expand the same expression into multiple BasicBlocks or + /// different places within the same BasicBlock can do so. + void clear() { InsertedExpressions.clear(); } + + /// isInsertedInstruction - Return true if the specified instruction was + /// inserted by the code rewriter. If so, the client should not modify the + /// instruction. + bool isInsertedInstruction(Instruction *I) const { + return InsertedInstructions.count(I); + } + + /// getOrInsertCanonicalInductionVariable - This method returns the + /// canonical induction variable of the specified type for the specified + /// loop (inserting one if there is none). A canonical induction variable + /// starts at zero and steps by one on each iteration. + Value *getOrInsertCanonicalInductionVariable(const Loop *L, const Type *Ty){ + assert(Ty->isInteger() && "Can only insert integer induction variables!"); + SCEVHandle H = SCEVAddRecExpr::get(SCEVUnknown::getIntegerSCEV(0, Ty), + SCEVUnknown::getIntegerSCEV(1, Ty), L); + return expand(H); + } + + /// addInsertedValue - Remember the specified instruction as being the + /// canonical form for the specified SCEV. + void addInsertedValue(Instruction *I, SCEV *S) { + InsertedExpressions[S] = (Value*)I; + InsertedInstructions.insert(I); + } + + Instruction *getInsertionPoint() const { return InsertPt; } + + /// expandCodeFor - Insert code to directly compute the specified SCEV + /// expression into the program. The inserted code is inserted into the + /// specified block. + Value *expandCodeFor(SCEVHandle SH, Instruction *IP) { + // Expand the code for this SCEV. + this->InsertPt = IP; + return expand(SH); + } + + /// InsertCastOfTo - Insert a cast of V to the specified type, doing what + /// we can to share the casts. + static Value *InsertCastOfTo(Instruction::CastOps opcode, Value *V, + const Type *Ty); + /// InsertBinop - Insert the specified binary operator, doing a small amount + /// of work to avoid inserting an obviously redundant operation. + static Value *InsertBinop(Instruction::BinaryOps Opcode, Value *LHS, + Value *RHS, Instruction *&InsertPt); + protected: + Value *expand(SCEV *S) { + // Check to see if we already expanded this. + std::map<SCEVHandle, Value*>::iterator I = InsertedExpressions.find(S); + if (I != InsertedExpressions.end()) + return I->second; + + Value *V = visit(S); + InsertedExpressions[S] = V; + return V; + } + + Value *visitConstant(SCEVConstant *S) { + return S->getValue(); + } + + Value *visitTruncateExpr(SCEVTruncateExpr *S) { + Value *V = expand(S->getOperand()); + return CastInst::createTruncOrBitCast(V, S->getType(), "tmp.", InsertPt); + } + + Value *visitZeroExtendExpr(SCEVZeroExtendExpr *S) { + Value *V = expand(S->getOperand()); + return CastInst::createZExtOrBitCast(V, S->getType(), "tmp.", InsertPt); + } + + Value *visitSignExtendExpr(SCEVSignExtendExpr *S) { + Value *V = expand(S->getOperand()); + return CastInst::createSExtOrBitCast(V, S->getType(), "tmp.", InsertPt); + } + + Value *visitAddExpr(SCEVAddExpr *S) { + Value *V = expand(S->getOperand(S->getNumOperands()-1)); + + // Emit a bunch of add instructions + for (int i = S->getNumOperands()-2; i >= 0; --i) + V = InsertBinop(Instruction::Add, V, expand(S->getOperand(i)), + InsertPt); + return V; + } + + Value *visitMulExpr(SCEVMulExpr *S); + + Value *visitSDivExpr(SCEVSDivExpr *S) { + Value *LHS = expand(S->getLHS()); + Value *RHS = expand(S->getRHS()); + return InsertBinop(Instruction::SDiv, LHS, RHS, InsertPt); + } + + Value *visitAddRecExpr(SCEVAddRecExpr *S); + + Value *visitUnknown(SCEVUnknown *S) { + return S->getValue(); + } + }; +} + +#endif + diff --git a/include/llvm/Analysis/ScalarEvolutionExpressions.h b/include/llvm/Analysis/ScalarEvolutionExpressions.h new file mode 100644 index 0000000..af1656e --- /dev/null +++ b/include/llvm/Analysis/ScalarEvolutionExpressions.h @@ -0,0 +1,580 @@ +//===- llvm/Analysis/ScalarEvolutionExpressions.h - SCEV Exprs --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the classes used to represent and build scalar expressions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_SCALAREVOLUTION_EXPRESSIONS_H +#define LLVM_ANALYSIS_SCALAREVOLUTION_EXPRESSIONS_H + +#include "llvm/Analysis/ScalarEvolution.h" + +namespace llvm { + class ConstantInt; + class ConstantRange; + class APInt; + + enum SCEVTypes { + // These should be ordered in terms of increasing complexity to make the + // folders simpler. + scConstant, scTruncate, scZeroExtend, scSignExtend, scAddExpr, scMulExpr, + scSDivExpr, scAddRecExpr, scUnknown, scCouldNotCompute + }; + + //===--------------------------------------------------------------------===// + /// SCEVConstant - This class represents a constant integer value. + /// + class SCEVConstant : public SCEV { + ConstantInt *V; + explicit SCEVConstant(ConstantInt *v) : SCEV(scConstant), V(v) {} + + virtual ~SCEVConstant(); + public: + /// get method - This just gets and returns a new SCEVConstant object. + /// + static SCEVHandle get(ConstantInt *V); + static SCEVHandle get(const APInt& Val); + + ConstantInt *getValue() const { return V; } + + /// getValueRange - Return the tightest constant bounds that this value is + /// known to have. This method is only valid on integer SCEV objects. + virtual ConstantRange getValueRange() const; + + virtual bool isLoopInvariant(const Loop *L) const { + return true; + } + + virtual bool hasComputableLoopEvolution(const Loop *L) const { + return false; // Not loop variant + } + + virtual const Type *getType() const; + + SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym, + const SCEVHandle &Conc) const { + return this; + } + + virtual void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVConstant *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scConstant; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVTruncateExpr - This class represents a truncation of an integer value + /// to a smaller integer value. + /// + class SCEVTruncateExpr : public SCEV { + SCEVHandle Op; + const Type *Ty; + SCEVTruncateExpr(const SCEVHandle &op, const Type *ty); + virtual ~SCEVTruncateExpr(); + public: + /// get method - This just gets and returns a new SCEVTruncate object + /// + static SCEVHandle get(const SCEVHandle &Op, const Type *Ty); + + const SCEVHandle &getOperand() const { return Op; } + virtual const Type *getType() const { return Ty; } + + virtual bool isLoopInvariant(const Loop *L) const { + return Op->isLoopInvariant(L); + } + + virtual bool hasComputableLoopEvolution(const Loop *L) const { + return Op->hasComputableLoopEvolution(L); + } + + SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym, + const SCEVHandle &Conc) const { + SCEVHandle H = Op->replaceSymbolicValuesWithConcrete(Sym, Conc); + if (H == Op) + return this; + return get(H, Ty); + } + + /// getValueRange - Return the tightest constant bounds that this value is + /// known to have. This method is only valid on integer SCEV objects. + virtual ConstantRange getValueRange() const; + + virtual void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVTruncateExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scTruncate; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVZeroExtendExpr - This class represents a zero extension of a small + /// integer value to a larger integer value. + /// + class SCEVZeroExtendExpr : public SCEV { + SCEVHandle Op; + const Type *Ty; + SCEVZeroExtendExpr(const SCEVHandle &op, const Type *ty); + virtual ~SCEVZeroExtendExpr(); + public: + /// get method - This just gets and returns a new SCEVZeroExtend object + /// + static SCEVHandle get(const SCEVHandle &Op, const Type *Ty); + + const SCEVHandle &getOperand() const { return Op; } + virtual const Type *getType() const { return Ty; } + + virtual bool isLoopInvariant(const Loop *L) const { + return Op->isLoopInvariant(L); + } + + virtual bool hasComputableLoopEvolution(const Loop *L) const { + return Op->hasComputableLoopEvolution(L); + } + + /// getValueRange - Return the tightest constant bounds that this value is + /// known to have. This method is only valid on integer SCEV objects. + virtual ConstantRange getValueRange() const; + + SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym, + const SCEVHandle &Conc) const { + SCEVHandle H = Op->replaceSymbolicValuesWithConcrete(Sym, Conc); + if (H == Op) + return this; + return get(H, Ty); + } + + virtual void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVZeroExtendExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scZeroExtend; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVSignExtendExpr - This class represents a sign extension of a small + /// integer value to a larger integer value. + /// + class SCEVSignExtendExpr : public SCEV { + SCEVHandle Op; + const Type *Ty; + SCEVSignExtendExpr(const SCEVHandle &op, const Type *ty); + virtual ~SCEVSignExtendExpr(); + public: + /// get method - This just gets and returns a new SCEVSignExtend object + /// + static SCEVHandle get(const SCEVHandle &Op, const Type *Ty); + + const SCEVHandle &getOperand() const { return Op; } + virtual const Type *getType() const { return Ty; } + + virtual bool isLoopInvariant(const Loop *L) const { + return Op->isLoopInvariant(L); + } + + virtual bool hasComputableLoopEvolution(const Loop *L) const { + return Op->hasComputableLoopEvolution(L); + } + + /// getValueRange - Return the tightest constant bounds that this value is + /// known to have. This method is only valid on integer SCEV objects. + virtual ConstantRange getValueRange() const; + + SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym, + const SCEVHandle &Conc) const { + SCEVHandle H = Op->replaceSymbolicValuesWithConcrete(Sym, Conc); + if (H == Op) + return this; + return get(H, Ty); + } + + virtual void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVSignExtendExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scSignExtend; + } + }; + + + //===--------------------------------------------------------------------===// + /// SCEVCommutativeExpr - This node is the base class for n'ary commutative + /// operators. + /// + class SCEVCommutativeExpr : public SCEV { + std::vector<SCEVHandle> Operands; + + protected: + SCEVCommutativeExpr(enum SCEVTypes T, const std::vector<SCEVHandle> &ops) + : SCEV(T) { + Operands.reserve(ops.size()); + Operands.insert(Operands.end(), ops.begin(), ops.end()); + } + ~SCEVCommutativeExpr(); + + public: + unsigned getNumOperands() const { return Operands.size(); } + const SCEVHandle &getOperand(unsigned i) const { + assert(i < Operands.size() && "Operand index out of range!"); + return Operands[i]; + } + + const std::vector<SCEVHandle> &getOperands() const { return Operands; } + typedef std::vector<SCEVHandle>::const_iterator op_iterator; + op_iterator op_begin() const { return Operands.begin(); } + op_iterator op_end() const { return Operands.end(); } + + + virtual bool isLoopInvariant(const Loop *L) const { + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (!getOperand(i)->isLoopInvariant(L)) return false; + return true; + } + + // hasComputableLoopEvolution - Commutative expressions have computable loop + // evolutions iff they have at least one operand that varies with the loop, + // but that all varying operands are computable. + virtual bool hasComputableLoopEvolution(const Loop *L) const { + bool HasVarying = false; + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (!getOperand(i)->isLoopInvariant(L)) + if (getOperand(i)->hasComputableLoopEvolution(L)) + HasVarying = true; + else + return false; + return HasVarying; + } + + SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym, + const SCEVHandle &Conc) const; + + virtual const char *getOperationStr() const = 0; + + virtual const Type *getType() const { return getOperand(0)->getType(); } + virtual void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVCommutativeExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scAddExpr || + S->getSCEVType() == scMulExpr; + } + }; + + + //===--------------------------------------------------------------------===// + /// SCEVAddExpr - This node represents an addition of some number of SCEVs. + /// + class SCEVAddExpr : public SCEVCommutativeExpr { + SCEVAddExpr(const std::vector<SCEVHandle> &ops) + : SCEVCommutativeExpr(scAddExpr, ops) { + } + + public: + static SCEVHandle get(std::vector<SCEVHandle> &Ops); + + static SCEVHandle get(const SCEVHandle &LHS, const SCEVHandle &RHS) { + std::vector<SCEVHandle> Ops; + Ops.push_back(LHS); + Ops.push_back(RHS); + return get(Ops); + } + + static SCEVHandle get(const SCEVHandle &Op0, const SCEVHandle &Op1, + const SCEVHandle &Op2) { + std::vector<SCEVHandle> Ops; + Ops.push_back(Op0); + Ops.push_back(Op1); + Ops.push_back(Op2); + return get(Ops); + } + + virtual const char *getOperationStr() const { return " + "; } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVAddExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scAddExpr; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVMulExpr - This node represents multiplication of some number of SCEVs. + /// + class SCEVMulExpr : public SCEVCommutativeExpr { + SCEVMulExpr(const std::vector<SCEVHandle> &ops) + : SCEVCommutativeExpr(scMulExpr, ops) { + } + + public: + static SCEVHandle get(std::vector<SCEVHandle> &Ops); + + static SCEVHandle get(const SCEVHandle &LHS, const SCEVHandle &RHS) { + std::vector<SCEVHandle> Ops; + Ops.push_back(LHS); + Ops.push_back(RHS); + return get(Ops); + } + + virtual const char *getOperationStr() const { return " * "; } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVMulExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scMulExpr; + } + }; + + + //===--------------------------------------------------------------------===// + /// SCEVSDivExpr - This class represents a binary signed division operation. + /// + class SCEVSDivExpr : public SCEV { + SCEVHandle LHS, RHS; + SCEVSDivExpr(const SCEVHandle &lhs, const SCEVHandle &rhs) + : SCEV(scSDivExpr), LHS(lhs), RHS(rhs) {} + + virtual ~SCEVSDivExpr(); + public: + /// get method - This just gets and returns a new SCEVSDiv object. + /// + static SCEVHandle get(const SCEVHandle &LHS, const SCEVHandle &RHS); + + const SCEVHandle &getLHS() const { return LHS; } + const SCEVHandle &getRHS() const { return RHS; } + + virtual bool isLoopInvariant(const Loop *L) const { + return LHS->isLoopInvariant(L) && RHS->isLoopInvariant(L); + } + + virtual bool hasComputableLoopEvolution(const Loop *L) const { + return LHS->hasComputableLoopEvolution(L) && + RHS->hasComputableLoopEvolution(L); + } + + SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym, + const SCEVHandle &Conc) const { + SCEVHandle L = LHS->replaceSymbolicValuesWithConcrete(Sym, Conc); + SCEVHandle R = RHS->replaceSymbolicValuesWithConcrete(Sym, Conc); + if (L == LHS && R == RHS) + return this; + else + return get(L, R); + } + + + virtual const Type *getType() const; + + void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVSDivExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scSDivExpr; + } + }; + + + //===--------------------------------------------------------------------===// + /// SCEVAddRecExpr - This node represents a polynomial recurrence on the trip + /// count of the specified loop. + /// + /// All operands of an AddRec are required to be loop invariant. + /// + class SCEVAddRecExpr : public SCEV { + std::vector<SCEVHandle> Operands; + const Loop *L; + + SCEVAddRecExpr(const std::vector<SCEVHandle> &ops, const Loop *l) + : SCEV(scAddRecExpr), Operands(ops), L(l) { + for (unsigned i = 0, e = Operands.size(); i != e; ++i) + assert(Operands[i]->isLoopInvariant(l) && + "Operands of AddRec must be loop-invariant!"); + } + ~SCEVAddRecExpr(); + public: + static SCEVHandle get(const SCEVHandle &Start, const SCEVHandle &Step, + const Loop *); + static SCEVHandle get(std::vector<SCEVHandle> &Operands, + const Loop *); + static SCEVHandle get(const std::vector<SCEVHandle> &Operands, + const Loop *L) { + std::vector<SCEVHandle> NewOp(Operands); + return get(NewOp, L); + } + + typedef std::vector<SCEVHandle>::const_iterator op_iterator; + op_iterator op_begin() const { return Operands.begin(); } + op_iterator op_end() const { return Operands.end(); } + + unsigned getNumOperands() const { return Operands.size(); } + const SCEVHandle &getOperand(unsigned i) const { return Operands[i]; } + const SCEVHandle &getStart() const { return Operands[0]; } + const Loop *getLoop() const { return L; } + + + /// getStepRecurrence - This method constructs and returns the recurrence + /// indicating how much this expression steps by. If this is a polynomial + /// of degree N, it returns a chrec of degree N-1. + SCEVHandle getStepRecurrence() const { + if (getNumOperands() == 2) return getOperand(1); + return SCEVAddRecExpr::get(std::vector<SCEVHandle>(op_begin()+1,op_end()), + getLoop()); + } + + virtual bool hasComputableLoopEvolution(const Loop *QL) const { + if (L == QL) return true; + return false; + } + + virtual bool isLoopInvariant(const Loop *QueryLoop) const; + + virtual const Type *getType() const { return Operands[0]->getType(); } + + /// isAffine - Return true if this is an affine AddRec (i.e., it represents + /// an expressions A+B*x where A and B are loop invariant values. + bool isAffine() const { + // We know that the start value is invariant. This expression is thus + // affine iff the step is also invariant. + return getNumOperands() == 2; + } + + /// isQuadratic - Return true if this is an quadratic AddRec (i.e., it + /// represents an expressions A+B*x+C*x^2 where A, B and C are loop + /// invariant values. This corresponds to an addrec of the form {L,+,M,+,N} + bool isQuadratic() const { + return getNumOperands() == 3; + } + + /// evaluateAtIteration - Return the value of this chain of recurrences at + /// the specified iteration number. + SCEVHandle evaluateAtIteration(SCEVHandle It) const; + + /// getNumIterationsInRange - Return the number of iterations of this loop + /// that produce values in the specified constant range. Another way of + /// looking at this is that it returns the first iteration number where the + /// value is not in the condition, thus computing the exit count. If the + /// iteration count can't be computed, an instance of SCEVCouldNotCompute is + /// returned. + SCEVHandle getNumIterationsInRange(ConstantRange Range) const; + + SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym, + const SCEVHandle &Conc) const; + + virtual void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVAddRecExpr *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scAddRecExpr; + } + }; + + //===--------------------------------------------------------------------===// + /// SCEVUnknown - This means that we are dealing with an entirely unknown SCEV + /// value, and only represent it as it's LLVM Value. This is the "bottom" + /// value for the analysis. + /// + class SCEVUnknown : public SCEV { + Value *V; + SCEVUnknown(Value *v) : SCEV(scUnknown), V(v) {} + + protected: + ~SCEVUnknown(); + public: + /// get method - For SCEVUnknown, this just gets and returns a new + /// SCEVUnknown. + static SCEVHandle get(Value *V); + + /// getIntegerSCEV - Given an integer or FP type, create a constant for the + /// specified signed integer value and return a SCEV for the constant. + static SCEVHandle getIntegerSCEV(int Val, const Type *Ty); + + Value *getValue() const { return V; } + + virtual bool isLoopInvariant(const Loop *L) const; + virtual bool hasComputableLoopEvolution(const Loop *QL) const { + return false; // not computable + } + + SCEVHandle replaceSymbolicValuesWithConcrete(const SCEVHandle &Sym, + const SCEVHandle &Conc) const { + if (&*Sym == this) return Conc; + return this; + } + + virtual const Type *getType() const; + + virtual void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SCEVUnknown *S) { return true; } + static inline bool classof(const SCEV *S) { + return S->getSCEVType() == scUnknown; + } + }; + + /// SCEVVisitor - This class defines a simple visitor class that may be used + /// for various SCEV analysis purposes. + template<typename SC, typename RetVal=void> + struct SCEVVisitor { + RetVal visit(SCEV *S) { + switch (S->getSCEVType()) { + case scConstant: + return ((SC*)this)->visitConstant((SCEVConstant*)S); + case scTruncate: + return ((SC*)this)->visitTruncateExpr((SCEVTruncateExpr*)S); + case scZeroExtend: + return ((SC*)this)->visitZeroExtendExpr((SCEVZeroExtendExpr*)S); + case scSignExtend: + return ((SC*)this)->visitSignExtendExpr((SCEVSignExtendExpr*)S); + case scAddExpr: + return ((SC*)this)->visitAddExpr((SCEVAddExpr*)S); + case scMulExpr: + return ((SC*)this)->visitMulExpr((SCEVMulExpr*)S); + case scSDivExpr: + return ((SC*)this)->visitSDivExpr((SCEVSDivExpr*)S); + case scAddRecExpr: + return ((SC*)this)->visitAddRecExpr((SCEVAddRecExpr*)S); + case scUnknown: + return ((SC*)this)->visitUnknown((SCEVUnknown*)S); + case scCouldNotCompute: + return ((SC*)this)->visitCouldNotCompute((SCEVCouldNotCompute*)S); + default: + assert(0 && "Unknown SCEV type!"); + abort(); + } + } + + RetVal visitCouldNotCompute(SCEVCouldNotCompute *S) { + assert(0 && "Invalid use of SCEVCouldNotCompute!"); + abort(); + return RetVal(); + } + }; +} + +#endif + diff --git a/include/llvm/Analysis/Trace.h b/include/llvm/Analysis/Trace.h new file mode 100644 index 0000000..65aa593c8 --- /dev/null +++ b/include/llvm/Analysis/Trace.h @@ -0,0 +1,120 @@ +//===- llvm/Analysis/Trace.h - Represent one trace of LLVM code -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class represents a single trace of LLVM basic blocks. A trace is a +// single entry, multiple exit, region of code that is often hot. Trace-based +// optimizations treat traces almost like they are a large, strange, basic +// block: because the trace path is assumed to be hot, optimizations for the +// fall-through path are made at the expense of the non-fall-through paths. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_TRACE_H +#define LLVM_ANALYSIS_TRACE_H + +#include "llvm/Support/Streams.h" +#include <vector> +#include <cassert> + +namespace llvm { + class BasicBlock; + class Function; + class Module; + +class Trace { + typedef std::vector<BasicBlock *> BasicBlockListType; + BasicBlockListType BasicBlocks; + +public: + /// Trace ctor - Make a new trace from a vector of basic blocks, + /// residing in the function which is the parent of the first + /// basic block in the vector. + /// + Trace(const std::vector<BasicBlock *> &vBB) : BasicBlocks (vBB) {} + + /// getEntryBasicBlock - Return the entry basic block (first block) + /// of the trace. + /// + BasicBlock *getEntryBasicBlock () const { return BasicBlocks[0]; } + + /// operator[]/getBlock - Return basic block N in the trace. + /// + BasicBlock *operator[](unsigned i) const { return BasicBlocks[i]; } + BasicBlock *getBlock(unsigned i) const { return BasicBlocks[i]; } + + /// getFunction - Return this trace's parent function. + /// + Function *getFunction () const; + + /// getModule - Return this Module that contains this trace's parent + /// function. + /// + Module *getModule () const; + + /// getBlockIndex - Return the index of the specified basic block in the + /// trace, or -1 if it is not in the trace. + int getBlockIndex(const BasicBlock *X) const { + for (unsigned i = 0, e = BasicBlocks.size(); i != e; ++i) + if (BasicBlocks[i] == X) + return i; + return -1; + } + + /// contains - Returns true if this trace contains the given basic + /// block. + /// + bool contains(const BasicBlock *X) const { + return getBlockIndex(X) != -1; + } + + /// Returns true if B1 occurs before B2 in the trace, or if it is the same + /// block as B2.. Both blocks must be in the trace. + /// + bool dominates(const BasicBlock *B1, const BasicBlock *B2) const { + int B1Idx = getBlockIndex(B1), B2Idx = getBlockIndex(B2); + assert(B1Idx != -1 && B2Idx != -1 && "Block is not in the trace!"); + return B1Idx <= B2Idx; + } + + // BasicBlock iterators... + typedef BasicBlockListType::iterator iterator; + typedef BasicBlockListType::const_iterator const_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + + iterator begin() { return BasicBlocks.begin(); } + const_iterator begin() const { return BasicBlocks.begin(); } + iterator end () { return BasicBlocks.end(); } + const_iterator end () const { return BasicBlocks.end(); } + + reverse_iterator rbegin() { return BasicBlocks.rbegin(); } + const_reverse_iterator rbegin() const { return BasicBlocks.rbegin(); } + reverse_iterator rend () { return BasicBlocks.rend(); } + const_reverse_iterator rend () const { return BasicBlocks.rend(); } + + unsigned size() const { return BasicBlocks.size(); } + bool empty() const { return BasicBlocks.empty(); } + + iterator erase(iterator q) { return BasicBlocks.erase (q); } + iterator erase(iterator q1, iterator q2) { return BasicBlocks.erase (q1, q2); } + + /// print - Write trace to output stream. + /// + void print (std::ostream &O) const; + void print (std::ostream *O) const { if (O) print(*O); } + + /// dump - Debugger convenience method; writes trace to standard error + /// output stream. + /// + void dump () const; +}; + +} // end namespace llvm + +#endif // TRACE_H diff --git a/include/llvm/Analysis/ValueNumbering.h b/include/llvm/Analysis/ValueNumbering.h new file mode 100644 index 0000000..64d528e --- /dev/null +++ b/include/llvm/Analysis/ValueNumbering.h @@ -0,0 +1,74 @@ +//===- llvm/Analysis/ValueNumbering.h - Value #'ing Interface ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the abstract ValueNumbering interface, which is used as the +// common interface used by all clients of value numbering information, and +// implemented by all value numbering implementations. +// +// Implementations of this interface must implement the various virtual methods, +// which automatically provides functionality for the entire suite of client +// APIs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_VALUE_NUMBERING_H +#define LLVM_ANALYSIS_VALUE_NUMBERING_H + +#include <vector> +#include "llvm/Pass.h" + +namespace llvm { + +class Value; +class Instruction; + +struct ValueNumbering { + static char ID; // Class identification, replacement for typeinfo + virtual ~ValueNumbering(); // We want to be subclassed + + /// getEqualNumberNodes - Return nodes with the same value number as the + /// specified Value. This fills in the argument vector with any equal values. + /// + virtual void getEqualNumberNodes(Value *V1, + std::vector<Value*> &RetVals) const = 0; + + ///===-------------------------------------------------------------------===// + /// Interfaces to update value numbering analysis information as the client + /// changes the program. + /// + + /// deleteValue - This method should be called whenever an LLVM Value is + /// deleted from the program, for example when an instruction is found to be + /// redundant and is eliminated. + /// + virtual void deleteValue(Value *V) {} + + /// copyValue - This method should be used whenever a preexisting value in the + /// program is copied or cloned, introducing a new value. Note that analysis + /// implementations should tolerate clients that use this method to introduce + /// the same value multiple times: if the analysis already knows about a + /// value, it should ignore the request. + /// + virtual void copyValue(Value *From, Value *To) {} + + /// replaceWithNewValue - This method is the obvious combination of the two + /// above, and it provided as a helper to simplify client code. + /// + void replaceWithNewValue(Value *Old, Value *New) { + copyValue(Old, New); + deleteValue(Old); + } +}; + +} // End llvm namespace + +// Force any file including this header to get the implementation as well +FORCE_DEFINING_FILE_TO_BE_LINKED(BasicValueNumbering) + +#endif diff --git a/include/llvm/Analysis/Verifier.h b/include/llvm/Analysis/Verifier.h new file mode 100644 index 0000000..dd914a4 --- /dev/null +++ b/include/llvm/Analysis/Verifier.h @@ -0,0 +1,75 @@ +//===-- llvm/Analysis/Verifier.h - Module Verifier --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the function verifier interface, that can be used for some +// sanity checking of input to the system, and for checking that transformations +// haven't done something bad. +// +// Note that this does not provide full 'java style' security and verifications, +// instead it just tries to ensure that code is well formed. +// +// To see what specifically is checked, look at the top of Verifier.cpp +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ANALYSIS_VERIFIER_H +#define LLVM_ANALYSIS_VERIFIER_H + +#include <string> + +namespace llvm { + +class FunctionPass; +class Module; +class Function; + +/// @brief An enumeration to specify the action to be taken if errors found. +/// +/// This enumeration is used in the functions below to indicate what should +/// happen if the verifier finds errors. Each of the functions that uses +/// this enumeration as an argument provides a default value for it. The +/// actions are listed below. +enum VerifierFailureAction { + AbortProcessAction, ///< verifyModule will print to stderr and abort() + PrintMessageAction, ///< verifyModule will print to stderr and return true + ReturnStatusAction ///< verifyModule will just return true +}; + +/// @brief Create a verifier pass. +/// +/// Check a module or function for validity. When the pass is used, the +/// action indicated by the \p action argument will be used if errors are +/// found. +FunctionPass *createVerifierPass( + VerifierFailureAction action = AbortProcessAction ///< Action to take +); + +/// @brief Check a module for errors. +/// +/// If there are no errors, the function returns false. If an error is found, +/// the action taken depends on the \p action parameter. +/// This should only be used for debugging, because it plays games with +/// PassManagers and stuff. + +bool verifyModule( + const Module &M, ///< The module to be verified + VerifierFailureAction action = AbortProcessAction, ///< Action to take + std::string *ErrorInfo = 0 ///< Information about failures. +); + +// verifyFunction - Check a function for errors, useful for use when debugging a +// pass. +bool verifyFunction( + const Function &F, ///< The function to be verified + VerifierFailureAction action = AbortProcessAction ///< Action to take +); + +} // End llvm namespace + +#endif diff --git a/include/llvm/Argument.h b/include/llvm/Argument.h new file mode 100644 index 0000000..c995043 --- /dev/null +++ b/include/llvm/Argument.h @@ -0,0 +1,72 @@ +//===-- llvm/Argument.h - Definition of the Argument class ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Argument class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ARGUMENT_H +#define LLVM_ARGUMENT_H + +#include "llvm/Value.h" + +namespace llvm { + +template<typename ValueSubClass, typename ItemParentClass> + class SymbolTableListTraits; + +/// A class to represent an incoming formal argument to a Function. An argument +/// is a very simple Value. It is essentially a named (optional) type. When used +/// in the body of a function, it represents the value of the actual argument +/// the function was called with. +/// @brief LLVM Argument representation +class Argument : public Value { // Defined in the Function.cpp file + Function *Parent; + + Argument *Prev, *Next; // Next and Prev links for our intrusive linked list + void setNext(Argument *N) { Next = N; } + void setPrev(Argument *N) { Prev = N; } + friend class SymbolTableListTraits<Argument, Function>; + void setParent(Function *parent); + +public: + /// Argument ctor - If Function argument is specified, this argument is + /// inserted at the end of the argument list for the function. + /// + explicit Argument(const Type *Ty, + const std::string &Name = "", + Function *F = 0); + + inline const Function *getParent() const { return Parent; } + inline Function *getParent() { return Parent; } + + virtual void print(std::ostream &OS) const; + void print(std::ostream *OS) const { + if (OS) print(*OS); + } + + /// classof - Methods for support type inquiry through isa, cast, and + /// dyn_cast: + /// + static inline bool classof(const Argument *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == ArgumentVal; + } + +private: + // getNext/Prev - Return the next or previous argument in the list. + Argument *getNext() { return Next; } + const Argument *getNext() const { return Next; } + Argument *getPrev() { return Prev; } + const Argument *getPrev() const { return Prev; } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Assembly/AsmAnnotationWriter.h b/include/llvm/Assembly/AsmAnnotationWriter.h new file mode 100644 index 0000000..9ed285a --- /dev/null +++ b/include/llvm/Assembly/AsmAnnotationWriter.h @@ -0,0 +1,53 @@ +//===-- AsmAnnotationWriter.h - Itf for annotation .ll files - --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Clients of the assembly writer can use this interface to add their own +// special-purpose annotations to LLVM assembly language printouts. Note that +// the assembly parser won't be able to parse these, in general, so +// implementations are advised to print stuff as LLVM comments. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASSEMBLY_ASMANNOTATIONWRITER_H +#define LLVM_ASSEMBLY_ASMANNOTATIONWRITER_H + +#include <iosfwd> + +namespace llvm { + +class Function; +class BasicBlock; +class Instruction; + +struct AssemblyAnnotationWriter { + + virtual ~AssemblyAnnotationWriter(); + + // emitFunctionAnnot - This may be implemented to emit a string right before + // the start of a function. + virtual void emitFunctionAnnot(const Function *F, std::ostream &OS) {} + + // emitBasicBlockStartAnnot - This may be implemented to emit a string right + // after the basic block label, but before the first instruction in the block. + virtual void emitBasicBlockStartAnnot(const BasicBlock *BB, std::ostream &OS){ + } + + // emitBasicBlockEndAnnot - This may be implemented to emit a string right + // after the basic block. + virtual void emitBasicBlockEndAnnot(const BasicBlock *BB, std::ostream &OS){ + } + + // emitInstructionAnnot - This may be implemented to emit a string right + // before an instruction is emitted. + virtual void emitInstructionAnnot(const Instruction *I, std::ostream &OS) {} +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Assembly/Parser.h b/include/llvm/Assembly/Parser.h new file mode 100644 index 0000000..bc7995e --- /dev/null +++ b/include/llvm/Assembly/Parser.h @@ -0,0 +1,97 @@ +//===-- llvm/Assembly/Parser.h - Parser for VM assembly files ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// These classes are implemented by the lib/AsmParser library. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASSEMBLY_PARSER_H +#define LLVM_ASSEMBLY_PARSER_H + +#include <string> + +namespace llvm { + +class Module; +class ParseError; + + +/// This function is the main interface to the LLVM Assembly Parse. It parses +/// an ascii file that (presumably) contains LLVM Assembly code. It returns a +/// Module (intermediate representation) with the corresponding features. Note +/// that this does not verify that the generated Module is valid, so you should +/// run the verifier after parsing the file to check that it is okay. +/// @brief Parse LLVM Assembly from a file +Module *ParseAssemblyFile( + const std::string &Filename, ///< The name of the file to parse + ParseError* Error = 0 ///< If not null, an object to return errors in. +); + +/// The function is a secondary interface to the LLVM Assembly Parse. It parses +/// an ascii string that (presumably) contains LLVM Assembly code. It returns a +/// Module (intermediate representation) with the corresponding features. Note +/// that this does not verify that the generated Module is valid, so you should +/// run the verifier after parsing the file to check that it is okay. +/// @brief Parse LLVM Assembly from a string +Module *ParseAssemblyString( + const char * AsmString, ///< The string containing assembly + Module * M, ///< A module to add the assembly too. + ParseError* Error = 0 ///< If not null, an object to return errors in. +); + +//===------------------------------------------------------------------------=== +// Helper Classes +//===------------------------------------------------------------------------=== + +/// An instance of this class can be passed to ParseAssemblyFile or +/// ParseAssemblyString functions in order to capture error information from +/// the parser. It provides a standard way to print out the error message +/// including the file name and line number where the error occurred. +/// @brief An LLVM Assembly Parsing Error Object +class ParseError { +public: + ParseError() : Filename("unknown"), Message("none"), LineNo(0), ColumnNo(0) {} + ParseError(const ParseError &E); + + // getMessage - Return the message passed in at construction time plus extra + // information extracted from the options used to parse with... + // + const std::string getMessage() const; + + inline const std::string &getRawMessage() const { // Just the raw message... + return Message; + } + + inline const std::string &getFilename() const { + return Filename; + } + + void setError(const std::string &filename, const std::string &message, + int LineNo = -1, int ColNo = -1); + + // getErrorLocation - Return the line and column number of the error in the + // input source file. The source filename can be derived from the + // ParserOptions in effect. If positional information is not applicable, + // these will return a value of -1. + // + inline const void getErrorLocation(int &Line, int &Column) const { + Line = LineNo; Column = ColumnNo; + } + +private : + std::string Filename; + std::string Message; + int LineNo, ColumnNo; // -1 if not relevant + + ParseError &operator=(const ParseError &E); // objects by reference +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Assembly/PrintModulePass.h b/include/llvm/Assembly/PrintModulePass.h new file mode 100644 index 0000000..0f65235 --- /dev/null +++ b/include/llvm/Assembly/PrintModulePass.h @@ -0,0 +1,81 @@ +//===- llvm/Assembly/PrintModulePass.h - Printing Pass ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines two passes to print out a module. The PrintModulePass pass +// simply prints out the entire module when it is executed. The +// PrintFunctionPass class is designed to be pipelined with other +// FunctionPass's, and prints out the functions of the class as they are +// processed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASSEMBLY_PRINTMODULEPASS_H +#define LLVM_ASSEMBLY_PRINTMODULEPASS_H + +#include "llvm/Pass.h" +#include "llvm/Module.h" +#include "llvm/Support/Streams.h" + +namespace llvm { + +class PrintModulePass : public ModulePass { + OStream *Out; // ostream to print on + bool DeleteStream; // Delete the ostream in our dtor? +public: + static char ID; + PrintModulePass() : ModulePass((intptr_t)&ID), Out(&cerr), DeleteStream(false) {} + PrintModulePass(OStream *o, bool DS = false) + : ModulePass((intptr_t)&ID), Out(o), DeleteStream(DS) {} + + ~PrintModulePass() { + if (DeleteStream) delete Out; + } + + bool runOnModule(Module &M) { + (*Out) << M << std::flush; + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } +}; + +class PrintFunctionPass : public FunctionPass { + std::string Banner; // String to print before each function + OStream *Out; // ostream to print on + bool DeleteStream; // Delete the ostream in our dtor? +public: + static char ID; + PrintFunctionPass() : FunctionPass((intptr_t)&ID), Banner(""), Out(&cerr), + DeleteStream(false) {} + PrintFunctionPass(const std::string &B, OStream *o = &cout, + bool DS = false) + : FunctionPass((intptr_t)&ID), Banner(B), Out(o), DeleteStream(DS) {} + + inline ~PrintFunctionPass() { + if (DeleteStream) delete Out; + } + + // runOnFunction - This pass just prints a banner followed by the function as + // it's processed. + // + bool runOnFunction(Function &F) { + (*Out) << Banner << static_cast<Value&>(F); + return false; + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Assembly/Writer.h b/include/llvm/Assembly/Writer.h new file mode 100644 index 0000000..45c9513 --- /dev/null +++ b/include/llvm/Assembly/Writer.h @@ -0,0 +1,45 @@ +//===-- llvm/Assembly/Writer.h - Printer for LLVM assembly files --*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This functionality is implemented by lib/VMCore/AsmWriter.cpp. +// This library is used to print LLVM assembly language files to an iostream. It +// can print LLVM code at a variety of granularities, including Modules, +// BasicBlocks, and Instructions. This makes it useful for debugging. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_ASSEMBLY_WRITER_H +#define LLVM_ASSEMBLY_WRITER_H + +#include <iosfwd> + +namespace llvm { + +class Type; +class Module; +class Value; + +// WriteTypeSymbolic - This attempts to write the specified type as a symbolic +// type, iff there is an entry in the Module's symbol table for the specified +// type or one of its component types. This is slower than a simple x << Type; +// +std::ostream &WriteTypeSymbolic(std::ostream &, const Type *, const Module *M); + +// WriteAsOperand - Write the name of the specified value out to the specified +// ostream. This can be useful when you just want to print int %reg126, not the +// whole instruction that generated it. If you specify a Module for context, +// then even constants get pretty-printed; for example, the type of a null +// pointer is printed symbolically. +// +std::ostream &WriteAsOperand(std::ostream &, const Value *, bool PrintTy = true, + const Module *Context = 0); + +} // End llvm namespace + +#endif diff --git a/include/llvm/BasicBlock.h b/include/llvm/BasicBlock.h new file mode 100644 index 0000000..f2722b0 --- /dev/null +++ b/include/llvm/BasicBlock.h @@ -0,0 +1,216 @@ +//===-- llvm/BasicBlock.h - Represent a basic block in the VM ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// +// This file contains the declaration of the BasicBlock class. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BASICBLOCK_H +#define LLVM_BASICBLOCK_H + +#include "llvm/Instruction.h" +#include "llvm/SymbolTableListTraits.h" +#include "llvm/ADT/ilist" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class TerminatorInst; +template <class Term, class BB> class SuccIterator; // Successor Iterator +template <class Ptr, class USE_iterator> class PredIterator; + +template<> struct ilist_traits<Instruction> + : public SymbolTableListTraits<Instruction, BasicBlock> { + // createSentinel is used to create a node that marks the end of the list... + static Instruction *createSentinel(); + static void destroySentinel(Instruction *I) { delete I; } + static iplist<Instruction> &getList(BasicBlock *BB); + static ValueSymbolTable *getSymTab(BasicBlock *ItemParent); + static int getListOffset(); +}; + +/// This represents a single basic block in LLVM. A basic block is simply a +/// container of instructions that execute sequentially. Basic blocks are Values +/// because they are referenced by instructions such as branches and switch +/// tables. The type of a BasicBlock is "Type::LabelTy" because the basic block +/// represents a label to which a branch can jump. +/// +/// A well formed basic block is formed of a list of non-terminating +/// instructions followed by a single TerminatorInst instruction. +/// TerminatorInst's may not occur in the middle of basic blocks, and must +/// terminate the blocks. The BasicBlock class allows malformed basic blocks to +/// occur because it may be useful in the intermediate stage of constructing or +/// modifying a program. However, the verifier will ensure that basic blocks +/// are "well formed". +/// @brief LLVM Basic Block Representation +class BasicBlock : public Value { // Basic blocks are data objects also +public: + typedef iplist<Instruction> InstListType; +private : + InstListType InstList; + BasicBlock *Prev, *Next; // Next and Prev links for our intrusive linked list + Function *Parent; + + void setParent(Function *parent); + void setNext(BasicBlock *N) { Next = N; } + void setPrev(BasicBlock *N) { Prev = N; } + friend class SymbolTableListTraits<BasicBlock, Function>; + + BasicBlock(const BasicBlock &); // Do not implement + void operator=(const BasicBlock &); // Do not implement + +public: + /// Instruction iterators... + typedef InstListType::iterator iterator; + typedef InstListType::const_iterator const_iterator; + + /// BasicBlock ctor - If the function parameter is specified, the basic block + /// is automatically inserted at either the end of the function (if + /// InsertBefore is null), or before the specified basic block. + /// + explicit BasicBlock(const std::string &Name = "", Function *Parent = 0, + BasicBlock *InsertBefore = 0); + ~BasicBlock(); + + /// getParent - Return the enclosing method, or null if none + /// + const Function *getParent() const { return Parent; } + Function *getParent() { return Parent; } + + /// use_back - Specialize the methods defined in Value, as we know that an + /// BasicBlock can only be used by Instructions (specifically PHI and terms). + Instruction *use_back() { return cast<Instruction>(*use_begin());} + const Instruction *use_back() const { return cast<Instruction>(*use_begin());} + + /// getTerminator() - If this is a well formed basic block, then this returns + /// a pointer to the terminator instruction. If it is not, then you get a + /// null pointer back. + /// + TerminatorInst *getTerminator(); + const TerminatorInst *const getTerminator() const; + + /// Returns a pointer to the first instructon in this block that is not a + /// PHINode instruction. When adding instruction to the beginning of the + /// basic block, they should be added before the returned value, not before + /// the first instruction, which might be PHI. + /// Returns 0 is there's no non-PHI instruction. + Instruction* getFirstNonPHI(); + + /// removeFromParent - This method unlinks 'this' from the containing + /// function, but does not delete it. + /// + void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing function + /// and deletes it. + /// + void eraseFromParent(); + + /// moveBefore - Unlink this basic block from its current function and + /// insert it into the function that MovePos lives in, right before MovePos. + void moveBefore(BasicBlock *MovePos); + + /// moveAfter - Unlink this basic block from its current function and + /// insert it into the function that MovePos lives in, right after MovePos. + void moveAfter(BasicBlock *MovePos); + + + /// getSinglePredecessor - If this basic block has a single predecessor block, + /// return the block, otherwise return a null pointer. + BasicBlock *getSinglePredecessor(); + const BasicBlock *getSinglePredecessor() const { + return const_cast<BasicBlock*>(this)->getSinglePredecessor(); + } + + //===--------------------------------------------------------------------===// + /// Instruction iterator methods + /// + inline iterator begin() { return InstList.begin(); } + inline const_iterator begin() const { return InstList.begin(); } + inline iterator end () { return InstList.end(); } + inline const_iterator end () const { return InstList.end(); } + + inline size_t size() const { return InstList.size(); } + inline bool empty() const { return InstList.empty(); } + inline const Instruction &front() const { return InstList.front(); } + inline Instruction &front() { return InstList.front(); } + inline const Instruction &back() const { return InstList.back(); } + inline Instruction &back() { return InstList.back(); } + + /// getInstList() - Return the underlying instruction list container. You + /// need to access it directly if you want to modify it currently. + /// + const InstListType &getInstList() const { return InstList; } + InstListType &getInstList() { return InstList; } + + virtual void print(std::ostream &OS) const { print(OS, 0); } + void print(std::ostream *OS) const { if (OS) print(*OS); } + void print(std::ostream &OS, AssemblyAnnotationWriter *AAW) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BasicBlock *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::BasicBlockVal; + } + + /// dropAllReferences() - This function causes all the subinstructions to "let + /// go" of all references that they are maintaining. This allows one to + /// 'delete' a whole class at a time, even though there may be circular + /// references... first all references are dropped, and all use counts go to + /// zero. Then everything is delete'd for real. Note that no operations are + /// valid on an object that has "dropped all references", except operator + /// delete. + /// + void dropAllReferences(); + + /// removePredecessor - This method is used to notify a BasicBlock that the + /// specified Predecessor of the block is no longer able to reach it. This is + /// actually not used to update the Predecessor list, but is actually used to + /// update the PHI nodes that reside in the block. Note that this should be + /// called while the predecessor still refers to this block. + /// + void removePredecessor(BasicBlock *Pred, bool DontDeleteUselessPHIs = false); + + /// splitBasicBlock - This splits a basic block into two at the specified + /// instruction. Note that all instructions BEFORE the specified iterator + /// stay as part of the original basic block, an unconditional branch is added + /// to the original BB, and the rest of the instructions in the BB are moved + /// to the new BB, including the old terminator. The newly formed BasicBlock + /// is returned. This function invalidates the specified iterator. + /// + /// Note that this only works on well formed basic blocks (must have a + /// terminator), and 'I' must not be the end of instruction list (which would + /// cause a degenerate basic block to be formed, having a terminator inside of + /// the basic block). + /// + BasicBlock *splitBasicBlock(iterator I, const std::string &BBName = ""); + + + static unsigned getInstListOffset() { + BasicBlock *Obj = 0; + return unsigned(reinterpret_cast<uintptr_t>(&Obj->InstList)); + } + +private: + // getNext/Prev - Return the next or previous basic block in the list. Access + // these with Function::iterator. + BasicBlock *getNext() { return Next; } + const BasicBlock *getNext() const { return Next; } + BasicBlock *getPrev() { return Prev; } + const BasicBlock *getPrev() const { return Prev; } +}; + +inline int +ilist_traits<Instruction>::getListOffset() { + return BasicBlock::getInstListOffset(); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/Bitcode/Archive.h b/include/llvm/Bitcode/Archive.h new file mode 100644 index 0000000..980bd07 --- /dev/null +++ b/include/llvm/Bitcode/Archive.h @@ -0,0 +1,555 @@ +//===-- llvm/Bitcode/Archive.h - LLVM Bitcode Archive -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and 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" +#include "llvm/System/Path.h" +#include "llvm/System/MappedFile.h" +#include <map> +#include <set> +#include <fstream> + +namespace llvm { + +// Forward declare classes +class ModuleProvider; // From VMCore +class Module; // From VMCore +class Archive; // Declared below +class ArchiveMemberHeader; // Internal implementation class + +/// 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 { + /// @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 { + CompressedFlag = 1, ///< Member is a normal compressed file + SVR4SymbolTableFlag = 2, ///< Member is a SVR4 symbol table + BSD4SymbolTableFlag = 4, ///< Member is a BSD4 symbol table + LLVMSymbolTableFlag = 8, ///< Member is an LLVM symbol table + BitcodeFlag = 16, ///< Member is bitcode + HasPathFlag = 64, ///< Member has a full or partial path + HasLongFilenameFlag = 128, ///< Member uses the long filename syntax + StringTableFlag = 256 ///< 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 applicabiity 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 void* getData() const { return data; } + + /// This method determines if the member is a regular compressed file. + /// @returns true iff the archive member is a compressed regular file. + /// @brief Determine if the member is a compressed regular file. + bool isCompressed() const { return flags&CompressedFlag; } + + /// @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 Determin 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 ilist methods - do not use + /// @{ + public: + const ArchiveMember *getNext() const { return next; } + const ArchiveMember *getPrev() const { return prev; } + ArchiveMember *getNext() { return next; } + ArchiveMember *getPrev() { return prev; } + void setPrev(ArchiveMember* p) { prev = p; } + void setNext(ArchiveMember* n) { next = n; } + + /// @} + /// @name Data + /// @{ + private: + ArchiveMember* next; ///< Pointer to next archive member + ArchiveMember* prev; ///< Pointer to previous archive member + 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 void* 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. + 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 unsigned 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. + ); + + /// 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 + 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 exception will be thrown. 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. + /// @throws std::string if an error occurs opening the file + /// @returns an Archive* that represents the archive file. + /// @brief Open an existing archive and load its symbols. + static Archive* OpenAndLoadSymbols( + const sys::Path& Filename, ///< Name of the archive file to open + 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. + /// @throws std::string if an error occurs + /// @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 + /// ModuleProvider 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 ModuleProvider + /// instance because the associated module defines multiple symbols. + /// @returns The ModuleProvider* found or null if the archive does not + /// contain a module that defines the \p symbol. + /// @brief Look up a module by symbol name. + ModuleProvider* 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 + std::set<ModuleProvider*>& 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 successfull. + /// @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 + bool Compress=false, ///< Compress files + 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 occured, 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. + Archive(const sys::Path& filename); + + /// @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 error 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 error 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 error 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 Writing member succeeded + /// @returns true 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? + bool ShouldCompress, ///< Should the member be compressed? + 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 ModuleProvider. + /// @brief Module mapping type + typedef std::map<unsigned,std::pair<ModuleProvider*,ArchiveMember*> > + ModuleMap; + + + /// @} + /// @name Data + /// @{ + protected: + sys::Path archPath; ///< Path to the archive file we read/write + MembersList members; ///< The ilist of ArchiveMember + sys::MappedFile* 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. + /// @} + /// @name Hidden + /// @{ + private: + Archive(); ///< Do not implement + Archive(const Archive&); ///< Do not implement + Archive& operator=(const Archive&); ///< Do not implement + /// @} +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Bitcode/BitCodes.h b/include/llvm/Bitcode/BitCodes.h new file mode 100644 index 0000000..59d57e7 --- /dev/null +++ b/include/llvm/Bitcode/BitCodes.h @@ -0,0 +1,179 @@ +//===- BitCodes.h - Enum values for the bitcode format ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header Bitcode enum values. +// +// The enum values defined in this file should be considered permanent. If +// new features are added, they should have values added at the end of the +// respective lists. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_BITCODES_H +#define LLVM_BITCODE_BITCODES_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/DataTypes.h" +#include <cassert> + +namespace llvm { +namespace bitc { + enum StandardWidths { + BlockIDWidth = 8, // We use VBR-8 for block IDs. + CodeLenWidth = 4, // Codelen are VBR-4. + BlockSizeWidth = 32 // BlockSize up to 2^32 32-bit words = 32GB per block. + }; + + // The standard abbrev namespace always has a way to exit a block, enter a + // nested block, define abbrevs, and define an unabbreviated record. + enum FixedAbbrevIDs { + END_BLOCK = 0, // Must be zero to guarantee termination for broken bitcode. + ENTER_SUBBLOCK = 1, + + /// DEFINE_ABBREV - Defines an abbrev for the current block. It consists + /// of a vbr5 for # operand infos. Each operand info is emitted with a + /// single bit to indicate if it is a literal encoding. If so, the value is + /// emitted with a vbr8. If not, the encoding is emitted as 3 bits followed + /// by the info value as a vbr5 if needed. + DEFINE_ABBREV = 2, + + // UNABBREV_RECORDs are emitted with a vbr6 for the record code, followed by + // a vbr6 for the # operands, followed by vbr6's for each operand. + UNABBREV_RECORD = 3, + + // This is not a code, this is a marker for the first abbrev assignment. + FIRST_APPLICATION_ABBREV = 4 + }; + + /// StandardBlockIDs - All bitcode files can optionally include a BLOCKINFO + /// block, which contains metadata about other blocks in the file. + enum StandardBlockIDs { + /// BLOCKINFO_BLOCK is used to define metadata about blocks, for example, + /// standard abbrevs that should be available to all blocks of a specified + /// ID. + BLOCKINFO_BLOCK_ID = 0, + + // Block IDs 1-7 are reserved for future expansion. + FIRST_APPLICATION_BLOCKID = 8 + }; + + /// BlockInfoCodes - The blockinfo block contains metadata about user-defined + /// blocks. + enum BlockInfoCodes { + BLOCKINFO_CODE_SETBID = 1 // SETBID: [blockid#] + // DEFINE_ABBREV has magic semantics here, applying to the current SETBID'd + // block, instead of the BlockInfo block. + // BLOCKNAME: give string name to block, if desired. + }; + +} // End bitc namespace + +/// BitCodeAbbrevOp - This describes one or more operands in an abbreviation. +/// This is actually a union of two different things: +/// 1. It could be a literal integer value ("the operand is always 17"). +/// 2. It could be an encoding specification ("this operand encoded like so"). +/// +class BitCodeAbbrevOp { + uint64_t Val; // A literal value or data for an encoding. + bool IsLiteral : 1; // Indicate whether this is a literal value or not. + unsigned Enc : 3; // The encoding to use. +public: + enum Encoding { + Fixed = 1, // A fixed width field, Val specifies number of bits. + VBR = 2, // A VBR field where Val specifies the width of each chunk. + Array = 3, // A sequence of fields, next field species elt encoding. + Char6 = 4 // A 6-bit fixed field which maps to [a-zA-Z0-9._]. + }; + + BitCodeAbbrevOp(uint64_t V) : Val(V), IsLiteral(true) {} + BitCodeAbbrevOp(Encoding E, uint64_t Data = 0) + : Val(Data), IsLiteral(false), Enc(E) {} + + bool isLiteral() const { return IsLiteral; } + bool isEncoding() const { return !IsLiteral; } + + // Accessors for literals. + uint64_t getLiteralValue() const { assert(isLiteral()); return Val; } + + // Accessors for encoding info. + Encoding getEncoding() const { assert(isEncoding()); return (Encoding)Enc; } + uint64_t getEncodingData() const { + assert(isEncoding() && hasEncodingData()); + return Val; + } + + bool hasEncodingData() const { return hasEncodingData(getEncoding()); } + static bool hasEncodingData(Encoding E) { + switch (E) { + default: assert(0 && "Unknown encoding"); + case Fixed: + case VBR: + return true; + case Array: + case Char6: + return false; + } + } + + /// isChar6 - Return true if this character is legal in the Char6 encoding. + static bool isChar6(char C) { + if (C >= 'a' && C <= 'z') return true; + if (C >= 'A' && C <= 'Z') return true; + if (C >= '0' && C <= '9') return true; + if (C == '.' || C == '_') return true; + return false; + } + static unsigned EncodeChar6(char C) { + if (C >= 'a' && C <= 'z') return C-'a'; + if (C >= 'A' && C <= 'Z') return C-'A'+26; + if (C >= '0' && C <= '9') return C-'0'+26+26; + if (C == '.') return 62; + if (C == '_') return 63; + assert(0 && "Not a value Char6 character!"); + return 0; + } + + static char DecodeChar6(unsigned V) { + assert((V & ~63) == 0 && "Not a Char6 encoded character!"); + if (V < 26) return V+'a'; + if (V < 26+26) return V-26+'A'; + if (V < 26+26+10) return V-26-26+'0'; + if (V == 62) return '.'; + if (V == 63) return '_'; + assert(0 && "Not a value Char6 character!"); + return ' '; + } + +}; + +/// BitCodeAbbrev - This class represents an abbreviation record. An +/// abbreviation allows a complex record that has redundancy to be stored in a +/// specialized format instead of the fully-general, fully-vbr, format. +class BitCodeAbbrev { + SmallVector<BitCodeAbbrevOp, 8> OperandList; + unsigned char RefCount; // Number of things using this. + ~BitCodeAbbrev() {} +public: + BitCodeAbbrev() : RefCount(1) {} + + void addRef() { ++RefCount; } + void dropRef() { if (--RefCount == 0) delete this; } + + unsigned getNumOperandInfos() const { return OperandList.size(); } + const BitCodeAbbrevOp &getOperandInfo(unsigned N) const { + return OperandList[N]; + } + + void Add(const BitCodeAbbrevOp &OpInfo) { + OperandList.push_back(OpInfo); + } +}; +} // End llvm namespace + +#endif diff --git a/include/llvm/Bitcode/BitstreamReader.h b/include/llvm/Bitcode/BitstreamReader.h new file mode 100644 index 0000000..86a26c2 --- /dev/null +++ b/include/llvm/Bitcode/BitstreamReader.h @@ -0,0 +1,465 @@ +//===- BitstreamReader.h - Low-level bitstream reader interface -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the BitstreamReader class. This class can be used to +// read an arbitrary bitstream, regardless of its contents. +// +//===----------------------------------------------------------------------===// + +#ifndef BITSTREAM_READER_H +#define BITSTREAM_READER_H + +#include "llvm/Bitcode/BitCodes.h" +#include <vector> + +namespace llvm { + +class BitstreamReader { + const unsigned char *NextChar; + const unsigned char *LastChar; + + /// CurWord - This is the current data we have pulled from the stream but have + /// not returned to the client. + uint32_t CurWord; + + /// BitsInCurWord - This is the number of bits in CurWord that are valid. This + /// is always from [0...31] inclusive. + unsigned BitsInCurWord; + + // CurCodeSize - This is the declared size of code values used for the current + // block, in bits. + unsigned CurCodeSize; + + /// CurAbbrevs - Abbrevs installed at in this block. + std::vector<BitCodeAbbrev*> CurAbbrevs; + + struct Block { + unsigned PrevCodeSize; + std::vector<BitCodeAbbrev*> PrevAbbrevs; + explicit Block(unsigned PCS) : PrevCodeSize(PCS) {} + }; + + /// BlockScope - This tracks the codesize of parent blocks. + SmallVector<Block, 8> BlockScope; + + /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. + /// These describe abbreviations that all blocks of the specified ID inherit. + struct BlockInfo { + unsigned BlockID; + std::vector<BitCodeAbbrev*> Abbrevs; + }; + std::vector<BlockInfo> BlockInfoRecords; + + /// FirstChar - This remembers the first byte of the stream. + const unsigned char *FirstChar; +public: + BitstreamReader() { + NextChar = FirstChar = LastChar = 0; + CurWord = 0; + BitsInCurWord = 0; + CurCodeSize = 0; + } + + BitstreamReader(const unsigned char *Start, const unsigned char *End) { + init(Start, End); + } + + void init(const unsigned char *Start, const unsigned char *End) { + NextChar = FirstChar = Start; + LastChar = End; + assert(((End-Start) & 3) == 0 &&"Bitcode stream not a multiple of 4 bytes"); + CurWord = 0; + BitsInCurWord = 0; + CurCodeSize = 2; + } + + ~BitstreamReader() { + // Abbrevs could still exist if the stream was broken. If so, don't leak + // them. + for (unsigned i = 0, e = CurAbbrevs.size(); i != e; ++i) + CurAbbrevs[i]->dropRef(); + + for (unsigned S = 0, e = BlockScope.size(); S != e; ++S) { + std::vector<BitCodeAbbrev*> &Abbrevs = BlockScope[S].PrevAbbrevs; + for (unsigned i = 0, e = Abbrevs.size(); i != e; ++i) + Abbrevs[i]->dropRef(); + } + + // Free the BlockInfoRecords. + while (!BlockInfoRecords.empty()) { + BlockInfo &Info = BlockInfoRecords.back(); + // Free blockinfo abbrev info. + for (unsigned i = 0, e = Info.Abbrevs.size(); i != e; ++i) + Info.Abbrevs[i]->dropRef(); + BlockInfoRecords.pop_back(); + } + } + + bool AtEndOfStream() const { + return NextChar == LastChar && BitsInCurWord == 0; + } + + /// GetCurrentBitNo - Return the bit # of the bit we are reading. + uint64_t GetCurrentBitNo() const { + return (NextChar-FirstChar)*8 + ((32-BitsInCurWord) & 31); + } + + /// JumpToBit - Reset the stream to the specified bit number. + void JumpToBit(uint64_t BitNo) { + uintptr_t ByteNo = uintptr_t(BitNo/8) & ~3; + uintptr_t WordBitNo = uintptr_t(BitNo) & 31; + assert(ByteNo < (uintptr_t)(LastChar-FirstChar) && "Invalid location"); + + // Move the cursor to the right word. + NextChar = FirstChar+ByteNo; + BitsInCurWord = 0; + + // Skip over any bits that are already consumed. + if (WordBitNo) { + NextChar -= 4; + Read(WordBitNo); + } + } + + /// GetAbbrevIDWidth - Return the number of bits used to encode an abbrev #. + unsigned GetAbbrevIDWidth() const { return CurCodeSize; } + + uint32_t Read(unsigned NumBits) { + // If the field is fully contained by CurWord, return it quickly. + if (BitsInCurWord >= NumBits) { + uint32_t R = CurWord & ((1U << NumBits)-1); + CurWord >>= NumBits; + BitsInCurWord -= NumBits; + return R; + } + + // If we run out of data, stop at the end of the stream. + if (LastChar == NextChar) { + CurWord = 0; + BitsInCurWord = 0; + return 0; + } + + unsigned R = CurWord; + + // Read the next word from the stream. + CurWord = (NextChar[0] << 0) | (NextChar[1] << 8) | + (NextChar[2] << 16) | (NextChar[3] << 24); + NextChar += 4; + + // Extract NumBits-BitsInCurWord from what we just read. + unsigned BitsLeft = NumBits-BitsInCurWord; + + // Be careful here, BitsLeft is in the range [1..32] inclusive. + R |= (CurWord & (~0U >> (32-BitsLeft))) << BitsInCurWord; + + // BitsLeft bits have just been used up from CurWord. + if (BitsLeft != 32) + CurWord >>= BitsLeft; + else + CurWord = 0; + BitsInCurWord = 32-BitsLeft; + return R; + } + + uint64_t Read64(unsigned NumBits) { + if (NumBits <= 32) return Read(NumBits); + + uint64_t V = Read(32); + return V | (uint64_t)Read(NumBits-32) << 32; + } + + uint32_t ReadVBR(unsigned NumBits) { + uint32_t Piece = Read(NumBits); + if ((Piece & (1U << (NumBits-1))) == 0) + return Piece; + + uint32_t Result = 0; + unsigned NextBit = 0; + while (1) { + Result |= (Piece & ((1U << (NumBits-1))-1)) << NextBit; + + if ((Piece & (1U << (NumBits-1))) == 0) + return Result; + + NextBit += NumBits-1; + Piece = Read(NumBits); + } + } + + uint64_t ReadVBR64(unsigned NumBits) { + uint64_t Piece = Read(NumBits); + if ((Piece & (1U << (NumBits-1))) == 0) + return Piece; + + uint64_t Result = 0; + unsigned NextBit = 0; + while (1) { + Result |= (Piece & ((1U << (NumBits-1))-1)) << NextBit; + + if ((Piece & (1U << (NumBits-1))) == 0) + return Result; + + NextBit += NumBits-1; + Piece = Read(NumBits); + } + } + + void SkipToWord() { + BitsInCurWord = 0; + CurWord = 0; + } + + + unsigned ReadCode() { + return Read(CurCodeSize); + } + + //===--------------------------------------------------------------------===// + // Block Manipulation + //===--------------------------------------------------------------------===// + +private: + /// getBlockInfo - If there is block info for the specified ID, return it, + /// otherwise return null. + BlockInfo *getBlockInfo(unsigned BlockID) { + // Common case, the most recent entry matches BlockID. + if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) + return &BlockInfoRecords.back(); + + for (unsigned i = 0, e = BlockInfoRecords.size(); i != e; ++i) + if (BlockInfoRecords[i].BlockID == BlockID) + return &BlockInfoRecords[i]; + return 0; + } +public: + + + // Block header: + // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen] + + /// ReadSubBlockID - Having read the ENTER_SUBBLOCK code, read the BlockID for + /// the block. + unsigned ReadSubBlockID() { + return ReadVBR(bitc::BlockIDWidth); + } + + /// SkipBlock - Having read the ENTER_SUBBLOCK abbrevid and a BlockID, skip + /// over the body of this block. If the block record is malformed, return + /// true. + bool SkipBlock() { + // Read and ignore the codelen value. Since we are skipping this block, we + // don't care what code widths are used inside of it. + ReadVBR(bitc::CodeLenWidth); + SkipToWord(); + unsigned NumWords = Read(bitc::BlockSizeWidth); + + // Check that the block wasn't partially defined, and that the offset isn't + // bogus. + if (AtEndOfStream() || NextChar+NumWords*4 > LastChar) + return true; + + NextChar += NumWords*4; + return false; + } + + /// EnterSubBlock - Having read the ENTER_SUBBLOCK abbrevid, read and enter + /// the block, returning the BlockID of the block we just entered. + bool EnterSubBlock(unsigned BlockID, unsigned *NumWordsP = 0) { + // Save the current block's state on BlockScope. + BlockScope.push_back(Block(CurCodeSize)); + BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + + // Add the abbrevs specific to this block to the CurAbbrevs list. + if (BlockInfo *Info = getBlockInfo(BlockID)) { + for (unsigned i = 0, e = Info->Abbrevs.size(); i != e; ++i) { + CurAbbrevs.push_back(Info->Abbrevs[i]); + CurAbbrevs.back()->addRef(); + } + } + + // Get the codesize of this block. + CurCodeSize = ReadVBR(bitc::CodeLenWidth); + SkipToWord(); + unsigned NumWords = Read(bitc::BlockSizeWidth); + if (NumWordsP) *NumWordsP = NumWords; + + // Validate that this block is sane. + if (CurCodeSize == 0 || AtEndOfStream() || NextChar+NumWords*4 > LastChar) + return true; + + return false; + } + + bool ReadBlockEnd() { + if (BlockScope.empty()) return true; + + // Block tail: + // [END_BLOCK, <align4bytes>] + SkipToWord(); + CurCodeSize = BlockScope.back().PrevCodeSize; + + // Delete abbrevs from popped scope. + for (unsigned i = 0, e = CurAbbrevs.size(); i != e; ++i) + CurAbbrevs[i]->dropRef(); + + BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + BlockScope.pop_back(); + return false; + } + + //===--------------------------------------------------------------------===// + // Record Processing + //===--------------------------------------------------------------------===// + +private: + void ReadAbbreviatedField(const BitCodeAbbrevOp &Op, + SmallVectorImpl<uint64_t> &Vals) { + if (Op.isLiteral()) { + // If the abbrev specifies the literal value to use, use it. + Vals.push_back(Op.getLiteralValue()); + } else { + // Decode the value as we are commanded. + switch (Op.getEncoding()) { + default: assert(0 && "Unknown encoding!"); + case BitCodeAbbrevOp::Fixed: + Vals.push_back(Read((unsigned)Op.getEncodingData())); + break; + case BitCodeAbbrevOp::VBR: + Vals.push_back(ReadVBR64((unsigned)Op.getEncodingData())); + break; + case BitCodeAbbrevOp::Char6: + Vals.push_back(BitCodeAbbrevOp::DecodeChar6(Read(6))); + break; + } + } + } +public: + unsigned ReadRecord(unsigned AbbrevID, SmallVectorImpl<uint64_t> &Vals) { + if (AbbrevID == bitc::UNABBREV_RECORD) { + unsigned Code = ReadVBR(6); + unsigned NumElts = ReadVBR(6); + for (unsigned i = 0; i != NumElts; ++i) + Vals.push_back(ReadVBR64(6)); + return Code; + } + + unsigned AbbrevNo = AbbrevID-bitc::FIRST_APPLICATION_ABBREV; + assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); + BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo]; + + for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) { + const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); + if (Op.isLiteral() || Op.getEncoding() != BitCodeAbbrevOp::Array) { + ReadAbbreviatedField(Op, Vals); + } else { + // Array case. Read the number of elements as a vbr6. + unsigned NumElts = ReadVBR(6); + + // Get the element encoding. + assert(i+2 == e && "array op not second to last?"); + const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i); + + // Read all the elements. + for (; NumElts; --NumElts) + ReadAbbreviatedField(EltEnc, Vals); + } + } + + unsigned Code = (unsigned)Vals[0]; + Vals.erase(Vals.begin()); + return Code; + } + + //===--------------------------------------------------------------------===// + // Abbrev Processing + //===--------------------------------------------------------------------===// + + void ReadAbbrevRecord() { + BitCodeAbbrev *Abbv = new BitCodeAbbrev(); + unsigned NumOpInfo = ReadVBR(5); + for (unsigned i = 0; i != NumOpInfo; ++i) { + bool IsLiteral = Read(1); + if (IsLiteral) { + Abbv->Add(BitCodeAbbrevOp(ReadVBR64(8))); + continue; + } + + BitCodeAbbrevOp::Encoding E = (BitCodeAbbrevOp::Encoding)Read(3); + if (BitCodeAbbrevOp::hasEncodingData(E)) + Abbv->Add(BitCodeAbbrevOp(E, ReadVBR64(5))); + else + Abbv->Add(BitCodeAbbrevOp(E)); + } + CurAbbrevs.push_back(Abbv); + } + + //===--------------------------------------------------------------------===// + // BlockInfo Block Reading + //===--------------------------------------------------------------------===// + +private: + BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { + if (BlockInfo *BI = getBlockInfo(BlockID)) + return *BI; + + // Otherwise, add a new record. + BlockInfoRecords.push_back(BlockInfo()); + BlockInfoRecords.back().BlockID = BlockID; + return BlockInfoRecords.back(); + } + +public: + + bool ReadBlockInfoBlock() { + if (EnterSubBlock(bitc::BLOCKINFO_BLOCK_ID)) return true; + + SmallVector<uint64_t, 64> Record; + BlockInfo *CurBlockInfo = 0; + + // Read all the records for this module. + while (1) { + unsigned Code = ReadCode(); + if (Code == bitc::END_BLOCK) + return ReadBlockEnd(); + if (Code == bitc::ENTER_SUBBLOCK) { + ReadSubBlockID(); + if (SkipBlock()) return true; + continue; + } + + // Read abbrev records, associate them with CurBID. + if (Code == bitc::DEFINE_ABBREV) { + if (!CurBlockInfo) return true; + ReadAbbrevRecord(); + + // ReadAbbrevRecord installs the abbrev in CurAbbrevs. Move it to the + // appropriate BlockInfo. + BitCodeAbbrev *Abbv = CurAbbrevs.back(); + CurAbbrevs.pop_back(); + CurBlockInfo->Abbrevs.push_back(Abbv); + continue; + } + + // Read a record. + Record.clear(); + switch (ReadRecord(Code, Record)) { + default: break; // Default behavior, ignore unknown content. + case bitc::BLOCKINFO_CODE_SETBID: + if (Record.size() < 1) return true; + CurBlockInfo = &getOrCreateBlockInfo((unsigned)Record[0]); + break; + } + } + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Bitcode/BitstreamWriter.h b/include/llvm/Bitcode/BitstreamWriter.h new file mode 100644 index 0000000..64598ed --- /dev/null +++ b/include/llvm/Bitcode/BitstreamWriter.h @@ -0,0 +1,398 @@ +//===- BitstreamWriter.h - Low-level bitstream writer interface -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines the BitstreamWriter class. This class can be used to +// write an arbitrary bitstream, regardless of its contents. +// +//===----------------------------------------------------------------------===// + +#ifndef BITSTREAM_WRITER_H +#define BITSTREAM_WRITER_H + +#include "llvm/Bitcode/BitCodes.h" +#include <vector> + +namespace llvm { + +class BitstreamWriter { + std::vector<unsigned char> &Out; + + /// CurBit - Always between 0 and 31 inclusive, specifies the next bit to use. + unsigned CurBit; + + /// CurValue - The current value. Only bits < CurBit are valid. + uint32_t CurValue; + + /// CurCodeSize - This is the declared size of code values used for the + /// current block, in bits. + unsigned CurCodeSize; + + /// BlockInfoCurBID - When emitting a BLOCKINFO_BLOCK, this is the currently + /// selected BLOCK ID. + unsigned BlockInfoCurBID; + + /// CurAbbrevs - Abbrevs installed at in this block. + std::vector<BitCodeAbbrev*> CurAbbrevs; + + struct Block { + unsigned PrevCodeSize; + unsigned StartSizeWord; + std::vector<BitCodeAbbrev*> PrevAbbrevs; + Block(unsigned PCS, unsigned SSW) : PrevCodeSize(PCS), StartSizeWord(SSW) {} + }; + + /// BlockScope - This tracks the current blocks that we have entered. + std::vector<Block> BlockScope; + + /// BlockInfo - This contains information emitted to BLOCKINFO_BLOCK blocks. + /// These describe abbreviations that all blocks of the specified ID inherit. + struct BlockInfo { + unsigned BlockID; + std::vector<BitCodeAbbrev*> Abbrevs; + }; + std::vector<BlockInfo> BlockInfoRecords; + +public: + BitstreamWriter(std::vector<unsigned char> &O) + : Out(O), CurBit(0), CurValue(0), CurCodeSize(2) {} + + ~BitstreamWriter() { + assert(CurBit == 0 && "Unflused data remaining"); + assert(BlockScope.empty() && CurAbbrevs.empty() && "Block imbalance"); + + // Free the BlockInfoRecords. + while (!BlockInfoRecords.empty()) { + BlockInfo &Info = BlockInfoRecords.back(); + // Free blockinfo abbrev info. + for (unsigned i = 0, e = Info.Abbrevs.size(); i != e; ++i) + Info.Abbrevs[i]->dropRef(); + BlockInfoRecords.pop_back(); + } + } + //===--------------------------------------------------------------------===// + // Basic Primitives for emitting bits to the stream. + //===--------------------------------------------------------------------===// + + void Emit(uint32_t Val, unsigned NumBits) { + assert(NumBits <= 32 && "Invalid value size!"); + assert((Val & ~(~0U >> (32-NumBits))) == 0 && "High bits set!"); + CurValue |= Val << CurBit; + if (CurBit + NumBits < 32) { + CurBit += NumBits; + return; + } + + // Add the current word. + unsigned V = CurValue; + Out.push_back((unsigned char)(V >> 0)); + Out.push_back((unsigned char)(V >> 8)); + Out.push_back((unsigned char)(V >> 16)); + Out.push_back((unsigned char)(V >> 24)); + + if (CurBit) + CurValue = Val >> (32-CurBit); + else + CurValue = 0; + CurBit = (CurBit+NumBits) & 31; + } + + void Emit64(uint64_t Val, unsigned NumBits) { + if (NumBits <= 32) + Emit((uint32_t)Val, NumBits); + else { + Emit((uint32_t)Val, 32); + Emit((uint32_t)(Val >> 32), NumBits-32); + } + } + + void FlushToWord() { + if (CurBit) { + unsigned V = CurValue; + Out.push_back((unsigned char)(V >> 0)); + Out.push_back((unsigned char)(V >> 8)); + Out.push_back((unsigned char)(V >> 16)); + Out.push_back((unsigned char)(V >> 24)); + CurBit = 0; + CurValue = 0; + } + } + + void EmitVBR(uint32_t Val, unsigned NumBits) { + uint32_t Threshold = 1U << (NumBits-1); + + // Emit the bits with VBR encoding, NumBits-1 bits at a time. + while (Val >= Threshold) { + Emit((Val & ((1 << (NumBits-1))-1)) | (1 << (NumBits-1)), NumBits); + Val >>= NumBits-1; + } + + Emit(Val, NumBits); + } + + void EmitVBR64(uint64_t Val, unsigned NumBits) { + if ((uint32_t)Val == Val) + return EmitVBR((uint32_t)Val, NumBits); + + uint64_t Threshold = 1U << (NumBits-1); + + // Emit the bits with VBR encoding, NumBits-1 bits at a time. + while (Val >= Threshold) { + Emit(((uint32_t)Val & ((1 << (NumBits-1))-1)) | + (1 << (NumBits-1)), NumBits); + Val >>= NumBits-1; + } + + Emit((uint32_t)Val, NumBits); + } + + /// EmitCode - Emit the specified code. + void EmitCode(unsigned Val) { + Emit(Val, CurCodeSize); + } + + //===--------------------------------------------------------------------===// + // Block Manipulation + //===--------------------------------------------------------------------===// + + /// getBlockInfo - If there is block info for the specified ID, return it, + /// otherwise return null. + BlockInfo *getBlockInfo(unsigned BlockID) { + // Common case, the most recent entry matches BlockID. + if (!BlockInfoRecords.empty() && BlockInfoRecords.back().BlockID == BlockID) + return &BlockInfoRecords.back(); + + for (unsigned i = 0, e = BlockInfoRecords.size(); i != e; ++i) + if (BlockInfoRecords[i].BlockID == BlockID) + return &BlockInfoRecords[i]; + return 0; + } + + void EnterSubblock(unsigned BlockID, unsigned CodeLen) { + // Block header: + // [ENTER_SUBBLOCK, blockid, newcodelen, <align4bytes>, blocklen] + EmitCode(bitc::ENTER_SUBBLOCK); + EmitVBR(BlockID, bitc::BlockIDWidth); + EmitVBR(CodeLen, bitc::CodeLenWidth); + FlushToWord(); + + unsigned BlockSizeWordLoc = Out.size(); + unsigned OldCodeSize = CurCodeSize; + + // Emit a placeholder, which will be replaced when the block is popped. + Emit(0, bitc::BlockSizeWidth); + + CurCodeSize = CodeLen; + + // Push the outer block's abbrev set onto the stack, start out with an + // empty abbrev set. + BlockScope.push_back(Block(OldCodeSize, BlockSizeWordLoc/4)); + BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + + // If there is a blockinfo for this BlockID, add all the predefined abbrevs + // to the abbrev list. + if (BlockInfo *Info = getBlockInfo(BlockID)) { + for (unsigned i = 0, e = Info->Abbrevs.size(); i != e; ++i) { + CurAbbrevs.push_back(Info->Abbrevs[i]); + Info->Abbrevs[i]->addRef(); + } + } + } + + void ExitBlock() { + assert(!BlockScope.empty() && "Block scope imbalance!"); + + // Delete all abbrevs. + for (unsigned i = 0, e = CurAbbrevs.size(); i != e; ++i) + CurAbbrevs[i]->dropRef(); + + const Block &B = BlockScope.back(); + + // Block tail: + // [END_BLOCK, <align4bytes>] + EmitCode(bitc::END_BLOCK); + FlushToWord(); + + // Compute the size of the block, in words, not counting the size field. + unsigned SizeInWords = Out.size()/4-B.StartSizeWord - 1; + unsigned ByteNo = B.StartSizeWord*4; + + // Update the block size field in the header of this sub-block. + Out[ByteNo++] = (unsigned char)(SizeInWords >> 0); + Out[ByteNo++] = (unsigned char)(SizeInWords >> 8); + Out[ByteNo++] = (unsigned char)(SizeInWords >> 16); + Out[ByteNo++] = (unsigned char)(SizeInWords >> 24); + + // Restore the inner block's code size and abbrev table. + CurCodeSize = B.PrevCodeSize; + BlockScope.back().PrevAbbrevs.swap(CurAbbrevs); + BlockScope.pop_back(); + } + + //===--------------------------------------------------------------------===// + // Record Emission + //===--------------------------------------------------------------------===// + +private: + /// EmitAbbreviatedField - Emit a single scalar field value with the specified + /// encoding. + template<typename uintty> + void EmitAbbreviatedField(const BitCodeAbbrevOp &Op, uintty V) { + if (Op.isLiteral()) { + // If the abbrev specifies the literal value to use, don't emit + // anything. + assert(V == Op.getLiteralValue() && + "Invalid abbrev for record!"); + return; + } + + // Encode the value as we are commanded. + switch (Op.getEncoding()) { + default: assert(0 && "Unknown encoding!"); + case BitCodeAbbrevOp::Fixed: + Emit((unsigned)V, (unsigned)Op.getEncodingData()); + break; + case BitCodeAbbrevOp::VBR: + EmitVBR64(V, (unsigned)Op.getEncodingData()); + break; + case BitCodeAbbrevOp::Char6: + Emit(BitCodeAbbrevOp::EncodeChar6((char)V), 6); + break; + } + } +public: + + /// EmitRecord - Emit the specified record to the stream, using an abbrev if + /// we have one to compress the output. + template<typename uintty> + void EmitRecord(unsigned Code, SmallVectorImpl<uintty> &Vals, + unsigned Abbrev = 0) { + if (Abbrev) { + unsigned AbbrevNo = Abbrev-bitc::FIRST_APPLICATION_ABBREV; + assert(AbbrevNo < CurAbbrevs.size() && "Invalid abbrev #!"); + BitCodeAbbrev *Abbv = CurAbbrevs[AbbrevNo]; + + EmitCode(Abbrev); + + // Insert the code into Vals to treat it uniformly. + Vals.insert(Vals.begin(), Code); + + unsigned RecordIdx = 0; + for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) { + const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); + if (Op.isLiteral() || Op.getEncoding() != BitCodeAbbrevOp::Array) { + assert(RecordIdx < Vals.size() && "Invalid abbrev/record"); + EmitAbbreviatedField(Op, Vals[RecordIdx]); + ++RecordIdx; + } else { + // Array case. + assert(i+2 == e && "array op not second to last?"); + const BitCodeAbbrevOp &EltEnc = Abbv->getOperandInfo(++i); + + // Emit a vbr6 to indicate the number of elements present. + EmitVBR(Vals.size()-RecordIdx, 6); + + // Emit each field. + for (; RecordIdx != Vals.size(); ++RecordIdx) + EmitAbbreviatedField(EltEnc, Vals[RecordIdx]); + } + } + assert(RecordIdx == Vals.size() && "Not all record operands emitted!"); + } else { + // If we don't have an abbrev to use, emit this in its fully unabbreviated + // form. + EmitCode(bitc::UNABBREV_RECORD); + EmitVBR(Code, 6); + EmitVBR(Vals.size(), 6); + for (unsigned i = 0, e = Vals.size(); i != e; ++i) + EmitVBR64(Vals[i], 6); + } + } + + //===--------------------------------------------------------------------===// + // Abbrev Emission + //===--------------------------------------------------------------------===// + +private: + // Emit the abbreviation as a DEFINE_ABBREV record. + void EncodeAbbrev(BitCodeAbbrev *Abbv) { + EmitCode(bitc::DEFINE_ABBREV); + EmitVBR(Abbv->getNumOperandInfos(), 5); + for (unsigned i = 0, e = Abbv->getNumOperandInfos(); i != e; ++i) { + const BitCodeAbbrevOp &Op = Abbv->getOperandInfo(i); + Emit(Op.isLiteral(), 1); + if (Op.isLiteral()) { + EmitVBR64(Op.getLiteralValue(), 8); + } else { + Emit(Op.getEncoding(), 3); + if (Op.hasEncodingData()) + EmitVBR64(Op.getEncodingData(), 5); + } + } + } +public: + + /// EmitAbbrev - This emits an abbreviation to the stream. Note that this + /// method takes ownership of the specified abbrev. + unsigned EmitAbbrev(BitCodeAbbrev *Abbv) { + // Emit the abbreviation as a record. + EncodeAbbrev(Abbv); + CurAbbrevs.push_back(Abbv); + return CurAbbrevs.size()-1+bitc::FIRST_APPLICATION_ABBREV; + } + + //===--------------------------------------------------------------------===// + // BlockInfo Block Emission + //===--------------------------------------------------------------------===// + + /// EnterBlockInfoBlock - Start emitting the BLOCKINFO_BLOCK. + void EnterBlockInfoBlock(unsigned CodeWidth) { + EnterSubblock(bitc::BLOCKINFO_BLOCK_ID, CodeWidth); + BlockInfoCurBID = -1U; + } +private: + /// SwitchToBlockID - If we aren't already talking about the specified block + /// ID, emit a BLOCKINFO_CODE_SETBID record. + void SwitchToBlockID(unsigned BlockID) { + if (BlockInfoCurBID == BlockID) return; + SmallVector<unsigned, 2> V; + V.push_back(BlockID); + EmitRecord(bitc::BLOCKINFO_CODE_SETBID, V); + BlockInfoCurBID = BlockID; + } + + BlockInfo &getOrCreateBlockInfo(unsigned BlockID) { + if (BlockInfo *BI = getBlockInfo(BlockID)) + return *BI; + + // Otherwise, add a new record. + BlockInfoRecords.push_back(BlockInfo()); + BlockInfoRecords.back().BlockID = BlockID; + return BlockInfoRecords.back(); + } + +public: + + /// EmitBlockInfoAbbrev - Emit a DEFINE_ABBREV record for the specified + /// BlockID. + unsigned EmitBlockInfoAbbrev(unsigned BlockID, BitCodeAbbrev *Abbv) { + SwitchToBlockID(BlockID); + EncodeAbbrev(Abbv); + + // Add the abbrev to the specified block record. + BlockInfo &Info = getOrCreateBlockInfo(BlockID); + Info.Abbrevs.push_back(Abbv); + + return Info.Abbrevs.size()-1+bitc::FIRST_APPLICATION_ABBREV; + } +}; + + +} // End llvm namespace + +#endif diff --git a/include/llvm/Bitcode/LLVMBitCodes.h b/include/llvm/Bitcode/LLVMBitCodes.h new file mode 100644 index 0000000..24e6729 --- /dev/null +++ b/include/llvm/Bitcode/LLVMBitCodes.h @@ -0,0 +1,195 @@ +//===- LLVMBitCodes.h - Enum values for the LLVM bitcode format -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines Bitcode enum values for LLVM IR bitcode files. +// +// The enum values defined in this file should be considered permanent. If +// new features are added, they should have values added at the end of the +// respective lists. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_LLVMBITCODES_H +#define LLVM_BITCODE_LLVMBITCODES_H + +#include "llvm/Bitcode/BitCodes.h" + +namespace llvm { +namespace bitc { + // The only top-level block type defined is for a module. + enum BlockIDs { + // Blocks + MODULE_BLOCK_ID = FIRST_APPLICATION_BLOCKID, + + // Module sub-block id's. + PARAMATTR_BLOCK_ID, + TYPE_BLOCK_ID, + CONSTANTS_BLOCK_ID, + FUNCTION_BLOCK_ID, + TYPE_SYMTAB_BLOCK_ID, + VALUE_SYMTAB_BLOCK_ID + }; + + + /// MODULE blocks have a number of optional fields and subblocks. + enum ModuleCodes { + MODULE_CODE_VERSION = 1, // VERSION: [version#] + MODULE_CODE_TRIPLE = 2, // TRIPLE: [strchr x N] + MODULE_CODE_DATALAYOUT = 3, // DATALAYOUT: [strchr x N] + MODULE_CODE_ASM = 4, // ASM: [strchr x N] + MODULE_CODE_SECTIONNAME = 5, // SECTIONNAME: [strchr x N] + MODULE_CODE_DEPLIB = 6, // DEPLIB: [strchr x N] + + // GLOBALVAR: [type, isconst, initid, + // linkage, alignment, section, visibility, threadlocal] + MODULE_CODE_GLOBALVAR = 7, + + // FUNCTION: [type, callingconv, isproto, linkage, paramattrs, alignment, + // section, visibility] + MODULE_CODE_FUNCTION = 8, + + // ALIAS: [alias type, aliasee val#, linkage] + MODULE_CODE_ALIAS = 9, + + /// MODULE_CODE_PURGEVALS: [numvals] + MODULE_CODE_PURGEVALS = 10 + }; + + /// PARAMATTR blocks have code for defining a parameter attribute set. + enum ParamAttrCodes { + PARAMATTR_CODE_ENTRY = 1 // ENTRY: [paramidx0, attr0, paramidx1, attr1...] + }; + + /// TYPE blocks have codes for each type primitive they use. + enum TypeCodes { + TYPE_CODE_NUMENTRY = 1, // NUMENTRY: [numentries] + + // Type Codes + TYPE_CODE_VOID = 2, // VOID + TYPE_CODE_FLOAT = 3, // FLOAT + TYPE_CODE_DOUBLE = 4, // DOUBLE + TYPE_CODE_LABEL = 5, // LABEL + TYPE_CODE_OPAQUE = 6, // OPAQUE + TYPE_CODE_INTEGER = 7, // INTEGER: [width] + TYPE_CODE_POINTER = 8, // POINTER: [pointee type] + TYPE_CODE_FUNCTION = 9, // FUNCTION: [vararg, retty, paramty x N] + TYPE_CODE_STRUCT = 10, // STRUCT: [ispacked, eltty x N] + TYPE_CODE_ARRAY = 11, // ARRAY: [numelts, eltty] + TYPE_CODE_VECTOR = 12 // VECTOR: [numelts, eltty] + // Any other type code is assumed to be an unknown type. + }; + + // The type symbol table only has one code (TST_ENTRY_CODE). + enum TypeSymtabCodes { + TST_CODE_ENTRY = 1 // TST_ENTRY: [typeid, namechar x N] + }; + + // The value symbol table only has one code (VST_ENTRY_CODE). + enum ValueSymtabCodes { + VST_CODE_ENTRY = 1, // VST_ENTRY: [valid, namechar x N] + VST_CODE_BBENTRY = 2 // VST_BBENTRY: [bbid, namechar x N] + }; + + // The constants block (CONSTANTS_BLOCK_ID) describes emission for each + // constant and maintains an implicit current type value. + enum ConstantsCodes { + CST_CODE_SETTYPE = 1, // SETTYPE: [typeid] + CST_CODE_NULL = 2, // NULL + CST_CODE_UNDEF = 3, // UNDEF + CST_CODE_INTEGER = 4, // INTEGER: [intval] + CST_CODE_WIDE_INTEGER = 5, // WIDE_INTEGER: [n x intval] + CST_CODE_FLOAT = 6, // FLOAT: [fpval] + CST_CODE_AGGREGATE = 7, // AGGREGATE: [n x value number] + CST_CODE_STRING = 8, // STRING: [values] + CST_CODE_CSTRING = 9, // CSTRING: [values] + CST_CODE_CE_BINOP = 10, // CE_BINOP: [opcode, opval, opval] + CST_CODE_CE_CAST = 11, // CE_CAST: [opcode, opty, opval] + CST_CODE_CE_GEP = 12, // CE_GEP: [n x operands] + CST_CODE_CE_SELECT = 13, // CE_SELECT: [opval, opval, opval] + CST_CODE_CE_EXTRACTELT = 14, // CE_EXTRACTELT: [opty, opval, opval] + CST_CODE_CE_INSERTELT = 15, // CE_INSERTELT: [opval, opval, opval] + CST_CODE_CE_SHUFFLEVEC = 16, // CE_SHUFFLEVEC: [opval, opval, opval] + CST_CODE_CE_CMP = 17, // CE_CMP: [opty, opval, opval, pred] + CST_CODE_INLINEASM = 18 // INLINEASM: [sideeffect,asmstr,conststr] + }; + + /// CastOpcodes - These are values used in the bitcode files to encode which + /// cast a CST_CODE_CE_CAST or a XXX refers to. The values of these enums + /// have no fixed relation to the LLVM IR enum values. Changing these will + /// break compatibility with old files. + enum CastOpcodes { + CAST_TRUNC = 0, + CAST_ZEXT = 1, + CAST_SEXT = 2, + CAST_FPTOUI = 3, + CAST_FPTOSI = 4, + CAST_UITOFP = 5, + CAST_SITOFP = 6, + CAST_FPTRUNC = 7, + CAST_FPEXT = 8, + CAST_PTRTOINT = 9, + CAST_INTTOPTR = 10, + CAST_BITCAST = 11 + }; + + /// BinaryOpcodes - These are values used in the bitcode files to encode which + /// binop a CST_CODE_CE_BINOP or a XXX refers to. The values of these enums + /// have no fixed relation to the LLVM IR enum values. Changing these will + /// break compatibility with old files. + enum BinaryOpcodes { + BINOP_ADD = 0, + BINOP_SUB = 1, + BINOP_MUL = 2, + BINOP_UDIV = 3, + BINOP_SDIV = 4, // overloaded for FP + BINOP_UREM = 5, + BINOP_SREM = 6, // overloaded for FP + BINOP_SHL = 7, + BINOP_LSHR = 8, + BINOP_ASHR = 9, + BINOP_AND = 10, + BINOP_OR = 11, + BINOP_XOR = 12 + }; + + + // The function body block (FUNCTION_BLOCK_ID) describes function bodies. It + // can contain a constant block (CONSTANTS_BLOCK_ID). + enum FunctionCodes { + FUNC_CODE_DECLAREBLOCKS = 1, // DECLAREBLOCKS: [n] + + FUNC_CODE_INST_BINOP = 2, // BINOP: [opcode, ty, opval, opval] + FUNC_CODE_INST_CAST = 3, // CAST: [opcode, ty, opty, opval] + FUNC_CODE_INST_GEP = 4, // GEP: [n x operands] + FUNC_CODE_INST_SELECT = 5, // SELECT: [ty, opval, opval, opval] + FUNC_CODE_INST_EXTRACTELT = 6, // EXTRACTELT: [opty, opval, opval] + FUNC_CODE_INST_INSERTELT = 7, // INSERTELT: [ty, opval, opval, opval] + FUNC_CODE_INST_SHUFFLEVEC = 8, // SHUFFLEVEC: [ty, opval, opval, opval] + FUNC_CODE_INST_CMP = 9, // CMP: [opty, opval, opval, pred] + + FUNC_CODE_INST_RET = 10, // RET: [opty,opval<both optional>] + FUNC_CODE_INST_BR = 11, // BR: [bb#, bb#, cond] or [bb#] + FUNC_CODE_INST_SWITCH = 12, // SWITCH: [opty, opval, n, n x ops] + FUNC_CODE_INST_INVOKE = 13, // INVOKE: [attr, fnty, op0,op1, ...] + FUNC_CODE_INST_UNWIND = 14, // UNWIND + FUNC_CODE_INST_UNREACHABLE = 15, // UNREACHABLE + + FUNC_CODE_INST_PHI = 16, // PHI: [ty, val0,bb0, ...] + FUNC_CODE_INST_MALLOC = 17, // MALLOC: [instty, op, align] + FUNC_CODE_INST_FREE = 18, // FREE: [opty, op] + FUNC_CODE_INST_ALLOCA = 19, // ALLOCA: [instty, op, align] + FUNC_CODE_INST_LOAD = 20, // LOAD: [opty, op, align, vol] + FUNC_CODE_INST_STORE = 21, // STORE: [ptrty,val,ptr, align, vol] + FUNC_CODE_INST_CALL = 22, // CALL: [attr, fnty, fnid, args...] + FUNC_CODE_INST_VAARG = 23 // VAARG: [valistty, valist, instty] + }; +} // End bitc namespace +} // End llvm namespace + +#endif diff --git a/include/llvm/Bitcode/ReaderWriter.h b/include/llvm/Bitcode/ReaderWriter.h new file mode 100644 index 0000000..7898385 --- /dev/null +++ b/include/llvm/Bitcode/ReaderWriter.h @@ -0,0 +1,48 @@ +//===-- llvm/Bitcode/ReaderWriter.h - Bitcode reader/writers ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header defines interfaces to read and write LLVM bitcode files/streams. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_BITCODE_H +#define LLVM_BITCODE_H + +#include <iosfwd> +#include <string> + +namespace llvm { + class Module; + class ModuleProvider; + class MemoryBuffer; + class ModulePass; + + /// getBitcodeModuleProvider - Read the header of the specified bitcode buffer + /// and prepare for lazy deserialization of function bodies. If successful, + /// this takes ownership of 'buffer' and returns a non-null pointer. On + /// error, this returns null, *does not* take ownership of Buffer, and fills + /// in *ErrMsg with an error description if ErrMsg is non-null. + ModuleProvider *getBitcodeModuleProvider(MemoryBuffer *Buffer, + std::string *ErrMsg = 0); + + /// ParseBitcodeFile - Read the specified bitcode file, returning the module. + /// If an error occurs, this returns null and fills in *ErrMsg if it is + /// non-null. This method *never* takes ownership of Buffer. + Module *ParseBitcodeFile(MemoryBuffer *Buffer, std::string *ErrMsg = 0); + + /// WriteBitcodeToFile - Write the specified module to the specified output + /// stream. + void WriteBitcodeToFile(const Module *M, std::ostream &Out); + + /// CreateBitcodeWriterPass - Create and return a pass that writes the module + /// to the specified ostream. + ModulePass *CreateBitcodeWriterPass(std::ostream &Str); +} // End llvm namespace + +#endif diff --git a/include/llvm/CallGraphSCCPass.h b/include/llvm/CallGraphSCCPass.h new file mode 100644 index 0000000..2bc163d --- /dev/null +++ b/include/llvm/CallGraphSCCPass.h @@ -0,0 +1,72 @@ +//===- CallGraphSCCPass.h - Pass that operates BU on call graph -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the CallGraphSCCPass class, which is used for passes which +// are implemented as bottom-up traversals on the call graph. Because there may +// be cycles in the call graph, passes of this type operate on the call-graph in +// SCC order: that is, they process function bottom-up, except for recursive +// functions, which they process all at once. +// +// These passes are inherently interprocedural, and are required to keep the +// call graph up-to-date if they do anything which could modify it. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CALL_GRAPH_SCC_PASS_H +#define LLVM_CALL_GRAPH_SCC_PASS_H + +#include "llvm/Pass.h" + +namespace llvm { + +class CallGraphNode; +class CallGraph; +class PMStack; + +struct CallGraphSCCPass : public Pass { + + explicit CallGraphSCCPass(intptr_t pid) : Pass(pid) {} + + /// doInitialization - This method is called before the SCC's of the program + /// has been processed, allowing the pass to do initialization as necessary. + virtual bool doInitialization(CallGraph &CG) { + return false; + } + + /// runOnSCC - This method should be implemented by the subclass to perform + /// whatever action is necessary for the specified SCC. Note that + /// non-recursive (or only self-recursive) functions will have an SCC size of + /// 1, where recursive portions of the call graph will have SCC size > 1. + /// + virtual bool runOnSCC(const std::vector<CallGraphNode *> &SCC) = 0; + + /// doFinalization - This method is called after the SCC's of the program has + /// been processed, allowing the pass to do final cleanup as necessary. + virtual bool doFinalization(CallGraph &CG) { + return false; + } + + /// Assign pass manager to manager this pass + virtual void assignPassManager(PMStack &PMS, + PassManagerType PMT = PMT_CallGraphPassManager); + + /// Return what kind of Pass Manager can manage this pass. + virtual PassManagerType getPotentialPassManagerType() const { + return PMT_CallGraphPassManager; + } + + /// getAnalysisUsage - For this class, we declare that we require and preserve + /// the call graph. If the derived class implements this method, it should + /// always explicitly call the implementation here. + virtual void getAnalysisUsage(AnalysisUsage &Info) const; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/CallingConv.h b/include/llvm/CallingConv.h new file mode 100644 index 0000000..a10bc39 --- /dev/null +++ b/include/llvm/CallingConv.h @@ -0,0 +1,66 @@ +//===-- llvm/CallingConv.h - LLVM Calling Conventions -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines LLVM's set of calling conventions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CALLINGCONV_H +#define LLVM_CALLINGCONV_H + +namespace llvm { + +/// CallingConv Namespace - This namespace contains an enum with a value for +/// the well-known calling conventions. +/// +namespace CallingConv { + /// A set of enums which specify the assigned numeric values for known llvm + /// calling conventions. + /// @brief LLVM Calling Convention Representation + enum ID { + /// C - The default llvm calling convention, compatible with C. This + /// convention is the only calling convention that supports varargs calls. + /// As with typical C calling conventions, the callee/caller have to + /// tolerate certain amounts of prototype mismatch. + C = 0, + + // Generic LLVM calling conventions. None of these calling conventions + // support varargs calls, and all assume that the caller and callee + // prototype exactly match. + + /// Fast - This calling convention attempts to make calls as fast as + /// possible /// (e.g. by passing things in registers). + Fast = 8, + + // Cold - This calling convention attempts to make code in the caller as + // efficient as possible under the assumption that the call is not commonly + // executed. As such, these calls often preserve all registers so that the + // call does not break any live ranges in the caller side. + Cold = 9, + + // Target - This is the start of the target-specific calling conventions, + // e.g. fastcall and thiscall on X86. + FirstTargetCC = 64, + + /// X86_StdCall - stdcall is the calling conventions mostly used by the + /// Win32 API. It is basically the same as the C convention with the + /// difference in that the callee is responsible for popping the arguments + /// from the stack. + X86_StdCall = 64, + + /// X86_FastCall - 'fast' analog of X86_StdCall. Passes first two arguments + /// in ECX:EDX registers, others - via stack. Callee is responsible for + /// stack cleaning. + X86_FastCall = 65 + }; +} // End CallingConv namespace + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h new file mode 100644 index 0000000..954b9bc --- /dev/null +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -0,0 +1,316 @@ +//===-- llvm/CodeGen/AsmPrinter.h - AsmPrinter Framework --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a class to be used as the base class for target specific +// asm writers. This class primarily handles common functionality used by +// all asm writers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_ASMPRINTER_H +#define LLVM_CODEGEN_ASMPRINTER_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Support/DataTypes.h" +#include <set> + +namespace llvm { + class Constant; + class ConstantArray; + class GlobalVariable; + class GlobalAlias; + class MachineConstantPoolEntry; + class MachineConstantPoolValue; + class Mangler; + class TargetAsmInfo; + + + /// AsmPrinter - This class is intended to be used as a driving class for all + /// asm writers. + class AsmPrinter : public MachineFunctionPass { + static char ID; + + /// FunctionNumber - This provides a unique ID for each function emitted in + /// this translation unit. It is autoincremented by SetupMachineFunction, + /// and can be accessed with getFunctionNumber() and + /// IncrementFunctionNumber(). + /// + unsigned FunctionNumber; + + protected: + // Necessary for external weak linkage support + std::set<const GlobalValue*> ExtWeakSymbols; + + public: + /// Output stream on which we're printing assembly code. + /// + std::ostream &O; + + /// Target machine description. + /// + TargetMachine &TM; + + /// Target Asm Printer information. + /// + const TargetAsmInfo *TAI; + + /// Name-mangler for global names. + /// + Mangler *Mang; + + /// Cache of mangled name for current function. This is recalculated at the + /// beginning of each call to runOnMachineFunction(). + /// + std::string CurrentFnName; + + /// CurrentSection - The current section we are emitting to. This is + /// controlled and used by the SwitchSection method. + std::string CurrentSection; + + protected: + AsmPrinter(std::ostream &o, TargetMachine &TM, const TargetAsmInfo *T); + + public: + /// SwitchToTextSection - Switch to the specified section of the executable + /// if we are not already in it! If GV is non-null and if the global has an + /// explicitly requested section, we switch to the section indicated for the + /// global instead of NewSection. + /// + /// If the new section is an empty string, this method forgets what the + /// current section is, but does not emit a .section directive. + /// + /// This method is used when about to emit executable code. + /// + void SwitchToTextSection(const char *NewSection, const GlobalValue *GV = NULL); + + /// SwitchToDataSection - Switch to the specified section of the executable + /// if we are not already in it! If GV is non-null and if the global has an + /// explicitly requested section, we switch to the section indicated for the + /// global instead of NewSection. + /// + /// If the new section is an empty string, this method forgets what the + /// current section is, but does not emit a .section directive. + /// + /// This method is used when about to emit data. For most assemblers, this + /// is the same as the SwitchToTextSection method, but not all assemblers + /// are the same. + /// + void SwitchToDataSection(const char *NewSection, const GlobalValue *GV = NULL); + + /// getGlobalLinkName - Returns the asm/link name of of the specified + /// global variable. Should be overridden by each target asm printer to + /// generate the appropriate value. + virtual const std::string getGlobalLinkName(const GlobalVariable *GV) const; + + /// EmitExternalGlobal - Emit the external reference to a global variable. + /// Should be overridden if an indirect reference should be used. + virtual void EmitExternalGlobal(const GlobalVariable *GV); + + protected: + /// doInitialization - Set up the AsmPrinter when we are working on a new + /// module. If your pass overrides this, it must make sure to explicitly + /// call this implementation. + bool doInitialization(Module &M); + + /// doFinalization - Shut down the asmprinter. If you override this in your + /// pass, you must make sure to call it explicitly. + bool doFinalization(Module &M); + + /// PrintSpecial - Print information related to the specified machine instr + /// that is independent of the operand, and may be independent of the instr + /// itself. This can be useful for portably encoding the comment character + /// or other bits of target-specific knowledge into the asmstrings. The + /// syntax used is ${:comment}. Targets can override this to add support + /// for their own strange codes. + virtual void PrintSpecial(const MachineInstr *MI, const char *Code); + + /// PrintAsmOperand - Print the specified operand of MI, an INLINEASM + /// instruction, using the specified assembler variant. Targets should + /// override this to format as appropriate. This method can return true if + /// the operand is erroneous. + virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode); + + /// PrintAsmMemoryOperand - Print the specified operand of MI, an INLINEASM + /// instruction, using the specified assembler variant as an address. + /// Targets should override this to format as appropriate. This method can + /// return true if the operand is erroneous. + virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, + const char *ExtraCode); + + /// getSectionForFunction - Return the section that we should emit the + /// specified function body into. This defaults to 'TextSection'. This + /// should most likely be overridden by the target to put linkonce/weak + /// functions into special sections. + virtual std::string getSectionForFunction(const Function &F) const; + + /// SetupMachineFunction - This should be called when a new MachineFunction + /// is being processed from runOnMachineFunction. + void SetupMachineFunction(MachineFunction &MF); + + /// getFunctionNumber - Return a unique ID for the current function. + /// + unsigned getFunctionNumber() const { return FunctionNumber; } + + /// IncrementFunctionNumber - Increase Function Number. AsmPrinters should + /// not normally call this, as the counter is automatically bumped by + /// SetupMachineFunction. + void IncrementFunctionNumber() { FunctionNumber++; } + + /// EmitConstantPool - Print to the current output stream assembly + /// representations of the constants in the constant pool MCP. This is + /// used to print out constants which have been "spilled to memory" by + /// the code generator. + /// + void EmitConstantPool(MachineConstantPool *MCP); + + /// EmitJumpTableInfo - Print assembly representations of the jump tables + /// used by the current function to the current output stream. + /// + void EmitJumpTableInfo(MachineJumpTableInfo *MJTI, MachineFunction &MF); + + /// EmitSpecialLLVMGlobal - Check to see if the specified global is a + /// special global used by LLVM. If so, emit it and return true, otherwise + /// do nothing and return false. + bool EmitSpecialLLVMGlobal(const GlobalVariable *GV); + + public: + //===------------------------------------------------------------------===// + /// LEB 128 number encoding. + + /// PrintULEB128 - Print a series of hexidecimal values(separated by commas) + /// representing an unsigned leb128 value. + void PrintULEB128(unsigned Value) const; + + /// SizeULEB128 - Compute the number of bytes required for an unsigned + /// leb128 value. + static unsigned SizeULEB128(unsigned Value); + + /// PrintSLEB128 - Print a series of hexidecimal values(separated by commas) + /// representing a signed leb128 value. + void PrintSLEB128(int Value) const; + + /// SizeSLEB128 - Compute the number of bytes required for a signed leb128 + /// value. + static unsigned SizeSLEB128(int Value); + + //===------------------------------------------------------------------===// + // Emission and print routines + // + + /// PrintHex - Print a value as a hexidecimal value. + /// + void PrintHex(int Value) const; + + /// EOL - Print a newline character to asm stream. If a comment is present + /// then it will be printed first. Comments should not contain '\n'. + void EOL() const; + void EOL(const std::string &Comment) const; + + /// EmitULEB128Bytes - Emit an assembler byte data directive to compose an + /// unsigned leb128 value. + void EmitULEB128Bytes(unsigned Value) const; + + /// EmitSLEB128Bytes - print an assembler byte data directive to compose a + /// signed leb128 value. + void EmitSLEB128Bytes(int Value) const; + + /// EmitInt8 - Emit a byte directive and value. + /// + void EmitInt8(int Value) const; + + /// EmitInt16 - Emit a short directive and value. + /// + void EmitInt16(int Value) const; + + /// EmitInt32 - Emit a long directive and value. + /// + void EmitInt32(int Value) const; + + /// EmitInt64 - Emit a long long directive and value. + /// + void EmitInt64(uint64_t Value) const; + + /// EmitString - Emit a string with quotes and a null terminator. + /// Special characters are emitted properly. + /// \literal (Eg. '\t') \endliteral + void EmitString(const std::string &String) const; + + //===------------------------------------------------------------------===// + + /// EmitAlignment - Emit an alignment directive to the specified power of + /// two boundary. For example, if you pass in 3 here, you will get an 8 + /// byte alignment. If a global value is specified, and if that global has + /// an explicit alignment requested, it will unconditionally override the + /// alignment request. However, if ForcedAlignBits is specified, this value + /// has final say: the ultimate alignment will be the max of ForcedAlignBits + /// and the alignment computed with NumBits and the global. + /// + /// The algorithm is: + /// Align = NumBits; + /// if (GV && GV->hasalignment) Align = GV->getalignment(); + /// Align = std::max(Align, ForcedAlignBits); + /// + void EmitAlignment(unsigned NumBits, const GlobalValue *GV = 0, + unsigned ForcedAlignBits = 0) const; + + protected: + /// EmitZeros - Emit a block of zeros. + /// + void EmitZeros(uint64_t NumZeros) const; + + /// EmitString - Emit a zero-byte-terminated string constant. + /// + virtual void EmitString(const ConstantArray *CVA) const; + + /// EmitConstantValueOnly - Print out the specified constant, without a + /// storage class. Only constants of first-class type are allowed here. + void EmitConstantValueOnly(const Constant *CV); + + /// EmitGlobalConstant - Print a general LLVM constant to the .s file. + /// + void EmitGlobalConstant(const Constant* CV); + + virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV); + + /// printInlineAsm - This method formats and prints the specified machine + /// instruction that is an inline asm. + void printInlineAsm(const MachineInstr *MI) const; + + /// printLabel - This method prints a local label used by debug and + /// exception handling tables. + void printLabel(const MachineInstr *MI) const; + + /// printBasicBlockLabel - This method prints the label for the specified + /// MachineBasicBlock + virtual void printBasicBlockLabel(const MachineBasicBlock *MBB, + bool printColon = false, + bool printComment = true) const; + + /// printSetLabel - This method prints a set label for the specified + /// MachineBasicBlock + void printSetLabel(unsigned uid, const MachineBasicBlock *MBB) const; + void printSetLabel(unsigned uid, unsigned uid2, + const MachineBasicBlock *MBB) const; + + /// printDataDirective - This method prints the asm directive for the + /// specified type. + void printDataDirective(const Type *type); + + private: + void EmitLLVMUsedList(Constant *List); + void EmitXXStructorList(Constant *List); + void EmitConstantPool(unsigned Alignment, const char *Section, + std::vector<std::pair<MachineConstantPoolEntry,unsigned> > &CP); + + }; +} + +#endif diff --git a/include/llvm/CodeGen/CallingConvLower.h b/include/llvm/CodeGen/CallingConvLower.h new file mode 100644 index 0000000..959d052 --- /dev/null +++ b/include/llvm/CodeGen/CallingConvLower.h @@ -0,0 +1,202 @@ +//===-- llvm/CallingConvLower.h - Calling Conventions -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the CCState and CCValAssign classes, used for lowering +// and implementing calling conventions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_CALLINGCONVLOWER_H +#define LLVM_CODEGEN_CALLINGCONVLOWER_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/CodeGen/ValueTypes.h" + +namespace llvm { + class MRegisterInfo; + class TargetMachine; + class CCState; + class SDNode; + +/// CCValAssign - Represent assignment of one arg/retval to a location. +class CCValAssign { +public: + enum LocInfo { + Full, // The value fills the full location. + SExt, // The value is sign extended in the location. + ZExt, // The value is zero extended in the location. + AExt // The value is extended with undefined upper bits. + // TODO: a subset of the value is in the location. + }; +private: + /// ValNo - This is the value number begin assigned (e.g. an argument number). + unsigned ValNo; + + /// Loc is either a stack offset or a register number. + unsigned Loc; + + /// isMem - True if this is a memory loc, false if it is a register loc. + bool isMem : 1; + + /// Information about how the value is assigned. + LocInfo HTP : 7; + + /// ValVT - The type of the value being assigned. + MVT::ValueType ValVT; + + /// LocVT - The type of the location being assigned to. + MVT::ValueType LocVT; +public: + + static CCValAssign getReg(unsigned ValNo, MVT::ValueType ValVT, + unsigned RegNo, MVT::ValueType LocVT, + LocInfo HTP) { + CCValAssign Ret; + Ret.ValNo = ValNo; + Ret.Loc = RegNo; + Ret.isMem = false; + Ret.HTP = HTP; + Ret.ValVT = ValVT; + Ret.LocVT = LocVT; + return Ret; + } + static CCValAssign getMem(unsigned ValNo, MVT::ValueType ValVT, + unsigned Offset, MVT::ValueType LocVT, + LocInfo HTP) { + CCValAssign Ret; + Ret.ValNo = ValNo; + Ret.Loc = Offset; + Ret.isMem = true; + Ret.HTP = HTP; + Ret.ValVT = ValVT; + Ret.LocVT = LocVT; + return Ret; + } + + unsigned getValNo() const { return ValNo; } + MVT::ValueType getValVT() const { return ValVT; } + + bool isRegLoc() const { return !isMem; } + bool isMemLoc() const { return isMem; } + + unsigned getLocReg() const { assert(isRegLoc()); return Loc; } + unsigned getLocMemOffset() const { assert(isMemLoc()); return Loc; } + MVT::ValueType getLocVT() const { return LocVT; } + + LocInfo getLocInfo() const { return HTP; } +}; + + +/// CCAssignFn - This function assigns a location for Val, updating State to +/// reflect the change. +typedef bool CCAssignFn(unsigned ValNo, MVT::ValueType ValVT, + MVT::ValueType LocVT, CCValAssign::LocInfo LocInfo, + unsigned ArgFlags, CCState &State); + + +/// CCState - This class holds information needed while lowering arguments and +/// return values. It captures which registers are already assigned and which +/// stack slots are used. It provides accessors to allocate these values. +class CCState { + unsigned CallingConv; + bool IsVarArg; + const TargetMachine &TM; + const MRegisterInfo &MRI; + SmallVector<CCValAssign, 16> &Locs; + + unsigned StackOffset; + SmallVector<uint32_t, 16> UsedRegs; +public: + CCState(unsigned CC, bool isVarArg, const TargetMachine &TM, + SmallVector<CCValAssign, 16> &locs); + + void addLoc(const CCValAssign &V) { + Locs.push_back(V); + } + + const TargetMachine &getTarget() const { return TM; } + unsigned getCallingConv() const { return CallingConv; } + bool isVarArg() const { return IsVarArg; } + + unsigned getNextStackOffset() const { return StackOffset; } + + /// isAllocated - Return true if the specified register (or an alias) is + /// allocated. + bool isAllocated(unsigned Reg) const { + return UsedRegs[Reg/32] & (1 << (Reg&31)); + } + + /// AnalyzeFormalArguments - Analyze an ISD::FORMAL_ARGUMENTS node, + /// incorporating info about the formals into this state. + void AnalyzeFormalArguments(SDNode *TheArgs, CCAssignFn Fn); + + /// AnalyzeReturn - Analyze the returned values of an ISD::RET node, + /// incorporating info about the result values into this state. + void AnalyzeReturn(SDNode *TheRet, CCAssignFn Fn); + + /// AnalyzeCallOperands - Analyze an ISD::CALL node, incorporating info + /// about the passed values into this state. + void AnalyzeCallOperands(SDNode *TheCall, CCAssignFn Fn); + + /// AnalyzeCallResult - Analyze the return values of an ISD::CALL node, + /// incorporating info about the passed values into this state. + void AnalyzeCallResult(SDNode *TheCall, CCAssignFn Fn); + + + /// getFirstUnallocated - Return the first unallocated register in the set, or + /// NumRegs if they are all allocated. + unsigned getFirstUnallocated(const unsigned *Regs, unsigned NumRegs) const { + for (unsigned i = 0; i != NumRegs; ++i) + if (!isAllocated(Regs[i])) + return i; + return NumRegs; + } + + /// AllocateReg - Attempt to allocate one register. If it is not available, + /// return zero. Otherwise, return the register, marking it and any aliases + /// as allocated. + unsigned AllocateReg(unsigned Reg) { + if (isAllocated(Reg)) return 0; + MarkAllocated(Reg); + return Reg; + } + + /// AllocateReg - Attempt to allocate one of the specified registers. If none + /// are available, return zero. Otherwise, return the first one available, + /// marking it and any aliases as allocated. + unsigned AllocateReg(const unsigned *Regs, unsigned NumRegs) { + unsigned FirstUnalloc = getFirstUnallocated(Regs, NumRegs); + if (FirstUnalloc == NumRegs) + return 0; // Didn't find the reg. + + // Mark the register and any aliases as allocated. + unsigned Reg = Regs[FirstUnalloc]; + MarkAllocated(Reg); + return Reg; + } + + /// AllocateStack - Allocate a chunk of stack space with the specified size + /// and alignment. + unsigned AllocateStack(unsigned Size, unsigned Align) { + assert(Align && ((Align-1) & Align) == 0); // Align is power of 2. + StackOffset = ((StackOffset + Align-1) & ~(Align-1)); + unsigned Result = StackOffset; + StackOffset += Size; + return Result; + } +private: + /// MarkAllocated - Mark a register and all of its aliases as allocated. + void MarkAllocated(unsigned Reg); +}; + + + +} // end namespace llvm + +#endif diff --git a/include/llvm/CodeGen/DwarfWriter.h b/include/llvm/CodeGen/DwarfWriter.h new file mode 100644 index 0000000..d5d6925 --- /dev/null +++ b/include/llvm/CodeGen/DwarfWriter.h @@ -0,0 +1,82 @@ +//===-- llvm/CodeGen/DwarfWriter.h - Dwarf Framework ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by James M. Laskey and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains support for writing Dwarf debug and exception info into +// asm files. For Details on the Dwarf 3 specfication see DWARF Debugging +// Information Format V.3 reference manual http://dwarf.freestandards.org , +// +// The role of the Dwarf Writer class is to extract information from the +// MachineModuleInfo object, organize it in Dwarf form and then emit it into asm +// the current asm file using data and high level Dwarf directives. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_DWARFWRITER_H +#define LLVM_CODEGEN_DWARFWRITER_H + +#include <iosfwd> + +namespace llvm { + +class AsmPrinter; +class DwarfDebug; +class DwarfException; +class MachineModuleInfo; +class MachineFunction; +class Module; +class TargetAsmInfo; + +//===----------------------------------------------------------------------===// +// DwarfWriter - Emits Dwarf debug and exception handling directives. +// + +class DwarfWriter { +private: + /// DD - Provides the DwarfWriter debug implementation. + /// + DwarfDebug *DD; + + /// DE - Provides the DwarfWriter exception implementation. + /// + DwarfException *DE; + +public: + + DwarfWriter(std::ostream &OS, AsmPrinter *A, const TargetAsmInfo *T); + virtual ~DwarfWriter(); + + /// SetModuleInfo - Set machine module info when it's known that pass manager + /// has created it. Set by the target AsmPrinter. + void SetModuleInfo(MachineModuleInfo *MMI); + + //===--------------------------------------------------------------------===// + // Main entry points. + // + + /// BeginModule - Emit all Dwarf sections that should come prior to the + /// content. + void BeginModule(Module *M); + + /// EndModule - Emit all Dwarf sections that should come after the content. + /// + void EndModule(); + + /// BeginFunction - Gather pre-function debug information. Assumes being + /// emitted immediately after the function entry point. + void BeginFunction(MachineFunction *MF); + + /// EndFunction - Gather and emit post-function debug information. + /// + void EndFunction(); +}; + + +} // end llvm namespace + +#endif diff --git a/include/llvm/CodeGen/ELFRelocation.h b/include/llvm/CodeGen/ELFRelocation.h new file mode 100644 index 0000000..1c0b3e9 --- /dev/null +++ b/include/llvm/CodeGen/ELFRelocation.h @@ -0,0 +1,52 @@ +//=== ELFRelocation.h - ELF Relocation Info ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Christopher Lamb and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ELFRelocation class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_ELF_RELOCATION_H +#define LLVM_CODEGEN_ELF_RELOCATION_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + + /// ELFRelocation - This class contains all the information necessary to + /// to generate any 32-bit or 64-bit ELF relocation entry. + class ELFRelocation { + uint64_t r_offset; // offset in the section of the object this applies to + uint32_t r_symidx; // symbol table index of the symbol to use + uint32_t r_type; // machine specific relocation type + int64_t r_add; // explicit relocation addend + bool r_rela; // if true then the addend is part of the entry + // otherwise the addend is at the location specified + // by r_offset + public: + + uint64_t getInfo(bool is64Bit = false) const { + if (is64Bit) + return ((uint64_t)r_symidx << 32) + ((uint64_t)r_type & 0xFFFFFFFFL); + else + return (r_symidx << 8) + (r_type & 0xFFL); + } + + uint64_t getOffset() const { return r_offset; } + uint64_t getAddress() const { return r_add; } + + ELFRelocation(uint64_t off, uint32_t sym, uint32_t type, + bool rela = true, int64_t addend = 0) : + r_offset(off), r_symidx(sym), r_type(type), + r_add(addend), r_rela(rela) {} + }; + +} // end llvm namespace + +#endif // LLVM_CODEGEN_ELF_RELOCATION_H + diff --git a/include/llvm/CodeGen/FileWriters.h b/include/llvm/CodeGen/FileWriters.h new file mode 100644 index 0000000..6baa89f --- /dev/null +++ b/include/llvm/CodeGen/FileWriters.h @@ -0,0 +1,32 @@ +//===-- FileWriters.h - File Writers Creation Functions ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Bill Wendling and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Functions to add the various file writer passes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_FILEWRITERS_H +#define LLVM_CODEGEN_FILEWRITERS_H + +#include <iosfwd> + +namespace llvm { + + class FunctionPassManager; + class MachineCodeEmitter; + class TargetMachine; + + MachineCodeEmitter *AddELFWriter(FunctionPassManager &FPM, std::ostream &O, + TargetMachine &TM); + MachineCodeEmitter *AddMachOWriter(FunctionPassManager &FPM, std::ostream &O, + TargetMachine &TM); + +} // end llvm namespace + +#endif // LLVM_CODEGEN_FILEWRITERS_H diff --git a/include/llvm/CodeGen/IntrinsicLowering.h b/include/llvm/CodeGen/IntrinsicLowering.h new file mode 100644 index 0000000..bff1b39 --- /dev/null +++ b/include/llvm/CodeGen/IntrinsicLowering.h @@ -0,0 +1,50 @@ +//===-- IntrinsicLowering.h - Intrinsic Function Lowering -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the IntrinsicLowering interface. This interface allows +// addition of domain-specific or front-end specific intrinsics to LLVM without +// having to modify all of the C backend or interpreter. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_INTRINSICLOWERING_H +#define LLVM_CODEGEN_INTRINSICLOWERING_H + +#include "llvm/Intrinsics.h" + +namespace llvm { + class CallInst; + class Module; + class TargetData; + + class IntrinsicLowering { + const TargetData& TD; + public: + explicit IntrinsicLowering(const TargetData &td) : TD(td) {} + + /// AddPrototypes - This method, if called, causes all of the prototypes + /// that might be needed by an intrinsic lowering implementation to be + /// inserted into the module specified. + void AddPrototypes(Module &M); + + /// LowerIntrinsicCall - This method replaces a call with the LLVM function + /// which should be used to implement the specified intrinsic function call. + /// If an intrinsic function must be implemented by the code generator + /// (such as va_start), this function should print a message and abort. + /// + /// Otherwise, if an intrinsic function call can be lowered, the code to + /// implement it (often a call to a non-intrinsic function) is inserted + /// _after_ the call instruction and the call is deleted. The caller must + /// be capable of handling this kind of change. + /// + void LowerIntrinsicCall(CallInst *CI); + }; +} + +#endif diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h new file mode 100644 index 0000000..15021c1 --- /dev/null +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -0,0 +1,48 @@ +//===- llvm/Codegen/LinkAllCodegenComponents.h ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by James M. Laskey and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file pulls in all codegen related passes for tools like lli and +// llc that need this functionality. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LINKALLCODEGENCOMPONENTS_H +#define LLVM_CODEGEN_LINKALLCODEGENCOMPONENTS_H + +#include "llvm/CodeGen/Passes.h" +#include "llvm/CodeGen/ScheduleDAG.h" + +namespace { + struct ForceCodegenLinking { + ForceCodegenLinking() { + // We must reference the passes in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + (void) llvm::createSimpleRegisterAllocator(); + (void) llvm::createLocalRegisterAllocator(); + (void) llvm::createBigBlockRegisterAllocator(); + (void) llvm::createLinearScanRegisterAllocator(); + + (void) llvm::createBFS_DAGScheduler(NULL, NULL, NULL); + (void) llvm::createSimpleDAGScheduler(NULL, NULL, NULL); + (void) llvm::createNoItinsDAGScheduler(NULL, NULL, NULL); + (void) llvm::createBURRListDAGScheduler(NULL, NULL, NULL); + (void) llvm::createTDRRListDAGScheduler(NULL, NULL, NULL); + (void) llvm::createTDListDAGScheduler(NULL, NULL, NULL); + (void) llvm::createDefaultScheduler(NULL, NULL, NULL); + + } + } ForceCodegenLinking; // Force link by creating a global definition. +} + +#endif diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h new file mode 100644 index 0000000..1912d64 --- /dev/null +++ b/include/llvm/CodeGen/LiveInterval.h @@ -0,0 +1,287 @@ +//===-- llvm/CodeGen/LiveInterval.h - Interval representation ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the LiveRange and LiveInterval classes. Given some +// numbering of each the machine instructions an interval [i, j) is said to be a +// live interval for register v if there is no instruction with number j' > j +// such that v is live at j' and there is no instruction with number i' < i such +// that v is live at i'. In this implementation intervals can have holes, +// i.e. an interval might look like [1,20), [50,65), [1000,1001). Each +// individual range is represented as an instance of LiveRange, and the whole +// interval is represented as an instance of LiveInterval. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVEINTERVAL_H +#define LLVM_CODEGEN_LIVEINTERVAL_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Streams.h" +#include <iosfwd> +#include <vector> +#include <cassert> + +namespace llvm { + class MachineInstr; + class MRegisterInfo; + + /// LiveRange structure - This represents a simple register range in the + /// program, with an inclusive start point and an exclusive end point. + /// These ranges are rendered as [start,end). + struct LiveRange { + unsigned start; // Start point of the interval (inclusive) + unsigned end; // End point of the interval (exclusive) + unsigned ValId; // identifier for the value contained in this interval. + + LiveRange(unsigned S, unsigned E, unsigned V) : start(S), end(E), ValId(V) { + assert(S < E && "Cannot create empty or backwards range"); + } + + /// contains - Return true if the index is covered by this range. + /// + bool contains(unsigned I) const { + return start <= I && I < end; + } + + bool operator<(const LiveRange &LR) const { + return start < LR.start || (start == LR.start && end < LR.end); + } + bool operator==(const LiveRange &LR) const { + return start == LR.start && end == LR.end; + } + + void dump() const; + void print(std::ostream &os) const; + void print(std::ostream *os) const { if (os) print(*os); } + + private: + LiveRange(); // DO NOT IMPLEMENT + }; + + std::ostream& operator<<(std::ostream& os, const LiveRange &LR); + + + inline bool operator<(unsigned V, const LiveRange &LR) { + return V < LR.start; + } + + inline bool operator<(const LiveRange &LR, unsigned V) { + return LR.start < V; + } + + /// LiveInterval - This class represents some number of live ranges for a + /// register or value. This class also contains a bit of register allocator + /// state. + struct LiveInterval { + typedef SmallVector<LiveRange,4> Ranges; + unsigned reg; // the register of this interval + unsigned preference; // preferred register to allocate for this interval + float weight; // weight of this interval + MachineInstr* remat; // definition if the definition rematerializable + Ranges ranges; // the ranges in which this register is live + private: + /// ValueNumberInfo - If this value number is not defined by a copy, this + /// holds ~0,x. If the value number is not in use, it contains ~1,x to + /// indicate that the value # is not used. If the val# is defined by a + /// copy, the first entry is the instruction # of the copy, and the second + /// is the register number copied from. + SmallVector<std::pair<unsigned,unsigned>, 4> ValueNumberInfo; + public: + + LiveInterval(unsigned Reg, float Weight) + : reg(Reg), preference(0), weight(Weight), remat(NULL) { + } + + typedef Ranges::iterator iterator; + iterator begin() { return ranges.begin(); } + iterator end() { return ranges.end(); } + + typedef Ranges::const_iterator const_iterator; + const_iterator begin() const { return ranges.begin(); } + const_iterator end() const { return ranges.end(); } + + + /// advanceTo - Advance the specified iterator to point to the LiveRange + /// containing the specified position, or end() if the position is past the + /// end of the interval. If no LiveRange contains this position, but the + /// position is in a hole, this method returns an iterator pointing the the + /// LiveRange immediately after the hole. + iterator advanceTo(iterator I, unsigned Pos) { + if (Pos >= endNumber()) + return end(); + while (I->end <= Pos) ++I; + return I; + } + + void swap(LiveInterval& other) { + std::swap(reg, other.reg); + std::swap(weight, other.weight); + std::swap(remat, other.remat); + std::swap(ranges, other.ranges); + std::swap(ValueNumberInfo, other.ValueNumberInfo); + } + + bool containsOneValue() const { return ValueNumberInfo.size() == 1; } + + unsigned getNumValNums() const { return ValueNumberInfo.size(); } + + /// getNextValue - Create a new value number and return it. MIIdx specifies + /// the instruction that defines the value number. + unsigned getNextValue(unsigned MIIdx, unsigned SrcReg) { + ValueNumberInfo.push_back(std::make_pair(MIIdx, SrcReg)); + return ValueNumberInfo.size()-1; + } + + /// getInstForValNum - Return the machine instruction index that defines the + /// specified value number. + unsigned getInstForValNum(unsigned ValNo) const { + //assert(ValNo < ValueNumberInfo.size()); + return ValueNumberInfo[ValNo].first; + } + + unsigned getSrcRegForValNum(unsigned ValNo) const { + //assert(ValNo < ValueNumberInfo.size()); + if (ValueNumberInfo[ValNo].first < ~2U) + return ValueNumberInfo[ValNo].second; + return 0; + } + + std::pair<unsigned, unsigned> getValNumInfo(unsigned ValNo) const { + //assert(ValNo < ValueNumberInfo.size()); + return ValueNumberInfo[ValNo]; + } + + /// setValueNumberInfo - Change the value number info for the specified + /// value number. + void setValueNumberInfo(unsigned ValNo, + const std::pair<unsigned, unsigned> &I){ + ValueNumberInfo[ValNo] = I; + } + + /// MergeValueNumberInto - This method is called when two value nubmers + /// are found to be equivalent. This eliminates V1, replacing all + /// LiveRanges with the V1 value number with the V2 value number. This can + /// cause merging of V1/V2 values numbers and compaction of the value space. + void MergeValueNumberInto(unsigned V1, unsigned V2); + + /// MergeInClobberRanges - For any live ranges that are not defined in the + /// current interval, but are defined in the Clobbers interval, mark them + /// used with an unknown definition value. + void MergeInClobberRanges(const LiveInterval &Clobbers); + + + /// MergeRangesInAsValue - Merge all of the intervals in RHS into this live + /// interval as the specified value number. The LiveRanges in RHS are + /// allowed to overlap with LiveRanges in the current interval, but only if + /// the overlapping LiveRanges have the specified value number. + void MergeRangesInAsValue(const LiveInterval &RHS, unsigned LHSValNo); + + bool empty() const { return ranges.empty(); } + + /// beginNumber - Return the lowest numbered slot covered by interval. + unsigned beginNumber() const { + assert(!empty() && "empty interval for register"); + return ranges.front().start; + } + + /// endNumber - return the maximum point of the interval of the whole, + /// exclusive. + unsigned endNumber() const { + assert(!empty() && "empty interval for register"); + return ranges.back().end; + } + + bool expiredAt(unsigned index) const { + return index >= endNumber(); + } + + bool liveAt(unsigned index) const; + + /// getLiveRangeContaining - Return the live range that contains the + /// specified index, or null if there is none. + const LiveRange *getLiveRangeContaining(unsigned Idx) const { + const_iterator I = FindLiveRangeContaining(Idx); + return I == end() ? 0 : &*I; + } + + /// FindLiveRangeContaining - Return an iterator to the live range that + /// contains the specified index, or end() if there is none. + const_iterator FindLiveRangeContaining(unsigned Idx) const; + + /// FindLiveRangeContaining - Return an iterator to the live range that + /// contains the specified index, or end() if there is none. + iterator FindLiveRangeContaining(unsigned Idx); + + /// getOverlapingRanges - Given another live interval which is defined as a + /// copy from this one, return a list of all of the live ranges where the + /// two overlap and have different value numbers. + void getOverlapingRanges(const LiveInterval &Other, unsigned CopyIdx, + std::vector<LiveRange*> &Ranges); + + /// overlaps - Return true if the intersection of the two live intervals is + /// not empty. + bool overlaps(const LiveInterval& other) const { + return overlapsFrom(other, other.begin()); + } + + /// overlapsFrom - Return true if the intersection of the two live intervals + /// is not empty. The specified iterator is a hint that we can begin + /// scanning the Other interval starting at I. + bool overlapsFrom(const LiveInterval& other, const_iterator I) const; + + /// addRange - Add the specified LiveRange to this interval, merging + /// intervals as appropriate. This returns an iterator to the inserted live + /// range (which may have grown since it was inserted. + void addRange(LiveRange LR) { + addRangeFrom(LR, ranges.begin()); + } + + /// join - Join two live intervals (this, and other) together. This applies + /// mappings to the value numbers in the LHS/RHS intervals as specified. If + /// the intervals are not joinable, this aborts. + void join(LiveInterval &Other, int *ValNoAssignments, + int *RHSValNoAssignments, + SmallVector<std::pair<unsigned,unsigned>,16> &NewValueNumberInfo); + + /// removeRange - Remove the specified range from this interval. Note that + /// the range must already be in this interval in its entirety. + void removeRange(unsigned Start, unsigned End); + + void removeRange(LiveRange LR) { + removeRange(LR.start, LR.end); + } + + /// getSize - Returns the sum of sizes of all the LiveRange's. + /// + unsigned getSize() const; + + bool operator<(const LiveInterval& other) const { + return beginNumber() < other.beginNumber(); + } + + void print(std::ostream &OS, const MRegisterInfo *MRI = 0) const; + void print(std::ostream *OS, const MRegisterInfo *MRI = 0) const { + if (OS) print(*OS, MRI); + } + void dump() const; + + private: + Ranges::iterator addRangeFrom(LiveRange LR, Ranges::iterator From); + void extendIntervalEndTo(Ranges::iterator I, unsigned NewEnd); + Ranges::iterator extendIntervalStartTo(Ranges::iterator I, unsigned NewStr); + LiveInterval& operator=(const LiveInterval& rhs); // DO NOT IMPLEMENT + }; + + inline std::ostream &operator<<(std::ostream &OS, const LiveInterval &LI) { + LI.print(OS); + return OS; + } +} + +#endif diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h new file mode 100644 index 0000000..4783df4 --- /dev/null +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -0,0 +1,235 @@ +//===-- LiveIntervalAnalysis.h - Live Interval Analysis ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the LiveInterval analysis pass. Given some numbering of +// each the machine instructions (in this implemention depth-first order) an +// interval [i, j) is said to be a live interval for register v if there is no +// instruction with number j' > j such that v is live at j' abd there is no +// instruction with number i' < i such that v is live at i'. In this +// implementation intervals can have holes, i.e. an interval might look like +// [1,20), [50,65), [1000,1001). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H +#define LLVM_CODEGEN_LIVEINTERVAL_ANALYSIS_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/LiveInterval.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IndexedMap.h" + +namespace llvm { + + class LiveVariables; + class MRegisterInfo; + class TargetInstrInfo; + class TargetRegisterClass; + class VirtRegMap; + + class LiveIntervals : public MachineFunctionPass { + MachineFunction* mf_; + const TargetMachine* tm_; + const MRegisterInfo* mri_; + const TargetInstrInfo* tii_; + LiveVariables* lv_; + + /// MBB2IdxMap - The index of the first instruction in the specified basic + /// block. + std::vector<unsigned> MBB2IdxMap; + + typedef std::map<MachineInstr*, unsigned> Mi2IndexMap; + Mi2IndexMap mi2iMap_; + + typedef std::vector<MachineInstr*> Index2MiMap; + Index2MiMap i2miMap_; + + typedef std::map<unsigned, LiveInterval> Reg2IntervalMap; + Reg2IntervalMap r2iMap_; + + BitVector allocatableRegs_; + + public: + static char ID; // Pass identification, replacement for typeid + LiveIntervals() : MachineFunctionPass((intptr_t)&ID) {} + + struct InstrSlots { + enum { + LOAD = 0, + USE = 1, + DEF = 2, + STORE = 3, + NUM = 4 + }; + }; + + static unsigned getBaseIndex(unsigned index) { + return index - (index % InstrSlots::NUM); + } + static unsigned getBoundaryIndex(unsigned index) { + return getBaseIndex(index + InstrSlots::NUM - 1); + } + static unsigned getLoadIndex(unsigned index) { + return getBaseIndex(index) + InstrSlots::LOAD; + } + static unsigned getUseIndex(unsigned index) { + return getBaseIndex(index) + InstrSlots::USE; + } + static unsigned getDefIndex(unsigned index) { + return getBaseIndex(index) + InstrSlots::DEF; + } + static unsigned getStoreIndex(unsigned index) { + return getBaseIndex(index) + InstrSlots::STORE; + } + + typedef Reg2IntervalMap::iterator iterator; + typedef Reg2IntervalMap::const_iterator const_iterator; + const_iterator begin() const { return r2iMap_.begin(); } + const_iterator end() const { return r2iMap_.end(); } + iterator begin() { return r2iMap_.begin(); } + iterator end() { return r2iMap_.end(); } + unsigned getNumIntervals() const { return r2iMap_.size(); } + + LiveInterval &getInterval(unsigned reg) { + Reg2IntervalMap::iterator I = r2iMap_.find(reg); + assert(I != r2iMap_.end() && "Interval does not exist for register"); + return I->second; + } + + const LiveInterval &getInterval(unsigned reg) const { + Reg2IntervalMap::const_iterator I = r2iMap_.find(reg); + assert(I != r2iMap_.end() && "Interval does not exist for register"); + return I->second; + } + + bool hasInterval(unsigned reg) const { + return r2iMap_.count(reg); + } + + /// getMBBStartIdx - Return the base index of the first instruction in the + /// specified MachineBasicBlock. + unsigned getMBBStartIdx(MachineBasicBlock *MBB) const { + return getMBBStartIdx(MBB->getNumber()); + } + + unsigned getMBBStartIdx(unsigned MBBNo) const { + assert(MBBNo < MBB2IdxMap.size() && "Invalid MBB number!"); + return MBB2IdxMap[MBBNo]; + } + + /// getInstructionIndex - returns the base index of instr + unsigned getInstructionIndex(MachineInstr* instr) const { + Mi2IndexMap::const_iterator it = mi2iMap_.find(instr); + assert(it != mi2iMap_.end() && "Invalid instruction!"); + return it->second; + } + + /// getInstructionFromIndex - given an index in any slot of an + /// instruction return a pointer the instruction + MachineInstr* getInstructionFromIndex(unsigned index) const { + index /= InstrSlots::NUM; // convert index to vector index + assert(index < i2miMap_.size() && + "index does not correspond to an instruction"); + return i2miMap_[index]; + } + + // Interval creation + + LiveInterval &getOrCreateInterval(unsigned reg) { + Reg2IntervalMap::iterator I = r2iMap_.find(reg); + if (I == r2iMap_.end()) + I = r2iMap_.insert(I, std::make_pair(reg, createInterval(reg))); + return I->second; + } + + /// CreateNewLiveInterval - Create a new live interval with the given live + /// ranges. The new live interval will have an infinite spill weight. + LiveInterval &CreateNewLiveInterval(const LiveInterval *LI, + const std::vector<LiveRange> &LRs); + + std::vector<LiveInterval*> addIntervalsForSpills(const LiveInterval& i, + VirtRegMap& vrm, + int slot); + + // Interval removal + + void removeInterval(unsigned Reg) { + r2iMap_.erase(Reg); + } + + /// isRemoved - returns true if the specified machine instr has been + /// removed. + bool isRemoved(MachineInstr* instr) const { + return !mi2iMap_.count(instr); + } + + /// RemoveMachineInstrFromMaps - This marks the specified machine instr as + /// deleted. + void RemoveMachineInstrFromMaps(MachineInstr *MI) { + // remove index -> MachineInstr and + // MachineInstr -> index mappings + Mi2IndexMap::iterator mi2i = mi2iMap_.find(MI); + if (mi2i != mi2iMap_.end()) { + i2miMap_[mi2i->second/InstrSlots::NUM] = 0; + mi2iMap_.erase(mi2i); + } + } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void releaseMemory(); + + /// runOnMachineFunction - pass entry point + virtual bool runOnMachineFunction(MachineFunction&); + + /// print - Implement the dump method. + virtual void print(std::ostream &O, const Module* = 0) const; + void print(std::ostream *O, const Module* M = 0) const { + if (O) print(*O, M); + } + + private: + /// computeIntervals - Compute live intervals. + void computeIntervals(); + + /// handleRegisterDef - update intervals for a register def + /// (calls handlePhysicalRegisterDef and + /// handleVirtualRegisterDef) + void handleRegisterDef(MachineBasicBlock *MBB, + MachineBasicBlock::iterator MI, unsigned MIIdx, + unsigned reg); + + /// handleVirtualRegisterDef - update intervals for a virtual + /// register def + void handleVirtualRegisterDef(MachineBasicBlock *MBB, + MachineBasicBlock::iterator MI, + unsigned MIIdx, + LiveInterval& interval); + + /// handlePhysicalRegisterDef - update intervals for a physical register + /// def. + void handlePhysicalRegisterDef(MachineBasicBlock* mbb, + MachineBasicBlock::iterator mi, + unsigned MIIdx, + LiveInterval &interval, + unsigned SrcReg); + + /// handleLiveInRegister - Create interval for a livein register. + void handleLiveInRegister(MachineBasicBlock* mbb, + unsigned MIIdx, + LiveInterval &interval, bool isAlias = false); + + static LiveInterval createInterval(unsigned Reg); + + void printRegName(unsigned reg) const; + }; + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/LiveVariables.h b/include/llvm/CodeGen/LiveVariables.h new file mode 100644 index 0000000..ec01556 --- /dev/null +++ b/include/llvm/CodeGen/LiveVariables.h @@ -0,0 +1,304 @@ +//===-- llvm/CodeGen/LiveVariables.h - Live Variable Analysis ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the LiveVariable analysis pass. For each machine +// instruction in the function, this pass calculates the set of registers that +// are immediately dead after the instruction (i.e., the instruction calculates +// the value, but it is never used) and the set of registers that are used by +// the instruction, but are never used after the instruction (i.e., they are +// killed). +// +// This class computes live variables using are sparse implementation based on +// the machine code SSA form. This class computes live variable information for +// each virtual and _register allocatable_ physical register in a function. It +// uses the dominance properties of SSA form to efficiently compute live +// variables for virtual registers, and assumes that physical registers are only +// live within a single basic block (allowing it to do a single local analysis +// to resolve physical register lifetimes in each basic block). If a physical +// register is not register allocatable, it is not tracked. This is useful for +// things like the stack pointer and condition codes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_LIVEVARIABLES_H +#define LLVM_CODEGEN_LIVEVARIABLES_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include <map> + +namespace llvm { + +class MRegisterInfo; + +class LiveVariables : public MachineFunctionPass { +public: + static char ID; // Pass identification, replacement for typeid + LiveVariables() : MachineFunctionPass((intptr_t)&ID) {} + + /// VarInfo - This represents the regions where a virtual register is live in + /// the program. We represent this with three different pieces of + /// information: the instruction that uniquely defines the value, the set of + /// blocks the instruction is live into and live out of, and the set of + /// non-phi instructions that are the last users of the value. + /// + /// In the common case where a value is defined and killed in the same block, + /// DefInst is the defining inst, there is one killing instruction, and + /// AliveBlocks is empty. + /// + /// Otherwise, the value is live out of the block. If the value is live + /// across any blocks, these blocks are listed in AliveBlocks. Blocks where + /// the liveness range ends are not included in AliveBlocks, instead being + /// captured by the Kills set. In these blocks, the value is live into the + /// block (unless the value is defined and killed in the same block) and lives + /// until the specified instruction. Note that there cannot ever be a value + /// whose Kills set contains two instructions from the same basic block. + /// + /// PHI nodes complicate things a bit. If a PHI node is the last user of a + /// value in one of its predecessor blocks, it is not listed in the kills set, + /// but does include the predecessor block in the AliveBlocks set (unless that + /// block also defines the value). This leads to the (perfectly sensical) + /// situation where a value is defined in a block, and the last use is a phi + /// node in the successor. In this case, DefInst will be the defining + /// instruction, AliveBlocks is empty (the value is not live across any + /// blocks) and Kills is empty (phi nodes are not included). This is sensical + /// because the value must be live to the end of the block, but is not live in + /// any successor blocks. + struct VarInfo { + /// DefInst - The machine instruction that defines this register. + /// + MachineInstr *DefInst; + + /// AliveBlocks - Set of blocks of which this value is alive completely + /// through. This is a bit set which uses the basic block number as an + /// index. + /// + BitVector AliveBlocks; + + /// NumUses - Number of uses of this register across the entire function. + /// + unsigned NumUses; + + /// Kills - List of MachineInstruction's which are the last use of this + /// virtual register (kill it) in their basic block. + /// + std::vector<MachineInstr*> Kills; + + VarInfo() : DefInst(0), NumUses(0) {} + + /// removeKill - Delete a kill corresponding to the specified + /// machine instruction. Returns true if there was a kill + /// corresponding to this instruction, false otherwise. + bool removeKill(MachineInstr *MI) { + for (std::vector<MachineInstr*>::iterator i = Kills.begin(), + e = Kills.end(); i != e; ++i) + if (*i == MI) { + Kills.erase(i); + return true; + } + return false; + } + + void dump() const; + }; + +private: + /// VirtRegInfo - This list is a mapping from virtual register number to + /// variable information. FirstVirtualRegister is subtracted from the virtual + /// register number before indexing into this list. + /// + std::vector<VarInfo> VirtRegInfo; + + /// ReservedRegisters - This vector keeps track of which registers + /// are reserved register which are not allocatable by the target machine. + /// We can not track liveness for values that are in this set. + /// + BitVector ReservedRegisters; + +private: // Intermediate data structures + MachineFunction *MF; + + const MRegisterInfo *RegInfo; + + // PhysRegInfo - Keep track of which instruction was the last def/use of a + // physical register. This is a purely local property, because all physical + // register references as presumed dead across basic blocks. + MachineInstr **PhysRegInfo; + + // PhysRegUsed - Keep track whether the physical register has been used after + // its last definition. This is local property. + bool *PhysRegUsed; + + // PhysRegPartUse - Keep track of which instruction was the last partial use + // of a physical register (e.g. on X86 a def of EAX followed by a use of AX). + // This is a purely local property. + MachineInstr **PhysRegPartUse; + + // PhysRegPartDef - Keep track of a list of instructions which "partially" + // defined the physical register (e.g. on X86 AX partially defines EAX). + // These are turned into use/mod/write if there is a use of the register + // later in the same block. This is local property. + SmallVector<MachineInstr*, 4> *PhysRegPartDef; + + SmallVector<unsigned, 4> *PHIVarInfo; + + /// addRegisterKilled - We have determined MI kills a register. Look for the + /// operand that uses it and mark it as IsKill. If AddIfNotFound is true, + /// add a implicit operand if it's not found. Returns true if the operand + /// exists / is added. + bool addRegisterKilled(unsigned IncomingReg, MachineInstr *MI, + bool AddIfNotFound = false); + + /// addRegisterDead - We have determined MI defined a register without a use. + /// Look for the operand that defines it and mark it as IsDead. If + /// AddIfNotFound is true, add a implicit operand if it's not found. Returns + /// true if the operand exists / is added. + bool addRegisterDead(unsigned IncomingReg, MachineInstr *MI, + bool AddIfNotFound = false); + + void addRegisterKills(unsigned Reg, MachineInstr *MI, + SmallSet<unsigned, 4> &SubKills); + + /// HandlePhysRegKill - Add kills of Reg and its sub-registers to the + /// uses. Pay special attention to the sub-register uses which may come below + /// the last use of the whole register. + bool HandlePhysRegKill(unsigned Reg, MachineInstr *MI, + SmallSet<unsigned, 4> &SubKills); + bool HandlePhysRegKill(unsigned Reg, MachineInstr *MI); + void HandlePhysRegUse(unsigned Reg, MachineInstr *MI); + void HandlePhysRegDef(unsigned Reg, MachineInstr *MI); + + /// analyzePHINodes - Gather information about the PHI nodes in here. In + /// particular, we want to map the variable information of a virtual + /// register which is used in a PHI node. We map that to the BB the vreg + /// is coming from. + void analyzePHINodes(const MachineFunction& Fn); +public: + + virtual bool runOnMachineFunction(MachineFunction &MF); + + /// KillsRegister - Return true if the specified instruction kills the + /// specified register. + bool KillsRegister(MachineInstr *MI, unsigned Reg) const; + + /// RegisterDefIsDead - Return true if the specified instruction defines the + /// specified register, but that definition is dead. + bool RegisterDefIsDead(MachineInstr *MI, unsigned Reg) const; + + /// ModifiesRegister - Return true if the specified instruction modifies the + /// specified register. + bool ModifiesRegister(MachineInstr *MI, unsigned Reg) const; + + //===--------------------------------------------------------------------===// + // API to update live variable information + + /// instructionChanged - When the address of an instruction changes, this + /// method should be called so that live variables can update its internal + /// data structures. This removes the records for OldMI, transfering them to + /// the records for NewMI. + void instructionChanged(MachineInstr *OldMI, MachineInstr *NewMI); + + /// addVirtualRegisterKilled - Add information about the fact that the + /// specified register is killed after being used by the specified + /// instruction. If AddIfNotFound is true, add a implicit operand if it's + /// not found. + void addVirtualRegisterKilled(unsigned IncomingReg, MachineInstr *MI, + bool AddIfNotFound = false) { + if (addRegisterKilled(IncomingReg, MI, AddIfNotFound)) + getVarInfo(IncomingReg).Kills.push_back(MI); + } + + /// removeVirtualRegisterKilled - Remove the specified virtual + /// register from the live variable information. Returns true if the + /// variable was marked as killed by the specified instruction, + /// false otherwise. + bool removeVirtualRegisterKilled(unsigned reg, + MachineBasicBlock *MBB, + MachineInstr *MI) { + if (!getVarInfo(reg).removeKill(MI)) + return false; + + bool Removed = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isUse() && MO.getReg() == reg) { + MO.unsetIsKill(); + Removed = true; + break; + } + } + + assert(Removed && "Register is not used by this instruction!"); + return true; + } + + /// removeVirtualRegistersKilled - Remove all killed info for the specified + /// instruction. + void removeVirtualRegistersKilled(MachineInstr *MI); + + /// addVirtualRegisterDead - Add information about the fact that the specified + /// register is dead after being used by the specified instruction. If + /// AddIfNotFound is true, add a implicit operand if it's not found. + void addVirtualRegisterDead(unsigned IncomingReg, MachineInstr *MI, + bool AddIfNotFound = false) { + if (addRegisterDead(IncomingReg, MI, AddIfNotFound)) + getVarInfo(IncomingReg).Kills.push_back(MI); + } + + /// removeVirtualRegisterDead - Remove the specified virtual + /// register from the live variable information. Returns true if the + /// variable was marked dead at the specified instruction, false + /// otherwise. + bool removeVirtualRegisterDead(unsigned reg, + MachineBasicBlock *MBB, + MachineInstr *MI) { + if (!getVarInfo(reg).removeKill(MI)) + return false; + + bool Removed = false; + for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) { + MachineOperand &MO = MI->getOperand(i); + if (MO.isReg() && MO.isDef() && MO.getReg() == reg) { + MO.unsetIsDead(); + Removed = true; + break; + } + } + assert(Removed && "Register is not defined by this instruction!"); + return true; + } + + /// removeVirtualRegistersDead - Remove all of the dead registers for the + /// specified instruction from the live variable information. + void removeVirtualRegistersDead(MachineInstr *MI); + + virtual void getAnalysisUsage(AnalysisUsage &AU) const { + AU.setPreservesAll(); + } + + virtual void releaseMemory() { + VirtRegInfo.clear(); + } + + /// getVarInfo - Return the VarInfo structure for the specified VIRTUAL + /// register. + VarInfo &getVarInfo(unsigned RegIdx); + + void MarkVirtRegAliveInBlock(VarInfo &VRInfo, MachineBasicBlock *BB); + void MarkVirtRegAliveInBlock(VarInfo &VRInfo, MachineBasicBlock *BB, + std::vector<MachineBasicBlock*> &WorkList); + void HandleVirtRegUse(VarInfo &VRInfo, MachineBasicBlock *MBB, + MachineInstr *MI); +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/MachORelocation.h b/include/llvm/CodeGen/MachORelocation.h new file mode 100644 index 0000000..6bf176d --- /dev/null +++ b/include/llvm/CodeGen/MachORelocation.h @@ -0,0 +1,54 @@ +//=== MachORelocation.h - Mach-O Relocation Info ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Bill Wendling and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the MachORelocation class. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CODEGEN_MACHO_RELOCATION_H +#define LLVM_CODEGEN_MACHO_RELOCATION_H + +namespace llvm { + + /// MachORelocation - This struct contains information about each relocation + /// that needs to be emitted to the file. + /// see <mach-o/reloc.h> + class MachORelocation { + uint32_t r_address; // offset in the section to what is being relocated + uint32_t r_symbolnum; // symbol index if r_extern == 1 else section index + bool r_pcrel; // was relocated pc-relative already + uint8_t r_length; // length = 2 ^ r_length + bool r_extern; // + uint8_t r_type; // if not 0, machine-specific relocation type. + bool r_scattered; // 1 = scattered, 0 = non-scattered + int32_t r_value; // the value the item to be relocated is referring + // to. + public: + uint32_t getPackedFields() const { + if (r_scattered) + return (1 << 31) | (r_pcrel << 30) | ((r_length & 3) << 28) | + ((r_type & 15) << 24) | (r_address & 0x00FFFFFF); + else + return (r_symbolnum << 8) | (r_pcrel << 7) | ((r_length & 3) << 5) | + (r_extern << 4) | (r_type & 15); + } + uint32_t getAddress() const { return r_scattered ? r_value : r_address; } + uint32_t getRawAddress() const { return r_address; } + + MachORelocation(uint32_t addr, uint32_t index, bool pcrel, uint8_t len, + bool ext, uint8_t type, bool scattered = false, + int32_t value = 0) : + r_address(addr), r_symbolnum(index), r_pcrel(pcrel), r_length(len), + r_extern(ext), r_type(type), r_scattered(scattered), r_value(value) {} + }; + +} // end llvm namespace + +#endif // LLVM_CODEGEN_MACHO_RELOCATION_H diff --git a/include/llvm/CodeGen/MachineBasicBlock.h b/include/llvm/CodeGen/MachineBasicBlock.h new file mode 100644 index 0000000..df6e5a3 --- /dev/null +++ b/include/llvm/CodeGen/MachineBasicBlock.h @@ -0,0 +1,371 @@ +//===-- llvm/CodeGen/MachineBasicBlock.h ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Collect the sequence of machine instructions for a basic block. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEBASICBLOCK_H +#define LLVM_CODEGEN_MACHINEBASICBLOCK_H + +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/ilist" +#include "llvm/Support/Streams.h" + +namespace llvm { + class MachineFunction; + +// ilist_traits +template <> +struct ilist_traits<MachineInstr> { +protected: + // this is only set by the MachineBasicBlock owning the ilist + friend class MachineBasicBlock; + MachineBasicBlock* parent; + +public: + ilist_traits<MachineInstr>() : parent(0) { } + + static MachineInstr* getPrev(MachineInstr* N) { return N->prev; } + static MachineInstr* getNext(MachineInstr* N) { return N->next; } + + static const MachineInstr* + getPrev(const MachineInstr* N) { return N->prev; } + + static const MachineInstr* + getNext(const MachineInstr* N) { return N->next; } + + static void setPrev(MachineInstr* N, MachineInstr* prev) { N->prev = prev; } + static void setNext(MachineInstr* N, MachineInstr* next) { N->next = next; } + + static MachineInstr* createSentinel(); + static void destroySentinel(MachineInstr *MI) { delete MI; } + void addNodeToList(MachineInstr* N); + void removeNodeFromList(MachineInstr* N); + void transferNodesFromList( + iplist<MachineInstr, ilist_traits<MachineInstr> >& toList, + ilist_iterator<MachineInstr> first, + ilist_iterator<MachineInstr> last); +}; + +class BasicBlock; + +class MachineBasicBlock { + typedef ilist<MachineInstr> Instructions; + Instructions Insts; + MachineBasicBlock *Prev, *Next; + const BasicBlock *BB; + int Number; + MachineFunction *Parent; + + /// Predecessors/Successors - Keep track of the predecessor / successor + /// basicblocks. + std::vector<MachineBasicBlock *> Predecessors; + std::vector<MachineBasicBlock *> Successors; + + /// LiveIns - Keep track of the physical registers that are livein of + /// the basicblock. + std::vector<unsigned> LiveIns; + + /// IsLandingPad - Indicate that this basic block is entered via an + /// exception handler. + bool IsLandingPad; + +public: + explicit MachineBasicBlock(const BasicBlock *bb = 0) : Prev(0), Next(0), + BB(bb), Number(-1), + Parent(0), + IsLandingPad(false) { + Insts.parent = this; + } + + ~MachineBasicBlock(); + + /// getBasicBlock - Return the LLVM basic block that this instance + /// corresponded to originally. + /// + const BasicBlock *getBasicBlock() const { return BB; } + + /// getParent - Return the MachineFunction containing this basic block. + /// + const MachineFunction *getParent() const { return Parent; } + MachineFunction *getParent() { return Parent; } + + typedef ilist<MachineInstr>::iterator iterator; + typedef ilist<MachineInstr>::const_iterator const_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + + unsigned size() const { return Insts.size(); } + bool empty() const { return Insts.empty(); } + + MachineInstr& front() { return Insts.front(); } + MachineInstr& back() { return Insts.back(); } + + iterator begin() { return Insts.begin(); } + const_iterator begin() const { return Insts.begin(); } + iterator end() { return Insts.end(); } + const_iterator end() const { return Insts.end(); } + reverse_iterator rbegin() { return Insts.rbegin(); } + const_reverse_iterator rbegin() const { return Insts.rbegin(); } + reverse_iterator rend () { return Insts.rend(); } + const_reverse_iterator rend () const { return Insts.rend(); } + + // Machine-CFG iterators + typedef std::vector<MachineBasicBlock *>::iterator pred_iterator; + typedef std::vector<MachineBasicBlock *>::const_iterator const_pred_iterator; + typedef std::vector<MachineBasicBlock *>::iterator succ_iterator; + typedef std::vector<MachineBasicBlock *>::const_iterator const_succ_iterator; + typedef std::vector<MachineBasicBlock *>::reverse_iterator + pred_reverse_iterator; + typedef std::vector<MachineBasicBlock *>::const_reverse_iterator + const_pred_reverse_iterator; + typedef std::vector<MachineBasicBlock *>::reverse_iterator + succ_reverse_iterator; + typedef std::vector<MachineBasicBlock *>::const_reverse_iterator + const_succ_reverse_iterator; + + pred_iterator pred_begin() { return Predecessors.begin(); } + const_pred_iterator pred_begin() const { return Predecessors.begin(); } + pred_iterator pred_end() { return Predecessors.end(); } + const_pred_iterator pred_end() const { return Predecessors.end(); } + pred_reverse_iterator pred_rbegin() + { return Predecessors.rbegin();} + const_pred_reverse_iterator pred_rbegin() const + { return Predecessors.rbegin();} + pred_reverse_iterator pred_rend() + { return Predecessors.rend(); } + const_pred_reverse_iterator pred_rend() const + { return Predecessors.rend(); } + unsigned pred_size() const { return Predecessors.size(); } + bool pred_empty() const { return Predecessors.empty(); } + succ_iterator succ_begin() { return Successors.begin(); } + const_succ_iterator succ_begin() const { return Successors.begin(); } + succ_iterator succ_end() { return Successors.end(); } + const_succ_iterator succ_end() const { return Successors.end(); } + succ_reverse_iterator succ_rbegin() + { return Successors.rbegin(); } + const_succ_reverse_iterator succ_rbegin() const + { return Successors.rbegin(); } + succ_reverse_iterator succ_rend() + { return Successors.rend(); } + const_succ_reverse_iterator succ_rend() const + { return Successors.rend(); } + unsigned succ_size() const { return Successors.size(); } + bool succ_empty() const { return Successors.empty(); } + + // LiveIn management methods. + + /// addLiveIn - Add the specified register as a live in. Note that it + /// is an error to add the same register to the same set more than once. + void addLiveIn(unsigned Reg) { LiveIns.push_back(Reg); } + + /// removeLiveIn - Remove the specified register from the live in set. + /// + void removeLiveIn(unsigned Reg); + + // Iteration support for live in sets. These sets are kept in sorted + // order by their register number. + typedef std::vector<unsigned>::iterator livein_iterator; + typedef std::vector<unsigned>::const_iterator const_livein_iterator; + livein_iterator livein_begin() { return LiveIns.begin(); } + const_livein_iterator livein_begin() const { return LiveIns.begin(); } + livein_iterator livein_end() { return LiveIns.end(); } + const_livein_iterator livein_end() const { return LiveIns.end(); } + bool livein_empty() const { return LiveIns.empty(); } + + /// isLandingPad - Returns true if the block is a landing pad. That is + /// this basic block is entered via an exception handler. + bool isLandingPad() const { return IsLandingPad; } + + /// setIsLandingPad - Indicates the block is a landing pad. That is + /// this basic block is entered via an exception handler. + void setIsLandingPad() { IsLandingPad = true; } + + // Code Layout methods. + + /// moveBefore/moveAfter - move 'this' block before or after the specified + /// block. This only moves the block, it does not modify the CFG or adjust + /// potential fall-throughs at the end of the block. + void moveBefore(MachineBasicBlock *NewAfter); + void moveAfter(MachineBasicBlock *NewBefore); + + // Machine-CFG mutators + + /// addSuccessor - Add succ as a successor of this MachineBasicBlock. + /// The Predecessors list of succ is automatically updated. + /// + void addSuccessor(MachineBasicBlock *succ); + + /// removeSuccessor - Remove successor from the successors list of this + /// MachineBasicBlock. The Predecessors list of succ is automatically updated. + /// + void removeSuccessor(MachineBasicBlock *succ); + + /// removeSuccessor - Remove specified successor from the successors list of + /// this MachineBasicBlock. The Predecessors list of succ is automatically + /// updated. Return the iterator to the element after the one removed. + /// + succ_iterator removeSuccessor(succ_iterator I); + + /// isSuccessor - Return true if the specified MBB is a successor of this + /// block. + bool isSuccessor(MachineBasicBlock *MBB) const; + + /// getFirstTerminator - returns an iterator to the first terminator + /// instruction of this basic block. If a terminator does not exist, + /// it returns end() + iterator getFirstTerminator(); + + void pop_front() { Insts.pop_front(); } + void pop_back() { Insts.pop_back(); } + void push_back(MachineInstr *MI) { Insts.push_back(MI); } + template<typename IT> + void insert(iterator I, IT S, IT E) { Insts.insert(I, S, E); } + iterator insert(iterator I, MachineInstr *M) { return Insts.insert(I, M); } + + // erase - Remove the specified element or range from the instruction list. + // These functions delete any instructions removed. + // + iterator erase(iterator I) { return Insts.erase(I); } + iterator erase(iterator I, iterator E) { return Insts.erase(I, E); } + MachineInstr *remove(MachineInstr *I) { return Insts.remove(I); } + void clear() { Insts.clear(); } + + /// splice - Take a block of instructions from MBB 'Other' in the range [From, + /// To), and insert them into this MBB right before 'where'. + void splice(iterator where, MachineBasicBlock *Other, iterator From, + iterator To) { + Insts.splice(where, Other->Insts, From, To); + } + + /// ReplaceUsesOfBlockWith - Given a machine basic block that branched to + /// 'Old', change the code and CFG so that it branches to 'New' instead. + void ReplaceUsesOfBlockWith(MachineBasicBlock *Old, MachineBasicBlock *New); + + /// CorrectExtraCFGEdges - Various pieces of code can cause excess edges in + /// the CFG to be inserted. If we have proven that MBB can only branch to + /// DestA and DestB, remove any other MBB successors from the CFG. DestA and + /// DestB can be null. Besides DestA and DestB, retain other edges leading + /// to LandingPads (currently there can be only one; we don't check or require + /// that here). Note it is possible that DestA and/or DestB are LandingPads. + bool CorrectExtraCFGEdges(MachineBasicBlock *DestA, + MachineBasicBlock *DestB, + bool isCond); + + // Debugging methods. + void dump() const; + void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + + /// getNumber - MachineBasicBlocks are uniquely numbered at the function + /// level, unless they're not in a MachineFunction yet, in which case this + /// will return -1. + /// + int getNumber() const { return Number; } + void setNumber(int N) { Number = N; } + +private: // Methods used to maintain doubly linked list of blocks... + friend struct ilist_traits<MachineBasicBlock>; + + MachineBasicBlock *getPrev() const { return Prev; } + MachineBasicBlock *getNext() const { return Next; } + void setPrev(MachineBasicBlock *P) { Prev = P; } + void setNext(MachineBasicBlock *N) { Next = N; } + + // Machine-CFG mutators + + /// addPredecessor - Remove pred as a predecessor of this MachineBasicBlock. + /// Don't do this unless you know what you're doing, because it doesn't + /// update pred's successors list. Use pred->addSuccessor instead. + /// + void addPredecessor(MachineBasicBlock *pred); + + /// removePredecessor - Remove pred as a predecessor of this + /// MachineBasicBlock. Don't do this unless you know what you're + /// doing, because it doesn't update pred's successors list. Use + /// pred->removeSuccessor instead. + /// + void removePredecessor(MachineBasicBlock *pred); +}; + +std::ostream& operator<<(std::ostream &OS, const MachineBasicBlock &MBB); + +//===--------------------------------------------------------------------===// +// GraphTraits specializations for machine basic block graphs (machine-CFGs) +//===--------------------------------------------------------------------===// + +// Provide specializations of GraphTraits to be able to treat a +// MachineFunction as a graph of MachineBasicBlocks... +// + +template <> struct GraphTraits<MachineBasicBlock *> { + typedef MachineBasicBlock NodeType; + typedef MachineBasicBlock::succ_iterator ChildIteratorType; + + static NodeType *getEntryNode(MachineBasicBlock *BB) { return BB; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->succ_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->succ_end(); + } +}; + +template <> struct GraphTraits<const MachineBasicBlock *> { + typedef const MachineBasicBlock NodeType; + typedef MachineBasicBlock::const_succ_iterator ChildIteratorType; + + static NodeType *getEntryNode(const MachineBasicBlock *BB) { return BB; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->succ_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->succ_end(); + } +}; + +// Provide specializations of GraphTraits to be able to treat a +// MachineFunction as a graph of MachineBasicBlocks... and to walk it +// in inverse order. Inverse order for a function is considered +// to be when traversing the predecessor edges of a MBB +// instead of the successor edges. +// +template <> struct GraphTraits<Inverse<MachineBasicBlock*> > { + typedef MachineBasicBlock NodeType; + typedef MachineBasicBlock::pred_iterator ChildIteratorType; + static NodeType *getEntryNode(Inverse<MachineBasicBlock *> G) { + return G.Graph; + } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->pred_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->pred_end(); + } +}; + +template <> struct GraphTraits<Inverse<const MachineBasicBlock*> > { + typedef const MachineBasicBlock NodeType; + typedef MachineBasicBlock::const_pred_iterator ChildIteratorType; + static NodeType *getEntryNode(Inverse<const MachineBasicBlock*> G) { + return G.Graph; + } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->pred_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->pred_end(); + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/MachineCodeEmitter.h b/include/llvm/CodeGen/MachineCodeEmitter.h new file mode 100644 index 0000000..018c5e5 --- /dev/null +++ b/include/llvm/CodeGen/MachineCodeEmitter.h @@ -0,0 +1,200 @@ +//===-- llvm/CodeGen/MachineCodeEmitter.h - Code emission -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines an abstract interface that is used by the machine code +// emission framework to output the code. This allows machine code emission to +// be separated from concerns such as resolution of call targets, and where the +// machine code will be written (memory or disk, f.e.). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINECODEEMITTER_H +#define LLVM_CODEGEN_MACHINECODEEMITTER_H + +#include "llvm/Support/DataTypes.h" +#include <vector> + +namespace llvm { + +class MachineBasicBlock; +class MachineConstantPool; +class MachineJumpTableInfo; +class MachineFunction; +class MachineRelocation; +class Value; +class GlobalValue; +class Function; + +/// MachineCodeEmitter - This class defines two sorts of methods: those for +/// emitting the actual bytes of machine code, and those for emitting auxillary +/// structures, such as jump tables, relocations, etc. +/// +/// Emission of machine code is complicated by the fact that we don't (in +/// general) know the size of the machine code that we're about to emit before +/// we emit it. As such, we preallocate a certain amount of memory, and set the +/// BufferBegin/BufferEnd pointers to the start and end of the buffer. As we +/// emit machine instructions, we advance the CurBufferPtr to indicate the +/// location of the next byte to emit. In the case of a buffer overflow (we +/// need to emit more machine code than we have allocated space for), the +/// CurBufferPtr will saturate to BufferEnd and ignore stores. Once the entire +/// function has been emitted, the overflow condition is checked, and if it has +/// occurred, more memory is allocated, and we reemit the code into it. +/// +class MachineCodeEmitter { +protected: + /// BufferBegin/BufferEnd - Pointers to the start and end of the memory + /// allocated for this code buffer. + unsigned char *BufferBegin, *BufferEnd; + + /// CurBufferPtr - Pointer to the next byte of memory to fill when emitting + /// code. This is guranteed to be in the range [BufferBegin,BufferEnd]. If + /// this pointer is at BufferEnd, it will never move due to code emission, and + /// all code emission requests will be ignored (this is the buffer overflow + /// condition). + unsigned char *CurBufferPtr; +public: + virtual ~MachineCodeEmitter() {} + + /// startFunction - This callback is invoked when the specified function is + /// about to be code generated. This initializes the BufferBegin/End/Ptr + /// fields. + /// + virtual void startFunction(MachineFunction &F) = 0; + + /// finishFunction - This callback is invoked when the specified function has + /// finished code generation. If a buffer overflow has occurred, this method + /// returns true (the callee is required to try again), otherwise it returns + /// false. + /// + virtual bool finishFunction(MachineFunction &F) = 0; + + /// startFunctionStub - This callback is invoked when the JIT needs the + /// address of a function that has not been code generated yet. The StubSize + /// specifies the total size required by the stub. Stubs are not allowed to + /// have constant pools, the can only use the other emitByte*/emitWord* + /// methods. + /// + virtual void startFunctionStub(unsigned StubSize, unsigned Alignment = 1) = 0; + + /// finishFunctionStub - This callback is invoked to terminate a function + /// stub. + /// + virtual void *finishFunctionStub(const Function *F) = 0; + + /// emitByte - This callback is invoked when a byte needs to be written to the + /// output stream. + /// + void emitByte(unsigned char B) { + if (CurBufferPtr != BufferEnd) + *CurBufferPtr++ = B; + } + + /// emitWordLE - This callback is invoked when a 32-bit word needs to be + /// written to the output stream in little-endian format. + /// + void emitWordLE(unsigned W) { + if (CurBufferPtr+4 <= BufferEnd) { + *CurBufferPtr++ = (unsigned char)(W >> 0); + *CurBufferPtr++ = (unsigned char)(W >> 8); + *CurBufferPtr++ = (unsigned char)(W >> 16); + *CurBufferPtr++ = (unsigned char)(W >> 24); + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitWordBE - This callback is invoked when a 32-bit word needs to be + /// written to the output stream in big-endian format. + /// + void emitWordBE(unsigned W) { + if (CurBufferPtr+4 <= BufferEnd) { + *CurBufferPtr++ = (unsigned char)(W >> 24); + *CurBufferPtr++ = (unsigned char)(W >> 16); + *CurBufferPtr++ = (unsigned char)(W >> 8); + *CurBufferPtr++ = (unsigned char)(W >> 0); + } else { + CurBufferPtr = BufferEnd; + } + } + + /// emitAlignment - Move the CurBufferPtr pointer up the the specified + /// alignment (saturated to BufferEnd of course). + void emitAlignment(unsigned Alignment) { + if (Alignment == 0) Alignment = 1; + // Move the current buffer ptr up to the specified alignment. + CurBufferPtr = + (unsigned char*)(((intptr_t)CurBufferPtr+Alignment-1) & + ~(intptr_t)(Alignment-1)); + if (CurBufferPtr > BufferEnd) + CurBufferPtr = BufferEnd; + } + + /// allocateSpace - Allocate a block of space in the current output buffer, + /// returning null (and setting conditions to indicate buffer overflow) on + /// failure. Alignment is the alignment in bytes of the buffer desired. + void *allocateSpace(intptr_t Size, unsigned Alignment) { + emitAlignment(Alignment); + void *Result = CurBufferPtr; + + // Allocate the space. + CurBufferPtr += Size; + + // Check for buffer overflow. + if (CurBufferPtr >= BufferEnd) { + CurBufferPtr = BufferEnd; + Result = 0; + } + return Result; + } + + /// StartMachineBasicBlock - This should be called by the target when a new + /// basic block is about to be emitted. This way the MCE knows where the + /// start of the block is, and can implement getMachineBasicBlockAddress. + virtual void StartMachineBasicBlock(MachineBasicBlock *MBB) = 0; + + /// getCurrentPCValue - This returns the address that the next emitted byte + /// will be output to. + /// + virtual intptr_t getCurrentPCValue() const { + return (intptr_t)CurBufferPtr; + } + + /// getCurrentPCOffset - Return the offset from the start of the emitted + /// buffer that we are currently writing to. + intptr_t getCurrentPCOffset() const { + return CurBufferPtr-BufferBegin; + } + + /// addRelocation - Whenever a relocatable address is needed, it should be + /// noted with this interface. + virtual void addRelocation(const MachineRelocation &MR) = 0; + + + /// FIXME: These should all be handled with relocations! + + /// getConstantPoolEntryAddress - Return the address of the 'Index' entry in + /// the constant pool that was last emitted with the emitConstantPool method. + /// + virtual intptr_t getConstantPoolEntryAddress(unsigned Index) const = 0; + + /// getJumpTableEntryAddress - Return the address of the jump table with index + /// 'Index' in the function that last called initJumpTableInfo. + /// + virtual intptr_t getJumpTableEntryAddress(unsigned Index) const = 0; + + /// getMachineBasicBlockAddress - Return the address of the specified + /// MachineBasicBlock, only usable after the label for the MBB has been + /// emitted. + /// + virtual intptr_t getMachineBasicBlockAddress(MachineBasicBlock *MBB) const= 0; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/MachineConstantPool.h b/include/llvm/CodeGen/MachineConstantPool.h new file mode 100644 index 0000000..1500053 --- /dev/null +++ b/include/llvm/CodeGen/MachineConstantPool.h @@ -0,0 +1,149 @@ +//===-- CodeGen/MachineConstantPool.h - Abstract Constant Pool --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file This file declares the MachineConstantPool class which is an abstract +/// constant pool to keep track of constants referenced by a function. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINECONSTANTPOOL_H +#define LLVM_CODEGEN_MACHINECONSTANTPOOL_H + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/Support/Streams.h" +#include <vector> +#include <iosfwd> + +namespace llvm { + +class AsmPrinter; +class Constant; +class TargetData; +class TargetMachine; +class MachineConstantPool; + +/// Abstract base class for all machine specific constantpool value subclasses. +/// +class MachineConstantPoolValue { + const Type *Ty; + +public: + explicit MachineConstantPoolValue(const Type *ty) : Ty(ty) {} + virtual ~MachineConstantPoolValue() {}; + + /// getType - get type of this MachineConstantPoolValue. + /// + inline const Type *getType() const { return Ty; } + + virtual int getExistingMachineCPValue(MachineConstantPool *CP, + unsigned Alignment) = 0; + + virtual void AddSelectionDAGCSEId(FoldingSetNodeID &ID) = 0; + + /// print - Implement operator<<... + /// + virtual void print(std::ostream &O) const = 0; + void print(std::ostream *O) const { if (O) print(*O); } +}; + +inline std::ostream &operator<<(std::ostream &OS, + const MachineConstantPoolValue &V) { + V.print(OS); + return OS; +} + +/// This class is a data container for one entry in a MachineConstantPool. +/// It contains a pointer to the value and an offset from the start of +/// the constant pool. +/// @brief An entry in a MachineConstantPool +class MachineConstantPoolEntry { +public: + /// The constant itself. + union { + Constant *ConstVal; + MachineConstantPoolValue *MachineCPVal; + } Val; + + /// The offset of the constant from the start of the pool. The top bit is set + /// when Val is a MachineConstantPoolValue. + unsigned Offset; + + MachineConstantPoolEntry(Constant *V, unsigned O) + : Offset(O) { + assert((int)Offset >= 0 && "Offset is too large"); + Val.ConstVal = V; + } + MachineConstantPoolEntry(MachineConstantPoolValue *V, unsigned O) + : Offset(O){ + assert((int)Offset >= 0 && "Offset is too large"); + Val.MachineCPVal = V; + Offset |= 1 << (sizeof(unsigned)*8-1); + } + + bool isMachineConstantPoolEntry() const { + return (int)Offset < 0; + } + + int getOffset() const { + return Offset & ~(1 << (sizeof(unsigned)*8-1)); + } + + const Type *getType() const; +}; + +/// The MachineConstantPool class keeps track of constants referenced by a +/// function which must be spilled to memory. This is used for constants which +/// are unable to be used directly as operands to instructions, which typically +/// include floating point and large integer constants. +/// +/// Instructions reference the address of these constant pool constants through +/// the use of MO_ConstantPoolIndex values. When emitting assembly or machine +/// code, these virtual address references are converted to refer to the +/// address of the function constant pool values. +/// @brief The machine constant pool. +class MachineConstantPool { + const TargetData *TD; ///< The machine's TargetData. + unsigned PoolAlignment; ///< The alignment for the pool. + std::vector<MachineConstantPoolEntry> Constants; ///< The pool of constants. +public: + /// @brief The only constructor. + MachineConstantPool(const TargetData *td) : TD(td), PoolAlignment(1) {} + ~MachineConstantPool(); + + /// getConstantPoolAlignment - Return the log2 of the alignment required by + /// the whole constant pool, of which the first element must be aligned. + unsigned getConstantPoolAlignment() const { return PoolAlignment; } + + /// getConstantPoolIndex - Create a new entry in the constant pool or return + /// an existing one. User must specify an alignment in bytes for the object. + unsigned getConstantPoolIndex(Constant *C, unsigned Alignment); + unsigned getConstantPoolIndex(MachineConstantPoolValue *V,unsigned Alignment); + + /// isEmpty - Return true if this constant pool contains no constants. + bool isEmpty() const { return Constants.empty(); } + + const std::vector<MachineConstantPoolEntry> &getConstants() const { + return Constants; + } + + /// print - Used by the MachineFunction printer to print information about + /// constant pool objects. Implemented in MachineFunction.cpp + /// + void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + + /// dump - Call print(std::cerr) to be called from the debugger. + /// + void dump() const; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h new file mode 100644 index 0000000..be481f7 --- /dev/null +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -0,0 +1,327 @@ +//===-- CodeGen/MachineFrameInfo.h - Abstract Stack Frame Rep. --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CODEGEN_MACHINEFRAMEINFO_H +#define LLVM_CODEGEN_MACHINEFRAMEINFO_H + +#include <vector> + +namespace llvm { +class TargetData; +class TargetRegisterClass; +class Type; +class MachineModuleInfo; +class MachineFunction; + +/// The CalleeSavedInfo class tracks the information need to locate where a +/// callee saved register in the current frame. +class CalleeSavedInfo { + +private: + unsigned Reg; + const TargetRegisterClass *RegClass; + int FrameIdx; + +public: + CalleeSavedInfo(unsigned R, const TargetRegisterClass *RC, int FI = 0) + : Reg(R) + , RegClass(RC) + , FrameIdx(FI) + {} + + // Accessors. + unsigned getReg() const { return Reg; } + const TargetRegisterClass *getRegClass() const { return RegClass; } + int getFrameIdx() const { return FrameIdx; } + void setFrameIdx(int FI) { FrameIdx = FI; } +}; + +/// The MachineFrameInfo class represents an abstract stack frame until +/// prolog/epilog code is inserted. This class is key to allowing stack frame +/// representation optimizations, such as frame pointer elimination. It also +/// allows more mundane (but still important) optimizations, such as reordering +/// of abstract objects on the stack frame. +/// +/// To support this, the class assigns unique integer identifiers to stack +/// objects requested clients. These identifiers are negative integers for +/// fixed stack objects (such as arguments passed on the stack) or positive +/// for objects that may be reordered. Instructions which refer to stack +/// objects use a special MO_FrameIndex operand to represent these frame +/// indexes. +/// +/// Because this class keeps track of all references to the stack frame, it +/// knows when a variable sized object is allocated on the stack. This is the +/// sole condition which prevents frame pointer elimination, which is an +/// important optimization on register-poor architectures. Because original +/// variable sized alloca's in the source program are the only source of +/// variable sized stack objects, it is safe to decide whether there will be +/// any variable sized objects before all stack objects are known (for +/// example, register allocator spill code never needs variable sized +/// objects). +/// +/// When prolog/epilog code emission is performed, the final stack frame is +/// built and the machine instructions are modified to refer to the actual +/// stack offsets of the object, eliminating all MO_FrameIndex operands from +/// the program. +/// +/// @brief Abstract Stack Frame Information +class MachineFrameInfo { + + // StackObject - Represent a single object allocated on the stack. + struct StackObject { + // The size of this object on the stack. 0 means a variable sized object + uint64_t Size; + + // Alignment - The required alignment of this stack slot. + unsigned Alignment; + + // SPOffset - The offset of this object from the stack pointer on entry to + // the function. This field has no meaning for a variable sized element. + int64_t SPOffset; + + StackObject(uint64_t Sz, unsigned Al, int64_t SP) + : Size(Sz), Alignment(Al), SPOffset(SP) {} + }; + + /// Objects - The list of stack objects allocated... + /// + std::vector<StackObject> Objects; + + /// NumFixedObjects - This contains the number of fixed objects contained on + /// the stack. Because fixed objects are stored at a negative index in the + /// Objects list, this is also the index to the 0th object in the list. + /// + unsigned NumFixedObjects; + + /// HasVarSizedObjects - This boolean keeps track of whether any variable + /// sized objects have been allocated yet. + /// + bool HasVarSizedObjects; + + /// StackSize - The prolog/epilog code inserter calculates the final stack + /// offsets for all of the fixed size objects, updating the Objects list + /// above. It then updates StackSize to contain the number of bytes that need + /// to be allocated on entry to the function. + /// + uint64_t StackSize; + + /// OffsetAdjustment - The amount that a frame offset needs to be adjusted to + /// have the actual offset from the stack/frame pointer. The calculation is + /// MFI->getObjectOffset(Index) + StackSize - TFI.getOffsetOfLocalArea() + + /// OffsetAdjustment. If OffsetAdjustment is zero (default) then offsets are + /// away from TOS. If OffsetAdjustment == StackSize then offsets are toward + /// TOS. + int OffsetAdjustment; + + /// MaxAlignment - The prolog/epilog code inserter may process objects + /// that require greater alignment than the default alignment the target + /// provides. To handle this, MaxAlignment is set to the maximum alignment + /// needed by the objects on the current frame. If this is greater than the + /// native alignment maintained by the compiler, dynamic alignment code will + /// be needed. + /// + unsigned MaxAlignment; + + /// HasCalls - Set to true if this function has any function calls. This is + /// only valid during and after prolog/epilog code insertion. + bool HasCalls; + + /// MaxCallFrameSize - This contains the size of the largest call frame if the + /// target uses frame setup/destroy pseudo instructions (as defined in the + /// TargetFrameInfo class). This information is important for frame pointer + /// elimination. If is only valid during and after prolog/epilog code + /// insertion. + /// + unsigned MaxCallFrameSize; + + /// CSInfo - The prolog/epilog code inserter fills in this vector with each + /// callee saved register saved in the frame. Beyond its use by the prolog/ + /// epilog code inserter, this data used for debug info and exception + /// handling. + std::vector<CalleeSavedInfo> CSInfo; + + /// MMI - This field is set (via setMachineModuleInfo) by a module info + /// consumer (ex. DwarfWriter) to indicate that frame layout information + /// should be acquired. Typically, it's the responsibility of the target's + /// MRegisterInfo prologue/epilogue emitting code to inform MachineModuleInfo + /// of frame layouts. + MachineModuleInfo *MMI; + +public: + MachineFrameInfo() { + StackSize = NumFixedObjects = OffsetAdjustment = MaxAlignment = 0; + HasVarSizedObjects = false; + HasCalls = false; + MaxCallFrameSize = 0; + MMI = 0; + } + + /// hasStackObjects - Return true if there are any stack objects in this + /// function. + /// + bool hasStackObjects() const { return !Objects.empty(); } + + /// hasVarSizedObjects - This method may be called any time after instruction + /// selection is complete to determine if the stack frame for this function + /// contains any variable sized objects. + /// + bool hasVarSizedObjects() const { return HasVarSizedObjects; } + + /// getObjectIndexBegin - Return the minimum frame object index... + /// + int getObjectIndexBegin() const { return -NumFixedObjects; } + + /// getObjectIndexEnd - Return one past the maximum frame object index... + /// + int getObjectIndexEnd() const { return Objects.size()-NumFixedObjects; } + + /// getObjectSize - Return the size of the specified object + /// + int64_t getObjectSize(int ObjectIdx) const { + assert(ObjectIdx+NumFixedObjects < Objects.size() && "Invalid Object Idx!"); + return Objects[ObjectIdx+NumFixedObjects].Size; + } + + /// getObjectAlignment - Return the alignment of the specified stack object... + int getObjectAlignment(int ObjectIdx) const { + assert(ObjectIdx+NumFixedObjects < Objects.size() && "Invalid Object Idx!"); + return Objects[ObjectIdx+NumFixedObjects].Alignment; + } + + /// getObjectOffset - Return the assigned stack offset of the specified object + /// from the incoming stack pointer. + /// + int64_t getObjectOffset(int ObjectIdx) const { + assert(ObjectIdx+NumFixedObjects < Objects.size() && "Invalid Object Idx!"); + return Objects[ObjectIdx+NumFixedObjects].SPOffset; + } + + /// setObjectOffset - Set the stack frame offset of the specified object. The + /// offset is relative to the stack pointer on entry to the function. + /// + void setObjectOffset(int ObjectIdx, int64_t SPOffset) { + assert(ObjectIdx+NumFixedObjects < Objects.size() && "Invalid Object Idx!"); + Objects[ObjectIdx+NumFixedObjects].SPOffset = SPOffset; + } + + /// getStackSize - Return the number of bytes that must be allocated to hold + /// all of the fixed size frame objects. This is only valid after + /// Prolog/Epilog code insertion has finalized the stack frame layout. + /// + uint64_t getStackSize() const { return StackSize; } + + /// setStackSize - Set the size of the stack... + /// + void setStackSize(uint64_t Size) { StackSize = Size; } + + /// getOffsetAdjustment - Return the correction for frame offsets. + /// + int getOffsetAdjustment() const { return OffsetAdjustment; } + + /// setOffsetAdjustment - Set the correction for frame offsets. + /// + void setOffsetAdjustment(int Adj) { OffsetAdjustment = Adj; } + + /// getMaxAlignment - Return the alignment in bytes that this function must be + /// aligned to, which is greater than the default stack alignment provided by + /// the target. + /// + unsigned getMaxAlignment() const { return MaxAlignment; } + + /// setMaxAlignment - Set the preferred alignment. + /// + void setMaxAlignment(unsigned Align) { MaxAlignment = Align; } + + /// hasCalls - Return true if the current function has no function calls. + /// This is only valid during or after prolog/epilog code emission. + /// + bool hasCalls() const { return HasCalls; } + void setHasCalls(bool V) { HasCalls = V; } + + /// getMaxCallFrameSize - Return the maximum size of a call frame that must be + /// allocated for an outgoing function call. This is only available if + /// CallFrameSetup/Destroy pseudo instructions are used by the target, and + /// then only during or after prolog/epilog code insertion. + /// + unsigned getMaxCallFrameSize() const { return MaxCallFrameSize; } + void setMaxCallFrameSize(unsigned S) { MaxCallFrameSize = S; } + + /// CreateFixedObject - Create a new object at a fixed location on the stack. + /// All fixed objects should be created before other objects are created for + /// efficiency. This returns an index with a negative value. + /// + int CreateFixedObject(uint64_t Size, int64_t SPOffset) { + assert(Size != 0 && "Cannot allocate zero size fixed stack objects!"); + Objects.insert(Objects.begin(), StackObject(Size, 1, SPOffset)); + return -++NumFixedObjects; + } + + /// isFixedObjectIndex - Returns true if the specified index corresponds to a + /// fixed stack object. + bool isFixedObjectIndex(int ObjectIdx) const { + return ObjectIdx < 0 && (ObjectIdx >= -(int)NumFixedObjects); + } + + /// CreateStackObject - Create a new statically sized stack object, returning + /// a postive identifier to represent it. + /// + int CreateStackObject(uint64_t Size, unsigned Alignment) { + // Keep track of the maximum alignment. + if (MaxAlignment < Alignment) MaxAlignment = Alignment; + + assert(Size != 0 && "Cannot allocate zero size stack objects!"); + Objects.push_back(StackObject(Size, Alignment, -1)); + return Objects.size()-NumFixedObjects-1; + } + + /// CreateVariableSizedObject - Notify the MachineFrameInfo object that a + /// variable sized object has been created. This must be created whenever a + /// variable sized object is created, whether or not the index returned is + /// actually used. + /// + int CreateVariableSizedObject() { + HasVarSizedObjects = true; + if (MaxAlignment < 1) MaxAlignment = 1; + Objects.push_back(StackObject(0, 1, -1)); + return Objects.size()-NumFixedObjects-1; + } + + /// getCalleeSavedInfo - Returns a reference to call saved info vector for the + /// current function. + const std::vector<CalleeSavedInfo> &getCalleeSavedInfo() const { + return CSInfo; + } + + /// setCalleeSavedInfo - Used by prolog/epilog inserter to set the function's + /// callee saved information. + void setCalleeSavedInfo(const std::vector<CalleeSavedInfo> &CSI) { + CSInfo = CSI; + } + + /// getMachineModuleInfo - Used by a prologue/epilogue emitter (MRegisterInfo) + /// to provide frame layout information. + MachineModuleInfo *getMachineModuleInfo() const { return MMI; } + + /// setMachineModuleInfo - Used by a meta info consumer (DwarfWriter) to + /// indicate that frame layout information should be gathered. + void setMachineModuleInfo(MachineModuleInfo *mmi) { MMI = mmi; } + + /// print - Used by the MachineFunction printer to print information about + /// stack objects. Implemented in MachineFunction.cpp + /// + void print(const MachineFunction &MF, std::ostream &OS) const; + + /// dump - Call print(MF, std::cerr) to be called from the debugger. + void dump(const MachineFunction &MF) const; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h new file mode 100644 index 0000000..00a1fe8 --- /dev/null +++ b/include/llvm/CodeGen/MachineFunction.h @@ -0,0 +1,374 @@ +//===-- llvm/CodeGen/MachineFunction.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Collect native machine code for a function. This class contains a list of +// MachineBasicBlock instances that make up the current compiled function. +// +// This class also contains pointers to various classes which hold +// target-specific information about the generated code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEFUNCTION_H +#define LLVM_CODEGEN_MACHINEFUNCTION_H + +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/Support/Annotation.h" +#include "llvm/ADT/BitVector.h" + +namespace llvm { + +class Function; +class TargetMachine; +class SSARegMap; +class MachineFrameInfo; +class MachineConstantPool; +class MachineJumpTableInfo; + +// ilist_traits +template <> +struct ilist_traits<MachineBasicBlock> { + // this is only set by the MachineFunction owning the ilist + friend class MachineFunction; + MachineFunction* Parent; + +public: + ilist_traits<MachineBasicBlock>() : Parent(0) { } + + static MachineBasicBlock* getPrev(MachineBasicBlock* N) { return N->Prev; } + static MachineBasicBlock* getNext(MachineBasicBlock* N) { return N->Next; } + + static const MachineBasicBlock* + getPrev(const MachineBasicBlock* N) { return N->Prev; } + + static const MachineBasicBlock* + getNext(const MachineBasicBlock* N) { return N->Next; } + + static void setPrev(MachineBasicBlock* N, MachineBasicBlock* prev) { + N->Prev = prev; + } + static void setNext(MachineBasicBlock* N, MachineBasicBlock* next) { + N->Next = next; + } + + static MachineBasicBlock* createSentinel(); + static void destroySentinel(MachineBasicBlock *MBB) { delete MBB; } + void addNodeToList(MachineBasicBlock* N); + void removeNodeFromList(MachineBasicBlock* N); + void transferNodesFromList(iplist<MachineBasicBlock, + ilist_traits<MachineBasicBlock> > &toList, + ilist_iterator<MachineBasicBlock> first, + ilist_iterator<MachineBasicBlock> last); +}; + +/// MachineFunctionInfo - This class can be derived from and used by targets to +/// hold private target-specific information for each MachineFunction. Objects +/// of type are accessed/created with MF::getInfo and destroyed when the +/// MachineFunction is destroyed. +struct MachineFunctionInfo { + virtual ~MachineFunctionInfo() {}; +}; + +class MachineFunction : private Annotation { + const Function *Fn; + const TargetMachine &Target; + + // List of machine basic blocks in function + ilist<MachineBasicBlock> BasicBlocks; + + // Keeping track of mapping from SSA values to registers + SSARegMap *SSARegMapping; + + // Used to keep track of target-specific per-machine function information for + // the target implementation. + MachineFunctionInfo *MFInfo; + + // Keep track of objects allocated on the stack. + MachineFrameInfo *FrameInfo; + + // Keep track of constants which are spilled to memory + MachineConstantPool *ConstantPool; + + // Keep track of jump tables for switch instructions + MachineJumpTableInfo *JumpTableInfo; + + // Function-level unique numbering for MachineBasicBlocks. When a + // MachineBasicBlock is inserted into a MachineFunction is it automatically + // numbered and this vector keeps track of the mapping from ID's to MBB's. + std::vector<MachineBasicBlock*> MBBNumbering; + + /// UsedPhysRegs - This is a bit vector that is computed and set by the + /// register allocator, and must be kept up to date by passes that run after + /// register allocation (though most don't modify this). This is used + /// so that the code generator knows which callee save registers to save and + /// for other target specific uses. + BitVector UsedPhysRegs; + + /// LiveIns/LiveOuts - Keep track of the physical registers that are + /// livein/liveout of the function. Live in values are typically arguments in + /// registers, live out values are typically return values in registers. + /// LiveIn values are allowed to have virtual registers associated with them, + /// stored in the second element. + std::vector<std::pair<unsigned, unsigned> > LiveIns; + std::vector<unsigned> LiveOuts; + +public: + MachineFunction(const Function *Fn, const TargetMachine &TM); + ~MachineFunction(); + + /// getFunction - Return the LLVM function that this machine code represents + /// + const Function *getFunction() const { return Fn; } + + /// getTarget - Return the target machine this machine code is compiled with + /// + const TargetMachine &getTarget() const { return Target; } + + /// SSARegMap Interface... Keep track of information about each SSA virtual + /// register, such as which register class it belongs to. + /// + SSARegMap *getSSARegMap() const { return SSARegMapping; } + void clearSSARegMap(); + + /// getFrameInfo - Return the frame info object for the current function. + /// This object contains information about objects allocated on the stack + /// frame of the current function in an abstract way. + /// + MachineFrameInfo *getFrameInfo() const { return FrameInfo; } + + /// getJumpTableInfo - Return the jump table info object for the current + /// function. This object contains information about jump tables for switch + /// instructions in the current function. + /// + MachineJumpTableInfo *getJumpTableInfo() const { return JumpTableInfo; } + + /// getConstantPool - Return the constant pool object for the current + /// function. + /// + MachineConstantPool *getConstantPool() const { return ConstantPool; } + + /// MachineFunctionInfo - Keep track of various per-function pieces of + /// information for backends that would like to do so. + /// + template<typename Ty> + Ty *getInfo() { + if (!MFInfo) MFInfo = new Ty(*this); + + assert((void*)dynamic_cast<Ty*>(MFInfo) == (void*)MFInfo && + "Invalid concrete type or multiple inheritence for getInfo"); + return static_cast<Ty*>(MFInfo); + } + + template<typename Ty> + const Ty *getInfo() const { + return const_cast<MachineFunction*>(this)->getInfo<Ty>(); + } + + /// isPhysRegUsed - Return true if the specified register is used in this + /// function. This only works after register allocation. + bool isPhysRegUsed(unsigned Reg) const { return UsedPhysRegs[Reg]; } + + /// setPhysRegUsed - Mark the specified register used in this function. + /// This should only be called during and after register allocation. + void setPhysRegUsed(unsigned Reg) { UsedPhysRegs[Reg] = true; } + + /// setPhysRegUnused - Mark the specified register unused in this function. + /// This should only be called during and after register allocation. + void setPhysRegUnused(unsigned Reg) { UsedPhysRegs[Reg] = false; } + + // LiveIn/LiveOut management methods. + + /// addLiveIn/Out - Add the specified register as a live in/out. Note that it + /// is an error to add the same register to the same set more than once. + void addLiveIn(unsigned Reg, unsigned vreg = 0) { + LiveIns.push_back(std::make_pair(Reg, vreg)); + } + void addLiveOut(unsigned Reg) { LiveOuts.push_back(Reg); } + + // Iteration support for live in/out sets. These sets are kept in sorted + // order by their register number. + typedef std::vector<std::pair<unsigned,unsigned> >::const_iterator + livein_iterator; + typedef std::vector<unsigned>::const_iterator liveout_iterator; + livein_iterator livein_begin() const { return LiveIns.begin(); } + livein_iterator livein_end() const { return LiveIns.end(); } + bool livein_empty() const { return LiveIns.empty(); } + liveout_iterator liveout_begin() const { return LiveOuts.begin(); } + liveout_iterator liveout_end() const { return LiveOuts.end(); } + bool liveout_empty() const { return LiveOuts.empty(); } + + /// getBlockNumbered - MachineBasicBlocks are automatically numbered when they + /// are inserted into the machine function. The block number for a machine + /// basic block can be found by using the MBB::getBlockNumber method, this + /// method provides the inverse mapping. + /// + MachineBasicBlock *getBlockNumbered(unsigned N) { + assert(N < MBBNumbering.size() && "Illegal block number"); + assert(MBBNumbering[N] && "Block was removed from the machine function!"); + return MBBNumbering[N]; + } + + /// getNumBlockIDs - Return the number of MBB ID's allocated. + /// + unsigned getNumBlockIDs() const { return MBBNumbering.size(); } + + /// RenumberBlocks - This discards all of the MachineBasicBlock numbers and + /// recomputes them. This guarantees that the MBB numbers are sequential, + /// dense, and match the ordering of the blocks within the function. If a + /// specific MachineBasicBlock is specified, only that block and those after + /// it are renumbered. + void RenumberBlocks(MachineBasicBlock *MBBFrom = 0); + + /// print - Print out the MachineFunction in a format suitable for debugging + /// to the specified stream. + /// + void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + + /// viewCFG - This function is meant for use from the debugger. You can just + /// say 'call F->viewCFG()' and a ghostview window should pop up from the + /// program, displaying the CFG of the current function with the code for each + /// basic block inside. This depends on there being a 'dot' and 'gv' program + /// in your path. + /// + void viewCFG() const; + + /// viewCFGOnly - This function is meant for use from the debugger. It works + /// just like viewCFG, but it does not include the contents of basic blocks + /// into the nodes, just the label. If you are only interested in the CFG + /// this can make the graph smaller. + /// + void viewCFGOnly() const; + + /// dump - Print the current MachineFunction to cerr, useful for debugger use. + /// + void dump() const; + + /// construct - Allocate and initialize a MachineFunction for a given Function + /// and Target + /// + static MachineFunction& construct(const Function *F, const TargetMachine &TM); + + /// destruct - Destroy the MachineFunction corresponding to a given Function + /// + static void destruct(const Function *F); + + /// get - Return a handle to a MachineFunction corresponding to the given + /// Function. This should not be called before "construct()" for a given + /// Function. + /// + static MachineFunction& get(const Function *F); + + // Provide accessors for the MachineBasicBlock list... + typedef ilist<MachineBasicBlock> BasicBlockListType; + typedef BasicBlockListType::iterator iterator; + typedef BasicBlockListType::const_iterator const_iterator; + typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + typedef std::reverse_iterator<iterator> reverse_iterator; + + // Provide accessors for basic blocks... + const BasicBlockListType &getBasicBlockList() const { return BasicBlocks; } + BasicBlockListType &getBasicBlockList() { return BasicBlocks; } + + //===--------------------------------------------------------------------===// + // BasicBlock iterator forwarding functions + // + iterator begin() { return BasicBlocks.begin(); } + const_iterator begin() const { return BasicBlocks.begin(); } + iterator end () { return BasicBlocks.end(); } + const_iterator end () const { return BasicBlocks.end(); } + + reverse_iterator rbegin() { return BasicBlocks.rbegin(); } + const_reverse_iterator rbegin() const { return BasicBlocks.rbegin(); } + reverse_iterator rend () { return BasicBlocks.rend(); } + const_reverse_iterator rend () const { return BasicBlocks.rend(); } + + unsigned size() const { return BasicBlocks.size(); } + bool empty() const { return BasicBlocks.empty(); } + const MachineBasicBlock &front() const { return BasicBlocks.front(); } + MachineBasicBlock &front() { return BasicBlocks.front(); } + const MachineBasicBlock & back() const { return BasicBlocks.back(); } + MachineBasicBlock & back() { return BasicBlocks.back(); } + + //===--------------------------------------------------------------------===// + // Internal functions used to automatically number MachineBasicBlocks + // + + /// getNextMBBNumber - Returns the next unique number to be assigned + /// to a MachineBasicBlock in this MachineFunction. + /// + unsigned addToMBBNumbering(MachineBasicBlock *MBB) { + MBBNumbering.push_back(MBB); + return MBBNumbering.size()-1; + } + + /// removeFromMBBNumbering - Remove the specific machine basic block from our + /// tracker, this is only really to be used by the MachineBasicBlock + /// implementation. + void removeFromMBBNumbering(unsigned N) { + assert(N < MBBNumbering.size() && "Illegal basic block #"); + MBBNumbering[N] = 0; + } +}; + +//===--------------------------------------------------------------------===// +// GraphTraits specializations for function basic block graphs (CFGs) +//===--------------------------------------------------------------------===// + +// Provide specializations of GraphTraits to be able to treat a +// machine function as a graph of machine basic blocks... these are +// the same as the machine basic block iterators, except that the root +// node is implicitly the first node of the function. +// +template <> struct GraphTraits<MachineFunction*> : + public GraphTraits<MachineBasicBlock*> { + static NodeType *getEntryNode(MachineFunction *F) { + return &F->front(); + } + + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + typedef MachineFunction::iterator nodes_iterator; + static nodes_iterator nodes_begin(MachineFunction *F) { return F->begin(); } + static nodes_iterator nodes_end (MachineFunction *F) { return F->end(); } +}; +template <> struct GraphTraits<const MachineFunction*> : + public GraphTraits<const MachineBasicBlock*> { + static NodeType *getEntryNode(const MachineFunction *F) { + return &F->front(); + } + + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + typedef MachineFunction::const_iterator nodes_iterator; + static nodes_iterator nodes_begin(const MachineFunction *F) { return F->begin(); } + static nodes_iterator nodes_end (const MachineFunction *F) { return F->end(); } +}; + + +// Provide specializations of GraphTraits to be able to treat a function as a +// graph of basic blocks... and to walk it in inverse order. Inverse order for +// a function is considered to be when traversing the predecessor edges of a BB +// instead of the successor edges. +// +template <> struct GraphTraits<Inverse<MachineFunction*> > : + public GraphTraits<Inverse<MachineBasicBlock*> > { + static NodeType *getEntryNode(Inverse<MachineFunction*> G) { + return &G.Graph->front(); + } +}; +template <> struct GraphTraits<Inverse<const MachineFunction*> > : + public GraphTraits<Inverse<const MachineBasicBlock*> > { + static NodeType *getEntryNode(Inverse<const MachineFunction *> G) { + return &G.Graph->front(); + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/MachineFunctionPass.h b/include/llvm/CodeGen/MachineFunctionPass.h new file mode 100644 index 0000000..f90c696 --- /dev/null +++ b/include/llvm/CodeGen/MachineFunctionPass.h @@ -0,0 +1,50 @@ +//===-- MachineFunctionPass.h - Pass for MachineFunctions --------*-C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the MachineFunctionPass class. MachineFunctionPass's are +// just FunctionPass's, except they operate on machine code as part of a code +// generator. Because they operate on machine code, not the LLVM +// representation, MachineFunctionPass's are not allowed to modify the LLVM +// representation. Due to this limitation, the MachineFunctionPass class takes +// care of declaring that no LLVM passes are invalidated. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINE_FUNCTION_PASS_H +#define LLVM_CODEGEN_MACHINE_FUNCTION_PASS_H + +#include "llvm/Pass.h" +#include "llvm/CodeGen/MachineFunction.h" + +namespace llvm { + +struct MachineFunctionPass : public FunctionPass { + + explicit MachineFunctionPass(intptr_t ID) : FunctionPass(ID) {} + +protected: + /// runOnMachineFunction - This method must be overloaded to perform the + /// desired machine code transformation or analysis. + /// + virtual bool runOnMachineFunction(MachineFunction &MF) = 0; + +public: + // FIXME: This pass should declare that the pass does not invalidate any LLVM + // passes. + bool runOnFunction(Function &F) { + return runOnMachineFunction(MachineFunction::get(&F)); + } + +private: + virtual void virtfn(); // out of line virtual fn to give class a home. +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h new file mode 100644 index 0000000..1f621c1 --- /dev/null +++ b/include/llvm/CodeGen/MachineInstr.h @@ -0,0 +1,567 @@ +//===-- llvm/CodeGen/MachineInstr.h - MachineInstr class --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MachineInstr class, which is the +// basic representation for all target dependent machine instructions used by +// the back end. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEINSTR_H +#define LLVM_CODEGEN_MACHINEINSTR_H + +#include "llvm/ADT/iterator" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Streams.h" +#include <vector> +#include <cassert> +#include <iosfwd> + +namespace llvm { + +class Value; +class Function; +class MachineBasicBlock; +class TargetInstrDescriptor; +class TargetMachine; +class GlobalValue; + +template <typename T> struct ilist_traits; +template <typename T> struct ilist; + +//===----------------------------------------------------------------------===// +// class MachineOperand +// +// Representation of each machine instruction operand. +// +struct MachineOperand { + enum MachineOperandType { + MO_Register, // Register operand. + MO_Immediate, // Immediate Operand + MO_MachineBasicBlock, // MachineBasicBlock reference + MO_FrameIndex, // Abstract Stack Frame Index + MO_ConstantPoolIndex, // Address of indexed Constant in Constant Pool + MO_JumpTableIndex, // Address of indexed Jump Table for switch + MO_ExternalSymbol, // Name of external global symbol + MO_GlobalAddress // Address of a global value + }; + +private: + union { + GlobalValue *GV; // For MO_GlobalAddress. + MachineBasicBlock *MBB; // For MO_MachineBasicBlock. + const char *SymbolName; // For MO_ExternalSymbol. + unsigned RegNo; // For MO_Register. + int64_t immedVal; // For MO_Immediate and MO_*Index. + } contents; + + MachineOperandType opType:8; // Discriminate the union. + bool IsDef : 1; // True if this is a def, false if this is a use. + bool IsImp : 1; // True if this is an implicit def or use. + + bool IsKill : 1; // True if this is a reg use and the reg is dead + // immediately after the read. + bool IsDead : 1; // True if this is a reg def and the reg is dead + // immediately after the write. i.e. A register + // that is defined but never used. + + /// auxInfo - auxiliary information used by the MachineOperand + union { + /// offset - Offset to address of global or external, only valid for + /// MO_GlobalAddress, MO_ExternalSym and MO_ConstantPoolIndex + int offset; + + /// subReg - SubRegister number, only valid for MO_Register. A value of 0 + /// indicates the MO_Register has no subReg. + unsigned subReg; + } auxInfo; + + MachineOperand() {} + + void print(std::ostream &os) const; + void print(std::ostream *os) const { if (os) print(*os); } + +public: + MachineOperand(const MachineOperand &M) { + *this = M; + } + + ~MachineOperand() {} + + static MachineOperand CreateImm(int64_t Val) { + MachineOperand Op; + Op.opType = MachineOperand::MO_Immediate; + Op.contents.immedVal = Val; + Op.IsDef = false; + Op.IsImp = false; + Op.IsKill = false; + Op.IsDead = false; + Op.auxInfo.offset = 0; + return Op; + } + + const MachineOperand &operator=(const MachineOperand &MO) { + contents = MO.contents; + IsDef = MO.IsDef; + IsImp = MO.IsImp; + IsKill = MO.IsKill; + IsDead = MO.IsDead; + opType = MO.opType; + auxInfo = MO.auxInfo; + return *this; + } + + /// getType - Returns the MachineOperandType for this operand. + /// + MachineOperandType getType() const { return opType; } + + /// Accessors that tell you what kind of MachineOperand you're looking at. + /// + bool isReg() const { return opType == MO_Register; } + bool isImm() const { return opType == MO_Immediate; } + bool isMBB() const { return opType == MO_MachineBasicBlock; } + + bool isRegister() const { return opType == MO_Register; } + bool isImmediate() const { return opType == MO_Immediate; } + bool isMachineBasicBlock() const { return opType == MO_MachineBasicBlock; } + bool isFrameIndex() const { return opType == MO_FrameIndex; } + bool isConstantPoolIndex() const { return opType == MO_ConstantPoolIndex; } + bool isJumpTableIndex() const { return opType == MO_JumpTableIndex; } + bool isGlobalAddress() const { return opType == MO_GlobalAddress; } + bool isExternalSymbol() const { return opType == MO_ExternalSymbol; } + + int64_t getImm() const { + assert(isImm() && "Wrong MachineOperand accessor"); + return contents.immedVal; + } + + int64_t getImmedValue() const { + assert(isImm() && "Wrong MachineOperand accessor"); + return contents.immedVal; + } + MachineBasicBlock *getMBB() const { + assert(isMachineBasicBlock() && "Wrong MachineOperand accessor"); + return contents.MBB; + } + MachineBasicBlock *getMachineBasicBlock() const { + assert(isMachineBasicBlock() && "Wrong MachineOperand accessor"); + return contents.MBB; + } + void setMachineBasicBlock(MachineBasicBlock *MBB) { + assert(isMachineBasicBlock() && "Wrong MachineOperand accessor"); + contents.MBB = MBB; + } + int getFrameIndex() const { + assert(isFrameIndex() && "Wrong MachineOperand accessor"); + return (int)contents.immedVal; + } + unsigned getConstantPoolIndex() const { + assert(isConstantPoolIndex() && "Wrong MachineOperand accessor"); + return (unsigned)contents.immedVal; + } + unsigned getJumpTableIndex() const { + assert(isJumpTableIndex() && "Wrong MachineOperand accessor"); + return (unsigned)contents.immedVal; + } + GlobalValue *getGlobal() const { + assert(isGlobalAddress() && "Wrong MachineOperand accessor"); + return contents.GV; + } + int getOffset() const { + assert((isGlobalAddress() || isExternalSymbol() || isConstantPoolIndex()) && + "Wrong MachineOperand accessor"); + return auxInfo.offset; + } + unsigned getSubReg() const { + assert(isRegister() && "Wrong MachineOperand accessor"); + return auxInfo.subReg; + } + const char *getSymbolName() const { + assert(isExternalSymbol() && "Wrong MachineOperand accessor"); + return contents.SymbolName; + } + + bool isUse() const { + assert(isRegister() && "Wrong MachineOperand accessor"); + return !IsDef; + } + bool isDef() const { + assert(isRegister() && "Wrong MachineOperand accessor"); + return IsDef; + } + void setIsUse() { + assert(isRegister() && "Wrong MachineOperand accessor"); + IsDef = false; + } + void setIsDef() { + assert(isRegister() && "Wrong MachineOperand accessor"); + IsDef = true; + } + + bool isImplicit() const { + assert(isRegister() && "Wrong MachineOperand accessor"); + return IsImp; + } + void setImplicit() { + assert(isRegister() && "Wrong MachineOperand accessor"); + IsImp = true; + } + + bool isKill() const { + assert(isRegister() && "Wrong MachineOperand accessor"); + return IsKill; + } + bool isDead() const { + assert(isRegister() && "Wrong MachineOperand accessor"); + return IsDead; + } + void setIsKill() { + assert(isRegister() && !IsDef && "Wrong MachineOperand accessor"); + IsKill = true; + } + void setIsDead() { + assert(isRegister() && IsDef && "Wrong MachineOperand accessor"); + IsDead = true; + } + void unsetIsKill() { + assert(isRegister() && !IsDef && "Wrong MachineOperand accessor"); + IsKill = false; + } + void unsetIsDead() { + assert(isRegister() && IsDef && "Wrong MachineOperand accessor"); + IsDead = false; + } + + /// getReg - Returns the register number. + /// + unsigned getReg() const { + assert(isRegister() && "This is not a register operand!"); + return contents.RegNo; + } + + /// MachineOperand mutators. + /// + void setReg(unsigned Reg) { + assert(isRegister() && "This is not a register operand!"); + contents.RegNo = Reg; + } + + void setImmedValue(int64_t immVal) { + assert(isImm() && "Wrong MachineOperand mutator"); + contents.immedVal = immVal; + } + void setImm(int64_t immVal) { + assert(isImm() && "Wrong MachineOperand mutator"); + contents.immedVal = immVal; + } + + void setOffset(int Offset) { + assert((isGlobalAddress() || isExternalSymbol() || isConstantPoolIndex() || + isJumpTableIndex()) && + "Wrong MachineOperand accessor"); + auxInfo.offset = Offset; + } + void setSubReg(unsigned subReg) { + assert(isRegister() && "Wrong MachineOperand accessor"); + auxInfo.subReg = subReg; + } + void setConstantPoolIndex(unsigned Idx) { + assert(isConstantPoolIndex() && "Wrong MachineOperand accessor"); + contents.immedVal = Idx; + } + void setJumpTableIndex(unsigned Idx) { + assert(isJumpTableIndex() && "Wrong MachineOperand accessor"); + contents.immedVal = Idx; + } + + /// isIdenticalTo - Return true if this operand is identical to the specified + /// operand. Note: This method ignores isKill and isDead properties. + bool isIdenticalTo(const MachineOperand &Other) const; + + /// ChangeToImmediate - Replace this operand with a new immediate operand of + /// the specified value. If an operand is known to be an immediate already, + /// the setImmedValue method should be used. + void ChangeToImmediate(int64_t ImmVal) { + opType = MO_Immediate; + contents.immedVal = ImmVal; + } + + /// ChangeToRegister - Replace this operand with a new register operand of + /// the specified value. If an operand is known to be an register already, + /// the setReg method should be used. + void ChangeToRegister(unsigned Reg, bool isDef, bool isImp = false, + bool isKill = false, bool isDead = false) { + opType = MO_Register; + contents.RegNo = Reg; + IsDef = isDef; + IsImp = isImp; + IsKill = isKill; + IsDead = isDead; + } + + friend std::ostream& operator<<(std::ostream& os, const MachineOperand& mop) { + mop.print(os); + return os; + } + + friend class MachineInstr; +}; + + +//===----------------------------------------------------------------------===// +/// MachineInstr - Representation of each machine instruction. +/// +class MachineInstr { + const TargetInstrDescriptor *TID; // Instruction descriptor. + unsigned short NumImplicitOps; // Number of implicit operands (which + // are determined at construction time). + + std::vector<MachineOperand> Operands; // the operands + MachineInstr* prev, *next; // links for our intrusive list + MachineBasicBlock* parent; // pointer to the owning basic block + + // OperandComplete - Return true if it's illegal to add a new operand + bool OperandsComplete() const; + + MachineInstr(const MachineInstr&); + void operator=(const MachineInstr&); // DO NOT IMPLEMENT + + // Intrusive list support + // + friend struct ilist_traits<MachineInstr>; + +public: + /// MachineInstr ctor - This constructor creates a dummy MachineInstr with + /// TID NULL and no operands. + MachineInstr(); + + /// MachineInstr ctor - This constructor create a MachineInstr and add the + /// implicit operands. It reserves space for number of operands specified by + /// TargetInstrDescriptor. + explicit MachineInstr(const TargetInstrDescriptor &TID); + + /// MachineInstr ctor - Work exactly the same as the ctor above, except that + /// the MachineInstr is created and added to the end of the specified basic + /// block. + /// + MachineInstr(MachineBasicBlock *MBB, const TargetInstrDescriptor &TID); + + ~MachineInstr(); + + const MachineBasicBlock* getParent() const { return parent; } + MachineBasicBlock* getParent() { return parent; } + + /// getInstrDescriptor - Returns the target instruction descriptor of this + /// MachineInstr. + const TargetInstrDescriptor *getInstrDescriptor() const { return TID; } + + /// getOpcode - Returns the opcode of this MachineInstr. + /// + const int getOpcode() const; + + /// Access to explicit operands of the instruction. + /// + unsigned getNumOperands() const { return Operands.size(); } + + const MachineOperand& getOperand(unsigned i) const { + assert(i < getNumOperands() && "getOperand() out of range!"); + return Operands[i]; + } + MachineOperand& getOperand(unsigned i) { + assert(i < getNumOperands() && "getOperand() out of range!"); + return Operands[i]; + } + + /// getNumExplicitOperands - Returns the number of non-implicit operands. + /// + unsigned getNumExplicitOperands() const; + + /// isIdenticalTo - Return true if this instruction is identical to (same + /// opcode and same operands as) the specified instruction. + bool isIdenticalTo(const MachineInstr *Other) const { + if (Other->getOpcode() != getOpcode() || + Other->getNumOperands() != getNumOperands()) + return false; + for (unsigned i = 0, e = getNumOperands(); i != e; ++i) + if (!getOperand(i).isIdenticalTo(Other->getOperand(i))) + return false; + return true; + } + + /// clone - Create a copy of 'this' instruction that is identical in + /// all ways except the the instruction has no parent, prev, or next. + MachineInstr* clone() const { return new MachineInstr(*this); } + + /// removeFromParent - This method unlinks 'this' from the containing basic + /// block, and returns it, but does not delete it. + MachineInstr *removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing basic + /// block and deletes it. + void eraseFromParent() { + delete removeFromParent(); + } + + /// findRegisterUseOperandIdx() - Returns the operand index that is a use of + /// the specific register or -1 if it is not found. It further tightening + /// the search criteria to a use that kills the register if isKill is true. + int findRegisterUseOperandIdx(unsigned Reg, bool isKill = false) const; + + /// findRegisterDefOperand() - Returns the MachineOperand that is a def of + /// the specific register or NULL if it is not found. + MachineOperand *findRegisterDefOperand(unsigned Reg); + + /// findFirstPredOperandIdx() - Find the index of the first operand in the + /// operand list that is used to represent the predicate. It returns -1 if + /// none is found. + int findFirstPredOperandIdx() const; + + /// copyKillDeadInfo - Copies kill / dead operand properties from MI. + /// + void copyKillDeadInfo(const MachineInstr *MI); + + /// copyPredicates - Copies predicate operand(s) from MI. + void copyPredicates(const MachineInstr *MI); + + // + // Debugging support + // + void print(std::ostream *OS, const TargetMachine *TM) const { + if (OS) print(*OS, TM); + } + void print(std::ostream &OS, const TargetMachine *TM) const; + void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + void dump() const; + friend std::ostream& operator<<(std::ostream& os, const MachineInstr& minstr){ + minstr.print(os); + return os; + } + + //===--------------------------------------------------------------------===// + // Accessors to add operands when building up machine instructions. + // + + /// addRegOperand - Add a register operand. + /// + void addRegOperand(unsigned Reg, bool IsDef, bool IsImp = false, + bool IsKill = false, bool IsDead = false) { + MachineOperand &Op = AddNewOperand(IsImp); + Op.opType = MachineOperand::MO_Register; + Op.IsDef = IsDef; + Op.IsImp = IsImp; + Op.IsKill = IsKill; + Op.IsDead = IsDead; + Op.contents.RegNo = Reg; + Op.auxInfo.subReg = 0; + } + + /// addImmOperand - Add a zero extended constant argument to the + /// machine instruction. + /// + void addImmOperand(int64_t Val) { + MachineOperand &Op = AddNewOperand(); + Op.opType = MachineOperand::MO_Immediate; + Op.contents.immedVal = Val; + Op.auxInfo.offset = 0; + } + + void addMachineBasicBlockOperand(MachineBasicBlock *MBB) { + MachineOperand &Op = AddNewOperand(); + Op.opType = MachineOperand::MO_MachineBasicBlock; + Op.contents.MBB = MBB; + Op.auxInfo.offset = 0; + } + + /// addFrameIndexOperand - Add an abstract frame index to the instruction + /// + void addFrameIndexOperand(unsigned Idx) { + MachineOperand &Op = AddNewOperand(); + Op.opType = MachineOperand::MO_FrameIndex; + Op.contents.immedVal = Idx; + Op.auxInfo.offset = 0; + } + + /// addConstantPoolndexOperand - Add a constant pool object index to the + /// instruction. + /// + void addConstantPoolIndexOperand(unsigned Idx, int Offset) { + MachineOperand &Op = AddNewOperand(); + Op.opType = MachineOperand::MO_ConstantPoolIndex; + Op.contents.immedVal = Idx; + Op.auxInfo.offset = Offset; + } + + /// addJumpTableIndexOperand - Add a jump table object index to the + /// instruction. + /// + void addJumpTableIndexOperand(unsigned Idx) { + MachineOperand &Op = AddNewOperand(); + Op.opType = MachineOperand::MO_JumpTableIndex; + Op.contents.immedVal = Idx; + Op.auxInfo.offset = 0; + } + + void addGlobalAddressOperand(GlobalValue *GV, int Offset) { + MachineOperand &Op = AddNewOperand(); + Op.opType = MachineOperand::MO_GlobalAddress; + Op.contents.GV = GV; + Op.auxInfo.offset = Offset; + } + + /// addExternalSymbolOperand - Add an external symbol operand to this instr + /// + void addExternalSymbolOperand(const char *SymName) { + MachineOperand &Op = AddNewOperand(); + Op.opType = MachineOperand::MO_ExternalSymbol; + Op.contents.SymbolName = SymName; + Op.auxInfo.offset = 0; + } + + //===--------------------------------------------------------------------===// + // Accessors used to modify instructions in place. + // + + /// setInstrDescriptor - Replace the instruction descriptor (thus opcode) of + /// the current instruction with a new one. + /// + void setInstrDescriptor(const TargetInstrDescriptor &tid) { TID = &tid; } + + /// RemoveOperand - Erase an operand from an instruction, leaving it with one + /// fewer operand than it started with. + /// + void RemoveOperand(unsigned i) { + Operands.erase(Operands.begin()+i); + } +private: + MachineOperand &AddNewOperand(bool IsImp = false) { + assert((IsImp || !OperandsComplete()) && + "Trying to add an operand to a machine instr that is already done!"); + if (IsImp || NumImplicitOps == 0) { // This is true most of the time. + Operands.push_back(MachineOperand()); + return Operands.back(); + } + return *Operands.insert(Operands.begin()+Operands.size()-NumImplicitOps, + MachineOperand()); + } + + /// addImplicitDefUseOperands - Add all implicit def and use operands to + /// this instruction. + void addImplicitDefUseOperands(); +}; + +//===----------------------------------------------------------------------===// +// Debugging Support + +std::ostream& operator<<(std::ostream &OS, const MachineInstr &MI); +std::ostream& operator<<(std::ostream &OS, const MachineOperand &MO); + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/MachineInstrBuilder.h b/include/llvm/CodeGen/MachineInstrBuilder.h new file mode 100644 index 0000000..eb45b6e --- /dev/null +++ b/include/llvm/CodeGen/MachineInstrBuilder.h @@ -0,0 +1,147 @@ +//===-- CodeGen/MachineInstBuilder.h - Simplify creation of MIs -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes a function named BuildMI, which is useful for dramatically +// simplifying how MachineInstr's are created. It allows use of code like this: +// +// M = BuildMI(X86::ADDrr8, 2).addReg(argVal1).addReg(argVal2); +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEINSTRBUILDER_H +#define LLVM_CODEGEN_MACHINEINSTRBUILDER_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" + +namespace llvm { + +class TargetInstrDescriptor; + +class MachineInstrBuilder { + MachineInstr *MI; +public: + explicit MachineInstrBuilder(MachineInstr *mi) : MI(mi) {} + + /// Allow automatic conversion to the machine instruction we are working on. + /// + operator MachineInstr*() const { return MI; } + operator MachineBasicBlock::iterator() const { return MI; } + + /// addReg - Add a new virtual register operand... + /// + const + MachineInstrBuilder &addReg(int RegNo, bool isDef = false, bool isImp = false, + bool isKill = false, bool isDead = false) const { + MI->addRegOperand(RegNo, isDef, isImp, isKill, isDead); + return *this; + } + + /// addImm - Add a new immediate operand. + /// + const MachineInstrBuilder &addImm(int64_t Val) const { + MI->addImmOperand(Val); + return *this; + } + + const MachineInstrBuilder &addMBB(MachineBasicBlock *MBB) const { + MI->addMachineBasicBlockOperand(MBB); + return *this; + } + + const MachineInstrBuilder &addFrameIndex(unsigned Idx) const { + MI->addFrameIndexOperand(Idx); + return *this; + } + + const MachineInstrBuilder &addConstantPoolIndex(unsigned Idx, + int Offset = 0) const { + MI->addConstantPoolIndexOperand(Idx, Offset); + return *this; + } + + const MachineInstrBuilder &addJumpTableIndex(unsigned Idx) const { + MI->addJumpTableIndexOperand(Idx); + return *this; + } + + const MachineInstrBuilder &addGlobalAddress(GlobalValue *GV, + int Offset = 0) const { + MI->addGlobalAddressOperand(GV, Offset); + return *this; + } + + const MachineInstrBuilder &addExternalSymbol(const char *FnName) const{ + MI->addExternalSymbolOperand(FnName); + return *this; + } +}; + +/// BuildMI - Builder interface. Specify how to create the initial instruction +/// itself. +/// +inline MachineInstrBuilder BuildMI(const TargetInstrDescriptor &TID) { + return MachineInstrBuilder(new MachineInstr(TID)); +} + +/// BuildMI - This version of the builder sets up the first operand as a +/// destination virtual register. +/// +inline MachineInstrBuilder BuildMI(const TargetInstrDescriptor &TID, + unsigned DestReg) { + return MachineInstrBuilder(new MachineInstr(TID)).addReg(DestReg, true); +} + +/// BuildMI - This version of the builder inserts the newly-built +/// instruction before the given position in the given MachineBasicBlock, and +/// sets up the first operand as a destination virtual register. +/// +inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, + const TargetInstrDescriptor &TID, + unsigned DestReg) { + MachineInstr *MI = new MachineInstr(TID); + BB.insert(I, MI); + return MachineInstrBuilder(MI).addReg(DestReg, true); +} + +/// BuildMI - This version of the builder inserts the newly-built +/// instruction before the given position in the given MachineBasicBlock, and +/// does NOT take a destination register. +/// +inline MachineInstrBuilder BuildMI(MachineBasicBlock &BB, + MachineBasicBlock::iterator I, + const TargetInstrDescriptor &TID) { + MachineInstr *MI = new MachineInstr(TID); + BB.insert(I, MI); + return MachineInstrBuilder(MI); +} + +/// BuildMI - This version of the builder inserts the newly-built +/// instruction at the end of the given MachineBasicBlock, and does NOT take a +/// destination register. +/// +inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, + const TargetInstrDescriptor &TID) { + return BuildMI(*BB, BB->end(), TID); +} + +/// BuildMI - This version of the builder inserts the newly-built +/// instruction at the end of the given MachineBasicBlock, and sets up the first +/// operand as a destination virtual register. +/// +inline MachineInstrBuilder BuildMI(MachineBasicBlock *BB, + const TargetInstrDescriptor &TID, + unsigned DestReg) { + return BuildMI(*BB, BB->end(), TID, DestReg); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/MachineJumpTableInfo.h b/include/llvm/CodeGen/MachineJumpTableInfo.h new file mode 100644 index 0000000..d440268 --- /dev/null +++ b/include/llvm/CodeGen/MachineJumpTableInfo.h @@ -0,0 +1,103 @@ +//===-- CodeGen/MachineJumpTableInfo.h - Abstract Jump Tables --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Nate Begeman and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The MachineJumpTableInfo class keeps track of jump tables referenced by +// lowered switch instructions in the MachineFunction. +// +// Instructions reference the address of these jump tables through the use of +// MO_JumpTableIndex values. When emitting assembly or machine code, these +// virtual address references are converted to refer to the address of the +// function jump tables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEJUMPTABLEINFO_H +#define LLVM_CODEGEN_MACHINEJUMPTABLEINFO_H + +#include <vector> +#include <iosfwd> + +namespace llvm { + +class MachineBasicBlock; +class TargetData; + +/// MachineJumpTableEntry - One jump table in the jump table info. +/// +struct MachineJumpTableEntry { + /// MBBs - The vector of basic blocks from which to create the jump table. + std::vector<MachineBasicBlock*> MBBs; + + explicit MachineJumpTableEntry(const std::vector<MachineBasicBlock*> &M) + : MBBs(M) {} +}; + +class MachineJumpTableInfo { + unsigned EntrySize; + unsigned Alignment; + std::vector<MachineJumpTableEntry> JumpTables; +public: + MachineJumpTableInfo(unsigned Size, unsigned Align) + : EntrySize(Size), Alignment(Align) {} + + /// getJumpTableIndex - Create a new jump table or return an existing one. + /// + unsigned getJumpTableIndex(const std::vector<MachineBasicBlock*> &DestBBs); + + /// isEmpty - Return true if there are no jump tables. + /// + bool isEmpty() const { return JumpTables.empty(); } + + const std::vector<MachineJumpTableEntry> &getJumpTables() const { + return JumpTables; + } + + /// RemoveJumpTable - Mark the specific index as being dead. This will cause + /// it to not be emitted. + void RemoveJumpTable(unsigned Idx) { + JumpTables[Idx].MBBs.clear(); + } + + /// ReplaceMBBInJumpTables - If Old is the target of any jump tables, update + /// the jump tables to branch to New instead. + bool ReplaceMBBInJumpTables(MachineBasicBlock *Old, MachineBasicBlock *New) { + assert(Old != New && "Not making a change?"); + bool MadeChange = false; + for (unsigned i = 0, e = JumpTables.size(); i != e; ++i) { + MachineJumpTableEntry &JTE = JumpTables[i]; + for (unsigned j = 0, e = JTE.MBBs.size(); j != e; ++j) + if (JTE.MBBs[j] == Old) { + JTE.MBBs[j] = New; + MadeChange = true; + } + } + return MadeChange; + } + + /// getEntrySize - Returns the size of an individual field in a jump table. + /// + unsigned getEntrySize() const { return EntrySize; } + + /// getAlignment - returns the target's preferred alignment for jump tables + unsigned getAlignment() const { return Alignment; } + + /// print - Used by the MachineFunction printer to print information about + /// jump tables. Implemented in MachineFunction.cpp + /// + void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + + /// dump - Call print(std::cerr) to be called from the debugger. + /// + void dump() const; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/MachineLocation.h b/include/llvm/CodeGen/MachineLocation.h new file mode 100644 index 0000000..c0a78ae --- /dev/null +++ b/include/llvm/CodeGen/MachineLocation.h @@ -0,0 +1,106 @@ +//===-- llvm/CodeGen/MachineLocation.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by James M. Laskey and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// The MachineLocation class is used to represent a simple location in a machine +// frame. Locations will be one of two forms; a register or an address formed +// from a base address plus an offset. Register indirection can be specified by +// using an offset of zero. +// +// The MachineMove class is used to represent abstract move operations in the +// prolog/epilog of a compiled function. A collection of these objects can be +// used by a debug consumer to track the location of values when unwinding stack +// frames. +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_CODEGEN_MACHINELOCATION_H +#define LLVM_CODEGEN_MACHINELOCATION_H + +namespace llvm { + +class MachineLocation { +private: + bool IsRegister; // True if location is a register. + unsigned Register; // gcc/gdb register number. + int Offset; // Displacement if not register. + +public: + enum { + // The target register number for an abstract frame pointer. The value is + // an arbitrary value greater than MRegisterInfo::FirstVirtualRegister. + VirtualFP = ~0U + }; + MachineLocation() + : IsRegister(false) + , Register(0) + , Offset(0) + {} + explicit MachineLocation(unsigned R) + : IsRegister(true) + , Register(R) + , Offset(0) + {} + MachineLocation(unsigned R, int O) + : IsRegister(false) + , Register(R) + , Offset(O) + {} + + // Accessors + bool isRegister() const { return IsRegister; } + unsigned getRegister() const { return Register; } + int getOffset() const { return Offset; } + void setIsRegister(bool Is) { IsRegister = Is; } + void setRegister(unsigned R) { Register = R; } + void setOffset(int O) { Offset = O; } + void set(unsigned R) { + IsRegister = true; + Register = R; + Offset = 0; + } + void set(unsigned R, int O) { + IsRegister = false; + Register = R; + Offset = O; + } + +#ifndef NDEBUG + void dump(); +#endif +}; + +class MachineMove { +private: + unsigned LabelID; // Label ID number for post-instruction + // address when result of move takes + // effect. + MachineLocation Destination; // Move to location. + MachineLocation Source; // Move from location. + +public: + MachineMove() + : LabelID(0) + , Destination() + , Source() + {} + + MachineMove(unsigned ID, MachineLocation &D, MachineLocation &S) + : LabelID(ID) + , Destination(D) + , Source(S) + {} + + // Accessors + unsigned getLabelID() const { return LabelID; } + const MachineLocation &getDestination() const { return Destination; } + const MachineLocation &getSource() const { return Source; } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h new file mode 100644 index 0000000..778b75c --- /dev/null +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -0,0 +1,1280 @@ +//===-- llvm/CodeGen/MachineModuleInfo.h ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by James M. Laskey and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Collect meta information for a module. This information should be in a +// neutral form that can be used by different debugging and exception handling +// schemes. +// +// The organization of information is primarily clustered around the source +// compile units. The main exception is source line correspondence where +// inlining may interleave code from various compile units. +// +// The following information can be retrieved from the MachineModuleInfo. +// +// -- Source directories - Directories are uniqued based on their canonical +// string and assigned a sequential numeric ID (base 1.) +// -- Source files - Files are also uniqued based on their name and directory +// ID. A file ID is sequential number (base 1.) +// -- Source line correspondence - A vector of file ID, line#, column# triples. +// A DEBUG_LOCATION instruction is generated by the DAG Legalizer +// corresponding to each entry in the source line list. This allows a debug +// emitter to generate labels referenced by debug information tables. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEMODULEINFO_H +#define LLVM_CODEGEN_MACHINEMODULEINFO_H + +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/UniqueVector.h" +#include "llvm/GlobalValue.h" +#include "llvm/Pass.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +// Forward declarations. +class Constant; +class DebugInfoDesc; +class GlobalVariable; +class MachineBasicBlock; +class MachineFunction; +class MachineMove; +class Module; +class PointerType; +class StructType; + +//===----------------------------------------------------------------------===// +// Debug info constants. + +enum { + LLVMDebugVersion = (6 << 16), // Current version of debug information. + LLVMDebugVersion5 = (5 << 16), // Constant for version 5. + LLVMDebugVersion4 = (4 << 16), // Constant for version 4. + LLVMDebugVersionMask = 0xffff0000 // Mask for version number. +}; + +//===----------------------------------------------------------------------===// +/// DIVisitor - Subclasses of this class apply steps to each of the fields in +/// the supplied DebugInfoDesc. +class DIVisitor { +public: + DIVisitor() {} + virtual ~DIVisitor() {} + + /// ApplyToFields - Target the visitor to each field of the debug information + /// descriptor. + void ApplyToFields(DebugInfoDesc *DD); + + /// Apply - Subclasses override each of these methods to perform the + /// appropriate action for the type of field. + virtual void Apply(int &Field) = 0; + virtual void Apply(unsigned &Field) = 0; + virtual void Apply(int64_t &Field) = 0; + virtual void Apply(uint64_t &Field) = 0; + virtual void Apply(bool &Field) = 0; + virtual void Apply(std::string &Field) = 0; + virtual void Apply(DebugInfoDesc *&Field) = 0; + virtual void Apply(GlobalVariable *&Field) = 0; + virtual void Apply(std::vector<DebugInfoDesc *> &Field) = 0; +}; + +//===----------------------------------------------------------------------===// +/// DebugInfoDesc - This class is the base class for debug info descriptors. +/// +class DebugInfoDesc { +private: + unsigned Tag; // Content indicator. Dwarf values are + // used but that does not limit use to + // Dwarf writers. + +protected: + explicit DebugInfoDesc(unsigned T) : Tag(T | LLVMDebugVersion) {} + +public: + virtual ~DebugInfoDesc() {} + + // Accessors + unsigned getTag() const { return Tag & ~LLVMDebugVersionMask; } + unsigned getVersion() const { return Tag & LLVMDebugVersionMask; } + void setTag(unsigned T) { Tag = T | LLVMDebugVersion; } + + /// TagFromGlobal - Returns the tag number from a debug info descriptor + /// GlobalVariable. Return DIIValid if operand is not an unsigned int. + static unsigned TagFromGlobal(GlobalVariable *GV); + + /// VersionFromGlobal - Returns the version number from a debug info + /// descriptor GlobalVariable. Return DIIValid if operand is not an unsigned + /// int. + static unsigned VersionFromGlobal(GlobalVariable *GV); + + /// DescFactory - Create an instance of debug info descriptor based on Tag. + /// Return NULL if not a recognized Tag. + static DebugInfoDesc *DescFactory(unsigned Tag); + + /// getLinkage - get linkage appropriate for this type of descriptor. + /// + virtual GlobalValue::LinkageTypes getLinkage() const; + + //===--------------------------------------------------------------------===// + // Subclasses should supply the following static methods. + + // Implement isa/cast/dyncast. + static bool classof(const DebugInfoDesc *) { return true; } + + //===--------------------------------------------------------------------===// + // Subclasses should supply the following virtual methods. + + /// ApplyToFields - Target the vistor to the fields of the descriptor. + /// + virtual void ApplyToFields(DIVisitor *Visitor); + + /// getDescString - Return a string used to compose global names and labels. + /// + virtual const char *getDescString() const = 0; + + /// getTypeString - Return a string used to label this descriptor's type. + /// + virtual const char *getTypeString() const = 0; + +#ifndef NDEBUG + virtual void dump() = 0; +#endif +}; + +//===----------------------------------------------------------------------===// +/// AnchorDesc - Descriptors of this class act as markers for identifying +/// descriptors of certain groups. +class AnchoredDesc; +class AnchorDesc : public DebugInfoDesc { +private: + unsigned AnchorTag; // Tag number of descriptors anchored + // by this object. + +public: + AnchorDesc(); + AnchorDesc(AnchoredDesc *D); + + // Accessors + unsigned getAnchorTag() const { return AnchorTag; } + + // Implement isa/cast/dyncast. + static bool classof(const AnchorDesc *) { return true; } + static bool classof(const DebugInfoDesc *D); + + /// getLinkage - get linkage appropriate for this type of descriptor. + /// + virtual GlobalValue::LinkageTypes getLinkage() const; + + /// ApplyToFields - Target the visitor to the fields of the AnchorDesc. + /// + virtual void ApplyToFields(DIVisitor *Visitor); + + /// getDescString - Return a string used to compose global names and labels. + /// + virtual const char *getDescString() const; + + /// getTypeString - Return a string used to label this descriptor's type. + /// + virtual const char *getTypeString() const; + +#ifndef NDEBUG + virtual void dump(); +#endif +}; + +//===----------------------------------------------------------------------===// +/// AnchoredDesc - This class manages anchors for a variety of top level +/// descriptors. +class AnchoredDesc : public DebugInfoDesc { +private: + DebugInfoDesc *Anchor; // Anchor for all descriptors of the + // same type. + +protected: + + AnchoredDesc(unsigned T); + +public: + // Accessors. + AnchorDesc *getAnchor() const { return static_cast<AnchorDesc *>(Anchor); } + void setAnchor(AnchorDesc *A) { Anchor = static_cast<DebugInfoDesc *>(A); } + + //===--------------------------------------------------------------------===// + // Subclasses should supply the following virtual methods. + + /// getAnchorString - Return a string used to label descriptor's anchor. + /// + virtual const char *getAnchorString() const = 0; + + /// ApplyToFields - Target the visitor to the fields of the AnchoredDesc. + /// + virtual void ApplyToFields(DIVisitor *Visitor); +}; + +//===----------------------------------------------------------------------===// +/// CompileUnitDesc - This class packages debug information associated with a +/// source/header file. +class CompileUnitDesc : public AnchoredDesc { +private: + unsigned Language; // Language number (ex. DW_LANG_C89.) + std::string FileName; // Source file name. + std::string Directory; // Source file directory. + std::string Producer; // Compiler string. + +public: + CompileUnitDesc(); + + + // Accessors + unsigned getLanguage() const { return Language; } + const std::string &getFileName() const { return FileName; } + const std::string &getDirectory() const { return Directory; } + const std::string &getProducer() const { return Producer; } + void setLanguage(unsigned L) { Language = L; } + void setFileName(const std::string &FN) { FileName = FN; } + void setDirectory(const std::string &D) { Directory = D; } + void setProducer(const std::string &P) { Producer = P; } + + // FIXME - Need translation unit getter/setter. + + // Implement isa/cast/dyncast. + static bool classof(const CompileUnitDesc *) { return true; } + static bool classof(const DebugInfoDesc *D); + + /// ApplyToFields - Target the visitor to the fields of the CompileUnitDesc. + /// + virtual void ApplyToFields(DIVisitor *Visitor); + + /// getDescString - Return a string used to compose global names and labels. + /// + virtual const char *getDescString() const; + + /// getTypeString - Return a string used to label this descriptor's type. + /// + virtual const char *getTypeString() const; + + /// getAnchorString - Return a string used to label this descriptor's anchor. + /// + static const char *AnchorString; + virtual const char *getAnchorString() const; + +#ifndef NDEBUG + virtual void dump(); +#endif +}; + +//===----------------------------------------------------------------------===// +/// TypeDesc - This class packages debug information associated with a type. +/// +class TypeDesc : public DebugInfoDesc { +private: + enum { + FlagPrivate = 1 << 0, + FlagProtected = 1 << 1 + }; + DebugInfoDesc *Context; // Context debug descriptor. + std::string Name; // Type name (may be empty.) + DebugInfoDesc *File; // Defined compile unit (may be NULL.) + unsigned Line; // Defined line# (may be zero.) + uint64_t Size; // Type bit size (may be zero.) + uint64_t Align; // Type bit alignment (may be zero.) + uint64_t Offset; // Type bit offset (may be zero.) + unsigned Flags; // Miscellaneous flags. + +public: + TypeDesc(unsigned T); + + // Accessors + DebugInfoDesc *getContext() const { return Context; } + const std::string &getName() const { return Name; } + CompileUnitDesc *getFile() const { + return static_cast<CompileUnitDesc *>(File); + } + unsigned getLine() const { return Line; } + uint64_t getSize() const { return Size; } + uint64_t getAlign() const { return Align; } + uint64_t getOffset() const { return Offset; } + bool isPrivate() const { + return (Flags & FlagPrivate) != 0; + } + bool isProtected() const { + return (Flags & FlagProtected) != 0; + } + void setContext(DebugInfoDesc *C) { Context = C; } + void setName(const std::string &N) { Name = N; } + void setFile(CompileUnitDesc *U) { + File = static_cast<DebugInfoDesc *>(U); + } + void setLine(unsigned L) { Line = L; } + void setSize(uint64_t S) { Size = S; } + void setAlign(uint64_t A) { Align = A; } + void setOffset(uint64_t O) { Offset = O; } + void setIsPrivate() { Flags |= FlagPrivate; } + void setIsProtected() { Flags |= FlagProtected; } + + /// ApplyToFields - Target the visitor to the fields of the TypeDesc. + /// + virtual void ApplyToFields(DIVisitor *Visitor); + + /// getDescString - Return a string used to compose global names and labels. + /// + virtual const char *getDescString() const; + + /// getTypeString - Return a string used to label this descriptor's type. + /// + virtual const char *getTypeString() const; + +#ifndef NDEBUG + virtual void dump(); +#endif +}; + +//===----------------------------------------------------------------------===// +/// BasicTypeDesc - This class packages debug information associated with a +/// basic type (eg. int, bool, double.) +class BasicTypeDesc : public TypeDesc { +private: + unsigned Encoding; // Type encoding. + +public: + BasicTypeDesc(); + + // Accessors + unsigned getEncoding() const { return Encoding; } + void setEncoding(unsigned E) { Encoding = E; } + + // Implement isa/cast/dyncast. + static bool classof(const BasicTypeDesc *) { return true; } + static bool classof(const DebugInfoDesc *D); + + /// ApplyToFields - Target the visitor to the fields of the BasicTypeDesc. + /// + virtual void ApplyToFields(DIVisitor *Visitor); + + /// getDescString - Return a string used to compose global names and labels. + /// + virtual const char *getDescString() const; + + /// getTypeString - Return a string used to label this descriptor's type. + /// + virtual const char *getTypeString() const; + +#ifndef NDEBUG + virtual void dump(); +#endif +}; + + +//===----------------------------------------------------------------------===// +/// DerivedTypeDesc - This class packages debug information associated with a +/// derived types (eg., typedef, pointer, reference.) +class DerivedTypeDesc : public TypeDesc { +private: + DebugInfoDesc *FromType; // Type derived from. + +public: + DerivedTypeDesc(unsigned T); + + // Accessors + TypeDesc *getFromType() const { + return static_cast<TypeDesc *>(FromType); + } + void setFromType(TypeDesc *F) { + FromType = static_cast<DebugInfoDesc *>(F); + } + + // Implement isa/cast/dyncast. + static bool classof(const DerivedTypeDesc *) { return true; } + static bool classof(const DebugInfoDesc *D); + + /// ApplyToFields - Target the visitor to the fields of the DerivedTypeDesc. + /// + virtual void ApplyToFields(DIVisitor *Visitor); + + /// getDescString - Return a string used to compose global names and labels. + /// + virtual const char *getDescString() const; + + /// getTypeString - Return a string used to label this descriptor's type. + /// + virtual const char *getTypeString() const; + +#ifndef NDEBUG + virtual void dump(); +#endif +}; + +//===----------------------------------------------------------------------===// +/// CompositeTypeDesc - This class packages debug information associated with a +/// array/struct types (eg., arrays, struct, union, enums.) +class CompositeTypeDesc : public DerivedTypeDesc { +private: + std::vector<DebugInfoDesc *> Elements;// Information used to compose type. + +public: + CompositeTypeDesc(unsigned T); + + // Accessors + std::vector<DebugInfoDesc *> &getElements() { return Elements; } + + // Implement isa/cast/dyncast. + static bool classof(const CompositeTypeDesc *) { return true; } + static bool classof(const DebugInfoDesc *D); + + /// ApplyToFields - Target the visitor to the fields of the CompositeTypeDesc. + /// + virtual void ApplyToFields(DIVisitor *Visitor); + + /// getDescString - Return a string used to compose global names and labels. + /// + virtual const char *getDescString() const; + + /// getTypeString - Return a string used to label this descriptor's type. + /// + virtual const char *getTypeString() const; + +#ifndef NDEBUG + virtual void dump(); +#endif +}; + +//===----------------------------------------------------------------------===// +/// SubrangeDesc - This class packages debug information associated with integer +/// value ranges. +class SubrangeDesc : public DebugInfoDesc { +private: + int64_t Lo; // Low value of range. + int64_t Hi; // High value of range. + +public: + SubrangeDesc(); + + // Accessors + int64_t getLo() const { return Lo; } + int64_t getHi() const { return Hi; } + void setLo(int64_t L) { Lo = L; } + void setHi(int64_t H) { Hi = H; } + + // Implement isa/cast/dyncast. + static bool classof(const SubrangeDesc *) { return true; } + static bool classof(const DebugInfoDesc *D); + + /// ApplyToFields - Target the visitor to the fields of the SubrangeDesc. + /// + virtual void ApplyToFields(DIVisitor *Visitor); + + /// getDescString - Return a string used to compose global names and labels. + /// + virtual const char *getDescString() const; + + /// getTypeString - Return a string used to label this descriptor's type. + /// + virtual const char *getTypeString() const; + +#ifndef NDEBUG + virtual void dump(); +#endif +}; + +//===----------------------------------------------------------------------===// +/// EnumeratorDesc - This class packages debug information associated with +/// named integer constants. +class EnumeratorDesc : public DebugInfoDesc { +private: + std::string Name; // Enumerator name. + int64_t Value; // Enumerator value. + +public: + EnumeratorDesc(); + + // Accessors + const std::string &getName() const { return Name; } + int64_t getValue() const { return Value; } + void setName(const std::string &N) { Name = N; } + void setValue(int64_t V) { Value = V; } + + // Implement isa/cast/dyncast. + static bool classof(const EnumeratorDesc *) { return true; } + static bool classof(const DebugInfoDesc *D); + + /// ApplyToFields - Target the visitor to the fields of the EnumeratorDesc. + /// + virtual void ApplyToFields(DIVisitor *Visitor); + + /// getDescString - Return a string used to compose global names and labels. + /// + virtual const char *getDescString() const; + + /// getTypeString - Return a string used to label this descriptor's type. + /// + virtual const char *getTypeString() const; + +#ifndef NDEBUG + virtual void dump(); +#endif +}; + +//===----------------------------------------------------------------------===// +/// VariableDesc - This class packages debug information associated with a +/// subprogram variable. +/// +class VariableDesc : public DebugInfoDesc { +private: + DebugInfoDesc *Context; // Context debug descriptor. + std::string Name; // Type name (may be empty.) + DebugInfoDesc *File; // Defined compile unit (may be NULL.) + unsigned Line; // Defined line# (may be zero.) + DebugInfoDesc *TyDesc; // Type of variable. + +public: + VariableDesc(unsigned T); + + // Accessors + DebugInfoDesc *getContext() const { return Context; } + const std::string &getName() const { return Name; } + CompileUnitDesc *getFile() const { + return static_cast<CompileUnitDesc *>(File); + } + unsigned getLine() const { return Line; } + TypeDesc *getType() const { + return static_cast<TypeDesc *>(TyDesc); + } + void setContext(DebugInfoDesc *C) { Context = C; } + void setName(const std::string &N) { Name = N; } + void setFile(CompileUnitDesc *U) { + File = static_cast<DebugInfoDesc *>(U); + } + void setLine(unsigned L) { Line = L; } + void setType(TypeDesc *T) { + TyDesc = static_cast<DebugInfoDesc *>(T); + } + + // Implement isa/cast/dyncast. + static bool classof(const VariableDesc *) { return true; } + static bool classof(const DebugInfoDesc *D); + + /// ApplyToFields - Target the visitor to the fields of the VariableDesc. + /// + virtual void ApplyToFields(DIVisitor *Visitor); + + /// getDescString - Return a string used to compose global names and labels. + /// + virtual const char *getDescString() const; + + /// getTypeString - Return a string used to label this descriptor's type. + /// + virtual const char *getTypeString() const; + +#ifndef NDEBUG + virtual void dump(); +#endif +}; + +//===----------------------------------------------------------------------===// +/// GlobalDesc - This class is the base descriptor for global functions and +/// variables. +class GlobalDesc : public AnchoredDesc { +private: + DebugInfoDesc *Context; // Context debug descriptor. + std::string Name; // Global name. + std::string FullName; // Fully qualified name. + std::string LinkageName; // Name for binding to MIPS linkage. + DebugInfoDesc *File; // Defined compile unit (may be NULL.) + unsigned Line; // Defined line# (may be zero.) + DebugInfoDesc *TyDesc; // Type debug descriptor. + bool IsStatic; // Is the global a static. + bool IsDefinition; // Is the global defined in context. + +protected: + GlobalDesc(unsigned T); + +public: + // Accessors + DebugInfoDesc *getContext() const { return Context; } + const std::string &getName() const { return Name; } + const std::string &getFullName() const { return FullName; } + const std::string &getLinkageName() const { return LinkageName; } + CompileUnitDesc *getFile() const { + return static_cast<CompileUnitDesc *>(File); + } + unsigned getLine() const { return Line; } + TypeDesc *getType() const { + return static_cast<TypeDesc *>(TyDesc); + } + bool isStatic() const { return IsStatic; } + bool isDefinition() const { return IsDefinition; } + void setContext(DebugInfoDesc *C) { Context = C; } + void setName(const std::string &N) { Name = N; } + void setFullName(const std::string &N) { FullName = N; } + void setLinkageName(const std::string &N) { LinkageName = N; } + void setFile(CompileUnitDesc *U) { + File = static_cast<DebugInfoDesc *>(U); + } + void setLine(unsigned L) { Line = L; } + void setType(TypeDesc *T) { + TyDesc = static_cast<DebugInfoDesc *>(T); + } + void setIsStatic(bool IS) { IsStatic = IS; } + void setIsDefinition(bool ID) { IsDefinition = ID; } + + /// ApplyToFields - Target the visitor to the fields of the GlobalDesc. + /// + virtual void ApplyToFields(DIVisitor *Visitor); +}; + +//===----------------------------------------------------------------------===// +/// GlobalVariableDesc - This class packages debug information associated with a +/// GlobalVariable. +class GlobalVariableDesc : public GlobalDesc { +private: + GlobalVariable *Global; // llvm global. + +public: + GlobalVariableDesc(); + + // Accessors. + GlobalVariable *getGlobalVariable() const { return Global; } + void setGlobalVariable(GlobalVariable *GV) { Global = GV; } + + // Implement isa/cast/dyncast. + static bool classof(const GlobalVariableDesc *) { return true; } + static bool classof(const DebugInfoDesc *D); + + /// ApplyToFields - Target the visitor to the fields of the + /// GlobalVariableDesc. + virtual void ApplyToFields(DIVisitor *Visitor); + + /// getDescString - Return a string used to compose global names and labels. + /// + virtual const char *getDescString() const; + + /// getTypeString - Return a string used to label this descriptor's type. + /// + virtual const char *getTypeString() const; + + /// getAnchorString - Return a string used to label this descriptor's anchor. + /// + static const char *AnchorString; + virtual const char *getAnchorString() const; + +#ifndef NDEBUG + virtual void dump(); +#endif +}; + +//===----------------------------------------------------------------------===// +/// SubprogramDesc - This class packages debug information associated with a +/// subprogram/function. +class SubprogramDesc : public GlobalDesc { +private: + +public: + SubprogramDesc(); + + // Accessors + + // Implement isa/cast/dyncast. + static bool classof(const SubprogramDesc *) { return true; } + static bool classof(const DebugInfoDesc *D); + + /// ApplyToFields - Target the visitor to the fields of the SubprogramDesc. + /// + virtual void ApplyToFields(DIVisitor *Visitor); + + /// getDescString - Return a string used to compose global names and labels. + /// + virtual const char *getDescString() const; + + /// getTypeString - Return a string used to label this descriptor's type. + /// + virtual const char *getTypeString() const; + + /// getAnchorString - Return a string used to label this descriptor's anchor. + /// + static const char *AnchorString; + virtual const char *getAnchorString() const; + +#ifndef NDEBUG + virtual void dump(); +#endif +}; + +//===----------------------------------------------------------------------===// +/// BlockDesc - This descriptor groups variables and blocks nested in a block. +/// +class BlockDesc : public DebugInfoDesc { +private: + DebugInfoDesc *Context; // Context debug descriptor. + +public: + BlockDesc(); + + // Accessors + DebugInfoDesc *getContext() const { return Context; } + void setContext(DebugInfoDesc *C) { Context = C; } + + // Implement isa/cast/dyncast. + static bool classof(const BlockDesc *) { return true; } + static bool classof(const DebugInfoDesc *D); + + /// ApplyToFields - Target the visitor to the fields of the BlockDesc. + /// + virtual void ApplyToFields(DIVisitor *Visitor); + + /// getDescString - Return a string used to compose global names and labels. + /// + virtual const char *getDescString() const; + + /// getTypeString - Return a string used to label this descriptor's type. + /// + virtual const char *getTypeString() const; + +#ifndef NDEBUG + virtual void dump(); +#endif +}; + +//===----------------------------------------------------------------------===// +/// DIDeserializer - This class is responsible for casting GlobalVariables +/// into DebugInfoDesc objects. +class DIDeserializer { +private: + std::map<GlobalVariable *, DebugInfoDesc *> GlobalDescs; + // Previously defined gloabls. + +public: + DIDeserializer() {} + ~DIDeserializer() {} + + /// Deserialize - Reconstitute a GlobalVariable into it's component + /// DebugInfoDesc objects. + DebugInfoDesc *Deserialize(Value *V); + DebugInfoDesc *Deserialize(GlobalVariable *GV); +}; + +//===----------------------------------------------------------------------===// +/// DISerializer - This class is responsible for casting DebugInfoDesc objects +/// into GlobalVariables. +class DISerializer { +private: + Module *M; // Definition space module. + PointerType *StrPtrTy; // A "sbyte *" type. Created lazily. + PointerType *EmptyStructPtrTy; // A "{ }*" type. Created lazily. + std::map<unsigned, StructType *> TagTypes; + // Types per Tag. Created lazily. + std::map<DebugInfoDesc *, GlobalVariable *> DescGlobals; + // Previously defined descriptors. + std::map<const std::string, Constant *> StringCache; + // Previously defined strings. + +public: + DISerializer() + : M(NULL) + , StrPtrTy(NULL) + , EmptyStructPtrTy(NULL) + , TagTypes() + , DescGlobals() + , StringCache() + {} + ~DISerializer() {} + + // Accessors + Module *getModule() const { return M; }; + void setModule(Module *module) { M = module; } + + /// getStrPtrType - Return a "sbyte *" type. + /// + const PointerType *getStrPtrType(); + + /// getEmptyStructPtrType - Return a "{ }*" type. + /// + const PointerType *getEmptyStructPtrType(); + + /// getTagType - Return the type describing the specified descriptor (via + /// tag.) + const StructType *getTagType(DebugInfoDesc *DD); + + /// getString - Construct the string as constant string global. + /// + Constant *getString(const std::string &String); + + /// Serialize - Recursively cast the specified descriptor into a + /// GlobalVariable so that it can be serialized to a .bc or .ll file. + GlobalVariable *Serialize(DebugInfoDesc *DD); +}; + +//===----------------------------------------------------------------------===// +/// DIVerifier - This class is responsible for verifying the given network of +/// GlobalVariables are valid as DebugInfoDesc objects. +class DIVerifier { +private: + enum { + Unknown = 0, + Invalid, + Valid + }; + std::map<GlobalVariable *, unsigned> Validity;// Tracks prior results. + std::map<unsigned, unsigned> Counts; // Count of fields per Tag type. + +public: + DIVerifier() + : Validity() + , Counts() + {} + ~DIVerifier() {} + + /// Verify - Return true if the GlobalVariable appears to be a valid + /// serialization of a DebugInfoDesc. + bool Verify(Value *V); + bool Verify(GlobalVariable *GV); +}; + +//===----------------------------------------------------------------------===// +/// SourceLineInfo - This class is used to record source line correspondence. +/// +class SourceLineInfo { +private: + unsigned Line; // Source line number. + unsigned Column; // Source column. + unsigned SourceID; // Source ID number. + unsigned LabelID; // Label in code ID number. + +public: + SourceLineInfo(unsigned L, unsigned C, unsigned S, unsigned I) + : Line(L), Column(C), SourceID(S), LabelID(I) {} + + // Accessors + unsigned getLine() const { return Line; } + unsigned getColumn() const { return Column; } + unsigned getSourceID() const { return SourceID; } + unsigned getLabelID() const { return LabelID; } +}; + +//===----------------------------------------------------------------------===// +/// SourceFileInfo - This class is used to track source information. +/// +class SourceFileInfo { +private: + unsigned DirectoryID; // Directory ID number. + std::string Name; // File name (not including directory.) + +public: + SourceFileInfo(unsigned D, const std::string &N) : DirectoryID(D), Name(N) {} + + // Accessors + unsigned getDirectoryID() const { return DirectoryID; } + const std::string &getName() const { return Name; } + + /// operator== - Used by UniqueVector to locate entry. + /// + bool operator==(const SourceFileInfo &SI) const { + return getDirectoryID() == SI.getDirectoryID() && getName() == SI.getName(); + } + + /// operator< - Used by UniqueVector to locate entry. + /// + bool operator<(const SourceFileInfo &SI) const { + return getDirectoryID() < SI.getDirectoryID() || + (getDirectoryID() == SI.getDirectoryID() && getName() < SI.getName()); + } +}; + +//===----------------------------------------------------------------------===// +/// DebugVariable - This class is used to track local variable information. +/// +class DebugVariable { +private: + VariableDesc *Desc; // Variable Descriptor. + unsigned FrameIndex; // Variable frame index. + +public: + DebugVariable(VariableDesc *D, unsigned I) + : Desc(D) + , FrameIndex(I) + {} + + // Accessors. + VariableDesc *getDesc() const { return Desc; } + unsigned getFrameIndex() const { return FrameIndex; } +}; + +//===----------------------------------------------------------------------===// +/// DebugScope - This class is used to track scope information. +/// +class DebugScope { +private: + DebugScope *Parent; // Parent to this scope. + DebugInfoDesc *Desc; // Debug info descriptor for scope. + // Either subprogram or block. + unsigned StartLabelID; // Label ID of the beginning of scope. + unsigned EndLabelID; // Label ID of the end of scope. + std::vector<DebugScope *> Scopes; // Scopes defined in scope. + std::vector<DebugVariable *> Variables;// Variables declared in scope. + +public: + DebugScope(DebugScope *P, DebugInfoDesc *D) + : Parent(P) + , Desc(D) + , StartLabelID(0) + , EndLabelID(0) + , Scopes() + , Variables() + {} + ~DebugScope(); + + // Accessors. + DebugScope *getParent() const { return Parent; } + DebugInfoDesc *getDesc() const { return Desc; } + unsigned getStartLabelID() const { return StartLabelID; } + unsigned getEndLabelID() const { return EndLabelID; } + std::vector<DebugScope *> &getScopes() { return Scopes; } + std::vector<DebugVariable *> &getVariables() { return Variables; } + void setStartLabelID(unsigned S) { StartLabelID = S; } + void setEndLabelID(unsigned E) { EndLabelID = E; } + + /// AddScope - Add a scope to the scope. + /// + void AddScope(DebugScope *S) { Scopes.push_back(S); } + + /// AddVariable - Add a variable to the scope. + /// + void AddVariable(DebugVariable *V) { Variables.push_back(V); } +}; + +//===----------------------------------------------------------------------===// +/// LandingPadInfo - This structure is used to retain landing pad info for +/// the current function. +/// +struct LandingPadInfo { + MachineBasicBlock *LandingPadBlock; // Landing pad block. + SmallVector<unsigned, 1> BeginLabels; // Labels prior to invoke. + SmallVector<unsigned, 1> EndLabels; // Labels after invoke. + unsigned LandingPadLabel; // Label at beginning of landing pad. + Function *Personality; // Personality function. + std::vector<int> TypeIds; // List of type ids (filters negative) + + LandingPadInfo(MachineBasicBlock *MBB) + : LandingPadBlock(MBB) + , LandingPadLabel(0) + , Personality(NULL) + , TypeIds(1, 0) // Always have cleanups + {} +}; + +//===----------------------------------------------------------------------===// +/// MachineModuleInfo - This class contains meta information specific to a +/// module. Queries can be made by different debugging and exception handling +/// schemes and reformated for specific use. +/// +class MachineModuleInfo : public ImmutablePass { +private: + // Use the same deserializer/verifier for the module. + DIDeserializer DR; + DIVerifier VR; + + // CompileUnits - Uniquing vector for compile units. + UniqueVector<CompileUnitDesc *> CompileUnits; + + // Directories - Uniquing vector for directories. + UniqueVector<std::string> Directories; + + // SourceFiles - Uniquing vector for source files. + UniqueVector<SourceFileInfo> SourceFiles; + + // Lines - List of of source line correspondence. + std::vector<SourceLineInfo> Lines; + + // LabelIDList - One entry per assigned label. Normally the entry is equal to + // the list index(+1). If the entry is zero then the label has been deleted. + // Any other value indicates the label has been deleted by is mapped to + // another label. + std::vector<unsigned> LabelIDList; + + // ScopeMap - Tracks the scopes in the current function. + std::map<DebugInfoDesc *, DebugScope *> ScopeMap; + + // RootScope - Top level scope for the current function. + // + DebugScope *RootScope; + + // FrameMoves - List of moves done by a function's prolog. Used to construct + // frame maps by debug and exception handling consumers. + std::vector<MachineMove> FrameMoves; + + // LandingPads - List of LandingPadInfo describing the landing pad information + // in the current function. + std::vector<LandingPadInfo> LandingPads; + + // TypeInfos - List of C++ TypeInfo used in the current function. + // + std::vector<GlobalVariable *> TypeInfos; + + // FilterIds - List of typeids encoding filters used in the current function. + // + std::vector<unsigned> FilterIds; + + // FilterEnds - List of the indices in FilterIds corresponding to filter + // terminators. + // + std::vector<unsigned> FilterEnds; + + // Personalities - Vector of all personality functions ever seen. Used to emit + // common EH frames. + std::vector<Function *> Personalities; + + bool CallsEHReturn; + bool CallsUnwindInit; +public: + static char ID; // Pass identification, replacement for typeid + + MachineModuleInfo(); + ~MachineModuleInfo(); + + /// doInitialization - Initialize the state for a new module. + /// + bool doInitialization(); + + /// doFinalization - Tear down the state after completion of a module. + /// + bool doFinalization(); + + /// BeginFunction - Begin gathering function meta information. + /// + void BeginFunction(MachineFunction *MF); + + /// EndFunction - Discard function meta information. + /// + void EndFunction(); + + /// getDescFor - Convert a Value to a debug information descriptor. + /// + // FIXME - use new Value type when available. + DebugInfoDesc *getDescFor(Value *V); + + /// Verify - Verify that a Value is debug information descriptor. + /// + bool Verify(Value *V); + + /// AnalyzeModule - Scan the module for global debug information. + /// + void AnalyzeModule(Module &M); + + /// hasDebugInfo - Returns true if valid debug info is present. + /// + bool hasDebugInfo() const { return !CompileUnits.empty(); } + + /// needsFrameInfo - Returns true if we need to gather callee-saved register + /// move info for the frame. + bool needsFrameInfo() const; + + bool callsEHReturn() const { return CallsEHReturn; } + void setCallsEHReturn(bool b) { CallsEHReturn = b; } + + bool callsUnwindInit() const { return CallsUnwindInit; } + void setCallsUnwindInit(bool b) { CallsUnwindInit = b; } + + /// NextLabelID - Return the next unique label id. + /// + unsigned NextLabelID() { + unsigned ID = LabelIDList.size() + 1; + LabelIDList.push_back(ID); + return ID; + } + + /// RecordLabel - Records location information and associates it with a + /// label. Returns a unique label ID used to generate a label and + /// provide correspondence to the source line list. + unsigned RecordLabel(unsigned Line, unsigned Column, unsigned Source); + + /// InvalidateLabel - Inhibit use of the specified label # from + /// MachineModuleInfo, for example because the code was deleted. + void InvalidateLabel(unsigned LabelID) { + // Remap to zero to indicate deletion. + RemapLabel(LabelID, 0); + } + + /// RemapLabel - Indicate that a label has been merged into another. + /// + void RemapLabel(unsigned OldLabelID, unsigned NewLabelID) { + assert(0 < OldLabelID && OldLabelID <= LabelIDList.size() && + "Old label ID out of range."); + assert(NewLabelID <= LabelIDList.size() && + "New label ID out of range."); + LabelIDList[OldLabelID - 1] = NewLabelID; + } + + /// MappedLabel - Find out the label's final ID. Zero indicates deletion. + /// ID != Mapped ID indicates that the label was folded into another label. + unsigned MappedLabel(unsigned LabelID) const { + assert(LabelID <= LabelIDList.size() && "Debug label ID out of range."); + return LabelID ? LabelIDList[LabelID - 1] : 0; + } + + /// RecordSource - Register a source file with debug info. Returns an source + /// ID. + unsigned RecordSource(const std::string &Directory, + const std::string &Source); + unsigned RecordSource(const CompileUnitDesc *CompileUnit); + + /// getDirectories - Return the UniqueVector of std::string representing + /// directories. + const UniqueVector<std::string> &getDirectories() const { + return Directories; + } + + /// getSourceFiles - Return the UniqueVector of source files. + /// + const UniqueVector<SourceFileInfo> &getSourceFiles() const { + return SourceFiles; + } + + /// getSourceLines - Return a vector of source lines. + /// + const std::vector<SourceLineInfo> &getSourceLines() const { + return Lines; + } + + /// SetupCompileUnits - Set up the unique vector of compile units. + /// + void SetupCompileUnits(Module &M); + + /// getCompileUnits - Return a vector of debug compile units. + /// + const UniqueVector<CompileUnitDesc *> getCompileUnits() const; + + /// getGlobalVariablesUsing - Return all of the GlobalVariables that use the + /// named GlobalVariable. + std::vector<GlobalVariable*> + getGlobalVariablesUsing(Module &M, const std::string &RootName); + + /// getAnchoredDescriptors - Return a vector of anchored debug descriptors. + /// + template <class T>std::vector<T *> getAnchoredDescriptors(Module &M) { + T Desc; + std::vector<GlobalVariable *> Globals = + getGlobalVariablesUsing(M, Desc.getAnchorString()); + std::vector<T *> AnchoredDescs; + for (unsigned i = 0, N = Globals.size(); i < N; ++i) { + GlobalVariable *GV = Globals[i]; + + // FIXME - In the short term, changes are too drastic to continue. + if (DebugInfoDesc::TagFromGlobal(GV) == Desc.getTag() && + DebugInfoDesc::VersionFromGlobal(GV) == LLVMDebugVersion) { + AnchoredDescs.push_back(cast<T>(DR.Deserialize(GV))); + } + } + + return AnchoredDescs; + } + + /// RecordRegionStart - Indicate the start of a region. + /// + unsigned RecordRegionStart(Value *V); + + /// RecordRegionEnd - Indicate the end of a region. + /// + unsigned RecordRegionEnd(Value *V); + + /// RecordVariable - Indicate the declaration of a local variable. + /// + void RecordVariable(Value *V, unsigned FrameIndex); + + /// getRootScope - Return current functions root scope. + /// + DebugScope *getRootScope() { return RootScope; } + + /// getOrCreateScope - Returns the scope associated with the given descriptor. + /// + DebugScope *getOrCreateScope(DebugInfoDesc *ScopeDesc); + + /// getFrameMoves - Returns a reference to a list of moves done in the current + /// function's prologue. Used to construct frame maps for debug and exception + /// handling comsumers. + std::vector<MachineMove> &getFrameMoves() { return FrameMoves; } + + //===-EH-----------------------------------------------------------------===// + + /// getOrCreateLandingPadInfo - Find or create an LandingPadInfo for the + /// specified MachineBasicBlock. + LandingPadInfo &getOrCreateLandingPadInfo(MachineBasicBlock *LandingPad); + + /// addInvoke - Provide the begin and end labels of an invoke style call and + /// associate it with a try landing pad block. + void addInvoke(MachineBasicBlock *LandingPad, unsigned BeginLabel, + unsigned EndLabel); + + /// addLandingPad - Add a new panding pad. Returns the label ID for the + /// landing pad entry. + unsigned addLandingPad(MachineBasicBlock *LandingPad); + + /// addPersonality - Provide the personality function for the exception + /// information. + void addPersonality(MachineBasicBlock *LandingPad, Function *Personality); + + /// getPersonalityIndex - Get index of the current personality function inside + /// Personalitites array + unsigned getPersonalityIndex() const; + + /// getPersonalities - Return array of personality functions ever seen. + const std::vector<Function *>& getPersonalities() const { + return Personalities; + } + + /// addCatchTypeInfo - Provide the catch typeinfo for a landing pad. + /// + void addCatchTypeInfo(MachineBasicBlock *LandingPad, + std::vector<GlobalVariable *> &TyInfo); + + /// addFilterTypeInfo - Provide the filter typeinfo for a landing pad. + /// + void addFilterTypeInfo(MachineBasicBlock *LandingPad, + std::vector<GlobalVariable *> &TyInfo); + + /// getTypeIDFor - Return the type id for the specified typeinfo. This is + /// function wide. + unsigned getTypeIDFor(GlobalVariable *TI); + + /// getFilterIDFor - Return the id of the filter encoded by TyIds. This is + /// function wide. + int getFilterIDFor(std::vector<unsigned> &TyIds); + + /// TidyLandingPads - Remap landing pad labels and remove any deleted landing + /// pads. + void TidyLandingPads(); + + /// getLandingPads - Return a reference to the landing pad info for the + /// current function. + const std::vector<LandingPadInfo> &getLandingPads() const { + return LandingPads; + } + + /// getTypeInfos - Return a reference to the C++ typeinfo for the current + /// function. + const std::vector<GlobalVariable *> &getTypeInfos() const { + return TypeInfos; + } + + /// getFilterIds - Return a reference to the typeids encoding filters used in + /// the current function. + const std::vector<unsigned> &getFilterIds() const { + return FilterIds; + } + + /// getPersonality - Return a personality function if available. The presence + /// of one is required to emit exception handling info. + Function *getPersonality() const; + +}; // End class MachineModuleInfo + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/MachinePassRegistry.h b/include/llvm/CodeGen/MachinePassRegistry.h new file mode 100644 index 0000000..4bb34b0 --- /dev/null +++ b/include/llvm/CodeGen/MachinePassRegistry.h @@ -0,0 +1,156 @@ +//===-- llvm/CodeGen/MachinePassRegistry.h ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the James M. Laskey and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the mechanics for machine function pass registries. A +// function pass registry (MachinePassRegistry) is auto filled by the static +// constructors of MachinePassRegistryNode. Further there is a command line +// parser (RegisterPassParser) which listens to each registry for additions +// and deletions, so that the appropriate command option is updated. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINEPASSREGISTRY_H +#define LLVM_CODEGEN_MACHINEPASSREGISTRY_H + +#include "llvm/CodeGen/Passes.h" +#include "llvm/Support/CommandLine.h" + +namespace llvm { + +typedef void *(*MachinePassCtor)(); + + +//===----------------------------------------------------------------------===// +/// +/// MachinePassRegistryListener - Listener to adds and removals of nodes in +/// registration list. +/// +//===----------------------------------------------------------------------===// +class MachinePassRegistryListener { +public: + MachinePassRegistryListener() {} + virtual ~MachinePassRegistryListener() {} + virtual void NotifyAdd(const char *N, MachinePassCtor C, const char *D) = 0; + virtual void NotifyRemove(const char *N) = 0; +}; + + +//===----------------------------------------------------------------------===// +/// +/// MachinePassRegistryNode - Machine pass node stored in registration list. +/// +//===----------------------------------------------------------------------===// +class MachinePassRegistryNode { + +private: + + MachinePassRegistryNode *Next; // Next function pass in list. + const char *Name; // Name of function pass. + const char *Description; // Description string. + MachinePassCtor Ctor; // Function pass creator. + +public: + + MachinePassRegistryNode(const char *N, const char *D, MachinePassCtor C) + : Next(NULL) + , Name(N) + , Description(D) + , Ctor(C) + {} + + // Accessors + MachinePassRegistryNode *getNext() const { return Next; } + MachinePassRegistryNode **getNextAddress() { return &Next; } + const char *getName() const { return Name; } + const char *getDescription() const { return Description; } + MachinePassCtor getCtor() const { return Ctor; } + void setNext(MachinePassRegistryNode *N) { Next = N; } + +}; + + +//===----------------------------------------------------------------------===// +/// +/// MachinePassRegistry - Track the registration of machine passes. +/// +//===----------------------------------------------------------------------===// +class MachinePassRegistry { + +private: + + MachinePassRegistryNode *List; // List of registry nodes. + MachinePassCtor Default; // Default function pass creator. + MachinePassRegistryListener* Listener;// Listener for list adds are removes. + +public: + + // NO CONSTRUCTOR - we don't want static constructor ordering to mess + // with the registry. + + // Accessors. + // + MachinePassRegistryNode *getList() { return List; } + MachinePassCtor getDefault() { return Default; } + void setDefault(MachinePassCtor C) { Default = C; } + void setListener(MachinePassRegistryListener *L) { Listener = L; } + + /// Add - Adds a function pass to the registration list. + /// + void Add(MachinePassRegistryNode *Node); + + /// Remove - Removes a function pass from the registration list. + /// + void Remove(MachinePassRegistryNode *Node); + +}; + + +//===----------------------------------------------------------------------===// +/// +/// RegisterPassParser class - Handle the addition of new machine passes. +/// +//===----------------------------------------------------------------------===// +template<class RegistryClass> +class RegisterPassParser : public MachinePassRegistryListener, + public cl::parser<typename RegistryClass::FunctionPassCtor> { +public: + RegisterPassParser() {} + ~RegisterPassParser() { RegistryClass::setListener(NULL); } + + void initialize(cl::Option &O) { + cl::parser<typename RegistryClass::FunctionPassCtor>::initialize(O); + + // Add existing passes to option. + for (RegistryClass *Node = RegistryClass::getList(); + Node; Node = Node->getNext()) { + addLiteralOption(Node->getName(), + (typename RegistryClass::FunctionPassCtor)Node->getCtor(), + Node->getDescription()); + } + + // Make sure we listen for list changes. + RegistryClass::setListener(this); + } + + // Implement the MachinePassRegistryListener callbacks. + // + virtual void NotifyAdd(const char *N, + MachinePassCtor C, + const char *D) { + this->addLiteralOption(N, (typename RegistryClass::FunctionPassCtor)C, D); + } + virtual void NotifyRemove(const char *N) { + this->removeLiteralOption(N); + } +}; + + +} // end namespace llvm + +#endif diff --git a/include/llvm/CodeGen/MachineRelocation.h b/include/llvm/CodeGen/MachineRelocation.h new file mode 100644 index 0000000..364b8b1 --- /dev/null +++ b/include/llvm/CodeGen/MachineRelocation.h @@ -0,0 +1,298 @@ +//===-- llvm/CodeGen/MachineRelocation.h - Target Relocation ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the MachineRelocation class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_MACHINERELOCATION_H +#define LLVM_CODEGEN_MACHINERELOCATION_H + +#include "llvm/Support/DataTypes.h" +#include <cassert> + +namespace llvm { +class GlobalValue; +class MachineBasicBlock; + +/// MachineRelocation - This represents a target-specific relocation value, +/// produced by the code emitter. This relocation is resolved after the has +/// been emitted, either to an object file or to memory, when the target of the +/// relocation can be resolved. +/// +/// A relocation is made up of the following logical portions: +/// 1. An offset in the machine code buffer, the location to modify. +/// 2. A target specific relocation type (a number from 0 to 63). +/// 3. A symbol being referenced, either as a GlobalValue* or as a string. +/// 4. An optional constant value to be added to the reference. +/// 5. A bit, CanRewrite, which indicates to the JIT that a function stub is +/// not needed for the relocation. +/// 6. An index into the GOT, if the target uses a GOT +/// +class MachineRelocation { + enum AddressType { + isResult, // Relocation has be transformed into its result pointer. + isGV, // The Target.GV field is valid. + isBB, // Relocation of BB address. + isExtSym, // The Target.ExtSym field is valid. + isConstPool, // Relocation of constant pool address. + isJumpTable, // Relocation of jump table address. + isGOTIndex // The Target.GOTIndex field is valid. + }; + + /// Offset - This is the offset from the start of the code buffer of the + /// relocation to perform. + intptr_t Offset; + + /// ConstantVal - A field that may be used by the target relocation type. + intptr_t ConstantVal; + + union { + void *Result; // If this has been resolved to a resolved pointer + GlobalValue *GV; // If this is a pointer to an LLVM global + MachineBasicBlock *MBB; // If this is a pointer to a LLVM BB + const char *ExtSym; // If this is a pointer to a named symbol + unsigned Index; // Constant pool / jump table index + unsigned GOTIndex; // Index in the GOT of this symbol/global + } Target; + + unsigned TargetReloType : 6; // The target relocation ID. + AddressType AddrType : 4; // The field of Target to use. + bool DoesntNeedFnStub : 1; // True if we don't need a fn stub. + bool GOTRelative : 1; // Should this relocation be relative to the GOT? + +public: + // Relocation types used in a generic implementation. Currently, relocation + // entries for all things use the generic VANILLA type until they are refined + // into target relocation types. + enum RelocationType { + VANILLA + }; + + /// MachineRelocation::getGV - Return a relocation entry for a GlobalValue. + /// + static MachineRelocation getGV(intptr_t offset, unsigned RelocationType, + GlobalValue *GV, intptr_t cst = 0, + bool DoesntNeedFunctionStub = 0, + bool GOTrelative = 0) { + assert((RelocationType & ~63) == 0 && "Relocation type too large!"); + MachineRelocation Result; + Result.Offset = offset; + Result.ConstantVal = cst; + Result.TargetReloType = RelocationType; + Result.AddrType = isGV; + Result.DoesntNeedFnStub = DoesntNeedFunctionStub; + Result.GOTRelative = GOTrelative; + Result.Target.GV = GV; + return Result; + } + + /// MachineRelocation::getBB - Return a relocation entry for a BB. + /// + static MachineRelocation getBB(intptr_t offset,unsigned RelocationType, + MachineBasicBlock *MBB, intptr_t cst = 0) { + assert((RelocationType & ~63) == 0 && "Relocation type too large!"); + MachineRelocation Result; + Result.Offset = offset; + Result.ConstantVal = cst; + Result.TargetReloType = RelocationType; + Result.AddrType = isBB; + Result.DoesntNeedFnStub = false; + Result.GOTRelative = false; + Result.Target.MBB = MBB; + return Result; + } + + /// MachineRelocation::getExtSym - Return a relocation entry for an external + /// symbol, like "free". + /// + static MachineRelocation getExtSym(intptr_t offset, unsigned RelocationType, + const char *ES, intptr_t cst = 0, + bool GOTrelative = 0) { + assert((RelocationType & ~63) == 0 && "Relocation type too large!"); + MachineRelocation Result; + Result.Offset = offset; + Result.ConstantVal = cst; + Result.TargetReloType = RelocationType; + Result.AddrType = isExtSym; + Result.DoesntNeedFnStub = false; + Result.GOTRelative = GOTrelative; + Result.Target.ExtSym = ES; + return Result; + } + + /// MachineRelocation::getConstPool - Return a relocation entry for a constant + /// pool entry. + /// + static MachineRelocation getConstPool(intptr_t offset,unsigned RelocationType, + unsigned CPI, intptr_t cst = 0) { + assert((RelocationType & ~63) == 0 && "Relocation type too large!"); + MachineRelocation Result; + Result.Offset = offset; + Result.ConstantVal = cst; + Result.TargetReloType = RelocationType; + Result.AddrType = isConstPool; + Result.DoesntNeedFnStub = false; + Result.GOTRelative = false; + Result.Target.Index = CPI; + return Result; + } + + /// MachineRelocation::getJumpTable - Return a relocation entry for a jump + /// table entry. + /// + static MachineRelocation getJumpTable(intptr_t offset,unsigned RelocationType, + unsigned JTI, intptr_t cst = 0) { + assert((RelocationType & ~63) == 0 && "Relocation type too large!"); + MachineRelocation Result; + Result.Offset = offset; + Result.ConstantVal = cst; + Result.TargetReloType = RelocationType; + Result.AddrType = isJumpTable; + Result.DoesntNeedFnStub = false; + Result.GOTRelative = false; + Result.Target.Index = JTI; + return Result; + } + + /// getMachineCodeOffset - Return the offset into the code buffer that the + /// relocation should be performed. + intptr_t getMachineCodeOffset() const { + return Offset; + } + + /// getRelocationType - Return the target-specific relocation ID for this + /// relocation. + unsigned getRelocationType() const { + return TargetReloType; + } + + /// getConstantVal - Get the constant value associated with this relocation. + /// This is often an offset from the symbol. + /// + intptr_t getConstantVal() const { + return ConstantVal; + } + + /// setConstantVal - Set the constant value associated with this relocation. + /// This is often an offset from the symbol. + /// + void setConstantVal(intptr_t val) { + ConstantVal = val; + } + + /// isGlobalValue - Return true if this relocation is a GlobalValue, as + /// opposed to a constant string. + bool isGlobalValue() const { + return AddrType == isGV; + } + + /// isBasicBlock - Return true if this relocation is a basic block reference. + /// + bool isBasicBlock() const { + return AddrType == isBB; + } + + /// isString - Return true if this is a constant string. + /// + bool isString() const { + return AddrType == isExtSym; + } + + /// isConstantPoolIndex - Return true if this is a constant pool reference. + /// + bool isConstantPoolIndex() const { + return AddrType == isConstPool; + } + + /// isJumpTableIndex - Return true if this is a jump table reference. + /// + bool isJumpTableIndex() const { + return AddrType == isJumpTable; + } + + /// isGOTRelative - Return true the target wants the index into the GOT of + /// the symbol rather than the address of the symbol. + bool isGOTRelative() const { + return GOTRelative; + } + + /// doesntNeedFunctionStub - This function returns true if the JIT for this + /// target is capable of directly handling the relocated instruction without + /// using a stub function. It is always conservatively correct for this flag + /// to be false, but targets can improve their compilation callback functions + /// to handle more general cases if they want improved performance. + bool doesntNeedFunctionStub() const { + return DoesntNeedFnStub; + } + + /// getGlobalValue - If this is a global value reference, return the + /// referenced global. + GlobalValue *getGlobalValue() const { + assert(isGlobalValue() && "This is not a global value reference!"); + return Target.GV; + } + + MachineBasicBlock *getBasicBlock() const { + assert(isBasicBlock() && "This is not a basic block reference!"); + return Target.MBB; + } + + /// getString - If this is a string value, return the string reference. + /// + const char *getString() const { + assert(isString() && "This is not a string reference!"); + return Target.ExtSym; + } + + /// getConstantPoolIndex - If this is a const pool reference, return + /// the index into the constant pool. + unsigned getConstantPoolIndex() const { + assert(isConstantPoolIndex() && "This is not a constant pool reference!"); + return Target.Index; + } + + /// getJumpTableIndex - If this is a jump table reference, return + /// the index into the jump table. + unsigned getJumpTableIndex() const { + assert(isJumpTableIndex() && "This is not a jump table reference!"); + return Target.Index; + } + + /// getResultPointer - Once this has been resolved to point to an actual + /// address, this returns the pointer. + void *getResultPointer() const { + assert(AddrType == isResult && "Result pointer isn't set yet!"); + return Target.Result; + } + + /// setResultPointer - Set the result to the specified pointer value. + /// + void setResultPointer(void *Ptr) { + Target.Result = Ptr; + AddrType = isResult; + } + + /// setGOTIndex - Set the GOT index to a specific value. + void setGOTIndex(unsigned idx) { + AddrType = isGOTIndex; + Target.GOTIndex = idx; + } + + /// getGOTIndex - Once this has been resolved to an entry in the GOT, + /// this returns that index. The index is from the lowest address entry + /// in the GOT. + unsigned getGOTIndex() const { + assert(AddrType == isGOTIndex); + return Target.GOTIndex; + } +}; +} + +#endif diff --git a/include/llvm/CodeGen/Passes.h b/include/llvm/CodeGen/Passes.h new file mode 100644 index 0000000..eda6a5d --- /dev/null +++ b/include/llvm/CodeGen/Passes.h @@ -0,0 +1,120 @@ +//===-- Passes.h - Target independent code generation passes ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines interfaces to access the target independent code generation +// passes provided by the LLVM backend. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_PASSES_H +#define LLVM_CODEGEN_PASSES_H + +#include <iosfwd> +#include <string> + +namespace llvm { + + class FunctionPass; + class PassInfo; + class TargetMachine; + + /// createUnreachableBlockEliminationPass - The LLVM code generator does not + /// work well with unreachable basic blocks (what live ranges make sense for a + /// block that cannot be reached?). As such, a code generator should either + /// not instruction select unreachable blocks, or it can run this pass as it's + /// last LLVM modifying pass to clean up blocks that are not reachable from + /// the entry block. + FunctionPass *createUnreachableBlockEliminationPass(); + + /// MachineFunctionPrinter pass - This pass prints out the machine function to + /// standard error, as a debugging tool. + FunctionPass *createMachineFunctionPrinterPass(std::ostream *OS, + const std::string &Banner =""); + + /// PHIElimination pass - This pass eliminates machine instruction PHI nodes + /// by inserting copy instructions. This destroys SSA information, but is the + /// desired input for some register allocators. This pass is "required" by + /// these register allocator like this: AU.addRequiredID(PHIEliminationID); + /// + extern const PassInfo *PHIEliminationID; + + /// SimpleRegisterCoalescing pass. Aggressively coalesces every register + /// copy it can. + /// + extern const PassInfo *SimpleRegisterCoalescingID; + + /// TwoAddressInstruction pass - This pass reduces two-address instructions to + /// use two operands. This destroys SSA information but it is desired by + /// register allocators. + extern const PassInfo *TwoAddressInstructionPassID; + + /// Creates a register allocator as the user specified on the command line. + /// + FunctionPass *createRegisterAllocator(); + + /// SimpleRegisterAllocation Pass - This pass converts the input machine code + /// from SSA form to use explicit registers by spilling every register. Wow, + /// great policy huh? + /// + FunctionPass *createSimpleRegisterAllocator(); + + /// LocalRegisterAllocation Pass - This pass register allocates the input code + /// a basic block at a time, yielding code better than the simple register + /// allocator, but not as good as a global allocator. + /// + FunctionPass *createLocalRegisterAllocator(); + + /// BigBlockRegisterAllocation Pass - The BigBlock register allocator + /// munches single basic blocks at a time, like the local register + /// allocator. While the BigBlock allocator is a little slower, and uses + /// somewhat more memory than the local register allocator, it tends to + /// yield the best allocations (of any of the allocators) for blocks that + /// have hundreds or thousands of instructions in sequence. + /// + FunctionPass *createBigBlockRegisterAllocator(); + + /// LinearScanRegisterAllocation Pass - This pass implements the linear scan + /// register allocation algorithm, a global register allocator. + /// + FunctionPass *createLinearScanRegisterAllocator(); + + /// PrologEpilogCodeInserter Pass - This pass inserts prolog and epilog code, + /// and eliminates abstract frame references. + /// + FunctionPass *createPrologEpilogCodeInserter(); + + /// createPostRAScheduler - under development. + FunctionPass *createPostRAScheduler(); + + /// BranchFolding Pass - This pass performs machine code CFG based + /// optimizations to delete branches to branches, eliminate branches to + /// successor blocks (creating fall throughs), and eliminating branches over + /// branches. + FunctionPass *createBranchFoldingPass(bool DefaultEnableTailMerge); + + /// IfConverter Pass - This pass performs machine code if conversion. + FunctionPass *createIfConverterPass(); + + /// DebugLabelFoldingPass - This pass prunes out redundant debug labels. This + /// allows a debug emitter to determine if the range of two labels is empty, + /// by seeing if the labels map to the same reduced label. + FunctionPass *createDebugLabelFoldingPass(); + + /// MachineCodeDeletion Pass - This pass deletes all of the machine code for + /// the current function, which should happen after the function has been + /// emitted to a .s file or to memory. + FunctionPass *createMachineCodeDeleter(); + + /// getRegisterAllocator - This creates an instance of the register allocator + /// for the Sparc. + FunctionPass *getRegisterAllocator(TargetMachine &T); + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/RegAllocRegistry.h b/include/llvm/CodeGen/RegAllocRegistry.h new file mode 100644 index 0000000..ba6a879 --- /dev/null +++ b/include/llvm/CodeGen/RegAllocRegistry.h @@ -0,0 +1,64 @@ +//===-- llvm/CodeGen/RegAllocRegistry.h -------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the James M. Laskey and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the implementation for register allocator function +// pass registry (RegisterRegAlloc). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGENREGALLOCREGISTRY_H +#define LLVM_CODEGENREGALLOCREGISTRY_H + +#include "llvm/CodeGen/MachinePassRegistry.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// +/// RegisterRegAlloc class - Track the registration of register allocators. +/// +//===----------------------------------------------------------------------===// +class RegisterRegAlloc : public MachinePassRegistryNode { + +public: + + typedef FunctionPass *(*FunctionPassCtor)(); + + static MachinePassRegistry Registry; + + RegisterRegAlloc(const char *N, const char *D, FunctionPassCtor C) + : MachinePassRegistryNode(N, D, (MachinePassCtor)C) + { Registry.Add(this); } + ~RegisterRegAlloc() { Registry.Remove(this); } + + + // Accessors. + // + RegisterRegAlloc *getNext() const { + return (RegisterRegAlloc *)MachinePassRegistryNode::getNext(); + } + static RegisterRegAlloc *getList() { + return (RegisterRegAlloc *)Registry.getList(); + } + static FunctionPassCtor getDefault() { + return (FunctionPassCtor)Registry.getDefault(); + } + static void setDefault(FunctionPassCtor C) { + Registry.setDefault((MachinePassCtor)C); + } + static void setListener(MachinePassRegistryListener *L) { + Registry.setListener(L); + } + +}; + +} // end namespace llvm + + +#endif diff --git a/include/llvm/CodeGen/RegisterScavenging.h b/include/llvm/CodeGen/RegisterScavenging.h new file mode 100644 index 0000000..ec23e76 --- /dev/null +++ b/include/llvm/CodeGen/RegisterScavenging.h @@ -0,0 +1,148 @@ +//===-- RegisterScavenging.h - Machine register scavenging ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the Evan Cheng and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the machine register scavenger class. It can provide +// information such as unused register at any point in a machine basic block. +// It also provides a mechanism to make registers availbale by evicting them +// to spill slots. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_REGISTER_SCAVENGING_H +#define LLVM_CODEGEN_REGISTER_SCAVENGING_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/ADT/BitVector.h" + +namespace llvm { + +class MRegisterInfo; +class TargetInstrInfo; +class TargetRegisterClass; + +class RegScavenger { + MachineBasicBlock *MBB; + MachineBasicBlock::iterator MBBI; + unsigned NumPhysRegs; + + /// Tracking - True if RegScavenger is currently tracking the liveness of + /// registers. + bool Tracking; + + /// ScavengingFrameIndex - Special spill slot used for scavenging a register + /// post register allocation. + int ScavengingFrameIndex; + + /// ScavengedReg - If none zero, the specific register is currently being + /// scavenged. That is, it is spilled to the special scavenging stack slot. + unsigned ScavengedReg; + + /// ScavengedRC - Register class of the scavenged register. + /// + const TargetRegisterClass *ScavengedRC; + + /// RegsAvailable - The current state of all the physical registers immediately + /// before MBBI. One bit per physical register. If bit is set that means it's + /// available, unset means the register is currently being used. + BitVector RegsAvailable; + +public: + RegScavenger() + : MBB(NULL), NumPhysRegs(0), Tracking(false), + ScavengingFrameIndex(-1), ScavengedReg(0), ScavengedRC(NULL) {}; + + explicit RegScavenger(MachineBasicBlock *mbb) + : MBB(mbb), NumPhysRegs(0), Tracking(false), + ScavengingFrameIndex(-1), ScavengedReg(0), ScavengedRC(NULL) {}; + + /// enterBasicBlock - Start tracking liveness from the begin of the specific + /// basic block. + void enterBasicBlock(MachineBasicBlock *mbb); + + /// forward / backward - Move the internal MBB iterator and update register + /// states. + void forward(); + void backward(); + + /// forward / backward - Move the internal MBB iterator and update register + /// states until it has processed the specific iterator. + void forward(MachineBasicBlock::iterator I) { + while (MBBI != I) forward(); + } + void backward(MachineBasicBlock::iterator I) { + while (MBBI != I) backward(); + } + + /// skipTo - Move the internal MBB iterator but do not update register states. + /// + void skipTo(MachineBasicBlock::iterator I) { MBBI = I; } + + /// isReserved - Returns true if a register is reserved. It is never "unused". + bool isReserved(unsigned Reg) const { return ReservedRegs[Reg]; } + + /// isUsed / isUsed - Test if a register is currently being used. + /// + bool isUsed(unsigned Reg) const { return !RegsAvailable[Reg]; } + bool isUnused(unsigned Reg) const { return RegsAvailable[Reg]; } + + /// getRegsUsed - return all registers currently in use in used. + void getRegsUsed(BitVector &used, bool includeReserved); + + /// setUsed / setUnused - Mark the state of one or a number of registers. + /// + void setUsed(unsigned Reg) { RegsAvailable.reset(Reg); } + void setUsed(BitVector Regs) { RegsAvailable &= ~Regs; } + void setUnused(unsigned Reg) { RegsAvailable.set(Reg); } + void setUnused(BitVector Regs) { RegsAvailable |= Regs; } + + /// FindUnusedReg - Find a unused register of the specified register class + /// from the specified set of registers. It return 0 is none is found. + unsigned FindUnusedReg(const TargetRegisterClass *RegClass, + const BitVector &Candidates) const; + + /// FindUnusedReg - Find a unused register of the specified register class. + /// Exclude callee saved registers if directed. It return 0 is none is found. + unsigned FindUnusedReg(const TargetRegisterClass *RegClass, + bool ExCalleeSaved = false) const; + + /// setScavengingFrameIndex / getScavengingFrameIndex - accessor and setter of + /// ScavengingFrameIndex. + void setScavengingFrameIndex(int FI) { ScavengingFrameIndex = FI; } + int getScavengingFrameIndex() const { return ScavengingFrameIndex; } + + /// scavengeRegister - Make a register of the specific register class + /// available and do the appropriate bookkeeping. SPAdj is the stack + /// adjustment due to call frame, it's passed along to eliminateFrameIndex(). + /// Returns the scavenged register. + unsigned scavengeRegister(const TargetRegisterClass *RegClass, + MachineBasicBlock::iterator I, int SPAdj); + unsigned scavengeRegister(const TargetRegisterClass *RegClass, int SPAdj) { + return scavengeRegister(RegClass, MBBI, SPAdj); + } + +private: + const MRegisterInfo *RegInfo; + const TargetInstrInfo *TII; + + /// CalleeSavedrRegs - A bitvector of callee saved registers for the target. + /// + BitVector CalleeSavedRegs; + + /// ReservedRegs - A bitvector of reserved registers. + /// + BitVector ReservedRegs; + + /// restoreScavengedReg - Restore scavenged by loading it back from the + /// emergency spill slot. Mark it used. + void restoreScavengedReg(); +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h new file mode 100644 index 0000000..2609c55 --- /dev/null +++ b/include/llvm/CodeGen/RuntimeLibcalls.h @@ -0,0 +1,109 @@ +//===-- CodeGen/RuntimeLibcall.h - Runtime Library Calls --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the Evan Cheng and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the enum representing the list of runtime library calls +// the backend may emit during code generation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_RUNTIMELIBCALLS_H +#define LLVM_CODEGEN_RUNTIMELIBCALLS_H + +namespace llvm { +namespace RTLIB { + /// RTLIB::Libcall enum - This enum defines all of the runtime library calls + /// the backend can emit. + /// + enum Libcall { + // Integer + SHL_I32, + SHL_I64, + SRL_I32, + SRL_I64, + SRA_I32, + SRA_I64, + MUL_I32, + MUL_I64, + SDIV_I32, + SDIV_I64, + UDIV_I32, + UDIV_I64, + SREM_I32, + SREM_I64, + UREM_I32, + UREM_I64, + NEG_I32, + NEG_I64, + + // FLOATING POINT + ADD_F32, + ADD_F64, + SUB_F32, + SUB_F64, + MUL_F32, + MUL_F64, + DIV_F32, + DIV_F64, + REM_F32, + REM_F64, + NEG_F32, + NEG_F64, + POWI_F32, + POWI_F64, + SQRT_F32, + SQRT_F64, + SIN_F32, + SIN_F64, + COS_F32, + COS_F64, + + // CONVERSION + FPEXT_F32_F64, + FPROUND_F64_F32, + FPTOSINT_F32_I32, + FPTOSINT_F32_I64, + FPTOSINT_F64_I32, + FPTOSINT_F64_I64, + FPTOUINT_F32_I32, + FPTOUINT_F32_I64, + FPTOUINT_F64_I32, + FPTOUINT_F64_I64, + SINTTOFP_I32_F32, + SINTTOFP_I32_F64, + SINTTOFP_I64_F32, + SINTTOFP_I64_F64, + UINTTOFP_I32_F32, + UINTTOFP_I32_F64, + UINTTOFP_I64_F32, + UINTTOFP_I64_F64, + + // COMPARISON + OEQ_F32, + OEQ_F64, + UNE_F32, + UNE_F64, + OGE_F32, + OGE_F64, + OLT_F32, + OLT_F64, + OLE_F32, + OLE_F64, + OGT_F32, + OGT_F64, + UO_F32, + UO_F64, + O_F32, + O_F64, + + UNKNOWN_LIBCALL + }; +} +} + +#endif diff --git a/include/llvm/CodeGen/SSARegMap.h b/include/llvm/CodeGen/SSARegMap.h new file mode 100644 index 0000000..97d8d69 --- /dev/null +++ b/include/llvm/CodeGen/SSARegMap.h @@ -0,0 +1,55 @@ +//===-- llvm/CodeGen/SSARegMap.h --------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Map register numbers to register classes that are correctly sized (typed) to +// hold the information. Assists register allocation. Contained by +// MachineFunction, should be deleted by register allocator when it is no +// longer needed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SSAREGMAP_H +#define LLVM_CODEGEN_SSAREGMAP_H + +#include "llvm/Target/MRegisterInfo.h" +#include "llvm/ADT/IndexedMap.h" + +namespace llvm { + +class TargetRegisterClass; + +class SSARegMap { + IndexedMap<const TargetRegisterClass*, VirtReg2IndexFunctor> RegClassMap; + unsigned NextRegNum; + + public: + SSARegMap() : NextRegNum(MRegisterInfo::FirstVirtualRegister) { } + + const TargetRegisterClass* getRegClass(unsigned Reg) { + return RegClassMap[Reg]; + } + + /// createVirtualRegister - Create and return a new virtual register in the + /// function with the specified register class. + /// + unsigned createVirtualRegister(const TargetRegisterClass *RegClass) { + assert(RegClass && "Cannot create register without RegClass!"); + RegClassMap.grow(NextRegNum); + RegClassMap[NextRegNum] = RegClass; + return NextRegNum++; + } + + unsigned getLastVirtReg() const { + return NextRegNum - 1; + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/SchedGraphCommon.h b/include/llvm/CodeGen/SchedGraphCommon.h new file mode 100644 index 0000000..4fcd9ac --- /dev/null +++ b/include/llvm/CodeGen/SchedGraphCommon.h @@ -0,0 +1,289 @@ +//===-- SchedGraphCommon.h - Scheduling Base Graph --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// A common graph class that is based on the SSA graph. It includes +// extra dependencies that are caused by machine resources. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SCHEDGRAPHCOMMON_H +#define LLVM_CODEGEN_SCHEDGRAPHCOMMON_H + +#include "llvm/Value.h" +#include "llvm/ADT/iterator" +#include "llvm/Support/Streams.h" +#include <vector> + +namespace llvm { + +class SchedGraphEdge; +class SchedGraphNode; + +/******************** Exported Data Types and Constants ********************/ + +typedef int ResourceId; +const ResourceId InvalidRID = -1; +const ResourceId MachineCCRegsRID = -2; // use +ve numbers for actual regs +const ResourceId MachineIntRegsRID = -3; // use +ve numbers for actual regs +const ResourceId MachineFPRegsRID = -4; // use +ve numbers for actual regs + + +//*********************** Public Class Declarations ************************/ +class SchedGraphNodeCommon { +protected: + unsigned ID; + std::vector<SchedGraphEdge*> inEdges; + std::vector<SchedGraphEdge*> outEdges; + int latency; + int origIndexInBB; // original position of instr in BB + +public: + typedef std::vector<SchedGraphEdge*>::iterator iterator; + typedef std::vector<SchedGraphEdge*>::const_iterator const_iterator; + typedef std::vector<SchedGraphEdge*>::reverse_iterator reverse_iterator; + typedef std::vector<SchedGraphEdge*>::const_reverse_iterator const_reverse_iterator; + + // Accessor methods + unsigned getNodeId() const { return ID; } + int getLatency() const { return latency; } + unsigned getNumInEdges() const { return inEdges.size(); } + unsigned getNumOutEdges() const { return outEdges.size(); } + int getOrigIndexInBB() const { return origIndexInBB; } + + // Iterators + iterator beginInEdges() { return inEdges.begin(); } + iterator endInEdges() { return inEdges.end(); } + iterator beginOutEdges() { return outEdges.begin(); } + iterator endOutEdges() { return outEdges.end(); } + + const_iterator beginInEdges() const { return inEdges.begin(); } + const_iterator endInEdges() const { return inEdges.end(); } + const_iterator beginOutEdges() const { return outEdges.begin(); } + const_iterator endOutEdges() const { return outEdges.end(); } + + void dump(int indent=0) const; + + // Debugging support + virtual void print(std::ostream &os) const = 0; + void print(std::ostream *os) const { if (os) print(*os); } + +protected: + friend class SchedGraphCommon; + friend class SchedGraphEdge; // give access for adding edges + + + // disable default constructor and provide a ctor for single-block graphs + SchedGraphNodeCommon(); // DO NOT IMPLEMENT + + inline SchedGraphNodeCommon(unsigned Id, int index, int late=0) : ID(Id), latency(late), origIndexInBB(index) {} + + virtual ~SchedGraphNodeCommon(); + + //Functions to add and remove edges + inline void addInEdge(SchedGraphEdge* edge) { inEdges.push_back(edge); } + inline void addOutEdge(SchedGraphEdge* edge) { outEdges.push_back(edge); } + void removeInEdge(const SchedGraphEdge* edge); + void removeOutEdge(const SchedGraphEdge* edge); + +}; + +// ostream << operator for SchedGraphNode class +inline std::ostream &operator<<(std::ostream &os, + const SchedGraphNodeCommon &node) { + node.print(os); + return os; +} + +// +// SchedGraphEdge - Edge class to represent dependencies +// +class SchedGraphEdge { +public: + enum SchedGraphEdgeDepType { + CtrlDep, MemoryDep, ValueDep, MachineRegister, MachineResource + }; + enum DataDepOrderType { + TrueDep = 0x1, AntiDep=0x2, OutputDep=0x4, NonDataDep=0x8 + }; + +protected: + SchedGraphNodeCommon* src; + SchedGraphNodeCommon* sink; + SchedGraphEdgeDepType depType; + unsigned int depOrderType; + int minDelay; // cached latency (assumes fixed target arch) + int iteDiff; + + union { + const Value* val; + int machineRegNum; + ResourceId resourceId; + }; + +public: + // For all constructors, if minDelay is unspecified, minDelay is + // set to _src->getLatency(). + + // constructor for CtrlDep or MemoryDep edges, selected by 3rd argument + SchedGraphEdge(SchedGraphNodeCommon* _src, SchedGraphNodeCommon* _sink, + SchedGraphEdgeDepType _depType, unsigned int _depOrderType, + int _minDelay = -1); + + // constructor for explicit value dependence (may be true/anti/output) + SchedGraphEdge(SchedGraphNodeCommon* _src, SchedGraphNodeCommon* _sink, + const Value* _val, unsigned int _depOrderType, + int _minDelay = -1); + + // constructor for machine register dependence + SchedGraphEdge(SchedGraphNodeCommon* _src,SchedGraphNodeCommon* _sink, + unsigned int _regNum, unsigned int _depOrderType, + int _minDelay = -1); + + // constructor for any other machine resource dependences. + // DataDepOrderType is always NonDataDep. It it not an argument to + // avoid overloading ambiguity with previous constructor. + SchedGraphEdge(SchedGraphNodeCommon* _src, SchedGraphNodeCommon* _sink, + ResourceId _resourceId, int _minDelay = -1); + + ~SchedGraphEdge() {} + + SchedGraphNodeCommon* getSrc() const { return src; } + SchedGraphNodeCommon* getSink() const { return sink; } + int getMinDelay() const { return minDelay; } + SchedGraphEdgeDepType getDepType() const { return depType; } + unsigned int getDepOrderType() const { return depOrderType; } + + const Value* getValue() const { + assert(depType == ValueDep); return val; + } + + int getMachineReg() const { + assert(depType == MachineRegister); return machineRegNum; + } + + int getResourceId() const { + assert(depType == MachineResource); return resourceId; + } + + void setIteDiff(int _iteDiff) { + iteDiff = _iteDiff; + } + + int getIteDiff() { + return iteDiff; + } + +public: + // Debugging support + void print(std::ostream &os) const; + void print(std::ostream *os) const { if (os) print(*os); } + void dump(int indent=0) const; + +private: + // disable default ctor + SchedGraphEdge(); // DO NOT IMPLEMENT +}; + +// ostream << operator for SchedGraphNode class +inline std::ostream &operator<<(std::ostream &os, const SchedGraphEdge &edge) { + edge.print(os); + return os; +} + +class SchedGraphCommon { + +protected: + SchedGraphNodeCommon* graphRoot; // the root and leaf are not inserted + SchedGraphNodeCommon* graphLeaf; // in the hash_map (see getNumNodes()) + +public: + // + // Accessor methods + // + SchedGraphNodeCommon* getRoot() const { return graphRoot; } + SchedGraphNodeCommon* getLeaf() const { return graphLeaf; } + + // + // Delete nodes or edges from the graph. + // + void eraseNode(SchedGraphNodeCommon* node); + void eraseIncomingEdges(SchedGraphNodeCommon* node, bool addDummyEdges = true); + void eraseOutgoingEdges(SchedGraphNodeCommon* node, bool addDummyEdges = true); + void eraseIncidentEdges(SchedGraphNodeCommon* node, bool addDummyEdges = true); + + SchedGraphCommon() {} + ~SchedGraphCommon(); +}; + + +//********************** Sched Graph Iterators *****************************/ + +// Ok to make it a template because it shd get instantiated at most twice: +// for <SchedGraphNode, SchedGraphNode::iterator> and +// for <const SchedGraphNode, SchedGraphNode::const_iterator>. +// +template <class _NodeType, class _EdgeType, class _EdgeIter> +class SGPredIterator: public bidirectional_iterator<_NodeType, ptrdiff_t> { +protected: + _EdgeIter oi; +public: + typedef SGPredIterator<_NodeType, _EdgeType, _EdgeIter> _Self; + + inline SGPredIterator(_EdgeIter startEdge) : oi(startEdge) {} + + inline bool operator==(const _Self& x) const { return oi == x.oi; } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + // operator*() differs for pred or succ iterator + inline _NodeType* operator*() const { return (_NodeType*)(*oi)->getSrc(); } + inline _NodeType* operator->() const { return operator*(); } + + inline _EdgeType* getEdge() const { return *(oi); } + + inline _Self &operator++() { ++oi; return *this; } // Preincrement + inline _Self operator++(int) { // Postincrement + _Self tmp(*this); ++*this; return tmp; + } + + inline _Self &operator--() { --oi; return *this; } // Predecrement + inline _Self operator--(int) { // Postdecrement + _Self tmp = *this; --*this; return tmp; + } +}; + +template <class _NodeType, class _EdgeType, class _EdgeIter> +class SGSuccIterator : public bidirectional_iterator<_NodeType, ptrdiff_t> { +protected: + _EdgeIter oi; +public: + typedef SGSuccIterator<_NodeType, _EdgeType, _EdgeIter> _Self; + + inline SGSuccIterator(_EdgeIter startEdge) : oi(startEdge) {} + + inline bool operator==(const _Self& x) const { return oi == x.oi; } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline _NodeType* operator*() const { return (_NodeType*)(*oi)->getSink(); } + inline _NodeType* operator->() const { return operator*(); } + + inline _EdgeType* getEdge() const { return *(oi); } + + inline _Self &operator++() { ++oi; return *this; } // Preincrement + inline _Self operator++(int) { // Postincrement + _Self tmp(*this); ++*this; return tmp; + } + + inline _Self &operator--() { --oi; return *this; } // Predecrement + inline _Self operator--(int) { // Postdecrement + _Self tmp = *this; --*this; return tmp; + } +}; +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h new file mode 100644 index 0000000..06d2f2e --- /dev/null +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -0,0 +1,306 @@ +//===------- llvm/CodeGen/ScheduleDAG.h - Common Base Class------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Evan Cheng and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the ScheduleDAG class, which is used as the common +// base class for SelectionDAG-based instruction scheduler. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SCHEDULEDAG_H +#define LLVM_CODEGEN_SCHEDULEDAG_H + +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallSet.h" + +namespace llvm { + struct InstrStage; + class MachineConstantPool; + class MachineModuleInfo; + class MachineInstr; + class MRegisterInfo; + class SelectionDAG; + class SelectionDAGISel; + class SSARegMap; + class TargetInstrInfo; + class TargetInstrDescriptor; + class TargetMachine; + + /// HazardRecognizer - This determines whether or not an instruction can be + /// issued this cycle, and whether or not a noop needs to be inserted to handle + /// the hazard. + class HazardRecognizer { + public: + virtual ~HazardRecognizer(); + + enum HazardType { + NoHazard, // This instruction can be emitted at this cycle. + Hazard, // This instruction can't be emitted at this cycle. + NoopHazard // This instruction can't be emitted, and needs noops. + }; + + /// getHazardType - Return the hazard type of emitting this node. There are + /// three possible results. Either: + /// * NoHazard: it is legal to issue this instruction on this cycle. + /// * Hazard: issuing this instruction would stall the machine. If some + /// other instruction is available, issue it first. + /// * NoopHazard: issuing this instruction would break the program. If + /// some other instruction can be issued, do so, otherwise issue a noop. + virtual HazardType getHazardType(SDNode *Node) { + return NoHazard; + } + + /// EmitInstruction - This callback is invoked when an instruction is + /// emitted, to advance the hazard state. + virtual void EmitInstruction(SDNode *Node) { + } + + /// AdvanceCycle - This callback is invoked when no instructions can be + /// issued on this cycle without a hazard. This should increment the + /// internal state of the hazard recognizer so that previously "Hazard" + /// instructions will now not be hazards. + virtual void AdvanceCycle() { + } + + /// EmitNoop - This callback is invoked when a noop was added to the + /// instruction stream. + virtual void EmitNoop() { + } + }; + + /// SUnit - Scheduling unit. It's an wrapper around either a single SDNode or + /// a group of nodes flagged together. + struct SUnit { + SDNode *Node; // Representative node. + SmallVector<SDNode*,4> FlaggedNodes;// All nodes flagged to Node. + + // Preds/Succs - The SUnits before/after us in the graph. The boolean value + // is true if the edge is a token chain edge, false if it is a value edge. + SmallVector<std::pair<SUnit*,bool>, 4> Preds; // All sunit predecessors. + SmallVector<std::pair<SUnit*,bool>, 4> Succs; // All sunit successors. + + typedef SmallVector<std::pair<SUnit*,bool>, 4>::iterator pred_iterator; + typedef SmallVector<std::pair<SUnit*,bool>, 4>::iterator succ_iterator; + typedef SmallVector<std::pair<SUnit*,bool>, 4>::const_iterator + const_pred_iterator; + typedef SmallVector<std::pair<SUnit*,bool>, 4>::const_iterator + const_succ_iterator; + + short NumPreds; // # of preds. + short NumSuccs; // # of sucss. + short NumPredsLeft; // # of preds not scheduled. + short NumSuccsLeft; // # of succs not scheduled. + short NumChainPredsLeft; // # of chain preds not scheduled. + short NumChainSuccsLeft; // # of chain succs not scheduled. + bool isTwoAddress : 1; // Is a two-address instruction. + bool isCommutable : 1; // Is a commutable instruction. + bool isPending : 1; // True once pending. + bool isAvailable : 1; // True once available. + bool isScheduled : 1; // True once scheduled. + unsigned short Latency; // Node latency. + unsigned CycleBound; // Upper/lower cycle to be scheduled at. + unsigned Cycle; // Once scheduled, the cycle of the op. + unsigned Depth; // Node depth; + unsigned Height; // Node height; + unsigned NodeNum; // Entry # of node in the node vector. + + SUnit(SDNode *node, unsigned nodenum) + : Node(node), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0), + NumChainPredsLeft(0), NumChainSuccsLeft(0), + isTwoAddress(false), isCommutable(false), + isPending(false), isAvailable(false), isScheduled(false), + Latency(0), CycleBound(0), Cycle(0), Depth(0), Height(0), + NodeNum(nodenum) {} + + /// addPred - This adds the specified node as a pred of the current node if + /// not already. This returns true if this is a new pred. + bool addPred(SUnit *N, bool isChain) { + for (unsigned i = 0, e = Preds.size(); i != e; ++i) + if (Preds[i].first == N && Preds[i].second == isChain) + return false; + Preds.push_back(std::make_pair(N, isChain)); + return true; + } + + /// addSucc - This adds the specified node as a succ of the current node if + /// not already. This returns true if this is a new succ. + bool addSucc(SUnit *N, bool isChain) { + for (unsigned i = 0, e = Succs.size(); i != e; ++i) + if (Succs[i].first == N && Succs[i].second == isChain) + return false; + Succs.push_back(std::make_pair(N, isChain)); + return true; + } + + void dump(const SelectionDAG *G) const; + void dumpAll(const SelectionDAG *G) const; + }; + + //===--------------------------------------------------------------------===// + /// SchedulingPriorityQueue - This interface is used to plug different + /// priorities computation algorithms into the list scheduler. It implements + /// the interface of a standard priority queue, where nodes are inserted in + /// arbitrary order and returned in priority order. The computation of the + /// priority and the representation of the queue are totally up to the + /// implementation to decide. + /// + class SchedulingPriorityQueue { + public: + virtual ~SchedulingPriorityQueue() {} + + virtual void initNodes(DenseMap<SDNode*, SUnit*> &SUMap, + std::vector<SUnit> &SUnits) = 0; + virtual void releaseState() = 0; + + virtual bool empty() const = 0; + virtual void push(SUnit *U) = 0; + + virtual void push_all(const std::vector<SUnit *> &Nodes) = 0; + virtual SUnit *pop() = 0; + + /// ScheduledNode - As each node is scheduled, this method is invoked. This + /// allows the priority function to adjust the priority of node that have + /// already been emitted. + virtual void ScheduledNode(SUnit *Node) {} + }; + + class ScheduleDAG { + public: + SelectionDAG &DAG; // DAG of the current basic block + MachineBasicBlock *BB; // Current basic block + const TargetMachine &TM; // Target processor + const TargetInstrInfo *TII; // Target instruction information + const MRegisterInfo *MRI; // Target processor register info + SSARegMap *RegMap; // Virtual/real register map + MachineConstantPool *ConstPool; // Target constant pool + std::vector<SUnit*> Sequence; // The schedule. Null SUnit*'s + // represent noop instructions. + DenseMap<SDNode*, SUnit*> SUnitMap; // SDNode to SUnit mapping (n -> 1). + std::vector<SUnit> SUnits; // The scheduling units. + SmallSet<SDNode*, 16> CommuteSet; // Nodes the should be commuted. + + ScheduleDAG(SelectionDAG &dag, MachineBasicBlock *bb, + const TargetMachine &tm) + : DAG(dag), BB(bb), TM(tm) {} + + virtual ~ScheduleDAG() {} + + /// Run - perform scheduling. + /// + MachineBasicBlock *Run(); + + /// isPassiveNode - Return true if the node is a non-scheduled leaf. + /// + static bool isPassiveNode(SDNode *Node) { + if (isa<ConstantSDNode>(Node)) return true; + if (isa<RegisterSDNode>(Node)) return true; + if (isa<GlobalAddressSDNode>(Node)) return true; + if (isa<BasicBlockSDNode>(Node)) return true; + if (isa<FrameIndexSDNode>(Node)) return true; + if (isa<ConstantPoolSDNode>(Node)) return true; + if (isa<JumpTableSDNode>(Node)) return true; + if (isa<ExternalSymbolSDNode>(Node)) return true; + return false; + } + + /// NewSUnit - Creates a new SUnit and return a ptr to it. + /// + SUnit *NewSUnit(SDNode *N) { + SUnits.push_back(SUnit(N, SUnits.size())); + return &SUnits.back(); + } + + /// BuildSchedUnits - Build SUnits from the selection dag that we are input. + /// This SUnit graph is similar to the SelectionDAG, but represents flagged + /// together nodes with a single SUnit. + void BuildSchedUnits(); + + /// CalculateDepths, CalculateHeights - Calculate node depth / height. + /// + void CalculateDepths(); + void CalculateHeights(); + + /// CountResults - The results of target nodes have register or immediate + /// operands first, then an optional chain, and optional flag operands + /// (which do not go into the machine instrs.) + static unsigned CountResults(SDNode *Node); + + /// CountOperands The inputs to target nodes have any actual inputs first, + /// followed by an optional chain operand, then flag operands. Compute the + /// number of actual operands that will go into the machine instr. + static unsigned CountOperands(SDNode *Node); + + /// EmitNode - Generate machine code for an node and needed dependencies. + /// VRBaseMap contains, for each already emitted node, the first virtual + /// register number for the results of the node. + /// + void EmitNode(SDNode *Node, DenseMap<SDOperand, unsigned> &VRBaseMap); + + /// EmitNoop - Emit a noop instruction. + /// + void EmitNoop(); + + void EmitSchedule(); + + void dumpSchedule() const; + + /// Schedule - Order nodes according to selected style. + /// + virtual void Schedule() {} + + private: + void AddOperand(MachineInstr *MI, SDOperand Op, unsigned IIOpNum, + const TargetInstrDescriptor *II, + DenseMap<SDOperand, unsigned> &VRBaseMap); + }; + + /// createBFS_DAGScheduler - This creates a simple breadth first instruction + /// scheduler. + ScheduleDAG *createBFS_DAGScheduler(SelectionDAGISel *IS, + SelectionDAG *DAG, + MachineBasicBlock *BB); + + /// createSimpleDAGScheduler - This creates a simple two pass instruction + /// scheduler using instruction itinerary. + ScheduleDAG* createSimpleDAGScheduler(SelectionDAGISel *IS, + SelectionDAG *DAG, + MachineBasicBlock *BB); + + /// createNoItinsDAGScheduler - This creates a simple two pass instruction + /// scheduler without using instruction itinerary. + ScheduleDAG* createNoItinsDAGScheduler(SelectionDAGISel *IS, + SelectionDAG *DAG, + MachineBasicBlock *BB); + + /// createBURRListDAGScheduler - This creates a bottom up register usage + /// reduction list scheduler. + ScheduleDAG* createBURRListDAGScheduler(SelectionDAGISel *IS, + SelectionDAG *DAG, + MachineBasicBlock *BB); + + /// createTDRRListDAGScheduler - This creates a top down register usage + /// reduction list scheduler. + ScheduleDAG* createTDRRListDAGScheduler(SelectionDAGISel *IS, + SelectionDAG *DAG, + MachineBasicBlock *BB); + + /// createTDListDAGScheduler - This creates a top-down list scheduler with + /// a hazard recognizer. + ScheduleDAG* createTDListDAGScheduler(SelectionDAGISel *IS, + SelectionDAG *DAG, + MachineBasicBlock *BB); + + /// createDefaultScheduler - This creates an instruction scheduler appropriate + /// for the target. + ScheduleDAG* createDefaultScheduler(SelectionDAGISel *IS, + SelectionDAG *DAG, + MachineBasicBlock *BB); +} + +#endif diff --git a/include/llvm/CodeGen/SchedulerRegistry.h b/include/llvm/CodeGen/SchedulerRegistry.h new file mode 100644 index 0000000..ed5e0ba --- /dev/null +++ b/include/llvm/CodeGen/SchedulerRegistry.h @@ -0,0 +1,71 @@ +//===-- llvm/CodeGen/SchedulerRegistry.h ------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the James M. Laskey and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the implementation for instruction scheduler function +// pass registry (RegisterScheduler). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGENSCHEDULERREGISTRY_H +#define LLVM_CODEGENSCHEDULERREGISTRY_H + +#include "llvm/CodeGen/MachinePassRegistry.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// +/// RegisterScheduler class - Track the registration of instruction schedulers. +/// +//===----------------------------------------------------------------------===// + +class SelectionDAGISel; +class ScheduleDAG; +class SelectionDAG; +class MachineBasicBlock; + +class RegisterScheduler : public MachinePassRegistryNode { + +public: + + typedef ScheduleDAG *(*FunctionPassCtor)(SelectionDAGISel*, SelectionDAG*, + MachineBasicBlock*); + + static MachinePassRegistry Registry; + + RegisterScheduler(const char *N, const char *D, FunctionPassCtor C) + : MachinePassRegistryNode(N, D, (MachinePassCtor)C) + { Registry.Add(this); } + ~RegisterScheduler() { Registry.Remove(this); } + + + // Accessors. + // + RegisterScheduler *getNext() const { + return (RegisterScheduler *)MachinePassRegistryNode::getNext(); + } + static RegisterScheduler *getList() { + return (RegisterScheduler *)Registry.getList(); + } + static FunctionPassCtor getDefault() { + return (FunctionPassCtor)Registry.getDefault(); + } + static void setDefault(FunctionPassCtor C) { + Registry.setDefault((MachinePassCtor)C); + } + static void setListener(MachinePassRegistryListener *L) { + Registry.setListener(L); + } + +}; + +} // end namespace llvm + + +#endif diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h new file mode 100644 index 0000000..9388df1 --- /dev/null +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -0,0 +1,524 @@ +//===-- llvm/CodeGen/SelectionDAG.h - InstSelection DAG ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the SelectionDAG class, and transitively defines the +// SDNode class and subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SELECTIONDAG_H +#define LLVM_CODEGEN_SELECTIONDAG_H + +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/ilist" +#include "llvm/CodeGen/SelectionDAGNodes.h" + +#include <list> +#include <vector> +#include <map> +#include <set> +#include <string> + +namespace llvm { + class AliasAnalysis; + class TargetLowering; + class TargetMachine; + class MachineModuleInfo; + class MachineFunction; + class MachineConstantPoolValue; + +/// SelectionDAG class - This is used to represent a portion of an LLVM function +/// in a low-level Data Dependence DAG representation suitable for instruction +/// selection. This DAG is constructed as the first step of instruction +/// selection in order to allow implementation of machine specific optimizations +/// and code simplifications. +/// +/// The representation used by the SelectionDAG is a target-independent +/// representation, which has some similarities to the GCC RTL representation, +/// but is significantly more simple, powerful, and is a graph form instead of a +/// linear form. +/// +class SelectionDAG { + TargetLowering &TLI; + MachineFunction &MF; + MachineModuleInfo *MMI; + + /// Root - The root of the entire DAG. EntryNode - The starting token. + SDOperand Root, EntryNode; + + /// AllNodes - A linked list of nodes in the current DAG. + ilist<SDNode> AllNodes; + + /// CSEMap - This structure is used to memoize nodes, automatically performing + /// CSE with existing nodes with a duplicate is requested. + FoldingSet<SDNode> CSEMap; + +public: + SelectionDAG(TargetLowering &tli, MachineFunction &mf, MachineModuleInfo *mmi) + : TLI(tli), MF(mf), MMI(mmi) { + EntryNode = Root = getNode(ISD::EntryToken, MVT::Other); + } + ~SelectionDAG(); + + MachineFunction &getMachineFunction() const { return MF; } + const TargetMachine &getTarget() const; + TargetLowering &getTargetLoweringInfo() const { return TLI; } + MachineModuleInfo *getMachineModuleInfo() const { return MMI; } + + /// viewGraph - Pop up a GraphViz/gv window with the DAG rendered using 'dot'. + /// + void viewGraph(); + +#ifndef NDEBUG + std::map<const SDNode *, std::string> NodeGraphAttrs; +#endif + + /// clearGraphAttrs - Clear all previously defined node graph attributes. + /// Intended to be used from a debugging tool (eg. gdb). + void clearGraphAttrs(); + + /// setGraphAttrs - Set graph attributes for a node. (eg. "color=red".) + /// + void setGraphAttrs(const SDNode *N, const char *Attrs); + + /// getGraphAttrs - Get graph attributes for a node. (eg. "color=red".) + /// Used from getNodeAttributes. + const std::string getGraphAttrs(const SDNode *N) const; + + /// setGraphColor - Convenience for setting node color attribute. + /// + void setGraphColor(const SDNode *N, const char *Color); + + typedef ilist<SDNode>::const_iterator allnodes_const_iterator; + allnodes_const_iterator allnodes_begin() const { return AllNodes.begin(); } + allnodes_const_iterator allnodes_end() const { return AllNodes.end(); } + typedef ilist<SDNode>::iterator allnodes_iterator; + allnodes_iterator allnodes_begin() { return AllNodes.begin(); } + allnodes_iterator allnodes_end() { return AllNodes.end(); } + + /// getRoot - Return the root tag of the SelectionDAG. + /// + const SDOperand &getRoot() const { return Root; } + + /// getEntryNode - Return the token chain corresponding to the entry of the + /// function. + const SDOperand &getEntryNode() const { return EntryNode; } + + /// setRoot - Set the current root tag of the SelectionDAG. + /// + const SDOperand &setRoot(SDOperand N) { return Root = N; } + + /// Combine - This iterates over the nodes in the SelectionDAG, folding + /// certain types of nodes together, or eliminating superfluous nodes. When + /// the AfterLegalize argument is set to 'true', Combine takes care not to + /// generate any nodes that will be illegal on the target. + void Combine(bool AfterLegalize, AliasAnalysis &AA); + + /// Legalize - This transforms the SelectionDAG into a SelectionDAG that is + /// compatible with the target instruction selector, as indicated by the + /// TargetLowering object. + /// + /// Note that this is an involved process that may invalidate pointers into + /// the graph. + void Legalize(); + + /// RemoveDeadNodes - This method deletes all unreachable nodes in the + /// SelectionDAG. + void RemoveDeadNodes(); + + /// RemoveDeadNode - Remove the specified node from the system. If any of its + /// operands then becomes dead, remove them as well. The vector Deleted is + /// populated with nodes that are deleted. + void RemoveDeadNode(SDNode *N, std::vector<SDNode*> &Deleted); + + /// DeleteNode - Remove the specified node from the system. This node must + /// have no referrers. + void DeleteNode(SDNode *N); + + /// getVTList - Return an SDVTList that represents the list of values + /// specified. + SDVTList getVTList(MVT::ValueType VT); + SDVTList getVTList(MVT::ValueType VT1, MVT::ValueType VT2); + SDVTList getVTList(MVT::ValueType VT1, MVT::ValueType VT2,MVT::ValueType VT3); + SDVTList getVTList(const MVT::ValueType *VTs, unsigned NumVTs); + + /// getNodeValueTypes - These are obsolete, use getVTList instead. + const MVT::ValueType *getNodeValueTypes(MVT::ValueType VT) { + return getVTList(VT).VTs; + } + const MVT::ValueType *getNodeValueTypes(MVT::ValueType VT1, + MVT::ValueType VT2) { + return getVTList(VT1, VT2).VTs; + } + const MVT::ValueType *getNodeValueTypes(MVT::ValueType VT1,MVT::ValueType VT2, + MVT::ValueType VT3) { + return getVTList(VT1, VT2, VT3).VTs; + } + const MVT::ValueType *getNodeValueTypes(std::vector<MVT::ValueType> &VTList) { + return getVTList(&VTList[0], VTList.size()).VTs; + } + + + //===--------------------------------------------------------------------===// + // Node creation methods. + // + SDOperand getString(const std::string &Val); + SDOperand getConstant(uint64_t Val, MVT::ValueType VT, bool isTarget = false); + SDOperand getTargetConstant(uint64_t Val, MVT::ValueType VT) { + return getConstant(Val, VT, true); + } + SDOperand getConstantFP(double Val, MVT::ValueType VT, bool isTarget = false); + SDOperand getTargetConstantFP(double Val, MVT::ValueType VT) { + return getConstantFP(Val, VT, true); + } + SDOperand getGlobalAddress(const GlobalValue *GV, MVT::ValueType VT, + int offset = 0, bool isTargetGA = false); + SDOperand getTargetGlobalAddress(const GlobalValue *GV, MVT::ValueType VT, + int offset = 0) { + return getGlobalAddress(GV, VT, offset, true); + } + SDOperand getFrameIndex(int FI, MVT::ValueType VT, bool isTarget = false); + SDOperand getTargetFrameIndex(int FI, MVT::ValueType VT) { + return getFrameIndex(FI, VT, true); + } + SDOperand getJumpTable(int JTI, MVT::ValueType VT, bool isTarget = false); + SDOperand getTargetJumpTable(int JTI, MVT::ValueType VT) { + return getJumpTable(JTI, VT, true); + } + SDOperand getConstantPool(Constant *C, MVT::ValueType VT, + unsigned Align = 0, int Offs = 0, bool isT=false); + SDOperand getTargetConstantPool(Constant *C, MVT::ValueType VT, + unsigned Align = 0, int Offset = 0) { + return getConstantPool(C, VT, Align, Offset, true); + } + SDOperand getConstantPool(MachineConstantPoolValue *C, MVT::ValueType VT, + unsigned Align = 0, int Offs = 0, bool isT=false); + SDOperand getTargetConstantPool(MachineConstantPoolValue *C, + MVT::ValueType VT, unsigned Align = 0, + int Offset = 0) { + return getConstantPool(C, VT, Align, Offset, true); + } + SDOperand getBasicBlock(MachineBasicBlock *MBB); + SDOperand getExternalSymbol(const char *Sym, MVT::ValueType VT); + SDOperand getTargetExternalSymbol(const char *Sym, MVT::ValueType VT); + SDOperand getValueType(MVT::ValueType); + SDOperand getRegister(unsigned Reg, MVT::ValueType VT); + + SDOperand getCopyToReg(SDOperand Chain, unsigned Reg, SDOperand N) { + return getNode(ISD::CopyToReg, MVT::Other, Chain, + getRegister(Reg, N.getValueType()), N); + } + + // This version of the getCopyToReg method takes an extra operand, which + // indicates that there is potentially an incoming flag value (if Flag is not + // null) and that there should be a flag result. + SDOperand getCopyToReg(SDOperand Chain, unsigned Reg, SDOperand N, + SDOperand Flag) { + const MVT::ValueType *VTs = getNodeValueTypes(MVT::Other, MVT::Flag); + SDOperand Ops[] = { Chain, getRegister(Reg, N.getValueType()), N, Flag }; + return getNode(ISD::CopyToReg, VTs, 2, Ops, Flag.Val ? 4 : 3); + } + + // Similar to last getCopyToReg() except parameter Reg is a SDOperand + SDOperand getCopyToReg(SDOperand Chain, SDOperand Reg, SDOperand N, + SDOperand Flag) { + const MVT::ValueType *VTs = getNodeValueTypes(MVT::Other, MVT::Flag); + SDOperand Ops[] = { Chain, Reg, N, Flag }; + return getNode(ISD::CopyToReg, VTs, 2, Ops, Flag.Val ? 4 : 3); + } + + SDOperand getCopyFromReg(SDOperand Chain, unsigned Reg, MVT::ValueType VT) { + const MVT::ValueType *VTs = getNodeValueTypes(VT, MVT::Other); + SDOperand Ops[] = { Chain, getRegister(Reg, VT) }; + return getNode(ISD::CopyFromReg, VTs, 2, Ops, 2); + } + + // This version of the getCopyFromReg method takes an extra operand, which + // indicates that there is potentially an incoming flag value (if Flag is not + // null) and that there should be a flag result. + SDOperand getCopyFromReg(SDOperand Chain, unsigned Reg, MVT::ValueType VT, + SDOperand Flag) { + const MVT::ValueType *VTs = getNodeValueTypes(VT, MVT::Other, MVT::Flag); + SDOperand Ops[] = { Chain, getRegister(Reg, VT), Flag }; + return getNode(ISD::CopyFromReg, VTs, 3, Ops, Flag.Val ? 3 : 2); + } + + SDOperand getCondCode(ISD::CondCode Cond); + + /// getZeroExtendInReg - Return the expression required to zero extend the Op + /// value assuming it was the smaller SrcTy value. + SDOperand getZeroExtendInReg(SDOperand Op, MVT::ValueType SrcTy); + + /// getCALLSEQ_START - Return a new CALLSEQ_START node, which always must have + /// a flag result (to ensure it's not CSE'd). + SDOperand getCALLSEQ_START(SDOperand Chain, SDOperand Op) { + const MVT::ValueType *VTs = getNodeValueTypes(MVT::Other, MVT::Flag); + SDOperand Ops[] = { Chain, Op }; + return getNode(ISD::CALLSEQ_START, VTs, 2, Ops, 2); + } + + /// getNode - Gets or creates the specified node. + /// + SDOperand getNode(unsigned Opcode, MVT::ValueType VT); + SDOperand getNode(unsigned Opcode, MVT::ValueType VT, SDOperand N); + SDOperand getNode(unsigned Opcode, MVT::ValueType VT, + SDOperand N1, SDOperand N2); + SDOperand getNode(unsigned Opcode, MVT::ValueType VT, + SDOperand N1, SDOperand N2, SDOperand N3); + SDOperand getNode(unsigned Opcode, MVT::ValueType VT, + SDOperand N1, SDOperand N2, SDOperand N3, SDOperand N4); + SDOperand getNode(unsigned Opcode, MVT::ValueType VT, + SDOperand N1, SDOperand N2, SDOperand N3, SDOperand N4, + SDOperand N5); + SDOperand getNode(unsigned Opcode, MVT::ValueType VT, + const SDOperand *Ops, unsigned NumOps); + SDOperand getNode(unsigned Opcode, std::vector<MVT::ValueType> &ResultTys, + const SDOperand *Ops, unsigned NumOps); + SDOperand getNode(unsigned Opcode, const MVT::ValueType *VTs, unsigned NumVTs, + const SDOperand *Ops, unsigned NumOps); + SDOperand getNode(unsigned Opcode, SDVTList VTs, + const SDOperand *Ops, unsigned NumOps); + + /// getSetCC - Helper function to make it easier to build SetCC's if you just + /// have an ISD::CondCode instead of an SDOperand. + /// + SDOperand getSetCC(MVT::ValueType VT, SDOperand LHS, SDOperand RHS, + ISD::CondCode Cond) { + return getNode(ISD::SETCC, VT, LHS, RHS, getCondCode(Cond)); + } + + /// getSelectCC - Helper function to make it easier to build SelectCC's if you + /// just have an ISD::CondCode instead of an SDOperand. + /// + SDOperand getSelectCC(SDOperand LHS, SDOperand RHS, + SDOperand True, SDOperand False, ISD::CondCode Cond) { + return getNode(ISD::SELECT_CC, True.getValueType(), LHS, RHS, True, False, + getCondCode(Cond)); + } + + /// getVAArg - VAArg produces a result and token chain, and takes a pointer + /// and a source value as input. + SDOperand getVAArg(MVT::ValueType VT, SDOperand Chain, SDOperand Ptr, + SDOperand SV); + + /// getLoad - Loads are not normal binary operators: their result type is not + /// determined by their operands, and they produce a value AND a token chain. + /// + SDOperand getLoad(MVT::ValueType VT, SDOperand Chain, SDOperand Ptr, + const Value *SV, int SVOffset, bool isVolatile=false, + unsigned Alignment=0); + SDOperand getExtLoad(ISD::LoadExtType ExtType, MVT::ValueType VT, + SDOperand Chain, SDOperand Ptr, const Value *SV, + int SVOffset, MVT::ValueType EVT, bool isVolatile=false, + unsigned Alignment=0); + SDOperand getIndexedLoad(SDOperand OrigLoad, SDOperand Base, + SDOperand Offset, ISD::MemIndexedMode AM); + + /// getStore - Helper function to build ISD::STORE nodes. + /// + SDOperand getStore(SDOperand Chain, SDOperand Val, SDOperand Ptr, + const Value *SV, int SVOffset, bool isVolatile=false, + unsigned Alignment=0); + SDOperand getTruncStore(SDOperand Chain, SDOperand Val, SDOperand Ptr, + const Value *SV, int SVOffset, MVT::ValueType TVT, + bool isVolatile=false, unsigned Alignment=0); + SDOperand getIndexedStore(SDOperand OrigStoe, SDOperand Base, + SDOperand Offset, ISD::MemIndexedMode AM); + + // getSrcValue - construct a node to track a Value* through the backend + SDOperand getSrcValue(const Value* I, int offset = 0); + + /// UpdateNodeOperands - *Mutate* the specified node in-place to have the + /// specified operands. If the resultant node already exists in the DAG, + /// this does not modify the specified node, instead it returns the node that + /// already exists. If the resultant node does not exist in the DAG, the + /// input node is returned. As a degenerate case, if you specify the same + /// input operands as the node already has, the input node is returned. + SDOperand UpdateNodeOperands(SDOperand N, SDOperand Op); + SDOperand UpdateNodeOperands(SDOperand N, SDOperand Op1, SDOperand Op2); + SDOperand UpdateNodeOperands(SDOperand N, SDOperand Op1, SDOperand Op2, + SDOperand Op3); + SDOperand UpdateNodeOperands(SDOperand N, SDOperand Op1, SDOperand Op2, + SDOperand Op3, SDOperand Op4); + SDOperand UpdateNodeOperands(SDOperand N, SDOperand Op1, SDOperand Op2, + SDOperand Op3, SDOperand Op4, SDOperand Op5); + SDOperand UpdateNodeOperands(SDOperand N, SDOperand *Ops, unsigned NumOps); + + /// SelectNodeTo - These are used for target selectors to *mutate* the + /// specified node to have the specified return type, Target opcode, and + /// operands. Note that target opcodes are stored as + /// ISD::BUILTIN_OP_END+TargetOpcode in the node opcode field. The 0th value + /// of the resultant node is returned. + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT::ValueType VT); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT::ValueType VT, + SDOperand Op1); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT::ValueType VT, + SDOperand Op1, SDOperand Op2); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT::ValueType VT, + SDOperand Op1, SDOperand Op2, SDOperand Op3); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT::ValueType VT, + const SDOperand *Ops, unsigned NumOps); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT::ValueType VT1, + MVT::ValueType VT2, SDOperand Op1, SDOperand Op2); + SDNode *SelectNodeTo(SDNode *N, unsigned TargetOpc, MVT::ValueType VT1, + MVT::ValueType VT2, SDOperand Op1, SDOperand Op2, + SDOperand Op3); + + + /// getTargetNode - These are used for target selectors to create a new node + /// with specified return type(s), target opcode, and operands. + /// + /// Note that getTargetNode returns the resultant node. If there is already a + /// node of the specified opcode and operands, it returns that node instead of + /// the current one. + SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT); + SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT, + SDOperand Op1); + SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT, + SDOperand Op1, SDOperand Op2); + SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT, + SDOperand Op1, SDOperand Op2, SDOperand Op3); + SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT, + const SDOperand *Ops, unsigned NumOps); + SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT1, + MVT::ValueType VT2, SDOperand Op1); + SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT1, + MVT::ValueType VT2, SDOperand Op1, SDOperand Op2); + SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT1, + MVT::ValueType VT2, SDOperand Op1, SDOperand Op2, + SDOperand Op3); + SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT1, + MVT::ValueType VT2, + const SDOperand *Ops, unsigned NumOps); + SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT1, + MVT::ValueType VT2, MVT::ValueType VT3, + SDOperand Op1, SDOperand Op2); + SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT1, + MVT::ValueType VT2, MVT::ValueType VT3, + SDOperand Op1, SDOperand Op2, SDOperand Op3); + SDNode *getTargetNode(unsigned Opcode, MVT::ValueType VT1, + MVT::ValueType VT2, MVT::ValueType VT3, + const SDOperand *Ops, unsigned NumOps); + + /// ReplaceAllUsesWith - Modify anything using 'From' to use 'To' instead. + /// This can cause recursive merging of nodes in the DAG. Use the first + /// version if 'From' is known to have a single result, use the second + /// if you have two nodes with identical results, use the third otherwise. + /// + /// These methods all take an optional vector, which (if not null) is + /// populated with any nodes that are deleted from the SelectionDAG, due to + /// new equivalences that are discovered. + /// + void ReplaceAllUsesWith(SDOperand From, SDOperand Op, + std::vector<SDNode*> *Deleted = 0); + void ReplaceAllUsesWith(SDNode *From, SDNode *To, + std::vector<SDNode*> *Deleted = 0); + void ReplaceAllUsesWith(SDNode *From, const SDOperand *To, + std::vector<SDNode*> *Deleted = 0); + + /// ReplaceAllUsesOfValueWith - Replace any uses of From with To, leaving + /// uses of other values produced by From.Val alone. The Deleted vector is + /// handled the same was as for ReplaceAllUsesWith, but it is required for + /// this method. + void ReplaceAllUsesOfValueWith(SDOperand From, SDOperand To, + std::vector<SDNode*> &Deleted); + + /// AssignNodeIds - Assign a unique node id for each node in the DAG based on + /// their allnodes order. It returns the maximum id. + unsigned AssignNodeIds(); + + /// AssignTopologicalOrder - Assign a unique node id for each node in the DAG + /// based on their topological order. It returns the maximum id and a vector + /// of the SDNodes* in assigned order by reference. + unsigned AssignTopologicalOrder(std::vector<SDNode*> &TopOrder); + + /// isCommutativeBinOp - Returns true if the opcode is a commutative binary + /// operation. + static bool isCommutativeBinOp(unsigned Opcode) { + switch (Opcode) { + case ISD::ADD: + case ISD::MUL: + case ISD::MULHU: + case ISD::MULHS: + case ISD::FADD: + case ISD::FMUL: + case ISD::AND: + case ISD::OR: + case ISD::XOR: + case ISD::ADDC: + case ISD::ADDE: return true; + default: return false; + } + } + + void dump() const; + + /// FoldSetCC - Constant fold a setcc to true or false. + SDOperand FoldSetCC(MVT::ValueType VT, SDOperand N1, + SDOperand N2, ISD::CondCode Cond); + + /// MaskedValueIsZero - Return true if 'Op & Mask' is known to be zero. We + /// use this predicate to simplify operations downstream. Op and Mask are + /// known to be the same type. + bool MaskedValueIsZero(SDOperand Op, uint64_t Mask, unsigned Depth = 0) + const; + + /// ComputeMaskedBits - Determine which of the bits specified in Mask are + /// known to be either zero or one and return them in the KnownZero/KnownOne + /// bitsets. This code only analyzes bits in Mask, in order to short-circuit + /// processing. Targets can implement the computeMaskedBitsForTargetNode + /// method in the TargetLowering class to allow target nodes to be understood. + void ComputeMaskedBits(SDOperand Op, uint64_t Mask, uint64_t &KnownZero, + uint64_t &KnownOne, unsigned Depth = 0) const; + + /// ComputeNumSignBits - Return the number of times the sign bit of the + /// register is replicated into the other bits. We know that at least 1 bit + /// is always equal to the sign bit (itself), but other cases can give us + /// information. For example, immediately after an "SRA X, 2", we know that + /// the top 3 bits are all equal to each other, so we return 3. Targets can + /// implement the ComputeNumSignBitsForTarget method in the TargetLowering + /// class to allow target nodes to be understood. + unsigned ComputeNumSignBits(SDOperand Op, unsigned Depth = 0) const; + +private: + void RemoveNodeFromCSEMaps(SDNode *N); + SDNode *AddNonLeafNodeToCSEMaps(SDNode *N); + SDNode *FindModifiedNodeSlot(SDNode *N, SDOperand Op, void *&InsertPos); + SDNode *FindModifiedNodeSlot(SDNode *N, SDOperand Op1, SDOperand Op2, + void *&InsertPos); + SDNode *FindModifiedNodeSlot(SDNode *N, const SDOperand *Ops, unsigned NumOps, + void *&InsertPos); + + void DeleteNodeNotInCSEMaps(SDNode *N); + + // List of non-single value types. + std::list<std::vector<MVT::ValueType> > VTList; + + // Maps to auto-CSE operations. + std::vector<CondCodeSDNode*> CondCodeNodes; + + std::vector<SDNode*> ValueTypeNodes; + std::map<std::string, SDNode*> ExternalSymbols; + std::map<std::string, SDNode*> TargetExternalSymbols; + std::map<std::string, StringSDNode*> StringNodes; +}; + +template <> struct GraphTraits<SelectionDAG*> : public GraphTraits<SDNode*> { + typedef SelectionDAG::allnodes_iterator nodes_iterator; + static nodes_iterator nodes_begin(SelectionDAG *G) { + return G->allnodes_begin(); + } + static nodes_iterator nodes_end(SelectionDAG *G) { + return G->allnodes_end(); + } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/CodeGen/SelectionDAGISel.h b/include/llvm/CodeGen/SelectionDAGISel.h new file mode 100644 index 0000000..497040d --- /dev/null +++ b/include/llvm/CodeGen/SelectionDAGISel.h @@ -0,0 +1,194 @@ +//===-- llvm/CodeGen/SelectionDAGISel.h - Common Base Class------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the SelectionDAGISel class, which is used as the common +// base class for SelectionDAG-based instruction selectors. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SELECTIONDAG_ISEL_H +#define LLVM_CODEGEN_SELECTIONDAG_ISEL_H + +#include "llvm/Pass.h" +#include "llvm/Constant.h" +#include "llvm/CodeGen/SelectionDAG.h" +#include "llvm/CodeGen/SelectionDAGNodes.h" + +namespace llvm { + class SelectionDAGLowering; + class SDOperand; + class SSARegMap; + class MachineBasicBlock; + class MachineFunction; + class MachineInstr; + class TargetLowering; + class FunctionLoweringInfo; + class HazardRecognizer; + +/// SelectionDAGISel - This is the common base class used for SelectionDAG-based +/// pattern-matching instruction selectors. +class SelectionDAGISel : public FunctionPass { +public: + TargetLowering &TLI; + SSARegMap *RegMap; + SelectionDAG *CurDAG; + MachineBasicBlock *BB; + std::vector<SDNode*> TopOrder; + unsigned DAGSize; + static char ID; + + explicit SelectionDAGISel(TargetLowering &tli) : + FunctionPass((intptr_t)&ID), TLI(tli), DAGSize(0) {} + + TargetLowering &getTargetLowering() { return TLI; } + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + virtual bool runOnFunction(Function &Fn); + + unsigned MakeReg(MVT::ValueType VT); + + virtual void EmitFunctionEntryCode(Function &Fn, MachineFunction &MF) {} + virtual void InstructionSelectBasicBlock(SelectionDAG &SD) = 0; + virtual void SelectRootInit() { + DAGSize = CurDAG->AssignTopologicalOrder(TopOrder); + } + + /// SelectInlineAsmMemoryOperand - Select the specified address as a target + /// addressing mode, according to the specified constraint code. If this does + /// not match or is not implemented, return true. The resultant operands + /// (which will appear in the machine instruction) should be added to the + /// OutOps vector. + virtual bool SelectInlineAsmMemoryOperand(const SDOperand &Op, + char ConstraintCode, + std::vector<SDOperand> &OutOps, + SelectionDAG &DAG) { + return true; + } + + /// CanBeFoldedBy - Returns true if the specific operand node N of U can be + /// folded during instruction selection that starts at Root? + virtual bool CanBeFoldedBy(SDNode *N, SDNode *U, SDNode *Root) { return true;} + + /// CreateTargetHazardRecognizer - Return a newly allocated hazard recognizer + /// to use for this target when scheduling the DAG. + virtual HazardRecognizer *CreateTargetHazardRecognizer(); + + /// CaseBlock - This structure is used to communicate between SDLowering and + /// SDISel for the code generation of additional basic blocks needed by multi- + /// case switch statements. + struct CaseBlock { + CaseBlock(ISD::CondCode cc, Value *cmplhs, Value *cmprhs, Value *cmpmiddle, + MachineBasicBlock *truebb, MachineBasicBlock *falsebb, + MachineBasicBlock *me) + : CC(cc), CmpLHS(cmplhs), CmpMHS(cmpmiddle), CmpRHS(cmprhs), + TrueBB(truebb), FalseBB(falsebb), ThisBB(me) {} + // CC - the condition code to use for the case block's setcc node + ISD::CondCode CC; + // CmpLHS/CmpRHS/CmpMHS - The LHS/MHS/RHS of the comparison to emit. + // Emit by default LHS op RHS. MHS is used for range comparisons: + // If MHS is not null: (LHS <= MHS) and (MHS <= RHS). + Value *CmpLHS, *CmpMHS, *CmpRHS; + // TrueBB/FalseBB - the block to branch to if the setcc is true/false. + MachineBasicBlock *TrueBB, *FalseBB; + // ThisBB - the block into which to emit the code for the setcc and branches + MachineBasicBlock *ThisBB; + }; + struct JumpTable { + JumpTable(unsigned R, unsigned J, MachineBasicBlock *M, + MachineBasicBlock *D): Reg(R), JTI(J), MBB(M), Default(D) {}; + + /// Reg - the virtual register containing the index of the jump table entry + //. to jump to. + unsigned Reg; + /// JTI - the JumpTableIndex for this jump table in the function. + unsigned JTI; + /// MBB - the MBB into which to emit the code for the indirect jump. + MachineBasicBlock *MBB; + /// Default - the MBB of the default bb, which is a successor of the range + /// check MBB. This is when updating PHI nodes in successors. + MachineBasicBlock *Default; + }; + struct JumpTableHeader { + JumpTableHeader(uint64_t F, uint64_t L, Value* SV, MachineBasicBlock* H, + bool E = false): + First(F), Last(L), SValue(SV), HeaderBB(H), Emitted(E) {}; + uint64_t First; + uint64_t Last; + Value *SValue; + MachineBasicBlock *HeaderBB; + bool Emitted; + }; + typedef std::pair<JumpTableHeader, JumpTable> JumpTableBlock; + + struct BitTestCase { + BitTestCase(uint64_t M, MachineBasicBlock* T, MachineBasicBlock* Tr): + Mask(M), ThisBB(T), TargetBB(Tr) { }; + uint64_t Mask; + MachineBasicBlock* ThisBB; + MachineBasicBlock* TargetBB; + }; + + typedef SmallVector<BitTestCase, 3> BitTestInfo; + + struct BitTestBlock { + BitTestBlock(uint64_t F, uint64_t R, Value* SV, + unsigned Rg, bool E, + MachineBasicBlock* P, MachineBasicBlock* D, + const BitTestInfo& C): + First(F), Range(R), SValue(SV), Reg(Rg), Emitted(E), + Parent(P), Default(D), Cases(C) { }; + uint64_t First; + uint64_t Range; + Value *SValue; + unsigned Reg; + bool Emitted; + MachineBasicBlock *Parent; + MachineBasicBlock *Default; + BitTestInfo Cases; + }; +protected: + /// Pick a safe ordering and emit instructions for each target node in the + /// graph. + void ScheduleAndEmitDAG(SelectionDAG &DAG); + + /// SelectInlineAsmMemoryOperands - Calls to this are automatically generated + /// by tblgen. Others should not call it. + void SelectInlineAsmMemoryOperands(std::vector<SDOperand> &Ops, + SelectionDAG &DAG); + + // Calls to these predicates are generated by tblgen. + bool CheckAndMask(SDOperand LHS, ConstantSDNode *RHS, int64_t DesiredMaskS); + bool CheckOrMask(SDOperand LHS, ConstantSDNode *RHS, int64_t DesiredMaskS); + +private: + void SelectBasicBlock(BasicBlock *BB, MachineFunction &MF, + FunctionLoweringInfo &FuncInfo); + + void BuildSelectionDAG(SelectionDAG &DAG, BasicBlock *LLVMBB, + std::vector<std::pair<MachineInstr*, unsigned> > &PHINodesToUpdate, + FunctionLoweringInfo &FuncInfo); + void CodeGenAndEmitDAG(SelectionDAG &DAG); + void LowerArguments(BasicBlock *BB, SelectionDAGLowering &SDL, + std::vector<SDOperand> &UnorderedChains); + + /// SwitchCases - Vector of CaseBlock structures used to communicate + /// SwitchInst code generation information. + std::vector<CaseBlock> SwitchCases; + + /// JTCases - Vector of JumpTable structures which holds necessary information + /// for emitting a jump tables during SwitchInst code generation. + std::vector<JumpTableBlock> JTCases; + + std::vector<BitTestBlock> BitTestCases; +}; + +} + +#endif /* LLVM_CODEGEN_SELECTIONDAG_ISEL_H */ diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h new file mode 100644 index 0000000..c96d516 --- /dev/null +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -0,0 +1,1641 @@ +//===-- llvm/CodeGen/SelectionDAGNodes.h - SelectionDAG Nodes ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the SDNode class and derived classes, which are used to +// represent the nodes and operations present in a SelectionDAG. These nodes +// and operations are machine code level operations, with some similarities to +// the GCC RTL representation. +// +// Clients should include the SelectionDAG.h file instead of this file directly. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SELECTIONDAGNODES_H +#define LLVM_CODEGEN_SELECTIONDAGNODES_H + +#include "llvm/Value.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/iterator" +#include "llvm/CodeGen/ValueTypes.h" +#include "llvm/Support/DataTypes.h" +#include <cassert> + +namespace llvm { + +class SelectionDAG; +class GlobalValue; +class MachineBasicBlock; +class MachineConstantPoolValue; +class SDNode; +template <typename T> struct DenseMapKeyInfo; +template <typename T> struct simplify_type; +template <typename T> struct ilist_traits; +template<typename NodeTy, typename Traits> class iplist; +template<typename NodeTy> class ilist_iterator; + +/// SDVTList - This represents a list of ValueType's that has been intern'd by +/// a SelectionDAG. Instances of this simple value class are returned by +/// SelectionDAG::getVTList(...). +/// +struct SDVTList { + const MVT::ValueType *VTs; + unsigned short NumVTs; +}; + +/// ISD namespace - This namespace contains an enum which represents all of the +/// SelectionDAG node types and value types. +/// +namespace ISD { + namespace ParamFlags { + enum Flags { + NoFlagSet = 0, + ZExt = 1<<0, ///< Parameter should be zero extended + ZExtOffs = 0, + SExt = 1<<1, ///< Parameter should be sign extended + SExtOffs = 1, + InReg = 1<<2, ///< Parameter should be passed in register + InRegOffs = 2, + StructReturn = 1<<3, ///< Hidden struct-return pointer + StructReturnOffs = 3, + ByVal = 1<<4, ///< Struct passed by value + ByValOffs = 4, + OrigAlignment = 0x1F<<27, + OrigAlignmentOffs = 27 + }; + } + + //===--------------------------------------------------------------------===// + /// ISD::NodeType enum - This enum defines all of the operators valid in a + /// SelectionDAG. + /// + enum NodeType { + // DELETED_NODE - This is an illegal flag value that is used to catch + // errors. This opcode is not a legal opcode for any node. + DELETED_NODE, + + // EntryToken - This is the marker used to indicate the start of the region. + EntryToken, + + // Token factor - This node takes multiple tokens as input and produces a + // single token result. This is used to represent the fact that the operand + // operators are independent of each other. + TokenFactor, + + // AssertSext, AssertZext - These nodes record if a register contains a + // value that has already been zero or sign extended from a narrower type. + // These nodes take two operands. The first is the node that has already + // been extended, and the second is a value type node indicating the width + // of the extension + AssertSext, AssertZext, + + // Various leaf nodes. + STRING, BasicBlock, VALUETYPE, CONDCODE, Register, + Constant, ConstantFP, + GlobalAddress, GlobalTLSAddress, FrameIndex, + JumpTable, ConstantPool, ExternalSymbol, + + // The address of the GOT + GLOBAL_OFFSET_TABLE, + + // FRAMEADDR, RETURNADDR - These nodes represent llvm.frameaddress and + // llvm.returnaddress on the DAG. These nodes take one operand, the index + // of the frame or return address to return. An index of zero corresponds + // to the current function's frame or return address, an index of one to the + // parent's frame or return address, and so on. + FRAMEADDR, RETURNADDR, + + // FRAME_TO_ARGS_OFFSET - This node represents offset from frame pointer to + // first (possible) on-stack argument. This is needed for correct stack + // 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 = 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 + // execution to HANDLER. Many platform-related details also :) + EH_RETURN, + + // TargetConstant* - Like Constant*, but the DAG does not do any folding or + // simplification of the constant. + TargetConstant, + TargetConstantFP, + + // TargetGlobalAddress - Like GlobalAddress, but the DAG does no folding or + // anything else with this node, and this is valid in the target-specific + // dag, turning into a GlobalAddress operand. + TargetGlobalAddress, + TargetGlobalTLSAddress, + TargetFrameIndex, + TargetJumpTable, + TargetConstantPool, + TargetExternalSymbol, + + /// RESULT = INTRINSIC_WO_CHAIN(INTRINSICID, arg1, arg2, ...) + /// This node represents a target intrinsic function with no side effects. + /// The first operand is the ID number of the intrinsic from the + /// llvm::Intrinsic namespace. The operands to the intrinsic follow. The + /// node has returns the result of the intrinsic. + INTRINSIC_WO_CHAIN, + + /// RESULT,OUTCHAIN = INTRINSIC_W_CHAIN(INCHAIN, INTRINSICID, arg1, ...) + /// This node represents a target intrinsic function with side effects that + /// returns a result. The first operand is a chain pointer. The second is + /// the ID number of the intrinsic from the llvm::Intrinsic namespace. The + /// operands to the intrinsic follow. The node has two results, the result + /// of the intrinsic and an output chain. + INTRINSIC_W_CHAIN, + + /// OUTCHAIN = INTRINSIC_VOID(INCHAIN, INTRINSICID, arg1, arg2, ...) + /// This node represents a target intrinsic function with side effects that + /// does not return a result. The first operand is a chain pointer. The + /// second is the ID number of the intrinsic from the llvm::Intrinsic + /// namespace. The operands to the intrinsic follow. + INTRINSIC_VOID, + + // CopyToReg - This node has three operands: a chain, a register number to + // set to this value, and a value. + CopyToReg, + + // CopyFromReg - This node indicates that the input value is a virtual or + // physical register that is defined outside of the scope of this + // SelectionDAG. The register is available from the RegSDNode object. + CopyFromReg, + + // UNDEF - An undefined node + UNDEF, + + /// FORMAL_ARGUMENTS(CHAIN, CC#, ISVARARG, FLAG0, ..., FLAGn) - This node + /// represents the formal arguments for a function. CC# is a Constant value + /// indicating the calling convention of the function, and ISVARARG is a + /// flag that indicates whether the function is varargs or not. This node + /// has one result value for each incoming argument, plus one for the output + /// chain. It must be custom legalized. See description of CALL node for + /// FLAG argument contents explanation. + /// + FORMAL_ARGUMENTS, + + /// RV1, RV2...RVn, CHAIN = CALL(CHAIN, CC#, ISVARARG, ISTAILCALL, CALLEE, + /// ARG0, FLAG0, ARG1, FLAG1, ... ARGn, FLAGn) + /// This node represents a fully general function call, before the legalizer + /// runs. This has one result value for each argument / flag pair, plus + /// a chain result. It must be custom legalized. Flag argument indicates + /// misc. argument attributes. Currently: + /// Bit 0 - signness + /// Bit 1 - 'inreg' attribute + /// Bit 2 - 'sret' attribute + /// Bits 31:27 - argument ABI alignment in the first argument piece and + /// alignment '1' in other argument pieces. + CALL, + + // EXTRACT_ELEMENT - This is used to get the first or second (determined by + // a Constant, which is required to be operand #1), element of the aggregate + // value specified as operand #0. This is only for use before legalization, + // for values that will be broken into multiple registers. + EXTRACT_ELEMENT, + + // BUILD_PAIR - This is the opposite of EXTRACT_ELEMENT in some ways. Given + // two values of the same integer value type, this produces a value twice as + // big. Like EXTRACT_ELEMENT, this can only be used before legalization. + BUILD_PAIR, + + // MERGE_VALUES - This node takes multiple discrete operands and returns + // them all as its individual results. This nodes has exactly the same + // number of inputs and outputs, and is only valid before legalization. + // This node is useful for some pieces of the code generator that want to + // think about a single node with multiple results, not multiple nodes. + MERGE_VALUES, + + // Simple integer binary arithmetic operators. + ADD, SUB, MUL, SDIV, UDIV, SREM, UREM, + + // CARRY_FALSE - This node is used when folding other nodes, + // like ADDC/SUBC, which indicate the carry result is always false. + CARRY_FALSE, + + // Carry-setting nodes for multiple precision addition and subtraction. + // These nodes take two operands of the same value type, and produce two + // results. The first result is the normal add or sub result, the second + // result is the carry flag result. + ADDC, SUBC, + + // Carry-using nodes for multiple precision addition and subtraction. These + // nodes take three operands: The first two are the normal lhs and rhs to + // the add or sub, and the third is the input carry flag. These nodes + // produce two results; the normal result of the add or sub, and the output + // carry flag. These nodes both read and write a carry flag to allow them + // to them to be chained together for add and sub of arbitrarily large + // values. + ADDE, SUBE, + + // Simple binary floating point operators. + FADD, FSUB, FMUL, FDIV, FREM, + + // FCOPYSIGN(X, Y) - Return the value of X with the sign of Y. NOTE: This + // DAG node does not require that X and Y have the same type, just that they + // are both floating point. X and the result must have the same type. + // FCOPYSIGN(f32, f64) is allowed. + FCOPYSIGN, + + /// BUILD_VECTOR(ELT0, ELT1, ELT2, ELT3,...) - Return a vector + /// with the specified, possibly variable, elements. The number of elements + /// is required to be a power of two. + BUILD_VECTOR, + + /// INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element + /// at IDX replaced with VAL. + INSERT_VECTOR_ELT, + + /// EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR + /// identified by the (potentially variable) element number IDX. + EXTRACT_VECTOR_ELT, + + /// CONCAT_VECTORS(VECTOR0, VECTOR1, ...) - Given a number of values of + /// vector type with the same length and element type, this produces a + /// concatenated vector result value, with length equal to the sum of the + /// lengths of the input vectors. + CONCAT_VECTORS, + + /// EXTRACT_SUBVECTOR(VECTOR, IDX) - Returns a subvector from VECTOR (an + /// vector value) starting with the (potentially variable) element number + /// IDX, which must be a multiple of the result vector length. + EXTRACT_SUBVECTOR, + + /// VECTOR_SHUFFLE(VEC1, VEC2, SHUFFLEVEC) - Returns a vector, of the same + /// type as VEC1/VEC2. SHUFFLEVEC is a BUILD_VECTOR of constant int values + /// (regardless of whether its datatype is legal or not) that indicate + /// which value each result element will get. The elements of VEC1/VEC2 are + /// enumerated in order. This is quite similar to the Altivec 'vperm' + /// instruction, except that the indices must be constants and are in terms + /// of the element size of VEC1/VEC2, not in terms of bytes. + VECTOR_SHUFFLE, + + /// SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a + /// scalar value into the low element of the resultant vector type. The top + /// elements of the vector are undefined. + SCALAR_TO_VECTOR, + + // MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing + // an unsigned/signed value of type i[2*n], then return the top part. + MULHU, MULHS, + + // Bitwise operators - logical and, logical or, logical xor, shift left, + // shift right algebraic (shift in sign bits), shift right logical (shift in + // zeroes), rotate left, rotate right, and byteswap. + AND, OR, XOR, SHL, SRA, SRL, ROTL, ROTR, BSWAP, + + // Counting operators + CTTZ, CTLZ, CTPOP, + + // Select(COND, TRUEVAL, FALSEVAL) + SELECT, + + // Select with condition operator - This selects between a true value and + // a false value (ops #2 and #3) based on the boolean result of comparing + // the lhs and rhs (ops #0 and #1) of a conditional expression with the + // condition code in op #4, a CondCodeSDNode. + SELECT_CC, + + // SetCC operator - This evaluates to a boolean (i1) true value if the + // condition is true. The operands to this are the left and right operands + // to compare (ops #0, and #1) and the condition code to compare them with + // (op #2) as a CondCodeSDNode. + SETCC, + + // SHL_PARTS/SRA_PARTS/SRL_PARTS - These operators are used for expanded + // integer shift operations, just like ADD/SUB_PARTS. The operation + // ordering is: + // [Lo,Hi] = op [LoLHS,HiLHS], Amt + SHL_PARTS, SRA_PARTS, SRL_PARTS, + + // Conversion operators. These are all single input single output + // operations. For all of these, the result type must be strictly + // wider or narrower (depending on the operation) than the source + // type. + + // SIGN_EXTEND - Used for integer types, replicating the sign bit + // into new bits. + SIGN_EXTEND, + + // ZERO_EXTEND - Used for integer types, zeroing the new bits. + ZERO_EXTEND, + + // ANY_EXTEND - Used for integer types. The high bits are undefined. + ANY_EXTEND, + + // TRUNCATE - Completely drop the high bits. + TRUNCATE, + + // [SU]INT_TO_FP - These operators convert integers (whose interpreted sign + // depends on the first letter) to floating point. + SINT_TO_FP, + UINT_TO_FP, + + // SIGN_EXTEND_INREG - This operator atomically performs a SHL/SRA pair to + // sign extend a small value in a large integer register (e.g. sign + // extending the low 8 bits of a 32-bit register to fill the top 24 bits + // with the 7th bit). The size of the smaller type is indicated by the 1th + // operand, a ValueType node. + SIGN_EXTEND_INREG, + + // FP_TO_[US]INT - Convert a floating point value to a signed or unsigned + // integer. + FP_TO_SINT, + FP_TO_UINT, + + // FP_ROUND - Perform a rounding operation from the current + // precision down to the specified precision (currently always 64->32). + FP_ROUND, + + // FP_ROUND_INREG - This operator takes a floating point register, and + // rounds it to a floating point value. It then promotes it and returns it + // in a register of the same size. This operation effectively just discards + // excess precision. The type to round down to is specified by the 1th + // operation, a VTSDNode (currently always 64->32->64). + FP_ROUND_INREG, + + // FP_EXTEND - Extend a smaller FP type into a larger FP type. + FP_EXTEND, + + // BIT_CONVERT - Theis operator converts between integer and FP values, as + // if one was stored to memory as integer and the other was loaded from the + // same address (or equivalently for vector format conversions, etc). The + // source and result are required to have the same bit size (e.g. + // f32 <-> i32). This can also be used for int-to-int or fp-to-fp + // conversions, but that is a noop, deleted by getNode(). + BIT_CONVERT, + + // FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI - Perform unary floating point + // negation, absolute value, square root, sine and cosine, and powi + // operations. + FNEG, FABS, FSQRT, FSIN, FCOS, FPOWI, + + // LOAD and STORE have token chains as their first operand, then the same + // operands as an LLVM load/store instruction, then an offset node that + // is added / subtracted from the base pointer to form the address (for + // indexed memory ops). + LOAD, STORE, + + // TRUNCSTORE - This operators truncates (for integer) or rounds (for FP) a + // value and stores it to memory in one operation. This can be used for + // either integer or floating point operands. The first four operands of + // this are the same as a standard store. The fifth is the ValueType to + // store it as (which will be smaller than the source value). + TRUNCSTORE, + + // DYNAMIC_STACKALLOC - Allocate some number of bytes on the stack aligned + // to a specified boundary. This node always has two return values: a new + // stack pointer value and a chain. The first operand is the token chain, + // the second is the number of bytes to allocate, and the third is the + // alignment boundary. The size is guaranteed to be a multiple of the stack + // alignment, and the alignment is guaranteed to be bigger than the stack + // alignment (if required) or 0 to get standard stack alignment. + DYNAMIC_STACKALLOC, + + // Control flow instructions. These all have token chains. + + // BR - Unconditional branch. The first operand is the chain + // operand, the second is the MBB to branch to. + BR, + + // BRIND - Indirect branch. The first operand is the chain, the second + // is the value to branch to, which must be of the same type as the target's + // pointer type. + BRIND, + + // BR_JT - Jumptable branch. The first operand is the chain, the second + // is the jumptable index, the last one is the jumptable entry index. + BR_JT, + + // BRCOND - Conditional branch. The first operand is the chain, + // the second is the condition, the third is the block to branch + // to if the condition is true. + BRCOND, + + // BR_CC - Conditional branch. The behavior is like that of SELECT_CC, in + // that the condition is represented as condition code, and two nodes to + // compare, rather than as a combined SetCC node. The operands in order are + // chain, cc, lhs, rhs, block to branch to if condition is true. + BR_CC, + + // RET - Return from function. The first operand is the chain, + // and any subsequent operands are pairs of return value and return value + // signness for the function. This operation can have variable number of + // operands. + RET, + + // INLINEASM - Represents an inline asm block. This node always has two + // return values: a chain and a flag result. The inputs are as follows: + // Operand #0 : Input chain. + // Operand #1 : a ExternalSymbolSDNode with a pointer to the asm string. + // Operand #2n+2: A RegisterNode. + // Operand #2n+3: A TargetConstant, indicating if the reg is a use/def + // Operand #last: Optional, an incoming flag. + INLINEASM, + + // LABEL - Represents a label in mid basic block used to track + // locations needed for debug and exception handling tables. This node + // returns a chain. + // Operand #0 : input chain. + // Operand #1 : module unique number use to identify the label. + LABEL, + + // STACKSAVE - STACKSAVE has one operand, an input chain. It produces a + // value, the same type as the pointer type for the system, and an output + // chain. + STACKSAVE, + + // STACKRESTORE has two operands, an input chain and a pointer to restore to + // it returns an output chain. + STACKRESTORE, + + // MEMSET/MEMCPY/MEMMOVE - The first operand is the chain, and the rest + // correspond to the operands of the LLVM intrinsic functions. The only + // result is a token chain. The alignment argument is guaranteed to be a + // Constant node. + MEMSET, + MEMMOVE, + MEMCPY, + + // CALLSEQ_START/CALLSEQ_END - These operators mark the beginning and end of + // a call sequence, and carry arbitrary information that target might want + // to know. The first operand is a chain, the rest are specified by the + // target and not touched by the DAG optimizers. + CALLSEQ_START, // Beginning of a call sequence + CALLSEQ_END, // End of a call sequence + + // VAARG - VAARG has three operands: an input chain, a pointer, and a + // SRCVALUE. It returns a pair of values: the vaarg value and a new chain. + VAARG, + + // VACOPY - VACOPY has five operands: an input chain, a destination pointer, + // a source pointer, a SRCVALUE for the destination, and a SRCVALUE for the + // source. + VACOPY, + + // VAEND, VASTART - VAEND and VASTART have three operands: an input chain, a + // pointer, and a SRCVALUE. + VAEND, VASTART, + + // SRCVALUE - This corresponds to a Value*, and is used to associate memory + // locations with their value. This allows one use alias analysis + // information in the backend. + SRCVALUE, + + // PCMARKER - This corresponds to the pcmarker intrinsic. + PCMARKER, + + // READCYCLECOUNTER - This corresponds to the readcyclecounter intrinsic. + // The only operand is a chain and a value and a chain are produced. The + // value is the contents of the architecture specific cycle counter like + // register (or other high accuracy low latency clock source) + READCYCLECOUNTER, + + // HANDLENODE node - Used as a handle for various purposes. + HANDLENODE, + + // LOCATION - This node is used to represent a source location for debug + // info. It takes token chain as input, then a line number, then a column + // number, then a filename, then a working dir. It produces a token chain + // as output. + LOCATION, + + // DEBUG_LOC - This node is used to represent source line information + // embedded in the code. It takes a token chain as input, then a line + // number, then a column then a file id (provided by MachineModuleInfo.) It + // produces a token chain as output. + DEBUG_LOC, + + // BUILTIN_OP_END - This must be the last enum value in this list. + BUILTIN_OP_END + }; + + /// Node predicates + + /// isBuildVectorAllOnes - Return true if the specified node is a + /// BUILD_VECTOR where all of the elements are ~0 or undef. + bool isBuildVectorAllOnes(const SDNode *N); + + /// isBuildVectorAllZeros - Return true if the specified node is a + /// BUILD_VECTOR where all of the elements are 0 or undef. + bool isBuildVectorAllZeros(const SDNode *N); + + //===--------------------------------------------------------------------===// + /// MemIndexedMode enum - This enum defines the load / store indexed + /// addressing modes. + /// + /// UNINDEXED "Normal" load / store. The effective address is already + /// computed and is available in the base pointer. The offset + /// operand is always undefined. In addition to producing a + /// chain, an unindexed load produces one value (result of the + /// load); an unindexed store does not produces a value. + /// + /// PRE_INC Similar to the unindexed mode where the effective address is + /// PRE_DEC the value of the base pointer add / subtract the offset. + /// It considers the computation as being folded into the load / + /// store operation (i.e. the load / store does the address + /// computation as well as performing the memory transaction). + /// The base operand is always undefined. In addition to + /// producing a chain, pre-indexed load produces two values + /// (result of the load and the result of the address + /// computation); a pre-indexed store produces one value (result + /// of the address computation). + /// + /// POST_INC The effective address is the value of the base pointer. The + /// POST_DEC value of the offset operand is then added to / subtracted + /// from the base after memory transaction. In addition to + /// producing a chain, post-indexed load produces two values + /// (the result of the load and the result of the base +/- offset + /// computation); a post-indexed store produces one value (the + /// the result of the base +/- offset computation). + /// + enum MemIndexedMode { + UNINDEXED = 0, + PRE_INC, + PRE_DEC, + POST_INC, + POST_DEC, + LAST_INDEXED_MODE + }; + + //===--------------------------------------------------------------------===// + /// LoadExtType enum - This enum defines the three variants of LOADEXT + /// (load with extension). + /// + /// SEXTLOAD loads the integer operand and sign extends it to a larger + /// integer result type. + /// ZEXTLOAD loads the integer operand and zero extends it to a larger + /// integer result type. + /// EXTLOAD is used for three things: floating point extending loads, + /// integer extending loads [the top bits are undefined], and vector + /// extending loads [load into low elt]. + /// + enum LoadExtType { + NON_EXTLOAD = 0, + EXTLOAD, + SEXTLOAD, + ZEXTLOAD, + LAST_LOADX_TYPE + }; + + //===--------------------------------------------------------------------===// + /// ISD::CondCode enum - These are ordered carefully to make the bitfields + /// below work out, when considering SETFALSE (something that never exists + /// dynamically) as 0. "U" -> Unsigned (for integer operands) or Unordered + /// (for floating point), "L" -> Less than, "G" -> Greater than, "E" -> Equal + /// to. If the "N" column is 1, the result of the comparison is undefined if + /// the input is a NAN. + /// + /// All of these (except for the 'always folded ops') should be handled for + /// floating point. For integer, only the SETEQ,SETNE,SETLT,SETLE,SETGT, + /// SETGE,SETULT,SETULE,SETUGT, and SETUGE opcodes are used. + /// + /// Note that these are laid out in a specific order to allow bit-twiddling + /// to transform conditions. + enum CondCode { + // Opcode N U L G E Intuitive operation + SETFALSE, // 0 0 0 0 Always false (always folded) + SETOEQ, // 0 0 0 1 True if ordered and equal + SETOGT, // 0 0 1 0 True if ordered and greater than + SETOGE, // 0 0 1 1 True if ordered and greater than or equal + SETOLT, // 0 1 0 0 True if ordered and less than + SETOLE, // 0 1 0 1 True if ordered and less than or equal + SETONE, // 0 1 1 0 True if ordered and operands are unequal + SETO, // 0 1 1 1 True if ordered (no nans) + SETUO, // 1 0 0 0 True if unordered: isnan(X) | isnan(Y) + SETUEQ, // 1 0 0 1 True if unordered or equal + SETUGT, // 1 0 1 0 True if unordered or greater than + SETUGE, // 1 0 1 1 True if unordered, greater than, or equal + SETULT, // 1 1 0 0 True if unordered or less than + SETULE, // 1 1 0 1 True if unordered, less than, or equal + SETUNE, // 1 1 1 0 True if unordered or not equal + SETTRUE, // 1 1 1 1 Always true (always folded) + // Don't care operations: undefined if the input is a nan. + SETFALSE2, // 1 X 0 0 0 Always false (always folded) + SETEQ, // 1 X 0 0 1 True if equal + SETGT, // 1 X 0 1 0 True if greater than + SETGE, // 1 X 0 1 1 True if greater than or equal + SETLT, // 1 X 1 0 0 True if less than + SETLE, // 1 X 1 0 1 True if less than or equal + SETNE, // 1 X 1 1 0 True if not equal + SETTRUE2, // 1 X 1 1 1 Always true (always folded) + + SETCC_INVALID // Marker value. + }; + + /// isSignedIntSetCC - Return true if this is a setcc instruction that + /// performs a signed comparison when used with integer operands. + inline bool isSignedIntSetCC(CondCode Code) { + return Code == SETGT || Code == SETGE || Code == SETLT || Code == SETLE; + } + + /// isUnsignedIntSetCC - Return true if this is a setcc instruction that + /// performs an unsigned comparison when used with integer operands. + inline bool isUnsignedIntSetCC(CondCode Code) { + return Code == SETUGT || Code == SETUGE || Code == SETULT || Code == SETULE; + } + + /// isTrueWhenEqual - Return true if the specified condition returns true if + /// the two operands to the condition are equal. Note that if one of the two + /// operands is a NaN, this value is meaningless. + inline bool isTrueWhenEqual(CondCode Cond) { + return ((int)Cond & 1) != 0; + } + + /// getUnorderedFlavor - This function returns 0 if the condition is always + /// false if an operand is a NaN, 1 if the condition is always true if the + /// operand is a NaN, and 2 if the condition is undefined if the operand is a + /// NaN. + inline unsigned getUnorderedFlavor(CondCode Cond) { + return ((int)Cond >> 3) & 3; + } + + /// getSetCCInverse - Return the operation corresponding to !(X op Y), where + /// 'op' is a valid SetCC operation. + CondCode getSetCCInverse(CondCode Operation, bool isInteger); + + /// getSetCCSwappedOperands - Return the operation corresponding to (Y op X) + /// when given the operation for (X op Y). + CondCode getSetCCSwappedOperands(CondCode Operation); + + /// getSetCCOrOperation - Return the result of a logical OR between different + /// comparisons of identical values: ((X op1 Y) | (X op2 Y)). This + /// function returns SETCC_INVALID if it is not possible to represent the + /// resultant comparison. + CondCode getSetCCOrOperation(CondCode Op1, CondCode Op2, bool isInteger); + + /// getSetCCAndOperation - Return the result of a logical AND between + /// different comparisons of identical values: ((X op1 Y) & (X op2 Y)). This + /// function returns SETCC_INVALID if it is not possible to represent the + /// resultant comparison. + CondCode getSetCCAndOperation(CondCode Op1, CondCode Op2, bool isInteger); +} // end llvm::ISD namespace + + +//===----------------------------------------------------------------------===// +/// SDOperand - Unlike LLVM values, Selection DAG nodes may return multiple +/// values as the result of a computation. Many nodes return multiple values, +/// from loads (which define a token and a return value) to ADDC (which returns +/// a result and a carry value), to calls (which may return an arbitrary number +/// of values). +/// +/// As such, each use of a SelectionDAG computation must indicate the node that +/// computes it as well as which return value to use from that node. This pair +/// of information is represented with the SDOperand value type. +/// +class SDOperand { +public: + SDNode *Val; // The node defining the value we are using. + unsigned ResNo; // Which return value of the node we are using. + + SDOperand() : Val(0), ResNo(0) {} + SDOperand(SDNode *val, unsigned resno) : Val(val), ResNo(resno) {} + + bool operator==(const SDOperand &O) const { + return Val == O.Val && ResNo == O.ResNo; + } + bool operator!=(const SDOperand &O) const { + return !operator==(O); + } + bool operator<(const SDOperand &O) const { + return Val < O.Val || (Val == O.Val && ResNo < O.ResNo); + } + + SDOperand getValue(unsigned R) const { + return SDOperand(Val, R); + } + + // isOperand - Return true if this node is an operand of N. + bool isOperand(SDNode *N) const; + + /// getValueType - Return the ValueType of the referenced return value. + /// + inline MVT::ValueType getValueType() const; + + // Forwarding methods - These forward to the corresponding methods in SDNode. + inline unsigned getOpcode() const; + inline unsigned getNumOperands() const; + inline const SDOperand &getOperand(unsigned i) const; + inline uint64_t getConstantOperandVal(unsigned i) const; + inline bool isTargetOpcode() const; + inline unsigned getTargetOpcode() const; + + /// hasOneUse - Return true if there is exactly one operation using this + /// result value of the defining operator. + inline bool hasOneUse() const; +}; + + +template<> struct DenseMapKeyInfo<SDOperand> { + static inline SDOperand getEmptyKey() { return SDOperand((SDNode*)-1, -1U); } + static inline SDOperand getTombstoneKey() { return SDOperand((SDNode*)-1, 0);} + static unsigned getHashValue(const SDOperand &Val) { + return (unsigned)((uintptr_t)Val.Val >> 4) ^ + (unsigned)((uintptr_t)Val.Val >> 9) + Val.ResNo; + } + static bool isPod() { return true; } +}; + +/// simplify_type specializations - Allow casting operators to work directly on +/// SDOperands as if they were SDNode*'s. +template<> struct simplify_type<SDOperand> { + typedef SDNode* SimpleType; + static SimpleType getSimplifiedValue(const SDOperand &Val) { + return static_cast<SimpleType>(Val.Val); + } +}; +template<> struct simplify_type<const SDOperand> { + typedef SDNode* SimpleType; + static SimpleType getSimplifiedValue(const SDOperand &Val) { + return static_cast<SimpleType>(Val.Val); + } +}; + + +/// SDNode - Represents one node in the SelectionDAG. +/// +class SDNode : public FoldingSetNode { + /// NodeType - The operation that this node performs. + /// + unsigned short NodeType; + + /// OperandsNeedDelete - This is true if OperandList was new[]'d. If true, + /// then they will be delete[]'d when the node is destroyed. + bool OperandsNeedDelete : 1; + + /// NodeId - Unique id per SDNode in the DAG. + int NodeId; + + /// OperandList - The values that are used by this operation. + /// + SDOperand *OperandList; + + /// ValueList - The types of the values this node defines. SDNode's may + /// define multiple values simultaneously. + const MVT::ValueType *ValueList; + + /// NumOperands/NumValues - The number of entries in the Operand/Value list. + unsigned short NumOperands, NumValues; + + /// Prev/Next pointers - These pointers form the linked list of of the + /// AllNodes list in the current DAG. + SDNode *Prev, *Next; + friend struct ilist_traits<SDNode>; + + /// Uses - These are all of the SDNode's that use a value produced by this + /// node. + SmallVector<SDNode*,3> Uses; + + // Out-of-line virtual method to give class a home. + virtual void ANCHOR(); +public: + virtual ~SDNode() { + assert(NumOperands == 0 && "Operand list not cleared before deletion"); + NodeType = ISD::DELETED_NODE; + } + + //===--------------------------------------------------------------------===// + // Accessors + // + unsigned getOpcode() const { return NodeType; } + bool isTargetOpcode() const { return NodeType >= ISD::BUILTIN_OP_END; } + unsigned getTargetOpcode() const { + assert(isTargetOpcode() && "Not a target opcode!"); + return NodeType - ISD::BUILTIN_OP_END; + } + + size_t use_size() const { return Uses.size(); } + bool use_empty() const { return Uses.empty(); } + bool hasOneUse() const { return Uses.size() == 1; } + + /// getNodeId - Return the unique node id. + /// + int getNodeId() const { return NodeId; } + + typedef SmallVector<SDNode*,3>::const_iterator use_iterator; + use_iterator use_begin() const { return Uses.begin(); } + use_iterator use_end() const { return Uses.end(); } + + /// hasNUsesOfValue - Return true if there are exactly NUSES uses of the + /// indicated value. This method ignores uses of other values defined by this + /// operation. + bool hasNUsesOfValue(unsigned NUses, unsigned Value) const; + + /// isOnlyUse - Return true if this node is the only use of N. + /// + bool isOnlyUse(SDNode *N) const; + + /// isOperand - Return true if this node is an operand of N. + /// + bool isOperand(SDNode *N) const; + + /// isPredecessor - Return true if this node is a predecessor of N. This node + /// is either an operand of N or it can be reached by recursively traversing + /// up the operands. + /// NOTE: this is an expensive method. Use it carefully. + bool isPredecessor(SDNode *N) const; + + /// getNumOperands - Return the number of values used by this operation. + /// + unsigned getNumOperands() const { return NumOperands; } + + /// getConstantOperandVal - Helper method returns the integer value of a + /// ConstantSDNode operand. + uint64_t getConstantOperandVal(unsigned Num) const; + + const SDOperand &getOperand(unsigned Num) const { + assert(Num < NumOperands && "Invalid child # of SDNode!"); + return OperandList[Num]; + } + + typedef const SDOperand* op_iterator; + op_iterator op_begin() const { return OperandList; } + op_iterator op_end() const { return OperandList+NumOperands; } + + + SDVTList getVTList() const { + SDVTList X = { ValueList, NumValues }; + return X; + }; + + /// getNumValues - Return the number of values defined/returned by this + /// operator. + /// + unsigned getNumValues() const { return NumValues; } + + /// getValueType - Return the type of a specified result. + /// + MVT::ValueType getValueType(unsigned ResNo) const { + assert(ResNo < NumValues && "Illegal result number!"); + return ValueList[ResNo]; + } + + typedef const MVT::ValueType* value_iterator; + value_iterator value_begin() const { return ValueList; } + value_iterator value_end() const { return ValueList+NumValues; } + + /// getOperationName - Return the opcode of this operation for printing. + /// + std::string getOperationName(const SelectionDAG *G = 0) const; + static const char* getIndexedModeName(ISD::MemIndexedMode AM); + void dump() const; + void dump(const SelectionDAG *G) const; + + static bool classof(const SDNode *) { return true; } + + /// Profile - Gather unique data for the node. + /// + void Profile(FoldingSetNodeID &ID); + +protected: + friend class SelectionDAG; + + /// getValueTypeList - Return a pointer to the specified value type. + /// + static MVT::ValueType *getValueTypeList(MVT::ValueType VT); + static SDVTList getSDVTList(MVT::ValueType VT) { + SDVTList Ret = { getValueTypeList(VT), 1 }; + return Ret; + } + + SDNode(unsigned Opc, SDVTList VTs, const SDOperand *Ops, unsigned NumOps) + : NodeType(Opc), NodeId(-1) { + OperandsNeedDelete = true; + NumOperands = NumOps; + OperandList = NumOps ? new SDOperand[NumOperands] : 0; + + for (unsigned i = 0; i != NumOps; ++i) { + OperandList[i] = Ops[i]; + Ops[i].Val->Uses.push_back(this); + } + + ValueList = VTs.VTs; + NumValues = VTs.NumVTs; + Prev = 0; Next = 0; + } + SDNode(unsigned Opc, SDVTList VTs) : NodeType(Opc), NodeId(-1) { + OperandsNeedDelete = false; // Operands set with InitOperands. + NumOperands = 0; + OperandList = 0; + + ValueList = VTs.VTs; + NumValues = VTs.NumVTs; + Prev = 0; Next = 0; + } + + /// InitOperands - Initialize the operands list of this node with the + /// specified values, which are part of the node (thus they don't need to be + /// copied in or allocated). + void InitOperands(SDOperand *Ops, unsigned NumOps) { + assert(OperandList == 0 && "Operands already set!"); + NumOperands = NumOps; + OperandList = Ops; + + for (unsigned i = 0; i != NumOps; ++i) + Ops[i].Val->Uses.push_back(this); + } + + /// MorphNodeTo - This frees the operands of the current node, resets the + /// opcode, types, and operands to the specified value. This should only be + /// used by the SelectionDAG class. + void MorphNodeTo(unsigned Opc, SDVTList L, + const SDOperand *Ops, unsigned NumOps); + + void addUser(SDNode *User) { + Uses.push_back(User); + } + void removeUser(SDNode *User) { + // Remove this user from the operand's use list. + for (unsigned i = Uses.size(); ; --i) { + assert(i != 0 && "Didn't find user!"); + if (Uses[i-1] == User) { + Uses[i-1] = Uses.back(); + Uses.pop_back(); + return; + } + } + } + + void setNodeId(int Id) { + NodeId = Id; + } +}; + + +// Define inline functions from the SDOperand class. + +inline unsigned SDOperand::getOpcode() const { + return Val->getOpcode(); +} +inline MVT::ValueType SDOperand::getValueType() const { + return Val->getValueType(ResNo); +} +inline unsigned SDOperand::getNumOperands() const { + return Val->getNumOperands(); +} +inline const SDOperand &SDOperand::getOperand(unsigned i) const { + return Val->getOperand(i); +} +inline uint64_t SDOperand::getConstantOperandVal(unsigned i) const { + return Val->getConstantOperandVal(i); +} +inline bool SDOperand::isTargetOpcode() const { + return Val->isTargetOpcode(); +} +inline unsigned SDOperand::getTargetOpcode() const { + return Val->getTargetOpcode(); +} +inline bool SDOperand::hasOneUse() const { + return Val->hasNUsesOfValue(1, ResNo); +} + +/// UnarySDNode - This class is used for single-operand SDNodes. This is solely +/// to allow co-allocation of node operands with the node itself. +class UnarySDNode : public SDNode { + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. + SDOperand Op; +public: + UnarySDNode(unsigned Opc, SDVTList VTs, SDOperand X) + : SDNode(Opc, VTs), Op(X) { + InitOperands(&Op, 1); + } +}; + +/// BinarySDNode - This class is used for two-operand SDNodes. This is solely +/// to allow co-allocation of node operands with the node itself. +class BinarySDNode : public SDNode { + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. + SDOperand Ops[2]; +public: + BinarySDNode(unsigned Opc, SDVTList VTs, SDOperand X, SDOperand Y) + : SDNode(Opc, VTs) { + Ops[0] = X; + Ops[1] = Y; + InitOperands(Ops, 2); + } +}; + +/// TernarySDNode - This class is used for three-operand SDNodes. This is solely +/// to allow co-allocation of node operands with the node itself. +class TernarySDNode : public SDNode { + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. + SDOperand Ops[3]; +public: + TernarySDNode(unsigned Opc, SDVTList VTs, SDOperand X, SDOperand Y, + SDOperand Z) + : SDNode(Opc, VTs) { + Ops[0] = X; + Ops[1] = Y; + Ops[2] = Z; + InitOperands(Ops, 3); + } +}; + + +/// HandleSDNode - This class is used to form a handle around another node that +/// is persistant and is updated across invocations of replaceAllUsesWith on its +/// operand. This node should be directly created by end-users and not added to +/// the AllNodes list. +class HandleSDNode : public SDNode { + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. + SDOperand Op; +public: + explicit HandleSDNode(SDOperand X) + : SDNode(ISD::HANDLENODE, getSDVTList(MVT::Other)), Op(X) { + InitOperands(&Op, 1); + } + ~HandleSDNode(); + SDOperand getValue() const { return Op; } +}; + +class StringSDNode : public SDNode { + std::string Value; + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. +protected: + friend class SelectionDAG; + explicit StringSDNode(const std::string &val) + : SDNode(ISD::STRING, getSDVTList(MVT::Other)), Value(val) { + } +public: + const std::string &getValue() const { return Value; } + static bool classof(const StringSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::STRING; + } +}; + +class ConstantSDNode : public SDNode { + uint64_t Value; + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. +protected: + friend class SelectionDAG; + ConstantSDNode(bool isTarget, uint64_t val, MVT::ValueType VT) + : SDNode(isTarget ? ISD::TargetConstant : ISD::Constant, getSDVTList(VT)), + Value(val) { + } +public: + + uint64_t getValue() const { return Value; } + + int64_t getSignExtended() const { + unsigned Bits = MVT::getSizeInBits(getValueType(0)); + return ((int64_t)Value << (64-Bits)) >> (64-Bits); + } + + bool isNullValue() const { return Value == 0; } + bool isAllOnesValue() const { + return Value == MVT::getIntVTBitMask(getValueType(0)); + } + + static bool classof(const ConstantSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::Constant || + N->getOpcode() == ISD::TargetConstant; + } +}; + +class ConstantFPSDNode : public SDNode { + double Value; + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. +protected: + friend class SelectionDAG; + ConstantFPSDNode(bool isTarget, double val, MVT::ValueType VT) + : SDNode(isTarget ? ISD::TargetConstantFP : ISD::ConstantFP, + getSDVTList(VT)), Value(val) { + } +public: + + double getValue() const { return Value; } + + /// isExactlyValue - We don't rely on operator== working on double values, as + /// it returns true for things that are clearly not equal, like -0.0 and 0.0. + /// As such, this method can be used to do an exact bit-for-bit comparison of + /// two floating point values. + bool isExactlyValue(double V) const; + + static bool classof(const ConstantFPSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::ConstantFP || + N->getOpcode() == ISD::TargetConstantFP; + } +}; + +class GlobalAddressSDNode : public SDNode { + GlobalValue *TheGlobal; + int Offset; + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. +protected: + friend class SelectionDAG; + GlobalAddressSDNode(bool isTarget, const GlobalValue *GA, MVT::ValueType VT, + int o = 0); +public: + + GlobalValue *getGlobal() const { return TheGlobal; } + int getOffset() const { return Offset; } + + static bool classof(const GlobalAddressSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::GlobalAddress || + N->getOpcode() == ISD::TargetGlobalAddress || + N->getOpcode() == ISD::GlobalTLSAddress || + N->getOpcode() == ISD::TargetGlobalTLSAddress; + } +}; + +class FrameIndexSDNode : public SDNode { + int FI; + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. +protected: + friend class SelectionDAG; + FrameIndexSDNode(int fi, MVT::ValueType VT, bool isTarg) + : SDNode(isTarg ? ISD::TargetFrameIndex : ISD::FrameIndex, getSDVTList(VT)), + FI(fi) { + } +public: + + int getIndex() const { return FI; } + + static bool classof(const FrameIndexSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::FrameIndex || + N->getOpcode() == ISD::TargetFrameIndex; + } +}; + +class JumpTableSDNode : public SDNode { + int JTI; + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. +protected: + friend class SelectionDAG; + JumpTableSDNode(int jti, MVT::ValueType VT, bool isTarg) + : SDNode(isTarg ? ISD::TargetJumpTable : ISD::JumpTable, getSDVTList(VT)), + JTI(jti) { + } +public: + + int getIndex() const { return JTI; } + + static bool classof(const JumpTableSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::JumpTable || + N->getOpcode() == ISD::TargetJumpTable; + } +}; + +class ConstantPoolSDNode : public SDNode { + union { + Constant *ConstVal; + MachineConstantPoolValue *MachineCPVal; + } Val; + int Offset; // It's a MachineConstantPoolValue if top bit is set. + unsigned Alignment; + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. +protected: + friend class SelectionDAG; + ConstantPoolSDNode(bool isTarget, Constant *c, MVT::ValueType VT, + int o=0) + : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, + getSDVTList(VT)), Offset(o), Alignment(0) { + assert((int)Offset >= 0 && "Offset is too large"); + Val.ConstVal = c; + } + ConstantPoolSDNode(bool isTarget, Constant *c, MVT::ValueType VT, int o, + unsigned Align) + : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, + getSDVTList(VT)), Offset(o), Alignment(Align) { + assert((int)Offset >= 0 && "Offset is too large"); + Val.ConstVal = c; + } + ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v, + MVT::ValueType VT, int o=0) + : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, + getSDVTList(VT)), Offset(o), Alignment(0) { + assert((int)Offset >= 0 && "Offset is too large"); + Val.MachineCPVal = v; + Offset |= 1 << (sizeof(unsigned)*8-1); + } + ConstantPoolSDNode(bool isTarget, MachineConstantPoolValue *v, + MVT::ValueType VT, int o, unsigned Align) + : SDNode(isTarget ? ISD::TargetConstantPool : ISD::ConstantPool, + getSDVTList(VT)), Offset(o), Alignment(Align) { + assert((int)Offset >= 0 && "Offset is too large"); + Val.MachineCPVal = v; + Offset |= 1 << (sizeof(unsigned)*8-1); + } +public: + + bool isMachineConstantPoolEntry() const { + return (int)Offset < 0; + } + + Constant *getConstVal() const { + assert(!isMachineConstantPoolEntry() && "Wrong constantpool type"); + return Val.ConstVal; + } + + MachineConstantPoolValue *getMachineCPVal() const { + assert(isMachineConstantPoolEntry() && "Wrong constantpool type"); + return Val.MachineCPVal; + } + + int getOffset() const { + return Offset & ~(1 << (sizeof(unsigned)*8-1)); + } + + // Return the alignment of this constant pool object, which is either 0 (for + // default alignment) or log2 of the desired value. + unsigned getAlignment() const { return Alignment; } + + const Type *getType() const; + + static bool classof(const ConstantPoolSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::ConstantPool || + N->getOpcode() == ISD::TargetConstantPool; + } +}; + +class BasicBlockSDNode : public SDNode { + MachineBasicBlock *MBB; + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. +protected: + friend class SelectionDAG; + explicit BasicBlockSDNode(MachineBasicBlock *mbb) + : SDNode(ISD::BasicBlock, getSDVTList(MVT::Other)), MBB(mbb) { + } +public: + + MachineBasicBlock *getBasicBlock() const { return MBB; } + + static bool classof(const BasicBlockSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::BasicBlock; + } +}; + +class SrcValueSDNode : public SDNode { + const Value *V; + int offset; + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. +protected: + friend class SelectionDAG; + SrcValueSDNode(const Value* v, int o) + : SDNode(ISD::SRCVALUE, getSDVTList(MVT::Other)), V(v), offset(o) { + } + +public: + const Value *getValue() const { return V; } + int getOffset() const { return offset; } + + static bool classof(const SrcValueSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::SRCVALUE; + } +}; + + +class RegisterSDNode : public SDNode { + unsigned Reg; + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. +protected: + friend class SelectionDAG; + RegisterSDNode(unsigned reg, MVT::ValueType VT) + : SDNode(ISD::Register, getSDVTList(VT)), Reg(reg) { + } +public: + + unsigned getReg() const { return Reg; } + + static bool classof(const RegisterSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::Register; + } +}; + +class ExternalSymbolSDNode : public SDNode { + const char *Symbol; + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. +protected: + friend class SelectionDAG; + ExternalSymbolSDNode(bool isTarget, const char *Sym, MVT::ValueType VT) + : SDNode(isTarget ? ISD::TargetExternalSymbol : ISD::ExternalSymbol, + getSDVTList(VT)), Symbol(Sym) { + } +public: + + const char *getSymbol() const { return Symbol; } + + static bool classof(const ExternalSymbolSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::ExternalSymbol || + N->getOpcode() == ISD::TargetExternalSymbol; + } +}; + +class CondCodeSDNode : public SDNode { + ISD::CondCode Condition; + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. +protected: + friend class SelectionDAG; + explicit CondCodeSDNode(ISD::CondCode Cond) + : SDNode(ISD::CONDCODE, getSDVTList(MVT::Other)), Condition(Cond) { + } +public: + + ISD::CondCode get() const { return Condition; } + + static bool classof(const CondCodeSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::CONDCODE; + } +}; + +/// VTSDNode - This class is used to represent MVT::ValueType's, which are used +/// to parameterize some operations. +class VTSDNode : public SDNode { + MVT::ValueType ValueType; + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. +protected: + friend class SelectionDAG; + explicit VTSDNode(MVT::ValueType VT) + : SDNode(ISD::VALUETYPE, getSDVTList(MVT::Other)), ValueType(VT) { + } +public: + + MVT::ValueType getVT() const { return ValueType; } + + static bool classof(const VTSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::VALUETYPE; + } +}; + +/// LoadSDNode - This class is used to represent ISD::LOAD nodes. +/// +class LoadSDNode : public SDNode { + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. + SDOperand Ops[3]; + + // AddrMode - unindexed, pre-indexed, post-indexed. + ISD::MemIndexedMode AddrMode; + + // ExtType - non-ext, anyext, sext, zext. + ISD::LoadExtType ExtType; + + // LoadedVT - VT of loaded value before extension. + MVT::ValueType LoadedVT; + + // SrcValue - Memory location for alias analysis. + const Value *SrcValue; + + // SVOffset - Memory location offset. + int SVOffset; + + // Alignment - Alignment of memory location in bytes. + unsigned Alignment; + + // IsVolatile - True if the load is volatile. + bool IsVolatile; +protected: + friend class SelectionDAG; + LoadSDNode(SDOperand *ChainPtrOff, SDVTList VTs, + ISD::MemIndexedMode AM, ISD::LoadExtType ETy, MVT::ValueType LVT, + const Value *SV, int O=0, unsigned Align=0, bool Vol=false) + : SDNode(ISD::LOAD, VTs), + AddrMode(AM), ExtType(ETy), LoadedVT(LVT), SrcValue(SV), SVOffset(O), + Alignment(Align), IsVolatile(Vol) { + Ops[0] = ChainPtrOff[0]; // Chain + Ops[1] = ChainPtrOff[1]; // Ptr + Ops[2] = ChainPtrOff[2]; // Off + InitOperands(Ops, 3); + assert(Align != 0 && "Loads should have non-zero aligment"); + assert((getOffset().getOpcode() == ISD::UNDEF || + AddrMode != ISD::UNINDEXED) && + "Only indexed load has a non-undef offset operand"); + } +public: + + const SDOperand getChain() const { return getOperand(0); } + const SDOperand getBasePtr() const { return getOperand(1); } + const SDOperand getOffset() const { return getOperand(2); } + ISD::MemIndexedMode getAddressingMode() const { return AddrMode; } + ISD::LoadExtType getExtensionType() const { return ExtType; } + MVT::ValueType getLoadedVT() const { return LoadedVT; } + const Value *getSrcValue() const { return SrcValue; } + int getSrcValueOffset() const { return SVOffset; } + unsigned getAlignment() const { return Alignment; } + bool isVolatile() const { return IsVolatile; } + + static bool classof(const LoadSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::LOAD; + } +}; + +/// StoreSDNode - This class is used to represent ISD::STORE nodes. +/// +class StoreSDNode : public SDNode { + virtual void ANCHOR(); // Out-of-line virtual method to give class a home. + SDOperand Ops[4]; + + // AddrMode - unindexed, pre-indexed, post-indexed. + ISD::MemIndexedMode AddrMode; + + // IsTruncStore - True is the op does a truncation before store. + bool IsTruncStore; + + // StoredVT - VT of the value after truncation. + MVT::ValueType StoredVT; + + // SrcValue - Memory location for alias analysis. + const Value *SrcValue; + + // SVOffset - Memory location offset. + int SVOffset; + + // Alignment - Alignment of memory location in bytes. + unsigned Alignment; + + // IsVolatile - True if the store is volatile. + bool IsVolatile; +protected: + friend class SelectionDAG; + StoreSDNode(SDOperand *ChainValuePtrOff, SDVTList VTs, + ISD::MemIndexedMode AM, bool isTrunc, MVT::ValueType SVT, + const Value *SV, int O=0, unsigned Align=0, bool Vol=false) + : SDNode(ISD::STORE, VTs), + AddrMode(AM), IsTruncStore(isTrunc), StoredVT(SVT), SrcValue(SV), + SVOffset(O), Alignment(Align), IsVolatile(Vol) { + Ops[0] = ChainValuePtrOff[0]; // Chain + Ops[1] = ChainValuePtrOff[1]; // Value + Ops[2] = ChainValuePtrOff[2]; // Ptr + Ops[3] = ChainValuePtrOff[3]; // Off + InitOperands(Ops, 4); + assert(Align != 0 && "Stores should have non-zero aligment"); + assert((getOffset().getOpcode() == ISD::UNDEF || + AddrMode != ISD::UNINDEXED) && + "Only indexed store has a non-undef offset operand"); + } +public: + + const SDOperand getChain() const { return getOperand(0); } + const SDOperand getValue() const { return getOperand(1); } + const SDOperand getBasePtr() const { return getOperand(2); } + const SDOperand getOffset() const { return getOperand(3); } + ISD::MemIndexedMode getAddressingMode() const { return AddrMode; } + bool isTruncatingStore() const { return IsTruncStore; } + MVT::ValueType getStoredVT() const { return StoredVT; } + const Value *getSrcValue() const { return SrcValue; } + int getSrcValueOffset() const { return SVOffset; } + unsigned getAlignment() const { return Alignment; } + bool isVolatile() const { return IsVolatile; } + + static bool classof(const StoreSDNode *) { return true; } + static bool classof(const SDNode *N) { + return N->getOpcode() == ISD::STORE; + } +}; + + +class SDNodeIterator : public forward_iterator<SDNode, ptrdiff_t> { + SDNode *Node; + unsigned Operand; + + SDNodeIterator(SDNode *N, unsigned Op) : Node(N), Operand(Op) {} +public: + bool operator==(const SDNodeIterator& x) const { + return Operand == x.Operand; + } + bool operator!=(const SDNodeIterator& x) const { return !operator==(x); } + + const SDNodeIterator &operator=(const SDNodeIterator &I) { + assert(I.Node == Node && "Cannot assign iterators to two different nodes!"); + Operand = I.Operand; + return *this; + } + + pointer operator*() const { + return Node->getOperand(Operand).Val; + } + pointer operator->() const { return operator*(); } + + SDNodeIterator& operator++() { // Preincrement + ++Operand; + return *this; + } + SDNodeIterator operator++(int) { // Postincrement + SDNodeIterator tmp = *this; ++*this; return tmp; + } + + static SDNodeIterator begin(SDNode *N) { return SDNodeIterator(N, 0); } + static SDNodeIterator end (SDNode *N) { + return SDNodeIterator(N, N->getNumOperands()); + } + + unsigned getOperand() const { return Operand; } + const SDNode *getNode() const { return Node; } +}; + +template <> struct GraphTraits<SDNode*> { + typedef SDNode NodeType; + typedef SDNodeIterator ChildIteratorType; + static inline NodeType *getEntryNode(SDNode *N) { return N; } + static inline ChildIteratorType child_begin(NodeType *N) { + return SDNodeIterator::begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return SDNodeIterator::end(N); + } +}; + +template<> +struct ilist_traits<SDNode> { + static SDNode *getPrev(const SDNode *N) { return N->Prev; } + static SDNode *getNext(const SDNode *N) { return N->Next; } + + static void setPrev(SDNode *N, SDNode *Prev) { N->Prev = Prev; } + static void setNext(SDNode *N, SDNode *Next) { N->Next = Next; } + + static SDNode *createSentinel() { + return new SDNode(ISD::EntryToken, SDNode::getSDVTList(MVT::Other)); + } + static void destroySentinel(SDNode *N) { delete N; } + //static SDNode *createNode(const SDNode &V) { return new SDNode(V); } + + + void addNodeToList(SDNode *NTy) {} + void removeNodeFromList(SDNode *NTy) {} + void transferNodesFromList(iplist<SDNode, ilist_traits> &L2, + const ilist_iterator<SDNode> &X, + const ilist_iterator<SDNode> &Y) {} +}; + +namespace ISD { + /// isNON_EXTLoad - Returns true if the specified node is a non-extending + /// load. + inline bool isNON_EXTLoad(const SDNode *N) { + return N->getOpcode() == ISD::LOAD && + cast<LoadSDNode>(N)->getExtensionType() == ISD::NON_EXTLOAD; + } + + /// isEXTLoad - Returns true if the specified node is a EXTLOAD. + /// + inline bool isEXTLoad(const SDNode *N) { + return N->getOpcode() == ISD::LOAD && + cast<LoadSDNode>(N)->getExtensionType() == ISD::EXTLOAD; + } + + /// isSEXTLoad - Returns true if the specified node is a SEXTLOAD. + /// + inline bool isSEXTLoad(const SDNode *N) { + return N->getOpcode() == ISD::LOAD && + cast<LoadSDNode>(N)->getExtensionType() == ISD::SEXTLOAD; + } + + /// isZEXTLoad - Returns true if the specified node is a ZEXTLOAD. + /// + inline bool isZEXTLoad(const SDNode *N) { + return N->getOpcode() == ISD::LOAD && + cast<LoadSDNode>(N)->getExtensionType() == ISD::ZEXTLOAD; + } + + /// isUNINDEXEDLoad - Returns true if the specified node is a unindexed load. + /// + inline bool isUNINDEXEDLoad(const SDNode *N) { + return N->getOpcode() == ISD::LOAD && + cast<LoadSDNode>(N)->getAddressingMode() == ISD::UNINDEXED; + } + + /// isNON_TRUNCStore - Returns true if the specified node is a non-truncating + /// store. + inline bool isNON_TRUNCStore(const SDNode *N) { + return N->getOpcode() == ISD::STORE && + !cast<StoreSDNode>(N)->isTruncatingStore(); + } + + /// isTRUNCStore - Returns true if the specified node is a truncating + /// store. + inline bool isTRUNCStore(const SDNode *N) { + return N->getOpcode() == ISD::STORE && + cast<StoreSDNode>(N)->isTruncatingStore(); + } +} + + +} // end llvm namespace + +#endif diff --git a/include/llvm/CodeGen/SimpleRegisterCoalescing.h b/include/llvm/CodeGen/SimpleRegisterCoalescing.h new file mode 100644 index 0000000..20bcb89 --- /dev/null +++ b/include/llvm/CodeGen/SimpleRegisterCoalescing.h @@ -0,0 +1,160 @@ +//===-- SimpleRegisterCoalescing.h - Register Coalescing --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a simple register copy coalescing phase. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H +#define LLVM_CODEGEN_SIMPLE_REGISTER_COALESCING_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/LiveInterval.h" +#include "llvm/CodeGen/LiveIntervalAnalysis.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/IndexedMap.h" + +namespace llvm { + + class LiveVariables; + class MRegisterInfo; + class TargetInstrInfo; + class VirtRegMap; + + class SimpleRegisterCoalescing : public MachineFunctionPass { + MachineFunction* mf_; + const TargetMachine* tm_; + const MRegisterInfo* mri_; + const TargetInstrInfo* tii_; + LiveIntervals *li_; + LiveVariables *lv_; + + typedef IndexedMap<unsigned> Reg2RegMap; + Reg2RegMap r2rMap_; + + BitVector allocatableRegs_; + DenseMap<const TargetRegisterClass*, BitVector> allocatableRCRegs_; + + /// JoinedLIs - Keep track which register intervals have been coalesced + /// with other intervals. + BitVector JoinedLIs; + + public: + static char ID; // Pass identifcation, replacement for typeid + SimpleRegisterCoalescing() : MachineFunctionPass((intptr_t)&ID) {}; + + struct CopyRec { + MachineInstr *MI; + unsigned SrcReg, DstReg; + }; + CopyRec getCopyRec(MachineInstr *MI, unsigned SrcReg, unsigned DstReg) { + CopyRec R; + R.MI = MI; + R.SrcReg = SrcReg; + R.DstReg = DstReg; + return R; + } + struct InstrSlots { + enum { + LOAD = 0, + USE = 1, + DEF = 2, + STORE = 3, + NUM = 4 + }; + }; + + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + virtual void releaseMemory(); + + /// runOnMachineFunction - pass entry point + virtual bool runOnMachineFunction(MachineFunction&); + + /// print - Implement the dump method. + virtual void print(std::ostream &O, const Module* = 0) const; + void print(std::ostream *O, const Module* M = 0) const { + if (O) print(*O, M); + } + + private: + /// joinIntervals - join compatible live intervals + void joinIntervals(); + + /// CopyCoalesceInMBB - Coalesce copies in the specified MBB, putting + /// copies that cannot yet be coalesced into the "TryAgain" list. + void CopyCoalesceInMBB(MachineBasicBlock *MBB, + std::vector<CopyRec> *TryAgain, bool PhysOnly = false); + + /// JoinCopy - Attempt to join intervals corresponding to SrcReg/DstReg, + /// which are the src/dst of the copy instruction CopyMI. This returns true + /// if the copy was successfully coalesced away, or if it is never possible + /// to coalesce these this copy, due to register constraints. It returns + /// false if it is not currently possible to coalesce this interval, but + /// it may be possible if other things get coalesced. + bool JoinCopy(MachineInstr *CopyMI, unsigned SrcReg, unsigned DstReg, + bool PhysOnly = false); + + /// JoinIntervals - Attempt to join these two intervals. On failure, this + /// returns false. Otherwise, if one of the intervals being joined is a + /// physreg, this method always canonicalizes DestInt to be it. The output + /// "SrcInt" will not have been modified, so we can use this information + /// below to update aliases. + bool JoinIntervals(LiveInterval &LHS, LiveInterval &RHS); + + /// SimpleJoin - Attempt to join the specified interval into this one. The + /// caller of this method must guarantee that the RHS only contains a single + /// value number and that the RHS is not defined by a copy from this + /// interval. This returns false if the intervals are not joinable, or it + /// joins them and returns true. + bool SimpleJoin(LiveInterval &LHS, LiveInterval &RHS); + + /// Return true if the two specified registers belong to different + /// register classes. The registers may be either phys or virt regs. + bool differingRegisterClasses(unsigned RegA, unsigned RegB) const; + + + bool AdjustCopiesBackFrom(LiveInterval &IntA, LiveInterval &IntB, + MachineInstr *CopyMI); + + /// lastRegisterUse - Returns the last use of the specific register between + /// cycles Start and End. It also returns the use operand by reference. It + /// returns NULL if there are no uses. + MachineInstr *lastRegisterUse(unsigned Start, unsigned End, unsigned Reg, + MachineOperand *&MOU); + + /// findDefOperand - Returns the MachineOperand that is a def of the specific + /// register. It returns NULL if the def is not found. + MachineOperand *findDefOperand(MachineInstr *MI, unsigned Reg); + + /// unsetRegisterKill - Unset IsKill property of all uses of the specific + /// register of the specific instruction. + void unsetRegisterKill(MachineInstr *MI, unsigned Reg); + + /// unsetRegisterKills - Unset IsKill property of all uses of specific register + /// between cycles Start and End. + void unsetRegisterKills(unsigned Start, unsigned End, unsigned Reg); + + /// hasRegisterDef - True if the instruction defines the specific register. + /// + bool hasRegisterDef(MachineInstr *MI, unsigned Reg); + + /// rep - returns the representative of this register + unsigned rep(unsigned Reg) { + unsigned Rep = r2rMap_[Reg]; + if (Rep) + return r2rMap_[Reg] = rep(Rep); + return Reg; + } + + void printRegName(unsigned reg) const; + }; + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h new file mode 100644 index 0000000..d2a6414 --- /dev/null +++ b/include/llvm/CodeGen/ValueTypes.h @@ -0,0 +1,284 @@ +//===- CodeGen/ValueTypes.h - Low-Level Target independ. types --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the set of low-level target independent types which various +// values in the code generator are. This allows the target specific behavior +// of instructions to be described to target independent passes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CODEGEN_VALUETYPES_H +#define LLVM_CODEGEN_VALUETYPES_H + +#include <cassert> +#include <string> +#include "llvm/Support/DataTypes.h" + +namespace llvm { + class Type; + +/// MVT namespace - This namespace defines the SimpleValueType enum, which +/// contains the various low-level value types, and the ValueType typedef. +/// +namespace MVT { // MVT = Machine Value Types + enum SimpleValueType { + // If you change this numbering, you must change the values in ValueTypes.td + // well! + Other = 0, // This is a non-standard value + i1 = 1, // This is a 1 bit integer value + i8 = 2, // This is an 8 bit integer value + i16 = 3, // This is a 16 bit integer value + i32 = 4, // This is a 32 bit integer value + i64 = 5, // This is a 64 bit integer value + i128 = 6, // This is a 128 bit integer value + + f32 = 7, // This is a 32 bit floating point value + f64 = 8, // This is a 64 bit floating point value + f80 = 9, // This is a 80 bit floating point value + f128 = 10, // This is a 128 bit floating point value + Flag = 11, // This is a condition code or machine flag. + + isVoid = 12, // This has no value + + v8i8 = 13, // 8 x i8 + v4i16 = 14, // 4 x i16 + v2i32 = 15, // 2 x i32 + v1i64 = 16, // 1 x i64 + v16i8 = 17, // 16 x i8 + v8i16 = 18, // 8 x i16 + v4i32 = 19, // 4 x i32 + v2i64 = 20, // 2 x i64 + + v2f32 = 21, // 2 x f32 + v4f32 = 22, // 4 x f32 + v2f64 = 23, // 2 x f64 + FIRST_VECTOR_VALUETYPE = v8i8, + LAST_VECTOR_VALUETYPE = v2f64, + + LAST_VALUETYPE = 24, // This always remains at the end of the list. + + // iAny - An integer value of any bit width. This is used for intrinsics + // that have overloadings based on integer bit widths. This is only for + // tblgen's consumption! + iAny = 254, + + // iPTR - An int value the size of the pointer of the current + // target. This should only be used internal to tblgen! + iPTR = 255 + }; + + /// MVT::ValueType - This type holds low-level value types. Valid values + /// include any of the values in the SimpleValueType enum, or any value + /// returned from a function in the MVT namespace that has a ValueType + /// return type. Any value type equal to one of the SimpleValueType enum + /// values is a "simple" value type. All other value types are "extended". + /// + /// Note that simple doesn't necessary mean legal for the target machine. + /// All legal value types must be simple, but often there are some simple + /// value types that are not legal. + /// + /// @internal + /// Currently extended types are always vector types. Extended types are + /// encoded by having the first SimpleTypeBits bits encode the vector + /// element type (which must be a scalar type) and the remaining upper + /// bits encode the vector length, offset by one. + typedef uint32_t ValueType; + + static const int SimpleTypeBits = 8; + + static const uint32_t SimpleTypeMask = + (~uint32_t(0) << (32 - SimpleTypeBits)) >> (32 - SimpleTypeBits); + + /// MVT::isExtendedVT - Test if the given ValueType is extended + /// (as opposed to being simple). + static inline bool isExtendedVT(ValueType VT) { + return VT > SimpleTypeMask; + } + + /// MVT::isInteger - Return true if this is an integer, or a vector integer + /// type. + static inline bool isInteger(ValueType VT) { + ValueType SVT = VT & SimpleTypeMask; + return (SVT >= i1 && SVT <= i128) || (SVT >= v8i8 && SVT <= v2i64); + } + + /// MVT::isFloatingPoint - Return true if this is an FP, or a vector FP type. + static inline bool isFloatingPoint(ValueType VT) { + ValueType SVT = VT & SimpleTypeMask; + return (SVT >= f32 && SVT <= f128) || (SVT >= v2f32 && SVT <= v2f64); + } + + /// MVT::isVector - Return true if this is a vector value type. + static inline bool isVector(ValueType VT) { + return (VT >= FIRST_VECTOR_VALUETYPE && VT <= LAST_VECTOR_VALUETYPE) || + isExtendedVT(VT); + } + + /// MVT::getVectorElementType - Given a vector type, return the type of + /// each element. + static inline ValueType getVectorElementType(ValueType VT) { + switch (VT) { + default: + if (isExtendedVT(VT)) + return VT & SimpleTypeMask; + assert(0 && "Invalid vector type!"); + case v8i8 : + case v16i8: return i8; + case v4i16: + case v8i16: return i16; + case v2i32: + case v4i32: return i32; + case v1i64: + case v2i64: return i64; + case v2f32: + case v4f32: return f32; + case v2f64: return f64; + } + } + + /// MVT::getVectorNumElements - Given a vector type, return the + /// number of elements it contains. + static inline unsigned getVectorNumElements(ValueType VT) { + switch (VT) { + default: + if (isExtendedVT(VT)) + return ((VT & ~SimpleTypeMask) >> SimpleTypeBits) - 1; + assert(0 && "Invalid vector type!"); + case v16i8: return 16; + case v8i8 : + case v8i16: return 8; + case v4i16: + case v4i32: + case v4f32: return 4; + case v2i32: + case v2i64: + case v2f32: + case v2f64: return 2; + case v1i64: return 1; + } + } + + /// MVT::getSizeInBits - Return the size of the specified value type + /// in bits. + /// + static inline unsigned getSizeInBits(ValueType VT) { + switch (VT) { + default: + if (isExtendedVT(VT)) + return getSizeInBits(getVectorElementType(VT)) * + getVectorNumElements(VT); + assert(0 && "ValueType has no known size!"); + case MVT::i1 : return 1; + case MVT::i8 : return 8; + case MVT::i16 : return 16; + case MVT::f32 : + case MVT::i32 : return 32; + case MVT::f64 : + case MVT::i64 : + case MVT::v8i8: + case MVT::v4i16: + case MVT::v2i32: + case MVT::v1i64: + case MVT::v2f32: return 64; + case MVT::f80 : return 80; + case MVT::f128: + case MVT::i128: + case MVT::v16i8: + case MVT::v8i16: + case MVT::v4i32: + case MVT::v2i64: + case MVT::v4f32: + case MVT::v2f64: return 128; + } + } + + /// MVT::getVectorType - Returns the ValueType that represents a vector + /// NumElements in length, where each element is of type VT. + /// + static inline ValueType getVectorType(ValueType VT, unsigned NumElements) { + switch (VT) { + default: + break; + case MVT::i8: + if (NumElements == 8) return MVT::v8i8; + if (NumElements == 16) return MVT::v16i8; + break; + case MVT::i16: + if (NumElements == 4) return MVT::v4i16; + if (NumElements == 8) return MVT::v8i16; + break; + case MVT::i32: + if (NumElements == 2) return MVT::v2i32; + if (NumElements == 4) return MVT::v4i32; + break; + case MVT::i64: + if (NumElements == 1) return MVT::v1i64; + if (NumElements == 2) return MVT::v2i64; + break; + case MVT::f32: + if (NumElements == 2) return MVT::v2f32; + if (NumElements == 4) return MVT::v4f32; + break; + case MVT::f64: + if (NumElements == 2) return MVT::v2f64; + break; + } + ValueType Result = VT | ((NumElements + 1) << SimpleTypeBits); + assert(getVectorElementType(Result) == VT && + "Bad vector element type!"); + assert(getVectorNumElements(Result) == NumElements && + "Bad vector length!"); + return Result; + } + + /// MVT::getIntVectorWithNumElements - Return any integer vector type that has + /// the specified number of elements. + static inline ValueType getIntVectorWithNumElements(unsigned NumElts) { + switch (NumElts) { + default: return getVectorType(i8, NumElts); + case 1: return v1i64; + case 2: return v2i32; + case 4: return v4i16; + case 8: return v8i8; + case 16: return v16i8; + } + } + + + /// MVT::getIntVTBitMask - Return an integer with 1's every place there are + /// bits in the specified integer value type. + static inline uint64_t getIntVTBitMask(ValueType VT) { + assert(isInteger(VT) && !isVector(VT) && "Only applies to int scalars!"); + return ~uint64_t(0UL) >> (64-getSizeInBits(VT)); + } + /// MVT::getIntVTSignBit - Return an integer with a 1 in the position of the + /// sign bit for the specified integer value type. + static inline uint64_t getIntVTSignBit(ValueType VT) { + assert(isInteger(VT) && !isVector(VT) && "Only applies to int scalars!"); + return uint64_t(1UL) << (getSizeInBits(VT)-1); + } + + /// MVT::getValueTypeString - This function returns value type as a string, + /// e.g. "i32". + std::string getValueTypeString(ValueType VT); + + /// MVT::getTypeForValueType - This method returns an LLVM type corresponding + /// to the specified ValueType. For integer types, this returns an unsigned + /// type. Note that this will abort for types that cannot be represented. + const Type *getTypeForValueType(ValueType VT); + + /// MVT::getValueType - Return the value type corresponding to the specified + /// type. This returns all pointers as MVT::iPTR. If HandleUnknown is true, + /// unknown types are returned as Other, otherwise they are invalid. + ValueType getValueType(const Type *Ty, bool HandleUnknown = false); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td new file mode 100644 index 0000000..557a02b --- /dev/null +++ b/include/llvm/CodeGen/ValueTypes.td @@ -0,0 +1,52 @@ +//===- ValueTypes.td - ValueType definitions ---------------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Value types - These values correspond to the register types defined in the +// ValueTypes.h file. If you update anything here, you must update it there as +// well! +// +//===----------------------------------------------------------------------===// + +class ValueType<int size, int value> { + string Namespace = "MVT"; + int Size = size; + int Value = value; +} + +def OtherVT: ValueType<0 , 0>; // "Other" value +def i1 : ValueType<1 , 1>; // One bit boolean value +def i8 : ValueType<8 , 2>; // 8-bit integer value +def i16 : ValueType<16 , 3>; // 16-bit integer value +def i32 : ValueType<32 , 4>; // 32-bit integer value +def i64 : ValueType<64 , 5>; // 64-bit integer value +def i128 : ValueType<128, 6>; // 128-bit integer value +def f32 : ValueType<32 , 7>; // 32-bit floating point value +def f64 : ValueType<64 , 8>; // 64-bit floating point value +def f80 : ValueType<80 , 9>; // 80-bit floating point value +def f128 : ValueType<128, 10>; // 128-bit floating point value +def FlagVT : ValueType<0 , 11>; // Condition code or machine flag +def isVoid : ValueType<0 , 12>; // Produces no value +def v8i8 : ValueType<64 , 13>; // 8 x i8 vector value +def v4i16 : ValueType<64 , 14>; // 4 x i16 vector value +def v2i32 : ValueType<64 , 15>; // 2 x i32 vector value +def v1i64 : ValueType<64 , 16>; // 1 x i64 vector value + +def v16i8 : ValueType<128, 17>; // 16 x i8 vector value +def v8i16 : ValueType<128, 18>; // 8 x i16 vector value +def v4i32 : ValueType<128, 19>; // 4 x i32 vector value +def v2i64 : ValueType<128, 20>; // 2 x i64 vector value +def v2f32 : ValueType<64, 21>; // 2 x f32 vector value +def v4f32 : ValueType<128, 22>; // 4 x f32 vector value +def v2f64 : ValueType<128, 23>; // 2 x f64 vector value + +// Pseudo valuetype to represent "integer of any bit width" +def iAny : ValueType<0 , 254>; // integer value of any bit width + +// Pseudo valuetype mapped to the current pointer size. +def iPTR : ValueType<0 , 255>; diff --git a/include/llvm/Config/alloca.h b/include/llvm/Config/alloca.h new file mode 100644 index 0000000..10fa74d --- /dev/null +++ b/include/llvm/Config/alloca.h @@ -0,0 +1,50 @@ +/* + * The LLVM Compiler Infrastructure + * + * This file was developed by the LLVM research group and is distributed under + * the University of Illinois Open Source License. See LICENSE.TXT for details. + * + ****************************************************************************** + * + * Description: + * This header file includes the infamous alloc.h header file if the + * autoconf system has found it. It hides all of the autoconf details + * from the rest of the application source code. + */ + +#ifndef _CONFIG_ALLOC_H +#define _CONFIG_ALLOC_H + +#include "llvm/Config/config.h" + +/* + * This is a modified version of that suggested by the Autoconf manual. + * 1) The #pragma is indented so that pre-ANSI C compilers ignore it. + * 2) If alloca.h cannot be found, then try stdlib.h. Some platforms + * (notably FreeBSD) defined alloca() there. + */ +#ifdef _MSC_VER +#include <malloc.h> +#define alloca _alloca +#elif defined(HAVE_ALLOCA_H) +#include <alloca.h> +#elif defined(__MINGW32__) && defined(HAVE_MALLOC_H) +#include <malloc.h> +#elif !defined(__GNUC__) +# ifdef _AIX +# pragma alloca +# else +# ifndef alloca + char * alloca (); +# endif +# endif +#else +# ifdef HAVE_STDLIB_H +# include <stdlib.h> +# else +# error "The function alloca() is required but not found!" +# endif +#endif + +#endif + diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in new file mode 100644 index 0000000..80b443f --- /dev/null +++ b/include/llvm/Config/config.h.in @@ -0,0 +1,564 @@ +/* include/llvm/Config/config.h.in. Generated from autoconf/configure.ac by autoheader. */ + +/* Define if dlopen(0) will open the symbols of the program */ +#undef CAN_DLOPEN_SELF + +/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP + systems. This function is required for `alloca.c' support on those systems. + */ +#undef CRAY_STACKSEG_END + +/* Define to 1 if using `alloca.c'. */ +#undef C_ALLOCA + +/* Define if CBE is enabled for printf %a output */ +#undef ENABLE_CBE_PRINTF_A + +/* Define if position independent code is enabled */ +#undef ENABLE_PIC + +/* Define if threads enabled */ +#undef ENABLE_THREADS + +/* Define to 1 if you have `alloca', as a function or macro. */ +#undef HAVE_ALLOCA + +/* Define to 1 if you have <alloca.h> and it should be used (not on Ultrix). + */ +#undef HAVE_ALLOCA_H + +/* Define to 1 if you have the `argz_append' function. */ +#undef HAVE_ARGZ_APPEND + +/* Define to 1 if you have the `argz_create_sep' function. */ +#undef HAVE_ARGZ_CREATE_SEP + +/* Define to 1 if you have the <argz.h> header file. */ +#undef HAVE_ARGZ_H + +/* Define to 1 if you have the `argz_insert' function. */ +#undef HAVE_ARGZ_INSERT + +/* Define to 1 if you have the `argz_next' function. */ +#undef HAVE_ARGZ_NEXT + +/* 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 + +/* Does not have bi-directional iterator */ +#undef HAVE_BI_ITERATOR + +/* Define to 1 if you have the `ceilf' function. */ +#undef HAVE_CEILF + +/* Define to 1 if you have the `closedir' function. */ +#undef HAVE_CLOSEDIR + +/* Define to 1 if you have the <ctype.h> header file. */ +#undef HAVE_CTYPE_H + +/* Define to 1 if you have the <dirent.h> header file, and it defines `DIR'. + */ +#undef HAVE_DIRENT_H + +/* 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 + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#undef HAVE_DLFCN_H + +/* 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 + +/* Define if the dotty program is available */ +#undef HAVE_DOTTY + +/* Define if you have the _dyld_func_lookup function. */ +#undef HAVE_DYLD + +/* Define to 1 if you have the <errno.h> header file. */ +#undef HAVE_ERRNO_H + +/* Define to 1 if the system has the type `error_t'. */ +#undef HAVE_ERROR_T + +/* Define to 1 if you have the <execinfo.h> header file. */ +#undef HAVE_EXECINFO_H + +/* Define to 1 if you have the <fcntl.h> header file. */ +#undef HAVE_FCNTL_H + +/* Set to 1 if the finite function is found in <ieeefp.h> */ +#undef HAVE_FINITE_IN_IEEEFP_H + +/* Define to 1 if you have the `floorf' function. */ +#undef HAVE_FLOORF + +/* Define to 1 if you have the `fmodf' function. */ +#undef HAVE_FMODF + +/* Does not have forward iterator */ +#undef HAVE_FWD_ITERATOR + +/* Define to 1 if you have the `getcwd' function. */ +#undef HAVE_GETCWD + +/* Define to 1 if you have the `getpagesize' function. */ +#undef HAVE_GETPAGESIZE + +/* Define to 1 if you have the `getrlimit' function. */ +#undef HAVE_GETRLIMIT + +/* Define to 1 if you have the `getrusage' function. */ +#undef HAVE_GETRUSAGE + +/* Define to 1 if you have the `gettimeofday' function. */ +#undef HAVE_GETTIMEOFDAY + +/* Does not have <hash_map> */ +#undef HAVE_GLOBAL_HASH_MAP + +/* Does not have hash_set in global namespace */ +#undef HAVE_GLOBAL_HASH_SET + +/* Does not have ext/hash_map */ +#undef HAVE_GNU_EXT_HASH_MAP + +/* Does not have hash_set in gnu namespace */ +#undef HAVE_GNU_EXT_HASH_SET + +/* Define if the Graphviz program is available */ +#undef HAVE_GRAPHVIZ + +/* 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 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `isatty' function. */ +#undef HAVE_ISATTY + +/* Set to 1 if the isinf function is found in <cmath> */ +#undef HAVE_ISINF_IN_CMATH + +/* Set to 1 if the isinf function is found in <math.h> */ +#undef HAVE_ISINF_IN_MATH_H + +/* Set to 1 if the isnan function is found in <cmath> */ +#undef HAVE_ISNAN_IN_CMATH + +/* Set to 1 if the isnan function is found in <math.h> */ +#undef HAVE_ISNAN_IN_MATH_H + +/* Define if you have the libdl library or equivalent. */ +#undef HAVE_LIBDL + +/* Define to 1 if you have the `elf' library (-lelf). */ +#undef HAVE_LIBELF + +/* Define to 1 if you have the `imagehlp' library (-limagehlp). */ +#undef HAVE_LIBIMAGEHLP + +/* Define to 1 if you have the `m' library (-lm). */ +#undef HAVE_LIBM + +/* Define to 1 if you have the `psapi' library (-lpsapi). */ +#undef HAVE_LIBPSAPI + +/* Define to 1 if you have the `pthread' library (-lpthread). */ +#undef HAVE_LIBPTHREAD + +/* Define to 1 if you have the `udis86' library (-ludis86). */ +#undef HAVE_LIBUDIS86 + +/* Define to 1 if you have the <limits.h> header file. */ +#undef HAVE_LIMITS_H + +/* Define to 1 if you have the <link.h> header file. */ +#undef 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 + +/* Define to 1 if you have the `longjmp' function. */ +#undef HAVE_LONGJMP + +/* Define if lt_dlopen() is available on this platform */ +#undef HAVE_LT_DLOPEN + +/* Define to 1 if you have the <mach/mach.h> header file. */ +#undef HAVE_MACH_MACH_H + +/* Define to 1 if you have the <mach-o/dyld.h> header file. */ +#undef HAVE_MACH_O_DYLD_H + +/* Define if mallinfo() is available on this platform. */ +#undef HAVE_MALLINFO + +/* Define to 1 if you have the <malloc.h> header file. */ +#undef HAVE_MALLOC_H + +/* Define to 1 if you have the <malloc/malloc.h> header file. */ +#undef HAVE_MALLOC_MALLOC_H + +/* 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 + +/* Define to 1 if you have the `mkdtemp' function. */ +#undef HAVE_MKDTEMP + +/* Define to 1 if you have the `mkstemp' function. */ +#undef HAVE_MKSTEMP + +/* Define to 1 if you have the `mktemp' function. */ +#undef HAVE_MKTEMP + +/* Define to 1 if you have a working `mmap' system call. */ +#undef HAVE_MMAP + +/* Define if mmap() uses MAP_ANONYMOUS to map anonymous pages, or undefine if + it uses MAP_ANON */ +#undef HAVE_MMAP_ANONYMOUS + +/* Define if mmap() can map files into memory */ +#undef HAVE_MMAP_FILE + +/* define if the compiler implements namespaces */ +#undef HAVE_NAMESPACES + +/* Define to 1 if you have the <ndir.h> header file, and it defines `DIR'. */ +#undef HAVE_NDIR_H + +/* Define to 1 if you have the `nearbyintf' function. */ +#undef HAVE_NEARBYINTF + +/* Define to 1 if you have the `opendir' function. */ +#undef HAVE_OPENDIR + +/* Define to 1 if you have the `powf' function. */ +#undef HAVE_POWF + +/* Define if libtool can extract symbol lists from object files. */ +#undef HAVE_PRELOADED_SYMBOLS + +/* Define to have the %a format string */ +#undef HAVE_PRINTF_A + +/* Have pthread_mutex_lock */ +#undef HAVE_PTHREAD_MUTEX_LOCK + +/* Define to 1 if srand48/lrand48/drand48 exist in <stdlib.h> */ +#undef HAVE_RAND48 + +/* Define to 1 if you have the `readdir' function. */ +#undef HAVE_READDIR + +/* 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 + +/* Define to 1 if you have the `round' function. */ +#undef HAVE_ROUND + +/* Define to 1 if you have the `roundf' function. */ +#undef HAVE_ROUNDF + +/* Define to 1 if you have the `sbrk' function. */ +#undef HAVE_SBRK + +/* Define to 1 if you have the `setjmp' function. */ +#undef HAVE_SETJMP + +/* Define to 1 if you have the <setjmp.h> header file. */ +#undef HAVE_SETJMP_H + +/* Define to 1 if you have the `setrlimit' function. */ +#undef HAVE_SETRLIMIT + +/* Define if you have the shl_load function. */ +#undef HAVE_SHL_LOAD + +/* Define to 1 if you have the `siglongjmp' function. */ +#undef HAVE_SIGLONGJMP + +/* Define to 1 if you have the <signal.h> header file. */ +#undef HAVE_SIGNAL_H + +/* Define to 1 if you have the `sigsetjmp' function. */ +#undef HAVE_SIGSETJMP + +/* 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 + +/* Does not have ext/hash_map> */ +#undef HAVE_STD_EXT_HASH_MAP + +/* Does not have hash_set in std namespace */ +#undef HAVE_STD_EXT_HASH_SET + +/* 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 + +/* Does not have std namespace iterator */ +#undef HAVE_STD_ITERATOR + +/* 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 + +/* Define to 1 if you have the `strerror_r' function. */ +#undef HAVE_STRERROR_R + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* 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 + +/* Define to 1 if you have the `strtoll' function. */ +#undef HAVE_STRTOLL + +/* Define to 1 if you have the `strtoq' function. */ +#undef HAVE_STRTOQ + +/* Define to 1 if you have the `sysconf' function. */ +#undef HAVE_SYSCONF + +/* Define to 1 if you have the <sys/dir.h> header file, and it defines `DIR'. + */ +#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/mman.h> header file. */ +#undef HAVE_SYS_MMAN_H + +/* Define to 1 if you have the <sys/ndir.h> header file, and it defines `DIR'. + */ +#undef HAVE_SYS_NDIR_H + +/* Define to 1 if you have the <sys/param.h> header file. */ +#undef HAVE_SYS_PARAM_H + +/* Define to 1 if you have the <sys/resource.h> header file. */ +#undef HAVE_SYS_RESOURCE_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/time.h> header file. */ +#undef HAVE_SYS_TIME_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */ +#undef HAVE_SYS_WAIT_H + +/* Define to 1 if the system has the type `uint64_t'. */ +#undef HAVE_UINT64_T + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Define to 1 if you have the <utime.h> header file. */ +#undef HAVE_UTIME_H + +/* Define to 1 if the system has the type `u_int64_t'. */ +#undef HAVE_U_INT64_T + +/* Define to 1 if you have the <windows.h> header file. */ +#undef HAVE_WINDOWS_H + +/* Installation directory for binary executables */ +#undef LLVM_BINDIR + +/* Time at which LLVM was configured */ +#undef LLVM_CONFIGTIME + +/* Installation directory for documentation */ +#undef LLVM_DATADIR + +/* Installation directory for config files */ +#undef LLVM_ETCDIR + +/* Installation directory for include files */ +#undef LLVM_INCLUDEDIR + +/* Installation directory for .info files */ +#undef LLVM_INFODIR + +/* Installation directory for libraries */ +#undef LLVM_LIBDIR + +/* Installation directory for man pages */ +#undef LLVM_MANDIR + +/* Define if this is Unixish platform */ +#undef LLVM_ON_UNIX + +/* Define if this is Win32ish platform */ +#undef LLVM_ON_WIN32 + +/* Define to path to dot program if found or 'echo dot' otherwise */ +#undef LLVM_PATH_DOT + +/* Define to path to dotty program if found or 'echo dotty' otherwise */ +#undef LLVM_PATH_DOTTY + +/* Define to path to Graphviz program if found or 'echo Graphviz' otherwise */ +#undef LLVM_PATH_GRAPHVIZ + +/* Define to path to gv program if found or 'echo gv' otherwise */ +#undef LLVM_PATH_GV + +/* Installation prefix directory */ +#undef LLVM_PREFIX + +/* Define if the OS needs help to load dependent libraries for dlopen(). */ +#undef LTDL_DLOPEN_DEPLIBS + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#undef LTDL_OBJDIR + +/* Define to the name of the environment variable that determines the dynamic + library search path. */ +#undef LTDL_SHLIBPATH_VAR + +/* Define to the extension used for shared libraries, say, ".so". */ +#undef LTDL_SHLIB_EXT + +/* Define to the system default library search path. */ +#undef LTDL_SYSSEARCHPATH + +/* Define if /dev/zero should be used when mapping RWX memory, or undefine if + its not necessary */ +#undef NEED_DEV_ZERO_FOR_MMAP + +/* Define if dlsym() requires a leading underscore in symbol names. */ +#undef NEED_USCORE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define as the return type of signal handlers (`int' or `void'). */ +#undef RETSIGTYPE + +/* If using the C implementation of alloca, define if you know the + direction of stack growth for your system; otherwise it will be + automatically deduced at runtime. + STACK_DIRECTION > 0 => grows toward higher addresses + STACK_DIRECTION < 0 => grows toward lower addresses + STACK_DIRECTION = 0 => direction of growth unknown */ +#undef STACK_DIRECTION + +/* Define to 1 if the `S_IS*' macros in <sys/stat.h> do not work properly. */ +#undef STAT_MACROS_BROKEN + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */ +#undef TIME_WITH_SYS_TIME + +/* Define to 1 if your <sys/time.h> declares `struct tm'. */ +#undef TM_IN_SYS_TIME + +/* Define if use udis86 library */ +#undef USE_UDIS86 + +/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a + `char[]'. */ +#undef YYTEXT_POINTER + +/* 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. */ +#undef error_t + +/* Define to `int' if <sys/types.h> does not define. */ +#undef pid_t + +/* Define to `unsigned int' if <sys/types.h> does not define. */ +#undef size_t diff --git a/include/llvm/Constant.h b/include/llvm/Constant.h new file mode 100644 index 0000000..d925fdb --- /dev/null +++ b/include/llvm/Constant.h @@ -0,0 +1,129 @@ +//===-- llvm/Constant.h - Constant class definition -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Constant class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CONSTANT_H +#define LLVM_CONSTANT_H + +#include "llvm/User.h" + +namespace llvm { + +/// This is an important base class in LLVM. It provides the common facilities +/// of all constant values in an LLVM program. A constant is a value that is +/// immutable at runtime. Functions are constants because their address is +/// immutable. Same with global variables. +/// +/// All constants share the capabilities provided in this class. All constants +/// can have a null value. They can have an operand list. Constants can be +/// simple (integer and floating point values), complex (arrays and structures), +/// or expression based (computations yielding a constant value composed of +/// only certain operators and other constant values). +/// +/// Note that Constants are immutable (once created they never change) +/// and are fully shared by structural equivalence. This means that two +/// structurally equivalent constants will always have the same address. +/// Constant's are created on demand as needed and never deleted: thus clients +/// don't have to worry about the lifetime of the objects. +/// @brief LLVM Constant Representation +class Constant : public User { + void operator=(const Constant &); // Do not implement + Constant(const Constant &); // Do not implement +protected: + Constant(const Type *Ty, ValueTy vty, Use *Ops, unsigned NumOps) + : User(Ty, vty, Ops, NumOps) {} + + void destroyConstantImpl(); +public: + /// Static constructor to get a '0' constant of arbitrary type... + /// + static Constant *getNullValue(const Type *Ty); + + /// Static constructor to get a '-1' constant. This supports integers and + /// vectors. + /// + static Constant *getAllOnesValue(const Type *Ty); + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const = 0; + + virtual void print(std::ostream &O) const; + void print(std::ostream *O) const { if (O) print(*O); } + + /// canTrap - Return true if evaluation of this constant could trap. This is + /// true for things like constant expressions that could divide by zero. + bool canTrap() const; + + /// ContaintsRelocations - Return true if the constant value contains + /// relocations which cannot be resolved at compile time. + bool ContainsRelocations() const; + + // Specialize get/setOperand for Constant's as their operands are always + // constants as well. + Constant *getOperand(unsigned i) { + return static_cast<Constant*>(User::getOperand(i)); + } + const Constant *getOperand(unsigned i) const { + return static_cast<const Constant*>(User::getOperand(i)); + } + void setOperand(unsigned i, Constant *C) { + User::setOperand(i, C); + } + + /// destroyConstant - Called if some element of this constant is no longer + /// valid. At this point only other constants may be on the use_list for this + /// constant. Any constants on our Use list must also be destroy'd. The + /// implementation must be sure to remove the constant from the list of + /// available cached constants. Implementations should call + /// destroyConstantImpl as the last thing they do, to destroy all users and + /// delete this. + virtual void destroyConstant() { assert(0 && "Not reached!"); } + + //// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Constant *) { return true; } + static inline bool classof(const GlobalValue *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() >= ConstantFirstVal && + V->getValueID() <= ConstantLastVal; + } + + /// replaceUsesOfWithOnConstant - This method is a special form of + /// User::replaceUsesOfWith (which does not work on constants) that does work + /// on constants. Basically this method goes through the trouble of building + /// a new constant that is equivalent to the current one, with all uses of + /// From replaced with uses of To. After this construction is completed, all + /// of the users of 'this' are replaced to use the new constant, and then + /// 'this' is deleted. In general, you should not call this method, instead, + /// use Value::replaceAllUsesWith, which automatically dispatches to this + /// method as needed. + /// + virtual void replaceUsesOfWithOnConstant(Value *, Value *, Use *) { + // Provide a default implementation for constants (like integers) that + // cannot use any other values. This cannot be called at runtime, but needs + // to be here to avoid link errors. + assert(getNumOperands() == 0 && "replaceUsesOfWithOnConstant must be " + "implemented for all constants that have operands!"); + assert(0 && "Constants that do not have operands cannot be using 'From'!"); + } + + /// getStringValue - Turn an LLVM constant pointer that eventually points to a + /// global into a string value. Return an empty string if we can't do it. + /// Parameter Chop determines if the result is chopped at the first null + /// terminator. + /// + std::string getStringValue(bool Chop = true, unsigned Offset = 0); +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h new file mode 100644 index 0000000..526f19c --- /dev/null +++ b/include/llvm/Constants.h @@ -0,0 +1,713 @@ +//===-- llvm/Constants.h - Constant class subclass definitions --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file This file contains the declarations for the subclasses of Constant, +/// which represent the different flavors of constant values that live in LLVM. +/// Note that Constants are immutable (once created they never change) and are +/// fully shared by structural equivalence. This means that two structurally +/// equivalent constants will always have the same address. Constant's are +/// created on demand as needed and never deleted: thus clients don't have to +/// worry about the lifetime of the objects. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CONSTANTS_H +#define LLVM_CONSTANTS_H + +#include "llvm/Constant.h" +#include "llvm/Type.h" +#include "llvm/ADT/APInt.h" + +namespace llvm { + +class ArrayType; +class StructType; +class PointerType; +class VectorType; + +template<class ConstantClass, class TypeClass, class ValType> +struct ConstantCreator; +template<class ConstantClass, class TypeClass> +struct ConvertConstantType; + +//===----------------------------------------------------------------------===// +/// This is the shared class of boolean and integer constants. This class +/// represents both boolean and integral constants. +/// @brief Class for constant integers. +class ConstantInt : public Constant { + static ConstantInt *TheTrueVal, *TheFalseVal; + ConstantInt(const ConstantInt &); // DO NOT IMPLEMENT + ConstantInt(const IntegerType *Ty, const APInt& V); + APInt Val; +public: + /// Return the constant as an APInt value reference. This allows clients to + /// obtain a copy of the value, with all its precision in tact. + /// @brief Return the constant's value. + inline const APInt& getValue() const { + return Val; + } + + /// getBitWidth - Return the bitwidth of this constant. + unsigned getBitWidth() const { return Val.getBitWidth(); } + + /// 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(); + } + + /// Return the constant as a 64-bit integer value after it has been sign + /// 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(); + } + + /// A helper method that can be used to determine if the constant contained + /// within is equal to a constant. This only works for very small values, + /// because this is all that can be represented with all types. + /// @brief Determine if this constant's value is same as an unsigned char. + bool equalsInt(uint64_t V) const { + return Val == V; + } + + /// getTrue/getFalse - Return the singleton true/false values. + static inline ConstantInt *getTrue() { + if (TheTrueVal) return TheTrueVal; + return CreateTrueFalseVals(true); + } + static inline ConstantInt *getFalse() { + if (TheFalseVal) return TheFalseVal; + return CreateTrueFalseVals(false); + } + + /// Return a ConstantInt with the specified value for the specified type. The + /// value V will be canonicalized to a an unsigned APInt. Accessing it with + /// either getSExtValue() or getZExtValue() will yield a correctly sized and + /// signed value for the type Ty. + /// @brief Get a ConstantInt for a specific value. + static ConstantInt *get(const Type *Ty, uint64_t V, bool isSigned = false); + + /// Return a ConstantInt with the specified value and an implied Type. The + /// type is the integer type that corresponds to the bit width of the value. + static ConstantInt *get(const APInt &V); + + /// getType - Specialize the getType() method to always return an IntegerType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline const IntegerType *getType() const { + return reinterpret_cast<const IntegerType*>(Value::getType()); + } + + /// This static method returns true if the type Ty is big enough to + /// represent the value V. This can be used to avoid having the get method + /// assert when V is larger than Ty can represent. Note that there are two + /// versions of this method, one for unsigned and one for signed integers. + /// Although ConstantInt canonicalizes everything to an unsigned integer, + /// the signed version avoids callers having to convert a signed quantity + /// to the appropriate unsigned type before calling the method. + /// @returns true if V is a valid value for type Ty + /// @brief Determine if the value is in range for the given type. + static bool isValueValidForType(const Type *Ty, uint64_t V); + static bool isValueValidForType(const Type *Ty, int64_t V); + + /// This function will return true iff this constant represents the "null" + /// value that would be returned by the getNullValue method. + /// @returns true if this is the null integer value. + /// @brief Determine if the value is null. + virtual bool isNullValue() const { + return Val == 0; + } + + /// This is just a convenience method to make client code smaller for a + /// common code. It also correctly performs the comparison without the + /// potential for an assertion from getZExtValue(). + bool isZero() const { + return Val == 0; + } + + /// This is just a convenience method to make client code smaller for a + /// common case. It also correctly performs the comparison without the + /// potential for an assertion from getZExtValue(). + /// @brief Determine if the value is one. + bool isOne() const { + return Val == 1; + } + + /// This function will return true iff every bit in this constant is set + /// to true. + /// @returns true iff this constant's bits are all set to true. + /// @brief Determine if the value is all ones. + bool isAllOnesValue() const { + return Val.isAllOnesValue(); + } + + /// This function will return true iff this constant represents the largest + /// value that may be represented by the constant's type. + /// @returns true iff this is the largest value that may be represented + /// by this type. + /// @brief Determine if the value is maximal. + bool isMaxValue(bool isSigned) const { + if (isSigned) + return Val.isMaxSignedValue(); + else + return Val.isMaxValue(); + } + + /// This function will return true iff this constant represents the smallest + /// value that may be represented by this constant's type. + /// @returns true if this is the smallest value that may be represented by + /// this type. + /// @brief Determine if the value is minimal. + bool isMinValue(bool isSigned) const { + if (isSigned) + return Val.isMinSignedValue(); + else + return Val.isMinValue(); + } + + /// This function will return true iff this constant represents a value with + /// active bits bigger than 64 bits or a value greater than the given uint64_t + /// value. + /// @returns true iff this constant is greater or equal to the given number. + /// @brief Determine if the value is greater or equal to the given number. + bool uge(uint64_t Num) { + return Val.getActiveBits() > 64 || Val.getZExtValue() >= Num; + } + + /// @returns the 64-bit value of this constant if its active bits number is + /// not greater than 64, otherwise, just return the given uint64_t number. + /// @brief Get the constant's value if possible. + uint64_t getLimitedValue(uint64_t Limit = ~0ULL) const { + return Val.getLimitedValue(Limit); + } + + /// @returns the value for an integer constant of the given type that has all + /// its bits set to true. + /// @brief Get the all ones value + static ConstantInt *getAllOnesValue(const Type *Ty); + + /// @brief Methods to support type inquiry through isa, cast, and dyn_cast. + static inline bool classof(const ConstantInt *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantIntVal; + } + static void ResetTrueFalse() { TheTrueVal = TheFalseVal = 0; } +private: + static ConstantInt *CreateTrueFalseVals(bool WhichOne); +}; + + +//===----------------------------------------------------------------------===// +/// ConstantFP - Floating Point Values [float, double] +/// +class ConstantFP : public Constant { + double Val; + ConstantFP(const ConstantFP &); // DO NOT IMPLEMENT +protected: + ConstantFP(const Type *Ty, double V); +public: + /// get() - Static factory methods - Return objects of the specified value + static ConstantFP *get(const Type *Ty, double V); + + /// isValueValidForType - return true if Ty is big enough to represent V. + static bool isValueValidForType(const Type *Ty, double V); + inline double getValue() const { return Val; } + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. Don't depend on == for doubles to tell us it's zero, it + /// considers -0.0 to be null as well as 0.0. :( + virtual bool isNullValue() const; + + /// isExactlyValue - We don't rely on operator== working on double values, as + /// it returns true for things that are clearly not equal, like -0.0 and 0.0. + /// As such, this method can be used to do an exact bit-for-bit comparison of + /// two floating point values. + bool isExactlyValue(double V) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ConstantFP *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantFPVal; + } +}; + +//===----------------------------------------------------------------------===// +/// ConstantAggregateZero - All zero aggregate value +/// +class ConstantAggregateZero : public Constant { + friend struct ConstantCreator<ConstantAggregateZero, Type, char>; + ConstantAggregateZero(const ConstantAggregateZero &); // DO NOT IMPLEMENT +protected: + explicit ConstantAggregateZero(const Type *Ty) + : Constant(Ty, ConstantAggregateZeroVal, 0, 0) {} +public: + /// get() - static factory method for creating a null aggregate. It is + /// illegal to call this method with a non-aggregate type. + static Constant *get(const Type *Ty); + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const { return true; } + + virtual void destroyConstant(); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + /// + static bool classof(const ConstantAggregateZero *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantAggregateZeroVal; + } +}; + + +//===----------------------------------------------------------------------===// +/// ConstantArray - Constant Array Declarations +/// +class ConstantArray : public Constant { + friend struct ConstantCreator<ConstantArray, ArrayType, + std::vector<Constant*> >; + ConstantArray(const ConstantArray &); // DO NOT IMPLEMENT +protected: + ConstantArray(const ArrayType *T, const std::vector<Constant*> &Val); + ~ConstantArray(); +public: + /// get() - Static factory methods - Return objects of the specified value + static Constant *get(const ArrayType *T, const std::vector<Constant*> &); + static Constant *get(const ArrayType *T, + Constant*const*Vals, unsigned NumVals) { + // FIXME: make this the primary ctor method. + return get(T, std::vector<Constant*>(Vals, Vals+NumVals)); + } + + /// This method constructs a ConstantArray and initializes it with a text + /// string. The default behavior (AddNull==true) causes a null terminator to + /// be placed at the end of the array. This effectively increases the length + /// of the array by one (you've been warned). However, in some situations + /// this is not desired so if AddNull==false then the string is copied without + /// null termination. + static Constant *get(const std::string &Initializer, bool AddNull = true); + + /// getType - Specialize the getType() method to always return an ArrayType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline const ArrayType *getType() const { + return reinterpret_cast<const ArrayType*>(Value::getType()); + } + + /// isString - This method returns true if the array is an array of sbyte or + /// ubyte, and if the elements of the array are all ConstantInt's. + bool isString() const; + + /// isCString - This method returns true if the array is a string (see + /// isString) and it ends in a null byte \0 and does not contains any other + /// null bytes except its terminator. + bool isCString() const; + + /// getAsString - If this array is isString(), then this method converts the + /// array to an std::string and returns it. Otherwise, it asserts out. + /// + std::string getAsString() const; + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. This always returns false because zero arrays are always + /// created as ConstantAggregateZero objects. + virtual bool isNullValue() const { return false; } + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ConstantArray *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantArrayVal; + } +}; + + +//===----------------------------------------------------------------------===// +// ConstantStruct - Constant Struct Declarations +// +class ConstantStruct : public Constant { + friend struct ConstantCreator<ConstantStruct, StructType, + std::vector<Constant*> >; + ConstantStruct(const ConstantStruct &); // DO NOT IMPLEMENT +protected: + ConstantStruct(const StructType *T, const std::vector<Constant*> &Val); + ~ConstantStruct(); +public: + /// get() - Static factory methods - Return objects of the specified value + /// + static Constant *get(const StructType *T, const std::vector<Constant*> &V); + static Constant *get(const std::vector<Constant*> &V, bool Packed = false); + static Constant *get(Constant*const* Vals, unsigned NumVals, + bool Packed = false) { + // FIXME: make this the primary ctor method. + return get(std::vector<Constant*>(Vals, Vals+NumVals), Packed); + } + + /// getType() specialization - Reduce amount of casting... + /// + inline const StructType *getType() const { + return reinterpret_cast<const StructType*>(Value::getType()); + } + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. This always returns false because zero structs are always + /// created as ConstantAggregateZero objects. + virtual bool isNullValue() const { + return false; + } + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ConstantStruct *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantStructVal; + } +}; + +//===----------------------------------------------------------------------===// +/// ConstantVector - Constant Vector Declarations +/// +class ConstantVector : public Constant { + friend struct ConstantCreator<ConstantVector, VectorType, + std::vector<Constant*> >; + ConstantVector(const ConstantVector &); // DO NOT IMPLEMENT +protected: + ConstantVector(const VectorType *T, const std::vector<Constant*> &Val); + ~ConstantVector(); +public: + /// get() - Static factory methods - Return objects of the specified value + static Constant *get(const VectorType *T, const std::vector<Constant*> &); + static Constant *get(const std::vector<Constant*> &V); + static Constant *get(Constant*const* Vals, unsigned NumVals) { + // FIXME: make this the primary ctor method. + return get(std::vector<Constant*>(Vals, Vals+NumVals)); + } + + /// getType - Specialize the getType() method to always return a VectorType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline const VectorType *getType() const { + return reinterpret_cast<const VectorType*>(Value::getType()); + } + + /// @returns the value for a vector integer constant of the given type that + /// has all its bits set to true. + /// @brief Get the all ones value + static ConstantVector *getAllOnesValue(const VectorType *Ty); + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. This always returns false because zero vectors are always + /// created as ConstantAggregateZero objects. + virtual bool isNullValue() const { return false; } + + /// This function will return true iff every element in this vector constant + /// is set to all ones. + /// @returns true iff this constant's emements are all set to all ones. + /// @brief Determine if the value is all ones. + bool isAllOnesValue() const; + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ConstantVector *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantVectorVal; + } +}; + +//===----------------------------------------------------------------------===// +/// ConstantPointerNull - a constant pointer value that points to null +/// +class ConstantPointerNull : public Constant { + friend struct ConstantCreator<ConstantPointerNull, PointerType, char>; + ConstantPointerNull(const ConstantPointerNull &); // DO NOT IMPLEMENT +protected: + explicit ConstantPointerNull(const PointerType *T) + : Constant(reinterpret_cast<const Type*>(T), + Value::ConstantPointerNullVal, 0, 0) {} + +public: + + /// get() - Static factory methods - Return objects of the specified value + static ConstantPointerNull *get(const PointerType *T); + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const { return true; } + + virtual void destroyConstant(); + + /// getType - Specialize the getType() method to always return an PointerType, + /// which reduces the amount of casting needed in parts of the compiler. + /// + inline const PointerType *getType() const { + return reinterpret_cast<const PointerType*>(Value::getType()); + } + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ConstantPointerNull *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == ConstantPointerNullVal; + } +}; + + +/// ConstantExpr - a constant value that is initialized with an expression using +/// other constant values. +/// +/// This class uses the standard Instruction opcodes to define the various +/// constant expressions. The Opcode field for the ConstantExpr class is +/// maintained in the Value::SubclassData field. +class ConstantExpr : public Constant { + friend struct ConstantCreator<ConstantExpr,Type, + std::pair<unsigned, std::vector<Constant*> > >; + friend struct ConvertConstantType<ConstantExpr, Type>; + +protected: + ConstantExpr(const Type *Ty, unsigned Opcode, Use *Ops, unsigned NumOps) + : Constant(Ty, ConstantExprVal, Ops, NumOps) { + // Operation type (an Instruction opcode) is stored as the SubclassData. + SubclassData = Opcode; + } + + // These private methods are used by the type resolution code to create + // ConstantExprs in intermediate forms. + static Constant *getTy(const Type *Ty, unsigned Opcode, + Constant *C1, Constant *C2); + static Constant *getCompareTy(unsigned short pred, Constant *C1, + Constant *C2); + static Constant *getSelectTy(const Type *Ty, + Constant *C1, Constant *C2, Constant *C3); + static Constant *getGetElementPtrTy(const Type *Ty, Constant *C, + Value* const *Idxs, unsigned NumIdxs); + static Constant *getExtractElementTy(const Type *Ty, Constant *Val, + Constant *Idx); + static Constant *getInsertElementTy(const Type *Ty, Constant *Val, + Constant *Elt, Constant *Idx); + static Constant *getShuffleVectorTy(const Type *Ty, Constant *V1, + Constant *V2, Constant *Mask); + +public: + // Static methods to construct a ConstantExpr of different kinds. Note that + // these methods may return a object that is not an instance of the + // ConstantExpr class, because they will attempt to fold the constant + // expression into something simpler if possible. + + /// Cast constant expr + /// + static Constant *getTrunc (Constant *C, const Type *Ty); + static Constant *getSExt (Constant *C, const Type *Ty); + static Constant *getZExt (Constant *C, const Type *Ty); + static Constant *getFPTrunc (Constant *C, const Type *Ty); + static Constant *getFPExtend(Constant *C, const Type *Ty); + static Constant *getUIToFP (Constant *C, const Type *Ty); + static Constant *getSIToFP (Constant *C, const Type *Ty); + static Constant *getFPToUI (Constant *C, const Type *Ty); + static Constant *getFPToSI (Constant *C, const Type *Ty); + static Constant *getPtrToInt(Constant *C, const Type *Ty); + static Constant *getIntToPtr(Constant *C, const Type *Ty); + static Constant *getBitCast (Constant *C, const Type *Ty); + + // @brief Convenience function for getting one of the casting operations + // using a CastOps opcode. + static Constant *getCast( + unsigned ops, ///< The opcode for the conversion + Constant *C, ///< The constant to be converted + const Type *Ty ///< The type to which the constant is converted + ); + + // @brief Create a ZExt or BitCast cast constant expression + static Constant *getZExtOrBitCast( + Constant *C, ///< The constant to zext or bitcast + const Type *Ty ///< The type to zext or bitcast C to + ); + + // @brief Create a SExt or BitCast cast constant expression + static Constant *getSExtOrBitCast( + Constant *C, ///< The constant to sext or bitcast + const Type *Ty ///< The type to sext or bitcast C to + ); + + // @brief Create a Trunc or BitCast cast constant expression + static Constant *getTruncOrBitCast( + Constant *C, ///< The constant to trunc or bitcast + const Type *Ty ///< The type to trunc or bitcast C to + ); + + /// @brief Create a BitCast or a PtrToInt cast constant expression + static Constant *getPointerCast( + Constant *C, ///< The pointer value to be casted (operand 0) + const Type *Ty ///< The type to which cast should be made + ); + + /// @brief Create a ZExt, Bitcast or Trunc for integer -> integer casts + static Constant *getIntegerCast( + Constant *C, ///< The integer constant to be casted + const Type *Ty, ///< The integer type to cast to + bool isSigned ///< Whether C should be treated as signed or not + ); + + /// @brief Create a FPExt, Bitcast or FPTrunc for fp -> fp casts + static Constant *getFPCast( + Constant *C, ///< The integer constant to be casted + const Type *Ty ///< The integer type to cast to + ); + + /// @brief Return true if this is a convert constant expression + bool isCast() const; + + /// @brief Return true if this is a compare constant expression + bool isCompare() const; + + /// Select constant expr + /// + static Constant *getSelect(Constant *C, Constant *V1, Constant *V2) { + return getSelectTy(V1->getType(), C, V1, V2); + } + + /// getSizeOf constant expr - computes the size of a type in a target + /// independent way (Note: the return type is a ULong). + /// + static Constant *getSizeOf(const Type *Ty); + + /// ConstantExpr::get - Return a binary or shift operator constant expression, + /// folding if possible. + /// + static Constant *get(unsigned Opcode, Constant *C1, Constant *C2); + + /// @brief Return an ICmp or FCmp comparison operator constant expression. + static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2); + + /// ConstantExpr::get* - Return some common constants without having to + /// specify the full Instruction::OPCODE identifier. + /// + static Constant *getNeg(Constant *C); + static Constant *getNot(Constant *C); + static Constant *getAdd(Constant *C1, Constant *C2); + static Constant *getSub(Constant *C1, Constant *C2); + static Constant *getMul(Constant *C1, Constant *C2); + static Constant *getUDiv(Constant *C1, Constant *C2); + static Constant *getSDiv(Constant *C1, Constant *C2); + static Constant *getFDiv(Constant *C1, Constant *C2); + static Constant *getURem(Constant *C1, Constant *C2); // unsigned rem + static Constant *getSRem(Constant *C1, Constant *C2); // signed rem + static Constant *getFRem(Constant *C1, Constant *C2); + static Constant *getAnd(Constant *C1, Constant *C2); + static Constant *getOr(Constant *C1, Constant *C2); + static Constant *getXor(Constant *C1, Constant *C2); + static Constant* getICmp(unsigned short pred, Constant* LHS, Constant* RHS); + static Constant* getFCmp(unsigned short pred, Constant* LHS, Constant* RHS); + static Constant *getShl(Constant *C1, Constant *C2); + static Constant *getLShr(Constant *C1, Constant *C2); + static Constant *getAShr(Constant *C1, Constant *C2); + + /// Getelementptr form. std::vector<Value*> is only accepted for convenience: + /// all elements must be Constant's. + /// + static Constant *getGetElementPtr(Constant *C, + Constant* const *IdxList, unsigned NumIdx); + static Constant *getGetElementPtr(Constant *C, + Value* const *IdxList, unsigned NumIdx); + + static Constant *getExtractElement(Constant *Vec, Constant *Idx); + static Constant *getInsertElement(Constant *Vec, Constant *Elt,Constant *Idx); + static Constant *getShuffleVector(Constant *V1, Constant *V2, Constant *Mask); + + /// Floating point negation must be implemented with f(x) = -0.0 - x. This + /// method returns the negative zero constant for floating point or vector + /// floating point types; for all other types, it returns the null value. + static Constant *getZeroValueForNegationExpr(const Type *Ty); + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const { return false; } + + /// getOpcode - Return the opcode at the root of this constant expression + unsigned getOpcode() const { return SubclassData; } + + /// getPredicate - Return the ICMP or FCMP predicate value. Assert if this is + /// not an ICMP or FCMP constant expression. + unsigned getPredicate() const; + + /// getOpcodeName - Return a string representation for an opcode. + const char *getOpcodeName() const; + + /// getWithOperandReplaced - Return a constant expression identical to this + /// one, but with the specified operand set to the specified value. + Constant *getWithOperandReplaced(unsigned OpNo, Constant *Op) const; + + /// getWithOperands - This returns the current constant expression with the + /// operands replaced with the specified values. The specified operands must + /// match count and type with the existing ones. + Constant *getWithOperands(const std::vector<Constant*> &Ops) const; + + virtual void destroyConstant(); + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + /// Override methods to provide more type information... + inline Constant *getOperand(unsigned i) { + return cast<Constant>(User::getOperand(i)); + } + inline Constant *getOperand(unsigned i) const { + return const_cast<Constant*>(cast<Constant>(User::getOperand(i))); + } + + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ConstantExpr *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == ConstantExprVal; + } +}; + + +//===----------------------------------------------------------------------===// +/// UndefValue - 'undef' values are things that do not have specified contents. +/// These are used for a variety of purposes, including global variable +/// initializers and operands to instructions. 'undef' values can occur with +/// any type. +/// +class UndefValue : public Constant { + friend struct ConstantCreator<UndefValue, Type, char>; + UndefValue(const UndefValue &); // DO NOT IMPLEMENT +protected: + explicit UndefValue(const Type *T) : Constant(T, UndefValueVal, 0, 0) {} +public: + /// get() - Static factory methods - Return an 'undef' object of the specified + /// type. + /// + static UndefValue *get(const Type *T); + + /// isNullValue - Return true if this is the value that would be returned by + /// getNullValue. + virtual bool isNullValue() const { return false; } + + virtual void destroyConstant(); + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const UndefValue *) { return true; } + static bool classof(const Value *V) { + return V->getValueID() == UndefValueVal; + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Debugger/Debugger.h b/include/llvm/Debugger/Debugger.h new file mode 100644 index 0000000..e708bc0 --- /dev/null +++ b/include/llvm/Debugger/Debugger.h @@ -0,0 +1,173 @@ +//===- Debugger.h - LLVM debugger library interface -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the LLVM source-level debugger library interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGGER_DEBUGGER_H +#define LLVM_DEBUGGER_DEBUGGER_H + +#include <string> +#include <vector> + +namespace llvm { + class Module; + class InferiorProcess; + + /// Debugger class - This class implements the LLVM source-level debugger. + /// This allows clients to handle the user IO processing without having to + /// worry about how the debugger itself works. + /// + class Debugger { + // State the debugger needs when starting and stopping the program. + std::vector<std::string> ProgramArguments; + + // The environment to run the program with. This should eventually be + // changed to vector of strings when we allow the user to edit the + // environment. + const char * const *Environment; + + // Program - The currently loaded program, or null if none is loaded. + Module *Program; + + // Process - The currently executing inferior process. + InferiorProcess *Process; + + Debugger(const Debugger &); // DO NOT IMPLEMENT + void operator=(const Debugger &); // DO NOT IMPLEMENT + public: + Debugger(); + ~Debugger(); + + //===------------------------------------------------------------------===// + // Methods for manipulating and inspecting the execution environment. + // + + /// initializeEnvironment - Specify the environment the program should run + /// with. This is used to initialize the environment of the program to the + /// environment of the debugger. + void initializeEnvironment(const char *const *envp) { + Environment = envp; + } + + /// setWorkingDirectory - Specify the working directory for the program to + /// be started from. + void setWorkingDirectory(const std::string &Dir) { + // FIXME: implement + } + + template<typename It> + void setProgramArguments(It I, It E) { + ProgramArguments.assign(I, E); + } + unsigned getNumProgramArguments() const { return ProgramArguments.size(); } + const std::string &getProgramArgument(unsigned i) const { + return ProgramArguments[i]; + } + + + //===------------------------------------------------------------------===// + // Methods for manipulating and inspecting the program currently loaded. + // + + /// isProgramLoaded - Return true if there is a program currently loaded. + /// + bool isProgramLoaded() const { return Program != 0; } + + /// getProgram - Return the LLVM module corresponding to the program. + /// + Module *getProgram() const { return Program; } + + /// getProgramPath - Get the path of the currently loaded program, or an + /// empty string if none is loaded. + std::string getProgramPath() const; + + /// loadProgram - If a program is currently loaded, unload it. Then search + /// the PATH for the specified program, loading it when found. If the + /// specified program cannot be found, an exception is thrown to indicate + /// the error. + void loadProgram(const std::string &Path); + + /// unloadProgram - If a program is running, kill it, then unload all traces + /// of the current program. If no program is loaded, this method silently + /// succeeds. + void unloadProgram(); + + //===------------------------------------------------------------------===// + // Methods for manipulating and inspecting the program currently running. + // + // If the program is running, and the debugger is active, then we know that + // the program has stopped. This being the case, we can inspect the + // program, ask it for its source location, set breakpoints, etc. + // + + /// isProgramRunning - Return true if a program is loaded and has a + /// currently active instance. + bool isProgramRunning() const { return Process != 0; } + + /// getRunningProcess - If there is no program running, throw an exception. + /// Otherwise return the running process so that it can be inspected by the + /// debugger. + const InferiorProcess &getRunningProcess() const { + if (Process == 0) throw "No process running."; + return *Process; + } + + /// createProgram - Create an instance of the currently loaded program, + /// killing off any existing one. This creates the program and stops it at + /// the first possible moment. If there is no program loaded or if there is + /// a problem starting the program, this method throws an exception. + void createProgram(); + + /// killProgram - If the program is currently executing, kill off the + /// process and free up any state related to the currently running program. + /// If there is no program currently running, this just silently succeeds. + /// If something horrible happens when killing the program, an exception + /// gets thrown. + void killProgram(); + + + //===------------------------------------------------------------------===// + // Methods for continuing execution. These methods continue the execution + // of the program by some amount. If the program is successfully stopped, + // execution returns, otherwise an exception is thrown. + // + // NOTE: These methods should always be used in preference to directly + // accessing the Dbg object, because these will delete the Process object if + // the process unexpectedly dies. + // + + /// stepProgram - Implement the 'step' command, continuing execution until + /// the next possible stop point. + void stepProgram(); + + /// nextProgram - Implement the 'next' command, continuing execution until + /// the next possible stop point that is in the current function. + void nextProgram(); + + /// finishProgram - Implement the 'finish' command, continuing execution + /// until the specified frame ID returns. + void finishProgram(void *Frame); + + /// contProgram - Implement the 'cont' command, continuing execution until + /// the next breakpoint is encountered. + void contProgram(); + }; + + class NonErrorException { + std::string Message; + public: + NonErrorException(const std::string &M) : Message(M) {} + const std::string &getMessage() const { return Message; } + }; + +} // end namespace llvm + +#endif diff --git a/include/llvm/Debugger/InferiorProcess.h b/include/llvm/Debugger/InferiorProcess.h new file mode 100644 index 0000000..980e5cf --- /dev/null +++ b/include/llvm/Debugger/InferiorProcess.h @@ -0,0 +1,138 @@ +//===- InferiorProcess.h - Represent the program being debugged -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the InferiorProcess class, which is used to represent, +// inspect, and manipulate a process under the control of the LLVM debugger. +// +// This is an abstract class which should allow various different types of +// implementations. Initially we implement a unix specific debugger backend +// that does not require code generator support, but we could eventually use +// code generator support with ptrace, support windows based targets, supported +// remote targets, etc. +// +// If the inferior process unexpectedly dies, an attempt to communicate with it +// will cause an InferiorProcessDead exception to be thrown, indicating the exit +// code of the process. When this occurs, no methods on the InferiorProcess +// class should be called except for the destructor. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGGER_INFERIORPROCESS_H +#define LLVM_DEBUGGER_INFERIORPROCESS_H + +#include <string> +#include <vector> + +namespace llvm { + class Module; + class GlobalVariable; + + /// InferiorProcessDead exception - This class is thrown by methods that + /// communicate with the interior process if the process unexpectedly exits or + /// dies. The instance variable indicates what the exit code of the process + /// was, or -1 if unknown. + class InferiorProcessDead { + int ExitCode; + public: + InferiorProcessDead(int EC) : ExitCode(EC) {} + int getExitCode() const { return ExitCode; } + }; + + /// InferiorProcess class - This class represents the process being debugged + /// by the debugger. Objects of this class should not be stack allocated, + /// because the destructor can throw exceptions. + /// + class InferiorProcess { + Module *M; + protected: + InferiorProcess(Module *m) : M(m) {} + public: + /// create - Create an inferior process of the specified module, and + /// stop it at the first opportunity. If there is a problem starting the + /// program (for example, it has no main), throw an exception. + static InferiorProcess *create(Module *M, + const std::vector<std::string> &Arguments, + const char * const *envp); + + // InferiorProcess destructor - Kill the current process. If something + // terrible happens, we throw an exception from the destructor. + virtual ~InferiorProcess() {} + + //===------------------------------------------------------------------===// + // Status methods - These methods return information about the currently + // stopped process. + // + + /// getStatus - Return a status message that is specific to the current type + /// of inferior process that is created. This can return things like the + /// PID of the inferior or other potentially interesting things. + virtual std::string getStatus() const { + return ""; + } + + //===------------------------------------------------------------------===// + // Methods for inspecting the call stack. + // + + /// getPreviousFrame - Given the descriptor for the current stack frame, + /// return the descriptor for the caller frame. This returns null when it + /// runs out of frames. If Frame is null, the initial frame should be + /// returned. + virtual void *getPreviousFrame(void *Frame) const = 0; + + /// getSubprogramDesc - Return the subprogram descriptor for the current + /// stack frame. + virtual const GlobalVariable *getSubprogramDesc(void *Frame) const = 0; + + /// getFrameLocation - This method returns the source location where each + /// stack frame is stopped. + virtual void getFrameLocation(void *Frame, unsigned &LineNo, + unsigned &ColNo, + const GlobalVariable *&SourceDesc) const = 0; + + //===------------------------------------------------------------------===// + // Methods for manipulating breakpoints. + // + + /// addBreakpoint - This method adds a breakpoint at the specified line, + /// column, and source file, and returns a unique identifier for it. + /// + /// It is up to the debugger to determine whether or not there is actually a + /// stop-point that corresponds with the specified location. + virtual unsigned addBreakpoint(unsigned LineNo, unsigned ColNo, + const GlobalVariable *SourceDesc) = 0; + + /// removeBreakpoint - This deletes the breakpoint with the specified ID + /// number. + virtual void removeBreakpoint(unsigned ID) = 0; + + + //===------------------------------------------------------------------===// + // Execution methods - These methods cause the program to continue execution + // by some amount. If the program successfully stops, this returns. + // Otherwise, if the program unexpectedly terminates, an InferiorProcessDead + // exception is thrown. + // + + /// stepProgram - Implement the 'step' command, continuing execution until + /// the next possible stop point. + virtual void stepProgram() = 0; + + /// finishProgram - Implement the 'finish' command, continuing execution + /// until the current function returns. + virtual void finishProgram(void *Frame) = 0; + + /// contProgram - Implement the 'cont' command, continuing execution until + /// a breakpoint is encountered. + virtual void contProgram() = 0; + }; +} // end namespace llvm + +#endif + diff --git a/include/llvm/Debugger/ProgramInfo.h b/include/llvm/Debugger/ProgramInfo.h new file mode 100644 index 0000000..b5f9402 --- /dev/null +++ b/include/llvm/Debugger/ProgramInfo.h @@ -0,0 +1,246 @@ +//===- ProgramInfo.h - Information about the loaded program -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines various pieces of information about the currently loaded +// program. One instance of this object is created every time a program is +// loaded, and destroyed every time it is unloaded. +// +// The various pieces of information gathered about the source program are all +// designed to be extended by various SourceLanguage implementations. This +// allows source languages to keep any extended information that they support in +// the derived class portions of the class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGGER_PROGRAMINFO_H +#define LLVM_DEBUGGER_PROGRAMINFO_H + +#include "llvm/System/TimeValue.h" +#include <string> +#include <map> +#include <vector> + +namespace llvm { + class GlobalVariable; + class Module; + class SourceFile; + class SourceLanguage; + class ProgramInfo; + + /// SourceLanguageCache - SourceLanguage implementations are allowed to cache + /// stuff in the ProgramInfo object. The only requirement we have on these + /// instances is that they are destroyable. + struct SourceLanguageCache { + virtual ~SourceLanguageCache() {} + }; + + /// SourceFileInfo - One instance of this structure is created for each + /// source file in the program. + /// + class SourceFileInfo { + /// BaseName - The filename of the source file. + std::string BaseName; + + /// Directory - The working directory of this source file when it was + /// compiled. + std::string Directory; + + /// Version - The version of the LLVM debug information that this file was + /// compiled with. + unsigned Version; + + /// Language - The source language that the file was compiled with. This + /// pointer is never null. + /// + const SourceLanguage *Language; + + /// Descriptor - The LLVM Global Variable which describes the source file. + /// + const GlobalVariable *Descriptor; + + /// SourceText - The body of this source file, or null if it has not yet + /// been loaded. + mutable SourceFile *SourceText; + public: + SourceFileInfo(const GlobalVariable *Desc, const SourceLanguage &Lang); + ~SourceFileInfo(); + + const std::string &getBaseName() const { return BaseName; } + const std::string &getDirectory() const { return Directory; } + unsigned getDebugVersion() const { return Version; } + const GlobalVariable *getDescriptor() const { return Descriptor; } + SourceFile &getSourceText() const; + + const SourceLanguage &getLanguage() const { return *Language; } + }; + + + /// SourceFunctionInfo - An instance of this class is used to represent each + /// source function in the program. + /// + class SourceFunctionInfo { + /// Name - This contains an abstract name that is potentially useful to the + /// end-user. If there is no explicit support for the current language, + /// then this string is used to identify the function. + std::string Name; + + /// Descriptor - The descriptor for this function. + /// + const GlobalVariable *Descriptor; + + /// SourceFile - The file that this function is defined in. + /// + const SourceFileInfo *SourceFile; + + /// LineNo, ColNo - The location of the first stop-point in the function. + /// These are computed on demand. + mutable unsigned LineNo, ColNo; + + public: + SourceFunctionInfo(ProgramInfo &PI, const GlobalVariable *Desc); + virtual ~SourceFunctionInfo() {} + + /// getSymbolicName - Return a human-readable symbolic name to identify the + /// function (for example, in stack traces). + virtual std::string getSymbolicName() const { return Name; } + + /// getDescriptor - This returns the descriptor for the function. + /// + const GlobalVariable *getDescriptor() const { return Descriptor; } + + /// getSourceFile - This returns the source file that defines the function. + /// + const SourceFileInfo &getSourceFile() const { return *SourceFile; } + + /// getSourceLocation - This method returns the location of the first + /// stopping point in the function. If the body of the function cannot be + /// found, this returns zeros for both values. + void getSourceLocation(unsigned &LineNo, unsigned &ColNo) const; + }; + + + /// ProgramInfo - This object contains information about the loaded program. + /// When a new program is loaded, an instance of this class is created. When + /// the program is unloaded, the instance is destroyed. This object basically + /// manages the lazy computation of information useful for the debugger. + class ProgramInfo { + Module *M; + + /// ProgramTimeStamp - This is the timestamp of the executable file that we + /// currently have loaded into the debugger. + sys::TimeValue ProgramTimeStamp; + + /// SourceFiles - This map is used to transform source file descriptors into + /// their corresponding SourceFileInfo objects. This mapping owns the + /// memory for the SourceFileInfo objects. + /// + bool SourceFilesIsComplete; + std::map<const GlobalVariable*, SourceFileInfo*> SourceFiles; + + /// SourceFileIndex - Mapping from source file basenames to the information + /// about the file. Note that there can be filename collisions, so this is + /// a multimap. This map is populated incrementally as the user interacts + /// with the program, through the getSourceFileFromDesc method. If ALL of + /// the source files are needed, the getSourceFiles() method scans the + /// entire program looking for them. + /// + std::multimap<std::string, SourceFileInfo*> SourceFileIndex; + + /// SourceFunctions - This map contains entries functions in the source + /// program. If SourceFunctionsIsComplete is true, then this is ALL of the + /// functions in the program are in this map. + bool SourceFunctionsIsComplete; + std::map<const GlobalVariable*, SourceFunctionInfo*> SourceFunctions; + + /// LanguageCaches - Each source language is permitted to keep a per-program + /// cache of information specific to whatever it needs. This vector is + /// effectively a small map from the languages that are active in the + /// program to their caches. This can be accessed by the language by the + /// "getLanguageCache" method. + std::vector<std::pair<const SourceLanguage*, + SourceLanguageCache*> > LanguageCaches; + public: + ProgramInfo(Module *m); + ~ProgramInfo(); + + /// getProgramTimeStamp - Return the time-stamp of the program when it was + /// loaded. + sys::TimeValue getProgramTimeStamp() const { return ProgramTimeStamp; } + + //===------------------------------------------------------------------===// + // Interfaces to the source code files that make up the program. + // + + /// getSourceFile - Return source file information for the specified source + /// file descriptor object, adding it to the collection as needed. This + /// method always succeeds (is unambiguous), and is always efficient. + /// + const SourceFileInfo &getSourceFile(const GlobalVariable *Desc); + + /// getSourceFile - Look up the file with the specified name. If there is + /// more than one match for the specified filename, prompt the user to pick + /// one. If there is no source file that matches the specified name, throw + /// an exception indicating that we can't find the file. Otherwise, return + /// the file information for that file. + /// + /// If the source file hasn't been discovered yet in the program, this + /// method might have to index the whole program by calling the + /// getSourceFiles() method. + /// + const SourceFileInfo &getSourceFile(const std::string &Filename); + + /// getSourceFiles - Index all of the source files in the program and return + /// them. This information is lazily computed the first time that it is + /// requested. Since this information can take a long time to compute, the + /// user is given a chance to cancel it. If this occurs, an exception is + /// thrown. + const std::map<const GlobalVariable*, SourceFileInfo*> & + getSourceFiles(bool RequiresCompleteMap = true); + + //===------------------------------------------------------------------===// + // Interfaces to the functions that make up the program. + // + + /// getFunction - Return source function information for the specified + /// function descriptor object, adding it to the collection as needed. This + /// method always succeeds (is unambiguous), and is always efficient. + /// + const SourceFunctionInfo &getFunction(const GlobalVariable *Desc); + + /// getSourceFunctions - Index all of the functions in the program and + /// return them. This information is lazily computed the first time that it + /// is requested. Since this information can take a long time to compute, + /// the user is given a chance to cancel it. If this occurs, an exception + /// is thrown. + const std::map<const GlobalVariable*, SourceFunctionInfo*> & + getSourceFunctions(bool RequiresCompleteMap = true); + + /// addSourceFunctionsRead - Return true if the source functions map is + /// complete: that is, all functions in the program have been read in. + bool allSourceFunctionsRead() const { return SourceFunctionsIsComplete; } + + /// getLanguageCache - This method is used to build per-program caches of + /// information, such as the functions or types visible to the program. + /// This can be used by SourceLanguage implementations because it requires + /// an accessible [sl]::CacheType typedef, where [sl] is the C++ type of the + /// source-language subclass. + template<typename SL> + typename SL::CacheType &getLanguageCache(const SL *L) { + for (unsigned i = 0, e = LanguageCaches.size(); i != e; ++i) + if (LanguageCaches[i].first == L) + return *(typename SL::CacheType*)LanguageCaches[i].second; + typename SL::CacheType *NewCache = L->createSourceLanguageCache(*this); + LanguageCaches.push_back(std::make_pair(L, NewCache)); + return *NewCache; + } + }; + +} // end namespace llvm + +#endif diff --git a/include/llvm/Debugger/RuntimeInfo.h b/include/llvm/Debugger/RuntimeInfo.h new file mode 100644 index 0000000..2f4d37a --- /dev/null +++ b/include/llvm/Debugger/RuntimeInfo.h @@ -0,0 +1,142 @@ +//===- RuntimeInfo.h - Information about running program --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines classes that capture various pieces of information about +// the currently executing, but stopped, program. One instance of this object +// is created every time a program is stopped, and destroyed every time it +// starts running again. This object's main goal is to make access to runtime +// information easy and efficient, by caching information as requested. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGGER_RUNTIMEINFO_H +#define LLVM_DEBUGGER_RUNTIMEINFO_H + +#include <vector> +#include <cassert> + +namespace llvm { + class ProgramInfo; + class RuntimeInfo; + class InferiorProcess; + class GlobalVariable; + class SourceFileInfo; + + /// StackFrame - One instance of this structure is created for each stack + /// frame that is active in the program. + /// + class StackFrame { + RuntimeInfo &RI; + void *FrameID; + const GlobalVariable *FunctionDesc; + + /// LineNo, ColNo, FileInfo - This information indicates WHERE in the source + /// code for the program the stack frame is located. + unsigned LineNo, ColNo; + const SourceFileInfo *SourceInfo; + public: + StackFrame(RuntimeInfo &RI, void *ParentFrameID); + + StackFrame &operator=(const StackFrame &RHS) { + FrameID = RHS.FrameID; + FunctionDesc = RHS.FunctionDesc; + return *this; + } + + /// getFrameID - return the low-level opaque frame ID of this stack frame. + /// + void *getFrameID() const { return FrameID; } + + /// getFunctionDesc - Return the descriptor for the function that contains + /// this stack frame, or null if it is unknown. + /// + const GlobalVariable *getFunctionDesc(); + + /// getSourceLocation - Return the source location that this stack frame is + /// sitting at. + void getSourceLocation(unsigned &LineNo, unsigned &ColNo, + const SourceFileInfo *&SourceInfo); + }; + + + /// RuntimeInfo - This class collects information about the currently running + /// process. It is created whenever the program stops execution for the + /// debugger, and destroyed whenver execution continues. + class RuntimeInfo { + /// ProgInfo - This object contains static information about the program. + /// + ProgramInfo *ProgInfo; + + /// IP - This object contains information about the actual inferior process + /// that we are communicating with and aggregating information from. + const InferiorProcess &IP; + + /// CallStack - This caches information about the current stack trace of the + /// program. This is lazily computed as needed. + std::vector<StackFrame> CallStack; + + /// CurrentFrame - The user can traverse the stack frame with the + /// up/down/frame family of commands. This index indicates the current + /// stack frame. + unsigned CurrentFrame; + + public: + RuntimeInfo(ProgramInfo *PI, const InferiorProcess &ip) + : ProgInfo(PI), IP(ip), CurrentFrame(0) { + // Make sure that the top of stack has been materialized. If this throws + // an exception, something is seriously wrong and the RuntimeInfo object + // would be unusable anyway. + getStackFrame(0); + } + + ProgramInfo &getProgramInfo() { return *ProgInfo; } + const InferiorProcess &getInferiorProcess() const { return IP; } + + //===------------------------------------------------------------------===// + // Methods for inspecting the call stack of the program. + // + + /// getStackFrame - Materialize the specified stack frame and return it. If + /// the specified ID is off of the bottom of the stack, throw an exception + /// indicating the problem. + StackFrame &getStackFrame(unsigned ID) { + if (ID >= CallStack.size()) + materializeFrame(ID); + return CallStack[ID]; + } + + /// getCurrentFrame - Return the current stack frame object that the user is + /// inspecting. + StackFrame &getCurrentFrame() { + assert(CallStack.size() > CurrentFrame && + "Must have materialized frame before making it current!"); + return CallStack[CurrentFrame]; + } + + /// getCurrentFrameIdx - Return the current frame the user is inspecting. + /// + unsigned getCurrentFrameIdx() const { return CurrentFrame; } + + /// setCurrentFrameIdx - Set the current frame index to the specified value. + /// Note that the specified frame must have been materialized with + /// getStackFrame before it can be made current. + void setCurrentFrameIdx(unsigned Idx) { + assert(Idx < CallStack.size() && + "Must materialize frame before making it current!"); + CurrentFrame = Idx; + } + private: + /// materializeFrame - Create and process all frames up to and including the + /// specified frame number. This throws an exception if the specified frame + /// ID is nonexistant. + void materializeFrame(unsigned ID); + }; +} + +#endif diff --git a/include/llvm/Debugger/SourceFile.h b/include/llvm/Debugger/SourceFile.h new file mode 100644 index 0000000..e54660c --- /dev/null +++ b/include/llvm/Debugger/SourceFile.h @@ -0,0 +1,97 @@ +//===- SourceFile.h - Class to represent a source code file -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the SourceFile class which is used to represent a single +// file of source code in the program, caching data from the file to make access +// efficient. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGGER_SOURCEFILE_H +#define LLVM_DEBUGGER_SOURCEFILE_H + +#include "llvm/System/Path.h" +#include "llvm/System/MappedFile.h" +#include <vector> + +namespace llvm { + class GlobalVariable; + + class SourceFile { + /// Filename - This is the full path of the file that is loaded. + /// + sys::Path Filename; + + /// Descriptor - The debugging descriptor for this source file. If there + /// are multiple descriptors for the same file, this is just the first one + /// encountered. + /// + const GlobalVariable *Descriptor; + + /// This is the memory mapping for the file so we can gain access to it. + sys::MappedFile File; + + /// LineOffset - This vector contains a mapping from source line numbers to + /// their offsets in the file. This data is computed lazily, the first time + /// it is asked for. If there are zero elements allocated in this vector, + /// then it has not yet been computed. + mutable std::vector<unsigned> LineOffset; + + public: + /// SourceFile constructor - Read in the specified source file if it exists, + /// but do not build the LineOffsets table until it is requested. This will + /// NOT throw an exception if the file is not found, if there is an error + /// reading it, or if the user cancels the operation. Instead, it will just + /// be an empty source file. + SourceFile(const std::string &fn, const GlobalVariable *Desc) + : Filename(fn), Descriptor(Desc), File() { + std::string ErrMsg; + if (File.open(Filename, sys::MappedFile::READ_ACCESS, &ErrMsg)) + throw ErrMsg; + readFile(); + } + ~SourceFile() { + File.unmap(); + } + + /// getDescriptor - Return the debugging decriptor for this source file. + /// + const GlobalVariable *getDescriptor() const { return Descriptor; } + + /// getFilename - Return the fully resolved path that this file was loaded + /// from. + const std::string &getFilename() const { return Filename.toString(); } + + /// getSourceLine - Given a line number, return the start and end of the + /// line in the file. If the line number is invalid, or if the file could + /// not be loaded, null pointers are returned for the start and end of the + /// file. Note that line numbers start with 0, not 1. This also strips off + /// any newlines from the end of the line, to ease formatting of the text. + void getSourceLine(unsigned LineNo, const char *&LineStart, + const char *&LineEnd) const; + + /// getNumLines - Return the number of lines the source file contains. + /// + unsigned getNumLines() const { + if (LineOffset.empty()) calculateLineOffsets(); + return LineOffset.size(); + } + + private: + /// readFile - Load Filename into memory + /// + void readFile(); + + /// calculateLineOffsets - Compute the LineOffset vector for the current + /// file. + void calculateLineOffsets() const; + }; +} // end namespace llvm + +#endif diff --git a/include/llvm/Debugger/SourceLanguage.h b/include/llvm/Debugger/SourceLanguage.h new file mode 100644 index 0000000..06f4381 --- /dev/null +++ b/include/llvm/Debugger/SourceLanguage.h @@ -0,0 +1,99 @@ +//===- SourceLanguage.h - Interact with source languages --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the abstract SourceLanguage interface, which is used by the +// LLVM debugger to parse source-language expressions and render program objects +// into a human readable string. In general, these classes perform all of the +// analysis and interpretation of the language-specific debugger information. +// +// This interface is designed to be completely stateless, so all methods are +// const. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGGER_SOURCELANGUAGE_H +#define LLVM_DEBUGGER_SOURCELANGUAGE_H + +#include <string> + +namespace llvm { + class GlobalVariable; + class SourceFileInfo; + class SourceFunctionInfo; + class ProgramInfo; + class RuntimeInfo; + + struct SourceLanguage { + virtual ~SourceLanguage() {} + + /// getSourceLanguageName - This method is used to implement the 'show + /// language' command in the debugger. + virtual const char *getSourceLanguageName() const = 0; + + //===------------------------------------------------------------------===// + // Methods used to implement debugger hooks. + // + + /// printInfo - Implementing this method allows the debugger to use + /// language-specific 'info' extensions, e.g., 'info selectors' for objc. + /// This method should return true if the specified string is recognized. + /// + virtual bool printInfo(const std::string &What) const { + return false; + } + + /// lookupFunction - Given a textual function name, return the + /// SourceFunctionInfo descriptor for that function, or null if it cannot be + /// found. If the program is currently running, the RuntimeInfo object + /// provides information about the current evaluation context, otherwise it + /// will be null. + /// + virtual SourceFunctionInfo *lookupFunction(const std::string &FunctionName, + ProgramInfo &PI, + RuntimeInfo *RI = 0) const { + return 0; + } + + + //===------------------------------------------------------------------===// + // Methods used to parse various pieces of program information. + // + + /// createSourceFileInfo - This method can be implemented by the front-end + /// if it needs to keep track of information beyond what the debugger + /// requires. + virtual SourceFileInfo * + createSourceFileInfo(const GlobalVariable *Desc, ProgramInfo &PI) const; + + /// createSourceFunctionInfo - This method can be implemented by the derived + /// SourceLanguage if it needs to keep track of more information than the + /// SourceFunctionInfo has. + virtual SourceFunctionInfo * + createSourceFunctionInfo(const GlobalVariable *Desc, ProgramInfo &PI) const; + + + //===------------------------------------------------------------------===// + // Static methods used to get instances of various source languages. + // + + /// get - This method returns a source-language instance for the specified + /// Dwarf 3 language identifier. If the language is unknown, an object is + /// returned that can support some minimal operations, but is not terribly + /// bright. + static const SourceLanguage &get(unsigned ID); + + /// get*Instance() - These methods return specific instances of languages. + /// + static const SourceLanguage &getCFamilyInstance(); + static const SourceLanguage &getCPlusPlusInstance(); + static const SourceLanguage &getUnknownLanguageInstance(); + }; +} + +#endif diff --git a/include/llvm/DerivedTypes.h b/include/llvm/DerivedTypes.h new file mode 100644 index 0000000..ba35d78 --- /dev/null +++ b/include/llvm/DerivedTypes.h @@ -0,0 +1,419 @@ +//===-- llvm/DerivedTypes.h - Classes for handling data types ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations of classes that represent "derived +// types". These are things like "arrays of x" or "structure of x, y, z" or +// "method returning x taking (y,z) as parameters", etc... +// +// The implementations of these classes live in the Type.cpp file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DERIVED_TYPES_H +#define LLVM_DERIVED_TYPES_H + +#include "llvm/Type.h" + +namespace llvm { + +class Value; +template<class ValType, class TypeClass> class TypeMap; +class FunctionValType; +class ArrayValType; +class StructValType; +class PointerValType; +class VectorValType; +class IntegerValType; +class APInt; +class ParamAttrsList; + +class DerivedType : public Type { + friend class Type; + +protected: + explicit DerivedType(TypeID id) : Type(id) {} + + /// notifyUsesThatTypeBecameConcrete - Notify AbstractTypeUsers of this type + /// that the current type has transitioned from being abstract to being + /// concrete. + /// + void notifyUsesThatTypeBecameConcrete(); + + /// dropAllTypeUses - When this (abstract) type is resolved to be equal to + /// another (more concrete) type, we must eliminate all references to other + /// types, to avoid some circular reference problems. + /// + void dropAllTypeUses(); + +public: + + //===--------------------------------------------------------------------===// + // Abstract Type handling methods - These types have special lifetimes, which + // are managed by (add|remove)AbstractTypeUser. See comments in + // AbstractTypeUser.h for more information. + + /// refineAbstractTypeTo - This function is used to when it is discovered that + /// the 'this' abstract type is actually equivalent to the NewType specified. + /// This causes all users of 'this' to switch to reference the more concrete + /// type NewType and for 'this' to be deleted. + /// + void refineAbstractTypeTo(const Type *NewType); + + void dump() const { Type::dump(); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const DerivedType *T) { return true; } + static inline bool classof(const Type *T) { + return T->isDerivedType(); + } +}; + +/// Class to represent integer types. Note that this class is also used to +/// represent the built-in integer types: Int1Ty, Int8Ty, Int16Ty, Int32Ty and +/// Int64Ty. +/// @brief Integer representation type +class IntegerType : public DerivedType { +protected: + explicit IntegerType(unsigned NumBits) : DerivedType(IntegerTyID) { + setSubclassData(NumBits); + } + friend class TypeMap<IntegerValType, IntegerType>; +public: + /// This enum is just used to hold constants we need for IntegerType. + enum { + MIN_INT_BITS = 1, ///< Minimum number of bits that can be specified + MAX_INT_BITS = (1<<23)-1 ///< Maximum number of bits that can be specified + ///< Note that bit width is stored in the Type classes SubclassData field + ///< which has 23 bits. This yields a maximum bit width of 8,388,607 bits. + }; + + /// This static method is the primary way of constructing an IntegerType. + /// If an IntegerType with the same NumBits value was previously instantiated, + /// that instance will be returned. Otherwise a new one will be created. Only + /// one instance with a given NumBits value is ever created. + /// @brief Get or create an IntegerType instance. + static const IntegerType* get(unsigned NumBits); + + /// @brief Get the number of bits in this IntegerType + unsigned getBitWidth() const { return getSubclassData(); } + + /// getBitMask - Return a bitmask with ones set for all of the bits + /// that can be set by an unsigned version of this type. This is 0xFF for + /// sbyte/ubyte, 0xFFFF for shorts, etc. + uint64_t getBitMask() const { + return ~uint64_t(0UL) >> (64-getBitWidth()); + } + + /// getSignBit - Return a uint64_t with just the most significant bit set (the + /// sign bit, if the value is treated as a signed number). + uint64_t getSignBit() const { + return 1ULL << (getBitWidth()-1); + } + + /// For example, this is 0xFF for an 8 bit integer, 0xFFFF for i16, etc. + /// @returns a bit mask with ones set for all the bits of this type. + /// @brief Get a bit mask for this type. + APInt getMask() const; + + /// This method determines if the width of this IntegerType is a power-of-2 + /// in terms of 8 bit bytes. + /// @returns true if this is a power-of-2 byte width. + /// @brief Is this a power-of-2 byte-width IntegerType ? + bool isPowerOf2ByteWidth() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IntegerType *T) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == IntegerTyID; + } +}; + + +/// FunctionType - Class to represent function types +/// +class FunctionType : public DerivedType { + friend class TypeMap<FunctionValType, FunctionType>; + bool isVarArgs; + const ParamAttrsList *ParamAttrs; + + FunctionType(const FunctionType &); // Do not implement + const FunctionType &operator=(const FunctionType &); // Do not implement + FunctionType(const Type *Result, const std::vector<const Type*> &Params, + bool IsVarArgs, const ParamAttrsList *Attrs = 0); + +public: + /// FunctionType::get - This static method is the primary way of constructing + /// a FunctionType. + /// + static FunctionType *get( + const Type *Result, ///< The result type + const std::vector<const Type*> &Params, ///< The types of the parameters + bool isVarArg, ///< Whether this is a variable argument length function + const ParamAttrsList *Attrs = 0 + ///< Indicates the parameter attributes to use, if any. The 0th entry + ///< in the list refers to the return type. Parameters are numbered + ///< starting at 1. This argument must be on the heap and FunctionType + ///< owns it after its passed here. + ); + + inline bool isVarArg() const { return isVarArgs; } + inline const Type *getReturnType() const { return ContainedTys[0]; } + + typedef Type::subtype_iterator param_iterator; + param_iterator param_begin() const { return ContainedTys + 1; } + param_iterator param_end() const { return &ContainedTys[NumContainedTys]; } + + // Parameter type accessors... + const Type *getParamType(unsigned i) const { return ContainedTys[i+1]; } + + /// getNumParams - Return the number of fixed parameters this function type + /// requires. This does not consider varargs. + /// + unsigned getNumParams() const { return NumContainedTys - 1; } + + bool isStructReturn() const; + + /// The parameter attributes for the \p ith parameter are returned. The 0th + /// parameter refers to the return type of the function. + /// @returns The ParameterAttributes for the \p ith parameter. + /// @brief Get the attributes for a parameter + const ParamAttrsList *getParamAttrs() const { return ParamAttrs; } + + // Implement the AbstractTypeUser interface. + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FunctionType *T) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == FunctionTyID; + } +}; + + +/// CompositeType - Common super class of ArrayType, StructType, PointerType +/// and VectorType +class CompositeType : public DerivedType { +protected: + inline explicit CompositeType(TypeID id) : DerivedType(id) { } +public: + + /// getTypeAtIndex - Given an index value into the type, return the type of + /// the element. + /// + virtual const Type *getTypeAtIndex(const Value *V) const = 0; + virtual bool indexValid(const Value *V) const = 0; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const CompositeType *T) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == ArrayTyID || + T->getTypeID() == StructTyID || + T->getTypeID() == PointerTyID || + T->getTypeID() == VectorTyID; + } +}; + + +/// StructType - Class to represent struct types +/// +class StructType : public CompositeType { + friend class TypeMap<StructValType, StructType>; + StructType(const StructType &); // Do not implement + const StructType &operator=(const StructType &); // Do not implement + StructType(const std::vector<const Type*> &Types, bool isPacked); +public: + /// StructType::get - This static method is the primary way to create a + /// StructType. + /// + static StructType *get(const std::vector<const Type*> &Params, + bool isPacked=false); + + // Iterator access to the elements + typedef Type::subtype_iterator element_iterator; + element_iterator element_begin() const { return ContainedTys; } + element_iterator element_end() const { return &ContainedTys[NumContainedTys];} + + // Random access to the elements + unsigned getNumElements() const { return NumContainedTys; } + const Type *getElementType(unsigned N) const { + assert(N < NumContainedTys && "Element number out of range!"); + return ContainedTys[N]; + } + + /// getTypeAtIndex - Given an index value into the type, return the type of + /// the element. For a structure type, this must be a constant value... + /// + virtual const Type *getTypeAtIndex(const Value *V) const ; + virtual bool indexValid(const Value *V) const; + + // Implement the AbstractTypeUser interface. + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const StructType *T) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == StructTyID; + } + + bool isPacked() const { return getSubclassData(); } +}; + + +/// SequentialType - This is the superclass of the array, pointer and vector +/// type classes. All of these represent "arrays" in memory. The array type +/// represents a specifically sized array, pointer types are unsized/unknown +/// size arrays, vector types represent specifically sized arrays that +/// allow for use of SIMD instructions. SequentialType holds the common +/// features of all, which stem from the fact that all three lay their +/// components out in memory identically. +/// +class SequentialType : public CompositeType { + PATypeHandle ContainedType; ///< Storage for the single contained type + SequentialType(const SequentialType &); // Do not implement! + const SequentialType &operator=(const SequentialType &); // Do not implement! +protected: + SequentialType(TypeID TID, const Type *ElType) + : CompositeType(TID), ContainedType(ElType, this) { + ContainedTys = &ContainedType; + NumContainedTys = 1; + } + +public: + inline const Type *getElementType() const { return ContainedTys[0]; } + + virtual bool indexValid(const Value *V) const; + + /// getTypeAtIndex - Given an index value into the type, return the type of + /// the element. For sequential types, there is only one subtype... + /// + virtual const Type *getTypeAtIndex(const Value *V) const { + return ContainedTys[0]; + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SequentialType *T) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == ArrayTyID || + T->getTypeID() == PointerTyID || + T->getTypeID() == VectorTyID; + } +}; + + +/// ArrayType - Class to represent array types +/// +class ArrayType : public SequentialType { + friend class TypeMap<ArrayValType, ArrayType>; + uint64_t NumElements; + + ArrayType(const ArrayType &); // Do not implement + const ArrayType &operator=(const ArrayType &); // Do not implement + ArrayType(const Type *ElType, uint64_t NumEl); +public: + /// ArrayType::get - This static method is the primary way to construct an + /// ArrayType + /// + static ArrayType *get(const Type *ElementType, uint64_t NumElements); + + inline uint64_t getNumElements() const { return NumElements; } + + // Implement the AbstractTypeUser interface. + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ArrayType *T) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == ArrayTyID; + } +}; + +/// VectorType - Class to represent vector types +/// +class VectorType : public SequentialType { + friend class TypeMap<VectorValType, VectorType>; + unsigned NumElements; + + VectorType(const VectorType &); // Do not implement + const VectorType &operator=(const VectorType &); // Do not implement + VectorType(const Type *ElType, unsigned NumEl); +public: + /// VectorType::get - This static method is the primary way to construct an + /// VectorType + /// + static VectorType *get(const Type *ElementType, unsigned NumElements); + + /// @brief Return the number of elements in the Vector type. + inline unsigned getNumElements() const { return NumElements; } + + /// @brief Return the number of bits in the Vector type. + inline unsigned getBitWidth() const { + return NumElements *getElementType()->getPrimitiveSizeInBits(); + } + + // Implement the AbstractTypeUser interface. + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const VectorType *T) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == VectorTyID; + } +}; + + +/// PointerType - Class to represent pointers +/// +class PointerType : public SequentialType { + friend class TypeMap<PointerValType, PointerType>; + PointerType(const PointerType &); // Do not implement + const PointerType &operator=(const PointerType &); // Do not implement + explicit PointerType(const Type *ElType); +public: + /// PointerType::get - This is the only way to construct a new pointer type. + static PointerType *get(const Type *ElementType); + + // Implement the AbstractTypeUser interface. + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); + + // Implement support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const PointerType *T) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == PointerTyID; + } +}; + + +/// OpaqueType - Class to represent abstract types +/// +class OpaqueType : public DerivedType { + OpaqueType(const OpaqueType &); // DO NOT IMPLEMENT + const OpaqueType &operator=(const OpaqueType &); // DO NOT IMPLEMENT + OpaqueType(); +public: + /// OpaqueType::get - Static factory method for the OpaqueType class... + /// + static OpaqueType *get() { + return new OpaqueType(); // All opaque types are distinct + } + + // Implement support for type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const OpaqueType *T) { return true; } + static inline bool classof(const Type *T) { + return T->getTypeID() == OpaqueTyID; + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/ExecutionEngine/ExecutionEngine.h b/include/llvm/ExecutionEngine/ExecutionEngine.h new file mode 100644 index 0000000..7100a5f --- /dev/null +++ b/include/llvm/ExecutionEngine/ExecutionEngine.h @@ -0,0 +1,227 @@ +//===- ExecutionEngine.h - Abstract Execution Engine Interface --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the abstract interface that implements execution support +// for LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef EXECUTION_ENGINE_H +#define EXECUTION_ENGINE_H + +#include <vector> +#include <map> +#include <cassert> +#include <string> +#include "llvm/System/Mutex.h" +#include "llvm/ADT/SmallVector.h" + +namespace llvm { + +struct GenericValue; +class Constant; +class Function; +class GlobalVariable; +class GlobalValue; +class Module; +class ModuleProvider; +class TargetData; +class Type; +class MutexGuard; + +class ExecutionEngineState { +private: + /// GlobalAddressMap - A mapping between LLVM global values and their + /// actualized version... + std::map<const GlobalValue*, void *> GlobalAddressMap; + + /// GlobalAddressReverseMap - This is the reverse mapping of GlobalAddressMap, + /// used to convert raw addresses into the LLVM global value that is emitted + /// at the address. This map is not computed unless getGlobalValueAtAddress + /// is called at some point. + std::map<void *, const GlobalValue*> GlobalAddressReverseMap; + +public: + std::map<const GlobalValue*, void *> & + getGlobalAddressMap(const MutexGuard &locked) { + return GlobalAddressMap; + } + + std::map<void*, const GlobalValue*> & + getGlobalAddressReverseMap(const MutexGuard& locked) { + return GlobalAddressReverseMap; + } +}; + + +class ExecutionEngine { + const TargetData *TD; + ExecutionEngineState state; + bool LazyCompilationDisabled; +protected: + /// Modules - This is a list of ModuleProvider's that we are JIT'ing from. We + /// use a smallvector to optimize for the case where there is only one module. + SmallVector<ModuleProvider*, 1> Modules; + + void setTargetData(const TargetData *td) { + TD = td; + } + + // To avoid having libexecutionengine depend on the JIT and interpreter + // libraries, the JIT and Interpreter set these functions to ctor pointers + // at startup time if they are linked in. + typedef ExecutionEngine *(*EECtorFn)(ModuleProvider*, std::string*); + static EECtorFn JITCtor, InterpCtor; + +public: + /// lock - This lock is protects the ExecutionEngine, JIT, JITResolver and + /// JITEmitter classes. It must be held while changing the internal state of + /// any of those classes. + sys::Mutex lock; // Used to make this class and subclasses thread-safe + + ExecutionEngine(ModuleProvider *P); + ExecutionEngine(Module *M); + virtual ~ExecutionEngine(); + + const TargetData *getTargetData() const { return TD; } + + /// addModuleProvider - Add a ModuleProvider to the list of modules that we + /// can JIT from. Note that this takes ownership of the ModuleProvider: when + /// the ExecutionEngine is destroyed, it destroys the MP as well. + void addModuleProvider(ModuleProvider *P) { + Modules.push_back(P); + } + + /// FindFunctionNamed - Search all of the active modules to find the one that + /// defines FnName. This is very slow operation and shouldn't be used for + /// general code. + Function *FindFunctionNamed(const char *FnName); + + /// create - This is the factory method for creating an execution engine which + /// is appropriate for the current machine. + static ExecutionEngine *create(ModuleProvider *MP, + bool ForceInterpreter = false, + std::string *ErrorStr = 0); + + /// runFunction - Execute the specified function with the specified arguments, + /// and return the result. + /// + virtual GenericValue runFunction(Function *F, + const std::vector<GenericValue> &ArgValues) = 0; + + /// runStaticConstructorsDestructors - This method is used to execute all of + /// the static constructors or destructors for a module, depending on the + /// value of isDtors. + void runStaticConstructorsDestructors(bool isDtors); + + + /// runFunctionAsMain - This is a helper function which wraps runFunction to + /// handle the common task of starting up main with the specified argc, argv, + /// and envp parameters. + int runFunctionAsMain(Function *Fn, const std::vector<std::string> &argv, + const char * const * envp); + + + /// addGlobalMapping - Tell the execution engine that the specified global is + /// at the specified location. This is used internally as functions are JIT'd + /// and as global variables are laid out in memory. It can and should also be + /// used by clients of the EE that want to have an LLVM global overlay + /// existing data in memory. + void addGlobalMapping(const GlobalValue *GV, void *Addr); + + /// clearAllGlobalMappings - Clear all global mappings and start over again + /// use in dynamic compilation scenarios when you want to move globals + void clearAllGlobalMappings(); + + /// updateGlobalMapping - Replace an existing mapping for GV with a new + /// address. This updates both maps as required. If "Addr" is null, the + /// entry for the global is removed from the mappings. + void updateGlobalMapping(const GlobalValue *GV, void *Addr); + + /// getPointerToGlobalIfAvailable - This returns the address of the specified + /// global value if it is has already been codegen'd, otherwise it returns + /// null. + /// + void *getPointerToGlobalIfAvailable(const GlobalValue *GV); + + /// getPointerToGlobal - This returns the address of the specified global + /// value. This may involve code generation if it's a function. + /// + void *getPointerToGlobal(const GlobalValue *GV); + + /// getPointerToFunction - The different EE's represent function bodies in + /// different ways. They should each implement this to say what a function + /// pointer should look like. + /// + virtual void *getPointerToFunction(Function *F) = 0; + + /// getPointerToFunctionOrStub - If the specified function has been + /// code-gen'd, return a pointer to the function. If not, compile it, or use + /// a stub to implement lazy compilation if available. + /// + virtual void *getPointerToFunctionOrStub(Function *F) { + // Default implementation, just codegen the function. + return getPointerToFunction(F); + } + + /// getGlobalValueAtAddress - Return the LLVM global value object that starts + /// at the specified address. + /// + const GlobalValue *getGlobalValueAtAddress(void *Addr); + + + void StoreValueToMemory(const GenericValue &Val, GenericValue *Ptr, const Type *Ty); + void InitializeMemory(const Constant *Init, void *Addr); + + /// recompileAndRelinkFunction - This method is used to force a function + /// which has already been compiled to be compiled again, possibly + /// after it has been modified. Then the entry to the old copy is overwritten + /// with a branch to the new copy. If there was no old copy, this acts + /// just like VM::getPointerToFunction(). + /// + virtual void *recompileAndRelinkFunction(Function *F) = 0; + + /// freeMachineCodeForFunction - Release memory in the ExecutionEngine + /// corresponding to the machine code emitted to execute this function, useful + /// for garbage-collecting generated code. + /// + virtual void freeMachineCodeForFunction(Function *F) = 0; + + /// getOrEmitGlobalVariable - Return the address of the specified global + /// variable, possibly emitting it to memory if needed. This is used by the + /// Emitter. + virtual void *getOrEmitGlobalVariable(const GlobalVariable *GV) { + return getPointerToGlobal((GlobalValue*)GV); + } + + /// DisableLazyCompilation - If called, the JIT will abort if lazy compilation + // is ever attempted. + void DisableLazyCompilation() { + LazyCompilationDisabled = true; + } + bool isLazyCompilationDisabled() const { + return LazyCompilationDisabled; + } + +protected: + void emitGlobals(); + + // EmitGlobalVariable - This method emits the specified global variable to the + // address specified in GlobalAddresses, or allocates new memory if it's not + // already in the map. + void EmitGlobalVariable(const GlobalVariable *GV); + + GenericValue getConstantValue(const Constant *C); + void LoadValueFromMemory(GenericValue &Result, GenericValue *Ptr, + const Type *Ty); +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/ExecutionEngine/GenericValue.h b/include/llvm/ExecutionEngine/GenericValue.h new file mode 100644 index 0000000..d0cd2cd --- /dev/null +++ b/include/llvm/ExecutionEngine/GenericValue.h @@ -0,0 +1,44 @@ +//===-- GenericValue.h - Represent any type of LLVM value -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// The GenericValue class is used to represent an LLVM value of arbitrary type. +// +//===----------------------------------------------------------------------===// + + +#ifndef GENERIC_VALUE_H +#define GENERIC_VALUE_H + +#include "llvm/ADT/APInt.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +typedef void* PointerTy; +class APInt; + +struct GenericValue { + union { + double DoubleVal; + float FloatVal; + PointerTy PointerVal; + struct { unsigned int first; unsigned int second; } UIntPairVal; + unsigned char Untyped[8]; + }; + APInt IntVal; + + GenericValue() : DoubleVal(0.0), IntVal(1,0) {} + GenericValue(void *V) : PointerVal(V), IntVal(1,0) { } +}; + +inline GenericValue PTOGV(void *P) { return GenericValue(P); } +inline void* GVTOP(const GenericValue &GV) { return GV.PointerVal; } + +} // End llvm namespace +#endif diff --git a/include/llvm/ExecutionEngine/Interpreter.h b/include/llvm/ExecutionEngine/Interpreter.h new file mode 100644 index 0000000..b46574d --- /dev/null +++ b/include/llvm/ExecutionEngine/Interpreter.h @@ -0,0 +1,40 @@ +//===-- Interpreter.h - Abstract Execution Engine Interface -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Jeff Cohen and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file forces the interpreter to link in on certain operating systems. +// (Windows). +// +//===----------------------------------------------------------------------===// + +#ifndef EXECUTION_ENGINE_INTERPRETER_H +#define EXECUTION_ENGINE_INTERPRETER_H + +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include <cstdlib> + +namespace llvm { + extern void LinkInInterpreter(); +} + +namespace { + struct ForceInterpreterLinking { + ForceInterpreterLinking() { + // We must reference the passes in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + llvm::LinkInInterpreter(); + } + } ForceInterpreterLinking; +} + +#endif diff --git a/include/llvm/ExecutionEngine/JIT.h b/include/llvm/ExecutionEngine/JIT.h new file mode 100644 index 0000000..b801f1d --- /dev/null +++ b/include/llvm/ExecutionEngine/JIT.h @@ -0,0 +1,40 @@ +//===-- JIT.h - Abstract Execution Engine Interface -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Jeff Cohen and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file forces the JIT to link in on certain operating systems. +// (Windows). +// +//===----------------------------------------------------------------------===// + +#ifndef EXECUTION_ENGINE_JIT_H +#define EXECUTION_ENGINE_JIT_H + +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include <cstdlib> + +namespace llvm { + extern void LinkInJIT(); +} + +namespace { + struct ForceJITLinking { + ForceJITLinking() { + // We must reference the passes in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + llvm::LinkInJIT(); + } + } ForceJITLinking; +} + +#endif diff --git a/include/llvm/Function.h b/include/llvm/Function.h new file mode 100644 index 0000000..b3b9716 --- /dev/null +++ b/include/llvm/Function.h @@ -0,0 +1,280 @@ +//===-- llvm/Function.h - Class to represent a single function --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Function class, which represents a +// single function/procedure in LLVM. +// +// A function basically consists of a list of basic blocks, a list of arguments, +// and a symbol table. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_FUNCTION_H +#define LLVM_FUNCTION_H + +#include "llvm/GlobalValue.h" +#include "llvm/BasicBlock.h" +#include "llvm/Argument.h" +#include "llvm/Support/Annotation.h" + +namespace llvm { + +class FunctionType; +class ParamAttrsList; + +// Traits for intrusive list of instructions... +template<> struct ilist_traits<BasicBlock> + : public SymbolTableListTraits<BasicBlock, Function> { + + // createSentinel is used to create a node that marks the end of the list... + static BasicBlock *createSentinel(); + static void destroySentinel(BasicBlock *BB) { delete BB; } + static iplist<BasicBlock> &getList(Function *F); + static ValueSymbolTable *getSymTab(Function *ItemParent); + static int getListOffset(); +}; + +template<> struct ilist_traits<Argument> + : public SymbolTableListTraits<Argument, Function> { + + // createSentinel is used to create a node that marks the end of the list... + static Argument *createSentinel(); + static void destroySentinel(Argument *A) { delete A; } + static iplist<Argument> &getList(Function *F); + static ValueSymbolTable *getSymTab(Function *ItemParent); + static int getListOffset(); +}; + +class Function : public GlobalValue, public Annotable { +public: + typedef iplist<Argument> ArgumentListType; + typedef iplist<BasicBlock> BasicBlockListType; + + // BasicBlock iterators... + typedef BasicBlockListType::iterator iterator; + typedef BasicBlockListType::const_iterator const_iterator; + + typedef ArgumentListType::iterator arg_iterator; + typedef ArgumentListType::const_iterator const_arg_iterator; + +private: + // Important things that make up a function! + BasicBlockListType BasicBlocks; ///< The basic blocks + ArgumentListType ArgumentList; ///< The formal arguments + ValueSymbolTable *SymTab; ///< Symbol table of args/instructions + ParamAttrsList *ParamAttrs; ///< Parameter attributes + + + // The Calling Convention is stored in Value::SubclassData. + /*unsigned CallingConvention;*/ + + friend class SymbolTableListTraits<Function, Module>; + + void setParent(Module *parent); + Function *Prev, *Next; + void setNext(Function *N) { Next = N; } + void setPrev(Function *N) { Prev = N; } + + // getNext/Prev - Return the next or previous function in the list. These + // methods should never be used directly, and are only used to implement the + // function list as part of the module. + // + Function *getNext() { return Next; } + const Function *getNext() const { return Next; } + Function *getPrev() { return Prev; } + const Function *getPrev() const { return Prev; } + +public: + /// Function ctor - If the (optional) Module argument is specified, the + /// function is automatically inserted into the end of the function list for + /// the module. + /// + Function(const FunctionType *Ty, LinkageTypes Linkage, + const std::string &N = "", Module *M = 0); + ~Function(); + + const Type *getReturnType() const; // Return the type of the ret val + const FunctionType *getFunctionType() const; // Return the FunctionType for me + + /// isVarArg - Return true if this function takes a variable number of + /// arguments. + bool isVarArg() const; + + /// isDeclaration - Is the body of this function unknown? (The basic block + /// list is empty if so.) This is true for function declarations, but not + /// true for function definitions. + /// + virtual bool isDeclaration() const { return BasicBlocks.empty(); } + + /// getIntrinsicID - This method returns the ID number of the specified + /// function, or Intrinsic::not_intrinsic if the function is not an + /// instrinsic, or if the pointer is null. This value is always defined to be + /// zero to allow easy checking for whether a function is intrinsic or not. + /// The particular intrinsic functions which correspond to this value are + /// defined in llvm/Intrinsics.h. + /// + unsigned getIntrinsicID(bool noAssert = false) const; + bool isIntrinsic() const { return getIntrinsicID() != 0; } + + /// getCallingConv()/setCallingConv(uint) - These method get and set the + /// calling convention of this function. The enum values for the known + /// calling conventions are defined in CallingConv.h. + unsigned getCallingConv() const { return SubclassData; } + void setCallingConv(unsigned CC) { SubclassData = CC; } + + /// Obtains a constant pointer to the ParamAttrsList object which holds the + /// parameter attributes information, if any. + /// @returns 0 if no parameter attributes have been set. + /// @brief Get the parameter attributes. + const ParamAttrsList *getParamAttrs() const { return ParamAttrs; } + + /// Sets the parameter attributes for this Function. To construct a + /// ParamAttrsList, see ParameterAttributes.h + /// @brief Set the parameter attributes. + void setParamAttrs(ParamAttrsList *attrs); + + /// deleteBody - This method deletes the body of the function, and converts + /// the linkage to external. + /// + void deleteBody() { + dropAllReferences(); + setLinkage(ExternalLinkage); + } + + /// removeFromParent - This method unlinks 'this' from the containing module, + /// but does not delete it. + /// + void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing module + /// and deletes it. + /// + void eraseFromParent(); + + + /// Get the underlying elements of the Function... the basic block list is + /// empty for external functions. + /// + const ArgumentListType &getArgumentList() const { return ArgumentList; } + ArgumentListType &getArgumentList() { return ArgumentList; } + + const BasicBlockListType &getBasicBlockList() const { return BasicBlocks; } + BasicBlockListType &getBasicBlockList() { return BasicBlocks; } + + const BasicBlock &getEntryBlock() const { return front(); } + BasicBlock &getEntryBlock() { return front(); } + + //===--------------------------------------------------------------------===// + // Symbol Table Accessing functions... + + /// getSymbolTable() - Return the symbol table... + /// + inline ValueSymbolTable &getValueSymbolTable() { return *SymTab; } + inline const ValueSymbolTable &getValueSymbolTable() const { return *SymTab; } + + + //===--------------------------------------------------------------------===// + // BasicBlock iterator forwarding functions + // + iterator begin() { return BasicBlocks.begin(); } + const_iterator begin() const { return BasicBlocks.begin(); } + iterator end () { return BasicBlocks.end(); } + const_iterator end () const { return BasicBlocks.end(); } + + size_t size() const { return BasicBlocks.size(); } + bool empty() const { return BasicBlocks.empty(); } + const BasicBlock &front() const { return BasicBlocks.front(); } + BasicBlock &front() { return BasicBlocks.front(); } + const BasicBlock &back() const { return BasicBlocks.back(); } + BasicBlock &back() { return BasicBlocks.back(); } + + //===--------------------------------------------------------------------===// + // Argument iterator forwarding functions + // + arg_iterator arg_begin() { return ArgumentList.begin(); } + const_arg_iterator arg_begin() const { return ArgumentList.begin(); } + arg_iterator arg_end () { return ArgumentList.end(); } + const_arg_iterator arg_end () const { return ArgumentList.end(); } + + size_t arg_size () const { return ArgumentList.size(); } + bool arg_empty() const { return ArgumentList.empty(); } + + virtual void print(std::ostream &OS) const { print(OS, 0); } + void print(std::ostream *OS) const { if (OS) print(*OS); } + void print(std::ostream &OS, AssemblyAnnotationWriter *AAW) const; + + /// viewCFG - This function is meant for use from the debugger. You can just + /// say 'call F->viewCFG()' and a ghostview window should pop up from the + /// program, displaying the CFG of the current function with the code for each + /// basic block inside. This depends on there being a 'dot' and 'gv' program + /// in your path. + /// + void viewCFG() const; + + /// viewCFGOnly - This function is meant for use from the debugger. It works + /// just like viewCFG, but it does not include the contents of basic blocks + /// into the nodes, just the label. If you are only interested in the CFG + /// this can make the graph smaller. + /// + void viewCFGOnly() const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Function *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::FunctionVal; + } + + /// dropAllReferences() - This method causes all the subinstructions to "let + /// go" of all references that they are maintaining. This allows one to + /// 'delete' a whole module at a time, even though there may be circular + /// references... first all references are dropped, and all use counts go to + /// zero. Then everything is deleted for real. Note that no operations are + /// valid on an object that has "dropped all references", except operator + /// delete. + /// + /// Since no other object in the module can have references into the body of a + /// function, dropping all references deletes the entire body of the function, + /// including any contained basic blocks. + /// + void dropAllReferences(); + + static unsigned getBasicBlockListOffset() { + Function *Obj = 0; + return unsigned(reinterpret_cast<uintptr_t>(&Obj->BasicBlocks)); + } + static unsigned getArgumentListOffset() { + Function *Obj = 0; + return unsigned(reinterpret_cast<uintptr_t>(&Obj->ArgumentList)); + } +}; + +inline ValueSymbolTable * +ilist_traits<BasicBlock>::getSymTab(Function *F) { + return F ? &F->getValueSymbolTable() : 0; +} + +inline ValueSymbolTable * +ilist_traits<Argument>::getSymTab(Function *F) { + return F ? &F->getValueSymbolTable() : 0; +} + +inline int +ilist_traits<BasicBlock>::getListOffset() { + return Function::getBasicBlockListOffset(); +} + +inline int +ilist_traits<Argument>::getListOffset() { + return Function::getArgumentListOffset(); +} + + +} // End llvm namespace + +#endif diff --git a/include/llvm/GlobalAlias.h b/include/llvm/GlobalAlias.h new file mode 100644 index 0000000..bbd19ba --- /dev/null +++ b/include/llvm/GlobalAlias.h @@ -0,0 +1,91 @@ +//===-------- llvm/GlobalAlias.h - GlobalAlias class ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Anton Korobeynikov and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the GlobalAlias class, which +// represents a single function or variable alias in the IR. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_GLOBAL_ALIAS_H +#define LLVM_GLOBAL_ALIAS_H + +#include "llvm/GlobalValue.h" + +namespace llvm { + +class Module; +class Constant; +class PointerType; +template<typename ValueSubClass, typename ItemParentClass> + class SymbolTableListTraits; + +class GlobalAlias : public GlobalValue { + friend class SymbolTableListTraits<GlobalAlias, Module>; + void operator=(const GlobalAlias &); // Do not implement + GlobalAlias(const GlobalAlias &); // Do not implement + + void setParent(Module *parent); + + GlobalAlias *Prev, *Next; + void setNext(GlobalAlias *N) { Next = N; } + void setPrev(GlobalAlias *N) { Prev = N; } + + // getNext/Prev - Return the next or previous alias in the list. + GlobalAlias *getNext() { return Next; } + const GlobalAlias *getNext() const { return Next; } + GlobalAlias *getPrev() { return Prev; } + const GlobalAlias *getPrev() const { return Prev; } + + Use Aliasee; +public: + /// GlobalAlias ctor - If a parent module is specified, the alias is + /// automatically inserted into the end of the specified module's alias list. + GlobalAlias(const Type *Ty, LinkageTypes Linkage, const std::string &Name = "", + Constant* Aliasee = 0, Module *Parent = 0); + + /// isDeclaration - Is this global variable lacking an initializer? If so, + /// the global variable is defined in some other translation unit, and is thus + /// only a declaration here. + virtual bool isDeclaration() const; + + /// removeFromParent - This method unlinks 'this' from the containing module, + /// but does not delete it. + /// + void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing module + /// and deletes it. + /// + void eraseFromParent(); + + virtual void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + + /// set/getAliasee - These methods retrive and set alias target. + void setAliasee(Constant* GV); + const Constant* getAliasee() const { + return cast_or_null<Constant>(getOperand(0)); + } + Constant* getAliasee() { + return cast_or_null<Constant>(getOperand(0)); + } + /// getAliasedGlobal() - Aliasee can be either global or bitcast of + /// global. This method retrives the global for both aliasee flavours. + const GlobalValue* getAliasedGlobal() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const GlobalAlias *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::GlobalAliasVal; + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/GlobalValue.h b/include/llvm/GlobalValue.h new file mode 100644 index 0000000..6735cb5 --- /dev/null +++ b/include/llvm/GlobalValue.h @@ -0,0 +1,151 @@ +//===-- llvm/GlobalValue.h - Class to represent a global value --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a common base class of all globally definable objects. As such, +// it is subclassed by GlobalVariable, GlobalAlias and by Function. This is +// used because you can do certain things with these global objects that you +// can't do to anything else. For example, use the address of one as a +// constant. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_GLOBALVALUE_H +#define LLVM_GLOBALVALUE_H + +#include "llvm/Constant.h" + +namespace llvm { + +class PointerType; +class Module; + +class GlobalValue : public Constant { + GlobalValue(const GlobalValue &); // do not implement +public: + /// @brief An enumeration for the kinds of linkage for global values. + enum LinkageTypes { + ExternalLinkage = 0,///< Externally visible function + LinkOnceLinkage, ///< Keep one copy of function when linking (inline) + WeakLinkage, ///< Keep one copy of named function when linking (weak) + AppendingLinkage, ///< Special purpose, only applies to global arrays + InternalLinkage, ///< Rename collisions when linking (static functions) + DLLImportLinkage, ///< Function to be imported from DLL + DLLExportLinkage, ///< Function to be accessible from DLL + ExternalWeakLinkage,///< ExternalWeak linkage description + GhostLinkage ///< Stand-in functions for streaming fns from BC files + }; + + /// @brief An enumeration for the kinds of visibility of global values. + enum VisibilityTypes { + DefaultVisibility = 0, ///< The GV is visible + HiddenVisibility, ///< The GV is hidden + ProtectedVisibility ///< The GV is protected + }; + +protected: + GlobalValue(const Type *Ty, ValueTy vty, Use *Ops, unsigned NumOps, + LinkageTypes linkage, const std::string &name = "") + : Constant(Ty, vty, Ops, NumOps), Parent(0), + Linkage(linkage), Visibility(DefaultVisibility), Alignment(0) { + if (!name.empty()) setName(name); + } + + Module *Parent; + // Note: VC++ treats enums as signed, so an extra bit is required to prevent + // Linkage and Visibility from turning into negative values. + LinkageTypes Linkage : 5; // The linkage of this global + unsigned Visibility : 2; // The visibility style of this global + unsigned Alignment : 16; // Alignment of this symbol, must be power of two + std::string Section; // Section to emit this into, empty mean default +public: + ~GlobalValue() { + removeDeadConstantUsers(); // remove any dead constants using this. + } + + unsigned getAlignment() const { return Alignment; } + void setAlignment(unsigned Align) { + assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!"); + Alignment = Align; + } + + VisibilityTypes getVisibility() const { return (VisibilityTypes)Visibility; } + bool hasHiddenVisibility() const { return Visibility == HiddenVisibility; } + bool hasProtectedVisibility() const { + return Visibility == ProtectedVisibility; + } + void setVisibility(VisibilityTypes V) { Visibility = V; } + + bool hasSection() const { return !Section.empty(); } + const std::string &getSection() const { return Section; } + void setSection(const std::string &S) { Section = S; } + + /// If the usage is empty (except transitively dead constants), then this + /// global value can can be safely deleted since the destructor will + /// delete the dead constants as well. + /// @brief Determine if the usage of this global value is empty except + /// for transitively dead constants. + bool use_empty_except_constants(); + + /// getType - Global values are always pointers. + inline const PointerType *getType() const { + return reinterpret_cast<const PointerType*>(User::getType()); + } + + bool hasExternalLinkage() const { return Linkage == ExternalLinkage; } + bool hasLinkOnceLinkage() const { return Linkage == LinkOnceLinkage; } + bool hasWeakLinkage() const { return Linkage == WeakLinkage; } + bool hasAppendingLinkage() const { return Linkage == AppendingLinkage; } + bool hasInternalLinkage() const { return Linkage == InternalLinkage; } + bool hasDLLImportLinkage() const { return Linkage == DLLImportLinkage; } + bool hasDLLExportLinkage() const { return Linkage == DLLExportLinkage; } + bool hasExternalWeakLinkage() const { return Linkage == ExternalWeakLinkage; } + void setLinkage(LinkageTypes LT) { Linkage = LT; } + LinkageTypes getLinkage() const { return Linkage; } + + /// hasNotBeenReadFromBitcode - If a module provider is being used to lazily + /// stream in functions from disk, this method can be used to check to see if + /// the function has been read in yet or not. Unless you are working on the + /// JIT or something else that streams stuff in lazily, you don't need to + /// worry about this. + bool hasNotBeenReadFromBitcode() const { return Linkage == GhostLinkage; } + + /// Override from Constant class. No GlobalValue's are null values so this + /// always returns false. + virtual bool isNullValue() const { return false; } + + /// Override from Constant class. + virtual void destroyConstant(); + + /// isDeclaration - Return true if the primary definition of this global + /// value is outside of the current translation unit... + virtual bool isDeclaration() const = 0; + + /// getParent - Get the module that this global value is contained inside + /// of... + inline Module *getParent() { return Parent; } + inline const Module *getParent() const { return Parent; } + + /// removeDeadConstantUsers - If there are any dead constant users dangling + /// off of this global value, remove them. This method is useful for clients + /// that want to check to see if a global is unused, but don't want to deal + /// with potentially dead constants hanging off of the globals. + void removeDeadConstantUsers(); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const GlobalValue *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::FunctionVal || + V->getValueID() == Value::GlobalVariableVal || + V->getValueID() == Value::GlobalAliasVal; + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/GlobalVariable.h b/include/llvm/GlobalVariable.h new file mode 100644 index 0000000..00d4acb --- /dev/null +++ b/include/llvm/GlobalVariable.h @@ -0,0 +1,139 @@ +//===-- llvm/GlobalVariable.h - GlobalVariable class ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the GlobalVariable class, which +// represents a single global variable (or constant) in the VM. +// +// Global variables are constant pointers that refer to hunks of space that are +// allocated by either the VM, or by the linker in a static compiler. A global +// variable may have an intial value, which is copied into the executables .data +// area. Global Constants are required to have initializers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_GLOBAL_VARIABLE_H +#define LLVM_GLOBAL_VARIABLE_H + +#include "llvm/GlobalValue.h" + +namespace llvm { + +class Module; +class Constant; +class PointerType; +template<typename ValueSubClass, typename ItemParentClass> + class SymbolTableListTraits; + +class GlobalVariable : public GlobalValue { + friend class SymbolTableListTraits<GlobalVariable, Module>; + void operator=(const GlobalVariable &); // Do not implement + GlobalVariable(const GlobalVariable &); // Do not implement + + void setParent(Module *parent); + + GlobalVariable *Prev, *Next; + void setNext(GlobalVariable *N) { Next = N; } + void setPrev(GlobalVariable *N) { Prev = N; } + + bool isConstantGlobal : 1; // Is this a global constant? + bool isThreadLocalSymbol : 1; // Is this symbol "Thread Local"? + Use Initializer; + +public: + /// GlobalVariable ctor - If a parent module is specified, the global is + /// automatically inserted into the end of the specified modules global list. + GlobalVariable(const Type *Ty, bool isConstant, LinkageTypes Linkage, + Constant *Initializer = 0, const std::string &Name = "", + Module *Parent = 0, bool ThreadLocal = false); + /// GlobalVariable ctor - This creates a global and inserts it before the + /// specified other global. + GlobalVariable(const Type *Ty, bool isConstant, LinkageTypes Linkage, + Constant *Initializer, const std::string &Name, + GlobalVariable *InsertBefore, bool ThreadLocal = false); + + /// isDeclaration - Is this global variable lacking an initializer? If so, + /// the global variable is defined in some other translation unit, and is thus + /// only a declaration here. + virtual bool isDeclaration() const { return getNumOperands() == 0; } + + /// hasInitializer - Unless a global variable isExternal(), it has an + /// initializer. The initializer for the global variable/constant is held by + /// Initializer if an initializer is specified. + /// + inline bool hasInitializer() const { return !isDeclaration(); } + + /// getInitializer - Return the initializer for this global variable. It is + /// illegal to call this method if the global is external, because we cannot + /// tell what the value is initialized to! + /// + inline Constant *getInitializer() const { + assert(hasInitializer() && "GV doesn't have initializer!"); + return reinterpret_cast<Constant*>(Initializer.get()); + } + inline Constant *getInitializer() { + assert(hasInitializer() && "GV doesn't have initializer!"); + return reinterpret_cast<Constant*>(Initializer.get()); + } + inline void setInitializer(Constant *CPV) { + if (CPV == 0) { + if (hasInitializer()) { + Initializer.set(0); + NumOperands = 0; + } + } else { + if (!hasInitializer()) + NumOperands = 1; + Initializer.set(CPV); + } + } + + /// If the value is a global constant, its value is immutable throughout the + /// runtime execution of the program. Assigning a value into the constant + /// leads to undefined behavior. + /// + bool isConstant() const { return isConstantGlobal; } + void setConstant(bool Value) { isConstantGlobal = Value; } + + /// If the value is "Thread Local", its value isn't shared by the threads. + bool isThreadLocal() const { return isThreadLocalSymbol; } + void setThreadLocal(bool Value) { isThreadLocalSymbol = Value; } + + /// removeFromParent - This method unlinks 'this' from the containing module, + /// but does not delete it. + /// + void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing module + /// and deletes it. + /// + void eraseFromParent(); + + /// Override Constant's implementation of this method so we can + /// replace constant initializers. + virtual void replaceUsesOfWithOnConstant(Value *From, Value *To, Use *U); + + virtual void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const GlobalVariable *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::GlobalVariableVal; + } +private: + // getNext/Prev - Return the next or previous global variable in the list. + GlobalVariable *getNext() { return Next; } + const GlobalVariable *getNext() const { return Next; } + GlobalVariable *getPrev() { return Prev; } + const GlobalVariable *getPrev() const { return Prev; } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/InlineAsm.h b/include/llvm/InlineAsm.h new file mode 100644 index 0000000..20c184ac --- /dev/null +++ b/include/llvm/InlineAsm.h @@ -0,0 +1,138 @@ +//===-- llvm/InlineAsm.h - Class to represent inline asm strings-*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class represents the inline asm strings, which are Value*'s that are +// used as the callee operand of call instructions. InlineAsm's are uniqued +// like constants, and created via InlineAsm::get(...). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INLINEASM_H +#define LLVM_INLINEASM_H + +#include "llvm/Value.h" +#include "llvm/System/IncludeFile.h" +#include <vector> + +namespace llvm { + +struct AssemblyAnnotationWriter; +class PointerType; +class FunctionType; +class Module; + +class InlineAsm : public Value { + InlineAsm(const InlineAsm &); // do not implement + void operator=(const InlineAsm&); // do not implement + + std::string AsmString, Constraints; + bool HasSideEffects; + + InlineAsm(const FunctionType *Ty, const std::string &AsmString, + const std::string &Constraints, bool hasSideEffects); + virtual ~InlineAsm(); +public: + + /// InlineAsm::get - Return the the specified uniqued inline asm string. + /// + static InlineAsm *get(const FunctionType *Ty, const std::string &AsmString, + const std::string &Constraints, bool hasSideEffects); + + bool hasSideEffects() const { return HasSideEffects; } + + /// getType - InlineAsm's are always pointers. + /// + const PointerType *getType() const { + return reinterpret_cast<const PointerType*>(Value::getType()); + } + + /// getFunctionType - InlineAsm's are always pointers to functions. + /// + const FunctionType *getFunctionType() const; + + const std::string &getAsmString() const { return AsmString; } + const std::string &getConstraintString() const { return Constraints; } + + virtual void print(std::ostream &O) const { print(O, 0); } + void print(std::ostream *O) const { if (O) print(*O); } + void print(std::ostream &OS, AssemblyAnnotationWriter *AAW) const; + + /// Verify - This static method can be used by the parser to check to see if + /// the specified constraint string is legal for the type. This returns true + /// if legal, false if not. + /// + static bool Verify(const FunctionType *Ty, const std::string &Constraints); + + // Constraint String Parsing + enum ConstraintPrefix { + isInput, // 'x' + isOutput, // '=x' + isClobber // '~x' + }; + + struct ConstraintInfo { + /// Type - The basic type of the constraint: input/output/clobber + /// + ConstraintPrefix Type; + + /// isEarlyClobber - "&": output operand writes result before inputs are all + /// read. This is only ever set for an output operand. + bool isEarlyClobber; + + /// hasMatchingInput - This is set to true for an output constraint iff + /// there is an input constraint that is required to match it (e.g. "0"). + bool hasMatchingInput; + + /// isCommutative - This is set to true for a constraint that is commutative + /// with the next operand. + bool isCommutative; + + /// isIndirect - True if this operand is an indirect operand. This means + /// that the address of the source or destination is present in the call + /// instruction, instead of it being returned or passed in explicitly. This + /// is represented with a '*' in the asm string. + bool isIndirect; + + /// Code - The constraint code, either the register name (in braces) or the + /// constraint letter/number. + std::vector<std::string> Codes; + + /// Parse - Analyze the specified string (e.g. "=*&{eax}") and fill in the + /// fields in this structure. If the constraint string is not understood, + /// return true, otherwise return false. + bool Parse(const std::string &Str, + std::vector<InlineAsm::ConstraintInfo> &ConstraintsSoFar); + }; + + /// ParseConstraints - Split up the constraint string into the specific + /// constraints and their prefixes. If this returns an empty vector, and if + /// the constraint string itself isn't empty, there was an error parsing. + static std::vector<ConstraintInfo> + ParseConstraints(const std::string &ConstraintString); + + /// ParseConstraints - Parse the constraints of this inlineasm object, + /// returning them the same way that ParseConstraints(str) does. + std::vector<ConstraintInfo> + ParseConstraints() const { + return ParseConstraints(Constraints); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const InlineAsm *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() == Value::InlineAsmVal; + } +}; + +} // End llvm namespace + +// Make sure the InlineAsm.cpp file is linked when this one is #included. +FORCE_DEFINING_FILE_TO_BE_LINKED(InlineAsm) + +#endif diff --git a/include/llvm/InstrTypes.h b/include/llvm/InstrTypes.h new file mode 100644 index 0000000..d96b20f --- /dev/null +++ b/include/llvm/InstrTypes.h @@ -0,0 +1,569 @@ +//===-- llvm/InstrTypes.h - Important Instruction subclasses ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines various meta classes of instructions that exist in the VM +// representation. Specific concrete subclasses of these may be found in the +// i*.h files... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INSTRUCTION_TYPES_H +#define LLVM_INSTRUCTION_TYPES_H + +#include "llvm/Instruction.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +// TerminatorInst Class +//===----------------------------------------------------------------------===// + +/// TerminatorInst - Subclasses of this class are all able to terminate a basic +/// block. Thus, these are all the flow control type of operations. +/// +class TerminatorInst : public Instruction { +protected: + TerminatorInst(const Type *Ty, Instruction::TermOps iType, + Use *Ops, unsigned NumOps, + Instruction *InsertBefore = 0) + : Instruction(Ty, iType, Ops, NumOps, InsertBefore) {} + + TerminatorInst(const Type *Ty, Instruction::TermOps iType, + Use *Ops, unsigned NumOps, BasicBlock *InsertAtEnd) + : Instruction(Ty, iType, Ops, NumOps, InsertAtEnd) {} + + // Out of line virtual method, so the vtable, etc has a home. + ~TerminatorInst(); + + /// Virtual methods - Terminators should overload these and provide inline + /// overrides of non-V methods. + virtual BasicBlock *getSuccessorV(unsigned idx) const = 0; + virtual unsigned getNumSuccessorsV() const = 0; + virtual void setSuccessorV(unsigned idx, BasicBlock *B) = 0; +public: + + virtual Instruction *clone() const = 0; + + /// getNumSuccessors - Return the number of successors that this terminator + /// has. + unsigned getNumSuccessors() const { + return getNumSuccessorsV(); + } + + /// getSuccessor - Return the specified successor. + /// + BasicBlock *getSuccessor(unsigned idx) const { + return getSuccessorV(idx); + } + + /// setSuccessor - Update the specified successor to point at the provided + /// block. + void setSuccessor(unsigned idx, BasicBlock *B) { + setSuccessorV(idx, B); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const TerminatorInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() >= TermOpsBegin && I->getOpcode() < TermOpsEnd; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// UnaryInstruction Class +//===----------------------------------------------------------------------===// + +class UnaryInstruction : public Instruction { + Use Op; +protected: + UnaryInstruction(const Type *Ty, unsigned iType, Value *V, Instruction *IB =0) + : Instruction(Ty, iType, &Op, 1, IB), Op(V, this) { + } + UnaryInstruction(const Type *Ty, unsigned iType, Value *V, BasicBlock *IAE) + : Instruction(Ty, iType, &Op, 1, IAE), Op(V, this) { + } +public: + // Out of line virtual method, so the vtable, etc has a home. + ~UnaryInstruction(); + + // Transparently provide more efficient getOperand methods. + Value *getOperand(unsigned i) const { + assert(i == 0 && "getOperand() out of range!"); + return Op; + } + void setOperand(unsigned i, Value *Val) { + assert(i == 0 && "setOperand() out of range!"); + Op = Val; + } + unsigned getNumOperands() const { return 1; } +}; + +//===----------------------------------------------------------------------===// +// BinaryOperator Class +//===----------------------------------------------------------------------===// + +class BinaryOperator : public Instruction { + Use Ops[2]; +protected: + void init(BinaryOps iType); + BinaryOperator(BinaryOps iType, Value *S1, Value *S2, const Type *Ty, + const std::string &Name, Instruction *InsertBefore); + BinaryOperator(BinaryOps iType, Value *S1, Value *S2, const Type *Ty, + const std::string &Name, BasicBlock *InsertAtEnd); +public: + + /// Transparently provide more efficient getOperand methods. + Value *getOperand(unsigned i) const { + assert(i < 2 && "getOperand() out of range!"); + return Ops[i]; + } + void setOperand(unsigned i, Value *Val) { + assert(i < 2 && "setOperand() out of range!"); + Ops[i] = Val; + } + unsigned getNumOperands() const { return 2; } + + /// create() - Construct a binary instruction, given the opcode and the two + /// operands. Optionally (if InstBefore is specified) insert the instruction + /// into a BasicBlock right before the specified instruction. The specified + /// Instruction is allowed to be a dereferenced end iterator. + /// + static BinaryOperator *create(BinaryOps Op, Value *S1, Value *S2, + const std::string &Name = "", + Instruction *InsertBefore = 0); + + /// create() - Construct a binary instruction, given the opcode and the two + /// operands. Also automatically insert this instruction to the end of the + /// BasicBlock specified. + /// + static BinaryOperator *create(BinaryOps Op, Value *S1, Value *S2, + const std::string &Name, + BasicBlock *InsertAtEnd); + + /// create* - These methods just forward to create, and are useful when you + /// statically know what type of instruction you're going to create. These + /// helpers just save some typing. +#define HANDLE_BINARY_INST(N, OPC, CLASS) \ + static BinaryOperator *create##OPC(Value *V1, Value *V2, \ + const std::string &Name = "") {\ + return create(Instruction::OPC, V1, V2, Name);\ + } +#include "llvm/Instruction.def" +#define HANDLE_BINARY_INST(N, OPC, CLASS) \ + static BinaryOperator *create##OPC(Value *V1, Value *V2, \ + const std::string &Name, BasicBlock *BB) {\ + return create(Instruction::OPC, V1, V2, Name, BB);\ + } +#include "llvm/Instruction.def" +#define HANDLE_BINARY_INST(N, OPC, CLASS) \ + static BinaryOperator *create##OPC(Value *V1, Value *V2, \ + const std::string &Name, Instruction *I) {\ + return create(Instruction::OPC, V1, V2, Name, I);\ + } +#include "llvm/Instruction.def" + + + /// Helper functions to construct and inspect unary operations (NEG and NOT) + /// via binary operators SUB and XOR: + /// + /// createNeg, createNot - Create the NEG and NOT + /// instructions out of SUB and XOR instructions. + /// + static BinaryOperator *createNeg(Value *Op, const std::string &Name = "", + Instruction *InsertBefore = 0); + static BinaryOperator *createNeg(Value *Op, const std::string &Name, + BasicBlock *InsertAtEnd); + static BinaryOperator *createNot(Value *Op, const std::string &Name = "", + Instruction *InsertBefore = 0); + static BinaryOperator *createNot(Value *Op, const std::string &Name, + BasicBlock *InsertAtEnd); + + /// isNeg, isNot - Check if the given Value is a NEG or NOT instruction. + /// + static bool isNeg(const Value *V); + static bool isNot(const Value *V); + + /// getNegArgument, getNotArgument - Helper functions to extract the + /// unary argument of a NEG or NOT operation implemented via Sub or Xor. + /// + static const Value *getNegArgument(const Value *BinOp); + static Value *getNegArgument( Value *BinOp); + static const Value *getNotArgument(const Value *BinOp); + static Value *getNotArgument( Value *BinOp); + + BinaryOps getOpcode() const { + return static_cast<BinaryOps>(Instruction::getOpcode()); + } + + virtual BinaryOperator *clone() const; + + /// swapOperands - Exchange the two operands to this instruction. + /// This instruction is safe to use on any binary instruction and + /// does not modify the semantics of the instruction. If the + /// instruction is order dependent (SetLT f.e.) the opcode is + /// changed. If the instruction cannot be reversed (ie, it's a Div), + /// then return true. + /// + bool swapOperands(); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BinaryOperator *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() >= BinaryOpsBegin && I->getOpcode() < BinaryOpsEnd; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// CastInst Class +//===----------------------------------------------------------------------===// + +/// CastInst - This is the base class for all instructions that perform data +/// casts. It is simply provided so that instruction category testing +/// can be performed with code like: +/// +/// if (isa<CastInst>(Instr)) { ... } +/// @brief Base class of casting instructions. +class CastInst : public UnaryInstruction { + /// @brief Copy constructor + CastInst(const CastInst &CI) + : UnaryInstruction(CI.getType(), CI.getOpcode(), CI.getOperand(0)) { + } + /// @brief Do not allow default construction + CastInst(); +protected: + /// @brief Constructor with insert-before-instruction semantics for subclasses + CastInst(const Type *Ty, unsigned iType, Value *S, + const std::string &Name = "", Instruction *InsertBefore = 0) + : UnaryInstruction(Ty, iType, S, InsertBefore) { + setName(Name); + } + /// @brief Constructor with insert-at-end-of-block semantics for subclasses + CastInst(const Type *Ty, unsigned iType, Value *S, + const std::string &Name, BasicBlock *InsertAtEnd) + : UnaryInstruction(Ty, iType, S, InsertAtEnd) { + setName(Name); + } +public: + /// Provides a way to construct any of the CastInst subclasses using an + /// opcode instead of the subclass's constructor. The opcode must be in the + /// CastOps category (Instruction::isCast(opcode) returns true). This + /// constructor has insert-before-instruction semantics to automatically + /// insert the new CastInst before InsertBefore (if it is non-null). + /// @brief Construct any of the CastInst subclasses + static CastInst *create( + Instruction::CastOps, ///< The opcode of the cast instruction + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which cast should be made + const std::string &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + /// Provides a way to construct any of the CastInst subclasses using an + /// opcode instead of the subclass's constructor. The opcode must be in the + /// CastOps category. This constructor has insert-at-end-of-block semantics + /// to automatically insert the new CastInst at the end of InsertAtEnd (if + /// its non-null). + /// @brief Construct any of the CastInst subclasses + static CastInst *create( + Instruction::CastOps, ///< The opcode for the cast instruction + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which operand is casted + const std::string &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a ZExt or BitCast cast instruction + static CastInst *createZExtOrBitCast( + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which cast should be made + const std::string &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a ZExt or BitCast cast instruction + static CastInst *createZExtOrBitCast( + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which operand is casted + const std::string &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a SExt or BitCast cast instruction + static CastInst *createSExtOrBitCast( + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which cast should be made + const std::string &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a BitCast or a PtrToInt cast instruction + static CastInst *createPointerCast( + Value *S, ///< The pointer value to be casted (operand 0) + const Type *Ty, ///< The type to which operand is casted + const std::string &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a BitCast or a PtrToInt cast instruction + static CastInst *createPointerCast( + Value *S, ///< The pointer value to be casted (operand 0) + const Type *Ty, ///< The type to which cast should be made + const std::string &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. + static CastInst *createIntegerCast( + Value *S, ///< The pointer value to be casted (operand 0) + const Type *Ty, ///< The type to which cast should be made + bool isSigned, ///< Whether to regard S as signed or not + const std::string &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a ZExt, BitCast, or Trunc for int -> int casts. + static CastInst *createIntegerCast( + Value *S, ///< The integer value to be casted (operand 0) + const Type *Ty, ///< The integer type to which operand is casted + bool isSigned, ///< Whether to regard S as signed or not + const std::string &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create an FPExt, BitCast, or FPTrunc for fp -> fp casts + static CastInst *createFPCast( + Value *S, ///< The floating point value to be casted + const Type *Ty, ///< The floating point type to cast to + const std::string &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create an FPExt, BitCast, or FPTrunc for fp -> fp casts + static CastInst *createFPCast( + Value *S, ///< The floating point value to be casted + const Type *Ty, ///< The floating point type to cast to + const std::string &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a SExt or BitCast cast instruction + static CastInst *createSExtOrBitCast( + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which operand is casted + const std::string &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Create a Trunc or BitCast cast instruction + static CastInst *createTruncOrBitCast( + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which cast should be made + const std::string &Name = "", ///< Name for the instruction + Instruction *InsertBefore = 0 ///< Place to insert the instruction + ); + + /// @brief Create a Trunc or BitCast cast instruction + static CastInst *createTruncOrBitCast( + Value *S, ///< The value to be casted (operand 0) + const Type *Ty, ///< The type to which operand is casted + const std::string &Name, ///< The name for the instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// Returns the opcode necessary to cast Val into Ty using usual casting + /// rules. + /// @brief Infer the opcode for cast operand and type + static Instruction::CastOps getCastOpcode( + const Value *Val, ///< The value to cast + bool SrcIsSigned, ///< Whether to treat the source as signed + const Type *Ty, ///< The Type to which the value should be casted + bool DstIsSigned ///< Whether to treate the dest. as signed + ); + + /// There are several places where we need to know if a cast instruction + /// only deals with integer source and destination types. To simplify that + /// logic, this method is provided. + /// @returns true iff the cast has only integral typed operand and dest type. + /// @brief Determine if this is an integer-only cast. + bool isIntegerCast() const; + + /// A lossless cast is one that does not alter the basic value. It implies + /// a no-op cast but is more stringent, preventing things like int->float, + /// long->double, int->ptr, or vector->anything. + /// @returns true iff the cast is lossless. + /// @brief Determine if this is a lossless cast. + bool isLosslessCast() const; + + /// A no-op cast is one that can be effected without changing any bits. + /// It implies that the source and destination types are the same size. The + /// IntPtrTy argument is used to make accurate determinations for casts + /// involving Integer and Pointer types. They are no-op casts if the integer + /// is the same size as the pointer. However, pointer size varies with + /// platform. Generally, the result of TargetData::getIntPtrType() should be + /// passed in. If that's not available, use Type::Int64Ty, which will make + /// the isNoopCast call conservative. + /// @brief Determine if this cast is a no-op cast. + bool isNoopCast( + const Type *IntPtrTy ///< Integer type corresponding to pointer + ) const; + + /// Determine how a pair of casts can be eliminated, if they can be at all. + /// This is a helper function for both CastInst and ConstantExpr. + /// @returns 0 if the CastInst pair can't be eliminated + /// @returns Instruction::CastOps value for a cast that can replace + /// the pair, casting SrcTy to DstTy. + /// @brief Determine if a cast pair is eliminable + static unsigned isEliminableCastPair( + Instruction::CastOps firstOpcode, ///< Opcode of first cast + Instruction::CastOps secondOpcode, ///< Opcode of second cast + const Type *SrcTy, ///< SrcTy of 1st cast + const Type *MidTy, ///< DstTy of 1st cast & SrcTy of 2nd cast + const Type *DstTy, ///< DstTy of 2nd cast + const Type *IntPtrTy ///< Integer type corresponding to Ptr types + ); + + /// @brief Return the opcode of this CastInst + Instruction::CastOps getOpcode() const { + return Instruction::CastOps(Instruction::getOpcode()); + } + + /// @brief Return the source type, as a convenience + const Type* getSrcTy() const { return getOperand(0)->getType(); } + /// @brief Return the destination type, as a convenience + const Type* getDestTy() const { return getType(); } + + /// This method can be used to determine if a cast from S to DstTy using + /// Opcode op is valid or not. + /// @returns true iff the proposed cast is valid. + /// @brief Determine if a cast is valid without creating one. + static bool castIsValid(Instruction::CastOps op, Value *S, const Type *DstTy); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const CastInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() >= CastOpsBegin && I->getOpcode() < CastOpsEnd; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// CmpInst Class +//===----------------------------------------------------------------------===// + +/// This class is the base class for the comparison instructions. +/// @brief Abstract base class of comparison instructions. +class CmpInst: public Instruction { + CmpInst(); // do not implement +protected: + CmpInst(Instruction::OtherOps op, unsigned short pred, Value *LHS, Value *RHS, + const std::string &Name = "", Instruction *InsertBefore = 0); + + CmpInst(Instruction::OtherOps op, unsigned short pred, Value *LHS, Value *RHS, + const std::string &Name, BasicBlock *InsertAtEnd); + + Use Ops[2]; // CmpInst instructions always have 2 operands, optimize + +public: + /// Construct a compare instruction, given the opcode, the predicate and + /// the two operands. Optionally (if InstBefore is specified) insert the + /// instruction into a BasicBlock right before the specified instruction. + /// The specified Instruction is allowed to be a dereferenced end iterator. + /// @brief Create a CmpInst + static CmpInst *create(OtherOps Op, unsigned short predicate, Value *S1, + Value *S2, const std::string &Name = "", + Instruction *InsertBefore = 0); + + /// Construct a compare instruction, given the opcode, the predicate and the + /// two operands. Also automatically insert this instruction to the end of + /// the BasicBlock specified. + /// @brief Create a CmpInst + static CmpInst *create(OtherOps Op, unsigned short predicate, Value *S1, + Value *S2, const std::string &Name, + BasicBlock *InsertAtEnd); + + /// @brief Implement superclass method. + virtual CmpInst *clone() const; + + /// @brief Get the opcode casted to the right type + OtherOps getOpcode() const { + return static_cast<OtherOps>(Instruction::getOpcode()); + } + + /// The predicate for CmpInst is defined by the subclasses but stored in + /// the SubclassData field (see Value.h). We allow it to be fetched here + /// as the predicate but there is no enum type for it, just the raw unsigned + /// short. This facilitates comparison of CmpInst instances without delving + /// into the subclasses since predicate values are distinct between the + /// CmpInst subclasses. + /// @brief Return the predicate for this instruction. + unsigned short getPredicate() const { + return SubclassData; + } + + /// @brief Provide more efficient getOperand methods. + Value *getOperand(unsigned i) const { + assert(i < 2 && "getOperand() out of range!"); + return Ops[i]; + } + void setOperand(unsigned i, Value *Val) { + assert(i < 2 && "setOperand() out of range!"); + Ops[i] = Val; + } + + /// @brief CmpInst instructions always have 2 operands. + unsigned getNumOperands() const { return 2; } + + /// This is just a convenience that dispatches to the subclasses. + /// @brief Swap the operands and adjust predicate accordingly to retain + /// the same comparison. + void swapOperands(); + + /// This is just a convenience that dispatches to the subclasses. + /// @brief Determine if this CmpInst is commutative. + bool isCommutative(); + + /// This is just a convenience that dispatches to the subclasses. + /// @brief Determine if this is an equals/not equals predicate. + bool isEquality(); + + /// @returns true if the predicate is unsigned, false otherwise. + /// @brief Determine if the predicate is an unsigned operation. + static bool isUnsigned(unsigned short predicate); + + /// @returns true if the predicate is signed, false otherwise. + /// @brief Determine if the predicate is an signed operation. + static bool isSigned(unsigned short predicate); + + /// @brief Determine if the predicate is an ordered operation. + static bool isOrdered(unsigned short predicate); + + /// @brief Determine if the predicate is an unordered operation. + static bool isUnordered(unsigned short predicate); + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const CmpInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ICmp || + I->getOpcode() == Instruction::FCmp; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Instruction.def b/include/llvm/Instruction.def new file mode 100644 index 0000000..41540c2 --- /dev/null +++ b/include/llvm/Instruction.def @@ -0,0 +1,191 @@ +//===-- llvm/Instruction.def - File that describes Instructions -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains descriptions of the various LLVM instructions. This is +// used as a central place for enumerating the different instructions and +// should eventually be the place to put comments about the instructions. +// +//===----------------------------------------------------------------------===// + +// NOTE: NO INCLUDE GUARD DESIRED! + +// Provide definitions of macros so that users of this file do not have to +// define everything to use it... +// +#ifndef FIRST_TERM_INST +#define FIRST_TERM_INST(num) +#endif +#ifndef HANDLE_TERM_INST +#ifndef HANDLE_INST +#define HANDLE_TERM_INST(num, opcode, Class) +#else +#define HANDLE_TERM_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_TERM_INST +#define LAST_TERM_INST(num) +#endif + +#ifndef FIRST_BINARY_INST +#define FIRST_BINARY_INST(num) +#endif +#ifndef HANDLE_BINARY_INST +#ifndef HANDLE_INST +#define HANDLE_BINARY_INST(num, opcode, instclass) +#else +#define HANDLE_BINARY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_BINARY_INST +#define LAST_BINARY_INST(num) +#endif + +#ifndef FIRST_MEMORY_INST +#define FIRST_MEMORY_INST(num) +#endif +#ifndef HANDLE_MEMORY_INST +#ifndef HANDLE_INST +#define HANDLE_MEMORY_INST(num, opcode, Class) +#else +#define HANDLE_MEMORY_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_MEMORY_INST +#define LAST_MEMORY_INST(num) +#endif + +#ifndef FIRST_CAST_INST +#define FIRST_CAST_INST(num) +#endif +#ifndef HANDLE_CAST_INST +#ifndef HANDLE_INST +#define HANDLE_CAST_INST(num, opcode, Class) +#else +#define HANDLE_CAST_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_CAST_INST +#define LAST_CAST_INST(num) +#endif + +#ifndef FIRST_OTHER_INST +#define FIRST_OTHER_INST(num) +#endif +#ifndef HANDLE_OTHER_INST +#ifndef HANDLE_INST +#define HANDLE_OTHER_INST(num, opcode, Class) +#else +#define HANDLE_OTHER_INST(num, opcode, Class) HANDLE_INST(num, opcode, Class) +#endif +#endif +#ifndef LAST_OTHER_INST +#define LAST_OTHER_INST(num) +#endif + + +// Terminator Instructions - These instructions are used to terminate a basic +// block of the program. Every basic block must end with one of these +// instructions for it to be a well formed basic block. +// + FIRST_TERM_INST ( 1) +HANDLE_TERM_INST ( 1, Ret , ReturnInst) +HANDLE_TERM_INST ( 2, Br , BranchInst) +HANDLE_TERM_INST ( 3, Switch , SwitchInst) +HANDLE_TERM_INST ( 4, Invoke , InvokeInst) +HANDLE_TERM_INST ( 5, Unwind , UnwindInst) +HANDLE_TERM_INST ( 6, Unreachable, UnreachableInst) + LAST_TERM_INST ( 6) + +// Standard binary operators... + FIRST_BINARY_INST( 7) +HANDLE_BINARY_INST( 7, Add , BinaryOperator) +HANDLE_BINARY_INST( 8, Sub , BinaryOperator) +HANDLE_BINARY_INST( 9, Mul , BinaryOperator) +HANDLE_BINARY_INST(10, UDiv , BinaryOperator) +HANDLE_BINARY_INST(11, SDiv , BinaryOperator) +HANDLE_BINARY_INST(12, FDiv , BinaryOperator) +HANDLE_BINARY_INST(13, URem , BinaryOperator) +HANDLE_BINARY_INST(14, SRem , BinaryOperator) +HANDLE_BINARY_INST(15, FRem , BinaryOperator) + +// Logical operators (integer operands) +HANDLE_BINARY_INST(16, Shl , BinaryOperator) // Shift left (logical) +HANDLE_BINARY_INST(17, LShr , BinaryOperator) // Shift right (logical) +HANDLE_BINARY_INST(18, AShr , BinaryOperator) // shift right (arithmetic) +HANDLE_BINARY_INST(19, And , BinaryOperator) +HANDLE_BINARY_INST(20, Or , BinaryOperator) +HANDLE_BINARY_INST(21, Xor , BinaryOperator) + LAST_BINARY_INST(21) + +// Memory operators... + FIRST_MEMORY_INST(22) +HANDLE_MEMORY_INST(22, Malloc, MallocInst) // Heap management instructions +HANDLE_MEMORY_INST(23, Free , FreeInst ) +HANDLE_MEMORY_INST(24, Alloca, AllocaInst) // Stack management +HANDLE_MEMORY_INST(25, Load , LoadInst ) // Memory manipulation instrs +HANDLE_MEMORY_INST(26, Store , StoreInst ) +HANDLE_MEMORY_INST(27, GetElementPtr, GetElementPtrInst) + LAST_MEMORY_INST(27) + +// Cast operators ... +// NOTE: The order matters here because CastInst::isEliminableCastPair +// NOTE: (see Instructions.cpp) encodes a table based on this ordering. + FIRST_CAST_INST(28) +HANDLE_CAST_INST(28, Trunc , TruncInst ) // Truncate integers +HANDLE_CAST_INST(29, ZExt , ZExtInst ) // Zero extend integers +HANDLE_CAST_INST(30, SExt , SExtInst ) // Sign extend integers +HANDLE_CAST_INST(31, FPToUI , FPToUIInst ) // floating point -> UInt +HANDLE_CAST_INST(32, FPToSI , FPToSIInst ) // floating point -> SInt +HANDLE_CAST_INST(33, UIToFP , UIToFPInst ) // UInt -> floating point +HANDLE_CAST_INST(34, SIToFP , SIToFPInst ) // SInt -> floating point +HANDLE_CAST_INST(35, FPTrunc , FPTruncInst ) // Truncate floating point +HANDLE_CAST_INST(36, FPExt , FPExtInst ) // Extend floating point +HANDLE_CAST_INST(37, PtrToInt, PtrToIntInst) // Pointer -> Integer +HANDLE_CAST_INST(38, IntToPtr, IntToPtrInst) // Integer -> Pointer +HANDLE_CAST_INST(39, BitCast , BitCastInst ) // Type cast + LAST_CAST_INST(39) + +// Other operators... + FIRST_OTHER_INST(40) +HANDLE_OTHER_INST(40, ICmp , ICmpInst ) // Integer comparison instruction +HANDLE_OTHER_INST(41, FCmp , FCmpInst ) // Floating point comparison instr. +HANDLE_OTHER_INST(42, PHI , PHINode ) // PHI node instruction +HANDLE_OTHER_INST(43, Call , CallInst ) // Call a function +HANDLE_OTHER_INST(44, Select , SelectInst ) // select instruction +HANDLE_OTHER_INST(45, UserOp1, Instruction) // May be used internally in a pass +HANDLE_OTHER_INST(46, UserOp2, Instruction) // Internal to passes only +HANDLE_OTHER_INST(47, VAArg , VAArgInst ) // vaarg instruction +HANDLE_OTHER_INST(48, ExtractElement, ExtractElementInst)// extract from vector. +HANDLE_OTHER_INST(49, InsertElement, InsertElementInst) // insert into vector +HANDLE_OTHER_INST(50, ShuffleVector, ShuffleVectorInst) // shuffle two vectors. + LAST_OTHER_INST(50) + +#undef FIRST_TERM_INST +#undef HANDLE_TERM_INST +#undef LAST_TERM_INST + +#undef FIRST_BINARY_INST +#undef HANDLE_BINARY_INST +#undef LAST_BINARY_INST + +#undef FIRST_MEMORY_INST +#undef HANDLE_MEMORY_INST +#undef LAST_MEMORY_INST + +#undef FIRST_CAST_INST +#undef HANDLE_CAST_INST +#undef LAST_CAST_INST + +#undef FIRST_OTHER_INST +#undef HANDLE_OTHER_INST +#undef LAST_OTHER_INST + +#ifdef HANDLE_INST +#undef HANDLE_INST +#endif diff --git a/include/llvm/Instruction.h b/include/llvm/Instruction.h new file mode 100644 index 0000000..8da89e2 --- /dev/null +++ b/include/llvm/Instruction.h @@ -0,0 +1,239 @@ +//===-- llvm/Instruction.h - Instruction class definition -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the Instruction class, which is the +// base class for all of the LLVM instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INSTRUCTION_H +#define LLVM_INSTRUCTION_H + +#include "llvm/User.h" + +namespace llvm { + +struct AssemblyAnnotationWriter; +class BinaryOperator; + +template<typename ValueSubClass, typename ItemParentClass> + class SymbolTableListTraits; + +class Instruction : public User { + void operator=(const Instruction &); // Do not implement + Instruction(const Instruction &); // Do not implement + + BasicBlock *Parent; + Instruction *Prev, *Next; // Next and Prev links for our intrusive linked list + + void setNext(Instruction *N) { Next = N; } + void setPrev(Instruction *N) { Prev = N; } + + friend class SymbolTableListTraits<Instruction, BasicBlock>; + void setParent(BasicBlock *P); +protected: + Instruction(const Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, + Instruction *InsertBefore = 0); + Instruction(const Type *Ty, unsigned iType, Use *Ops, unsigned NumOps, + BasicBlock *InsertAtEnd); +public: + // Out of line virtual method, so the vtable, etc has a home. + ~Instruction(); + + /// mayWriteToMemory - Return true if this instruction may modify memory. + /// + bool mayWriteToMemory() const; + + /// clone() - Create a copy of 'this' instruction that is identical in all + /// ways except the following: + /// * The instruction has no parent + /// * The instruction has no name + /// + virtual Instruction *clone() const = 0; + + /// isIdenticalTo - Return true if the specified instruction is exactly + /// identical to the current one. This means that all operands match and any + /// extra information (e.g. load is volatile) agree. + bool isIdenticalTo(Instruction *I) const; + + /// This function determines if the specified instruction executes the same + /// operation as the current one. This means that the opcodes, type, operand + /// types and any other factors affecting the operation must be the same. This + /// is similar to isIdenticalTo except the operands themselves don't have to + /// be identical. + /// @returns true if the specified instruction is the same operation as + /// the current one. + /// @brief Determine if one instruction is the same operation as another. + bool isSameOperationAs(Instruction *I) const; + + /// use_back - Specialize the methods defined in Value, as we know that an + /// instruction can only be used by other instructions. + Instruction *use_back() { return cast<Instruction>(*use_begin());} + const Instruction *use_back() const { return cast<Instruction>(*use_begin());} + + // Accessor methods... + // + inline const BasicBlock *getParent() const { return Parent; } + inline BasicBlock *getParent() { return Parent; } + + /// removeFromParent - This method unlinks 'this' from the containing basic + /// block, but does not delete it. + /// + void removeFromParent(); + + /// eraseFromParent - This method unlinks 'this' from the containing basic + /// block and deletes it. + /// + void eraseFromParent(); + + /// moveBefore - Unlink this instruction from its current basic block and + /// insert it into the basic block that MovePos lives in, right before + /// MovePos. + void moveBefore(Instruction *MovePos); + + // --------------------------------------------------------------------------- + /// Subclass classification... getOpcode() returns a member of + /// one of the enums that is coming soon (down below)... + /// + unsigned getOpcode() const { return getValueID() - InstructionVal; } + const char *getOpcodeName() const { + return getOpcodeName(getOpcode()); + } + static const char* getOpcodeName(unsigned OpCode); + + static inline bool isTerminator(unsigned OpCode) { + return OpCode >= TermOpsBegin && OpCode < TermOpsEnd; + } + + inline bool isTerminator() const { // Instance of TerminatorInst? + return isTerminator(getOpcode()); + } + + inline bool isBinaryOp() const { + return getOpcode() >= BinaryOpsBegin && getOpcode() < BinaryOpsEnd; + } + + /// @brief Determine if the Opcode is one of the shift instructions. + static inline bool isShift(unsigned Opcode) { + return Opcode >= Shl && Opcode <= AShr; + } + + /// @brief Determine if the instruction's opcode is one of the shift + /// instructions. + inline bool isShift() { return isShift(getOpcode()); } + + /// isLogicalShift - Return true if this is a logical shift left or a logical + /// shift right. + inline bool isLogicalShift() { + return getOpcode() == Shl || getOpcode() == LShr; + } + + /// isLogicalShift - Return true if this is a logical shift left or a logical + /// shift right. + inline bool isArithmeticShift() { + return getOpcode() == AShr; + } + + /// @brief Determine if the OpCode is one of the CastInst instructions. + static inline bool isCast(unsigned OpCode) { + return OpCode >= CastOpsBegin && OpCode < CastOpsEnd; + } + + /// @brief Determine if this is one of the CastInst instructions. + inline bool isCast() const { + return isCast(getOpcode()); + } + + /// isAssociative - Return true if the instruction is associative: + /// + /// Associative operators satisfy: x op (y op z) === (x op y) op z + /// + /// In LLVM, the Add, Mul, And, Or, and Xor operators are associative, when + /// not applied to floating point types. + /// + bool isAssociative() const { return isAssociative(getOpcode(), getType()); } + static bool isAssociative(unsigned op, const Type *Ty); + + /// isCommutative - Return true if the instruction is commutative: + /// + /// Commutative operators satisfy: (x op y) === (y op x) + /// + /// In LLVM, these are the associative operators, plus SetEQ and SetNE, when + /// applied to any type. + /// + bool isCommutative() const { return isCommutative(getOpcode()); } + static bool isCommutative(unsigned op); + + /// isTrappingInstruction - Return true if the instruction may trap. + /// + bool isTrapping() const { + return isTrapping(getOpcode()); + } + static bool isTrapping(unsigned op); + + virtual void print(std::ostream &OS) const { print(OS, 0); } + void print(std::ostream *OS) const { if (OS) print(*OS); } + void print(std::ostream &OS, AssemblyAnnotationWriter *AAW) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Instruction *) { return true; } + static inline bool classof(const Value *V) { + return V->getValueID() >= Value::InstructionVal; + } + + //---------------------------------------------------------------------- + // Exported enumerations... + // + enum TermOps { // These terminate basic blocks +#define FIRST_TERM_INST(N) TermOpsBegin = N, +#define HANDLE_TERM_INST(N, OPC, CLASS) OPC = N, +#define LAST_TERM_INST(N) TermOpsEnd = N+1 +#include "llvm/Instruction.def" + }; + + enum BinaryOps { +#define FIRST_BINARY_INST(N) BinaryOpsBegin = N, +#define HANDLE_BINARY_INST(N, OPC, CLASS) OPC = N, +#define LAST_BINARY_INST(N) BinaryOpsEnd = N+1 +#include "llvm/Instruction.def" + }; + + enum MemoryOps { +#define FIRST_MEMORY_INST(N) MemoryOpsBegin = N, +#define HANDLE_MEMORY_INST(N, OPC, CLASS) OPC = N, +#define LAST_MEMORY_INST(N) MemoryOpsEnd = N+1 +#include "llvm/Instruction.def" + }; + + enum CastOps { +#define FIRST_CAST_INST(N) CastOpsBegin = N, +#define HANDLE_CAST_INST(N, OPC, CLASS) OPC = N, +#define LAST_CAST_INST(N) CastOpsEnd = N+1 +#include "llvm/Instruction.def" + }; + + enum OtherOps { +#define FIRST_OTHER_INST(N) OtherOpsBegin = N, +#define HANDLE_OTHER_INST(N, OPC, CLASS) OPC = N, +#define LAST_OTHER_INST(N) OtherOpsEnd = N+1 +#include "llvm/Instruction.def" + }; + +private: + // getNext/Prev - Return the next or previous instruction in the list. The + // last node in the list is a terminator instruction. + Instruction *getNext() { return Next; } + const Instruction *getNext() const { return Next; } + Instruction *getPrev() { return Prev; } + const Instruction *getPrev() const { return Prev; } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Instructions.h b/include/llvm/Instructions.h new file mode 100644 index 0000000..b501b8e --- /dev/null +++ b/include/llvm/Instructions.h @@ -0,0 +1,2112 @@ +//===-- llvm/Instructions.h - Instruction subclass definitions --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes the class definitions of all of the subclasses of the +// Instruction class. This is meant to be an easy way to get access to all +// instruction subclasses. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INSTRUCTIONS_H +#define LLVM_INSTRUCTIONS_H + +#include "llvm/InstrTypes.h" + +namespace llvm { + +class BasicBlock; +class ConstantInt; +class PointerType; +class VectorType; +class ConstantRange; +class APInt; +class ParamAttrsList; + +//===----------------------------------------------------------------------===// +// AllocationInst Class +//===----------------------------------------------------------------------===// + +/// AllocationInst - This class is the common base class of MallocInst and +/// AllocaInst. +/// +class AllocationInst : public UnaryInstruction { + unsigned Alignment; +protected: + AllocationInst(const Type *Ty, Value *ArraySize, unsigned iTy, unsigned Align, + const std::string &Name = "", Instruction *InsertBefore = 0); + AllocationInst(const Type *Ty, Value *ArraySize, unsigned iTy, unsigned Align, + const std::string &Name, BasicBlock *InsertAtEnd); +public: + // Out of line virtual method, so the vtable, etc has a home. + virtual ~AllocationInst(); + + /// isArrayAllocation - Return true if there is an allocation size parameter + /// to the allocation instruction that is not 1. + /// + bool isArrayAllocation() const; + + /// getArraySize - Get the number of element allocated, for a simple + /// allocation of a single element, this will return a constant 1 value. + /// + inline const Value *getArraySize() const { return getOperand(0); } + inline Value *getArraySize() { return getOperand(0); } + + /// getType - Overload to return most specific pointer type + /// + inline const PointerType *getType() const { + return reinterpret_cast<const PointerType*>(Instruction::getType()); + } + + /// getAllocatedType - Return the type that is being allocated by the + /// instruction. + /// + const Type *getAllocatedType() const; + + /// getAlignment - Return the alignment of the memory that is being allocated + /// by the instruction. + /// + unsigned getAlignment() const { return Alignment; } + void setAlignment(unsigned Align) { + assert((Align & (Align-1)) == 0 && "Alignment is not a power of 2!"); + Alignment = Align; + } + + virtual Instruction *clone() const = 0; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const AllocationInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Alloca || + I->getOpcode() == Instruction::Malloc; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + + +//===----------------------------------------------------------------------===// +// MallocInst Class +//===----------------------------------------------------------------------===// + +/// MallocInst - an instruction to allocated memory on the heap +/// +class MallocInst : public AllocationInst { + MallocInst(const MallocInst &MI); +public: + explicit MallocInst(const Type *Ty, Value *ArraySize = 0, + const std::string &Name = "", + Instruction *InsertBefore = 0) + : AllocationInst(Ty, ArraySize, Malloc, 0, Name, InsertBefore) {} + MallocInst(const Type *Ty, Value *ArraySize, const std::string &Name, + BasicBlock *InsertAtEnd) + : AllocationInst(Ty, ArraySize, Malloc, 0, Name, InsertAtEnd) {} + + MallocInst(const Type *Ty, const std::string &Name, + Instruction *InsertBefore = 0) + : AllocationInst(Ty, 0, Malloc, 0, Name, InsertBefore) {} + MallocInst(const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd) + : AllocationInst(Ty, 0, Malloc, 0, Name, InsertAtEnd) {} + + MallocInst(const Type *Ty, Value *ArraySize, unsigned Align, + const std::string &Name, BasicBlock *InsertAtEnd) + : AllocationInst(Ty, ArraySize, Malloc, Align, Name, InsertAtEnd) {} + MallocInst(const Type *Ty, Value *ArraySize, unsigned Align, + const std::string &Name = "", + Instruction *InsertBefore = 0) + : AllocationInst(Ty, ArraySize, Malloc, Align, Name, InsertBefore) {} + + virtual MallocInst *clone() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MallocInst *) { return true; } + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::Malloc); + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + + +//===----------------------------------------------------------------------===// +// AllocaInst Class +//===----------------------------------------------------------------------===// + +/// AllocaInst - an instruction to allocate memory on the stack +/// +class AllocaInst : public AllocationInst { + AllocaInst(const AllocaInst &); +public: + explicit AllocaInst(const Type *Ty, Value *ArraySize = 0, + const std::string &Name = "", + Instruction *InsertBefore = 0) + : AllocationInst(Ty, ArraySize, Alloca, 0, Name, InsertBefore) {} + AllocaInst(const Type *Ty, Value *ArraySize, const std::string &Name, + BasicBlock *InsertAtEnd) + : AllocationInst(Ty, ArraySize, Alloca, 0, Name, InsertAtEnd) {} + + AllocaInst(const Type *Ty, const std::string &Name, + Instruction *InsertBefore = 0) + : AllocationInst(Ty, 0, Alloca, 0, Name, InsertBefore) {} + AllocaInst(const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd) + : AllocationInst(Ty, 0, Alloca, 0, Name, InsertAtEnd) {} + + AllocaInst(const Type *Ty, Value *ArraySize, unsigned Align, + const std::string &Name = "", Instruction *InsertBefore = 0) + : AllocationInst(Ty, ArraySize, Alloca, Align, Name, InsertBefore) {} + AllocaInst(const Type *Ty, Value *ArraySize, unsigned Align, + const std::string &Name, BasicBlock *InsertAtEnd) + : AllocationInst(Ty, ArraySize, Alloca, Align, Name, InsertAtEnd) {} + + virtual AllocaInst *clone() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const AllocaInst *) { return true; } + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::Alloca); + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + + +//===----------------------------------------------------------------------===// +// FreeInst Class +//===----------------------------------------------------------------------===// + +/// FreeInst - an instruction to deallocate memory +/// +class FreeInst : public UnaryInstruction { + void AssertOK(); +public: + explicit FreeInst(Value *Ptr, Instruction *InsertBefore = 0); + FreeInst(Value *Ptr, BasicBlock *InsertAfter); + + virtual FreeInst *clone() const; + + // Accessor methods for consistency with other memory operations + Value *getPointerOperand() { return getOperand(0); } + const Value *getPointerOperand() const { return getOperand(0); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FreeInst *) { return true; } + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::Free); + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + + +//===----------------------------------------------------------------------===// +// LoadInst Class +//===----------------------------------------------------------------------===// + +/// LoadInst - an instruction for reading from memory. This uses the +/// SubclassData field in Value to store whether or not the load is volatile. +/// +class LoadInst : public UnaryInstruction { + + LoadInst(const LoadInst &LI) + : UnaryInstruction(LI.getType(), Load, LI.getOperand(0)) { + setVolatile(LI.isVolatile()); + setAlignment(LI.getAlignment()); + +#ifndef NDEBUG + AssertOK(); +#endif + } + void AssertOK(); +public: + LoadInst(Value *Ptr, const std::string &Name, Instruction *InsertBefore); + LoadInst(Value *Ptr, const std::string &Name, BasicBlock *InsertAtEnd); + LoadInst(Value *Ptr, const std::string &Name, bool isVolatile = false, + Instruction *InsertBefore = 0); + LoadInst(Value *Ptr, const std::string &Name, bool isVolatile, unsigned Align, + Instruction *InsertBefore = 0); + LoadInst(Value *Ptr, const std::string &Name, bool isVolatile, + BasicBlock *InsertAtEnd); + + LoadInst(Value *Ptr, const char *Name, Instruction *InsertBefore); + LoadInst(Value *Ptr, const char *Name, BasicBlock *InsertAtEnd); + explicit LoadInst(Value *Ptr, const char *Name = 0, bool isVolatile = false, + Instruction *InsertBefore = 0); + LoadInst(Value *Ptr, const char *Name, bool isVolatile, + BasicBlock *InsertAtEnd); + + /// isVolatile - Return true if this is a load from a volatile memory + /// location. + /// + bool isVolatile() const { return SubclassData & 1; } + + /// setVolatile - Specify whether this is a volatile load or not. + /// + void setVolatile(bool V) { + SubclassData = (SubclassData & ~1) | ((V) ? 1 : 0); + } + + virtual LoadInst *clone() const; + + /// getAlignment - Return the alignment of the access that is being performed + /// + unsigned getAlignment() const { + return (1 << (SubclassData>>1)) >> 1; + } + + void setAlignment(unsigned Align); + + Value *getPointerOperand() { return getOperand(0); } + const Value *getPointerOperand() const { return getOperand(0); } + static unsigned getPointerOperandIndex() { return 0U; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const LoadInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Load; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + + +//===----------------------------------------------------------------------===// +// StoreInst Class +//===----------------------------------------------------------------------===// + +/// StoreInst - an instruction for storing to memory +/// +class StoreInst : public Instruction { + Use Ops[2]; + + StoreInst(const StoreInst &SI) : Instruction(SI.getType(), Store, Ops, 2) { + Ops[0].init(SI.Ops[0], this); + Ops[1].init(SI.Ops[1], this); + setVolatile(SI.isVolatile()); + setAlignment(SI.getAlignment()); + +#ifndef NDEBUG + AssertOK(); +#endif + } + void AssertOK(); +public: + StoreInst(Value *Val, Value *Ptr, Instruction *InsertBefore); + StoreInst(Value *Val, Value *Ptr, BasicBlock *InsertAtEnd); + StoreInst(Value *Val, Value *Ptr, bool isVolatile = false, + Instruction *InsertBefore = 0); + StoreInst(Value *Val, Value *Ptr, bool isVolatile, + unsigned Align, Instruction *InsertBefore = 0); + StoreInst(Value *Val, Value *Ptr, bool isVolatile, BasicBlock *InsertAtEnd); + + + /// isVolatile - Return true if this is a load from a volatile memory + /// location. + /// + bool isVolatile() const { return SubclassData & 1; } + + /// setVolatile - Specify whether this is a volatile load or not. + /// + void setVolatile(bool V) { + SubclassData = (SubclassData & ~1) | ((V) ? 1 : 0); + } + + /// Transparently provide more efficient getOperand methods. + Value *getOperand(unsigned i) const { + assert(i < 2 && "getOperand() out of range!"); + return Ops[i]; + } + void setOperand(unsigned i, Value *Val) { + assert(i < 2 && "setOperand() out of range!"); + Ops[i] = Val; + } + unsigned getNumOperands() const { return 2; } + + /// getAlignment - Return the alignment of the access that is being performed + /// + unsigned getAlignment() const { + return (1 << (SubclassData>>1)) >> 1; + } + + void setAlignment(unsigned Align); + + virtual StoreInst *clone() const; + + Value *getPointerOperand() { return getOperand(1); } + const Value *getPointerOperand() const { return getOperand(1); } + static unsigned getPointerOperandIndex() { return 1U; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const StoreInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Store; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + + +//===----------------------------------------------------------------------===// +// GetElementPtrInst Class +//===----------------------------------------------------------------------===// + +/// GetElementPtrInst - an instruction for type-safe pointer arithmetic to +/// access elements of arrays and structs +/// +class GetElementPtrInst : public Instruction { + GetElementPtrInst(const GetElementPtrInst &GEPI) + : Instruction(reinterpret_cast<const Type*>(GEPI.getType()), GetElementPtr, + 0, GEPI.getNumOperands()) { + Use *OL = OperandList = new Use[NumOperands]; + Use *GEPIOL = GEPI.OperandList; + for (unsigned i = 0, E = NumOperands; i != E; ++i) + OL[i].init(GEPIOL[i], this); + } + void init(Value *Ptr, Value* const *Idx, unsigned NumIdx); + void init(Value *Ptr, Value *Idx0, Value *Idx1); + void init(Value *Ptr, Value *Idx); +public: + /// Constructors - Create a getelementptr instruction with a base pointer an + /// list of indices. The first ctor can optionally insert before an existing + /// instruction, the second appends the new instruction to the specified + /// BasicBlock. + GetElementPtrInst(Value *Ptr, Value* const *Idx, unsigned NumIdx, + const std::string &Name = "", Instruction *InsertBefore =0); + GetElementPtrInst(Value *Ptr, Value* const *Idx, unsigned NumIdx, + const std::string &Name, BasicBlock *InsertAtEnd); + + /// Constructors - These two constructors are convenience methods because one + /// and two index getelementptr instructions are so common. + GetElementPtrInst(Value *Ptr, Value *Idx, + const std::string &Name = "", Instruction *InsertBefore =0); + GetElementPtrInst(Value *Ptr, Value *Idx, + const std::string &Name, BasicBlock *InsertAtEnd); + GetElementPtrInst(Value *Ptr, Value *Idx0, Value *Idx1, + const std::string &Name = "", Instruction *InsertBefore =0); + GetElementPtrInst(Value *Ptr, Value *Idx0, Value *Idx1, + const std::string &Name, BasicBlock *InsertAtEnd); + ~GetElementPtrInst(); + + virtual GetElementPtrInst *clone() const; + + // getType - Overload to return most specific pointer type... + inline const PointerType *getType() const { + return reinterpret_cast<const PointerType*>(Instruction::getType()); + } + + /// getIndexedType - Returns the type of the element that would be loaded with + /// a load instruction with the specified parameters. + /// + /// A null type is returned if the indices are invalid for the specified + /// pointer type. + /// + static const Type *getIndexedType(const Type *Ptr, + Value* const *Idx, unsigned NumIdx, + bool AllowStructLeaf = false); + + static const Type *getIndexedType(const Type *Ptr, Value *Idx0, Value *Idx1, + bool AllowStructLeaf = false); + static const Type *getIndexedType(const Type *Ptr, Value *Idx); + + inline op_iterator idx_begin() { return op_begin()+1; } + inline const_op_iterator idx_begin() const { return op_begin()+1; } + inline op_iterator idx_end() { return op_end(); } + inline const_op_iterator idx_end() const { return op_end(); } + + Value *getPointerOperand() { + return getOperand(0); + } + const Value *getPointerOperand() const { + return getOperand(0); + } + static unsigned getPointerOperandIndex() { + return 0U; // get index for modifying correct operand + } + + inline unsigned getNumIndices() const { // Note: always non-negative + return getNumOperands() - 1; + } + + inline bool hasIndices() const { + return getNumOperands() > 1; + } + + /// hasAllZeroIndices - Return true if all of the indices of this GEP are + /// zeros. If so, the result pointer and the first operand have the same + /// value, just potentially different types. + bool hasAllZeroIndices() const; + + /// hasAllConstantIndices - Return true if all of the indices of this GEP are + /// constant integers. If so, the result pointer and the first operand have + /// a constant offset between them. + bool hasAllConstantIndices() const; + + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const GetElementPtrInst *) { return true; } + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::GetElementPtr); + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// ICmpInst Class +//===----------------------------------------------------------------------===// + +/// This instruction compares its operands according to the predicate given +/// to the constructor. It only operates on integers, pointers, or packed +/// vectors of integrals. The two operands must be the same type. +/// @brief Represent an integer comparison operator. +class ICmpInst: public CmpInst { +public: + /// This enumeration lists the possible predicates for the ICmpInst. The + /// values in the range 0-31 are reserved for FCmpInst while values in the + /// range 32-64 are reserved for ICmpInst. This is necessary to ensure the + /// predicate values are not overlapping between the classes. + enum Predicate { + ICMP_EQ = 32, ///< equal + ICMP_NE = 33, ///< not equal + ICMP_UGT = 34, ///< unsigned greater than + ICMP_UGE = 35, ///< unsigned greater or equal + ICMP_ULT = 36, ///< unsigned less than + ICMP_ULE = 37, ///< unsigned less or equal + ICMP_SGT = 38, ///< signed greater than + ICMP_SGE = 39, ///< signed greater or equal + ICMP_SLT = 40, ///< signed less than + ICMP_SLE = 41, ///< signed less or equal + FIRST_ICMP_PREDICATE = ICMP_EQ, + LAST_ICMP_PREDICATE = ICMP_SLE, + BAD_ICMP_PREDICATE = ICMP_SLE + 1 + }; + + /// @brief Constructor with insert-before-instruction semantics. + ICmpInst( + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const std::string &Name = "", ///< Name of the instruction + Instruction *InsertBefore = 0 ///< Where to insert + ) : CmpInst(Instruction::ICmp, pred, LHS, RHS, Name, InsertBefore) { + } + + /// @brief Constructor with insert-at-block-end semantics. + ICmpInst( + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const std::string &Name, ///< Name of the instruction + BasicBlock *InsertAtEnd ///< Block to insert into. + ) : CmpInst(Instruction::ICmp, pred, LHS, RHS, Name, InsertAtEnd) { + } + + /// @brief Return the predicate for this instruction. + Predicate getPredicate() const { return Predicate(SubclassData); } + + /// @brief Set the predicate for this instruction to the specified value. + void setPredicate(Predicate P) { SubclassData = P; } + + /// For example, EQ -> NE, UGT -> ULE, SLT -> SGE, etc. + /// @returns the inverse predicate for the instruction's current predicate. + /// @brief Return the inverse of the instruction's predicate. + Predicate getInversePredicate() const { + return getInversePredicate(getPredicate()); + } + + /// For example, EQ -> NE, UGT -> ULE, SLT -> SGE, etc. + /// @returns the inverse predicate for predicate provided in \p pred. + /// @brief Return the inverse of a given predicate + static Predicate getInversePredicate(Predicate pred); + + /// For example, EQ->EQ, SLE->SGE, ULT->UGT, etc. + /// @returns the predicate that would be the result of exchanging the two + /// operands of the ICmpInst instruction without changing the result + /// produced. + /// @brief Return the predicate as if the operands were swapped + Predicate getSwappedPredicate() const { + return getSwappedPredicate(getPredicate()); + } + + /// This is a static version that you can use without an instruction + /// available. + /// @brief Return the predicate as if the operands were swapped. + static Predicate getSwappedPredicate(Predicate pred); + + /// For example, EQ->EQ, SLE->SLE, UGT->SGT, etc. + /// @returns the predicate that would be the result if the operand were + /// regarded as signed. + /// @brief Return the signed version of the predicate + Predicate getSignedPredicate() const { + return getSignedPredicate(getPredicate()); + } + + /// This is a static version that you can use without an instruction. + /// @brief Return the signed version of the predicate. + static Predicate getSignedPredicate(Predicate pred); + + /// This also tests for commutativity. If isEquality() returns true then + /// the predicate is also commutative. + /// @returns true if the predicate of this instruction is EQ or NE. + /// @brief Determine if this is an equality predicate. + bool isEquality() const { + return SubclassData == ICMP_EQ || SubclassData == ICMP_NE; + } + + /// @returns true if the predicate of this ICmpInst is commutative + /// @brief Determine if this relation is commutative. + bool isCommutative() const { return isEquality(); } + + /// @returns true if the predicate is relational (not EQ or NE). + /// @brief Determine if this a relational predicate. + bool isRelational() const { + return !isEquality(); + } + + /// @returns true if the predicate of this ICmpInst is signed, false otherwise + /// @brief Determine if this instruction's predicate is signed. + bool isSignedPredicate() { return isSignedPredicate(getPredicate()); } + + /// @returns true if the predicate provided is signed, false otherwise + /// @brief Determine if the predicate is signed. + static bool isSignedPredicate(Predicate pred); + + /// Initialize a set of values that all satisfy the predicate with C. + /// @brief Make a ConstantRange for a relation with a constant value. + static ConstantRange makeConstantRange(Predicate pred, const APInt &C); + + /// Exchange the two operands to this instruction in such a way that it does + /// not modify the semantics of the instruction. The predicate value may be + /// changed to retain the same result if the predicate is order dependent + /// (e.g. ult). + /// @brief Swap operands and adjust predicate. + void swapOperands() { + SubclassData = getSwappedPredicate(); + std::swap(Ops[0], Ops[1]); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ICmpInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ICmp; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// FCmpInst Class +//===----------------------------------------------------------------------===// + +/// This instruction compares its operands according to the predicate given +/// to the constructor. It only operates on floating point values or packed +/// vectors of floating point values. The operands must be identical types. +/// @brief Represents a floating point comparison operator. +class FCmpInst: public CmpInst { +public: + /// This enumeration lists the possible predicates for the FCmpInst. Values + /// in the range 0-31 are reserved for FCmpInst. + enum Predicate { + // Opcode U L G E Intuitive operation + FCMP_FALSE = 0, ///< 0 0 0 0 Always false (always folded) + FCMP_OEQ = 1, ///< 0 0 0 1 True if ordered and equal + FCMP_OGT = 2, ///< 0 0 1 0 True if ordered and greater than + FCMP_OGE = 3, ///< 0 0 1 1 True if ordered and greater than or equal + FCMP_OLT = 4, ///< 0 1 0 0 True if ordered and less than + FCMP_OLE = 5, ///< 0 1 0 1 True if ordered and less than or equal + FCMP_ONE = 6, ///< 0 1 1 0 True if ordered and operands are unequal + FCMP_ORD = 7, ///< 0 1 1 1 True if ordered (no nans) + FCMP_UNO = 8, ///< 1 0 0 0 True if unordered: isnan(X) | isnan(Y) + FCMP_UEQ = 9, ///< 1 0 0 1 True if unordered or equal + FCMP_UGT =10, ///< 1 0 1 0 True if unordered or greater than + FCMP_UGE =11, ///< 1 0 1 1 True if unordered, greater than, or equal + FCMP_ULT =12, ///< 1 1 0 0 True if unordered or less than + FCMP_ULE =13, ///< 1 1 0 1 True if unordered, less than, or equal + FCMP_UNE =14, ///< 1 1 1 0 True if unordered or not equal + FCMP_TRUE =15, ///< 1 1 1 1 Always true (always folded) + FIRST_FCMP_PREDICATE = FCMP_FALSE, + LAST_FCMP_PREDICATE = FCMP_TRUE, + BAD_FCMP_PREDICATE = FCMP_TRUE + 1 + }; + + /// @brief Constructor with insert-before-instruction semantics. + FCmpInst( + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const std::string &Name = "", ///< Name of the instruction + Instruction *InsertBefore = 0 ///< Where to insert + ) : CmpInst(Instruction::FCmp, pred, LHS, RHS, Name, InsertBefore) { + } + + /// @brief Constructor with insert-at-block-end semantics. + FCmpInst( + Predicate pred, ///< The predicate to use for the comparison + Value *LHS, ///< The left-hand-side of the expression + Value *RHS, ///< The right-hand-side of the expression + const std::string &Name, ///< Name of the instruction + BasicBlock *InsertAtEnd ///< Block to insert into. + ) : CmpInst(Instruction::FCmp, pred, LHS, RHS, Name, InsertAtEnd) { + } + + /// @brief Return the predicate for this instruction. + Predicate getPredicate() const { return Predicate(SubclassData); } + + /// @brief Set the predicate for this instruction to the specified value. + void setPredicate(Predicate P) { SubclassData = P; } + + /// For example, OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc. + /// @returns the inverse predicate for the instructions current predicate. + /// @brief Return the inverse of the predicate + Predicate getInversePredicate() const { + return getInversePredicate(getPredicate()); + } + + /// For example, OEQ -> UNE, UGT -> OLE, OLT -> UGE, etc. + /// @returns the inverse predicate for \p pred. + /// @brief Return the inverse of a given predicate + static Predicate getInversePredicate(Predicate pred); + + /// For example, OEQ->OEQ, ULE->UGE, OLT->OGT, etc. + /// @returns the predicate that would be the result of exchanging the two + /// operands of the ICmpInst instruction without changing the result + /// produced. + /// @brief Return the predicate as if the operands were swapped + Predicate getSwappedPredicate() const { + return getSwappedPredicate(getPredicate()); + } + + /// This is a static version that you can use without an instruction + /// available. + /// @brief Return the predicate as if the operands were swapped. + static Predicate getSwappedPredicate(Predicate Opcode); + + /// This also tests for commutativity. If isEquality() returns true then + /// the predicate is also commutative. Only the equality predicates are + /// commutative. + /// @returns true if the predicate of this instruction is EQ or NE. + /// @brief Determine if this is an equality predicate. + bool isEquality() const { + return SubclassData == FCMP_OEQ || SubclassData == FCMP_ONE || + SubclassData == FCMP_UEQ || SubclassData == FCMP_UNE; + } + bool isCommutative() const { return isEquality(); } + + /// @returns true if the predicate is relational (not EQ or NE). + /// @brief Determine if this a relational predicate. + bool isRelational() const { return !isEquality(); } + + /// Exchange the two operands to this instruction in such a way that it does + /// not modify the semantics of the instruction. The predicate value may be + /// changed to retain the same result if the predicate is order dependent + /// (e.g. ult). + /// @brief Swap operands and adjust predicate. + void swapOperands() { + SubclassData = getSwappedPredicate(); + std::swap(Ops[0], Ops[1]); + } + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FCmpInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::FCmp; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// CallInst Class +//===----------------------------------------------------------------------===// + +/// CallInst - This class represents a function call, abstracting a target +/// machine's calling convention. This class uses low bit of the SubClassData +/// field to indicate whether or not this is a tail call. The rest of the bits +/// hold the calling convention of the call. +/// +class CallInst : public Instruction { + ParamAttrsList *ParamAttrs; ///< parameter attributes for call + CallInst(const CallInst &CI); + void init(Value *Func, Value* const *Params, unsigned NumParams); + void init(Value *Func, Value *Actual1, Value *Actual2); + void init(Value *Func, Value *Actual); + void init(Value *Func); + +public: + CallInst(Value *F, Value* const *Args, unsigned NumArgs, + const std::string &Name = "", Instruction *InsertBefore = 0); + CallInst(Value *F, Value *const *Args, unsigned NumArgs, + const std::string &Name, BasicBlock *InsertAtEnd); + + // Alternate CallInst ctors w/ two actuals, w/ one actual and no + // actuals, respectively. + CallInst(Value *F, Value *Actual1, Value *Actual2, + const std::string& Name = "", Instruction *InsertBefore = 0); + CallInst(Value *F, Value *Actual1, Value *Actual2, + const std::string& Name, BasicBlock *InsertAtEnd); + CallInst(Value *F, Value *Actual, const std::string& Name = "", + Instruction *InsertBefore = 0); + CallInst(Value *F, Value *Actual, const std::string& Name, + BasicBlock *InsertAtEnd); + explicit CallInst(Value *F, const std::string &Name = "", + Instruction *InsertBefore = 0); + CallInst(Value *F, const std::string &Name, BasicBlock *InsertAtEnd); + ~CallInst(); + + virtual CallInst *clone() const; + + bool isTailCall() const { return SubclassData & 1; } + void setTailCall(bool isTailCall = true) { + SubclassData = (SubclassData & ~1) | unsigned(isTailCall); + } + + /// getCallingConv/setCallingConv - Get or set the calling convention of this + /// function call. + unsigned getCallingConv() const { return SubclassData >> 1; } + void setCallingConv(unsigned CC) { + SubclassData = (SubclassData & 1) | (CC << 1); + } + + /// Obtains a pointer to the ParamAttrsList object which holds the + /// parameter attributes information, if any. + /// @returns 0 if no attributes have been set. + /// @brief Get the parameter attributes. + ParamAttrsList *getParamAttrs() const { return ParamAttrs; } + + /// Sets the parameter attributes for this CallInst. To construct a + /// ParamAttrsList, see ParameterAttributes.h + /// @brief Set the parameter attributes. + void setParamAttrs(ParamAttrsList *attrs); + + /// getCalledFunction - Return the function being called by this instruction + /// if it is a direct call. If it is a call through a function pointer, + /// return null. + Function *getCalledFunction() const { + return static_cast<Function*>(dyn_cast<Function>(getOperand(0))); + } + + /// getCalledValue - Get a pointer to the function that is invoked by this + /// instruction + inline const Value *getCalledValue() const { return getOperand(0); } + inline Value *getCalledValue() { return getOperand(0); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const CallInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Call; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// SelectInst Class +//===----------------------------------------------------------------------===// + +/// SelectInst - This class represents the LLVM 'select' instruction. +/// +class SelectInst : public Instruction { + Use Ops[3]; + + void init(Value *C, Value *S1, Value *S2) { + Ops[0].init(C, this); + Ops[1].init(S1, this); + Ops[2].init(S2, this); + } + + SelectInst(const SelectInst &SI) + : Instruction(SI.getType(), SI.getOpcode(), Ops, 3) { + init(SI.Ops[0], SI.Ops[1], SI.Ops[2]); + } +public: + SelectInst(Value *C, Value *S1, Value *S2, const std::string &Name = "", + Instruction *InsertBefore = 0) + : Instruction(S1->getType(), Instruction::Select, Ops, 3, InsertBefore) { + init(C, S1, S2); + setName(Name); + } + SelectInst(Value *C, Value *S1, Value *S2, const std::string &Name, + BasicBlock *InsertAtEnd) + : Instruction(S1->getType(), Instruction::Select, Ops, 3, InsertAtEnd) { + init(C, S1, S2); + setName(Name); + } + + Value *getCondition() const { return Ops[0]; } + Value *getTrueValue() const { return Ops[1]; } + Value *getFalseValue() const { return Ops[2]; } + + /// Transparently provide more efficient getOperand methods. + Value *getOperand(unsigned i) const { + assert(i < 3 && "getOperand() out of range!"); + return Ops[i]; + } + void setOperand(unsigned i, Value *Val) { + assert(i < 3 && "setOperand() out of range!"); + Ops[i] = Val; + } + unsigned getNumOperands() const { return 3; } + + OtherOps getOpcode() const { + return static_cast<OtherOps>(Instruction::getOpcode()); + } + + virtual SelectInst *clone() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SelectInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Select; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// VAArgInst Class +//===----------------------------------------------------------------------===// + +/// VAArgInst - This class represents the va_arg llvm instruction, which returns +/// an argument of the specified type given a va_list and increments that list +/// +class VAArgInst : public UnaryInstruction { + VAArgInst(const VAArgInst &VAA) + : UnaryInstruction(VAA.getType(), VAArg, VAA.getOperand(0)) {} +public: + VAArgInst(Value *List, const Type *Ty, const std::string &Name = "", + Instruction *InsertBefore = 0) + : UnaryInstruction(Ty, VAArg, List, InsertBefore) { + setName(Name); + } + VAArgInst(Value *List, const Type *Ty, const std::string &Name, + BasicBlock *InsertAtEnd) + : UnaryInstruction(Ty, VAArg, List, InsertAtEnd) { + setName(Name); + } + + virtual VAArgInst *clone() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const VAArgInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == VAArg; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// ExtractElementInst Class +//===----------------------------------------------------------------------===// + +/// ExtractElementInst - This instruction extracts a single (scalar) +/// element from a VectorType value +/// +class ExtractElementInst : public Instruction { + Use Ops[2]; + ExtractElementInst(const ExtractElementInst &EE) : + Instruction(EE.getType(), ExtractElement, Ops, 2) { + Ops[0].init(EE.Ops[0], this); + Ops[1].init(EE.Ops[1], this); + } + +public: + ExtractElementInst(Value *Vec, Value *Idx, const std::string &Name = "", + Instruction *InsertBefore = 0); + ExtractElementInst(Value *Vec, unsigned Idx, const std::string &Name = "", + Instruction *InsertBefore = 0); + ExtractElementInst(Value *Vec, Value *Idx, const std::string &Name, + BasicBlock *InsertAtEnd); + ExtractElementInst(Value *Vec, unsigned Idx, const std::string &Name, + BasicBlock *InsertAtEnd); + + /// isValidOperands - Return true if an extractelement instruction can be + /// formed with the specified operands. + static bool isValidOperands(const Value *Vec, const Value *Idx); + + virtual ExtractElementInst *clone() const; + + /// Transparently provide more efficient getOperand methods. + Value *getOperand(unsigned i) const { + assert(i < 2 && "getOperand() out of range!"); + return Ops[i]; + } + void setOperand(unsigned i, Value *Val) { + assert(i < 2 && "setOperand() out of range!"); + Ops[i] = Val; + } + unsigned getNumOperands() const { return 2; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ExtractElementInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ExtractElement; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// InsertElementInst Class +//===----------------------------------------------------------------------===// + +/// InsertElementInst - This instruction inserts a single (scalar) +/// element into a VectorType value +/// +class InsertElementInst : public Instruction { + Use Ops[3]; + InsertElementInst(const InsertElementInst &IE); +public: + InsertElementInst(Value *Vec, Value *NewElt, Value *Idx, + const std::string &Name = "",Instruction *InsertBefore = 0); + InsertElementInst(Value *Vec, Value *NewElt, unsigned Idx, + const std::string &Name = "",Instruction *InsertBefore = 0); + InsertElementInst(Value *Vec, Value *NewElt, Value *Idx, + const std::string &Name, BasicBlock *InsertAtEnd); + InsertElementInst(Value *Vec, Value *NewElt, unsigned Idx, + const std::string &Name, BasicBlock *InsertAtEnd); + + /// isValidOperands - Return true if an insertelement instruction can be + /// formed with the specified operands. + static bool isValidOperands(const Value *Vec, const Value *NewElt, + const Value *Idx); + + virtual InsertElementInst *clone() const; + + /// getType - Overload to return most specific vector type. + /// + inline const VectorType *getType() const { + return reinterpret_cast<const VectorType*>(Instruction::getType()); + } + + /// Transparently provide more efficient getOperand methods. + Value *getOperand(unsigned i) const { + assert(i < 3 && "getOperand() out of range!"); + return Ops[i]; + } + void setOperand(unsigned i, Value *Val) { + assert(i < 3 && "setOperand() out of range!"); + Ops[i] = Val; + } + unsigned getNumOperands() const { return 3; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const InsertElementInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::InsertElement; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// ShuffleVectorInst Class +//===----------------------------------------------------------------------===// + +/// ShuffleVectorInst - This instruction constructs a fixed permutation of two +/// input vectors. +/// +class ShuffleVectorInst : public Instruction { + Use Ops[3]; + ShuffleVectorInst(const ShuffleVectorInst &IE); +public: + ShuffleVectorInst(Value *V1, Value *V2, Value *Mask, + const std::string &Name = "", Instruction *InsertBefor = 0); + ShuffleVectorInst(Value *V1, Value *V2, Value *Mask, + const std::string &Name, BasicBlock *InsertAtEnd); + + /// isValidOperands - Return true if a shufflevector instruction can be + /// formed with the specified operands. + static bool isValidOperands(const Value *V1, const Value *V2, + const Value *Mask); + + virtual ShuffleVectorInst *clone() const; + + /// getType - Overload to return most specific vector type. + /// + inline const VectorType *getType() const { + return reinterpret_cast<const VectorType*>(Instruction::getType()); + } + + /// Transparently provide more efficient getOperand methods. + Value *getOperand(unsigned i) const { + assert(i < 3 && "getOperand() out of range!"); + return Ops[i]; + } + void setOperand(unsigned i, Value *Val) { + assert(i < 3 && "setOperand() out of range!"); + Ops[i] = Val; + } + unsigned getNumOperands() const { return 3; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ShuffleVectorInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::ShuffleVector; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + + +//===----------------------------------------------------------------------===// +// PHINode Class +//===----------------------------------------------------------------------===// + +// PHINode - The PHINode class is used to represent the magical mystical PHI +// node, that can not exist in nature, but can be synthesized in a computer +// scientist's overactive imagination. +// +class PHINode : public Instruction { + /// ReservedSpace - The number of operands actually allocated. NumOperands is + /// the number actually in use. + unsigned ReservedSpace; + PHINode(const PHINode &PN); +public: + explicit PHINode(const Type *Ty, const std::string &Name = "", + Instruction *InsertBefore = 0) + : Instruction(Ty, Instruction::PHI, 0, 0, InsertBefore), + ReservedSpace(0) { + setName(Name); + } + + PHINode(const Type *Ty, const std::string &Name, BasicBlock *InsertAtEnd) + : Instruction(Ty, Instruction::PHI, 0, 0, InsertAtEnd), + ReservedSpace(0) { + setName(Name); + } + + ~PHINode(); + + /// reserveOperandSpace - This method can be used to avoid repeated + /// reallocation of PHI operand lists by reserving space for the correct + /// number of operands before adding them. Unlike normal vector reserves, + /// this method can also be used to trim the operand space. + void reserveOperandSpace(unsigned NumValues) { + resizeOperands(NumValues*2); + } + + virtual PHINode *clone() const; + + /// getNumIncomingValues - Return the number of incoming edges + /// + unsigned getNumIncomingValues() const { return getNumOperands()/2; } + + /// getIncomingValue - Return incoming value number x + /// + Value *getIncomingValue(unsigned i) const { + assert(i*2 < getNumOperands() && "Invalid value number!"); + return getOperand(i*2); + } + void setIncomingValue(unsigned i, Value *V) { + assert(i*2 < getNumOperands() && "Invalid value number!"); + setOperand(i*2, V); + } + unsigned getOperandNumForIncomingValue(unsigned i) { + return i*2; + } + + /// getIncomingBlock - Return incoming basic block number x + /// + BasicBlock *getIncomingBlock(unsigned i) const { + return reinterpret_cast<BasicBlock*>(getOperand(i*2+1)); + } + void setIncomingBlock(unsigned i, BasicBlock *BB) { + setOperand(i*2+1, reinterpret_cast<Value*>(BB)); + } + unsigned getOperandNumForIncomingBlock(unsigned i) { + return i*2+1; + } + + /// addIncoming - Add an incoming value to the end of the PHI list + /// + void addIncoming(Value *V, BasicBlock *BB) { + assert(getType() == V->getType() && + "All operands to PHI node must be the same type as the PHI node!"); + unsigned OpNo = NumOperands; + if (OpNo+2 > ReservedSpace) + resizeOperands(0); // Get more space! + // Initialize some new operands. + NumOperands = OpNo+2; + OperandList[OpNo].init(V, this); + OperandList[OpNo+1].init(reinterpret_cast<Value*>(BB), this); + } + + /// removeIncomingValue - Remove an incoming value. This is useful if a + /// predecessor basic block is deleted. The value removed is returned. + /// + /// If the last incoming value for a PHI node is removed (and DeletePHIIfEmpty + /// is true), the PHI node is destroyed and any uses of it are replaced with + /// dummy values. The only time there should be zero incoming values to a PHI + /// node is when the block is dead, so this strategy is sound. + /// + Value *removeIncomingValue(unsigned Idx, bool DeletePHIIfEmpty = true); + + Value *removeIncomingValue(const BasicBlock *BB, bool DeletePHIIfEmpty =true){ + int Idx = getBasicBlockIndex(BB); + assert(Idx >= 0 && "Invalid basic block argument to remove!"); + return removeIncomingValue(Idx, DeletePHIIfEmpty); + } + + /// getBasicBlockIndex - Return the first index of the specified basic + /// block in the value list for this PHI. Returns -1 if no instance. + /// + int getBasicBlockIndex(const BasicBlock *BB) const { + Use *OL = OperandList; + for (unsigned i = 0, e = getNumOperands(); i != e; i += 2) + if (OL[i+1] == reinterpret_cast<const Value*>(BB)) return i/2; + return -1; + } + + Value *getIncomingValueForBlock(const BasicBlock *BB) const { + return getIncomingValue(getBasicBlockIndex(BB)); + } + + /// hasConstantValue - If the specified PHI node always merges together the + /// same value, return the value, otherwise return null. + /// + Value *hasConstantValue(bool AllowNonDominatingInstruction = false) const; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const PHINode *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::PHI; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } + private: + void resizeOperands(unsigned NumOperands); +}; + +//===----------------------------------------------------------------------===// +// ReturnInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// ReturnInst - Return a value (possibly void), from a function. Execution +/// does not continue in this function any longer. +/// +class ReturnInst : public TerminatorInst { + Use RetVal; // Return Value: null if 'void'. + ReturnInst(const ReturnInst &RI); + void init(Value *RetVal); + +public: + // ReturnInst constructors: + // ReturnInst() - 'ret void' instruction + // ReturnInst( null) - 'ret void' instruction + // ReturnInst(Value* X) - 'ret X' instruction + // ReturnInst( null, Inst *) - 'ret void' instruction, insert before I + // ReturnInst(Value* X, Inst *I) - 'ret X' instruction, insert before I + // ReturnInst( null, BB *B) - 'ret void' instruction, insert @ end of BB + // ReturnInst(Value* X, BB *B) - 'ret X' instruction, insert @ end of BB + // + // NOTE: If the Value* passed is of type void then the constructor behaves as + // if it was passed NULL. + explicit ReturnInst(Value *retVal = 0, Instruction *InsertBefore = 0); + ReturnInst(Value *retVal, BasicBlock *InsertAtEnd); + explicit ReturnInst(BasicBlock *InsertAtEnd); + + virtual ReturnInst *clone() const; + + // Transparently provide more efficient getOperand methods. + Value *getOperand(unsigned i) const { + assert(i < getNumOperands() && "getOperand() out of range!"); + return RetVal; + } + void setOperand(unsigned i, Value *Val) { + assert(i < getNumOperands() && "setOperand() out of range!"); + RetVal = Val; + } + + Value *getReturnValue() const { return RetVal; } + + unsigned getNumSuccessors() const { return 0; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ReturnInst *) { return true; } + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::Ret); + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } + private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +//===----------------------------------------------------------------------===// +// BranchInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// BranchInst - Conditional or Unconditional Branch instruction. +/// +class BranchInst : public TerminatorInst { + /// Ops list - Branches are strange. The operands are ordered: + /// TrueDest, FalseDest, Cond. This makes some accessors faster because + /// they don't have to check for cond/uncond branchness. + Use Ops[3]; + BranchInst(const BranchInst &BI); + void AssertOK(); +public: + // BranchInst constructors (where {B, T, F} are blocks, and C is a condition): + // BranchInst(BB *B) - 'br B' + // BranchInst(BB* T, BB *F, Value *C) - 'br C, T, F' + // BranchInst(BB* B, Inst *I) - 'br B' insert before I + // BranchInst(BB* T, BB *F, Value *C, Inst *I) - 'br C, T, F', insert before I + // BranchInst(BB* B, BB *I) - 'br B' insert at end + // BranchInst(BB* T, BB *F, Value *C, BB *I) - 'br C, T, F', insert at end + explicit BranchInst(BasicBlock *IfTrue, Instruction *InsertBefore = 0); + BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, + Instruction *InsertBefore = 0); + BranchInst(BasicBlock *IfTrue, BasicBlock *InsertAtEnd); + BranchInst(BasicBlock *IfTrue, BasicBlock *IfFalse, Value *Cond, + BasicBlock *InsertAtEnd); + + /// Transparently provide more efficient getOperand methods. + Value *getOperand(unsigned i) const { + assert(i < getNumOperands() && "getOperand() out of range!"); + return Ops[i]; + } + void setOperand(unsigned i, Value *Val) { + assert(i < getNumOperands() && "setOperand() out of range!"); + Ops[i] = Val; + } + + virtual BranchInst *clone() const; + + inline bool isUnconditional() const { return getNumOperands() == 1; } + inline bool isConditional() const { return getNumOperands() == 3; } + + inline Value *getCondition() const { + assert(isConditional() && "Cannot get condition of an uncond branch!"); + return getOperand(2); + } + + void setCondition(Value *V) { + assert(isConditional() && "Cannot set condition of unconditional branch!"); + setOperand(2, V); + } + + // setUnconditionalDest - Change the current branch to an unconditional branch + // targeting the specified block. + // FIXME: Eliminate this ugly method. + void setUnconditionalDest(BasicBlock *Dest) { + if (isConditional()) { // Convert this to an uncond branch. + NumOperands = 1; + Ops[1].set(0); + Ops[2].set(0); + } + setOperand(0, reinterpret_cast<Value*>(Dest)); + } + + unsigned getNumSuccessors() const { return 1+isConditional(); } + + BasicBlock *getSuccessor(unsigned i) const { + assert(i < getNumSuccessors() && "Successor # out of range for Branch!"); + return cast<BasicBlock>(getOperand(i)); + } + + void setSuccessor(unsigned idx, BasicBlock *NewSucc) { + assert(idx < getNumSuccessors() && "Successor # out of range for Branch!"); + setOperand(idx, reinterpret_cast<Value*>(NewSucc)); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BranchInst *) { return true; } + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::Br); + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +//===----------------------------------------------------------------------===// +// SwitchInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// SwitchInst - Multiway switch +/// +class SwitchInst : public TerminatorInst { + unsigned ReservedSpace; + // Operand[0] = Value to switch on + // Operand[1] = Default basic block destination + // Operand[2n ] = Value to match + // Operand[2n+1] = BasicBlock to go to on match + SwitchInst(const SwitchInst &RI); + void init(Value *Value, BasicBlock *Default, unsigned NumCases); + void resizeOperands(unsigned No); +public: + /// SwitchInst ctor - Create a new switch instruction, specifying a value to + /// switch on and a default destination. The number of additional cases can + /// be specified here to make memory allocation more efficient. This + /// constructor can also autoinsert before another instruction. + SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, + Instruction *InsertBefore = 0); + + /// SwitchInst ctor - Create a new switch instruction, specifying a value to + /// switch on and a default destination. The number of additional cases can + /// be specified here to make memory allocation more efficient. This + /// constructor also autoinserts at the end of the specified BasicBlock. + SwitchInst(Value *Value, BasicBlock *Default, unsigned NumCases, + BasicBlock *InsertAtEnd); + ~SwitchInst(); + + + // Accessor Methods for Switch stmt + inline Value *getCondition() const { return getOperand(0); } + void setCondition(Value *V) { setOperand(0, V); } + + inline BasicBlock *getDefaultDest() const { + return cast<BasicBlock>(getOperand(1)); + } + + /// getNumCases - return the number of 'cases' in this switch instruction. + /// Note that case #0 is always the default case. + unsigned getNumCases() const { + return getNumOperands()/2; + } + + /// getCaseValue - Return the specified case value. Note that case #0, the + /// default destination, does not have a case value. + ConstantInt *getCaseValue(unsigned i) { + assert(i && i < getNumCases() && "Illegal case value to get!"); + return getSuccessorValue(i); + } + + /// getCaseValue - Return the specified case value. Note that case #0, the + /// default destination, does not have a case value. + const ConstantInt *getCaseValue(unsigned i) const { + assert(i && i < getNumCases() && "Illegal case value to get!"); + return getSuccessorValue(i); + } + + /// findCaseValue - Search all of the case values for the specified constant. + /// If it is explicitly handled, return the case number of it, otherwise + /// return 0 to indicate that it is handled by the default handler. + unsigned findCaseValue(const ConstantInt *C) const { + for (unsigned i = 1, e = getNumCases(); i != e; ++i) + if (getCaseValue(i) == C) + return i; + return 0; + } + + /// findCaseDest - Finds the unique case value for a given successor. Returns + /// null if the successor is not found, not unique, or is the default case. + ConstantInt *findCaseDest(BasicBlock *BB) { + if (BB == getDefaultDest()) return NULL; + + ConstantInt *CI = NULL; + for (unsigned i = 1, e = getNumCases(); i != e; ++i) { + if (getSuccessor(i) == BB) { + if (CI) return NULL; // Multiple cases lead to BB. + else CI = getCaseValue(i); + } + } + return CI; + } + + /// addCase - Add an entry to the switch instruction... + /// + void addCase(ConstantInt *OnVal, BasicBlock *Dest); + + /// removeCase - This method removes the specified successor from the switch + /// instruction. Note that this cannot be used to remove the default + /// destination (successor #0). + /// + void removeCase(unsigned idx); + + virtual SwitchInst *clone() const; + + unsigned getNumSuccessors() const { return getNumOperands()/2; } + BasicBlock *getSuccessor(unsigned idx) const { + assert(idx < getNumSuccessors() &&"Successor idx out of range for switch!"); + return cast<BasicBlock>(getOperand(idx*2+1)); + } + void setSuccessor(unsigned idx, BasicBlock *NewSucc) { + assert(idx < getNumSuccessors() && "Successor # out of range for switch!"); + setOperand(idx*2+1, reinterpret_cast<Value*>(NewSucc)); + } + + // getSuccessorValue - Return the value associated with the specified + // successor. + inline ConstantInt *getSuccessorValue(unsigned idx) const { + assert(idx < getNumSuccessors() && "Successor # out of range!"); + return reinterpret_cast<ConstantInt*>(getOperand(idx*2)); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SwitchInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Switch; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +//===----------------------------------------------------------------------===// +// InvokeInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- + +/// InvokeInst - Invoke instruction. The SubclassData field is used to hold the +/// calling convention of the call. +/// +class InvokeInst : public TerminatorInst { + ParamAttrsList *ParamAttrs; + InvokeInst(const InvokeInst &BI); + void init(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException, + Value* const *Args, unsigned NumArgs); +public: + InvokeInst(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException, + Value* const* Args, unsigned NumArgs, const std::string &Name = "", + Instruction *InsertBefore = 0); + InvokeInst(Value *Fn, BasicBlock *IfNormal, BasicBlock *IfException, + Value* const* Args, unsigned NumArgs, const std::string &Name, + BasicBlock *InsertAtEnd); + ~InvokeInst(); + + virtual InvokeInst *clone() const; + + /// getCallingConv/setCallingConv - Get or set the calling convention of this + /// function call. + unsigned getCallingConv() const { return SubclassData; } + void setCallingConv(unsigned CC) { + SubclassData = CC; + } + + /// Obtains a pointer to the ParamAttrsList object which holds the + /// parameter attributes information, if any. + /// @returns 0 if no attributes have been set. + /// @brief Get the parameter attributes. + ParamAttrsList *getParamAttrs() const { return ParamAttrs; } + + /// Sets the parameter attributes for this InvokeInst. To construct a + /// ParamAttrsList, see ParameterAttributes.h + /// @brief Set the parameter attributes. + void setParamAttrs(ParamAttrsList *attrs); + + /// getCalledFunction - Return the function called, or null if this is an + /// indirect function invocation. + /// + Function *getCalledFunction() const { + return dyn_cast<Function>(getOperand(0)); + } + + // getCalledValue - Get a pointer to a function that is invoked by this inst. + inline Value *getCalledValue() const { return getOperand(0); } + + // get*Dest - Return the destination basic blocks... + BasicBlock *getNormalDest() const { + return cast<BasicBlock>(getOperand(1)); + } + BasicBlock *getUnwindDest() const { + return cast<BasicBlock>(getOperand(2)); + } + void setNormalDest(BasicBlock *B) { + setOperand(1, reinterpret_cast<Value*>(B)); + } + + void setUnwindDest(BasicBlock *B) { + setOperand(2, reinterpret_cast<Value*>(B)); + } + + inline BasicBlock *getSuccessor(unsigned i) const { + assert(i < 2 && "Successor # out of range for invoke!"); + return i == 0 ? getNormalDest() : getUnwindDest(); + } + + void setSuccessor(unsigned idx, BasicBlock *NewSucc) { + assert(idx < 2 && "Successor # out of range for invoke!"); + setOperand(idx+1, reinterpret_cast<Value*>(NewSucc)); + } + + unsigned getNumSuccessors() const { return 2; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const InvokeInst *) { return true; } + static inline bool classof(const Instruction *I) { + return (I->getOpcode() == Instruction::Invoke); + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + + +//===----------------------------------------------------------------------===// +// UnwindInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// UnwindInst - Immediately exit the current function, unwinding the stack +/// until an invoke instruction is found. +/// +class UnwindInst : public TerminatorInst { +public: + explicit UnwindInst(Instruction *InsertBefore = 0); + explicit UnwindInst(BasicBlock *InsertAtEnd); + + virtual UnwindInst *clone() const; + + unsigned getNumSuccessors() const { return 0; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const UnwindInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Unwind; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +//===----------------------------------------------------------------------===// +// UnreachableInst Class +//===----------------------------------------------------------------------===// + +//===--------------------------------------------------------------------------- +/// UnreachableInst - This function has undefined behavior. In particular, the +/// presence of this instruction indicates some higher level knowledge that the +/// end of the block cannot be reached. +/// +class UnreachableInst : public TerminatorInst { +public: + explicit UnreachableInst(Instruction *InsertBefore = 0); + explicit UnreachableInst(BasicBlock *InsertAtEnd); + + virtual UnreachableInst *clone() const; + + unsigned getNumSuccessors() const { return 0; } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const UnreachableInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Instruction::Unreachable; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +private: + virtual BasicBlock *getSuccessorV(unsigned idx) const; + virtual unsigned getNumSuccessorsV() const; + virtual void setSuccessorV(unsigned idx, BasicBlock *B); +}; + +//===----------------------------------------------------------------------===// +// TruncInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a truncation of integer types. +class TruncInst : public CastInst { + /// Private copy constructor + TruncInst(const TruncInst &CI) + : CastInst(CI.getType(), Trunc, CI.getOperand(0)) { + } +public: + /// @brief Constructor with insert-before-instruction semantics + TruncInst( + Value *S, ///< The value to be truncated + const Type *Ty, ///< The (smaller) type to truncate to + const std::string &Name = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + TruncInst( + Value *S, ///< The value to be truncated + const Type *Ty, ///< The (smaller) type to truncate to + const std::string &Name, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Clone an identical TruncInst + virtual CastInst *clone() const; + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const TruncInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == Trunc; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// ZExtInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents zero extension of integer types. +class ZExtInst : public CastInst { + /// @brief Private copy constructor + ZExtInst(const ZExtInst &CI) + : CastInst(CI.getType(), ZExt, CI.getOperand(0)) { + } +public: + /// @brief Constructor with insert-before-instruction semantics + ZExtInst( + Value *S, ///< The value to be zero extended + const Type *Ty, ///< The type to zero extend to + const std::string &Name = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end semantics. + ZExtInst( + Value *S, ///< The value to be zero extended + const Type *Ty, ///< The type to zero extend to + const std::string &Name, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Clone an identical ZExtInst + virtual CastInst *clone() const; + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const ZExtInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == ZExt; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// SExtInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a sign extension of integer types. +class SExtInst : public CastInst { + /// @brief Private copy constructor + SExtInst(const SExtInst &CI) + : CastInst(CI.getType(), SExt, CI.getOperand(0)) { + } +public: + /// @brief Constructor with insert-before-instruction semantics + SExtInst( + Value *S, ///< The value to be sign extended + const Type *Ty, ///< The type to sign extend to + const std::string &Name = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + SExtInst( + Value *S, ///< The value to be sign extended + const Type *Ty, ///< The type to sign extend to + const std::string &Name, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Clone an identical SExtInst + virtual CastInst *clone() const; + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SExtInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == SExt; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// FPTruncInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a truncation of floating point types. +class FPTruncInst : public CastInst { + FPTruncInst(const FPTruncInst &CI) + : CastInst(CI.getType(), FPTrunc, CI.getOperand(0)) { + } +public: + /// @brief Constructor with insert-before-instruction semantics + FPTruncInst( + Value *S, ///< The value to be truncated + const Type *Ty, ///< The type to truncate to + const std::string &Name = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-before-instruction semantics + FPTruncInst( + Value *S, ///< The value to be truncated + const Type *Ty, ///< The type to truncate to + const std::string &Name, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Clone an identical FPTruncInst + virtual CastInst *clone() const; + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FPTruncInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == FPTrunc; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// FPExtInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents an extension of floating point types. +class FPExtInst : public CastInst { + FPExtInst(const FPExtInst &CI) + : CastInst(CI.getType(), FPExt, CI.getOperand(0)) { + } +public: + /// @brief Constructor with insert-before-instruction semantics + FPExtInst( + Value *S, ///< The value to be extended + const Type *Ty, ///< The type to extend to + const std::string &Name = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + FPExtInst( + Value *S, ///< The value to be extended + const Type *Ty, ///< The type to extend to + const std::string &Name, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Clone an identical FPExtInst + virtual CastInst *clone() const; + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FPExtInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == FPExt; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// UIToFPInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a cast unsigned integer to floating point. +class UIToFPInst : public CastInst { + UIToFPInst(const UIToFPInst &CI) + : CastInst(CI.getType(), UIToFP, CI.getOperand(0)) { + } +public: + /// @brief Constructor with insert-before-instruction semantics + UIToFPInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const std::string &Name = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + UIToFPInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const std::string &Name, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Clone an identical UIToFPInst + virtual CastInst *clone() const; + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const UIToFPInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == UIToFP; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// SIToFPInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a cast from signed integer to floating point. +class SIToFPInst : public CastInst { + SIToFPInst(const SIToFPInst &CI) + : CastInst(CI.getType(), SIToFP, CI.getOperand(0)) { + } +public: + /// @brief Constructor with insert-before-instruction semantics + SIToFPInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const std::string &Name = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + SIToFPInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const std::string &Name, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Clone an identical SIToFPInst + virtual CastInst *clone() const; + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const SIToFPInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == SIToFP; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// FPToUIInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a cast from floating point to unsigned integer +class FPToUIInst : public CastInst { + FPToUIInst(const FPToUIInst &CI) + : CastInst(CI.getType(), FPToUI, CI.getOperand(0)) { + } +public: + /// @brief Constructor with insert-before-instruction semantics + FPToUIInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const std::string &Name = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + FPToUIInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const std::string &Name, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< Where to insert the new instruction + ); + + /// @brief Clone an identical FPToUIInst + virtual CastInst *clone() const; + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FPToUIInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == FPToUI; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// FPToSIInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a cast from floating point to signed integer. +class FPToSIInst : public CastInst { + FPToSIInst(const FPToSIInst &CI) + : CastInst(CI.getType(), FPToSI, CI.getOperand(0)) { + } +public: + /// @brief Constructor with insert-before-instruction semantics + FPToSIInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const std::string &Name = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + FPToSIInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const std::string &Name, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Clone an identical FPToSIInst + virtual CastInst *clone() const; + + /// @brief Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const FPToSIInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == FPToSI; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// IntToPtrInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a cast from an integer to a pointer. +class IntToPtrInst : public CastInst { + IntToPtrInst(const IntToPtrInst &CI) + : CastInst(CI.getType(), IntToPtr, CI.getOperand(0)) { + } +public: + /// @brief Constructor with insert-before-instruction semantics + IntToPtrInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const std::string &Name = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + IntToPtrInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const std::string &Name, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Clone an identical IntToPtrInst + virtual CastInst *clone() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IntToPtrInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == IntToPtr; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// PtrToIntInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a cast from a pointer to an integer +class PtrToIntInst : public CastInst { + PtrToIntInst(const PtrToIntInst &CI) + : CastInst(CI.getType(), PtrToInt, CI.getOperand(0)) { + } +public: + /// @brief Constructor with insert-before-instruction semantics + PtrToIntInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const std::string &Name = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + PtrToIntInst( + Value *S, ///< The value to be converted + const Type *Ty, ///< The type to convert to + const std::string &Name, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Clone an identical PtrToIntInst + virtual CastInst *clone() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const PtrToIntInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == PtrToInt; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +//===----------------------------------------------------------------------===// +// BitCastInst Class +//===----------------------------------------------------------------------===// + +/// @brief This class represents a no-op cast from one type to another. +class BitCastInst : public CastInst { + BitCastInst(const BitCastInst &CI) + : CastInst(CI.getType(), BitCast, CI.getOperand(0)) { + } +public: + /// @brief Constructor with insert-before-instruction semantics + BitCastInst( + Value *S, ///< The value to be casted + const Type *Ty, ///< The type to casted to + const std::string &Name = "", ///< A name for the new instruction + Instruction *InsertBefore = 0 ///< Where to insert the new instruction + ); + + /// @brief Constructor with insert-at-end-of-block semantics + BitCastInst( + Value *S, ///< The value to be casted + const Type *Ty, ///< The type to casted to + const std::string &Name, ///< A name for the new instruction + BasicBlock *InsertAtEnd ///< The block to insert the instruction into + ); + + /// @brief Clone an identical BitCastInst + virtual CastInst *clone() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const BitCastInst *) { return true; } + static inline bool classof(const Instruction *I) { + return I->getOpcode() == BitCast; + } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) && classof(cast<Instruction>(V)); + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/IntrinsicInst.h b/include/llvm/IntrinsicInst.h new file mode 100644 index 0000000..4e4d475 --- /dev/null +++ b/include/llvm/IntrinsicInst.h @@ -0,0 +1,323 @@ +//===-- llvm/IntrinsicInst.h - Intrinsic Instruction Wrappers ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines classes that make it really easy to deal with intrinsic +// functions with the isa/dyncast family of functions. In particular, this +// allows you to do things like: +// +// if (MemCpyInst *MCI = dyn_cast<MemCpyInst>(Inst)) +// ... MCI->getDest() ... MCI->getSource() ... +// +// All intrinsic function calls are instances of the call instruction, so these +// are all subclasses of the CallInst class. Note that none of these classes +// has state or virtual methods, which is an important part of this gross/neat +// hack working. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INTRINSICINST_H +#define LLVM_INTRINSICINST_H + +#include "llvm/Constants.h" +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/System/IncludeFile.h" + +namespace llvm { + /// IntrinsicInst - A useful wrapper class for inspecting calls to intrinsic + /// functions. This allows the standard isa/dyncast/cast functionality to + /// work with calls to intrinsic functions. + class IntrinsicInst : public CallInst { + IntrinsicInst(); // DO NOT IMPLEMENT + IntrinsicInst(const IntrinsicInst&); // DO NOT IMPLEMENT + void operator=(const IntrinsicInst&); // DO NOT IMPLEMENT + public: + + /// StripPointerCasts - This static method strips off any unneeded pointer + /// casts from the specified value, returning the original uncasted value. + /// Note that the returned value is guaranteed to have pointer type. + static Value *StripPointerCasts(Value *Ptr); + + /// getIntrinsicID - Return the intrinsic ID of this intrinsic. + /// + Intrinsic::ID getIntrinsicID() const { + return (Intrinsic::ID)getCalledFunction()->getIntrinsicID(); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const IntrinsicInst *) { return true; } + static inline bool classof(const CallInst *I) { + if (const Function *CF = I->getCalledFunction()) + return CF->getIntrinsicID() != 0; + return false; + } + static inline bool classof(const Value *V) { + return isa<CallInst>(V) && classof(cast<CallInst>(V)); + } + }; + + /// DbgInfoIntrinsic - This is the common base class for debug info intrinsics + /// + struct DbgInfoIntrinsic : public IntrinsicInst { + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const DbgInfoIntrinsic *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::dbg_stoppoint: + case Intrinsic::dbg_func_start: + case Intrinsic::dbg_region_start: + case Intrinsic::dbg_region_end: + case Intrinsic::dbg_declare: + return true; + default: return false; + } + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + + static Value *StripCast(Value *C); + }; + + /// DbgStopPointInst - This represents the llvm.dbg.stoppoint instruction. + /// + struct DbgStopPointInst : public DbgInfoIntrinsic { + Value *getLineValue() const { return const_cast<Value*>(getOperand(1)); } + Value *getColumnValue() const { return const_cast<Value*>(getOperand(2)); } + Value *getContext() const { + return StripCast(getOperand(3)); + } + + unsigned getLine() const { + return unsigned(cast<ConstantInt>(getOperand(1))->getZExtValue()); + } + unsigned getColumn() const { + return unsigned(cast<ConstantInt>(getOperand(2))->getZExtValue()); + } + + std::string getFileName() const; + std::string getDirectory() const; + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const DbgStopPointInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::dbg_stoppoint; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + /// DbgFuncStartInst - This represents the llvm.dbg.func.start instruction. + /// + struct DbgFuncStartInst : public DbgInfoIntrinsic { + Value *getSubprogram() const { return StripCast(getOperand(1)); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const DbgFuncStartInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::dbg_func_start; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + /// DbgRegionStartInst - This represents the llvm.dbg.region.start + /// instruction. + struct DbgRegionStartInst : public DbgInfoIntrinsic { + Value *getContext() const { return StripCast(getOperand(1)); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const DbgRegionStartInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::dbg_region_start; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + /// DbgRegionEndInst - This represents the llvm.dbg.region.end instruction. + /// + struct DbgRegionEndInst : public DbgInfoIntrinsic { + Value *getContext() const { return StripCast(getOperand(1)); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const DbgRegionEndInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::dbg_region_end; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + /// DbgDeclareInst - This represents the llvm.dbg.declare instruction. + /// + struct DbgDeclareInst : public DbgInfoIntrinsic { + Value *getAddress() const { return getOperand(1); } + Value *getVariable() const { return StripCast(getOperand(2)); } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const DbgDeclareInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::dbg_declare; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + /// MemIntrinsic - This is the common base class for memset/memcpy/memmove. + /// + struct MemIntrinsic : public IntrinsicInst { + Value *getRawDest() const { return const_cast<Value*>(getOperand(1)); } + + Value *getLength() const { return const_cast<Value*>(getOperand(3)); } + ConstantInt *getAlignment() const { + return cast<ConstantInt>(const_cast<Value*>(getOperand(4))); + } + + /// getDest - This is just like getRawDest, but it strips off any cast + /// instructions that feed it, giving the original input. The returned + /// value is guaranteed to be a pointer. + Value *getDest() const { return StripPointerCasts(getRawDest()); } + + /// set* - Set the specified arguments of the instruction. + /// + void setDest(Value *Ptr) { + assert(getRawDest()->getType() == Ptr->getType() && + "setDest called with pointer of wrong type!"); + setOperand(1, Ptr); + } + + void setLength(Value *L) { + assert(getLength()->getType() == L->getType() && + "setLength called with value of wrong type!"); + setOperand(3, L); + } + void setAlignment(ConstantInt *A) { + assert(getAlignment()->getType() == A->getType() && + "setAlignment called with value of wrong type!"); + setOperand(4, A); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MemIntrinsic *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + switch (I->getIntrinsicID()) { + case Intrinsic::memcpy_i32: + case Intrinsic::memcpy_i64: + case Intrinsic::memmove_i32: + case Intrinsic::memmove_i64: + case Intrinsic::memset_i32: + case Intrinsic::memset_i64: + return true; + default: return false; + } + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + + /// MemCpyInst - This class wraps the llvm.memcpy intrinsic. + /// + struct MemCpyInst : public MemIntrinsic { + /// get* - Return the arguments to the instruction. + /// + Value *getRawSource() const { return const_cast<Value*>(getOperand(2)); } + + /// getSource - This is just like getRawSource, but it strips off any cast + /// instructions that feed it, giving the original input. The returned + /// value is guaranteed to be a pointer. + Value *getSource() const { return StripPointerCasts(getRawSource()); } + + + void setSource(Value *Ptr) { + assert(getRawSource()->getType() == Ptr->getType() && + "setSource called with pointer of wrong type!"); + setOperand(2, Ptr); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MemCpyInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::memcpy_i32 || + I->getIntrinsicID() == Intrinsic::memcpy_i64; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + /// MemMoveInst - This class wraps the llvm.memmove intrinsic. + /// + struct MemMoveInst : public MemIntrinsic { + /// get* - Return the arguments to the instruction. + /// + Value *getRawSource() const { return const_cast<Value*>(getOperand(2)); } + + /// getSource - This is just like getRawSource, but it strips off any cast + /// instructions that feed it, giving the original input. The returned + /// value is guaranteed to be a pointer. + Value *getSource() const { return StripPointerCasts(getRawSource()); } + + void setSource(Value *Ptr) { + assert(getRawSource()->getType() == Ptr->getType() && + "setSource called with pointer of wrong type!"); + setOperand(2, Ptr); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MemMoveInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::memmove_i32 || + I->getIntrinsicID() == Intrinsic::memmove_i64; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + + /// MemSetInst - This class wraps the llvm.memset intrinsic. + /// + struct MemSetInst : public MemIntrinsic { + /// get* - Return the arguments to the instruction. + /// + Value *getValue() const { return const_cast<Value*>(getOperand(2)); } + + void setValue(Value *Val) { + assert(getValue()->getType() == Val->getType() && + "setSource called with pointer of wrong type!"); + setOperand(2, Val); + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const MemSetInst *) { return true; } + static inline bool classof(const IntrinsicInst *I) { + return I->getIntrinsicID() == Intrinsic::memset_i32 || + I->getIntrinsicID() == Intrinsic::memset_i64; + } + static inline bool classof(const Value *V) { + return isa<IntrinsicInst>(V) && classof(cast<IntrinsicInst>(V)); + } + }; + +} + +// Ensure that the IntrinsicInst.cpp file gets added as a dependency of any +// file that includes this header +FORCE_DEFINING_FILE_TO_BE_LINKED(IntrinsicInst) + +#endif diff --git a/include/llvm/Intrinsics.h b/include/llvm/Intrinsics.h new file mode 100644 index 0000000..3a97b33 --- /dev/null +++ b/include/llvm/Intrinsics.h @@ -0,0 +1,58 @@ +//===-- llvm/Instrinsics.h - LLVM Intrinsic Function Handling ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a set of enums which allow processing of intrinsic +// functions. Values of these enum types are returned by +// Function::getIntrinsicID. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_INTRINSICS_H +#define LLVM_INTRINSICS_H + +namespace llvm { + +class Type; +class FunctionType; +class Function; +class Module; + +/// Intrinsic Namespace - This namespace contains an enum with a value for +/// every intrinsic/builtin function known by LLVM. These enum values are +/// returned by Function::getIntrinsicID(). +/// +namespace Intrinsic { + enum ID { + not_intrinsic = 0, // Must be zero + + // Get the intrinsic enums generated from Intrinsics.td +#define GET_INTRINSIC_ENUM_VALUES +#include "llvm/Intrinsics.gen" +#undef GET_INTRINSIC_ENUM_VALUES + , num_intrinsics + }; + + /// Intrinsic::getName(ID) - Return the LLVM name for an intrinsic, such as + /// "llvm.ppc.altivec.lvx". + std::string getName(ID id, const Type **Tys = 0, unsigned numTys = 0); + + /// Intrinsic::getType(ID) - Return the function type for an intrinsic. + /// + const FunctionType *getType(ID id, const Type **Tys = 0, unsigned numTys = 0); + + /// Intrinsic::getDeclaration(M, ID) - Create or insert an LLVM Function + /// declaration for an intrinsic, and return it. + Function *getDeclaration(Module *M, ID id, const Type **Tys = 0, + unsigned numTys = 0); + +} // End Intrinsic namespace + +} // End llvm namespace + +#endif diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td new file mode 100644 index 0000000..e5bb2f6 --- /dev/null +++ b/include/llvm/Intrinsics.td @@ -0,0 +1,255 @@ +//===- Intrinsics.td - Defines all LLVM intrinsics ---------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines properties of all LLVM intrinsics. +// +//===----------------------------------------------------------------------===// + +include "llvm/CodeGen/ValueTypes.td" + +//===----------------------------------------------------------------------===// +// Properties we keep track of for intrinsics. +//===----------------------------------------------------------------------===// + +class IntrinsicProperty; + +// Intr*Mem - Memory properties. An intrinsic is allowed to have exactly one of +// these properties set. They are listed from the most aggressive (best to use +// if correct) to the least aggressive. If no property is set, the worst case +// is assumed (IntrWriteMem). + +// IntrNoMem - The intrinsic does not access memory or have any other side +// effects. It may be CSE'd deleted if dead, etc. +def IntrNoMem : IntrinsicProperty; + +// IntrReadArgMem - This intrinsic reads only from memory that one of its +// arguments points to, but may read an unspecified amount. +def IntrReadArgMem : IntrinsicProperty; + +// IntrReadMem - This intrinsic reads from unspecified memory, so it cannot be +// moved across stores. However, it can be reordered otherwise and can be +// deleted if dead. +def IntrReadMem : IntrinsicProperty; + +// IntrWriteArgMem - This intrinsic reads and writes only from memory that one +// of its arguments points to, but may access an unspecified amount. It has no +// other side effects. This may only be used if the intrinsic doesn't "capture" +// the argument pointer (e.g. storing it someplace). +def IntrWriteArgMem : IntrinsicProperty; + +// IntrWriteMem - This intrinsic may read or modify unspecified memory or has +// other side effects. It cannot be modified by the optimizer. This is the +// default if the intrinsic has no other Intr*Mem property. +def IntrWriteMem : IntrinsicProperty; + +//===----------------------------------------------------------------------===// +// Types used by intrinsics. +//===----------------------------------------------------------------------===// + +class LLVMType<ValueType vt, string typeval> { + ValueType VT = vt; + string TypeVal = typeval; +} + +class LLVMIntegerType<ValueType VT, int width> + : LLVMType<VT, "Type::IntegerTyID"> { + int Width = width; +} + +class LLVMVectorType<ValueType VT, int numelts, LLVMType elty> + : LLVMType<VT, "Type::VectorTyID">{ + int NumElts = numelts; + LLVMType ElTy = elty; +} + +class LLVMPointerType<LLVMType elty> + : LLVMType<iPTR, "Type::PointerTyID">{ + LLVMType ElTy = elty; +} + +class LLVMEmptyStructType + : LLVMType<OtherVT, "Type::StructTyID">{ +} + +def llvm_void_ty : LLVMType<isVoid, "Type::VoidTyID">; +def llvm_int_ty : LLVMIntegerType<iAny, 0>; +def llvm_i1_ty : LLVMIntegerType<i1 , 1>; +def llvm_i8_ty : LLVMIntegerType<i8 , 8>; +def llvm_i16_ty : LLVMIntegerType<i16, 16>; +def llvm_i32_ty : LLVMIntegerType<i32, 32>; +def llvm_i64_ty : LLVMIntegerType<i64, 64>; +def llvm_float_ty : LLVMType<f32, "Type::FloatTyID">; +def llvm_double_ty : LLVMType<f64, "Type::DoubleTyID">; +def llvm_ptr_ty : LLVMPointerType<llvm_i8_ty>; // i8* +def llvm_ptrptr_ty : LLVMPointerType<llvm_ptr_ty>; // i8** +def llvm_empty_ty : LLVMEmptyStructType; // { } +def llvm_descriptor_ty : LLVMPointerType<llvm_empty_ty>; // { }* + +def llvm_v16i8_ty : LLVMVectorType<v16i8,16, llvm_i8_ty>; // 16 x i8 +def llvm_v8i16_ty : LLVMVectorType<v8i16, 8, llvm_i16_ty>; // 8 x i16 +def llvm_v2i64_ty : LLVMVectorType<v2i64, 2, llvm_i64_ty>; // 2 x i64 +def llvm_v2i32_ty : LLVMVectorType<v2i32, 2, llvm_i32_ty>; // 2 x i32 +def llvm_v1i64_ty : LLVMVectorType<v1i64, 1, llvm_i64_ty>; // 1 x i64 +def llvm_v4i32_ty : LLVMVectorType<v4i32, 4, llvm_i32_ty>; // 4 x i32 +def llvm_v4f32_ty : LLVMVectorType<v4f32, 4, llvm_float_ty>; // 4 x float +def llvm_v2f64_ty : LLVMVectorType<v2f64, 2, llvm_double_ty>;// 2 x double + +// MMX Vector Types +def llvm_v8i8_ty : LLVMVectorType<v8i8, 8, llvm_i8_ty>; // 8 x i8 +def llvm_v4i16_ty : LLVMVectorType<v4i16, 4, llvm_i16_ty>; // 4 x i16 + +def llvm_vararg_ty : LLVMType<isVoid, "...">; // vararg + +//===----------------------------------------------------------------------===// +// Intrinsic Definitions. +//===----------------------------------------------------------------------===// + +// Intrinsic class - This is used to define one LLVM intrinsic. The name of the +// intrinsic definition should start with "int_", then match the LLVM intrinsic +// name with the "llvm." prefix removed, and all "."s turned into "_"s. For +// example, llvm.bswap.i16 -> int_bswap_i16. +// +// * Types is a list containing the return type and the argument types +// expected for the intrinsic. +// * Properties can be set to describe the behavior of the intrinsic. +// +class Intrinsic<list<LLVMType> types, + list<IntrinsicProperty> properties = [], + string name = ""> { + string LLVMName = name; + string TargetPrefix = ""; // Set to a prefix for target-specific intrinsics. + list<LLVMType> Types = types; + list<IntrinsicProperty> Properties = properties; +} + +/// GCCBuiltin - If this intrinsic exactly corresponds to a GCC builtin, this +/// specifies the name of the builtin. This provides automatic CBE and CFE +/// support. +class GCCBuiltin<string name> { + string GCCBuiltinName = name; +} + + +//===--------------- Variable Argument Handling Intrinsics ----------------===// +// + +def int_vastart : Intrinsic<[llvm_void_ty, llvm_ptr_ty], [], "llvm.va_start">; +def int_vacopy : Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_ptr_ty], [], + "llvm.va_copy">; +def int_vaend : Intrinsic<[llvm_void_ty, llvm_ptr_ty], [], "llvm.va_end">; + +//===------------------- Garbage Collection Intrinsics --------------------===// +// +def int_gcroot : Intrinsic<[llvm_void_ty, llvm_ptrptr_ty, llvm_ptr_ty]>; +def int_gcread : Intrinsic<[llvm_ptr_ty, llvm_ptr_ty, llvm_ptrptr_ty], + [IntrReadArgMem]>; +def int_gcwrite : Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_ptr_ty, + llvm_ptrptr_ty], [IntrWriteArgMem]>; + +//===--------------------- Code Generator Intrinsics ----------------------===// +// +def int_returnaddress : Intrinsic<[llvm_ptr_ty, llvm_i32_ty], [IntrNoMem]>; +def int_frameaddress : Intrinsic<[llvm_ptr_ty, llvm_i32_ty], [IntrNoMem]>; +def int_stacksave : Intrinsic<[llvm_ptr_ty], [IntrReadMem]>, + GCCBuiltin<"__builtin_stack_save">; +def int_stackrestore : Intrinsic<[llvm_void_ty, llvm_ptr_ty]>, + GCCBuiltin<"__builtin_stack_restore">; +def int_prefetch : Intrinsic<[llvm_void_ty, llvm_ptr_ty, + llvm_i32_ty, llvm_i32_ty]>; +def int_pcmarker : Intrinsic<[llvm_void_ty, llvm_i32_ty]>; + +def int_readcyclecounter : Intrinsic<[llvm_i64_ty]>; + +//===------------------- Standard C Library Intrinsics --------------------===// +// + +let Properties = [IntrWriteArgMem] in { + def int_memcpy_i32 : Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_ptr_ty, + llvm_i32_ty, llvm_i32_ty]>; + def int_memcpy_i64 : Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_ptr_ty, + llvm_i64_ty, llvm_i32_ty]>; + def int_memmove_i32 : Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_ptr_ty, + llvm_i32_ty, llvm_i32_ty]>; + def int_memmove_i64 : Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_ptr_ty, + llvm_i64_ty, llvm_i32_ty]>; + def int_memset_i32 : Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_i8_ty, + llvm_i32_ty, llvm_i32_ty]>; + def int_memset_i64 : Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_i8_ty, + llvm_i64_ty, llvm_i32_ty]>; +} + +let Properties = [IntrNoMem] in { + def int_sqrt_f32 : Intrinsic<[llvm_float_ty , llvm_float_ty]>; + def int_sqrt_f64 : Intrinsic<[llvm_double_ty, llvm_double_ty]>; + + def int_powi_f32 : Intrinsic<[llvm_float_ty , llvm_float_ty, llvm_i32_ty]>; + def int_powi_f64 : Intrinsic<[llvm_double_ty, llvm_double_ty, llvm_i32_ty]>; +} + +// NOTE: these are internal interfaces. +def int_setjmp : Intrinsic<[llvm_i32_ty , llvm_ptr_ty]>; +def int_longjmp : Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_i32_ty]>; +def int_sigsetjmp : Intrinsic<[llvm_i32_ty , llvm_ptr_ty, llvm_i32_ty]>; +def int_siglongjmp : Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_i32_ty]>; + +//===-------------------- Bit Manipulation Intrinsics ---------------------===// +// + +// None of these intrinsics accesses memory at all. +let Properties = [IntrNoMem] in { + def int_bswap: Intrinsic<[llvm_int_ty, llvm_int_ty]>; + def int_ctpop: Intrinsic<[llvm_i32_ty, llvm_int_ty]>; + def int_ctlz : Intrinsic<[llvm_i32_ty, llvm_int_ty]>; + def int_cttz : Intrinsic<[llvm_i32_ty, llvm_int_ty]>; + def int_part_select : + Intrinsic<[llvm_int_ty, llvm_int_ty, llvm_i32_ty, llvm_i32_ty]>; + def int_part_set : + Intrinsic<[llvm_int_ty, llvm_int_ty, llvm_int_ty, llvm_i32_ty, + llvm_i32_ty]>; +} + +//===------------------------ Debugger Intrinsics -------------------------===// +// + +def int_dbg_stoppoint : Intrinsic<[llvm_void_ty, + llvm_i32_ty, llvm_i32_ty, + llvm_descriptor_ty]>; +def int_dbg_region_start : Intrinsic<[llvm_void_ty, llvm_descriptor_ty]>; +def int_dbg_region_end : Intrinsic<[llvm_void_ty, llvm_descriptor_ty]>; +def int_dbg_func_start : Intrinsic<[llvm_void_ty, llvm_descriptor_ty]>; +def int_dbg_declare : Intrinsic<[llvm_void_ty, llvm_descriptor_ty, + llvm_descriptor_ty]>; + +//===------------------ Exception Handling Intrinsics----------------------===// +// +def int_eh_exception : Intrinsic<[llvm_ptr_ty]>; +def int_eh_selector : Intrinsic<[llvm_i32_ty, llvm_ptr_ty, llvm_ptr_ty, + llvm_vararg_ty]>; +def int_eh_typeid_for : Intrinsic<[llvm_i32_ty, llvm_ptr_ty]>; + +def int_eh_return : Intrinsic<[llvm_void_ty, llvm_i32_ty, llvm_ptr_ty]>, + GCCBuiltin<"__builtin_eh_return">; + +def int_eh_unwind_init: Intrinsic<[llvm_void_ty]>, + GCCBuiltin<"__builtin_unwind_init">; + +def int_eh_dwarf_cfa : Intrinsic<[llvm_ptr_ty, llvm_i32_ty]>; + +//===---------------- Generic Variable Attribute Intrinsics----------------===// +// +def int_var_annotation : Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_ptr_ty, + llvm_ptr_ty, llvm_i32_ty], + [], "llvm.var.annotation">; + +//===----------------------------------------------------------------------===// +// Target-specific intrinsics +//===----------------------------------------------------------------------===// + +include "llvm/IntrinsicsPowerPC.td" +include "llvm/IntrinsicsX86.td" diff --git a/include/llvm/IntrinsicsPowerPC.td b/include/llvm/IntrinsicsPowerPC.td new file mode 100644 index 0000000..666426a --- /dev/null +++ b/include/llvm/IntrinsicsPowerPC.td @@ -0,0 +1,462 @@ +//===- IntrinsicsPowerPC.td - Defines PowerPC intrinsics ---*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the PowerPC-specific intrinsics. +// +//===----------------------------------------------------------------------===// + +//===----------------------------------------------------------------------===// +// Definitions for all PowerPC intrinsics. +// + +// Non-altivec intrinsics. +let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". + // dcba/dcbf/dcbi/dcbst/dcbt/dcbz/dcbzl(PPC970) instructions. + def int_ppc_dcba : Intrinsic<[llvm_void_ty, llvm_ptr_ty], [IntrWriteMem]>; + def int_ppc_dcbf : Intrinsic<[llvm_void_ty, llvm_ptr_ty], [IntrWriteMem]>; + def int_ppc_dcbi : Intrinsic<[llvm_void_ty, llvm_ptr_ty], [IntrWriteMem]>; + def int_ppc_dcbst : Intrinsic<[llvm_void_ty, llvm_ptr_ty], [IntrWriteMem]>; + def int_ppc_dcbt : Intrinsic<[llvm_void_ty, llvm_ptr_ty], [IntrWriteMem]>; + def int_ppc_dcbtst: Intrinsic<[llvm_void_ty, llvm_ptr_ty], [IntrWriteMem]>; + def int_ppc_dcbz : Intrinsic<[llvm_void_ty, llvm_ptr_ty], [IntrWriteMem]>; + def int_ppc_dcbzl : Intrinsic<[llvm_void_ty, llvm_ptr_ty], [IntrWriteMem]>; +} + + +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + /// PowerPC_Vec_Intrinsic - Base class for all altivec intrinsics. + class PowerPC_Vec_Intrinsic<string GCCIntSuffix, list<LLVMType> types, + list<IntrinsicProperty> properties> + : GCCBuiltin<!strconcat("__builtin_altivec_", GCCIntSuffix)>, + Intrinsic<types, properties>; +} + +//===----------------------------------------------------------------------===// +// PowerPC Altivec Intrinsic Class Definitions. +// + +/// PowerPC_Vec_FF_Intrinsic - A PowerPC intrinsic that takes one v4f32 +/// vector and returns one. These intrinsics have no side effects. +class PowerPC_Vec_FF_Intrinsic<string GCCIntSuffix> + : PowerPC_Vec_Intrinsic<GCCIntSuffix, + [llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; + +/// PowerPC_Vec_FFF_Intrinsic - A PowerPC intrinsic that takes two v4f32 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_FFF_Intrinsic<string GCCIntSuffix> + : PowerPC_Vec_Intrinsic<GCCIntSuffix, + [llvm_v4f32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + +/// PowerPC_Vec_BBB_Intrinsic - A PowerPC intrinsic that takes two v16f8 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_BBB_Intrinsic<string GCCIntSuffix> + : PowerPC_Vec_Intrinsic<GCCIntSuffix, + [llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + +/// PowerPC_Vec_HHH_Intrinsic - A PowerPC intrinsic that takes two v8i16 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_HHH_Intrinsic<string GCCIntSuffix> + : PowerPC_Vec_Intrinsic<GCCIntSuffix, + [llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + +/// PowerPC_Vec_WWW_Intrinsic - A PowerPC intrinsic that takes two v4i32 +/// vectors and returns one. These intrinsics have no side effects. +class PowerPC_Vec_WWW_Intrinsic<string GCCIntSuffix> + : PowerPC_Vec_Intrinsic<GCCIntSuffix, + [llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + + +//===----------------------------------------------------------------------===// +// PowerPC Altivec Intrinsic Definitions. + +let TargetPrefix = "ppc" in { // All intrinsics start with "llvm.ppc.". + // Data Stream Control. + def int_ppc_altivec_dss : GCCBuiltin<"__builtin_altivec_dss">, + Intrinsic<[llvm_void_ty, llvm_i32_ty], [IntrWriteMem]>; + def int_ppc_altivec_dssall : GCCBuiltin<"__builtin_altivec_dssall">, + Intrinsic<[llvm_void_ty], [IntrWriteMem]>; + def int_ppc_altivec_dst : GCCBuiltin<"__builtin_altivec_dst">, + Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + [IntrWriteMem]>; + def int_ppc_altivec_dstt : GCCBuiltin<"__builtin_altivec_dstt">, + Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + [IntrWriteMem]>; + def int_ppc_altivec_dstst : GCCBuiltin<"__builtin_altivec_dstst">, + Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + [IntrWriteMem]>; + def int_ppc_altivec_dststt : GCCBuiltin<"__builtin_altivec_dststt">, + Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_i32_ty, llvm_i32_ty], + [IntrWriteMem]>; + + // VSCR access. + def int_ppc_altivec_mfvscr : GCCBuiltin<"__builtin_altivec_mfvscr">, + Intrinsic<[llvm_v8i16_ty], [IntrReadMem]>; + def int_ppc_altivec_mtvscr : GCCBuiltin<"__builtin_altivec_mtvscr">, + Intrinsic<[llvm_void_ty, llvm_v4i32_ty], [IntrWriteMem]>; + + + // Loads. These don't map directly to GCC builtins because they represent the + // source address with a single pointer. + def int_ppc_altivec_lvx : + Intrinsic<[llvm_v4i32_ty, llvm_ptr_ty], [IntrReadMem]>; + def int_ppc_altivec_lvxl : + Intrinsic<[llvm_v4i32_ty, llvm_ptr_ty], [IntrReadMem]>; + def int_ppc_altivec_lvebx : + Intrinsic<[llvm_v16i8_ty, llvm_ptr_ty], [IntrReadMem]>; + def int_ppc_altivec_lvehx : + Intrinsic<[llvm_v8i16_ty, llvm_ptr_ty], [IntrReadMem]>; + def int_ppc_altivec_lvewx : + Intrinsic<[llvm_v4i32_ty, llvm_ptr_ty], [IntrReadMem]>; + + // Stores. These don't map directly to GCC builtins because they represent the + // source address with a single pointer. + def int_ppc_altivec_stvx : + Intrinsic<[llvm_void_ty, llvm_v4i32_ty, llvm_ptr_ty], + [IntrWriteMem]>; + def int_ppc_altivec_stvxl : + Intrinsic<[llvm_void_ty, llvm_v4i32_ty, llvm_ptr_ty], + [IntrWriteMem]>; + def int_ppc_altivec_stvebx : + Intrinsic<[llvm_void_ty, llvm_v16i8_ty, llvm_ptr_ty], + [IntrWriteMem]>; + def int_ppc_altivec_stvehx : + Intrinsic<[llvm_void_ty, llvm_v8i16_ty, llvm_ptr_ty], + [IntrWriteMem]>; + def int_ppc_altivec_stvewx : + Intrinsic<[llvm_void_ty, llvm_v4i32_ty, llvm_ptr_ty], + [IntrWriteMem]>; + + // Comparisons setting a vector. + def int_ppc_altivec_vcmpbfp : GCCBuiltin<"__builtin_altivec_vcmpbfp">, + Intrinsic<[llvm_v4i32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpeqfp : GCCBuiltin<"__builtin_altivec_vcmpeqfp">, + Intrinsic<[llvm_v4i32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgefp : GCCBuiltin<"__builtin_altivec_vcmpgefp">, + Intrinsic<[llvm_v4i32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtfp : GCCBuiltin<"__builtin_altivec_vcmpgtfp">, + Intrinsic<[llvm_v4i32_ty, llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequw : GCCBuiltin<"__builtin_altivec_vcmpequw">, + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsw : GCCBuiltin<"__builtin_altivec_vcmpgtsw">, + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtuw : GCCBuiltin<"__builtin_altivec_vcmpgtuw">, + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequh : GCCBuiltin<"__builtin_altivec_vcmpequh">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsh : GCCBuiltin<"__builtin_altivec_vcmpgtsh">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtuh : GCCBuiltin<"__builtin_altivec_vcmpgtuh">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequb : GCCBuiltin<"__builtin_altivec_vcmpequb">, + Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsb : GCCBuiltin<"__builtin_altivec_vcmpgtsb">, + Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtub : GCCBuiltin<"__builtin_altivec_vcmpgtub">, + Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + + // Predicate Comparisons. The first operand specifies interpretation of CR6. + def int_ppc_altivec_vcmpbfp_p : GCCBuiltin<"__builtin_altivec_vcmpbfp_p">, + Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpeqfp_p : GCCBuiltin<"__builtin_altivec_vcmpeqfp_p">, + Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgefp_p : GCCBuiltin<"__builtin_altivec_vcmpgefp_p">, + Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtfp_p : GCCBuiltin<"__builtin_altivec_vcmpgtfp_p">, + Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_v4f32_ty,llvm_v4f32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequw_p : GCCBuiltin<"__builtin_altivec_vcmpequw_p">, + Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_v4i32_ty,llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsw_p : GCCBuiltin<"__builtin_altivec_vcmpgtsw_p">, + Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_v4i32_ty,llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtuw_p : GCCBuiltin<"__builtin_altivec_vcmpgtuw_p">, + Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_v4i32_ty,llvm_v4i32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequh_p : GCCBuiltin<"__builtin_altivec_vcmpequh_p">, + Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_v8i16_ty,llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsh_p : GCCBuiltin<"__builtin_altivec_vcmpgtsh_p">, + Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_v8i16_ty,llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtuh_p : GCCBuiltin<"__builtin_altivec_vcmpgtuh_p">, + Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_v8i16_ty,llvm_v8i16_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vcmpequb_p : GCCBuiltin<"__builtin_altivec_vcmpequb_p">, + Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_v16i8_ty,llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtsb_p : GCCBuiltin<"__builtin_altivec_vcmpgtsb_p">, + Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_v16i8_ty,llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcmpgtub_p : GCCBuiltin<"__builtin_altivec_vcmpgtub_p">, + Intrinsic<[llvm_i32_ty, llvm_i32_ty, llvm_v16i8_ty,llvm_v16i8_ty], + [IntrNoMem]>; +} + +// Vector average. +def int_ppc_altivec_vavgsb : PowerPC_Vec_BBB_Intrinsic<"vavgsb">; +def int_ppc_altivec_vavgsh : PowerPC_Vec_HHH_Intrinsic<"vavgsh">; +def int_ppc_altivec_vavgsw : PowerPC_Vec_WWW_Intrinsic<"vavgsw">; +def int_ppc_altivec_vavgub : PowerPC_Vec_BBB_Intrinsic<"vavgub">; +def int_ppc_altivec_vavguh : PowerPC_Vec_HHH_Intrinsic<"vavguh">; +def int_ppc_altivec_vavguw : PowerPC_Vec_WWW_Intrinsic<"vavguw">; + +// Vector maximum. +def int_ppc_altivec_vmaxfp : PowerPC_Vec_FFF_Intrinsic<"vmaxfp">; +def int_ppc_altivec_vmaxsb : PowerPC_Vec_BBB_Intrinsic<"vmaxsb">; +def int_ppc_altivec_vmaxsh : PowerPC_Vec_HHH_Intrinsic<"vmaxsh">; +def int_ppc_altivec_vmaxsw : PowerPC_Vec_WWW_Intrinsic<"vmaxsw">; +def int_ppc_altivec_vmaxub : PowerPC_Vec_BBB_Intrinsic<"vmaxub">; +def int_ppc_altivec_vmaxuh : PowerPC_Vec_HHH_Intrinsic<"vmaxuh">; +def int_ppc_altivec_vmaxuw : PowerPC_Vec_WWW_Intrinsic<"vmaxuw">; + +// Vector minimum. +def int_ppc_altivec_vminfp : PowerPC_Vec_FFF_Intrinsic<"vminfp">; +def int_ppc_altivec_vminsb : PowerPC_Vec_BBB_Intrinsic<"vminsb">; +def int_ppc_altivec_vminsh : PowerPC_Vec_HHH_Intrinsic<"vminsh">; +def int_ppc_altivec_vminsw : PowerPC_Vec_WWW_Intrinsic<"vminsw">; +def int_ppc_altivec_vminub : PowerPC_Vec_BBB_Intrinsic<"vminub">; +def int_ppc_altivec_vminuh : PowerPC_Vec_HHH_Intrinsic<"vminuh">; +def int_ppc_altivec_vminuw : PowerPC_Vec_WWW_Intrinsic<"vminuw">; + +// Saturating adds. +def int_ppc_altivec_vaddubs : PowerPC_Vec_BBB_Intrinsic<"vaddubs">; +def int_ppc_altivec_vaddsbs : PowerPC_Vec_BBB_Intrinsic<"vaddsbs">; +def int_ppc_altivec_vadduhs : PowerPC_Vec_HHH_Intrinsic<"vadduhs">; +def int_ppc_altivec_vaddshs : PowerPC_Vec_HHH_Intrinsic<"vaddshs">; +def int_ppc_altivec_vadduws : PowerPC_Vec_WWW_Intrinsic<"vadduws">; +def int_ppc_altivec_vaddsws : PowerPC_Vec_WWW_Intrinsic<"vaddsws">; +def int_ppc_altivec_vaddcuw : PowerPC_Vec_WWW_Intrinsic<"vaddcuw">; + +// Saturating subs. +def int_ppc_altivec_vsububs : PowerPC_Vec_BBB_Intrinsic<"vsububs">; +def int_ppc_altivec_vsubsbs : PowerPC_Vec_BBB_Intrinsic<"vsubsbs">; +def int_ppc_altivec_vsubuhs : PowerPC_Vec_HHH_Intrinsic<"vsubuhs">; +def int_ppc_altivec_vsubshs : PowerPC_Vec_HHH_Intrinsic<"vsubshs">; +def int_ppc_altivec_vsubuws : PowerPC_Vec_WWW_Intrinsic<"vsubuws">; +def int_ppc_altivec_vsubsws : PowerPC_Vec_WWW_Intrinsic<"vsubsws">; +def int_ppc_altivec_vsubcuw : PowerPC_Vec_WWW_Intrinsic<"vsubcuw">; + +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + // Saturating multiply-adds. + def int_ppc_altivec_vmhaddshs : GCCBuiltin<"__builtin_altivec_vmhaddshs">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vmhraddshs : GCCBuiltin<"__builtin_altivec_vmhraddshs">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty, llvm_v8i16_ty], [IntrNoMem]>; + + def int_ppc_altivec_vmaddfp : GCCBuiltin<"__builtin_altivec_vmaddfp">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; + def int_ppc_altivec_vnmsubfp : GCCBuiltin<"__builtin_altivec_vnmsubfp">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; + + // Vector Multiply Sum Intructions. + def int_ppc_altivec_vmsummbm : GCCBuiltin<"__builtin_altivec_vmsummbm">, + Intrinsic<[llvm_v4i32_ty, llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumshm : GCCBuiltin<"__builtin_altivec_vmsumshm">, + Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumshs : GCCBuiltin<"__builtin_altivec_vmsumshs">, + Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumubm : GCCBuiltin<"__builtin_altivec_vmsumubm">, + Intrinsic<[llvm_v4i32_ty, llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumuhm : GCCBuiltin<"__builtin_altivec_vmsumuhm">, + Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_ppc_altivec_vmsumuhs : GCCBuiltin<"__builtin_altivec_vmsumuhs">, + Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + + // Vector Multiply Intructions. + def int_ppc_altivec_vmulesb : GCCBuiltin<"__builtin_altivec_vmulesb">, + Intrinsic<[llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmulesh : GCCBuiltin<"__builtin_altivec_vmulesh">, + Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmuleub : GCCBuiltin<"__builtin_altivec_vmuleub">, + Intrinsic<[llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmuleuh : GCCBuiltin<"__builtin_altivec_vmuleuh">, + Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vmulosb : GCCBuiltin<"__builtin_altivec_vmulosb">, + Intrinsic<[llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmulosh : GCCBuiltin<"__builtin_altivec_vmulosh">, + Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmuloub : GCCBuiltin<"__builtin_altivec_vmuloub">, + Intrinsic<[llvm_v8i16_ty, llvm_v16i8_ty, llvm_v16i8_ty], + [IntrNoMem]>; + def int_ppc_altivec_vmulouh : GCCBuiltin<"__builtin_altivec_vmulouh">, + Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + + // Vector Sum Intructions. + def int_ppc_altivec_vsumsws : GCCBuiltin<"__builtin_altivec_vsumsws">, + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsum2sws : GCCBuiltin<"__builtin_altivec_vsum2sws">, + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsum4sbs : GCCBuiltin<"__builtin_altivec_vsum4sbs">, + Intrinsic<[llvm_v4i32_ty, llvm_v16i8_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsum4shs : GCCBuiltin<"__builtin_altivec_vsum4shs">, + Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vsum4ubs : GCCBuiltin<"__builtin_altivec_vsum4ubs">, + Intrinsic<[llvm_v4i32_ty, llvm_v16i8_ty, llvm_v4i32_ty], + [IntrNoMem]>; + + // Other multiplies. + def int_ppc_altivec_vmladduhm : GCCBuiltin<"__builtin_altivec_vmladduhm">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + + // Packs. + def int_ppc_altivec_vpkpx : GCCBuiltin<"__builtin_altivec_vpkpx">, + Intrinsic<[llvm_v8i16_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpkshss : GCCBuiltin<"__builtin_altivec_vpkshss">, + Intrinsic<[llvm_v16i8_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpkshus : GCCBuiltin<"__builtin_altivec_vpkshus">, + Intrinsic<[llvm_v16i8_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpkswss : GCCBuiltin<"__builtin_altivec_vpkswss">, + Intrinsic<[llvm_v16i8_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vpkswus : GCCBuiltin<"__builtin_altivec_vpkswus">, + Intrinsic<[llvm_v8i16_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + // vpkuhum is lowered to a shuffle. + def int_ppc_altivec_vpkuhus : GCCBuiltin<"__builtin_altivec_vpkuhus">, + Intrinsic<[llvm_v16i8_ty, llvm_v8i16_ty, llvm_v8i16_ty], + [IntrNoMem]>; + // vpkuwum is lowered to a shuffle. + def int_ppc_altivec_vpkuwus : GCCBuiltin<"__builtin_altivec_vpkuwus">, + Intrinsic<[llvm_v8i16_ty, llvm_v4i32_ty, llvm_v4i32_ty], + [IntrNoMem]>; + + // Unpacks. + def int_ppc_altivec_vupkhpx : GCCBuiltin<"__builtin_altivec_vupkhpx">, + Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vupkhsb : GCCBuiltin<"__builtin_altivec_vupkhsb">, + Intrinsic<[llvm_v8i16_ty, llvm_v16i8_ty], [IntrNoMem]>; + def int_ppc_altivec_vupkhsh : GCCBuiltin<"__builtin_altivec_vupkhsh">, + Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vupklpx : GCCBuiltin<"__builtin_altivec_vupklpx">, + Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty], [IntrNoMem]>; + def int_ppc_altivec_vupklsb : GCCBuiltin<"__builtin_altivec_vupklsb">, + Intrinsic<[llvm_v8i16_ty, llvm_v16i8_ty], [IntrNoMem]>; + def int_ppc_altivec_vupklsh : GCCBuiltin<"__builtin_altivec_vupklsh">, + Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty], [IntrNoMem]>; + + + // FP <-> integer conversion. + def int_ppc_altivec_vcfsx : GCCBuiltin<"__builtin_altivec_vcfsx">, + Intrinsic<[llvm_v4f32_ty, llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vcfux : GCCBuiltin<"__builtin_altivec_vcfux">, + Intrinsic<[llvm_v4f32_ty, llvm_v4i32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vctsxs : GCCBuiltin<"__builtin_altivec_vctsxs">, + Intrinsic<[llvm_v4i32_ty, llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; + def int_ppc_altivec_vctuxs : GCCBuiltin<"__builtin_altivec_vctuxs">, + Intrinsic<[llvm_v4i32_ty, llvm_v4f32_ty, llvm_i32_ty], + [IntrNoMem]>; + + def int_ppc_altivec_vrfim : GCCBuiltin<"__builtin_altivec_vrfim">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; + def int_ppc_altivec_vrfin : GCCBuiltin<"__builtin_altivec_vrfin">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; + def int_ppc_altivec_vrfip : GCCBuiltin<"__builtin_altivec_vrfip">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; + def int_ppc_altivec_vrfiz : GCCBuiltin<"__builtin_altivec_vrfiz">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty], [IntrNoMem]>; +} + +def int_ppc_altivec_vsl : PowerPC_Vec_WWW_Intrinsic<"vsl">; +def int_ppc_altivec_vslo : PowerPC_Vec_WWW_Intrinsic<"vslo">; + +def int_ppc_altivec_vslb : PowerPC_Vec_BBB_Intrinsic<"vslb">; +def int_ppc_altivec_vslh : PowerPC_Vec_HHH_Intrinsic<"vslh">; +def int_ppc_altivec_vslw : PowerPC_Vec_WWW_Intrinsic<"vslw">; + +// Right Shifts. +def int_ppc_altivec_vsr : PowerPC_Vec_WWW_Intrinsic<"vsr">; +def int_ppc_altivec_vsro : PowerPC_Vec_WWW_Intrinsic<"vsro">; + +def int_ppc_altivec_vsrb : PowerPC_Vec_BBB_Intrinsic<"vsrb">; +def int_ppc_altivec_vsrh : PowerPC_Vec_HHH_Intrinsic<"vsrh">; +def int_ppc_altivec_vsrw : PowerPC_Vec_WWW_Intrinsic<"vsrw">; +def int_ppc_altivec_vsrab : PowerPC_Vec_BBB_Intrinsic<"vsrab">; +def int_ppc_altivec_vsrah : PowerPC_Vec_HHH_Intrinsic<"vsrah">; +def int_ppc_altivec_vsraw : PowerPC_Vec_WWW_Intrinsic<"vsraw">; + +// Rotates. +def int_ppc_altivec_vrlb : PowerPC_Vec_BBB_Intrinsic<"vrlb">; +def int_ppc_altivec_vrlh : PowerPC_Vec_HHH_Intrinsic<"vrlh">; +def int_ppc_altivec_vrlw : PowerPC_Vec_WWW_Intrinsic<"vrlw">; + +let TargetPrefix = "ppc" in { // All PPC intrinsics start with "llvm.ppc.". + // Miscellaneous. + def int_ppc_altivec_lvsl : + Intrinsic<[llvm_v16i8_ty, llvm_ptr_ty], [IntrNoMem]>; + def int_ppc_altivec_lvsr : + Intrinsic<[llvm_v16i8_ty, llvm_ptr_ty], [IntrNoMem]>; + + def int_ppc_altivec_vperm : GCCBuiltin<"__builtin_altivec_vperm_4si">, + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_v16i8_ty], [IntrNoMem]>; + def int_ppc_altivec_vsel : GCCBuiltin<"__builtin_altivec_vsel_4si">, + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; +} + +def int_ppc_altivec_vexptefp : PowerPC_Vec_FF_Intrinsic<"vexptefp">; +def int_ppc_altivec_vlogefp : PowerPC_Vec_FF_Intrinsic<"vlogefp">; +def int_ppc_altivec_vrefp : PowerPC_Vec_FF_Intrinsic<"vrefp">; +def int_ppc_altivec_vrsqrtefp : PowerPC_Vec_FF_Intrinsic<"vrsqrtefp">; diff --git a/include/llvm/IntrinsicsX86.td b/include/llvm/IntrinsicsX86.td new file mode 100644 index 0000000..0f61e24 --- /dev/null +++ b/include/llvm/IntrinsicsX86.td @@ -0,0 +1,715 @@ +//===- IntrinsicsX86.td - Defines X86 intrinsics -----------*- tablegen -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines all of the X86-specific intrinsics. +// +//===----------------------------------------------------------------------===// + + +//===----------------------------------------------------------------------===// +// SSE1 + +// Arithmetic ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_add_ss : GCCBuiltin<"__builtin_ia32_addss">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_sub_ss : GCCBuiltin<"__builtin_ia32_subss">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_mul_ss : GCCBuiltin<"__builtin_ia32_mulss">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_div_ss : GCCBuiltin<"__builtin_ia32_divss">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_sqrt_ss : GCCBuiltin<"__builtin_ia32_sqrtss">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_sqrt_ps : GCCBuiltin<"__builtin_ia32_sqrtps">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_rcp_ss : GCCBuiltin<"__builtin_ia32_rcpss">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_rcp_ps : GCCBuiltin<"__builtin_ia32_rcpps">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_rsqrt_ss : GCCBuiltin<"__builtin_ia32_rsqrtss">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_rsqrt_ps : GCCBuiltin<"__builtin_ia32_rsqrtps">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty], + [IntrNoMem]>; + def int_x86_sse_min_ss : GCCBuiltin<"__builtin_ia32_minss">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_min_ps : GCCBuiltin<"__builtin_ia32_minps">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_max_ss : GCCBuiltin<"__builtin_ia32_maxss">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_max_ps : GCCBuiltin<"__builtin_ia32_maxps">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; +} + +// Comparison ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_cmp_ss : + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_sse_cmp_ps : + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_sse_comieq_ss : GCCBuiltin<"__builtin_ia32_comieq">, + Intrinsic<[llvm_i32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comilt_ss : GCCBuiltin<"__builtin_ia32_comilt">, + Intrinsic<[llvm_i32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comile_ss : GCCBuiltin<"__builtin_ia32_comile">, + Intrinsic<[llvm_i32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comigt_ss : GCCBuiltin<"__builtin_ia32_comigt">, + Intrinsic<[llvm_i32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comige_ss : GCCBuiltin<"__builtin_ia32_comige">, + Intrinsic<[llvm_i32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_comineq_ss : GCCBuiltin<"__builtin_ia32_comineq">, + Intrinsic<[llvm_i32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomieq_ss : GCCBuiltin<"__builtin_ia32_ucomieq">, + Intrinsic<[llvm_i32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomilt_ss : GCCBuiltin<"__builtin_ia32_ucomilt">, + Intrinsic<[llvm_i32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomile_ss : GCCBuiltin<"__builtin_ia32_ucomile">, + Intrinsic<[llvm_i32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomigt_ss : GCCBuiltin<"__builtin_ia32_ucomigt">, + Intrinsic<[llvm_i32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomige_ss : GCCBuiltin<"__builtin_ia32_ucomige">, + Intrinsic<[llvm_i32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_ucomineq_ss : GCCBuiltin<"__builtin_ia32_ucomineq">, + Intrinsic<[llvm_i32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; +} + + +// Conversion ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_cvtss2si : GCCBuiltin<"__builtin_ia32_cvtss2si">, + Intrinsic<[llvm_i32_ty, llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvttss2si : GCCBuiltin<"__builtin_ia32_cvttss2si">, + Intrinsic<[llvm_i32_ty, llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse_cvtsi2ss : GCCBuiltin<"__builtin_ia32_cvtsi2ss">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, + llvm_i32_ty], [IntrNoMem]>; +} + +// SIMD load ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_loadu_ps : GCCBuiltin<"__builtin_ia32_loadups">, + Intrinsic<[llvm_v4f32_ty, llvm_ptr_ty], [IntrReadMem]>; +} + +// SIMD store ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_storeu_ps : GCCBuiltin<"__builtin_ia32_storeups">, + Intrinsic<[llvm_void_ty, llvm_ptr_ty, + llvm_v4f32_ty], [IntrWriteMem]>; +} + +// Cacheability support ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_movnt_ps : GCCBuiltin<"__builtin_ia32_movntps">, + Intrinsic<[llvm_void_ty, llvm_ptr_ty, + llvm_v4f32_ty], [IntrWriteMem]>; + def int_x86_sse_sfence : GCCBuiltin<"__builtin_ia32_sfence">, + Intrinsic<[llvm_void_ty], [IntrWriteMem]>; +} + +// Control register. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_stmxcsr : + Intrinsic<[llvm_void_ty, llvm_ptr_ty], [IntrWriteMem]>; + def int_x86_sse_ldmxcsr : + Intrinsic<[llvm_void_ty, llvm_ptr_ty], [IntrWriteMem]>; +} + +// Misc. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse_movmsk_ps : GCCBuiltin<"__builtin_ia32_movmskps">, + Intrinsic<[llvm_i32_ty, llvm_v4f32_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// SSE2 + +// FP arithmetic ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_add_sd : GCCBuiltin<"__builtin_ia32_addsd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_sub_sd : GCCBuiltin<"__builtin_ia32_subsd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_mul_sd : GCCBuiltin<"__builtin_ia32_mulsd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_div_sd : GCCBuiltin<"__builtin_ia32_divsd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_sqrt_sd : GCCBuiltin<"__builtin_ia32_sqrtsd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_sse2_sqrt_pd : GCCBuiltin<"__builtin_ia32_sqrtpd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_sse2_rcp_sd : GCCBuiltin<"__builtin_ia32_rcpsd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_sse2_rcp_pd : GCCBuiltin<"__builtin_ia32_rcppd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_sse2_rsqrt_sd : GCCBuiltin<"__builtin_ia32_rsqrtsd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_sse2_rsqrt_pd : GCCBuiltin<"__builtin_ia32_rsqrtpd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty], + [IntrNoMem]>; + def int_x86_sse2_min_sd : GCCBuiltin<"__builtin_ia32_minsd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_min_pd : GCCBuiltin<"__builtin_ia32_minpd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_max_sd : GCCBuiltin<"__builtin_ia32_maxsd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_max_pd : GCCBuiltin<"__builtin_ia32_maxpd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; +} + +// FP comparison ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_cmp_sd : + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_sse2_cmp_pd : + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; + def int_x86_sse2_comieq_sd : GCCBuiltin<"__builtin_ia32_comisdeq">, + Intrinsic<[llvm_i32_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comilt_sd : GCCBuiltin<"__builtin_ia32_comisdlt">, + Intrinsic<[llvm_i32_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comile_sd : GCCBuiltin<"__builtin_ia32_comisdle">, + Intrinsic<[llvm_i32_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comigt_sd : GCCBuiltin<"__builtin_ia32_comisdgt">, + Intrinsic<[llvm_i32_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comige_sd : GCCBuiltin<"__builtin_ia32_comisdge">, + Intrinsic<[llvm_i32_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_comineq_sd : GCCBuiltin<"__builtin_ia32_comisdneq">, + Intrinsic<[llvm_i32_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomieq_sd : GCCBuiltin<"__builtin_ia32_ucomisdeq">, + Intrinsic<[llvm_i32_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomilt_sd : GCCBuiltin<"__builtin_ia32_ucomisdlt">, + Intrinsic<[llvm_i32_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomile_sd : GCCBuiltin<"__builtin_ia32_ucomisdle">, + Intrinsic<[llvm_i32_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomigt_sd : GCCBuiltin<"__builtin_ia32_ucomisdgt">, + Intrinsic<[llvm_i32_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomige_sd : GCCBuiltin<"__builtin_ia32_ucomisdge">, + Intrinsic<[llvm_i32_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_ucomineq_sd : GCCBuiltin<"__builtin_ia32_ucomisdneq">, + Intrinsic<[llvm_i32_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; +} + +// Integer arithmetic ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_padds_b : GCCBuiltin<"__builtin_ia32_paddsb128">, + Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_padds_w : GCCBuiltin<"__builtin_ia32_paddsw128">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_paddus_b : GCCBuiltin<"__builtin_ia32_paddusb128">, + Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_paddus_w : GCCBuiltin<"__builtin_ia32_paddusw128">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_psubs_b : GCCBuiltin<"__builtin_ia32_psubsb128">, + Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_psubs_w : GCCBuiltin<"__builtin_ia32_psubsw128">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_psubus_b : GCCBuiltin<"__builtin_ia32_psubusb128">, + Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_psubus_w : GCCBuiltin<"__builtin_ia32_psubusw128">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_pmulhu_w : GCCBuiltin<"__builtin_ia32_pmulhuw128">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw128">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_pmulu_dq : GCCBuiltin<"__builtin_ia32_pmuludq128">, + Intrinsic<[llvm_v2i64_ty, llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd128">, + Intrinsic<[llvm_v4i32_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_pavg_b : GCCBuiltin<"__builtin_ia32_pavgb128">, + Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_pavg_w : GCCBuiltin<"__builtin_ia32_pavgw128">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_pmaxu_b : GCCBuiltin<"__builtin_ia32_pmaxub128">, + Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_pmaxs_w : GCCBuiltin<"__builtin_ia32_pmaxsw128">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_pminu_b : GCCBuiltin<"__builtin_ia32_pminub128">, + Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_pmins_w : GCCBuiltin<"__builtin_ia32_pminsw128">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw128">, + Intrinsic<[llvm_v2i64_ty, llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; +} + +// Integer shift ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_psll_w : + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_psll_d : + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_psll_q : + Intrinsic<[llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_psll_dq : GCCBuiltin<"__builtin_ia32_pslldqi128">, + Intrinsic<[llvm_v2i64_ty, llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_w : + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_d : + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_q : + Intrinsic<[llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_psrl_dq : GCCBuiltin<"__builtin_ia32_psrldqi128">, + Intrinsic<[llvm_v2i64_ty, llvm_v2i64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_psra_w : + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_psra_d : + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; +} + +// Integer comparison ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_pcmpeq_b : GCCBuiltin<"__builtin_ia32_pcmpeqb128">, + Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_pcmpeq_w : GCCBuiltin<"__builtin_ia32_pcmpeqw128">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_pcmpeq_d : GCCBuiltin<"__builtin_ia32_pcmpeqd128">, + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_pcmpgt_b : GCCBuiltin<"__builtin_ia32_pcmpgtb128">, + Intrinsic<[llvm_v16i8_ty, llvm_v16i8_ty, + llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_pcmpgt_w : GCCBuiltin<"__builtin_ia32_pcmpgtw128">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_pcmpgt_d : GCCBuiltin<"__builtin_ia32_pcmpgtd128">, + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; +} + +// Conversion ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_cvtdq2pd : GCCBuiltin<"__builtin_ia32_cvtdq2pd">, + Intrinsic<[llvm_v2f64_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtdq2ps : GCCBuiltin<"__builtin_ia32_cvtdq2ps">, + Intrinsic<[llvm_v4f32_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtpd2dq : GCCBuiltin<"__builtin_ia32_cvtpd2dq">, + Intrinsic<[llvm_v4i32_ty, llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvttpd2dq : GCCBuiltin<"__builtin_ia32_cvttpd2dq">, + Intrinsic<[llvm_v4i32_ty, llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtpd2ps : GCCBuiltin<"__builtin_ia32_cvtpd2ps">, + Intrinsic<[llvm_v4f32_ty, llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtps2dq : GCCBuiltin<"__builtin_ia32_cvtps2dq">, + Intrinsic<[llvm_v4i32_ty, llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse2_cvttps2dq : GCCBuiltin<"__builtin_ia32_cvttps2dq">, + Intrinsic<[llvm_v4i32_ty, llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtps2pd : GCCBuiltin<"__builtin_ia32_cvtps2pd">, + Intrinsic<[llvm_v2f64_ty, llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtsd2si : GCCBuiltin<"__builtin_ia32_cvtsd2si">, + Intrinsic<[llvm_i32_ty, llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvttsd2si : GCCBuiltin<"__builtin_ia32_cvttsd2si">, + Intrinsic<[llvm_i32_ty, llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtsi2sd : GCCBuiltin<"__builtin_ia32_cvtsi2sd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_cvtsd2ss : GCCBuiltin<"__builtin_ia32_cvtsd2ss">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_cvtss2sd : GCCBuiltin<"__builtin_ia32_cvtss2sd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v4f32_ty], [IntrNoMem]>; +} + +// SIMD load ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_loadu_pd : GCCBuiltin<"__builtin_ia32_loadupd">, + Intrinsic<[llvm_v2f64_ty, llvm_ptr_ty], [IntrReadMem]>; + def int_x86_sse2_loadu_dq : GCCBuiltin<"__builtin_ia32_loaddqu">, + Intrinsic<[llvm_v16i8_ty, llvm_ptr_ty], [IntrReadMem]>; +} + +// SIMD store ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_storeu_pd : GCCBuiltin<"__builtin_ia32_storeupd">, + Intrinsic<[llvm_void_ty, llvm_ptr_ty, + llvm_v2f64_ty], [IntrWriteMem]>; + def int_x86_sse2_storeu_dq : GCCBuiltin<"__builtin_ia32_storedqu">, + Intrinsic<[llvm_void_ty, llvm_ptr_ty, + llvm_v16i8_ty], [IntrWriteMem]>; + def int_x86_sse2_storel_dq : GCCBuiltin<"__builtin_ia32_storelv4si">, + Intrinsic<[llvm_void_ty, llvm_ptr_ty, + llvm_v4i32_ty], [IntrWriteMem]>; +} + +// Cacheability support ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_movnt_dq : GCCBuiltin<"__builtin_ia32_movntdq">, + Intrinsic<[llvm_void_ty, llvm_ptr_ty, + llvm_v2i64_ty], [IntrWriteMem]>; + def int_x86_sse2_movnt_pd : GCCBuiltin<"__builtin_ia32_movntpd">, + Intrinsic<[llvm_void_ty, llvm_ptr_ty, + llvm_v2f64_ty], [IntrWriteMem]>; + def int_x86_sse2_movnt_i : GCCBuiltin<"__builtin_ia32_movnti">, + Intrinsic<[llvm_void_ty, llvm_ptr_ty, + llvm_i32_ty], [IntrWriteMem]>; +} + +// Misc. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_packsswb_128 : GCCBuiltin<"__builtin_ia32_packsswb128">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_packssdw_128 : GCCBuiltin<"__builtin_ia32_packssdw128">, + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty, + llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_packuswb_128 : GCCBuiltin<"__builtin_ia32_packuswb128">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; + def int_x86_sse2_movl_dq : GCCBuiltin<"__builtin_ia32_movqv4si">, + Intrinsic<[llvm_v4i32_ty, llvm_v4i32_ty], [IntrNoMem]>; + def int_x86_sse2_movmsk_pd : GCCBuiltin<"__builtin_ia32_movmskpd">, + Intrinsic<[llvm_i32_ty, llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_pmovmskb_128 : GCCBuiltin<"__builtin_ia32_pmovmskb128">, + Intrinsic<[llvm_i32_ty, llvm_v16i8_ty], [IntrNoMem]>; + def int_x86_sse2_maskmov_dqu : GCCBuiltin<"__builtin_ia32_maskmovdqu">, + Intrinsic<[llvm_void_ty, llvm_v16i8_ty, + llvm_v16i8_ty, llvm_ptr_ty], [IntrWriteMem]>; + def int_x86_sse2_clflush : GCCBuiltin<"__builtin_ia32_clflush">, + Intrinsic<[llvm_void_ty, llvm_ptr_ty], [IntrWriteMem]>; + def int_x86_sse2_lfence : GCCBuiltin<"__builtin_ia32_lfence">, + Intrinsic<[llvm_void_ty], [IntrWriteMem]>; + def int_x86_sse2_mfence : GCCBuiltin<"__builtin_ia32_mfence">, + Intrinsic<[llvm_void_ty], [IntrWriteMem]>; +} + +// Shuffles. +// FIXME: Temporary workarounds since 2-wide shuffle is broken. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse2_movs_d : GCCBuiltin<"__builtin_ia32_movsd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_loadh_pd : GCCBuiltin<"__builtin_ia32_loadhpd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_ptr_ty], [IntrReadMem]>; + def int_x86_sse2_loadl_pd : GCCBuiltin<"__builtin_ia32_loadlpd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_ptr_ty], [IntrReadMem]>; + def int_x86_sse2_shuf_pd : GCCBuiltin<"__builtin_ia32_shufpd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty, llvm_i32_ty], [IntrNoMem]>; + def int_x86_sse2_unpckh_pd : GCCBuiltin<"__builtin_ia32_unpckhpd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_unpckl_pd : GCCBuiltin<"__builtin_ia32_unpcklpd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse2_punpckh_qdq : GCCBuiltin<"__builtin_ia32_punpckhqdq128">, + Intrinsic<[llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty], [IntrNoMem]>; + def int_x86_sse2_punpckl_qdq : GCCBuiltin<"__builtin_ia32_punpcklqdq128">, + Intrinsic<[llvm_v2i64_ty, llvm_v2i64_ty, + llvm_v2i64_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// SSE3 + +// Addition / subtraction ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse3_addsub_ps : GCCBuiltin<"__builtin_ia32_addsubps">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse3_addsub_pd : GCCBuiltin<"__builtin_ia32_addsubpd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; +} + +// Horizontal ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse3_hadd_ps : GCCBuiltin<"__builtin_ia32_haddps">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse3_hadd_pd : GCCBuiltin<"__builtin_ia32_haddpd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; + def int_x86_sse3_hsub_ps : GCCBuiltin<"__builtin_ia32_hsubps">, + Intrinsic<[llvm_v4f32_ty, llvm_v4f32_ty, + llvm_v4f32_ty], [IntrNoMem]>; + def int_x86_sse3_hsub_pd : GCCBuiltin<"__builtin_ia32_hsubpd">, + Intrinsic<[llvm_v2f64_ty, llvm_v2f64_ty, + llvm_v2f64_ty], [IntrNoMem]>; +} + +// Specialized unaligned load. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse3_ldu_dq : GCCBuiltin<"__builtin_ia32_lddqu">, + Intrinsic<[llvm_v16i8_ty, llvm_ptr_ty], [IntrReadMem]>; +} + +// Thread synchronization ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_sse3_monitor : GCCBuiltin<"__builtin_ia32_monitor">, + Intrinsic<[llvm_void_ty, llvm_ptr_ty, + llvm_i32_ty, llvm_i32_ty], [IntrWriteMem]>; + def int_x86_sse3_mwait : GCCBuiltin<"__builtin_ia32_mwait">, + Intrinsic<[llvm_void_ty, llvm_i32_ty, + llvm_i32_ty], [IntrWriteMem]>; +} + +//===----------------------------------------------------------------------===// +// SSSE3 + +// FP arithmetic ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_ssse3_pmulhrsw_128 : GCCBuiltin<"__builtin_ia32_pmulhrsw128">, + Intrinsic<[llvm_v8i16_ty, llvm_v8i16_ty, + llvm_v8i16_ty], [IntrNoMem]>; +} + +//===----------------------------------------------------------------------===// +// MMX + +// Empty MMX state op. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_mmx_emms : GCCBuiltin<"__builtin_ia32_emms">, + Intrinsic<[llvm_void_ty], [IntrWriteMem]>; + def int_x86_mmx_femms : GCCBuiltin<"__builtin_ia32_femms">, + Intrinsic<[llvm_void_ty], [IntrWriteMem]>; +} + +// Integer arithmetic ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + // Addition + def int_x86_mmx_padds_b : GCCBuiltin<"__builtin_ia32_paddsb">, + Intrinsic<[llvm_v8i8_ty, llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; + def int_x86_mmx_padds_w : GCCBuiltin<"__builtin_ia32_paddsw">, + Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + + def int_x86_mmx_paddus_b : GCCBuiltin<"__builtin_ia32_paddusb">, + Intrinsic<[llvm_v8i8_ty, llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; + def int_x86_mmx_paddus_w : GCCBuiltin<"__builtin_ia32_paddusw">, + Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + + // Subtraction + def int_x86_mmx_psubs_b : GCCBuiltin<"__builtin_ia32_psubsb">, + Intrinsic<[llvm_v8i8_ty, llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; + def int_x86_mmx_psubs_w : GCCBuiltin<"__builtin_ia32_psubsw">, + Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + + def int_x86_mmx_psubus_b : GCCBuiltin<"__builtin_ia32_psubusb">, + Intrinsic<[llvm_v8i8_ty, llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; + def int_x86_mmx_psubus_w : GCCBuiltin<"__builtin_ia32_psubusw">, + Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + + // Multiplication + def int_x86_mmx_pmulh_w : GCCBuiltin<"__builtin_ia32_pmulhw">, + Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + def int_x86_mmx_pmulhu_w : GCCBuiltin<"__builtin_ia32_pmulhuw">, + Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + def int_x86_mmx_pmulu_dq : GCCBuiltin<"__builtin_ia32_pmuludq">, + Intrinsic<[llvm_v2i32_ty, llvm_v2i32_ty, + llvm_v2i32_ty], [IntrNoMem]>; + def int_x86_mmx_pmadd_wd : GCCBuiltin<"__builtin_ia32_pmaddwd">, + Intrinsic<[llvm_v2i32_ty, llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + + // Averages + def int_x86_mmx_pavg_b : GCCBuiltin<"__builtin_ia32_pavgb">, + Intrinsic<[llvm_v8i8_ty, llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; + def int_x86_mmx_pavg_w : GCCBuiltin<"__builtin_ia32_pavgw">, + Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + + // Maximum + def int_x86_mmx_pmaxu_b : GCCBuiltin<"__builtin_ia32_pmaxub">, + Intrinsic<[llvm_v8i8_ty, llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; + def int_x86_mmx_pmaxs_w : GCCBuiltin<"__builtin_ia32_pmaxsw">, + Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + + // Minimum + def int_x86_mmx_pminu_b : GCCBuiltin<"__builtin_ia32_pminub">, + Intrinsic<[llvm_v8i8_ty, llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; + def int_x86_mmx_pmins_w : GCCBuiltin<"__builtin_ia32_pminsw">, + Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + + // Packed sum of absolute differences + def int_x86_mmx_psad_bw : GCCBuiltin<"__builtin_ia32_psadbw">, + Intrinsic<[llvm_v4i16_ty, llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; +} + +// Integer shift ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + // Shift left logical + def int_x86_mmx_psll_w : GCCBuiltin<"__builtin_ia32_psllw">, + Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, + llvm_v2i32_ty], [IntrNoMem]>; + def int_x86_mmx_psll_d : GCCBuiltin<"__builtin_ia32_pslld">, + Intrinsic<[llvm_v2i32_ty, llvm_v2i32_ty, + llvm_v2i32_ty], [IntrNoMem]>; + def int_x86_mmx_psll_q : GCCBuiltin<"__builtin_ia32_psllq">, + Intrinsic<[llvm_v2i32_ty, llvm_v2i32_ty, + llvm_v2i32_ty], [IntrNoMem]>; + + def int_x86_mmx_psrl_w : GCCBuiltin<"__builtin_ia32_psrlw">, + Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, + llvm_v2i32_ty], [IntrNoMem]>; + def int_x86_mmx_psrl_d : GCCBuiltin<"__builtin_ia32_psrld">, + Intrinsic<[llvm_v2i32_ty, llvm_v2i32_ty, + llvm_v2i32_ty], [IntrNoMem]>; + def int_x86_mmx_psrl_q : GCCBuiltin<"__builtin_ia32_psrlq">, + Intrinsic<[llvm_v2i32_ty, llvm_v2i32_ty, + llvm_v2i32_ty], [IntrNoMem]>; + + def int_x86_mmx_psra_w : GCCBuiltin<"__builtin_ia32_psraw">, + Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, + llvm_v2i32_ty], [IntrNoMem]>; + def int_x86_mmx_psra_d : GCCBuiltin<"__builtin_ia32_psrad">, + Intrinsic<[llvm_v2i32_ty, llvm_v2i32_ty, + llvm_v2i32_ty], [IntrNoMem]>; +} + +// Pack ops. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_mmx_packsswb : GCCBuiltin<"__builtin_ia32_packsswb">, + Intrinsic<[llvm_v8i8_ty, llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + def int_x86_mmx_packssdw : GCCBuiltin<"__builtin_ia32_packssdw">, + Intrinsic<[llvm_v4i16_ty, llvm_v2i32_ty, + llvm_v2i32_ty], [IntrNoMem]>; + def int_x86_mmx_packuswb : GCCBuiltin<"__builtin_ia32_packuswb">, + Intrinsic<[llvm_v8i8_ty, llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; +} + +// Integer comparison ops +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_mmx_pcmpeq_b : GCCBuiltin<"__builtin_ia32_pcmpeqb">, + Intrinsic<[llvm_v8i8_ty, llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; + def int_x86_mmx_pcmpeq_w : GCCBuiltin<"__builtin_ia32_pcmpeqw">, + Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + def int_x86_mmx_pcmpeq_d : GCCBuiltin<"__builtin_ia32_pcmpeqd">, + Intrinsic<[llvm_v2i32_ty, llvm_v2i32_ty, + llvm_v2i32_ty], [IntrNoMem]>; + + def int_x86_mmx_pcmpgt_b : GCCBuiltin<"__builtin_ia32_pcmpgtb">, + Intrinsic<[llvm_v8i8_ty, llvm_v8i8_ty, + llvm_v8i8_ty], [IntrNoMem]>; + def int_x86_mmx_pcmpgt_w : GCCBuiltin<"__builtin_ia32_pcmpgtw">, + Intrinsic<[llvm_v4i16_ty, llvm_v4i16_ty, + llvm_v4i16_ty], [IntrNoMem]>; + def int_x86_mmx_pcmpgt_d : GCCBuiltin<"__builtin_ia32_pcmpgtd">, + Intrinsic<[llvm_v2i32_ty, llvm_v2i32_ty, + llvm_v2i32_ty], [IntrNoMem]>; +} + +// Misc. +let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". + def int_x86_mmx_maskmovq : GCCBuiltin<"__builtin_ia32_maskmovq">, + Intrinsic<[llvm_void_ty, llvm_v8i8_ty, llvm_v8i8_ty, llvm_ptr_ty], + [IntrWriteMem]>; + + def int_x86_mmx_pmovmskb : GCCBuiltin<"__builtin_ia32_pmovmskb">, + Intrinsic<[llvm_i32_ty, llvm_v8i8_ty], [IntrNoMem]>; + + def int_x86_mmx_movnt_dq : GCCBuiltin<"__builtin_ia32_movntq">, + Intrinsic<[llvm_void_ty, llvm_ptr_ty, + llvm_v1i64_ty], [IntrWriteMem]>; +} diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h new file mode 100644 index 0000000..b445ba0 --- /dev/null +++ b/include/llvm/LinkAllPasses.h @@ -0,0 +1,127 @@ +//===- llvm/LinkAllPasses.h ------------ Reference All Passes ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Jeff Cohen and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file pulls in all transformation and analysis passes for tools +// like opt and bugpoint that need this functionality. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LINKALLPASSES_H +#define LLVM_LINKALLPASSES_H + +#include "llvm/Analysis/AliasSetTracker.h" +#include "llvm/Analysis/FindUsedTypes.h" +#include "llvm/Analysis/IntervalPartition.h" +#include "llvm/Analysis/LoadValueNumbering.h" +#include "llvm/Analysis/Passes.h" +#include "llvm/Analysis/PostDominators.h" +#include "llvm/Analysis/ScalarEvolution.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/Function.h" +#include "llvm/Transforms/Instrumentation.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/Scalar.h" +#include "llvm/Transforms/Utils/UnifyFunctionExitNodes.h" +#include <cstdlib> + +namespace { + struct ForcePassLinking { + ForcePassLinking() { + // We must reference the passes in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + + (void) llvm::createAAEvalPass(); + (void) llvm::createAggressiveDCEPass(); + (void) llvm::createAliasAnalysisCounterPass(); + (void) llvm::createAliasDebugger(); + (void) llvm::createAndersensPass(); + (void) llvm::createArgumentPromotionPass(); + (void) llvm::createBasicAliasAnalysisPass(); + (void) llvm::createBasicVNPass(); + (void) llvm::createBlockPlacementPass(); + (void) llvm::createBlockProfilerPass(); + (void) llvm::createBreakCriticalEdgesPass(); + (void) llvm::createCFGSimplificationPass(); + (void) llvm::createConstantMergePass(); + (void) llvm::createConstantPropagationPass(); + (void) llvm::createCorrelatedExpressionEliminationPass(); + (void) llvm::createDeadArgEliminationPass(); + (void) llvm::createDeadCodeEliminationPass(); + (void) llvm::createDeadInstEliminationPass(); + (void) llvm::createDeadStoreEliminationPass(); + (void) llvm::createDeadTypeEliminationPass(); + (void) llvm::createEdgeProfilerPass(); + (void) llvm::createFastDeadStoreEliminationPass(); + (void) llvm::createFunctionInliningPass(); + (void) llvm::createFunctionProfilerPass(); + (void) llvm::createGCSEPass(); + (void) llvm::createGlobalDCEPass(); + (void) llvm::createGlobalOptimizerPass(); + (void) llvm::createGlobalsModRefPass(); + (void) llvm::createGVNPREPass(); + (void) llvm::createIPConstantPropagationPass(); + (void) llvm::createIPSCCPPass(); + (void) llvm::createIndVarSimplifyPass(); + (void) llvm::createInstructionCombiningPass(); + (void) llvm::createInternalizePass(false); + (void) llvm::createLCSSAPass(); + (void) llvm::createLICMPass(); + (void) llvm::createLoadValueNumberingPass(); + (void) llvm::createLoopExtractorPass(); + (void) llvm::createLoopSimplifyPass(); + (void) llvm::createLoopStrengthReducePass(); + (void) llvm::createLoopUnrollPass(); + (void) llvm::createLoopUnswitchPass(); + (void) llvm::createLoopRotatePass(); + (void) llvm::createLowerAllocationsPass(); + (void) llvm::createLowerGCPass(); + (void) llvm::createLowerInvokePass(); + (void) llvm::createLowerPackedPass(); + (void) llvm::createLowerSelectPass(); + (void) llvm::createLowerSetJmpPass(); + (void) llvm::createLowerSwitchPass(); + (void) llvm::createNoAAPass(); + (void) llvm::createNoProfileInfoPass(); + (void) llvm::createProfileLoaderPass(); + (void) llvm::createPromoteMemoryToRegisterPass(); + (void) llvm::createDemoteRegisterToMemoryPass(); + (void) llvm::createPruneEHPass(); + (void) llvm::createRaiseAllocationsPass(); + (void) llvm::createReassociatePass(); + (void) llvm::createSCCPPass(); + (void) llvm::createScalarReplAggregatesPass(); + (void) llvm::createSimplifyLibCallsPass(); + (void) llvm::createSingleLoopExtractorPass(); + (void) llvm::createStripSymbolsPass(); + (void) llvm::createTailCallEliminationPass(); + (void) llvm::createTailDuplicationPass(); + (void) llvm::createUnifyFunctionExitNodesPass(); + (void) llvm::createCondPropagationPass(); + (void) llvm::createNullProfilerRSPass(); + (void) llvm::createRSProfilingPass(); + (void) llvm::createIndMemRemPass(); + (void) llvm::createInstCountPass(); + (void) llvm::createPredicateSimplifierPass(); + (void) llvm::createCodeGenPreparePass(); + + (void)new llvm::IntervalPartition(); + (void)new llvm::FindUsedTypes(); + (void)new llvm::ScalarEvolution(); + ((llvm::Function*)0)->viewCFGOnly(); + llvm::AliasSetTracker X(*(llvm::AliasAnalysis*)0); + X.add((llvm::Value*)0, 0); // for -print-alias-sets + } + } ForcePassLinking; // Force link by creating a global definition. +} + +#endif diff --git a/include/llvm/LinkAllVMCore.h b/include/llvm/LinkAllVMCore.h new file mode 100644 index 0000000..ae1e1cd --- /dev/null +++ b/include/llvm/LinkAllVMCore.h @@ -0,0 +1,57 @@ +//===- LinkAllVMCore.h - Reference All VMCore Code --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file pulls in all the object modules of the VMCore library so +// that tools like llc, opt, and lli can ensure they are linked with all symbols +// from libVMCore.a It should only be used from a tool's main program. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LINKALLVMCORE_H +#define LLVM_LINKALLVMCORE_H + +#include "llvm/System/IncludeFile.h" + +#include "llvm/Module.h" +#include "llvm/Instructions.h" +#include "llvm/IntrinsicInst.h" +#include "llvm/InlineAsm.h" +#include "llvm/Analysis/Verifier.h" +#include "llvm/System/Alarm.h" +#include "llvm/System/DynamicLibrary.h" +#include "llvm/System/MappedFile.h" +#include "llvm/System/Memory.h" +#include "llvm/System/Mutex.h" +#include "llvm/System/Path.h" +#include "llvm/System/Process.h" +#include "llvm/System/Program.h" +#include "llvm/System/Signals.h" +#include "llvm/System/TimeValue.h" +#include "llvm/Support/Dwarf.h" +#include "llvm/Support/Mangler.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Support/SlowOperationInformer.h" + +namespace { + struct ForceVMCoreLinking { + ForceVMCoreLinking() { + // We must reference VMCore in such a way that compilers will not + // delete it all as dead code, even with whole program optimization, + // yet is effectively a NO-OP. As the compiler isn't smart enough + // to know that getenv() never returns -1, this will do the job. + if (std::getenv("bar") != (char*) -1) + return; + (void)new llvm::Module(""); + (void)new llvm::UnreachableInst(); + (void) llvm::createVerifierPass(); + } + } ForceVMCoreLinking; +} + +#endif diff --git a/include/llvm/LinkTimeOptimizer.h b/include/llvm/LinkTimeOptimizer.h new file mode 100644 index 0000000..164232d --- /dev/null +++ b/include/llvm/LinkTimeOptimizer.h @@ -0,0 +1,153 @@ +//===-- llvm/LinkTimeOptimizer.h - Public Interface ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Devang Patel and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header provides public interface to use LLVM link time optimization +// library. This is intended to be used by linker to do link time optimization. +// +//===----------------------------------------------------------------------===// + +#ifndef __LTO_H__ +#define __LTO_H__ + +#include <string> +#include <vector> +#include <set> +#include <llvm/ADT/hash_map> + +namespace llvm { + + class Module; + class GlobalValue; + class TargetMachine; + + enum LTOStatus { + LTO_UNKNOWN, + LTO_OPT_SUCCESS, + LTO_READ_SUCCESS, + LTO_READ_FAILURE, + LTO_WRITE_FAILURE, + LTO_NO_TARGET, + LTO_NO_WORK, + LTO_MODULE_MERGE_FAILURE, + LTO_ASM_FAILURE + }; + + enum LTOLinkageTypes { + LTOExternalLinkage, // Externally visible function + LTOLinkOnceLinkage, // Keep one copy of named function when linking (inline) + LTOWeakLinkage, // Keep one copy of named function when linking (weak) + LTOInternalLinkage // Rename collisions when linking (static functions) + }; + + /// This class represents LLVM symbol information without exposing details + /// of LLVM global values. It encapsulates symbol linkage information. This + /// is typically used in hash_map where associated name identifies the + /// the symbol name. + class LLVMSymbol { + + public: + + LTOLinkageTypes getLinkage() const { return linkage; } + void mayBeNotUsed(); + + LLVMSymbol (enum LTOLinkageTypes lt, GlobalValue *g, const std::string &n, + const std::string &m, int a) : linkage(lt), gv(g), name(n), + mangledName(m), alignment(a) {} + + const char *getName() { return name.c_str(); } + const char *getMangledName() { return mangledName.c_str(); } + int getAlignment() { return alignment; } + + private: + enum LTOLinkageTypes linkage; + GlobalValue *gv; + std::string name; + std::string mangledName; + int alignment; + }; + + class string_compare { + public: + bool operator()(const char* left, const char* right) const { + return (strcmp(left, right) == 0); + } + }; + + /// This is abstract class to facilitate dlopen() interface. + /// See LTO below for more info. + class LinkTimeOptimizer { + public: + typedef hash_map<const char*, LLVMSymbol*, hash<const char*>, + string_compare> NameToSymbolMap; + typedef hash_map<const char*, Module*, hash<const char*>, + string_compare> NameToModuleMap; + virtual enum LTOStatus readLLVMObjectFile(const std::string &, + NameToSymbolMap &, + std::set<std::string> &) = 0; + virtual enum LTOStatus optimizeModules(const std::string &, + std::vector<const char*> &, + std::string &, bool, + const char *) = 0; + virtual void getTargetTriple(const std::string &, std::string &) = 0; + virtual void removeModule (const std::string &InputFilename) = 0; + virtual void printVersion () = 0; + virtual ~LinkTimeOptimizer() = 0; + }; + + /// This is the main link time optimization class. It exposes simple API + /// to perform link time optimization using LLVM intermodular optimizer. + class LTO : public LinkTimeOptimizer { + + public: + typedef hash_map<const char*, LLVMSymbol*, hash<const char*>, + string_compare> NameToSymbolMap; + typedef hash_map<const char*, Module*, hash<const char*>, + string_compare> NameToModuleMap; + + enum LTOStatus readLLVMObjectFile(const std::string &InputFilename, + NameToSymbolMap &symbols, + std::set<std::string> &references); + enum LTOStatus optimizeModules(const std::string &OutputFilename, + std::vector<const char*> &exportList, + std::string &targetTriple, bool saveTemps, + const char *); + void getTargetTriple(const std::string &InputFilename, + std::string &targetTriple); + void removeModule (const std::string &InputFilename); + void printVersion(); + + // Constructors and destructors + LTO() { + /// TODO: Use Target info, it is available at this time. + Target = NULL; + } + ~LTO(); + + private: + Module *getModule (const std::string &InputFilename); + enum LTOStatus optimize(Module *, std::ostream &, + std::vector<const char *> &); + void getTarget(Module *); + + private: + std::vector<Module *> modules; + NameToSymbolMap allSymbols; + NameToModuleMap allModules; + TargetMachine *Target; + }; + +} // End llvm namespace + +/// This provides C interface to initialize link time optimizer. This allows +/// linker to use dlopen() interface to dynamically load LinkTimeOptimizer. +/// extern "C" helps, because dlopen() interface uses name to find the symbol. +extern "C" +llvm::LinkTimeOptimizer *createLLVMOptimizer(); + +#endif diff --git a/include/llvm/Linker.h b/include/llvm/Linker.h new file mode 100644 index 0000000..cc0372d --- /dev/null +++ b/include/llvm/Linker.h @@ -0,0 +1,297 @@ +//===- llvm/Linker.h - Module Linker Interface ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the interface to the module/file/archive linker. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_LINKER_H +#define LLVM_LINKER_H + +#include "llvm/System/Path.h" +#include <vector> +#include <memory> + +namespace llvm { + +class Module; + +/// This class provides the core functionality of linking in LLVM. It retains a +/// Module object which is the composite of the modules and libraries linked +/// into it. The composite Module can be retrieved via the getModule() method. +/// In this case the Linker still retains ownership of the Module. If the +/// releaseModule() method is used, the ownership of the Module is transferred +/// to the caller and the Linker object is only suitable for destruction. +/// The Linker can link Modules from memory, bitcode files, or bitcode +/// archives. It retains a set of search paths in which to find any libraries +/// presented to it. By default, the linker will generate error and warning +/// messages to std::cerr but this capability can be turned off with the +/// QuietWarnings and QuietErrors flags. It can also be instructed to verbosely +/// print out the linking actions it is taking with the Verbose flag. +/// @brief The LLVM Linker. +class Linker { + + /// @name Types + /// @{ + public: + /// This type is used to pass the linkage items (libraries and files) to + /// the LinkItems function. It is composed of string/bool pairs. The string + /// provides the name of the file or library (as with the -l option). The + /// bool should be true for libraries and false for files, signifying + /// "isLibrary". + /// @brief A list of linkage items + typedef std::vector<std::pair<std::string,bool> > ItemList; + + /// This enumeration is used to control various optional features of the + /// linker. + enum ControlFlags { + Verbose = 1, ///< Print to std::cerr what steps the linker is taking + QuietWarnings = 2, ///< Don't print errors and warnings to std::cerr. + QuietErrors = 4 ///< Indicate that this link is for a native executable + }; + + /// @} + /// @name Constructors + /// @{ + public: + /// Construct the Linker with an empty module which will be given the + /// name \p progname. \p progname will also be used for error messages. + /// @brief Construct with empty module + Linker( + const std::string& progname, ///< name of tool running linker + const std::string& modulename, ///< name of linker's end-result module + unsigned Flags = 0 ///< ControlFlags (one or more |'d together) + ); + + /// Construct the Linker with a previously defined module, \p aModule. Use + /// \p progname for the name of the program in error messages. + /// @brief Construct with existing module + Linker(const std::string& progname, Module* aModule, unsigned Flags = 0); + + /// Destruct the Linker. + /// @brief Destructor + ~Linker(); + + /// @} + /// @name Accessors + /// @{ + public: + /// This method gets the composite module into which linking is being + /// done. The Composite module starts out empty and accumulates modules + /// linked into it via the various LinkIn* methods. This method does not + /// release the Module to the caller. The Linker retains ownership and will + /// destruct the Module when the Linker is destructed. + /// @see releaseModule + /// @brief Get the linked/composite module. + Module* getModule() const { return Composite; } + + /// This method releases the composite Module into which linking is being + /// done. Ownership of the composite Module is transferred to the caller who + /// must arrange for its destruct. After this method is called, the Linker + /// terminates the linking session for the returned Module. It will no + /// longer utilize the returned Module but instead resets itself for + /// subsequent linking as if the constructor had been called. The Linker's + /// LibPaths and flags to be reset, and memory will be released. + /// @brief Release the linked/composite module. + Module* releaseModule(); + + /// This method gets the list of libraries that form the path that the + /// Linker will search when it is presented with a library name. + /// @brief Get the Linkers library path + const std::vector<sys::Path>& getLibPaths() const { return LibPaths; } + + /// This method returns an error string suitable for printing to the user. + /// The return value will be empty unless an error occurred in one of the + /// LinkIn* methods. In those cases, the LinkIn* methods will have returned + /// true, indicating an error occurred. At most one error is retained so + /// this function always returns the last error that occurred. Note that if + /// the Quiet control flag is not set, the error string will have already + /// been printed to std::cerr. + /// @brief Get the text of the last error that occurred. + const std::string& getLastError() const { return Error; } + + /// @} + /// @name Mutators + /// @{ + public: + /// Add a path to the list of paths that the Linker will search. The Linker + /// accumulates the set of libraries added + /// library paths for the target platform. The standard libraries will + /// always be searched last. The added libraries will be searched in the + /// order added. + /// @brief Add a path. + void addPath(const sys::Path& path); + + /// Add a set of paths to the list of paths that the linker will search. The + /// Linker accumulates the set of libraries added. The \p paths will be + /// added to the end of the Linker's list. Order will be retained. + /// @brief Add a set of paths. + void addPaths(const std::vector<std::string>& paths); + + /// This method augments the Linker's list of library paths with the system + /// paths of the host operating system, include LLVM_LIB_SEARCH_PATH. + /// @brief Add the system paths. + void addSystemPaths(); + + /// Control optional linker behavior by setting a group of flags. The flags + /// are defined in the ControlFlags enumeration. + /// @see ControlFlags + /// @brief Set control flags. + void setFlags(unsigned flags) { Flags = flags; } + + /// This method is the main interface to the linker. It can be used to + /// link a set of linkage items into a module. A linkage item is either a + /// file name with fully qualified path, or a library for which the Linker's + /// LibraryPath will be utilized to locate the library. The bool value in + /// the LinkItemKind should be set to true for libraries. This function + /// allows linking to preserve the order of specification associated with + /// the command line, or for other purposes. Each item will be linked in + /// turn as it occurs in \p Items. + /// @returns true if an error occurred, false otherwise + /// @see LinkItemKind + /// @see getLastError + /// @throws nothing + bool LinkInItems ( + const ItemList& Items, ///< Set of libraries/files to link in + ItemList& NativeItems ///< Output list of native files/libs + ); + + /// This function links the bitcode \p Files into the composite module. + /// Note that this does not do any linking of unresolved symbols. The \p + /// Files are all completely linked into \p HeadModule regardless of + /// unresolved symbols. This function just loads each bitcode file and + /// calls LinkInModule on them. + /// @returns true if an error occurs, false otherwise + /// @see getLastError + /// @brief Link in multiple files. + bool LinkInFiles ( + const std::vector<sys::Path> & Files ///< Files to link in + ); + + /// This function links a single bitcode file, \p File, into the composite + /// module. Note that this does not attempt to resolve symbols. This method + /// just loads the bitcode file and calls LinkInModule on it. If an error + /// occurs, the Linker's error string is set. + /// @returns true if an error occurs, false otherwise + /// @see getLastError + /// @brief Link in a single file. + bool LinkInFile( + const sys::Path& File, ///< File to link in. + bool &is_native ///< Indicates if the file is native object file + ); + + /// This function provides a way to selectively link in a set of modules, + /// found in libraries, based on the unresolved symbols in the composite + /// module. Each item in \p Libraries should be the base name of a library, + /// as if given with the -l option of a linker tool. The Linker's LibPaths + /// are searched for the \p Libraries and any found will be linked in with + /// LinkInArchive. If an error occurs, the Linker's error string is set. + /// @see LinkInArchive + /// @see getLastError + /// @returns true if an error occurs, false otherwise + /// @brief Link libraries into the module + bool LinkInLibraries ( + const std::vector<std::string> & Libraries ///< Libraries to link in + ); + + /// This function provides a way to selectively link in a set of modules, + /// found in one library, based on the unresolved symbols in the composite + /// module.The \p Library should be the base name of a library, as if given + /// with the -l option of a linker tool. The Linker's LibPaths are searched + /// for the \P Library and if found, it will be linked in with via the + /// LinkInArchive method. If an error occurs, the Linker's error string is + /// set. + /// @see LinkInArchive + /// @see getLastError + /// @returns true if an error occurs, false otherwise + /// @brief Link one library into the module + bool LinkInLibrary ( + const std::string& Library, ///< The library to link in + bool& is_native ///< Indicates if lib a native library + ); + + /// This function links one bitcode archive, \p Filename, into the module. + /// The archive is searched to resolve outstanding symbols. Any modules in + /// the archive that resolve outstanding symbols will be linked in. The + /// library is searched repeatedly until no more modules that resolve + /// symbols can be found. If an error occurs, the error string is set. + /// To speed up this function, ensure the the archive has been processed + /// llvm-ranlib or the S option was given to llvm-ar when the archive was + /// created. These tools add a symbol table to the archive which makes the + /// search for undefined symbols much faster. + /// @see getLastError + /// @returns true if an error occurs, otherwise false. + /// @brief Link in one archive. + bool LinkInArchive( + const sys::Path& Filename, ///< Filename of the archive to link + bool& is_native ///< Indicates if archive is a native archive + ); + + /// This method links the \p Src module into the Linker's Composite module + /// by calling LinkModules. All the other LinkIn* methods eventually + /// result in calling this method to link a Module into the Linker's + /// composite. + /// @see LinkModules + /// @returns True if an error occurs, false otherwise. + /// @brief Link in a module. + bool LinkInModule( + Module* Src, ///< Module linked into \p Dest + std::string* ErrorMsg = 0 /// Error/diagnostic string + ) { + return LinkModules(Composite, Src, ErrorMsg ); + } + + /// This is the heart of the linker. This method will take unconditional + /// control of the \p Src module and link it into the \p Dest module. The + /// \p Src module will be destructed or subsumed by this method. In either + /// case it is not usable by the caller after this method is invoked. Only + /// the \p Dest module will remain. The \p Src module is linked into the + /// Linker's composite module such that types, global variables, functions, + /// and etc. are matched and resolved. If an error occurs, this function + /// returns true and ErrorMsg is set to a descriptive message about the + /// error. + /// @returns True if an error occurs, false otherwise. + /// @brief Generically link two modules together. + static bool LinkModules(Module* Dest, Module* Src, std::string* ErrorMsg); + + /// This function looks through the Linker's LibPaths to find a library with + /// the name \p Filename. If the library cannot be found, the returned path + /// will be empty (i.e. sys::Path::isEmpty() will return true). + /// @returns A sys::Path to the found library + /// @brief Find a library from its short name. + sys::Path FindLib(const std::string &Filename); + + /// @} + /// @name Implementation + /// @{ + private: + /// Read in and parse the bitcode file named by FN and return the + /// Module it contains (wrapped in an auto_ptr), or 0 if an error occurs. + std::auto_ptr<Module> LoadObject(const sys::Path& FN); + + bool warning(const std::string& message); + bool error(const std::string& message); + void verbose(const std::string& message); + + /// @} + /// @name Data + /// @{ + private: + Module* Composite; ///< The composite module linked together + std::vector<sys::Path> LibPaths; ///< The library search paths + unsigned Flags; ///< Flags to control optional behavior. + std::string Error; ///< Text of error that occurred. + std::string ProgramName; ///< Name of the program being linked + /// @} + +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Module.h b/include/llvm/Module.h new file mode 100644 index 0000000..9bd02ec --- /dev/null +++ b/include/llvm/Module.h @@ -0,0 +1,425 @@ +//===-- llvm/Module.h - C++ class to represent a VM module ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file This file contains the declarations for the Module class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MODULE_H +#define LLVM_MODULE_H + +#include "llvm/Function.h" +#include "llvm/GlobalVariable.h" +#include "llvm/GlobalAlias.h" +#include "llvm/Support/DataTypes.h" +#include <vector> + +namespace llvm { + +class GlobalValueRefMap; // Used by ConstantVals.cpp +class FunctionType; + +template<> struct ilist_traits<Function> + : public SymbolTableListTraits<Function, Module> { + // createSentinel is used to create a node that marks the end of the list. + static Function *createSentinel(); + static void destroySentinel(Function *F) { delete F; } + static iplist<Function> &getList(Module *M); + static inline ValueSymbolTable *getSymTab(Module *M); + static int getListOffset(); +}; +template<> struct ilist_traits<GlobalVariable> + : public SymbolTableListTraits<GlobalVariable, Module> { + // createSentinel is used to create a node that marks the end of the list. + static GlobalVariable *createSentinel(); + static void destroySentinel(GlobalVariable *GV) { delete GV; } + static iplist<GlobalVariable> &getList(Module *M); + static inline ValueSymbolTable *getSymTab(Module *M); + static int getListOffset(); +}; +template<> struct ilist_traits<GlobalAlias> + : public SymbolTableListTraits<GlobalAlias, Module> { + // createSentinel is used to create a node that marks the end of the list. + static GlobalAlias *createSentinel(); + static void destroySentinel(GlobalAlias *GA) { delete GA; } + static iplist<GlobalAlias> &getList(Module *M); + static inline ValueSymbolTable *getSymTab(Module *M); + static int getListOffset(); +}; + +/// A Module instance is used to store all the information related to an +/// LLVM module. Modules are the top level container of all other LLVM +/// Intermediate Representation (IR) objects. Each module directly contains a +/// list of globals variables, a list of functions, a list of libraries (or +/// other modules) this module depends on, a symbol table, and various data +/// about the target's characteristics. +/// +/// A module maintains a GlobalValRefMap object that is used to hold all +/// constant references to global variables in the module. When a global +/// variable is destroyed, it should have no entries in the GlobalValueRefMap. +/// @brief The main container class for the LLVM Intermediate Representation. +class Module { +/// @name Types And Enumerations +/// @{ +public: + /// The type for the list of global variables. + typedef iplist<GlobalVariable> GlobalListType; + /// The type for the list of functions. + typedef iplist<Function> FunctionListType; + /// The type for the list of aliases. + typedef iplist<GlobalAlias> AliasListType; + + /// The type for the list of dependent libraries. + typedef std::vector<std::string> LibraryListType; + + /// The Global Variable iterator. + typedef GlobalListType::iterator global_iterator; + /// The Global Variable constant iterator. + typedef GlobalListType::const_iterator const_global_iterator; + + /// The Function iterators. + typedef FunctionListType::iterator iterator; + /// The Function constant iterator + typedef FunctionListType::const_iterator const_iterator; + + /// The Global Alias iterators. + typedef AliasListType::iterator alias_iterator; + /// The Global Alias constant iterator + typedef AliasListType::const_iterator const_alias_iterator; + + /// The Library list iterator. + typedef LibraryListType::const_iterator lib_iterator; + + /// An enumeration for describing the endianess of the target machine. + enum Endianness { AnyEndianness, LittleEndian, BigEndian }; + + /// An enumeration for describing the size of a pointer on the target machine. + enum PointerSize { AnyPointerSize, Pointer32, Pointer64 }; + +/// @} +/// @name Member Variables +/// @{ +private: + GlobalListType GlobalList; ///< The Global Variables in the module + FunctionListType FunctionList; ///< The Functions in the module + AliasListType AliasList; ///< The Aliases in the module + LibraryListType LibraryList; ///< The Libraries needed by the module + std::string GlobalScopeAsm; ///< Inline Asm at global scope. + ValueSymbolTable *ValSymTab; ///< Symbol table for values + TypeSymbolTable *TypeSymTab; ///< Symbol table for types + std::string ModuleID; ///< Human readable identifier for the module + std::string TargetTriple; ///< Platform target triple Module compiled on + std::string DataLayout; ///< Target data description + + friend class Constant; + +/// @} +/// @name Constructors +/// @{ +public: + /// The Module constructor. Note that there is no default constructor. You + /// must provide a name for the module upon construction. + explicit Module(const std::string &ModuleID); + /// The module destructor. This will dropAllReferences. + ~Module(); + +/// @} +/// @name Module Level Accessors +/// @{ +public: + /// Get the module identifier which is, essentially, the name of the module. + /// @returns the module identifier as a string + const std::string &getModuleIdentifier() const { return ModuleID; } + + /// Get the data layout string for the module's target platform. This encodes + /// the type sizes and alignments expected by this module. + /// @returns the data layout as a string + const std::string& getDataLayout() const { return DataLayout; } + + /// Get the target triple which is a string describing the target host. + /// @returns a string containing the target triple. + const std::string &getTargetTriple() const { return TargetTriple; } + + /// Get the target endian information. + /// @returns Endianess - an enumeration for the endianess of the target + Endianness getEndianness() const; + + /// Get the target pointer size. + /// @returns PointerSize - an enumeration for the size of the target's pointer + PointerSize getPointerSize() const; + + /// Get any module-scope inline assembly blocks. + /// @returns a string containing the module-scope inline assembly blocks. + const std::string &getModuleInlineAsm() const { return GlobalScopeAsm; } +/// @} +/// @name Module Level Mutators +/// @{ +public: + + /// Set the module identifier. + void setModuleIdentifier(const std::string &ID) { ModuleID = ID; } + + /// Set the data layout + void setDataLayout(const std::string& DL) { DataLayout = DL; } + + /// Set the target triple. + void setTargetTriple(const std::string &T) { TargetTriple = T; } + + /// Set the module-scope inline assembly blocks. + void setModuleInlineAsm(const std::string &Asm) { GlobalScopeAsm = Asm; } + + /// Append to the module-scope inline assembly blocks, automatically + /// appending a newline to the end. + void appendModuleInlineAsm(const std::string &Asm) { + GlobalScopeAsm += Asm; + GlobalScopeAsm += '\n'; + } + +/// @} +/// @name Function Accessors +/// @{ +public: + /// getOrInsertFunction - Look up the specified function in the module symbol + /// table. Four possibilities: + /// 1. If it does not exist, add a prototype for the function and return it. + /// 2. If it exists, and has internal linkage, the existing function is + /// renamed and a new one is inserted. + /// 3. Otherwise, if the existing function has the correct prototype, return + /// the existing function. + /// 4. Finally, the function exists but has the wrong prototype: return the + /// function with a constantexpr cast to the right prototype. + Constant *getOrInsertFunction(const std::string &Name, const FunctionType *T); + + /// getOrInsertFunction - Look up the specified function in the module symbol + /// table. If it does not exist, add a prototype for the function and return + /// it. This function guarantees to return a constant of pointer to the + /// specified function type or a ConstantExpr BitCast of that type if the + /// named function has a different type. This version of the method takes a + /// null terminated list of function arguments, which makes it easier for + /// clients to use. + Constant *getOrInsertFunction(const std::string &Name, const Type *RetTy,...) + END_WITH_NULL; + + /// getFunction - Look up the specified function in the module symbol table. + /// If it does not exist, return null. + Function *getFunction(const std::string &Name) const; + +/// @} +/// @name Global Variable Accessors +/// @{ +public: + /// getGlobalVariable - Look up the specified global variable in the module + /// symbol table. If it does not exist, return null. The type argument + /// should be the underlying type of the global, i.e., it should not have + /// the top-level PointerType, which represents the address of the global. + /// If AllowInternal is set to true, this function will return types that + /// have InternalLinkage. By default, these types are not returned. + GlobalVariable *getGlobalVariable(const std::string &Name, + bool AllowInternal = false) const; + + /// getNamedGlobal - Return the first 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(const std::string &Name) const { + return getGlobalVariable(Name, true); + } + +/// @} +/// @name Global Variable Accessors +/// @{ +public: + /// getNamedGlobal - Return the first global alias in the module with the + /// specified name, of arbitrary type. This method returns null if a global + /// with the specified name is not found. + GlobalAlias *getNamedAlias(const std::string &Name) const; + +/// @} +/// @name Type Accessors +/// @{ +public: + /// addTypeName - Insert an entry in the symbol table mapping Str to Type. If + /// there is already an entry for this name, true is returned and the symbol + /// table is not modified. + bool addTypeName(const std::string &Name, const Type *Ty); + + /// getTypeName - If there is at least one entry in the symbol table for the + /// specified type, return it. + std::string getTypeName(const Type *Ty) const; + + /// getTypeByName - Return the type with the specified name in this module, or + /// null if there is none by that name. + const Type *getTypeByName(const std::string &Name) const; + +/// @} +/// @name Direct access to the globals list, functions list, and symbol table +/// @{ +public: + /// Get the Module's list of global variables (constant). + const GlobalListType &getGlobalList() const { return GlobalList; } + /// Get the Module's list of global variables. + GlobalListType &getGlobalList() { return GlobalList; } + /// Get the Module's list of functions (constant). + const FunctionListType &getFunctionList() const { return FunctionList; } + /// Get the Module's list of functions. + FunctionListType &getFunctionList() { return FunctionList; } + /// Get the Module's list of aliases (constant). + const AliasListType &getAliasList() const { return AliasList; } + /// Get the Module's list of aliases. + AliasListType &getAliasList() { return AliasList; } + /// Get the symbol table of global variable and function identifiers + const ValueSymbolTable &getValueSymbolTable() const { return *ValSymTab; } + /// Get the Module's symbol table of global variable and function identifiers. + ValueSymbolTable &getValueSymbolTable() { return *ValSymTab; } + /// Get the symbol table of types + const TypeSymbolTable &getTypeSymbolTable() const { return *TypeSymTab; } + /// Get the Module's symbol table of types + TypeSymbolTable &getTypeSymbolTable() { return *TypeSymTab; } + +/// @} +/// @name Global Variable Iteration +/// @{ +public: + /// Get an iterator to the first global variable + global_iterator global_begin() { return GlobalList.begin(); } + /// Get a constant iterator to the first global variable + const_global_iterator global_begin() const { return GlobalList.begin(); } + /// Get an iterator to the last global variable + global_iterator global_end () { return GlobalList.end(); } + /// Get a constant iterator to the last global variable + const_global_iterator global_end () const { return GlobalList.end(); } + /// Determine if the list of globals is empty. + bool global_empty() const { return GlobalList.empty(); } + +/// @} +/// @name Function Iteration +/// @{ +public: + /// Get an iterator to the first function. + iterator begin() { return FunctionList.begin(); } + /// Get a constant iterator to the first function. + const_iterator begin() const { return FunctionList.begin(); } + /// Get an iterator to the last function. + iterator end () { return FunctionList.end(); } + /// Get a constant iterator to the last function. + const_iterator end () const { return FunctionList.end(); } + /// Determine how many functions are in the Module's list of functions. + size_t size() const { return FunctionList.size(); } + /// Determine if the list of functions is empty. + bool empty() const { return FunctionList.empty(); } + +/// @} +/// @name Dependent Library Iteration +/// @{ +public: + /// @brief Get a constant iterator to beginning of dependent library list. + inline lib_iterator lib_begin() const { return LibraryList.begin(); } + /// @brief Get a constant iterator to end of dependent library list. + inline lib_iterator lib_end() const { return LibraryList.end(); } + /// @brief Returns the number of items in the list of libraries. + inline size_t lib_size() const { return LibraryList.size(); } + /// @brief Add a library to the list of dependent libraries + void addLibrary(const std::string& Lib); + /// @brief Remove a library from the list of dependent libraries + void removeLibrary(const std::string& Lib); + /// @brief Get all the libraries + inline const LibraryListType& getLibraries() const { return LibraryList; } + +/// @} +/// @name Alias Iteration +/// @{ +public: + /// Get an iterator to the first alias. + alias_iterator alias_begin() { return AliasList.begin(); } + /// Get a constant iterator to the first alias. + const_alias_iterator alias_begin() const { return AliasList.begin(); } + /// Get an iterator to the last alias. + alias_iterator alias_end () { return AliasList.end(); } + /// Get a constant iterator to the last alias. + const_alias_iterator alias_end () const { return AliasList.end(); } + /// Determine how many functions are in the Module's list of aliases. + size_t alias_size () const { return AliasList.size(); } + /// Determine if the list of aliases is empty. + bool alias_empty() const { return AliasList.empty(); } + +/// @} +/// @name Utility functions for printing and dumping Module objects +/// @{ +public: + /// Print the module to an output stream + void print(std::ostream &OS) const { print(OS, 0); } + void print(std::ostream *OS) const { if (OS) print(*OS); } + /// Print the module to an output stream with AssemblyAnnotationWriter. + void print(std::ostream &OS, AssemblyAnnotationWriter *AAW) const; + void print(std::ostream *OS, AssemblyAnnotationWriter *AAW) const { + if (OS) print(*OS, AAW); + } + /// Dump the module to std::cerr (for debugging). + void dump() const; + /// This function causes all the subinstructions to "let go" of all references + /// that they are maintaining. This allows one to 'delete' a whole class at + /// a time, even though there may be circular references... first all + /// references are dropped, and all use counts go to zero. Then everything + /// is delete'd for real. Note that no operations are valid on an object + /// that has "dropped all references", except operator delete. + void dropAllReferences(); +/// @} + + static unsigned getFunctionListOffset() { + Module *Obj = 0; + return unsigned(reinterpret_cast<uintptr_t>(&Obj->FunctionList)); + } + static unsigned getGlobalVariableListOffset() { + Module *Obj = 0; + return unsigned(reinterpret_cast<uintptr_t>(&Obj->GlobalList)); + } + static unsigned getAliasListOffset() { + Module *Obj = 0; + return unsigned(reinterpret_cast<uintptr_t>(&Obj->AliasList)); + } +}; + +/// An iostream inserter for modules. +inline std::ostream &operator<<(std::ostream &O, const Module &M) { + M.print(O); + return O; +} + +inline ValueSymbolTable * +ilist_traits<Function>::getSymTab(Module *M) { + return M ? &M->getValueSymbolTable() : 0; +} + +inline ValueSymbolTable * +ilist_traits<GlobalVariable>::getSymTab(Module *M) { + return M ? &M->getValueSymbolTable() : 0; +} + +inline ValueSymbolTable * +ilist_traits<GlobalAlias>::getSymTab(Module *M) { + return M ? &M->getValueSymbolTable() : 0; +} + +inline int +ilist_traits<Function>::getListOffset() { + return Module::getFunctionListOffset(); +} + +inline int +ilist_traits<GlobalVariable>::getListOffset() { + return Module::getGlobalVariableListOffset(); +} + +inline int +ilist_traits<GlobalAlias>::getListOffset() { + return Module::getAliasListOffset(); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/ModuleProvider.h b/include/llvm/ModuleProvider.h new file mode 100644 index 0000000..0a91cd1 --- /dev/null +++ b/include/llvm/ModuleProvider.h @@ -0,0 +1,88 @@ +//===-- llvm/ModuleProvider.h - Interface for module providers --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides an abstract interface for loading a module from some +// place. This interface allows incremental or random access loading of +// functions from the file. This is useful for applications like JIT compilers +// or interprocedural optimizers that do not need the entire program in memory +// at the same time. +// +//===----------------------------------------------------------------------===// + +#ifndef MODULEPROVIDER_H +#define MODULEPROVIDER_H + +#include <string> + +namespace llvm { + +class Function; +class Module; + +class ModuleProvider { +protected: + Module *TheModule; + ModuleProvider(); + +public: + virtual ~ModuleProvider(); + + /// getModule - returns the module this provider is encapsulating. + /// + Module* getModule() { return TheModule; } + + /// materializeFunction - make sure the given function is fully read. If the + /// module is corrupt, this returns true and fills in the optional string + /// with information about the problem. If successful, this returns false. + /// + virtual bool materializeFunction(Function *F, std::string *ErrInfo = 0) = 0; + + /// dematerializeFunction - If the given function is read in, and if the + /// module provider supports it, release the memory for the function, and set + /// it up to be materialized lazily. If the provider doesn't support this + /// capability, this method is a noop. + /// + virtual void dematerializeFunction(Function *F) {} + + /// materializeModule - make sure the entire Module has been completely read. + /// On error, return null and fill in the error string if specified. + /// + virtual Module* materializeModule(std::string *ErrInfo = 0) = 0; + + /// releaseModule - no longer delete the Module* when provider is destroyed. + /// On error, return null and fill in the error string if specified. + /// + virtual Module* releaseModule(std::string *ErrInfo = 0) { + // Since we're losing control of this Module, we must hand it back complete + if (!materializeModule(ErrInfo)) + return 0; + Module *tempM = TheModule; + TheModule = 0; + return tempM; + } +}; + + +/// ExistingModuleProvider - Allow conversion from a fully materialized Module +/// into a ModuleProvider, allowing code that expects a ModuleProvider to work +/// if we just have a Module. Note that the ModuleProvider takes ownership of +/// the Module specified. +struct ExistingModuleProvider : public ModuleProvider { + ExistingModuleProvider(Module *M) { + TheModule = M; + } + bool materializeFunction(Function *F, std::string *ErrInfo = 0) { + return false; + } + Module* materializeModule(std::string *ErrInfo = 0) { return TheModule; } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/ParameterAttributes.h b/include/llvm/ParameterAttributes.h new file mode 100644 index 0000000..b1cb966 --- /dev/null +++ b/include/llvm/ParameterAttributes.h @@ -0,0 +1,221 @@ +//===-- llvm/ParameterAttributes.h - Container for ParamAttrs ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the types necessary to represent the parameter attributes +// associated with functions and their calls. +// +// The implementations of these classes live in lib/VMCore/Function.cpp. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PARAMETER_ATTRIBUTES_H +#define LLVM_PARAMETER_ATTRIBUTES_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/FoldingSet.h" + +namespace llvm { +namespace ParamAttr { + +/// Function parameters and results can have attributes to indicate how they +/// should be treated by optimizations and code generation. This enumeration +/// lists the attributes that can be associated with parameters or function +/// results. +/// @brief Function parameter attributes. +enum Attributes { + None = 0, ///< No attributes have been set + ZExt = 1 << 0, ///< zero extended before/after call + SExt = 1 << 1, ///< sign extended before/after call + NoReturn = 1 << 2, ///< mark the function as not returning + InReg = 1 << 3, ///< force argument to be passed in register + StructRet = 1 << 4, ///< hidden pointer to structure to return + NoUnwind = 1 << 5, ///< Function doesn't unwind stack + NoAlias = 1 << 6, ///< Considered to not alias after call. + ByVal = 1 << 7 ///< Pass structure by value +}; + +} + +/// This is just a pair of values to associate a set of parameter attributes +/// with a parameter index. +/// @brief ParameterAttributes with a parameter index. +struct ParamAttrsWithIndex { + uint16_t attrs; ///< The attributes that are set, |'d together + uint16_t index; ///< Index of the parameter for which the attributes apply + + static ParamAttrsWithIndex get(uint16_t idx, uint16_t attrs) { + ParamAttrsWithIndex P; + P.index = idx; + P.attrs = attrs; + return P; + } +}; + +/// @brief A vector of attribute/index pairs. +typedef SmallVector<ParamAttrsWithIndex,4> ParamAttrsVector; + +/// @brief A more friendly way to reference the attributes. +typedef ParamAttr::Attributes ParameterAttributes; + +/// This class represents a list of attribute/index pairs for parameter +/// attributes. Each entry in the list contains the index of a function +/// parameter and the associated ParameterAttributes. If a parameter's index is +/// not present in the list, then no attributes are set for that parameter. The +/// list may also be empty, but this does not occur in practice. An item in +/// the list with an index of 0 refers to the function as a whole or its result. +/// To construct a ParamAttrsList, you must first fill a ParamAttrsVector with +/// the attribute/index pairs you wish to set. The list of attributes can be +/// turned into a string of mnemonics suitable for LLVM Assembly output. +/// Various accessors are provided to obtain information about the attributes. +/// Note that objects of this class are "uniqued". The \p get method can return +/// the pointer of an existing and identical instance. Consequently, reference +/// counting is necessary in order to determine when the last reference to a +/// ParamAttrsList of a given shape is dropped. Users of this class should use +/// the addRef and dropRef methods to add/drop references. When the reference +/// count goes to zero, the ParamAttrsList object is deleted. +/// This class is used by Function, CallInst and InvokeInst to represent their +/// sets of parameter attributes. +/// @brief A List of ParameterAttributes. +class ParamAttrsList : public FoldingSetNode { + /// @name Construction + /// @{ + private: + // ParamAttrsList is uniqued, these should not be publicly available + void operator=(const ParamAttrsList &); // Do not implement + ParamAttrsList(const ParamAttrsList &); // Do not implement + ParamAttrsList(); // Do not implement + ~ParamAttrsList(); // Private implementation + + /// Only the \p get method can invoke this when it wants to create a + /// new instance. + /// @brief Construct an ParamAttrsList from a ParamAttrsVector + explicit ParamAttrsList(const ParamAttrsVector &attrVec) + : attrs(attrVec), refCount(0) {} + + public: + /// This method ensures the uniqueness of ParamAttrsList instances. The + /// argument is a vector of attribute/index pairs as represented by the + /// ParamAttrsWithIndex structure. The vector is used in the construction of + /// the ParamAttrsList instance. If an instance with identical vector pairs + /// exists, it will be returned instead of creating a new instance. + /// @brief Get a ParamAttrsList instance. + static ParamAttrsList *get(const ParamAttrsVector &attrVec); + + /// @} + /// @name Accessors + /// @{ + public: + /// The parameter attributes for the \p indexth parameter are returned. + /// The 0th parameter refers to the return type of the function. Note that + /// the \p param_index is an index into the function's parameters, not an + /// index into this class's list of attributes. The result of getParamIndex + /// is always suitable input to this function. + /// @returns The all the ParameterAttributes for the \p indexth parameter + /// as a uint16_t of enumeration values OR'd together. + /// @brief Get the attributes for a parameter + uint16_t getParamAttrs(uint16_t param_index) const; + + /// This checks to see if the \p ith function parameter has the parameter + /// attribute given by \p attr set. + /// @returns true if the parameter attribute is set + /// @brief Determine if a ParameterAttributes is set + bool paramHasAttr(uint16_t i, ParameterAttributes attr) const { + return getParamAttrs(i) & attr; + } + + /// The set of ParameterAttributes set in Attributes is converted to a + /// string of equivalent mnemonics. This is, presumably, for writing out + /// the mnemonics for the assembly writer. + /// @brief Convert parameter attribute bits to text + static std::string getParamAttrsText(uint16_t Attributes); + + /// The \p Indexth parameter attribute is converted to string. + /// @brief Get the text for the parmeter attributes for one parameter. + std::string getParamAttrsTextByIndex(uint16_t Index) const { + return getParamAttrsText(getParamAttrs(Index)); + } + + /// @brief Comparison operator for ParamAttrsList + bool operator < (const ParamAttrsList& that) const { + if (this->attrs.size() < that.attrs.size()) + return true; + if (this->attrs.size() > that.attrs.size()) + return false; + for (unsigned i = 0; i < attrs.size(); ++i) { + if (attrs[i].index < that.attrs[i].index) + return true; + if (attrs[i].index > that.attrs[i].index) + return false; + if (attrs[i].attrs < that.attrs[i].attrs) + return true; + if (attrs[i].attrs > that.attrs[i].attrs) + return false; + } + return false; + } + + /// Returns the parameter index of a particular parameter attribute in this + /// list of attributes. Note that the attr_index is an index into this + /// class's list of attributes, not the index of a parameter. The result + /// is the index of the parameter. Clients generally should not use this + /// method. It is used internally by LLVM. + /// @brief Get a parameter index + uint16_t getParamIndex(unsigned attr_index) const { + return attrs[attr_index].index; + } + + uint16_t getParamAttrsAtIndex(unsigned attr_index) const { + return attrs[attr_index].attrs; + } + + /// Determines how many parameter attributes are set in this ParamAttrsList. + /// This says nothing about how many parameters the function has. It also + /// says nothing about the highest parameter index that has attributes. + /// Clients generally should not use this method. It is used internally by + /// LLVM. + /// @returns the number of parameter attributes in this ParamAttrsList. + /// @brief Return the number of parameter attributes this type has. + unsigned size() const { return attrs.size(); } + + /// Classes retaining references to ParamAttrsList objects should call this + /// method to increment the reference count. This ensures that the + /// ParamAttrsList object will not disappear until the class drops it. + /// @brief Add a reference to this instance. + void addRef() const { refCount++; } + + /// Classes retaining references to ParamAttrsList objects should call this + /// method to decrement the reference count and possibly delete the + /// ParamAttrsList object. This ensures that ParamAttrsList objects are + /// cleaned up only when the last reference to them is dropped. + /// @brief Drop a reference to this instance. + void dropRef() const { + assert(refCount != 0 && "dropRef without addRef"); + if (--refCount == 0) + delete this; + } + + /// @} + /// @name Implementation Details + /// @{ + public: + void Profile(FoldingSetNodeID &ID) const; + void dump() const; + + /// @} + /// @name Data + /// @{ + private: + ParamAttrsVector attrs; ///< The list of attributes + mutable unsigned refCount; ///< The number of references to this object + /// @} +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Pass.h b/include/llvm/Pass.h new file mode 100644 index 0000000..a5a98f5 --- /dev/null +++ b/include/llvm/Pass.h @@ -0,0 +1,418 @@ +//===- llvm/Pass.h - Base class for Passes ----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a base class that indicates that a specified class is a +// transformation pass implementation. +// +// Passes are designed this way so that it is possible to run passes in a cache +// and organizationally optimal order without having to specify it at the front +// end. This allows arbitrary passes to be strung together and have them +// executed as effeciently as possible. +// +// Passes should extend one of the classes below, depending on the guarantees +// that it can make about what will be modified as it is run. For example, most +// global optimizations should derive from FunctionPass, because they do not add +// or delete functions, they operate on the internals of the function. +// +// Note that this file #includes PassSupport.h and PassAnalysisSupport.h (at the +// bottom), so the APIs exposed by these files are also automatically available +// to all users of this file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASS_H +#define LLVM_PASS_H + +#include "llvm/Support/Streams.h" +#include <vector> +#include <deque> +#include <map> +#include <iosfwd> +#include <cassert> + +namespace llvm { + +class Value; +class BasicBlock; +class Function; +class Module; +class AnalysisUsage; +class PassInfo; +class ImmutablePass; +class PMStack; +class AnalysisResolver; +class PMDataManager; + +// AnalysisID - Use the PassInfo to identify a pass... +typedef const PassInfo* AnalysisID; + +/// Different types of internal pass managers. External pass managers +/// (PassManager and FunctionPassManager) are not represented here. +/// Ordering of pass manager types is important here. +enum PassManagerType { + PMT_Unknown = 0, + PMT_ModulePassManager = 1, /// MPPassManager + PMT_CallGraphPassManager, /// CGPassManager + PMT_FunctionPassManager, /// FPPassManager + PMT_LoopPassManager, /// LPPassManager + PMT_BasicBlockPassManager, /// BBPassManager + PMT_Last +}; + +typedef enum PassManagerType PassManagerType; + +//===----------------------------------------------------------------------===// +/// Pass interface - Implemented by all 'passes'. Subclass this if you are an +/// interprocedural optimization or you do not fit into any of the more +/// constrained passes described below. +/// +class Pass { + AnalysisResolver *Resolver; // Used to resolve analysis + intptr_t PassID; + + // AnalysisImpls - This keeps track of which passes implement the interfaces + // that are required by the current pass (to implement getAnalysis()). + // + std::vector<std::pair<const PassInfo*, Pass*> > AnalysisImpls; + + void operator=(const Pass&); // DO NOT IMPLEMENT + Pass(const Pass &); // DO NOT IMPLEMENT +public: + explicit Pass(intptr_t pid) : Resolver(0), PassID(pid) {} + virtual ~Pass(); + + /// getPassName - Return a nice clean name for a pass. This usually + /// implemented in terms of the name that is registered by one of the + /// Registration templates, but can be overloaded directly, and if nothing + /// else is available, C++ RTTI will be consulted to get a SOMEWHAT + /// intelligible name for the pass. + /// + virtual const char *getPassName() const; + + /// getPassInfo - Return the PassInfo data structure that corresponds to this + /// pass... If the pass has not been registered, this will return null. + /// + const PassInfo *getPassInfo() const; + + /// runPass - Run this pass, returning true if a modification was made to the + /// module argument. This should be implemented by all concrete subclasses. + /// + virtual bool runPass(Module &M) { return false; } + virtual bool runPass(BasicBlock&) { return false; } + + /// print - Print out the internal state of the pass. This is called by + /// Analyze to print out the contents of an analysis. Otherwise it is not + /// necessary to implement this method. Beware that the module pointer MAY be + /// null. This automatically forwards to a virtual function that does not + /// provide the Module* in case the analysis doesn't need it it can just be + /// ignored. + /// + virtual void print(std::ostream &O, const Module *M) const; + void print(std::ostream *O, const Module *M) const { if (O) print(*O, M); } + void dump() const; // dump - call print(std::cerr, 0); + + /// Each pass is responsible for assigning a pass manager to itself. + /// PMS is the stack of available pass manager. + virtual void assignPassManager(PMStack &PMS, + PassManagerType T = PMT_Unknown) {} + /// Check if available pass managers are suitable for this pass or not. + virtual void preparePassManager(PMStack &PMS) {} + + /// Return what kind of Pass Manager can manage this pass. + virtual PassManagerType getPotentialPassManagerType() const { + return PMT_Unknown; + } + + // Access AnalysisResolver + inline void setResolver(AnalysisResolver *AR) { + assert (!Resolver && "Resolver is already set"); + Resolver = AR; + } + inline AnalysisResolver *getResolver() { + assert (Resolver && "Resolver is not set"); + return Resolver; + } + + /// getAnalysisUsage - This function should be overriden by passes that need + /// analysis information to do their job. If a pass specifies that it uses a + /// particular analysis result to this function, it can then use the + /// getAnalysis<AnalysisType>() function, below. + /// + virtual void getAnalysisUsage(AnalysisUsage &Info) const { + // By default, no analysis results are used, all are invalidated. + } + + /// releaseMemory() - This member can be implemented by a pass if it wants to + /// be able to release its memory when it is no longer needed. The default + /// behavior of passes is to hold onto memory for the entire duration of their + /// lifetime (which is the entire compile time). For pipelined passes, this + /// is not a big deal because that memory gets recycled every time the pass is + /// invoked on another program unit. For IP passes, it is more important to + /// free memory when it is unused. + /// + /// Optionally implement this function to release pass memory when it is no + /// longer used. + /// + virtual void releaseMemory() {} + + // dumpPassStructure - Implement the -debug-passes=PassStructure option + virtual void dumpPassStructure(unsigned Offset = 0); + + template<typename AnalysisClass> + static const PassInfo *getClassPassInfo() { + return lookupPassInfo((intptr_t)&AnalysisClass::ID); + } + + // lookupPassInfo - Return the pass info object for the specified pass class, + // or null if it is not known. + static const PassInfo *lookupPassInfo(intptr_t TI); + + /// getAnalysisToUpdate<AnalysisType>() - This function is used by subclasses + /// to get to the analysis information that might be around that needs to be + /// updated. This is different than getAnalysis in that it can fail (ie the + /// analysis results haven't been computed), so should only be used if you + /// provide the capability to update an analysis that exists. This method is + /// often used by transformation APIs to update analysis results for a pass + /// automatically as the transform is performed. + /// + template<typename AnalysisType> + AnalysisType *getAnalysisToUpdate() const; // Defined in PassAnalysisSupport.h + + /// mustPreserveAnalysisID - This method serves the same function as + /// getAnalysisToUpdate, but works if you just have an AnalysisID. This + /// obviously cannot give you a properly typed instance of the class if you + /// don't have the class name available (use getAnalysisToUpdate if you do), + /// but it can tell you if you need to preserve the pass at least. + /// + bool mustPreserveAnalysisID(const PassInfo *AnalysisID) const; + + /// getAnalysis<AnalysisType>() - This function is used by subclasses to get + /// to the analysis information that they claim to use by overriding the + /// getAnalysisUsage function. + /// + template<typename AnalysisType> + AnalysisType &getAnalysis() const; // Defined in PassAnalysisSupport.h + + template<typename AnalysisType> + AnalysisType &getAnalysis(Function &F); // Defined in PassanalysisSupport.h + + template<typename AnalysisType> + AnalysisType &getAnalysisID(const PassInfo *PI) const; + + template<typename AnalysisType> + AnalysisType &getAnalysisID(const PassInfo *PI, Function &F); +}; + +inline std::ostream &operator<<(std::ostream &OS, const Pass &P) { + P.print(OS, 0); return OS; +} + +//===----------------------------------------------------------------------===// +/// ModulePass class - This class is used to implement unstructured +/// interprocedural optimizations and analyses. ModulePasses may do anything +/// they want to the program. +/// +class ModulePass : public Pass { +public: + /// runOnModule - Virtual method overriden by subclasses to process the module + /// being operated on. + virtual bool runOnModule(Module &M) = 0; + + virtual bool runPass(Module &M) { return runOnModule(M); } + virtual bool runPass(BasicBlock&) { return false; } + + virtual void assignPassManager(PMStack &PMS, + PassManagerType T = PMT_ModulePassManager); + + /// Return what kind of Pass Manager can manage this pass. + virtual PassManagerType getPotentialPassManagerType() const { + return PMT_ModulePassManager; + } + + explicit ModulePass(intptr_t pid) : Pass(pid) {} + // Force out-of-line virtual method. + virtual ~ModulePass(); +}; + + +//===----------------------------------------------------------------------===// +/// ImmutablePass class - This class is used to provide information that does +/// not need to be run. This is useful for things like target information and +/// "basic" versions of AnalysisGroups. +/// +class ImmutablePass : public ModulePass { +public: + /// initializePass - This method may be overriden by immutable passes to allow + /// them to perform various initialization actions they require. This is + /// primarily because an ImmutablePass can "require" another ImmutablePass, + /// and if it does, the overloaded version of initializePass may get access to + /// these passes with getAnalysis<>. + /// + virtual void initializePass() {} + + /// ImmutablePasses are never run. + /// + virtual bool runOnModule(Module &M) { return false; } + + explicit ImmutablePass(intptr_t pid) : ModulePass(pid) {} + // Force out-of-line virtual method. + virtual ~ImmutablePass(); +}; + +//===----------------------------------------------------------------------===// +/// FunctionPass class - This class is used to implement most global +/// optimizations. Optimizations should subclass this class if they meet the +/// following constraints: +/// +/// 1. Optimizations are organized globally, i.e., a function at a time +/// 2. Optimizing a function does not cause the addition or removal of any +/// functions in the module +/// +class FunctionPass : public Pass { +public: + explicit FunctionPass(intptr_t pid) : Pass(pid) {} + + /// doInitialization - Virtual method overridden by subclasses to do + /// any necessary per-module initialization. + /// + virtual bool doInitialization(Module &M) { return false; } + + /// runOnFunction - Virtual method overriden by subclasses to do the + /// per-function processing of the pass. + /// + virtual bool runOnFunction(Function &F) = 0; + + /// doFinalization - Virtual method overriden by subclasses to do any post + /// processing needed after all passes have run. + /// + virtual bool doFinalization(Module &M) { return false; } + + /// runOnModule - On a module, we run this pass by initializing, + /// ronOnFunction'ing once for every function in the module, then by + /// finalizing. + /// + virtual bool runOnModule(Module &M); + + /// run - On a function, we simply initialize, run the function, then + /// finalize. + /// + bool run(Function &F); + + virtual void assignPassManager(PMStack &PMS, + PassManagerType T = PMT_FunctionPassManager); + + /// Return what kind of Pass Manager can manage this pass. + virtual PassManagerType getPotentialPassManagerType() const { + return PMT_FunctionPassManager; + } +}; + + + +//===----------------------------------------------------------------------===// +/// BasicBlockPass class - This class is used to implement most local +/// optimizations. Optimizations should subclass this class if they +/// meet the following constraints: +/// 1. Optimizations are local, operating on either a basic block or +/// instruction at a time. +/// 2. Optimizations do not modify the CFG of the contained function, or any +/// other basic block in the function. +/// 3. Optimizations conform to all of the constraints of FunctionPasses. +/// +class BasicBlockPass : public Pass { +public: + explicit BasicBlockPass(intptr_t pid) : Pass(pid) {} + + /// doInitialization - Virtual method overridden by subclasses to do + /// any necessary per-module initialization. + /// + virtual bool doInitialization(Module &M) { return false; } + + /// doInitialization - Virtual method overridden by BasicBlockPass subclasses + /// to do any necessary per-function initialization. + /// + virtual bool doInitialization(Function &F) { return false; } + + /// runOnBasicBlock - Virtual method overriden by subclasses to do the + /// per-basicblock processing of the pass. + /// + virtual bool runOnBasicBlock(BasicBlock &BB) = 0; + + /// doFinalization - Virtual method overriden by BasicBlockPass subclasses to + /// do any post processing needed after all passes have run. + /// + virtual bool doFinalization(Function &F) { return false; } + + /// doFinalization - Virtual method overriden by subclasses to do any post + /// processing needed after all passes have run. + /// + virtual bool doFinalization(Module &M) { return false; } + + + // To run this pass on a function, we simply call runOnBasicBlock once for + // each function. + // + bool runOnFunction(Function &F); + + /// To run directly on the basic block, we initialize, runOnBasicBlock, then + /// finalize. + /// + virtual bool runPass(Module &M) { return false; } + virtual bool runPass(BasicBlock &BB); + + virtual void assignPassManager(PMStack &PMS, + PassManagerType T = PMT_BasicBlockPassManager); + + /// Return what kind of Pass Manager can manage this pass. + virtual PassManagerType getPotentialPassManagerType() const { + return PMT_BasicBlockPassManager; + } +}; + +/// PMStack +/// Top level pass manager (see PasManager.cpp) maintains active Pass Managers +/// using PMStack. Each Pass implements assignPassManager() to connect itself +/// with appropriate manager. assignPassManager() walks PMStack to find +/// suitable manager. +/// +/// PMStack is just a wrapper around standard deque that overrides pop() and +/// push() methods. +class PMStack { +public: + typedef std::deque<PMDataManager *>::reverse_iterator iterator; + iterator begin() { return S.rbegin(); } + iterator end() { return S.rend(); } + + void handleLastUserOverflow(); + + void pop(); + inline PMDataManager *top() { return S.back(); } + void push(Pass *P); + inline bool empty() { return S.empty(); } + + void dump(); +private: + std::deque<PMDataManager *> S; +}; + + +/// If the user specifies the -time-passes argument on an LLVM tool command line +/// then the value of this boolean will be true, otherwise false. +/// @brief This is the storage for the -time-passes option. +extern bool TimePassesIsEnabled; + +} // End llvm namespace + +// Include support files that contain important APIs commonly used by Passes, +// but that we want to separate out to make it easier to read the header files. +// +#include "llvm/PassSupport.h" +#include "llvm/PassAnalysisSupport.h" + +#endif diff --git a/include/llvm/PassAnalysisSupport.h b/include/llvm/PassAnalysisSupport.h new file mode 100644 index 0000000..0454f21 --- /dev/null +++ b/include/llvm/PassAnalysisSupport.h @@ -0,0 +1,240 @@ +//===- llvm/PassAnalysisSupport.h - Analysis Pass Support code --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines stuff that is used to define and "use" Analysis Passes. +// This file is automatically #included by Pass.h, so: +// +// NO .CPP FILES SHOULD INCLUDE THIS FILE DIRECTLY +// +// Instead, #include Pass.h +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASS_ANALYSIS_SUPPORT_H +#define LLVM_PASS_ANALYSIS_SUPPORT_H + +#include <vector> + +namespace llvm { + +// No need to include Pass.h, we are being included by it! + +//===----------------------------------------------------------------------===// +// AnalysisUsage - Represent the analysis usage information of a pass. This +// tracks analyses that the pass REQUIRES (must be available when the pass +// runs), REQUIRES TRANSITIVE (must be available throughout the lifetime of the +// pass), and analyses that the pass PRESERVES (the pass does not invalidate the +// results of these analyses). This information is provided by a pass to the +// Pass infrastructure through the getAnalysisUsage virtual function. +// +class AnalysisUsage { + // Sets of analyses required and preserved by a pass + std::vector<AnalysisID> Required, RequiredTransitive, Preserved; + bool PreservesAll; +public: + AnalysisUsage() : PreservesAll(false) {} + + // addRequired - Add the specified ID to the required set of the usage info + // for a pass. + // + AnalysisUsage &addRequiredID(AnalysisID ID) { + assert(ID && "Pass class not registered!"); + Required.push_back(ID); + return *this; + } + template<class PassClass> + AnalysisUsage &addRequired() { + return addRequiredID(Pass::getClassPassInfo<PassClass>()); + } + + AnalysisUsage &addRequiredTransitiveID(AnalysisID ID) { + assert(ID && "Pass class not registered!"); + Required.push_back(ID); + RequiredTransitive.push_back(ID); + return *this; + } + template<class PassClass> + AnalysisUsage &addRequiredTransitive() { + AnalysisID ID = Pass::getClassPassInfo<PassClass>(); + return addRequiredTransitiveID(ID); + } + + // addPreserved - Add the specified ID to the set of analyses preserved by + // this pass + // + AnalysisUsage &addPreservedID(AnalysisID ID) { + Preserved.push_back(ID); + return *this; + } + + template<class PassClass> + AnalysisUsage &addPreserved() { + assert(Pass::getClassPassInfo<PassClass>() && "Pass class not registered!"); + Preserved.push_back(Pass::getClassPassInfo<PassClass>()); + return *this; + } + + // setPreservesAll - Set by analyses that do not transform their input at all + void setPreservesAll() { PreservesAll = true; } + bool getPreservesAll() const { return PreservesAll; } + + /// setPreservesCFG - This function should be called by the pass, iff they do + /// not: + /// + /// 1. Add or remove basic blocks from the function + /// 2. Modify terminator instructions in any way. + /// + /// This function annotates the AnalysisUsage info object to say that analyses + /// that only depend on the CFG are preserved by this pass. + /// + void setPreservesCFG(); + + const std::vector<AnalysisID> &getRequiredSet() const { return Required; } + const std::vector<AnalysisID> &getRequiredTransitiveSet() const { + return RequiredTransitive; + } + const std::vector<AnalysisID> &getPreservedSet() const { return Preserved; } +}; + +//===----------------------------------------------------------------------===// +// AnalysisResolver - Simple interface used by Pass objects to pull all +// analysis information out of pass manager that is responsible to manage +// the pass. +// +class PMDataManager; +class AnalysisResolver { +private: + AnalysisResolver(); // DO NOT IMPLEMENT + +public: + explicit AnalysisResolver(PMDataManager &P) : PM(P) { } + + inline PMDataManager &getPMDataManager() { return PM; } + + // Find pass that is implementing PI. + Pass *findImplPass(const PassInfo *PI) { + Pass *ResultPass = 0; + for (unsigned i = 0; i < AnalysisImpls.size() ; ++i) { + if (AnalysisImpls[i].first == PI) { + ResultPass = AnalysisImpls[i].second; + break; + } + } + return ResultPass; + } + + // Find pass that is implementing PI. Initialize pass for Function F. + Pass *findImplPass(Pass *P, const PassInfo *PI, Function &F); + + void addAnalysisImplsPair(const PassInfo *PI, Pass *P) { + std::pair<const PassInfo*, Pass*> pir = std::make_pair(PI,P); + AnalysisImpls.push_back(pir); + } + + // getAnalysisToUpdate - Return an analysis result or null if it doesn't exist + Pass *getAnalysisToUpdate(AnalysisID ID, bool Direction) const; + + // AnalysisImpls - This keeps track of which passes implements the interfaces + // that are required by the current pass (to implement getAnalysis()). + // NOTE : Remove AnalysisImpls from class Pass, when AnalysisResolver + // replaces AnalysisResolver + std::vector<std::pair<const PassInfo*, Pass*> > AnalysisImpls; + +private: + // PassManager that is used to resolve analysis info + PMDataManager &PM; +}; + +/// getAnalysisToUpdate<AnalysisType>() - This function is used by subclasses +/// to get to the analysis information that might be around that needs to be +/// updated. This is different than getAnalysis in that it can fail (ie the +/// analysis results haven't been computed), so should only be used if you +/// provide the capability to update an analysis that exists. This method is +/// often used by transformation APIs to update analysis results for a pass +/// automatically as the transform is performed. +/// +template<typename AnalysisType> +AnalysisType *Pass::getAnalysisToUpdate() const { + assert(Resolver && "Pass not resident in a PassManager object!"); + + const PassInfo *PI = getClassPassInfo<AnalysisType>(); + if (PI == 0) return 0; + return dynamic_cast<AnalysisType*> + (Resolver->getAnalysisToUpdate(PI, true)); +} + +/// getAnalysis<AnalysisType>() - This function is used by subclasses to get +/// to the analysis information that they claim to use by overriding the +/// getAnalysisUsage function. +/// +template<typename AnalysisType> +AnalysisType &Pass::getAnalysis() const { + assert(Resolver &&"Pass has not been inserted into a PassManager object!"); + + return getAnalysisID<AnalysisType>(getClassPassInfo<AnalysisType>()); +} + +template<typename AnalysisType> +AnalysisType &Pass::getAnalysisID(const PassInfo *PI) const { + assert(PI && "getAnalysis for unregistered pass!"); + assert(Resolver&&"Pass has not been inserted into a PassManager object!"); + // PI *must* appear in AnalysisImpls. Because the number of passes used + // should be a small number, we just do a linear search over a (dense) + // vector. + Pass *ResultPass = Resolver->findImplPass(PI); + assert (ResultPass && + "getAnalysis*() called on an analysis that was not " + "'required' by pass!"); + + // Because the AnalysisType may not be a subclass of pass (for + // AnalysisGroups), we must use dynamic_cast here to potentially adjust the + // return pointer (because the class may multiply inherit, once from pass, + // once from AnalysisType). + // + AnalysisType *Result = dynamic_cast<AnalysisType*>(ResultPass); + assert(Result && "Pass does not implement interface required!"); + return *Result; +} + +/// getAnalysis<AnalysisType>() - This function is used by subclasses to get +/// to the analysis information that they claim to use by overriding the +/// getAnalysisUsage function. +/// +template<typename AnalysisType> +AnalysisType &Pass::getAnalysis(Function &F) { + assert(Resolver &&"Pass has not been inserted into a PassManager object!"); + + return getAnalysisID<AnalysisType>(getClassPassInfo<AnalysisType>(), F); +} + +template<typename AnalysisType> +AnalysisType &Pass::getAnalysisID(const PassInfo *PI, Function &F) { + assert(PI && "getAnalysis for unregistered pass!"); + assert(Resolver&&"Pass has not been inserted into a PassManager object!"); + // PI *must* appear in AnalysisImpls. Because the number of passes used + // should be a small number, we just do a linear search over a (dense) + // vector. + Pass *ResultPass = Resolver->findImplPass(this, PI, F); + assert (ResultPass && + "getAnalysis*() called on an analysis that was not " + "'required' by pass!"); + + // Because the AnalysisType may not be a subclass of pass (for + // AnalysisGroups), we must use dynamic_cast here to potentially adjust the + // return pointer (because the class may multiply inherit, once from pass, + // once from AnalysisType). + // + AnalysisType *Result = dynamic_cast<AnalysisType*>(ResultPass); + assert(Result && "Pass does not implement interface required!"); + return *Result; +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/PassManager.h b/include/llvm/PassManager.h new file mode 100644 index 0000000..5d936c4 --- /dev/null +++ b/include/llvm/PassManager.h @@ -0,0 +1,93 @@ +//===- llvm/PassManager.h - Container for Passes ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the PassManager class. This class is used to hold, +// maintain, and optimize execution of Passes. The PassManager class ensures +// that analysis results are available before a pass runs, and that Pass's are +// destroyed when the PassManager is destroyed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASSMANAGER_H +#define LLVM_PASSMANAGER_H + +#include "llvm/Pass.h" + +namespace llvm { + +class Pass; +class ModulePass; +class Module; +class ModuleProvider; + +class PassManagerImpl; +class FunctionPassManagerImpl; + +/// PassManager manages ModulePassManagers +class PassManager { + +public: + + PassManager(); + ~PassManager(); + + /// add - Add a pass to the queue of passes to run. This passes ownership of + /// the Pass to the PassManager. When the PassManager is destroyed, the pass + /// will be destroyed as well, so there is no need to delete the pass. This + /// implies that all passes MUST be allocated with 'new'. + void add(Pass *P); + + /// run - Execute all of the passes scheduled for execution. Keep track of + /// whether any of the passes modifies the module, and if so, return true. + bool run(Module &M); + +private: + + /// PassManagerImpl_New is the actual class. PassManager is just the + /// wraper to publish simple pass manager interface + PassManagerImpl *PM; + +}; + +/// FunctionPassManager manages FunctionPasses and BasicBlockPassManagers. +class FunctionPassManager { +public: + explicit FunctionPassManager(ModuleProvider *P); + FunctionPassManager(); + ~FunctionPassManager(); + + /// add - Add a pass to the queue of passes to run. This passes + /// ownership of the Pass to the PassManager. When the + /// PassManager_X is destroyed, the pass will be destroyed as well, so + /// there is no need to delete the pass. (TODO delete passes.) + /// This implies that all passes MUST be allocated with 'new'. + void add(Pass *P); + + /// run - Execute all of the passes scheduled for execution. Keep + /// track of whether any of the passes modifies the function, and if + /// so, return true. + /// + bool run(Function &F); + + /// doInitialization - Run all of the initializers for the function passes. + /// + bool doInitialization(); + + /// doFinalization - Run all of the initializers for the function passes. + /// + bool doFinalization(); +private: + + FunctionPassManagerImpl *FPM; + ModuleProvider *MP; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/PassManagers.h b/include/llvm/PassManagers.h new file mode 100644 index 0000000..da05647 --- /dev/null +++ b/include/llvm/PassManagers.h @@ -0,0 +1,382 @@ +//===- llvm/PassManager.h - Pass Inftrastructre classes --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Devang Patel and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the LLVM Pass Manager infrastructure. +// +//===----------------------------------------------------------------------===// + +#include "llvm/PassManager.h" +#include "llvm/ADT/SmallVector.h" +using namespace llvm; +class llvm::PMDataManager; +class llvm::PMStack; + +//===----------------------------------------------------------------------===// +// Overview: +// The Pass Manager Infrastructure manages passes. It's responsibilities are: +// +// o Manage optimization pass execution order +// o Make required Analysis information available before pass P is run +// o Release memory occupied by dead passes +// o If Analysis information is dirtied by a pass then regenerate Analysis +// information before it is consumed by another pass. +// +// Pass Manager Infrastructure uses multiple pass managers. They are +// PassManager, FunctionPassManager, MPPassManager, FPPassManager, BBPassManager. +// This class hierarcy uses multiple inheritance but pass managers do not derive +// from another pass manager. +// +// PassManager and FunctionPassManager are two top-level pass manager that +// represents the external interface of this entire pass manager infrastucture. +// +// Important classes : +// +// [o] class PMTopLevelManager; +// +// Two top level managers, PassManager and FunctionPassManager, derive from +// PMTopLevelManager. PMTopLevelManager manages information used by top level +// managers such as last user info. +// +// [o] class PMDataManager; +// +// PMDataManager manages information, e.g. list of available analysis info, +// used by a pass manager to manage execution order of passes. It also provides +// a place to implement common pass manager APIs. All pass managers derive from +// PMDataManager. +// +// [o] class BBPassManager : public FunctionPass, public PMDataManager; +// +// BBPassManager manages BasicBlockPasses. +// +// [o] class FunctionPassManager; +// +// This is a external interface used by JIT to manage FunctionPasses. This +// interface relies on FunctionPassManagerImpl to do all the tasks. +// +// [o] class FunctionPassManagerImpl : public ModulePass, PMDataManager, +// public PMTopLevelManager; +// +// FunctionPassManagerImpl is a top level manager. It manages FPPassManagers +// +// [o] class FPPassManager : public ModulePass, public PMDataManager; +// +// FPPassManager manages FunctionPasses and BBPassManagers +// +// [o] class MPPassManager : public Pass, public PMDataManager; +// +// MPPassManager manages ModulePasses and FPPassManagers +// +// [o] class PassManager; +// +// This is a external interface used by various tools to manages passes. It +// relies on PassManagerImpl to do all the tasks. +// +// [o] class PassManagerImpl : public Pass, public PMDataManager, +// public PMDTopLevelManager +// +// PassManagerImpl is a top level pass manager responsible for managing +// MPPassManagers. +//===----------------------------------------------------------------------===// + +namespace llvm { + +/// FunctionPassManager and PassManager, two top level managers, serve +/// as the public interface of pass manager infrastructure. +enum TopLevelManagerType { + TLM_Function, // FunctionPassManager + TLM_Pass // PassManager +}; + +// enums for debugging strings +enum PassDebuggingString { + EXECUTION_MSG, // "Executing Pass '" + MODIFICATION_MSG, // "' Made Modification '" + FREEING_MSG, // " Freeing Pass '" + ON_BASICBLOCK_MSG, // "' on BasicBlock '" + PassName + "'...\n" + ON_FUNCTION_MSG, // "' on Function '" + FunctionName + "'...\n" + ON_MODULE_MSG, // "' on Module '" + ModuleName + "'...\n" + ON_LOOP_MSG, // " 'on Loop ...\n'" + ON_CG_MSG // "' on Call Graph ...\n'" +}; + +//===----------------------------------------------------------------------===// +// PMTopLevelManager +// +/// PMTopLevelManager manages LastUser info and collects common APIs used by +/// top level pass managers. +class PMTopLevelManager { +public: + + virtual unsigned getNumContainedManagers() { + return PassManagers.size(); + } + + /// Schedule pass P for execution. Make sure that passes required by + /// P are run before P is run. Update analysis info maintained by + /// the manager. Remove dead passes. This is a recursive function. + void schedulePass(Pass *P); + + /// This is implemented by top level pass manager and used by + /// schedulePass() to add analysis info passes that are not available. + virtual void addTopLevelPass(Pass *P) = 0; + + /// Set pass P as the last user of the given analysis passes. + void setLastUser(std::vector<Pass *> &AnalysisPasses, Pass *P); + + /// Collect passes whose last user is P + void collectLastUses(std::vector<Pass *> &LastUses, Pass *P); + + /// Find the pass that implements Analysis AID. Search immutable + /// passes and all pass managers. If desired pass is not found + /// then return NULL. + Pass *findAnalysisPass(AnalysisID AID); + + explicit PMTopLevelManager(enum TopLevelManagerType t); + virtual ~PMTopLevelManager(); + + /// Add immutable pass and initialize it. + inline void addImmutablePass(ImmutablePass *P) { + P->initializePass(); + ImmutablePasses.push_back(P); + } + + inline std::vector<ImmutablePass *>& getImmutablePasses() { + return ImmutablePasses; + } + + void addPassManager(Pass *Manager) { + PassManagers.push_back(Manager); + } + + // Add Manager into the list of managers that are not directly + // maintained by this top level pass manager + inline void addIndirectPassManager(PMDataManager *Manager) { + IndirectPassManagers.push_back(Manager); + } + + // Print passes managed by this top level manager. + void dumpPasses() const; + void dumpArguments() const; + + void initializeAllAnalysisInfo(); + + // Active Pass Managers + PMStack activeStack; + +protected: + + /// Collection of pass managers + std::vector<Pass *> PassManagers; + +private: + + /// Collection of pass managers that are not directly maintained + /// by this pass manager + std::vector<PMDataManager *> IndirectPassManagers; + + // Map to keep track of last user of the analysis pass. + // LastUser->second is the last user of Lastuser->first. + std::map<Pass *, Pass *> LastUser; + + /// Immutable passes are managed by top level manager. + std::vector<ImmutablePass *> ImmutablePasses; +}; + + + +//===----------------------------------------------------------------------===// +// PMDataManager + +/// PMDataManager provides the common place to manage the analysis data +/// used by pass managers. +class PMDataManager { +public: + + explicit PMDataManager(int Depth) : TPM(NULL), Depth(Depth) { + initializeAnalysisInfo(); + } + + virtual ~PMDataManager(); + + /// Return true IFF pass P's required analysis set does not required new + /// manager. + bool manageablePass(Pass *P); + + /// Augment AvailableAnalysis by adding analysis made available by pass P. + void recordAvailableAnalysis(Pass *P); + + /// Remove Analysis that is not preserved by the pass + void removeNotPreservedAnalysis(Pass *P); + + /// Remove dead passes + void removeDeadPasses(Pass *P, std::string Msg, enum PassDebuggingString); + + /// Add pass P into the PassVector. Update + /// AvailableAnalysis appropriately if ProcessAnalysis is true. + void add(Pass *P, bool ProcessAnalysis = true); + + /// Add RequiredPass into list of lower level passes required by pass P. + /// RequiredPass is run on the fly by Pass Manager when P requests it + /// through getAnalysis interface. + virtual void addLowerLevelRequiredPass(Pass *P, Pass *RequiredPass) { + assert (0 && + "Unable to handle Pass that requires lower level Analysis pass"); + } + + virtual Pass * getOnTheFlyPass(Pass *P, const PassInfo *PI, Function &F) { + assert (0 && "Unable to find on the fly pass"); + return NULL; + } + + /// Initialize available analysis information. + void initializeAnalysisInfo() { + AvailableAnalysis.clear(); + for (unsigned i = 0; i < PMT_Last; ++i) + InheritedAnalysis[i] = NULL; + } + + // Return true if P preserves high level analysis used by other + // passes that are managed by this manager. + bool preserveHigherLevelAnalysis(Pass *P); + + + /// Populate RequiredPasses with analysis pass that are required by + /// pass P and are available. Populate ReqPassNotAvailable with analysis + /// pass that are required by pass P but are not available. + void collectRequiredAnalysis(SmallVector<Pass *, 8> &RequiredPasses, + SmallVector<AnalysisID, 8> &ReqPassNotAvailable, + Pass *P); + + /// All Required analyses should be available to the pass as it runs! Here + /// we fill in the AnalysisImpls member of the pass so that it can + /// successfully use the getAnalysis() method to retrieve the + /// implementations it needs. + void initializeAnalysisImpl(Pass *P); + + /// Find the pass that implements Analysis AID. If desired pass is not found + /// then return NULL. + Pass *findAnalysisPass(AnalysisID AID, bool Direction); + + // Access toplevel manager + PMTopLevelManager *getTopLevelManager() { return TPM; } + void setTopLevelManager(PMTopLevelManager *T) { TPM = T; } + + unsigned getDepth() const { return Depth; } + + // Print routines used by debug-pass + void dumpLastUses(Pass *P, unsigned Offset) const; + void dumpPassArguments() const; + void dumpPassInfo(Pass *P, enum PassDebuggingString S1, + enum PassDebuggingString S2, std::string Msg); + void dumpAnalysisSetInfo(const char *Msg, Pass *P, + const std::vector<AnalysisID> &Set) const; + + virtual unsigned getNumContainedPasses() { + return PassVector.size(); + } + + virtual PassManagerType getPassManagerType() const { + assert ( 0 && "Invalid use of getPassManagerType"); + return PMT_Unknown; + } + + std::map<AnalysisID, Pass*> *getAvailableAnalysis() { + return &AvailableAnalysis; + } + + // Collect AvailableAnalysis from all the active Pass Managers. + void populateInheritedAnalysis(PMStack &PMS) { + unsigned Index = 0; + for (PMStack::iterator I = PMS.begin(), E = PMS.end(); + I != E; ++I) + InheritedAnalysis[Index++] = (*I)->getAvailableAnalysis(); + } + +protected: + + // Top level manager. + PMTopLevelManager *TPM; + + // Collection of pass that are managed by this manager + std::vector<Pass *> PassVector; + + // Collection of Analysis provided by Parent pass manager and + // used by current pass manager. At at time there can not be more + // then PMT_Last active pass mangers. + std::map<AnalysisID, Pass *> *InheritedAnalysis[PMT_Last]; + +private: + // Set of available Analysis. This information is used while scheduling + // pass. If a pass requires an analysis which is not not available then + // equired analysis pass is scheduled to run before the pass itself is + // scheduled to run. + std::map<AnalysisID, Pass*> AvailableAnalysis; + + // Collection of higher level analysis used by the pass managed by + // this manager. + std::vector<Pass *> HigherLevelAnalysis; + + unsigned Depth; +}; + +//===----------------------------------------------------------------------===// +// FPPassManager +// +/// FPPassManager manages BBPassManagers and FunctionPasses. +/// It batches all function passes and basic block pass managers together and +/// sequence them to process one function at a time before processing next +/// function. + +class FPPassManager : public ModulePass, public PMDataManager { + +public: + static char ID; + explicit FPPassManager(int Depth) + : ModulePass((intptr_t)&ID), PMDataManager(Depth) { } + + /// run - Execute all of the passes scheduled for execution. Keep track of + /// whether any of the passes modifies the module, and if so, return true. + bool runOnFunction(Function &F); + bool runOnModule(Module &M); + + /// doInitialization - Run all of the initializers for the function passes. + /// + bool doInitialization(Module &M); + + /// doFinalization - Run all of the initializers for the function passes. + /// + bool doFinalization(Module &M); + + /// Pass Manager itself does not invalidate any analysis info. + void getAnalysisUsage(AnalysisUsage &Info) const { + Info.setPreservesAll(); + } + + // Print passes managed by this manager + void dumpPassStructure(unsigned Offset); + + virtual const char *getPassName() const { + return "Function Pass Manager"; + } + + FunctionPass *getContainedPass(unsigned N) { + assert ( N < PassVector.size() && "Pass number out of range!"); + FunctionPass *FP = static_cast<FunctionPass *>(PassVector[N]); + return FP; + } + + virtual PassManagerType getPassManagerType() const { + return PMT_FunctionPassManager; + } +}; + +} + +extern void StartPassTimer(Pass *); +extern void StopPassTimer(Pass *); diff --git a/include/llvm/PassSupport.h b/include/llvm/PassSupport.h new file mode 100644 index 0000000..f594d45 --- /dev/null +++ b/include/llvm/PassSupport.h @@ -0,0 +1,257 @@ +//===- llvm/PassSupport.h - Pass Support code -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines stuff that is used to define and "use" Passes. This file +// is automatically #included by Pass.h, so: +// +// NO .CPP FILES SHOULD INCLUDE THIS FILE DIRECTLY +// +// Instead, #include Pass.h. +// +// This file defines Pass registration code and classes used for it. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_PASS_SUPPORT_H +#define LLVM_PASS_SUPPORT_H + +#include "llvm/System/IncludeFile.h" +// No need to include Pass.h, we are being included by it! + +namespace llvm { + +class TargetMachine; + +//===--------------------------------------------------------------------------- +/// PassInfo class - An instance of this class exists for every pass known by +/// the system, and can be obtained from a live Pass by calling its +/// getPassInfo() method. These objects are set up by the RegisterPass<> +/// template, defined below. +/// +class PassInfo { + const char *PassName; // Nice name for Pass + const char *PassArgument; // Command Line argument to run this pass + intptr_t PassID; + bool IsCFGOnlyPass; // Pass only looks at the CFG. + bool IsAnalysisGroup; // True if an analysis group. + std::vector<const PassInfo*> ItfImpl;// Interfaces implemented by this pass + + Pass *(*NormalCtor)(); + +public: + /// PassInfo ctor - Do not call this directly, this should only be invoked + /// through RegisterPass. + PassInfo(const char *name, const char *arg, intptr_t pi, + Pass *(*normal)() = 0, bool isCFGOnly = false) + : PassName(name), PassArgument(arg), PassID(pi), + IsCFGOnlyPass(isCFGOnly), IsAnalysisGroup(false), NormalCtor(normal) { + } + + /// getPassName - Return the friendly name for the pass, never returns null + /// + const char *getPassName() const { return PassName; } + void setPassName(const char *Name) { PassName = Name; } + + /// getPassArgument - Return the command line option that may be passed to + /// 'opt' that will cause this pass to be run. This will return null if there + /// is no argument. + /// + const char *getPassArgument() const { return PassArgument; } + + /// getTypeInfo - Return the type_info object for the pass... + /// TODO : Rename + intptr_t getTypeInfo() const { return PassID; } + + /// isAnalysisGroup - Return true if this is an analysis group, not a normal + /// pass. + /// + bool isAnalysisGroup() const { return IsAnalysisGroup; } + void SetIsAnalysisGroup() { IsAnalysisGroup = true; } + + /// isCFGOnlyPass - return true if this pass only looks at the CFG for the + /// function. + bool isCFGOnlyPass() const { return IsCFGOnlyPass; } + + /// getNormalCtor - Return a pointer to a function, that when called, creates + /// an instance of the pass and returns it. This pointer may be null if there + /// is no default constructor for the pass. + /// + Pass *(*getNormalCtor() const)() { + return NormalCtor; + } + void setNormalCtor(Pass *(*Ctor)()) { + NormalCtor = Ctor; + } + + /// createPass() - Use this method to create an instance of this pass. + Pass *createPass() const { + assert((!isAnalysisGroup() || NormalCtor) && + "No default implementation found for analysis group!"); + assert(NormalCtor && + "Cannot call createPass on PassInfo without default ctor!"); + return NormalCtor(); + } + + /// addInterfaceImplemented - This method is called when this pass is + /// registered as a member of an analysis group with the RegisterAnalysisGroup + /// template. + /// + void addInterfaceImplemented(const PassInfo *ItfPI) { + ItfImpl.push_back(ItfPI); + } + + /// getInterfacesImplemented - Return a list of all of the analysis group + /// interfaces implemented by this pass. + /// + const std::vector<const PassInfo*> &getInterfacesImplemented() const { + return ItfImpl; + } +}; + + +//===--------------------------------------------------------------------------- +/// RegisterPass<t> template - This template class is used to notify the system +/// that a Pass is available for use, and registers it into the internal +/// database maintained by the PassManager. Unless this template is used, opt, +/// for example will not be able to see the pass and attempts to create the pass +/// will fail. This template is used in the follow manner (at global scope, in +/// your .cpp file): +/// +/// static RegisterPass<YourPassClassName> tmp("passopt", "My Pass Name"); +/// +/// This statement will cause your pass to be created by calling the default +/// constructor exposed by the pass. If you have a different constructor that +/// must be called, create a global constructor function (which takes the +/// arguments you need and returns a Pass*) and register your pass like this: +/// +/// static RegisterPass<PassClassName> tmp("passopt", "My Name"); +/// +struct RegisterPassBase { + /// getPassInfo - Get the pass info for the registered class... + /// + const PassInfo *getPassInfo() const { return &PIObj; } + + typedef Pass* (*NormalCtor_t)(); + + RegisterPassBase(const char *Name, const char *Arg, intptr_t TI, + NormalCtor_t NormalCtor = 0, bool CFGOnly = false) + : PIObj(Name, Arg, TI, NormalCtor, CFGOnly) { + registerPass(); + } + RegisterPassBase(intptr_t TI) + : PIObj("", "", TI) { + // This ctor may only be used for analysis groups: it does not auto-register + // the pass. + PIObj.SetIsAnalysisGroup(); + } + +protected: + PassInfo PIObj; // The PassInfo object for this pass + void registerPass(); + void unregisterPass(); +}; + +template<typename PassName> +Pass *callDefaultCtor() { return new PassName(); } + +template<typename PassName> +struct RegisterPass : public RegisterPassBase { + + // Register Pass using default constructor... + RegisterPass(const char *PassArg, const char *Name, bool CFGOnly = false) + : RegisterPassBase(Name, PassArg, (intptr_t)&PassName::ID, + (RegisterPassBase::NormalCtor_t)callDefaultCtor<PassName>, CFGOnly) { + } +}; + + +/// RegisterAnalysisGroup - Register a Pass as a member of an analysis _group_. +/// Analysis groups are used to define an interface (which need not derive from +/// Pass) that is required by passes to do their job. Analysis Groups differ +/// from normal analyses because any available implementation of the group will +/// be used if it is available. +/// +/// If no analysis implementing the interface is available, a default +/// implementation is created and added. A pass registers itself as the default +/// implementation by specifying 'true' as the third template argument of this +/// class. +/// +/// In addition to registering itself as an analysis group member, a pass must +/// register itself normally as well. Passes may be members of multiple groups +/// and may still be "required" specifically by name. +/// +/// The actual interface may also be registered as well (by not specifying the +/// second template argument). The interface should be registered to associate +/// a nice name with the interface. +/// +class RegisterAGBase : public RegisterPassBase { + PassInfo *InterfaceInfo; + const PassInfo *ImplementationInfo; + bool isDefaultImplementation; +protected: + explicit RegisterAGBase(intptr_t InterfaceID, + intptr_t PassID = 0, + bool isDefault = false); + void setGroupName(const char *Name); +}; + +template<typename Interface, bool Default = false> +struct RegisterAnalysisGroup : public RegisterAGBase { + explicit RegisterAnalysisGroup(RegisterPassBase &RPB) + : RegisterAGBase((intptr_t) &Interface::ID, RPB.getPassInfo()->getTypeInfo(), + Default) { + } + + explicit RegisterAnalysisGroup(const char *Name) + : RegisterAGBase((intptr_t) &Interface::ID) { + setGroupName(Name); + } +}; + + + +//===--------------------------------------------------------------------------- +/// PassRegistrationListener class - This class is meant to be derived from by +/// clients that are interested in which passes get registered and unregistered +/// at runtime (which can be because of the RegisterPass constructors being run +/// as the program starts up, or may be because a shared object just got +/// loaded). Deriving from the PassRegistationListener class automatically +/// registers your object to receive callbacks indicating when passes are loaded +/// and removed. +/// +struct PassRegistrationListener { + + /// PassRegistrationListener ctor - Add the current object to the list of + /// PassRegistrationListeners... + PassRegistrationListener(); + + /// dtor - Remove object from list of listeners... + /// + virtual ~PassRegistrationListener(); + + /// Callback functions - These functions are invoked whenever a pass is loaded + /// or removed from the current executable. + /// + virtual void passRegistered(const PassInfo *P) {} + + /// enumeratePasses - Iterate over the registered passes, calling the + /// passEnumerate callback on each PassInfo object. + /// + void enumeratePasses(); + + /// passEnumerate - Callback function invoked when someone calls + /// enumeratePasses on this PassRegistrationListener object. + /// + virtual void passEnumerate(const PassInfo *P) {} +}; + + +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/AIXDataTypesFix.h b/include/llvm/Support/AIXDataTypesFix.h new file mode 100644 index 0000000..256e45f --- /dev/null +++ b/include/llvm/Support/AIXDataTypesFix.h @@ -0,0 +1,25 @@ +//===-- llvm/Support/AIXDataTypesFix.h - Fix datatype defs ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file overrides default system-defined types and limits which cannot be +// done in DataTypes.h.in because it is processed by autoheader first, which +// comments out any #undef statement +// +//===----------------------------------------------------------------------===// + +// No include guards desired! + +#ifndef SUPPORT_DATATYPES_H +#error "AIXDataTypesFix.h must only be included via DataTypes.h!" +#endif + +// GCC is strict about defining large constants: they must have LL modifier. +// These will be defined properly at the end of DataTypes.h +#undef INT64_MAX +#undef INT64_MIN diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h new file mode 100644 index 0000000..527d4c6 --- /dev/null +++ b/include/llvm/Support/Allocator.h @@ -0,0 +1,48 @@ +//===--- Allocator.h - Simple memory allocation abstraction -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the MallocAllocator and BumpPtrAllocator interfaces. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ALLOCATOR_H +#define LLVM_SUPPORT_ALLOCATOR_H + +#include <cstdlib> + +namespace llvm { + +class MallocAllocator { +public: + MallocAllocator() {} + ~MallocAllocator() {} + + void *Allocate(unsigned Size, unsigned Alignment) { return malloc(Size); } + void Deallocate(void *Ptr) { free(Ptr); } + void PrintStats() const {} +}; + +/// BumpPtrAllocator - This allocator is useful for containers that need very +/// simple memory allocation strategies. In particular, this just keeps +/// allocating memory, and never deletes it until the entire block is dead. This +/// makes allocation speedy, but must only be used when the trade-off is ok. +class BumpPtrAllocator { + void *TheMemory; +public: + BumpPtrAllocator(); + ~BumpPtrAllocator(); + + void *Allocate(unsigned Size, unsigned Alignment); + void Deallocate(void *Ptr) {} + void PrintStats() const; +}; + +} // end namespace clang + +#endif diff --git a/include/llvm/Support/Annotation.h b/include/llvm/Support/Annotation.h new file mode 100644 index 0000000..f9d9f60 --- /dev/null +++ b/include/llvm/Support/Annotation.h @@ -0,0 +1,216 @@ +//===-- llvm/Support/Annotation.h - Annotation classes ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declarations for two classes: Annotation & Annotable. +// Using these two simple classes, anything that derives from Annotable can have +// Annotation subclasses attached to them, ready for easy retrieval. +// +// Annotations are designed to be easily attachable to various classes. +// +// The AnnotationManager class is essential for using these classes. It is +// responsible for turning Annotation name strings into tokens [unique id #'s] +// that may be used to search for and create annotations. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ANNOTATION_H +#define LLVM_SUPPORT_ANNOTATION_H + +#include <string> +#include <cassert> + +namespace llvm { + +class AnnotationID; +class Annotation; +class Annotable; +struct AnnotationManager; + +//===----------------------------------------------------------------------===// +// +// AnnotationID - This class is a thin wrapper around an unsigned integer that +// is used to hopefully prevent errors using AnnotationID's. They may be copied +// freely around and passed byvalue with little or no overhead. +// +class AnnotationID { + friend struct AnnotationManager; + unsigned ID; + + AnnotationID(); // Default ctor is disabled + inline AnnotationID(unsigned i) : ID(i) {} // Only creatable from AnnMgr +public: + inline AnnotationID(const AnnotationID &A) : ID(A.ID) {} + + inline bool operator==(const AnnotationID &A) const { + return A.ID == ID; + } + inline bool operator<(const AnnotationID &A) const { + return ID < A.ID; + } +}; + + +//===----------------------------------------------------------------------===// +// +// Annotation Class - This class serves as a base class for any specific +// annotations that you might need. Simply subclass this to add extra +// information to the annotations. +// +class Annotation { + friend class Annotable; // Annotable manipulates Next list + AnnotationID ID; // ID number, as obtained from AnnotationManager + Annotation *Next; // The next annotation in the linked list +public: + inline Annotation(AnnotationID id) : ID(id), Next(0) {} + virtual ~Annotation(); // Designed to be subclassed + + // getID - Return the unique ID# of this annotation + inline AnnotationID getID() const { return ID; } + + // getNext - Return the next annotation in the list... + inline Annotation *getNext() const { return Next; } +}; + + +//===----------------------------------------------------------------------===// +// +// Annotable - This class is used as a base class for all objects that would +// like to have annotation capability. +// +// Annotable objects keep their annotation list sorted as annotations are +// inserted and deleted. This is used to ensure that annotations with identical +// ID#'s are stored sequentially. +// +class Annotable { + mutable Annotation *AnnotationList; + + Annotable(const Annotable &); // Do not implement + void operator=(const Annotable &); // Do not implement +public: + Annotable() : AnnotationList(0) {} + ~Annotable(); + + // getAnnotation - Search the list for annotations of the specified ID. The + // pointer returned is either null (if no annotations of the specified ID + // exist), or it points to the first element of a potentially list of elements + // with identical ID #'s. + // + Annotation *getAnnotation(AnnotationID ID) const { + for (Annotation *A = AnnotationList; A; A = A->getNext()) + if (A->getID() == ID) return A; + return 0; + } + + // getOrCreateAnnotation - Search through the annotation list, if there is + // no annotation with the specified ID, then use the AnnotationManager to + // create one. + // + inline Annotation *getOrCreateAnnotation(AnnotationID ID) const; + + // addAnnotation - Insert the annotation into the list in a sorted location. + // + void addAnnotation(Annotation *A) const { + assert(A->Next == 0 && "Annotation already in list?!?"); + + Annotation **AL = &AnnotationList; + while (*AL && (*AL)->ID < A->getID()) // Find where to insert annotation + AL = &((*AL)->Next); + A->Next = *AL; // Link the annotation in + *AL = A; + } + + // unlinkAnnotation - Remove the first annotation of the specified ID... and + // then return the unlinked annotation. The annotation object is not deleted. + // + inline Annotation *unlinkAnnotation(AnnotationID ID) const { + for (Annotation **A = &AnnotationList; *A; A = &((*A)->Next)) + if ((*A)->getID() == ID) { + Annotation *Ret = *A; + *A = Ret->Next; + Ret->Next = 0; + return Ret; + } + return 0; + } + + // deleteAnnotation - Delete the first annotation of the specified ID in the + // list. Unlink unlinkAnnotation, this actually deletes the annotation object + // + bool deleteAnnotation(AnnotationID ID) const { + Annotation *A = unlinkAnnotation(ID); + delete A; + return A != 0; + } +}; + + +//===----------------------------------------------------------------------===// +// +// AnnotationManager - This class is primarily responsible for maintaining a +// one-to-one mapping between string Annotation names and Annotation ID numbers. +// +// Compared to the rest of the Annotation system, these mapping methods are +// relatively slow, so they should be avoided by locally caching Annotation +// ID #'s. These methods are safe to call at any time, even by static ctors, so +// they should be used by static ctors most of the time. +// +// This class also provides support for annotations that are created on demand +// by the Annotable::getOrCreateAnnotation method. To get this to work, simply +// register an annotation handler +// +struct AnnotationManager { + typedef Annotation *(*Factory)(AnnotationID, const Annotable *, void*); + + //===--------------------------------------------------------------------===// + // Basic ID <-> Name map functionality + + static AnnotationID getID(const std::string &Name); // Name -> ID + static const std::string &getName(AnnotationID ID); // ID -> Name + + // getID - Name -> ID + registration of a factory function for demand driven + // annotation support. + static AnnotationID getID(const std::string &Name, Factory Fact, + void *Data = 0); + + //===--------------------------------------------------------------------===// + // Annotation creation on demand support... + + // registerAnnotationFactory - This method is used to register a callback + // function used to create an annotation on demand if it is needed by the + // Annotable::getOrCreateAnnotation method. + // + static void registerAnnotationFactory(AnnotationID ID, Factory Func, + void *ExtraData = 0); + + // createAnnotation - Create an annotation of the specified ID for the + // specified object, using a register annotation creation function. + // + static Annotation *createAnnotation(AnnotationID ID, const Annotable *Obj); +}; + + + +// getOrCreateAnnotation - Search through the annotation list, if there is +// no annotation with the specified ID, then use the AnnotationManager to +// create one. +// +inline Annotation *Annotable::getOrCreateAnnotation(AnnotationID ID) const { + Annotation *A = getAnnotation(ID); // Fast path, check for preexisting ann + if (A) return A; + + // No annotation found, ask the annotation manager to create an annotation... + A = AnnotationManager::createAnnotation(ID, this); + assert(A && "AnnotationManager could not create annotation!"); + addAnnotation(A); + return A; +} + +} // End namespace llvm + +#endif diff --git a/include/llvm/Support/CFG.h b/include/llvm/Support/CFG.h new file mode 100644 index 0000000..4efefa7 --- /dev/null +++ b/include/llvm/Support/CFG.h @@ -0,0 +1,266 @@ +//===-- llvm/Support/CFG.h - Process LLVM structures as graphs --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines specializations of GraphTraits that allow Function and +// BasicBlock graphs to be treated as proper graphs for generic algorithms. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CFG_H +#define LLVM_SUPPORT_CFG_H + +#include "llvm/ADT/GraphTraits.h" +#include "llvm/Function.h" +#include "llvm/InstrTypes.h" +#include "llvm/ADT/iterator" + +namespace llvm { + +//===--------------------------------------------------------------------===// +// BasicBlock pred_iterator definition +//===--------------------------------------------------------------------===// + +template <class _Ptr, class _USE_iterator> // Predecessor Iterator +class PredIterator : public forward_iterator<_Ptr, ptrdiff_t> { + typedef forward_iterator<_Ptr, ptrdiff_t> super; + _Ptr *BB; + _USE_iterator It; +public: + typedef PredIterator<_Ptr,_USE_iterator> _Self; + typedef typename super::pointer pointer; + + inline void advancePastNonTerminators() { + // Loop to ignore non terminator uses (for example PHI nodes)... + while (It != BB->use_end() && !isa<TerminatorInst>(*It)) + ++It; + } + + inline PredIterator(_Ptr *bb) : BB(bb), It(bb->use_begin()) { + advancePastNonTerminators(); + } + inline PredIterator(_Ptr *bb, bool) : BB(bb), It(bb->use_end()) {} + + inline bool operator==(const _Self& x) const { return It == x.It; } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline pointer operator*() const { + assert(It != BB->use_end() && "pred_iterator out of range!"); + return cast<TerminatorInst>(*It)->getParent(); + } + inline pointer *operator->() const { return &(operator*()); } + + inline _Self& operator++() { // Preincrement + assert(It != BB->use_end() && "pred_iterator out of range!"); + ++It; advancePastNonTerminators(); + return *this; + } + + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } +}; + +typedef PredIterator<BasicBlock, Value::use_iterator> pred_iterator; +typedef PredIterator<const BasicBlock, + Value::use_const_iterator> pred_const_iterator; + +inline pred_iterator pred_begin(BasicBlock *BB) { return pred_iterator(BB); } +inline pred_const_iterator pred_begin(const BasicBlock *BB) { + return pred_const_iterator(BB); +} +inline pred_iterator pred_end(BasicBlock *BB) { return pred_iterator(BB, true);} +inline pred_const_iterator pred_end(const BasicBlock *BB) { + return pred_const_iterator(BB, true); +} + + + +//===--------------------------------------------------------------------===// +// BasicBlock succ_iterator definition +//===--------------------------------------------------------------------===// + +template <class Term_, class BB_> // Successor Iterator +class SuccIterator : public bidirectional_iterator<BB_, ptrdiff_t> { + const Term_ Term; + unsigned idx; + typedef bidirectional_iterator<BB_, ptrdiff_t> super; +public: + typedef SuccIterator<Term_, BB_> _Self; + typedef typename super::pointer pointer; + // TODO: This can be random access iterator, need operator+ and stuff tho + + inline SuccIterator(Term_ T) : Term(T), idx(0) { // begin iterator + assert(T && "getTerminator returned null!"); + } + inline SuccIterator(Term_ T, bool) // end iterator + : Term(T), idx(Term->getNumSuccessors()) { + assert(T && "getTerminator returned null!"); + } + + inline const _Self &operator=(const _Self &I) { + assert(Term == I.Term &&"Cannot assign iterators to two different blocks!"); + idx = I.idx; + return *this; + } + + /// getSuccessorIndex - This is used to interface between code that wants to + /// operate on terminator instructions directly. + unsigned getSuccessorIndex() const { return idx; } + + inline bool operator==(const _Self& x) const { return idx == x.idx; } + inline bool operator!=(const _Self& x) const { return !operator==(x); } + + inline pointer operator*() const { return Term->getSuccessor(idx); } + inline pointer operator->() const { return operator*(); } + + inline _Self& operator++() { ++idx; return *this; } // Preincrement + inline _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + + inline _Self& operator--() { --idx; return *this; } // Predecrement + inline _Self operator--(int) { // Postdecrement + _Self tmp = *this; --*this; return tmp; + } +}; + +typedef SuccIterator<TerminatorInst*, BasicBlock> succ_iterator; +typedef SuccIterator<const TerminatorInst*, + const BasicBlock> succ_const_iterator; + +inline succ_iterator succ_begin(BasicBlock *BB) { + return succ_iterator(BB->getTerminator()); +} +inline succ_const_iterator succ_begin(const BasicBlock *BB) { + return succ_const_iterator(BB->getTerminator()); +} +inline succ_iterator succ_end(BasicBlock *BB) { + return succ_iterator(BB->getTerminator(), true); +} +inline succ_const_iterator succ_end(const BasicBlock *BB) { + return succ_const_iterator(BB->getTerminator(), true); +} + + + +//===--------------------------------------------------------------------===// +// GraphTraits specializations for basic block graphs (CFGs) +//===--------------------------------------------------------------------===// + +// Provide specializations of GraphTraits to be able to treat a function as a +// graph of basic blocks... + +template <> struct GraphTraits<BasicBlock*> { + typedef BasicBlock NodeType; + typedef succ_iterator ChildIteratorType; + + static NodeType *getEntryNode(BasicBlock *BB) { return BB; } + static inline ChildIteratorType child_begin(NodeType *N) { + return succ_begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return succ_end(N); + } +}; + +template <> struct GraphTraits<const BasicBlock*> { + typedef const BasicBlock NodeType; + typedef succ_const_iterator ChildIteratorType; + + static NodeType *getEntryNode(const BasicBlock *BB) { return BB; } + + static inline ChildIteratorType child_begin(NodeType *N) { + return succ_begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return succ_end(N); + } +}; + +// Provide specializations of GraphTraits to be able to treat a function as a +// graph of basic blocks... and to walk it in inverse order. Inverse order for +// a function is considered to be when traversing the predecessor edges of a BB +// instead of the successor edges. +// +template <> struct GraphTraits<Inverse<BasicBlock*> > { + typedef BasicBlock NodeType; + typedef pred_iterator ChildIteratorType; + static NodeType *getEntryNode(Inverse<BasicBlock *> G) { return G.Graph; } + static inline ChildIteratorType child_begin(NodeType *N) { + return pred_begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return pred_end(N); + } +}; + +template <> struct GraphTraits<Inverse<const BasicBlock*> > { + typedef const BasicBlock NodeType; + typedef pred_const_iterator ChildIteratorType; + static NodeType *getEntryNode(Inverse<const BasicBlock*> G) { + return G.Graph; + } + static inline ChildIteratorType child_begin(NodeType *N) { + return pred_begin(N); + } + static inline ChildIteratorType child_end(NodeType *N) { + return pred_end(N); + } +}; + + + +//===--------------------------------------------------------------------===// +// GraphTraits specializations for function basic block graphs (CFGs) +//===--------------------------------------------------------------------===// + +// Provide specializations of GraphTraits to be able to treat a function as a +// graph of basic blocks... these are the same as the basic block iterators, +// except that the root node is implicitly the first node of the function. +// +template <> struct GraphTraits<Function*> : public GraphTraits<BasicBlock*> { + static NodeType *getEntryNode(Function *F) { return &F->getEntryBlock(); } + + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + 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(); } +}; +template <> struct GraphTraits<const Function*> : + public GraphTraits<const BasicBlock*> { + static NodeType *getEntryNode(const Function *F) {return &F->getEntryBlock();} + + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + 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(); } +}; + + +// Provide specializations of GraphTraits to be able to treat a function as a +// graph of basic blocks... and to walk it in inverse order. Inverse order for +// a function is considered to be when traversing the predecessor edges of a BB +// instead of the successor edges. +// +template <> struct GraphTraits<Inverse<Function*> > : + public GraphTraits<Inverse<BasicBlock*> > { + static NodeType *getEntryNode(Inverse<Function*> G) { + return &G.Graph->getEntryBlock(); + } +}; +template <> struct GraphTraits<Inverse<const Function*> > : + public GraphTraits<Inverse<const BasicBlock*> > { + static NodeType *getEntryNode(Inverse<const Function *> G) { + return &G.Graph->getEntryBlock(); + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/CallSite.h b/include/llvm/Support/CallSite.h new file mode 100644 index 0000000..e14caad --- /dev/null +++ b/include/llvm/Support/CallSite.h @@ -0,0 +1,122 @@ +//===-- llvm/Support/CallSite.h - Abstract Call & Invoke instrs -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the CallSite class, which is a handy wrapper for code that +// wants to treat Call and Invoke instructions in a generic way. +// +// NOTE: This class is supposed to have "value semantics". So it should be +// passed by value, not by reference; it should not be "new"ed or "delete"d. It +// is efficiently copyable, assignable and constructable, with cost equivalent +// to copying a pointer (notice that it has only a single data member). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CALLSITE_H +#define LLVM_SUPPORT_CALLSITE_H + +#include "llvm/Instruction.h" +#include "llvm/BasicBlock.h" + +namespace llvm { + +class CallInst; +class InvokeInst; + +class CallSite { + Instruction *I; +public: + CallSite() : I(0) {} + CallSite(CallInst *CI) : I(reinterpret_cast<Instruction*>(CI)) {} + CallSite(InvokeInst *II) : I(reinterpret_cast<Instruction*>(II)) {} + CallSite(const CallSite &CS) : I(CS.I) {} + CallSite &operator=(const CallSite &CS) { I = CS.I; return *this; } + + /// CallSite::get - This static method is sort of like a constructor. It will + /// create an appropriate call site for a Call or Invoke instruction, but it + /// can also create a null initialized CallSite object for something which is + /// NOT a call site. + /// + static CallSite get(Value *V) { + if (Instruction *I = dyn_cast<Instruction>(V)) { + if (I->getOpcode() == Instruction::Call) + return CallSite(reinterpret_cast<CallInst*>(I)); + else if (I->getOpcode() == Instruction::Invoke) + return CallSite(reinterpret_cast<InvokeInst*>(I)); + } + return CallSite(); + } + + /// getCallingConv/setCallingConv - get or set the calling convention of the + /// call. + unsigned getCallingConv() const; + void setCallingConv(unsigned CC); + + /// getType - Return the type of the instruction that generated this call site + /// + const Type *getType() const { return I->getType(); } + + /// getInstruction - Return the instruction this call site corresponds to + /// + Instruction *getInstruction() const { return I; } + + /// getCaller - Return the caller function for this call site + /// + Function *getCaller() const { return I->getParent()->getParent(); } + + /// getCalledValue - Return the pointer to function that is being called... + /// + Value *getCalledValue() const { + assert(I && "Not a call or invoke instruction!"); + return I->getOperand(0); + } + + /// getCalledFunction - Return the function being called if this is a direct + /// call, otherwise return null (if it's an indirect call). + /// + Function *getCalledFunction() const { + return dyn_cast<Function>(getCalledValue()); + } + + /// setCalledFunction - Set the callee to the specified value... + /// + void setCalledFunction(Value *V) { + assert(I && "Not a call or invoke instruction!"); + I->setOperand(0, V); + } + + Value *getArgument(unsigned ArgNo) const { + assert(arg_begin() + ArgNo < arg_end() && "Argument # out of range!"); + return *(arg_begin()+ArgNo); + } + + /// arg_iterator - The type of iterator to use when looping over actual + /// arguments at this call site... + typedef User::op_iterator arg_iterator; + + /// arg_begin/arg_end - Return iterators corresponding to the actual argument + /// list for a call site. + /// + arg_iterator arg_begin() const { + assert(I && "Not a call or invoke instruction!"); + if (I->getOpcode() == Instruction::Call) + return I->op_begin()+1; // Skip Function + else + return I->op_begin()+3; // Skip Function, BB, BB + } + arg_iterator arg_end() const { return I->op_end(); } + unsigned arg_size() const { return unsigned(arg_end() - arg_begin()); } + + bool operator<(const CallSite &CS) const { + return getInstruction() < CS.getInstruction(); + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/Casting.h b/include/llvm/Support/Casting.h new file mode 100644 index 0000000..dc31839 --- /dev/null +++ b/include/llvm/Support/Casting.h @@ -0,0 +1,303 @@ +//===-- llvm/Support/Casting.h - Allow flexible, checked, casts -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the isa<X>(), cast<X>(), dyn_cast<X>(), cast_or_null<X>(), +// and dyn_cast_or_null<X>() templates. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CASTING_H +#define LLVM_SUPPORT_CASTING_H + +#include <cassert> + +namespace llvm { + +//===----------------------------------------------------------------------===// +// isa<x> Support Templates +//===----------------------------------------------------------------------===// + +template<typename FromCl> struct isa_impl_cl; + +// Define a template that can be specialized by smart pointers to reflect the +// fact that they are automatically dereferenced, and are not involved with the +// template selection process... the default implementation is a noop. +// +template<typename From> struct simplify_type { + typedef From SimpleType; // The real type this represents... + + // An accessor to get the real value... + static SimpleType &getSimplifiedValue(From &Val) { return Val; } +}; + +template<typename From> struct simplify_type<const From> { + typedef const From SimpleType; + static SimpleType &getSimplifiedValue(const From &Val) { + return simplify_type<From>::getSimplifiedValue(static_cast<From&>(Val)); + } +}; + + +// isa<X> - Return true if the parameter to the template is an instance of the +// template type argument. Used like this: +// +// if (isa<Type*>(myVal)) { ... } +// +template <typename To, typename From> +inline bool isa_impl(const From &Val) { + return To::classof(&Val); +} + +template<typename To, typename From, typename SimpleType> +struct isa_impl_wrap { + // When From != SimplifiedType, we can simplify the type some more by using + // the simplify_type template. + static bool doit(const From &Val) { + return isa_impl_cl<const SimpleType>::template + isa<To>(simplify_type<const From>::getSimplifiedValue(Val)); + } +}; + +template<typename To, typename FromTy> +struct isa_impl_wrap<To, const FromTy, const FromTy> { + // When From == SimpleType, we are as simple as we are going to get. + static bool doit(const FromTy &Val) { + return isa_impl<To,FromTy>(Val); + } +}; + +// isa_impl_cl - Use class partial specialization to transform types to a single +// canonical form for isa_impl. +// +template<typename FromCl> +struct isa_impl_cl { + template<class ToCl> + static bool isa(const FromCl &Val) { + return isa_impl_wrap<ToCl,const FromCl, + typename simplify_type<const FromCl>::SimpleType>::doit(Val); + } +}; + +// Specialization used to strip const qualifiers off of the FromCl type... +template<typename FromCl> +struct isa_impl_cl<const FromCl> { + template<class ToCl> + static bool isa(const FromCl &Val) { + return isa_impl_cl<FromCl>::template isa<ToCl>(Val); + } +}; + +// Define pointer traits in terms of base traits... +template<class FromCl> +struct isa_impl_cl<FromCl*> { + template<class ToCl> + static bool isa(FromCl *Val) { + return isa_impl_cl<FromCl>::template isa<ToCl>(*Val); + } +}; + +// Define reference traits in terms of base traits... +template<class FromCl> +struct isa_impl_cl<FromCl&> { + template<class ToCl> + static bool isa(FromCl &Val) { + return isa_impl_cl<FromCl>::template isa<ToCl>(&Val); + } +}; + +template <class X, class Y> +inline bool isa(const Y &Val) { + return isa_impl_cl<Y>::template isa<X>(Val); +} + +//===----------------------------------------------------------------------===// +// cast<x> Support Templates +//===----------------------------------------------------------------------===// + +template<class To, class From> struct cast_retty; + + +// Calculate what type the 'cast' function should return, based on a requested +// type of To and a source type of From. +template<class To, class From> struct cast_retty_impl { + typedef To& ret_type; // Normal case, return Ty& +}; +template<class To, class From> struct cast_retty_impl<To, const From> { + typedef const To &ret_type; // Normal case, return Ty& +}; + +template<class To, class From> struct cast_retty_impl<To, From*> { + typedef To* ret_type; // Pointer arg case, return Ty* +}; + +template<class To, class From> struct cast_retty_impl<To, const From*> { + typedef const To* ret_type; // Constant pointer arg case, return const Ty* +}; + +template<class To, class From> struct cast_retty_impl<To, const From*const> { + typedef const To* ret_type; // Constant pointer arg case, return const Ty* +}; + + +template<class To, class From, class SimpleFrom> +struct cast_retty_wrap { + // When the simplified type and the from type are not the same, use the type + // simplifier to reduce the type, then reuse cast_retty_impl to get the + // resultant type. + typedef typename cast_retty<To, SimpleFrom>::ret_type ret_type; +}; + +template<class To, class FromTy> +struct cast_retty_wrap<To, FromTy, FromTy> { + // When the simplified type is equal to the from type, use it directly. + typedef typename cast_retty_impl<To,FromTy>::ret_type ret_type; +}; + +template<class To, class From> +struct cast_retty { + typedef typename cast_retty_wrap<To, From, + typename simplify_type<From>::SimpleType>::ret_type ret_type; +}; + +// Ensure the non-simple values are converted using the simplify_type template +// that may be specialized by smart pointers... +// +template<class To, class From, class SimpleFrom> struct cast_convert_val { + // This is not a simple type, use the template to simplify it... + static typename cast_retty<To, From>::ret_type doit(const From &Val) { + return cast_convert_val<To, SimpleFrom, + typename simplify_type<SimpleFrom>::SimpleType>::doit( + simplify_type<From>::getSimplifiedValue(Val)); + } +}; + +template<class To, class FromTy> struct cast_convert_val<To,FromTy,FromTy> { + // This _is_ a simple type, just cast it. + static typename cast_retty<To, FromTy>::ret_type doit(const FromTy &Val) { + return reinterpret_cast<typename cast_retty<To, FromTy>::ret_type>( + const_cast<FromTy&>(Val)); + } +}; + + + +// 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 +// on failure. But it will correctly return NULL when the input is NULL. +// Used Like this: +// +// cast<Instruction>(myVal)->getParent() +// +template <class X, class Y> +inline typename cast_retty<X, Y>::ret_type cast(const 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); +} + +// cast_or_null<X> - Functionally identical to cast, except that a null value is +// accepted. +// +template <class X, class Y> +inline typename cast_retty<X, Y*>::ret_type cast_or_null(Y *Val) { + if (Val == 0) return 0; + assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!"); + return cast<X>(Val); +} + + +// dyn_cast<X> - Return the argument parameter cast to the specified type. This +// casting operator returns null if the argument is of the wrong type, so it can +// be used to test for a type as well as cast if successful. This should be +// used in the context of an if statement like this: +// +// if (const Instruction *I = dyn_cast<Instruction>(myVal)) { ... } +// + +template <class X, class Y> +inline typename cast_retty<X, Y>::ret_type dyn_cast(Y Val) { + return isa<X>(Val) ? cast<X, Y>(Val) : 0; +} + +// dyn_cast_or_null<X> - Functionally identical to dyn_cast, except that a null +// value is accepted. +// +template <class X, class Y> +inline typename cast_retty<X, Y>::ret_type dyn_cast_or_null(Y Val) { + return (Val && isa<X>(Val)) ? cast<X, Y>(Val) : 0; +} + + +#ifdef DEBUG_CAST_OPERATORS +#include "llvm/Support/Debug.h" + +struct bar { + bar() {} +private: + bar(const bar &); +}; +struct foo { + void ext() const; + /* static bool classof(const bar *X) { + cerr << "Classof: " << X << "\n"; + return true; + }*/ +}; + +template <> inline bool isa_impl<foo,bar>(const bar &Val) { + cerr << "Classof: " << &Val << "\n"; + return true; +} + + +bar *fub(); +void test(bar &B1, const bar *B2) { + // test various configurations of const + const bar &B3 = B1; + const bar *const B4 = B2; + + // test isa + if (!isa<foo>(B1)) return; + if (!isa<foo>(B2)) return; + if (!isa<foo>(B3)) return; + if (!isa<foo>(B4)) return; + + // test cast + foo &F1 = cast<foo>(B1); + const foo *F3 = cast<foo>(B2); + const foo *F4 = cast<foo>(B2); + const foo &F8 = cast<foo>(B3); + const foo *F9 = cast<foo>(B4); + foo *F10 = cast<foo>(fub()); + + // test cast_or_null + const foo *F11 = cast_or_null<foo>(B2); + const foo *F12 = cast_or_null<foo>(B2); + const foo *F13 = cast_or_null<foo>(B4); + const foo *F14 = cast_or_null<foo>(fub()); // Shouldn't print. + + // These lines are errors... + //foo *F20 = cast<foo>(B2); // Yields const foo* + //foo &F21 = cast<foo>(B3); // Yields const foo& + //foo *F22 = cast<foo>(B4); // Yields const foo* + //foo &F23 = cast_or_null<foo>(B1); + //const foo &F24 = cast_or_null<foo>(B3); +} + +bar *fub() { return 0; } +void main() { + bar B; + test(B, &B); +} + +#endif + +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h new file mode 100644 index 0000000..23b7cf3 --- /dev/null +++ b/include/llvm/Support/CommandLine.h @@ -0,0 +1,1332 @@ +//===- llvm/Support/CommandLine.h - Command line handler --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class implements a command line argument processor that is useful when +// creating a tool. It provides a simple, minimalistic interface that is easily +// extensible and supports nonlocal (library) command line options. +// +// Note that rather than trying to figure out what this code does, you should +// read the library documentation located in docs/CommandLine.html or looks at +// the many example usages in tools/*/*.cpp +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_COMMANDLINE_H +#define LLVM_SUPPORT_COMMANDLINE_H + +#include "llvm/Support/type_traits.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Compiler.h" +#include "llvm/ADT/SmallVector.h" +#include <string> +#include <vector> +#include <utility> +#include <cstdarg> +#include <cassert> + +namespace llvm { + +/// cl Namespace - This namespace contains all of the command line option +/// processing machinery. It is intentionally a short name to make qualified +/// usage concise. +namespace cl { + +//===----------------------------------------------------------------------===// +// ParseCommandLineOptions - Command line option processing entry point. +// +void ParseCommandLineOptions(int &argc, char **argv, + const char *Overview = 0); + +//===----------------------------------------------------------------------===// +// ParseEnvironmentOptions - Environment variable option processing alternate +// entry point. +// +void ParseEnvironmentOptions(const char *progName, const char *envvar, + const char *Overview = 0); + +///===---------------------------------------------------------------------===// +/// SetVersionPrinter - Override the default (LLVM specific) version printer +/// used to print out the version when --version is given +/// on the command line. This gives other systems using the +/// CommandLine utilities to print their own version string. +void SetVersionPrinter(void (*func)()); + + +// MarkOptionsChanged - Internal helper function. +void MarkOptionsChanged(); + +//===----------------------------------------------------------------------===// +// Flags permitted to be passed to command line arguments +// + +enum NumOccurrences { // Flags for the number of occurrences allowed + Optional = 0x01, // Zero or One occurrence + ZeroOrMore = 0x02, // Zero or more occurrences allowed + Required = 0x03, // One occurrence required + OneOrMore = 0x04, // One or more occurrences required + + // ConsumeAfter - Indicates that this option is fed anything that follows the + // last positional argument required by the application (it is an error if + // there are zero positional arguments, and a ConsumeAfter option is used). + // Thus, for example, all arguments to LLI are processed until a filename is + // found. Once a filename is found, all of the succeeding arguments are + // passed, unprocessed, to the ConsumeAfter option. + // + ConsumeAfter = 0x05, + + OccurrencesMask = 0x07 +}; + +enum ValueExpected { // Is a value required for the option? + ValueOptional = 0x08, // The value can appear... or not + ValueRequired = 0x10, // The value is required to appear! + ValueDisallowed = 0x18, // A value may not be specified (for flags) + ValueMask = 0x18 +}; + +enum OptionHidden { // Control whether -help shows this option + NotHidden = 0x20, // Option included in --help & --help-hidden + Hidden = 0x40, // -help doesn't, but --help-hidden does + ReallyHidden = 0x60, // Neither --help nor --help-hidden show this arg + HiddenMask = 0x60 +}; + +// Formatting flags - This controls special features that the option might have +// that cause it to be parsed differently... +// +// Prefix - This option allows arguments that are otherwise unrecognized to be +// matched by options that are a prefix of the actual value. This is useful for +// cases like a linker, where options are typically of the form '-lfoo' or +// '-L../../include' where -l or -L are the actual flags. When prefix is +// enabled, and used, the value for the flag comes from the suffix of the +// argument. +// +// Grouping - With this option enabled, multiple letter options are allowed to +// bunch together with only a single hyphen for the whole group. This allows +// emulation of the behavior that ls uses for example: ls -la === ls -l -a +// + +enum FormattingFlags { + NormalFormatting = 0x000, // Nothing special + Positional = 0x080, // Is a positional argument, no '-' required + Prefix = 0x100, // Can this option directly prefix its value? + Grouping = 0x180, // Can this option group with other options? + FormattingMask = 0x180 // Union of the above flags. +}; + +enum MiscFlags { // Miscellaneous flags to adjust argument + CommaSeparated = 0x200, // Should this cl::list split between commas? + PositionalEatsArgs = 0x400, // Should this positional cl::list eat -args? + MiscMask = 0x600 // Union of the above flags. +}; + + + +//===----------------------------------------------------------------------===// +// Option Base class +// +class alias; +class Option { + friend void cl::ParseCommandLineOptions(int &, char **, const char *); + friend class alias; + + // handleOccurrences - Overriden by subclasses to handle the value passed into + // an argument. Should return true if there was an error processing the + // argument and the program should exit. + // + virtual bool handleOccurrence(unsigned pos, const char *ArgName, + const std::string &Arg) = 0; + + virtual enum ValueExpected getValueExpectedFlagDefault() const { + return ValueOptional; + } + + // Out of line virtual function to provide home for the class. + virtual void anchor(); + + int NumOccurrences; // The number of times specified + int Flags; // Flags for the argument + unsigned Position; // Position of last occurrence of the option + Option *NextRegistered; // Singly linked list of registered options. +public: + const char *ArgStr; // The argument string itself (ex: "help", "o") + const char *HelpStr; // The descriptive text message for --help + const char *ValueStr; // String describing what the value of this option is + + inline enum NumOccurrences getNumOccurrencesFlag() const { + return static_cast<enum NumOccurrences>(Flags & OccurrencesMask); + } + inline enum ValueExpected getValueExpectedFlag() const { + int VE = Flags & ValueMask; + return VE ? static_cast<enum ValueExpected>(VE) + : getValueExpectedFlagDefault(); + } + inline enum OptionHidden getOptionHiddenFlag() const { + return static_cast<enum OptionHidden>(Flags & HiddenMask); + } + inline enum FormattingFlags getFormattingFlag() const { + return static_cast<enum FormattingFlags>(Flags & FormattingMask); + } + inline unsigned getMiscFlags() const { + return Flags & MiscMask; + } + inline unsigned getPosition() const { return Position; } + + // hasArgStr - Return true if the argstr != "" + bool hasArgStr() const { return ArgStr[0] != 0; } + + //-------------------------------------------------------------------------=== + // Accessor functions set by OptionModifiers + // + void setArgStr(const char *S) { ArgStr = S; } + void setDescription(const char *S) { HelpStr = S; } + void setValueStr(const char *S) { ValueStr = S; } + + void setFlag(unsigned Flag, unsigned FlagMask) { + Flags &= ~FlagMask; + Flags |= Flag; + } + + void setNumOccurrencesFlag(enum NumOccurrences Val) { + setFlag(Val, OccurrencesMask); + } + void setValueExpectedFlag(enum ValueExpected Val) { setFlag(Val, ValueMask); } + void setHiddenFlag(enum OptionHidden Val) { setFlag(Val, HiddenMask); } + void setFormattingFlag(enum FormattingFlags V) { setFlag(V, FormattingMask); } + void setMiscFlag(enum MiscFlags M) { setFlag(M, M); } + void setPosition(unsigned pos) { Position = pos; } +protected: + explicit Option(unsigned DefaultFlags) + : NumOccurrences(0), Flags(DefaultFlags | NormalFormatting), Position(0), + NextRegistered(0), ArgStr(""), HelpStr(""), ValueStr("") { + assert(getNumOccurrencesFlag() != 0 && + getOptionHiddenFlag() != 0 && "Not all default flags specified!"); + } + +public: + // addArgument - Register this argument with the commandline system. + // + void addArgument(); + + Option *getNextRegisteredOption() const { return NextRegistered; } + + // Return the width of the option tag for printing... + virtual unsigned getOptionWidth() const = 0; + + // printOptionInfo - Print out information about this option. The + // to-be-maintained width is specified. + // + virtual void printOptionInfo(unsigned GlobalWidth) const = 0; + + virtual void getExtraOptionNames(std::vector<const char*> &OptionNames) {} + + // addOccurrence - Wrapper around handleOccurrence that enforces Flags + // + bool addOccurrence(unsigned pos, const char *ArgName, + const std::string &Value); + + // Prints option name followed by message. Always returns true. + bool error(std::string Message, const char *ArgName = 0); + +public: + inline int getNumOccurrences() const { return NumOccurrences; } + virtual ~Option() {} +}; + + +//===----------------------------------------------------------------------===// +// Command line option modifiers that can be used to modify the behavior of +// command line option parsers... +// + +// desc - Modifier to set the description shown in the --help output... +struct desc { + const char *Desc; + desc(const char *Str) : Desc(Str) {} + void apply(Option &O) const { O.setDescription(Desc); } +}; + +// value_desc - Modifier to set the value description shown in the --help +// output... +struct value_desc { + const char *Desc; + value_desc(const char *Str) : Desc(Str) {} + void apply(Option &O) const { O.setValueStr(Desc); } +}; + +// init - Specify a default (initial) value for the command line argument, if +// the default constructor for the argument type does not give you what you +// want. This is only valid on "opt" arguments, not on "list" arguments. +// +template<class Ty> +struct initializer { + const Ty &Init; + initializer(const Ty &Val) : Init(Val) {} + + template<class Opt> + void apply(Opt &O) const { O.setInitialValue(Init); } +}; + +template<class Ty> +initializer<Ty> init(const Ty &Val) { + return initializer<Ty>(Val); +} + + +// location - Allow the user to specify which external variable they want to +// store the results of the command line argument processing into, if they don't +// want to store it in the option itself. +// +template<class Ty> +struct LocationClass { + Ty &Loc; + LocationClass(Ty &L) : Loc(L) {} + + template<class Opt> + void apply(Opt &O) const { O.setLocation(O, Loc); } +}; + +template<class Ty> +LocationClass<Ty> location(Ty &L) { return LocationClass<Ty>(L); } + + +//===----------------------------------------------------------------------===// +// Enum valued command line option +// +#define clEnumVal(ENUMVAL, DESC) #ENUMVAL, int(ENUMVAL), DESC +#define clEnumValN(ENUMVAL, FLAGNAME, DESC) FLAGNAME, int(ENUMVAL), DESC +#define clEnumValEnd (reinterpret_cast<void*>(0)) + +// values - For custom data types, allow specifying a group of values together +// as the values that go into the mapping that the option handler uses. Note +// that the values list must always have a 0 at the end of the list to indicate +// that the list has ended. +// +template<class DataType> +class ValuesClass { + // Use a vector instead of a map, because the lists should be short, + // the overhead is less, and most importantly, it keeps them in the order + // inserted so we can print our option out nicely. + SmallVector<std::pair<const char *, std::pair<int, const char *> >,4> Values; + void processValues(va_list Vals); +public: + ValuesClass(const char *EnumName, DataType Val, const char *Desc, + va_list ValueArgs) { + // Insert the first value, which is required. + Values.push_back(std::make_pair(EnumName, std::make_pair(Val, Desc))); + + // Process the varargs portion of the values... + while (const char *EnumName = va_arg(ValueArgs, const char *)) { + DataType EnumVal = static_cast<DataType>(va_arg(ValueArgs, int)); + const char *EnumDesc = va_arg(ValueArgs, const char *); + Values.push_back(std::make_pair(EnumName, // Add value to value map + std::make_pair(EnumVal, EnumDesc))); + } + } + + template<class Opt> + void apply(Opt &O) const { + for (unsigned i = 0, e = Values.size(); i != e; ++i) + O.getParser().addLiteralOption(Values[i].first, Values[i].second.first, + Values[i].second.second); + } +}; + +template<class DataType> +ValuesClass<DataType> END_WITH_NULL values(const char *Arg, DataType Val, + const char *Desc, ...) { + va_list ValueArgs; + va_start(ValueArgs, Desc); + ValuesClass<DataType> Vals(Arg, Val, Desc, ValueArgs); + va_end(ValueArgs); + return Vals; +} + + +//===----------------------------------------------------------------------===// +// parser class - Parameterizable parser for different data types. By default, +// known data types (string, int, bool) have specialized parsers, that do what +// you would expect. The default parser, used for data types that are not +// built-in, uses a mapping table to map specific options to values, which is +// used, among other things, to handle enum types. + +//-------------------------------------------------- +// generic_parser_base - This class holds all the non-generic code that we do +// not need replicated for every instance of the generic parser. This also +// allows us to put stuff into CommandLine.cpp +// +struct generic_parser_base { + virtual ~generic_parser_base() {} // Base class should have virtual-dtor + + // getNumOptions - Virtual function implemented by generic subclass to + // indicate how many entries are in Values. + // + virtual unsigned getNumOptions() const = 0; + + // getOption - Return option name N. + virtual const char *getOption(unsigned N) const = 0; + + // getDescription - Return description N + virtual const char *getDescription(unsigned N) const = 0; + + // Return the width of the option tag for printing... + virtual unsigned getOptionWidth(const Option &O) const; + + // printOptionInfo - Print out information about this option. The + // to-be-maintained width is specified. + // + virtual void printOptionInfo(const Option &O, unsigned GlobalWidth) const; + + void initialize(Option &O) { + // All of the modifiers for the option have been processed by now, so the + // argstr field should be stable, copy it down now. + // + hasArgStr = O.hasArgStr(); + } + + void getExtraOptionNames(std::vector<const char*> &OptionNames) { + // If there has been no argstr specified, that means that we need to add an + // argument for every possible option. This ensures that our options are + // vectored to us. + if (!hasArgStr) + for (unsigned i = 0, e = getNumOptions(); i != e; ++i) + OptionNames.push_back(getOption(i)); + } + + + enum ValueExpected getValueExpectedFlagDefault() const { + // If there is an ArgStr specified, then we are of the form: + // + // -opt=O2 or -opt O2 or -optO2 + // + // In which case, the value is required. Otherwise if an arg str has not + // been specified, we are of the form: + // + // -O2 or O2 or -la (where -l and -a are separate options) + // + // If this is the case, we cannot allow a value. + // + if (hasArgStr) + return ValueRequired; + else + return ValueDisallowed; + } + + // findOption - Return the option number corresponding to the specified + // argument string. If the option is not found, getNumOptions() is returned. + // + unsigned findOption(const char *Name); + +protected: + bool hasArgStr; +}; + +// Default parser implementation - This implementation depends on having a +// mapping of recognized options to values of some sort. In addition to this, +// each entry in the mapping also tracks a help message that is printed with the +// command line option for --help. Because this is a simple mapping parser, the +// data type can be any unsupported type. +// +template <class DataType> +class parser : public generic_parser_base { +protected: + SmallVector<std::pair<const char *, + std::pair<DataType, const char *> >, 8> Values; +public: + typedef DataType parser_data_type; + + // Implement virtual functions needed by generic_parser_base + unsigned getNumOptions() const { return unsigned(Values.size()); } + const char *getOption(unsigned N) const { return Values[N].first; } + const char *getDescription(unsigned N) const { + return Values[N].second.second; + } + + // parse - Return true on error. + bool parse(Option &O, const char *ArgName, const std::string &Arg, + DataType &V) { + std::string ArgVal; + if (hasArgStr) + ArgVal = Arg; + else + ArgVal = ArgName; + + for (unsigned i = 0, e = Values.size(); i != e; ++i) + if (ArgVal == Values[i].first) { + V = Values[i].second.first; + return false; + } + + return O.error(": Cannot find option named '" + ArgVal + "'!"); + } + + /// addLiteralOption - Add an entry to the mapping table. + /// + template <class DT> + void addLiteralOption(const char *Name, const DT &V, const char *HelpStr) { + assert(findOption(Name) == Values.size() && "Option already exists!"); + Values.push_back(std::make_pair(Name, + std::make_pair(static_cast<DataType>(V),HelpStr))); + MarkOptionsChanged(); + } + + /// removeLiteralOption - Remove the specified option. + /// + void removeLiteralOption(const char *Name) { + unsigned N = findOption(Name); + assert(N != Values.size() && "Option not found!"); + Values.erase(Values.begin()+N); + } +}; + +//-------------------------------------------------- +// basic_parser - Super class of parsers to provide boilerplate code +// +struct basic_parser_impl { // non-template implementation of basic_parser<t> + virtual ~basic_parser_impl() {} + + enum ValueExpected getValueExpectedFlagDefault() const { + return ValueRequired; + } + + void getExtraOptionNames(std::vector<const char*> &OptionNames) {} + + void initialize(Option &O) {} + + // Return the width of the option tag for printing... + unsigned getOptionWidth(const Option &O) const; + + // printOptionInfo - Print out information about this option. The + // to-be-maintained width is specified. + // + void printOptionInfo(const Option &O, unsigned GlobalWidth) const; + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "value"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +// basic_parser - The real basic parser is just a template wrapper that provides +// a typedef for the provided data type. +// +template<class DataType> +struct basic_parser : public basic_parser_impl { + typedef DataType parser_data_type; +}; + +//-------------------------------------------------- +// parser<bool> +// +template<> +class parser<bool> : public basic_parser<bool> { +public: + // parse - Return true on error. + bool parse(Option &O, const char *ArgName, const std::string &Arg, bool &Val); + + enum ValueExpected getValueExpectedFlagDefault() const { + return ValueOptional; + } + + // getValueName - Do not print =<value> at all. + virtual const char *getValueName() const { return 0; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<bool>); + +//-------------------------------------------------- +// parser<boolOrDefault> +enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE }; +template<> +class parser<boolOrDefault> : public basic_parser<boolOrDefault> { +public: + // parse - Return true on error. + bool parse(Option &O, const char *ArgName, const std::string &Arg, + boolOrDefault &Val); + + enum ValueExpected getValueExpectedFlagDefault() const { + return ValueOptional; + } + + // getValueName - Do not print =<value> at all. + virtual const char *getValueName() const { return 0; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<boolOrDefault>); + +//-------------------------------------------------- +// parser<int> +// +template<> +class parser<int> : public basic_parser<int> { +public: + // parse - Return true on error. + bool parse(Option &O, const char *ArgName, const std::string &Arg, int &Val); + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "int"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<int>); + + +//-------------------------------------------------- +// parser<unsigned> +// +template<> +class parser<unsigned> : public basic_parser<unsigned> { +public: + // parse - Return true on error. + bool parse(Option &O, const char *AN, const std::string &Arg, unsigned &Val); + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "uint"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned>); + +//-------------------------------------------------- +// parser<double> +// +template<> +class parser<double> : public basic_parser<double> { +public: + // parse - Return true on error. + bool parse(Option &O, const char *AN, const std::string &Arg, double &Val); + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "number"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<double>); + +//-------------------------------------------------- +// parser<float> +// +template<> +class parser<float> : public basic_parser<float> { +public: + // parse - Return true on error. + bool parse(Option &O, const char *AN, const std::string &Arg, float &Val); + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "number"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<float>); + +//-------------------------------------------------- +// parser<std::string> +// +template<> +class parser<std::string> : public basic_parser<std::string> { +public: + // parse - Return true on error. + bool parse(Option &O, const char *AN, const std::string &Arg, + std::string &Value) { + Value = Arg; + return false; + } + + // getValueName - Overload in subclass to provide a better default value. + virtual const char *getValueName() const { return "string"; } + + // An out-of-line virtual method to provide a 'home' for this class. + virtual void anchor(); +}; + +EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<std::string>); + +//===----------------------------------------------------------------------===// +// applicator class - This class is used because we must use partial +// specialization to handle literal string arguments specially (const char* does +// not correctly respond to the apply method). Because the syntax to use this +// is a pain, we have the 'apply' method below to handle the nastiness... +// +template<class Mod> struct applicator { + template<class Opt> + static void opt(const Mod &M, Opt &O) { M.apply(O); } +}; + +// Handle const char* as a special case... +template<unsigned n> struct applicator<char[n]> { + template<class Opt> + static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +}; +template<unsigned n> struct applicator<const char[n]> { + template<class Opt> + static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +}; +template<> struct applicator<const char*> { + template<class Opt> + static void opt(const char *Str, Opt &O) { O.setArgStr(Str); } +}; + +template<> struct applicator<NumOccurrences> { + static void opt(NumOccurrences NO, Option &O) { O.setNumOccurrencesFlag(NO); } +}; +template<> struct applicator<ValueExpected> { + static void opt(ValueExpected VE, Option &O) { O.setValueExpectedFlag(VE); } +}; +template<> struct applicator<OptionHidden> { + static void opt(OptionHidden OH, Option &O) { O.setHiddenFlag(OH); } +}; +template<> struct applicator<FormattingFlags> { + static void opt(FormattingFlags FF, Option &O) { O.setFormattingFlag(FF); } +}; +template<> struct applicator<MiscFlags> { + static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); } +}; + +// apply method - Apply a modifier to an option in a type safe way. +template<class Mod, class Opt> +void apply(const Mod &M, Opt *O) { + applicator<Mod>::opt(M, *O); +} + + +//===----------------------------------------------------------------------===// +// opt_storage class + +// Default storage class definition: external storage. This implementation +// assumes the user will specify a variable to store the data into with the +// cl::location(x) modifier. +// +template<class DataType, bool ExternalStorage, bool isClass> +class opt_storage { + DataType *Location; // Where to store the object... + + void check() { + assert(Location != 0 && "cl::location(...) not specified for a command " + "line option with external storage, " + "or cl::init specified before cl::location()!!"); + } +public: + opt_storage() : Location(0) {} + + bool setLocation(Option &O, DataType &L) { + if (Location) + return O.error(": cl::location(x) specified more than once!"); + Location = &L; + return false; + } + + template<class T> + void setValue(const T &V) { + check(); + *Location = V; + } + + DataType &getValue() { check(); return *Location; } + const DataType &getValue() const { check(); return *Location; } +}; + + +// Define how to hold a class type object, such as a string. Since we can +// inherit from a class, we do so. This makes us exactly compatible with the +// object in all cases that it is used. +// +template<class DataType> +class opt_storage<DataType,false,true> : public DataType { +public: + template<class T> + void setValue(const T &V) { DataType::operator=(V); } + + DataType &getValue() { return *this; } + const DataType &getValue() const { return *this; } +}; + +// Define a partial specialization to handle things we cannot inherit from. In +// this case, we store an instance through containment, and overload operators +// to get at the value. +// +template<class DataType> +class opt_storage<DataType, false, false> { +public: + DataType Value; + + // Make sure we initialize the value with the default constructor for the + // type. + opt_storage() : Value(DataType()) {} + + template<class T> + void setValue(const T &V) { Value = V; } + DataType &getValue() { return Value; } + DataType getValue() const { return Value; } + + // If the datatype is a pointer, support -> on it. + DataType operator->() const { return Value; } +}; + + +//===----------------------------------------------------------------------===// +// opt - A scalar command line option. +// +template <class DataType, bool ExternalStorage = false, + class ParserClass = parser<DataType> > +class opt : public Option, + public opt_storage<DataType, ExternalStorage, + is_class<DataType>::value> { + ParserClass Parser; + + virtual bool handleOccurrence(unsigned pos, const char *ArgName, + const std::string &Arg) { + typename ParserClass::parser_data_type Val = + typename ParserClass::parser_data_type(); + if (Parser.parse(*this, ArgName, Arg, Val)) + return true; // Parse error! + setValue(Val); + setPosition(pos); + return false; + } + + virtual enum ValueExpected getValueExpectedFlagDefault() const { + return Parser.getValueExpectedFlagDefault(); + } + virtual void getExtraOptionNames(std::vector<const char*> &OptionNames) { + return Parser.getExtraOptionNames(OptionNames); + } + + // Forward printing stuff to the parser... + virtual unsigned getOptionWidth() const {return Parser.getOptionWidth(*this);} + virtual void printOptionInfo(unsigned GlobalWidth) const { + Parser.printOptionInfo(*this, GlobalWidth); + } + + void done() { + addArgument(); + Parser.initialize(*this); + } +public: + // setInitialValue - Used by the cl::init modifier... + void setInitialValue(const DataType &V) { this->setValue(V); } + + ParserClass &getParser() { return Parser; } + + operator DataType() const { return this->getValue(); } + + template<class T> + DataType &operator=(const T &Val) { + this->setValue(Val); + return this->getValue(); + } + + // One option... + template<class M0t> + opt(const M0t &M0) : Option(Optional | NotHidden) { + apply(M0, this); + done(); + } + + // Two options... + template<class M0t, class M1t> + opt(const M0t &M0, const M1t &M1) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); + done(); + } + + // Three options... + template<class M0t, class M1t, class M2t> + opt(const M0t &M0, const M1t &M1, + const M2t &M2) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); + done(); + } + // Four options... + template<class M0t, class M1t, class M2t, class M3t> + opt(const M0t &M0, const M1t &M1, const M2t &M2, + const M3t &M3) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + done(); + } + // Five options... + template<class M0t, class M1t, class M2t, class M3t, class M4t> + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); + done(); + } + // Six options... + template<class M0t, class M1t, class M2t, class M3t, + class M4t, class M5t> + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); + done(); + } + // Seven options... + template<class M0t, class M1t, class M2t, class M3t, + class M4t, class M5t, class M6t> + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5, + const M6t &M6) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); apply(M6, this); + done(); + } + // Eight options... + template<class M0t, class M1t, class M2t, class M3t, + class M4t, class M5t, class M6t, class M7t> + opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5, const M6t &M6, + const M7t &M7) : Option(Optional | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + done(); + } +}; + +EXTERN_TEMPLATE_INSTANTIATION(class opt<unsigned>); +EXTERN_TEMPLATE_INSTANTIATION(class opt<int>); +EXTERN_TEMPLATE_INSTANTIATION(class opt<std::string>); +EXTERN_TEMPLATE_INSTANTIATION(class opt<bool>); + +//===----------------------------------------------------------------------===// +// list_storage class + +// Default storage class definition: external storage. This implementation +// assumes the user will specify a variable to store the data into with the +// cl::location(x) modifier. +// +template<class DataType, class StorageClass> +class list_storage { + StorageClass *Location; // Where to store the object... + +public: + list_storage() : Location(0) {} + + bool setLocation(Option &O, StorageClass &L) { + if (Location) + return O.error(": cl::location(x) specified more than once!"); + Location = &L; + return false; + } + + template<class T> + void addValue(const T &V) { + assert(Location != 0 && "cl::location(...) not specified for a command " + "line option with external storage!"); + Location->push_back(V); + } +}; + + +// Define how to hold a class type object, such as a string. Since we can +// inherit from a class, we do so. This makes us exactly compatible with the +// object in all cases that it is used. +// +template<class DataType> +class list_storage<DataType, bool> : public std::vector<DataType> { +public: + template<class T> + void addValue(const T &V) { push_back(V); } +}; + + +//===----------------------------------------------------------------------===// +// list - A list of command line options. +// +template <class DataType, class Storage = bool, + class ParserClass = parser<DataType> > +class list : public Option, public list_storage<DataType, Storage> { + std::vector<unsigned> Positions; + ParserClass Parser; + + virtual enum ValueExpected getValueExpectedFlagDefault() const { + return Parser.getValueExpectedFlagDefault(); + } + virtual void getExtraOptionNames(std::vector<const char*> &OptionNames) { + return Parser.getExtraOptionNames(OptionNames); + } + + virtual bool handleOccurrence(unsigned pos, const char *ArgName, + const std::string &Arg) { + typename ParserClass::parser_data_type Val = + typename ParserClass::parser_data_type(); + if (Parser.parse(*this, ArgName, Arg, Val)) + return true; // Parse Error! + addValue(Val); + setPosition(pos); + Positions.push_back(pos); + return false; + } + + // Forward printing stuff to the parser... + virtual unsigned getOptionWidth() const {return Parser.getOptionWidth(*this);} + virtual void printOptionInfo(unsigned GlobalWidth) const { + Parser.printOptionInfo(*this, GlobalWidth); + } + + void done() { + addArgument(); + Parser.initialize(*this); + } +public: + ParserClass &getParser() { return Parser; } + + unsigned getPosition(unsigned optnum) const { + assert(optnum < this->size() && "Invalid option index"); + return Positions[optnum]; + } + + // One option... + template<class M0t> + list(const M0t &M0) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); + done(); + } + // Two options... + template<class M0t, class M1t> + list(const M0t &M0, const M1t &M1) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); + done(); + } + // Three options... + template<class M0t, class M1t, class M2t> + list(const M0t &M0, const M1t &M1, const M2t &M2) + : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); + done(); + } + // Four options... + template<class M0t, class M1t, class M2t, class M3t> + list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) + : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + done(); + } + // Five options... + template<class M0t, class M1t, class M2t, class M3t, class M4t> + list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); + done(); + } + // Six options... + template<class M0t, class M1t, class M2t, class M3t, + class M4t, class M5t> + list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); + done(); + } + // Seven options... + template<class M0t, class M1t, class M2t, class M3t, + class M4t, class M5t, class M6t> + list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5, const M6t &M6) + : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); apply(M6, this); + done(); + } + // Eight options... + template<class M0t, class M1t, class M2t, class M3t, + class M4t, class M5t, class M6t, class M7t> + list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5, const M6t &M6, + const M7t &M7) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + done(); + } +}; + +//===----------------------------------------------------------------------===// +// bits_storage class + +// Default storage class definition: external storage. This implementation +// assumes the user will specify a variable to store the data into with the +// cl::location(x) modifier. +// +template<class DataType, class StorageClass> +class bits_storage { + unsigned *Location; // Where to store the bits... + + template<class T> + static unsigned Bit(const T &V) { + unsigned BitPos = reinterpret_cast<unsigned>(V); + assert(BitPos < sizeof(unsigned) * 8 && + "enum exceeds width of bit vector!"); + return 1 << BitPos; + } + +public: + bits_storage() : Location(0) {} + + bool setLocation(Option &O, unsigned &L) { + if (Location) + return O.error(": cl::location(x) specified more than once!"); + Location = &L; + return false; + } + + template<class T> + void addValue(const T &V) { + assert(Location != 0 && "cl::location(...) not specified for a command " + "line option with external storage!"); + *Location |= Bit(V); + } + + unsigned getBits() { return *Location; } + + template<class T> + bool isSet(const T &V) { + return (*Location & Bit(V)) != 0; + } +}; + + +// Define how to hold bits. Since we can inherit from a class, we do so. +// This makes us exactly compatible with the bits in all cases that it is used. +// +template<class DataType> +class bits_storage<DataType, bool> { + unsigned Bits; // Where to store the bits... + + template<class T> + static unsigned Bit(const T &V) { + unsigned BitPos = reinterpret_cast<unsigned>(V); + assert(BitPos < sizeof(unsigned) * 8 && + "enum exceeds width of bit vector!"); + return 1 << BitPos; + } + +public: + template<class T> + void addValue(const T &V) { + Bits |= Bit(V); + } + + unsigned getBits() { return Bits; } + + template<class T> + bool isSet(const T &V) { + return (Bits & Bit(V)) != 0; + } +}; + + +//===----------------------------------------------------------------------===// +// bits - A bit vector of command options. +// +template <class DataType, class Storage = bool, + class ParserClass = parser<DataType> > +class bits : public Option, public bits_storage<DataType, Storage> { + std::vector<unsigned> Positions; + ParserClass Parser; + + virtual enum ValueExpected getValueExpectedFlagDefault() const { + return Parser.getValueExpectedFlagDefault(); + } + virtual void getExtraOptionNames(std::vector<const char*> &OptionNames) { + return Parser.getExtraOptionNames(OptionNames); + } + + virtual bool handleOccurrence(unsigned pos, const char *ArgName, + const std::string &Arg) { + typename ParserClass::parser_data_type Val = + typename ParserClass::parser_data_type(); + if (Parser.parse(*this, ArgName, Arg, Val)) + return true; // Parse Error! + addValue(Val); + setPosition(pos); + Positions.push_back(pos); + return false; + } + + // Forward printing stuff to the parser... + virtual unsigned getOptionWidth() const {return Parser.getOptionWidth(*this);} + virtual void printOptionInfo(unsigned GlobalWidth) const { + Parser.printOptionInfo(*this, GlobalWidth); + } + + void done() { + addArgument(); + Parser.initialize(*this); + } +public: + ParserClass &getParser() { return Parser; } + + unsigned getPosition(unsigned optnum) const { + assert(optnum < this->size() && "Invalid option index"); + return Positions[optnum]; + } + + // One option... + template<class M0t> + bits(const M0t &M0) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); + done(); + } + // Two options... + template<class M0t, class M1t> + bits(const M0t &M0, const M1t &M1) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); + done(); + } + // Three options... + template<class M0t, class M1t, class M2t> + bits(const M0t &M0, const M1t &M1, const M2t &M2) + : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); + done(); + } + // Four options... + template<class M0t, class M1t, class M2t, class M3t> + bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) + : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + done(); + } + // Five options... + template<class M0t, class M1t, class M2t, class M3t, class M4t> + bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); + done(); + } + // Six options... + template<class M0t, class M1t, class M2t, class M3t, + class M4t, class M5t> + bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); + done(); + } + // Seven options... + template<class M0t, class M1t, class M2t, class M3t, + class M4t, class M5t, class M6t> + bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5, const M6t &M6) + : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); apply(M6, this); + done(); + } + // Eight options... + template<class M0t, class M1t, class M2t, class M3t, + class M4t, class M5t, class M6t, class M7t> + bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, + const M4t &M4, const M5t &M5, const M6t &M6, + const M7t &M7) : Option(ZeroOrMore | NotHidden) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + apply(M4, this); apply(M5, this); apply(M6, this); apply(M7, this); + done(); + } +}; + +//===----------------------------------------------------------------------===// +// Aliased command line option (alias this name to a preexisting name) +// + +class alias : public Option { + Option *AliasFor; + virtual bool handleOccurrence(unsigned pos, const char *ArgName, + const std::string &Arg) { + return AliasFor->handleOccurrence(pos, AliasFor->ArgStr, Arg); + } + // Handle printing stuff... + virtual unsigned getOptionWidth() const; + virtual void printOptionInfo(unsigned GlobalWidth) const; + + void done() { + if (!hasArgStr()) + error(": cl::alias must have argument name specified!"); + if (AliasFor == 0) + error(": cl::alias must have an cl::aliasopt(option) specified!"); + addArgument(); + } +public: + void setAliasFor(Option &O) { + if (AliasFor) + error(": cl::alias must only have one cl::aliasopt(...) specified!"); + AliasFor = &O; + } + + // One option... + template<class M0t> + alias(const M0t &M0) : Option(Optional | Hidden), AliasFor(0) { + apply(M0, this); + done(); + } + // Two options... + template<class M0t, class M1t> + alias(const M0t &M0, const M1t &M1) : Option(Optional | Hidden), AliasFor(0) { + apply(M0, this); apply(M1, this); + done(); + } + // Three options... + template<class M0t, class M1t, class M2t> + alias(const M0t &M0, const M1t &M1, const M2t &M2) + : Option(Optional | Hidden), AliasFor(0) { + apply(M0, this); apply(M1, this); apply(M2, this); + done(); + } + // Four options... + template<class M0t, class M1t, class M2t, class M3t> + alias(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) + : Option(Optional | Hidden), AliasFor(0) { + apply(M0, this); apply(M1, this); apply(M2, this); apply(M3, this); + done(); + } +}; + +// aliasfor - Modifier to set the option an alias aliases. +struct aliasopt { + Option &Opt; + aliasopt(Option &O) : Opt(O) {} + void apply(alias &A) const { A.setAliasFor(Opt); } +}; + +// extrahelp - provide additional help at the end of the normal help +// output. All occurrences of cl::extrahelp will be accumulated and +// printed to std::cerr at the end of the regular help, just before +// exit is called. +struct extrahelp { + const char * morehelp; + extrahelp(const char* help); +}; + +void PrintVersionMessage(); +// This function just prints the help message, exactly the same way as if the +// --help option had been given on the command line. +// NOTE: THIS FUNCTION TERMINATES THE PROGRAM! +void PrintHelpMessage(); + +} // End namespace cl + +} // End namespace llvm + +#endif diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h new file mode 100644 index 0000000..06be685 --- /dev/null +++ b/include/llvm/Support/Compiler.h @@ -0,0 +1,48 @@ +//===-- llvm/Support/Compiler.h - Compiler abstraction support --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines several macros, based on the current compiler. This allows +// use of compiler-specific features in a way that remains portable. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_COMPILER_H +#define LLVM_SUPPORT_COMPILER_H + +// The VISIBILITY_HIDDEN macro, used for marking classes with the GCC-specific +// visibility("hidden") attribute. +#if __GNUC__ >= 4 +#define VISIBILITY_HIDDEN __attribute__ ((visibility("hidden"))) +#else +#define VISIBILITY_HIDDEN +#endif + + +// C++ doesn't support 'extern template' of template specializations. GCC does, +// but requires __extension__ before it. In the header, use this: +// EXTERN_TEMPLATE_INSTANTIATION(class foo<bar>); +// in the .cpp file, use this: +// TEMPLATE_INSTANTIATION(class foo<bar>); +#ifdef __GNUC__ +#define EXTERN_TEMPLATE_INSTANTIATION(X) __extension__ extern template X +#define TEMPLATE_INSTANTIATION(X) template X +#else +#define EXTERN_TEMPLATE_INSTANTIATION(X) +#define TEMPLATE_INSTANTIATION(X) +#endif + +// DISABLE_INLINE - On compilers where we have a directive to do so, mark a +// method "not for inlining". +#if (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +#define DISABLE_INLINE __attribute__((noinline)) +#else +#define DISABLE_INLINE +#endif + +#endif diff --git a/include/llvm/Support/ConstantRange.h b/include/llvm/Support/ConstantRange.h new file mode 100644 index 0000000..778827c --- /dev/null +++ b/include/llvm/Support/ConstantRange.h @@ -0,0 +1,198 @@ +//===-- llvm/Support/ConstantRange.h - Represent a range --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Represent a range of possible values that may occur when the program is run +// for an integral value. This keeps track of a lower and upper bound for the +// constant, which MAY wrap around the end of the numeric range. To do this, it +// keeps track of a [lower, upper) bound, which specifies an interval just like +// STL iterators. When used with boolean values, the following are important +// ranges: : +// +// [F, F) = {} = Empty set +// [T, F) = {T} +// [F, T) = {F} +// [T, T) = {F, T} = Full set +// +// The other integral ranges use min/max values for special range values. For +// example, for 8-bit types, it uses: +// [0, 0) = {} = Empty set +// [255, 255) = {0..255} = Full Set +// +// Note that ConstantRange always keeps unsigned values. +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_CONSTANT_RANGE_H +#define LLVM_SUPPORT_CONSTANT_RANGE_H + +#include "llvm/ADT/APInt.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Streams.h" +#include <iosfwd> + +namespace llvm { + +class ConstantRange { + APInt Lower, Upper; + static ConstantRange intersect1Wrapped(const ConstantRange &LHS, + const ConstantRange &RHS); + public: + /// Initialize a full (the default) or empty set for the specified bit width. + /// + ConstantRange(uint32_t BitWidth, bool isFullSet = true); + + /// Initialize a range to hold the single specified value. + /// + ConstantRange(const APInt &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); + + /// getLower - Return the lower value for this range... + /// + const APInt &getLower() const { return Lower; } + + /// getUpper - Return the upper value for this range... + /// + const APInt &getUpper() const { return Upper; } + + /// getBitWidth - get the bit width of this ConstantRange + /// + uint32_t getBitWidth() const { return Lower.getBitWidth(); } + + /// isFullSet - Return true if this set contains all of the elements possible + /// for this data-type + /// + bool isFullSet() const; + + /// isEmptySet - Return true if this set contains no members. + /// + bool isEmptySet() const; + + /// isWrappedSet - Return true if this set wraps around the top of the range, + /// for example: [100, 8) + /// + bool isWrappedSet() const; + + /// contains - Return true if the specified value is in the set. + /// + bool contains(const APInt &Val) const; + + /// getSingleElement - If this set contains a single element, return it, + /// otherwise return null. + /// + const APInt *getSingleElement() const { + if (Upper == Lower + 1) + return &Lower; + return 0; + } + + /// isSingleElement - Return true if this set contains exactly one member. + /// + bool isSingleElement() const { return getSingleElement() != 0; } + + /// getSetSize - Return the number of elements in this set. + /// + APInt getSetSize() const; + + /// getUnsignedMax - Return the largest unsigned value contained in the + /// ConstantRange. + /// + APInt getUnsignedMax() const; + + /// getUnsignedMin - Return the smallest unsigned value contained in the + /// ConstantRange. + /// + APInt getUnsignedMin() const; + + /// getSignedMax - Return the largest signed value contained in the + /// ConstantRange. + /// + APInt getSignedMax() const; + + /// getSignedMin - Return the smallest signed value contained in the + /// ConstantRange. + /// + APInt getSignedMin() const; + + /// operator== - Return true if this range is equal to another range. + /// + bool operator==(const ConstantRange &CR) const { + return Lower == CR.Lower && Upper == CR.Upper; + } + bool operator!=(const ConstantRange &CR) const { + return !operator==(CR); + } + + /// subtract - Subtract the specified constant from the endpoints of this + /// constant range. + ConstantRange subtract(const APInt &CI) const; + + /// intersectWith - Return the range that results from the intersection of + /// this range with another range. The resultant range is pruned as much as + /// possible, but there may be cases where elements are included that are in + /// one of the sets but not the other. For example: [100, 8) intersect [3, + /// 120) yields [3, 120) + /// + ConstantRange intersectWith(const ConstantRange &CR) const; + + /// maximalIntersectWith - Return the range that results from the intersection + /// of this range with another range. The resultant range is guaranteed to + /// include all elements contained in both input ranges, and to have the + /// smallest possible set size that does so. Because there may be two + /// intersections with the same set size, A.maximalIntersectWith(B) might not + /// be equal to B.maximalIntersectWith(A). + /// + ConstantRange maximalIntersectWith(const ConstantRange &CR) const; + + /// unionWith - Return the range that results from the union of this range + /// with another range. The resultant range is guaranteed to include the + /// elements of both sets, but may contain more. For example, [3, 9) union + /// [12,15) is [3, 15), which includes 9, 10, and 11, which were not included + /// in either set before. + /// + ConstantRange unionWith(const ConstantRange &CR) const; + + /// zeroExtend - Return a new range in the specified integer type, which must + /// be strictly larger than the current type. The returned range will + /// correspond to the possible range of values if the source range had been + /// zero extended to BitWidth. + ConstantRange zeroExtend(uint32_t BitWidth) const; + + /// signExtend - Return a new range in the specified integer type, which must + /// be strictly larger than the current type. The returned range will + /// correspond to the possible range of values if the source range had been + /// sign extended to BitWidth. + ConstantRange signExtend(uint32_t BitWidth) const; + + /// truncate - Return a new range in the specified integer type, which must be + /// strictly smaller than the current type. The returned range will + /// correspond to the possible range of values if the source range had been + /// truncated to the specified type. + ConstantRange truncate(uint32_t BitWidth) const; + + /// print - Print out the bounds to a stream... + /// + void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + + /// dump - Allow printing from a debugger easily... + /// + void dump() const; +}; + +inline std::ostream &operator<<(std::ostream &OS, const ConstantRange &CR) { + CR.print(OS); + return OS; +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/DOTGraphTraits.h b/include/llvm/Support/DOTGraphTraits.h new file mode 100644 index 0000000..ed59303 --- /dev/null +++ b/include/llvm/Support/DOTGraphTraits.h @@ -0,0 +1,122 @@ +//===-- llvm/Support/DotGraphTraits.h - Customize .dot output ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a template class that can be used to customize dot output +// graphs generated by the GraphWriter.h file. The default implementation of +// this file will produce a simple, but not very polished graph. By +// specializing this template, lots of customization opportunities are possible. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DOTGRAPHTRAITS_H +#define LLVM_SUPPORT_DOTGRAPHTRAITS_H + +#include <string> + +namespace llvm { + +/// DefaultDOTGraphTraits - This class provides the default implementations of +/// all of the DOTGraphTraits methods. If a specialization does not need to +/// override all methods here it should inherit so that it can get the default +/// implementations. +/// +struct DefaultDOTGraphTraits { + /// getGraphName - Return the label for the graph as a whole. Printed at the + /// top of the graph. + /// + template<typename GraphType> + static std::string getGraphName(GraphType Graph) { return ""; } + + /// getGraphProperties - Return any custom properties that should be included + /// in the top level graph structure for dot. + /// + template<typename GraphType> + static std::string getGraphProperties(GraphType Graph) { + return ""; + } + + /// renderGraphFromBottomUp - If this function returns true, the graph is + /// emitted bottom-up instead of top-down. This requires graphviz 2.0 to work + /// though. + static bool renderGraphFromBottomUp() { + return false; + } + + /// getNodeLabel - Given a node and a pointer to the top level graph, return + /// the label to print in the node. + template<typename GraphType> + static std::string getNodeLabel(const void *Node, GraphType Graph) { + return ""; + } + + /// hasNodeAddressLabel - If this method returns true, the address of the node + /// is added to the label of the node. + template<typename GraphType> + static bool hasNodeAddressLabel(const void *Node, GraphType Graph) { + return false; + } + + /// If you want to specify custom node attributes, this is the place to do so + /// + template<typename GraphType> + static std::string getNodeAttributes(const void *Node, GraphType Graph) { + return ""; + } + + /// If you want to override the dot attributes printed for a particular edge, + /// override this method. + template<typename EdgeIter> + static std::string getEdgeAttributes(const void *Node, EdgeIter EI) { + return ""; + } + + /// getEdgeSourceLabel - If you want to label the edge source itself, + /// implement this method. + template<typename EdgeIter> + static std::string getEdgeSourceLabel(const void *Node, EdgeIter I) { + return ""; + } + + /// edgeTargetsEdgeSource - This method returns true if this outgoing edge + /// should actually target another edge source, not a node. If this method is + /// implemented, getEdgeTarget should be implemented. + template<typename EdgeIter> + static bool edgeTargetsEdgeSource(const void *Node, EdgeIter I) { + return false; + } + + /// getEdgeTarget - If edgeTargetsEdgeSource returns true, this method is + /// called to determine which outgoing edge of Node is the target of this + /// edge. + template<typename EdgeIter> + static EdgeIter getEdgeTarget(const void *Node, EdgeIter I) { + return I; + } + + /// addCustomGraphFeatures - If a graph is made up of more than just + /// straight-forward nodes and edges, this is the place to put all of the + /// custom stuff necessary. The GraphWriter object, instantiated with your + /// GraphType is passed in as an argument. You may call arbitrary methods on + /// it to add things to the output graph. + /// + template<typename GraphType, typename GraphWriter> + static void addCustomGraphFeatures(GraphType Graph, GraphWriter &GW) {} +}; + + +/// DOTGraphTraits - Template class that can be specialized to customize how +/// graphs are converted to 'dot' graphs. When specializing, you may inherit +/// from DefaultDOTGraphTraits if you don't need to override everything. +/// +template <typename Ty> +struct DOTGraphTraits : public DefaultDOTGraphTraits {}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/DataTypes.h.in b/include/llvm/Support/DataTypes.h.in new file mode 100644 index 0000000..dcf7bfc --- /dev/null +++ b/include/llvm/Support/DataTypes.h.in @@ -0,0 +1,131 @@ +//===-- include/Support/DataTypes.h - Define fixed size types ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains definitions to figure out the size of _HOST_ data types. +// This file is important because different host OS's define different macros, +// which makes portability tough. This file exports the following definitions: +// +// [u]int(32|64)_t : typedefs for signed and unsigned 32/64 bit system types +// [U]INT(8|16|32|64)_(MIN|MAX) : Constants for the min and max values. +// +// No library is required when using these functinons. +// +//===----------------------------------------------------------------------===// + +#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 +#undef HAVE_U_INT64_T + +#ifndef _MSC_VER + +// Note that this header's correct operation depends on __STDC_LIMIT_MACROS +// being defined. We would define it here, but in order to prevent Bad Things +// happening when system headers or C++ STL headers include stdint.h before +// we define it here, we define it on the g++ command line (in Makefile.rules). +#if !defined(__STDC_LIMIT_MACROS) +# error "Must #define __STDC_LIMIT_MACROS before #including Support/DataTypes.h" +#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> +#endif + +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif + +#ifdef __cplusplus +#include <cmath> +#else +#include <math.h> +#endif + +#ifdef _AIX +#include "llvm/Support/AIXDataTypesFix.h" +#endif + +// Handle incorrect definition of uint64_t as u_int64_t +#ifndef HAVE_UINT64_T +#ifdef HAVE_U_INT64_T +typedef u_int64_t uint64_t; +#else +# error "Don't have a definition for uint64_t on this platform" +#endif +#endif + +#ifdef _OpenBSD_ +#define INT8_MAX 127 +#define INT8_MIN -128 +#define UINT8_MAX 255 +#define INT16_MAX 32767 +#define INT16_MIN -32768 +#define UINT16_MAX 65535 +#define INT32_MAX 2147483647 +#define INT32_MIN -2147483648 +#define UINT32_MAX 4294967295U +#endif + +#else /* _MSC_VER */ +// Visual C++ doesn't provide standard integer headers, but it does provide +// built-in data types. +#include <stdlib.h> +#include <stddef.h> +#include <sys/types.h> +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; +typedef signed int int32_t; +typedef unsigned int uint32_t; +typedef short int16_t; +typedef unsigned short uint16_t; +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef signed int ssize_t; +#define INT8_MAX 127 +#define INT8_MIN -128 +#define UINT8_MAX 255 +#define INT16_MAX 32767 +#define INT16_MIN -32768 +#define UINT16_MAX 65535 +#define INT32_MAX 2147483647 +#define INT32_MIN -2147483648 +#define UINT32_MAX 4294967295U +#endif /* _MSC_VER */ + +/* Set defaults for constants which we cannot find. */ +#if !defined(INT64_MAX) +# define INT64_MAX 9223372036854775807LL +#endif +#if !defined(INT64_MIN) +# define INT64_MIN ((-INT64_MAX)-1) +#endif +#if !defined(UINT64_MAX) +# define UINT64_MAX 0xffffffffffffffffULL +#endif + +#if __GNUC__ > 3 +#define END_WITH_NULL __attribute__((sentinel)) +#else +#define END_WITH_NULL +#endif + +#ifndef HUGE_VALF +#define HUGE_VALF (float)HUGE_VAL +#endif + +#endif /* SUPPORT_DATATYPES_H */ diff --git a/include/llvm/Support/Debug.h b/include/llvm/Support/Debug.h new file mode 100644 index 0000000..cbfaf15 --- /dev/null +++ b/include/llvm/Support/Debug.h @@ -0,0 +1,78 @@ +//===- llvm/Support/Debug.h - Easy way to add debug output ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a handy way of adding debugging information to your +// code, without it being enabled all of the time, and without having to add +// command line options to enable it. +// +// In particular, just wrap your code with the DEBUG() macro, and it will be +// enabled automatically if you specify '-debug' on the command-line. +// Alternatively, you can also use the SET_DEBUG_TYPE("foo") macro to specify +// that your debug code belongs to class "foo". Then, on the command line, you +// can specify '-debug-only=foo' to enable JUST the debug information for the +// foo class. +// +// When compiling in release mode, the -debug-* options and all code in DEBUG() +// statements disappears, so it does not effect the runtime of the code. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DEBUG_H +#define LLVM_SUPPORT_DEBUG_H + +#include "llvm/Support/Streams.h" + +namespace llvm { + +// DebugFlag - This boolean is set to true if the '-debug' command line option +// is specified. This should probably not be referenced directly, instead, use +// the DEBUG macro below. +// +extern bool DebugFlag; + +// isCurrentDebugType - Return true if the specified string is the debug type +// specified on the command line, or if none was specified on the command line +// with the -debug-only=X option. +// +bool isCurrentDebugType(const char *Type); + +// DEBUG macro - This macro should be used by passes to emit debug information. +// In the '-debug' option is specified on the commandline, and if this is a +// debug build, then the code specified as the option to the macro will be +// executed. Otherwise it will not be. Example: +// +// DEBUG(cerr << "Bitset contains: " << Bitset << "\n"); +// + +#ifndef DEBUG_TYPE +#define DEBUG_TYPE "" +#endif + +#ifdef NDEBUG +#define DEBUG(X) +#else +#define DEBUG(X) \ + do { if (DebugFlag && isCurrentDebugType(DEBUG_TYPE)) { X; } } while (0) +#endif + +/// getErrorOutputStream - Returns the error output stream (std::cerr). This +/// places the std::c* I/O streams into one .cpp file and relieves the whole +/// program from having to have hundreds of static c'tor/d'tors for them. +/// +OStream &getErrorOutputStream(const char *DebugType); + +#ifdef NDEBUG +#define DOUT llvm::OStream(0) +#else +#define DOUT llvm::getErrorOutputStream(DEBUG_TYPE) +#endif + +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h new file mode 100644 index 0000000..21f49f6 --- /dev/null +++ b/include/llvm/Support/Dwarf.h @@ -0,0 +1,572 @@ +//===-- llvm/Support/Dwarf.h ---Dwarf Constants------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by James M. Laskey and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains constants used for implementing Dwarf debug support. For +// Details on the Dwarf 3 specfication see DWARF Debugging Information Format +// V.3 reference manual http://dwarf.freestandards.org , +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DWARF_H +#define LLVM_SUPPORT_DWARF_H + +#include "llvm/System/IncludeFile.h" + +namespace llvm { + +namespace dwarf { + +//===----------------------------------------------------------------------===// +// Dwarf constants as gleaned from the DWARF Debugging Information Format V.3 +// reference manual http://dwarf.freestandards.org . +// + +// Do not mix the following two enumerations sets. DW_TAG_invalid changes the +// enumeration base type. + +enum llvm_dwarf_constants { + // llvm mock tags + DW_TAG_invalid = ~0U, // Tag for invalid results. + + DW_TAG_anchor = 0, // Tag for descriptor anchors. + DW_TAG_auto_variable = 0x100, // Tag for local (auto) variables. + DW_TAG_arg_variable = 0x101, // Tag for argument variables. + DW_TAG_return_variable = 0x102, // Tag for return variables. + + DW_TAG_vector_type = 0x103, // Tag for vector types. + + DW_TAG_user_base = 0x1000, // Recommended base for user tags. + + DW_CIE_VERSION = 1, // Common frame information version. + DW_CIE_ID = 0xffffffff // Common frame information mark. +}; + +enum dwarf_constants { + DWARF_VERSION = 2, + + // Tags + DW_TAG_array_type = 0x01, + DW_TAG_class_type = 0x02, + DW_TAG_entry_point = 0x03, + DW_TAG_enumeration_type = 0x04, + DW_TAG_formal_parameter = 0x05, + DW_TAG_imported_declaration = 0x08, + DW_TAG_label = 0x0a, + DW_TAG_lexical_block = 0x0b, + DW_TAG_member = 0x0d, + DW_TAG_pointer_type = 0x0f, + DW_TAG_reference_type = 0x10, + DW_TAG_compile_unit = 0x11, + DW_TAG_string_type = 0x12, + DW_TAG_structure_type = 0x13, + DW_TAG_subroutine_type = 0x15, + DW_TAG_typedef = 0x16, + DW_TAG_union_type = 0x17, + DW_TAG_unspecified_parameters = 0x18, + DW_TAG_variant = 0x19, + DW_TAG_common_block = 0x1a, + DW_TAG_common_inclusion = 0x1b, + DW_TAG_inheritance = 0x1c, + DW_TAG_inlined_subroutine = 0x1d, + DW_TAG_module = 0x1e, + DW_TAG_ptr_to_member_type = 0x1f, + DW_TAG_set_type = 0x20, + DW_TAG_subrange_type = 0x21, + DW_TAG_with_stmt = 0x22, + DW_TAG_access_declaration = 0x23, + DW_TAG_base_type = 0x24, + DW_TAG_catch_block = 0x25, + DW_TAG_const_type = 0x26, + DW_TAG_constant = 0x27, + DW_TAG_enumerator = 0x28, + DW_TAG_file_type = 0x29, + DW_TAG_friend = 0x2a, + DW_TAG_namelist = 0x2b, + DW_TAG_namelist_item = 0x2c, + DW_TAG_packed_type = 0x2d, + DW_TAG_subprogram = 0x2e, + DW_TAG_template_type_parameter = 0x2f, + DW_TAG_template_value_parameter = 0x30, + DW_TAG_thrown_type = 0x31, + DW_TAG_try_block = 0x32, + DW_TAG_variant_part = 0x33, + DW_TAG_variable = 0x34, + DW_TAG_volatile_type = 0x35, + DW_TAG_dwarf_procedure = 0x36, + DW_TAG_restrict_type = 0x37, + DW_TAG_interface_type = 0x38, + DW_TAG_namespace = 0x39, + DW_TAG_imported_module = 0x3a, + DW_TAG_unspecified_type = 0x3b, + DW_TAG_partial_unit = 0x3c, + DW_TAG_imported_unit = 0x3d, + DW_TAG_condition = 0x3f, + DW_TAG_shared_type = 0x40, + DW_TAG_lo_user = 0x4080, + DW_TAG_hi_user = 0xffff, + + // Children flag + DW_CHILDREN_no = 0x00, + DW_CHILDREN_yes = 0x01, + + // Attributes + DW_AT_sibling = 0x01, + DW_AT_location = 0x02, + DW_AT_name = 0x03, + DW_AT_ordering = 0x09, + DW_AT_byte_size = 0x0b, + DW_AT_bit_offset = 0x0c, + DW_AT_bit_size = 0x0d, + DW_AT_stmt_list = 0x10, + DW_AT_low_pc = 0x11, + DW_AT_high_pc = 0x12, + DW_AT_language = 0x13, + DW_AT_discr = 0x15, + DW_AT_discr_value = 0x16, + DW_AT_visibility = 0x17, + DW_AT_import = 0x18, + DW_AT_string_length = 0x19, + DW_AT_common_reference = 0x1a, + DW_AT_comp_dir = 0x1b, + DW_AT_const_value = 0x1c, + DW_AT_containing_type = 0x1d, + DW_AT_default_value = 0x1e, + DW_AT_inline = 0x20, + DW_AT_is_optional = 0x21, + DW_AT_lower_bound = 0x22, + DW_AT_producer = 0x25, + DW_AT_prototyped = 0x27, + DW_AT_return_addr = 0x2a, + DW_AT_start_scope = 0x2c, + DW_AT_bit_stride = 0x2e, + DW_AT_upper_bound = 0x2f, + DW_AT_abstract_origin = 0x31, + DW_AT_accessibility = 0x32, + DW_AT_address_class = 0x33, + DW_AT_artificial = 0x34, + DW_AT_base_types = 0x35, + DW_AT_calling_convention = 0x36, + DW_AT_count = 0x37, + DW_AT_data_member_location = 0x38, + DW_AT_decl_column = 0x39, + DW_AT_decl_file = 0x3a, + DW_AT_decl_line = 0x3b, + DW_AT_declaration = 0x3c, + DW_AT_discr_list = 0x3d, + DW_AT_encoding = 0x3e, + DW_AT_external = 0x3f, + DW_AT_frame_base = 0x40, + DW_AT_friend = 0x41, + DW_AT_identifier_case = 0x42, + DW_AT_macro_info = 0x43, + DW_AT_namelist_item = 0x44, + DW_AT_priority = 0x45, + DW_AT_segment = 0x46, + DW_AT_specification = 0x47, + DW_AT_static_link = 0x48, + DW_AT_type = 0x49, + DW_AT_use_location = 0x4a, + DW_AT_variable_parameter = 0x4b, + DW_AT_virtuality = 0x4c, + DW_AT_vtable_elem_location = 0x4d, + DW_AT_allocated = 0x4e, + DW_AT_associated = 0x4f, + DW_AT_data_location = 0x50, + DW_AT_byte_stride = 0x51, + DW_AT_entry_pc = 0x52, + DW_AT_use_UTF8 = 0x53, + DW_AT_extension = 0x54, + DW_AT_ranges = 0x55, + DW_AT_trampoline = 0x56, + DW_AT_call_column = 0x57, + DW_AT_call_file = 0x58, + DW_AT_call_line = 0x59, + DW_AT_description = 0x5a, + DW_AT_binary_scale = 0x5b, + DW_AT_decimal_scale = 0x5c, + DW_AT_small = 0x5d, + DW_AT_decimal_sign = 0x5e, + DW_AT_digit_count = 0x5f, + DW_AT_picture_string = 0x60, + DW_AT_mutable = 0x61, + DW_AT_threads_scaled = 0x62, + DW_AT_explicit = 0x63, + DW_AT_object_pointer = 0x64, + DW_AT_endianity = 0x65, + DW_AT_elemental = 0x66, + DW_AT_pure = 0x67, + DW_AT_recursive = 0x68, + DW_AT_MIPS_linkage_name = 0x2007, + DW_AT_sf_names = 0x2101, + DW_AT_src_info = 0x2102, + DW_AT_mac_info = 0x2103, + DW_AT_src_coords = 0x2104, + DW_AT_body_begin = 0x2105, + DW_AT_body_end = 0x2106, + DW_AT_GNU_vector = 0x2107, + DW_AT_lo_user = 0x2000, + DW_AT_hi_user = 0x3fff, + + // Attribute form encodings + DW_FORM_addr = 0x01, + DW_FORM_block2 = 0x03, + DW_FORM_block4 = 0x04, + DW_FORM_data2 = 0x05, + DW_FORM_data4 = 0x06, + DW_FORM_data8 = 0x07, + DW_FORM_string = 0x08, + DW_FORM_block = 0x09, + DW_FORM_block1 = 0x0a, + DW_FORM_data1 = 0x0b, + DW_FORM_flag = 0x0c, + DW_FORM_sdata = 0x0d, + DW_FORM_strp = 0x0e, + DW_FORM_udata = 0x0f, + DW_FORM_ref_addr = 0x10, + DW_FORM_ref1 = 0x11, + DW_FORM_ref2 = 0x12, + DW_FORM_ref4 = 0x13, + DW_FORM_ref8 = 0x14, + DW_FORM_ref_udata = 0x15, + DW_FORM_indirect = 0x16, + + // Operation encodings + DW_OP_addr = 0x03, + DW_OP_deref = 0x06, + DW_OP_const1u = 0x08, + DW_OP_const1s = 0x09, + DW_OP_const2u = 0x0a, + DW_OP_const2s = 0x0b, + DW_OP_const4u = 0x0c, + DW_OP_const4s = 0x0d, + DW_OP_const8u = 0x0e, + DW_OP_const8s = 0x0f, + DW_OP_constu = 0x10, + DW_OP_consts = 0x11, + DW_OP_dup = 0x12, + DW_OP_drop = 0x13, + DW_OP_over = 0x14, + DW_OP_pick = 0x15, + DW_OP_swap = 0x16, + DW_OP_rot = 0x17, + DW_OP_xderef = 0x18, + DW_OP_abs = 0x19, + DW_OP_and = 0x1a, + DW_OP_div = 0x1b, + DW_OP_minus = 0x1c, + DW_OP_mod = 0x1d, + DW_OP_mul = 0x1e, + DW_OP_neg = 0x1f, + DW_OP_not = 0x20, + DW_OP_or = 0x21, + DW_OP_plus = 0x22, + DW_OP_plus_uconst = 0x23, + DW_OP_shl = 0x24, + DW_OP_shr = 0x25, + DW_OP_shra = 0x26, + DW_OP_xor = 0x27, + DW_OP_skip = 0x2f, + DW_OP_bra = 0x28, + DW_OP_eq = 0x29, + DW_OP_ge = 0x2a, + DW_OP_gt = 0x2b, + DW_OP_le = 0x2c, + DW_OP_lt = 0x2d, + DW_OP_ne = 0x2e, + DW_OP_lit0 = 0x30, + DW_OP_lit1 = 0x31, + DW_OP_lit31 = 0x4f, + DW_OP_reg0 = 0x50, + DW_OP_reg1 = 0x51, + DW_OP_reg31 = 0x6f, + DW_OP_breg0 = 0x70, + DW_OP_breg1 = 0x71, + DW_OP_breg31 = 0x8f, + DW_OP_regx = 0x90, + DW_OP_fbreg = 0x91, + DW_OP_bregx = 0x92, + DW_OP_piece = 0x93, + DW_OP_deref_size = 0x94, + DW_OP_xderef_size = 0x95, + DW_OP_nop = 0x96, + DW_OP_push_object_address = 0x97, + DW_OP_call2 = 0x98, + DW_OP_call4 = 0x99, + DW_OP_call_ref = 0x9a, + DW_OP_form_tls_address = 0x9b, + DW_OP_call_frame_cfa = 0x9c, + DW_OP_lo_user = 0xe0, + DW_OP_hi_user = 0xff, + + // Encoding attribute values + DW_ATE_address = 0x01, + DW_ATE_boolean = 0x02, + DW_ATE_complex_float = 0x03, + DW_ATE_float = 0x04, + DW_ATE_signed = 0x05, + DW_ATE_signed_char = 0x06, + DW_ATE_unsigned = 0x07, + DW_ATE_unsigned_char = 0x08, + DW_ATE_imaginary_float = 0x09, + DW_ATE_packed_decimal = 0x0a, + DW_ATE_numeric_string = 0x0b, + DW_ATE_edited = 0x0c, + DW_ATE_signed_fixed = 0x0d, + DW_ATE_unsigned_fixed = 0x0e, + DW_ATE_decimal_float = 0x0f, + DW_ATE_lo_user = 0x80, + DW_ATE_hi_user = 0xff, + + // Decimal sign attribute values + DW_DS_unsigned = 0x01, + DW_DS_leading_overpunch = 0x02, + DW_DS_trailing_overpunch = 0x03, + DW_DS_leading_separate = 0x04, + DW_DS_trailing_separate = 0x05, + + // Endianity attribute values + DW_END_default = 0x00, + DW_END_big = 0x01, + DW_END_little = 0x02, + DW_END_lo_user = 0x40, + DW_END_hi_user = 0xff, + + // Accessibility codes + DW_ACCESS_public = 0x01, + DW_ACCESS_protected = 0x02, + DW_ACCESS_private = 0x03, + + // Visibility codes + DW_VIS_local = 0x01, + DW_VIS_exported = 0x02, + DW_VIS_qualified = 0x03, + + // Virtuality codes + DW_VIRTUALITY_none = 0x00, + DW_VIRTUALITY_virtual = 0x01, + DW_VIRTUALITY_pure_virtual = 0x02, + + // Language names + DW_LANG_C89 = 0x0001, + DW_LANG_C = 0x0002, + DW_LANG_Ada83 = 0x0003, + DW_LANG_C_plus_plus = 0x0004, + DW_LANG_Cobol74 = 0x0005, + DW_LANG_Cobol85 = 0x0006, + DW_LANG_Fortran77 = 0x0007, + DW_LANG_Fortran90 = 0x0008, + DW_LANG_Pascal83 = 0x0009, + DW_LANG_Modula2 = 0x000a, + DW_LANG_Java = 0x000b, + DW_LANG_C99 = 0x000c, + DW_LANG_Ada95 = 0x000d, + DW_LANG_Fortran95 = 0x000e, + DW_LANG_PLI = 0x000f, + DW_LANG_ObjC = 0x0010, + DW_LANG_ObjC_plus_plus = 0x0011, + DW_LANG_UPC = 0x0012, + DW_LANG_D = 0x0013, + DW_LANG_lo_user = 0x8000, + DW_LANG_hi_user = 0xffff, + + // Identifier case codes + DW_ID_case_sensitive = 0x00, + DW_ID_up_case = 0x01, + DW_ID_down_case = 0x02, + DW_ID_case_insensitive = 0x03, + + // Calling convention codes + DW_CC_normal = 0x01, + DW_CC_program = 0x02, + DW_CC_nocall = 0x03, + DW_CC_lo_user = 0x40, + DW_CC_hi_user = 0xff, + + // Inline codes + DW_INL_not_inlined = 0x00, + DW_INL_inlined = 0x01, + DW_INL_declared_not_inlined = 0x02, + DW_INL_declared_inlined = 0x03, + + // Array ordering + DW_ORD_row_major = 0x00, + DW_ORD_col_major = 0x01, + + // Discriminant descriptor values + DW_DSC_label = 0x00, + DW_DSC_range = 0x01, + + // Line Number Standard Opcode Encodings + DW_LNS_copy = 0x01, + DW_LNS_advance_pc = 0x02, + DW_LNS_advance_line = 0x03, + DW_LNS_set_file = 0x04, + DW_LNS_set_column = 0x05, + DW_LNS_negate_stmt = 0x06, + DW_LNS_set_basic_block = 0x07, + DW_LNS_const_add_pc = 0x08, + DW_LNS_fixed_advance_pc = 0x09, + DW_LNS_set_prologue_end = 0x0a, + DW_LNS_set_epilogue_begin = 0x0b, + DW_LNS_set_isa = 0x0c, + + // Line Number Extended Opcode Encodings + DW_LNE_end_sequence = 0x01, + DW_LNE_set_address = 0x02, + DW_LNE_define_file = 0x03, + DW_LNE_lo_user = 0x80, + DW_LNE_hi_user = 0xff, + + // Macinfo Type Encodings + DW_MACINFO_define = 0x01, + DW_MACINFO_undef = 0x02, + DW_MACINFO_start_file = 0x03, + DW_MACINFO_end_file = 0x04, + DW_MACINFO_vendor_ext = 0xff, + + // Call frame instruction encodings + DW_CFA_extended = 0x00, + DW_CFA_advance_loc = 0x40, + DW_CFA_offset = 0x80, + DW_CFA_restore = 0xc0, + DW_CFA_set_loc = 0x01, + DW_CFA_advance_loc1 = 0x02, + DW_CFA_advance_loc2 = 0x03, + DW_CFA_advance_loc4 = 0x04, + DW_CFA_offset_extended = 0x05, + DW_CFA_restore_extended = 0x06, + DW_CFA_undefined = 0x07, + DW_CFA_same_value = 0x08, + DW_CFA_register = 0x09, + DW_CFA_remember_state = 0x0a, + DW_CFA_restore_state = 0x0b, + DW_CFA_def_cfa = 0x0c, + DW_CFA_def_cfa_register = 0x0d, + DW_CFA_def_cfa_offset = 0x0e, + DW_CFA_def_cfa_expression = 0x0f, + DW_CFA_expression = 0x10, + DW_CFA_offset_extended_sf = 0x11, + DW_CFA_def_cfa_sf = 0x12, + DW_CFA_def_cfa_offset_sf = 0x13, + DW_CFA_val_offset = 0x14, + DW_CFA_val_offset_sf = 0x15, + DW_CFA_val_expression = 0x16, + DW_CFA_lo_user = 0x1c, + DW_CFA_hi_user = 0x3f, + + DW_EH_PE_absptr = 0x00, + DW_EH_PE_omit = 0xff, + DW_EH_PE_uleb128 = 0x01, + DW_EH_PE_udata2 = 0x02, + DW_EH_PE_udata4 = 0x03, + DW_EH_PE_udata8 = 0x04, + DW_EH_PE_sleb128 = 0x09, + DW_EH_PE_sdata2 = 0x0A, + DW_EH_PE_sdata4 = 0x0B, + DW_EH_PE_sdata8 = 0x0C, + DW_EH_PE_signed = 0x08, + DW_EH_PE_pcrel = 0x10, + DW_EH_PE_textrel = 0x20, + DW_EH_PE_datarel = 0x30, + DW_EH_PE_funcrel = 0x40, + DW_EH_PE_aligned = 0x50, + DW_EH_PE_indirect = 0x80 +}; + +/// TagString - Return the string for the specified tag. +/// +const char *TagString(unsigned Tag); + +/// ChildrenString - Return the string for the specified children flag. +/// +const char *ChildrenString(unsigned Children); + +/// AttributeString - Return the string for the specified attribute. +/// +const char *AttributeString(unsigned Attribute); + +/// FormEncodingString - Return the string for the specified form encoding. +/// +const char *FormEncodingString(unsigned Encoding); + +/// OperationEncodingString - Return the string for the specified operation +/// encoding. +const char *OperationEncodingString(unsigned Encoding); + +/// AttributeEncodingString - Return the string for the specified attribute +/// encoding. +const char *AttributeEncodingString(unsigned Encoding); + +/// DecimalSignString - Return the string for the specified decimal sign +/// attribute. +const char *DecimalSignString(unsigned Sign); + +/// EndianityString - Return the string for the specified endianity. +/// +const char *EndianityString(unsigned Endian); + +/// AccessibilityString - Return the string for the specified accessibility. +/// +const char *AccessibilityString(unsigned Access); + +/// VisibilityString - Return the string for the specified visibility. +/// +const char *VisibilityString(unsigned Visibility); + +/// VirtualityString - Return the string for the specified virtuality. +/// +const char *VirtualityString(unsigned Virtuality); + +/// LanguageString - Return the string for the specified language. +/// +const char *LanguageString(unsigned Language); + +/// CaseString - Return the string for the specified identifier case. +/// +const char *CaseString(unsigned Case); + +/// ConventionString - Return the string for the specified calling convention. +/// +const char *ConventionString(unsigned Convention); + +/// InlineCodeString - Return the string for the specified inline code. +/// +const char *InlineCodeString(unsigned Code); + +/// ArrayOrderString - Return the string for the specified array order. +/// +const char *ArrayOrderString(unsigned Order); + +/// DiscriminantString - Return the string for the specified discriminant +/// descriptor. +const char *DiscriminantString(unsigned Discriminant); + +/// LNStandardString - Return the string for the specified line number standard. +/// +const char *LNStandardString(unsigned Standard); + +/// LNExtendedString - Return the string for the specified line number extended +/// opcode encodings. +const char *LNExtendedString(unsigned Encoding); + +/// MacinfoString - Return the string for the specified macinfo type encodings. +/// +const char *MacinfoString(unsigned Encoding); + +/// CallFrameString - Return the string for the specified call frame instruction +/// encodings. +const char *CallFrameString(unsigned Encoding); + +} // End of namespace dwarf + +} // End of namespace llvm + +FORCE_DEFINING_FILE_TO_BE_LINKED(SupportDwarf) + +#endif diff --git a/include/llvm/Support/DynamicLinker.h b/include/llvm/Support/DynamicLinker.h new file mode 100644 index 0000000..e996b0f --- /dev/null +++ b/include/llvm/Support/DynamicLinker.h @@ -0,0 +1,40 @@ +//===-- llvm/Support/DynamicLinker.h - Portable Dynamic Linker --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Lightweight interface to dynamic library linking and loading, and dynamic +// symbol lookup functionality, in whatever form the operating system +// provides it. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_DYNAMICLINKER_H +#define LLVM_SUPPORT_DYNAMICLINKER_H + +#include <string> + +namespace llvm { + +/// LinkDynamicObject - Load the named file as a dynamic library +/// and link it with the currently running process. Returns false +/// on success, true if there is an error (and sets ErrorMessage +/// if it is not NULL). Analogous to dlopen(). +/// +bool LinkDynamicObject (const char *filename, std::string *ErrorMessage); + +/// GetAddressOfSymbol - Returns the address of the named symbol in +/// the currently running process, as reported by the dynamic linker, +/// or NULL if the symbol does not exist or some other error has +/// occurred. +/// +void *GetAddressOfSymbol (const char *symbolName); +void *GetAddressOfSymbol (const std::string &symbolName); + +} // End llvm namespace + +#endif // SUPPORT_DYNAMICLINKER_H diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h new file mode 100644 index 0000000..cd811f2 --- /dev/null +++ b/include/llvm/Support/ELF.h @@ -0,0 +1,300 @@ +//===-- llvm/Support/ELF.h - ELF constants and data structures --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header contains common, non-processor-specific data structures and +// constants for the ELF file format. +// +// The details of the ELF32 bits in this file are largely based on +// the Tool Interface Standard (TIS) Executable and Linking Format +// (ELF) Specification Version 1.2, May 1995. The ELF64 stuff is not +// standardized, as far as I can tell. It was largely based on information +// I found in OpenBSD header files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_ELF_H +#define LLVM_SUPPORT_ELF_H + +#include "llvm/Support/DataTypes.h" +#include <cstring> +#include <cstdlib> + +namespace llvm { + +namespace ELF { + +typedef uint32_t Elf32_Addr; // Program address +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; // File offset +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +typedef uint64_t Elf64_Addr; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Shalf; +typedef int32_t Elf64_Sword; +typedef uint32_t Elf64_Word; +typedef int64_t Elf64_Sxword; +typedef uint64_t Elf64_Xword; +typedef uint32_t Elf64_Half; +typedef uint16_t Elf64_Quarter; + +// Object file magic string. +static const char ElfMagic[] = { 0x7f, 'E', 'L', 'F', '\0' }; + +struct Elf32_Ehdr { + unsigned char e_ident[16]; // ELF Identification bytes + Elf32_Half e_type; // Type of file (see ET_* below) + Elf32_Half e_machine; // Required architecture for this file (see EM_*) + Elf32_Word e_version; // Must be equal to 1 + Elf32_Addr e_entry; // Address to jump to in order to start program + Elf32_Off e_phoff; // Program header table's file offset, in bytes + Elf32_Off e_shoff; // Section header table's file offset, in bytes + Elf32_Word e_flags; // Processor-specific flags + Elf32_Half e_ehsize; // Size of ELF header, in bytes + Elf32_Half e_phentsize; // Size of an entry in the program header table + Elf32_Half e_phnum; // Number of entries in the program header table + Elf32_Half e_shentsize; // Size of an entry in the section header table + Elf32_Half e_shnum; // Number of entries in the section header table + Elf32_Half e_shstrndx; // Sect hdr table index of sect name string table + bool checkMagic () const { + return (memcmp (e_ident, ElfMagic, strlen (ElfMagic))) == 0; + } + unsigned char getFileClass () const { return e_ident[4]; } + unsigned char getDataEncoding () { return e_ident[5]; } +}; + +// 64-bit ELF header. Fields are the same as for ELF32, but with different +// types (see above). +struct Elf64_Ehdr { + unsigned char e_ident[16]; + Elf64_Quarter e_type; + Elf64_Quarter e_machine; + Elf64_Half e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Half e_flags; + Elf64_Quarter e_ehsize; + Elf64_Quarter e_phentsize; + Elf64_Quarter e_phnum; + Elf64_Quarter e_shentsize; + Elf64_Quarter e_shnum; + Elf64_Quarter e_shstrndx; +}; + +// File types +enum { + ET_NONE = 0, // No file type + ET_REL = 1, // Relocatable file + ET_EXEC = 2, // Executable file + ET_DYN = 3, // Shared object file + ET_CORE = 4, // Core file + ET_LOPROC = 0xff00, // Beginning of processor-specific codes + ET_HIPROC = 0xffff // Processor-specific +}; + +// Machine architectures +enum { + EM_NONE = 0, // No machine + EM_M32 = 1, // AT&T WE 32100 + EM_SPARC = 2, // SPARC + EM_386 = 3, // Intel 386 + EM_68K = 4, // Motorola 68000 + EM_88K = 5, // Motorola 88000 + EM_486 = 6, // Intel 486 (deprecated) + EM_860 = 7, // Intel 80860 + EM_MIPS = 8, // MIPS R3000 + EM_PPC = 20, // PowerPC + EM_ARM = 40, // ARM + EM_ALPHA = 41, // DEC Alpha + EM_SPARCV9 = 43 // SPARC V9 +}; + +// Object file classes. +enum { + ELFCLASS32 = 1, // 32-bit object file + ELFCLASS64 = 2 // 64-bit object file +}; + +// Object file byte orderings. +enum { + ELFDATA2LSB = 1, // Little-endian object file + ELFDATA2MSB = 2 // Big-endian object file +}; + +// Section header. +struct Elf32_Shdr { + Elf32_Word sh_name; // Section name (index into string table) + Elf32_Word sh_type; // Section type (SHT_*) + Elf32_Word sh_flags; // Section flags (SHF_*) + Elf32_Addr sh_addr; // Address where section is to be loaded + Elf32_Off sh_offset; // File offset of section data, in bytes + Elf32_Word sh_size; // Size of section, in bytes + Elf32_Word sh_link; // Section type-specific header table index link + Elf32_Word sh_info; // Section type-specific extra information + Elf32_Word sh_addralign; // Section address alignment + Elf32_Word sh_entsize; // Size of records contained within the section +}; + +// Section header for ELF64 - same fields as ELF32, different types. +struct Elf64_Shdr { + Elf64_Half sh_name; + Elf64_Half sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Half sh_link; + Elf64_Half sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +}; + +// Special section indices. +enum { + SHN_UNDEF = 0, // Undefined, missing, irrelevant, or meaningless + SHN_LORESERVE = 0xff00, // Lowest reserved index + SHN_LOPROC = 0xff00, // Lowest processor-specific index + SHN_HIPROC = 0xff1f, // Highest processor-specific index + SHN_ABS = 0xfff1, // Symbol has absolute value; does not need relocation + SHN_COMMON = 0xfff2, // FORTRAN COMMON or C external global variables + SHN_HIRESERVE = 0xffff // Highest reserved index +}; + +// Section types. +enum { + SHT_NULL = 0, // No associated section (inactive entry). + SHT_PROGBITS = 1, // Program-defined contents. + SHT_SYMTAB = 2, // Symbol table. + SHT_STRTAB = 3, // String table. + SHT_RELA = 4, // Relocation entries; explicit addends. + SHT_HASH = 5, // Symbol hash table. + SHT_DYNAMIC = 6, // Information for dynamic linking. + SHT_NOTE = 7, // Information about the file. + SHT_NOBITS = 8, // Data occupies no space in the file. + SHT_REL = 9, // Relocation entries; no explicit addends. + SHT_SHLIB = 10, // Reserved. + SHT_DYNSYM = 11, // Symbol table. + SHT_LOPROC = 0x70000000, // Lowest processor architecture-specific type. + SHT_HIPROC = 0x7fffffff, // Highest processor architecture-specific type. + SHT_LOUSER = 0x80000000, // Lowest type reserved for applications. + SHT_HIUSER = 0xffffffff // Highest type reserved for applications. +}; + +// Section flags. +enum { + SHF_WRITE = 0x1, // Section data should be writable during execution. + SHF_ALLOC = 0x2, // Section occupies memory during program execution. + SHF_EXECINSTR = 0x4, // Section contains executable machine instructions. + SHF_MASKPROC = 0xf0000000 // Bits indicating processor-specific flags. +}; + +// Symbol table entries. +struct Elf32_Sym { + Elf32_Word st_name; // Symbol name (index into string table) + Elf32_Addr st_value; // Value or address associated with the symbol + Elf32_Word st_size; // Size of the symbol + unsigned char st_info; // Symbol's type and binding attributes + unsigned char st_other; // Must be zero; reserved + Elf32_Half st_shndx; // Which section (header table index) it's defined in + + // These accessors and mutators correspond to the ELF32_ST_BIND, + // ELF32_ST_TYPE, and ELF32_ST_INFO macros defined in the ELF specification: + unsigned char getBinding () const { return st_info >> 4; } + unsigned char getType () const { return st_info & 0x0f; } + void setBinding (unsigned char b) { setBindingAndType (b, getType ()); } + void setType (unsigned char t) { setBindingAndType (getBinding (), t); } + void setBindingAndType (unsigned char b, unsigned char t) { + st_info = (b << 4) + (t & 0x0f); + } +}; + +// Symbol bindings. +enum { + STB_LOCAL = 0, // Local symbol, not visible outside obj file containing def + STB_GLOBAL = 1, // Global symbol, visible to all object files being combined + STB_WEAK = 2, // Weak symbol, like global but lower-precedence + STB_LOPROC = 13, // Lowest processor-specific binding type + STB_HIPROC = 15 // Highest processor-specific binding type +}; + +// Symbol types. +enum { + STT_NOTYPE = 0, // Symbol's type is not specified + STT_OBJECT = 1, // Symbol is a data object (variable, array, etc.) + STT_FUNC = 2, // Symbol is executable code (function, etc.) + STT_SECTION = 3, // Symbol refers to a section + STT_FILE = 4, // Local, absolute symbol that refers to a file + STT_LOPROC = 13, // Lowest processor-specific symbol type + STT_HIPROC = 15 // Highest processor-specific symbol type +}; + +// Relocation entry, without explicit addend. +struct Elf32_Rel { + Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf32_Word r_info; // Symbol table index and type of relocation to apply + + // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, + // and ELF32_R_INFO macros defined in the ELF specification: + Elf32_Word getSymbol () const { return (r_info >> 8); } + unsigned char getType () const { return (unsigned char) (r_info & 0x0ff); } + void setSymbol (Elf32_Word s) { setSymbolAndType (s, getType ()); } + void setType (unsigned char t) { setSymbolAndType (getSymbol(), t); } + void setSymbolAndType (Elf32_Word s, unsigned char t) { + r_info = (s << 8) + t; + }; +}; + +// Relocation entry with explicit addend. +struct Elf32_Rela { + Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) + Elf32_Word r_info; // Symbol table index and type of relocation to apply + Elf32_Sword r_addend; // Compute value for relocatable field by adding this + + // These accessors and mutators correspond to the ELF32_R_SYM, ELF32_R_TYPE, + // and ELF32_R_INFO macros defined in the ELF specification: + Elf32_Word getSymbol () const { return (r_info >> 8); } + unsigned char getType () const { return (unsigned char) (r_info & 0x0ff); } + void setSymbol (Elf32_Word s) { setSymbolAndType (s, getType ()); } + void setType (unsigned char t) { setSymbolAndType (getSymbol(), t); } + void setSymbolAndType (Elf32_Word s, unsigned char t) { + r_info = (s << 8) + t; + }; +}; + +// Program header. +struct Elf32_Phdr { + Elf32_Word p_type; // Type of segment + Elf32_Off p_offset; // File offset where segment is located, in bytes + Elf32_Addr p_vaddr; // Virtual address of beginning of segment + Elf32_Addr p_paddr; // Physical address of beginning of segment (OS-specific) + Elf32_Word p_filesz; // Num. of bytes in file image of segment (may be zero) + Elf32_Word p_memsz; // Num. of bytes in mem image of segment (may be zero) + Elf32_Word p_flags; // Segment flags + Elf32_Word p_align; // Segment alignment constraint +}; + +enum { + PT_NULL = 0, // Unused segment. + PT_LOAD = 1, // Loadable segment. + PT_DYNAMIC = 2, // Dynamic linking information. + PT_INTERP = 3, // Interpreter pathname. + PT_NOTE = 4, // Auxiliary information. + PT_SHLIB = 5, // Reserved. + PT_PHDR = 6, // The program header table itself. + PT_LOPROC = 0x70000000, // Lowest processor-specific program hdr entry type. + PT_HIPROC = 0x7fffffff // Highest processor-specific program hdr entry type. +}; + +} // end namespace ELF + +} // end namespace llvm + +#endif diff --git a/include/llvm/Support/FileUtilities.h b/include/llvm/Support/FileUtilities.h new file mode 100644 index 0000000..9cebe23 --- /dev/null +++ b/include/llvm/Support/FileUtilities.h @@ -0,0 +1,59 @@ +//===- llvm/Support/FileUtilities.h - File System Utilities -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a family of utility functions which are useful for doing +// various things with files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_FILEUTILITIES_H +#define LLVM_SUPPORT_FILEUTILITIES_H + +#include "llvm/System/Path.h" + +namespace llvm { + + /// DiffFilesWithTolerance - Compare the two files specified, returning 0 if + /// the files match, 1 if they are different, and 2 if there is a file error. + /// This function allows you to specify an absolete and relative FP error that + /// is allowed to exist. If you specify a string to fill in for the error + /// 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, + double AbsTol, double RelTol, + std::string *Error = 0); + + + /// FileRemover - This class is a simple object meant to be stack allocated. + /// If an exception is thrown from a region, the object removes the filename + /// specified (if deleteIt is true). + /// + class FileRemover { + sys::Path Filename; + bool DeleteIt; + public: + FileRemover(const sys::Path &filename, bool deleteIt = true) + : Filename(filename), DeleteIt(deleteIt) {} + + ~FileRemover() { + if (DeleteIt) { + // Ignore problems deleting the file. + Filename.eraseFromDisk(); + } + } + + /// releaseFile - Take ownership of the file away from the FileRemover so it + /// will not be removed when the object is destroyed. + void releaseFile() { DeleteIt = false; } + }; +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/GetElementPtrTypeIterator.h b/include/llvm/Support/GetElementPtrTypeIterator.h new file mode 100644 index 0000000..846332e --- /dev/null +++ b/include/llvm/Support/GetElementPtrTypeIterator.h @@ -0,0 +1,112 @@ +//===- llvm/Support/GetElementPtrTypeIterator.h -----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements an iterator for walking through the types indexed by +// getelementptr instructions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_GETELEMENTPTRTYPE_H +#define LLVM_SUPPORT_GETELEMENTPTRTYPE_H + +#include "llvm/User.h" +#include "llvm/DerivedTypes.h" + +namespace llvm { + template<typename ItTy = User::const_op_iterator> + class generic_gep_type_iterator + : public forward_iterator<const Type *, ptrdiff_t> { + typedef forward_iterator<const Type*, ptrdiff_t> super; + + ItTy OpIt; + const Type *CurTy; + generic_gep_type_iterator() {} + public: + + static generic_gep_type_iterator begin(const Type *Ty, ItTy It) { + generic_gep_type_iterator I; + I.CurTy = Ty; + I.OpIt = It; + return I; + } + static generic_gep_type_iterator end(ItTy It) { + generic_gep_type_iterator I; + I.CurTy = 0; + I.OpIt = It; + return I; + } + + bool operator==(const generic_gep_type_iterator& x) const { + return OpIt == x.OpIt; + } + bool operator!=(const generic_gep_type_iterator& x) const { + return !operator==(x); + } + + const Type *operator*() const { + return CurTy; + } + + const Type *getIndexedType() const { + const CompositeType *CT = cast<CompositeType>(CurTy); + return CT->getTypeAtIndex(getOperand()); + } + + // This is a non-standard operator->. It allows you to call methods on the + // current type directly. + const Type *operator->() const { return operator*(); } + + Value *getOperand() const { return *OpIt; } + + generic_gep_type_iterator& operator++() { // Preincrement + if (const CompositeType *CT = dyn_cast<CompositeType>(CurTy)) { + CurTy = CT->getTypeAtIndex(getOperand()); + } else { + CurTy = 0; + } + ++OpIt; + return *this; + } + + generic_gep_type_iterator operator++(int) { // Postincrement + generic_gep_type_iterator tmp = *this; ++*this; return tmp; + } + }; + + typedef generic_gep_type_iterator<> gep_type_iterator; + + inline gep_type_iterator gep_type_begin(const User *GEP) { + return gep_type_iterator::begin(GEP->getOperand(0)->getType(), + GEP->op_begin()+1); + } + inline gep_type_iterator gep_type_end(const User *GEP) { + return gep_type_iterator::end(GEP->op_end()); + } + inline gep_type_iterator gep_type_begin(const User &GEP) { + return gep_type_iterator::begin(GEP.getOperand(0)->getType(), + GEP.op_begin()+1); + } + inline gep_type_iterator gep_type_end(const User &GEP) { + return gep_type_iterator::end(GEP.op_end()); + } + + template<typename ItTy> + inline generic_gep_type_iterator<ItTy> + gep_type_begin(const Type *Op0, ItTy I, ItTy E) { + return generic_gep_type_iterator<ItTy>::begin(Op0, I); + } + + template<typename ItTy> + inline generic_gep_type_iterator<ItTy> + gep_type_end(const Type *Op0, ItTy I, ItTy E) { + return generic_gep_type_iterator<ItTy>::end(E); + } +} // end namespace llvm + +#endif diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h new file mode 100644 index 0000000..b9566b8 --- /dev/null +++ b/include/llvm/Support/GraphWriter.h @@ -0,0 +1,308 @@ +//===-- llvm/Support/GraphWriter.h - Write graph to a .dot file -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a simple interface that can be used to print out generic +// LLVM graphs to ".dot" files. "dot" is a tool that is part of the AT&T +// graphviz package (http://www.research.att.com/sw/tools/graphviz/) which can +// be used to turn the files output by this interface into a variety of +// different graphics formats. +// +// Graphs do not need to implement any interface past what is already required +// by the GraphTraits template, but they can choose to implement specializations +// of the DOTGraphTraits template if they want to customize the graphs output in +// any way. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_GRAPHWRITER_H +#define LLVM_SUPPORT_GRAPHWRITER_H + +#include "llvm/Support/Debug.h" +#include "llvm/Support/DOTGraphTraits.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/System/Path.h" +#include <fstream> +#include <vector> + +namespace llvm { + +namespace DOT { // Private functions... + inline std::string EscapeString(const std::string &Label) { + std::string Str(Label); + for (unsigned i = 0; i != Str.length(); ++i) + switch (Str[i]) { + case '\n': + Str.insert(Str.begin()+i, '\\'); // Escape character... + ++i; + Str[i] = 'n'; + break; + case '\t': + Str.insert(Str.begin()+i, ' '); // Convert to two spaces + ++i; + Str[i] = ' '; + break; + case '\\': + if (i+1 != Str.length() && Str[i+1] == 'l') + break; // don't disturb \l + case '{': case '}': + case '<': case '>': + case '"': + Str.insert(Str.begin()+i, '\\'); // Escape character... + ++i; // don't infinite loop + break; + } + return Str; + } +} + +void DisplayGraph(const sys::Path& Filename); + +template<typename GraphType> +class GraphWriter { + std::ostream &O; + const GraphType &G; + + typedef DOTGraphTraits<GraphType> DOTTraits; + typedef GraphTraits<GraphType> GTraits; + typedef typename GTraits::NodeType NodeType; + typedef typename GTraits::nodes_iterator node_iterator; + typedef typename GTraits::ChildIteratorType child_iterator; +public: + GraphWriter(std::ostream &o, const GraphType &g) : O(o), G(g) {} + + void writeHeader(const std::string &Name) { + if (Name.empty()) + O << "digraph foo {\n"; // Graph name doesn't matter + else + O << "digraph " << Name << " {\n"; + + if (DOTTraits::renderGraphFromBottomUp()) + O << "\trankdir=\"BT\";\n"; + + std::string GraphName = DOTTraits::getGraphName(G); + if (!GraphName.empty()) + O << "\tlabel=\"" << DOT::EscapeString(GraphName) << "\";\n"; + O << DOTTraits::getGraphProperties(G); + O << "\n"; + } + + void writeFooter() { + // Finish off the graph + O << "}\n"; + } + + void writeNodes() { + // Loop over the graph, printing it out... + for (node_iterator I = GTraits::nodes_begin(G), E = GTraits::nodes_end(G); + I != E; ++I) + writeNode(&*I); + } + + void writeNode(NodeType *const *Node) { + writeNode(*Node); + } + + void writeNode(NodeType *Node) { + std::string NodeAttributes = DOTTraits::getNodeAttributes(Node, G); + + O << "\tNode" << reinterpret_cast<const void*>(Node) << " [shape=record,"; + if (!NodeAttributes.empty()) O << NodeAttributes << ","; + O << "label=\"{"; + + if (!DOTTraits::renderGraphFromBottomUp()) { + O << DOT::EscapeString(DOTTraits::getNodeLabel(Node, G)); + + // If we should include the address of the node in the label, do so now. + if (DOTTraits::hasNodeAddressLabel(Node, G)) + O << "|" << (void*)Node; + } + + // Print out the fields of the current node... + child_iterator EI = GTraits::child_begin(Node); + child_iterator EE = GTraits::child_end(Node); + if (EI != EE) { + if (!DOTTraits::renderGraphFromBottomUp()) O << "|"; + O << "{"; + + for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) { + if (i) O << "|"; + O << "<g" << i << ">" << DOTTraits::getEdgeSourceLabel(Node, EI); + } + + if (EI != EE) + O << "|<g64>truncated..."; + O << "}"; + if (DOTTraits::renderGraphFromBottomUp()) O << "|"; + } + + if (DOTTraits::renderGraphFromBottomUp()) { + O << DOT::EscapeString(DOTTraits::getNodeLabel(Node, G)); + + // If we should include the address of the node in the label, do so now. + if (DOTTraits::hasNodeAddressLabel(Node, G)) + O << "|" << (void*)Node; + } + + O << "}\"];\n"; // Finish printing the "node" line + + // Output all of the edges now + EI = GTraits::child_begin(Node); + for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) + writeEdge(Node, i, EI); + for (; EI != EE; ++EI) + writeEdge(Node, 64, EI); + } + + void writeEdge(NodeType *Node, unsigned edgeidx, child_iterator EI) { + if (NodeType *TargetNode = *EI) { + int DestPort = -1; + if (DOTTraits::edgeTargetsEdgeSource(Node, EI)) { + child_iterator TargetIt = DOTTraits::getEdgeTarget(Node, EI); + + // Figure out which edge this targets... + unsigned Offset = std::distance(GTraits::child_begin(TargetNode), + TargetIt); + DestPort = static_cast<int>(Offset); + } + + emitEdge(reinterpret_cast<const void*>(Node), edgeidx, + reinterpret_cast<const void*>(TargetNode), DestPort, + DOTTraits::getEdgeAttributes(Node, EI)); + } + } + + /// emitSimpleNode - Outputs a simple (non-record) node + void emitSimpleNode(const void *ID, const std::string &Attr, + const std::string &Label, unsigned NumEdgeSources = 0, + const std::vector<std::string> *EdgeSourceLabels = 0) { + O << "\tNode" << ID << "[ "; + if (!Attr.empty()) + O << Attr << ","; + O << " label =\""; + if (NumEdgeSources) O << "{"; + O << DOT::EscapeString(Label); + if (NumEdgeSources) { + O << "|{"; + + for (unsigned i = 0; i != NumEdgeSources; ++i) { + if (i) O << "|"; + O << "<g" << i << ">"; + if (EdgeSourceLabels) O << (*EdgeSourceLabels)[i]; + } + O << "}}"; + } + O << "\"];\n"; + } + + /// emitEdge - Output an edge from a simple node into the graph... + void emitEdge(const void *SrcNodeID, int SrcNodePort, + const void *DestNodeID, int DestNodePort, + const std::string &Attrs) { + if (SrcNodePort > 64) return; // Eminating from truncated part? + if (DestNodePort > 64) DestNodePort = 64; // Targetting the truncated part? + + O << "\tNode" << SrcNodeID; + if (SrcNodePort >= 0) + O << ":g" << SrcNodePort; + O << " -> Node" << reinterpret_cast<const void*>(DestNodeID); + if (DestNodePort >= 0) + O << ":g" << DestNodePort; + + if (!Attrs.empty()) + O << "[" << Attrs << "]"; + O << ";\n"; + } +}; + +template<typename GraphType> +std::ostream &WriteGraph(std::ostream &O, const GraphType &G, + const std::string &Name = "") { + // Start the graph emission process... + GraphWriter<GraphType> W(O, G); + + // Output the header for the graph... + W.writeHeader(Name); + + // Emit all of the nodes in the graph... + W.writeNodes(); + + // Output any customizations on the graph + DOTGraphTraits<GraphType>::addCustomGraphFeatures(G, W); + + // Output the end of the graph + W.writeFooter(); + return O; +} + +template<typename GraphType> +sys::Path WriteGraph(const GraphType &G, + const std::string& Name, + const std::string& Title = "") { + std::string ErrMsg; + sys::Path Filename = sys::Path::GetTemporaryDirectory(&ErrMsg); + if (Filename.isEmpty()) { + cerr << "Error: " << ErrMsg << "\n"; + return Filename; + } + Filename.appendComponent(Name + ".dot"); + if (Filename.makeUnique(true,&ErrMsg)) { + cerr << "Error: " << ErrMsg << "\n"; + return sys::Path(); + } + + cerr << "Writing '" << Filename << "'... "; + + std::ofstream O(Filename.c_str()); + + if (O.good()) { + // Start the graph emission process... + GraphWriter<GraphType> W(O, G); + + // Output the header for the graph... + W.writeHeader(Title); + + // Emit all of the nodes in the graph... + W.writeNodes(); + + // Output any customizations on the graph + DOTGraphTraits<GraphType>::addCustomGraphFeatures(G, W); + + // Output the end of the graph + W.writeFooter(); + cerr << " done. \n"; + + O.close(); + + } else { + cerr << "error opening file for writing!\n"; + Filename.clear(); + } + + return Filename; +} + +/// ViewGraph - Emit a dot graph, run 'dot', run gv on the postscript file, +/// then cleanup. For use from the debugger. +/// +template<typename GraphType> +void ViewGraph(const GraphType& G, + const std::string& Name, + const std::string& Title = "") { + sys::Path Filename = WriteGraph(G, Name, Title); + + if (Filename.isEmpty()) { + return; + } + + DisplayGraph(Filename); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/InstIterator.h b/include/llvm/Support/InstIterator.h new file mode 100644 index 0000000..6f3a45e --- /dev/null +++ b/include/llvm/Support/InstIterator.h @@ -0,0 +1,147 @@ +//===- llvm/Support/InstIterator.h - Classes for inst iteration -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains definitions of two iterators for iterating over the +// instructions in a function. This is effectively a wrapper around a two level +// iterator that can probably be genericized later. +// +// Note that this iterator gets invalidated any time that basic blocks or +// instructions are moved around. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_INSTITERATOR_H +#define LLVM_SUPPORT_INSTITERATOR_H + +#include "llvm/BasicBlock.h" +#include "llvm/Function.h" + +namespace llvm { + +// This class implements inst_begin() & inst_end() for +// inst_iterator and const_inst_iterator's. +// +template <class _BB_t, class _BB_i_t, class _BI_t, class _II_t> +class InstIterator { + typedef _BB_t BBty; + typedef _BB_i_t BBIty; + typedef _BI_t BIty; + typedef _II_t IIty; + _BB_t *BBs; // BasicBlocksType + _BB_i_t BB; // BasicBlocksType::iterator + _BI_t BI; // BasicBlock::iterator +public: + typedef std::bidirectional_iterator_tag iterator_category; + typedef IIty value_type; + typedef signed difference_type; + typedef IIty* pointer; + typedef IIty& reference; + + // Default constructor + InstIterator() {} + + // Copy constructor... + template<typename A, typename B, typename C, typename D> + InstIterator(const InstIterator<A,B,C,D> &II) + : BBs(II.BBs), BB(II.BB), BI(II.BI) {} + + template<typename A, typename B, typename C, typename D> + InstIterator(InstIterator<A,B,C,D> &II) + : BBs(II.BBs), BB(II.BB), BI(II.BI) {} + + template<class M> InstIterator(M &m) + : BBs(&m.getBasicBlockList()), BB(BBs->begin()) { // begin ctor + if (BB != BBs->end()) { + BI = BB->begin(); + advanceToNextBB(); + } + } + + template<class M> InstIterator(M &m, bool) + : BBs(&m.getBasicBlockList()), BB(BBs->end()) { // end ctor + } + + // Accessors to get at the underlying iterators... + inline BBIty &getBasicBlockIterator() { return BB; } + inline BIty &getInstructionIterator() { return BI; } + + inline reference operator*() const { return *BI; } + inline pointer operator->() const { return &operator*(); } + + inline bool operator==(const InstIterator &y) const { + return BB == y.BB && (BB == BBs->end() || BI == y.BI); + } + inline bool operator!=(const InstIterator& y) const { + return !operator==(y); + } + + InstIterator& operator++() { + ++BI; + advanceToNextBB(); + return *this; + } + inline InstIterator operator++(int) { + InstIterator tmp = *this; ++*this; return tmp; + } + + InstIterator& operator--() { + while (BB == BBs->end() || BI == BB->begin()) { + --BB; + BI = BB->end(); + } + --BI; + return *this; + } + inline InstIterator operator--(int) { + InstIterator tmp = *this; --*this; return tmp; + } + + inline bool atEnd() const { return BB == BBs->end(); } + +private: + inline void advanceToNextBB() { + // The only way that the II could be broken is if it is now pointing to + // the end() of the current BasicBlock and there are successor BBs. + while (BI == BB->end()) { + ++BB; + if (BB == BBs->end()) break; + BI = BB->begin(); + } + } +}; + + +typedef InstIterator<iplist<BasicBlock>, + Function::iterator, BasicBlock::iterator, + Instruction> inst_iterator; +typedef InstIterator<const iplist<BasicBlock>, + Function::const_iterator, + BasicBlock::const_iterator, + const Instruction> const_inst_iterator; + +inline inst_iterator inst_begin(Function *F) { return inst_iterator(*F); } +inline inst_iterator inst_end(Function *F) { return inst_iterator(*F, true); } +inline const_inst_iterator inst_begin(const Function *F) { + return const_inst_iterator(*F); +} +inline const_inst_iterator inst_end(const Function *F) { + return const_inst_iterator(*F, true); +} +inline inst_iterator inst_begin(Function &F) { return inst_iterator(F); } +inline inst_iterator inst_end(Function &F) { return inst_iterator(F, true); } +inline const_inst_iterator inst_begin(const Function &F) { + return const_inst_iterator(F); +} +inline const_inst_iterator inst_end(const Function &F) { + return const_inst_iterator(F, true); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/InstVisitor.h b/include/llvm/Support/InstVisitor.h new file mode 100644 index 0000000..e848c9b --- /dev/null +++ b/include/llvm/Support/InstVisitor.h @@ -0,0 +1,221 @@ +//===- llvm/Support/InstVisitor.h - Define instruction visitors -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_SUPPORT_INSTVISITOR_H +#define LLVM_SUPPORT_INSTVISITOR_H + +#include "llvm/Function.h" +#include "llvm/Instructions.h" +#include "llvm/Module.h" + +namespace llvm { + +// We operate on opaque instruction classes, so forward declare all instruction +// types now... +// +#define HANDLE_INST(NUM, OPCODE, CLASS) class CLASS; +#include "llvm/Instruction.def" + +// Forward declare the intermediate types... +class TerminatorInst; class BinaryOperator; +class AllocationInst; + +#define DELEGATE(CLASS_TO_VISIT) \ + return static_cast<SubClass*>(this)-> \ + visit##CLASS_TO_VISIT(static_cast<CLASS_TO_VISIT&>(I)) + + +/// @brief Base class for instruction visitors +/// +/// Instruction visitors are used when you want to perform different action for +/// different kinds of instruction without without having to use lots of casts +/// and a big switch statement (in your code that is). +/// +/// To define your own visitor, inherit from this class, specifying your +/// new type for the 'SubClass' template parameter, and "override" visitXXX +/// functions in your class. I say "overriding" because this class is defined +/// in terms of statically resolved overloading, not virtual functions. +/// +/// For example, here is a visitor that counts the number of malloc +/// instructions processed: +/// +/// /// Declare the class. Note that we derive from InstVisitor instantiated +/// /// with _our new subclasses_ type. +/// /// +/// struct CountMallocVisitor : public InstVisitor<CountMallocVisitor> { +/// unsigned Count; +/// CountMallocVisitor() : Count(0) {} +/// +/// void visitMallocInst(MallocInst &MI) { ++Count; } +/// }; +/// +/// And this class would be used like this: +/// CountMallocVistor CMV; +/// CMV.visit(function); +/// NumMallocs = CMV.Count; +/// +/// The defined has 'visit' methods for Instruction, and also for BasicBlock, +/// Function, and Module, which recursively process all conained instructions. +/// +/// Note that if you don't implement visitXXX for some instruction type, +/// the visitXXX method for instruction superclass will be invoked. So +/// if instructions are added in the future, they will be automatically +/// supported, if you handle on of their superclasses. +/// +/// The optional second template argument specifies the type that instruction +/// visitation functions should return. If you specify this, you *MUST* provide +/// an implementation of visitInstruction though!. +/// +/// Note that this class is specifically designed as a template to avoid +/// virtual function call overhead. Defining and using an InstVisitor is just +/// as efficient as having your own switch statement over the instruction +/// opcode. +template<typename SubClass, typename RetTy=void> +class InstVisitor { + //===--------------------------------------------------------------------===// + // Interface code - This is the public interface of the InstVisitor that you + // use to visit instructions... + // + +public: + // Generic visit method - Allow visitation to all instructions in a range + template<class Iterator> + void visit(Iterator Start, Iterator End) { + while (Start != End) + static_cast<SubClass*>(this)->visit(*Start++); + } + + // Define visitors for functions and basic blocks... + // + void visit(Module &M) { + static_cast<SubClass*>(this)->visitModule(M); + visit(M.begin(), M.end()); + } + void visit(Function &F) { + static_cast<SubClass*>(this)->visitFunction(F); + visit(F.begin(), F.end()); + } + void visit(BasicBlock &BB) { + static_cast<SubClass*>(this)->visitBasicBlock(BB); + visit(BB.begin(), BB.end()); + } + + // Forwarding functions so that the user can visit with pointers AND refs. + void visit(Module *M) { visit(*M); } + void visit(Function *F) { visit(*F); } + void visit(BasicBlock *BB) { visit(*BB); } + RetTy visit(Instruction *I) { return visit(*I); } + + // visit - Finally, code to visit an instruction... + // + RetTy visit(Instruction &I) { + switch (I.getOpcode()) { + default: assert(0 && "Unknown instruction type encountered!"); + abort(); + // Build the switch statement using the Instruction.def file... +#define HANDLE_INST(NUM, OPCODE, CLASS) \ + case Instruction::OPCODE: return \ + static_cast<SubClass*>(this)-> \ + visit##OPCODE(static_cast<CLASS&>(I)); +#include "llvm/Instruction.def" + } + } + + //===--------------------------------------------------------------------===// + // Visitation functions... these functions provide default fallbacks in case + // the user does not specify what to do for a particular instruction type. + // The default behavior is to generalize the instruction type to its subtype + // and try visiting the subtype. All of this should be inlined perfectly, + // because there are no virtual functions to get in the way. + // + + // When visiting a module, function or basic block directly, these methods get + // called to indicate when transitioning into a new unit. + // + void visitModule (Module &M) {} + void visitFunction (Function &F) {} + void visitBasicBlock(BasicBlock &BB) {} + + // Define instruction specific visitor functions that can be overridden to + // handle SPECIFIC instructions. These functions automatically define + // visitMul to proxy to visitBinaryOperator for instance in case the user does + // not need this generality. + // + // The one problem case we have to handle here though is that the PHINode + // class and opcode name are the exact same. Because of this, we cannot + // define visitPHINode (the inst version) to forward to visitPHINode (the + // generic version) without multiply defined symbols and recursion. To handle + // this, we do not autoexpand "Other" instructions, we do it manually. + // +#define HANDLE_INST(NUM, OPCODE, CLASS) \ + RetTy visit##OPCODE(CLASS &I) { DELEGATE(CLASS); } +#include "llvm/Instruction.def" + + // Specific Instruction type classes... note that all of the casts are + // necessary because we use the instruction classes as opaque types... + // + RetTy visitReturnInst(ReturnInst &I) { DELEGATE(TerminatorInst);} + RetTy visitBranchInst(BranchInst &I) { DELEGATE(TerminatorInst);} + RetTy visitSwitchInst(SwitchInst &I) { DELEGATE(TerminatorInst);} + RetTy visitInvokeInst(InvokeInst &I) { DELEGATE(TerminatorInst);} + RetTy visitUnwindInst(UnwindInst &I) { DELEGATE(TerminatorInst);} + RetTy visitUnreachableInst(UnreachableInst &I) { DELEGATE(TerminatorInst);} + RetTy visitICmpInst(ICmpInst &I) { DELEGATE(CmpInst);} + RetTy visitFCmpInst(FCmpInst &I) { DELEGATE(CmpInst);} + RetTy visitMallocInst(MallocInst &I) { DELEGATE(AllocationInst);} + RetTy visitAllocaInst(AllocaInst &I) { DELEGATE(AllocationInst);} + RetTy visitFreeInst(FreeInst &I) { DELEGATE(Instruction); } + RetTy visitLoadInst(LoadInst &I) { DELEGATE(Instruction); } + RetTy visitStoreInst(StoreInst &I) { DELEGATE(Instruction); } + RetTy visitGetElementPtrInst(GetElementPtrInst &I){ DELEGATE(Instruction); } + RetTy visitPHINode(PHINode &I) { DELEGATE(Instruction); } + RetTy visitTruncInst(TruncInst &I) { DELEGATE(CastInst); } + RetTy visitZExtInst(ZExtInst &I) { DELEGATE(CastInst); } + RetTy visitSExtInst(SExtInst &I) { DELEGATE(CastInst); } + RetTy visitFPTruncInst(FPTruncInst &I) { DELEGATE(CastInst); } + RetTy visitFPExtInst(FPExtInst &I) { DELEGATE(CastInst); } + RetTy visitFPToUIInst(FPToUIInst &I) { DELEGATE(CastInst); } + RetTy visitFPToSIInst(FPToSIInst &I) { DELEGATE(CastInst); } + RetTy visitUIToFPInst(UIToFPInst &I) { DELEGATE(CastInst); } + RetTy visitSIToFPInst(SIToFPInst &I) { DELEGATE(CastInst); } + RetTy visitPtrToIntInst(PtrToIntInst &I) { DELEGATE(CastInst); } + RetTy visitIntToPtrInst(IntToPtrInst &I) { DELEGATE(CastInst); } + RetTy visitBitCastInst(BitCastInst &I) { DELEGATE(CastInst); } + RetTy visitSelectInst(SelectInst &I) { DELEGATE(Instruction); } + RetTy visitCallInst(CallInst &I) { DELEGATE(Instruction); } + RetTy visitVAArgInst(VAArgInst &I) { DELEGATE(Instruction); } + RetTy visitExtractElementInst(ExtractElementInst &I) { DELEGATE(Instruction);} + RetTy visitInsertElementInst(InsertElementInst &I) { DELEGATE(Instruction); } + RetTy visitShuffleVectorInst(ShuffleVectorInst &I) { DELEGATE(Instruction); } + + // Next level propagators... if the user does not overload a specific + // instruction type, they can overload one of these to get the whole class + // of instructions... + // + RetTy visitTerminatorInst(TerminatorInst &I) { DELEGATE(Instruction); } + RetTy visitBinaryOperator(BinaryOperator &I) { DELEGATE(Instruction); } + RetTy visitAllocationInst(AllocationInst &I) { DELEGATE(Instruction); } + RetTy visitCmpInst(CmpInst &I) { DELEGATE(Instruction); } + RetTy visitCastInst(CastInst &I) { DELEGATE(Instruction); } + + // If the user wants a 'default' case, they can choose to override this + // function. If this function is not overloaded in the users subclass, then + // this instruction just gets ignored. + // + // Note that you MUST override this function if your return type is not void. + // + void visitInstruction(Instruction &I) {} // Ignore unhandled instructions +}; + +#undef DELEGATE + +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/LLVMBuilder.h b/include/llvm/Support/LLVMBuilder.h new file mode 100644 index 0000000..5a80e41 --- /dev/null +++ b/include/llvm/Support/LLVMBuilder.h @@ -0,0 +1,431 @@ +//===-- llvm/Support/LLVMBuilder.h - Builder for LLVM Instrs ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the LLVMBuilder class, which is used as a convenient way +// to create LLVM instructions with a consistent and simplified interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_LLVMBUILDER_H +#define LLVM_SUPPORT_LLVMBUILDER_H + +#include "llvm/BasicBlock.h" +#include "llvm/Instructions.h" + +namespace llvm { + +/// LLVMBuilder - This provides a uniform API for creating instructions and +/// inserting them into a basic block: either at the end of a BasicBlock, or +/// at a specific iterator location in a block. +/// +/// Note that the builder does not expose the full generality of LLVM +/// instructions. For example, it cannot be used to create instructions with +/// arbitrary names (specifically, names with nul characters in them) - It only +/// supports nul-terminated C strings. For fully generic names, use +/// I->setName(). For access to extra instruction properties, use the mutators +/// (e.g. setVolatile) on the instructions after they have been created. +class LLVMBuilder { + BasicBlock *BB; + BasicBlock::iterator InsertPt; +public: + LLVMBuilder() { ClearInsertionPoint(); } + explicit LLVMBuilder(BasicBlock *TheBB) { SetInsertPoint(TheBB); } + LLVMBuilder(BasicBlock *TheBB, BasicBlock::iterator IP) { + SetInsertPoint(TheBB, IP); + } + + //===--------------------------------------------------------------------===// + // Builder configuration methods + //===--------------------------------------------------------------------===// + + /// ClearInsertionPoint - Clear the insertion point: created instructions will + /// not be inserted into a block. + void ClearInsertionPoint() { + BB = 0; + } + + BasicBlock *GetInsertBlock() const { return BB; } + + /// SetInsertPoint - This specifies that created instructions should be + /// appended to the end of the specified block. + void SetInsertPoint(BasicBlock *TheBB) { + BB = TheBB; + InsertPt = BB->end(); + } + + /// SetInsertPoint - This specifies that created instructions should be + /// inserted at the specified point. + void SetInsertPoint(BasicBlock *TheBB, BasicBlock::iterator IP) { + BB = TheBB; + InsertPt = IP; + } + + /// Insert - Insert and return the specified instruction. + template<typename InstTy> + InstTy *Insert(InstTy *I) const { + InsertHelper(I); + return I; + } + + /// InsertHelper - Insert the specified instruction at the specified insertion + /// point. This is split out of Insert so that it isn't duplicated for every + /// template instantiation. + void InsertHelper(Instruction *I) const { + if (BB) BB->getInstList().insert(InsertPt, I); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Terminators + //===--------------------------------------------------------------------===// + + /// CreateRetVoid - Create a 'ret void' instruction. + ReturnInst *CreateRetVoid() { + return Insert(new ReturnInst()); + } + + /// CreateRet - Create a 'ret <val>' instruction. + ReturnInst *CreateRet(Value *V) { + return Insert(new ReturnInst(V)); + } + + /// CreateBr - Create an unconditional 'br label X' instruction. + BranchInst *CreateBr(BasicBlock *Dest) { + return Insert(new BranchInst(Dest)); + } + + /// CreateCondBr - Create a conditional 'br Cond, TrueDest, FalseDest' + /// instruction. + BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False) { + return Insert(new BranchInst(True, False, Cond)); + } + + /// CreateSwitch - Create a switch instruction with the specified value, + /// default dest, and with a hint for the number of cases that will be added + /// (for efficient allocation). + SwitchInst *CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases = 10) { + return Insert(new SwitchInst(V, Dest, NumCases)); + } + + /// CreateInvoke - Create an invoke instruction. + InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, + BasicBlock *UnwindDest, + Value *const* Args, unsigned NumArgs, + const char *Name = "") { + return Insert(new InvokeInst(Callee, NormalDest, UnwindDest, Args, NumArgs, + Name)); + } + + UnwindInst *CreateUnwind() { + return Insert(new UnwindInst()); + } + + UnreachableInst *CreateUnreachable() { + return Insert(new UnreachableInst()); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Binary Operators + //===--------------------------------------------------------------------===// + + BinaryOperator *CreateAdd(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(BinaryOperator::createAdd(LHS, RHS, Name)); + } + BinaryOperator *CreateSub(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(BinaryOperator::createSub(LHS, RHS, Name)); + } + BinaryOperator *CreateMul(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(BinaryOperator::createMul(LHS, RHS, Name)); + } + BinaryOperator *CreateUDiv(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(BinaryOperator::createUDiv(LHS, RHS, Name)); + } + BinaryOperator *CreateSDiv(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(BinaryOperator::createSDiv(LHS, RHS, Name)); + } + BinaryOperator *CreateFDiv(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(BinaryOperator::createFDiv(LHS, RHS, Name)); + } + BinaryOperator *CreateURem(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(BinaryOperator::createURem(LHS, RHS, Name)); + } + BinaryOperator *CreateSRem(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(BinaryOperator::createSRem(LHS, RHS, Name)); + } + BinaryOperator *CreateFRem(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(BinaryOperator::createFRem(LHS, RHS, Name)); + } + BinaryOperator *CreateShl(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(BinaryOperator::createShl(LHS, RHS, Name)); + } + BinaryOperator *CreateLShr(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(BinaryOperator::createLShr(LHS, RHS, Name)); + } + BinaryOperator *CreateAShr(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(BinaryOperator::createAShr(LHS, RHS, Name)); + } + BinaryOperator *CreateAnd(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(BinaryOperator::createAnd(LHS, RHS, Name)); + } + BinaryOperator *CreateOr(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(BinaryOperator::createOr(LHS, RHS, Name)); + } + BinaryOperator *CreateXor(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(BinaryOperator::createXor(LHS, RHS, Name)); + } + + BinaryOperator *CreateBinOp(Instruction::BinaryOps Opc, + Value *LHS, Value *RHS, const char *Name = "") { + return Insert(BinaryOperator::create(Opc, LHS, RHS, Name)); + } + + BinaryOperator *CreateNeg(Value *V, const char *Name = "") { + return Insert(BinaryOperator::createNeg(V, Name)); + } + BinaryOperator *CreateNot(Value *V, const char *Name = "") { + return Insert(BinaryOperator::createNot(V, Name)); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Memory Instructions + //===--------------------------------------------------------------------===// + + MallocInst *CreateMalloc(const Type *Ty, Value *ArraySize = 0, + const char *Name = "") { + return Insert(new MallocInst(Ty, ArraySize, Name)); + } + AllocaInst *CreateAlloca(const Type *Ty, Value *ArraySize = 0, + const char *Name = "") { + return Insert(new AllocaInst(Ty, ArraySize, Name)); + } + FreeInst *CreateFree(Value *Ptr) { + return Insert(new FreeInst(Ptr)); + } + LoadInst *CreateLoad(Value *Ptr, const char *Name = 0) { + return Insert(new LoadInst(Ptr, Name)); + } + LoadInst *CreateLoad(Value *Ptr, bool isVolatile, const char *Name = 0) { + return Insert(new LoadInst(Ptr, Name, isVolatile)); + } + StoreInst *CreateStore(Value *Val, Value *Ptr, bool isVolatile = false) { + return Insert(new StoreInst(Val, Ptr, isVolatile)); + } + GetElementPtrInst *CreateGEP(Value *Ptr, Value* const *Idx, unsigned NumIdx, + const char *Name = "") { + return Insert(new GetElementPtrInst(Ptr, Idx, NumIdx, Name)); + } + GetElementPtrInst *CreateGEP(Value *Ptr, Value *Idx, const char *Name = "") { + return Insert(new GetElementPtrInst(Ptr, &Idx, 1, Name)); + } + GetElementPtrInst *CreateGEP(Value *Ptr, Value *Idx0, Value *Idx1, + const char *Name = "") { + return Insert(new GetElementPtrInst(Ptr, Idx0, Idx1, Name)); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Cast/Conversion Operators + //===--------------------------------------------------------------------===// + + TruncInst *CreateTrunc(Value *V, const Type *DestTy, const char *Name = "") { + return Insert(new TruncInst(V, DestTy, Name)); + } + ZExtInst *CreateZExt(Value *V, const Type *DestTy, const char *Name = "") { + return Insert(new ZExtInst(V, DestTy, Name)); + } + SExtInst *CreateSExt(Value *V, const Type *DestTy, const char *Name = "") { + return Insert(new SExtInst(V, DestTy, Name)); + } + FPToUIInst *CreateFPToUI(Value *V, const Type *DestTy, const char *Name = ""){ + return Insert(new FPToUIInst(V, DestTy, Name)); + } + FPToSIInst *CreateFPToSI(Value *V, const Type *DestTy, const char *Name = ""){ + return Insert(new FPToSIInst(V, DestTy, Name)); + } + UIToFPInst *CreateUIToFP(Value *V, const Type *DestTy, const char *Name = ""){ + return Insert(new UIToFPInst(V, DestTy, Name)); + } + SIToFPInst *CreateSIToFP(Value *V, const Type *DestTy, const char *Name = ""){ + return Insert(new SIToFPInst(V, DestTy, Name)); + } + FPTruncInst *CreateFPTrunc(Value *V, const Type *DestTy, + const char *Name = "") { + return Insert(new FPTruncInst(V, DestTy, Name)); + } + FPExtInst *CreateFPExt(Value *V, const Type *DestTy, const char *Name = "") { + return Insert(new FPExtInst(V, DestTy, Name)); + } + PtrToIntInst *CreatePtrToInt(Value *V, const Type *DestTy, + const char *Name = "") { + return Insert(new PtrToIntInst(V, DestTy, Name)); + } + IntToPtrInst *CreateIntToPtr(Value *V, const Type *DestTy, + const char *Name = "") { + return Insert(new IntToPtrInst(V, DestTy, Name)); + } + BitCastInst *CreateBitCast(Value *V, const Type *DestTy, + const char *Name = "") { + return Insert(new BitCastInst(V, DestTy, Name)); + } + + CastInst *CreateCast(Instruction::CastOps Op, Value *V, const Type *DestTy, + const char *Name = "") { + return Insert(CastInst::create(Op, V, DestTy, Name)); + } + CastInst *CreateIntCast(Value *V, const Type *DestTy, bool isSigned, + const char *Name = "") { + return Insert(CastInst::createIntegerCast(V, DestTy, isSigned, Name)); + } + + + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Compare Instructions + //===--------------------------------------------------------------------===// + + ICmpInst *CreateICmpEQ(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new ICmpInst(ICmpInst::ICMP_EQ, LHS, RHS, Name)); + } + ICmpInst *CreateICmpNE(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new ICmpInst(ICmpInst::ICMP_NE, LHS, RHS, Name)); + } + ICmpInst *CreateICmpUGT(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new ICmpInst(ICmpInst::ICMP_UGT, LHS, RHS, Name)); + } + ICmpInst *CreateICmpUGE(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new ICmpInst(ICmpInst::ICMP_UGE, LHS, RHS, Name)); + } + ICmpInst *CreateICmpULT(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new ICmpInst(ICmpInst::ICMP_ULT, LHS, RHS, Name)); + } + ICmpInst *CreateICmpULE(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new ICmpInst(ICmpInst::ICMP_ULE, LHS, RHS, Name)); + } + ICmpInst *CreateICmpSGT(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new ICmpInst(ICmpInst::ICMP_SGT, LHS, RHS, Name)); + } + ICmpInst *CreateICmpSGE(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new ICmpInst(ICmpInst::ICMP_SGE, LHS, RHS, Name)); + } + ICmpInst *CreateICmpSLT(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new ICmpInst(ICmpInst::ICMP_SLT, LHS, RHS, Name)); + } + ICmpInst *CreateICmpSLE(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new ICmpInst(ICmpInst::ICMP_SLE, LHS, RHS, Name)); + } + + FCmpInst *CreateFCmpOEQ(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new FCmpInst(FCmpInst::FCMP_OEQ, LHS, RHS, Name)); + } + FCmpInst *CreateFCmpOGT(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new FCmpInst(FCmpInst::FCMP_OGT, LHS, RHS, Name)); + } + FCmpInst *CreateFCmpOGE(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new FCmpInst(FCmpInst::FCMP_OGE, LHS, RHS, Name)); + } + FCmpInst *CreateFCmpOLT(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new FCmpInst(FCmpInst::FCMP_OLT, LHS, RHS, Name)); + } + FCmpInst *CreateFCmpOLE(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new FCmpInst(FCmpInst::FCMP_OLE, LHS, RHS, Name)); + } + FCmpInst *CreateFCmpONE(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new FCmpInst(FCmpInst::FCMP_ONE, LHS, RHS, Name)); + } + FCmpInst *CreateFCmpORD(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new FCmpInst(FCmpInst::FCMP_ORD, LHS, RHS, Name)); + } + FCmpInst *CreateFCmpUNO(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new FCmpInst(FCmpInst::FCMP_UNO, LHS, RHS, Name)); + } + FCmpInst *CreateFCmpUEQ(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new FCmpInst(FCmpInst::FCMP_UEQ, LHS, RHS, Name)); + } + FCmpInst *CreateFCmpUGT(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new FCmpInst(FCmpInst::FCMP_UGT, LHS, RHS, Name)); + } + FCmpInst *CreateFCmpUGE(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new FCmpInst(FCmpInst::FCMP_UGE, LHS, RHS, Name)); + } + FCmpInst *CreateFCmpULT(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new FCmpInst(FCmpInst::FCMP_ULT, LHS, RHS, Name)); + } + FCmpInst *CreateFCmpULE(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new FCmpInst(FCmpInst::FCMP_ULE, LHS, RHS, Name)); + } + FCmpInst *CreateFCmpUNE(Value *LHS, Value *RHS, const char *Name = "") { + return Insert(new FCmpInst(FCmpInst::FCMP_UNE, LHS, RHS, Name)); + } + + + ICmpInst *CreateICmp(ICmpInst::Predicate P, Value *LHS, Value *RHS, + const char *Name = "") { + return Insert(new ICmpInst(P, LHS, RHS, Name)); + } + FCmpInst *CreateFCmp(FCmpInst::Predicate P, Value *LHS, Value *RHS, + const char *Name = "") { + return Insert(new FCmpInst(P, LHS, RHS, Name)); + } + + //===--------------------------------------------------------------------===// + // Instruction creation methods: Other Instructions + //===--------------------------------------------------------------------===// + + PHINode *CreatePHI(const Type *Ty, const char *Name = "") { + return Insert(new PHINode(Ty, Name)); + } + + CallInst *CreateCall(Value *Callee, const char *Name = "") { + return Insert(new CallInst(Callee, (Value**)0, 0, Name)); + } + CallInst *CreateCall(Value *Callee, Value *Arg, const char *Name = "") { + return Insert(new CallInst(Callee, &Arg, 1, Name)); + } + CallInst *CreateCall(Value *Callee, Value *Arg0, Value *Arg1, + const char *Name = "") { + Value *Args[] = { Arg0, Arg1 }; + return Insert(new CallInst(Callee, Args, 2, Name)); + } + + + CallInst *CreateCall(Value *Callee, Value* const *Args, unsigned NumArgs, + const char *Name = "") { + return Insert(new CallInst(Callee, Args, NumArgs, Name)); + } + + SelectInst *CreateSelect(Value *C, Value *True, Value *False, + const char *Name = "") { + return Insert(new SelectInst(C, True, False, Name)); + } + + VAArgInst *CreateVAArg(Value *List, const Type *Ty, const char *Name = "") { + return Insert(new VAArgInst(List, Ty, Name)); + } + + ExtractElementInst *CreateExtractElement(Value *Vec, Value *Idx, + const char *Name = "") { + return Insert(new ExtractElementInst(Vec, Idx, Name)); + } + + InsertElementInst *CreateInsertElement(Value *Vec, Value *NewElt, Value *Idx, + const char *Name = "") { + return Insert(new InsertElementInst(Vec, NewElt, Idx, Name)); + } + + ShuffleVectorInst *CreateShuffleVector(Value *V1, Value *V2, Value *Mask, + const char *Name = "") { + return Insert(new ShuffleVectorInst(V1, V2, Mask, Name)); + } +}; + +// TODO: A version of LLVMBuilder that constant folds operands as they come in. +//class LLVMFoldingBuilder { +//}; + +} + +#endif diff --git a/include/llvm/Support/LeakDetector.h b/include/llvm/Support/LeakDetector.h new file mode 100644 index 0000000..92784ee --- /dev/null +++ b/include/llvm/Support/LeakDetector.h @@ -0,0 +1,91 @@ +//===-- llvm/Support/LeakDetector.h - Provide leak detection ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a class that can be used to provide very simple memory leak +// checks for an API. Basically LLVM uses this to make sure that Instructions, +// for example, are deleted when they are supposed to be, and not leaked away. +// +// When compiling with NDEBUG (Release build), this class does nothing, thus +// adding no checking overhead to release builds. Note that this class is +// implemented in a very simple way, requiring completely manual manipulation +// and checking for garbage, but this is intentional: users should not be using +// this API, only other APIs should. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_LEAKDETECTOR_H +#define LLVM_SUPPORT_LEAKDETECTOR_H + +#include <string> + +namespace llvm { + +class Value; + +struct LeakDetector { + /// addGarbageObject - Add a pointer to the internal set of "garbage" object + /// pointers. This should be called when objects are created, or if they are + /// taken out of an owning collection. + /// + static void addGarbageObject(void *Object) { +#ifndef NDEBUG + addGarbageObjectImpl(Object); +#endif + } + + /// removeGarbageObject - Remove a pointer from our internal representation of + /// our "garbage" objects. This should be called when an object is added to + /// an "owning" collection. + /// + static void removeGarbageObject(void *Object) { +#ifndef NDEBUG + removeGarbageObjectImpl(Object); +#endif + } + + /// checkForGarbage - Traverse the internal representation of garbage + /// pointers. If there are any pointers that have been add'ed, but not + /// remove'd, big obnoxious warnings about memory leaks are issued. + /// + /// The specified message will be printed indicating when the check was + /// performed. + /// + static void checkForGarbage(const std::string &Message) { +#ifndef NDEBUG + checkForGarbageImpl(Message); +#endif + } + + /// Overload the normal methods to work better with Value*'s because they are + /// by far the most common in LLVM. This does not affect the actual + /// functioning of this class, it just makes the warning messages nicer. + /// + static void addGarbageObject(const Value *Object) { +#ifndef NDEBUG + addGarbageObjectImpl(Object); +#endif + } + static void removeGarbageObject(const Value *Object) { +#ifndef NDEBUG + removeGarbageObjectImpl(Object); +#endif + } + +private: + // If we are debugging, the actual implementations will be called... + static void addGarbageObjectImpl(const Value *Object); + static void removeGarbageObjectImpl(const Value *Object); + static void addGarbageObjectImpl(void *Object); + static void removeGarbageObjectImpl(void *Object); + static void checkForGarbageImpl(const std::string &Message); +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/ManagedStatic.h b/include/llvm/Support/ManagedStatic.h new file mode 100644 index 0000000..e65fb1b --- /dev/null +++ b/include/llvm/Support/ManagedStatic.h @@ -0,0 +1,96 @@ +//===-- llvm/Support/ManagedStatic.h - Static Global wrapper ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ManagedStatic class and the llvm_shutdown() function. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MANAGED_STATIC_H +#define LLVM_SUPPORT_MANAGED_STATIC_H + +namespace llvm { + +/// object_deleter - Helper method for ManagedStatic. +/// +template<class C> +void object_deleter(void *Ptr) { + delete (C*)Ptr; +} + +/// ManagedStaticBase - Common base class for ManagedStatic instances. +class ManagedStaticBase { +protected: + // This should only be used as a static variable, which guarantees that this + // will be zero initialized. + mutable void *Ptr; + mutable void (*DeleterFn)(void*); + mutable const ManagedStaticBase *Next; + + void RegisterManagedStatic(void *ObjPtr, void (*deleter)(void*)) const; +public: + /// isConstructed - Return true if this object has not been created yet. + bool isConstructed() const { return Ptr != 0; } + + void destroy() const; +}; + +/// ManagedStatic - This transparently changes the behavior of global statics to +/// be lazily constructed on demand (good for reducing startup times of dynamic +/// libraries that link in LLVM components) and for making destruction be +/// explicit through the llvm_shutdown() function call. +/// +template<class C> +class ManagedStatic : public ManagedStaticBase { +public: + + // Accessors. + C &operator*() { + if (!Ptr) LazyInit(); + return *static_cast<C*>(Ptr); + } + C *operator->() { + if (!Ptr) LazyInit(); + return static_cast<C*>(Ptr); + } + const C &operator*() const { + if (!Ptr) LazyInit(); + return *static_cast<C*>(Ptr); + } + const C *operator->() const { + if (!Ptr) LazyInit(); + return static_cast<C*>(Ptr); + } + +public: + void LazyInit() const { + RegisterManagedStatic(new C(), object_deleter<C>); + } +}; + +template<void (*CleanupFn)(void*)> +class ManagedCleanup : public ManagedStaticBase { +public: + void Register() { RegisterManagedStatic(0, CleanupFn); } +}; + + +/// llvm_shutdown - Deallocate and destroy all ManagedStatic variables. +void llvm_shutdown(); + + +/// llvm_shutdown_obj - This is a simple helper class that calls +/// llvm_shutdown() when it is destroyed. +struct llvm_shutdown_obj { + llvm_shutdown_obj() {} + ~llvm_shutdown_obj() { llvm_shutdown(); } +}; + +} + +#endif diff --git a/include/llvm/Support/Mangler.h b/include/llvm/Support/Mangler.h new file mode 100644 index 0000000..b6f9839 --- /dev/null +++ b/include/llvm/Support/Mangler.h @@ -0,0 +1,118 @@ +//===-- llvm/Support/Mangler.h - Self-contained name mangler ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Unified name mangler for various backends. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MANGLER_H +#define LLVM_SUPPORT_MANGLER_H + +#include "llvm/System/IncludeFile.h" +#include <map> +#include <set> +#include <string> + +namespace llvm { +class Type; +class Module; +class Value; +class GlobalValue; + +class Mangler { + /// Prefix - This string is added to each symbol that is emitted, unless the + /// symbol is marked as not needing this prefix. + const char *Prefix; + + /// UseQuotes - If this is set, the target accepts global names in quotes, + /// e.g. "foo bar" is a legal name. This syntax is used instead of escaping + /// the space character. By default, this is false. + bool UseQuotes; + + /// PreserveAsmNames - If this is set, the asm escape character is not removed + /// from names with 'asm' specifiers. + bool PreserveAsmNames; + + /// Memo - This is used to remember the name that we assign a value. + /// + std::map<const Value*, std::string> Memo; + + /// Count - This simple counter is used to unique value names. + /// + unsigned Count; + + /// TypeMap - If the client wants us to unique types, this keeps track of the + /// current assignments and TypeCounter keeps track of the next id to assign. + std::map<const Type*, unsigned> TypeMap; + unsigned TypeCounter; + + /// This keeps track of which global values have had their names + /// mangled in the current module. + /// + std::set<const GlobalValue*> MangledGlobals; + + /// AcceptableChars - This bitfield contains a one for each character that is + /// allowed to be part of an unmangled name. + unsigned AcceptableChars[256/32]; +public: + + // Mangler ctor - if a prefix is specified, it will be prepended onto all + // symbols. + Mangler(Module &M, const char *Prefix = ""); + + /// setUseQuotes - If UseQuotes is set to true, this target accepts quoted + /// strings for assembler labels. + void setUseQuotes(bool Val) { UseQuotes = Val; } + + /// setPreserveAsmNames - If the mangler should not strip off the asm name + /// identifier (\001), this should be set. + void setPreserveAsmNames(bool Val) { PreserveAsmNames = Val; } + + /// Acceptable Characters - This allows the target to specify which characters + /// are acceptable to the assembler without being mangled. By default we + /// allow letters, numbers, '_', '$', and '.', which is what GAS accepts. + void markCharAcceptable(unsigned char X) { + AcceptableChars[X/32] |= 1 << (X&31); + } + void markCharUnacceptable(unsigned char X) { + AcceptableChars[X/32] &= ~(1 << (X&31)); + } + bool isCharAcceptable(unsigned char X) const { + return (AcceptableChars[X/32] & (1 << (X&31))) != 0; + } + + /// getTypeID - Return a unique ID for the specified LLVM type. + /// + unsigned getTypeID(const Type *Ty); + + /// getValueName - Returns the mangled name of V, an LLVM Value, + /// in the current module. + /// + std::string getValueName(const GlobalValue *V); + std::string getValueName(const Value *V); + + /// makeNameProper - We don't want identifier names with ., space, or + /// - in them, so we mangle these characters into the strings "d_", + /// "s_", and "D_", respectively. This is a very simple mangling that + /// doesn't guarantee unique names for values. getValueName already + /// does this for you, so there's no point calling it on the result + /// from getValueName. + /// + std::string makeNameProper(const std::string &x, const char *Prefix = ""); + +private: + void InsertName(GlobalValue *GV, std::map<std::string, GlobalValue*> &Names); +}; + +} // End llvm namespace + +// Force the Mangler.cpp file to be linked when this header is #included +FORCE_DEFINING_FILE_TO_BE_LINKED(Mangler) + +#endif // LLVM_SUPPORT_MANGLER_H diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h new file mode 100644 index 0000000..88a1103 --- /dev/null +++ b/include/llvm/Support/MathExtras.h @@ -0,0 +1,363 @@ +//===-- llvm/Support/MathExtras.h - Useful math functions -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains some functions that are useful for math stuff. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MATHEXTRAS_H +#define LLVM_SUPPORT_MATHEXTRAS_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +// NOTE: The following support functions use the _32/_64 extensions instead of +// type overloading so that signed and unsigned integers can be used without +// ambiguity. + +/// Hi_32 - This function returns the high 32 bits of a 64 bit value. +inline uint32_t Hi_32(uint64_t Value) { + return static_cast<uint32_t>(Value >> 32); +} + +/// Lo_32 - This function returns the low 32 bits of a 64 bit value. +inline uint32_t Lo_32(uint64_t Value) { + return static_cast<uint32_t>(Value); +} + +/// is?Type - these functions produce optimal testing for integer data types. +inline bool isInt8 (int64_t Value) { + return static_cast<int8_t>(Value) == Value; +} +inline bool isUInt8 (int64_t Value) { + return static_cast<uint8_t>(Value) == Value; +} +inline bool isInt16 (int64_t Value) { + return static_cast<int16_t>(Value) == Value; +} +inline bool isUInt16(int64_t Value) { + return static_cast<uint16_t>(Value) == Value; +} +inline bool isInt32 (int64_t Value) { + return static_cast<int32_t>(Value) == Value; +} +inline bool isUInt32(int64_t Value) { + return static_cast<uint32_t>(Value) == Value; +} + +/// isMask_32 - This function returns true if the argument is a sequence of ones +/// starting at the least significant bit with the remainder zero (32 bit +/// version). Ex. isMask_32(0x0000FFFFU) == true. +inline bool isMask_32(uint32_t Value) { + return Value && ((Value + 1) & Value) == 0; +} + +/// isMask_64 - This function returns true if the argument is a sequence of ones +/// starting at the least significant bit with the remainder zero (64 bit +/// version). +inline bool isMask_64(uint64_t Value) { + return Value && ((Value + 1) & Value) == 0; +} + +/// isShiftedMask_32 - This function returns true if the argument contains a +/// sequence of ones with the remainder zero (32 bit version.) +/// Ex. isShiftedMask_32(0x0000FF00U) == true. +inline bool isShiftedMask_32(uint32_t Value) { + return isMask_32((Value - 1) | Value); +} + +/// isShiftedMask_64 - This function returns true if the argument contains a +/// sequence of ones with the remainder zero (64 bit version.) +inline bool isShiftedMask_64(uint64_t Value) { + return isMask_64((Value - 1) | Value); +} + +/// isPowerOf2_32 - This function returns true if the argument is a power of +/// two > 0. Ex. isPowerOf2_32(0x00100000U) == true (32 bit edition.) +inline bool isPowerOf2_32(uint32_t Value) { + return Value && !(Value & (Value - 1)); +} + +/// isPowerOf2_64 - This function returns true if the argument is a power of two +/// > 0 (64 bit edition.) +inline bool isPowerOf2_64(uint64_t Value) { + return Value && !(Value & (Value - int64_t(1L))); +} + +/// ByteSwap_16 - This function returns a byte-swapped representation of the +/// 16-bit argument, Value. +inline uint16_t ByteSwap_16(uint16_t Value) { +#if defined(_MSC_VER) && !defined(_DEBUG) + // The DLL version of the runtime lacks these functions (bug!?), but in a + // release build they're replaced with BSWAP instructions anyway. + return _byteswap_ushort(Value); +#else + uint16_t Hi = Value << 8; + uint16_t Lo = Value >> 8; + return Hi | Lo; +#endif +} + +/// ByteSwap_32 - This function returns a byte-swapped representation of the +/// 32-bit argument, Value. +inline uint32_t ByteSwap_32(uint32_t Value) { +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) + return __builtin_bswap32(Value); +#elif defined(_MSC_VER) && !defined(_DEBUG) + return _byteswap_ulong(Value); +#else + uint32_t Byte0 = Value & 0x000000FF; + uint32_t Byte1 = Value & 0x0000FF00; + uint32_t Byte2 = Value & 0x00FF0000; + uint32_t Byte3 = Value & 0xFF000000; + return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24); +#endif +} + +/// ByteSwap_64 - This function returns a byte-swapped representation of the +/// 64-bit argument, Value. +inline uint64_t ByteSwap_64(uint64_t Value) { +#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3) + return __builtin_bswap64(Value); +#elif defined(_MSC_VER) && !defined(_DEBUG) + return _byteswap_uint64(Value); +#else + uint64_t Hi = ByteSwap_32(uint32_t(Value)); + uint32_t Lo = ByteSwap_32(uint32_t(Value >> 32)); + return (Hi << 32) | Lo; +#endif +} + +/// CountLeadingZeros_32 - this function performs the platform optimal form of +/// counting the number of zeros from the most significant bit to the first one +/// bit. Ex. CountLeadingZeros_32(0x00F000FF) == 8. +/// Returns 32 if the word is zero. +inline unsigned CountLeadingZeros_32(uint32_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clz(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (!Value) return 32; +#endif + Count = __builtin_clz(Value); +#else + if (!Value) return 32; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 32 >> 1; Shift; Shift >>= 1) { + uint32_t Tmp = Value >> Shift; + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } +#endif + return Count; +} + +/// CountLeadingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the most significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +inline unsigned CountLeadingZeros_64(uint64_t Value) { + unsigned Count; // result +#if __GNUC__ >= 4 + // PowerPC is defined for __builtin_clzll(0) +#if !defined(__ppc__) && !defined(__ppc64__) + if (!Value) return 64; +#endif + Count = __builtin_clzll(Value); +#else + if (sizeof(long) == sizeof(int64_t)) { + if (!Value) return 64; + Count = 0; + // bisecton method for count leading zeros + for (unsigned Shift = 64 >> 1; Shift; Shift >>= 1) { + uint64_t Tmp = Value >> Shift; + if (Tmp) { + Value = Tmp; + } else { + Count |= Shift; + } + } + } else { + // get hi portion + uint32_t Hi = Hi_32(Value); + + // if some bits in hi portion + if (Hi) { + // leading zeros in hi portion plus all bits in lo portion + Count = CountLeadingZeros_32(Hi); + } else { + // get lo portion + uint32_t Lo = Lo_32(Value); + // same as 32 bit value + Count = CountLeadingZeros_32(Lo)+32; + } + } +#endif + return Count; +} + +/// CountTrailingZeros_32 - this function performs the platform optimal form of +/// counting the number of zeros from the least significant bit to the first one +/// bit. Ex. CountTrailingZeros_32(0xFF00FF00) == 8. +/// Returns 32 if the word is zero. +inline unsigned CountTrailingZeros_32(uint32_t Value) { +#if __GNUC__ >= 4 + return Value ? __builtin_ctz(Value) : 32; +#else + static const unsigned Mod37BitPosition[] = { + 32, 0, 1, 26, 2, 23, 27, 0, 3, 16, 24, 30, 28, 11, 0, 13, + 4, 7, 17, 0, 25, 22, 31, 15, 29, 10, 12, 6, 0, 21, 14, 9, + 5, 20, 8, 19, 18 + }; + return Mod37BitPosition[(-Value & Value) % 37]; +#endif +} + +/// CountTrailingZeros_64 - This function performs the platform optimal form +/// of counting the number of zeros from the least significant bit to the first +/// one bit (64 bit edition.) +/// Returns 64 if the word is zero. +inline unsigned CountTrailingZeros_64(uint64_t Value) { +#if __GNUC__ >= 4 + return Value ? __builtin_ctzll(Value) : 64; +#else + static const unsigned Mod67Position[] = { + 64, 0, 1, 39, 2, 15, 40, 23, 3, 12, 16, 59, 41, 19, 24, 54, + 4, 64, 13, 10, 17, 62, 60, 28, 42, 30, 20, 51, 25, 44, 55, + 47, 5, 32, 65, 38, 14, 22, 11, 58, 18, 53, 63, 9, 61, 27, + 29, 50, 43, 46, 31, 37, 21, 57, 52, 8, 26, 49, 45, 36, 56, + 7, 48, 35, 6, 34, 33, 0 + }; + return Mod67Position[(-Value & Value) % 67]; +#endif +} + +/// CountPopulation_32 - this function counts the number of set bits in a value. +/// Ex. CountPopulation(0xF000F000) = 8 +/// Returns 0 if the word is zero. +inline unsigned CountPopulation_32(uint32_t Value) { +#if __GNUC__ >= 4 + return __builtin_popcount(Value); +#else + uint32_t v = Value - ((Value >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); + return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; +#endif +} + +/// CountPopulation_64 - this function counts the number of set bits in a value, +/// (64 bit edition.) +inline unsigned CountPopulation_64(uint64_t Value) { +#if __GNUC__ >= 4 + return __builtin_popcountll(Value); +#else + uint64_t v = Value - ((Value >> 1) & 0x5555555555555555ULL); + v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); + v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; + return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); +#endif +} + +/// Log2_32 - This function returns the floor log base 2 of the specified value, +/// -1 if the value is zero. (32 bit edition.) +/// Ex. Log2_32(32) == 5, Log2_32(1) == 0, Log2_32(0) == -1, Log2_32(6) == 2 +inline unsigned Log2_32(uint32_t Value) { + return 31 - CountLeadingZeros_32(Value); +} + +/// Log2_64 - This function returns the floor log base 2 of the specified value, +/// -1 if the value is zero. (64 bit edition.) +inline unsigned Log2_64(uint64_t Value) { + return 63 - CountLeadingZeros_64(Value); +} + +/// Log2_32_Ceil - This function returns the ceil log base 2 of the specified +/// value, 32 if the value is zero. (32 bit edition). +/// Ex. Log2_32_Ceil(32) == 5, Log2_32_Ceil(1) == 0, Log2_32_Ceil(6) == 3 +inline unsigned Log2_32_Ceil(uint32_t Value) { + return 32-CountLeadingZeros_32(Value-1); +} + +/// Log2_64 - This function returns the ceil log base 2 of the specified value, +/// 64 if the value is zero. (64 bit edition.) +inline unsigned Log2_64_Ceil(uint64_t Value) { + return 64-CountLeadingZeros_64(Value-1); +} + +/// GreatestCommonDivisor64 - Return the greatest common divisor of the two +/// values using Euclid's algorithm. +inline uint64_t GreatestCommonDivisor64(uint64_t A, uint64_t B) { + while (B) { + uint64_t T = B; + B = A % B; + A = T; + } + return A; +} + +/// BitsToDouble - This function takes a 64-bit integer and returns the bit +/// equivalent double. +inline double BitsToDouble(uint64_t Bits) { + union { + uint64_t L; + double D; + } T; + T.L = Bits; + return T.D; +} + +/// BitsToFloat - This function takes a 32-bit integer and returns the bit +/// equivalent float. +inline float BitsToFloat(uint32_t Bits) { + union { + uint32_t I; + float F; + } T; + T.I = Bits; + return T.F; +} + +/// DoubleToBits - This function takes a double and returns the bit +/// equivalent 64-bit integer. +inline uint64_t DoubleToBits(double Double) { + union { + uint64_t L; + double D; + } T; + T.D = Double; + return T.L; +} + +/// FloatToBits - This function takes a float and returns the bit +/// equivalent 32-bit integer. +inline uint32_t FloatToBits(float Float) { + union { + uint32_t I; + float F; + } T; + T.F = Float; + return T.I; +} + +/// Platform-independent wrappers for the C99 isnan() function. +int IsNAN(float f); +int IsNAN(double d); + +/// Platform-independent wrappers for the C99 isinf() function. +int IsInf(float f); +int IsInf(double d); + +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h new file mode 100644 index 0000000..d7e0317 --- /dev/null +++ b/include/llvm/Support/MemoryBuffer.h @@ -0,0 +1,106 @@ +//===--- MemoryBuffer.h - Memory Buffer Interface ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Chris Lattner and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the MemoryBuffer interface. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MEMORYBUFFER_H +#define LLVM_SUPPORT_MEMORYBUFFER_H + +#include "llvm/Support/DataTypes.h" +#include <string> + +namespace llvm { + +/// MemoryBuffer - This interface provides simple read-only access to a block +/// of memory, and provides simple methods for reading files and standard input +/// into a memory buffer. In addition to basic access to the characters in the +/// file, this interface guarantees you can read one character past the end of +/// the file, and that this character will read as '\0'. +class MemoryBuffer { + const char *BufferStart; // Start of the buffer. + const char *BufferEnd; // End of the buffer. + + /// MustDeleteBuffer - True if we allocated this buffer. If so, the + /// destructor must know the delete[] it. + bool MustDeleteBuffer; +protected: + MemoryBuffer() : MustDeleteBuffer(false) {} + void init(const char *BufStart, const char *BufEnd); + void initCopyOf(const char *BufStart, const char *BufEnd); +public: + virtual ~MemoryBuffer(); + + const char *getBufferStart() const { return BufferStart; } + const char *getBufferEnd() const { return BufferEnd; } + unsigned getBufferSize() const { return BufferEnd-BufferStart; } + + /// getBufferIdentifier - Return an identifier for this buffer, typically the + /// filename it was read from. + virtual const char *getBufferIdentifier() const { + return "Unknown buffer"; + } + + /// getFile - Open the specified file as a MemoryBuffer, returning a new + /// MemoryBuffer if successful, otherwise returning null. If FileSize is + /// specified, this means that the client knows that the file exists and that + /// it has the specified size. + static MemoryBuffer *getFile(const char *FilenameStart, unsigned FnSize, + std::string *ErrStr = 0, + int64_t FileSize = -1); + + /// getMemBuffer - Open the specified memory range as a MemoryBuffer. Note + /// that EndPtr[0] must be a null byte and be accessible! + static MemoryBuffer *getMemBuffer(const char *StartPtr, const char *EndPtr, + const char *BufferName = ""); + + /// getNewMemBuffer - Allocate a new MemoryBuffer of the specified size that + /// is completely initialized to zeros. Note that the caller should + /// initialize the memory allocated by this method. The memory is owned by + /// the MemoryBuffer object. + static MemoryBuffer *getNewMemBuffer(unsigned Size, + const char *BufferName = ""); + + /// getNewUninitMemBuffer - Allocate a new MemoryBuffer of the specified size + /// that is not initialized. Note that the caller should initialize the + /// memory allocated by this method. The memory is owned by the MemoryBuffer + /// object. + static MemoryBuffer *getNewUninitMemBuffer(unsigned Size, + const char *BufferName = ""); + + /// getSTDIN - Read all of stdin into a file buffer, and return it. This + /// fails if stdin is empty. + static MemoryBuffer *getSTDIN(); + + + /// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin + /// if the Filename is "-". If an error occurs, this returns null and fills + /// in *ErrStr with a reason. + static MemoryBuffer *getFileOrSTDIN(const char *FilenameStart,unsigned FnSize, + std::string *ErrStr = 0, + int64_t FileSize = -1) { + if (FnSize == 1 && FilenameStart[0] == '-') + return getSTDIN(); + return getFile(FilenameStart, FnSize, ErrStr, FileSize); + } + + /// getFileOrSTDIN - Open the specified file as a MemoryBuffer, or open stdin + /// if the Filename is "-". If an error occurs, this returns null and fills + /// in *ErrStr with a reason. + static MemoryBuffer *getFileOrSTDIN(const std::string &FN, + std::string *ErrStr = 0, + int64_t FileSize = -1) { + return getFileOrSTDIN(&FN[0], FN.size(), ErrStr, FileSize); + } +}; + +} // end namespace llvm + +#endif diff --git a/include/llvm/Support/MutexGuard.h b/include/llvm/Support/MutexGuard.h new file mode 100644 index 0000000..21c756d --- /dev/null +++ b/include/llvm/Support/MutexGuard.h @@ -0,0 +1,41 @@ +//===-- Support/MutexGuard.h - Acquire/Release Mutex In Scope ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a guard for a block of code that ensures a Mutex is locked +// upon construction and released upon destruction. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MUTEXGUARD_H +#define LLVM_SUPPORT_MUTEXGUARD_H + +#include <llvm/System/Mutex.h> + +namespace llvm { + /// Instances of this class acquire a given Mutex Lock when constructed and + /// hold that lock until destruction. The intention is to instantiate one of + /// these on the stack at the top of some scope to be assured that C++ + /// destruction of the object will always release the Mutex and thus avoid + /// a host of nasty multi-threading problems in the face of exceptions, etc. + /// @brief Guard a section of code with a Mutex. + class MutexGuard { + sys::Mutex &M; + MutexGuard(const MutexGuard &); // DO NOT IMPLEMENT + void operator=(const MutexGuard &); // DO NOT IMPLEMENT + public: + MutexGuard(sys::Mutex &m) : M(m) { M.acquire(); } + ~MutexGuard() { M.release(); } + /// holds - Returns true if this locker instance holds the specified lock. + /// This is mostly used in assertions to validate that the correct mutex + /// is held. + bool holds(const sys::Mutex& lock) const { return &M == &lock; } + }; +} + +#endif // LLVM_SUPPORT_MUTEXGUARD_H diff --git a/include/llvm/Support/OutputBuffer.h b/include/llvm/Support/OutputBuffer.h new file mode 100644 index 0000000..9c6456a --- /dev/null +++ b/include/llvm/Support/OutputBuffer.h @@ -0,0 +1,152 @@ +//=== OutputBuffer.h - Output Buffer ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Bill Wendling and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Methods to output values to a data buffer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_OUTPUTBUFFER_H +#define LLVM_SUPPORT_OUTPUTBUFFER_H + +#include <string> +#include <vector> + +namespace llvm { + + class OutputBuffer { + /// Output buffer. + std::vector<unsigned char> &Output; + + /// is64Bit/isLittleEndian - This information is inferred from the target + /// machine directly, indicating what header values and flags to set. + bool is64Bit, isLittleEndian; + public: + OutputBuffer(std::vector<unsigned char> &Out, + bool is64bit, bool le) + : Output(Out), is64Bit(is64bit), isLittleEndian(le) {} + + // align - Emit padding into the file until the current output position is + // aligned to the specified power of two boundary. + void align(unsigned Boundary) { + assert(Boundary && (Boundary & (Boundary - 1)) == 0 && + "Must align to 2^k boundary"); + size_t Size = Output.size(); + + if (Size & (Boundary - 1)) { + // Add padding to get alignment to the correct place. + size_t Pad = Boundary - (Size & (Boundary - 1)); + Output.resize(Size + Pad); + } + } + + //===------------------------------------------------------------------===// + // Out Functions - Output the specified value to the data buffer. + + void outbyte(unsigned char X) { + Output.push_back(X); + } + void outhalf(unsigned short X) { + if (isLittleEndian) { + Output.push_back(X & 255); + Output.push_back(X >> 8); + } else { + Output.push_back(X >> 8); + Output.push_back(X & 255); + } + } + void outword(unsigned X) { + if (isLittleEndian) { + Output.push_back((X >> 0) & 255); + Output.push_back((X >> 8) & 255); + Output.push_back((X >> 16) & 255); + Output.push_back((X >> 24) & 255); + } else { + Output.push_back((X >> 24) & 255); + Output.push_back((X >> 16) & 255); + Output.push_back((X >> 8) & 255); + Output.push_back((X >> 0) & 255); + } + } + void outxword(uint64_t X) { + if (isLittleEndian) { + Output.push_back(unsigned(X >> 0) & 255); + Output.push_back(unsigned(X >> 8) & 255); + Output.push_back(unsigned(X >> 16) & 255); + Output.push_back(unsigned(X >> 24) & 255); + Output.push_back(unsigned(X >> 32) & 255); + Output.push_back(unsigned(X >> 40) & 255); + Output.push_back(unsigned(X >> 48) & 255); + Output.push_back(unsigned(X >> 56) & 255); + } else { + Output.push_back(unsigned(X >> 56) & 255); + Output.push_back(unsigned(X >> 48) & 255); + Output.push_back(unsigned(X >> 40) & 255); + Output.push_back(unsigned(X >> 32) & 255); + Output.push_back(unsigned(X >> 24) & 255); + Output.push_back(unsigned(X >> 16) & 255); + Output.push_back(unsigned(X >> 8) & 255); + Output.push_back(unsigned(X >> 0) & 255); + } + } + void outaddr32(unsigned X) { + outword(X); + } + void outaddr64(uint64_t X) { + outxword(X); + } + void outaddr(uint64_t X) { + if (!is64Bit) + outword((unsigned)X); + else + outxword(X); + } + void outstring(const std::string &S, unsigned Length) { + unsigned len_to_copy = S.length() < Length ? S.length() : Length; + unsigned len_to_fill = S.length() < Length ? Length - S.length() : 0; + + for (unsigned i = 0; i < len_to_copy; ++i) + outbyte(S[i]); + + for (unsigned i = 0; i < len_to_fill; ++i) + outbyte(0); + } + + //===------------------------------------------------------------------===// + // Fix Functions - Replace an existing entry at an offset. + + void fixhalf(unsigned short X, unsigned Offset) { + unsigned char *P = &Output[Offset]; + P[0] = (X >> (isLittleEndian ? 0 : 8)) & 255; + P[1] = (X >> (isLittleEndian ? 8 : 0)) & 255; + } + void fixword(unsigned X, unsigned Offset) { + unsigned char *P = &Output[Offset]; + P[0] = (X >> (isLittleEndian ? 0 : 24)) & 255; + P[1] = (X >> (isLittleEndian ? 8 : 16)) & 255; + P[2] = (X >> (isLittleEndian ? 16 : 8)) & 255; + P[3] = (X >> (isLittleEndian ? 24 : 0)) & 255; + } + void fixaddr(uint64_t X, unsigned Offset) { + if (!is64Bit) + fixword((unsigned)X, Offset); + else + assert(0 && "Emission of 64-bit data not implemented yet!"); + } + + unsigned char &operator[](unsigned Index) { + return Output[Index]; + } + const unsigned char &operator[](unsigned Index) const { + return Output[Index]; + } + }; + +} // end llvm namespace + +#endif // LLVM_SUPPORT_OUTPUTBUFFER_H diff --git a/include/llvm/Support/PassNameParser.h b/include/llvm/Support/PassNameParser.h new file mode 100644 index 0000000..e87e16a --- /dev/null +++ b/include/llvm/Support/PassNameParser.h @@ -0,0 +1,94 @@ +//===- llvm/Support/PassNameParser.h ----------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file the PassNameParser and FilteredPassNameParser<> classes, which are +// used to add command line arguments to a utility for all of the passes that +// have been registered into the system. +// +// The PassNameParser class adds ALL passes linked into the system (that are +// creatable) as command line arguments to the tool (when instantiated with the +// appropriate command line option template). The FilteredPassNameParser<> +// template is used for the same purposes as PassNameParser, except that it only +// includes passes that have a PassType that are compatible with the filter +// (which is the template argument). +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PASS_NAME_PARSER_H +#define LLVM_SUPPORT_PASS_NAME_PARSER_H + +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Debug.h" +#include "llvm/Pass.h" +#include <algorithm> + +namespace llvm { + +//===----------------------------------------------------------------------===// +// PassNameParser class - Make use of the pass registration mechanism to +// automatically add a command line argument to opt for each pass. +// +class PassNameParser : public PassRegistrationListener, + public cl::parser<const PassInfo*> { + cl::Option *Opt; +public: + PassNameParser() : Opt(0) {} + + void initialize(cl::Option &O) { + Opt = &O; + cl::parser<const PassInfo*>::initialize(O); + + // Add all of the passes to the map that got initialized before 'this' did. + enumeratePasses(); + } + + // ignorablePassImpl - Can be overriden in subclasses to refine the list of + // which passes we want to include. + // + virtual bool ignorablePassImpl(const PassInfo *P) const { return false; } + + inline bool ignorablePass(const PassInfo *P) const { + // Ignore non-selectable and non-constructible passes! Ignore + // non-optimizations. + return P->getPassArgument() == 0 || *P->getPassArgument() == 0 || + P->getNormalCtor() == 0 || ignorablePassImpl(P); + } + + // Implement the PassRegistrationListener callbacks used to populate our map + // + virtual void passRegistered(const PassInfo *P) { + if (ignorablePass(P) || !Opt) return; + if (findOption(P->getPassArgument()) != getNumOptions()) { + cerr << "Two passes with the same argument (-" + << P->getPassArgument() << ") attempted to be registered!\n"; + abort(); + } + addLiteralOption(P->getPassArgument(), P, P->getPassName()); + } + virtual void passEnumerate(const PassInfo *P) { passRegistered(P); } + + // ValLessThan - Provide a sorting comparator for Values elements... + typedef std::pair<const char*, + std::pair<const PassInfo*, const char*> > ValType; + static bool ValLessThan(const ValType &VT1, const ValType &VT2) { + return std::string(VT1.first) < std::string(VT2.first); + } + + // printOptionInfo - Print out information about this option. Override the + // default implementation to sort the table before we print... + virtual void printOptionInfo(const cl::Option &O, unsigned GlobalWidth) const{ + PassNameParser *PNP = const_cast<PassNameParser*>(this); + std::sort(PNP->Values.begin(), PNP->Values.end(), ValLessThan); + cl::parser<const PassInfo*>::printOptionInfo(O, GlobalWidth); + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/PatternMatch.h b/include/llvm/Support/PatternMatch.h new file mode 100644 index 0000000..6b295d6 --- /dev/null +++ b/include/llvm/Support/PatternMatch.h @@ -0,0 +1,382 @@ +//===-- llvm/Support/PatternMatch.h - Match on the LLVM IR ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a simple and efficient mechanism for performing general +// tree-based pattern matches on the LLVM IR. The power of these routines is +// that it allows you to write concise patterns that are expressive and easy to +// understand. The other major advantage of this is that it allows you to +// trivially capture/bind elements in the pattern to variables. For example, +// you can do something like this: +// +// Value *Exp = ... +// Value *X, *Y; ConstantInt *C1, *C2; // (X & C1) | (Y & C2) +// if (match(Exp, m_Or(m_And(m_Value(X), m_ConstantInt(C1)), +// m_And(m_Value(Y), m_ConstantInt(C2))))) { +// ... Pattern is matched and variables are bound ... +// } +// +// This is primarily useful to things like the instruction combiner, but can +// also be useful for static analysis tools or code generators. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PATTERNMATCH_H +#define LLVM_SUPPORT_PATTERNMATCH_H + +#include "llvm/Constants.h" +#include "llvm/Instructions.h" + +namespace llvm { +namespace PatternMatch { + +template<typename Val, typename Pattern> +bool match(Val *V, const Pattern &P) { + return const_cast<Pattern&>(P).match(V); +} + +template<typename Class> +struct leaf_ty { + template<typename ITy> + bool match(ITy *V) { return isa<Class>(V); } +}; + +inline leaf_ty<Value> m_Value() { return leaf_ty<Value>(); } +inline leaf_ty<ConstantInt> m_ConstantInt() { return leaf_ty<ConstantInt>(); } + +template<typename Class> +struct bind_ty { + Class *&VR; + bind_ty(Class *&V) : VR(V) {} + + template<typename ITy> + bool match(ITy *V) { + if (Class *CV = dyn_cast<Class>(V)) { + VR = CV; + return true; + } + return false; + } +}; + +inline bind_ty<Value> m_Value(Value *&V) { return V; } +inline bind_ty<ConstantInt> m_ConstantInt(ConstantInt *&CI) { return CI; } + +//===----------------------------------------------------------------------===// +// Matchers for specific binary operators. +// + +template<typename LHS_t, typename RHS_t, + unsigned Opcode, typename ConcreteTy = BinaryOperator> +struct BinaryOp_match { + LHS_t L; + RHS_t R; + + BinaryOp_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + + template<typename OpTy> + bool match(OpTy *V) { + if (V->getValueID() == Value::InstructionVal + Opcode) { + ConcreteTy *I = cast<ConcreteTy>(V); + return I->getOpcode() == Opcode && L.match(I->getOperand(0)) && + R.match(I->getOperand(1)); + } + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) + return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) && + R.match(CE->getOperand(1)); + return false; + } +}; + +template<typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::Add> m_Add(const LHS &L, + const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::Add>(L, R); +} + +template<typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::Sub> m_Sub(const LHS &L, + const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::Sub>(L, R); +} + +template<typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::Mul> m_Mul(const LHS &L, + const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::Mul>(L, R); +} + +template<typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::UDiv> m_UDiv(const LHS &L, + const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::UDiv>(L, R); +} + +template<typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::SDiv> m_SDiv(const LHS &L, + const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::SDiv>(L, R); +} + +template<typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::FDiv> m_FDiv(const LHS &L, + const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::FDiv>(L, R); +} + +template<typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::URem> m_URem(const LHS &L, + const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::URem>(L, R); +} + +template<typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::SRem> m_SRem(const LHS &L, + const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::SRem>(L, R); +} + +template<typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::FRem> m_FRem(const LHS &L, + const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::FRem>(L, R); +} + +template<typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::And> m_And(const LHS &L, + const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::And>(L, R); +} + +template<typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::Or> m_Or(const LHS &L, + const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::Or>(L, R); +} + +template<typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::Xor> m_Xor(const LHS &L, + const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::Xor>(L, R); +} + +template<typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::Shl> m_Shl(const LHS &L, + const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::Shl>(L, R); +} + +template<typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::LShr> m_LShr(const LHS &L, + const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::LShr>(L, R); +} + +template<typename LHS, typename RHS> +inline BinaryOp_match<LHS, RHS, Instruction::AShr> m_AShr(const LHS &L, + const RHS &R) { + return BinaryOp_match<LHS, RHS, Instruction::AShr>(L, R); +} + +//===----------------------------------------------------------------------===// +// Matchers for either AShr or LShr .. for convenience +// +template<typename LHS_t, typename RHS_t, typename ConcreteTy = BinaryOperator> +struct Shr_match { + LHS_t L; + RHS_t R; + + Shr_match(const LHS_t &LHS, const RHS_t &RHS) : L(LHS), R(RHS) {} + + template<typename OpTy> + bool match(OpTy *V) { + if (V->getValueID() == Value::InstructionVal + Instruction::LShr || + V->getValueID() == Value::InstructionVal + Instruction::AShr) { + ConcreteTy *I = cast<ConcreteTy>(V); + return (I->getOpcode() == Instruction::AShr || + I->getOpcode() == Instruction::LShr) && + L.match(I->getOperand(0)) && + R.match(I->getOperand(1)); + } + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) + return (CE->getOpcode() == Instruction::LShr || + CE->getOpcode() == Instruction::AShr) && + L.match(CE->getOperand(0)) && + R.match(CE->getOperand(1)); + return false; + } +}; + +template<typename LHS, typename RHS> +inline Shr_match<LHS, RHS> m_Shr(const LHS &L, const RHS &R) { + return Shr_match<LHS, RHS>(L, R); +} + +//===----------------------------------------------------------------------===// +// Matchers for binary classes +// + +template<typename LHS_t, typename RHS_t, typename Class, typename OpcType> +struct BinaryOpClass_match { + OpcType *Opcode; + LHS_t L; + RHS_t R; + + BinaryOpClass_match(OpcType &Op, const LHS_t &LHS, + const RHS_t &RHS) + : Opcode(&Op), L(LHS), R(RHS) {} + BinaryOpClass_match(const LHS_t &LHS, const RHS_t &RHS) + : Opcode(0), L(LHS), R(RHS) {} + + template<typename OpTy> + bool match(OpTy *V) { + if (Class *I = dyn_cast<Class>(V)) + if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) { + if (Opcode) + *Opcode = I->getOpcode(); + return true; + } +#if 0 // Doesn't handle constantexprs yet! + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) + return CE->getOpcode() == Opcode && L.match(CE->getOperand(0)) && + R.match(CE->getOperand(1)); +#endif + return false; + } +}; + +template<typename LHS, typename RHS> +inline BinaryOpClass_match<LHS, RHS, BinaryOperator, Instruction::BinaryOps> +m_Shift(Instruction::BinaryOps &Op, const LHS &L, const RHS &R) { + return BinaryOpClass_match<LHS, RHS, + BinaryOperator, Instruction::BinaryOps>(Op, L, R); +} + +template<typename LHS, typename RHS> +inline BinaryOpClass_match<LHS, RHS, BinaryOperator, Instruction::BinaryOps> +m_Shift(const LHS &L, const RHS &R) { + return BinaryOpClass_match<LHS, RHS, + BinaryOperator, Instruction::BinaryOps>(L, R); +} + +//===----------------------------------------------------------------------===// +// Matchers for CmpInst classes +// + +template<typename LHS_t, typename RHS_t, typename Class, typename PredicateTy> +struct CmpClass_match { + PredicateTy &Predicate; + LHS_t L; + RHS_t R; + + CmpClass_match(PredicateTy &Pred, const LHS_t &LHS, + const RHS_t &RHS) + : Predicate(Pred), L(LHS), R(RHS) {} + + template<typename OpTy> + bool match(OpTy *V) { + if (Class *I = dyn_cast<Class>(V)) + if (L.match(I->getOperand(0)) && R.match(I->getOperand(1))) { + Predicate = I->getPredicate(); + return true; + } + return false; + } +}; + +template<typename LHS, typename RHS> +inline CmpClass_match<LHS, RHS, ICmpInst, ICmpInst::Predicate> +m_ICmp(ICmpInst::Predicate &Pred, const LHS &L, const RHS &R) { + return CmpClass_match<LHS, RHS, + ICmpInst, ICmpInst::Predicate>(Pred, L, R); +} + +template<typename LHS, typename RHS> +inline CmpClass_match<LHS, RHS, FCmpInst, FCmpInst::Predicate> +m_FCmp(FCmpInst::Predicate &Pred, const LHS &L, const RHS &R) { + return CmpClass_match<LHS, RHS, + FCmpInst, FCmpInst::Predicate>(Pred, L, R); +} + +//===----------------------------------------------------------------------===// +// Matchers for unary operators +// + +template<typename LHS_t> +struct not_match { + LHS_t L; + + not_match(const LHS_t &LHS) : L(LHS) {} + + template<typename OpTy> + bool match(OpTy *V) { + if (Instruction *I = dyn_cast<Instruction>(V)) + if (I->getOpcode() == Instruction::Xor) + return matchIfNot(I->getOperand(0), I->getOperand(1)); + if (ConstantExpr *CE = dyn_cast<ConstantExpr>(V)) + if (CE->getOpcode() == Instruction::Xor) + return matchIfNot(CE->getOperand(0), CE->getOperand(1)); + if (ConstantInt *CI = dyn_cast<ConstantInt>(V)) + return L.match(ConstantExpr::getNot(CI)); + return false; + } +private: + bool matchIfNot(Value *LHS, Value *RHS) { + if (ConstantInt *CI = dyn_cast<ConstantInt>(RHS)) + return CI->isAllOnesValue() && L.match(LHS); + if (ConstantInt *CI = dyn_cast<ConstantInt>(LHS)) + return CI->isAllOnesValue() && L.match(RHS); + if (ConstantVector *CV = dyn_cast<ConstantVector>(RHS)) + return CV->isAllOnesValue() && L.match(LHS); + if (ConstantVector *CV = dyn_cast<ConstantVector>(LHS)) + return CV->isAllOnesValue() && L.match(RHS); + return false; + } +}; + +template<typename LHS> +inline not_match<LHS> m_Not(const LHS &L) { return L; } + + +//===----------------------------------------------------------------------===// +// Matchers for control flow +// + +template<typename Cond_t> +struct brc_match { + Cond_t Cond; + BasicBlock *&T, *&F; + brc_match(const Cond_t &C, BasicBlock *&t, BasicBlock *&f) + : Cond(C), T(t), F(f) { + } + + template<typename OpTy> + bool match(OpTy *V) { + if (BranchInst *BI = dyn_cast<BranchInst>(V)) + if (BI->isConditional()) { + if (Cond.match(BI->getCondition())) { + T = BI->getSuccessor(0); + F = BI->getSuccessor(1); + return true; + } + } + return false; + } +}; + +template<typename Cond_t> +inline brc_match<Cond_t> m_Br(const Cond_t &C, BasicBlock *&T, BasicBlock *&F){ + return brc_match<Cond_t>(C, T, F); +} + + +}} // end llvm::match + + +#endif + diff --git a/include/llvm/Support/PluginLoader.h b/include/llvm/Support/PluginLoader.h new file mode 100644 index 0000000..7789ae8 --- /dev/null +++ b/include/llvm/Support/PluginLoader.h @@ -0,0 +1,37 @@ +//===-- llvm/Support/PluginLoader.h - Plugin Loader for Tools ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// A tool can #include this file to get a -load option that allows the user to +// load arbitrary shared objects into the tool's address space. Note that this +// header can only be included by a program ONCE, so it should never to used by +// library authors. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_PLUGINLOADER_H +#define LLVM_SUPPORT_PLUGINLOADER_H + +#include "llvm/Support/CommandLine.h" + +namespace llvm { + struct PluginLoader { + void operator=(const std::string &Filename); + static unsigned getNumPlugins(); + static std::string& getPlugin(unsigned num); + }; + +#ifndef DONT_GET_PLUGIN_LOADER_OPTION + // This causes operator= above to be invoked for every -load option. + static cl::opt<PluginLoader, false, cl::parser<std::string> > + LoadOpt("load", cl::ZeroOrMore, cl::value_desc("pluginfilename"), + cl::desc("Load the specified plugin")); +#endif +} + +#endif diff --git a/include/llvm/Support/SlowOperationInformer.h b/include/llvm/Support/SlowOperationInformer.h new file mode 100644 index 0000000..d057926 --- /dev/null +++ b/include/llvm/Support/SlowOperationInformer.h @@ -0,0 +1,65 @@ +//===- llvm/Support/SlowOperationInformer.h - Keep user informed *- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a simple object which can be used to let the user know what +// is going on when a slow operation is happening, and gives them the ability to +// cancel it. Potentially slow operations can stack allocate one of these +// objects, and periodically call the "progress" method to update the progress +// bar. If the operation takes more than 1 second to complete, the progress bar +// is automatically shown and updated. As such, the slow operation should not +// print stuff to the screen, and should not be confused if an extra line +// appears on the screen (ie, the cursor should be at the start of the line). +// +// If the user presses CTRL-C during the operation, the next invocation of the +// progress method return true indicating that the operation was cancelled. +// +// Because SlowOperationInformers fiddle around with signals, they cannot be +// nested, and interact poorly with threads. The SIGALRM handler is set back to +// SIGDFL, but the SIGINT signal handler is restored when the +// SlowOperationInformer is destroyed. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_SLOW_OPERATION_INFORMER_H +#define LLVM_SUPPORT_SLOW_OPERATION_INFORMER_H + +#include <string> +#include <cassert> +#include "llvm/Support/DataTypes.h" + +namespace llvm { + class SlowOperationInformer { + std::string OperationName; + unsigned LastPrintAmount; + + SlowOperationInformer(const SlowOperationInformer&); // DO NOT IMPLEMENT + void operator=(const SlowOperationInformer&); // DO NOT IMPLEMENT + public: + SlowOperationInformer(const std::string &Name); + ~SlowOperationInformer(); + + /// progress - Clients should periodically call this method when they can + /// handle cancellation. The Amount variable should indicate how far + /// along the operation is, given in 1/10ths of a percent (in other words, + /// Amount should range from 0 to 1000). If the user cancels the operation, + /// this returns true, false otherwise. + bool progress(unsigned Amount); + + /// progress - Same as the method above, but this performs the division for + /// you, and helps you avoid overflow if you are dealing with largish + /// numbers. + bool progress(unsigned Current, unsigned Maximum) { + assert(Maximum != 0 && + "Shouldn't be doing work if there is nothing to do!"); + return progress(Current*uint64_t(1000UL)/Maximum); + } + }; +} // end namespace llvm + +#endif /* SLOW_OPERATION_INFORMER_H */ diff --git a/include/llvm/Support/StableBasicBlockNumbering.h b/include/llvm/Support/StableBasicBlockNumbering.h new file mode 100644 index 0000000..3ba72ea --- /dev/null +++ b/include/llvm/Support/StableBasicBlockNumbering.h @@ -0,0 +1,59 @@ +//===- StableBasicBlockNumbering.h - Provide BB identifiers -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class provides a *stable* numbering of basic blocks that does not depend +// on their address in memory (which is nondeterministic). When requested, this +// class simply provides a unique ID for each basic block in the function +// specified and the inverse mapping. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_STABLEBASICBLOCKNUMBERING_H +#define LLVM_SUPPORT_STABLEBASICBLOCKNUMBERING_H + +#include "llvm/Function.h" +#include "llvm/ADT/UniqueVector.h" + +namespace llvm { + class StableBasicBlockNumbering { + // BBNumbering - Holds the numbering. + UniqueVector<BasicBlock*> BBNumbering; + public: + StableBasicBlockNumbering(Function *F = 0) { + if (F) compute(*F); + } + + /// compute - If we have not computed a numbering for the function yet, do + /// so. + void compute(Function &F) { + if (BBNumbering.empty()) { + for (Function::iterator I = F.begin(), E = F.end(); I != E; ++I) + BBNumbering.insert(I); + } + } + + /// getNumber - Return the ID number for the specified BasicBlock. + /// + unsigned getNumber(BasicBlock *BB) const { + unsigned Idx = BBNumbering.idFor(BB); + assert(Idx && "Invalid basic block or numbering not computed!"); + return Idx-1; + } + + /// getBlock - Return the BasicBlock corresponding to a particular ID. + /// + BasicBlock *getBlock(unsigned N) const { + assert(N < BBNumbering.size() && + "Block ID out of range or numbering not computed!"); + return BBNumbering[N+1]; + } + }; +} + +#endif diff --git a/include/llvm/Support/Streams.h b/include/llvm/Support/Streams.h new file mode 100644 index 0000000..4e1e4f3 --- /dev/null +++ b/include/llvm/Support/Streams.h @@ -0,0 +1,72 @@ +//===- llvm/Support/Streams.h - Wrappers for iostreams ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Bill Wendling and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a wrapper for the STL I/O streams. It prevents the need +// to include <iostream> in a file just to get I/O. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_STREAMS_H +#define LLVM_SUPPORT_STREAMS_H + +#include <iosfwd> + +namespace llvm { + + /// BaseStream - Acts like the STL streams. It's a wrapper for the std::cerr, + /// std::cout, std::cin, etc. streams. However, it doesn't require #including + /// <iostream> in every file (doing so increases static c'tors & d'tors in the + /// object code). + /// + template <typename StreamTy> + class BaseStream { + StreamTy *Stream; + public: + BaseStream() : Stream(0) {} + BaseStream(StreamTy &S) : Stream(&S) {} + BaseStream(StreamTy *S) : Stream(S) {} + + StreamTy *stream() const { return Stream; } + + inline BaseStream &operator << (StreamTy &(*Func)(StreamTy&)) { + if (Stream) *Stream << Func; + return *this; + } + + template <typename Ty> + BaseStream &operator << (const Ty &Thing) { + if (Stream) *Stream << Thing; + return *this; + } + + template <typename Ty> + BaseStream &operator >> (const Ty &Thing) { + if (Stream) *Stream >> Thing; + return *this; + } + + operator StreamTy* () { return Stream; } + + bool operator == (const StreamTy &S) { return &S == Stream; } + bool operator != (const StreamTy &S) { return !(*this == S); } + bool operator == (const BaseStream &S) { return S.Stream == Stream; } + bool operator != (const BaseStream &S) { return !(*this == S); } + }; + + typedef BaseStream<std::ostream> OStream; + typedef BaseStream<std::istream> IStream; + typedef BaseStream<std::stringstream> StringStream; + + extern OStream cout; + extern OStream cerr; + extern IStream cin; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/SystemUtils.h b/include/llvm/Support/SystemUtils.h new file mode 100644 index 0000000..6dc5c27 --- /dev/null +++ b/include/llvm/Support/SystemUtils.h @@ -0,0 +1,42 @@ +//===- SystemUtils.h - Utilities to do low-level system stuff ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains functions used to do a variety of low-level, often +// system-specific, tasks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_SYSTEMUTILS_H +#define LLVM_SUPPORT_SYSTEMUTILS_H + +#include "llvm/System/Program.h" + +namespace llvm { + +/// Determine if the ostream provided is connected to the std::cout and +/// displayed or not (to a console window). If so, generate a warning message +/// advising against display of bitcode and return true. Otherwise just return +/// false +/// @brief Check for output written to a console +bool CheckBitcodeOutputToConsole( + std::ostream* stream_to_check, ///< The stream to be checked + bool print_warning = true ///< Control whether warnings are printed +); + +/// FindExecutable - Find a named executable, giving the argv[0] of program +/// being executed. This allows us to find another LLVM tool if it is built into +/// the same directory, but that directory is neither the current directory, nor +/// in the PATH. If the executable cannot be found, return an empty string. +/// @brief Find a named executable. +sys::Path FindExecutable(const std::string &ExeName, + const std::string &ProgramPath); + +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/Timer.h b/include/llvm/Support/Timer.h new file mode 100644 index 0000000..5a97f49 --- /dev/null +++ b/include/llvm/Support/Timer.h @@ -0,0 +1,165 @@ +//===-- llvm/Support/Timer.h - Interval Timing Support ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines three classes: Timer, TimeRegion, and TimerGroup, +// documented below. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TIMER_H +#define LLVM_SUPPORT_TIMER_H + +#include "llvm/Support/DataTypes.h" +#include <string> +#include <vector> +#include <iosfwd> +#include <cassert> + +namespace llvm { + +class TimerGroup; + +/// Timer - This class is used to track the amount of time spent between +/// invocations of it's startTimer()/stopTimer() methods. Given appropriate OS +/// support it can also keep track of the RSS of the program at various points. +/// By default, the Timer will print the amount of time it has captured to +/// standard error when the laster timer is destroyed, otherwise it is printed +/// when it's TimerGroup is destroyed. Timer's do not print their information +/// if they are never started. +/// +class Timer { + double Elapsed; // Wall clock time elapsed in seconds + double UserTime; // User time elapsed + double SystemTime; // System time elapsed + ssize_t MemUsed; // Memory allocated (in bytes) + size_t PeakMem; // Peak memory used + size_t PeakMemBase; // Temporary for peak calculation... + std::string Name; // The name of this time variable + bool Started; // Has this time variable ever been started? + TimerGroup *TG; // The TimerGroup this Timer is in. +public: + Timer(const std::string &N); + Timer(const std::string &N, TimerGroup &tg); + Timer(const Timer &T); + ~Timer(); + + double getProcessTime() const { return UserTime+SystemTime; } + double getWallTime() const { return Elapsed; } + ssize_t getMemUsed() const { return MemUsed; } + size_t getPeakMem() const { return PeakMem; } + std::string getName() const { return Name; } + + const Timer &operator=(const Timer &T) { + Elapsed = T.Elapsed; + UserTime = T.UserTime; + SystemTime = T.SystemTime; + MemUsed = T.MemUsed; + PeakMem = T.PeakMem; + PeakMemBase = T.PeakMemBase; + Name = T.Name; + Started = T.Started; + assert(TG == T.TG && "Can only assign timers in the same TimerGroup!"); + return *this; + } + + // operator< - Allow sorting... + bool operator<(const Timer &T) const { + // Sort by Wall Time elapsed, as it is the only thing really accurate + return Elapsed < T.Elapsed; + } + bool operator>(const Timer &T) const { return T.operator<(*this); } + + /// startTimer - Start the timer running. Time between calls to + /// startTimer/stopTimer is counted by the Timer class. Note that these calls + /// must be correctly paired. + /// + void startTimer(); + + /// stopTimer - Stop the timer. + /// + void stopTimer(); + + /// addPeakMemoryMeasurement - This method should be called whenever memory + /// usage needs to be checked. It adds a peak memory measurement to the + /// currently active timers, which will be printed when the timer group prints + /// + static void addPeakMemoryMeasurement(); + + /// print - Print the current timer to standard error, and reset the "Started" + /// flag. + void print(const Timer &Total, std::ostream &OS); + +private: + friend class TimerGroup; + + // Copy ctor, initialize with no TG member. + Timer(bool, const Timer &T); + + /// sum - Add the time accumulated in the specified timer into this timer. + /// + void sum(const Timer &T); +}; + + +/// The TimeRegion class is used as a helper class to call the startTimer() and +/// stopTimer() methods of the Timer class. When the object is constructed, it +/// starts the timer specified as it's argument. When it is destroyed, it stops +/// the relevant timer. This makes it easy to time a region of code. +/// +class TimeRegion { + Timer &T; + TimeRegion(const TimeRegion &); // DO NOT IMPLEMENT +public: + TimeRegion(Timer &t) : T(t) { + T.startTimer(); + } + ~TimeRegion() { + T.stopTimer(); + } +}; + + +/// NamedRegionTimer - This class is basically a combination of TimeRegion and +/// Timer. It allows you to declare a new timer, AND specify the region to +/// time, all in one statement. All timers with the same name are merged. This +/// is primarily used for debugging and for hunting performance problems. +/// +struct NamedRegionTimer : public TimeRegion { + NamedRegionTimer(const std::string &Name); +}; + + +/// The TimerGroup class is used to group together related timers into a single +/// report that is printed when the TimerGroup is destroyed. It is illegal to +/// destroy a TimerGroup object before all of the Timers in it are gone. A +/// TimerGroup can be specified for a newly created timer in its constructor. +/// +class TimerGroup { + std::string Name; + unsigned NumTimers; + std::vector<Timer> TimersToPrint; +public: + TimerGroup(const std::string &name) : Name(name), NumTimers(0) {} + ~TimerGroup() { + assert(NumTimers == 0 && + "TimerGroup destroyed before all contained timers!"); + } + +private: + friend class Timer; + void addTimer() { ++NumTimers; } + void removeTimer(); + void addTimerToPrint(const Timer &T) { + TimersToPrint.push_back(Timer(true, T)); + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/TypeInfo.h b/include/llvm/Support/TypeInfo.h new file mode 100644 index 0000000..0dfa583 --- /dev/null +++ b/include/llvm/Support/TypeInfo.h @@ -0,0 +1,76 @@ +//===- llvm/Support/TypeInfo.h - Support for type_info objects -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class makes std::type_info objects behave like first class objects that +// can be put in maps and hashtables. This code is based off of code in the +// Loki C++ library from the Modern C++ Design book. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TYPEINFO_H +#define LLVM_SUPPORT_TYPEINFO_H + +#include <typeinfo> + +namespace llvm { + +struct TypeInfo { + TypeInfo() { // needed for containers + struct Nil {}; // Anonymous class distinct from all others... + Info = &typeid(Nil); + } + + TypeInfo(const std::type_info &ti) : Info(&ti) { // non-explicit + } + + // Access for the wrapped std::type_info + const std::type_info &get() const { + return *Info; + } + + // Compatibility functions + bool before(const TypeInfo &rhs) const { + return Info->before(*rhs.Info) != 0; + } + const char *getClassName() const { + return Info->name(); + } + +private: + const std::type_info *Info; +}; + +// Comparison operators +inline bool operator==(const TypeInfo &lhs, const TypeInfo &rhs) { + return lhs.get() == rhs.get(); +} + +inline bool operator<(const TypeInfo &lhs, const TypeInfo &rhs) { + return lhs.before(rhs); +} + +inline bool operator!=(const TypeInfo &lhs, const TypeInfo &rhs) { + return !(lhs == rhs); +} + +inline bool operator>(const TypeInfo &lhs, const TypeInfo &rhs) { + return rhs < lhs; +} + +inline bool operator<=(const TypeInfo &lhs, const TypeInfo &rhs) { + return !(lhs > rhs); +} + +inline bool operator>=(const TypeInfo &lhs, const TypeInfo &rhs) { + return !(lhs < rhs); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h new file mode 100644 index 0000000..8befb25 --- /dev/null +++ b/include/llvm/Support/type_traits.h @@ -0,0 +1,54 @@ +//===- llvm/Support/type_traits.h - Simplfied type traits -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a template class that determines if a type is a class or +// not. The basic mechanism, based on using the pointer to member function of +// a zero argument to a function was "boosted" from the boost type_traits +// library. See http://www.boost.org/ for all the gory details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TYPE_TRAITS_H +#define LLVM_SUPPORT_TYPE_TRAITS_H + +// This is actually the conforming implementation which works with abstract +// classes. However, enough compilers have trouble with it that most will use +// the one in boost/type_traits/object_traits.hpp. This implementation actually +// works with VC7.0, but other interactions seem to fail when we use it. + +namespace llvm { + +namespace dont_use +{ + // These two functions should never be used. They are helpers to + // the is_class template below. They cannot be located inside + // is_class because doing so causes at least GCC to think that + // the value of the "value" enumerator is not constant. Placing + // them out here (for some strange reason) allows the sizeof + // operator against them to magically be constant. This is + // important to make the is_class<T>::value idiom zero cost. it + // evaluates to a constant 1 or 0 depending on whether the + // parameter T is a class or not (respectively). + template<typename T> char is_class_helper(void(T::*)(void)); + template<typename T> double is_class_helper(...); +} + +template <typename T> +struct is_class +{ + // is_class<> metafunction due to Paul Mensonides (leavings@attbi.com). For + // more details: + // http://groups.google.com/groups?hl=en&selm=000001c1cc83%24e154d5e0%247772e50c%40c161550a&rnum=1 + public: + enum { value = sizeof(char) == sizeof(dont_use::is_class_helper<T>(0)) }; +}; + +} + +#endif diff --git a/include/llvm/SymbolTableListTraits.h b/include/llvm/SymbolTableListTraits.h new file mode 100644 index 0000000..205b409 --- /dev/null +++ b/include/llvm/SymbolTableListTraits.h @@ -0,0 +1,76 @@ +//===-- llvm/SymbolTableListTraits.h - Traits for iplist --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a generic class that is used to implement the automatic +// symbol table manipulation that occurs when you put (for example) a named +// instruction into a basic block. +// +// The way that this is implemented is by using a special traits class with the +// intrusive list that makes up the list of instructions in a basic block. When +// a new element is added to the list of instructions, the traits class is +// notified, allowing the symbol table to be updated. +// +// This generic class implements the traits class. It must be generic so that +// it can work for all uses it, which include lists of instructions, basic +// blocks, arguments, functions, global variables, etc... +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYMBOLTABLELISTTRAITS_H +#define LLVM_SYMBOLTABLELISTTRAITS_H + +namespace llvm { + +template<typename NodeTy> class ilist_iterator; +template<typename NodeTy, typename Traits> class iplist; +template<typename Ty> struct ilist_traits; + +// ValueSubClass - The type of objects that I hold, e.g. Instruction. +// ItemParentType - The type of object that owns the list, e.g. BasicBlock. +// TraitBaseClass - The class this trait should inherit from, it should +// inherit from ilist_traits<ValueSubClass> +// +template<typename ValueSubClass, typename ItemParentClass> +class SymbolTableListTraits { + typedef ilist_traits<ValueSubClass> TraitsClass; +public: + SymbolTableListTraits() {} + + /// getListOwner - Return the object that owns this list. If this is a list + /// of instructions, it returns the BasicBlock that owns them. + ItemParentClass *getListOwner() { + return reinterpret_cast<ItemParentClass*>((char*)this- + TraitsClass::getListOffset()); + } + static ValueSubClass *getPrev(ValueSubClass *V) { return V->getPrev(); } + static ValueSubClass *getNext(ValueSubClass *V) { return V->getNext(); } + static const ValueSubClass *getPrev(const ValueSubClass *V) { + return V->getPrev(); + } + static const ValueSubClass *getNext(const ValueSubClass *V) { + return V->getNext(); + } + + static void setPrev(ValueSubClass *V, ValueSubClass *P) { V->setPrev(P); } + static void setNext(ValueSubClass *V, ValueSubClass *N) { V->setNext(N); } + + void addNodeToList(ValueSubClass *V); + void removeNodeFromList(ValueSubClass *V); + void transferNodesFromList(iplist<ValueSubClass, + ilist_traits<ValueSubClass> > &L2, + ilist_iterator<ValueSubClass> first, + ilist_iterator<ValueSubClass> last); +//private: + template<typename TPtr> + void setSymTabObject(TPtr *, TPtr); +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/System/Alarm.h b/include/llvm/System/Alarm.h new file mode 100644 index 0000000..2b78da6 --- /dev/null +++ b/include/llvm/System/Alarm.h @@ -0,0 +1,49 @@ +//===- llvm/System/Alarm.h - Alarm Generation support ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides an operating system independent interface to alarm(2) +// type functionality. The Alarm class allows a one-shot alarm to be set up +// at some number of seconds in the future. When the alarm triggers, a method +// is called to process the event +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_ALARM_H +#define LLVM_SYSTEM_ALARM_H + +#include "llvm/System/IncludeFile.h" + +namespace llvm { +namespace sys { + + /// This function registers an alarm to trigger some number of \p seconds in + /// the future. When that time arrives, the AlarmStatus function will begin + /// to return 1 instead of 0. The user must poll the status of the alarm by + /// making occasional calls to AlarmStatus. If the user sends an interrupt + /// signal, AlarmStatus will begin returning -1, even if the alarm event + /// occurred. + /// @returns nothing + void SetupAlarm( + unsigned seconds ///< Number of seconds in future when alarm arrives + ); + + /// This function terminates the alarm previously set up + /// @returns nothing + void TerminateAlarm(); + + /// This function acquires the status of the alarm. + /// @returns -1=cancelled, 0=untriggered, 1=triggered + int AlarmStatus(); + +} // End sys namespace +} // End llvm namespace + +FORCE_DEFINING_FILE_TO_BE_LINKED(SystemAlarm) + +#endif diff --git a/include/llvm/System/Disassembler.h b/include/llvm/System/Disassembler.h new file mode 100644 index 0000000..fd08f2d --- /dev/null +++ b/include/llvm/System/Disassembler.h @@ -0,0 +1,35 @@ +//===- llvm/Support/Disassembler.h ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Anton Korobeynikov and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the necessary glue to call external disassembler +// libraries. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_DISASSEMBLER_H +#define LLVM_SYSTEM_DISASSEMBLER_H + +#include "llvm/Support/DataTypes.h" +#include <string> + +namespace llvm { +namespace sys { + +/// This function returns true, if there is possible to use some external +/// disassembler library. False otherwise. +bool hasDisassembler(void); + +/// This function provides some "glue" code to call external disassembler +/// libraries. +std::string disassembleBuffer(uint8_t* start, size_t length, uint64_t pc = 0); + +} +} + +#endif // LLVM_SYSTEM_DISASSEMBLER_H diff --git a/include/llvm/System/DynamicLibrary.h b/include/llvm/System/DynamicLibrary.h new file mode 100644 index 0000000..5499f9d --- /dev/null +++ b/include/llvm/System/DynamicLibrary.h @@ -0,0 +1,125 @@ +//===-- llvm/System/DynamicLibrary.h - Portable Dynamic Library -*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the sys::DynamicLibrary class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_DYNAMIC_LIBRARY_H +#define LLVM_SYSTEM_DYNAMIC_LIBRARY_H + +#include "llvm/System/Path.h" +#include "llvm/System/IncludeFile.h" +#include <string> + +namespace llvm { +namespace sys { + + /// This class provides a portable interface to dynamic libraries which also + /// might be known as shared libraries, shared objects, dynamic shared + /// objects, or dynamic link libraries. Regardless of the terminology or the + /// operating system interface, this class provides a portable interface that + /// allows dynamic libraries to be loaded and and searched for externally + /// defined symbols. This is typically used to provide "plug-in" support. + /// It also allows for symbols to be defined which don't live in any library, + /// but rather the main program itself, useful on Windows where the main + /// executable cannot be searched. + /// @since 1.4 + /// @brief Portable dynamic library abstraction. + class DynamicLibrary { + /// @name Constructors + /// @{ + public: + /// Construct a DynamicLibrary that represents the currently executing + /// program. The program must have been linked with -export-dynamic or + /// -dlopen self for this to work. Any symbols retrieved with the + /// GetAddressOfSymbol function will refer to the program not to any + /// library. + /// @throws std::string indicating why the program couldn't be opened. + /// @brief Open program as dynamic library. + DynamicLibrary(); + + /// After destruction, the symbols of the library will no longer be + /// available to the program. It is important to make sure the lifespan + /// of a DynamicLibrary exceeds the lifetime of the pointers returned + /// by the GetAddressOfSymbol otherwise the program may walk off into + /// uncharted territory. + /// @see GetAddressOfSymbol. + /// @brief Closes the DynamicLibrary + ~DynamicLibrary(); + + /// @} + /// @name Functions + /// @{ + public: + /// This function allows a library to be loaded without instantiating a + /// DynamicLibrary object. Consequently, it is marked as being permanent + /// and will only be unloaded when the program terminates. This returns + /// false on success or returns true and fills in *ErrMsg on failure. + /// @brief Open a dynamic library permanently. + static bool LoadLibraryPermanently(const char* filename, + std::string *ErrMsg = 0); + + /// This function will search through all previously loaded dynamic + /// libraries for the symbol \p symbolName. If it is found, the addressof + /// that symbol is returned. If not, null is returned. Note that this will + /// search permanently loaded libraries (LoadLibraryPermanently) as well + /// as ephemerally loaded libraries (constructors). + /// @throws std::string on error. + /// @brief Search through libraries for address of a symbol + static void* SearchForAddressOfSymbol(const char* symbolName); + + /// @brief Convenience function for C++ophiles. + static void* SearchForAddressOfSymbol(const std::string& symbolName) { + return SearchForAddressOfSymbol(symbolName.c_str()); + } + + /// This functions permanently adds the symbol \p symbolName with the + /// value \p symbolValue. These symbols are searched before any + /// libraries. + /// @brief Add searchable symbol/value pair. + static void AddSymbol(const char* symbolName, void *symbolValue); + + /// @brief Convenience function for C++ophiles. + static void AddSymbol(const std::string& symbolName, void *symbolValue) { + AddSymbol(symbolName.c_str(), symbolValue); + } + + /// @} + /// @name Accessors + /// @{ + public: + /// Looks up a \p symbolName in the DynamicLibrary and returns its address + /// if it exists. If the symbol does not exist, returns (void*)0. + /// @returns the address of the symbol or 0. + /// @brief Get the address of a symbol in the DynamicLibrary. + void* GetAddressOfSymbol(const char* symbolName); + + /// @brief Convenience function for C++ophiles. + void* GetAddressOfSymbol(const std::string& symbolName) { + return GetAddressOfSymbol(symbolName.c_str()); + } + + /// @} + /// @name Implementation + /// @{ + protected: + void* handle; // Opaque handle for information about the library + + DynamicLibrary(const DynamicLibrary&); ///< Do not implement + DynamicLibrary& operator=(const DynamicLibrary&); ///< Do not implement + /// @} + }; + +} // End sys namespace +} // End llvm namespace + +FORCE_DEFINING_FILE_TO_BE_LINKED(SystemDynamicLibrary) + +#endif // LLVM_SYSTEM_DYNAMIC_LIBRARY_H diff --git a/include/llvm/System/IncludeFile.h b/include/llvm/System/IncludeFile.h new file mode 100644 index 0000000..c9f3882 --- /dev/null +++ b/include/llvm/System/IncludeFile.h @@ -0,0 +1,65 @@ +//===- llvm/System/IncludeFile.h - Ensure Linking Of Library ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the FORCE_DEFINING_FILE_TO_BE_LINKED and DEFINE_FILE_FOR +// macros. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_INCLUDEFILE_H +#define LLVM_SYSTEM_INCLUDEFILE_H + +/// This macro is the public interface that IncludeFile.h exports. This gives +/// us the option to implement the "link the definition" capability in any +/// manner that we choose. All header files that depend on a specific .cpp +/// file being linked at run time should use this macro instead of the +/// IncludeFile class directly. +/// +/// For example, foo.h would use:<br/> +/// <tt>FORCE_DEFINING_FILE_TO_BE_LINKED(foo)</tt><br/> +/// +/// And, foo.cp would use:<br/> +/// <tt>DEFINING_FILE_FOR(foo)</tt><br/> +#define FORCE_DEFINING_FILE_TO_BE_LINKED(name) \ + namespace llvm { \ + extern char name ## LinkVar; \ + static IncludeFile name ## LinkObj ( &name ## LinkVar ); \ + } + +/// This macro is the counterpart to FORCE_DEFINING_FILE_TO_BE_LINKED. It should +/// be used in a .cpp file to define the name referenced in a header file that +/// will cause linkage of the .cpp file. It should only be used at extern level. +#define DEFINING_FILE_FOR(name) namespace llvm { char name ## LinkVar; } + +namespace llvm { + +/// This class is used in the implementation of FORCE_DEFINING_FILE_TO_BE_LINKED +/// macro to make sure that the implementation of a header file is included +/// into a tool that uses the header. This is solely +/// to overcome problems linking .a files and not getting the implementation +/// of compilation units we need. This is commonly an issue with the various +/// Passes but also occurs elsewhere in LLVM. We like to use .a files because +/// they link faster and provide the smallest executables. However, sometimes +/// those executables are too small, if the program doesn't reference something +/// that might be needed, especially by a loaded share object. This little class +/// helps to resolve that problem. The basic strategy is to use this class in +/// a header file and pass the address of a variable to the constructor. If the +/// variable is defined in the header file's corresponding .cpp file then all +/// tools/libraries that #include the header file will require the .cpp as well. +/// For example:<br/> +/// <tt>extern int LinkMyCodeStub;</tt><br/> +/// <tt>static IncludeFile LinkMyModule(&LinkMyCodeStub);</tt><br/> +/// @brief Class to ensure linking of corresponding object file. +struct IncludeFile { + IncludeFile(void *); +}; + +} + +#endif diff --git a/include/llvm/System/LICENSE.TXT b/include/llvm/System/LICENSE.TXT new file mode 100644 index 0000000..f569da2 --- /dev/null +++ b/include/llvm/System/LICENSE.TXT @@ -0,0 +1,6 @@ +LLVM System Interface Library +------------------------------------------------------------------------------- +The LLVM System Interface Library is licensed under the Illinois Open Source +License and has the following additional copyright: + +Copyright (C) 2004 eXtensible Systems, Inc. diff --git a/include/llvm/System/MappedFile.h b/include/llvm/System/MappedFile.h new file mode 100644 index 0000000..6276bc3 --- /dev/null +++ b/include/llvm/System/MappedFile.h @@ -0,0 +1,175 @@ +//===- llvm/System/MappedFile.h - MappedFile OS Concept ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::MappedFile class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_MAPPEDFILE_H +#define LLVM_SYSTEM_MAPPEDFILE_H + +#include "llvm/System/Path.h" +#include "llvm/System/IncludeFile.h" + +namespace llvm { +namespace sys { + + /// Forward declare a class used for holding platform specific information + /// that needs to be + struct MappedFileInfo; + + /// This class provides an abstraction for a memory mapped file in the + /// operating system's filesystem. It provides platform independent operations + /// for mapping a file into memory for both read and write access. This class + /// does not provide facilities for finding the file or operating on paths to + /// files. The sys::Path class is used for that. + /// @since 1.4 + /// @brief An abstraction for memory mapped files. + class MappedFile { + /// @name Types + /// @{ + public: + enum MappingOptions { + READ_ACCESS = 0x0001, ///< Map the file for reading + WRITE_ACCESS = 0x0002, ///< Map the file for write access + EXEC_ACCESS = 0x0004, ///< Map the file for execution access + SHARED_MAPPING = 0x0008 ///< Map the file shared with other processes + }; + /// @} + /// @name Constructors + /// @{ + public: + /// Construct a MappedFile to the \p path in the operating system's file + /// system with the mapping \p options provided. + /// @throws std::string if an error occurs + MappedFile() : path_(), options_(READ_ACCESS), base_(0), info_(0) {} + + /// Destruct a MappedFile and release all memory associated with it. + /// @throws std::string if an error occurs + ~MappedFile() { if (info_) terminate(); } + + /// @} + /// @name Accessors + /// @{ + public: + /// This function determines if the file is currently mapped or not. + /// @returns true iff the file is mapped into memory, false otherwise + /// @brief Determine if a MappedFile is currently mapped + /// @throws nothing + bool isMapped() const { return base_ != 0; } + + /// This function returns a void* pointer to the base address of the file + /// mapping. This is the memory address of the first byte in the file. + /// Note that although a non-const pointer is returned, the memory might + /// not actually be writable, depending on the MappingOptions used when + /// the MappedFile was opened. + /// @returns The base pointer to the memory mapped file. + /// @brief Obtain the base pointer to the memory mapped file. + /// @throws nothing + void* base() const { return base_; } + + /// This function returns a char* pointer to the base address of the file + /// mapping. This is the memory address of the first byte in the file. + /// Note that although a non-const pointer is returned, the memory might + /// not actually be writable, depending on the MappingOptions used when + /// the MappedFile was opened. + /// @returns The base pointer to the memory mapped file as a char pointer. + /// @brief Obtain the base pointer to the memory mapped file. + /// @throws nothing + char* charBase() const { return reinterpret_cast<char*>(base_); } + + /// This function returns a reference to the sys::Path object kept by the + /// MappedFile object. This contains the path to the file that is or + /// will be mapped. + /// @returns sys::Path containing the path name. + /// @brief Returns the mapped file's path as a sys::Path + /// @throws nothing + const sys::Path& path() const { return path_; } + + /// This function returns the number of bytes in the file. + /// @throws std::string if an error occurs + size_t size() const; + + /// @} + /// @name Mutators + /// @{ + public: + /// Open a file to be mapped and get its size but don't map it yet. + /// @returns true if an error occurred + bool open( + const sys::Path& p, ///< Path to file to be mapped + int options = READ_ACCESS, ///< Access mode for the mapping + std::string* ErrMsg = 0 ///< Optional error string pointer + ) { + path_ = p; + options_ = options; + return initialize(ErrMsg); + } + + /// The mapped file is removed from memory. If the file was mapped for + /// write access, the memory contents will be automatically synchronized + /// with the file's disk contents. + /// @brief Remove the file mapping from memory. + void unmap(); + + /// The mapped file is put into memory. + /// @returns The base memory address of the mapped file or 0 if an error + /// occurred. + /// @brief Map the file into memory. + void* map( + std::string* ErrMsg = 0///< Optional error string pointer + ); + + /// This method causes the size of the file, and consequently the size + /// of the mapping to be set. This is logically the same as unmap(), + /// adjust size of the file, map(). Consequently, when calling this + /// function, the caller should not rely on previous results of the + /// map(), base(), or baseChar() members as they may point to invalid + /// areas of memory after this call. + /// @throws std::string if an error occurs + /// @brief Set the size of the file and memory mapping. + bool size(size_t new_size, std::string* ErrMsg = 0); + + void close() { if (info_) terminate(); } + + /// @} + /// @name Implementation + /// @{ + private: + /// @brief Initialize platform-specific portion + bool initialize(std::string* ErrMsg); + + /// @brief Terminate platform-specific portion + void terminate(); + + /// @} + /// @name Data + /// @{ + private: + sys::PathWithStatus path_; ///< Path to the file. + int options_; ///< Options used to create the mapping + void* base_; ///< Pointer to the base memory address + mutable MappedFileInfo* info_; ///< Platform specific info for the mapping + + /// @} + /// @name Disabled + /// @{ + private: + ///< Disallow assignment + MappedFile& operator = ( const MappedFile & that ); + ///< Disallow copying + MappedFile(const MappedFile& that); + /// @} + }; +} +} + +FORCE_DEFINING_FILE_TO_BE_LINKED(SystemMappedFile) + +#endif diff --git a/include/llvm/System/Memory.h b/include/llvm/System/Memory.h new file mode 100644 index 0000000..c343177 --- /dev/null +++ b/include/llvm/System/Memory.h @@ -0,0 +1,76 @@ +//===- llvm/System/Memory.h - Memory Support --------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::Memory class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_MEMORY_H +#define LLVM_SYSTEM_MEMORY_H + +#include <string> +#include "llvm/System/IncludeFile.h" + +namespace llvm { +namespace sys { + + /// This class encapsulates the notion of a memory block which has an address + /// and a size. It is used by the Memory class (a friend) as the result of + /// various memory allocation operations. + /// @see Memory + /// @brief Memory block abstraction. + class MemoryBlock { + public: + void *base() const { return Address; } + unsigned size() const { return Size; } + private: + void *Address; ///< Address of first byte of memory area + unsigned Size; ///< Size, in bytes of the memory area + friend class Memory; + }; + + /// This class provides various memory handling functions that manipulate + /// MemoryBlock instances. + /// @since 1.4 + /// @brief An abstraction for memory operations. + class Memory { + /// @name Functions + /// @{ + public: + /// This method allocates a block of Read/Write/Execute memory that is + /// suitable for executing dynamically generated code (e.g. JIT). An + /// attempt to allocate \p NumBytes bytes of virtual memory is made. + /// \p NearBlock may point to an existing allocation in which case + /// an attempt is made to allocate more memory near the existing block. + /// + /// On success, this returns a non-null memory block, otherwise it returns + /// a null memory block and fills in *ErrMsg. + /// + /// @brief Allocate Read/Write/Execute memory. + static MemoryBlock AllocateRWX(unsigned NumBytes, + const MemoryBlock *NearBlock, + std::string *ErrMsg = 0); + + /// This method releases a block of Read/Write/Execute memory that was + /// allocated with the AllocateRWX method. It should not be used to + /// release any memory block allocated any other way. + /// + /// On success, this returns false, otherwise it returns true and fills + /// in *ErrMsg. + /// @throws std::string if an error occurred. + /// @brief Release Read/Write/Execute memory. + static bool ReleaseRWX(MemoryBlock &block, std::string *ErrMsg = 0); + /// @} + }; +} +} + +FORCE_DEFINING_FILE_TO_BE_LINKED(SystemMemory) + +#endif diff --git a/include/llvm/System/Mutex.h b/include/llvm/System/Mutex.h new file mode 100644 index 0000000..27bcea1 --- /dev/null +++ b/include/llvm/System/Mutex.h @@ -0,0 +1,88 @@ +//===- llvm/System/Mutex.h - Mutex Operating System Concept -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::Mutex class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_MUTEX_H +#define LLVM_SYSTEM_MUTEX_H + +#include "llvm/System/IncludeFile.h" + +namespace llvm +{ + namespace sys + { + /// @brief Platform agnostic Mutex class. + class Mutex + { + /// @name Constructors + /// @{ + public: + + /// Initializes the lock but doesn't acquire it. if \p recursive is set + /// to false, the lock will not be recursive which makes it cheaper but + /// also more likely to deadlock (same thread can't acquire more than + /// once). + /// @brief Default Constructor. + Mutex ( bool recursive = true ); + + /// Releases and removes the lock + /// @brief Destructor + ~Mutex ( void ); + + /// @} + /// @name Methods + /// @{ + public: + + /// Attempts to unconditionally acquire the lock. If the lock is held by + /// another thread, this method will wait until it can acquire the lock. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally acquire the lock. + bool acquire(); + + /// Attempts to release the lock. If the lock is held by the current + /// thread, the lock is released allowing other threads to acquire the + /// lock. + /// @returns false if any kind of error occurs, true otherwise. + /// @brief Unconditionally release the lock. + bool release(void); + + /// Attempts to acquire the lock without blocking. If the lock is not + /// available, this function returns false quickly (without blocking). If + /// the lock is available, it is acquired. + /// @returns false if any kind of error occurs or the lock is not + /// available, true otherwise. + /// @brief Try to acquire the lock. + bool tryacquire(); + + //@} + /// @name Platform Dependent Data + /// @{ + private: +#ifdef ENABLE_THREADS + void* data_; ///< We don't know what the data will be +#endif + + /// @} + /// @name Do Not Implement + /// @{ + private: + Mutex(const Mutex & original); + void operator=(const Mutex &); + /// @} + }; + } +} + +FORCE_DEFINING_FILE_TO_BE_LINKED(SystemMutex) + +#endif diff --git a/include/llvm/System/Path.h b/include/llvm/System/Path.h new file mode 100644 index 0000000..e7aa45b --- /dev/null +++ b/include/llvm/System/Path.h @@ -0,0 +1,656 @@ +//===- llvm/System/Path.h - Path Operating System Concept -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and 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_SYSTEM_PATH_H +#define LLVM_SYSTEM_PATH_H + +#include "llvm/System/TimeValue.h" +#include "llvm/System/IncludeFile.h" +#include <set> +#include <string> +#include <vector> +#include <iosfwd> + +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 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 the root directory of the file system. The root + /// directory is a top level directory above which there are no more + /// directories. For example, on UNIX, the root directory is /. On Windows + /// it is C:\. Other operating systems may have different notions of + /// what the root directory is or none at all. In that case, a consistent + /// default root directory will be used. + static Path GetRootDirectory(); + + /// 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 Constrct a path to an new, unique, existing temporary + /// directory. + static Path GetTemporaryDirectory(std::string* ErrMsg = 0); + + /// Construct a vector of sys::Path that contains the "standard" system + /// library paths suitable for linking into programs. This function *must* + /// return the value of LLVM_LIB_SEARCH_PATH as the first item in \p Paths + /// if that environment variable is set and it references a directory. + /// @brief Construct a path to the system library directory + static void GetSystemLibraryPaths(std::vector<sys::Path>& Paths); + + /// Construct a vector of sys::Path that contains the "standard" bitcode + /// library paths suitable for linking into an llvm program. This function + /// *must* return the value of LLVM_LIB_SEARCH_PATH as well as the value + /// of LLVM_LIBDIR. It also must provide the System library paths as + /// returned by GetSystemLibraryPaths. + /// @see GetSystemLibraryPaths + /// @brief Construct a list of directories in which bitcode could be + /// found. + static void GetBitcodeLibraryPaths(std::vector<sys::Path>& Paths); + + /// Find the path to a library using its short name. Use the system + /// dependent library paths to locate the library. + /// @brief Find a library. + static Path FindLibrary(std::string& short_name); + + /// Construct a path to the default LLVM configuration directory. The + /// implementation must ensure that this is a well-known (same on many + /// systems) directory in which llvm configuration files exist. For + /// example, on Unix, the /etc/llvm directory has been selected. + /// @brief Construct a path to the default LLVM configuration directory + static Path GetLLVMDefaultConfigDir(); + + /// Construct a path to the LLVM installed configuration directory. The + /// implementation must ensure that this refers to the "etc" directory of + /// the LLVM installation. This is the location where configuration files + /// will be located for a particular installation of LLVM on a machine. + /// @brief Construct a path to the LLVM installed configuration directory + static Path GetLLVMConfigDir(); + + /// Construct a path to the current user's home directory. The + /// implementation must use an operating system specific mechanism for + /// determining the user's home directory. For example, the environment + /// variable "HOME" could be used on Unix. If a given operating system + /// does not have the concept of a user's home directory, this static + /// constructor must provide the same result as GetRootDirectory. + /// @brief Construct a path to the current user's "home" directory + static Path GetUserHomeDirectory(); + + /// Return the suffix commonly used on file names that contain a shared + /// object, shared archive, or dynamic link library. Such files are + /// linked at runtime into a process and their code images are shared + /// between processes. + /// @returns The dynamic link library suffix for the current platform. + /// @brief Return the dynamic link library suffix. + static std::string GetDLLSuffix(); + + /// 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 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(const std::string& p) : path(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 p The path to assign. + /// @brief Construct a Path from a string. + explicit Path(const char *StrStart, unsigned StrLen) + : path(StrStart, StrStart+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; + } + + /// 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 { + return 0 == path.compare(that.path); + } + + /// 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 0 != path.compare(that.path); + } + + /// 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 { + return 0 > path.compare(that.path); + } + + /// @} + /// @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(); } + + /// This function returns the current contents of the path as a + /// std::string. This allows the underlying path string to be manipulated. + /// @returns std::string containing the path name. + /// @brief Returns the path as a std::string. + const std::string &toString() const { return path; } + + /// This function returns the last component of the path name. The last + /// component is the file or directory name occuring after the last + /// directory separator. If no directory separator is present, the entire + /// path name is returned (i.e. same as toString). + /// @returns std::string containing the last component of the path name. + /// @brief Returns the last component of the path name. + std::string getLast() const; + + /// This function strips off the path and suffix of the file or directory + /// name and returns just the basename. For example /a/foo.bar would cause + /// this function to return "foo". + /// @returns std::string containing the basename of the path + /// @brief Get the base name of the path + std::string getBasename() const; + + /// 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(); } + + /// @} + /// @name Disk Accessors + /// @{ + public: + /// This function determines if the path name in this object references + /// the root (top level directory) of the file system. The details of what + /// is considered the "root" may vary from system to system so this method + /// will do the necessary checking. + /// @returns true iff the path name references the root directory. + /// @brief Determines if the path references the root directory. + bool isRootDirectory() const; + + /// This function determines if the path name is absolute, as opposed to + /// relative. + /// @breif Determine if the path is absolute. + bool isAbsolute() const; + + /// This function opens the file associated with the path name provided by + /// the Path object and reads its magic number. If the magic number at the + /// start of the file matches \p magic, true is returned. In all other + /// cases (file not found, file not accessible, etc.) it returns false. + /// @returns true if the magic number of the file matches \p magic. + /// @brief Determine if file has a specific magic number + bool hasMagicNumber(const std::string& magic) const; + + /// This function retrieves the first \p len bytes of the file associated + /// with \p this. These bytes are returned as the "magic number" in the + /// \p Magic parameter. + /// @returns true if the Path is a file and the magic number is retrieved, + /// false otherwise. + /// @brief Get the file's magic number. + bool getMagicNumber(std::string& Magic, unsigned len) const; + + /// 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 an + /// LLVM Bitcode file by looking at its magic number. + /// @returns true if the file starts with the magic number for LLVM + /// bitcode files. + /// @brief Determine if the path references a bitcode file. + bool isBitcodeFile() 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. + /// @return strue if the file starts with the magid number for a native + /// shared library. + /// @brief Determine if the path reference a dynamic library. + bool isDynamicLibrary() 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. + bool exists() const; + + /// 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 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 std::string + bool set(const std::string& 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( const std::string& component ); + + /// A period and the \p suffix are appended to the end of the pathname. + /// The precondition for this function is that the Path reference a file + /// name (i.e. isFile() returns true). If the Path is not a file, no + /// action is taken and the function returns false. If the path would + /// become invalid for the host operating system, false is returned. + /// @returns false if the suffix could not be added, true if it was. + /// @brief Adds a period and the \p suffix to the end of the pathname. + bool appendSuffix(const std::string& 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 ); + + /// @} + /// @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 attempts to make the file referenced by the Path object + /// available for execution so that the canExecute() method will return + /// true. + /// @brief Make the file readable; + bool makeExecutableOnDisk(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 method attempts to create a file in the file system with the same + /// name as the Path object. The intermediate directories must all exist + /// at the time this method is called. Use createDirectoriesOnDisk to + /// accomplish that. The created file will be empty upon return from this + /// function. + /// @returns true if the file could not be created, false otherwise. + /// @brief Create the file this Path refers to. + bool createFileOnDisk( + 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 + /// 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: + 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 explicity 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 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 PathWithStatus(const std::string& p) + : 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. + /// @param p The path to assign. + /// @brief Construct a Path from a string. + explicit PathWithStatus(const char *StrStart, unsigned StrLen) + : 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) + /// @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 enumeration delineates the kinds of files that LLVM knows about. + enum LLVMFileType { + Unknown_FileType = 0, ///< Unrecognized file + Bitcode_FileType, ///< Bitcode file + Archive_FileType, ///< ar style archive file + ELF_Relocatable_FileType, ///< ELF Relocatable object file + ELF_Executable_FileType, ///< ELF Executable image + ELF_SharedObject_FileType, ///< ELF dynamically linked shared lib + ELF_Core_FileType, ///< ELF core image + Mach_O_Object_FileType, ///< Mach-O Object file + Mach_O_Executable_FileType, ///< Mach-O Executable + Mach_O_FixedVirtualMemorySharedLib_FileType, ///< Mach-O Shared Lib, FVM + Mach_O_Core_FileType, ///< Mach-O Core File + Mach_O_PreloadExectuable_FileType, ///< Mach-O Preloaded Executable + Mach_O_DynamicallyLinkedSharedLib_FileType, ///< Mach-O dynlinked shared lib + Mach_O_DynamicLinker_FileType, ///< The Mach-O dynamic linker + Mach_O_Bundle_FileType, ///< Mach-O Bundle file + Mach_O_DynamicallyLinkedSharedLibStub_FileType, ///< Mach-O Shared lib stub + COFF_FileType ///< COFF object file or lib + }; + + /// This utility function allows any memory block to be examined in order + /// to determine its file type. + LLVMFileType IdentifyFileType(const char*magic, unsigned length); + + /// This function can be used to copy the file specified by Src to the + /// file specified by Dest. If an error occurs, Dest is removed. + /// @returns true if an error occurs, false otherwise + /// @brief Copy one file to another. + bool CopyFile(const Path& Dest, const Path& Src, std::string* ErrMsg); +} + +std::ostream& operator<<(std::ostream& strm, const sys::Path& aPath); +inline std::ostream& operator<<(std::ostream& strm, + const sys::PathWithStatus& aPath) { + strm << static_cast<const sys::Path&>(aPath); + return strm; +} + +} + +FORCE_DEFINING_FILE_TO_BE_LINKED(SystemPath) +#endif diff --git a/include/llvm/System/Process.h b/include/llvm/System/Process.h new file mode 100644 index 0000000..f843af3 --- /dev/null +++ b/include/llvm/System/Process.h @@ -0,0 +1,105 @@ +//===- llvm/System/Process.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::Process class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_PROCESS_H +#define LLVM_SYSTEM_PROCESS_H + +#include "llvm/System/TimeValue.h" +#include "llvm/System/IncludeFile.h" + +namespace llvm { +namespace sys { + + /// This class provides an abstraction for getting information about the + /// currently executing process. + /// @since 1.4 + /// @brief An abstraction for operating system processes. + class Process { + /// @name Accessors + /// @{ + public: + /// This static function will return the operating system's virtual memory + /// page size. + /// @returns The number of bytes in a virtual memory page. + /// @throws nothing + /// @brief Get the virtual memory page size + static unsigned GetPageSize(); + + /// This static function will return the total amount of memory allocated + /// by the process. This only counts the memory allocated via the malloc, + /// calloc and realloc functions and includes any "free" holes in the + /// allocated space. + /// @throws nothing + /// @brief Return process memory usage. + static size_t GetMallocUsage(); + + /// This static function will return the total memory usage of the + /// process. This includes code, data, stack and mapped pages usage. Notei + /// that the value returned here is not necessarily the Running Set Size, + /// it is the total virtual memory usage, regardless of mapped state of + /// that memory. + static size_t GetTotalMemoryUsage(); + + /// This static function will set \p user_time to the amount of CPU time + /// spent in user (non-kernel) mode and \p sys_time to the amount of CPU + /// time spent in system (kernel) mode. If the operating system does not + /// support collection of these metrics, a zero TimeValue will be for both + /// values. + static void GetTimeUsage( + TimeValue& elapsed, + ///< Returns the TimeValue::now() giving current time + TimeValue& user_time, + ///< Returns the current amount of user time for the process + TimeValue& sys_time + ///< Returns the current amount of system time for the process + ); + + /// This static function will return the process' current user id number. + /// Not all operating systems support this feature. Where it is not + /// supported, the function should return 65536 as the value. + static int GetCurrentUserId(); + + /// This static function will return the process' current group id number. + /// Not all operating systems support this feature. Where it is not + /// supported, the function should return 65536 as the value. + static int GetCurrentGroupId(); + + /// This function makes the necessary calls to the operating system to + /// prevent core files or any other kind of large memory dumps that can + /// occur when a program fails. + /// @brief Prevent core file generation. + static void PreventCoreFiles(); + + /// This function determines if the standard input is connected directly + /// to a user's input (keyboard probably), rather than coming from a file + /// or pipe. + static bool StandardInIsUserInput(); + + /// This function determines if the standard output is connected to a + /// "tty" or "console" window. That is, the output would be displayed to + /// the user rather than being put on a pipe or stored in a file. + static bool StandardOutIsDisplayed(); + + /// This function determines if the standard error is connected to a + /// "tty" or "console" window. That is, the output would be displayed to + /// the user rather than being put on a pipe or stored in a file. + static bool StandardErrIsDisplayed(); + + /// @} + }; +} +} + +FORCE_DEFINING_FILE_TO_BE_LINKED(SystemProcess) + +#endif diff --git a/include/llvm/System/Program.h b/include/llvm/System/Program.h new file mode 100644 index 0000000..cef3805 --- /dev/null +++ b/include/llvm/System/Program.h @@ -0,0 +1,95 @@ +//===- llvm/System/Program.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the llvm::sys::Program class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_PROGRAM_H +#define LLVM_SYSTEM_PROGRAM_H + +#include "llvm/System/Path.h" +#include "llvm/System/IncludeFile.h" +#include <vector> + +namespace llvm { +namespace sys { + + /// 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 { + /// @name Methods + /// @{ + 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). + /// @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. + /// @throws nothing + /// @brief Construct a Program by finding it by name. + static Path FindProgramByName(const std::string& name); + + /// This function executes the program using the \p arguments provided and + /// waits for the program to exit. This function will block the current + /// program until the invoked program exits. 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 an integer result code indicating the status of the program. + /// A zero or positive value indicates the result code of the program. A + /// negative value is the signal number on which it terminated. + /// @see FindProgrambyName + /// @brief Executes the program with the given set of \p args. + static int ExecuteAndWait( + 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 + ///< 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 + ///< 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. + 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 + ///< instance in which error messages will be returned. If the string + ///< is non-empty upon return an error occurred while invoking the + ///< program. + ); + // These methods change the specified standard stream (stdin or stdout) to + // binary mode. They return true if an error occurred + static bool ChangeStdinToBinary(); + static bool ChangeStdoutToBinary(); + /// @} + }; +} +} + +FORCE_DEFINING_FILE_TO_BE_LINKED(SystemProgram) + +#endif diff --git a/include/llvm/System/Signals.h b/include/llvm/System/Signals.h new file mode 100644 index 0000000..f4b8b14 --- /dev/null +++ b/include/llvm/System/Signals.h @@ -0,0 +1,55 @@ +//===- llvm/System/Signals.h - Signal Handling support ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines some helpful functions for dealing with the possibility of +// unix signals occuring while your program is running. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_SIGNALS_H +#define LLVM_SYSTEM_SIGNALS_H + +#include "llvm/System/Path.h" +#include "llvm/System/IncludeFile.h" + +namespace llvm { +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); + + /// This function registers a signal handler to ensure that if a fatal signal + /// gets delivered to the process that the named directory and all its + /// contents are removed. + /// @brief Remove a directory if a fatal signal occurs. + bool RemoveDirectoryOnSignal(const Path& path, std::string* ErrMsg = 0); + + /// When an error signal (such as SIBABRT or SIGSEGV) is delivered to the + /// process, print a stack trace and then exit. + /// @brief Print a stack trace if a fatal signal occurs. + void PrintStackTraceOnErrorSignal(); + + /// This function registers a function to be called when the user "interrupts" + /// the program (typically by pressing ctrl-c). When the user interrupts the + /// program, the specified interrupt function is called instead of the program + /// being killed, and the interrupt function automatically disabled. Note + /// that interrupt functions are not allowed to call any non-reentrant + /// functions. An null interrupt function pointer disables the current + /// installed function. Note also that the handler may be executed on a + /// different thread on some platforms. + /// @brief Register a function to be called when ctrl-c is pressed. + void SetInterruptFunction(void (*IF)()); +} // End sys namespace +} // End llvm namespace + +FORCE_DEFINING_FILE_TO_BE_LINKED(SystemSignals) + +#endif diff --git a/include/llvm/System/TimeValue.h b/include/llvm/System/TimeValue.h new file mode 100644 index 0000000..93610b8 --- /dev/null +++ b/include/llvm/System/TimeValue.h @@ -0,0 +1,385 @@ +//===-- TimeValue.h - Declare OS TimeValue Concept --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file declares the operating system TimeValue concept. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/DataTypes.h" +#include "llvm/System/IncludeFile.h" +#include <string> + +#ifndef LLVM_SYSTEM_TIMEVALUE_H +#define LLVM_SYSTEM_TIMEVALUE_H + +namespace llvm { +namespace sys { + /// This class is used where a precise fixed point in time is required. The + /// range of TimeValue spans many hundreds of billions of years both past and + /// present. The precision of TimeValue is to the nanosecond. However, the + /// actual precision of its values will be determined by the resolution of + /// the system clock. The TimeValue class is used in conjunction with several + /// other lib/System interfaces to specify the time at which a call should + /// timeout, etc. + /// @since 1.4 + /// @brief Provides an abstraction for a fixed point in time. + class TimeValue { + + /// @name Constants + /// @{ + public: + + /// A constant TimeValue representing the smallest time + /// value permissable by the class. MinTime is some point + /// in the distant past, about 300 billion years BCE. + /// @brief The smallest possible time value. + static const TimeValue MinTime; + + /// A constant TimeValue representing the largest time + /// value permissable by the class. MaxTime is some point + /// in the distant future, about 300 billion years AD. + /// @brief The largest possible time value. + static const TimeValue MaxTime; + + /// A constant TimeValue representing the base time, + /// or zero time of 00:00:00 (midnight) January 1st, 2000. + /// @brief 00:00:00 Jan 1, 2000 UTC. + static const TimeValue ZeroTime; + + /// A constant TimeValue for the Posix base time which is + /// 00:00:00 (midnight) January 1st, 1970. + /// @brief 00:00:00 Jan 1, 1970 UTC. + static const TimeValue PosixZeroTime; + + /// A constant TimeValue for the Win32 base time which is + /// 00:00:00 (midnight) January 1st, 1601. + /// @brief 00:00:00 Jan 1, 1601 UTC. + static const TimeValue Win32ZeroTime; + + /// @} + /// @name Types + /// @{ + public: + typedef int64_t SecondsType; ///< Type used for representing seconds. + typedef int32_t NanoSecondsType; ///< Type used for representing nanoseconds. + + enum TimeConversions { + NANOSECONDS_PER_SECOND = 1000000000, ///< One Billion + MICROSECONDS_PER_SECOND = 1000000, ///< One Million + MILLISECONDS_PER_SECOND = 1000, ///< One Thousand + NANOSECONDS_PER_MICROSECOND = 1000, ///< One Thousand + NANOSECONDS_PER_MILLISECOND = 1000000,///< One Million + NANOSECONDS_PER_POSIX_TICK = 100, ///< Posix tick is 100 Hz (10ms) + NANOSECONDS_PER_WIN32_TICK = 100 ///< Win32 tick is 100 Hz (10ms) + }; + + /// @} + /// @name Constructors + /// @{ + public: + /// Caller provides the exact value in seconds and nanoseconds. The + /// \p nanos argument defaults to zero for convenience. + /// @brief Explicit constructor + explicit TimeValue (SecondsType seconds, NanoSecondsType nanos = 0) + : seconds_( seconds ), nanos_( nanos ) { this->normalize(); } + + /// Caller provides the exact value as a double in seconds with the + /// fractional part representing nanoseconds. + /// @brief Double Constructor. + explicit TimeValue( double new_time ) + : seconds_( 0 ) , nanos_ ( 0 ) { + SecondsType integer_part = static_cast<SecondsType>( new_time ); + seconds_ = integer_part; + nanos_ = static_cast<NanoSecondsType>( (new_time - + static_cast<double>(integer_part)) * NANOSECONDS_PER_SECOND ); + this->normalize(); + } + + /// This is a static constructor that returns a TimeValue that represents + /// the current time. + /// @brief Creates a TimeValue with the current time (UTC). + static TimeValue now(); + + /// @} + /// @name Operators + /// @{ + public: + /// Add \p that to \p this. + /// @returns this + /// @brief Incrementing assignment operator. + TimeValue& operator += (const TimeValue& that ) { + this->seconds_ += that.seconds_ ; + this->nanos_ += that.nanos_ ; + this->normalize(); + return *this; + } + + /// Subtract \p that from \p this. + /// @returns this + /// @brief Decrementing assignment operator. + TimeValue& operator -= (const TimeValue &that ) { + this->seconds_ -= that.seconds_ ; + this->nanos_ -= that.nanos_ ; + this->normalize(); + return *this; + } + + /// Determine if \p this is less than \p that. + /// @returns True iff *this < that. + /// @brief True if this < that. + int operator < (const TimeValue &that) const { return that > *this; } + + /// Determine if \p this is greather than \p that. + /// @returns True iff *this > that. + /// @brief True if this > that. + int operator > (const TimeValue &that) const { + if ( this->seconds_ > that.seconds_ ) { + return 1; + } else if ( this->seconds_ == that.seconds_ ) { + if ( this->nanos_ > that.nanos_ ) return 1; + } + return 0; + } + + /// Determine if \p this is less than or equal to \p that. + /// @returns True iff *this <= that. + /// @brief True if this <= that. + int operator <= (const TimeValue &that) const { return that >= *this; } + + /// Determine if \p this is greater than or equal to \p that. + /// @returns True iff *this >= that. + /// @brief True if this >= that. + int operator >= (const TimeValue &that) const { + if ( this->seconds_ > that.seconds_ ) { + return 1; + } else if ( this->seconds_ == that.seconds_ ) { + if ( this->nanos_ >= that.nanos_ ) return 1; + } + return 0; + } + + /// Determines if two TimeValue objects represent the same moment in time. + /// @brief True iff *this == that. + /// @brief True if this == that. + int operator == (const TimeValue &that) const { + return (this->seconds_ == that.seconds_) && + (this->nanos_ == that.nanos_); + } + + /// Determines if two TimeValue objects represent times that are not the + /// same. + /// @return True iff *this != that. + /// @brief True if this != that. + int operator != (const TimeValue &that) const { return !(*this == that); } + + /// Adds two TimeValue objects together. + /// @returns The sum of the two operands as a new TimeValue + /// @brief Addition operator. + friend TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2); + + /// Subtracts two TimeValue objects. + /// @returns The difference of the two operands as a new TimeValue + /// @brief Subtraction operator. + friend TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2); + + /// @} + /// @name Accessors + /// @{ + public: + + /// Returns only the seconds component of the TimeValue. The nanoseconds + /// portion is ignored. No rounding is performed. + /// @brief Retrieve the seconds component + SecondsType seconds() const { return seconds_; } + + /// Returns only the nanoseconds component of the TimeValue. The seconds + /// portion is ignored. + /// @brief Retrieve the nanoseconds component. + NanoSecondsType nanoseconds() const { return nanos_; } + + /// Returns only the fractional portion of the TimeValue rounded down to the + /// nearest microsecond (divide by one thousand). + /// @brief Retrieve the fractional part as microseconds; + uint32_t microseconds() const { + return nanos_ / NANOSECONDS_PER_MICROSECOND; + } + + /// Returns only the fractional portion of the TimeValue rounded down to the + /// nearest millisecond (divide by one million). + /// @brief Retrieve the fractional part as milliseconds; + uint32_t milliseconds() const { + return nanos_ / NANOSECONDS_PER_MILLISECOND; + } + + /// Returns the TimeValue as a number of microseconds. Note that the value + /// returned can overflow because the range of a uint64_t is smaller than + /// the range of a TimeValue. Nevertheless, this is useful on some operating + /// systems and is therefore provided. + /// @brief Convert to a number of microseconds (can overflow) + uint64_t usec() const { + return seconds_ * MICROSECONDS_PER_SECOND + + ( nanos_ / NANOSECONDS_PER_MICROSECOND ); + } + + /// Returns the TimeValue as a number of milliseconds. Note that the value + /// returned can overflow because the range of a uint64_t is smaller than + /// the range of a TimeValue. Nevertheless, this is useful on some operating + /// systems and is therefore provided. + /// @brief Convert to a number of milliseconds (can overflow) + uint64_t msec() const { + return seconds_ * MILLISECONDS_PER_SECOND + + ( nanos_ / NANOSECONDS_PER_MILLISECOND ); + } + + /// Converts the TimeValue into the corresponding number of "ticks" for + /// Posix, correcting for the difference in Posix zero time. + /// @brief Convert to unix time (100 nanoseconds since 12:00:00a Jan 1,1970) + uint64_t toPosixTime() const { + uint64_t result = seconds_ - PosixZeroTime.seconds_; + result += nanos_ / NANOSECONDS_PER_POSIX_TICK; + return result; + } + + /// Converts the TimeValue into the corresponding number of seconds + /// since the epoch (00:00:00 Jan 1,1970). + uint64_t toEpochTime() const { + return seconds_ - PosixZeroTime.seconds_; + } + + /// Converts the TiemValue into the correspodning 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) + uint64_t toWin32Time() const { + uint64_t result = seconds_ - Win32ZeroTime.seconds_; + result += nanos_ / NANOSECONDS_PER_WIN32_TICK; + return result; + } + + /// Provides the seconds and nanoseconds as results in its arguments after + /// correction for the Posix zero time. + /// @brief Convert to timespec time (ala POSIX.1b) + void getTimespecTime( uint64_t& seconds, uint32_t& nanos ) const { + seconds = seconds_ - PosixZeroTime.seconds_; + nanos = nanos_; + } + + /// Provides conversion of the TimeValue into a readable time & date. + /// @returns std::string containing the readable time value + /// @brief Convert time to a string. + std::string toString() const; + + /// @} + /// @name Mutators + /// @{ + public: + /// The seconds component of the TimeValue is set to \p sec without + /// modifying the nanoseconds part. This is useful for whole second + /// arithmetic. + /// @brief Set the seconds component. + void seconds (SecondsType sec ) { + this->seconds_ = sec; + this->normalize(); + } + + /// The nanoseconds component of the TimeValue is set to \p nanos without + /// modifying the seconds part. This is useful for basic computations + /// involving just the nanoseconds portion. Note that the TimeValue will be + /// normalized after this call so that the fractional (nanoseconds) portion + /// will have the smallest equivalent value. + /// @brief Set the nanoseconds component using a number of nanoseconds. + void nanoseconds ( NanoSecondsType nanos ) { + this->nanos_ = nanos; + this->normalize(); + } + + /// The seconds component remains unchanged. + /// @brief Set the nanoseconds component using a number of microseconds. + void microseconds ( int32_t micros ) { + this->nanos_ = micros * NANOSECONDS_PER_MICROSECOND; + this->normalize(); + } + + /// The seconds component remains unchanged. + /// @brief Set the nanoseconds component using a number of milliseconds. + void milliseconds ( int32_t millis ) { + this->nanos_ = millis * NANOSECONDS_PER_MILLISECOND; + this->normalize(); + } + + /// @brief Converts from microsecond format to TimeValue format + void usec( int64_t microseconds ) { + this->seconds_ = microseconds / MICROSECONDS_PER_SECOND; + this->nanos_ = NanoSecondsType(microseconds % MICROSECONDS_PER_SECOND) * + NANOSECONDS_PER_MICROSECOND; + this->normalize(); + } + + /// @brief Converts from millisecond format to TimeValue format + void msec( int64_t milliseconds ) { + this->seconds_ = milliseconds / MILLISECONDS_PER_SECOND; + this->nanos_ = NanoSecondsType(milliseconds % MILLISECONDS_PER_SECOND) * + NANOSECONDS_PER_MILLISECOND; + this->normalize(); + } + + /// Converts the \p seconds argument from PosixTime to the corresponding + /// TimeValue and assigns that value to \p this. + /// @brief Convert seconds form PosixTime to TimeValue + void fromEpochTime( SecondsType seconds ) { + seconds_ = seconds + PosixZeroTime.seconds_; + nanos_ = 0; + this->normalize(); + } + + /// Converts the \p win32Time argument from Windows FILETIME to the + /// corresponding TimeValue and assigns that value to \p this. + /// @brief Convert seconds form Windows FILETIME to TimeValue + void fromWin32Time( uint64_t win32Time ) { + this->seconds_ = win32Time / 10000000 + Win32ZeroTime.seconds_; + this->nanos_ = NanoSecondsType(win32Time % 10000000) * 100; + } + + /// @} + /// @name Implementation + /// @{ + private: + /// This causes the values to be represented so that the fractional + /// part is minimized, possibly incrementing the seconds part. + /// @brief Normalize to canonical form. + void normalize(); + + /// @} + /// @name Data + /// @{ + private: + /// Store the values as a <timeval>. + SecondsType seconds_;///< Stores the seconds part of the TimeVal + NanoSecondsType nanos_; ///< Stores the nanoseconds part of the TimeVal + /// @} + + }; + +inline TimeValue operator + (const TimeValue &tv1, const TimeValue &tv2) { + TimeValue sum (tv1.seconds_ + tv2.seconds_, tv1.nanos_ + tv2.nanos_); + sum.normalize (); + return sum; +} + +inline TimeValue operator - (const TimeValue &tv1, const TimeValue &tv2) { + TimeValue difference (tv1.seconds_ - tv2.seconds_, tv1.nanos_ - tv2.nanos_ ); + difference.normalize (); + return difference; +} + +} +} + +FORCE_DEFINING_FILE_TO_BE_LINKED(SystemTimeValue) + +#endif diff --git a/include/llvm/Target/MRegisterInfo.h b/include/llvm/Target/MRegisterInfo.h new file mode 100644 index 0000000..d2b76b8 --- /dev/null +++ b/include/llvm/Target/MRegisterInfo.h @@ -0,0 +1,624 @@ +//===- Target/MRegisterInfo.h - Target Register Information -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes an abstract interface used to get information about a +// target machines register file. This information is used for a variety of +// purposed, especially register allocation. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_MREGISTERINFO_H +#define LLVM_TARGET_MREGISTERINFO_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/ValueTypes.h" +#include <cassert> +#include <functional> + +namespace llvm { + +class BitVector; +class CalleeSavedInfo; +class MachineFunction; +class MachineInstr; +class MachineLocation; +class MachineMove; +class RegScavenger; +class TargetRegisterClass; +class Type; + +/// TargetRegisterDesc - This record contains all of the information known about +/// a particular register. The AliasSet field (if not null) contains a pointer +/// to a Zero terminated array of registers that this register aliases. This is +/// needed for architectures like X86 which have AL alias AX alias EAX. +/// Registers that this does not apply to simply should set this to null. +/// The SubRegs field is a zero terminated array of registers that are +/// sub-registers of the specific register, e.g. AL, AH are sub-registers of AX. +/// The ImmsubRegs field is a subset of SubRegs. It includes only the immediate +/// sub-registers. e.g. EAX has only one immediate sub-register of AX, not AH, +/// AL which are immediate sub-registers of AX. The SuperRegs field is a zero +/// terminated array of registers that are super-registers of the specific +/// register, e.g. RAX, EAX, are super-registers of AX. +/// +struct TargetRegisterDesc { + const char *Name; // Assembly language name for the register + const unsigned *AliasSet; // Register Alias Set, described above + const unsigned *SubRegs; // Sub-register set, described above + const unsigned *ImmSubRegs; // Immediate sub-register set, described above + const unsigned *SuperRegs; // Super-register set, described above +}; + +class TargetRegisterClass { +public: + typedef const unsigned* iterator; + typedef const unsigned* const_iterator; + + typedef const MVT::ValueType* vt_iterator; + typedef const TargetRegisterClass* const * sc_iterator; +private: + unsigned ID; + bool isSubClass; + const vt_iterator VTs; + const sc_iterator SubClasses; + const sc_iterator SuperClasses; + const sc_iterator SubRegClasses; + const unsigned RegSize, Alignment; // Size & Alignment of register in bytes + const iterator RegsBegin, RegsEnd; +public: + TargetRegisterClass(unsigned id, + const MVT::ValueType *vts, + const TargetRegisterClass * const *subcs, + const TargetRegisterClass * const *supcs, + const TargetRegisterClass * const *subregcs, + unsigned RS, unsigned Al, iterator RB, iterator RE) + : ID(id), VTs(vts), SubClasses(subcs), SuperClasses(supcs), + SubRegClasses(subregcs), + RegSize(RS), Alignment(Al), RegsBegin(RB), RegsEnd(RE) {} + virtual ~TargetRegisterClass() {} // Allow subclasses + + /// getID() - Return the register class ID number. + /// + unsigned getID() const { return ID; } + + /// begin/end - Return all of the registers in this class. + /// + iterator begin() const { return RegsBegin; } + iterator end() const { return RegsEnd; } + + /// getNumRegs - Return the number of registers in this class. + /// + unsigned getNumRegs() const { return RegsEnd-RegsBegin; } + + /// getRegister - Return the specified register in the class. + /// + unsigned getRegister(unsigned i) const { + assert(i < getNumRegs() && "Register number out of range!"); + return RegsBegin[i]; + } + + /// contains - Return true if the specified register is included in this + /// register class. + bool contains(unsigned Reg) const { + for (iterator I = begin(), E = end(); I != E; ++I) + if (*I == Reg) return true; + return false; + } + + /// hasType - return true if this TargetRegisterClass has the ValueType vt. + /// + bool hasType(MVT::ValueType vt) const { + for(int i = 0; VTs[i] != MVT::Other; ++i) + if (VTs[i] == vt) + return true; + return false; + } + + /// vt_begin / vt_end - Loop over all of the value types that can be + /// represented by values in this register class. + vt_iterator vt_begin() const { + return VTs; + } + + vt_iterator vt_end() const { + vt_iterator I = VTs; + while (*I != MVT::Other) ++I; + return I; + } + + /// hasSubRegClass - return true if the specified TargetRegisterClass is a + /// sub-register class of this TargetRegisterClass. + bool hasSubRegClass(const TargetRegisterClass *cs) const { + for (int i = 0; SubClasses[i] != NULL; ++i) + if (SubClasses[i] == cs) + return true; + return false; + } + + /// subclasses_begin / subclasses_end - Loop over all of the sub-classes of + /// this register class. + sc_iterator subclasses_begin() const { + return SubClasses; + } + + sc_iterator subclasses_end() const { + sc_iterator I = SubClasses; + while (*I != NULL) ++I; + return I; + } + + /// hasSuperRegClass - return true if the specified TargetRegisterClass is a + /// super-register class of this TargetRegisterClass. + bool hasSuperRegClass(const TargetRegisterClass *cs) const { + for (int i = 0; SuperClasses[i] != NULL; ++i) + if (SuperClasses[i] == cs) + return true; + return false; + } + + /// superclasses_begin / superclasses_end - Loop over all of the super-classes + /// of this register class. + sc_iterator superclasses_begin() const { + return SuperClasses; + } + + sc_iterator superclasses_end() const { + sc_iterator I = SuperClasses; + while (*I != NULL) ++I; + return I; + } + + /// hasSubRegForClass - return true if the specified TargetRegisterClass is a + /// class of a sub-register class for this TargetRegisterClass. + bool hasSubRegForClass(const TargetRegisterClass *cs) const { + for (int i = 0; SubRegClasses[i] != NULL; ++i) + if (SubRegClasses[i] == cs) + return true; + return false; + } + + /// hasClassForSubReg - return true if the specified TargetRegisterClass is a + /// class of a sub-register class for this TargetRegisterClass. + bool hasClassForSubReg(unsigned SubReg) const { + --SubReg; + for (unsigned i = 0; SubRegClasses[i] != NULL; ++i) + if (i == SubReg) + return true; + return false; + } + + /// getClassForSubReg - return theTargetRegisterClass for the sub-register + /// at idx for this TargetRegisterClass. + sc_iterator getClassForSubReg(unsigned SubReg) const { + --SubReg; + for (unsigned i = 0; SubRegClasses[i] != NULL; ++i) + if (i == SubReg) + return &SubRegClasses[i]; + return NULL; + } + + /// subregclasses_begin / subregclasses_end - Loop over all of + /// the subregister classes of this register class. + sc_iterator subregclasses_begin() const { + return SubRegClasses; + } + + sc_iterator subregclasses_end() const { + sc_iterator I = SubRegClasses; + while (*I != NULL) ++I; + return I; + } + + /// allocation_order_begin/end - These methods define a range of registers + /// which specify the registers in this class that are valid to register + /// allocate, and the preferred order to allocate them in. For example, + /// callee saved registers should be at the end of the list, because it is + /// cheaper to allocate caller saved registers. + /// + /// These methods take a MachineFunction argument, which can be used to tune + /// the allocatable registers based on the characteristics of the function. + /// One simple example is that the frame pointer register can be used if + /// frame-pointer-elimination is performed. + /// + /// By default, these methods return all registers in the class. + /// + virtual iterator allocation_order_begin(const MachineFunction &MF) const { + return begin(); + } + virtual iterator allocation_order_end(const MachineFunction &MF) const { + return end(); + } + + + + /// getSize - Return the size of the register in bytes, which is also the size + /// of a stack slot allocated to hold a spilled copy of this register. + unsigned getSize() const { return RegSize; } + + /// getAlignment - Return the minimum required alignment for a register of + /// this class. + unsigned getAlignment() const { return Alignment; } +}; + + +/// MRegisterInfo base class - We assume that the target defines a static array +/// of TargetRegisterDesc objects that represent all of the machine registers +/// that the target has. As such, we simply have to track a pointer to this +/// array so that we can turn register number into a register descriptor. +/// +class MRegisterInfo { +public: + typedef const TargetRegisterClass * const * regclass_iterator; +private: + const TargetRegisterDesc *Desc; // Pointer to the descriptor array + unsigned NumRegs; // Number of entries in the array + + regclass_iterator RegClassBegin, RegClassEnd; // List of regclasses + + int CallFrameSetupOpcode, CallFrameDestroyOpcode; +protected: + MRegisterInfo(const TargetRegisterDesc *D, unsigned NR, + regclass_iterator RegClassBegin, regclass_iterator RegClassEnd, + int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1); + virtual ~MRegisterInfo(); +public: + + enum { // Define some target independent constants + /// NoRegister - This physical register is not a real target register. It + /// is useful as a sentinal. + NoRegister = 0, + + /// FirstVirtualRegister - This is the first register number that is + /// considered to be a 'virtual' register, which is part of the SSA + /// namespace. This must be the same for all targets, which means that each + /// target is limited to 1024 registers. + FirstVirtualRegister = 1024 + }; + + /// isPhysicalRegister - Return true if the specified register number is in + /// the physical register namespace. + static bool isPhysicalRegister(unsigned Reg) { + assert(Reg && "this is not a register!"); + return Reg < FirstVirtualRegister; + } + + /// isVirtualRegister - Return true if the specified register number is in + /// the virtual register namespace. + static bool isVirtualRegister(unsigned Reg) { + assert(Reg && "this is not a register!"); + return Reg >= FirstVirtualRegister; + } + + /// getAllocatableSet - Returns a bitset indexed by register number + /// indicating if a register is allocatable or not. If a register class is + /// specified, returns the subset for the class. + BitVector getAllocatableSet(MachineFunction &MF, + const TargetRegisterClass *RC = NULL) const; + + const TargetRegisterDesc &operator[](unsigned RegNo) const { + assert(RegNo < NumRegs && + "Attempting to access record for invalid register number!"); + return Desc[RegNo]; + } + + /// Provide a get method, equivalent to [], but more useful if we have a + /// pointer to this object. + /// + const TargetRegisterDesc &get(unsigned RegNo) const { + return operator[](RegNo); + } + + /// getAliasSet - Return the set of registers aliased by the specified + /// register, or a null list of there are none. The list returned is zero + /// terminated. + /// + const unsigned *getAliasSet(unsigned RegNo) const { + return get(RegNo).AliasSet; + } + + /// getSubRegisters - Return the set of registers that are sub-registers of + /// the specified register, or a null list of there are none. The list + /// returned is zero terminated. + /// + const unsigned *getSubRegisters(unsigned RegNo) const { + return get(RegNo).SubRegs; + } + + /// getImmediateSubRegisters - Return the set of registers that are immediate + /// sub-registers of the specified register, or a null list of there are none. + /// The list returned is zero terminated. + /// + const unsigned *getImmediateSubRegisters(unsigned RegNo) const { + return get(RegNo).ImmSubRegs; + } + + /// getSuperRegisters - Return the set of registers that are super-registers + /// of the specified register, or a null list of there are none. The list + /// returned is zero terminated. + /// + const unsigned *getSuperRegisters(unsigned RegNo) const { + return get(RegNo).SuperRegs; + } + + /// getName - Return the symbolic target specific name for the specified + /// physical register. + const char *getName(unsigned RegNo) const { + return get(RegNo).Name; + } + + /// getNumRegs - Return the number of registers this target has + /// (useful for sizing arrays holding per register information) + unsigned getNumRegs() const { + return NumRegs; + } + + /// areAliases - Returns true if the two registers alias each other, + /// false otherwise + bool areAliases(unsigned regA, unsigned regB) const { + for (const unsigned *Alias = getAliasSet(regA); *Alias; ++Alias) + if (*Alias == regB) return true; + return false; + } + + /// regsOverlap - Returns true if the two registers are equal or alias + /// each other. The registers may be virtual register. + bool regsOverlap(unsigned regA, unsigned regB) const { + if (regA == regB) + return true; + + if (isVirtualRegister(regA) || isVirtualRegister(regB)) + return false; + return areAliases(regA, regB); + } + + /// isSubRegister - Returns true if regB is a sub-register of regA. + /// + bool isSubRegister(unsigned regA, unsigned regB) const { + for (const unsigned *SR = getSubRegisters(regA); *SR; ++SR) + if (*SR == regB) return true; + return false; + } + + /// isSuperRegister - Returns true if regB is a super-register of regA. + /// + bool isSuperRegister(unsigned regA, unsigned regB) const { + for (const unsigned *SR = getSuperRegisters(regA); *SR; ++SR) + if (*SR == regB) return true; + return false; + } + + /// getCalleeSavedRegs - Return a null-terminated list of all of the + /// callee saved registers on this target. The register should be in the + /// order of desired callee-save stack frame offset. The first register is + /// closed to the incoming stack pointer if stack grows down, and vice versa. + virtual const unsigned* getCalleeSavedRegs(const MachineFunction *MF = 0) + const = 0; + + /// getCalleeSavedRegClasses - Return a null-terminated list of the preferred + /// register classes to spill each callee saved register with. The order and + /// length of this list match the getCalleeSaveRegs() list. + virtual const TargetRegisterClass* const *getCalleeSavedRegClasses( + const MachineFunction *MF) const =0; + + /// getReservedRegs - Returns a bitset indexed by physical register number + /// indicating if a register is a special register that has particular uses and + /// should be considered unavailable at all times, e.g. SP, RA. This is used by + /// register scavenger to determine what registers are free. + virtual BitVector getReservedRegs(const MachineFunction &MF) const = 0; + + /// getSubReg - Returns the physical register number of sub-register "Index" + /// for physical register RegNo. + virtual unsigned getSubReg(unsigned RegNo, unsigned Index) const = 0; + + //===--------------------------------------------------------------------===// + // Register Class Information + // + + /// Register class iterators + /// + regclass_iterator regclass_begin() const { return RegClassBegin; } + regclass_iterator regclass_end() const { return RegClassEnd; } + + unsigned getNumRegClasses() const { + return regclass_end()-regclass_begin(); + } + + /// getRegClass - Returns the register class associated with the enumeration + /// value. See class TargetOperandInfo. + const TargetRegisterClass *getRegClass(unsigned i) const { + assert(i <= getNumRegClasses() && "Register Class ID out of range"); + return i ? RegClassBegin[i - 1] : NULL; + } + + //===--------------------------------------------------------------------===// + // Interfaces used by the register allocator and stack frame + // manipulation passes to move data around between registers, + // immediates and memory. FIXME: Move these to TargetInstrInfo.h. + // + + /// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee saved + /// registers and returns true if it isn't possible / profitable to do so by + /// issuing a series of store instructions via storeRegToStackSlot(). Returns + /// false otherwise. + virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI) const { + return false; + } + + /// restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee + /// saved registers and returns true if it isn't possible / profitable to do + /// so by issuing a series of load instructions via loadRegToStackSlot(). + /// Returns false otherwise. + virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + const std::vector<CalleeSavedInfo> &CSI) const { + return false; + } + + virtual void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned SrcReg, int FrameIndex, + const TargetRegisterClass *RC) const = 0; + + virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, int FrameIndex, + const TargetRegisterClass *RC) const = 0; + + virtual void copyRegToReg(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, unsigned SrcReg, + const TargetRegisterClass *RC) const = 0; + + /// reMaterialize - Re-issue the specified 'original' instruction at the + /// specific location targeting a new destination register. + virtual void reMaterialize(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI, + unsigned DestReg, + const MachineInstr *Orig) const = 0; + + /// foldMemoryOperand - Attempt to fold a load or store of the + /// specified stack slot into the specified machine instruction for + /// the specified operand. If this is possible, a new instruction + /// is returned with the specified operand folded, otherwise NULL is + /// returned. The client is responsible for removing the old + /// instruction and adding the new one in the instruction stream + virtual MachineInstr* foldMemoryOperand(MachineInstr* MI, + unsigned OpNum, + int FrameIndex) const { + return 0; + } + + /// targetHandlesStackFrameRounding - Returns true if the target is responsible + /// for rounding up the stack frame (probably at emitPrologue time). + virtual bool targetHandlesStackFrameRounding() const { + return false; + } + + /// requiresRegisterScavenging - returns true if the target requires (and + /// can make use of) the register scavenger. + virtual bool requiresRegisterScavenging(const MachineFunction &MF) const { + return false; + } + + /// hasFP - Return true if the specified function should have a dedicated frame + /// pointer register. For most targets this is true only if the function has + /// variable sized allocas or if frame pointer elimination is disabled. + virtual bool hasFP(const MachineFunction &MF) const = 0; + + // hasReservedCallFrame - Under normal circumstances, when a frame pointer is + // not required, we reserve argument space for call sites in the function + // immediately on entry to the current function. This eliminates the need for + // add/sub sp brackets around call sites. Returns true if the call frame is + // included as part of the stack frame. + virtual bool hasReservedCallFrame(MachineFunction &MF) const { + return !hasFP(MF); + } + + /// getCallFrameSetup/DestroyOpcode - These methods return the opcode of the + /// frame setup/destroy instructions if they exist (-1 otherwise). Some + /// targets use pseudo instructions in order to abstract away the difference + /// between operating with a frame pointer and operating without, through the + /// use of these two instructions. + /// + int getCallFrameSetupOpcode() const { return CallFrameSetupOpcode; } + int getCallFrameDestroyOpcode() const { return CallFrameDestroyOpcode; } + + + /// eliminateCallFramePseudoInstr - This method is called during prolog/epilog + /// code insertion to eliminate call frame setup and destroy pseudo + /// instructions (but only if the Target is using them). It is responsible + /// for eliminating these instructions, replacing them with concrete + /// instructions. This method need only be implemented if using call frame + /// setup/destroy pseudo instructions. + /// + virtual void + eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const { + assert(getCallFrameSetupOpcode()== -1 && getCallFrameDestroyOpcode()== -1 && + "eliminateCallFramePseudoInstr must be implemented if using" + " call frame setup/destroy pseudo instructions!"); + assert(0 && "Call Frame Pseudo Instructions do not exist on this target!"); + } + + /// processFunctionBeforeCalleeSavedScan - This method is called immediately + /// before PrologEpilogInserter scans the physical registers used to determine + /// what callee saved registers should be spilled. This method is optional. + virtual void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS = NULL) const { + + } + + /// processFunctionBeforeFrameFinalized - This method is called immediately + /// before the specified functions frame layout (MF.getFrameInfo()) is + /// finalized. Once the frame is finalized, MO_FrameIndex operands are + /// replaced with direct constants. This method is optional. + /// + virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF) const { + } + + /// eliminateFrameIndex - This method must be overriden to eliminate abstract + /// frame indices from instructions which may use them. The instruction + /// referenced by the iterator contains an MO_FrameIndex operand which must be + /// eliminated by this method. This method may modify or replace the + /// specified instruction, as long as it keeps the iterator pointing the the + /// finished product. SPAdj is the SP adjustment due to call frame setup + /// instruction. The return value is the number of instructions added to + /// (negative if removed from) the basic block. + /// + virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI, + int SPAdj, RegScavenger *RS=NULL) const = 0; + + /// emitProlog/emitEpilog - These methods insert prolog and epilog code into + /// the function. The return value is the number of instructions + /// added to (negative if removed from) the basic block (entry for prologue). + /// + virtual void emitPrologue(MachineFunction &MF) const = 0; + virtual void emitEpilogue(MachineFunction &MF, + MachineBasicBlock &MBB) const = 0; + + //===--------------------------------------------------------------------===// + /// Debug information queries. + + /// getDwarfRegNum - Map a target register to an equivalent dwarf register + /// number. Returns -1 if there is no equivalent value. + virtual int getDwarfRegNum(unsigned RegNum) const = 0; + + /// getFrameRegister - This method should return the register used as a base + /// for values allocated in the current stack frame. + virtual unsigned getFrameRegister(MachineFunction &MF) const = 0; + + /// getRARegister - This method should return the register where the return + /// address can be found. + virtual unsigned getRARegister() const = 0; + + /// getLocation - This method should return the actual location of a frame + /// variable given the frame index. The location is returned in ML. + /// Subclasses should override this method for special handling of frame + /// variables and call MRegisterInfo::getLocation for the default action. + virtual void getLocation(MachineFunction &MF, unsigned Index, + MachineLocation &ML) const; + + /// getInitialFrameState - Returns a list of machine moves that are assumed + /// on entry to all functions. Note that LabelID is ignored (assumed to be + /// the beginning of the function.) + virtual void getInitialFrameState(std::vector<MachineMove> &Moves) const; +}; + +// This is useful when building IndexedMaps keyed on virtual registers +struct VirtReg2IndexFunctor : std::unary_function<unsigned, unsigned> { + unsigned operator()(unsigned Reg) const { + return Reg - MRegisterInfo::FirstVirtualRegister; + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Target/SubtargetFeature.h b/include/llvm/Target/SubtargetFeature.h new file mode 100644 index 0000000..e809fc0 --- /dev/null +++ b/include/llvm/Target/SubtargetFeature.h @@ -0,0 +1,110 @@ +//===-- llvm/Target/SubtargetFeature.h - CPU characteristics ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by James M. Laskey and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines and manages user or tool specified CPU characteristics. +// The intent is to be able to package specific features that should or should +// not be used on a specific target processor. A tool, such as llc, could, as +// as example, gather chip info from the command line, a long with features +// that should be used on that chip. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_SUBTARGETFEATURE_H +#define LLVM_TARGET_SUBTARGETFEATURE_H + +#include <string> +#include <vector> +#include <iosfwd> +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// +/// SubtargetFeatureKV - Used to provide key value pairs for feature and +/// CPU bit flags. +// +struct SubtargetFeatureKV { + const char *Key; // K-V key string + const char *Desc; // Help descriptor + uint32_t Value; // K-V integer value + uint32_t Implies; // K-V bit mask + + // Compare routine for std binary search + bool operator<(const SubtargetFeatureKV &S) const { + return strcmp(Key, S.Key) < 0; + } +}; + +//===----------------------------------------------------------------------===// +/// +/// SubtargetInfoKV - Used to provide key value pairs for CPU and arbitrary +/// pointers. +// +struct SubtargetInfoKV { + const char *Key; // K-V key string + void *Value; // K-V pointer value + + // Compare routine for std binary search + bool operator<(const SubtargetInfoKV &S) const { + return strcmp(Key, S.Key) < 0; + } +}; + +//===----------------------------------------------------------------------===// +/// +/// SubtargetFeatures - Manages the enabling and disabling of subtarget +/// specific features. Features are encoded as a string of the form +/// "cpu,+attr1,+attr2,-attr3,...,+attrN" +/// A comma separates each feature from the next (all lowercase.) +/// The first feature is always the CPU subtype (eg. pentiumm). If the CPU +/// value is "generic" then the CPU subtype should be generic for the target. +/// Each of the remaining features is prefixed with + or - indicating whether +/// that feature should be enabled or disabled contrary to the cpu +/// specification. +/// + +class SubtargetFeatures { + std::vector<std::string> Features; // Subtarget features as a vector +public: + SubtargetFeatures(const std::string &Initial = std::string()); + + /// Features string accessors. + std::string getString() const; + void setString(const std::string &Initial); + + /// Set the CPU string. Replaces previous setting. Setting to "" clears CPU. + void setCPU(const std::string &String); + + /// Setting CPU string only if no string is set. + void setCPUIfNone(const std::string &String); + + /// Adding Features. + void AddFeature(const std::string &String, bool IsEnabled = true); + + /// Get feature bits. + uint32_t getBits(const SubtargetFeatureKV *CPUTable, + size_t CPUTableSize, + const SubtargetFeatureKV *FeatureTable, + size_t FeatureTableSize); + + /// Get info pointer + void *getInfo(const SubtargetInfoKV *Table, size_t TableSize); + + /// Print feature string. + void print(std::ostream &OS) const; + void print(std::ostream *OS) const { if (OS) print(*OS); } + + // Dump feature info. + void dump() const; +}; + +} // End namespace llvm + +#endif diff --git a/include/llvm/Target/TargetAsmInfo.h b/include/llvm/Target/TargetAsmInfo.h new file mode 100644 index 0000000..4e6d3b9 --- /dev/null +++ b/include/llvm/Target/TargetAsmInfo.h @@ -0,0 +1,615 @@ +//===-- llvm/Target/TargetAsmInfo.h - Asm info ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by James M. Laskey and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains a class to be used as the basis for target specific +// asm writers. This class primarily takes care of global printing constants, +// which are used in very similar ways across all targets. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_ASM_INFO_H +#define LLVM_TARGET_ASM_INFO_H + +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + class TargetMachine; + class CallInst; + + /// TargetAsmInfo - This class is intended to be used as a base class for asm + /// properties and features specific to the target. + class TargetAsmInfo { + protected: + //===------------------------------------------------------------------===// + // Properties to be set by the target writer, used to configure asm printer. + // + + /// TextSection - Section directive for standard text. + /// + const char *TextSection; // Defaults to ".text". + + /// DataSection - Section directive for standard data. + /// + const char *DataSection; // Defaults to ".data". + + /// BSSSection - Section directive for uninitialized data. Null if this + /// target doesn't support a BSS section. + /// + const char *BSSSection; // Default to ".bss". + + /// TLSDataSection - Section directive for Thread Local data. + /// + const char *TLSDataSection;// Defaults to ".section .tdata,"awT",@progbits". + + /// TLSBSSSection - Section directive for Thread Local uninitialized data. + /// Null if this target doesn't support a BSS section. + /// + const char *TLSBSSSection;// Default to ".section .tbss,"awT",@nobits". + /// ZeroFillDirective - Directive for emitting a global to the ZeroFill + /// section on this target. Null if this target doesn't support zerofill. + const char *ZeroFillDirective; // Default is null. + + /// AddressSize - Size of addresses used in file. + /// + unsigned AddressSize; // Defaults to 4. + + /// NeedsSet - True if target asm can't compute addresses on data + /// directives. + bool NeedsSet; // Defaults to false. + + /// MaxInstLength - This is the maximum possible length of an instruction, + /// which is needed to compute the size of an inline asm. + unsigned MaxInstLength; // Defaults to 4. + + /// PCSymbol - The symbol used to represent the current PC. Used in PC + /// relative expressions. + const char *PCSymbol; // Defaults to "$". + + /// SeparatorChar - This character, if specified, is used to separate + /// instructions from each other when on the same line. This is used to + /// measure inline asm instructions. + char SeparatorChar; // Defaults to ';' + + /// CommentString - This indicates the comment character used by the + /// assembler. + const char *CommentString; // Defaults to "#" + + /// GlobalPrefix - If this is set to a non-empty string, it is prepended + /// onto all global symbols. This is often used for "_" or ".". + const char *GlobalPrefix; // Defaults to "" + + /// PrivateGlobalPrefix - This prefix is used for globals like constant + /// pool entries that are completely private to the .o file and should not + /// have names in the .o file. This is often "." or "L". + const char *PrivateGlobalPrefix; // Defaults to "." + + /// JumpTableSpecialLabelPrefix - If not null, a extra (dead) label is + /// emitted before jump tables with the specified prefix. + const char *JumpTableSpecialLabelPrefix; // Default to null. + + /// GlobalVarAddrPrefix/Suffix - If these are nonempty, these strings + /// will enclose any GlobalVariable (that isn't a function) + /// + const char *GlobalVarAddrPrefix; // Defaults to "" + const char *GlobalVarAddrSuffix; // Defaults to "" + + /// FunctionAddrPrefix/Suffix - If these are nonempty, these strings + /// will enclose any GlobalVariable that points to a function. + /// For example, this is used by the IA64 backend to materialize + /// function descriptors, by decorating the ".data8" object with the + /// \literal @fptr( ) \endliteral + /// link-relocation operator. + /// + const char *FunctionAddrPrefix; // Defaults to "" + const char *FunctionAddrSuffix; // Defaults to "" + + /// InlineAsmStart/End - If these are nonempty, they contain a directive to + /// emit before and after an inline assembly statement. + const char *InlineAsmStart; // Defaults to "#APP\n" + const char *InlineAsmEnd; // Defaults to "#NO_APP\n" + + /// AssemblerDialect - Which dialect of an assembler variant to use. + unsigned AssemblerDialect; // Defaults to 0 + + //===--- Data Emission Directives -------------------------------------===// + + /// ZeroDirective - this should be set to the directive used to get some + /// number of zero bytes emitted to the current section. Common cases are + /// "\t.zero\t" and "\t.space\t". If this is set to null, the + /// Data*bitsDirective's will be used to emit zero bytes. + const char *ZeroDirective; // Defaults to "\t.zero\t" + const char *ZeroDirectiveSuffix; // Defaults to "" + + /// AsciiDirective - This directive allows emission of an ascii string with + /// the standard C escape characters embedded into it. + const char *AsciiDirective; // Defaults to "\t.ascii\t" + + /// AscizDirective - If not null, this allows for special handling of + /// zero terminated strings on this target. This is commonly supported as + /// ".asciz". If a target doesn't support this, it can be set to null. + const char *AscizDirective; // Defaults to "\t.asciz\t" + + /// DataDirectives - These directives are used to output some unit of + /// integer data to the current section. If a data directive is set to + /// null, smaller data directives will be used to emit the large sizes. + const char *Data8bitsDirective; // Defaults to "\t.byte\t" + const char *Data16bitsDirective; // Defaults to "\t.short\t" + const char *Data32bitsDirective; // Defaults to "\t.long\t" + const char *Data64bitsDirective; // Defaults to "\t.quad\t" + + //===--- Alignment Information ----------------------------------------===// + + /// AlignDirective - The directive used to emit round up to an alignment + /// boundary. + /// + const char *AlignDirective; // Defaults to "\t.align\t" + + /// AlignmentIsInBytes - If this is true (the default) then the asmprinter + /// emits ".align N" directives, where N is the number of bytes to align to. + /// Otherwise, it emits ".align log2(N)", e.g. 3 to align to an 8 byte + /// boundary. + bool AlignmentIsInBytes; // Defaults to true + + //===--- Section Switching Directives ---------------------------------===// + + /// SwitchToSectionDirective - This is the directive used when we want to + /// emit a global to an arbitrary section. The section name is emited after + /// this. + const char *SwitchToSectionDirective; // Defaults to "\t.section\t" + + /// TextSectionStartSuffix - This is printed after each start of section + /// directive for text sections. + const char *TextSectionStartSuffix; // Defaults to "". + + /// DataSectionStartSuffix - This is printed after each start of section + /// directive for data sections. + const char *DataSectionStartSuffix; // Defaults to "". + + /// SectionEndDirectiveSuffix - If non-null, the asm printer will close each + /// section with the section name and this suffix printed. + const char *SectionEndDirectiveSuffix;// Defaults to null. + + /// ConstantPoolSection - This is the section that we SwitchToSection right + /// before emitting the constant pool for a function. + const char *ConstantPoolSection; // Defaults to "\t.section .rodata" + + /// JumpTableDataSection - This is the section that we SwitchToSection right + /// before emitting the jump tables for a function when the relocation model + /// is not PIC. + const char *JumpTableDataSection; // Defaults to "\t.section .rodata" + + /// JumpTableDirective - if non-null, the directive to emit before a jump + /// table. + const char *JumpTableDirective; + + /// CStringSection - If not null, this allows for special handling of + /// cstring constants (\0 terminated string that does not contain any + /// other null bytes) on this target. This is commonly supported as + /// ".cstring". + const char *CStringSection; // Defaults to NULL + + /// StaticCtorsSection - This is the directive that is emitted to switch to + /// a section to emit the static constructor list. + /// Defaults to "\t.section .ctors,\"aw\",@progbits". + const char *StaticCtorsSection; + + /// StaticDtorsSection - This is the directive that is emitted to switch to + /// a section to emit the static destructor list. + /// Defaults to "\t.section .dtors,\"aw\",@progbits". + const char *StaticDtorsSection; + + /// FourByteConstantSection, EightByteConstantSection, + /// SixteenByteConstantSection - These are special sections where we place + /// 4-, 8-, and 16- byte constant literals. + const char *FourByteConstantSection; + const char *EightByteConstantSection; + const char *SixteenByteConstantSection; + + /// ReadOnlySection - This is the directive that is emitted to switch to a + /// read-only section for constant data (e.g. data declared const, + /// jump tables). + const char *ReadOnlySection; // Defaults to NULL + + //===--- Global Variable Emission Directives --------------------------===// + + /// GlobalDirective - This is the directive used to declare a global entity. + /// + const char *GlobalDirective; // Defaults to NULL. + + /// SetDirective - This is the name of a directive that can be used to tell + /// the assembler to set the value of a variable to some expression. + const char *SetDirective; // Defaults to null. + + /// LCOMMDirective - This is the name of a directive (if supported) that can + /// be used to efficiently declare a local (internal) block of zero + /// initialized data in the .bss/.data section. The syntax expected is: + /// \literal <LCOMMDirective> SYMBOLNAME LENGTHINBYTES, ALIGNMENT + /// \endliteral + const char *LCOMMDirective; // Defaults to null. + + const char *COMMDirective; // Defaults to "\t.comm\t". + + /// COMMDirectiveTakesAlignment - True if COMMDirective take a third + /// argument that specifies the alignment of the declaration. + bool COMMDirectiveTakesAlignment; // Defaults to true. + + /// HasDotTypeDotSizeDirective - True if the target has .type and .size + /// directives, this is true for most ELF targets. + bool HasDotTypeDotSizeDirective; // Defaults to true. + + /// UsedDirective - This directive, if non-null, is used to declare a global + /// as being used somehow that the assembler can't see. This prevents dead + /// code elimination on some targets. + const char *UsedDirective; // Defaults to null. + + /// WeakRefDirective - This directive, if non-null, is used to declare a + /// global as being a weak undefined symbol. + const char *WeakRefDirective; // Defaults to null. + + /// HiddenDirective - This directive, if non-null, is used to declare a + /// global or function as having hidden visibility. + const char *HiddenDirective; // Defaults to "\t.hidden\t". + + /// ProtectedDirective - This directive, if non-null, is used to declare a + /// global or function as having protected visibility. + const char *ProtectedDirective; // Defaults to "\t.protected\t". + + //===--- Dwarf Emission Directives -----------------------------------===// + + /// AbsoluteDebugSectionOffsets - True if we should emit abolute section + /// offsets for debug information. Defaults to false. + bool AbsoluteDebugSectionOffsets; + + /// AbsoluteEHSectionOffsets - True if we should emit abolute section + /// offsets for EH information. Defaults to false. + bool AbsoluteEHSectionOffsets; + + /// HasLEB128 - True if target asm supports leb128 directives. + /// + bool HasLEB128; // Defaults to false. + + /// hasDotLoc - True if target asm supports .loc directives. + /// + bool HasDotLoc; // Defaults to false. + + /// HasDotFile - True if target asm supports .file directives. + /// + bool HasDotFile; // Defaults to false. + + /// SupportsDebugInformation - True if target supports emission of debugging + /// information. + bool SupportsDebugInformation; + + /// SupportsExceptionHandling - True if target supports + /// exception handling. + /// + bool SupportsExceptionHandling; // Defaults to false. + + /// RequiresFrameSection - true if the Dwarf2 output needs a frame section + /// + bool DwarfRequiresFrameSection; // Defaults to true. + + /// DwarfSectionOffsetDirective - Special section offset directive. + const char* DwarfSectionOffsetDirective; // Defaults to NULL + + /// DwarfAbbrevSection - Section directive for Dwarf abbrev. + /// + const char *DwarfAbbrevSection; // Defaults to ".debug_abbrev". + + /// DwarfInfoSection - Section directive for Dwarf info. + /// + const char *DwarfInfoSection; // Defaults to ".debug_info". + + /// DwarfLineSection - Section directive for Dwarf info. + /// + const char *DwarfLineSection; // Defaults to ".debug_line". + + /// DwarfFrameSection - Section directive for Dwarf info. + /// + const char *DwarfFrameSection; // Defaults to ".debug_frame". + + /// DwarfPubNamesSection - Section directive for Dwarf info. + /// + const char *DwarfPubNamesSection; // Defaults to ".debug_pubnames". + + /// DwarfPubTypesSection - Section directive for Dwarf info. + /// + const char *DwarfPubTypesSection; // Defaults to ".debug_pubtypes". + + /// DwarfStrSection - Section directive for Dwarf info. + /// + const char *DwarfStrSection; // Defaults to ".debug_str". + + /// DwarfLocSection - Section directive for Dwarf info. + /// + const char *DwarfLocSection; // Defaults to ".debug_loc". + + /// DwarfARangesSection - Section directive for Dwarf info. + /// + const char *DwarfARangesSection; // Defaults to ".debug_aranges". + + /// DwarfRangesSection - Section directive for Dwarf info. + /// + const char *DwarfRangesSection; // Defaults to ".debug_ranges". + + /// DwarfMacInfoSection - Section directive for Dwarf info. + /// + const char *DwarfMacInfoSection; // Defaults to ".debug_macinfo". + + /// DwarfEHFrameSection - Section directive for Exception frames. + /// + const char *DwarfEHFrameSection; // Defaults to ".eh_frame". + + /// DwarfExceptionSection - Section directive for Exception table. + /// + const char *DwarfExceptionSection; // Defaults to ".gcc_except_table". + + + //===--- CBE Asm Translation Table -----------------------------------===// + + const char** AsmTransCBE; // Defaults to empty + + public: + TargetAsmInfo(); + virtual ~TargetAsmInfo(); + + /// Measure the specified inline asm to determine an approximation of its + /// length. + virtual unsigned getInlineAsmLength(const char *Str) const; + + /// 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. + virtual bool ExpandInlineAsm(CallInst *CI) const { + return false; + } + + // Accessors. + // + const char *getTextSection() const { + return TextSection; + } + const char *getDataSection() const { + return DataSection; + } + const char *getBSSSection() const { + return BSSSection; + } + const char *getTLSDataSection() const { + return TLSDataSection; + } + const char *getTLSBSSSection() const { + return TLSBSSSection; + } + const char *getZeroFillDirective() const { + return ZeroFillDirective; + } + unsigned getAddressSize() const { + return AddressSize; + } + bool needsSet() const { + return NeedsSet; + } + const char *getPCSymbol() const { + return PCSymbol; + } + char getSeparatorChar() const { + return SeparatorChar; + } + const char *getCommentString() const { + return CommentString; + } + const char *getGlobalPrefix() const { + return GlobalPrefix; + } + const char *getPrivateGlobalPrefix() const { + return PrivateGlobalPrefix; + } + const char *getJumpTableSpecialLabelPrefix() const { + return JumpTableSpecialLabelPrefix; + } + const char *getGlobalVarAddrPrefix() const { + return GlobalVarAddrPrefix; + } + const char *getGlobalVarAddrSuffix() const { + return GlobalVarAddrSuffix; + } + const char *getFunctionAddrPrefix() const { + return FunctionAddrPrefix; + } + const char *getFunctionAddrSuffix() const { + return FunctionAddrSuffix; + } + const char *getInlineAsmStart() const { + return InlineAsmStart; + } + const char *getInlineAsmEnd() const { + return InlineAsmEnd; + } + unsigned getAssemblerDialect() const { + return AssemblerDialect; + } + const char *getZeroDirective() const { + return ZeroDirective; + } + const char *getZeroDirectiveSuffix() const { + return ZeroDirectiveSuffix; + } + const char *getAsciiDirective() const { + return AsciiDirective; + } + const char *getAscizDirective() const { + return AscizDirective; + } + const char *getData8bitsDirective() const { + return Data8bitsDirective; + } + const char *getData16bitsDirective() const { + return Data16bitsDirective; + } + const char *getData32bitsDirective() const { + return Data32bitsDirective; + } + const char *getData64bitsDirective() const { + return Data64bitsDirective; + } + const char *getJumpTableDirective() const { + return JumpTableDirective; + } + const char *getAlignDirective() const { + return AlignDirective; + } + bool getAlignmentIsInBytes() const { + return AlignmentIsInBytes; + } + const char *getSwitchToSectionDirective() const { + return SwitchToSectionDirective; + } + const char *getTextSectionStartSuffix() const { + return TextSectionStartSuffix; + } + const char *getDataSectionStartSuffix() const { + return DataSectionStartSuffix; + } + const char *getSectionEndDirectiveSuffix() const { + return SectionEndDirectiveSuffix; + } + const char *getConstantPoolSection() const { + return ConstantPoolSection; + } + const char *getJumpTableDataSection() const { + return JumpTableDataSection; + } + const char *getCStringSection() const { + return CStringSection; + } + const char *getStaticCtorsSection() const { + return StaticCtorsSection; + } + const char *getStaticDtorsSection() const { + return StaticDtorsSection; + } + const char *getFourByteConstantSection() const { + return FourByteConstantSection; + } + const char *getEightByteConstantSection() const { + return EightByteConstantSection; + } + const char *getSixteenByteConstantSection() const { + return SixteenByteConstantSection; + } + const char *getReadOnlySection() const { + return ReadOnlySection; + } + const char *getGlobalDirective() const { + return GlobalDirective; + } + const char *getSetDirective() const { + return SetDirective; + } + const char *getLCOMMDirective() const { + return LCOMMDirective; + } + const char *getCOMMDirective() const { + return COMMDirective; + } + bool getCOMMDirectiveTakesAlignment() const { + return COMMDirectiveTakesAlignment; + } + bool hasDotTypeDotSizeDirective() const { + return HasDotTypeDotSizeDirective; + } + const char *getUsedDirective() const { + return UsedDirective; + } + const char *getWeakRefDirective() const { + return WeakRefDirective; + } + const char *getHiddenDirective() const { + return HiddenDirective; + } + const char *getProtectedDirective() const { + return ProtectedDirective; + } + bool isAbsoluteDebugSectionOffsets() const { + return AbsoluteDebugSectionOffsets; + } + bool isAbsoluteEHSectionOffsets() const { + return AbsoluteEHSectionOffsets; + } + bool hasLEB128() const { + return HasLEB128; + } + bool hasDotLoc() const { + return HasDotLoc; + } + bool hasDotFile() const { + return HasDotFile; + } + bool doesSupportDebugInformation() const { + return SupportsDebugInformation; + } + bool doesSupportExceptionHandling() const { + return SupportsExceptionHandling; + } + bool doesDwarfRequireFrameSection() const { + return DwarfRequiresFrameSection; + } + const char *getDwarfSectionOffsetDirective() const { + return DwarfSectionOffsetDirective; + } + const char *getDwarfAbbrevSection() const { + return DwarfAbbrevSection; + } + const char *getDwarfInfoSection() const { + return DwarfInfoSection; + } + const char *getDwarfLineSection() const { + return DwarfLineSection; + } + const char *getDwarfFrameSection() const { + return DwarfFrameSection; + } + const char *getDwarfPubNamesSection() const { + return DwarfPubNamesSection; + } + const char *getDwarfPubTypesSection() const { + return DwarfPubTypesSection; + } + const char *getDwarfStrSection() const { + return DwarfStrSection; + } + const char *getDwarfLocSection() const { + return DwarfLocSection; + } + const char *getDwarfARangesSection() const { + return DwarfARangesSection; + } + const char *getDwarfRangesSection() const { + return DwarfRangesSection; + } + const char *getDwarfMacInfoSection() const { + return DwarfMacInfoSection; + } + const char *getDwarfEHFrameSection() const { + return DwarfEHFrameSection; + } + const char *getDwarfExceptionSection() const { + return DwarfExceptionSection; + } + const char** getAsmCBE() const { + return AsmTransCBE; + } + }; +} + +#endif + diff --git a/include/llvm/Target/TargetData.h b/include/llvm/Target/TargetData.h new file mode 100644 index 0000000..5756079 --- /dev/null +++ b/include/llvm/Target/TargetData.h @@ -0,0 +1,243 @@ +//===-- llvm/Target/TargetData.h - Data size & alignment info ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines target properties related to datatype size/offset/alignment +// information. It uses lazy annotations to cache information about how +// structure types are laid out and used. +// +// This structure should be created once, filled in if the defaults are not +// correct and then passed around by const&. None of the members functions +// require modification to the object. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETDATA_H +#define LLVM_TARGET_TARGETDATA_H + +#include "llvm/Pass.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/SmallVector.h" +#include <string> + +namespace llvm { + +class Value; +class Type; +class StructType; +class StructLayout; +class GlobalVariable; + +/// Enum used to categorize the alignment types stored by TargetAlignElem +enum AlignTypeEnum { + INTEGER_ALIGN = 'i', ///< Integer type alignment + VECTOR_ALIGN = 'v', ///< Vector type alignment + FLOAT_ALIGN = 'f', ///< Floating point type alignment + AGGREGATE_ALIGN = 'a' ///< Aggregate alignment +}; +/// Target alignment element. +/// +/// Stores the alignment data associated with a given alignment type (pointer, +/// integer, vector, float) and type bit width. +/// +/// @note The unusual order of elements in the structure attempts to reduce +/// padding and make the structure slightly more cache friendly. +struct TargetAlignElem { + AlignTypeEnum AlignType : 8; //< Alignment type (AlignTypeEnum) + unsigned char ABIAlign; //< ABI alignment for this type/bitw + unsigned char PrefAlign; //< Pref. alignment for this type/bitw + uint32_t TypeBitWidth; //< Type bit width + + /// Initializer + static TargetAlignElem get(AlignTypeEnum align_type, unsigned char abi_align, + unsigned char pref_align, uint32_t bit_width); + /// Equality predicate + bool operator==(const TargetAlignElem &rhs) const; + /// output stream operator + std::ostream &dump(std::ostream &os) const; +}; + +class TargetData : public ImmutablePass { +private: + bool LittleEndian; ///< Defaults to false + unsigned char PointerMemSize; ///< Pointer size in bytes + unsigned char PointerABIAlign; ///< Pointer ABI alignment + unsigned char PointerPrefAlign; ///< Pointer preferred alignment + + //! Where the primitive type alignment data is stored. + /*! + @sa init(). + @note Could support multiple size pointer alignments, e.g., 32-bit pointers + vs. 64-bit pointers by extending TargetAlignment, but for now, we don't. + */ + SmallVector<TargetAlignElem, 16> Alignments; + //! Alignment iterator shorthand + typedef SmallVector<TargetAlignElem, 16>::iterator align_iterator; + //! Constant alignment iterator shorthand + typedef SmallVector<TargetAlignElem, 16>::const_iterator align_const_iterator; + //! Invalid alignment. + /*! + This member is a signal that a requested alignment type and bit width were + not found in the SmallVector. + */ + static const TargetAlignElem InvalidAlignmentElem; + + //! Set/initialize target alignments + void setAlignment(AlignTypeEnum align_type, unsigned char abi_align, + unsigned char pref_align, uint32_t bit_width); + unsigned getAlignmentInfo(AlignTypeEnum align_type, uint32_t bit_width, + bool ABIAlign) const; + //! Internal helper method that returns requested alignment for type. + unsigned char getAlignment(const Type *Ty, bool abi_or_pref) const; + + /// Valid alignment predicate. + /// + /// Predicate that tests a TargetAlignElem reference returned by get() against + /// InvalidAlignmentElem. + inline bool validAlignment(const TargetAlignElem &align) const { + return (&align != &InvalidAlignmentElem); + } + +public: + /// Default ctor. + /// + /// @note This has to exist, because this is a pass, but it should never be + /// used. + TargetData() : ImmutablePass((intptr_t)&ID) { + assert(0 && "ERROR: Bad TargetData ctor used. " + "Tool did not specify a TargetData to use?"); + abort(); + } + + /// Constructs a TargetData from a specification string. See init(). + TargetData(const std::string &TargetDescription) + : ImmutablePass((intptr_t)&ID) { + init(TargetDescription); + } + + /// Initialize target data from properties stored in the module. + TargetData(const Module *M); + + TargetData(const TargetData &TD) : + ImmutablePass((intptr_t)&ID), + LittleEndian(TD.isLittleEndian()), + PointerMemSize(TD.PointerMemSize), + PointerABIAlign(TD.PointerABIAlign), + PointerPrefAlign(TD.PointerPrefAlign), + Alignments(TD.Alignments) + { } + + ~TargetData(); // Not virtual, do not subclass this class + + //! Parse a target data layout string and initialize TargetData alignments. + void init(const std::string &TargetDescription); + + /// Target endianness... + bool isLittleEndian() const { return LittleEndian; } + bool isBigEndian() const { return !LittleEndian; } + + /// getStringRepresentation - Return the string representation of the + /// TargetData. This representation is in the same format accepted by the + /// string constructor above. + std::string getStringRepresentation() const; + /// Target pointer alignment + unsigned char getPointerABIAlignment() const { return PointerABIAlign; } + /// Return target's alignment for stack-based pointers + unsigned char getPointerPrefAlignment() const { return PointerPrefAlign; } + /// Target pointer size + unsigned char getPointerSize() const { return PointerMemSize; } + /// Target pointer size, in bits + unsigned char getPointerSizeInBits() const { return 8*PointerMemSize; } + + /// getTypeSize - Return the number of bytes necessary to hold the specified + /// type. + uint64_t getTypeSize(const Type *Ty) const; + + /// getTypeSizeInBits - Return the number of bits necessary to hold the + /// specified type. + uint64_t getTypeSizeInBits(const Type* Ty) const; + + /// getABITypeAlignment - Return the minimum ABI-required alignment for the + /// specified type. + unsigned char getABITypeAlignment(const Type *Ty) const; + + /// getPrefTypeAlignment - Return the preferred stack/global alignment for + /// the specified type. + unsigned char getPrefTypeAlignment(const Type *Ty) const; + + /// getPreferredTypeAlignmentShift - Return the preferred alignment for the + /// specified type, returned as log2 of the value (a shift amount). + /// + unsigned char getPreferredTypeAlignmentShift(const Type *Ty) const; + + /// getIntPtrType - Return an unsigned integer type that is the same size or + /// greater to the host pointer size. + /// + const Type *getIntPtrType() const; + + /// getIndexedOffset - return the offset from the beginning of the type for the + /// specified indices. This is used to implement getelementptr. + /// + uint64_t getIndexedOffset(const Type *Ty, + Value* const* Indices, unsigned NumIndices) const; + + /// getStructLayout - Return a StructLayout object, indicating the alignment + /// of the struct, its size, and the offsets of its fields. Note that this + /// information is lazily cached. + const StructLayout *getStructLayout(const StructType *Ty) const; + + /// InvalidateStructLayoutInfo - TargetData speculatively caches StructLayout + /// objects. If a TargetData object is alive when types are being refined and + /// removed, this method must be called whenever a StructType is removed to + /// avoid a dangling pointer in this cache. + void InvalidateStructLayoutInfo(const StructType *Ty) const; + + /// getPreferredAlignmentLog - Return the preferred alignment of the + /// specified global, returned in log form. This includes an explicitly + /// requested alignment (if the global has one). + unsigned getPreferredAlignmentLog(const GlobalVariable *GV) const; + + static char ID; // Pass identification, replacement for typeid +}; + +/// StructLayout - used to lazily calculate structure layout information for a +/// target machine, based on the TargetData structure. +/// +class StructLayout { + uint64_t StructSize; + unsigned StructAlignment; + unsigned NumElements; + uint64_t MemberOffsets[1]; // variable sized array! +public: + + uint64_t getSizeInBytes() const { + return StructSize; + } + + unsigned getAlignment() const { + return StructAlignment; + } + + /// getElementContainingOffset - Given a valid offset into the structure, + /// return the structure index that contains it. + /// + unsigned getElementContainingOffset(uint64_t Offset) const; + + uint64_t getElementOffset(unsigned Idx) const { + assert(Idx < NumElements && "Invalid element idx!"); + return MemberOffsets[Idx]; + } + +private: + friend class TargetData; // Only TargetData can create this class + StructLayout(const StructType *ST, const TargetData &TD); +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Target/TargetELFWriterInfo.h b/include/llvm/Target/TargetELFWriterInfo.h new file mode 100644 index 0000000..a8332df --- /dev/null +++ b/include/llvm/Target/TargetELFWriterInfo.h @@ -0,0 +1,43 @@ +//===-- llvm/Target/TargetELFWriterInfo.h - ELF Writer Info -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Bill Wendling and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the TargetELFWriterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETELFWRITERINFO_H +#define LLVM_TARGET_TARGETELFWRITERINFO_H + +namespace llvm { + + class MachineBasicBlock; + + //===--------------------------------------------------------------------===// + // TargetELFWriterInfo + //===--------------------------------------------------------------------===// + + class TargetELFWriterInfo { + // EMachine - This field is the target specific value to emit as the + // e_machine member of the ELF header. + unsigned short EMachine; + public: + enum MachineType { + NoMachine, + EM_386 = 3 + }; + + TargetELFWriterInfo(MachineType machine) : EMachine(machine) {} + virtual ~TargetELFWriterInfo() {} + + unsigned short getEMachine() const { return EMachine; } + }; + +} // end llvm namespace + +#endif // LLVM_TARGET_TARGETELFWRITERINFO_H diff --git a/include/llvm/Target/TargetFrameInfo.h b/include/llvm/Target/TargetFrameInfo.h new file mode 100644 index 0000000..53430a5 --- /dev/null +++ b/include/llvm/Target/TargetFrameInfo.h @@ -0,0 +1,82 @@ +//===-- llvm/Target/TargetFrameInfo.h ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Interface to describe the layout of a stack frame on the target machine. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETFRAMEINFO_H +#define LLVM_TARGET_TARGETFRAMEINFO_H + +#include <utility> + +namespace llvm { + +class MachineFunction; + +/// Information about stack frame layout on the target. It holds the direction +/// of stack growth, the known stack alignment on entry to each function, and +/// the offset to the locals area. +/// +/// The offset to the local area is the offset from the stack pointer on +/// function entry to the first location where function data (local variables, +/// spill locations) can be stored. +class TargetFrameInfo { +public: + enum StackDirection { + StackGrowsUp, // Adding to the stack increases the stack address + StackGrowsDown // Adding to the stack decreases the stack address + }; +private: + StackDirection StackDir; + unsigned StackAlignment; + int LocalAreaOffset; +public: + TargetFrameInfo(StackDirection D, unsigned StackAl, int LAO) + : StackDir(D), StackAlignment(StackAl), LocalAreaOffset(LAO) {} + + virtual ~TargetFrameInfo(); + + // These methods return information that describes the abstract stack layout + // of the target machine. + + /// getStackGrowthDirection - Return the direction the stack grows + /// + StackDirection getStackGrowthDirection() const { return StackDir; } + + /// getStackAlignment - This method returns the number of bytes that the stack + /// pointer must be aligned to. Typically, this is the largest alignment for + /// any data object in the target. + /// + unsigned getStackAlignment() const { return StackAlignment; } + + /// getOffsetOfLocalArea - This method returns the offset of the local area + /// from the stack pointer on entrance to a function. + /// + int getOffsetOfLocalArea() const { return LocalAreaOffset; } + + /// 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. + /// + /// Each entry in this array contains a <register,offset> pair, indicating the + /// fixed offset from the incoming stack pointer that each register should be + /// spilled at. If a register is not listed here, the code generator is + /// allowed to spill it anywhere it chooses. + /// + virtual const std::pair<unsigned, int> * + getCalleeSavedSpillSlots(unsigned &NumEntries) const { + NumEntries = 0; + return 0; + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h new file mode 100644 index 0000000..25fb79f --- /dev/null +++ b/include/llvm/Target/TargetInstrInfo.h @@ -0,0 +1,478 @@ +//===-- llvm/Target/TargetInstrInfo.h - Instruction Info --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the target machine instructions to the code generator. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETINSTRINFO_H +#define LLVM_TARGET_TARGETINSTRINFO_H + +#include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/CodeGen/MachineFunction.h" +#include "llvm/Support/DataTypes.h" +#include <vector> +#include <cassert> + +namespace llvm { + +class MachineInstr; +class TargetMachine; +class MachineCodeForInstruction; +class TargetRegisterClass; +class LiveVariables; + +//--------------------------------------------------------------------------- +// Data types used to define information about a single machine instruction +//--------------------------------------------------------------------------- + +typedef short MachineOpCode; +typedef unsigned InstrSchedClass; + +//--------------------------------------------------------------------------- +// struct TargetInstrDescriptor: +// Predefined information about each machine instruction. +// Designed to initialized statically. +// + +const unsigned M_BRANCH_FLAG = 1 << 0; +const unsigned M_CALL_FLAG = 1 << 1; +const unsigned M_RET_FLAG = 1 << 2; +const unsigned M_BARRIER_FLAG = 1 << 3; +const unsigned M_DELAY_SLOT_FLAG = 1 << 4; +const unsigned M_LOAD_FLAG = 1 << 5; +const unsigned M_STORE_FLAG = 1 << 6; + +// M_CONVERTIBLE_TO_3_ADDR - This is a 2-address instruction which can be +// changed into a 3-address instruction if the first two operands cannot be +// assigned to the same register. The target must implement the +// TargetInstrInfo::convertToThreeAddress method for this instruction. +const unsigned M_CONVERTIBLE_TO_3_ADDR = 1 << 7; + +// This M_COMMUTABLE - is a 2- or 3-address instruction (of the form X = op Y, +// Z), which produces the same result if Y and Z are exchanged. +const unsigned M_COMMUTABLE = 1 << 8; + +// M_TERMINATOR_FLAG - Is this instruction part of the terminator for a basic +// block? Typically this is things like return and branch instructions. +// Various passes use this to insert code into the bottom of a basic block, but +// before control flow occurs. +const unsigned M_TERMINATOR_FLAG = 1 << 9; + +// M_USES_CUSTOM_DAG_SCHED_INSERTION - Set if this instruction requires custom +// insertion support when the DAG scheduler is inserting it into a machine basic +// block. +const unsigned M_USES_CUSTOM_DAG_SCHED_INSERTION = 1 << 10; + +// M_VARIABLE_OPS - Set if this instruction can have a variable number of extra +// operands in addition to the minimum number operands specified. +const unsigned M_VARIABLE_OPS = 1 << 11; + +// M_PREDICABLE - Set if this instruction has a predicate operand that +// controls execution. It may be set to 'always'. +const unsigned M_PREDICABLE = 1 << 12; + +// M_REMATERIALIZIBLE - Set if this instruction can be trivally re-materialized +// at any time, e.g. constant generation, load from constant pool. +const unsigned M_REMATERIALIZIBLE = 1 << 13; + +// M_NOT_DUPLICABLE - Set if this instruction cannot be safely duplicated. +// (e.g. instructions with unique labels attached). +const unsigned M_NOT_DUPLICABLE = 1 << 14; + +// M_HAS_OPTIONAL_DEF - Set if this instruction has an optional definition, e.g. +// ARM instructions which can set condition code if 's' bit is set. +const unsigned M_HAS_OPTIONAL_DEF = 1 << 15; + +// Machine operand flags +// M_LOOK_UP_PTR_REG_CLASS - Set if this operand is a pointer value and it +// requires a callback to look up its register class. +const unsigned M_LOOK_UP_PTR_REG_CLASS = 1 << 0; + +/// M_PREDICATE_OPERAND - Set if this is one of the operands that made up of the +/// predicate operand that controls an M_PREDICATED instruction. +const unsigned M_PREDICATE_OPERAND = 1 << 1; + +/// M_OPTIONAL_DEF_OPERAND - Set if this operand is a optional def. +/// +const unsigned M_OPTIONAL_DEF_OPERAND = 1 << 2; + +namespace TOI { + // Operand constraints: only "tied_to" for now. + enum OperandConstraint { + TIED_TO = 0 // Must be allocated the same register as. + }; +} + +/// TargetOperandInfo - This holds information about one operand of a machine +/// instruction, indicating the register class for register operands, etc. +/// +class TargetOperandInfo { +public: + /// RegClass - This specifies the register class enumeration of the operand + /// if the operand is a register. If not, this contains 0. + unsigned short RegClass; + unsigned short Flags; + /// Lower 16 bits are used to specify which constraints are set. The higher 16 + /// bits are used to specify the value of constraints (4 bits each). + unsigned int Constraints; + /// Currently no other information. +}; + + +class TargetInstrDescriptor { +public: + MachineOpCode Opcode; // The opcode. + unsigned short numOperands; // Num of args (may be more if variable_ops). + const char * Name; // Assembly language mnemonic for the opcode. + InstrSchedClass schedClass; // enum identifying instr sched class + unsigned Flags; // flags identifying machine instr class + unsigned TSFlags; // Target Specific Flag values + const unsigned *ImplicitUses; // Registers implicitly read by this instr + const unsigned *ImplicitDefs; // Registers implicitly defined by this instr + const TargetOperandInfo *OpInfo; // 'numOperands' entries about operands. + + /// getOperandConstraint - Returns the value of the specific constraint if + /// it is set. Returns -1 if it is not set. + int getOperandConstraint(unsigned OpNum, + TOI::OperandConstraint Constraint) const { + assert((OpNum < numOperands || (Flags & M_VARIABLE_OPS)) && + "Invalid operand # of TargetInstrInfo"); + if (OpNum < numOperands && + (OpInfo[OpNum].Constraints & (1 << Constraint))) { + unsigned Pos = 16 + Constraint * 4; + return (int)(OpInfo[OpNum].Constraints >> Pos) & 0xf; + } + return -1; + } + + /// findTiedToSrcOperand - Returns the operand that is tied to the specified + /// dest operand. Returns -1 if there isn't one. + int findTiedToSrcOperand(unsigned OpNum) const; +}; + + +//--------------------------------------------------------------------------- +/// +/// TargetInstrInfo - Interface to description of machine instructions +/// +class TargetInstrInfo { + const TargetInstrDescriptor* desc; // raw array to allow static init'n + unsigned NumOpcodes; // number of entries in the desc array + unsigned numRealOpCodes; // number of non-dummy op codes + + TargetInstrInfo(const TargetInstrInfo &); // DO NOT IMPLEMENT + void operator=(const TargetInstrInfo &); // DO NOT IMPLEMENT +public: + TargetInstrInfo(const TargetInstrDescriptor *desc, unsigned NumOpcodes); + virtual ~TargetInstrInfo(); + + // Invariant opcodes: All instruction sets have these as their low opcodes. + enum { + PHI = 0, + INLINEASM = 1, + LABEL = 2 + }; + + unsigned getNumOpcodes() const { return NumOpcodes; } + + /// get - Return the machine instruction descriptor that corresponds to the + /// specified instruction opcode. + /// + const TargetInstrDescriptor& get(MachineOpCode Opcode) const { + assert((unsigned)Opcode < NumOpcodes); + return desc[Opcode]; + } + + const char *getName(MachineOpCode Opcode) const { + return get(Opcode).Name; + } + + int getNumOperands(MachineOpCode Opcode) const { + return get(Opcode).numOperands; + } + + InstrSchedClass getSchedClass(MachineOpCode Opcode) const { + return get(Opcode).schedClass; + } + + const unsigned *getImplicitUses(MachineOpCode Opcode) const { + return get(Opcode).ImplicitUses; + } + + const unsigned *getImplicitDefs(MachineOpCode Opcode) const { + return get(Opcode).ImplicitDefs; + } + + + // + // Query instruction class flags according to the machine-independent + // flags listed above. + // + bool isReturn(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_RET_FLAG; + } + + bool isCommutableInstr(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_COMMUTABLE; + } + bool isTerminatorInstr(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_TERMINATOR_FLAG; + } + + bool isBranch(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_BRANCH_FLAG; + } + + /// isBarrier - Returns true if the specified instruction stops control flow + /// from executing the instruction immediately following it. Examples include + /// unconditional branches and return instructions. + bool isBarrier(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_BARRIER_FLAG; + } + + bool isCall(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_CALL_FLAG; + } + bool isLoad(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_LOAD_FLAG; + } + bool isStore(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_STORE_FLAG; + } + + /// hasDelaySlot - Returns true if the specified instruction has a delay slot + /// which must be filled by the code generator. + bool hasDelaySlot(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_DELAY_SLOT_FLAG; + } + + /// usesCustomDAGSchedInsertionHook - Return true if this instruction requires + /// custom insertion support when the DAG scheduler is inserting it into a + /// machine basic block. + bool usesCustomDAGSchedInsertionHook(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_USES_CUSTOM_DAG_SCHED_INSERTION; + } + + bool hasVariableOperands(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_VARIABLE_OPS; + } + + bool isPredicable(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_PREDICABLE; + } + + bool isNotDuplicable(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_NOT_DUPLICABLE; + } + + bool hasOptionalDef(MachineOpCode Opcode) const { + return get(Opcode).Flags & M_HAS_OPTIONAL_DEF; + } + + /// isTriviallyReMaterializable - Return true if the instruction is trivially + /// rematerializable, meaning it has no side effects and requires no operands + /// that aren't always available. + bool isTriviallyReMaterializable(MachineInstr *MI) const { + return (MI->getInstrDescriptor()->Flags & M_REMATERIALIZIBLE) && + isReallyTriviallyReMaterializable(MI); + } + +protected: + /// isReallyTriviallyReMaterializable - For instructions with opcodes for + /// which the M_REMATERIALIZABLE flag is set, this function tests whether the + /// instruction itself is actually trivially rematerializable, considering + /// its operands. This is used for targets that have instructions that are + /// only trivially rematerializable for specific uses. This predicate must + /// return false if the instruction has any side effects other than + /// producing a value, or if it requres any address registers that are not + /// always available. + virtual bool isReallyTriviallyReMaterializable(MachineInstr *MI) const { + return true; + } + +public: + /// getOperandConstraint - Returns the value of the specific constraint if + /// it is set. Returns -1 if it is not set. + int getOperandConstraint(MachineOpCode Opcode, unsigned OpNum, + TOI::OperandConstraint Constraint) const { + return get(Opcode).getOperandConstraint(OpNum, Constraint); + } + + /// Return true if the instruction is a register to register move + /// and leave the source and dest operands in the passed parameters. + virtual bool isMoveInstr(const MachineInstr& MI, + unsigned& sourceReg, + unsigned& destReg) const { + return false; + } + + /// isLoadFromStackSlot - If the specified machine instruction is a direct + /// load from a stack slot, return the virtual or physical register number of + /// the destination along with the FrameIndex of the loaded stack slot. If + /// not, return 0. This predicate must return 0 if the instruction has + /// any side effects other than loading from the stack slot. + virtual unsigned isLoadFromStackSlot(MachineInstr *MI, int &FrameIndex) const{ + return 0; + } + + /// isStoreToStackSlot - If the specified machine instruction is a direct + /// store to a stack slot, return the virtual or physical register number of + /// the source reg along with the FrameIndex of the loaded stack slot. If + /// not, return 0. This predicate must return 0 if the instruction has + /// any side effects other than storing to the stack slot. + virtual unsigned isStoreToStackSlot(MachineInstr *MI, int &FrameIndex) const { + return 0; + } + + /// convertToThreeAddress - This method must be implemented by targets that + /// set the M_CONVERTIBLE_TO_3_ADDR flag. When this flag is set, the target + /// may be able to convert a two-address instruction into one or more true + /// three-address instructions on demand. This allows the X86 target (for + /// example) to convert ADD and SHL instructions into LEA instructions if they + /// would require register copies due to two-addressness. + /// + /// This method returns a null pointer if the transformation cannot be + /// performed, otherwise it returns the last new instruction. + /// + virtual MachineInstr * + convertToThreeAddress(MachineFunction::iterator &MFI, + MachineBasicBlock::iterator &MBBI, LiveVariables &LV) const { + return 0; + } + + /// commuteInstruction - If a target has any instructions that are commutable, + /// but require converting to a different instruction or making non-trivial + /// changes to commute them, this method can overloaded to do this. The + /// default implementation of this method simply swaps the first two operands + /// of MI and returns it. + /// + /// If a target wants to make more aggressive changes, they can construct and + /// return a new machine instruction. If an instruction cannot commute, it + /// can also return null. + /// + virtual MachineInstr *commuteInstruction(MachineInstr *MI) const; + + /// AnalyzeBranch - Analyze the branching code at the end of MBB, returning + /// true if it cannot be understood (e.g. it's a switch dispatch or isn't + /// implemented for a target). Upon success, this returns false and returns + /// with the following information in various cases: + /// + /// 1. If this block ends with no branches (it just falls through to its succ) + /// just return false, leaving TBB/FBB null. + /// 2. If this block ends with only an unconditional branch, it sets TBB to be + /// the destination block. + /// 3. If this block ends with an conditional branch and it falls through to + /// an successor block, it sets TBB to be the branch destination block and a + /// list of operands that evaluate the condition. These + /// operands can be passed to other TargetInstrInfo methods to create new + /// branches. + /// 4. If this block ends with an conditional branch and an unconditional + /// block, it returns the 'true' destination in TBB, the 'false' destination + /// in FBB, and a list of operands that evaluate the condition. These + /// operands can be passed to other TargetInstrInfo methods to create new + /// branches. + /// + /// Note that RemoveBranch and InsertBranch must be implemented to support + /// cases where this method returns success. + /// + virtual bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + std::vector<MachineOperand> &Cond) const { + return true; + } + + /// RemoveBranch - Remove the branching code at the end of the specific MBB. + /// this is only invoked in cases where AnalyzeBranch returns success. It + /// returns the number of instructions that were removed. + virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const { + assert(0 && "Target didn't implement TargetInstrInfo::RemoveBranch!"); + return 0; + } + + /// InsertBranch - Insert a branch into the end of the specified + /// MachineBasicBlock. This operands to this method are the same as those + /// returned by AnalyzeBranch. This is invoked in cases where AnalyzeBranch + /// returns success and when an unconditional branch (TBB is non-null, FBB is + /// null, Cond is empty) needs to be inserted. It returns the number of + /// instructions inserted. + virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const std::vector<MachineOperand> &Cond) const { + assert(0 && "Target didn't implement TargetInstrInfo::InsertBranch!"); + return 0; + } + + /// BlockHasNoFallThrough - Return true if the specified block does not + /// fall-through into its successor block. This is primarily used when a + /// branch is unanalyzable. It is useful for things like unconditional + /// indirect branches (jump tables). + virtual bool BlockHasNoFallThrough(MachineBasicBlock &MBB) const { + return false; + } + + /// ReverseBranchCondition - Reverses the branch condition of the specified + /// condition list, returning false on success and true if it cannot be + /// reversed. + virtual bool ReverseBranchCondition(std::vector<MachineOperand> &Cond) const { + return true; + } + + /// insertNoop - Insert a noop into the instruction stream at the specified + /// point. + virtual void insertNoop(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const { + assert(0 && "Target didn't implement insertNoop!"); + abort(); + } + + /// isPredicated - Returns true if the instruction is already predicated. + /// + virtual bool isPredicated(const MachineInstr *MI) const { + return false; + } + + /// isUnpredicatedTerminator - Returns true if the instruction is a + /// terminator instruction that has not been predicated. + virtual bool isUnpredicatedTerminator(const MachineInstr *MI) const; + + /// PredicateInstruction - Convert the instruction into a predicated + /// instruction. It returns true if the operation was successful. + virtual + bool PredicateInstruction(MachineInstr *MI, + const std::vector<MachineOperand> &Pred) const; + + /// SubsumesPredicate - Returns true if the first specified predicate + /// subsumes the second, e.g. GE subsumes GT. + virtual + bool SubsumesPredicate(const std::vector<MachineOperand> &Pred1, + const std::vector<MachineOperand> &Pred2) const { + return false; + } + + /// DefinesPredicate - If the specified instruction defines any predicate + /// or condition code register(s) used for predication, returns true as well + /// as the definition predicate(s) by reference. + virtual bool DefinesPredicate(MachineInstr *MI, + std::vector<MachineOperand> &Pred) const { + return false; + } + + /// getPointerRegClass - Returns a TargetRegisterClass used for pointer + /// values. + virtual const TargetRegisterClass *getPointerRegClass() const { + assert(0 && "Target didn't implement getPointerRegClass!"); + abort(); + return 0; // Must return a value in order to compile with VS 2005 + } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Target/TargetInstrItineraries.h b/include/llvm/Target/TargetInstrItineraries.h new file mode 100644 index 0000000..ee47443 --- /dev/null +++ b/include/llvm/Target/TargetInstrItineraries.h @@ -0,0 +1,84 @@ +//===-- llvm/Target/TargetInstrItineraries.h - Scheduling -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the James M. Laskey and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the structures used for instruction itineraries and +// states. This is used by schedulers to determine instruction states and +// latencies. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETINSTRITINERARIES_H +#define LLVM_TARGET_TARGETINSTRITINERARIES_H + +namespace llvm { + +//===----------------------------------------------------------------------===// +// Instruction stage - These values represent a step in the execution of an +// instruction. The latency represents the number of discrete time slots used +// need to complete the stage. Units represent the choice of functional units +// that can be used to complete the stage. Eg. IntUnit1, IntUnit2. +// +struct InstrStage { + unsigned Cycles; // Length of stage in machine cycles + unsigned Units; // Choice of functional units +}; + + +//===----------------------------------------------------------------------===// +// Instruction itinerary - An itinerary represents a sequential series of steps +// required to complete an instruction. Itineraries are represented as +// sequences of instruction stages. +// +struct InstrItinerary { + unsigned First; // Index of first stage in itinerary + unsigned Last; // Index of last + 1 stage in itinerary +}; + + + +//===----------------------------------------------------------------------===// +// Instruction itinerary Data - Itinerary data supplied by a subtarget to be +// used by a target. +// +struct InstrItineraryData { + InstrStage *Stages; // Array of stages selected + InstrItinerary *Itineratries; // Array of itineraries selected + +// +// Ctors. +// + InstrItineraryData() : Stages(0), Itineratries(0) {} + InstrItineraryData(InstrStage *S, InstrItinerary *I) : Stages(S), Itineratries(I) {} + + // + // isEmpty - Returns true if there are no itineraries. + // + inline bool isEmpty() const { return Itineratries == 0; } + + // + // begin - Return the first stage of the itinerary. + // + inline InstrStage *begin(unsigned ItinClassIndx) const { + unsigned StageIdx = Itineratries[ItinClassIndx].First; + return Stages + StageIdx; + } + + // + // end - Return the last+1 stage of the itinerary. + // + inline InstrStage *end(unsigned ItinClassIndx) const { + unsigned StageIdx = Itineratries[ItinClassIndx].Last; + return Stages + StageIdx; + } +}; + + +} // End llvm namespace + +#endif diff --git a/include/llvm/Target/TargetJITInfo.h b/include/llvm/Target/TargetJITInfo.h new file mode 100644 index 0000000..b80b055 --- /dev/null +++ b/include/llvm/Target/TargetJITInfo.h @@ -0,0 +1,90 @@ +//===- Target/TargetJITInfo.h - Target Information for JIT ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes an abstract interface used by the Just-In-Time code +// generator to perform target-specific activities, such as emitting stubs. If +// a TargetMachine supports JIT code generation, it should provide one of these +// objects through the getJITInfo() method. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETJITINFO_H +#define LLVM_TARGET_TARGETJITINFO_H + +#include <cassert> +#include <vector> + +namespace llvm { + class Function; + class FunctionPassManager; + class MachineBasicBlock; + class MachineCodeEmitter; + class MachineRelocation; + + /// TargetJITInfo - Target specific information required by the Just-In-Time + /// code generator. + class TargetJITInfo { + public: + virtual ~TargetJITInfo() {} + + /// replaceMachineCodeForFunction - Make it so that calling the function + /// whose machine code is at OLD turns into a call to NEW, perhaps by + /// overwriting OLD with a branch to NEW. This is used for self-modifying + /// code. + /// + virtual void replaceMachineCodeForFunction(void *Old, void *New) = 0; + + /// emitFunctionStub - Use the specified MachineCodeEmitter object to emit a + /// small native function that simply calls the function at the specified + /// address. Return the address of the resultant function. + virtual void *emitFunctionStub(void *Fn, MachineCodeEmitter &MCE) { + assert(0 && "This target doesn't implement emitFunctionStub!"); + return 0; + } + + /// LazyResolverFn - This typedef is used to represent the function that + /// unresolved call points should invoke. This is a target specific + /// function that knows how to walk the stack and find out which stub the + /// call is coming from. + typedef void (*LazyResolverFn)(); + + /// JITCompilerFn - This typedef is used to represent the JIT function that + /// lazily compiles the function corresponding to a stub. The JIT keeps + /// track of the mapping between stubs and LLVM Functions, the target + /// provides the ability to figure out the address of a stub that is called + /// by the LazyResolverFn. + typedef void* (*JITCompilerFn)(void *); + + /// getLazyResolverFunction - This method is used to initialize the JIT, + /// giving the target the function that should be used to compile a + /// function, and giving the JIT the target function used to do the lazy + /// resolving. + virtual LazyResolverFn getLazyResolverFunction(JITCompilerFn) { + assert(0 && "Not implemented for this target!"); + return 0; + } + + /// relocate - Before the JIT can run a block of code that has been emitted, + /// it must rewrite the code to contain the actual addresses of any + /// referenced global symbols. + virtual void relocate(void *Function, MachineRelocation *MR, + unsigned NumRelocs, unsigned char* GOTBase) { + assert(NumRelocs == 0 && "This target does not have relocations!"); + } + + /// needsGOT - Allows a target to specify that it would like the + // JIT to manage a GOT for it. + bool needsGOT() const { return useGOT; } + + protected: + bool useGOT; + }; +} // End llvm namespace + +#endif diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h new file mode 100644 index 0000000..a95a03b --- /dev/null +++ b/include/llvm/Target/TargetLowering.h @@ -0,0 +1,1153 @@ +//===-- llvm/Target/TargetLowering.h - Target Lowering Info -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source 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. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETLOWERING_H +#define LLVM_TARGET_TARGETLOWERING_H + +#include "llvm/CodeGen/SelectionDAGNodes.h" +#include "llvm/CodeGen/RuntimeLibcalls.h" +#include <map> +#include <vector> + +namespace llvm { + class Value; + class Function; + class TargetMachine; + class TargetData; + class TargetRegisterClass; + class SDNode; + class SDOperand; + class SelectionDAG; + class MachineBasicBlock; + class MachineInstr; + class VectorType; + +//===----------------------------------------------------------------------===// +/// TargetLowering - 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: + /// LegalizeAction - 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. + Expand, // Try to expand this to other ops, otherwise use a libcall. + Custom // Use the LowerOperation hook to implement custom lowering. + }; + + enum OutOfRangeShiftAmount { + Undefined, // Oversized shift amounts are undefined (default). + Mask, // Shift amounts are auto masked (anded) to value size. + Extend // Oversized shift pulls in zeros or sign bits. + }; + + enum SetCCResultValue { + UndefinedSetCCResult, // SetCC returns a garbage/unknown extend. + ZeroOrOneSetCCResult, // SetCC returns a zero extended result. + ZeroOrNegativeOneSetCCResult // SetCC returns a sign extended result. + }; + + enum SchedPreference { + SchedulingForLatency, // Scheduling for shortest total latency. + SchedulingForRegPressure // Scheduling for lowest register pressure. + }; + + TargetLowering(TargetMachine &TM); + virtual ~TargetLowering(); + + TargetMachine &getTargetMachine() const { return TM; } + const TargetData *getTargetData() const { return TD; } + + bool isLittleEndian() const { return IsLittleEndian; } + MVT::ValueType getPointerTy() const { return PointerTy; } + MVT::ValueType getShiftAmountTy() const { return ShiftAmountTy; } + OutOfRangeShiftAmount getShiftAmountFlavor() const {return ShiftAmtHandling; } + + /// usesGlobalOffsetTable - Return true if this target uses a GOT for PIC + /// codegen. + bool usesGlobalOffsetTable() const { return UsesGlobalOffsetTable; } + + /// isSelectExpensive - Return true if the select operation is expensive for + /// this target. + bool isSelectExpensive() const { return SelectIsExpensive; } + + /// isIntDivCheap() - 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; } + + /// isPow2DivCheap() - Return true if pow2 div is cheaper than a chain of + /// srl/add/sra. + bool isPow2DivCheap() const { return Pow2DivIsCheap; } + + /// getSetCCResultTy - Return the ValueType of the result of setcc operations. + /// + MVT::ValueType getSetCCResultTy() const { return SetCCResultTy; } + + /// getSetCCResultContents - For targets without boolean registers, this flag + /// returns information about the contents of the high-bits in the setcc + /// result register. + SetCCResultValue getSetCCResultContents() const { return SetCCResultContents;} + + /// getSchedulingPreference - Return target scheduling preference. + SchedPreference getSchedulingPreference() const { + return SchedPreferenceInfo; + } + + /// getRegClassFor - Return the register class that should be used for the + /// specified value type. This may only be called on legal types. + TargetRegisterClass *getRegClassFor(MVT::ValueType VT) const { + assert(!MVT::isExtendedVT(VT)); + TargetRegisterClass *RC = RegClassForVT[VT]; + assert(RC && "This value type is not natively supported!"); + return RC; + } + + /// 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. + bool isTypeLegal(MVT::ValueType VT) const { + return !MVT::isExtendedVT(VT) && RegClassForVT[VT] != 0; + } + + class ValueTypeActionImpl { + /// ValueTypeActions - This is a bitvector that contains two bits for each + /// value type, where the two bits correspond to the LegalizeAction enum. + /// This can be queried with "getTypeAction(VT)". + uint32_t ValueTypeActions[2]; + public: + ValueTypeActionImpl() { + ValueTypeActions[0] = ValueTypeActions[1] = 0; + } + ValueTypeActionImpl(const ValueTypeActionImpl &RHS) { + ValueTypeActions[0] = RHS.ValueTypeActions[0]; + ValueTypeActions[1] = RHS.ValueTypeActions[1]; + } + + LegalizeAction getTypeAction(MVT::ValueType VT) const { + if (MVT::isExtendedVT(VT)) return Expand; + return (LegalizeAction)((ValueTypeActions[VT>>4] >> ((2*VT) & 31)) & 3); + } + void setTypeAction(MVT::ValueType VT, LegalizeAction Action) { + assert(!MVT::isExtendedVT(VT)); + assert(unsigned(VT >> 4) < + sizeof(ValueTypeActions)/sizeof(ValueTypeActions[0])); + ValueTypeActions[VT>>4] |= Action << ((VT*2) & 31); + } + }; + + const ValueTypeActionImpl &getValueTypeActions() const { + 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. + LegalizeAction getTypeAction(MVT::ValueType VT) const { + 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. + MVT::ValueType getTypeToTransformTo(MVT::ValueType VT) const { + if (MVT::isExtendedVT(VT)) + return MVT::getVectorType(MVT::getVectorElementType(VT), + MVT::getVectorNumElements(VT) / 2); + + return TransformToType[VT]; + } + + /// 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. + MVT::ValueType getTypeToExpandTo(MVT::ValueType VT) const { + assert(!MVT::isExtendedVT(VT)); + while (true) { + switch (getTypeAction(VT)) { + case Legal: + return VT; + case Expand: + VT = getTypeToTransformTo(VT); + break; + default: + assert(false && "Type is not legal nor is it to be expanded!"); + return VT; + } + } + return VT; + } + + /// getVectorTypeBreakdown - Vector types are broken down into some number of + /// legal first class types. For example, MVT::v8f32 maps to 2 MVT::v4f32 + /// with Altivec or SSE1, or 8 promoted MVT::f64 values with the X86 FP stack. + /// Similarly, MVT::v2i64 turns into 4 MVT::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(MVT::ValueType VT, + MVT::ValueType &IntermediateVT, + unsigned &NumIntermediates, + MVT::ValueType &RegisterVT) const; + + typedef std::vector<double>::const_iterator legal_fpimm_iterator; + legal_fpimm_iterator legal_fpimm_begin() const { + return LegalFPImmediates.begin(); + } + legal_fpimm_iterator legal_fpimm_end() const { + return LegalFPImmediates.end(); + } + + /// 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. + virtual bool isShuffleMaskLegal(SDOperand Mask, MVT::ValueType VT) const { + return true; + } + + /// 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. + virtual bool isVectorClearMaskLegal(std::vector<SDOperand> &BVOps, + MVT::ValueType EVT, + SelectionDAG &DAG) 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. + LegalizeAction getOperationAction(unsigned Op, MVT::ValueType VT) const { + if (MVT::isExtendedVT(VT)) return Expand; + return (LegalizeAction)((OpActions[Op] >> (2*VT)) & 3); + } + + /// isOperationLegal - Return true if the specified operation is legal on this + /// target. + bool isOperationLegal(unsigned Op, MVT::ValueType VT) const { + return getOperationAction(Op, VT) == Legal || + getOperationAction(Op, VT) == Custom; + } + + /// getLoadXAction - 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 getLoadXAction(unsigned LType, MVT::ValueType VT) const { + if (MVT::isExtendedVT(VT)) return Expand; + return (LegalizeAction)((LoadXActions[LType] >> (2*VT)) & 3); + } + + /// isLoadXLegal - Return true if the specified load with extension is legal + /// on this target. + bool isLoadXLegal(unsigned LType, MVT::ValueType VT) const { + return getLoadXAction(LType, VT) == Legal || + getLoadXAction(LType, VT) == Custom; + } + + /// getStoreXAction - 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 getStoreXAction(MVT::ValueType VT) const { + if (MVT::isExtendedVT(VT)) return Expand; + return (LegalizeAction)((StoreXActions >> (2*VT)) & 3); + } + + /// isStoreXLegal - Return true if the specified store with truncation is + /// legal on this target. + bool isStoreXLegal(MVT::ValueType VT) const { + return getStoreXAction(VT) == Legal || getStoreXAction(VT) == Custom; + } + + /// 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. + LegalizeAction + getIndexedLoadAction(unsigned IdxMode, MVT::ValueType VT) const { + if (MVT::isExtendedVT(VT)) return Expand; + return (LegalizeAction)((IndexedModeActions[0][IdxMode] >> (2*VT)) & 3); + } + + /// isIndexedLoadLegal - Return true if the specified indexed load is legal + /// on this target. + bool isIndexedLoadLegal(unsigned IdxMode, MVT::ValueType VT) const { + return getIndexedLoadAction(IdxMode, VT) == Legal || + getIndexedLoadAction(IdxMode, VT) == 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. + LegalizeAction + getIndexedStoreAction(unsigned IdxMode, MVT::ValueType VT) const { + if (MVT::isExtendedVT(VT)) return Expand; + return (LegalizeAction)((IndexedModeActions[1][IdxMode] >> (2*VT)) & 3); + } + + /// isIndexedStoreLegal - Return true if the specified indexed load is legal + /// on this target. + bool isIndexedStoreLegal(unsigned IdxMode, MVT::ValueType VT) const { + return getIndexedStoreAction(IdxMode, VT) == Legal || + getIndexedStoreAction(IdxMode, VT) == Custom; + } + + /// getTypeToPromoteTo - If the action for this operation is to promote, this + /// method returns the ValueType to promote to. + MVT::ValueType getTypeToPromoteTo(unsigned Op, MVT::ValueType VT) const { + assert(getOperationAction(Op, VT) == Promote && + "This operation isn't promoted!"); + + // See if this has an explicit type specified. + std::map<std::pair<unsigned, MVT::ValueType>, + MVT::ValueType>::const_iterator PTTI = + PromoteToType.find(std::make_pair(Op, VT)); + if (PTTI != PromoteToType.end()) return PTTI->second; + + assert((MVT::isInteger(VT) || MVT::isFloatingPoint(VT)) && + "Cannot autopromote this type, add it with AddPromotedToType."); + + MVT::ValueType NVT = VT; + do { + NVT = (MVT::ValueType)(NVT+1); + assert(MVT::isInteger(NVT) == MVT::isInteger(VT) && NVT != MVT::isVoid && + "Didn't find type to promote to!"); + } while (!isTypeLegal(NVT) || + getOperationAction(Op, NVT) == Promote); + return NVT; + } + + /// getValueType - Return the MVT::ValueType 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 MVT + /// counterpart (e.g. structs), otherwise it will assert. + MVT::ValueType getValueType(const Type *Ty, bool AllowUnknown = false) const { + MVT::ValueType VT = MVT::getValueType(Ty, AllowUnknown); + return VT == MVT::iPTR ? PointerTy : VT; + } + + /// getRegisterType - Return the type of registers that this ValueType will + /// eventually require. + MVT::ValueType getRegisterType(MVT::ValueType VT) const { + if (!MVT::isExtendedVT(VT)) + return RegisterTypeForVT[VT]; + + MVT::ValueType VT1, RegisterVT; + unsigned NumIntermediates; + (void)getVectorTypeBreakdown(VT, VT1, NumIntermediates, RegisterVT); + return RegisterVT; + } + + /// 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. + unsigned getNumRegisters(MVT::ValueType VT) const { + if (!MVT::isExtendedVT(VT)) + return NumRegistersForVT[VT]; + + MVT::ValueType VT1, VT2; + unsigned NumIntermediates; + return getVectorTypeBreakdown(VT, VT1, NumIntermediates, VT2); + } + + /// hasTargetDAGCombine - If true, the target has custom DAG combine + /// transformations that it can perform for the specified node. + bool hasTargetDAGCombine(ISD::NodeType NT) const { + return TargetDAGCombineArray[NT >> 3] & (1 << (NT&7)); + } + + /// 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. + /// @brief Get maximum # of store operations permitted for llvm.memset + unsigned getMaxStoresPerMemset() const { return maxStoresPerMemset; } + + /// 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. + /// @brief Get maximum # of store operations permitted for llvm.memcpy + unsigned getMaxStoresPerMemcpy() const { return maxStoresPerMemcpy; } + + /// 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. + /// @brief Get maximum # of store operations permitted for llvm.memmove + unsigned getMaxStoresPerMemmove() const { return maxStoresPerMemmove; } + + /// This function returns true if the target allows unaligned memory accesses. + /// This is used, 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 the target machine. + /// @brief Determine if the target supports unaligned memory accesses. + bool allowsUnalignedMemoryAccesses() const { + return allowUnalignedMemoryAccesses; + } + + /// usesUnderscoreSetJmp - 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. + bool usesUnderscoreLongJmp() const { + return UseUnderscoreLongJmp; + } + + /// getStackPointerRegisterToSaveRestore - If a physical register, this + /// specifies the register that llvm.savestack/llvm.restorestack should save + /// and restore. + unsigned getStackPointerRegisterToSaveRestore() const { + return StackPointerRegisterToSaveRestore; + } + + /// getExceptionAddressRegister - If a physical register, this returns + /// the register that receives the exception address on entry to a landing + /// pad. + unsigned getExceptionAddressRegister() const { + return ExceptionPointerRegister; + } + + /// getExceptionSelectorRegister - 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) + unsigned getJumpBufSize() const { + return JumpBufSize; + } + + /// getJumpBufAlignment - returns the target's jmp_buf alignment in bytes + /// (if never set, the default is 0) + unsigned getJumpBufAlignment() const { + return JumpBufAlignment; + } + + /// getIfCvtBlockLimit - returns the target specific if-conversion block size + /// limit. Any block whose size is greater should not be predicated. + virtual unsigned getIfCvtBlockSizeLimit() const { + return IfCvtBlockSizeLimit; + } + + /// getIfCvtDupBlockLimit - returns the target specific size limit for a + /// block to be considered for duplication. Any block whose size is greater + /// should not be duplicated to facilitate its predication. + virtual unsigned getIfCvtDupBlockSizeLimit() const { + return IfCvtDupBlockSizeLimit; + } + + /// 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. + virtual bool getPreIndexedAddressParts(SDNode *N, SDOperand &Base, + SDOperand &Offset, + ISD::MemIndexedMode &AM, + SelectionDAG &DAG) { + 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. + virtual bool getPostIndexedAddressParts(SDNode *N, SDNode *Op, + SDOperand &Base, SDOperand &Offset, + ISD::MemIndexedMode &AM, + SelectionDAG &DAG) { + return false; + } + + //===--------------------------------------------------------------------===// + // TargetLowering Optimization Methods + // + + /// TargetLoweringOpt - A convenience struct that encapsulates a DAG, and two + /// SDOperands for returning information from TargetLowering to its clients + /// that want to combine + struct TargetLoweringOpt { + SelectionDAG &DAG; + SDOperand Old; + SDOperand New; + + TargetLoweringOpt(SelectionDAG &InDAG) : DAG(InDAG) {} + + bool CombineTo(SDOperand O, SDOperand N) { + Old = O; + New = N; + 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. + bool ShrinkDemandedConstant(SDOperand Op, uint64_t Demanded); + }; + + /// 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. + bool SimplifyDemandedBits(SDOperand Op, uint64_t DemandedMask, + uint64_t &KnownZero, uint64_t &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. + virtual void computeMaskedBitsForTargetNode(const SDOperand Op, + uint64_t Mask, + uint64_t &KnownZero, + uint64_t &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. + virtual unsigned ComputeNumSignBitsForTargetNode(SDOperand Op, + unsigned Depth = 0) const; + + struct DAGCombinerInfo { + void *DC; // The DAG Combiner object. + bool BeforeLegalize; + bool CalledByLegalizer; + public: + SelectionDAG &DAG; + + DAGCombinerInfo(SelectionDAG &dag, bool bl, bool cl, void *dc) + : DC(dc), BeforeLegalize(bl), CalledByLegalizer(cl), DAG(dag) {} + + bool isBeforeLegalize() const { return BeforeLegalize; } + bool isCalledByLegalizer() const { return CalledByLegalizer; } + + void AddToWorklist(SDNode *N); + SDOperand CombineTo(SDNode *N, const std::vector<SDOperand> &To); + SDOperand CombineTo(SDNode *N, SDOperand Res); + SDOperand CombineTo(SDNode *N, SDOperand Res0, SDOperand Res1); + }; + + /// SimplifySetCC - Try to simplify a setcc built with the specified operands + /// and cc. If it is unable to simplify it, return a null SDOperand. + SDOperand SimplifySetCC(MVT::ValueType VT, SDOperand N0, SDOperand N1, + ISD::CondCode Cond, bool foldBooleans, + DAGCombinerInfo &DCI) 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. + /// + /// The semantics are as follows: + /// Return Value: + /// SDOperand.Val == 0 - No change was made + /// SDOperand.Val == N - N was replaced, is dead, and is already handled. + /// otherwise - N should be replaced by the returned Operand. + /// + /// In addition, methods provided by DAGCombinerInfo may be used to perform + /// more complex transformations. + /// + virtual SDOperand PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const; + + //===--------------------------------------------------------------------===// + // TargetLowering Configuration Methods - These methods should be invoked by + // the derived class constructor to configure this object for the target. + // + +protected: + /// setUsesGlobalOffsetTable - Specify that this target does or doesn't use a + /// GOT for PC-relative code. + void setUsesGlobalOffsetTable(bool V) { UsesGlobalOffsetTable = V; } + + /// setShiftAmountType - Describe the type that should be used for shift + /// amounts. This type defaults to the pointer type. + void setShiftAmountType(MVT::ValueType VT) { ShiftAmountTy = VT; } + + /// setSetCCResultType - Describe the type that shoudl be used as the result + /// of a setcc operation. This defaults to the pointer type. + void setSetCCResultType(MVT::ValueType VT) { SetCCResultTy = VT; } + + /// setSetCCResultContents - Specify how the target extends the result of a + /// setcc operation in a register. + void setSetCCResultContents(SetCCResultValue Ty) { SetCCResultContents = Ty; } + + /// setSchedulingPreference - Specify the target scheduling preference. + void setSchedulingPreference(SchedPreference Pref) { + SchedPreferenceInfo = Pref; + } + + /// setShiftAmountFlavor - Describe how the target handles out of range shift + /// amounts. + void setShiftAmountFlavor(OutOfRangeShiftAmount OORSA) { + ShiftAmtHandling = OORSA; + } + + /// setUseUnderscoreSetJmp - 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. + void setUseUnderscoreLongJmp(bool Val) { + UseUnderscoreLongJmp = Val; + } + + /// setStackPointerRegisterToSaveRestore - 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. + 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. + void setExceptionSelectorRegister(unsigned R) { + ExceptionSelectorRegister = R; + } + + /// SelectIsExpensive - Tells the code generator not to expand operations + /// into sequences that use the select operations if possible. + void setSelectIsExpensive() { SelectIsExpensive = true; } + + /// 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. + void setIntDivIsCheap(bool isCheap = true) { IntDivIsCheap = isCheap; } + + /// 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. + 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. + void addRegisterClass(MVT::ValueType VT, TargetRegisterClass *RC) { + assert(!MVT::isExtendedVT(VT)); + AvailableRegClasses.push_back(std::make_pair(VT, RC)); + RegClassForVT[VT] = RC; + } + + /// computeRegisterProperties - 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. + void setOperationAction(unsigned Op, MVT::ValueType VT, + LegalizeAction Action) { + assert(VT < 32 && Op < sizeof(OpActions)/sizeof(OpActions[0]) && + "Table isn't big enough!"); + OpActions[Op] &= ~(uint64_t(3UL) << VT*2); + OpActions[Op] |= (uint64_t)Action << VT*2; + } + + /// setLoadXAction - Indicate that the specified load with extension does not + /// work with the with specified type and indicate what to do about it. + void setLoadXAction(unsigned ExtType, MVT::ValueType VT, + LegalizeAction Action) { + assert(VT < 32 && ExtType < sizeof(LoadXActions)/sizeof(LoadXActions[0]) && + "Table isn't big enough!"); + LoadXActions[ExtType] &= ~(uint64_t(3UL) << VT*2); + LoadXActions[ExtType] |= (uint64_t)Action << VT*2; + } + + /// setStoreXAction - Indicate that the specified store with truncation does + /// not work with the with specified type and indicate what to do about it. + void setStoreXAction(MVT::ValueType VT, LegalizeAction Action) { + assert(VT < 32 && "Table isn't big enough!"); + StoreXActions &= ~(uint64_t(3UL) << VT*2); + StoreXActions |= (uint64_t)Action << VT*2; + } + + /// setIndexedLoadAction - Indicate that the specified indexed load does or + /// does not work with the with 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::ValueType VT, + LegalizeAction Action) { + assert(VT < 32 && IdxMode < + sizeof(IndexedModeActions[0]) / sizeof(IndexedModeActions[0][0]) && + "Table isn't big enough!"); + IndexedModeActions[0][IdxMode] &= ~(uint64_t(3UL) << VT*2); + IndexedModeActions[0][IdxMode] |= (uint64_t)Action << VT*2; + } + + /// setIndexedStoreAction - Indicate that the specified indexed store does or + /// does not work with the with 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::ValueType VT, + LegalizeAction Action) { + assert(VT < 32 && IdxMode < + sizeof(IndexedModeActions[1]) / sizeof(IndexedModeActions[1][0]) && + "Table isn't big enough!"); + IndexedModeActions[1][IdxMode] &= ~(uint64_t(3UL) << VT*2); + IndexedModeActions[1][IdxMode] |= (uint64_t)Action << VT*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. + void AddPromotedToType(unsigned Opc, MVT::ValueType OrigVT, + MVT::ValueType DestVT) { + PromoteToType[std::make_pair(Opc, OrigVT)] = DestVT; + } + + /// addLegalFPImmediate - Indicate that this target can instruction select + /// the specified FP immediate natively. + void addLegalFPImmediate(double Imm) { + LegalFPImmediates.push_back(Imm); + } + + /// 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. + void setTargetDAGCombine(ISD::NodeType NT) { + TargetDAGCombineArray[NT >> 3] |= 1 << (NT&7); + } + + /// setJumpBufSize - 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 + void setJumpBufAlignment(unsigned Align) { + JumpBufAlignment = Align; + } + + /// setIfCvtBlockSizeLimit - Set the target's if-conversion block size + /// limit (in number of instructions); default is 2. + void setIfCvtBlockSizeLimit(unsigned Limit) { + IfCvtBlockSizeLimit = Limit; + } + + /// setIfCvtDupBlockSizeLimit - Set the target's block size limit (in number + /// of instructions) to be considered for code duplication during + /// if-conversion; default is 2. + void setIfCvtDupBlockSizeLimit(unsigned Limit) { + IfCvtDupBlockSizeLimit = Limit; + } + +public: + + //===--------------------------------------------------------------------===// + // Lowering methods - These methods must be implemented by targets so that + // the SelectionDAGLowering code knows how to lower these. + // + + /// LowerArguments - This hook must be implemented to indicate how we should + /// lower the arguments for the specified function, into the specified DAG. + virtual std::vector<SDOperand> + LowerArguments(Function &F, SelectionDAG &DAG); + + /// LowerCallTo - This hook 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. + struct ArgListEntry { + SDOperand Node; + const Type* Ty; + bool isSExt; + bool isZExt; + bool isInReg; + bool isSRet; + + ArgListEntry():isSExt(false), isZExt(false), isInReg(false), isSRet(false) { }; + }; + typedef std::vector<ArgListEntry> ArgListTy; + virtual std::pair<SDOperand, SDOperand> + LowerCallTo(SDOperand Chain, const Type *RetTy, bool RetTyIsSigned, + bool isVarArg, unsigned CallingConv, bool isTailCall, + SDOperand Callee, ArgListTy &Args, SelectionDAG &DAG); + + /// 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. + virtual SDOperand LowerOperation(SDOperand Op, SelectionDAG &DAG); + + /// CustomPromoteOperation - This callback is invoked for operations that are + /// unsupported by the target, are registered to use 'custom' lowering, and + /// whose type needs to be promoted. + virtual SDOperand CustomPromoteOperation(SDOperand Op, SelectionDAG &DAG); + + /// getTargetNodeName() - This method returns the name of a target specific + /// DAG node. + virtual const char *getTargetNodeName(unsigned Opcode) const; + + //===--------------------------------------------------------------------===// + // Inline Asm Support hooks + // + + enum ConstraintType { + C_Register, // Constraint represents a single register. + C_RegisterClass, // Constraint represents one or more registers. + C_Memory, // Memory constraint. + C_Other, // Something else. + C_Unknown // Unsupported constraint. + }; + + /// getConstraintType - Given a constraint, return the type of constraint it + /// is for this target. + virtual ConstraintType getConstraintType(const std::string &Constraint) const; + + + /// getRegClassForInlineAsmConstraint - Given a constraint letter (e.g. "r"), + /// return a list of registers that can be used to satisfy the constraint. + /// This should only be used for C_RegisterClass constraints. + virtual std::vector<unsigned> + getRegClassForInlineAsmConstraint(const std::string &Constraint, + MVT::ValueType VT) const; + + /// getRegForInlineAsmConstraint - 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.. + virtual std::pair<unsigned, const TargetRegisterClass*> + getRegForInlineAsmConstraint(const std::string &Constraint, + MVT::ValueType VT) const; + + + /// isOperandValidForConstraint - Return the specified operand (possibly + /// modified) if the specified SDOperand is valid for the specified target + /// constraint letter, otherwise return null. + virtual SDOperand + isOperandValidForConstraint(SDOperand Op, char ConstraintLetter, + SelectionDAG &DAG); + + //===--------------------------------------------------------------------===// + // Scheduler hooks + // + + // InsertAtEndOfBasicBlock - This method should be implemented by targets that + // mark instructions with the 'usesCustomDAGSchedInserter' 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 the scheduler passes ownership of it to this method. + virtual MachineBasicBlock *InsertAtEndOfBasicBlock(MachineInstr *MI, + MachineBasicBlock *MBB); + + //===--------------------------------------------------------------------===// + // Addressing mode description hooks (used by LSR etc). + // + + /// AddrMode - 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; + bool HasBaseReg; + int64_t Scale; + 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. + /// TODO: Handle pre/postinc as well. + virtual bool isLegalAddressingMode(const AddrMode &AM, const Type *Ty) const; + + //===--------------------------------------------------------------------===// + // Div utility functions + // + SDOperand BuildSDIV(SDNode *N, SelectionDAG &DAG, + std::vector<SDNode*>* Created) const; + SDOperand BuildUDIV(SDNode *N, SelectionDAG &DAG, + std::vector<SDNode*>* Created) const; + + + //===--------------------------------------------------------------------===// + // Runtime Library hooks + // + + /// setLibcallName - 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. + /// + 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. + 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. + ISD::CondCode getCmpLibcallCC(RTLIB::Libcall Call) const { + return CmpLibcallCCs[Call]; + } + +private: + TargetMachine &TM; + const TargetData *TD; + + /// IsLittleEndian - True if this is a little endian target. + /// + bool IsLittleEndian; + + /// PointerTy - The type to use for pointers, usually i32 or i64. + /// + MVT::ValueType PointerTy; + + /// UsesGlobalOffsetTable - True if this target uses a GOT for PIC codegen. + /// + bool UsesGlobalOffsetTable; + + /// ShiftAmountTy - The type to use for shift amounts, usually i8 or whatever + /// PointerTy is. + MVT::ValueType ShiftAmountTy; + + OutOfRangeShiftAmount ShiftAmtHandling; + + /// SelectIsExpensive - 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. + bool IntDivIsCheap; + + /// 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. + bool Pow2DivIsCheap; + + /// SetCCResultTy - The type that SetCC operations use. This defaults to the + /// PointerTy. + MVT::ValueType SetCCResultTy; + + /// SetCCResultContents - Information about the contents of the high-bits in + /// the result of a setcc comparison operation. + SetCCResultValue SetCCResultContents; + + /// SchedPreferenceInfo - The target scheduling preference: shortest possible + /// total cycles or lowest register usage. + SchedPreference SchedPreferenceInfo; + + /// UseUnderscoreSetJmp - 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. + bool UseUnderscoreLongJmp; + + /// JumpBufSize - 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 + unsigned JumpBufAlignment; + + /// IfCvtBlockSizeLimit - The maximum allowed size for a block to be + /// if-converted. + unsigned IfCvtBlockSizeLimit; + + /// IfCvtDupBlockSizeLimit - The maximum allowed size for a block to be + /// duplicated during if-conversion. + unsigned IfCvtDupBlockSizeLimit; + + /// StackPointerRegisterToSaveRestore - 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. + unsigned ExceptionPointerRegister; + + /// ExceptionSelectorRegister - 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. + TargetRegisterClass *RegClassForVT[MVT::LAST_VALUETYPE]; + unsigned char NumRegistersForVT[MVT::LAST_VALUETYPE]; + MVT::ValueType RegisterTypeForVT[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). + MVT::ValueType 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 + /// operations that are not should be described. Note that operations on + /// non-legal value types are not described here. + uint64_t OpActions[156]; + + /// LoadXActions - For each load of load extension type and each value type, + /// keep a LegalizeAction that indicates how instruction selection should deal + /// with the load. + uint64_t LoadXActions[ISD::LAST_LOADX_TYPE]; + + /// StoreXActions - For each store with truncation of each value type, keep a + /// LegalizeAction that indicates how instruction selection should deal with + /// the store. + uint64_t StoreXActions; + + /// 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. + uint64_t IndexedModeActions[2][ISD::LAST_INDEXED_MODE]; + + ValueTypeActionImpl ValueTypeActions; + + std::vector<double> LegalFPImmediates; + + std::vector<std::pair<MVT::ValueType, + 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. + unsigned char TargetDAGCombineArray[156/(sizeof(unsigned char)*8)]; + + /// 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. + /// + /// Targets add entries to this map with AddPromotedToType(..), clients access + /// this with getTypeToPromoteTo(..). + std::map<std::pair<unsigned, MVT::ValueType>, MVT::ValueType> PromoteToType; + + /// LibcallRoutineNames - 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. + ISD::CondCode CmpLibcallCCs[RTLIB::UNKNOWN_LIBCALL]; + +protected: + /// 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 + /// should assume that the memset will be done using as many of the largest + /// store operations first, followed by smaller ones, if necessary, per + /// 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; + + /// 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 + /// should assume that the memcpy will be done using as many of the largest + /// store operations first, followed by smaller ones, if necessary, per + /// alignment restrictions. For example, storing 7 bytes on a 32-bit machine + /// 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; + + /// 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 + /// should assume that the memmove will be done using as many of the largest + /// store operations first, followed by smaller ones, if necessary, per + /// 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; + + /// This field specifies whether the target machine permits unaligned memory + /// accesses. This is used, for example, to determine the size of store + /// operations when copying small arrays and other similar tasks. + /// @brief Indicate whether the target permits unaligned memory accesses. + bool allowUnalignedMemoryAccesses; +}; +} // end llvm namespace + +#endif diff --git a/include/llvm/Target/TargetMachOWriterInfo.h b/include/llvm/Target/TargetMachOWriterInfo.h new file mode 100644 index 0000000..b37b454 --- /dev/null +++ b/include/llvm/Target/TargetMachOWriterInfo.h @@ -0,0 +1,112 @@ +//===-- llvm/Target/TargetMachOWriterInfo.h - MachO Writer Info--*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Bill Wendling and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the TargetMachOWriterInfo class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETMACHOWRITERINFO_H +#define LLVM_TARGET_TARGETMACHOWRITERINFO_H + +#include "llvm/CodeGen/MachineRelocation.h" + +namespace llvm { + + class MachineBasicBlock; + class OutputBuffer; + + //===--------------------------------------------------------------------===// + // TargetMachOWriterInfo + //===--------------------------------------------------------------------===// + + class TargetMachOWriterInfo { + uint32_t CPUType; // CPU specifier + uint32_t CPUSubType; // Machine specifier + public: + // The various CPU_TYPE_* constants are already defined by at least one + // system header file and create compilation errors if not respected. +#if !defined(CPU_TYPE_I386) +#define CPU_TYPE_I386 7 +#endif +#if !defined(CPU_TYPE_X86_64) +#define CPU_TYPE_X86_64 (CPU_TYPE_I386 | 0x1000000) +#endif +#if !defined(CPU_TYPE_ARM) +#define CPU_TYPE_ARM 12 +#endif +#if !defined(CPU_TYPE_SPARC) +#define CPU_TYPE_SPARC 14 +#endif +#if !defined(CPU_TYPE_POWERPC) +#define CPU_TYPE_POWERPC 18 +#endif +#if !defined(CPU_TYPE_POWERPC64) +#define CPU_TYPE_POWERPC64 (CPU_TYPE_POWERPC | 0x1000000) +#endif + + // Constants for the cputype field + // see <mach/machine.h> + enum { + HDR_CPU_TYPE_I386 = CPU_TYPE_I386, + HDR_CPU_TYPE_X86_64 = CPU_TYPE_X86_64, + HDR_CPU_TYPE_ARM = CPU_TYPE_ARM, + HDR_CPU_TYPE_SPARC = CPU_TYPE_SPARC, + HDR_CPU_TYPE_POWERPC = CPU_TYPE_POWERPC, + HDR_CPU_TYPE_POWERPC64 = CPU_TYPE_POWERPC64 + }; + +#if !defined(CPU_SUBTYPE_I386_ALL) +#define CPU_SUBTYPE_I386_ALL 3 +#endif +#if !defined(CPU_SUBTYPE_X86_64_ALL) +#define CPU_SUBTYPE_X86_64_ALL 3 +#endif +#if !defined(CPU_SUBTYPE_ARM_ALL) +#define CPU_SUBTYPE_ARM_ALL 0 +#endif +#if !defined(CPU_SUBTYPE_SPARC_ALL) +#define CPU_SUBTYPE_SPARC_ALL 0 +#endif +#if !defined(CPU_SUBTYPE_POWERPC_ALL) +#define CPU_SUBTYPE_POWERPC_ALL 0 +#endif + + // Constants for the cpusubtype field + // see <mach/machine.h> + enum { + HDR_CPU_SUBTYPE_I386_ALL = CPU_SUBTYPE_I386_ALL, + HDR_CPU_SUBTYPE_X86_64_ALL = CPU_SUBTYPE_X86_64_ALL, + HDR_CPU_SUBTYPE_ARM_ALL = CPU_SUBTYPE_ARM_ALL, + HDR_CPU_SUBTYPE_SPARC_ALL = CPU_SUBTYPE_SPARC_ALL, + HDR_CPU_SUBTYPE_POWERPC_ALL = CPU_SUBTYPE_POWERPC_ALL + }; + + TargetMachOWriterInfo(uint32_t cputype, uint32_t cpusubtype) + : CPUType(cputype), CPUSubType(cpusubtype) {} + virtual ~TargetMachOWriterInfo(); + + virtual MachineRelocation GetJTRelocation(unsigned Offset, + MachineBasicBlock *MBB) const; + + virtual unsigned GetTargetRelocation(MachineRelocation &MR, + unsigned FromIdx, + unsigned ToAddr, + unsigned ToIdx, + OutputBuffer &RelocOut, + OutputBuffer &SecOut, + bool Scattered, + bool Extern) const { return 0; } + + uint32_t getCPUType() const { return CPUType; } + uint32_t getCPUSubType() const { return CPUSubType; } + }; + +} // end llvm namespace + +#endif // LLVM_TARGET_TARGETMACHOWRITERINFO_H diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h new file mode 100644 index 0000000..e7f211b --- /dev/null +++ b/include/llvm/Target/TargetMachine.h @@ -0,0 +1,330 @@ +//===-- llvm/Target/TargetMachine.h - Target Information --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the TargetMachine and LLVMTargetMachine classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETMACHINE_H +#define LLVM_TARGET_TARGETMACHINE_H + +#include "llvm/Target/TargetInstrItineraries.h" +#include <cassert> +#include <string> + +namespace llvm { + +class TargetAsmInfo; +class TargetData; +class TargetSubtarget; +class TargetInstrInfo; +class TargetInstrDescriptor; +class TargetJITInfo; +class TargetLowering; +class TargetFrameInfo; +class MachineCodeEmitter; +class MRegisterInfo; +class Module; +class FunctionPassManager; +class PassManager; +class Pass; +class TargetMachOWriterInfo; +class TargetELFWriterInfo; + +// Relocation model types. +namespace Reloc { + enum Model { + Default, + Static, + PIC_, // Cannot be named PIC due to collision with -DPIC + DynamicNoPIC + }; +} + +// Code model types. +namespace CodeModel { + enum Model { + Default, + Small, + Kernel, + Medium, + Large + }; +} + +namespace FileModel { + enum Model { + Error, + None, + AsmFile, + MachOFile, + ElfFile + }; +} + +//===----------------------------------------------------------------------===// +/// +/// TargetMachine - Primary interface to the complete machine description for +/// the target machine. All target-specific information should be accessible +/// through this interface. +/// +class TargetMachine { + TargetMachine(const TargetMachine &); // DO NOT IMPLEMENT + void operator=(const TargetMachine &); // DO NOT IMPLEMENT +protected: // Can only create subclasses. + TargetMachine() : AsmInfo(NULL) { } + + /// getSubtargetImpl - virtual method implemented by subclasses that returns + /// a reference to that target's TargetSubtarget-derived member variable. + virtual const TargetSubtarget *getSubtargetImpl() const { return 0; } + + /// AsmInfo - Contains target specific asm information. + /// + mutable const TargetAsmInfo *AsmInfo; + + /// createTargetAsmInfo - Create a new instance of target specific asm + /// information. + virtual const TargetAsmInfo *createTargetAsmInfo() const { return NULL; } + +public: + virtual ~TargetMachine(); + + /// getModuleMatchQuality - This static method should be implemented by + /// targets to indicate how closely they match the specified module. This is + /// used by the LLC tool to determine which target to use when an explicit + /// -march option is not specified. If a target returns zero, it will never + /// be chosen without an explicit -march option. + static unsigned getModuleMatchQuality(const Module &M) { return 0; } + + /// getJITMatchQuality - This static method should be implemented by targets + /// that provide JIT capabilities to indicate how suitable they are for + /// execution on the current host. If a value of 0 is returned, the target + /// will not be used unless an explicit -march option is used. + static unsigned getJITMatchQuality() { return 0; } + + // 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 + // + virtual const TargetInstrInfo *getInstrInfo() const { return 0; } + virtual const TargetFrameInfo *getFrameInfo() const { return 0; } + virtual TargetLowering *getTargetLowering() const { return 0; } + virtual const TargetData *getTargetData() const { return 0; } + + + /// getTargetAsmInfo - Return target specific asm information. + /// + const TargetAsmInfo *getTargetAsmInfo() const { + if (!AsmInfo) AsmInfo = createTargetAsmInfo(); + return AsmInfo; + } + + /// getSubtarget - This method returns a pointer to the specified type of + /// TargetSubtarget. In debug builds, it verifies that the object being + /// returned is of the correct type. + template<typename STC> const STC &getSubtarget() const { + const TargetSubtarget *TST = getSubtargetImpl(); + assert(TST && dynamic_cast<const STC*>(TST) && + "Not the right kind of subtarget!"); + return *static_cast<const STC*>(TST); + } + + /// getRegisterInfo - If register information is available, return it. If + /// not, return null. This is kept separate from RegInfo until RegInfo has + /// details of graph coloring register allocation removed from it. + /// + virtual const MRegisterInfo *getRegisterInfo() const { return 0; } + + /// getJITInfo - If this target supports a JIT, return information for it, + /// otherwise return null. + /// + virtual TargetJITInfo *getJITInfo() { return 0; } + + /// getInstrItineraryData - Returns instruction itinerary data for the target + /// or specific subtarget. + /// + virtual const InstrItineraryData getInstrItineraryData() const { + return InstrItineraryData(); + } + + /// getMachOWriterInfo - If this target supports a Mach-O writer, return + /// information for it, otherwise return null. + /// + virtual const TargetMachOWriterInfo *getMachOWriterInfo() const { return 0; } + + /// getELFWriterInfo - If this target supports an ELF writer, return + /// information for it, otherwise return null. + /// + virtual const TargetELFWriterInfo *getELFWriterInfo() const { return 0; } + + /// getRelocationModel - Returns the code generation relocation model. The + /// choices are static, PIC, and dynamic-no-pic, and target default. + static Reloc::Model getRelocationModel(); + + /// setRelocationModel - Sets the code generation relocation model. + static void setRelocationModel(Reloc::Model Model); + + /// getCodeModel - Returns the code model. The choices are small, kernel, + /// medium, large, and target default. + static CodeModel::Model getCodeModel(); + + /// setCodeModel - Sets the code model. + static void setCodeModel(CodeModel::Model Model); + + /// CodeGenFileType - These enums are meant to be passed into + /// addPassesToEmitFile to indicate what type of file to emit. + enum CodeGenFileType { + AssemblyFile, ObjectFile, DynamicLibrary + }; + + /// getEnableTailMergeDefault - the default setting for -enable-tail-merge + /// on this target. User flag overrides. + virtual const bool getEnableTailMergeDefault() const { return true; } + + /// addPassesToEmitFile - Add passes to the specified pass manager to get the + /// specified file emitted. Typically this will involve several steps of code + /// generation. If Fast is set to true, the code generator should emit code + /// as fast as possible, without regard for compile time. This method should + /// return FileModel::Error if emission of this file type is not supported. + /// + virtual FileModel::Model addPassesToEmitFile(FunctionPassManager &PM, + std::ostream &Out, + CodeGenFileType FileType, + bool Fast) { + return FileModel::None; + } + + /// addPassesToEmitFileFinish - If the passes to emit the specified file had + /// to be split up (e.g., to add an object writer pass), this method can be + /// used to finish up adding passes to emit the file, if necessary. + /// + virtual bool addPassesToEmitFileFinish(FunctionPassManager &PM, + MachineCodeEmitter *MCE, bool Fast) { + return true; + } + + /// addPassesToEmitMachineCode - Add passes to the specified pass manager to + /// get machine code emitted. This uses a MachineCodeEmitter object to handle + /// actually outputting the machine code and resolving things like the address + /// of functions. This method returns true if machine code emission is + /// not supported. + /// + virtual bool addPassesToEmitMachineCode(FunctionPassManager &PM, + MachineCodeEmitter &MCE, bool Fast) { + return true; + } + + /// addPassesToEmitWholeFile - This method can be implemented by targets that + /// require having the entire module at once. This is not recommended, do not + /// use this. + virtual bool WantsWholeFile() const { return false; } + virtual bool addPassesToEmitWholeFile(PassManager &PM, std::ostream &Out, + CodeGenFileType FileType, bool Fast) { + return true; + } +}; + +/// LLVMTargetMachine - This class describes a target machine that is +/// implemented with the LLVM target-independent code generator. +/// +class LLVMTargetMachine : public TargetMachine { +protected: // Can only create subclasses. + LLVMTargetMachine() { } +public: + + /// addPassesToEmitFile - Add passes to the specified pass manager to get the + /// specified file emitted. Typically this will involve several steps of code + /// generation. If Fast is set to true, the code generator should emit code + /// as fast as possible, without regard for compile time. This method should + /// return FileModel::Error if emission of this file type is not supported. + /// + /// The default implementation of this method adds components from the + /// LLVM retargetable code generator, invoking the methods below to get + /// target-specific passes in standard locations. + /// + virtual FileModel::Model addPassesToEmitFile(FunctionPassManager &PM, + std::ostream &Out, + CodeGenFileType FileType, + bool Fast); + + /// addPassesToEmitFileFinish - If the passes to emit the specified file had + /// to be split up (e.g., to add an object writer pass), this method can be + /// used to finish up adding passes to emit the file, if necessary. + /// + virtual bool addPassesToEmitFileFinish(FunctionPassManager &PM, + MachineCodeEmitter *MCE, bool Fast); + + /// addPassesToEmitMachineCode - Add passes to the specified pass manager to + /// get machine code emitted. This uses a MachineCodeEmitter object to handle + /// actually outputting the machine code and resolving things like the address + /// of functions. This method returns true if machine code emission is + /// not supported. + /// + virtual bool addPassesToEmitMachineCode(FunctionPassManager &PM, + MachineCodeEmitter &MCE, bool Fast); + + /// Target-Independent Code Generator Pass Configuration Options. + + /// addInstSelector - This method should add any "last minute" LLVM->LLVM + /// passes, then install an instruction selector pass, which converts from + /// LLVM code to machine instructions. + virtual bool addInstSelector(FunctionPassManager &PM, bool Fast) { + return true; + } + + /// addPostRegAllocPasses - This method may be implemented by targets that + /// want to run passes after register allocation but before prolog-epilog + /// insertion. This should return true if -print-machineinstrs should print + /// after these passes. + virtual bool addPostRegAlloc(FunctionPassManager &PM, bool Fast) { + return false; + } + + /// addPreEmitPass - This pass may be implemented by targets that want to run + /// passes immediately before machine code is emitted. This should return + /// true if -print-machineinstrs should print out the code after the passes. + virtual bool addPreEmitPass(FunctionPassManager &PM, bool Fast) { + return false; + } + + + /// addAssemblyEmitter - This pass should be overridden by the target to add + /// the asmprinter, if asm emission is supported. If this is not supported, + /// 'true' should be returned. + virtual bool addAssemblyEmitter(FunctionPassManager &PM, bool Fast, + std::ostream &Out) { + return true; + } + + /// addCodeEmitter - This pass should be overridden by the target to add a + /// code emitter, if supported. If this is not supported, 'true' should be + /// returned. + virtual bool addCodeEmitter(FunctionPassManager &PM, bool Fast, + MachineCodeEmitter &MCE) { + return true; + } + + /// addSimpleCodeEmitter - This pass should be overridden by the target to add + /// a code emitter (without setting flags), if supported. If this is not + /// supported, 'true' should be returned. + virtual bool addSimpleCodeEmitter(FunctionPassManager &PM, bool Fast, + MachineCodeEmitter &MCE) { + return true; + } + + /// getEnableTailMergeDefault - the default setting for -enable-tail-merge + /// on this target. User flag overrides. + virtual const bool getEnableTailMergeDefault() const { return true; } +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Target/TargetMachineRegistry.h b/include/llvm/Target/TargetMachineRegistry.h new file mode 100644 index 0000000..dd3ed7d --- /dev/null +++ b/include/llvm/Target/TargetMachineRegistry.h @@ -0,0 +1,128 @@ +//===-- Target/TargetMachineRegistry.h - Target Registration ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes two classes: the TargetMachineRegistry class, which allows +// tools to inspect all of registered targets, and the RegisterTarget class, +// which TargetMachine implementations should use to register themselves with +// the system. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETMACHINEREGISTRY_H +#define LLVM_TARGET_TARGETMACHINEREGISTRY_H + +#include "llvm/Support/CommandLine.h" + +namespace llvm { + class Module; + class TargetMachine; + + struct TargetMachineRegistry { + struct Entry; + + /// TargetMachineRegistry::getList - This static method returns the list of + /// target machines that are registered with the system. + static const Entry *getList() { return List; } + + /// getClosestStaticTargetForModule - Given an LLVM module, pick the best + /// target that is compatible with the module. If no close target can be + /// found, this returns null and sets the Error string to a reason. + static const Entry *getClosestStaticTargetForModule(const Module &M, + std::string &Error); + + /// getClosestTargetForJIT - Given an LLVM module, pick the best target that + /// is compatible with the current host and the specified module. If no + /// close target can be found, this returns null and sets the Error string + /// to a reason. + static const Entry *getClosestTargetForJIT(std::string &Error); + + + /// Entry - One instance of this struct is created for each target that is + /// registered. + struct Entry { + const char *Name; + const char *ShortDesc; + TargetMachine *(*CtorFn)(const Module &, const std::string &); + unsigned (*ModuleMatchQualityFn)(const Module &M); + unsigned (*JITMatchQualityFn)(); + + const Entry *getNext() const { return Next; } + + protected: + Entry(const char *N, const char *SD, + TargetMachine *(*CF)(const Module &, const std::string &), + unsigned (*MMF)(const Module &M), unsigned (*JMF)()); + private: + const Entry *Next; // Next entry in the linked list. + }; + + private: + static const Entry *List; + }; + + //===--------------------------------------------------------------------===// + /// RegisterTarget - This class is used to make targets automatically register + /// themselves with the tool they are linked. Targets should define an + /// instance of this and implement the static methods described in the + /// TargetMachine comments. + /// The type 'TargetMachineImpl' should provide a constructor with two + /// parameters: + /// - const Module& M: the module that is being compiled: + /// - const std::string& FS: target-specific string describing target + /// flavour. + + template<class TargetMachineImpl> + struct RegisterTarget : public TargetMachineRegistry::Entry { + RegisterTarget(const char *Name, const char *ShortDesc) : + TargetMachineRegistry::Entry(Name, ShortDesc, &Allocator, + &TargetMachineImpl::getModuleMatchQuality, + &TargetMachineImpl::getJITMatchQuality) { + } + private: + static TargetMachine *Allocator(const Module &M, const std::string &FS) { + return new TargetMachineImpl(M, FS); + } + }; + + /// TargetRegistrationListener - This class allows code to listen for targets + /// that are dynamically registered, and be notified of it when they are. + class TargetRegistrationListener { + TargetRegistrationListener **Prev, *Next; + public: + TargetRegistrationListener(); + virtual ~TargetRegistrationListener(); + + TargetRegistrationListener *getNext() const { return Next; } + + virtual void targetRegistered(const TargetMachineRegistry::Entry *E) = 0; + }; + + + //===--------------------------------------------------------------------===// + /// TargetNameParser - This option can be used to provide a command line + /// option to choose among the various registered targets (commonly -march). + class TargetNameParser : public TargetRegistrationListener, + public cl::parser<const TargetMachineRegistry::Entry*> { + public: + void initialize(cl::Option &O) { + for (const TargetMachineRegistry::Entry *E = + TargetMachineRegistry::getList(); E; E = E->getNext()) + Values.push_back(std::make_pair(E->Name, + std::make_pair(E, E->ShortDesc))); + cl::parser<const TargetMachineRegistry::Entry*>::initialize(O); + } + + virtual void targetRegistered(const TargetMachineRegistry::Entry *E) { + Values.push_back(std::make_pair(E->Name, + std::make_pair(E, E->ShortDesc))); + } + }; +} + +#endif diff --git a/include/llvm/Target/TargetOptions.h b/include/llvm/Target/TargetOptions.h new file mode 100644 index 0000000..76f2d55 --- /dev/null +++ b/include/llvm/Target/TargetOptions.h @@ -0,0 +1,79 @@ +//===-- llvm/Target/TargetOptions.h - Target Options ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines command line option flags that are shared across various +// targets. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETOPTIONS_H +#define LLVM_TARGET_TARGETOPTIONS_H + +namespace llvm { + /// PrintMachineCode - This flag is enabled when the -print-machineinstrs + /// option is specified on the command line, and should enable debugging + /// output from the code generator. + extern bool PrintMachineCode; + + /// NoFramePointerElim - This flag is enabled when the -disable-fp-elim is + /// specified on the command line. If the target supports the frame pointer + /// elimination optimization, this option should disable it. + extern bool NoFramePointerElim; + + /// NoExcessFPPrecision - This flag is enabled when the + /// -disable-excess-fp-precision flag is specified on the command line. When + /// this flag is off (the default), the code generator is allowed to produce + /// results that are "more precise" than IEEE allows. This includes use of + /// FMA-like operations and use of the X86 FP registers without rounding all + /// over the place. + extern bool NoExcessFPPrecision; + + /// UnsafeFPMath - This flag is enabled when the + /// -enable-unsafe-fp-math flag is specified on the command line. When + /// this flag is off (the default), the code generator is not allowed to + /// produce results that are "less precise" than IEEE allows. This includes + /// use of X86 instructions like FSIN and FCOS instead of libcalls. + /// UnsafeFPMath implies FiniteOnlyFPMath. + extern bool UnsafeFPMath; + + /// FiniteOnlyFPMath - This returns true when the -enable-finite-only-fp-math + /// option is specified on the command line. If this returns false (default), + /// the code generator is not allowed to assume that FP arithmetic arguments + /// and results are never NaNs or +-Infs. + extern bool FiniteOnlyFPMathOption; + extern bool FiniteOnlyFPMath(); + + /// HonorSignDependentRoundingFPMath - This returns true when the + /// -enable-sign-dependent-rounding-fp-math is specified. If this returns + /// false (the default), the code generator is allowed to assume that the + /// rounding behavior is the default (round-to-zero for all floating point to + /// integer conversions, and round-to-nearest for all other arithmetic + /// truncations). If this is enabled (set to true), the code generator must + /// assume that the rounding mode may dynamically change. + extern bool HonorSignDependentRoundingFPMathOption; + extern bool HonorSignDependentRoundingFPMath(); + + /// UseSoftFloat - This flag is enabled when the -soft-float flag is specified + /// on the command line. When this flag is on, the code generator will + /// generate libcalls to the software floating point library instead of + /// target FP instructions. + extern bool UseSoftFloat; + + /// NoZerosInBSS - By default some codegens place zero-initialized data to + /// .bss section. This flag disables such behaviour (necessary, e.g. for + /// crt*.o compiling). + extern bool NoZerosInBSS; + + /// ExceptionHandling - This flag indicates that exception information should + /// be emitted. + extern bool ExceptionHandling; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Target/TargetSubtarget.h b/include/llvm/Target/TargetSubtarget.h new file mode 100644 index 0000000..3b174c2 --- /dev/null +++ b/include/llvm/Target/TargetSubtarget.h @@ -0,0 +1,36 @@ +//==-- llvm/Target/TargetSubtarget.h - Target Information --------*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Nate Begeman and is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file describes the subtarget options of a Target machine. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TARGET_TARGETSUBTARGET_H +#define LLVM_TARGET_TARGETSUBTARGET_H + +namespace llvm { + +//===----------------------------------------------------------------------===// +/// +/// TargetSubtarget - Generic base class for all target subtargets. All +/// Target-specific options that control code generation and printing should +/// be exposed through a TargetSubtarget-derived class. +/// +class TargetSubtarget { + TargetSubtarget(const TargetSubtarget&); // DO NOT IMPLEMENT + void operator=(const TargetSubtarget&); // DO NOT IMPLEMENT +protected: // Can only create subclasses... + TargetSubtarget(); +public: + virtual ~TargetSubtarget(); +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Transforms/IPO.h b/include/llvm/Transforms/IPO.h new file mode 100644 index 0000000..6ab6d7b --- /dev/null +++ b/include/llvm/Transforms/IPO.h @@ -0,0 +1,173 @@ +//===- llvm/Transforms/IPO.h - Interprocedural Transformations --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file defines prototypes for accessor functions that expose passes +// in the IPO transformations library. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_IPO_H +#define LLVM_TRANSFORMS_IPO_H + +#include <vector> + +namespace llvm { + +class FunctionPass; +class ModulePass; +class Pass; +class Function; +class BasicBlock; + +//===----------------------------------------------------------------------===// +// +// These functions removes symbols from functions and modules. If OnlyDebugInfo +// is true, only debugging information is removed from the module. +// +ModulePass *createStripSymbolsPass(bool OnlyDebugInfo = false); + +//===----------------------------------------------------------------------===// +/// createLowerSetJmpPass - This function lowers the setjmp/longjmp intrinsics +/// to invoke/unwind instructions. This should really be part of the C/C++ +/// front-end, but it's so much easier to write transformations in LLVM proper. +/// +ModulePass* createLowerSetJmpPass(); + +//===----------------------------------------------------------------------===// +/// createConstantMergePass - This function returns a new pass that merges +/// duplicate global constants together into a single constant that is shared. +/// This is useful because some passes (ie TraceValues) insert a lot of string +/// constants into the program, regardless of whether or not they duplicate an +/// existing string. +/// +ModulePass *createConstantMergePass(); + + +//===----------------------------------------------------------------------===// +/// createGlobalOptimizerPass - This function returns a new pass that optimizes +/// non-address taken internal globals. +/// +ModulePass *createGlobalOptimizerPass(); + + +//===----------------------------------------------------------------------===// +/// createRaiseAllocationsPass - Return a new pass that transforms malloc and +/// free function calls into malloc and free instructions. +/// +ModulePass *createRaiseAllocationsPass(); + + +//===----------------------------------------------------------------------===// +/// createDeadTypeEliminationPass - Return a new pass that eliminates symbol +/// table entries for types that are never used. +/// +ModulePass *createDeadTypeEliminationPass(); + + +//===----------------------------------------------------------------------===// +/// createGlobalDCEPass - This transform is designed to eliminate unreachable +/// internal globals (functions or global variables) +/// +ModulePass *createGlobalDCEPass(); + + +//===----------------------------------------------------------------------===// +/// createFunctionExtractionPass - If deleteFn is true, this pass deletes as +/// the specified function. Otherwise, it deletes as much of the module as +/// possible, except for the function specified. +/// +ModulePass *createFunctionExtractionPass(Function *F, bool deleteFn = false, + bool relinkCallees = false); + + +//===----------------------------------------------------------------------===// +/// createFunctionInliningPass - Return a new pass object that uses a heuristic +/// to inline direct function calls to small functions. +/// +Pass *createFunctionInliningPass(); + +//===----------------------------------------------------------------------===// +/// createPruneEHPass - Return a new pass object which transforms invoke +/// instructions into calls, if the callee can _not_ unwind the stack. +/// +Pass *createPruneEHPass(); + +//===----------------------------------------------------------------------===// +/// createInternalizePass - This pass loops over all of the functions in the +/// input module, looking for a main function. If a list of symbols is +/// specified with the -internalize-public-api-* command line options, those +/// symbols are internalized. Otherwise if InternalizeEverything is set and +/// the main function is found, all other globals are marked as internal. +/// +ModulePass *createInternalizePass(bool InternalizeEverything); +ModulePass *createInternalizePass(const std::vector<const char *> &exportList); + +//===----------------------------------------------------------------------===// +/// createDeadArgEliminationPass - This pass removes arguments from functions +/// which are not used by the body of the function. +/// +ModulePass *createDeadArgEliminationPass(); + +/// DeadArgHacking pass - Same as DAE, but delete arguments of external +/// functions as well. This is definitely not safe, and should only be used by +/// bugpoint. +ModulePass *createDeadArgHackingPass(); + +//===----------------------------------------------------------------------===// +/// createArgumentPromotionPass - This pass promotes "by reference" arguments to +/// be passed by value. +/// +Pass *createArgumentPromotionPass(); + +//===----------------------------------------------------------------------===// +/// createIPConstantPropagationPass - This pass propagates constants from call +/// sites into the bodies of functions. +/// +ModulePass *createIPConstantPropagationPass(); + +//===----------------------------------------------------------------------===// +/// createIPSCCPPass - This pass propagates constants from call sites into the +/// bodies of functions, and keeps track of whether basic blocks are executable +/// in the process. +/// +ModulePass *createIPSCCPPass(); + +//===----------------------------------------------------------------------===// +// +/// createLoopExtractorPass - This pass extracts all natural loops from the +/// program into a function if it can. +/// +FunctionPass *createLoopExtractorPass(); + +/// createSingleLoopExtractorPass - This pass extracts one natural loop from the +/// program into a function if it can. This is used by bugpoint. +/// +FunctionPass *createSingleLoopExtractorPass(); + +/// createBlockExtractorPass - This pass extracts all blocks (except those +/// specified in the argument list) from the functions in the module. +/// +ModulePass *createBlockExtractorPass(std::vector<BasicBlock*> &BTNE); + +/// createOptimizeWellKnownCallsPass - This pass optimizes specific calls to +/// specific well-known (library) functions. +ModulePass *createSimplifyLibCallsPass(); + + +/// createIndMemRemPass - This pass removes potential indirect calls of +/// malloc and free +ModulePass *createIndMemRemPass(); + +/// createStripDeadPrototypesPass - This pass removes any function declarations +/// (prototypes) that are not used. +ModulePass *createStripDeadPrototypesPass(); + +} // End llvm namespace + +#endif diff --git a/include/llvm/Transforms/IPO/InlinerPass.h b/include/llvm/Transforms/IPO/InlinerPass.h new file mode 100644 index 0000000..01f1aff --- /dev/null +++ b/include/llvm/Transforms/IPO/InlinerPass.h @@ -0,0 +1,64 @@ +//===- InlinerPass.h - Code common to all inliners --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines a simple policy-based bottom-up inliner. This file +// implements all of the boring mechanics of the bottom-up inlining, while the +// subclass determines WHAT to inline, which is the much more interesting +// component. +// +//===----------------------------------------------------------------------===// + +#ifndef INLINER_H +#define INLINER_H + +#include "llvm/CallGraphSCCPass.h" + +namespace llvm { + class CallSite; + +/// Inliner - This class contains all of the helper code which is used to +/// perform the inlining operations that does not depend on the policy. +/// +struct Inliner : public CallGraphSCCPass { + Inliner(const void *ID); + + /// getAnalysisUsage - For this class, we declare that we require and preserve + /// the call graph. If the derived class implements this method, it should + /// always explicitly call the implementation here. + virtual void getAnalysisUsage(AnalysisUsage &Info) const; + + // Main run interface method, this implements the interface required by the + // Pass class. + virtual bool runOnSCC(const std::vector<CallGraphNode *> &SCC); + + // doFinalization - Remove now-dead linkonce functions at the end of + // processing to avoid breaking the SCC traversal. + virtual bool doFinalization(CallGraph &CG); + + + /// This method returns the value specified by the -inline-threshold value, + /// specified on the command line. This is typically not directly needed. + /// + unsigned getInlineThreshold() const { return InlineThreshold; } + + /// getInlineCost - This method must be implemented by the subclass to + /// determine the cost of inlining the specified call site. If the cost + /// returned is greater than the current inline threshold, the call site is + /// not inlined. + /// + virtual int getInlineCost(CallSite CS) = 0; + +private: + // InlineThreshold - Cache the value here for easy access. + unsigned InlineThreshold; +}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/Transforms/Instrumentation.h b/include/llvm/Transforms/Instrumentation.h new file mode 100644 index 0000000..82e4676 --- /dev/null +++ b/include/llvm/Transforms/Instrumentation.h @@ -0,0 +1,37 @@ +//===- Transforms/Instrumentation.h - Instrumentation passes ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This files defines constructor functions for instrumentation passes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_INSTRUMENTATION_H +#define LLVM_TRANSFORMS_INSTRUMENTATION_H + +namespace llvm { + +class ModulePass; +class FunctionPass; + +// Insert function profiling instrumentation +ModulePass *createFunctionProfilerPass(); + +// Insert block profiling instrumentation +ModulePass *createBlockProfilerPass(); + +// Insert edge profiling instrumentation +ModulePass *createEdgeProfilerPass(); + +// Random Sampling Profiling Framework +ModulePass* createNullProfilerRSPass(); +FunctionPass* createRSProfilingPass(); + +} // End llvm namespace + +#endif diff --git a/include/llvm/Transforms/RSProfiling.h b/include/llvm/Transforms/RSProfiling.h new file mode 100644 index 0000000..b5cb302 --- /dev/null +++ b/include/llvm/Transforms/RSProfiling.h @@ -0,0 +1,33 @@ +//===- RSProfiling.cpp - Various profiling using random sampling ----------===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the abstract interface that a profiler must implement to +// support the random profiling transform. +// +//===----------------------------------------------------------------------===// + +namespace llvm { + //===--------------------------------------------------------------------===// + /// RSProfilers - The basic Random Sampling Profiler Interface Any profiler + /// that implements this interface can be transformed by the random sampling + /// pass to be sample based rather than always on. + /// + /// The only exposed function can be queried to find out if an instruction + /// was original or if it was inserted by the profiler. Implementations of + /// this interface are expected to chain to other implementations, such that + /// multiple profilers can be support simultaniously. + struct RSProfilers : public ModulePass { + static char ID; // Pass identification, replacement for typeinfo + RSProfilers() : ModulePass((intptr_t)&ID) {} + + /// isProfiling - This method returns true if the value passed it was + /// inserted by the profiler. + virtual bool isProfiling(Value* v) = 0; + }; +} diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h new file mode 100644 index 0000000..4fea3f7 --- /dev/null +++ b/include/llvm/Transforms/Scalar.h @@ -0,0 +1,341 @@ +//===-- Scalar.h - Scalar Transformations -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header file defines prototypes for accessor functions that expose passes +// in the Scalar transformations library. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_SCALAR_H +#define LLVM_TRANSFORMS_SCALAR_H + +#include <cstdlib> + +namespace llvm { + +class FunctionPass; +class LoopPass; +class Pass; +class GetElementPtrInst; +class PassInfo; +class TerminatorInst; +class TargetLowering; + +//===----------------------------------------------------------------------===// +// +// ConstantPropagation - A worklist driven constant propagation pass +// +FunctionPass *createConstantPropagationPass(); + +//===----------------------------------------------------------------------===// +// +// SCCP - Sparse conditional constant propagation. +// +FunctionPass *createSCCPPass(); + +//===----------------------------------------------------------------------===// +// +// DeadInstElimination - This pass quickly removes trivially dead instructions +// without modifying the CFG of the function. It is a BasicBlockPass, so it +// runs efficiently when queued next to other BasicBlockPass's. +// +Pass *createDeadInstEliminationPass(); + +//===----------------------------------------------------------------------===// +// +// DeadCodeElimination - This pass is more powerful than DeadInstElimination, +// because it is worklist driven that can potentially revisit instructions when +// their other instructions become dead, to eliminate chains of dead +// computations. +// +FunctionPass *createDeadCodeEliminationPass(); + +//===----------------------------------------------------------------------===// +// +// DeadStoreElimination - This pass deletes stores that are post-dominated by +// must-aliased stores and are not loaded used between the stores. +// +FunctionPass *createDeadStoreEliminationPass(); + +//===----------------------------------------------------------------------===// +// +// AggressiveDCE - This pass uses the SSA based Aggressive DCE algorithm. This +// algorithm assumes instructions are dead until proven otherwise, which makes +// it more successful are removing non-obviously dead instructions. +// +FunctionPass *createAggressiveDCEPass(); + +//===----------------------------------------------------------------------===// +// +// ScalarReplAggregates - Break up alloca's of aggregates into multiple allocas +// if possible. +// +FunctionPass *createScalarReplAggregatesPass(signed Threshold = -1); + +//===----------------------------------------------------------------------===// +// +// GCSE - This pass is designed to be a very quick global transformation that +// eliminates global common subexpressions from a function. It does this by +// examining the SSA value graph of the function, instead of doing slow +// bit-vector computations. +// +FunctionPass *createGCSEPass(); + +//===----------------------------------------------------------------------===// +// +// InductionVariableSimplify - Transform induction variables in a program to all +// use a single canonical induction variable per loop. +// +LoopPass *createIndVarSimplifyPass(); + +//===----------------------------------------------------------------------===// +// +// InstructionCombining - Combine instructions to form fewer, simple +// instructions. This pass does not modify the CFG, and has a tendency to make +// instructions dead, so a subsequent DCE pass is useful. +// +// This pass combines things like: +// %Y = add int 1, %X +// %Z = add int 1, %Y +// into: +// %Z = add int 2, %X +// +FunctionPass *createInstructionCombiningPass(); + +//===----------------------------------------------------------------------===// +// +// LICM - This pass is a loop invariant code motion and memory promotion pass. +// +LoopPass *createLICMPass(); + +//===----------------------------------------------------------------------===// +// +// LoopStrengthReduce - This pass is strength reduces GEP instructions that use +// a loop's canonical induction variable as one of their indices. It takes an +// optional parameter used to consult the target machine whether certain +// transformations are profitable. +// +LoopPass *createLoopStrengthReducePass(const TargetLowering *TLI = 0); + +//===----------------------------------------------------------------------===// +// +// LoopUnswitch - This pass is a simple loop unswitching pass. +// +LoopPass *createLoopUnswitchPass(bool OptimizeForSize = false); + +//===----------------------------------------------------------------------===// +// +// LoopUnroll - This pass is a simple loop unrolling pass. +// +LoopPass *createLoopUnrollPass(); + +//===----------------------------------------------------------------------===// +// +// LoopRotate - This pass is a simple loop rotating pass. +// +LoopPass *createLoopRotatePass(); + + +//===----------------------------------------------------------------------===// +// +// PromoteMemoryToRegister - This pass is used to promote memory references to +// be register references. A simple example of the transformation performed by +// this pass is: +// +// FROM CODE TO CODE +// %X = alloca int, uint 1 ret int 42 +// store int 42, int *%X +// %Y = load int* %X +// ret int %Y +// +FunctionPass *createPromoteMemoryToRegisterPass(); +extern const PassInfo *PromoteMemoryToRegisterID; + +//===----------------------------------------------------------------------===// +// +// DemoteRegisterToMemoryPass - This pass is used to demote registers to memory +// references. In basically undoes the PromoteMemoryToRegister pass to make cfg +// hacking easier. +// +FunctionPass *createDemoteRegisterToMemoryPass(); +extern const PassInfo *DemoteRegisterToMemoryID; + +//===----------------------------------------------------------------------===// +// +// Reassociate - This pass reassociates commutative expressions in an order that +// is designed to promote better constant propagation, GCSE, LICM, PRE... +// +// For example: 4 + (x + 5) -> x + (4 + 5) +// +FunctionPass *createReassociatePass(); + +//===----------------------------------------------------------------------===// +// +// CorrelatedExpressionElimination - This pass eliminates correlated +// conditions, such as these: +// if (X == 0) +// if (X > 2) ; // Known false +// else +// Y = X * Z; // = 0 +// +FunctionPass *createCorrelatedExpressionEliminationPass(); + +//===----------------------------------------------------------------------===// +// +// CondPropagationPass - This pass propagates information about conditional +// expressions through the program, allowing it to eliminate conditional +// branches in some cases. +// +FunctionPass *createCondPropagationPass(); + +//===----------------------------------------------------------------------===// +// +// TailDuplication - Eliminate unconditional branches through controlled code +// duplication, creating simpler CFG structures. +// +FunctionPass *createTailDuplicationPass(); + +//===----------------------------------------------------------------------===// +// +// CFGSimplification - Merge basic blocks, eliminate unreachable blocks, +// simplify terminator instructions, etc... +// +FunctionPass *createCFGSimplificationPass(); + +//===----------------------------------------------------------------------===// +// +// 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: +// +// AU.addRequiredID(BreakCriticalEdgesID); +// +// This pass obviously invalidates the CFG, but can update forward dominator +// (set, immediate dominators, tree, and frontier) information. +// +FunctionPass *createBreakCriticalEdgesPass(); +extern const PassInfo *BreakCriticalEdgesID; + +//===----------------------------------------------------------------------===// +// +// LoopSimplify - Insert Pre-header blocks into the CFG for every function in +// the module. This pass updates dominator information, loop information, and +// does not add critical edges to the CFG. +// +// AU.addRequiredID(LoopSimplifyID); +// +FunctionPass *createLoopSimplifyPass(); +extern const PassInfo *LoopSimplifyID; + +//===----------------------------------------------------------------------===// +// +// LowerSelect - This pass converts SelectInst instructions into conditional +// branch and PHI instructions. If the OnlyFP flag is set to true, then only +// floating point select instructions are lowered. +// +FunctionPass *createLowerSelectPass(bool OnlyFP = false); +extern const PassInfo *LowerSelectID; + +//===----------------------------------------------------------------------===// +// +// LowerAllocations - Turn malloc and free instructions into %malloc and %free +// calls. +// +// AU.addRequiredID(LowerAllocationsID); +// +Pass *createLowerAllocationsPass(bool LowerMallocArgToInteger = false); +extern const PassInfo *LowerAllocationsID; + +//===----------------------------------------------------------------------===// +// +// TailCallElimination - This pass eliminates call instructions to the current +// function which occur immediately before return instructions. +// +FunctionPass *createTailCallEliminationPass(); + +//===----------------------------------------------------------------------===// +// +// LowerSwitch - This pass converts SwitchInst instructions into a sequence of +// chained binary branch instructions. +// +FunctionPass *createLowerSwitchPass(); +extern const PassInfo *LowerSwitchID; + +//===----------------------------------------------------------------------===// +// +// LowerPacked - This pass converts VectorType operations into low-level scalar +// operations. +// +FunctionPass *createLowerPackedPass(); + +//===----------------------------------------------------------------------===// +// +// LowerInvoke - This pass converts invoke and unwind instructions to use sjlj +// exception handling mechanisms. Note that after this pass runs the CFG is not +// entirely accurate (exceptional control flow edges are not correct anymore) so +// only very simple things should be done after the lowerinvoke pass has run +// (like generation of native code). This should *NOT* be used as a general +// purpose "my LLVM-to-LLVM pass doesn't support the invoke instruction yet" +// lowering pass. +// +FunctionPass *createLowerInvokePass(const TargetLowering *TLI = NULL); +extern const PassInfo *LowerInvokePassID; + +//===----------------------------------------------------------------------===// +// +// LowerGCPass - This function returns an instance of the "lowergc" pass, which +// lowers garbage collection intrinsics to normal LLVM code. +// +FunctionPass *createLowerGCPass(); + +//===----------------------------------------------------------------------===// +// +// BlockPlacement - This pass reorders basic blocks in order to increase the +// number of fall-through conditional branches. +// +FunctionPass *createBlockPlacementPass(); + +//===----------------------------------------------------------------------===// +// +// LCSSA - This pass inserts phi nodes at loop boundaries to simplify other loop +// optimizations. +// +LoopPass *createLCSSAPass(); +extern const PassInfo *LCSSAID; + +//===----------------------------------------------------------------------===// +// +// PredicateSimplifier - This pass collapses duplicate variables into one +// canonical form, and tries to simplify expressions along the way. +// +FunctionPass *createPredicateSimplifierPass(); + +//===----------------------------------------------------------------------===// +// +// GVN-PRE - This pass performs global value numbering and partial redundancy +// elimination. +// +FunctionPass *createGVNPREPass(); + +//===----------------------------------------------------------------------===// +// +// FastDeadStoreElimination - This pass deletes stores that are post-dominated by +// must-aliased stores and are not loaded used between the stores. +// +FunctionPass *createFastDeadStoreEliminationPass(); + +//===----------------------------------------------------------------------===// +// +// CodeGenPrepare - This pass prepares a function for instruction selection. +// +FunctionPass *createCodeGenPreparePass(const TargetLowering *TLI = 0); + +} // End llvm namespace + +#endif diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h new file mode 100644 index 0000000..47bbcbe --- /dev/null +++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -0,0 +1,123 @@ +//===-- Transform/Utils/BasicBlockUtils.h - BasicBlock Utils ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of functions perform manipulations on basic blocks, and +// instructions contained within basic blocks. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_BASICBLOCK_H +#define LLVM_TRANSFORMS_UTILS_BASICBLOCK_H + +// FIXME: Move to this file: BasicBlock::removePredecessor, BB::splitBasicBlock + +#include "llvm/BasicBlock.h" +#include "llvm/Support/CFG.h" + +namespace llvm { + +class Instruction; +class Pass; + +// ReplaceInstWithValue - Replace all uses of an instruction (specified by BI) +// with a value, then remove and delete the original instruction. +// +void ReplaceInstWithValue(BasicBlock::InstListType &BIL, + BasicBlock::iterator &BI, Value *V); + +// ReplaceInstWithInst - Replace the instruction specified by BI with the +// instruction specified by I. The original instruction is deleted and BI is +// updated to point to the new instruction. +// +void ReplaceInstWithInst(BasicBlock::InstListType &BIL, + BasicBlock::iterator &BI, Instruction *I); + +// ReplaceInstWithInst - Replace the instruction specified by From with the +// instruction specified by To. +// +void ReplaceInstWithInst(Instruction *From, Instruction *To); + + +// RemoveSuccessor - Change the specified terminator instruction such that its +// successor #SuccNum no longer exists. Because this reduces the outgoing +// degree of the current basic block, the actual terminator instruction itself +// may have to be changed. In the case where the last successor of the block is +// deleted, a return instruction is inserted in its place which can cause a +// suprising change in program behavior if it is not expected. +// +void RemoveSuccessor(TerminatorInst *TI, unsigned SuccNum); + +/// 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 will not invalidate +/// either of them. This returns true if the edge was split, false otherwise. +/// If MergeIdenticalEdges is true (the default), *all* edges from TI to the +/// specified successor will be merged into the same critical edge block. +/// This is most commonly interesting with switch instructions, which may +/// have many edges to any one destination. This ensures that all edges to that +/// dest go to one block instead of each going to a different block, but isn't +/// the standard definition of a "critical edge". +/// +bool SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P = 0, + bool MergeIdenticalEdges = false); + +inline bool SplitCriticalEdge(BasicBlock *BB, succ_iterator SI, Pass *P = 0) { + return SplitCriticalEdge(BB->getTerminator(), SI.getSuccessorIndex(), P); +} + +/// SplitCriticalEdge - If the edge from *PI to BB is not critical, return +/// false. Otherwise, split all edges between the two blocks and return true. +/// This updates all of the same analyses as the other SplitCriticalEdge +/// function. If P is specified, it updates the analyses +/// described above. +inline bool SplitCriticalEdge(BasicBlock *Succ, pred_iterator PI, Pass *P = 0) { + bool MadeChange = false; + TerminatorInst *TI = (*PI)->getTerminator(); + for (unsigned i = 0, e = TI->getNumSuccessors(); i != e; ++i) + if (TI->getSuccessor(i) == Succ) + MadeChange |= SplitCriticalEdge(TI, i, P); + return MadeChange; +} + +/// SplitCriticalEdge - If an edge from Src to Dst is critical, split the edge +/// and return true, otherwise return false. This method requires that there be +/// an edge between the two blocks. If P is specified, it updates the analyses +/// described above. +inline bool SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst, Pass *P = 0, + bool MergeIdenticalEdges = false) { + TerminatorInst *TI = Src->getTerminator(); + unsigned i = 0; + while (1) { + assert(i != TI->getNumSuccessors() && "Edge doesn't exist!"); + if (TI->getSuccessor(i) == Dst) + return SplitCriticalEdge(TI, i, P, MergeIdenticalEdges); + ++i; + } +} + +/// SplitEdge - Split the edge connecting specified block. Pass P must +/// not be NULL. +BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To, Pass *P); + +/// SplitBlock - Split the specified block at the specified instruction - every +/// thing before SplitPt stays in Old and everything starting with SplitPt moves +/// to a new block. The two blocks are joined by an unconditional branch and +/// the loop info is updated. +/// +BasicBlock *SplitBlock(BasicBlock *Old, Instruction *SplitPt, Pass *P); +} // End llvm namespace + +#endif diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h new file mode 100644 index 0000000..9f1aad7 --- /dev/null +++ b/include/llvm/Transforms/Utils/Cloning.h @@ -0,0 +1,181 @@ +//===- Cloning.h - Clone various parts of LLVM programs ---------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines various functions that are used to clone chunks of LLVM +// code for various purposes. This varies from copying whole modules into new +// modules, to cloning functions with different arguments, to inlining +// functions, to copying basic blocks to support loop unrolling or superblock +// formation, etc. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_CLONING_H +#define LLVM_TRANSFORMS_UTILS_CLONING_H + +#include <vector> +#include "llvm/ADT/DenseMap.h" + +namespace llvm { + +class Module; +class Function; +class BasicBlock; +class Value; +class CallInst; +class InvokeInst; +class ReturnInst; +class CallSite; +class Trace; +class CallGraph; +class TargetData; + +/// CloneModule - Return an exact copy of the specified module +/// +Module *CloneModule(const Module *M); +Module *CloneModule(const Module *M, DenseMap<const Value*, Value*> &ValueMap); + +/// ClonedCodeInfo - This struct can be used to capture information about code +/// being cloned, while it is being cloned. +struct ClonedCodeInfo { + /// ContainsCalls - This is set to true if the cloned code contains a normal + /// call instruction. + bool ContainsCalls; + + /// ContainsUnwinds - This is set to true if the cloned code contains an + /// unwind instruction. + bool ContainsUnwinds; + + /// ContainsDynamicAllocas - This is set to true if the cloned code contains + /// a 'dynamic' alloca. Dynamic allocas are allocas that are either not in + /// the entry block or they are in the entry block but are not a constant + /// size. + bool ContainsDynamicAllocas; + + ClonedCodeInfo() { + ContainsCalls = false; + ContainsUnwinds = false; + ContainsDynamicAllocas = false; + } +}; + + +/// CloneBasicBlock - Return a copy of the specified basic block, but without +/// embedding the block into a particular function. The block returned is an +/// exact copy of the specified basic block, without any remapping having been +/// performed. Because of this, this is only suitable for applications where +/// the basic block will be inserted into the same function that it was cloned +/// from (loop unrolling would use this, for example). +/// +/// Also, note that this function makes a direct copy of the basic block, and +/// can thus produce illegal LLVM code. In particular, it will copy any PHI +/// nodes from the original block, even though there are no predecessors for the +/// newly cloned block (thus, phi nodes will have to be updated). Also, this +/// block will branch to the old successors of the original block: these +/// successors will have to have any PHI nodes updated to account for the new +/// incoming edges. +/// +/// The correlation between instructions in the source and result basic blocks +/// is recorded in the ValueMap map. +/// +/// If you have a particular suffix you'd like to use to add to any cloned +/// names, specify it as the optional third parameter. +/// +/// If you would like the basic block to be auto-inserted into the end of a +/// function, you can specify it as the optional fourth parameter. +/// +/// If you would like to collect additional information about the cloned +/// function, you can specify a ClonedCodeInfo object with the optional fifth +/// parameter. +/// +BasicBlock *CloneBasicBlock(const BasicBlock *BB, + DenseMap<const Value*, Value*> &ValueMap, + const char *NameSuffix = "", Function *F = 0, + ClonedCodeInfo *CodeInfo = 0); + + +/// CloneFunction - Return a copy of the specified function, but without +/// embedding the function into another module. Also, any references specified +/// in the ValueMap are changed to refer to their mapped value instead of the +/// original one. If any of the arguments to the function are in the ValueMap, +/// the arguments are deleted from the resultant function. The ValueMap is +/// updated to include mappings from all of the instructions and basicblocks in +/// the function from their old to new values. The final argument captures +/// information about the cloned code if non-null. +/// +Function *CloneFunction(const Function *F, + DenseMap<const Value*, Value*> &ValueMap, + ClonedCodeInfo *CodeInfo = 0); + +/// CloneFunction - Version of the function that doesn't need the ValueMap. +/// +inline Function *CloneFunction(const Function *F, ClonedCodeInfo *CodeInfo = 0){ + DenseMap<const Value*, Value*> ValueMap; + return CloneFunction(F, ValueMap, CodeInfo); +} + +/// Clone OldFunc into NewFunc, transforming the old arguments into references +/// to ArgMap values. Note that if NewFunc already has basic blocks, the ones +/// cloned into it will be added to the end of the function. This function +/// fills in a list of return instructions, and can optionally append the +/// specified suffix to all values cloned. +/// +void CloneFunctionInto(Function *NewFunc, const Function *OldFunc, + DenseMap<const Value*, Value*> &ValueMap, + std::vector<ReturnInst*> &Returns, + const char *NameSuffix = "", + ClonedCodeInfo *CodeInfo = 0); + +/// CloneAndPruneFunctionInto - This works exactly like CloneFunctionInto, +/// except that it does some simple constant prop and DCE on the fly. The +/// effect of this is to copy significantly less code in cases where (for +/// example) a function call with constant arguments is inlined, and those +/// constant arguments cause a significant amount of code in the callee to be +/// dead. Since this doesn't produce an exactly copy of the input, it can't be +/// used for things like CloneFunction or CloneModule. +void CloneAndPruneFunctionInto(Function *NewFunc, const Function *OldFunc, + DenseMap<const Value*, Value*> &ValueMap, + std::vector<ReturnInst*> &Returns, + const char *NameSuffix = "", + ClonedCodeInfo *CodeInfo = 0, + const TargetData *TD = 0); + + +/// CloneTraceInto - Clone T into NewFunc. Original<->clone mapping is +/// saved in ValueMap. +/// +void CloneTraceInto(Function *NewFunc, Trace &T, + DenseMap<const Value*, Value*> &ValueMap, + const char *NameSuffix); + +/// CloneTrace - Returns a copy of the specified trace. +/// It takes a vector of basic blocks clones the basic blocks, removes internal +/// phi nodes, adds it to the same function as the original (although there is +/// no jump to it) and returns the new vector of basic blocks. +std::vector<BasicBlock *> CloneTrace(const std::vector<BasicBlock*> &origTrace); + +/// InlineFunction - This function inlines the called function into the basic +/// block of the caller. This returns false if it is not possible to inline +/// this call. The program is still in a well defined state if this occurs +/// though. +/// +/// Note that this only does one level of inlining. For example, if the +/// instruction 'call B' is inlined, and 'B' calls 'C', then the call to 'C' now +/// exists in the instruction stream. Similiarly this will inline a recursive +/// function by one level. +/// +/// If a non-null callgraph pointer is provided, these functions update the +/// CallGraph to represent the program after inlining. +/// +bool InlineFunction(CallInst *C, CallGraph *CG = 0, const TargetData *TD = 0); +bool InlineFunction(InvokeInst *II, CallGraph *CG = 0, const TargetData *TD =0); +bool InlineFunction(CallSite CS, CallGraph *CG = 0, const TargetData *TD = 0); + +} // End llvm namespace + +#endif diff --git a/include/llvm/Transforms/Utils/FunctionUtils.h b/include/llvm/Transforms/Utils/FunctionUtils.h new file mode 100644 index 0000000..cf8abdf --- /dev/null +++ b/include/llvm/Transforms/Utils/FunctionUtils.h @@ -0,0 +1,41 @@ +//===-- Transform/Utils/FunctionUtils.h - Function Utils --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of transformations manipulate LLVM functions. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_FUNCTION_H +#define LLVM_TRANSFORMS_UTILS_FUNCTION_H + +#include <llvm/Analysis/Dominators.h> +#include <vector> + +namespace llvm { + class BasicBlock; + class Function; + class Loop; + + /// ExtractCodeRegion - rip out a sequence of basic blocks into a new function + /// + Function* ExtractCodeRegion(DominatorTree& DT, + const std::vector<BasicBlock*> &code, + bool AggregateArgs = false); + + /// ExtractLoop - rip out a natural loop into a new function + /// + Function* ExtractLoop(DominatorTree& DT, Loop *L, + bool AggregateArgs = false); + + /// ExtractBasicBlock - rip out a basic block into a new function + /// + Function* ExtractBasicBlock(BasicBlock *BB, bool AggregateArgs = false); +} + +#endif diff --git a/include/llvm/Transforms/Utils/Local.h b/include/llvm/Transforms/Utils/Local.h new file mode 100644 index 0000000..c2b95db --- /dev/null +++ b/include/llvm/Transforms/Utils/Local.h @@ -0,0 +1,90 @@ +//===-- Local.h - Functions to perform local transformations ----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This family of functions perform various local transformations to the +// program. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_LOCAL_H +#define LLVM_TRANSFORMS_UTILS_LOCAL_H + +#include "llvm/Function.h" + +namespace llvm { + +class Pass; +class PHINode; +class AllocaInst; +class ConstantExpr; +class TargetData; + +//===----------------------------------------------------------------------===// +// Local constant propagation... +// + +/// doConstantPropagation - Constant prop a specific instruction. Returns true +/// and potentially moves the iterator if constant propagation was performed. +/// +bool doConstantPropagation(BasicBlock::iterator &I, const TargetData *TD = 0); + +/// ConstantFoldTerminator - If a terminator instruction is predicated on a +/// constant value, convert it into an unconditional branch to the constant +/// destination. This is a nontrivial operation because the successors of this +/// basic block must have their PHI nodes updated. +/// +bool ConstantFoldTerminator(BasicBlock *BB); + +//===----------------------------------------------------------------------===// +// Local dead code elimination... +// + +/// isInstructionTriviallyDead - Return true if the result produced by the +/// instruction is not used, and the instruction has no side effects. +/// +bool isInstructionTriviallyDead(Instruction *I); + + +/// dceInstruction - Inspect the instruction at *BBI and figure out if it +/// isTriviallyDead. If so, remove the instruction and update the iterator to +/// point to the instruction that immediately succeeded the original +/// instruction. +/// +bool dceInstruction(BasicBlock::iterator &BBI); + +//===----------------------------------------------------------------------===// +// Control Flow Graph Restructuring... +// + +/// SimplifyCFG - This function is used to do simplification of a CFG. For +/// example, it adjusts branches to branches to eliminate the extra hop, it +/// eliminates unreachable basic blocks, and does other "peephole" optimization +/// of the CFG. It returns true if a modification was made, possibly deleting +/// the basic block that was pointed to. +/// +/// WARNING: The entry node of a method may not be simplified. +/// +bool SimplifyCFG(BasicBlock *BB); + +/// DemoteRegToStack - This function takes a virtual register computed by an +/// Instruction and replaces it with a slot in the stack frame, allocated via +/// alloca. This allows the CFG to be changed around without fear of +/// invalidating the SSA information for the value. It returns the pointer to +/// the alloca inserted to create a stack slot for X. +/// +AllocaInst *DemoteRegToStack(Instruction &X, bool VolatileLoads = false); + +/// 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. +AllocaInst *DemotePHIToStack(PHINode *P); + +} // End llvm namespace + +#endif diff --git a/include/llvm/Transforms/Utils/PromoteMemToReg.h b/include/llvm/Transforms/Utils/PromoteMemToReg.h new file mode 100644 index 0000000..4e8bfeb --- /dev/null +++ b/include/llvm/Transforms/Utils/PromoteMemToReg.h @@ -0,0 +1,46 @@ +//===- PromoteMemToReg.h - Promote Allocas to Scalars -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file exposes an interface to promote alloca instructions to SSA +// registers, by using the SSA construction algorithm. +// +//===----------------------------------------------------------------------===// + +#ifndef TRANSFORMS_UTILS_PROMOTEMEMTOREG_H +#define TRANSFORMS_UTILS_PROMOTEMEMTOREG_H + +#include <vector> + +namespace llvm { + +class AllocaInst; +class DominatorTree; +class DominanceFrontier; +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... +/// +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. +/// +/// 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, DominanceFrontier &DF, + AliasSetTracker *AST = 0); + +} // End llvm namespace + +#endif diff --git a/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h new file mode 100644 index 0000000..1898c30 --- /dev/null +++ b/include/llvm/Transforms/Utils/UnifyFunctionExitNodes.h @@ -0,0 +1,55 @@ +//===-- UnifyFunctionExitNodes.h - Ensure fn's have one return --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass is used to ensure that functions have at most one return and one +// unwind instruction in them. Additionally, it keeps track of which node is +// the new exit node of the CFG. If there are no return or unwind instructions +// in the function, the getReturnBlock/getUnwindBlock methods will return a null +// pointer. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UNIFYFUNCTIONEXITNODES_H +#define LLVM_TRANSFORMS_UNIFYFUNCTIONEXITNODES_H + +#include "llvm/Pass.h" + +namespace llvm { + +struct UnifyFunctionExitNodes : public FunctionPass { + BasicBlock *ReturnBlock, *UnwindBlock, *UnreachableBlock; +public: + static char ID; // Pass identification, replacement for typeid + UnifyFunctionExitNodes() : FunctionPass((intptr_t)&ID), + ReturnBlock(0), UnwindBlock(0) {} + + // We can preserve non-critical-edgeness when we unify function exit nodes + virtual void getAnalysisUsage(AnalysisUsage &AU) const; + + // getReturn|Unwind|UnreachableBlock - Return the new single (or nonexistant) + // return, unwind, or unreachable basic blocks in the CFG. + // + BasicBlock *getReturnBlock() const { return ReturnBlock; } + BasicBlock *getUnwindBlock() const { return UnwindBlock; } + BasicBlock *getUnreachableBlock() const { return UnreachableBlock; } + + virtual bool runOnFunction(Function &F); + + // Force linking the impl of this class into anything that uses this header. + static int stub; +}; + +Pass *createUnifyFunctionExitNodesPass(); + +static IncludeFile +UNIFY_FUNCTION_EXIT_NODES_INCLUDE_FILE(&UnifyFunctionExitNodes::stub); + +} // End llvm namespace + +#endif diff --git a/include/llvm/Type.h b/include/llvm/Type.h new file mode 100644 index 0000000..cf1c64f --- /dev/null +++ b/include/llvm/Type.h @@ -0,0 +1,403 @@ +//===-- llvm/Type.h - Classes for handling data types -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#ifndef LLVM_TYPE_H +#define LLVM_TYPE_H + +#include "llvm/AbstractTypeUser.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/Support/Streams.h" +#include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/iterator" +#include <string> +#include <vector> + +namespace llvm { + +class DerivedType; +class PointerType; +class IntegerType; +class TypeMapBase; + +/// This file contains the declaration of the Type class. For more "Type" type +/// stuff, look in DerivedTypes.h. +/// +/// The instances of the Type class are immutable: once they are created, +/// they are never changed. Also note that only one instance of a particular +/// type is ever created. Thus seeing if two types are equal is a matter of +/// doing a trivial pointer comparison. To enforce that no two equal instances +/// are created, Type instances can only be created via static factory methods +/// in class Type and in derived classes. +/// +/// Once allocated, Types are never free'd, unless they are an abstract type +/// that is resolved to a more concrete type. +/// +/// Types themself don't have a name, and can be named either by: +/// - using SymbolTable instance, typically from some Module, +/// - using convenience methods in the Module class (which uses module's +/// SymbolTable too). +/// +/// Opaque types are simple derived types with no state. There may be many +/// different Opaque type objects floating around, but two are only considered +/// identical if they are pointer equals of each other. This allows us to have +/// two opaque types that end up resolving to different concrete types later. +/// +/// Opaque types are also kinda weird and scary and different because they have +/// to keep a list of uses of the type. When, through linking, parsing, or +/// bitcode reading, they become resolved, they need to find and update all +/// users of the unknown type, causing them to reference a new, more concrete +/// type. Opaque types are deleted when their use list dwindles to zero users. +/// +/// @brief Root of type hierarchy +class Type : public AbstractTypeUser { +public: + //===-------------------------------------------------------------------===// + /// Definitions of all of the base types for the Type system. Based on this + /// value, you can cast to a "DerivedType" subclass (see DerivedTypes.h) + /// Note: If you add an element to this, you need to add an element to the + /// Type::getPrimitiveType function, or else things will break! + /// + enum TypeID { + // PrimitiveTypes .. make sure LastPrimitiveTyID stays up to date + VoidTyID = 0, ///< 0: type with no size + FloatTyID, ///< 1: 32 bit floating point type + DoubleTyID, ///< 2: 64 bit floating point type + LabelTyID, ///< 3: Labels + + // Derived types... see DerivedTypes.h file... + // Make sure FirstDerivedTyID stays up to date!!! + IntegerTyID, ///< 4: Arbitrary bit width integers + FunctionTyID, ///< 5: Functions + StructTyID, ///< 6: Structures + PackedStructTyID,///< 7: Packed Structure. This is for bitcode only + ArrayTyID, ///< 8: Arrays + PointerTyID, ///< 9: Pointers + OpaqueTyID, ///< 10: Opaque: type with unknown structure + VectorTyID, ///< 11: SIMD 'packed' format, or other vector type + + NumTypeIDs, // Must remain as last defined ID + LastPrimitiveTyID = LabelTyID, + FirstDerivedTyID = IntegerTyID + }; + +private: + TypeID ID : 8; // The current base type of this type. + bool Abstract : 1; // True if type contains an OpaqueType + unsigned SubclassData : 23; //Space for subclasses to store data + + /// RefCount - This counts the number of PATypeHolders that are pointing to + /// this type. When this number falls to zero, if the type is abstract and + /// has no AbstractTypeUsers, the type is deleted. This is only sensical for + /// derived types. + /// + mutable unsigned RefCount; + + const Type *getForwardedTypeInternal() const; + + // Some Type instances are allocated as arrays, some aren't. So we provide + // this method to get the right kind of destruction for the type of Type. + void destroy() const; // const is a lie, this does "delete this"! + +protected: + explicit Type(TypeID id) : ID(id), Abstract(false), SubclassData(0), + RefCount(0), ForwardType(0), NumContainedTys(0), + ContainedTys(0) {} + virtual ~Type() { + assert(AbstractTypeUsers.empty() && "Abstract types remain"); + } + + /// Types can become nonabstract later, if they are refined. + /// + inline void setAbstract(bool Val) { Abstract = Val; } + + unsigned getRefCount() const { return RefCount; } + + unsigned getSubclassData() const { return SubclassData; } + void setSubclassData(unsigned val) { SubclassData = val; } + + /// ForwardType - This field is used to implement the union find scheme for + /// abstract types. When types are refined to other types, this field is set + /// to the more refined type. Only abstract types can be forwarded. + mutable const Type *ForwardType; + + + /// AbstractTypeUsers - Implement a list of the users that need to be notified + /// if I am a type, and I get resolved into a more concrete type. + /// + mutable std::vector<AbstractTypeUser *> AbstractTypeUsers; + + /// NumContainedTys - Keeps track of how many PATypeHandle instances there + /// are at the end of this type instance for the list of contained types. It + /// is the subclasses responsibility to set this up. Set to 0 if there are no + /// contained types in this type. + unsigned NumContainedTys; + + /// ContainedTys - A pointer to the array of Types (PATypeHandle) contained + /// by this Type. For example, this includes the arguments of a function + /// type, the elements of a structure, the pointee of a pointer, the element + /// type of an array, etc. This pointer may be 0 for types that don't + /// contain other types (Integer, Double, Float). In general, the subclass + /// should arrange for space for the PATypeHandles to be included in the + /// allocation of the type object and set this pointer to the address of the + /// first element. This allows the Type class to manipulate the ContainedTys + /// without understanding the subclass's placement for this array. keeping + /// it here also allows the subtype_* members to be implemented MUCH more + /// efficiently, and dynamically very few types do not contain any elements. + PATypeHandle *ContainedTys; + +public: + void print(std::ostream &O) const; + void print(std::ostream *O) const { if (O) print(*O); } + + /// @brief Debugging support: print to stderr + void dump() const; + + //===--------------------------------------------------------------------===// + // Property accessors for dealing with types... Some of these virtual methods + // are defined in private classes defined in Type.cpp for primitive types. + // + + /// getTypeID - Return the type id for the type. This will return one + /// of the TypeID enum elements defined above. + /// + inline TypeID getTypeID() const { return ID; } + + /// getDescription - Return the string representation of the type... + const std::string &getDescription() const; + + /// isInteger - True if this is an instance of IntegerType. + /// + bool isInteger() const { return ID == IntegerTyID; } + + /// isFloatingPoint - Return true if this is one of the two floating point + /// types + bool isFloatingPoint() const { return ID == FloatTyID || ID == DoubleTyID; } + + /// isFPOrFPVector - Return true if this is a FP type or a vector of FP types. + /// + bool isFPOrFPVector() const; + + /// isAbstract - True if the type is either an Opaque type, or is a derived + /// type that includes an opaque type somewhere in it. + /// + inline bool isAbstract() const { return Abstract; } + + /// canLosslesslyBitCastTo - Return true if this type could be converted + /// with a lossless BitCast to type 'Ty'. For example, uint to int. BitCasts + /// are valid for types of the same size only where no re-interpretation of + /// the bits is done. + /// @brief Determine if this type could be losslessly bitcast to Ty + bool canLosslesslyBitCastTo(const Type *Ty) const; + + + /// Here are some useful little methods to query what type derived types are + /// Note that all other types can just compare to see if this == Type::xxxTy; + /// + inline bool isPrimitiveType() const { return ID <= LastPrimitiveTyID; } + inline bool isDerivedType() const { return ID >= FirstDerivedTyID; } + + /// isFirstClassType - Return true if the value is holdable in a register. + /// + inline bool isFirstClassType() const { + return (ID != VoidTyID && ID <= LastPrimitiveTyID) || + ID == IntegerTyID || ID == PointerTyID || ID == VectorTyID; + } + + /// isSized - Return true if it makes sense to take the size of this type. To + /// get the actual size for a particular target, it is reasonable to use the + /// TargetData subsystem to do this. + /// + bool isSized() const { + // If it's a primitive, it is always sized. + if (ID == IntegerTyID || isFloatingPoint() || ID == PointerTyID) + return true; + // If it is not something that can have a size (e.g. a function or label), + // it doesn't have a size. + if (ID != StructTyID && ID != ArrayTyID && ID != VectorTyID && + ID != PackedStructTyID) + return false; + // If it is something that can have a size and it's concrete, it definitely + // has a size, otherwise we have to try harder to decide. + return !isAbstract() || isSizedDerivedType(); + } + + /// getPrimitiveSizeInBits - Return the basic size of this type if it is a + /// primitive type. These are fixed by LLVM and are not target dependent. + /// This will return zero if the type does not have a size or is not a + /// primitive type. + /// + unsigned getPrimitiveSizeInBits() const; + + /// getForwaredType - Return the type that this type has been resolved to if + /// it has been resolved to anything. This is used to implement the + /// union-find algorithm for type resolution, and shouldn't be used by general + /// purpose clients. + const Type *getForwardedType() const { + if (!ForwardType) return 0; + return getForwardedTypeInternal(); + } + + /// getVAArgsPromotedType - Return the type an argument of this type + /// will be promoted to if passed through a variable argument + /// function. + const Type *getVAArgsPromotedType() const; + + //===--------------------------------------------------------------------===// + // Type Iteration support + // + typedef PATypeHandle *subtype_iterator; + subtype_iterator subtype_begin() const { return ContainedTys; } + subtype_iterator subtype_end() const { return &ContainedTys[NumContainedTys];} + + /// getContainedType - This method is used to implement the type iterator + /// (defined a the end of the file). For derived types, this returns the + /// types 'contained' in the derived type. + /// + const Type *getContainedType(unsigned i) const { + assert(i < NumContainedTys && "Index out of range!"); + return ContainedTys[i].get(); + } + + /// getNumContainedTypes - Return the number of types in the derived type. + /// + unsigned getNumContainedTypes() const { return NumContainedTys; } + + //===--------------------------------------------------------------------===// + // Static members exported by the Type class itself. Useful for getting + // instances of Type. + // + + /// getPrimitiveType - Return a type based on an identifier. + static const Type *getPrimitiveType(TypeID IDNumber); + + //===--------------------------------------------------------------------===// + // These are the builtin types that are always available... + // + static const Type *VoidTy, *LabelTy, *FloatTy, *DoubleTy; + static const IntegerType *Int1Ty, *Int8Ty, *Int16Ty, *Int32Ty, *Int64Ty; + + /// Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Type *T) { return true; } + + void addRef() const { + assert(isAbstract() && "Cannot add a reference to a non-abstract type!"); + ++RefCount; + } + + void dropRef() const { + assert(isAbstract() && "Cannot drop a reference to a non-abstract type!"); + assert(RefCount && "No objects are currently referencing this object!"); + + // If this is the last PATypeHolder using this object, and there are no + // PATypeHandles using it, the type is dead, delete it now. + if (--RefCount == 0 && AbstractTypeUsers.empty()) + this->destroy(); + } + + /// addAbstractTypeUser - Notify an abstract type that there is a new user of + /// it. This function is called primarily by the PATypeHandle class. + /// + void addAbstractTypeUser(AbstractTypeUser *U) const { + assert(isAbstract() && "addAbstractTypeUser: Current type not abstract!"); + AbstractTypeUsers.push_back(U); + } + + /// removeAbstractTypeUser - Notify an abstract type that a user of the class + /// no longer has a handle to the type. This function is called primarily by + /// the PATypeHandle class. When there are no users of the abstract type, it + /// is annihilated, because there is no way to get a reference to it ever + /// again. + /// + void removeAbstractTypeUser(AbstractTypeUser *U) const; + +private: + /// isSizedDerivedType - Derived types like structures and arrays are sized + /// iff all of the members of the type are sized as well. Since asking for + /// their size is relatively uncommon, move this operation out of line. + bool isSizedDerivedType() const; + + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + virtual void typeBecameConcrete(const DerivedType *AbsTy); + +protected: + // PromoteAbstractToConcrete - This is an internal method used to calculate + // change "Abstract" from true to false when types are refined. + void PromoteAbstractToConcrete(); + friend class TypeMapBase; +}; + +//===----------------------------------------------------------------------===// +// Define some inline methods for the AbstractTypeUser.h:PATypeHandle class. +// These are defined here because they MUST be inlined, yet are dependent on +// the definition of the Type class. +// +inline void PATypeHandle::addUser() { + assert(Ty && "Type Handle has a null type!"); + if (Ty->isAbstract()) + Ty->addAbstractTypeUser(User); +} +inline void PATypeHandle::removeUser() { + if (Ty->isAbstract()) + Ty->removeAbstractTypeUser(User); +} + +// Define inline methods for PATypeHolder... + +inline void PATypeHolder::addRef() { + if (Ty->isAbstract()) + Ty->addRef(); +} + +inline void PATypeHolder::dropRef() { + if (Ty->isAbstract()) + Ty->dropRef(); +} + + +//===----------------------------------------------------------------------===// +// Provide specializations of GraphTraits to be able to treat a type as a +// graph of sub types... + +template <> struct GraphTraits<Type*> { + typedef Type NodeType; + typedef Type::subtype_iterator ChildIteratorType; + + static inline NodeType *getEntryNode(Type *T) { return T; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->subtype_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->subtype_end(); + } +}; + +template <> struct GraphTraits<const Type*> { + typedef const Type NodeType; + typedef Type::subtype_iterator ChildIteratorType; + + static inline NodeType *getEntryNode(const Type *T) { return T; } + static inline ChildIteratorType child_begin(NodeType *N) { + return N->subtype_begin(); + } + static inline ChildIteratorType child_end(NodeType *N) { + return N->subtype_end(); + } +}; + +template <> inline bool isa_impl<PointerType, Type>(const Type &Ty) { + return Ty.getTypeID() == Type::PointerTyID; +} + +std::ostream &operator<<(std::ostream &OS, const Type &T); + +} // End llvm namespace + +#endif diff --git a/include/llvm/TypeSymbolTable.h b/include/llvm/TypeSymbolTable.h new file mode 100644 index 0000000..abe312e --- /dev/null +++ b/include/llvm/TypeSymbolTable.h @@ -0,0 +1,137 @@ +//===-- llvm/TypeSymbolTable.h - Implement a Type Symtab --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer. It is distributed under the +// University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the name/type symbol table for LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TYPE_SYMBOL_TABLE_H +#define LLVM_TYPE_SYMBOL_TABLE_H + +#include "llvm/Type.h" +#include <map> + +namespace llvm { + +/// This class provides a symbol table of name/type pairs with operations to +/// support constructing, searching and iterating over the symbol table. The +/// class derives from AbstractTypeUser so that the contents of the symbol +/// table can be updated when abstract types become concrete. +class TypeSymbolTable : public AbstractTypeUser { + +/// @name Types +/// @{ +public: + + /// @brief A mapping of names to types. + typedef std::map<const std::string, const Type*> TypeMap; + + /// @brief An iterator over the TypeMap. + typedef TypeMap::iterator iterator; + + /// @brief A const_iterator over the TypeMap. + typedef TypeMap::const_iterator const_iterator; + +/// @} +/// @name Constructors +/// @{ +public: + + TypeSymbolTable() {} + ~TypeSymbolTable(); + +/// @} +/// @name Accessors +/// @{ +public: + + /// Generates a unique name for a type based on the \p BaseName by + /// incrementing an integer and appending it to the name, if necessary + /// @returns the unique name + /// @brief Get a unique name for a type + std::string getUniqueName(const std::string &BaseName) const; + + /// This method finds the type with the given \p name in the type map + /// and returns it. + /// @returns null if the name is not found, otherwise the Type + /// associated with the \p name. + /// @brief Lookup a type by name. + Type* lookup(const std::string& name) const; + + /// @returns true iff the symbol table is empty. + /// @brief Determine if the symbol table is empty + inline bool empty() const { return tmap.empty(); } + + /// @returns the size of the symbol table + /// @brief The number of name/type pairs is returned. + inline unsigned size() const { return unsigned(tmap.size()); } + + /// This function can be used from the debugger to display the + /// content of the symbol table while debugging. + /// @brief Print out symbol table on stderr + void dump() const; + +/// @} +/// @name Iteration +/// @{ +public: + /// Get an iterator to the start of the symbol table + inline iterator begin() { return tmap.begin(); } + + /// @brief Get a const_iterator to the start of the symbol table + inline const_iterator begin() const { return tmap.begin(); } + + /// Get an iterator to the end of the symbol talbe. + inline iterator end() { return tmap.end(); } + + /// Get a const_iterator to the end of the symbol table. + inline const_iterator end() const { return tmap.end(); } + +/// @} +/// @name Mutators +/// @{ +public: + + /// Inserts a type into the symbol table with the specified name. There can be + /// a many-to-one mapping between names and types. This method allows a type + /// with an existing entry in the symbol table to get a new name. + /// @brief Insert a type under a new name. + void insert(const std::string &Name, const Type *Typ); + + /// Remove a type at the specified position in the symbol table. + /// @returns the removed Type. + /// @returns the Type that was erased from the symbol table. + Type* remove(iterator TI); + +/// @} +/// @name AbstractTypeUser Methods +/// @{ +private: + /// This function is called when one of the types in the type plane + /// is refined. + virtual void refineAbstractType(const DerivedType *OldTy, const Type *NewTy); + + /// This function markes a type as being concrete (defined). + virtual void typeBecameConcrete(const DerivedType *AbsTy); + +/// @} +/// @name Internal Data +/// @{ +private: + TypeMap tmap; ///< This is the mapping of names to types. + mutable uint32_t LastUnique; ///< Counter for tracking unique names + +/// @} + +}; + +} // End llvm namespace + +#endif + diff --git a/include/llvm/Use.h b/include/llvm/Use.h new file mode 100644 index 0000000..c88d41f --- /dev/null +++ b/include/llvm/Use.h @@ -0,0 +1,176 @@ +//===-- llvm/Use.h - Definition of the Use class ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This defines the Use class. The Use class represents the operand of an +// instruction or some other User instance which refers to a Value. The Use +// class keeps the "use list" of the referenced value up to date. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_USE_H +#define LLVM_USE_H + +#include "llvm/Support/Casting.h" +#include "llvm/ADT/iterator" + +namespace llvm { + +class Value; +class User; + + +//===----------------------------------------------------------------------===// +// Use Class +//===----------------------------------------------------------------------===// + +// Use is here to make keeping the "use" list of a Value up-to-date really easy. +// +class Use { +public: + inline void init(Value *V, User *U); + + Use(Value *V, User *U) { init(V, U); } + Use(const Use &U) { init(U.Val, U.U); } + inline ~Use(); + + /// Default ctor - This leaves the Use completely unitialized. The only thing + /// that is valid to do with this use is to call the "init" method. + inline Use() : Val(0) {} + + + operator Value*() const { return Val; } + Value *get() const { return Val; } + User *getUser() const { return U; } + + inline void set(Value *Val); + + Value *operator=(Value *RHS) { + set(RHS); + return RHS; + } + const Use &operator=(const Use &RHS) { + set(RHS.Val); + return *this; + } + + Value *operator->() { return Val; } + const Value *operator->() const { return Val; } + + Use *getNext() const { return Next; } +private: + Use *Next, **Prev; + Value *Val; + User *U; + + void addToList(Use **List) { + Next = *List; + if (Next) Next->Prev = &Next; + Prev = List; + *List = this; + } + void removeFromList() { + *Prev = Next; + if (Next) Next->Prev = Prev; + } + + friend class Value; +}; + +// simplify_type - Allow clients to treat uses just like values when using +// casting operators. +template<> struct simplify_type<Use> { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const Use &Val) { + return static_cast<SimpleType>(Val.get()); + } +}; +template<> struct simplify_type<const Use> { + typedef Value* SimpleType; + static SimpleType getSimplifiedValue(const Use &Val) { + return static_cast<SimpleType>(Val.get()); + } +}; + + + +template<typename UserTy> // UserTy == 'User' or 'const User' +class value_use_iterator : public forward_iterator<UserTy*, ptrdiff_t> { + typedef forward_iterator<UserTy*, ptrdiff_t> super; + typedef value_use_iterator<UserTy> _Self; + + Use *U; + value_use_iterator(Use *u) : U(u) {} + friend class Value; +public: + typedef typename super::reference reference; + typedef typename super::pointer pointer; + + value_use_iterator(const _Self &I) : U(I.U) {} + value_use_iterator() {} + + bool operator==(const _Self &x) const { + return U == x.U; + } + bool operator!=(const _Self &x) const { + return !operator==(x); + } + + // Iterator traversal: forward iteration only + _Self &operator++() { // Preincrement + assert(U && "Cannot increment end iterator!"); + U = U->getNext(); + return *this; + } + _Self operator++(int) { // Postincrement + _Self tmp = *this; ++*this; return tmp; + } + + // Retrieve a reference to the current SCC + UserTy *operator*() const { + assert(U && "Cannot increment end iterator!"); + return U->getUser(); + } + + UserTy *operator->() const { return operator*(); } + + Use &getUse() const { return *U; } + + /// getOperandNo - Return the operand # of this use in its User. Defined in + /// User.h + /// + unsigned getOperandNo() const; +}; + + +template<> struct simplify_type<value_use_iterator<User> > { + typedef User* SimpleType; + + static SimpleType getSimplifiedValue(const value_use_iterator<User> &Val) { + return *Val; + } +}; + +template<> struct simplify_type<const value_use_iterator<User> > + : public simplify_type<value_use_iterator<User> > {}; + +template<> struct simplify_type<value_use_iterator<const User> > { + typedef const User* SimpleType; + + static SimpleType getSimplifiedValue(const + value_use_iterator<const User> &Val) { + return *Val; + } +}; + +template<> struct simplify_type<const value_use_iterator<const User> > + : public simplify_type<value_use_iterator<const User> > {}; + +} // End llvm namespace + +#endif diff --git a/include/llvm/User.h b/include/llvm/User.h new file mode 100644 index 0000000..1ea5e18 --- /dev/null +++ b/include/llvm/User.h @@ -0,0 +1,122 @@ +//===-- llvm/User.h - User class definition ---------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This class defines the interface that one who 'use's a Value must implement. +// Each instance of the Value class keeps track of what User's have handles +// to it. +// +// * Instructions are the largest class of User's. +// * Constants may be users of other constants (think arrays and stuff) +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_USER_H +#define LLVM_USER_H + +#include "llvm/Value.h" + +namespace llvm { + +class User : public Value { + User(const User &); // Do not implement +protected: + /// OperandList - This is a pointer to the array of Users for this operand. + /// For nodes of fixed arity (e.g. a binary operator) this array will live + /// embedded into the derived class. For nodes of variable arity + /// (e.g. ConstantArrays, CallInst, PHINodes, etc), this memory will be + /// dynamically allocated and should be destroyed by the classes virtual dtor. + Use *OperandList; + + /// NumOperands - The number of values used by this User. + /// + unsigned NumOperands; + +public: + User(const Type *Ty, unsigned vty, Use *OpList, unsigned NumOps) + : Value(Ty, vty), OperandList(OpList), NumOperands(NumOps) {} + + Value *getOperand(unsigned i) const { + assert(i < NumOperands && "getOperand() out of range!"); + return OperandList[i]; + } + void setOperand(unsigned i, Value *Val) { + assert(i < NumOperands && "setOperand() out of range!"); + OperandList[i] = Val; + } + unsigned getNumOperands() const { return NumOperands; } + + // --------------------------------------------------------------------------- + // Operand Iterator interface... + // + typedef Use* op_iterator; + typedef const Use* const_op_iterator; + + inline op_iterator op_begin() { return OperandList; } + inline const_op_iterator op_begin() const { return OperandList; } + inline op_iterator op_end() { return OperandList+NumOperands; } + inline const_op_iterator op_end() const { return OperandList+NumOperands; } + + // dropAllReferences() - This function is in charge of "letting go" of all + // objects that this User refers to. This allows one to + // 'delete' a whole class at a time, even though there may be circular + // references... first all references are dropped, and all use counts go to + // zero. Then everything is delete'd for real. Note that no operations are + // valid on an object that has "dropped all references", except operator + // delete. + // + void dropAllReferences() { + Use *OL = OperandList; + for (unsigned i = 0, e = NumOperands; i != e; ++i) + OL[i].set(0); + } + + /// replaceUsesOfWith - Replaces all references to the "From" definition with + /// references to the "To" definition. + /// + void replaceUsesOfWith(Value *From, Value *To); + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const User *) { return true; } + static inline bool classof(const Value *V) { + return isa<Instruction>(V) || isa<Constant>(V); + } +}; + +template<> struct simplify_type<User::op_iterator> { + typedef Value* SimpleType; + + static SimpleType getSimplifiedValue(const User::op_iterator &Val) { + return static_cast<SimpleType>(Val->get()); + } +}; + +template<> struct simplify_type<const User::op_iterator> + : public simplify_type<User::op_iterator> {}; + +template<> struct simplify_type<User::const_op_iterator> { + typedef Value* SimpleType; + + static SimpleType getSimplifiedValue(const User::const_op_iterator &Val) { + return static_cast<SimpleType>(Val->get()); + } +}; + +template<> struct simplify_type<const User::const_op_iterator> + : public simplify_type<User::const_op_iterator> {}; + + +// value_use_iterator::getOperandNo - Requires the definition of the User class. +template<typename UserTy> +unsigned value_use_iterator<UserTy>::getOperandNo() const { + return U - U->getUser()->op_begin(); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/Value.h b/include/llvm/Value.h new file mode 100644 index 0000000..44c4453 --- /dev/null +++ b/include/llvm/Value.h @@ -0,0 +1,262 @@ +//===-- llvm/Value.h - Definition of the Value class ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by the LLVM research group and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the Value class. +// This file also defines the Use<> template for users of value. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_VALUE_H +#define LLVM_VALUE_H + +#include "llvm/AbstractTypeUser.h" +#include "llvm/Use.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/Streams.h" +#include <string> + +namespace llvm { + +class Constant; +class Argument; +class Instruction; +class BasicBlock; +class GlobalValue; +class Function; +class GlobalVariable; +class GlobalAlias; +class InlineAsm; +class ValueSymbolTable; +class TypeSymbolTable; +template<typename ValueTy> class StringMapEntry; +typedef StringMapEntry<Value*> ValueName; + +//===----------------------------------------------------------------------===// +// Value Class +//===----------------------------------------------------------------------===// + +/// This is a very important LLVM class. It is the base class of all values +/// computed by a program that may be used as operands to other values. Value is +/// the super class of other important classes such as Instruction and Function. +/// All Values have a Type. Type is not a subclass of Value. All types can have +/// a name and they should belong to some Module. Setting the name on the Value +/// automatically update's the module's symbol table. +/// +/// Every value has a "use list" that keeps track of which other Values are +/// using this Value. +/// @brief LLVM Value Representation +class Value { + const unsigned short SubclassID; // Subclass identifier (for isa/dyn_cast) +protected: + /// SubclassData - This member is defined by this class, but is not used for + /// anything. Subclasses can use it to hold whatever state they find useful. + /// This field is initialized to zero by the ctor. + unsigned short SubclassData; +private: + PATypeHolder Ty; + Use *UseList; + + friend class ValueSymbolTable; // Allow ValueSymbolTable to directly mod Name. + friend class SymbolTable; // Allow SymbolTable to directly poke Name. + ValueName *Name; + + void operator=(const Value &); // Do not implement + Value(const Value &); // Do not implement + +public: + Value(const Type *Ty, unsigned scid); + virtual ~Value(); + + /// dump - Support for debugging, callable in GDB: V->dump() + // + virtual void dump() const; + + /// print - Implement operator<< on Value... + /// + virtual void print(std::ostream &O) const = 0; + void print(std::ostream *O) const { if (O) print(*O); } + + /// All values are typed, get the type of this value. + /// + inline const Type *getType() const { return Ty; } + + // All values can potentially be named... + inline bool hasName() const { return Name != 0; } + std::string getName() const { return getNameStr(); } + std::string getNameStr() const; + ValueName *getValueName() const { return Name; } + + void setName(const std::string &name); + void setName(const char *Name, unsigned NameLen); + void setName(const char *Name); // Takes a null-terminated string. + + + /// takeName - transfer the name from V to this value, setting V's name to + /// empty. It is an error to call V->takeName(V). + void takeName(Value *V); + + /// replaceAllUsesWith - Go through the uses list for this definition and make + /// each use point to "V" instead of "this". After this completes, 'this's + /// use list is guaranteed to be empty. + /// + void replaceAllUsesWith(Value *V); + + // uncheckedReplaceAllUsesWith - Just like replaceAllUsesWith but dangerous. + // Only use when in type resolution situations! + void uncheckedReplaceAllUsesWith(Value *V); + + //---------------------------------------------------------------------- + // Methods for handling the vector of uses of this Value. + // + typedef value_use_iterator<User> use_iterator; + typedef value_use_iterator<const User> use_const_iterator; + + bool use_empty() const { return UseList == 0; } + use_iterator use_begin() { return use_iterator(UseList); } + use_const_iterator use_begin() const { return use_const_iterator(UseList); } + use_iterator use_end() { return use_iterator(0); } + use_const_iterator use_end() const { return use_const_iterator(0); } + User *use_back() { return *use_begin(); } + const User *use_back() const { return *use_begin(); } + + /// hasOneUse - Return true if there is exactly one user of this value. This + /// is specialized because it is a common request and does not require + /// traversing the whole use list. + /// + bool hasOneUse() const { + use_const_iterator I = use_begin(), E = use_end(); + if (I == E) return false; + return ++I == E; + } + + /// hasNUses - Return true if this Value has exactly N users. + /// + bool hasNUses(unsigned N) const; + + /// hasNUsesOrMore - Return true if this value has N users or more. This is + /// logically equivalent to getNumUses() >= N. + /// + bool hasNUsesOrMore(unsigned N) const; + + /// getNumUses - This method computes the number of uses of this Value. This + /// is a linear time operation. Use hasOneUse, hasNUses, or hasMoreThanNUses + /// to check for specific values. + unsigned getNumUses() const; + + /// addUse/killUse - These two methods should only be used by the Use class. + /// + void addUse(Use &U) { U.addToList(&UseList); } + + /// An enumeration for keeping track of the concrete subclass of Value that + /// is actually instantiated. Values of this enumeration are kept in the + /// Value classes SubclassID field. They are used for concrete type + /// identification. + enum ValueTy { + ArgumentVal, // This is an instance of Argument + BasicBlockVal, // This is an instance of BasicBlock + FunctionVal, // This is an instance of Function + GlobalAliasVal, // This is an instance of GlobalAlias + GlobalVariableVal, // This is an instance of GlobalVariable + UndefValueVal, // This is an instance of UndefValue + ConstantExprVal, // This is an instance of ConstantExpr + ConstantAggregateZeroVal, // This is an instance of ConstantAggregateNull + ConstantIntVal, // This is an instance of ConstantInt + ConstantFPVal, // This is an instance of ConstantFP + ConstantArrayVal, // This is an instance of ConstantArray + ConstantStructVal, // This is an instance of ConstantStruct + ConstantVectorVal, // This is an instance of ConstantVector + ConstantPointerNullVal, // This is an instance of ConstantPointerNull + InlineAsmVal, // This is an instance of InlineAsm + InstructionVal, // This is an instance of Instruction + + // Markers: + ConstantFirstVal = FunctionVal, + ConstantLastVal = ConstantPointerNullVal + }; + + /// getValueID - Return an ID for the concrete type of this object. This is + /// used to implement the classof checks. This should not be used for any + /// other purpose, as the values may change as LLVM evolves. Also, note that + /// for instructions, the Instruction's opcode is added to InstructionVal. So + /// this means three things: + /// # there is no value with code InstructionVal (no opcode==0). + /// # there are more possible values for the value type than in ValueTy enum. + /// # the InstructionVal enumerator must be the highest valued enumerator in + /// the ValueTy enum. + unsigned getValueID() const { + return SubclassID; + } + + // Methods for support type inquiry through isa, cast, and dyn_cast: + static inline bool classof(const Value *) { + return true; // Values are always values. + } + + /// getRawType - This should only be used to implement the vmcore library. + /// + const Type *getRawType() const { return Ty.getRawType(); } +}; + +inline std::ostream &operator<<(std::ostream &OS, const Value &V) { + V.print(OS); + return OS; +} + +void Use::init(Value *v, User *user) { + Val = v; + U = user; + if (Val) Val->addUse(*this); +} + +Use::~Use() { + if (Val) removeFromList(); +} + +void Use::set(Value *V) { + if (Val) removeFromList(); + Val = V; + if (V) V->addUse(*this); +} + + +// isa - Provide some specializations of isa so that we don't have to include +// the subtype header files to test to see if the value is a subclass... +// +template <> inline bool isa_impl<Constant, Value>(const Value &Val) { + return Val.getValueID() >= Value::ConstantFirstVal && + Val.getValueID() <= Value::ConstantLastVal; +} +template <> inline bool isa_impl<Argument, Value>(const Value &Val) { + return Val.getValueID() == Value::ArgumentVal; +} +template <> inline bool isa_impl<InlineAsm, Value>(const Value &Val) { + return Val.getValueID() == Value::InlineAsmVal; +} +template <> inline bool isa_impl<Instruction, Value>(const Value &Val) { + return Val.getValueID() >= Value::InstructionVal; +} +template <> inline bool isa_impl<BasicBlock, Value>(const Value &Val) { + return Val.getValueID() == Value::BasicBlockVal; +} +template <> inline bool isa_impl<Function, Value>(const Value &Val) { + return Val.getValueID() == Value::FunctionVal; +} +template <> inline bool isa_impl<GlobalVariable, Value>(const Value &Val) { + return Val.getValueID() == Value::GlobalVariableVal; +} +template <> inline bool isa_impl<GlobalAlias, Value>(const Value &Val) { + return Val.getValueID() == Value::GlobalAliasVal; +} +template <> inline bool isa_impl<GlobalValue, Value>(const Value &Val) { + return isa<GlobalVariable>(Val) || isa<Function>(Val) || isa<GlobalAlias>(Val); +} + +} // End llvm namespace + +#endif diff --git a/include/llvm/ValueSymbolTable.h b/include/llvm/ValueSymbolTable.h new file mode 100644 index 0000000..a695ee8 --- /dev/null +++ b/include/llvm/ValueSymbolTable.h @@ -0,0 +1,137 @@ +//===-- llvm/ValueSymbolTable.h - Implement a Value Symtab ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Reid Spencer and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements the name/Value symbol table for LLVM. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_VALUE_SYMBOL_TABLE_H +#define LLVM_VALUE_SYMBOL_TABLE_H + +#include "llvm/Value.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + template<typename ValueSubClass, typename ItemParentClass> + class SymbolTableListTraits; + class BasicBlock; + class Function; + class Module; + +/// This class provides a symbol table of name/value pairs. It is essentially +/// a std::map<std::string,Value*> but has a controlled interface provided by +/// LLVM as well as ensuring uniqueness of names. +/// +class ValueSymbolTable { + friend class Value; + friend class SymbolTableListTraits<Argument, Function>; + friend class SymbolTableListTraits<BasicBlock, Function>; + friend class SymbolTableListTraits<Instruction, BasicBlock>; + friend class SymbolTableListTraits<Function, Module>; + friend class SymbolTableListTraits<GlobalVariable, Module>; + friend class SymbolTableListTraits<GlobalAlias, Module>; +/// @name Types +/// @{ +public: + /// @brief A mapping of names to values. + typedef StringMap<Value*> ValueMap; + + /// @brief An iterator over a ValueMap. + typedef ValueMap::iterator iterator; + + /// @brief A const_iterator over a ValueMap. + typedef ValueMap::const_iterator const_iterator; + +/// @} +/// @name Constructors +/// @{ +public: + + ValueSymbolTable() : vmap(0), LastUnique(0) {} + ~ValueSymbolTable(); + +/// @} +/// @name Accessors +/// @{ +public: + + /// This method finds the value with the given \p name in the + /// the symbol table. + /// @returns the value associated with the \p name + /// @brief Lookup a named Value. + Value *lookup(const std::string &name) const; + + /// @returns true iff the symbol table is empty + /// @brief Determine if the symbol table is empty + inline bool empty() const { return vmap.empty(); } + + /// @brief The number of name/type pairs is returned. + inline unsigned size() const { return unsigned(vmap.size()); } + + /// Given a base name, return a string that is either equal to it or + /// derived from it that does not already occur in the symbol table + /// for the specified type. + /// @brief Get a name unique to this symbol table + std::string getUniqueName(const std::string &BaseName) const; + + /// This function can be used from the debugger to display the + /// content of the symbol table while debugging. + /// @brief Print out symbol table on stderr + void dump() const; + +/// @} +/// @name Iteration +/// @{ +public: + /// @brief Get an iterator that from the beginning of the symbol table. + inline iterator begin() { return vmap.begin(); } + + /// @brief Get a const_iterator that from the beginning of the symbol table. + inline const_iterator begin() const { return vmap.begin(); } + + /// @brief Get an iterator to the end of the symbol table. + inline iterator end() { return vmap.end(); } + + /// @brief Get a const_iterator to the end of the symbol table. + inline const_iterator end() const { return vmap.end(); } + +/// @} +/// @name Mutators +/// @{ +private: + /// This method adds the provided value \p N to the symbol table. The Value + /// must have a name which is used to place the value in the symbol table. + /// If the inserted name conflicts, this renames the value. + /// @brief Add a named value to the symbol table + void reinsertValue(Value *V); + + /// createValueName - This method attempts to create a value name and insert + /// it into the symbol table with the specified name. If it conflicts, it + /// auto-renames the name and returns that instead. + ValueName *createValueName(const char *NameStart, unsigned NameLen, Value *V); + + /// This method removes a value from the symbol table. It leaves the + /// ValueName attached to the value, but it is no longer inserted in the + /// symtab. + void removeValueName(ValueName *V); + +/// @} +/// @name Internal Data +/// @{ +private: + ValueMap vmap; ///< The map that holds the symbol table. + mutable uint32_t LastUnique; ///< Counter for tracking unique names + +/// @} +}; + +} // End llvm namespace + +#endif |