diff options
author | rdivacky <rdivacky@FreeBSD.org> | 2010-05-27 15:15:58 +0000 |
---|---|---|
committer | rdivacky <rdivacky@FreeBSD.org> | 2010-05-27 15:15:58 +0000 |
commit | 1e3dec662ea18131c495db50caccc57f77b7a5fe (patch) | |
tree | 9fad9a5d5dd8c4ff54af48edad9c8cc26dd5fda1 /include | |
parent | 377552607e51dc1d3e6ff33833f9620bcfe815ac (diff) | |
download | FreeBSD-src-1e3dec662ea18131c495db50caccc57f77b7a5fe.zip FreeBSD-src-1e3dec662ea18131c495db50caccc57f77b7a5fe.tar.gz |
Update LLVM to r104832.
Diffstat (limited to 'include')
72 files changed, 1820 insertions, 769 deletions
diff --git a/include/llvm/ADT/DenseMap.h b/include/llvm/ADT/DenseMap.h index 393473bd..5c99473 100644 --- a/include/llvm/ADT/DenseMap.h +++ b/include/llvm/ADT/DenseMap.h @@ -79,13 +79,14 @@ public: typedef DenseMapIterator<KeyT, ValueT, KeyInfoT, ValueInfoT, true> const_iterator; inline iterator begin() { - return iterator(Buckets, Buckets+NumBuckets); + // When the map is empty, avoid the overhead of AdvancePastEmptyBuckets(). + return empty() ? end() : iterator(Buckets, Buckets+NumBuckets); } inline iterator end() { return iterator(Buckets+NumBuckets, Buckets+NumBuckets); } inline const_iterator begin() const { - return const_iterator(Buckets, Buckets+NumBuckets); + return empty() ? end() : const_iterator(Buckets, Buckets+NumBuckets); } inline const_iterator end() const { return const_iterator(Buckets+NumBuckets, Buckets+NumBuckets); diff --git a/include/llvm/ADT/EquivalenceClasses.h b/include/llvm/ADT/EquivalenceClasses.h index 5f89823..91a1429 100644 --- a/include/llvm/ADT/EquivalenceClasses.h +++ b/include/llvm/ADT/EquivalenceClasses.h @@ -191,7 +191,7 @@ public: /// 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; + return TheMapping.insert(ECValue(Data)).first; } /// findLeader - Given a value in the set, return a member iterator for the diff --git a/include/llvm/ADT/SparseBitVector.h b/include/llvm/ADT/SparseBitVector.h index 6c813ec..0862981 100644 --- a/include/llvm/ADT/SparseBitVector.h +++ b/include/llvm/ADT/SparseBitVector.h @@ -889,13 +889,17 @@ operator-(const SparseBitVector<ElementSize> &LHS, // Dump a SparseBitVector to a stream template <unsigned ElementSize> void dump(const SparseBitVector<ElementSize> &LHS, raw_ostream &out) { - out << "[ "; - - typename SparseBitVector<ElementSize>::iterator bi; - for (bi = LHS.begin(); bi != LHS.end(); ++bi) { - out << *bi << " "; + out << "["; + + typename SparseBitVector<ElementSize>::iterator bi = LHS.begin(), + be = LHS.end(); + if (bi != be) { + out << *bi; + for (++bi; bi != be; ++bi) { + out << " " << *bi; + } } - out << " ]\n"; + out << "]\n"; } } // end namespace llvm diff --git a/include/llvm/ADT/StringRef.h b/include/llvm/ADT/StringRef.h index ab6358b..33756f6 100644 --- a/include/llvm/ADT/StringRef.h +++ b/include/llvm/ADT/StringRef.h @@ -128,6 +128,10 @@ namespace llvm { /// compare_lower - Compare two strings, ignoring case. int compare_lower(StringRef RHS) const; + /// compare_numeric - Compare two strings, treating sequences of digits as + /// numbers. + int compare_numeric(StringRef RHS) const; + /// \brief Determine the edit distance between this string and another /// string. /// diff --git a/include/llvm/ADT/Twine.h b/include/llvm/ADT/Twine.h index 97e9df4..b519a3e 100644 --- a/include/llvm/ADT/Twine.h +++ b/include/llvm/ADT/Twine.h @@ -99,11 +99,12 @@ namespace llvm { /// A pointer to a StringRef instance. StringRefKind, - /// A pointer to an unsigned int value, to render as an unsigned decimal - /// integer. + /// An unsigned int value reinterpreted as a pointer, to render as an + /// unsigned decimal integer. DecUIKind, - /// A pointer to an int value, to render as a signed decimal integer. + /// An int value reinterpreted as a pointer, to render as a signed + /// decimal integer. DecIKind, /// A pointer to an unsigned long value, to render as an unsigned decimal @@ -259,13 +260,13 @@ namespace llvm { } /// Construct a twine to print \arg Val as an unsigned decimal integer. - explicit Twine(const unsigned int &Val) - : LHS(&Val), LHSKind(DecUIKind), RHSKind(EmptyKind) { + explicit Twine(unsigned Val) + : LHS((void*)(intptr_t)Val), LHSKind(DecUIKind), RHSKind(EmptyKind) { } /// Construct a twine to print \arg Val as a signed decimal integer. - explicit Twine(const int &Val) - : LHS(&Val), LHSKind(DecIKind), RHSKind(EmptyKind) { + explicit Twine(int Val) + : LHS((void*)(intptr_t)Val), LHSKind(DecIKind), RHSKind(EmptyKind) { } /// Construct a twine to print \arg Val as an unsigned decimal integer. diff --git a/include/llvm/ADT/ilist_node.h b/include/llvm/ADT/ilist_node.h index da25f95..f008003 100644 --- a/include/llvm/ADT/ilist_node.h +++ b/include/llvm/ADT/ilist_node.h @@ -49,6 +49,56 @@ class ilist_node : private ilist_half_node<NodeTy> { void setNext(NodeTy *N) { Next = N; } protected: ilist_node() : Next(0) {} + +public: + /// @name Adjacent Node Accessors + /// @{ + + /// \brief Get the previous node, or 0 for the list head. + NodeTy *getPrevNode() { + NodeTy *Prev = this->getPrev(); + + // Check for sentinel. + if (!Prev->getNext()) + return 0; + + return Prev; + } + + /// \brief Get the previous node, or 0 for the list head. + const NodeTy *getPrevNode() const { + const NodeTy *Prev = this->getPrev(); + + // Check for sentinel. + if (!Prev->getNext()) + return 0; + + return Prev; + } + + /// \brief Get the next node, or 0 for the list tail. + NodeTy *getNextNode() { + NodeTy *Next = getNext(); + + // Check for sentinel. + if (!Next->getNext()) + return 0; + + return Next; + } + + /// \brief Get the next node, or 0 for the list tail. + const NodeTy *getNextNode() const { + const NodeTy *Next = getNext(); + + // Check for sentinel. + if (!Next->getNext()) + return 0; + + return Next; + } + + /// @} }; } // End llvm namespace diff --git a/include/llvm/Analysis/DebugInfo.h b/include/llvm/Analysis/DebugInfo.h index 9b1379d..473b127 100644 --- a/include/llvm/Analysis/DebugInfo.h +++ b/include/llvm/Analysis/DebugInfo.h @@ -34,13 +34,14 @@ namespace llvm { class Instruction; class MDNode; class LLVMContext; + class raw_ostream; /// DIDescriptor - A thin wraper around MDNode to access encoded debug info. /// This should not be stored in a container, because underly MDNode may /// change in certain situations. class DIDescriptor { protected: - MDNode *DbgNode; + const MDNode *DbgNode; StringRef getStringField(unsigned Elt) const; unsigned getUnsignedField(unsigned Elt) const { @@ -51,18 +52,19 @@ namespace llvm { template <typename DescTy> DescTy getFieldAs(unsigned Elt) const { - return DescTy(getDescriptorField(Elt).getNode()); + return DescTy(getDescriptorField(Elt)); } GlobalVariable *getGlobalVariableField(unsigned Elt) const; public: explicit DIDescriptor() : DbgNode(0) {} - explicit DIDescriptor(MDNode *N) : DbgNode(N) {} + explicit DIDescriptor(const MDNode *N) : DbgNode(N) {} bool Verify() const { return DbgNode != 0; } - MDNode *getNode() const { return DbgNode; } + operator MDNode *() const { return const_cast<MDNode*>(DbgNode); } + MDNode *operator ->() const { return const_cast<MDNode*>(DbgNode); } unsigned getVersion() const { return getUnsignedField(0) & LLVMDebugVersionMask; @@ -72,10 +74,10 @@ namespace llvm { return getUnsignedField(0) & ~LLVMDebugVersionMask; } - /// ValidDebugInfo - Return true if N represents valid debug info value. - static bool ValidDebugInfo(MDNode *N, unsigned OptLevel); + /// print - print descriptor. + void print(raw_ostream &OS) const; - /// dump - print descriptor. + /// dump - print descriptor to dbgs() with a newline. void dump() const; bool isDerivedType() const; @@ -98,7 +100,7 @@ namespace llvm { /// DISubrange - This is used to represent ranges, for array bounds. class DISubrange : public DIDescriptor { public: - explicit DISubrange(MDNode *N = 0) : DIDescriptor(N) {} + explicit DISubrange(const MDNode *N = 0) : DIDescriptor(N) {} int64_t getLo() const { return (int64_t)getUInt64Field(1); } int64_t getHi() const { return (int64_t)getUInt64Field(2); } @@ -107,7 +109,7 @@ namespace llvm { /// DIArray - This descriptor holds an array of descriptors. class DIArray : public DIDescriptor { public: - explicit DIArray(MDNode *N = 0) + explicit DIArray(const MDNode *N = 0) : DIDescriptor(N) {} unsigned getNumElements() const; @@ -119,7 +121,7 @@ namespace llvm { /// DIScope - A base class for various scopes. class DIScope : public DIDescriptor { public: - explicit DIScope(MDNode *N = 0) : DIDescriptor (N) {} + explicit DIScope(const MDNode *N = 0) : DIDescriptor (N) {} virtual ~DIScope() {} StringRef getFilename() const; @@ -129,7 +131,7 @@ namespace llvm { /// DICompileUnit - A wrapper for a compile unit. class DICompileUnit : public DIScope { public: - explicit DICompileUnit(MDNode *N = 0) : DIScope(N) {} + explicit DICompileUnit(const MDNode *N = 0) : DIScope(N) {} unsigned getLanguage() const { return getUnsignedField(2); } StringRef getFilename() const { return getStringField(3); } @@ -153,14 +155,17 @@ namespace llvm { /// Verify - Verify that a compile unit is well formed. bool Verify() const; - /// dump - print compile unit. + /// print - print compile unit. + void print(raw_ostream &OS) const; + + /// dump - print compile unit to dbgs() with a newline. void dump() const; }; /// DIFile - This is a wrapper for a file. class DIFile : public DIScope { public: - explicit DIFile(MDNode *N = 0) : DIScope(N) { + explicit DIFile(const MDNode *N = 0) : DIScope(N) { if (DbgNode && !isFile()) DbgNode = 0; } @@ -174,7 +179,7 @@ namespace llvm { /// type/precision or a file/line pair for location info. class DIEnumerator : public DIDescriptor { public: - explicit DIEnumerator(MDNode *N = 0) : DIDescriptor(N) {} + explicit DIEnumerator(const MDNode *N = 0) : DIDescriptor(N) {} StringRef getName() const { return getStringField(1); } uint64_t getEnumValue() const { return getUInt64Field(2); } @@ -199,14 +204,14 @@ namespace llvm { protected: // This ctor is used when the Tag has already been validated by a derived // ctor. - DIType(MDNode *N, bool, bool) : DIScope(N) {} + DIType(const MDNode *N, bool, bool) : DIScope(N) {} public: /// Verify - Verify that a type descriptor is well formed. bool Verify() const; public: - explicit DIType(MDNode *N); + explicit DIType(const MDNode *N); explicit DIType() {} virtual ~DIType() {} @@ -253,18 +258,25 @@ namespace llvm { } StringRef getFilename() const { return getCompileUnit().getFilename();} StringRef getDirectory() const { return getCompileUnit().getDirectory();} - /// dump - print type. + + /// print - print type. + void print(raw_ostream &OS) const; + + /// dump - print type to dbgs() with a newline. void dump() const; }; /// DIBasicType - A basic type, like 'int' or 'float'. class DIBasicType : public DIType { public: - explicit DIBasicType(MDNode *N = 0) : DIType(N) {} + explicit DIBasicType(const MDNode *N = 0) : DIType(N) {} unsigned getEncoding() const { return getUnsignedField(9); } - /// dump - print basic type. + /// print - print basic type. + void print(raw_ostream &OS) const; + + /// dump - print basic type to dbgs() with a newline. void dump() const; }; @@ -272,10 +284,10 @@ namespace llvm { /// a typedef, a pointer or reference, etc. class DIDerivedType : public DIType { protected: - explicit DIDerivedType(MDNode *N, bool, bool) + explicit DIDerivedType(const MDNode *N, bool, bool) : DIType(N, true, true) {} public: - explicit DIDerivedType(MDNode *N = 0) + explicit DIDerivedType(const MDNode *N = 0) : DIType(N, true, true) {} DIType getTypeDerivedFrom() const { return getFieldAs<DIType>(9); } @@ -283,7 +295,11 @@ namespace llvm { /// getOriginalTypeSize - If this type is derived from a base type then /// return base type size. uint64_t getOriginalTypeSize() const; - /// dump - print derived type. + + /// print - print derived type. + void print(raw_ostream &OS) const; + + /// dump - print derived type to dbgs() with a newline. void dump() const; /// replaceAllUsesWith - Replace all uses of debug info referenced by @@ -297,7 +313,7 @@ namespace llvm { /// FIXME: Why is this a DIDerivedType?? class DICompositeType : public DIDerivedType { public: - explicit DICompositeType(MDNode *N = 0) + explicit DICompositeType(const MDNode *N = 0) : DIDerivedType(N, true, true) { if (N && !isCompositeType()) DbgNode = 0; @@ -312,46 +328,17 @@ namespace llvm { /// Verify - Verify that a composite type descriptor is well formed. bool Verify() const; - /// dump - print composite type. - void dump() const; - }; - - /// DIGlobal - This is a common class for global variables and subprograms. - class DIGlobal : public DIDescriptor { - protected: - explicit DIGlobal(MDNode *N) : DIDescriptor(N) {} - - public: - virtual ~DIGlobal() {} - - DIScope getContext() const { return getFieldAs<DIScope>(2); } - StringRef getName() const { return getStringField(3); } - StringRef getDisplayName() const { return getStringField(4); } - StringRef getLinkageName() const { return getStringField(5); } - DICompileUnit getCompileUnit() const{ - if (getVersion() == llvm::LLVMDebugVersion7) - return getFieldAs<DICompileUnit>(6); - - DIFile F = getFieldAs<DIFile>(6); - return F.getCompileUnit(); - } - - unsigned getLineNumber() const { return getUnsignedField(7); } - DIType getType() const { return getFieldAs<DIType>(8); } + /// print - print composite type. + void print(raw_ostream &OS) const; - /// isLocalToUnit - Return true if this subprogram is local to the current - /// compile unit, like 'static' in C. - unsigned isLocalToUnit() const { return getUnsignedField(9); } - unsigned isDefinition() const { return getUnsignedField(10); } - - /// dump - print global. + /// dump - print composite type to dbgs() with a newline. void dump() const; }; /// DISubprogram - This is a wrapper for a subprogram (e.g. a function). class DISubprogram : public DIScope { public: - explicit DISubprogram(MDNode *N = 0) : DIScope(N) {} + explicit DISubprogram(const MDNode *N = 0) : DIScope(N) {} DIScope getContext() const { return getFieldAs<DIScope>(2); } StringRef getName() const { return getStringField(3); } @@ -373,7 +360,7 @@ namespace llvm { DICompositeType DCT(getFieldAs<DICompositeType>(8)); if (DCT.Verify()) { DIArray A = DCT.getTypeArray(); - DIType T(A.getElement(0).getNode()); + DIType T(A.getElement(0)); return T.getName(); } DIType T(getFieldAs<DIType>(8)); @@ -413,7 +400,10 @@ namespace llvm { /// Verify - Verify that a subprogram descriptor is well formed. bool Verify() const; - /// dump - print subprogram. + /// print - print subprogram. + void print(raw_ostream &OS) const; + + /// dump - print subprogram to dbgs() with a newline. void dump() const; /// describes - Return true if this subprogram provides debugging @@ -422,16 +412,36 @@ namespace llvm { }; /// DIGlobalVariable - This is a wrapper for a global variable. - class DIGlobalVariable : public DIGlobal { + class DIGlobalVariable : public DIDescriptor { public: - explicit DIGlobalVariable(MDNode *N = 0) : DIGlobal(N) {} + explicit DIGlobalVariable(const MDNode *N = 0) : DIDescriptor(N) {} + + DIScope getContext() const { return getFieldAs<DIScope>(2); } + StringRef getName() const { return getStringField(3); } + StringRef getDisplayName() const { return getStringField(4); } + StringRef getLinkageName() const { return getStringField(5); } + DICompileUnit getCompileUnit() const{ + if (getVersion() == llvm::LLVMDebugVersion7) + return getFieldAs<DICompileUnit>(6); + + DIFile F = getFieldAs<DIFile>(6); + return F.getCompileUnit(); + } + + unsigned getLineNumber() const { return getUnsignedField(7); } + DIType getType() const { return getFieldAs<DIType>(8); } + unsigned isLocalToUnit() const { return getUnsignedField(9); } + unsigned isDefinition() const { return getUnsignedField(10); } GlobalVariable *getGlobal() const { return getGlobalVariableField(11); } /// Verify - Verify that a global variable descriptor is well formed. bool Verify() const; - /// dump - print global variable. + /// print - print global variable. + void print(raw_ostream &OS) const; + + /// dump - print global variable to dbgs() with a newline. void dump() const; }; @@ -439,7 +449,7 @@ namespace llvm { /// global etc). class DIVariable : public DIDescriptor { public: - explicit DIVariable(MDNode *N = 0) + explicit DIVariable(const MDNode *N = 0) : DIDescriptor(N) {} DIScope getContext() const { return getFieldAs<DIScope>(1); } @@ -479,14 +489,17 @@ namespace llvm { /// information for an inlined function arguments. bool isInlinedFnArgument(const Function *CurFn); - /// dump - print variable. + /// print - print variable. + void print(raw_ostream &OS) const; + + /// dump - print variable to dbgs() with a newline. void dump() const; }; /// DILexicalBlock - This is a wrapper for a lexical block. class DILexicalBlock : public DIScope { public: - explicit DILexicalBlock(MDNode *N = 0) : DIScope(N) {} + explicit DILexicalBlock(const MDNode *N = 0) : DIScope(N) {} DIScope getContext() const { return getFieldAs<DIScope>(1); } StringRef getDirectory() const { return getContext().getDirectory(); } StringRef getFilename() const { return getContext().getFilename(); } @@ -497,7 +510,7 @@ namespace llvm { /// DINameSpace - A wrapper for a C++ style name space. class DINameSpace : public DIScope { public: - explicit DINameSpace(MDNode *N = 0) : DIScope(N) {} + explicit DINameSpace(const MDNode *N = 0) : DIScope(N) {} DIScope getContext() const { return getFieldAs<DIScope>(1); } StringRef getName() const { return getStringField(2); } StringRef getDirectory() const { return getContext().getDirectory(); } @@ -510,13 +523,14 @@ namespace llvm { return F.getCompileUnit(); } unsigned getLineNumber() const { return getUnsignedField(4); } + bool Verify() const; }; /// DILocation - This object holds location information. This object /// is not associated with any DWARF tag. class DILocation : public DIDescriptor { public: - explicit DILocation(MDNode *N) : DIDescriptor(N) { } + explicit DILocation(const MDNode *N) : DIDescriptor(N) { } unsigned getLineNumber() const { return getUnsignedField(0); } unsigned getColumnNumber() const { return getUnsignedField(1); } @@ -663,7 +677,7 @@ namespace llvm { DIVariable CreateVariable(unsigned Tag, DIDescriptor Context, StringRef Name, DIFile F, unsigned LineNo, - DIType Ty); + DIType Ty, bool AlwaysPreserve = false); /// CreateComplexVariable - Create a new descriptor for the specified /// variable which has a complex address expression for its address. @@ -715,7 +729,7 @@ namespace llvm { std::string &Dir); /// getDISubprogram - Find subprogram that is enclosing this scope. - DISubprogram getDISubprogram(MDNode *Scope); + DISubprogram getDISubprogram(const MDNode *Scope); /// getDICompositeType - Find underlying composite type. DICompositeType getDICompositeType(DIType T); @@ -755,20 +769,20 @@ namespace llvm { bool addType(DIType DT); public: - typedef SmallVector<MDNode *, 8>::iterator iterator; - iterator compile_unit_begin() { return CUs.begin(); } - iterator compile_unit_end() { return CUs.end(); } - iterator subprogram_begin() { return SPs.begin(); } - iterator subprogram_end() { return SPs.end(); } - iterator global_variable_begin() { return GVs.begin(); } - iterator global_variable_end() { return GVs.end(); } - iterator type_begin() { return TYs.begin(); } - iterator type_end() { return TYs.end(); } - - unsigned compile_unit_count() { return CUs.size(); } - unsigned global_variable_count() { return GVs.size(); } - unsigned subprogram_count() { return SPs.size(); } - unsigned type_count() { return TYs.size(); } + typedef SmallVector<MDNode *, 8>::const_iterator iterator; + iterator compile_unit_begin() const { return CUs.begin(); } + iterator compile_unit_end() const { return CUs.end(); } + iterator subprogram_begin() const { return SPs.begin(); } + iterator subprogram_end() const { return SPs.end(); } + iterator global_variable_begin() const { return GVs.begin(); } + iterator global_variable_end() const { return GVs.end(); } + iterator type_begin() const { return TYs.begin(); } + iterator type_end() const { return TYs.end(); } + + unsigned compile_unit_count() const { return CUs.size(); } + unsigned global_variable_count() const { return GVs.size(); } + unsigned subprogram_count() const { return SPs.size(); } + unsigned type_count() const { return TYs.size(); } private: SmallVector<MDNode *, 8> CUs; // Compile Units diff --git a/include/llvm/Analysis/InlineCost.h b/include/llvm/Analysis/InlineCost.h index d51dd6c..cac7cfe 100644 --- a/include/llvm/Analysis/InlineCost.h +++ b/include/llvm/Analysis/InlineCost.h @@ -198,6 +198,9 @@ namespace llvm { /// has been inlined. If Callee is NULL it means a dead call has been /// eliminated. void growCachedCostInfo(Function* Caller, Function* Callee); + + /// clear - empty the cache of inline costs + void clear(); }; /// callIsSmall - If a call is likely to lower to a single target instruction, diff --git a/include/llvm/Analysis/Lint.h b/include/llvm/Analysis/Lint.h index 2f01366..eb65d22 100644 --- a/include/llvm/Analysis/Lint.h +++ b/include/llvm/Analysis/Lint.h @@ -38,8 +38,7 @@ FunctionPass *createLintPass(); /// This should only be used for debugging, because it plays games with /// PassManagers and stuff. void lintModule( - const Module &M, ///< The module to be checked - std::string *ErrorInfo = 0 ///< Information about failures. + const Module &M ///< The module to be checked ); // lintFunction - Check a function. diff --git a/include/llvm/Analysis/Passes.h b/include/llvm/Analysis/Passes.h index 1a5cbb2..ce3f7a6 100644 --- a/include/llvm/Analysis/Passes.h +++ b/include/llvm/Analysis/Passes.h @@ -153,6 +153,9 @@ namespace llvm { // print debug info intrinsics in human readable form FunctionPass *createDbgInfoPrinterPass(); + + // Print module-level debug info metadata in human-readable form. + ModulePass *createModuleDebugInfoPrinterPass(); } #endif diff --git a/include/llvm/CallingConv.h b/include/llvm/CallingConv.h index 624390d..b0481b9 100644 --- a/include/llvm/CallingConv.h +++ b/include/llvm/CallingConv.h @@ -74,7 +74,12 @@ namespace CallingConv { ARM_AAPCS_VFP = 68, /// MSP430_INTR - Calling convention used for MSP430 interrupt routines. - MSP430_INTR = 69 + MSP430_INTR = 69, + + /// X86_ThisCall - Similar to X86_StdCall. Passes first argument in ECX, + /// others via stack. Callee is responsible for stack cleaning. MSVC uses + /// this by default for methods in its ABI. + X86_ThisCall = 70 }; } // End CallingConv namespace diff --git a/include/llvm/CodeGen/ELFRelocation.h b/include/llvm/CodeGen/ELFRelocation.h deleted file mode 100644 index e58b8df..0000000 --- a/include/llvm/CodeGen/ELFRelocation.h +++ /dev/null @@ -1,51 +0,0 @@ -//=== ELFRelocation.h - ELF Relocation Info ---------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the ELFRelocation class. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CODEGEN_ELF_RELOCATION_H -#define LLVM_CODEGEN_ELF_RELOCATION_H - -#include "llvm/System/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/FastISel.h b/include/llvm/CodeGen/FastISel.h index 5a2b0e7..005c7bc 100644 --- a/include/llvm/CodeGen/FastISel.h +++ b/include/llvm/CodeGen/FastISel.h @@ -60,6 +60,7 @@ protected: const TargetData &TD; const TargetInstrInfo &TII; const TargetLowering &TLI; + bool IsBottomUp; public: /// startNewBlock - Set the current block to which generated machine @@ -105,7 +106,7 @@ public: /// getRegForGEPIndex - This is a wrapper around getRegForValue that also /// takes care of truncating or sign-extending the given getelementptr /// index value. - unsigned getRegForGEPIndex(const Value *V); + std::pair<unsigned, bool> getRegForGEPIndex(const Value *V); virtual ~FastISel(); @@ -141,7 +142,8 @@ protected: /// virtual unsigned FastEmit_r(MVT VT, MVT RetVT, - unsigned Opcode, unsigned Op0); + unsigned Opcode, + unsigned Op0, bool Op0IsKill); /// FastEmit_rr - This method is called by target-independent code /// to request that an instruction with the given type, opcode, and @@ -150,7 +152,8 @@ protected: virtual unsigned FastEmit_rr(MVT VT, MVT RetVT, unsigned Opcode, - unsigned Op0, unsigned Op1); + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill); /// FastEmit_ri - This method is called by target-independent code /// to request that an instruction with the given type, opcode, and @@ -159,7 +162,8 @@ protected: virtual unsigned FastEmit_ri(MVT VT, MVT RetVT, unsigned Opcode, - unsigned Op0, uint64_t Imm); + unsigned Op0, bool Op0IsKill, + uint64_t Imm); /// FastEmit_rf - This method is called by target-independent code /// to request that an instruction with the given type, opcode, and @@ -168,7 +172,8 @@ protected: virtual unsigned FastEmit_rf(MVT VT, MVT RetVT, unsigned Opcode, - unsigned Op0, const ConstantFP *FPImm); + unsigned Op0, bool Op0IsKill, + const ConstantFP *FPImm); /// FastEmit_rri - This method is called by target-independent code /// to request that an instruction with the given type, opcode, and @@ -177,7 +182,9 @@ protected: virtual unsigned FastEmit_rri(MVT VT, MVT RetVT, unsigned Opcode, - unsigned Op0, unsigned Op1, uint64_t Imm); + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill, + uint64_t Imm); /// FastEmit_ri_ - This method is a wrapper of FastEmit_ri. It first tries /// to emit an instruction with an immediate operand using FastEmit_ri. @@ -185,8 +192,8 @@ protected: /// FastEmit_rr instead. unsigned FastEmit_ri_(MVT VT, unsigned Opcode, - unsigned Op0, uint64_t Imm, - MVT ImmType); + unsigned Op0, bool Op0IsKill, + uint64_t Imm, MVT ImmType); /// FastEmit_rf_ - This method is a wrapper of FastEmit_rf. It first tries /// to emit an instruction with an immediate operand using FastEmit_rf. @@ -194,8 +201,8 @@ protected: /// FastEmit_rr instead. unsigned FastEmit_rf_(MVT VT, unsigned Opcode, - unsigned Op0, const ConstantFP *FPImm, - MVT ImmType); + unsigned Op0, bool Op0IsKill, + const ConstantFP *FPImm, MVT ImmType); /// FastEmit_i - This method is called by target-independent code /// to request that an instruction with the given type, opcode, and @@ -224,35 +231,40 @@ protected: /// unsigned FastEmitInst_r(unsigned MachineInstOpcode, const TargetRegisterClass *RC, - unsigned Op0); + unsigned Op0, bool Op0IsKill); /// FastEmitInst_rr - Emit a MachineInstr with two register operands /// and a result register in the given register class. /// unsigned FastEmitInst_rr(unsigned MachineInstOpcode, const TargetRegisterClass *RC, - unsigned Op0, unsigned Op1); + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill); /// FastEmitInst_ri - Emit a MachineInstr with two register operands /// and a result register in the given register class. /// unsigned FastEmitInst_ri(unsigned MachineInstOpcode, const TargetRegisterClass *RC, - unsigned Op0, uint64_t Imm); + unsigned Op0, bool Op0IsKill, + uint64_t Imm); /// FastEmitInst_rf - Emit a MachineInstr with two register operands /// and a result register in the given register class. /// unsigned FastEmitInst_rf(unsigned MachineInstOpcode, const TargetRegisterClass *RC, - unsigned Op0, const ConstantFP *FPImm); + unsigned Op0, bool Op0IsKill, + const ConstantFP *FPImm); /// FastEmitInst_rri - Emit a MachineInstr with two register operands, /// an immediate, and a result register in the given register class. /// unsigned FastEmitInst_rri(unsigned MachineInstOpcode, const TargetRegisterClass *RC, - unsigned Op0, unsigned Op1, uint64_t Imm); + unsigned Op0, bool Op0IsKill, + unsigned Op1, bool Op1IsKill, + uint64_t Imm); /// FastEmitInst_i - Emit a MachineInstr with a single immediate /// operand, and a result register in the given register class. @@ -263,12 +275,13 @@ protected: /// FastEmitInst_extractsubreg - Emit a MachineInstr for an extract_subreg /// from a specified index of a superregister to a specified type. unsigned FastEmitInst_extractsubreg(MVT RetVT, - unsigned Op0, uint32_t Idx); + unsigned Op0, bool Op0IsKill, + uint32_t Idx); /// FastEmitZExtFromI1 - Emit MachineInstrs to compute the value of Op /// with all but the least significant bit set to zero. unsigned FastEmitZExtFromI1(MVT VT, - unsigned Op); + unsigned Op0, bool Op0IsKill); /// FastEmitBranch - Emit an unconditional branch to the given block, /// unless it is the immediate (fall-through) successor, and update @@ -316,6 +329,9 @@ private: /// called when the value isn't already available in a register and must /// be materialized with new instructions. unsigned materializeRegForValue(const Value *V, MVT VT); + + /// hasTrivialKill - Test whether the given value has exactly one use. + bool hasTrivialKill(const Value *V) const; }; } diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index ba554d3..a5e9dd5 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -95,6 +95,18 @@ namespace ISD { // execution to HANDLER. Many platform-related details also :) EH_RETURN, + // OUTCHAIN = EH_SJLJ_SETJMP(INCHAIN, buffer) + // This corresponds to the eh.sjlj.setjmp intrinsic. + // It takes an input chain and a pointer to the jump buffer as inputs + // and returns an outchain. + EH_SJLJ_SETJMP, + + // OUTCHAIN = EH_SJLJ_LONGJMP(INCHAIN, buffer) + // This corresponds to the eh.sjlj.longjmp intrinsic. + // It takes an input chain and a pointer to the jump buffer as inputs + // and returns an outchain. + EH_SJLJ_LONGJMP, + // TargetConstant* - Like Constant*, but the DAG does not do any folding, // simplification, or lowering of the constant. They are used for constants // which are known to fit in the immediate fields of their users, or for diff --git a/include/llvm/CodeGen/LatencyPriorityQueue.h b/include/llvm/CodeGen/LatencyPriorityQueue.h index 7ac0418..13cebea 100644 --- a/include/llvm/CodeGen/LatencyPriorityQueue.h +++ b/include/llvm/CodeGen/LatencyPriorityQueue.h @@ -17,7 +17,6 @@ #define LATENCY_PRIORITY_QUEUE_H #include "llvm/CodeGen/ScheduleDAG.h" -#include "llvm/ADT/PriorityQueue.h" namespace llvm { class LatencyPriorityQueue; @@ -41,10 +40,11 @@ namespace llvm { std::vector<unsigned> NumNodesSolelyBlocking; /// Queue - The queue. - PriorityQueue<SUnit*, std::vector<SUnit*>, latency_sort> Queue; + std::vector<SUnit*> Queue; + latency_sort Picker; -public: - LatencyPriorityQueue() : Queue(latency_sort(this)) { + public: + LatencyPriorityQueue() : Picker(this) { } void initNodes(std::vector<SUnit> &sunits) { @@ -73,31 +73,13 @@ public: return NumNodesSolelyBlocking[NodeNum]; } - unsigned size() const { return Queue.size(); } - bool empty() const { return Queue.empty(); } - virtual void push(SUnit *U) { - push_impl(U); - } - void push_impl(SUnit *U); - - void push_all(const std::vector<SUnit *> &Nodes) { - for (unsigned i = 0, e = Nodes.size(); i != e; ++i) - push_impl(Nodes[i]); - } + virtual void push(SUnit *U); - SUnit *pop() { - if (empty()) return NULL; - SUnit *V = Queue.top(); - Queue.pop(); - return V; - } + virtual SUnit *pop(); - void remove(SUnit *SU) { - assert(!Queue.empty() && "Not in queue!"); - Queue.erase_one(SU); - } + virtual void remove(SUnit *SU); // ScheduledNode - As nodes are scheduled, we look to see if there are any // successor nodes that have a single unscheduled predecessor. If so, that diff --git a/include/llvm/CodeGen/LinkAllCodegenComponents.h b/include/llvm/CodeGen/LinkAllCodegenComponents.h index 0064776..b4c2f2f 100644 --- a/include/llvm/CodeGen/LinkAllCodegenComponents.h +++ b/include/llvm/CodeGen/LinkAllCodegenComponents.h @@ -46,6 +46,7 @@ namespace { (void) llvm::createBURRListDAGScheduler(NULL, llvm::CodeGenOpt::Default); (void) llvm::createTDRRListDAGScheduler(NULL, llvm::CodeGenOpt::Default); (void) llvm::createSourceListDAGScheduler(NULL,llvm::CodeGenOpt::Default); + (void) llvm::createHybridListDAGScheduler(NULL,llvm::CodeGenOpt::Default); (void) llvm::createTDListDAGScheduler(NULL, llvm::CodeGenOpt::Default); (void) llvm::createFastDAGScheduler(NULL, llvm::CodeGenOpt::Default); (void) llvm::createDefaultScheduler(NULL, llvm::CodeGenOpt::Default); diff --git a/include/llvm/CodeGen/LiveInterval.h b/include/llvm/CodeGen/LiveInterval.h index 70e79ce..637f52b 100644 --- a/include/llvm/CodeGen/LiveInterval.h +++ b/include/llvm/CodeGen/LiveInterval.h @@ -551,10 +551,6 @@ namespace llvm { /// Also remove the value# from value# list. void removeValNo(VNInfo *ValNo); - /// scaleNumbering - Renumber VNI and ranges to provide gaps for new - /// instructions. - void scaleNumbering(unsigned factor); - /// getSize - Returns the sum of sizes of all the LiveRange's. /// unsigned getSize() const; diff --git a/include/llvm/CodeGen/LiveIntervalAnalysis.h b/include/llvm/CodeGen/LiveIntervalAnalysis.h index 351217c..32fa709 100644 --- a/include/llvm/CodeGen/LiveIntervalAnalysis.h +++ b/include/llvm/CodeGen/LiveIntervalAnalysis.h @@ -303,6 +303,12 @@ namespace llvm { SlotIndex MIIdx, MachineOperand& MO, unsigned MOIdx); + /// isPartialRedef - Return true if the specified def at the specific index + /// is partially re-defining the specified live interval. A common case of + /// this is a definition of the sub-register. + bool isPartialRedef(SlotIndex MIIdx, MachineOperand &MO, + LiveInterval &interval); + /// handleVirtualRegisterDef - update intervals for a virtual /// register def void handleVirtualRegisterDef(MachineBasicBlock *MBB, diff --git a/include/llvm/CodeGen/MachineFrameInfo.h b/include/llvm/CodeGen/MachineFrameInfo.h index c7c5300..fe2c298 100644 --- a/include/llvm/CodeGen/MachineFrameInfo.h +++ b/include/llvm/CodeGen/MachineFrameInfo.h @@ -125,6 +125,10 @@ class MachineFrameInfo { /// to builtin \@llvm.frameaddress. bool FrameAddressTaken; + /// ReturnAddressTaken - This boolean keeps track of whether there is a call + /// to builtin \@llvm.returnaddress. + bool ReturnAddressTaken; + /// 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 @@ -152,8 +156,12 @@ class MachineFrameInfo { /// unsigned MaxAlignment; - /// HasCalls - Set to true if this function has any function calls. This is - /// only valid during and after prolog/epilog code insertion. + /// AdjustsStack - Set to true if this function adjusts the stack -- e.g., + /// when calling another function. This is only valid during and after + /// prolog/epilog code insertion. + bool AdjustsStack; + + /// HasCalls - Set to true if this function has any function calls. bool HasCalls; /// StackProtectorIdx - The frame index for the stack protector. @@ -189,6 +197,8 @@ public: StackSize = NumFixedObjects = OffsetAdjustment = MaxAlignment = 0; HasVarSizedObjects = false; FrameAddressTaken = false; + ReturnAddressTaken = false; + AdjustsStack = false; HasCalls = false; StackProtectorIdx = -1; MaxCallFrameSize = 0; @@ -218,6 +228,12 @@ public: bool isFrameAddressTaken() const { return FrameAddressTaken; } void setFrameAddressIsTaken(bool T) { FrameAddressTaken = T; } + /// isReturnAddressTaken - This method may be called any time after instruction + /// selection is complete to determine if there is a call to + /// \@llvm.returnaddress in this function. + bool isReturnAddressTaken() const { return ReturnAddressTaken; } + void setReturnAddressIsTaken(bool s) { ReturnAddressTaken = s; } + /// getObjectIndexBegin - Return the minimum frame object index. /// int getObjectIndexBegin() const { return -NumFixedObjects; } @@ -313,9 +329,13 @@ public: /// 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. - /// + /// AdjustsStack - Return true if this function adjusts the stack -- e.g., + /// when calling another function. This is only valid during and after + /// prolog/epilog code insertion. + bool adjustsStack() const { return AdjustsStack; } + void setAdjustsStack(bool V) { AdjustsStack = V; } + + /// hasCalls - Return true if the current function has any function calls. bool hasCalls() const { return HasCalls; } void setHasCalls(bool V) { HasCalls = V; } diff --git a/include/llvm/CodeGen/MachineFunction.h b/include/llvm/CodeGen/MachineFunction.h index 595872a..409d13ee 100644 --- a/include/llvm/CodeGen/MachineFunction.h +++ b/include/llvm/CodeGen/MachineFunction.h @@ -114,9 +114,14 @@ class MachineFunction { /// unsigned FunctionNumber; - /// The alignment of the function. + /// Alignment - The alignment of the function. unsigned Alignment; + /// CallsSetJmp - True if the function calls setjmp or sigsetjmp. This is used + /// to limit optimizations which cannot reason about the control flow of + /// setjmp. + bool CallsSetJmp; + MachineFunction(const MachineFunction &); // DO NOT IMPLEMENT void operator=(const MachineFunction&); // DO NOT IMPLEMENT public: @@ -181,6 +186,17 @@ public: void EnsureAlignment(unsigned A) { if (Alignment < A) Alignment = A; } + + /// callsSetJmp - Returns true if the function calls setjmp or sigsetjmp. + bool callsSetJmp() const { + return CallsSetJmp; + } + + /// setCallsSetJmp - Set a flag that indicates if there's a call to setjmp or + /// sigsetjmp. + void setCallsSetJmp(bool B) { + CallsSetJmp = B; + } /// getInfo - Keep track of various per-function pieces of information for /// backends that would like to do so. diff --git a/include/llvm/CodeGen/MachineInstr.h b/include/llvm/CodeGen/MachineInstr.h index c4adca1..cf691bb 100644 --- a/include/llvm/CodeGen/MachineInstr.h +++ b/include/llvm/CodeGen/MachineInstr.h @@ -28,6 +28,7 @@ namespace llvm { +template <typename T> class SmallVectorImpl; class AliasAnalysis; class TargetInstrDesc; class TargetInstrInfo; @@ -223,14 +224,33 @@ public: bool isSubregToReg() const { return getOpcode() == TargetOpcode::SUBREG_TO_REG; } + bool isRegSequence() const { + return getOpcode() == TargetOpcode::REG_SEQUENCE; + } /// readsRegister - Return true if the MachineInstr reads the specified /// register. If TargetRegisterInfo is passed, then it also checks if there /// is a read of a super-register. + /// This does not count partial redefines of virtual registers as reads: + /// %reg1024:6 = OP. bool readsRegister(unsigned Reg, const TargetRegisterInfo *TRI = NULL) const { return findRegisterUseOperandIdx(Reg, false, TRI) != -1; } + /// readsVirtualRegister - Return true if the MachineInstr reads the specified + /// virtual register. Take into account that a partial define is a + /// read-modify-write operation. + bool readsVirtualRegister(unsigned Reg) const { + return readsWritesVirtualRegister(Reg).first; + } + + /// readsWritesVirtualRegister - Return a pair of bools (reads, writes) + /// indicating if this instruction reads or writes Reg. This also considers + /// partial defines. + /// If Ops is not null, all operand indices for Reg are added. + std::pair<bool,bool> readsWritesVirtualRegister(unsigned Reg, + SmallVectorImpl<unsigned> *Ops = 0) const; + /// killsRegister - Return true if the MachineInstr kills the specified /// register. If TargetRegisterInfo is passed, then it also checks if there is /// a kill of a super-register. @@ -238,12 +258,19 @@ public: return findRegisterUseOperandIdx(Reg, true, TRI) != -1; } - /// modifiesRegister - Return true if the MachineInstr modifies the + /// definesRegister - Return true if the MachineInstr fully defines the /// specified register. If TargetRegisterInfo is passed, then it also checks /// if there is a def of a super-register. - bool modifiesRegister(unsigned Reg, - const TargetRegisterInfo *TRI = NULL) const { - return findRegisterDefOperandIdx(Reg, false, TRI) != -1; + /// NOTE: It's ignoring subreg indices on virtual registers. + bool definesRegister(unsigned Reg, const TargetRegisterInfo *TRI=NULL) const { + return findRegisterDefOperandIdx(Reg, false, false, TRI) != -1; + } + + /// modifiesRegister - Return true if the MachineInstr modifies (fully define + /// or partially define) the specified register. + /// NOTE: It's ignoring subreg indices on virtual registers. + bool modifiesRegister(unsigned Reg, const TargetRegisterInfo *TRI) const { + return findRegisterDefOperandIdx(Reg, false, true, TRI) != -1; } /// registerDefIsDead - Returns true if the register is dead in this machine @@ -251,7 +278,7 @@ public: /// if there is a dead def of a super-register. bool registerDefIsDead(unsigned Reg, const TargetRegisterInfo *TRI = NULL) const { - return findRegisterDefOperandIdx(Reg, true, TRI) != -1; + return findRegisterDefOperandIdx(Reg, true, false, TRI) != -1; } /// findRegisterUseOperandIdx() - Returns the operand index that is a use of @@ -270,16 +297,18 @@ public: /// findRegisterDefOperandIdx() - Returns the operand index that is a def of /// the specified register or -1 if it is not found. If isDead is true, defs - /// that are not dead are skipped. If TargetRegisterInfo is non-null, then it - /// also checks if there is a def of a super-register. - int findRegisterDefOperandIdx(unsigned Reg, bool isDead = false, + /// that are not dead are skipped. If Overlap is true, then it also looks for + /// defs that merely overlap the specified register. If TargetRegisterInfo is + /// non-null, then it also checks if there is a def of a super-register. + int findRegisterDefOperandIdx(unsigned Reg, + bool isDead = false, bool Overlap = false, const TargetRegisterInfo *TRI = NULL) const; /// findRegisterDefOperand - Wrapper for findRegisterDefOperandIdx, it returns /// a pointer to the MachineOperand rather than an index. MachineOperand *findRegisterDefOperand(unsigned Reg, bool isDead = false, const TargetRegisterInfo *TRI = NULL) { - int Idx = findRegisterDefOperandIdx(Reg, isDead, TRI); + int Idx = findRegisterDefOperandIdx(Reg, isDead, false, TRI); return (Idx == -1) ? NULL : &getOperand(Idx); } @@ -299,6 +328,10 @@ public: /// reference if DefOpIdx is not null. bool isRegTiedToDefOperand(unsigned UseOpIdx, unsigned *DefOpIdx = 0) const; + /// clearKillInfo - Clears kill flags on all operands. + /// + void clearKillInfo(); + /// copyKillDeadInfo - Copies kill / dead operand properties from MI. /// void copyKillDeadInfo(const MachineInstr *MI); @@ -324,7 +357,7 @@ public: /// addRegisterDefined - We have determined MI defines a register. Make sure /// there is an operand defining Reg. void addRegisterDefined(unsigned IncomingReg, - const TargetRegisterInfo *RegInfo); + const TargetRegisterInfo *RegInfo = 0); /// isSafeToMove - Return true if it is safe to move this instruction. If /// SawStore is set to true, it means that there is a store (or call) between diff --git a/include/llvm/CodeGen/MachineRegisterInfo.h b/include/llvm/CodeGen/MachineRegisterInfo.h index b377dec..fa14fdc 100644 --- a/include/llvm/CodeGen/MachineRegisterInfo.h +++ b/include/llvm/CodeGen/MachineRegisterInfo.h @@ -93,6 +93,20 @@ public: /// specified register (it may be live-in). bool reg_empty(unsigned RegNo) const { return reg_begin(RegNo) == reg_end(); } + /// reg_nodbg_iterator/reg_nodbg_begin/reg_nodbg_end - Walk all defs and uses + /// of the specified register, skipping those marked as Debug. + typedef defusechain_iterator<true,true,true> reg_nodbg_iterator; + reg_nodbg_iterator reg_nodbg_begin(unsigned RegNo) const { + return reg_nodbg_iterator(getRegUseDefListHead(RegNo)); + } + static reg_nodbg_iterator reg_nodbg_end() { return reg_nodbg_iterator(0); } + + /// reg_nodbg_empty - Return true if the only instructions using or defining + /// Reg are Debug instructions. + bool reg_nodbg_empty(unsigned RegNo) const { + return reg_nodbg_begin(RegNo) == reg_nodbg_end(); + } + /// def_iterator/def_begin/def_end - Walk all defs of the specified register. typedef defusechain_iterator<false,true,false> def_iterator; def_iterator def_begin(unsigned RegNo) const { @@ -162,6 +176,12 @@ public: /// register or null if none is found. This assumes that the code is in SSA /// form, so there should only be one definition. MachineInstr *getVRegDef(unsigned Reg) const; + + /// clearKillFlags - Iterate over all the uses of the given register and + /// clear the kill flag from the MachineOperand. This function is used by + /// optimization passes which extend register lifetimes and need only + /// preserve conservative kill flag information. + void clearKillFlags(unsigned Reg) const; #ifndef NDEBUG void dumpUses(unsigned RegNo) const; @@ -196,7 +216,8 @@ public: /// getRegClassVirtRegs - Return the list of virtual registers of the given /// target register class. - std::vector<unsigned> &getRegClassVirtRegs(const TargetRegisterClass *RC) { + const std::vector<unsigned> & + getRegClassVirtRegs(const TargetRegisterClass *RC) const { return RegClass2VRegMap[RC->getID()]; } @@ -229,11 +250,18 @@ public: /// 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; } - + + /// addPhysRegsUsed - Mark the specified registers used in this function. + /// This should only be called during and after register allocation. + void addPhysRegsUsed(const BitVector &Regs) { UsedPhysRegs |= Regs; } + /// 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; } - + + /// closePhysRegsUsed - Expand UsedPhysRegs to its transitive closure over + /// subregisters. That means that if R is used, so are all subregisters. + void closePhysRegsUsed(const TargetRegisterInfo&); //===--------------------------------------------------------------------===// // LiveIn/LiveOut Management @@ -265,6 +293,10 @@ public: /// corresponding live-in physical register. unsigned getLiveInPhysReg(unsigned VReg) const; + /// getLiveInVirtReg - If PReg is a live-in physical register, return the + /// corresponding live-in physical register. + unsigned getLiveInVirtReg(unsigned PReg) const; + /// EmitLiveInCopies - Emit copies to initialize livein virtual registers /// into the given entry block. void EmitLiveInCopies(MachineBasicBlock *EntryMBB, diff --git a/include/llvm/CodeGen/MachineSSAUpdater.h b/include/llvm/CodeGen/MachineSSAUpdater.h index 979ef01..cbb45a7 100644 --- a/include/llvm/CodeGen/MachineSSAUpdater.h +++ b/include/llvm/CodeGen/MachineSSAUpdater.h @@ -23,6 +23,7 @@ namespace llvm { class TargetInstrInfo; class TargetRegisterClass; template<typename T> class SmallVectorImpl; + template<typename T> class SSAUpdaterTraits; class BumpPtrAllocator; /// MachineSSAUpdater - This class updates SSA form for a set of virtual @@ -30,9 +31,7 @@ namespace llvm { /// or another unstructured transformation wants to rewrite a set of uses of one /// vreg with uses of a set of vregs. class MachineSSAUpdater { -public: - class BBInfo; - typedef SmallVectorImpl<BBInfo*> BlockListTy; + friend class SSAUpdaterTraits<MachineSSAUpdater>; private: /// AvailableVals - This keeps track of which value to use on a per-block @@ -40,11 +39,6 @@ private: //typedef DenseMap<MachineBasicBlock*, unsigned > AvailableValsTy; void *AV; - /// BBMap - The GetValueAtEndOfBlock method maintains this mapping from - /// basic blocks to BBInfo structures. - /// typedef DenseMap<MachineBasicBlock*, BBInfo*> BBMapTy; - void *BM; - /// VR - Current virtual register whose uses are being updated. unsigned VR; @@ -111,14 +105,6 @@ public: private: void ReplaceRegWith(unsigned OldReg, unsigned NewReg); unsigned GetValueAtEndOfBlockInternal(MachineBasicBlock *BB); - void BuildBlockList(MachineBasicBlock *BB, BlockListTy *BlockList, - BumpPtrAllocator *Allocator); - void FindDominators(BlockListTy *BlockList); - void FindPHIPlacement(BlockListTy *BlockList); - void FindAvailableVals(BlockListTy *BlockList); - void FindExistingPHI(MachineBasicBlock *BB, BlockListTy *BlockList); - bool CheckIfPHIMatches(MachineInstr *PHI); - void RecordMatchingPHI(MachineInstr *PHI); void operator=(const MachineSSAUpdater&); // DO NOT IMPLEMENT MachineSSAUpdater(const MachineSSAUpdater&); // DO NOT IMPLEMENT diff --git a/include/llvm/CodeGen/ScheduleDAG.h b/include/llvm/CodeGen/ScheduleDAG.h index 7c025e3..076268b 100644 --- a/include/llvm/CodeGen/ScheduleDAG.h +++ b/include/llvm/CodeGen/ScheduleDAG.h @@ -16,6 +16,7 @@ #define LLVM_CODEGEN_SCHEDULEDAG_H #include "llvm/CodeGen/MachineBasicBlock.h" +#include "llvm/Target/TargetMachine.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/BitVector.h" #include "llvm/ADT/GraphTraits.h" @@ -34,7 +35,6 @@ namespace llvm { class SDNode; class TargetInstrInfo; class TargetInstrDesc; - class TargetLowering; class TargetMachine; class TargetRegisterClass; template<class Graph> class GraphWriter; @@ -226,7 +226,6 @@ namespace llvm { private: SDNode *Node; // Representative node. MachineInstr *Instr; // Alternatively, a MachineInstr. - MachineInstr *DbgInstr; // A dbg_value referencing this. public: SUnit *OrigNode; // If not this, the node from which // this node was cloned. @@ -240,7 +239,7 @@ namespace llvm { typedef SmallVector<SDep, 4>::iterator succ_iterator; typedef SmallVector<SDep, 4>::const_iterator const_pred_iterator; typedef SmallVector<SDep, 4>::const_iterator const_succ_iterator; - + unsigned NodeNum; // Entry # of node in the node vector. unsigned NodeQueueId; // Queue id of node. unsigned short Latency; // Node latency. @@ -257,6 +256,9 @@ namespace llvm { bool isScheduled : 1; // True once scheduled. bool isScheduleHigh : 1; // True if preferable to schedule high. bool isCloned : 1; // True if this node has been cloned. + Sched::Preference SchedulingPref; // Scheduling preference. + + SmallVector<MachineInstr*, 4> DbgInstrList; // dbg_values referencing this. private: bool isDepthCurrent : 1; // True if Depth is current. bool isHeightCurrent : 1; // True if Height is current. @@ -269,35 +271,38 @@ namespace llvm { /// SUnit - Construct an SUnit for pre-regalloc scheduling to represent /// an SDNode and any nodes flagged to it. SUnit(SDNode *node, unsigned nodenum) - : Node(node), Instr(0), DbgInstr(0), OrigNode(0), NodeNum(nodenum), + : Node(node), Instr(0), OrigNode(0), NodeNum(nodenum), NodeQueueId(0), Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0), isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), isAvailable(false), isScheduled(false), isScheduleHigh(false), isCloned(false), + SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), CopyDstRC(NULL), CopySrcRC(NULL) {} /// SUnit - Construct an SUnit for post-regalloc scheduling to represent /// a MachineInstr. SUnit(MachineInstr *instr, unsigned nodenum) - : Node(0), Instr(instr), DbgInstr(0), OrigNode(0), NodeNum(nodenum), + : Node(0), Instr(instr), OrigNode(0), NodeNum(nodenum), NodeQueueId(0), Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0), isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), isAvailable(false), isScheduled(false), isScheduleHigh(false), isCloned(false), + SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), CopyDstRC(NULL), CopySrcRC(NULL) {} /// SUnit - Construct a placeholder SUnit. SUnit() - : Node(0), Instr(0), DbgInstr(0), OrigNode(0), NodeNum(~0u), + : Node(0), Instr(0), OrigNode(0), NodeNum(~0u), NodeQueueId(0), Latency(0), NumPreds(0), NumSuccs(0), NumPredsLeft(0), NumSuccsLeft(0), isTwoAddress(false), isCommutable(false), hasPhysRegDefs(false), hasPhysRegClobbers(false), isPending(false), isAvailable(false), isScheduled(false), isScheduleHigh(false), isCloned(false), + SchedulingPref(Sched::None), isDepthCurrent(false), isHeightCurrent(false), Depth(0), Height(0), CopyDstRC(NULL), CopySrcRC(NULL) {} @@ -329,20 +334,6 @@ namespace llvm { return Instr; } - /// setDbgInstr - Assign the debug instruction for the SUnit. - /// This may be used during post-regalloc scheduling. - void setDbgInstr(MachineInstr *MI) { - assert(!Node && "Setting debug MachineInstr of SUnit with SDNode!"); - DbgInstr = MI; - } - - /// getDbgInstr - Return the debug MachineInstr for this SUnit. - /// This may be used during post-regalloc scheduling. - MachineInstr *getDbgInstr() const { - assert(!Node && "Reading debug MachineInstr of SUnit with SDNode!"); - return DbgInstr; - } - /// addPred - This adds the specified edge as a pred of the current node if /// not already. It also adds the current node as a successor of the /// specified node. @@ -404,7 +395,7 @@ namespace llvm { return true; return false; } - + void dump(const ScheduleDAG *G) const; void dumpAll(const ScheduleDAG *G) const; void print(raw_ostream &O, const ScheduleDAG *G) const; @@ -423,7 +414,9 @@ namespace llvm { /// implementation to decide. /// class SchedulingPriorityQueue { + unsigned CurCycle; public: + SchedulingPriorityQueue() : CurCycle(0) {} virtual ~SchedulingPriorityQueue() {} virtual void initNodes(std::vector<SUnit> &SUnits) = 0; @@ -431,11 +424,15 @@ namespace llvm { virtual void updateNode(const SUnit *SU) = 0; virtual void releaseState() = 0; - virtual unsigned size() const = 0; virtual bool empty() const = 0; virtual void push(SUnit *U) = 0; - virtual void push_all(const std::vector<SUnit *> &Nodes) = 0; + void push_all(const std::vector<SUnit *> &Nodes) { + for (std::vector<SUnit *>::const_iterator I = Nodes.begin(), + E = Nodes.end(); I != E; ++I) + push(*I); + } + virtual SUnit *pop() = 0; virtual void remove(SUnit *SU) = 0; @@ -447,6 +444,14 @@ namespace llvm { virtual void ScheduledNode(SUnit *) {} virtual void UnscheduledNode(SUnit *) {} + + void setCurCycle(unsigned Cycle) { + CurCycle = Cycle; + } + + unsigned getCurCycle() const { + return CurCycle; + } }; class ScheduleDAG { @@ -456,7 +461,6 @@ namespace llvm { const TargetMachine &TM; // Target processor const TargetInstrInfo *TII; // Target instruction information const TargetRegisterInfo *TRI; // Target processor register info - const TargetLowering *TLI; // Target lowering info MachineFunction &MF; // Machine function MachineRegisterInfo &MRI; // Virtual/real register map std::vector<SUnit*> Sequence; // The schedule. Null SUnit*'s diff --git a/include/llvm/CodeGen/SchedulerRegistry.h b/include/llvm/CodeGen/SchedulerRegistry.h index cf3274f..14c33e2 100644 --- a/include/llvm/CodeGen/SchedulerRegistry.h +++ b/include/llvm/CodeGen/SchedulerRegistry.h @@ -73,11 +73,17 @@ ScheduleDAGSDNodes *createBURRListDAGScheduler(SelectionDAGISel *IS, ScheduleDAGSDNodes *createTDRRListDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level OptLevel); -/// createBURRListDAGScheduler - This creates a bottom up register usage -/// reduction list scheduler that schedules in source code order when possible. +/// createBURRListDAGScheduler - This creates a bottom up list scheduler that +/// schedules nodes in source code order when possible. ScheduleDAGSDNodes *createSourceListDAGScheduler(SelectionDAGISel *IS, CodeGenOpt::Level OptLevel); +/// createHybridListDAGScheduler - This creates a bottom up hybrid register +/// usage reduction list scheduler that make use of latency information to +/// avoid stalls for long latency instructions. +ScheduleDAGSDNodes *createHybridListDAGScheduler(SelectionDAGISel *IS, + CodeGenOpt::Level); + /// createTDListDAGScheduler - This creates a top-down list scheduler with /// a hazard recognizer. ScheduleDAGSDNodes *createTDListDAGScheduler(SelectionDAGISel *IS, diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index ae15230..97202bd 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -36,6 +36,7 @@ class MDNode; class SDNodeOrdering; class SDDbgValue; class TargetLowering; +class TargetSelectionDAGInfo; template<> struct ilist_traits<SDNode> : public ilist_default_traits<SDNode> { private: @@ -131,6 +132,7 @@ void checkForCycles(const SelectionDAG *DAG); class SelectionDAG { const TargetMachine &TM; const TargetLowering &TLI; + const TargetSelectionDAGInfo &TSI; MachineFunction *MF; FunctionLoweringInfo &FLI; LLVMContext *Context; @@ -201,6 +203,7 @@ public: MachineFunction &getMachineFunction() const { return *MF; } const TargetMachine &getTarget() const { return TM; } const TargetLowering &getTargetLoweringInfo() const { return TLI; } + const TargetSelectionDAGInfo &getSelectionDAGInfo() const { return TSI; } FunctionLoweringInfo &getFunctionLoweringInfo() const { return FLI; } LLVMContext *getContext() const {return Context; } @@ -334,6 +337,8 @@ public: SDValue getTargetConstant(const ConstantInt &Val, EVT VT) { return getConstant(Val, VT, true); } + // The forms below that take a double should only be used for simple + // constants that can be exactly represented in VT. No checks are made. SDValue getConstantFP(double Val, EVT VT, bool isTarget = false); SDValue getConstantFP(const APFloat& Val, EVT VT, bool isTarget = false); SDValue getConstantFP(const ConstantFP &CF, EVT VT, bool isTarget = false); diff --git a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h index 90905f5..3aaab88 100644 --- a/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h +++ b/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h @@ -84,6 +84,23 @@ public: class TargetLoweringObjectFileMachO : public TargetLoweringObjectFile { + /// TLSDataSection - Section for thread local data. + /// + const MCSection *TLSDataSection; // Defaults to ".tdata". + + /// TLSBSSSection - Section for thread local uninitialized data. + /// + const MCSection *TLSBSSSection; // Defaults to ".tbss". + + /// TLSTLVSection - Section for thread local structure infomation. + /// Contains the source code name of the variable, visibility and a pointer + /// to the initial value (.tdata or .tbss). + const MCSection *TLSTLVSection; // Defaults to ".tlv". + + /// TLSThreadInitSection - Section for thread local data initialization + /// functions. + const MCSection *TLSThreadInitSection; // Defaults to ".thread_init_func". + const MCSection *CStringSection; const MCSection *UStringSection; const MCSection *TextCoalSection; @@ -161,13 +178,15 @@ public: class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile { - mutable void *UniquingMap; + const MCSection *DrectveSection; public: - TargetLoweringObjectFileCOFF() : UniquingMap(0) {} - ~TargetLoweringObjectFileCOFF(); + TargetLoweringObjectFileCOFF() {} + ~TargetLoweringObjectFileCOFF() {} virtual void Initialize(MCContext &Ctx, const TargetMachine &TM); + virtual const MCSection *getDrectveSection() const { return DrectveSection; } + virtual const MCSection * getExplicitSectionGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const; @@ -175,11 +194,6 @@ public: virtual const MCSection * SelectSectionForGlobal(const GlobalValue *GV, SectionKind Kind, Mangler *Mang, const TargetMachine &TM) const; - - /// getCOFFSection - Return the MCSection for the specified COFF section. - /// FIXME: Switch this to a semantic view eventually. - const MCSection *getCOFFSection(StringRef Name, bool isDirective, - SectionKind K) const; }; } // end namespace llvm diff --git a/include/llvm/CodeGen/ValueTypes.h b/include/llvm/CodeGen/ValueTypes.h index a7aafc0..6e2a102 100644 --- a/include/llvm/CodeGen/ValueTypes.h +++ b/include/llvm/CodeGen/ValueTypes.h @@ -63,21 +63,22 @@ namespace llvm { v1i64 = 24, // 1 x i64 v2i64 = 25, // 2 x i64 v4i64 = 26, // 4 x i64 + v8i64 = 27, // 8 x i64 - v2f32 = 27, // 2 x f32 - v4f32 = 28, // 4 x f32 - v8f32 = 29, // 8 x f32 - v2f64 = 30, // 2 x f64 - v4f64 = 31, // 4 x f64 + v2f32 = 28, // 2 x f32 + v4f32 = 29, // 4 x f32 + v8f32 = 30, // 8 x f32 + v2f64 = 31, // 2 x f64 + v4f64 = 32, // 4 x f64 FIRST_VECTOR_VALUETYPE = v2i8, LAST_VECTOR_VALUETYPE = v4f64, - Flag = 32, // This glues nodes together during pre-RA sched + Flag = 33, // This glues nodes together during pre-RA sched - isVoid = 33, // This has no value + isVoid = 34, // This has no value - LAST_VALUETYPE = 34, // This always remains at the end of the list. + LAST_VALUETYPE = 35, // This always remains at the end of the list. // This is the current maximum for LAST_VALUETYPE. // EVT::MAX_ALLOWED_VALUETYPE is used for asserts and to size bit vectors @@ -140,7 +141,7 @@ namespace llvm { bool isInteger() const { return ((SimpleTy >= MVT::FIRST_INTEGER_VALUETYPE && SimpleTy <= MVT::LAST_INTEGER_VALUETYPE) || - (SimpleTy >= MVT::v2i8 && SimpleTy <= MVT::v4i64)); + (SimpleTy >= MVT::v2i8 && SimpleTy <= MVT::v8i64)); } /// isVector - Return true if this is a vector value type. @@ -192,7 +193,8 @@ namespace llvm { case v8i32: return i32; case v1i64: case v2i64: - case v4i64: return i64; + case v4i64: + case v8i64: return i64; case v2f32: case v4f32: case v8f32: return f32; @@ -211,6 +213,7 @@ namespace llvm { case v8i8 : case v8i16: case v8i32: + case v8i64: case v8f32: return 8; case v4i8: case v4i16: @@ -269,6 +272,7 @@ namespace llvm { case v4i64: case v8f32: case v4f64: return 256; + case v8i64: return 512; } } @@ -332,6 +336,7 @@ namespace llvm { if (NumElements == 1) return MVT::v1i64; if (NumElements == 2) return MVT::v2i64; if (NumElements == 4) return MVT::v4i64; + if (NumElements == 8) return MVT::v8i64; break; case MVT::f32: if (NumElements == 2) return MVT::v2f32; @@ -468,10 +473,15 @@ namespace llvm { /// is256BitVector - Return true if this is a 256-bit vector type. inline bool is256BitVector() const { - return isSimple() ? - (V==MVT::v8f32 || V==MVT::v4f64 || V==MVT::v32i8 || - V==MVT::v16i16 || V==MVT::v8i32 || V==MVT::v4i64) : - isExtended256BitVector(); + return isSimple() + ? (V==MVT::v8f32 || V==MVT::v4f64 || V==MVT::v32i8 || + V==MVT::v16i16 || V==MVT::v8i32 || V==MVT::v4i64) + : isExtended256BitVector(); + } + + /// is512BitVector - Return true if this is a 512-bit vector type. + inline bool is512BitVector() const { + return isSimple() ? (V == MVT::v8i64) : isExtended512BitVector(); } /// isOverloaded - Return true if this is an overloaded type for TableGen. @@ -668,6 +678,7 @@ namespace llvm { bool isExtended64BitVector() const; bool isExtended128BitVector() const; bool isExtended256BitVector() const; + bool isExtended512BitVector() const; EVT getExtendedVectorElementType() const; unsigned getExtendedVectorNumElements() const; unsigned getExtendedSizeInBits() const; diff --git a/include/llvm/CodeGen/ValueTypes.td b/include/llvm/CodeGen/ValueTypes.td index c8bb789..8151c0b 100644 --- a/include/llvm/CodeGen/ValueTypes.td +++ b/include/llvm/CodeGen/ValueTypes.td @@ -47,15 +47,16 @@ def v8i32 : ValueType<256, 23>; // 8 x i32 vector value def v1i64 : ValueType<64 , 24>; // 1 x i64 vector value def v2i64 : ValueType<128, 25>; // 2 x i64 vector value def v4i64 : ValueType<256, 26>; // 4 x f64 vector value +def v8i64 : ValueType<512, 27>; // 4 x f64 vector value -def v2f32 : ValueType<64, 27>; // 2 x f32 vector value -def v4f32 : ValueType<128, 28>; // 4 x f32 vector value -def v8f32 : ValueType<256, 29>; // 8 x f32 vector value -def v2f64 : ValueType<128, 30>; // 2 x f64 vector value -def v4f64 : ValueType<256, 31>; // 4 x f64 vector value +def v2f32 : ValueType<64, 28>; // 2 x f32 vector value +def v4f32 : ValueType<128, 29>; // 4 x f32 vector value +def v8f32 : ValueType<256, 30>; // 8 x f32 vector value +def v2f64 : ValueType<128, 31>; // 2 x f64 vector value +def v4f64 : ValueType<256, 32>; // 4 x f64 vector value -def FlagVT : ValueType<0 , 32>; // Pre-RA sched glue -def isVoid : ValueType<0 , 33>; // Produces no value +def FlagVT : ValueType<0 , 33>; // Pre-RA sched glue +def isVoid : ValueType<0 , 34>; // Produces no value def MetadataVT: ValueType<0, 250>; // Metadata diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index adbcc11..e7594ba 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -312,6 +312,9 @@ /* Define to 1 if you have the `roundf' function. */ #undef HAVE_ROUNDF +/* Define to 1 if you have the `round' function. */ +#cmakedefine HAVE_ROUND ${HAVE_ROUND} + /* Define to 1 if you have the `sbrk' function. */ #cmakedefine HAVE_SBRK ${HAVE_SBRK} diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index c2ab23e..99d2ab5 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -24,6 +24,9 @@ /* Define if threads enabled */ #undef ENABLE_THREADS +/* Define if timestamp information (e.g., __DATE___) is allowed */ +#undef ENABLE_TIMESTAMPS + /* Define to 1 if you have the `argz_append' function. */ #undef HAVE_ARGZ_APPEND diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index 1cebb20..9ca845e 100644 --- a/include/llvm/Constants.h +++ b/include/llvm/Constants.h @@ -691,9 +691,6 @@ public: // ConstantExpr class, because they will attempt to fold the constant // expression into something simpler if possible. - /// Cast constant expr - /// - /// getAlignOf constant expr - computes the alignment of a type in a target /// independent way (Note: the return type is an i64). static Constant *getAlignOf(const Type* Ty); @@ -926,7 +923,11 @@ DEFINE_TRANSPARENT_CASTED_OPERAND_ACCESSORS(ConstantExpr, Constant) /// 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. +/// any first-class type. +/// +/// Undef values aren't exactly constants; if they have multiple uses, they +/// can appear to have different bit patterns at each use. See +/// LangRef.html#undefvalues for details. /// class UndefValue : public Constant { friend struct ConstantCreator<UndefValue, Type, char>; @@ -957,6 +958,7 @@ public: return V->getValueID() == UndefValueVal; } }; + } // End llvm namespace #endif diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td index 8bbfd77..2b4df54 100644 --- a/include/llvm/Intrinsics.td +++ b/include/llvm/Intrinsics.td @@ -306,11 +306,13 @@ def int_eh_unwind_init: Intrinsic<[]>, def int_eh_dwarf_cfa : Intrinsic<[llvm_ptr_ty], [llvm_i32_ty]>; let Properties = [IntrNoMem] in { - def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>; - def int_eh_sjlj_longjmp : Intrinsic<[], [llvm_ptr_ty]>; def int_eh_sjlj_lsda : Intrinsic<[llvm_ptr_ty]>; def int_eh_sjlj_callsite: Intrinsic<[], [llvm_i32_ty]>; } +def int_eh_sjlj_setjmp : Intrinsic<[llvm_i32_ty], [llvm_ptr_ty]>, + GCCBuiltin<"__builtin_setjmp">; +def int_eh_sjlj_longjmp : Intrinsic<[], [llvm_ptr_ty]>, + GCCBuiltin<"__builtin_longjmp">; //===---------------- Generic Variable Attribute Intrinsics----------------===// // diff --git a/include/llvm/IntrinsicsX86.td b/include/llvm/IntrinsicsX86.td index 3ca9cb4..cea4856 100644 --- a/include/llvm/IntrinsicsX86.td +++ b/include/llvm/IntrinsicsX86.td @@ -786,9 +786,9 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_aesni_aesdeclast : GCCBuiltin<"__builtin_ia32_aesdeclast128">, Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_v2i64_ty], [IntrNoMem]>; - def int_x86_aesni_aeskeygenassist : + def int_x86_aesni_aeskeygenassist : GCCBuiltin<"__builtin_ia32_aeskeygenassist128">, - Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i32_ty], + Intrinsic<[llvm_v2i64_ty], [llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; } diff --git a/include/llvm/LinkAllPasses.h b/include/llvm/LinkAllPasses.h index 1e2c37a..c2375ea 100644 --- a/include/llvm/LinkAllPasses.h +++ b/include/llvm/LinkAllPasses.h @@ -132,12 +132,14 @@ namespace { (void) llvm::createPrintModulePass(0); (void) llvm::createPrintFunctionPass("", 0); (void) llvm::createDbgInfoPrinterPass(); + (void) llvm::createModuleDebugInfoPrinterPass(); (void) llvm::createPartialInliningPass(); (void) llvm::createSSIPass(); (void) llvm::createSSIEverythingPass(); (void) llvm::createGEPSplitterPass(); (void) llvm::createABCDPass(); (void) llvm::createLintPass(); + (void) llvm::createSinkingPass(); (void)new llvm::IntervalPartition(); (void)new llvm::FindUsedTypes(); diff --git a/include/llvm/MC/MCAsmInfo.h b/include/llvm/MC/MCAsmInfo.h index f57f642..8516de0 100644 --- a/include/llvm/MC/MCAsmInfo.h +++ b/include/llvm/MC/MCAsmInfo.h @@ -41,6 +41,10 @@ namespace llvm { /// the macho-specific .zerofill directive for emitting BSS Symbols. bool HasMachoZeroFillDirective; // Default is false. + /// HasMachoTBSSDirective - True if this is a MachO target that supports + /// the macho-specific .tbss directive for emitting thread local BSS Symbols + bool HasMachoTBSSDirective; // Default is false. + /// HasStaticCtorDtorReferenceInStaticMode - True if the compiler should /// emit a ".reference .constructors_used" or ".reference .destructors_used" /// directive after the a static ctor/dtor list. This directive is only @@ -303,6 +307,7 @@ namespace llvm { // Accessors. // bool hasMachoZeroFillDirective() const { return HasMachoZeroFillDirective; } + bool hasMachoTBSSDirective() const { return HasMachoTBSSDirective; } bool hasStaticCtorDtorReferenceInStaticMode() const { return HasStaticCtorDtorReferenceInStaticMode; } diff --git a/include/llvm/MC/MCAsmLayout.h b/include/llvm/MC/MCAsmLayout.h index ebf0520..b9565ba 100644 --- a/include/llvm/MC/MCAsmLayout.h +++ b/include/llvm/MC/MCAsmLayout.h @@ -10,6 +10,8 @@ #ifndef LLVM_MC_MCASMLAYOUT_H #define LLVM_MC_MCASMLAYOUT_H +#include "llvm/ADT/SmallVector.h" + namespace llvm { class MCAssembler; class MCFragment; @@ -24,11 +26,30 @@ class MCSymbolData; /// efficiently compute the exact addresses of any symbol in the assembly file, /// even during the relaxation process. class MCAsmLayout { +public: + typedef llvm::SmallVectorImpl<MCSectionData*>::const_iterator const_iterator; + typedef llvm::SmallVectorImpl<MCSectionData*>::iterator iterator; + private: MCAssembler &Assembler; + /// List of sections in layout order. + llvm::SmallVector<MCSectionData*, 16> SectionOrder; + + /// The last fragment which was layed out, or 0 if nothing has been layed + /// out. Fragments are always layed out in order, so all fragments with a + /// lower ordinal will be up to date. + mutable MCFragment *LastValidFragment; + + /// \brief Make sure that the layout for the given fragment is valid, lazily + /// computing it if necessary. + void EnsureValid(const MCFragment *F) const; + + bool isSectionUpToDate(const MCSectionData *SD) const; + bool isFragmentUpToDate(const MCFragment *F) const; + public: - MCAsmLayout(MCAssembler &_Assembler) : Assembler(_Assembler) {} + MCAsmLayout(MCAssembler &_Assembler); /// Get the assembler object this is a layout for. MCAssembler &getAssembler() const { return Assembler; } @@ -38,6 +59,33 @@ public: /// the delta from the old size. void UpdateForSlide(MCFragment *F, int SlideAmount); + /// \brief Update the layout because a fragment has been replaced. + void FragmentReplaced(MCFragment *Src, MCFragment *Dst); + + /// \brief Perform a full layout. + void LayoutFile(); + + /// \brief Perform layout for a single fragment, assuming that the previous + /// fragment has already been layed out correctly, and the parent section has + /// been initialized. + void LayoutFragment(MCFragment *Fragment); + + /// \brief Performs initial layout for a single section, assuming that the + /// previous section (including its fragments) has already been layed out + /// correctly. + void LayoutSection(MCSectionData *SD); + + /// @name Section Access (in layout order) + /// @{ + + llvm::SmallVectorImpl<MCSectionData*> &getSectionOrder() { + return SectionOrder; + } + const llvm::SmallVectorImpl<MCSectionData*> &getSectionOrder() const { + return SectionOrder; + } + + /// @} /// @name Fragment Layout Data /// @{ @@ -45,15 +93,9 @@ public: /// current layout. uint64_t getFragmentEffectiveSize(const MCFragment *F) const; - /// \brief Set the effective size of the given fragment. - void setFragmentEffectiveSize(MCFragment *F, uint64_t Value); - /// \brief Get the offset of the given fragment inside its containing section. uint64_t getFragmentOffset(const MCFragment *F) const; - /// \brief Set the offset of the given fragment inside its containing section. - void setFragmentOffset(MCFragment *F, uint64_t Value); - /// @} /// @name Section Layout Data /// @{ @@ -61,22 +103,6 @@ public: /// \brief Get the computed address of the given section. uint64_t getSectionAddress(const MCSectionData *SD) const; - /// \brief Set the computed address of the given section. - void setSectionAddress(MCSectionData *SD, uint64_t Value); - - /// \brief Get the data size of the given section, as emitted to the object - /// file. This may include additional padding, or be 0 for virtual sections. - uint64_t getSectionFileSize(const MCSectionData *SD) const; - - /// \brief Set the data size of the given section. - void setSectionFileSize(MCSectionData *SD, uint64_t Value); - - /// \brief Get the actual data size of the given section. - uint64_t getSectionSize(const MCSectionData *SD) const; - - /// \brief Set the actual data size of the given section. - void setSectionSize(MCSectionData *SD, uint64_t Value); - /// @} /// @name Utility Functions /// @{ @@ -85,6 +111,18 @@ public: /// layout. uint64_t getFragmentAddress(const MCFragment *F) const; + /// \brief Get the address space size of the given section, as it effects + /// layout. This may differ from the size reported by \see getSectionSize() by + /// not including section tail padding. + uint64_t getSectionAddressSize(const MCSectionData *SD) const; + + /// \brief Get the data size of the given section, as emitted to the object + /// file. This may include additional padding, or be 0 for virtual sections. + uint64_t getSectionFileSize(const MCSectionData *SD) const; + + /// \brief Get the logical data size of the given section. + uint64_t getSectionSize(const MCSectionData *SD) const; + /// \brief Get the address of the given symbol, as computed in the current /// layout. uint64_t getSymbolAddress(const MCSymbolData *SD) const; diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h index c1b60f0..d9963ec 100644 --- a/include/llvm/MC/MCAssembler.h +++ b/include/llvm/MC/MCAssembler.h @@ -32,30 +32,10 @@ class MCObjectWriter; class MCSection; class MCSectionData; class MCSymbol; +class MCSymbolData; class MCValue; class TargetAsmBackend; -/// MCAsmFixup - Represent a fixed size region of bytes inside some fragment -/// which needs to be rewritten. This region will either be rewritten by the -/// assembler or cause a relocation entry to be generated. -// -// FIXME: This should probably just be merged with MCFixup. -class MCAsmFixup { -public: - /// Offset - The offset inside the fragment which needs to be rewritten. - uint64_t Offset; - - /// Value - The expression to eventually write into the fragment. - const MCExpr *Value; - - /// Kind - The fixup kind. - MCFixupKind Kind; - -public: - MCAsmFixup(uint64_t _Offset, const MCExpr &_Value, MCFixupKind _Kind) - : Offset(_Offset), Value(&_Value), Kind(_Kind) {} -}; - class MCFragment : public ilist_node<MCFragment> { friend class MCAsmLayout; @@ -68,8 +48,7 @@ public: FT_Data, FT_Fill, FT_Inst, - FT_Org, - FT_ZeroFill + FT_Org }; private: @@ -78,6 +57,11 @@ private: /// Parent - The data for the section this fragment is in. MCSectionData *Parent; + /// Atom - The atom this fragment is in, as represented by it's defining + /// symbol. Atom's are only used by backends which set + /// \see MCAsmBackend::hasReliableSymbolDifference(). + MCSymbolData *Atom; + /// @name Assembler Backend Data /// @{ // @@ -91,9 +75,9 @@ private: /// initialized. uint64_t EffectiveSize; - /// Ordinal - The global index of this fragment. This is the index across all - /// sections, not just the parent section. - unsigned Ordinal; + /// LayoutOrder - The global layout order of this fragment. This is the index + /// across all fragments in the file, not just within the section. + unsigned LayoutOrder; /// @} @@ -103,30 +87,32 @@ protected: public: // Only for sentinel. MCFragment(); - virtual ~MCFragment(); FragmentType getKind() const { return Kind; } MCSectionData *getParent() const { return Parent; } void setParent(MCSectionData *Value) { Parent = Value; } - unsigned getOrdinal() const { return Ordinal; } - void setOrdinal(unsigned Value) { Ordinal = Value; } + MCSymbolData *getAtom() const { return Atom; } + void setAtom(MCSymbolData *Value) { Atom = Value; } + + unsigned getLayoutOrder() const { return LayoutOrder; } + void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } static bool classof(const MCFragment *O) { return true; } - virtual void dump(); + void dump(); }; class MCDataFragment : public MCFragment { SmallString<32> Contents; /// Fixups - The list of fixups in this fragment. - std::vector<MCAsmFixup> Fixups; + std::vector<MCFixup> Fixups; public: - typedef std::vector<MCAsmFixup>::const_iterator const_fixup_iterator; - typedef std::vector<MCAsmFixup>::iterator fixup_iterator; + typedef std::vector<MCFixup>::const_iterator const_fixup_iterator; + typedef std::vector<MCFixup>::iterator fixup_iterator; public: MCDataFragment(MCSectionData *SD = 0) : MCFragment(FT_Data, SD) {} @@ -141,15 +127,15 @@ public: /// @name Fixup Access /// @{ - void addFixup(MCAsmFixup Fixup) { + void addFixup(MCFixup Fixup) { // Enforce invariant that fixups are in offset order. - assert((Fixups.empty() || Fixup.Offset > Fixups.back().Offset) && + assert((Fixups.empty() || Fixup.getOffset() > Fixups.back().getOffset()) && "Fixups must be added in order!"); Fixups.push_back(Fixup); } - std::vector<MCAsmFixup> &getFixups() { return Fixups; } - const std::vector<MCAsmFixup> &getFixups() const { return Fixups; } + std::vector<MCFixup> &getFixups() { return Fixups; } + const std::vector<MCFixup> &getFixups() const { return Fixups; } fixup_iterator fixup_begin() { return Fixups.begin(); } const_fixup_iterator fixup_begin() const { return Fixups.begin(); } @@ -165,8 +151,6 @@ public: return F->getKind() == MCFragment::FT_Data; } static bool classof(const MCDataFragment *) { return true; } - - virtual void dump(); }; // FIXME: This current incarnation of MCInstFragment doesn't make much sense, as @@ -182,11 +166,11 @@ class MCInstFragment : public MCFragment { SmallString<8> Code; /// Fixups - The list of fixups in this fragment. - SmallVector<MCAsmFixup, 1> Fixups; + SmallVector<MCFixup, 1> Fixups; public: - typedef SmallVectorImpl<MCAsmFixup>::const_iterator const_fixup_iterator; - typedef SmallVectorImpl<MCAsmFixup>::iterator fixup_iterator; + typedef SmallVectorImpl<MCFixup>::const_iterator const_fixup_iterator; + typedef SmallVectorImpl<MCFixup>::iterator fixup_iterator; public: MCInstFragment(MCInst _Inst, MCSectionData *SD = 0) @@ -210,8 +194,8 @@ public: /// @name Fixup Access /// @{ - SmallVectorImpl<MCAsmFixup> &getFixups() { return Fixups; } - const SmallVectorImpl<MCAsmFixup> &getFixups() const { return Fixups; } + SmallVectorImpl<MCFixup> &getFixups() { return Fixups; } + const SmallVectorImpl<MCFixup> &getFixups() const { return Fixups; } fixup_iterator fixup_begin() { return Fixups.begin(); } const_fixup_iterator fixup_begin() const { return Fixups.begin(); } @@ -227,8 +211,6 @@ public: return F->getKind() == MCFragment::FT_Inst; } static bool classof(const MCInstFragment *) { return true; } - - virtual void dump(); }; class MCAlignFragment : public MCFragment { @@ -245,17 +227,24 @@ class MCAlignFragment : public MCFragment { /// cannot be satisfied in this width then this fragment is ignored. unsigned MaxBytesToEmit; - /// EmitNops - true when aligning code and optimal nops to be used for - /// filling. - bool EmitNops; + /// EmitNops - Flag to indicate that (optimal) NOPs should be emitted instead + /// of using the provided value. The exact interpretation of this flag is + /// target dependent. + bool EmitNops : 1; + + /// OnlyAlignAddress - Flag to indicate that this align is only used to adjust + /// the address space size of a section and that it should not be included as + /// part of the section size. This flag can only be used on the last fragment + /// in a section. + bool OnlyAlignAddress : 1; public: MCAlignFragment(unsigned _Alignment, int64_t _Value, unsigned _ValueSize, - unsigned _MaxBytesToEmit, bool _EmitNops, - MCSectionData *SD = 0) + unsigned _MaxBytesToEmit, MCSectionData *SD = 0) : MCFragment(FT_Align, SD), Alignment(_Alignment), Value(_Value),ValueSize(_ValueSize), - MaxBytesToEmit(_MaxBytesToEmit), EmitNops(_EmitNops) {} + MaxBytesToEmit(_MaxBytesToEmit), EmitNops(false), + OnlyAlignAddress(false) {} /// @name Accessors /// @{ @@ -268,7 +257,11 @@ public: unsigned getMaxBytesToEmit() const { return MaxBytesToEmit; } - unsigned getEmitNops() const { return EmitNops; } + bool hasEmitNops() const { return EmitNops; } + void setEmitNops(bool Value) { EmitNops = Value; } + + bool hasOnlyAlignAddress() const { return OnlyAlignAddress; } + void setOnlyAlignAddress(bool Value) { OnlyAlignAddress = Value; } /// @} @@ -276,25 +269,27 @@ public: return F->getKind() == MCFragment::FT_Align; } static bool classof(const MCAlignFragment *) { return true; } - - virtual void dump(); }; class MCFillFragment : public MCFragment { /// Value - Value to use for filling bytes. int64_t Value; - /// ValueSize - The size (in bytes) of \arg Value to use when filling. + /// ValueSize - The size (in bytes) of \arg Value to use when filling, or 0 if + /// this is a virtual fill fragment. unsigned ValueSize; - /// Count - The number of copies of \arg Value to insert. - uint64_t Count; + /// Size - The number of bytes to insert. + uint64_t Size; public: - MCFillFragment(int64_t _Value, unsigned _ValueSize, uint64_t _Count, + MCFillFragment(int64_t _Value, unsigned _ValueSize, uint64_t _Size, MCSectionData *SD = 0) : MCFragment(FT_Fill, SD), - Value(_Value), ValueSize(_ValueSize), Count(_Count) {} + Value(_Value), ValueSize(_ValueSize), Size(_Size) { + assert((!ValueSize || (Size % ValueSize) == 0) && + "Fill size must be a multiple of the value size!"); + } /// @name Accessors /// @{ @@ -303,7 +298,7 @@ public: unsigned getValueSize() const { return ValueSize; } - uint64_t getCount() const { return Count; } + uint64_t getSize() const { return Size; } /// @} @@ -311,8 +306,6 @@ public: return F->getKind() == MCFragment::FT_Fill; } static bool classof(const MCFillFragment *) { return true; } - - virtual void dump(); }; class MCOrgFragment : public MCFragment { @@ -340,39 +333,6 @@ public: return F->getKind() == MCFragment::FT_Org; } static bool classof(const MCOrgFragment *) { return true; } - - virtual void dump(); -}; - -/// MCZeroFillFragment - Represent data which has a fixed size and alignment, -/// but requires no physical space in the object file. -class MCZeroFillFragment : public MCFragment { - /// Size - The size of this fragment. - uint64_t Size; - - /// Alignment - The alignment for this fragment. - unsigned Alignment; - -public: - MCZeroFillFragment(uint64_t _Size, unsigned _Alignment, MCSectionData *SD = 0) - : MCFragment(FT_ZeroFill, SD), - Size(_Size), Alignment(_Alignment) {} - - /// @name Accessors - /// @{ - - uint64_t getSize() const { return Size; } - - unsigned getAlignment() const { return Alignment; } - - /// @} - - static bool classof(const MCFragment *F) { - return F->getKind() == MCFragment::FT_ZeroFill; - } - static bool classof(const MCZeroFillFragment *) { return true; } - - virtual void dump(); }; // FIXME: Should this be a separate class, or just merged into MCSection? Since @@ -400,6 +360,9 @@ private: /// Ordinal - The section index in the assemblers section list. unsigned Ordinal; + /// LayoutOrder - The index of this section in the layout order. + unsigned LayoutOrder; + /// Alignment - The maximum alignment seen in this section. unsigned Alignment; @@ -412,13 +375,6 @@ private: /// initialized. uint64_t Address; - /// Size - The content size of this section. This is ~0 until initialized. - uint64_t Size; - - /// FileSize - The size of this section in the object file. This is ~0 until - /// initialized. - uint64_t FileSize; - /// HasInstructions - Whether this section has had instructions emitted into /// it. unsigned HasInstructions : 1; @@ -441,6 +397,9 @@ public: unsigned getOrdinal() const { return Ordinal; } void setOrdinal(unsigned Value) { Ordinal = Value; } + unsigned getLayoutOrder() const { return LayoutOrder; } + void setLayoutOrder(unsigned Value) { LayoutOrder = Value; } + /// @name Fragment Access /// @{ @@ -562,6 +521,11 @@ public: /// setFlags - Set the (implementation defined) symbol flags. void setFlags(uint32_t Value) { Flags = Value; } + /// modifyFlags - Modify the flags via a mask + void modifyFlags(uint32_t Value, uint32_t Mask) { + Flags = (Flags & ~Mask) | Value; + } + /// getIndex - Get the (implementation defined) index. uint64_t getIndex() const { return Index; } @@ -642,26 +606,23 @@ private: /// \arg Value result is fixed, otherwise the value may change due to /// relocation. bool EvaluateFixup(const MCAsmLayout &Layout, - const MCAsmFixup &Fixup, const MCFragment *DF, + const MCFixup &Fixup, const MCFragment *DF, MCValue &Target, uint64_t &Value) const; /// Check whether a fixup can be satisfied, or whether it needs to be relaxed /// (increased in size, in order to hold its value correctly). - bool FixupNeedsRelaxation(const MCAsmFixup &Fixup, const MCFragment *DF, + bool FixupNeedsRelaxation(const MCFixup &Fixup, const MCFragment *DF, const MCAsmLayout &Layout) const; /// Check whether the given fragment needs relaxation. bool FragmentNeedsRelaxation(const MCInstFragment *IF, const MCAsmLayout &Layout) const; - /// LayoutSection - Assign the section the given \arg StartAddress, and then - /// assign offsets and sizes to the fragments in the section \arg SD, and - /// update the section size. - /// - /// \return The address at the end of the section, for use in laying out the - /// succeeding section. - uint64_t LayoutSection(MCSectionData &SD, MCAsmLayout &Layout, - uint64_t StartAddress); + /// Compute the effective fragment size assuming it is layed out at the given + /// \arg SectionAddress and \arg FragmentOffset. + uint64_t ComputeFragmentSize(MCAsmLayout &Layout, const MCFragment &F, + uint64_t SectionAddress, + uint64_t FragmentOffset) const; /// LayoutOnce - Perform one layout iteration and return true if any offsets /// were adjusted. @@ -671,18 +632,8 @@ private: void FinishLayout(MCAsmLayout &Layout); public: - /// Find the symbol which defines the atom containing given address, inside - /// the given section, or null if there is no such symbol. - // - // FIXME-PERF: Eliminate this, it is very slow. - const MCSymbolData *getAtomForAddress(const MCAsmLayout &Layout, - const MCSectionData *Section, - uint64_t Address) const; - /// Find the symbol which defines the atom containing the given symbol, or /// null if there is no such symbol. - // - // FIXME-PERF: Eliminate this, it is very slow. const MCSymbolData *getAtom(const MCAsmLayout &Layout, const MCSymbolData *Symbol) const; diff --git a/include/llvm/MC/MCContext.h b/include/llvm/MC/MCContext.h index 4434341..03b5fb0 100644 --- a/include/llvm/MC/MCContext.h +++ b/include/llvm/MC/MCContext.h @@ -20,6 +20,7 @@ namespace llvm { class MCExpr; class MCSection; class MCSymbol; + class MCLabel; class StringRef; class Twine; class MCSectionMachO; @@ -43,6 +44,15 @@ namespace llvm { /// NextUniqueID - The next ID to dole out to an unnamed assembler temporary /// symbol. unsigned NextUniqueID; + + /// Instances of directional local labels. + DenseMap<unsigned, MCLabel *> Instances; + /// NextInstance() creates the next instance of the directional local label + /// for the LocalLabelVal and adds it to the map if needed. + unsigned NextInstance(int64_t LocalLabelVal); + /// GetInstance() gets the current instance of the directional local label + /// for the LocalLabelVal and adds it to the map if needed. + unsigned GetInstance(int64_t LocalLabelVal); /// Allocator - Allocator object used for creating machine code objects. /// @@ -50,7 +60,7 @@ namespace llvm { /// objects. BumpPtrAllocator Allocator; - void *MachOUniquingMap, *ELFUniquingMap; + void *MachOUniquingMap, *ELFUniquingMap, *COFFUniquingMap; public: explicit MCContext(const MCAsmInfo &MAI); ~MCContext(); @@ -64,6 +74,14 @@ namespace llvm { /// with a unique but unspecified name. MCSymbol *CreateTempSymbol(); + /// CreateDirectionalLocalSymbol - Create the defintion of a directional + /// local symbol for numbered label (used for "1:" defintions). + MCSymbol *CreateDirectionalLocalSymbol(int64_t LocalLabelVal); + + /// GetDirectionalLocalSymbol - Create and return a directional local + /// symbol for numbered label (used for "1b" or 1f" references). + MCSymbol *GetDirectionalLocalSymbol(int64_t LocalLabelVal, int bORf); + /// GetOrCreateSymbol - Lookup the symbol inside with the specified /// @p Name. If it exists, return it. If not, create a forward /// reference and return it. @@ -97,6 +115,15 @@ namespace llvm { const MCSection *getELFSection(StringRef Section, unsigned Type, unsigned Flags, SectionKind Kind, bool IsExplicit = false); + + const MCSection *getCOFFSection(StringRef Section, unsigned Characteristics, + int Selection, SectionKind Kind); + + const MCSection *getCOFFSection(StringRef Section, unsigned Characteristics, + SectionKind Kind) { + return getCOFFSection (Section, Characteristics, 0, Kind); + } + /// @} diff --git a/include/llvm/MC/MCExpr.h b/include/llvm/MC/MCExpr.h index bd0684d..1f9b8f2 100644 --- a/include/llvm/MC/MCExpr.h +++ b/include/llvm/MC/MCExpr.h @@ -134,7 +134,10 @@ public: VK_NTPOFF, VK_PLT, VK_TLSGD, - VK_TPOFF + VK_TPOFF, + VK_ARM_HI16, // The R_ARM_MOVT_ABS relocation (:upper16: in the asm file) + VK_ARM_LO16, // The R_ARM_MOVW_ABS_NC relocation (:lower16: in the asm file) + VK_TLVP // Mach-O thread local variable relocation }; private: diff --git a/include/llvm/MC/MCFixup.h b/include/llvm/MC/MCFixup.h index cd0dd19..eed4c34 100644 --- a/include/llvm/MC/MCFixup.h +++ b/include/llvm/MC/MCFixup.h @@ -10,26 +10,12 @@ #ifndef LLVM_MC_MCFIXUP_H #define LLVM_MC_MCFIXUP_H +#include "llvm/System/DataTypes.h" #include <cassert> namespace llvm { class MCExpr; -// Private constants, do not use. -// -// This is currently laid out so that the MCFixup fields can be efficiently -// accessed, while keeping the offset field large enough that the assembler -// backend can reasonably use the MCFixup representation for an entire fragment -// (splitting any overly large fragments). -// -// The division of bits between the kind and the opindex can be tweaked if we -// end up needing more bits for target dependent kinds. -enum { - MCFIXUP_NUM_GENERIC_KINDS = 128, - MCFIXUP_NUM_KIND_BITS = 16, - MCFIXUP_NUM_OFFSET_BITS = (32 - MCFIXUP_NUM_KIND_BITS) -}; - /// MCFixupKind - Extensible enumeration to represent the type of a fixup. enum MCFixupKind { FK_Data_1 = 0, ///< A one-byte fixup. @@ -37,12 +23,14 @@ enum MCFixupKind { FK_Data_4, ///< A four-byte fixup. FK_Data_8, ///< A eight-byte fixup. - FirstTargetFixupKind = MCFIXUP_NUM_GENERIC_KINDS, + FirstTargetFixupKind = 128, - MaxTargetFixupKind = (1 << MCFIXUP_NUM_KIND_BITS) + // Limit range of target fixups, in case we want to pack more efficiently + // later. + MaxTargetFixupKind = (1 << 8) }; -/// MCFixup - Encode information on a single operation to perform on an byte +/// MCFixup - Encode information on a single operation to perform on a byte /// sequence (e.g., an encoded instruction) which requires assemble- or run- /// time patching. /// @@ -57,36 +45,33 @@ enum MCFixupKind { /// fixups become relocations in the object file (or errors, if the fixup cannot /// be encoded on the target). class MCFixup { - static const unsigned MaxOffset = 1 << MCFIXUP_NUM_KIND_BITS; - /// The value to put into the fixup location. The exact interpretation of the - /// expression is target dependent, usually it will one of the operands to an - /// instruction or an assembler directive. + /// expression is target dependent, usually it will be one of the operands to + /// an instruction or an assembler directive. const MCExpr *Value; /// The byte index of start of the relocation inside the encoded instruction. - unsigned Offset : MCFIXUP_NUM_OFFSET_BITS; + uint32_t Offset; /// The target dependent kind of fixup item this is. The kind is used to /// determine how the operand value should be encoded into the instruction. - unsigned Kind : MCFIXUP_NUM_KIND_BITS; + unsigned Kind; public: - static MCFixup Create(unsigned Offset, const MCExpr *Value, + static MCFixup Create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind) { + assert(unsigned(Kind) < MaxTargetFixupKind && "Kind out of range!"); MCFixup FI; FI.Value = Value; FI.Offset = Offset; FI.Kind = unsigned(Kind); - - assert(Offset == FI.getOffset() && "Offset out of range!"); - assert(Kind == FI.getKind() && "Kind out of range!"); return FI; } MCFixupKind getKind() const { return MCFixupKind(Kind); } - unsigned getOffset() const { return Offset; } + uint32_t getOffset() const { return Offset; } + void setOffset(uint32_t Value) { Offset = Value; } const MCExpr *getValue() const { return Value; } diff --git a/include/llvm/MC/MCLabel.h b/include/llvm/MC/MCLabel.h new file mode 100644 index 0000000..727520d --- /dev/null +++ b/include/llvm/MC/MCLabel.h @@ -0,0 +1,56 @@ +//===- MCLabel.h - Machine Code Directional Local Labels --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains the declaration of the MCLabel class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCLABEL_H +#define LLVM_MC_MCLABEL_H + +namespace llvm { + class MCContext; + class raw_ostream; + + /// MCLabel - Instances of this class represent a label name in the MC file, + /// and MCLabel are created and unique'd by the MCContext class. MCLabel + /// should only be constructed for valid instances in the object file. + class MCLabel { + // Instance - the instance number of this Directional Local Label + unsigned Instance; + + private: // MCContext creates and uniques these. + friend class MCContext; + MCLabel(unsigned instance) + : Instance(instance) {} + + MCLabel(const MCLabel&); // DO NOT IMPLEMENT + void operator=(const MCLabel&); // DO NOT IMPLEMENT + public: + /// getInstance - Get the current instance of this Directional Local Label. + unsigned getInstance() const { return Instance; } + + /// incInstance - Increment the current instance of this Directional Local + /// Label. + unsigned incInstance() { return ++Instance; } + + /// print - Print the value to the stream \arg OS. + void print(raw_ostream &OS) const; + + /// dump - Print the value to stderr. + void dump() const; + }; + + inline raw_ostream &operator<<(raw_ostream &OS, const MCLabel &Label) { + Label.print(OS); + return OS; + } +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCMachOSymbolFlags.h b/include/llvm/MC/MCMachOSymbolFlags.h new file mode 100644 index 0000000..c938c81 --- /dev/null +++ b/include/llvm/MC/MCMachOSymbolFlags.h @@ -0,0 +1,44 @@ +//===- MCMachOSymbolFlags.h - MachO Symbol Flags ----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the SymbolFlags used for the MachO target. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCMACHOSYMBOLFLAGS_H +#define LLVM_MC_MCMACHOSYMBOLFLAGS_H + +// These flags are mostly used in MCMachOStreamer.cpp but also needed in +// MachObjectWriter.cpp to test for Weak Definitions of symbols to emit +// the correct relocation information. + +namespace llvm { + /// SymbolFlags - We store the value for the 'desc' symbol field in the lowest + /// 16 bits of the implementation defined flags. + enum SymbolFlags { // See <mach-o/nlist.h>. + SF_DescFlagsMask = 0xFFFF, + + // Reference type flags. + SF_ReferenceTypeMask = 0x0007, + SF_ReferenceTypeUndefinedNonLazy = 0x0000, + SF_ReferenceTypeUndefinedLazy = 0x0001, + SF_ReferenceTypeDefined = 0x0002, + SF_ReferenceTypePrivateDefined = 0x0003, + SF_ReferenceTypePrivateUndefinedNonLazy = 0x0004, + SF_ReferenceTypePrivateUndefinedLazy = 0x0005, + + // Other 'desc' flags. + SF_NoDeadStrip = 0x0020, + SF_WeakReference = 0x0040, + SF_WeakDefinition = 0x0080 + }; + +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCObjectWriter.h b/include/llvm/MC/MCObjectWriter.h index 522ee77..e900584 100644 --- a/include/llvm/MC/MCObjectWriter.h +++ b/include/llvm/MC/MCObjectWriter.h @@ -15,9 +15,9 @@ #include <cassert> namespace llvm { -class MCAsmFixup; class MCAsmLayout; class MCAssembler; +class MCFixup; class MCFragment; class MCValue; class raw_ostream; @@ -72,13 +72,13 @@ public: virtual void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, - const MCAsmFixup &Fixup, MCValue Target, + const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) = 0; /// Write the object file. /// /// This routine is called by the assembler after layout and relaxation is - /// complete, fixups have been evaluate and applied, and relocations + /// complete, fixups have been evaluated and applied, and relocations /// generated. virtual void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout) = 0; @@ -152,6 +152,8 @@ public: } void WriteBytes(StringRef Str, unsigned ZeroFillSize = 0) { + assert((ZeroFillSize == 0 || Str.size () <= ZeroFillSize) && + "data size greater than fill size, unexpected large write will occur"); OS << Str; if (ZeroFillSize) WriteZeros(ZeroFillSize - Str.size()); diff --git a/include/llvm/MC/MCParser/AsmParser.h b/include/llvm/MC/MCParser/AsmParser.h index 7a78906..e929fd1 100644 --- a/include/llvm/MC/MCParser/AsmParser.h +++ b/include/llvm/MC/MCParser/AsmParser.h @@ -131,11 +131,13 @@ private: /// ParseDirectiveSymbolAttribute - Parse a directive like ".globl" which /// accepts a single symbol (which should be a label or an external). bool ParseDirectiveSymbolAttribute(MCSymbolAttr Attr); + bool ParseDirectiveELFType(); // ELF specific ".type" bool ParseDirectiveDarwinSymbolDesc(); // Darwin specific ".desc" bool ParseDirectiveDarwinLsym(); // Darwin specific ".lsym" bool ParseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm" bool ParseDirectiveDarwinZerofill(); // Darwin specific ".zerofill" + bool ParseDirectiveDarwinTBSS(); // Darwin specific ".tbss" // Darwin specific ".subsections_via_symbols" bool ParseDirectiveDarwinSubsectionsViaSymbols(); diff --git a/include/llvm/MC/MCParser/MCAsmLexer.h b/include/llvm/MC/MCParser/MCAsmLexer.h index 075b69b..bd1496f 100644 --- a/include/llvm/MC/MCParser/MCAsmLexer.h +++ b/include/llvm/MC/MCParser/MCAsmLexer.h @@ -47,7 +47,7 @@ public: Pipe, PipePipe, Caret, Amp, AmpAmp, Exclaim, ExclaimEqual, Percent, Hash, Less, LessEqual, LessLess, LessGreater, - Greater, GreaterEqual, GreaterGreater + Greater, GreaterEqual, GreaterGreater, At }; TokenKind Kind; diff --git a/include/llvm/MC/MCSection.h b/include/llvm/MC/MCSection.h index e9c19fc..808767c 100644 --- a/include/llvm/MC/MCSection.h +++ b/include/llvm/MC/MCSection.h @@ -17,6 +17,7 @@ #include <string> #include "llvm/ADT/StringRef.h" #include "llvm/MC/SectionKind.h" +#include "llvm/Support/Casting.h" namespace llvm { class MCContext; @@ -27,15 +28,27 @@ namespace llvm { /// section in the current translation unit. The MCContext class uniques and /// creates these. class MCSection { + public: + enum SectionVariant { + SV_COFF = 0, + SV_ELF, + SV_MachO, + SV_PIC16 + }; + + private: MCSection(const MCSection&); // DO NOT IMPLEMENT void operator=(const MCSection&); // DO NOT IMPLEMENT protected: - MCSection(SectionKind K) : Kind(K) {} + MCSection(SectionVariant V, SectionKind K) : Variant(V), Kind(K) {} + SectionVariant Variant; SectionKind Kind; public: virtual ~MCSection(); SectionKind getKind() const { return Kind; } + + SectionVariant getVariant() const { return Variant; } virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS) const = 0; @@ -47,32 +60,8 @@ namespace llvm { virtual bool isBaseAddressKnownZero() const { return false; } - }; - - class MCSectionCOFF : public MCSection { - // The memory for this string is stored in the same MCContext as *this. - StringRef Name; - - /// IsDirective - This is true if the section name is a directive, not - /// something that should be printed with ".section". - /// - /// FIXME: This is a hack. Switch to a semantic view of the section instead - /// of a syntactic one. - bool IsDirective; - - MCSectionCOFF(StringRef name, bool isDirective, SectionKind K) - : MCSection(K), Name(name), IsDirective(isDirective) { - } - public: - - static MCSectionCOFF *Create(StringRef Name, bool IsDirective, - SectionKind K, MCContext &Ctx); - StringRef getName() const { return Name; } - bool isDirective() const { return IsDirective; } - - virtual void PrintSwitchToSection(const MCAsmInfo &MAI, - raw_ostream &OS) const; + static bool classof(const MCSection *) { return true; } }; } // end namespace llvm diff --git a/include/llvm/MC/MCSectionCOFF.h b/include/llvm/MC/MCSectionCOFF.h new file mode 100644 index 0000000..938a388 --- /dev/null +++ b/include/llvm/MC/MCSectionCOFF.h @@ -0,0 +1,115 @@ +//===- MCSectionCOFF.h - COFF Machine Code Sections -------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file declares the MCSectionCOFF class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_MC_MCSECTIONCOFF_H +#define LLVM_MC_MCSECTIONCOFF_H + +#include "llvm/MC/MCSection.h" + +namespace llvm { + +/// MCSectionCOFF - This represents a section on Windows + class MCSectionCOFF : public MCSection { + // The memory for this string is stored in the same MCContext as *this. + StringRef SectionName; + + /// Characteristics - This is the Characteristics field of a section, + // drawn from the enums below. + unsigned Characteristics; + + /// Selection - This is the Selection field for the section symbol, if + /// it is a COMDAT section (Characteristics & IMAGE_SCN_LNK_COMDAT) != 0 + int Selection; + + private: + friend class MCContext; + MCSectionCOFF(StringRef Section, unsigned Characteristics, + int Selection, SectionKind K) + : MCSection(SV_COFF, K), SectionName(Section), + Characteristics(Characteristics), Selection (Selection) { + assert ((Characteristics & 0x00F00000) == 0 && + "alignment must not be set upon section creation"); + } + ~MCSectionCOFF(); + + public: + /// ShouldOmitSectionDirective - Decides whether a '.section' directive + /// should be printed before the section name + bool ShouldOmitSectionDirective(StringRef Name, const MCAsmInfo &MAI) const; + + //FIXME: all COFF enumerations/flags should be standardized into one place... + // Target/X86COFF.h doesn't seem right as COFF can be used for other targets, + // MC/WinCOFF.h maybe right as it isn't target or entity specific, and it is + // pretty low on the dependancy graph (is there any need to support non + // windows COFF?) + // here is good for section stuff, but others should go elsewhere + + /// Valid section flags. + enum { + IMAGE_SCN_TYPE_NO_PAD = 0x00000008, + IMAGE_SCN_CNT_CODE = 0x00000020, + IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040, + IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080, + IMAGE_SCN_LNK_OTHER = 0x00000100, + IMAGE_SCN_LNK_INFO = 0x00000200, + IMAGE_SCN_LNK_REMOVE = 0x00000800, + IMAGE_SCN_LNK_COMDAT = 0x00001000, + IMAGE_SCN_MEM_FARDATA = 0x00008000, + IMAGE_SCN_MEM_PURGEABLE = 0x00020000, + IMAGE_SCN_MEM_16BIT = 0x00020000, + IMAGE_SCN_MEM_LOCKED = 0x00040000, + IMAGE_SCN_MEM_PRELOAD = 0x00080000, + /* these are handled elsewhere + IMAGE_SCN_ALIGN_1BYTES = 0x00100000, + IMAGE_SCN_ALIGN_2BYTES = 0x00200000, + IMAGE_SCN_ALIGN_4BYTES = 0x00300000, + IMAGE_SCN_ALIGN_8BYTES = 0x00400000, + IMAGE_SCN_ALIGN_16BYTES = 0x00500000, + IMAGE_SCN_ALIGN_32BYTES = 0x00600000, + IMAGE_SCN_ALIGN_64BYTES = 0x00700000, + */ + IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000, + IMAGE_SCN_MEM_DISCARDABLE = 0x02000000, + IMAGE_SCN_MEM_NOT_CACHED = 0x04000000, + IMAGE_SCN_MEM_NOT_PAGED = 0x08000000, + IMAGE_SCN_MEM_SHARED = 0x10000000, + IMAGE_SCN_MEM_EXECUTE = 0x20000000, + IMAGE_SCN_MEM_READ = 0x40000000, + IMAGE_SCN_MEM_WRITE = 0x80000000 + }; + + enum { + IMAGE_COMDAT_SELECT_NODUPLICATES = 1, + IMAGE_COMDAT_SELECT_ANY, + IMAGE_COMDAT_SELECT_SAME_SIZE, + IMAGE_COMDAT_SELECT_EXACT_MATCH, + IMAGE_COMDAT_SELECT_ASSOCIATIVE, + IMAGE_COMDAT_SELECT_LARGEST + }; + + StringRef getSectionName() const { return SectionName; } + unsigned getCharacteristics() const { return Characteristics; } + int getSelection () const { return Selection; } + + virtual void PrintSwitchToSection(const MCAsmInfo &MAI, + raw_ostream &OS) const; + + static bool classof(const MCSection *S) { + return S->getVariant() == SV_COFF; + } + static bool classof(const MCSectionCOFF *) { return true; } + }; + +} // end namespace llvm + +#endif diff --git a/include/llvm/MC/MCSectionELF.h b/include/llvm/MC/MCSectionELF.h index 7054668..5fe8171 100644 --- a/include/llvm/MC/MCSectionELF.h +++ b/include/llvm/MC/MCSectionELF.h @@ -40,7 +40,7 @@ private: friend class MCContext; MCSectionELF(StringRef Section, unsigned type, unsigned flags, SectionKind K, bool isExplicit) - : MCSection(K), SectionName(Section), Type(type), Flags(flags), + : MCSection(SV_ELF, K), SectionName(Section), Type(type), Flags(flags), IsExplicit(isExplicit) {} ~MCSectionELF(); public: @@ -178,6 +178,11 @@ public: virtual bool isBaseAddressKnownZero() const { return (getFlags() & SHF_ALLOC) == 0; } + + static bool classof(const MCSection *S) { + return S->getVariant() == SV_ELF; + } + static bool classof(const MCSectionELF *) { return true; } }; } // end namespace llvm diff --git a/include/llvm/MC/MCSectionMachO.h b/include/llvm/MC/MCSectionMachO.h index f3bc8ed..2d9d133 100644 --- a/include/llvm/MC/MCSectionMachO.h +++ b/include/llvm/MC/MCSectionMachO.h @@ -87,8 +87,20 @@ public: /// S_LAZY_DYLIB_SYMBOL_POINTERS - Section with lazy symbol pointers to /// lazy loaded dylibs. S_LAZY_DYLIB_SYMBOL_POINTERS = 0x10U, + /// S_THREAD_LOCAL_REGULAR - Section with .... + S_THREAD_LOCAL_REGULAR = 0x11U, + /// S_THREAD_LOCAL_ZEROFILL - Thread local zerofill section. + S_THREAD_LOCAL_ZEROFILL = 0x12U, + /// S_THREAD_LOCAL_VARIABLES - Section with thread local variable structure + /// data. + S_THREAD_LOCAL_VARIABLES = 0x13U, + /// S_THREAD_LOCAL_VARIABLE_POINTERS - Section with .... + S_THREAD_LOCAL_VARIABLE_POINTERS = 0x14U, + /// S_THREAD_LOCAL_INIT_FUNCTION_POINTERS - Section with thread local + /// variable initialization pointers to functions. + S_THREAD_LOCAL_INIT_FUNCTION_POINTERS = 0x15U, - LAST_KNOWN_SECTION_TYPE = S_LAZY_DYLIB_SYMBOL_POINTERS, + LAST_KNOWN_SECTION_TYPE = S_THREAD_LOCAL_INIT_FUNCTION_POINTERS, // Valid section attributes. @@ -136,6 +148,9 @@ public: unsigned getStubSize() const { return Reserved2; } unsigned getType() const { return TypeAndAttributes & SECTION_TYPE; } + bool hasAttribute(unsigned Value) const { + return (TypeAndAttributes & Value) != 0; + } /// ParseSectionSpecifier - Parse the section specifier indicated by "Spec". /// This is a string that can appear after a .section directive in a mach-o @@ -150,6 +165,11 @@ public: virtual void PrintSwitchToSection(const MCAsmInfo &MAI, raw_ostream &OS) const; + + static bool classof(const MCSection *S) { + return S->getVariant() == SV_MachO; + } + static bool classof(const MCSectionMachO *) { return true; } }; } // end namespace llvm diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index 4667c41..0783159 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -27,7 +27,7 @@ namespace llvm { class MCSection; class MCSymbol; class StringRef; -class TargetAsmBackend; + class TargetAsmBackend; class Twine; class raw_ostream; class formatted_raw_ostream; @@ -138,7 +138,24 @@ class TargetAsmBackend; /// @param DescValue - The value to set into the n_desc field. virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) = 0; - + /// BeginCOFFSymbolDef - Start emitting COFF symbol definition + /// + /// @param Symbol - The symbol to have its External & Type fields set. + virtual void BeginCOFFSymbolDef(const MCSymbol *Symbol) = 0; + + /// EmitCOFFSymbolStorageClass - Emit the storage class of the symbol. + /// + /// @param StorageClass - The storage class the symbol should have. + virtual void EmitCOFFSymbolStorageClass(int StorageClass) = 0; + + /// EmitCOFFSymbolType - Emit the type of the symbol. + /// + /// @param Type - A COFF type identifier (see COFF::SymbolType in X86COFF.h) + virtual void EmitCOFFSymbolType(int Type) = 0; + + /// EndCOFFSymbolDef - Marks the end of the symbol definition. + virtual void EndCOFFSymbolDef() = 0; + /// EmitELFSize - Emit an ELF .size directive. /// /// This corresponds to an assembler statement such as: @@ -161,7 +178,7 @@ class TargetAsmBackend; /// @param Size - The size of the common symbol. virtual void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size) = 0; - /// EmitZerofill - Emit a the zerofill section and an option symbol. + /// EmitZerofill - Emit the zerofill section and an optional symbol. /// /// @param Section - The zerofill section to create and or to put the symbol /// @param Symbol - The zerofill symbol to emit, if non-NULL. @@ -171,6 +188,15 @@ class TargetAsmBackend; virtual void EmitZerofill(const MCSection *Section, MCSymbol *Symbol = 0, unsigned Size = 0,unsigned ByteAlignment = 0) = 0; + /// EmitTBSSSymbol - Emit a thread local bss (.tbss) symbol. + /// + /// @param Section - The thread local common section. + /// @param Symbol - The thread local common symbol to emit. + /// @param Size - The size of the symbol. + /// @param ByteAlignment - The alignment of the thread local common symbol + /// if non-zero. This must be a power of 2 on some targets. + virtual void EmitTBSSSymbol(const MCSection *Section, MCSymbol *Symbol, + uint64_t Size, unsigned ByteAlignment = 0) = 0; /// @} /// @name Generating Data /// @{ @@ -315,12 +341,18 @@ class TargetAsmBackend; MCCodeEmitter *CE = 0, bool ShowInst = false); - /// createMachOStream - Create a machine code streamer which will generative + /// createMachOStreamer - Create a machine code streamer which will generative /// Mach-O format object files. MCStreamer *createMachOStreamer(MCContext &Ctx, TargetAsmBackend &TAB, raw_ostream &OS, MCCodeEmitter *CE, bool RelaxAll = false); + /// createLoggingStreamer - Create a machine code streamer which just logs the + /// API calls and then dispatches to another streamer. + /// + /// The new streamer takes ownership of the \arg Child. + MCStreamer *createLoggingStreamer(MCStreamer *Child, raw_ostream &OS); + } // end namespace llvm #endif diff --git a/include/llvm/MC/MCSymbol.h b/include/llvm/MC/MCSymbol.h index fb96506..1b432c2 100644 --- a/include/llvm/MC/MCSymbol.h +++ b/include/llvm/MC/MCSymbol.h @@ -52,10 +52,15 @@ namespace llvm { /// "Lfoo" or ".foo". unsigned IsTemporary : 1; + /// IsUsedInExpr - True if this symbol has been used in an expression and + /// cannot be redefined. + unsigned IsUsedInExpr : 1; + private: // MCContext creates and uniques these. friend class MCContext; MCSymbol(StringRef name, bool isTemporary) - : Name(name), Section(0), Value(0), IsTemporary(isTemporary) {} + : Name(name), Section(0), Value(0), + IsTemporary(isTemporary), IsUsedInExpr(false) {} MCSymbol(const MCSymbol&); // DO NOT IMPLEMENT void operator=(const MCSymbol&); // DO NOT IMPLEMENT @@ -63,13 +68,15 @@ namespace llvm { /// getName - Get the symbol name. StringRef getName() const { return Name; } - /// @name Symbol Type + /// @name Accessors /// @{ /// isTemporary - Check if this is an assembler temporary symbol. - bool isTemporary() const { - return IsTemporary; - } + bool isTemporary() const { return IsTemporary; } + + /// isUsedInExpr - Check if this is an assembler temporary symbol. + bool isUsedInExpr() const { return IsUsedInExpr; } + void setUsedInExpr(bool Value) { IsUsedInExpr = Value; } /// @} /// @name Associated Sections @@ -125,14 +132,14 @@ namespace llvm { return Value != 0; } - /// getValue() - Get the value for variable symbols, or null if the symbol - /// is not a variable. - const MCExpr *getValue() const { return Value; } - - void setValue(const MCExpr *Value) { - this->Value = Value; + /// getValue() - Get the value for variable symbols. + const MCExpr *getVariableValue() const { + assert(isVariable() && "Invalid accessor!"); + return Value; } + void setVariableValue(const MCExpr *Value); + /// @} /// print - Print the value to the stream \arg OS. diff --git a/include/llvm/MC/MachObjectWriter.h b/include/llvm/MC/MachObjectWriter.h index 844025d..9b1ff1d 100644 --- a/include/llvm/MC/MachObjectWriter.h +++ b/include/llvm/MC/MachObjectWriter.h @@ -15,9 +15,9 @@ #include <cassert> namespace llvm { -class MCAsmFixup; class MCAssembler; class MCFragment; +class MCFixup; class MCValue; class raw_ostream; @@ -33,7 +33,7 @@ public: virtual void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFragment *Fragment, - const MCAsmFixup &Fixup, MCValue Target, + const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue); virtual void WriteObject(const MCAssembler &Asm, const MCAsmLayout &Layout); diff --git a/include/llvm/PassManager.h b/include/llvm/PassManager.h index 4d91163..8de0f83 100644 --- a/include/llvm/PassManager.h +++ b/include/llvm/PassManager.h @@ -60,6 +60,9 @@ public: bool run(Module &M); private: + /// addImpl - Add a pass to the queue of passes to run, without + /// checking whether to add a printer pass. + void addImpl(Pass *P); /// PassManagerImpl_New is the actual class. PassManager is just the /// wraper to publish simple pass manager interface @@ -96,6 +99,10 @@ public: bool doFinalization(); private: + /// addImpl - Add a pass to the queue of passes to run, without + /// checking whether to add a printer pass. + void addImpl(Pass *P); + FunctionPassManagerImpl *FPM; Module *M; }; diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index 881a0fe..b2ce76d 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -15,12 +15,21 @@ #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. +/// LLVM_LIBRARY_VISIBILITY - If a class marked with this attribute is linked +/// into a shared library, then the class should be private to the library and +/// not accessible from outside it. Can also be used to mark variables and +/// functions, making them private to any shared library they are linked into. + +/// LLVM_GLOBAL_VISIBILITY - If a class marked with this attribute is linked +/// into a shared library, then the class will be accessible from outside the +/// the library. Can also be used to mark variables and functions, making them +/// accessible from outside any shared library they are linked into. #if (__GNUC__ >= 4) && !defined(__MINGW32__) && !defined(__CYGWIN__) -#define VISIBILITY_HIDDEN __attribute__ ((visibility("hidden"))) +#define LLVM_LIBRARY_VISIBILITY __attribute__ ((visibility("hidden"))) +#define LLVM_GLOBAL_VISIBILITY __attribute__ ((visibility("default"))) #else -#define VISIBILITY_HIDDEN +#define LLVM_LIBRARY_VISIBILITY +#define LLVM_GLOBAL_VISIBILITY #endif #if (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1)) diff --git a/include/llvm/Support/DOTGraphTraits.h b/include/llvm/Support/DOTGraphTraits.h index 54ced15..796c74a 100644 --- a/include/llvm/Support/DOTGraphTraits.h +++ b/include/llvm/Support/DOTGraphTraits.h @@ -36,7 +36,7 @@ protected: } public: - DefaultDOTGraphTraits (bool simple=false) : IsSimple (simple) {} + explicit DefaultDOTGraphTraits(bool simple=false) : IsSimple (simple) {} /// getGraphName - Return the label for the graph as a whole. Printed at the /// top of the graph. @@ -59,6 +59,12 @@ public: return false; } + /// isNodeHidden - If the function returns true, the given node is not + /// displayed in the graph. + static bool isNodeHidden(const void *Node) { + 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> diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h index 13e6682..559f004 100644 --- a/include/llvm/Support/GraphWriter.h +++ b/include/llvm/Support/GraphWriter.h @@ -122,7 +122,20 @@ public: // 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); + if (!isNodeHidden(*I)) + writeNode(*I); + } + + bool isNodeHidden(NodeType &Node) { + return isNodeHidden(&Node); + } + + bool isNodeHidden(NodeType *const *Node) { + return isNodeHidden(*Node); + } + + bool isNodeHidden(NodeType *Node) { + return DTraits.isNodeHidden(Node); } void writeNode(NodeType& Node) { @@ -189,9 +202,11 @@ public: child_iterator EI = GTraits::child_begin(Node); child_iterator EE = GTraits::child_end(Node); for (unsigned i = 0; EI != EE && i != 64; ++EI, ++i) - writeEdge(Node, i, EI); + if (!DTraits.isNodeHidden(*EI)) + writeEdge(Node, i, EI); for (; EI != EE; ++EI) - writeEdge(Node, 64, EI); + if (!DTraits.isNodeHidden(*EI)) + writeEdge(Node, 64, EI); } void writeEdge(NodeType *Node, unsigned edgeidx, child_iterator EI) { diff --git a/include/llvm/Support/StandardPasses.h b/include/llvm/Support/StandardPasses.h index f233c18..b97ad29 100644 --- a/include/llvm/Support/StandardPasses.h +++ b/include/llvm/Support/StandardPasses.h @@ -31,7 +31,7 @@ namespace llvm { /// /// \arg OptimizationLevel - The optimization level, corresponding to -O0, /// -O1, etc. - static inline void createStandardFunctionPasses(FunctionPassManager *PM, + static inline void createStandardFunctionPasses(PassManagerBase *PM, unsigned OptimizationLevel); /// createStandardModulePasses - Add the standard list of module passes to the @@ -46,7 +46,7 @@ namespace llvm { /// \arg HaveExceptions - Whether the module may have code using exceptions. /// \arg InliningPass - The inlining pass to use, if any, or null. This will /// always be added, even at -O0.a - static inline void createStandardModulePasses(PassManager *PM, + static inline void createStandardModulePasses(PassManagerBase *PM, unsigned OptimizationLevel, bool OptimizeSize, bool UnitAtATime, @@ -61,14 +61,14 @@ namespace llvm { /// Internalize - Run the internalize pass. /// RunInliner - Use a function inlining pass. /// VerifyEach - Run the verifier after each pass. - static inline void createStandardLTOPasses(PassManager *PM, + static inline void createStandardLTOPasses(PassManagerBase *PM, bool Internalize, bool RunInliner, bool VerifyEach); // Implementations - static inline void createStandardFunctionPasses(FunctionPassManager *PM, + static inline void createStandardFunctionPasses(PassManagerBase *PM, unsigned OptimizationLevel) { if (OptimizationLevel > 0) { PM->add(createCFGSimplificationPass()); @@ -82,7 +82,7 @@ namespace llvm { /// createStandardModulePasses - Add the standard module passes. This is /// expected to be run after the standard function passes. - static inline void createStandardModulePasses(PassManager *PM, + static inline void createStandardModulePasses(PassManagerBase *PM, unsigned OptimizationLevel, bool OptimizeSize, bool UnitAtATime, @@ -164,14 +164,14 @@ namespace llvm { } } - static inline void addOnePass(PassManager *PM, Pass *P, bool AndVerify) { + static inline void addOnePass(PassManagerBase *PM, Pass *P, bool AndVerify) { PM->add(P); if (AndVerify) PM->add(createVerifierPass()); } - static inline void createStandardLTOPasses(PassManager *PM, + static inline void createStandardLTOPasses(PassManagerBase *PM, bool Internalize, bool RunInliner, bool VerifyEach) { diff --git a/include/llvm/System/Signals.h b/include/llvm/System/Signals.h index 2b9d8ca..504420c 100644 --- a/include/llvm/System/Signals.h +++ b/include/llvm/System/Signals.h @@ -20,6 +20,10 @@ namespace llvm { namespace sys { + /// This function runs all the registered interrupt handlers, including the + /// removal of files registered by RemoveFileOnSignal. + void RunInterruptHandlers(); + /// 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. diff --git a/include/llvm/Target/SubtargetFeature.h b/include/llvm/Target/SubtargetFeature.h index 38a3cc2..4546871 100644 --- a/include/llvm/Target/SubtargetFeature.h +++ b/include/llvm/Target/SubtargetFeature.h @@ -108,9 +108,10 @@ public: // Dump feature info. void dump() const; - /// Retrieve a formatted string of the default features for - /// the specified target triple. - static std::string getDefaultSubtargetFeatures(const Triple &Triple); + /// Retrieve a formatted string of the default features for the specified + /// target triple. + void getDefaultSubtargetFeatures(const std::string &CPU, + const Triple& Triple); }; } // End namespace llvm diff --git a/include/llvm/Target/Target.td b/include/llvm/Target/Target.td index cc19e0d..ca551e5 100644 --- a/include/llvm/Target/Target.td +++ b/include/llvm/Target/Target.td @@ -21,6 +21,11 @@ include "llvm/Intrinsics.td" class RegisterClass; // Forward def +// SubRegIndex - Use instances of SubRegIndex to identify subregisters. +class SubRegIndex { + string Namespace = ""; +} + // Register - You should define one instance of this class for each register // in the target machine. String n will become the "name" of the register. class Register<string n> { @@ -49,6 +54,23 @@ class Register<string n> { // not [AX, AH, AL]. list<Register> SubRegs = []; + // SubRegIndices - For each register in SubRegs, specify the SubRegIndex used + // to address it. Sub-sub-register indices are automatically inherited from + // SubRegs. + list<SubRegIndex> SubRegIndices = []; + + // CompositeIndices - Specify subreg indices that don't correspond directly to + // a register in SubRegs and are not inherited. The following formats are + // supported: + // + // (a) Identity - Reg:a == Reg + // (a b) Alias - Reg:a == Reg:b + // (a b,c) Composite - Reg:a == (Reg:b):c + // + // This can be used to disambiguate a sub-sub-register that exists in more + // than one subregister and other weird stuff. + list<dag> CompositeIndices = []; + // DwarfNumbers - Numbers used internally by gcc/gdb to identify the register. // These values can be determined by locating the <target>.h file in the // directory llvmgcc/gcc/config/<target>/ and looking for REGISTER_NAMES. The @@ -68,17 +90,6 @@ class RegisterWithSubRegs<string n, list<Register> subregs> : Register<n> { let SubRegs = subregs; } -// SubRegSet - This can be used to define a specific mapping of registers to -// indices, for use as named subregs of a particular physical register. Each -// register in 'subregs' becomes an addressable subregister at index 'n' of the -// corresponding register in 'regs'. -class SubRegSet<int n, list<Register> regs, list<Register> subregs> { - int index = n; - - list<Register> From = regs; - list<Register> To = subregs; -} - // RegisterClass - Now that all of the registers are defined, and aliases // between registers are defined, specify which registers belong to which // register classes. This also defines the default allocation order of @@ -117,9 +128,9 @@ class RegisterClass<string namespace, list<ValueType> regTypes, int alignment, // list<Register> MemberList = regList; - // SubClassList - Specify which register classes correspond to subregisters - // of this class. The order should be by subregister set index. - list<RegisterClass> SubRegClassList = []; + // SubRegClasses - Specify the register class of subregisters as a list of + // dags: (RegClass SubRegIndex, SubRegindex, ...) + list<dag> SubRegClasses = []; // MethodProtos/MethodBodies - These members can be used to insert arbitrary // code into a generated register class. The normal usage of this is to @@ -221,6 +232,9 @@ class Instruction { // purposes. bit isCodeGenOnly = 0; + // Is this instruction a pseudo instruction for use by the assembler parser. + bit isAsmParserOnly = 0; + InstrItinClass Itinerary = NoItinerary;// Execution steps used for scheduling. string Constraints = ""; // OperandConstraint, e.g. $src = $dst. @@ -296,8 +310,8 @@ class AsmOperandClass { /// The name to use for this class, which should be usable as an enum value. string Name = ?; - /// The super class of this operand. - AsmOperandClass SuperClass = ?; + /// The super classes of this operand. + list<AsmOperandClass> SuperClasses = []; /// The name of the method on the target specific operand to call to test /// whether the operand is an instance of this class. If not set, this will @@ -331,10 +345,10 @@ class Operand<ValueType ty> { // in. Match classes are used to define the order in which instructions are // match, to ensure that which instructions gets matched is deterministic. // - // The target specific parser must be able to classify an parsed operand - // into a unique class, which does not partially overlap with any other - // classes. It can match a subset of some other class, in which case - // ParserMatchSuperClass should be set to the name of that class. + // The target specific parser must be able to classify an parsed operand into + // a unique class, which does not partially overlap with any other classes. It + // can match a subset of some other class, in which case the AsmOperandClass + // should declare the other operand as one of its super classes. AsmOperandClass ParserMatchClass = ImmAsmOperand; } diff --git a/include/llvm/Target/TargetAsmBackend.h b/include/llvm/Target/TargetAsmBackend.h index f350ecc..979595a 100644 --- a/include/llvm/Target/TargetAsmBackend.h +++ b/include/llvm/Target/TargetAsmBackend.h @@ -13,10 +13,9 @@ #include "llvm/System/DataTypes.h" namespace llvm { -class MCAsmFixup; class MCDataFragment; +class MCFixup; class MCInst; -class MCInstFragment; class MCObjectWriter; class MCSection; template<typename T> @@ -90,6 +89,14 @@ public: return false; } + /// isSectionAtomizable - Check whether the given section can be split into + /// atoms. + /// + /// \see MCAssembler::isSymbolLinkerVisible(). + virtual bool isSectionAtomizable(const MCSection &Section) const { + return true; + } + /// isVirtualSection - Check whether the given section is "virtual", that is /// has no actual object file contents. virtual bool isVirtualSection(const MCSection &Section) const = 0; @@ -97,22 +104,22 @@ public: /// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided /// data fragment, at the offset specified by the fixup and following the /// fixup kind as appropriate. - virtual void ApplyFixup(const MCAsmFixup &Fixup, MCDataFragment &Fragment, + virtual void ApplyFixup(const MCFixup &Fixup, MCDataFragment &Fragment, uint64_t Value) const = 0; /// MayNeedRelaxation - Check whether the given instruction may need /// relaxation. /// - /// \arg Inst - The instruction to test. - /// \arg Fixups - The actual fixups this instruction encoded to, for potential - /// use by the target backend. - virtual bool MayNeedRelaxation(const MCInst &Inst, - const SmallVectorImpl<MCAsmFixup> &Fixups) const = 0; + /// \param Inst - The instruction to test. + virtual bool MayNeedRelaxation(const MCInst &Inst) const = 0; /// RelaxInstruction - Relax the instruction in the given fragment to the next /// wider instruction. - virtual void RelaxInstruction(const MCInstFragment *IF, - MCInst &Res) const = 0; + /// + /// \param Inst - The instruction to relax, which may be the same as the + /// output. + /// \parm Res [output] - On return, the relaxed instruction. + virtual void RelaxInstruction(const MCInst &Inst, MCInst &Res) const = 0; /// WriteNopData - Write an (optimal) nop sequence of Count bytes to the given /// output. If the target cannot generate such a sequence, it should return an diff --git a/include/llvm/Target/TargetInstrInfo.h b/include/llvm/Target/TargetInstrInfo.h index 143dbcc..2e5697e 100644 --- a/include/llvm/Target/TargetInstrInfo.h +++ b/include/llvm/Target/TargetInstrInfo.h @@ -315,7 +315,8 @@ public: MachineBasicBlock::iterator MI, unsigned DestReg, unsigned SrcReg, const TargetRegisterClass *DestRC, - const TargetRegisterClass *SrcRC) const { + const TargetRegisterClass *SrcRC, + DebugLoc DL) const { assert(0 && "Target didn't implement TargetInstrInfo::copyRegToReg!"); return false; } @@ -328,7 +329,8 @@ public: virtual void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned SrcReg, bool isKill, int FrameIndex, - const TargetRegisterClass *RC) const { + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { assert(0 && "Target didn't implement TargetInstrInfo::storeRegToStackSlot!"); } @@ -339,7 +341,8 @@ public: virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned DestReg, int FrameIndex, - const TargetRegisterClass *RC) const { + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const { assert(0 && "Target didn't implement TargetInstrInfo::loadRegFromStackSlot!"); } @@ -349,7 +352,8 @@ public: /// storeRegToStackSlot(). Returns false otherwise. virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, - const std::vector<CalleeSavedInfo> &CSI) const { + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const { return false; } @@ -359,7 +363,8 @@ public: /// Returns false otherwise. virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, - const std::vector<CalleeSavedInfo> &CSI) const { + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const { return false; } diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 4ea6c94..5efebe6 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -55,7 +55,6 @@ namespace llvm { class TargetData; class TargetMachine; class TargetRegisterClass; - class TargetSubtarget; class TargetLoweringObjectFile; class Value; @@ -98,11 +97,6 @@ public: ZeroOrNegativeOneBooleanContent // All bits equal to bit 0. }; - enum SchedPreference { - SchedulingForLatency, // Scheduling for shortest total latency. - SchedulingForRegPressure // Scheduling for lowest register pressure. - }; - /// NOTE: The constructor takes ownership of TLOF. explicit TargetLowering(const TargetMachine &TM, const TargetLoweringObjectFile *TLOF); @@ -151,13 +145,20 @@ public: BooleanContent getBooleanContents() const { return BooleanContents;} /// getSchedulingPreference - Return target scheduling preference. - SchedPreference getSchedulingPreference() const { + Sched::Preference getSchedulingPreference() const { return SchedPreferenceInfo; } + /// getSchedulingPreference - Some scheduler, e.g. hybrid, can switch to + /// different scheduling heuristics for different nodes. This function returns + /// the preference (or none) for the given node. + virtual Sched::Preference getSchedulingPreference(SDNode *N) const { + return Sched::None; + } + /// getRegClassFor - Return the register class that should be used for the - /// specified value type. This may only be called on legal types. - TargetRegisterClass *getRegClassFor(EVT VT) const { + /// specified value type. + virtual TargetRegisterClass *getRegClassFor(EVT VT) const { assert(VT.isSimple() && "getRegClassFor called on illegal type!"); TargetRegisterClass *RC = RegClassForVT[VT.getSimpleVT().SimpleTy]; assert(RC && "This value type is not natively supported!"); @@ -181,11 +182,9 @@ public: } 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)". - /// dimension by (MVT::MAX_ALLOWED_VALUETYPE/32) * 2 - uint32_t ValueTypeActions[(MVT::MAX_ALLOWED_VALUETYPE/32)*2]; + /// ValueTypeActions - For each value type, keep a LegalizeAction enum + /// that indicates how instruction selection should deal with the type. + uint8_t ValueTypeActions[MVT::LAST_VALUETYPE]; public: ValueTypeActionImpl() { std::fill(ValueTypeActions, array_endof(ValueTypeActions), 0); @@ -202,13 +201,11 @@ public: return Legal; } unsigned I = VT.getSimpleVT().SimpleTy; - assert(I<4*array_lengthof(ValueTypeActions)*sizeof(ValueTypeActions[0])); - return (LegalizeAction)((ValueTypeActions[I>>4] >> ((2*I) & 31)) & 3); + return (LegalizeAction)ValueTypeActions[I]; } void setTypeAction(EVT VT, LegalizeAction Action) { unsigned I = VT.getSimpleVT().SimpleTy; - assert(I<4*array_lengthof(ValueTypeActions)*sizeof(ValueTypeActions[0])); - ValueTypeActions[I>>4] |= Action << ((I*2) & 31); + ValueTypeActions[I] = Action; } }; @@ -357,13 +354,9 @@ public: /// for it. LegalizeAction getOperationAction(unsigned Op, EVT VT) const { if (VT.isExtended()) return Expand; - assert(Op < array_lengthof(OpActions[0]) && - (unsigned)VT.getSimpleVT().SimpleTy < sizeof(OpActions[0][0])*8 && - "Table isn't big enough!"); + assert(Op < array_lengthof(OpActions[0]) && "Table isn't big enough!"); unsigned I = (unsigned) VT.getSimpleVT().SimpleTy; - unsigned J = I & 31; - I = I >> 5; - return (LegalizeAction)((OpActions[I][Op] >> (J*2) ) & 3); + return (LegalizeAction)OpActions[I][Op]; } /// isOperationLegalOrCustom - Return true if the specified operation is @@ -386,35 +379,31 @@ public: /// either it is legal, needs to be promoted to a larger size, needs to be /// expanded to some other code sequence, or the target has a custom expander /// for it. - LegalizeAction getLoadExtAction(unsigned LType, EVT VT) const { - assert(LType < array_lengthof(LoadExtActions) && - (unsigned)VT.getSimpleVT().SimpleTy < sizeof(LoadExtActions[0])*4 && + LegalizeAction getLoadExtAction(unsigned ExtType, EVT VT) const { + assert(ExtType < ISD::LAST_LOADEXT_TYPE && + (unsigned)VT.getSimpleVT().SimpleTy < MVT::LAST_VALUETYPE && "Table isn't big enough!"); - return (LegalizeAction)((LoadExtActions[LType] >> - (2*VT.getSimpleVT().SimpleTy)) & 3); + return (LegalizeAction)LoadExtActions[VT.getSimpleVT().SimpleTy][ExtType]; } /// isLoadExtLegal - Return true if the specified load with extension is legal /// on this target. - bool isLoadExtLegal(unsigned LType, EVT VT) const { + bool isLoadExtLegal(unsigned ExtType, EVT VT) const { return VT.isSimple() && - (getLoadExtAction(LType, VT) == Legal || - getLoadExtAction(LType, VT) == Custom); + (getLoadExtAction(ExtType, VT) == Legal || + getLoadExtAction(ExtType, VT) == Custom); } /// getTruncStoreAction - Return how this store with truncation should be /// treated: either it is legal, needs to be promoted to a larger size, needs /// to be expanded to some other code sequence, or the target has a custom /// expander for it. - LegalizeAction getTruncStoreAction(EVT ValVT, - EVT MemVT) const { - assert((unsigned)ValVT.getSimpleVT().SimpleTy < - array_lengthof(TruncStoreActions) && - (unsigned)MemVT.getSimpleVT().SimpleTy < - sizeof(TruncStoreActions[0])*4 && + LegalizeAction getTruncStoreAction(EVT ValVT, EVT MemVT) const { + assert((unsigned)ValVT.getSimpleVT().SimpleTy < MVT::LAST_VALUETYPE && + (unsigned)MemVT.getSimpleVT().SimpleTy < MVT::LAST_VALUETYPE && "Table isn't big enough!"); - return (LegalizeAction)((TruncStoreActions[ValVT.getSimpleVT().SimpleTy] >> - (2*MemVT.getSimpleVT().SimpleTy)) & 3); + return (LegalizeAction)TruncStoreActions[ValVT.getSimpleVT().SimpleTy] + [MemVT.getSimpleVT().SimpleTy]; } /// isTruncStoreLegal - Return true if the specified store with truncation is @@ -431,11 +420,11 @@ public: /// for it. LegalizeAction getIndexedLoadAction(unsigned IdxMode, EVT VT) const { - assert( IdxMode < array_lengthof(IndexedModeActions[0][0]) && + assert( IdxMode < ISD::LAST_INDEXED_MODE && ((unsigned)VT.getSimpleVT().SimpleTy) < MVT::LAST_VALUETYPE && "Table isn't big enough!"); - return (LegalizeAction)((IndexedModeActions[ - (unsigned)VT.getSimpleVT().SimpleTy][0][IdxMode])); + unsigned Ty = (unsigned)VT.getSimpleVT().SimpleTy; + return (LegalizeAction)((IndexedModeActions[Ty][IdxMode] & 0xf0) >> 4); } /// isIndexedLoadLegal - Return true if the specified indexed load is legal @@ -452,11 +441,11 @@ public: /// for it. LegalizeAction getIndexedStoreAction(unsigned IdxMode, EVT VT) const { - assert(IdxMode < array_lengthof(IndexedModeActions[0][1]) && - (unsigned)VT.getSimpleVT().SimpleTy < MVT::LAST_VALUETYPE && + assert( IdxMode < ISD::LAST_INDEXED_MODE && + ((unsigned)VT.getSimpleVT().SimpleTy) < MVT::LAST_VALUETYPE && "Table isn't big enough!"); - return (LegalizeAction)((IndexedModeActions[ - (unsigned)VT.getSimpleVT().SimpleTy][1][IdxMode])); + unsigned Ty = (unsigned)VT.getSimpleVT().SimpleTy; + return (LegalizeAction)(IndexedModeActions[Ty][IdxMode] & 0x0f); } /// isIndexedStoreLegal - Return true if the specified indexed load is legal @@ -919,7 +908,7 @@ protected: void setBooleanContents(BooleanContent Ty) { BooleanContents = Ty; } /// setSchedulingPreference - Specify the target scheduling preference. - void setSchedulingPreference(SchedPreference Pref) { + void setSchedulingPreference(Sched::Preference Pref) { SchedPreferenceInfo = Pref; } @@ -991,33 +980,28 @@ protected: /// with the specified type and indicate what to do about it. void setOperationAction(unsigned Op, MVT VT, LegalizeAction Action) { - unsigned I = (unsigned)VT.SimpleTy; - unsigned J = I & 31; - I = I >> 5; - OpActions[I][Op] &= ~(uint64_t(3UL) << (J*2)); - OpActions[I][Op] |= (uint64_t)Action << (J*2); + assert(Op < array_lengthof(OpActions[0]) && "Table isn't big enough!"); + OpActions[(unsigned)VT.SimpleTy][Op] = (uint8_t)Action; } /// setLoadExtAction - Indicate that the specified load with extension does /// not work with the specified type and indicate what to do about it. void setLoadExtAction(unsigned ExtType, MVT VT, - LegalizeAction Action) { - assert((unsigned)VT.SimpleTy*2 < 63 && - ExtType < array_lengthof(LoadExtActions) && + LegalizeAction Action) { + assert(ExtType < ISD::LAST_LOADEXT_TYPE && + (unsigned)VT.SimpleTy < MVT::LAST_VALUETYPE && "Table isn't big enough!"); - LoadExtActions[ExtType] &= ~(uint64_t(3UL) << VT.SimpleTy*2); - LoadExtActions[ExtType] |= (uint64_t)Action << VT.SimpleTy*2; + LoadExtActions[VT.SimpleTy][ExtType] = (uint8_t)Action; } /// setTruncStoreAction - Indicate that the specified truncating store does /// not work with the specified type and indicate what to do about it. void setTruncStoreAction(MVT ValVT, MVT MemVT, LegalizeAction Action) { - assert((unsigned)ValVT.SimpleTy < array_lengthof(TruncStoreActions) && - (unsigned)MemVT.SimpleTy*2 < 63 && + assert((unsigned)ValVT.SimpleTy < MVT::LAST_VALUETYPE && + (unsigned)MemVT.SimpleTy < MVT::LAST_VALUETYPE && "Table isn't big enough!"); - TruncStoreActions[ValVT.SimpleTy] &= ~(uint64_t(3UL) << MemVT.SimpleTy*2); - TruncStoreActions[ValVT.SimpleTy] |= (uint64_t)Action << MemVT.SimpleTy*2; + TruncStoreActions[ValVT.SimpleTy][MemVT.SimpleTy] = (uint8_t)Action; } /// setIndexedLoadAction - Indicate that the specified indexed load does or @@ -1027,9 +1011,12 @@ protected: void setIndexedLoadAction(unsigned IdxMode, MVT VT, LegalizeAction Action) { assert((unsigned)VT.SimpleTy < MVT::LAST_VALUETYPE && - IdxMode < array_lengthof(IndexedModeActions[0][0]) && + IdxMode < ISD::LAST_INDEXED_MODE && + (unsigned)Action < 0xf && "Table isn't big enough!"); - IndexedModeActions[(unsigned)VT.SimpleTy][0][IdxMode] = (uint8_t)Action; + // Load action are kept in the upper half. + IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] &= ~0xf0; + IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] |= ((uint8_t)Action) <<4; } /// setIndexedStoreAction - Indicate that the specified indexed store does or @@ -1039,9 +1026,12 @@ protected: void setIndexedStoreAction(unsigned IdxMode, MVT VT, LegalizeAction Action) { assert((unsigned)VT.SimpleTy < MVT::LAST_VALUETYPE && - IdxMode < array_lengthof(IndexedModeActions[0][1] ) && + IdxMode < ISD::LAST_INDEXED_MODE && + (unsigned)Action < 0xf && "Table isn't big enough!"); - IndexedModeActions[(unsigned)VT.SimpleTy][1][IdxMode] = (uint8_t)Action; + // Store action are kept in the lower half. + IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] &= ~0x0f; + IndexedModeActions[(unsigned)VT.SimpleTy][IdxMode] |= ((uint8_t)Action); } /// setCondCodeAction - Indicate that the specified condition code is or isn't @@ -1103,12 +1093,6 @@ protected: } public: - - virtual const TargetSubtarget *getSubtarget() const { - assert(0 && "Not Implemented"); - return NULL; // this is here to silence compiler errors - } - //===--------------------------------------------------------------------===// // Lowering methods - These methods must be implemented by targets so that // the SelectionDAGLowering code knows how to lower these. @@ -1200,61 +1184,6 @@ public: return SDValue(); // this is here to silence compiler errors } - /// EmitTargetCodeForMemcpy - Emit target-specific code that performs a - /// memcpy. This can be used by targets to provide code sequences for cases - /// that don't fit the target's parameters for simple loads/stores and can be - /// more efficient than using a library call. This function can return a null - /// SDValue if the target declines to use custom code and a different - /// lowering strategy should be used. - /// - /// If AlwaysInline is true, the size is constant and the target should not - /// emit any calls and is strongly encouraged to attempt to emit inline code - /// even if it is beyond the usual threshold because this intrinsic is being - /// expanded in a place where calls are not feasible (e.g. within the prologue - /// for another call). If the target chooses to decline an AlwaysInline - /// request here, legalize will resort to using simple loads and stores. - virtual SDValue - EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, - SDValue Chain, - SDValue Op1, SDValue Op2, - SDValue Op3, unsigned Align, bool isVolatile, - bool AlwaysInline, - const Value *DstSV, uint64_t DstOff, - const Value *SrcSV, uint64_t SrcOff) const { - return SDValue(); - } - - /// EmitTargetCodeForMemmove - Emit target-specific code that performs a - /// memmove. This can be used by targets to provide code sequences for cases - /// that don't fit the target's parameters for simple loads/stores and can be - /// more efficient than using a library call. This function can return a null - /// SDValue if the target declines to use custom code and a different - /// lowering strategy should be used. - virtual SDValue - EmitTargetCodeForMemmove(SelectionDAG &DAG, DebugLoc dl, - SDValue Chain, - SDValue Op1, SDValue Op2, - SDValue Op3, unsigned Align, bool isVolatile, - const Value *DstSV, uint64_t DstOff, - const Value *SrcSV, uint64_t SrcOff) const { - return SDValue(); - } - - /// EmitTargetCodeForMemset - Emit target-specific code that performs a - /// memset. This can be used by targets to provide code sequences for cases - /// that don't fit the target's parameters for simple stores and can be more - /// efficient than using a library call. This function can return a null - /// SDValue if the target declines to use custom code and a different - /// lowering strategy should be used. - virtual SDValue - EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl, - SDValue Chain, - SDValue Op1, SDValue Op2, - SDValue Op3, unsigned Align, bool isVolatile, - const Value *DstSV, uint64_t DstOff) const { - return SDValue(); - } - /// LowerOperationWrapper - This callback is invoked by the type legalizer /// to legalize nodes with an illegal operand type but legal result types. /// It replaces the LowerOperation callback in the type Legalizer. @@ -1594,7 +1523,7 @@ private: /// SchedPreferenceInfo - The target scheduling preference: shortest possible /// total cycles or lowest register usage. - SchedPreference SchedPreferenceInfo; + Sched::Preference SchedPreferenceInfo; /// JumpBufSize - The size, in bytes, of the target's jmp_buf buffers unsigned JumpBufSize; @@ -1653,26 +1582,24 @@ private: /// 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. - /// This array is accessed using VT.getSimpleVT(), so it is subject to - /// the MVT::MAX_ALLOWED_VALUETYPE * 2 bits. - uint64_t OpActions[MVT::MAX_ALLOWED_VALUETYPE/(sizeof(uint64_t)*4)][ISD::BUILTIN_OP_END]; + uint8_t OpActions[MVT::LAST_VALUETYPE][ISD::BUILTIN_OP_END]; - /// LoadExtActions - For each load of load extension type and each value type, + /// LoadExtActions - For each load extension type and each value type, /// keep a LegalizeAction that indicates how instruction selection should deal - /// with the load. - uint64_t LoadExtActions[ISD::LAST_LOADEXT_TYPE]; + /// with a load of a specific value type and extension type. + uint8_t LoadExtActions[MVT::LAST_VALUETYPE][ISD::LAST_LOADEXT_TYPE]; - /// TruncStoreActions - For each truncating store, keep a LegalizeAction that - /// indicates how instruction selection should deal with the store. - uint64_t TruncStoreActions[MVT::LAST_VALUETYPE]; + /// TruncStoreActions - For each value type pair keep a LegalizeAction that + /// indicates whether a truncating store of a specific value type and + /// truncating type is legal. + uint8_t TruncStoreActions[MVT::LAST_VALUETYPE][MVT::LAST_VALUETYPE]; /// IndexedModeActions - For each indexed mode and each value type, /// keep a pair of LegalizeAction that indicates how instruction - /// selection should deal with the load / store. The first - /// dimension is now the value_type for the reference. The second - /// dimension is the load [0] vs. store[1]. The third dimension - /// represents the various modes for load store. - uint8_t IndexedModeActions[MVT::LAST_VALUETYPE][2][ISD::LAST_INDEXED_MODE]; + /// selection should deal with the load / store. The first dimension is the + /// value_type for the reference. The second dimension represents the various + /// modes for load store. + uint8_t IndexedModeActions[MVT::LAST_VALUETYPE][ISD::LAST_INDEXED_MODE]; /// CondCodeActions - For each condition code (ISD::CondCode) keep a /// LegalizeAction that indicates how instruction selection should diff --git a/include/llvm/Target/TargetLoweringObjectFile.h b/include/llvm/Target/TargetLoweringObjectFile.h index 6c99598..819709f 100644 --- a/include/llvm/Target/TargetLoweringObjectFile.h +++ b/include/llvm/Target/TargetLoweringObjectFile.h @@ -88,6 +88,10 @@ protected: const MCSection *DwarfRangesSection; const MCSection *DwarfMacroInfoSection; + // Extra TLS Variable Data section. If the target needs to put additional + // information for a TLS variable, it'll go here. + const MCSection *TLSExtraDataSection; + /// SupportsWeakEmptyEHFrame - True if target object file supports a /// weak_definition of constant 0 for an omitted EH frame. bool SupportsWeakOmittedEHFrame; @@ -147,6 +151,9 @@ public: const MCSection *getDwarfMacroInfoSection() const { return DwarfMacroInfoSection; } + const MCSection *getTLSExtraDataSection() const { + return TLSExtraDataSection; + } /// shouldEmitUsedDirectiveFor - This hook allows targets to selectively /// decide not to emit the UsedDirective for some symbols in llvm.used. diff --git a/include/llvm/Target/TargetMachine.h b/include/llvm/Target/TargetMachine.h index c734cf4..227499b 100644 --- a/include/llvm/Target/TargetMachine.h +++ b/include/llvm/Target/TargetMachine.h @@ -70,6 +70,15 @@ namespace CodeGenOpt { }; } +namespace Sched { + enum Preference { + None, // No preference + Latency, // Scheduling for shortest total latency. + RegPressure, // Scheduling for lowest register pressure. + Hybrid // Scheduling for both latency and register pressure. + }; +} + //===----------------------------------------------------------------------===// /// /// TargetMachine - Primary interface to the complete machine description for @@ -92,7 +101,9 @@ protected: // Can only create subclasses. /// AsmInfo - Contains target specific asm information. /// const MCAsmInfo *AsmInfo; - + + unsigned MCRelaxAll : 1; + public: virtual ~TargetMachine(); @@ -149,6 +160,14 @@ public: /// virtual const TargetELFWriterInfo *getELFWriterInfo() const { return 0; } + /// hasMCRelaxAll - Check whether all machine code instructions should be + /// relaxed. + bool hasMCRelaxAll() const { return MCRelaxAll; } + + /// setMCRelaxAll - Set whether all machine code instructions should be + /// relaxed. + void setMCRelaxAll(bool Value) { MCRelaxAll = Value; } + /// getRelocationModel - Returns the code generation relocation model. The /// choices are static, PIC, and dynamic-no-pic, and target default. static Reloc::Model getRelocationModel(); @@ -225,17 +244,6 @@ public: bool = true) { 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 &, formatted_raw_ostream &, - CodeGenFileType, - CodeGenOpt::Level, - bool = true) { - return true; - } }; /// LLVMTargetMachine - This class describes a target machine that is diff --git a/include/llvm/Target/TargetRegisterInfo.h b/include/llvm/Target/TargetRegisterInfo.h index 29b862a..7c37b73 100644 --- a/include/llvm/Target/TargetRegisterInfo.h +++ b/include/llvm/Target/TargetRegisterInfo.h @@ -28,6 +28,7 @@ class BitVector; class MachineFunction; class MachineMove; class RegScavenger; +template<class T> class SmallVectorImpl; /// TargetRegisterDesc - This record contains all of the information known about /// a particular register. The AliasSet field (if not null) contains a pointer @@ -151,9 +152,6 @@ public: /// index SubIdx, or NULL if no such class exists. const TargetRegisterClass* getSubRegisterRegClass(unsigned SubIdx) const { assert(SubIdx>0 && "Invalid subregister index"); - for (unsigned s = 0; s != SubIdx-1; ++s) - if (!SubRegClasses[s]) - return NULL; return SubRegClasses[SubIdx-1]; } @@ -262,14 +260,13 @@ class TargetRegisterInfo { protected: const unsigned* SubregHash; const unsigned SubregHashSize; - const unsigned* SuperregHash; - const unsigned SuperregHashSize; const unsigned* AliasesHash; const unsigned AliasesHashSize; public: typedef const TargetRegisterClass * const * regclass_iterator; private: const TargetRegisterDesc *Desc; // Pointer to the descriptor array + const char *const *SubRegIndexNames; // Names of subreg indexes. unsigned NumRegs; // Number of entries in the array regclass_iterator RegClassBegin, RegClassEnd; // List of regclasses @@ -280,12 +277,11 @@ protected: TargetRegisterInfo(const TargetRegisterDesc *D, unsigned NR, regclass_iterator RegClassBegin, regclass_iterator RegClassEnd, + const char *const *subregindexnames, int CallFrameSetupOpcode = -1, int CallFrameDestroyOpcode = -1, const unsigned* subregs = 0, const unsigned subregsize = 0, - const unsigned* superregs = 0, - const unsigned superregsize = 0, const unsigned* aliases = 0, const unsigned aliasessize = 0); virtual ~TargetRegisterInfo(); @@ -380,6 +376,13 @@ public: return NumRegs; } + /// getSubRegIndexName - Return the human-readable symbolic target-specific + /// name for the specified SubRegIndex. + const char *getSubRegIndexName(unsigned SubIdx) const { + assert(SubIdx && "This is not a subregister index"); + return SubRegIndexNames[SubIdx-1]; + } + /// 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 { @@ -425,19 +428,7 @@ public: /// isSuperRegister - Returns true if regB is a super-register of regA. /// bool isSuperRegister(unsigned regA, unsigned regB) const { - // SuperregHash is a simple quadratically probed hash table. - size_t index = (regA + regB * 37) & (SuperregHashSize-1); - unsigned ProbeAmt = 2; - while (SuperregHash[index*2] != 0 && - SuperregHash[index*2+1] != 0) { - if (SuperregHash[index*2] == regA && SuperregHash[index*2+1] == regB) - return true; - - index = (index + ProbeAmt) & (SuperregHashSize-1); - ProbeAmt += 2; - } - - return false; + return isSubRegister(regB, regA); } /// getCalleeSavedRegs - Return a null-terminated list of all of the @@ -479,6 +470,17 @@ public: return 0; } + /// canCombinedSubRegIndex - Given a register class and a list of sub-register + /// indices, return true if it's possible to combine the sub-register indices + /// into one that corresponds to a larger sub-register. Return the new sub- + /// register index by reference. Note the new index by be zero if the given + /// sub-registers combined to form the whole register. + virtual bool canCombinedSubRegIndex(const TargetRegisterClass *RC, + SmallVectorImpl<unsigned> &SubIndices, + unsigned &NewSubIdx) const { + return 0; + } + /// getMatchingSuperRegClass - Return a subclass of the specified register /// class A so that each register in it has a sub-register of the /// specified sub-register index which is in the specified register class B. diff --git a/include/llvm/Target/TargetRegistry.h b/include/llvm/Target/TargetRegistry.h index 36bbe00..1418bee 100644 --- a/include/llvm/Target/TargetRegistry.h +++ b/include/llvm/Target/TargetRegistry.h @@ -73,6 +73,13 @@ namespace llvm { typedef MCCodeEmitter *(*CodeEmitterCtorTy)(const Target &T, TargetMachine &TM, MCContext &Ctx); + typedef MCStreamer *(*ObjectStreamerCtorTy)(const Target &T, + const std::string &TT, + MCContext &Ctx, + TargetAsmBackend &TAB, + raw_ostream &_OS, + MCCodeEmitter *_Emitter, + bool RelaxAll); private: /// Next - The next registered target in the linked list, maintained by the @@ -126,6 +133,10 @@ namespace llvm { /// if registered. CodeEmitterCtorTy CodeEmitterCtorFn; + /// ObjectStreamerCtorFn - Construction function for this target's + /// ObjectStreamer, if registered. + ObjectStreamerCtorTy ObjectStreamerCtorFn; + public: /// @name Target Information /// @{ @@ -170,6 +181,9 @@ namespace llvm { /// hasCodeEmitter - Check if this target supports instruction encoding. bool hasCodeEmitter() const { return CodeEmitterCtorFn != 0; } + /// hasObjectStreamer - Check if this target supports streaming to files. + bool hasObjectStreamer() const { return ObjectStreamerCtorFn != 0; } + /// @} /// @name Feature Constructors /// @{ @@ -258,6 +272,24 @@ namespace llvm { return CodeEmitterCtorFn(*this, TM, Ctx); } + /// createObjectStreamer - Create a target specific MCStreamer. + /// + /// \arg TT - The target triple. + /// \arg Ctx - The target context. + /// \arg TAB - The target assembler backend object. + /// \arg _OS - The stream object. + /// \arg _Emitter - The target independent assembler object. + /// \arg RelaxAll - Relax all fixups? + MCStreamer *createObjectStreamer(const std::string &TT, MCContext &Ctx, + TargetAsmBackend &TAB, + raw_ostream &_OS, + MCCodeEmitter *_Emitter, + bool RelaxAll) const { + if (!ObjectStreamerCtorFn) + return 0; + return ObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, RelaxAll); + } + /// @} }; @@ -479,6 +511,20 @@ namespace llvm { T.CodeEmitterCtorFn = Fn; } + /// RegisterObjectStreamer - Register an MCStreamer implementation + /// for the given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCStreamer for the target. + static void RegisterObjectStreamer(Target &T, Target::ObjectStreamerCtorTy Fn) { + if (!T.ObjectStreamerCtorFn) + T.ObjectStreamerCtorFn = Fn; + } + /// @} }; diff --git a/include/llvm/Target/TargetSelectionDAGInfo.h b/include/llvm/Target/TargetSelectionDAGInfo.h index 943bdea..2be1834 100644 --- a/include/llvm/Target/TargetSelectionDAGInfo.h +++ b/include/llvm/Target/TargetSelectionDAGInfo.h @@ -16,19 +16,84 @@ #ifndef LLVM_TARGET_TARGETSELECTIONDAGINFO_H #define LLVM_TARGET_TARGETSELECTIONDAGINFO_H +#include "llvm/CodeGen/SelectionDAGNodes.h" + namespace llvm { +class TargetData; +class TargetMachine; + //===----------------------------------------------------------------------===// -/// TargetSelectionDAGLowering - Targets can subclass this to parameterize the +/// TargetSelectionDAGInfo - Targets can subclass this to parameterize the /// SelectionDAG lowering and instruction selection process. /// class TargetSelectionDAGInfo { TargetSelectionDAGInfo(const TargetSelectionDAGInfo &); // DO NOT IMPLEMENT void operator=(const TargetSelectionDAGInfo &); // DO NOT IMPLEMENT + const TargetData *TD; + +protected: + const TargetData *getTargetData() const { return TD; } + public: - TargetSelectionDAGInfo(); + explicit TargetSelectionDAGInfo(const TargetMachine &TM); virtual ~TargetSelectionDAGInfo(); + + /// EmitTargetCodeForMemcpy - Emit target-specific code that performs a + /// memcpy. This can be used by targets to provide code sequences for cases + /// that don't fit the target's parameters for simple loads/stores and can be + /// more efficient than using a library call. This function can return a null + /// SDValue if the target declines to use custom code and a different + /// lowering strategy should be used. + /// + /// If AlwaysInline is true, the size is constant and the target should not + /// emit any calls and is strongly encouraged to attempt to emit inline code + /// even if it is beyond the usual threshold because this intrinsic is being + /// expanded in a place where calls are not feasible (e.g. within the prologue + /// for another call). If the target chooses to decline an AlwaysInline + /// request here, legalize will resort to using simple loads and stores. + virtual SDValue + EmitTargetCodeForMemcpy(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, + SDValue Op1, SDValue Op2, + SDValue Op3, unsigned Align, bool isVolatile, + bool AlwaysInline, + const Value *DstSV, uint64_t DstOff, + const Value *SrcSV, uint64_t SrcOff) const { + return SDValue(); + } + + /// EmitTargetCodeForMemmove - Emit target-specific code that performs a + /// memmove. This can be used by targets to provide code sequences for cases + /// that don't fit the target's parameters for simple loads/stores and can be + /// more efficient than using a library call. This function can return a null + /// SDValue if the target declines to use custom code and a different + /// lowering strategy should be used. + virtual SDValue + EmitTargetCodeForMemmove(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, + SDValue Op1, SDValue Op2, + SDValue Op3, unsigned Align, bool isVolatile, + const Value *DstSV, uint64_t DstOff, + const Value *SrcSV, uint64_t SrcOff) const { + return SDValue(); + } + + /// EmitTargetCodeForMemset - Emit target-specific code that performs a + /// memset. This can be used by targets to provide code sequences for cases + /// that don't fit the target's parameters for simple stores and can be more + /// efficient than using a library call. This function can return a null + /// SDValue if the target declines to use custom code and a different + /// lowering strategy should be used. + virtual SDValue + EmitTargetCodeForMemset(SelectionDAG &DAG, DebugLoc dl, + SDValue Chain, + SDValue Op1, SDValue Op2, + SDValue Op3, unsigned Align, bool isVolatile, + const Value *DstSV, uint64_t DstOff) const { + return SDValue(); + } }; } // end llvm namespace diff --git a/include/llvm/Transforms/Scalar.h b/include/llvm/Transforms/Scalar.h index a8c9c6a..0d338b5 100644 --- a/include/llvm/Transforms/Scalar.h +++ b/include/llvm/Transforms/Scalar.h @@ -332,6 +332,12 @@ FunctionPass *createGEPSplitterPass(); // FunctionPass *createABCDPass(); +//===----------------------------------------------------------------------===// +// +// Sink - Code Sinking +// +FunctionPass *createSinkingPass(); + } // End llvm namespace #endif diff --git a/include/llvm/Transforms/Utils/SSAUpdater.h b/include/llvm/Transforms/Utils/SSAUpdater.h index 5b77ed6..ca98466 100644 --- a/include/llvm/Transforms/Utils/SSAUpdater.h +++ b/include/llvm/Transforms/Utils/SSAUpdater.h @@ -19,8 +19,8 @@ namespace llvm { class BasicBlock; class Use; class PHINode; - template<typename T> - class SmallVectorImpl; + template<typename T> class SmallVectorImpl; + template<typename T> class SSAUpdaterTraits; class BumpPtrAllocator; /// SSAUpdater - This class updates SSA form for a set of values defined in @@ -28,9 +28,7 @@ namespace llvm { /// transformation wants to rewrite a set of uses of one value with uses of a /// set of values. class SSAUpdater { -public: - class BBInfo; - typedef SmallVectorImpl<BBInfo*> BlockListTy; + friend class SSAUpdaterTraits<SSAUpdater>; private: /// AvailableVals - This keeps track of which value to use on a per-block @@ -42,14 +40,10 @@ private: /// and a type for PHI nodes. Value *PrototypeValue; - /// BBMap - The GetValueAtEndOfBlock method maintains this mapping from - /// basic blocks to BBInfo structures. - /// typedef DenseMap<BasicBlock*, BBInfo*> BBMapTy; - void *BM; - /// InsertedPHIs - If this is non-null, the SSAUpdater adds all PHI nodes that /// it creates to the vector. SmallVectorImpl<PHINode*> *InsertedPHIs; + public: /// SSAUpdater constructor. If InsertedPHIs is specified, it will be filled /// in with all PHI Nodes created by rewriting. @@ -102,14 +96,6 @@ public: private: Value *GetValueAtEndOfBlockInternal(BasicBlock *BB); - void BuildBlockList(BasicBlock *BB, BlockListTy *BlockList, - BumpPtrAllocator *Allocator); - void FindDominators(BlockListTy *BlockList); - void FindPHIPlacement(BlockListTy *BlockList); - void FindAvailableVals(BlockListTy *BlockList); - void FindExistingPHI(BasicBlock *BB, BlockListTy *BlockList); - bool CheckIfPHIMatches(PHINode *PHI); - void RecordMatchingPHI(PHINode *PHI); void operator=(const SSAUpdater&); // DO NOT IMPLEMENT SSAUpdater(const SSAUpdater&); // DO NOT IMPLEMENT diff --git a/include/llvm/Transforms/Utils/SSAUpdaterImpl.h b/include/llvm/Transforms/Utils/SSAUpdaterImpl.h new file mode 100644 index 0000000..5a03d22 --- /dev/null +++ b/include/llvm/Transforms/Utils/SSAUpdaterImpl.h @@ -0,0 +1,469 @@ +//===-- SSAUpdaterImpl.h - SSA Updater Implementation -----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file provides a template that implements the core algorithm for the +// SSAUpdater and MachineSSAUpdater. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_SSAUPDATERIMPL_H +#define LLVM_TRANSFORMS_UTILS_SSAUPDATERIMPL_H + +namespace llvm { + +template<typename T> class SSAUpdaterTraits; + +template<typename UpdaterT> +class SSAUpdaterImpl { +private: + UpdaterT *Updater; + + typedef SSAUpdaterTraits<UpdaterT> Traits; + typedef typename Traits::BlkT BlkT; + typedef typename Traits::ValT ValT; + typedef typename Traits::PhiT PhiT; + + /// BBInfo - Per-basic block information used internally by SSAUpdaterImpl. + /// The predecessors of each block are cached here since pred_iterator is + /// slow and we need to iterate over the blocks at least a few times. + class BBInfo { + public: + BlkT *BB; // Back-pointer to the corresponding block. + ValT AvailableVal; // Value to use in this block. + BBInfo *DefBB; // Block that defines the available value. + int BlkNum; // Postorder number. + BBInfo *IDom; // Immediate dominator. + unsigned NumPreds; // Number of predecessor blocks. + BBInfo **Preds; // Array[NumPreds] of predecessor blocks. + PhiT *PHITag; // Marker for existing PHIs that match. + + BBInfo(BlkT *ThisBB, ValT V) + : BB(ThisBB), AvailableVal(V), DefBB(V ? this : 0), BlkNum(0), IDom(0), + NumPreds(0), Preds(0), PHITag(0) { } + }; + + typedef DenseMap<BlkT*, ValT> AvailableValsTy; + AvailableValsTy *AvailableVals; + + SmallVectorImpl<PhiT*> *InsertedPHIs; + + typedef SmallVectorImpl<BBInfo*> BlockListTy; + typedef DenseMap<BlkT*, BBInfo*> BBMapTy; + BBMapTy BBMap; + BumpPtrAllocator Allocator; + +public: + explicit SSAUpdaterImpl(UpdaterT *U, AvailableValsTy *A, + SmallVectorImpl<PhiT*> *Ins) : + Updater(U), AvailableVals(A), InsertedPHIs(Ins) { } + + /// GetValue - Check to see if AvailableVals has an entry for the specified + /// BB and if so, return it. If not, construct SSA form by first + /// calculating the required placement of PHIs and then inserting new PHIs + /// where needed. + ValT GetValue(BlkT *BB) { + SmallVector<BBInfo*, 100> BlockList; + BBInfo *PseudoEntry = BuildBlockList(BB, &BlockList); + + // Special case: bail out if BB is unreachable. + if (BlockList.size() == 0) { + ValT V = Traits::GetUndefVal(BB, Updater); + (*AvailableVals)[BB] = V; + return V; + } + + FindDominators(&BlockList, PseudoEntry); + FindPHIPlacement(&BlockList); + FindAvailableVals(&BlockList); + + return BBMap[BB]->DefBB->AvailableVal; + } + + /// BuildBlockList - Starting from the specified basic block, traverse back + /// through its predecessors until reaching blocks with known values. + /// Create BBInfo structures for the blocks and append them to the block + /// list. + BBInfo *BuildBlockList(BlkT *BB, BlockListTy *BlockList) { + SmallVector<BBInfo*, 10> RootList; + SmallVector<BBInfo*, 64> WorkList; + + BBInfo *Info = new (Allocator) BBInfo(BB, 0); + BBMap[BB] = Info; + WorkList.push_back(Info); + + // Search backward from BB, creating BBInfos along the way and stopping + // when reaching blocks that define the value. Record those defining + // blocks on the RootList. + SmallVector<BlkT*, 10> Preds; + while (!WorkList.empty()) { + Info = WorkList.pop_back_val(); + Preds.clear(); + Traits::FindPredecessorBlocks(Info->BB, &Preds); + Info->NumPreds = Preds.size(); + if (Info->NumPreds == 0) + Info->Preds = 0; + else + Info->Preds = static_cast<BBInfo**> + (Allocator.Allocate(Info->NumPreds * sizeof(BBInfo*), + AlignOf<BBInfo*>::Alignment)); + + for (unsigned p = 0; p != Info->NumPreds; ++p) { + BlkT *Pred = Preds[p]; + // Check if BBMap already has a BBInfo for the predecessor block. + typename BBMapTy::value_type &BBMapBucket = + BBMap.FindAndConstruct(Pred); + if (BBMapBucket.second) { + Info->Preds[p] = BBMapBucket.second; + continue; + } + + // Create a new BBInfo for the predecessor. + ValT PredVal = AvailableVals->lookup(Pred); + BBInfo *PredInfo = new (Allocator) BBInfo(Pred, PredVal); + BBMapBucket.second = PredInfo; + Info->Preds[p] = PredInfo; + + if (PredInfo->AvailableVal) { + RootList.push_back(PredInfo); + continue; + } + WorkList.push_back(PredInfo); + } + } + + // Now that we know what blocks are backwards-reachable from the starting + // block, do a forward depth-first traversal to assign postorder numbers + // to those blocks. + BBInfo *PseudoEntry = new (Allocator) BBInfo(0, 0); + unsigned BlkNum = 1; + + // Initialize the worklist with the roots from the backward traversal. + while (!RootList.empty()) { + Info = RootList.pop_back_val(); + Info->IDom = PseudoEntry; + Info->BlkNum = -1; + WorkList.push_back(Info); + } + + while (!WorkList.empty()) { + Info = WorkList.back(); + + if (Info->BlkNum == -2) { + // All the successors have been handled; assign the postorder number. + Info->BlkNum = BlkNum++; + // If not a root, put it on the BlockList. + if (!Info->AvailableVal) + BlockList->push_back(Info); + WorkList.pop_back(); + continue; + } + + // Leave this entry on the worklist, but set its BlkNum to mark that its + // successors have been put on the worklist. When it returns to the top + // the list, after handling its successors, it will be assigned a + // number. + Info->BlkNum = -2; + + // Add unvisited successors to the work list. + for (typename Traits::BlkSucc_iterator SI = + Traits::BlkSucc_begin(Info->BB), + E = Traits::BlkSucc_end(Info->BB); SI != E; ++SI) { + BBInfo *SuccInfo = BBMap[*SI]; + if (!SuccInfo || SuccInfo->BlkNum) + continue; + SuccInfo->BlkNum = -1; + WorkList.push_back(SuccInfo); + } + } + PseudoEntry->BlkNum = BlkNum; + return PseudoEntry; + } + + /// IntersectDominators - This is the dataflow lattice "meet" operation for + /// finding dominators. Given two basic blocks, it walks up the dominator + /// tree until it finds a common dominator of both. It uses the postorder + /// number of the blocks to determine how to do that. + BBInfo *IntersectDominators(BBInfo *Blk1, BBInfo *Blk2) { + while (Blk1 != Blk2) { + while (Blk1->BlkNum < Blk2->BlkNum) { + Blk1 = Blk1->IDom; + if (!Blk1) + return Blk2; + } + while (Blk2->BlkNum < Blk1->BlkNum) { + Blk2 = Blk2->IDom; + if (!Blk2) + return Blk1; + } + } + return Blk1; + } + + /// FindDominators - Calculate the dominator tree for the subset of the CFG + /// corresponding to the basic blocks on the BlockList. This uses the + /// algorithm from: "A Simple, Fast Dominance Algorithm" by Cooper, Harvey + /// and Kennedy, published in Software--Practice and Experience, 2001, + /// 4:1-10. Because the CFG subset does not include any edges leading into + /// blocks that define the value, the results are not the usual dominator + /// tree. The CFG subset has a single pseudo-entry node with edges to a set + /// of root nodes for blocks that define the value. The dominators for this + /// subset CFG are not the standard dominators but they are adequate for + /// placing PHIs within the subset CFG. + void FindDominators(BlockListTy *BlockList, BBInfo *PseudoEntry) { + bool Changed; + do { + Changed = false; + // Iterate over the list in reverse order, i.e., forward on CFG edges. + for (typename BlockListTy::reverse_iterator I = BlockList->rbegin(), + E = BlockList->rend(); I != E; ++I) { + BBInfo *Info = *I; + BBInfo *NewIDom = 0; + + // Iterate through the block's predecessors. + for (unsigned p = 0; p != Info->NumPreds; ++p) { + BBInfo *Pred = Info->Preds[p]; + + // Treat an unreachable predecessor as a definition with 'undef'. + if (Pred->BlkNum == 0) { + Pred->AvailableVal = Traits::GetUndefVal(Pred->BB, Updater); + (*AvailableVals)[Pred->BB] = Pred->AvailableVal; + Pred->DefBB = Pred; + Pred->BlkNum = PseudoEntry->BlkNum; + PseudoEntry->BlkNum++; + } + + if (!NewIDom) + NewIDom = Pred; + else + NewIDom = IntersectDominators(NewIDom, Pred); + } + + // Check if the IDom value has changed. + if (NewIDom && NewIDom != Info->IDom) { + Info->IDom = NewIDom; + Changed = true; + } + } + } while (Changed); + } + + /// IsDefInDomFrontier - Search up the dominator tree from Pred to IDom for + /// any blocks containing definitions of the value. If one is found, then + /// the successor of Pred is in the dominance frontier for the definition, + /// and this function returns true. + bool IsDefInDomFrontier(const BBInfo *Pred, const BBInfo *IDom) { + for (; Pred != IDom; Pred = Pred->IDom) { + if (Pred->DefBB == Pred) + return true; + } + return false; + } + + /// FindPHIPlacement - PHIs are needed in the iterated dominance frontiers + /// of the known definitions. Iteratively add PHIs in the dom frontiers + /// until nothing changes. Along the way, keep track of the nearest + /// dominating definitions for non-PHI blocks. + void FindPHIPlacement(BlockListTy *BlockList) { + bool Changed; + do { + Changed = false; + // Iterate over the list in reverse order, i.e., forward on CFG edges. + for (typename BlockListTy::reverse_iterator I = BlockList->rbegin(), + E = BlockList->rend(); I != E; ++I) { + BBInfo *Info = *I; + + // If this block already needs a PHI, there is nothing to do here. + if (Info->DefBB == Info) + continue; + + // Default to use the same def as the immediate dominator. + BBInfo *NewDefBB = Info->IDom->DefBB; + for (unsigned p = 0; p != Info->NumPreds; ++p) { + if (IsDefInDomFrontier(Info->Preds[p], Info->IDom)) { + // Need a PHI here. + NewDefBB = Info; + break; + } + } + + // Check if anything changed. + if (NewDefBB != Info->DefBB) { + Info->DefBB = NewDefBB; + Changed = true; + } + } + } while (Changed); + } + + /// FindAvailableVal - If this block requires a PHI, first check if an + /// existing PHI matches the PHI placement and reaching definitions computed + /// earlier, and if not, create a new PHI. Visit all the block's + /// predecessors to calculate the available value for each one and fill in + /// the incoming values for a new PHI. + void FindAvailableVals(BlockListTy *BlockList) { + // Go through the worklist in forward order (i.e., backward through the CFG) + // and check if existing PHIs can be used. If not, create empty PHIs where + // they are needed. + for (typename BlockListTy::iterator I = BlockList->begin(), + E = BlockList->end(); I != E; ++I) { + BBInfo *Info = *I; + // Check if there needs to be a PHI in BB. + if (Info->DefBB != Info) + continue; + + // Look for an existing PHI. + FindExistingPHI(Info->BB, BlockList); + if (Info->AvailableVal) + continue; + + ValT PHI = Traits::CreateEmptyPHI(Info->BB, Info->NumPreds, Updater); + Info->AvailableVal = PHI; + (*AvailableVals)[Info->BB] = PHI; + } + + // Now go back through the worklist in reverse order to fill in the + // arguments for any new PHIs added in the forward traversal. + for (typename BlockListTy::reverse_iterator I = BlockList->rbegin(), + E = BlockList->rend(); I != E; ++I) { + BBInfo *Info = *I; + + if (Info->DefBB != Info) { + // Record the available value at join nodes to speed up subsequent + // uses of this SSAUpdater for the same value. + if (Info->NumPreds > 1) + (*AvailableVals)[Info->BB] = Info->DefBB->AvailableVal; + continue; + } + + // Check if this block contains a newly added PHI. + PhiT *PHI = Traits::ValueIsNewPHI(Info->AvailableVal, Updater); + if (!PHI) + continue; + + // Iterate through the block's predecessors. + for (unsigned p = 0; p != Info->NumPreds; ++p) { + BBInfo *PredInfo = Info->Preds[p]; + BlkT *Pred = PredInfo->BB; + // Skip to the nearest preceding definition. + if (PredInfo->DefBB != PredInfo) + PredInfo = PredInfo->DefBB; + Traits::AddPHIOperand(PHI, PredInfo->AvailableVal, Pred); + } + + DEBUG(dbgs() << " Inserted PHI: " << *PHI << "\n"); + + // If the client wants to know about all new instructions, tell it. + if (InsertedPHIs) InsertedPHIs->push_back(PHI); + } + } + + /// FindExistingPHI - Look through the PHI nodes in a block to see if any of + /// them match what is needed. + void FindExistingPHI(BlkT *BB, BlockListTy *BlockList) { + for (typename BlkT::iterator BBI = BB->begin(), BBE = BB->end(); + BBI != BBE; ++BBI) { + PhiT *SomePHI = Traits::InstrIsPHI(BBI); + if (!SomePHI) + break; + if (CheckIfPHIMatches(SomePHI)) { + RecordMatchingPHI(SomePHI); + break; + } + // Match failed: clear all the PHITag values. + for (typename BlockListTy::iterator I = BlockList->begin(), + E = BlockList->end(); I != E; ++I) + (*I)->PHITag = 0; + } + } + + /// CheckIfPHIMatches - Check if a PHI node matches the placement and values + /// in the BBMap. + bool CheckIfPHIMatches(PhiT *PHI) { + SmallVector<PhiT*, 20> WorkList; + WorkList.push_back(PHI); + + // Mark that the block containing this PHI has been visited. + BBMap[PHI->getParent()]->PHITag = PHI; + + while (!WorkList.empty()) { + PHI = WorkList.pop_back_val(); + + // Iterate through the PHI's incoming values. + for (typename Traits::PHI_iterator I = Traits::PHI_begin(PHI), + E = Traits::PHI_end(PHI); I != E; ++I) { + ValT IncomingVal = I.getIncomingValue(); + BBInfo *PredInfo = BBMap[I.getIncomingBlock()]; + // Skip to the nearest preceding definition. + if (PredInfo->DefBB != PredInfo) + PredInfo = PredInfo->DefBB; + + // Check if it matches the expected value. + if (PredInfo->AvailableVal) { + if (IncomingVal == PredInfo->AvailableVal) + continue; + return false; + } + + // Check if the value is a PHI in the correct block. + PhiT *IncomingPHIVal = Traits::ValueIsPHI(IncomingVal, Updater); + if (!IncomingPHIVal || IncomingPHIVal->getParent() != PredInfo->BB) + return false; + + // If this block has already been visited, check if this PHI matches. + if (PredInfo->PHITag) { + if (IncomingPHIVal == PredInfo->PHITag) + continue; + return false; + } + PredInfo->PHITag = IncomingPHIVal; + + WorkList.push_back(IncomingPHIVal); + } + } + return true; + } + + /// RecordMatchingPHI - For a PHI node that matches, record it and its input + /// PHIs in both the BBMap and the AvailableVals mapping. + void RecordMatchingPHI(PhiT *PHI) { + SmallVector<PhiT*, 20> WorkList; + WorkList.push_back(PHI); + + // Record this PHI. + BlkT *BB = PHI->getParent(); + ValT PHIVal = Traits::GetPHIValue(PHI); + (*AvailableVals)[BB] = PHIVal; + BBMap[BB]->AvailableVal = PHIVal; + + while (!WorkList.empty()) { + PHI = WorkList.pop_back_val(); + + // Iterate through the PHI's incoming values. + for (typename Traits::PHI_iterator I = Traits::PHI_begin(PHI), + E = Traits::PHI_end(PHI); I != E; ++I) { + ValT IncomingVal = I.getIncomingValue(); + PhiT *IncomingPHI = Traits::ValueIsPHI(IncomingVal, Updater); + if (!IncomingPHI) continue; + BB = IncomingPHI->getParent(); + BBInfo *Info = BBMap[BB]; + if (!Info || Info->AvailableVal) + continue; + + // Record the PHI and add it to the worklist. + (*AvailableVals)[BB] = IncomingVal; + Info->AvailableVal = IncomingVal; + WorkList.push_back(IncomingPHI); + } + } + } +}; + +} // End llvm namespace + +#endif |