diff options
Diffstat (limited to 'include/llvm/Support')
35 files changed, 1851 insertions, 1943 deletions
diff --git a/include/llvm/Support/AlignOf.h b/include/llvm/Support/AlignOf.h index cebfa79..85607c8 100644 --- a/include/llvm/Support/AlignOf.h +++ b/include/llvm/Support/AlignOf.h @@ -15,6 +15,9 @@ #ifndef LLVM_SUPPORT_ALIGNOF_H #define LLVM_SUPPORT_ALIGNOF_H +#include "llvm/Support/Compiler.h" +#include <cstddef> + namespace llvm { template <typename T> @@ -54,7 +57,94 @@ struct AlignOf { /// class besides some cosmetic cleanliness. Example usage: /// alignOf<int>() returns the alignment of an int. template <typename T> -static inline unsigned alignOf() { return AlignOf<T>::Alignment; } +inline unsigned alignOf() { return AlignOf<T>::Alignment; } + + +/// \brief Helper for building an aligned character array type. +/// +/// This template is used to explicitly build up a collection of aligned +/// character types. We have to build these up using a macro and explicit +/// specialization to cope with old versions of MSVC and GCC where only an +/// integer literal can be used to specify an alignment constraint. Once built +/// up here, we can then begin to indirect between these using normal C++ +/// template parameters. +template <size_t Alignment> struct AlignedCharArrayImpl {}; +template <> struct AlignedCharArrayImpl<0> { + typedef char type; +}; +#if __has_feature(cxx_alignas) +#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ + template <> struct AlignedCharArrayImpl<x> { \ + typedef char alignas(x) type; \ + } +#elif defined(__clang__) || defined(__GNUC__) +#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ + template <> struct AlignedCharArrayImpl<x> { \ + typedef char type __attribute__((aligned(x))); \ + } +#elif defined(_MSC_VER) +#define LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(x) \ + template <> struct AlignedCharArrayImpl<x> { \ + typedef __declspec(align(x)) char type; \ + } +#else +# error No supported align as directive. +#endif + +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(16); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(32); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(64); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(128); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(512); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(1024); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(2048); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(4096); +LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT(8192); +// Any larger and MSVC complains. +#undef LLVM_ALIGNEDCHARARRAY_TEMPLATE_ALIGNMENT + +/// \brief This class template exposes a typedef for type containing a suitable +/// aligned character array to hold elements of any of up to four types. +/// +/// These types may be arrays, structs, or any other types. The goal is to +/// produce a union type containing a character array which, when used, forms +/// storage suitable to placement new any of these types over. Support for more +/// than four types can be added at the cost of more boiler plate. +template <typename T1, + typename T2 = char, typename T3 = char, typename T4 = char> +class AlignedCharArray { + class AlignerImpl { + T1 t1; T2 t2; T3 t3; T4 t4; + + AlignerImpl(); // Never defined or instantiated. + }; + union SizerImpl { + char arr1[sizeof(T1)], arr2[sizeof(T2)], arr3[sizeof(T3)], arr4[sizeof(T4)]; + }; + +public: + // Sadly, Clang and GCC both fail to align a character array properly even + // with an explicit alignment attribute. To work around this, we union + // the character array that will actually be used with a struct that contains + // a single aligned character member. Tests seem to indicate that both Clang + // and GCC will properly register the alignment of a struct containing an + // aligned member, and this alignment should carry over to the character + // array in the union. + union union_type { + // This is the only member of the union which should be used by clients: + char buffer[sizeof(SizerImpl)]; + + // This member of the union only exists to force the alignment. + struct { + typename llvm::AlignedCharArrayImpl<AlignOf<AlignerImpl>::Alignment>::type + nonce_inner_member; + } nonce_member; + }; +}; } // end namespace llvm #endif diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index 88c60ba..6c2ee08 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -50,6 +50,8 @@ namespace COFF { }; enum MachineTypes { + MT_Invalid = -1, + IMAGE_FILE_MACHINE_UNKNOWN = 0x0, IMAGE_FILE_MACHINE_AM33 = 0x13, IMAGE_FILE_MACHINE_AMD64 = 0x8664, @@ -74,6 +76,8 @@ namespace COFF { }; enum Characteristics { + C_Invalid = 0, + /// The file does not contain base relocations and must be loaded at its /// preferred base. If this cannot be done, the loader will error. IMAGE_FILE_RELOCS_STRIPPED = 0x0001, @@ -114,9 +118,9 @@ namespace COFF { struct symbol { char Name[NameSize]; uint32_t Value; + uint16_t SectionNumber; uint16_t Type; uint8_t StorageClass; - uint16_t SectionNumber; uint8_t NumberOfAuxSymbols; }; @@ -138,6 +142,8 @@ namespace COFF { /// Storage class tells where and what the symbol represents enum SymbolStorageClass { + SSC_Invalid = -1, + IMAGE_SYM_CLASS_END_OF_FUNCTION = -1, ///< Physical end of function IMAGE_SYM_CLASS_NULL = 0, ///< No symbol IMAGE_SYM_CLASS_AUTOMATIC = 1, ///< Stack variable @@ -214,6 +220,8 @@ namespace COFF { }; enum SectionCharacteristics { + SC_Invalid = -1, + IMAGE_SCN_TYPE_NO_PAD = 0x00000008, IMAGE_SCN_CNT_CODE = 0x00000020, IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040, diff --git a/include/llvm/Support/CallSite.h b/include/llvm/Support/CallSite.h index 20634ed..c23bb6a 100644 --- a/include/llvm/Support/CallSite.h +++ b/include/llvm/Support/CallSite.h @@ -184,6 +184,11 @@ public: CALLSITE_DELEGATE_SETTER(setAttributes(PAL)); } + /// \brief Return true if this function has the given attribute. + bool hasFnAttr(Attributes N) const { + CALLSITE_DELEGATE_GETTER(hasFnAttr(N)); + } + /// paramHasAttr - whether the call or the callee has the given attribute. bool paramHasAttr(uint16_t i, Attributes attr) const { CALLSITE_DELEGATE_GETTER(paramHasAttr(i, attr)); diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index c212d2d..ae1570d 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -217,11 +217,11 @@ public: void setMiscFlag(enum MiscFlags M) { Misc |= M; } void setPosition(unsigned pos) { Position = pos; } protected: - explicit Option(enum NumOccurrencesFlag Occurrences, + explicit Option(enum NumOccurrencesFlag OccurrencesFlag, enum OptionHidden Hidden) - : NumOccurrences(0), Occurrences(Occurrences), HiddenFlag(Hidden), - Formatting(NormalFormatting), Position(0), - AdditionalVals(0), NextRegistered(0), + : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), + HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), + Position(0), AdditionalVals(0), NextRegistered(0), ArgStr(""), HelpStr(""), ValueStr("") { } diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index d0b186e..f654f32 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -19,6 +19,25 @@ # define __has_feature(x) 0 #endif +/// LLVM_HAS_RVALUE_REFERENCES - Does the compiler provide r-value references? +/// This implies that <utility> provides the one-argument std::move; it +/// does not imply the existence of any other C++ library features. +#if (__has_feature(cxx_rvalue_references) \ + || defined(__GXX_EXPERIMENTAL_CXX0X__) \ + || _MSC_VER >= 1600) +#define LLVM_USE_RVALUE_REFERENCES 1 +#else +#define LLVM_USE_RVALUE_REFERENCES 0 +#endif + +/// llvm_move - Expands to ::std::move if the compiler supports +/// r-value references; otherwise, expands to the argument. +#if LLVM_USE_RVALUE_REFERENCES +#define llvm_move(value) (::std::move(value)) +#else +#define llvm_move(value) (value) +#endif + /// 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 @@ -102,7 +121,7 @@ // 3.4 supported this but is buggy in various cases and produces unimplemented // errors, just use it in GCC 4.0 and later. #if __GNUC__ > 3 -#define LLVM_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) +#define LLVM_ATTRIBUTE_ALWAYS_INLINE inline __attribute__((always_inline)) #elif defined(_MSC_VER) #define LLVM_ATTRIBUTE_ALWAYS_INLINE __forceinline #else diff --git a/include/llvm/Support/ConstantRange.h b/include/llvm/Support/ConstantRange.h index ced3a2c..90dd69f 100644 --- a/include/llvm/Support/ConstantRange.h +++ b/include/llvm/Support/ConstantRange.h @@ -155,6 +155,10 @@ public: /// constant range. ConstantRange subtract(const APInt &CI) const; + /// \brief Subtract the specified range from this range (aka relative + /// complement of the sets). + ConstantRange difference(const ConstantRange &CR) const; + /// intersectWith - Return the range that results from the intersection of /// this range with another range. The resultant range is guaranteed to /// include all elements contained in both input ranges, and to have the diff --git a/include/llvm/Support/DataTypes.h.cmake b/include/llvm/Support/DataTypes.h.cmake index a3a6489..7484abd 100644 --- a/include/llvm/Support/DataTypes.h.cmake +++ b/include/llvm/Support/DataTypes.h.cmake @@ -79,18 +79,6 @@ typedef u_int64_t uint64_t; #endif #endif -#ifdef _OpenBSD_ -#define INT8_MAX 127 -#define INT8_MIN -128 -#define UINT8_MAX 255 -#define INT16_MAX 32767 -#define INT16_MIN -32768 -#define UINT16_MAX 65535 -#define INT32_MAX 2147483647 -#define INT32_MIN -2147483648 -#define UINT32_MAX 4294967295U -#endif - #else /* _MSC_VER */ /* Visual C++ doesn't provide standard integer headers, but it does provide built-in data types. */ diff --git a/include/llvm/Support/DataTypes.h.in b/include/llvm/Support/DataTypes.h.in index b492bb1..b9fb48a 100644 --- a/include/llvm/Support/DataTypes.h.in +++ b/include/llvm/Support/DataTypes.h.in @@ -79,18 +79,6 @@ typedef u_int64_t uint64_t; #endif #endif -#ifdef _OpenBSD_ -#define INT8_MAX 127 -#define INT8_MIN -128 -#define UINT8_MAX 255 -#define INT16_MAX 32767 -#define INT16_MIN -32768 -#define UINT16_MAX 65535 -#define INT32_MAX 2147483647 -#define INT32_MIN -2147483648 -#define UINT32_MAX 4294967295U -#endif - #else /* _MSC_VER */ /* Visual C++ doesn't provide standard integer headers, but it does provide built-in data types. */ diff --git a/include/llvm/Support/Debug.h b/include/llvm/Support/Debug.h index e723272..896fe84 100644 --- a/include/llvm/Support/Debug.h +++ b/include/llvm/Support/Debug.h @@ -19,7 +19,7 @@ // foo class. // // When compiling without assertions, the -debug-* options and all code in -// DEBUG() statements disappears, so it does not effect the runtime of the code. +// DEBUG() statements disappears, so it does not affect the runtime of the code. // //===----------------------------------------------------------------------===// @@ -49,11 +49,11 @@ extern bool DebugFlag; /// bool isCurrentDebugType(const char *Type); -/// SetCurrentDebugType - Set the current debug type, as if the -debug-only=X +/// setCurrentDebugType - Set the current debug type, as if the -debug-only=X /// option were specified. Note that DebugFlag also needs to be set to true for /// debug output to be produced. /// -void SetCurrentDebugType(const char *Type); +void setCurrentDebugType(const char *Type); /// DEBUG_WITH_TYPE macro - This macro should be used by passes to emit debug /// information. In the '-debug' option is specified on the commandline, and if @@ -70,7 +70,7 @@ void SetCurrentDebugType(const char *Type); #else #define isCurrentDebugType(X) (false) -#define SetCurrentDebugType(X) +#define setCurrentDebugType(X) #define DEBUG_WITH_TYPE(TYPE, X) do { } while (0) #endif diff --git a/include/llvm/Support/DebugLoc.h b/include/llvm/Support/DebugLoc.h index 2ee9f87..0498075 100644 --- a/include/llvm/Support/DebugLoc.h +++ b/include/llvm/Support/DebugLoc.h @@ -15,9 +15,8 @@ #ifndef LLVM_SUPPORT_DEBUGLOC_H #define LLVM_SUPPORT_DEBUGLOC_H -#include "llvm/ADT/DenseMapInfo.h" - namespace llvm { + template <typename T> struct DenseMapInfo; class MDNode; class LLVMContext; @@ -103,10 +102,10 @@ namespace llvm { template <> struct DenseMapInfo<DebugLoc> { - static DebugLoc getEmptyKey(); - static DebugLoc getTombstoneKey(); + static DebugLoc getEmptyKey() { return DebugLoc::getEmptyKey(); } + static DebugLoc getTombstoneKey() { return DebugLoc::getTombstoneKey(); } static unsigned getHashValue(const DebugLoc &Key); - static bool isEqual(const DebugLoc &LHS, const DebugLoc &RHS); + static bool isEqual(DebugLoc LHS, DebugLoc RHS) { return LHS == RHS; } }; } // end namespace llvm diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index 04953b6..f7ae60f 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -248,7 +248,7 @@ enum { EM_CYPRESS_M8C = 161, // Cypress M8C microprocessor EM_R32C = 162, // Renesas R32C series microprocessors EM_TRIMEDIA = 163, // NXP Semiconductors TriMedia architecture family - EM_QDSP6 = 164, // QUALCOMM DSP6 Processor + EM_HEXAGON = 164, // Qualcomm Hexagon processor EM_8051 = 165, // Intel 8051 and variants EM_STXP7X = 166, // STMicroelectronics STxP7x family of configurable // and extensible RISC processors @@ -674,6 +674,97 @@ enum { R_MIPS_NUM = 218 }; +// ELF Relocation types for Hexagon +// Release 5 ABI - Document: 80-V9418-3 Rev. J +enum { + R_HEX_NONE = 0, + R_HEX_B22_PCREL = 1, + R_HEX_B15_PCREL = 2, + R_HEX_B7_PCREL = 3, + R_HEX_LO16 = 4, + R_HEX_HI16 = 5, + R_HEX_32 = 6, + R_HEX_16 = 7, + R_HEX_8 = 8, + R_HEX_GPREL16_0 = 9, + R_HEX_GPREL16_1 = 10, + R_HEX_GPREL16_2 = 11, + R_HEX_GPREL16_3 = 12, + R_HEX_HL16 = 13, + R_HEX_B13_PCREL = 14, + R_HEX_B9_PCREL = 15, + R_HEX_B32_PCREL_X = 16, + R_HEX_32_6_X = 17, + R_HEX_B22_PCREL_X = 18, + R_HEX_B15_PCREL_X = 19, + R_HEX_B13_PCREL_X = 20, + R_HEX_B9_PCREL_X = 21, + R_HEX_B7_PCREL_X = 22, + R_HEX_16_X = 23, + R_HEX_12_X = 24, + R_HEX_11_X = 25, + R_HEX_10_X = 26, + R_HEX_9_X = 27, + R_HEX_8_X = 28, + R_HEX_7_X = 29, + R_HEX_6_X = 30, + R_HEX_32_PCREL = 31, + R_HEX_COPY = 32, + R_HEX_GLOB_DAT = 33, + R_HEX_JMP_SLOT = 34, + R_HEX_RELATIVE = 35, + R_HEX_PLT_B22_PCREL = 36, + R_HEX_GOTREL_LO16 = 37, + R_HEX_GOTREL_HI16 = 38, + R_HEX_GOTREL_32 = 39, + R_HEX_GOT_LO16 = 40, + R_HEX_GOT_HI16 = 41, + R_HEX_GOT_32 = 42, + R_HEX_GOT_16 = 43, + R_HEX_DTPMOD_32 = 44, + R_HEX_DTPREL_LO16 = 45, + R_HEX_DTPREL_HI16 = 46, + R_HEX_DTPREL_32 = 47, + R_HEX_DTPREL_16 = 48, + R_HEX_GD_PLT_B22_PCREL = 49, + R_HEX_GD_GOT_LO16 = 50, + R_HEX_GD_GOT_HI16 = 51, + R_HEX_GD_GOT_32 = 52, + R_HEX_GD_GOT_16 = 53, + R_HEX_IE_LO16 = 54, + R_HEX_IE_HI16 = 55, + R_HEX_IE_32 = 56, + R_HEX_IE_GOT_LO16 = 57, + R_HEX_IE_GOT_HI16 = 58, + R_HEX_IE_GOT_32 = 59, + R_HEX_IE_GOT_16 = 60, + R_HEX_TPREL_LO16 = 61, + R_HEX_TPREL_HI16 = 62, + R_HEX_TPREL_32 = 63, + R_HEX_TPREL_16 = 64, + R_HEX_6_PCREL_X = 65, + R_HEX_GOTREL_32_6_X = 66, + R_HEX_GOTREL_16_X = 67, + R_HEX_GOTREL_11_X = 68, + R_HEX_GOT_32_6_X = 69, + R_HEX_GOT_16_X = 70, + R_HEX_GOT_11_X = 71, + R_HEX_DTPREL_32_6_X = 72, + R_HEX_DTPREL_16_X = 73, + R_HEX_DTPREL_11_X = 74, + R_HEX_GD_GOT_32_6_X = 75, + R_HEX_GD_GOT_16_X = 76, + R_HEX_GD_GOT_11_X = 77, + R_HEX_IE_32_6_X = 78, + R_HEX_IE_16_X = 79, + R_HEX_IE_GOT_32_6_X = 80, + R_HEX_IE_GOT_16_X = 81, + R_HEX_IE_GOT_11_X = 82, + R_HEX_TPREL_32_6_X = 83, + R_HEX_TPREL_16_X = 84, + R_HEX_TPREL_11_X = 85 +}; + // Section header. struct Elf32_Shdr { Elf32_Word sh_name; // Section name (index into string table) @@ -736,6 +827,8 @@ enum { SHT_GROUP = 17, // Section group. SHT_SYMTAB_SHNDX = 18, // Indices for SHN_XINDEX entries. SHT_LOOS = 0x60000000, // Lowest operating system-specific type. + SHT_GNU_ATTRIBUTES= 0x6ffffff5, // Object attributes. + SHT_GNU_HASH = 0x6ffffff6, // GNU-style hash table. SHT_GNU_verdef = 0x6ffffffd, // GNU version definitions. SHT_GNU_verneed = 0x6ffffffe, // GNU version references. SHT_GNU_versym = 0x6fffffff, // GNU symbol versions table. @@ -1017,6 +1110,9 @@ enum { PT_SUNW_EH_FRAME = 0x6474e550, PT_SUNW_UNWIND = 0x6464e550, + PT_GNU_STACK = 0x6474e551, // Indicates stack executability. + PT_GNU_RELRO = 0x6474e552, // Read-only after relocation. + PT_HIOS = 0x6fffffff, // Highest operating system-specific pt entry type. PT_LOPROC = 0x70000000, // Lowest processor-specific program hdr entry type. PT_HIPROC = 0x7fffffff // Highest processor-specific program hdr entry type. @@ -1095,7 +1191,16 @@ enum { DT_LOOS = 0x60000000, // Start of environment specific tags. DT_HIOS = 0x6FFFFFFF, // End of environment specific tags. DT_LOPROC = 0x70000000, // Start of processor specific tags. - DT_HIPROC = 0x7FFFFFFF // End of processor specific tags. + DT_HIPROC = 0x7FFFFFFF, // End of processor specific tags. + + DT_RELACOUNT = 0x6FFFFFF9, // ELF32_Rela count. + DT_RELCOUNT = 0x6FFFFFFA, // ELF32_Rel count. + + DT_FLAGS_1 = 0X6FFFFFFB, // Flags_1. + DT_VERDEF = 0X6FFFFFFC, // The address of the version definition table. + DT_VERDEFNUM = 0X6FFFFFFD, // The number of entries in DT_VERDEF. + DT_VERNEED = 0X6FFFFFFE, // The address of the version Dependency table. + DT_VERNEEDNUM = 0X6FFFFFFF // The number of entries in DT_VERNEED. }; // DT_FLAGS values. @@ -1107,6 +1212,27 @@ enum { DF_STATIC_TLS = 0x10 // Reject attempts to load dynamically. }; +// State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 entry. +enum { + DF_1_NOW = 0x00000001, // Set RTLD_NOW for this object. + DF_1_GLOBAL = 0x00000002, // Set RTLD_GLOBAL for this object. + DF_1_GROUP = 0x00000004, // Set RTLD_GROUP for this object. + DF_1_NODELETE = 0x00000008, // Set RTLD_NODELETE for this object. + DF_1_LOADFLTR = 0x00000010, // Trigger filtee loading at runtime. + DF_1_INITFIRST = 0x00000020, // Set RTLD_INITFIRST for this object. + DF_1_NOOPEN = 0x00000040, // Set RTLD_NOOPEN for this object. + DF_1_ORIGIN = 0x00000080, // $ORIGIN must be handled. + DF_1_DIRECT = 0x00000100, // Direct binding enabled. + DF_1_TRANS = 0x00000200, + DF_1_INTERPOSE = 0x00000400, // Object is used to interpose. + DF_1_NODEFLIB = 0x00000800, // Ignore default lib search path. + DF_1_NODUMP = 0x00001000, // Object can't be dldump'ed. + DF_1_CONFALT = 0x00002000, // Configuration alternative created. + DF_1_ENDFILTEE = 0x00004000, // Filtee terminates filters search. + DF_1_DISPRELDNE = 0x00008000, // Disp reloc applied at build time. + DF_1_DISPRELPND = 0x00010000 // Disp reloc applied at run-time. +}; + // ElfXX_VerDef structure version (GNU versioning) enum { VER_DEF_NONE = 0, diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h index 733ab75..8d5649d 100644 --- a/include/llvm/Support/Endian.h +++ b/include/llvm/Support/Endian.h @@ -49,7 +49,7 @@ struct alignment_access_helper<value_type, unaligned> namespace endian { template<typename value_type, alignment align> - static value_type read_le(const void *memory) { + inline value_type read_le(const void *memory) { value_type t = reinterpret_cast<const detail::alignment_access_helper <value_type, align> *>(memory)->val; @@ -59,7 +59,7 @@ namespace endian { } template<typename value_type, alignment align> - static void write_le(void *memory, value_type value) { + inline void write_le(void *memory, value_type value) { if (sys::isBigEndianHost()) value = sys::SwapByteOrder(value); reinterpret_cast<detail::alignment_access_helper<value_type, align> *> @@ -67,7 +67,7 @@ namespace endian { } template<typename value_type, alignment align> - static value_type read_be(const void *memory) { + inline value_type read_be(const void *memory) { value_type t = reinterpret_cast<const detail::alignment_access_helper <value_type, align> *>(memory)->val; @@ -77,7 +77,7 @@ namespace endian { } template<typename value_type, alignment align> - static void write_be(void *memory, value_type value) { + inline void write_be(void *memory, value_type value) { if (sys::isLittleEndianHost()) value = sys::SwapByteOrder(value); reinterpret_cast<detail::alignment_access_helper<value_type, align> *> diff --git a/include/llvm/Support/FileOutputBuffer.h b/include/llvm/Support/FileOutputBuffer.h new file mode 100644 index 0000000..0f07164 --- /dev/null +++ b/include/llvm/Support/FileOutputBuffer.h @@ -0,0 +1,97 @@ +//=== FileOutputBuffer.h - File Output Buffer -------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Utility for creating a in-memory buffer that will be written to a file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_FILEOUTPUTBUFFER_H +#define LLVM_SUPPORT_FILEOUTPUTBUFFER_H + +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class error_code; +template<class T> class OwningPtr; + +/// FileOutputBuffer - This interface provides simple way to create an in-memory +/// buffer which will be written to a file. During the lifetime of these +/// objects, the content or existence of the specified file is undefined. That +/// is, creating an OutputBuffer for a file may immediately remove the file. +/// If the FileOutputBuffer is committed, the target file's content will become +/// the buffer content at the time of the commit. If the FileOutputBuffer is +/// not committed, the file will be deleted in the FileOutputBuffer destructor. +class FileOutputBuffer { +public: + + enum { + F_executable = 1 /// set the 'x' bit on the resulting file + }; + + /// Factory method to create an OutputBuffer object which manages a read/write + /// buffer of the specified size. When committed, the buffer will be written + /// to the file at the specified path. + static error_code create(StringRef FilePath, size_t Size, + OwningPtr<FileOutputBuffer> &Result, + unsigned Flags=0); + + + /// Returns a pointer to the start of the buffer. + uint8_t *getBufferStart() const { + return BufferStart; + } + + /// Returns a pointer to the end of the buffer. + uint8_t *getBufferEnd() const { + return BufferEnd; + } + + /// Returns size of the buffer. + size_t getBufferSize() const { + return BufferEnd - BufferStart; + } + + /// Returns path where file will show up if buffer is committed. + StringRef getPath() const { + return FinalPath; + } + + /// Flushes the content of the buffer to its file and deallocates the + /// buffer. If commit() is not called before this object's destructor + /// is called, the file is deleted in the destructor. The optional parameter + /// is used if it turns out you want the file size to be smaller than + /// initially requested. + error_code commit(int64_t NewSmallerSize = -1); + + /// If this object was previously committed, the destructor just deletes + /// this object. If this object was not committed, the destructor + /// deallocates the buffer and the target file is never written. + ~FileOutputBuffer(); + + +protected: + FileOutputBuffer(const FileOutputBuffer &); // DO NOT IMPLEMENT + FileOutputBuffer &operator=(const FileOutputBuffer &); // DO NOT IMPLEMENT + FileOutputBuffer(uint8_t *Start, uint8_t *End, + StringRef Path, StringRef TempPath); + + uint8_t *BufferStart; + uint8_t *BufferEnd; + SmallString<128> FinalPath; + SmallString<128> TempPath; +}; + + + +} // end namespace llvm + +#endif diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index e6f9926..e0353f9 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -94,13 +94,62 @@ struct space_info { uint64_t available; }; + +enum perms { + no_perms = 0, + owner_read = 0400, + owner_write = 0200, + owner_exe = 0100, + owner_all = owner_read | owner_write | owner_exe, + group_read = 040, + group_write = 020, + group_exe = 010, + group_all = group_read | group_write | group_exe, + others_read = 04, + others_write = 02, + others_exe = 01, + others_all = others_read | others_write | others_exe, + all_all = owner_all | group_all | others_all, + set_uid_on_exe = 04000, + set_gid_on_exe = 02000, + sticky_bit = 01000, + perms_mask = all_all | set_uid_on_exe | set_gid_on_exe | sticky_bit, + perms_not_known = 0xFFFF, + add_perms = 0x1000, + remove_perms = 0x2000, + symlink_perms = 0x4000 +}; + +// Helper functions so that you can use & and | to manipulate perms bits: +inline perms operator|(perms l , perms r) { + return static_cast<perms>( + static_cast<unsigned short>(l) | static_cast<unsigned short>(r)); +} +inline perms operator&(perms l , perms r) { + return static_cast<perms>( + static_cast<unsigned short>(l) & static_cast<unsigned short>(r)); +} +inline perms &operator|=(perms &l, perms r) { + l = l | r; + return l; +} +inline perms &operator&=(perms &l, perms r) { + l = l & r; + return l; +} +inline perms operator~(perms x) { + return static_cast<perms>(~static_cast<unsigned short>(x)); +} + + + /// file_status - Represents the result of a call to stat and friends. It has /// a platform specific member to store the result. class file_status { #if defined(LLVM_ON_UNIX) - dev_t st_dev; - ino_t st_ino; + dev_t fs_st_dev; + ino_t fs_st_ino; #elif defined (LLVM_ON_WIN32) uint32_t LastWriteTimeHigh; uint32_t LastWriteTimeLow; @@ -113,12 +162,19 @@ class file_status friend bool equivalent(file_status A, file_status B); friend error_code status(const Twine &path, file_status &result); file_type Type; + perms Perms; public: - explicit file_status(file_type v=file_type::status_error) - : Type(v) {} + explicit file_status(file_type v=file_type::status_error, + perms prms=perms_not_known) + : Type(v), Perms(prms) {} + // getters file_type type() const { return Type; } + perms permissions() const { return Perms; } + + // setters void type(file_type v) { Type = v; } + void permissions(perms p) { Perms = p; } }; /// file_magic - An "enum class" enumeration of file types based on magic (the first @@ -309,6 +365,13 @@ bool equivalent(file_status A, file_status B); /// platform specific error_code. error_code equivalent(const Twine &A, const Twine &B, bool &result); +/// @brief Simpler version of equivalent for clients that don't need to +/// differentiate between an error and false. +inline bool equivalent(const Twine &A, const Twine &B) { + bool result; + return !equivalent(A, B, result) && result; +} + /// @brief Get file size. /// /// @param path Input path. @@ -388,6 +451,13 @@ error_code is_symlink(const Twine &path, bool &result); /// platform specific error_code. error_code status(const Twine &path, file_status &result); +/// @brief Modifies permission bits on a file +/// +/// @param path Input path. +/// @results errc::success if permissions have been changed, otherwise a +/// platform specific error_code. +error_code permissions(const Twine &path, perms prms); + /// @brief Is status available? /// /// @param path Input path. @@ -422,8 +492,8 @@ error_code status_known(const Twine &path, bool &result); /// @results errc::success if result_{fd,path} have been successfully set, /// otherwise a platform specific error_code. error_code unique_file(const Twine &model, int &result_fd, - SmallVectorImpl<char> &result_path, - bool makeAbsolute = true); + SmallVectorImpl<char> &result_path, + bool makeAbsolute = true, unsigned mode = 0600); /// @brief Canonicalize path. /// @@ -506,6 +576,33 @@ error_code FindLibrary(const Twine &short_name, SmallVectorImpl<char> &result); error_code GetMainExecutable(const char *argv0, void *MainAddr, SmallVectorImpl<char> &result); + +/// @brief Memory maps the contents of a file +/// +/// @param path Path to file to map. +/// @param file_offset Byte offset in file where mapping should begin. +/// @param size_t Byte length of range of the file to map. +/// @param map_writable If true, the file will be mapped in r/w such +/// that changes to the mapped buffer will be flushed back +/// to the file. If false, the file will be mapped read-only +/// and the buffer will be read-only. +/// @param result Set to the start address of the mapped buffer. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code map_file_pages(const Twine &path, off_t file_offset, size_t size, + bool map_writable, void *&result); + + +/// @brief Memory unmaps the contents of a file +/// +/// @param base Pointer to the start of the buffer. +/// @param size Byte length of the range to unmmap. +/// @results errc::success if result has been successfully set, otherwise a +/// platform specific error_code. +error_code unmap_file_pages(void *base, size_t size); + + + /// @} /// @name Iterators /// @{ diff --git a/include/llvm/Support/GCOV.h b/include/llvm/Support/GCOV.h index 49cd87f..19e1ce8 100644 --- a/include/llvm/Support/GCOV.h +++ b/include/llvm/Support/GCOV.h @@ -63,8 +63,8 @@ public: bool readFunctionTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\0' || Tag[3] != '\1') { + Tag[0] != '\0' || Tag[1] != '\0' || + Tag[2] != '\0' || Tag[3] != '\1') { return false; } Cursor += 4; @@ -76,8 +76,8 @@ public: bool readBlockTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\x41' || Tag[3] != '\x01') { + Tag[0] != '\0' || Tag[1] != '\0' || + Tag[2] != '\x41' || Tag[3] != '\x01') { return false; } Cursor += 4; @@ -89,8 +89,8 @@ public: bool readEdgeTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\x43' || Tag[3] != '\x01') { + Tag[0] != '\0' || Tag[1] != '\0' || + Tag[2] != '\x43' || Tag[3] != '\x01') { return false; } Cursor += 4; @@ -102,8 +102,8 @@ public: bool readLineTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\x45' || Tag[3] != '\x01') { + Tag[0] != '\0' || Tag[1] != '\0' || + Tag[2] != '\x45' || Tag[3] != '\x01') { return false; } Cursor += 4; @@ -115,8 +115,8 @@ public: bool readArcTag() { StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\xa1' || Tag[3] != '\1') { + Tag[0] != '\0' || Tag[1] != '\0' || + Tag[2] != '\xa1' || Tag[3] != '\1') { return false; } Cursor += 4; diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h index ae32da5..f178b0c 100644 --- a/include/llvm/Support/GraphWriter.h +++ b/include/llvm/Support/GraphWriter.h @@ -172,7 +172,7 @@ public: // If we should include the address of the node in the label, do so now. if (DTraits.hasNodeAddressLabel(Node, G)) - O << "|" << (void*)Node; + O << "|" << static_cast<const void*>(Node); } std::string edgeSourceLabels; @@ -192,7 +192,7 @@ public: // If we should include the address of the node in the label, do so now. if (DTraits.hasNodeAddressLabel(Node, G)) - O << "|" << (void*)Node; + O << "|" << static_cast<const void*>(Node); } if (DTraits.hasEdgeDestLabels()) { diff --git a/include/llvm/Support/IRBuilder.h b/include/llvm/Support/IRBuilder.h deleted file mode 100644 index ef00e8e..0000000 --- a/include/llvm/Support/IRBuilder.h +++ /dev/null @@ -1,1281 +0,0 @@ -//===---- llvm/Support/IRBuilder.h - Builder for LLVM Instrs ----*- 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 IRBuilder class, which is used as a convenient way -// to create LLVM instructions with a consistent and simplified interface. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_IRBUILDER_H -#define LLVM_SUPPORT_IRBUILDER_H - -#include "llvm/Instructions.h" -#include "llvm/BasicBlock.h" -#include "llvm/LLVMContext.h" -#include "llvm/ADT/ArrayRef.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/ADT/Twine.h" -#include "llvm/Support/ConstantFolder.h" - -namespace llvm { - class MDNode; - -/// IRBuilderDefaultInserter - This provides the default implementation of the -/// IRBuilder 'InsertHelper' method that is called whenever an instruction is -/// created by IRBuilder and needs to be inserted. By default, this inserts the -/// instruction at the insertion point. -template <bool preserveNames = true> -class IRBuilderDefaultInserter { -protected: - void InsertHelper(Instruction *I, const Twine &Name, - BasicBlock *BB, BasicBlock::iterator InsertPt) const { - if (BB) BB->getInstList().insert(InsertPt, I); - if (preserveNames) - I->setName(Name); - } -}; - -/// IRBuilderBase - Common base class shared among various IRBuilders. -class IRBuilderBase { - DebugLoc CurDbgLocation; -protected: - BasicBlock *BB; - BasicBlock::iterator InsertPt; - LLVMContext &Context; -public: - - IRBuilderBase(LLVMContext &context) - : Context(context) { - ClearInsertionPoint(); - } - - //===--------------------------------------------------------------------===// - // Builder configuration methods - //===--------------------------------------------------------------------===// - - /// ClearInsertionPoint - Clear the insertion point: created instructions will - /// not be inserted into a block. - void ClearInsertionPoint() { - BB = 0; - } - - BasicBlock *GetInsertBlock() const { return BB; } - BasicBlock::iterator GetInsertPoint() const { return InsertPt; } - LLVMContext &getContext() const { return Context; } - - /// SetInsertPoint - This specifies that created instructions should be - /// appended to the end of the specified block. - void SetInsertPoint(BasicBlock *TheBB) { - BB = TheBB; - InsertPt = BB->end(); - } - - /// SetInsertPoint - This specifies that created instructions should be - /// inserted before the specified instruction. - void SetInsertPoint(Instruction *I) { - BB = I->getParent(); - InsertPt = I; - SetCurrentDebugLocation(I->getDebugLoc()); - } - - /// SetInsertPoint - This specifies that created instructions should be - /// inserted at the specified point. - void SetInsertPoint(BasicBlock *TheBB, BasicBlock::iterator IP) { - BB = TheBB; - InsertPt = IP; - } - - /// SetInsertPoint(Use) - Find the nearest point that dominates this use, and - /// specify that created instructions should be inserted at this point. - void SetInsertPoint(Use &U) { - Instruction *UseInst = cast<Instruction>(U.getUser()); - if (PHINode *Phi = dyn_cast<PHINode>(UseInst)) { - BasicBlock *PredBB = Phi->getIncomingBlock(U); - assert(U != PredBB->getTerminator() && "critical edge not split"); - SetInsertPoint(PredBB, PredBB->getTerminator()); - return; - } - SetInsertPoint(UseInst); - } - - /// SetCurrentDebugLocation - Set location information used by debugging - /// information. - void SetCurrentDebugLocation(const DebugLoc &L) { - CurDbgLocation = L; - } - - /// getCurrentDebugLocation - Get location information used by debugging - /// information. - DebugLoc getCurrentDebugLocation() const { return CurDbgLocation; } - - /// SetInstDebugLocation - If this builder has a current debug location, set - /// it on the specified instruction. - void SetInstDebugLocation(Instruction *I) const { - if (!CurDbgLocation.isUnknown()) - I->setDebugLoc(CurDbgLocation); - } - - /// getCurrentFunctionReturnType - Get the return type of the current function - /// that we're emitting into. - Type *getCurrentFunctionReturnType() const; - - /// InsertPoint - A saved insertion point. - class InsertPoint { - BasicBlock *Block; - BasicBlock::iterator Point; - - public: - /// Creates a new insertion point which doesn't point to anything. - InsertPoint() : Block(0) {} - - /// Creates a new insertion point at the given location. - InsertPoint(BasicBlock *InsertBlock, BasicBlock::iterator InsertPoint) - : Block(InsertBlock), Point(InsertPoint) {} - - /// isSet - Returns true if this insert point is set. - bool isSet() const { return (Block != 0); } - - llvm::BasicBlock *getBlock() const { return Block; } - llvm::BasicBlock::iterator getPoint() const { return Point; } - }; - - /// saveIP - Returns the current insert point. - InsertPoint saveIP() const { - return InsertPoint(GetInsertBlock(), GetInsertPoint()); - } - - /// saveAndClearIP - Returns the current insert point, clearing it - /// in the process. - InsertPoint saveAndClearIP() { - InsertPoint IP(GetInsertBlock(), GetInsertPoint()); - ClearInsertionPoint(); - return IP; - } - - /// restoreIP - Sets the current insert point to a previously-saved - /// location. - void restoreIP(InsertPoint IP) { - if (IP.isSet()) - SetInsertPoint(IP.getBlock(), IP.getPoint()); - else - ClearInsertionPoint(); - } - - //===--------------------------------------------------------------------===// - // Miscellaneous creation methods. - //===--------------------------------------------------------------------===// - - /// CreateGlobalString - Make a new global variable with an initializer that - /// has array of i8 type filled in with the nul terminated string value - /// specified. The new global variable will be marked mergable with any - /// others of the same contents. If Name is specified, it is the name of the - /// global variable created. - Value *CreateGlobalString(StringRef Str, const Twine &Name = ""); - - /// getInt1 - Get a constant value representing either true or false. - ConstantInt *getInt1(bool V) { - return ConstantInt::get(getInt1Ty(), V); - } - - /// getTrue - Get the constant value for i1 true. - ConstantInt *getTrue() { - return ConstantInt::getTrue(Context); - } - - /// getFalse - Get the constant value for i1 false. - ConstantInt *getFalse() { - return ConstantInt::getFalse(Context); - } - - /// getInt8 - Get a constant 8-bit value. - ConstantInt *getInt8(uint8_t C) { - return ConstantInt::get(getInt8Ty(), C); - } - - /// getInt16 - Get a constant 16-bit value. - ConstantInt *getInt16(uint16_t C) { - return ConstantInt::get(getInt16Ty(), C); - } - - /// getInt32 - Get a constant 32-bit value. - ConstantInt *getInt32(uint32_t C) { - return ConstantInt::get(getInt32Ty(), C); - } - - /// getInt64 - Get a constant 64-bit value. - ConstantInt *getInt64(uint64_t C) { - return ConstantInt::get(getInt64Ty(), C); - } - - /// getInt - Get a constant integer value. - ConstantInt *getInt(const APInt &AI) { - return ConstantInt::get(Context, AI); - } - - //===--------------------------------------------------------------------===// - // Type creation methods - //===--------------------------------------------------------------------===// - - /// getInt1Ty - Fetch the type representing a single bit - IntegerType *getInt1Ty() { - return Type::getInt1Ty(Context); - } - - /// getInt8Ty - Fetch the type representing an 8-bit integer. - IntegerType *getInt8Ty() { - return Type::getInt8Ty(Context); - } - - /// getInt16Ty - Fetch the type representing a 16-bit integer. - IntegerType *getInt16Ty() { - return Type::getInt16Ty(Context); - } - - /// getInt32Ty - Fetch the type resepresenting a 32-bit integer. - IntegerType *getInt32Ty() { - return Type::getInt32Ty(Context); - } - - /// getInt64Ty - Fetch the type representing a 64-bit integer. - IntegerType *getInt64Ty() { - return Type::getInt64Ty(Context); - } - - /// getFloatTy - Fetch the type representing a 32-bit floating point value. - Type *getFloatTy() { - return Type::getFloatTy(Context); - } - - /// getDoubleTy - Fetch the type representing a 64-bit floating point value. - Type *getDoubleTy() { - return Type::getDoubleTy(Context); - } - - /// getVoidTy - Fetch the type representing void. - Type *getVoidTy() { - return Type::getVoidTy(Context); - } - - PointerType *getInt8PtrTy(unsigned AddrSpace = 0) { - return Type::getInt8PtrTy(Context, AddrSpace); - } - - //===--------------------------------------------------------------------===// - // Intrinsic creation methods - //===--------------------------------------------------------------------===// - - /// CreateMemSet - Create and insert a memset to the specified pointer and the - /// specified value. If the pointer isn't an i8*, it will be converted. If a - /// TBAA tag is specified, it will be added to the instruction. - CallInst *CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0) { - return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag); - } - - CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0); - - /// CreateMemCpy - Create and insert a memcpy between the specified pointers. - /// If the pointers aren't i8*, they will be converted. If a TBAA tag is - /// specified, it will be added to the instruction. - CallInst *CreateMemCpy(Value *Dst, Value *Src, uint64_t Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0) { - return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); - } - - CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0); - - /// CreateMemMove - Create and insert a memmove between the specified - /// pointers. If the pointers aren't i8*, they will be converted. If a TBAA - /// tag is specified, it will be added to the instruction. - CallInst *CreateMemMove(Value *Dst, Value *Src, uint64_t Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0) { - return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag); - } - - CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile = false, MDNode *TBAATag = 0); - - /// CreateLifetimeStart - Create a lifetime.start intrinsic. If the pointer - /// isn't i8* it will be converted. - CallInst *CreateLifetimeStart(Value *Ptr, ConstantInt *Size = 0); - - /// CreateLifetimeEnd - Create a lifetime.end intrinsic. If the pointer isn't - /// i8* it will be converted. - CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = 0); - -private: - Value *getCastedInt8PtrValue(Value *Ptr); -}; - -/// IRBuilder - This provides a uniform API for creating instructions and -/// inserting them into a basic block: either at the end of a BasicBlock, or -/// at a specific iterator location in a block. -/// -/// Note that the builder does not expose the full generality of LLVM -/// instructions. For access to extra instruction properties, use the mutators -/// (e.g. setVolatile) on the instructions after they have been created. -/// The first template argument handles whether or not to preserve names in the -/// final instruction output. This defaults to on. The second template argument -/// specifies a class to use for creating constants. This defaults to creating -/// minimally folded constants. The fourth template argument allows clients to -/// specify custom insertion hooks that are called on every newly created -/// insertion. -template<bool preserveNames = true, typename T = ConstantFolder, - typename Inserter = IRBuilderDefaultInserter<preserveNames> > -class IRBuilder : public IRBuilderBase, public Inserter { - T Folder; - MDNode *DefaultFPMathTag; -public: - IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter(), - MDNode *FPMathTag = 0) - : IRBuilderBase(C), Inserter(I), Folder(F), DefaultFPMathTag(FPMathTag) { - } - - explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = 0) : IRBuilderBase(C), - Folder(), DefaultFPMathTag(FPMathTag) { - } - - explicit IRBuilder(BasicBlock *TheBB, const T &F, MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(F), - DefaultFPMathTag(FPMathTag) { - SetInsertPoint(TheBB); - } - - explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(), - DefaultFPMathTag(FPMathTag) { - SetInsertPoint(TheBB); - } - - explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = 0) - : IRBuilderBase(IP->getContext()), Folder(), DefaultFPMathTag(FPMathTag) { - SetInsertPoint(IP); - SetCurrentDebugLocation(IP->getDebugLoc()); - } - - explicit IRBuilder(Use &U, MDNode *FPMathTag = 0) - : IRBuilderBase(U->getContext()), Folder(), DefaultFPMathTag(FPMathTag) { - SetInsertPoint(U); - SetCurrentDebugLocation(cast<Instruction>(U.getUser())->getDebugLoc()); - } - - IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F, - MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(F), - DefaultFPMathTag(FPMathTag) { - SetInsertPoint(TheBB, IP); - } - - IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, MDNode *FPMathTag = 0) - : IRBuilderBase(TheBB->getContext()), Folder(), - DefaultFPMathTag(FPMathTag) { - SetInsertPoint(TheBB, IP); - } - - /// getFolder - Get the constant folder being used. - const T &getFolder() { return Folder; } - - /// getDefaultFPMathTag - Get the floating point math metadata being used. - MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; } - - /// SetDefaultFPMathTag - Set the floating point math metadata to be used. - void SetDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; } - - /// isNamePreserving - Return true if this builder is configured to actually - /// add the requested names to IR created through it. - bool isNamePreserving() const { return preserveNames; } - - /// Insert - Insert and return the specified instruction. - template<typename InstTy> - InstTy *Insert(InstTy *I, const Twine &Name = "") const { - this->InsertHelper(I, Name, BB, InsertPt); - if (!getCurrentDebugLocation().isUnknown()) - this->SetInstDebugLocation(I); - return I; - } - - /// Insert - No-op overload to handle constants. - Constant *Insert(Constant *C, const Twine& = "") const { - return C; - } - - //===--------------------------------------------------------------------===// - // Instruction creation methods: Terminators - //===--------------------------------------------------------------------===// - - /// CreateRetVoid - Create a 'ret void' instruction. - ReturnInst *CreateRetVoid() { - return Insert(ReturnInst::Create(Context)); - } - - /// @verbatim - /// CreateRet - Create a 'ret <val>' instruction. - /// @endverbatim - ReturnInst *CreateRet(Value *V) { - return Insert(ReturnInst::Create(Context, V)); - } - - /// CreateAggregateRet - Create a sequence of N insertvalue instructions, - /// with one Value from the retVals array each, that build a aggregate - /// return value one value at a time, and a ret instruction to return - /// the resulting aggregate value. This is a convenience function for - /// code that uses aggregate return values as a vehicle for having - /// multiple return values. - /// - ReturnInst *CreateAggregateRet(Value *const *retVals, unsigned N) { - Value *V = UndefValue::get(getCurrentFunctionReturnType()); - for (unsigned i = 0; i != N; ++i) - V = CreateInsertValue(V, retVals[i], i, "mrv"); - return Insert(ReturnInst::Create(Context, V)); - } - - /// CreateBr - Create an unconditional 'br label X' instruction. - BranchInst *CreateBr(BasicBlock *Dest) { - return Insert(BranchInst::Create(Dest)); - } - - /// CreateCondBr - Create a conditional 'br Cond, TrueDest, FalseDest' - /// instruction. - BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False) { - return Insert(BranchInst::Create(True, False, Cond)); - } - - /// CreateSwitch - Create a switch instruction with the specified value, - /// default dest, and with a hint for the number of cases that will be added - /// (for efficient allocation). - SwitchInst *CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases = 10) { - return Insert(SwitchInst::Create(V, Dest, NumCases)); - } - - /// CreateIndirectBr - Create an indirect branch instruction with the - /// specified address operand, with an optional hint for the number of - /// destinations that will be added (for efficient allocation). - IndirectBrInst *CreateIndirectBr(Value *Addr, unsigned NumDests = 10) { - return Insert(IndirectBrInst::Create(Addr, NumDests)); - } - - InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, - BasicBlock *UnwindDest, const Twine &Name = "") { - return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, - ArrayRef<Value *>()), - Name); - } - InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, - BasicBlock *UnwindDest, Value *Arg1, - const Twine &Name = "") { - return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, Arg1), - Name); - } - InvokeInst *CreateInvoke3(Value *Callee, BasicBlock *NormalDest, - BasicBlock *UnwindDest, Value *Arg1, - Value *Arg2, Value *Arg3, - const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2, Arg3 }; - return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, Args), - Name); - } - /// CreateInvoke - Create an invoke instruction. - InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest, - BasicBlock *UnwindDest, ArrayRef<Value *> Args, - const Twine &Name = "") { - return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, Args), - Name); - } - - ResumeInst *CreateResume(Value *Exn) { - return Insert(ResumeInst::Create(Exn)); - } - - UnreachableInst *CreateUnreachable() { - return Insert(new UnreachableInst(Context)); - } - - //===--------------------------------------------------------------------===// - // Instruction creation methods: Binary Operators - //===--------------------------------------------------------------------===// -private: - BinaryOperator *CreateInsertNUWNSWBinOp(BinaryOperator::BinaryOps Opc, - Value *LHS, Value *RHS, - const Twine &Name, - bool HasNUW, bool HasNSW) { - BinaryOperator *BO = Insert(BinaryOperator::Create(Opc, LHS, RHS), Name); - if (HasNUW) BO->setHasNoUnsignedWrap(); - if (HasNSW) BO->setHasNoSignedWrap(); - return BO; - } - - Instruction *AddFPMathTag(Instruction *I, MDNode *FPMathTag) const { - if (!FPMathTag) - FPMathTag = DefaultFPMathTag; - if (FPMathTag) - I->setMetadata(LLVMContext::MD_fpmath, FPMathTag); - return I; - } -public: - Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "", - bool HasNUW = false, bool HasNSW = false) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateAdd(LC, RC, HasNUW, HasNSW), Name); - return CreateInsertNUWNSWBinOp(Instruction::Add, LHS, RHS, Name, - HasNUW, HasNSW); - } - Value *CreateNSWAdd(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateAdd(LHS, RHS, Name, false, true); - } - Value *CreateNUWAdd(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateAdd(LHS, RHS, Name, true, false); - } - Value *CreateFAdd(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = 0) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateFAdd(LC, RC), Name); - return Insert(AddFPMathTag(BinaryOperator::CreateFAdd(LHS, RHS), - FPMathTag), Name); - } - Value *CreateSub(Value *LHS, Value *RHS, const Twine &Name = "", - bool HasNUW = false, bool HasNSW = false) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateSub(LC, RC), Name); - return CreateInsertNUWNSWBinOp(Instruction::Sub, LHS, RHS, Name, - HasNUW, HasNSW); - } - Value *CreateNSWSub(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateSub(LHS, RHS, Name, false, true); - } - Value *CreateNUWSub(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateSub(LHS, RHS, Name, true, false); - } - Value *CreateFSub(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = 0) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateFSub(LC, RC), Name); - return Insert(AddFPMathTag(BinaryOperator::CreateFSub(LHS, RHS), - FPMathTag), Name); - } - Value *CreateMul(Value *LHS, Value *RHS, const Twine &Name = "", - bool HasNUW = false, bool HasNSW = false) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateMul(LC, RC), Name); - return CreateInsertNUWNSWBinOp(Instruction::Mul, LHS, RHS, Name, - HasNUW, HasNSW); - } - Value *CreateNSWMul(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateMul(LHS, RHS, Name, false, true); - } - Value *CreateNUWMul(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateMul(LHS, RHS, Name, true, false); - } - Value *CreateFMul(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = 0) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateFMul(LC, RC), Name); - return Insert(AddFPMathTag(BinaryOperator::CreateFMul(LHS, RHS), - FPMathTag), Name); - } - Value *CreateUDiv(Value *LHS, Value *RHS, const Twine &Name = "", - bool isExact = false) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateUDiv(LC, RC, isExact), Name); - if (!isExact) - return Insert(BinaryOperator::CreateUDiv(LHS, RHS), Name); - return Insert(BinaryOperator::CreateExactUDiv(LHS, RHS), Name); - } - Value *CreateExactUDiv(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateUDiv(LHS, RHS, Name, true); - } - Value *CreateSDiv(Value *LHS, Value *RHS, const Twine &Name = "", - bool isExact = false) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateSDiv(LC, RC, isExact), Name); - if (!isExact) - return Insert(BinaryOperator::CreateSDiv(LHS, RHS), Name); - return Insert(BinaryOperator::CreateExactSDiv(LHS, RHS), Name); - } - Value *CreateExactSDiv(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateSDiv(LHS, RHS, Name, true); - } - Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = 0) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateFDiv(LC, RC), Name); - return Insert(AddFPMathTag(BinaryOperator::CreateFDiv(LHS, RHS), - FPMathTag), Name); - } - Value *CreateURem(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateURem(LC, RC), Name); - return Insert(BinaryOperator::CreateURem(LHS, RHS), Name); - } - Value *CreateSRem(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateSRem(LC, RC), Name); - return Insert(BinaryOperator::CreateSRem(LHS, RHS), Name); - } - Value *CreateFRem(Value *LHS, Value *RHS, const Twine &Name = "", - MDNode *FPMathTag = 0) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateFRem(LC, RC), Name); - return Insert(AddFPMathTag(BinaryOperator::CreateFRem(LHS, RHS), - FPMathTag), Name); - } - - Value *CreateShl(Value *LHS, Value *RHS, const Twine &Name = "", - bool HasNUW = false, bool HasNSW = false) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateShl(LC, RC, HasNUW, HasNSW), Name); - return CreateInsertNUWNSWBinOp(Instruction::Shl, LHS, RHS, Name, - HasNUW, HasNSW); - } - Value *CreateShl(Value *LHS, const APInt &RHS, const Twine &Name = "", - bool HasNUW = false, bool HasNSW = false) { - return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name, - HasNUW, HasNSW); - } - Value *CreateShl(Value *LHS, uint64_t RHS, const Twine &Name = "", - bool HasNUW = false, bool HasNSW = false) { - return CreateShl(LHS, ConstantInt::get(LHS->getType(), RHS), Name, - HasNUW, HasNSW); - } - - Value *CreateLShr(Value *LHS, Value *RHS, const Twine &Name = "", - bool isExact = false) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateLShr(LC, RC, isExact), Name); - if (!isExact) - return Insert(BinaryOperator::CreateLShr(LHS, RHS), Name); - return Insert(BinaryOperator::CreateExactLShr(LHS, RHS), Name); - } - Value *CreateLShr(Value *LHS, const APInt &RHS, const Twine &Name = "", - bool isExact = false) { - return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); - } - Value *CreateLShr(Value *LHS, uint64_t RHS, const Twine &Name = "", - bool isExact = false) { - return CreateLShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); - } - - Value *CreateAShr(Value *LHS, Value *RHS, const Twine &Name = "", - bool isExact = false) { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateAShr(LC, RC, isExact), Name); - if (!isExact) - return Insert(BinaryOperator::CreateAShr(LHS, RHS), Name); - return Insert(BinaryOperator::CreateExactAShr(LHS, RHS), Name); - } - Value *CreateAShr(Value *LHS, const APInt &RHS, const Twine &Name = "", - bool isExact = false) { - return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); - } - Value *CreateAShr(Value *LHS, uint64_t RHS, const Twine &Name = "", - bool isExact = false) { - return CreateAShr(LHS, ConstantInt::get(LHS->getType(), RHS), Name,isExact); - } - - Value *CreateAnd(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *RC = dyn_cast<Constant>(RHS)) { - if (isa<ConstantInt>(RC) && cast<ConstantInt>(RC)->isAllOnesValue()) - return LHS; // LHS & -1 -> LHS - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Insert(Folder.CreateAnd(LC, RC), Name); - } - return Insert(BinaryOperator::CreateAnd(LHS, RHS), Name); - } - Value *CreateAnd(Value *LHS, const APInt &RHS, const Twine &Name = "") { - return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name); - } - Value *CreateAnd(Value *LHS, uint64_t RHS, const Twine &Name = "") { - return CreateAnd(LHS, ConstantInt::get(LHS->getType(), RHS), Name); - } - - Value *CreateOr(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *RC = dyn_cast<Constant>(RHS)) { - if (RC->isNullValue()) - return LHS; // LHS | 0 -> LHS - if (Constant *LC = dyn_cast<Constant>(LHS)) - return Insert(Folder.CreateOr(LC, RC), Name); - } - return Insert(BinaryOperator::CreateOr(LHS, RHS), Name); - } - Value *CreateOr(Value *LHS, const APInt &RHS, const Twine &Name = "") { - return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name); - } - Value *CreateOr(Value *LHS, uint64_t RHS, const Twine &Name = "") { - return CreateOr(LHS, ConstantInt::get(LHS->getType(), RHS), Name); - } - - Value *CreateXor(Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateXor(LC, RC), Name); - return Insert(BinaryOperator::CreateXor(LHS, RHS), Name); - } - Value *CreateXor(Value *LHS, const APInt &RHS, const Twine &Name = "") { - return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name); - } - Value *CreateXor(Value *LHS, uint64_t RHS, const Twine &Name = "") { - return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name); - } - - Value *CreateBinOp(Instruction::BinaryOps Opc, - Value *LHS, Value *RHS, const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateBinOp(Opc, LC, RC), Name); - return Insert(BinaryOperator::Create(Opc, LHS, RHS), Name); - } - - Value *CreateNeg(Value *V, const Twine &Name = "", - bool HasNUW = false, bool HasNSW = false) { - if (Constant *VC = dyn_cast<Constant>(V)) - return Insert(Folder.CreateNeg(VC, HasNUW, HasNSW), Name); - BinaryOperator *BO = Insert(BinaryOperator::CreateNeg(V), Name); - if (HasNUW) BO->setHasNoUnsignedWrap(); - if (HasNSW) BO->setHasNoSignedWrap(); - return BO; - } - Value *CreateNSWNeg(Value *V, const Twine &Name = "") { - return CreateNeg(V, Name, false, true); - } - Value *CreateNUWNeg(Value *V, const Twine &Name = "") { - return CreateNeg(V, Name, true, false); - } - Value *CreateFNeg(Value *V, const Twine &Name = "", MDNode *FPMathTag = 0) { - if (Constant *VC = dyn_cast<Constant>(V)) - return Insert(Folder.CreateFNeg(VC), Name); - return Insert(AddFPMathTag(BinaryOperator::CreateFNeg(V), FPMathTag), Name); - } - Value *CreateNot(Value *V, const Twine &Name = "") { - if (Constant *VC = dyn_cast<Constant>(V)) - return Insert(Folder.CreateNot(VC), Name); - return Insert(BinaryOperator::CreateNot(V), Name); - } - - //===--------------------------------------------------------------------===// - // Instruction creation methods: Memory Instructions - //===--------------------------------------------------------------------===// - - AllocaInst *CreateAlloca(Type *Ty, Value *ArraySize = 0, - const Twine &Name = "") { - return Insert(new AllocaInst(Ty, ArraySize), Name); - } - // Provided to resolve 'CreateLoad(Ptr, "...")' correctly, instead of - // converting the string to 'bool' for the isVolatile parameter. - LoadInst *CreateLoad(Value *Ptr, const char *Name) { - return Insert(new LoadInst(Ptr), Name); - } - LoadInst *CreateLoad(Value *Ptr, const Twine &Name = "") { - return Insert(new LoadInst(Ptr), Name); - } - LoadInst *CreateLoad(Value *Ptr, bool isVolatile, const Twine &Name = "") { - return Insert(new LoadInst(Ptr, 0, isVolatile), Name); - } - StoreInst *CreateStore(Value *Val, Value *Ptr, bool isVolatile = false) { - return Insert(new StoreInst(Val, Ptr, isVolatile)); - } - FenceInst *CreateFence(AtomicOrdering Ordering, - SynchronizationScope SynchScope = CrossThread) { - return Insert(new FenceInst(Context, Ordering, SynchScope)); - } - AtomicCmpXchgInst *CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New, - AtomicOrdering Ordering, - SynchronizationScope SynchScope = CrossThread) { - return Insert(new AtomicCmpXchgInst(Ptr, Cmp, New, Ordering, SynchScope)); - } - AtomicRMWInst *CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val, - AtomicOrdering Ordering, - SynchronizationScope SynchScope = CrossThread) { - return Insert(new AtomicRMWInst(Op, Ptr, Val, Ordering, SynchScope)); - } - Value *CreateGEP(Value *Ptr, ArrayRef<Value *> IdxList, - const Twine &Name = "") { - if (Constant *PC = dyn_cast<Constant>(Ptr)) { - // Every index must be constant. - size_t i, e; - for (i = 0, e = IdxList.size(); i != e; ++i) - if (!isa<Constant>(IdxList[i])) - break; - if (i == e) - return Insert(Folder.CreateGetElementPtr(PC, IdxList), Name); - } - return Insert(GetElementPtrInst::Create(Ptr, IdxList), Name); - } - Value *CreateInBoundsGEP(Value *Ptr, ArrayRef<Value *> IdxList, - const Twine &Name = "") { - if (Constant *PC = dyn_cast<Constant>(Ptr)) { - // Every index must be constant. - size_t i, e; - for (i = 0, e = IdxList.size(); i != e; ++i) - if (!isa<Constant>(IdxList[i])) - break; - if (i == e) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, IdxList), Name); - } - return Insert(GetElementPtrInst::CreateInBounds(Ptr, IdxList), Name); - } - Value *CreateGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { - if (Constant *PC = dyn_cast<Constant>(Ptr)) - if (Constant *IC = dyn_cast<Constant>(Idx)) - return Insert(Folder.CreateGetElementPtr(PC, IC), Name); - return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); - } - Value *CreateInBoundsGEP(Value *Ptr, Value *Idx, const Twine &Name = "") { - if (Constant *PC = dyn_cast<Constant>(Ptr)) - if (Constant *IC = dyn_cast<Constant>(Idx)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, IC), Name); - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); - } - Value *CreateConstGEP1_32(Value *Ptr, unsigned Idx0, const Twine &Name = "") { - Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); - - if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idx), Name); - - return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); - } - Value *CreateConstInBoundsGEP1_32(Value *Ptr, unsigned Idx0, - const Twine &Name = "") { - Value *Idx = ConstantInt::get(Type::getInt32Ty(Context), Idx0); - - if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name); - - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); - } - Value *CreateConstGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, - const Twine &Name = "") { - Value *Idxs[] = { - ConstantInt::get(Type::getInt32Ty(Context), Idx0), - ConstantInt::get(Type::getInt32Ty(Context), Idx1) - }; - - if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name); - - return Insert(GetElementPtrInst::Create(Ptr, Idxs), Name); - } - Value *CreateConstInBoundsGEP2_32(Value *Ptr, unsigned Idx0, unsigned Idx1, - const Twine &Name = "") { - Value *Idxs[] = { - ConstantInt::get(Type::getInt32Ty(Context), Idx0), - ConstantInt::get(Type::getInt32Ty(Context), Idx1) - }; - - if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name); - - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs), Name); - } - Value *CreateConstGEP1_64(Value *Ptr, uint64_t Idx0, const Twine &Name = "") { - Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); - - if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idx), Name); - - return Insert(GetElementPtrInst::Create(Ptr, Idx), Name); - } - Value *CreateConstInBoundsGEP1_64(Value *Ptr, uint64_t Idx0, - const Twine &Name = "") { - Value *Idx = ConstantInt::get(Type::getInt64Ty(Context), Idx0); - - if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idx), Name); - - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idx), Name); - } - Value *CreateConstGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, - const Twine &Name = "") { - Value *Idxs[] = { - ConstantInt::get(Type::getInt64Ty(Context), Idx0), - ConstantInt::get(Type::getInt64Ty(Context), Idx1) - }; - - if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateGetElementPtr(PC, Idxs), Name); - - return Insert(GetElementPtrInst::Create(Ptr, Idxs), Name); - } - Value *CreateConstInBoundsGEP2_64(Value *Ptr, uint64_t Idx0, uint64_t Idx1, - const Twine &Name = "") { - Value *Idxs[] = { - ConstantInt::get(Type::getInt64Ty(Context), Idx0), - ConstantInt::get(Type::getInt64Ty(Context), Idx1) - }; - - if (Constant *PC = dyn_cast<Constant>(Ptr)) - return Insert(Folder.CreateInBoundsGetElementPtr(PC, Idxs), Name); - - return Insert(GetElementPtrInst::CreateInBounds(Ptr, Idxs), Name); - } - Value *CreateStructGEP(Value *Ptr, unsigned Idx, const Twine &Name = "") { - return CreateConstInBoundsGEP2_32(Ptr, 0, Idx, Name); - } - - /// CreateGlobalStringPtr - Same as CreateGlobalString, but return a pointer - /// with "i8*" type instead of a pointer to array of i8. - Value *CreateGlobalStringPtr(StringRef Str, const Twine &Name = "") { - Value *gv = CreateGlobalString(Str, Name); - Value *zero = ConstantInt::get(Type::getInt32Ty(Context), 0); - Value *Args[] = { zero, zero }; - return CreateInBoundsGEP(gv, Args, Name); - } - - //===--------------------------------------------------------------------===// - // Instruction creation methods: Cast/Conversion Operators - //===--------------------------------------------------------------------===// - - Value *CreateTrunc(Value *V, Type *DestTy, const Twine &Name = "") { - return CreateCast(Instruction::Trunc, V, DestTy, Name); - } - Value *CreateZExt(Value *V, Type *DestTy, const Twine &Name = "") { - return CreateCast(Instruction::ZExt, V, DestTy, Name); - } - Value *CreateSExt(Value *V, Type *DestTy, const Twine &Name = "") { - return CreateCast(Instruction::SExt, V, DestTy, Name); - } - Value *CreateFPToUI(Value *V, Type *DestTy, const Twine &Name = ""){ - return CreateCast(Instruction::FPToUI, V, DestTy, Name); - } - Value *CreateFPToSI(Value *V, Type *DestTy, const Twine &Name = ""){ - return CreateCast(Instruction::FPToSI, V, DestTy, Name); - } - Value *CreateUIToFP(Value *V, Type *DestTy, const Twine &Name = ""){ - return CreateCast(Instruction::UIToFP, V, DestTy, Name); - } - Value *CreateSIToFP(Value *V, Type *DestTy, const Twine &Name = ""){ - return CreateCast(Instruction::SIToFP, V, DestTy, Name); - } - Value *CreateFPTrunc(Value *V, Type *DestTy, - const Twine &Name = "") { - return CreateCast(Instruction::FPTrunc, V, DestTy, Name); - } - Value *CreateFPExt(Value *V, Type *DestTy, const Twine &Name = "") { - return CreateCast(Instruction::FPExt, V, DestTy, Name); - } - Value *CreatePtrToInt(Value *V, Type *DestTy, - const Twine &Name = "") { - return CreateCast(Instruction::PtrToInt, V, DestTy, Name); - } - Value *CreateIntToPtr(Value *V, Type *DestTy, - const Twine &Name = "") { - return CreateCast(Instruction::IntToPtr, V, DestTy, Name); - } - Value *CreateBitCast(Value *V, Type *DestTy, - const Twine &Name = "") { - return CreateCast(Instruction::BitCast, V, DestTy, Name); - } - Value *CreateZExtOrBitCast(Value *V, Type *DestTy, - const Twine &Name = "") { - if (V->getType() == DestTy) - return V; - if (Constant *VC = dyn_cast<Constant>(V)) - return Insert(Folder.CreateZExtOrBitCast(VC, DestTy), Name); - return Insert(CastInst::CreateZExtOrBitCast(V, DestTy), Name); - } - Value *CreateSExtOrBitCast(Value *V, Type *DestTy, - const Twine &Name = "") { - if (V->getType() == DestTy) - return V; - if (Constant *VC = dyn_cast<Constant>(V)) - return Insert(Folder.CreateSExtOrBitCast(VC, DestTy), Name); - return Insert(CastInst::CreateSExtOrBitCast(V, DestTy), Name); - } - Value *CreateTruncOrBitCast(Value *V, Type *DestTy, - const Twine &Name = "") { - if (V->getType() == DestTy) - return V; - if (Constant *VC = dyn_cast<Constant>(V)) - return Insert(Folder.CreateTruncOrBitCast(VC, DestTy), Name); - return Insert(CastInst::CreateTruncOrBitCast(V, DestTy), Name); - } - Value *CreateCast(Instruction::CastOps Op, Value *V, Type *DestTy, - const Twine &Name = "") { - if (V->getType() == DestTy) - return V; - if (Constant *VC = dyn_cast<Constant>(V)) - return Insert(Folder.CreateCast(Op, VC, DestTy), Name); - return Insert(CastInst::Create(Op, V, DestTy), Name); - } - Value *CreatePointerCast(Value *V, Type *DestTy, - const Twine &Name = "") { - if (V->getType() == DestTy) - return V; - if (Constant *VC = dyn_cast<Constant>(V)) - return Insert(Folder.CreatePointerCast(VC, DestTy), Name); - return Insert(CastInst::CreatePointerCast(V, DestTy), Name); - } - Value *CreateIntCast(Value *V, Type *DestTy, bool isSigned, - const Twine &Name = "") { - if (V->getType() == DestTy) - return V; - if (Constant *VC = dyn_cast<Constant>(V)) - return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name); - return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name); - } -private: - // Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a compile time - // error, instead of converting the string to bool for the isSigned parameter. - Value *CreateIntCast(Value *, Type *, const char *); // DO NOT IMPLEMENT -public: - Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") { - if (V->getType() == DestTy) - return V; - if (Constant *VC = dyn_cast<Constant>(V)) - return Insert(Folder.CreateFPCast(VC, DestTy), Name); - return Insert(CastInst::CreateFPCast(V, DestTy), Name); - } - - //===--------------------------------------------------------------------===// - // Instruction creation methods: Compare Instructions - //===--------------------------------------------------------------------===// - - Value *CreateICmpEQ(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_EQ, LHS, RHS, Name); - } - Value *CreateICmpNE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_NE, LHS, RHS, Name); - } - Value *CreateICmpUGT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_UGT, LHS, RHS, Name); - } - Value *CreateICmpUGE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_UGE, LHS, RHS, Name); - } - Value *CreateICmpULT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_ULT, LHS, RHS, Name); - } - Value *CreateICmpULE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_ULE, LHS, RHS, Name); - } - Value *CreateICmpSGT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_SGT, LHS, RHS, Name); - } - Value *CreateICmpSGE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_SGE, LHS, RHS, Name); - } - Value *CreateICmpSLT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_SLT, LHS, RHS, Name); - } - Value *CreateICmpSLE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateICmp(ICmpInst::ICMP_SLE, LHS, RHS, Name); - } - - Value *CreateFCmpOEQ(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OEQ, LHS, RHS, Name); - } - Value *CreateFCmpOGT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OGT, LHS, RHS, Name); - } - Value *CreateFCmpOGE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OGE, LHS, RHS, Name); - } - Value *CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OLT, LHS, RHS, Name); - } - Value *CreateFCmpOLE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_OLE, LHS, RHS, Name); - } - Value *CreateFCmpONE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_ONE, LHS, RHS, Name); - } - Value *CreateFCmpORD(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_ORD, LHS, RHS, Name); - } - Value *CreateFCmpUNO(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UNO, LHS, RHS, Name); - } - Value *CreateFCmpUEQ(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UEQ, LHS, RHS, Name); - } - Value *CreateFCmpUGT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UGT, LHS, RHS, Name); - } - Value *CreateFCmpUGE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UGE, LHS, RHS, Name); - } - Value *CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_ULT, LHS, RHS, Name); - } - Value *CreateFCmpULE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_ULE, LHS, RHS, Name); - } - Value *CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name = "") { - return CreateFCmp(FCmpInst::FCMP_UNE, LHS, RHS, Name); - } - - Value *CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS, - const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateICmp(P, LC, RC), Name); - return Insert(new ICmpInst(P, LHS, RHS), Name); - } - Value *CreateFCmp(CmpInst::Predicate P, Value *LHS, Value *RHS, - const Twine &Name = "") { - if (Constant *LC = dyn_cast<Constant>(LHS)) - if (Constant *RC = dyn_cast<Constant>(RHS)) - return Insert(Folder.CreateFCmp(P, LC, RC), Name); - return Insert(new FCmpInst(P, LHS, RHS), Name); - } - - //===--------------------------------------------------------------------===// - // Instruction creation methods: Other Instructions - //===--------------------------------------------------------------------===// - - PHINode *CreatePHI(Type *Ty, unsigned NumReservedValues, - const Twine &Name = "") { - return Insert(PHINode::Create(Ty, NumReservedValues), Name); - } - - CallInst *CreateCall(Value *Callee, const Twine &Name = "") { - return Insert(CallInst::Create(Callee), Name); - } - CallInst *CreateCall(Value *Callee, Value *Arg, const Twine &Name = "") { - return Insert(CallInst::Create(Callee, Arg), Name); - } - CallInst *CreateCall2(Value *Callee, Value *Arg1, Value *Arg2, - const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2 }; - return Insert(CallInst::Create(Callee, Args), Name); - } - CallInst *CreateCall3(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, - const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2, Arg3 }; - return Insert(CallInst::Create(Callee, Args), Name); - } - CallInst *CreateCall4(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, - Value *Arg4, const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2, Arg3, Arg4 }; - return Insert(CallInst::Create(Callee, Args), Name); - } - CallInst *CreateCall5(Value *Callee, Value *Arg1, Value *Arg2, Value *Arg3, - Value *Arg4, Value *Arg5, const Twine &Name = "") { - Value *Args[] = { Arg1, Arg2, Arg3, Arg4, Arg5 }; - return Insert(CallInst::Create(Callee, Args), Name); - } - - CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args, - const Twine &Name = "") { - return Insert(CallInst::Create(Callee, Args), Name); - } - - Value *CreateSelect(Value *C, Value *True, Value *False, - const Twine &Name = "") { - if (Constant *CC = dyn_cast<Constant>(C)) - if (Constant *TC = dyn_cast<Constant>(True)) - if (Constant *FC = dyn_cast<Constant>(False)) - return Insert(Folder.CreateSelect(CC, TC, FC), Name); - return Insert(SelectInst::Create(C, True, False), Name); - } - - VAArgInst *CreateVAArg(Value *List, Type *Ty, const Twine &Name = "") { - return Insert(new VAArgInst(List, Ty), Name); - } - - Value *CreateExtractElement(Value *Vec, Value *Idx, - const Twine &Name = "") { - if (Constant *VC = dyn_cast<Constant>(Vec)) - if (Constant *IC = dyn_cast<Constant>(Idx)) - return Insert(Folder.CreateExtractElement(VC, IC), Name); - return Insert(ExtractElementInst::Create(Vec, Idx), Name); - } - - Value *CreateInsertElement(Value *Vec, Value *NewElt, Value *Idx, - const Twine &Name = "") { - if (Constant *VC = dyn_cast<Constant>(Vec)) - if (Constant *NC = dyn_cast<Constant>(NewElt)) - if (Constant *IC = dyn_cast<Constant>(Idx)) - return Insert(Folder.CreateInsertElement(VC, NC, IC), Name); - return Insert(InsertElementInst::Create(Vec, NewElt, Idx), Name); - } - - Value *CreateShuffleVector(Value *V1, Value *V2, Value *Mask, - const Twine &Name = "") { - if (Constant *V1C = dyn_cast<Constant>(V1)) - if (Constant *V2C = dyn_cast<Constant>(V2)) - if (Constant *MC = dyn_cast<Constant>(Mask)) - return Insert(Folder.CreateShuffleVector(V1C, V2C, MC), Name); - return Insert(new ShuffleVectorInst(V1, V2, Mask), Name); - } - - Value *CreateExtractValue(Value *Agg, - ArrayRef<unsigned> Idxs, - const Twine &Name = "") { - if (Constant *AggC = dyn_cast<Constant>(Agg)) - return Insert(Folder.CreateExtractValue(AggC, Idxs), Name); - return Insert(ExtractValueInst::Create(Agg, Idxs), Name); - } - - Value *CreateInsertValue(Value *Agg, Value *Val, - ArrayRef<unsigned> Idxs, - const Twine &Name = "") { - if (Constant *AggC = dyn_cast<Constant>(Agg)) - if (Constant *ValC = dyn_cast<Constant>(Val)) - return Insert(Folder.CreateInsertValue(AggC, ValC, Idxs), Name); - return Insert(InsertValueInst::Create(Agg, Val, Idxs), Name); - } - - LandingPadInst *CreateLandingPad(Type *Ty, Value *PersFn, unsigned NumClauses, - const Twine &Name = "") { - return Insert(LandingPadInst::Create(Ty, PersFn, NumClauses, Name)); - } - - //===--------------------------------------------------------------------===// - // Utility creation methods - //===--------------------------------------------------------------------===// - - /// CreateIsNull - Return an i1 value testing if \arg Arg is null. - Value *CreateIsNull(Value *Arg, const Twine &Name = "") { - return CreateICmpEQ(Arg, Constant::getNullValue(Arg->getType()), - Name); - } - - /// CreateIsNotNull - Return an i1 value testing if \arg Arg is not null. - Value *CreateIsNotNull(Value *Arg, const Twine &Name = "") { - return CreateICmpNE(Arg, Constant::getNullValue(Arg->getType()), - Name); - } - - /// CreatePtrDiff - Return the i64 difference between two pointer values, - /// dividing out the size of the pointed-to objects. This is intended to - /// implement C-style pointer subtraction. As such, the pointers must be - /// appropriately aligned for their element types and pointing into the - /// same object. - Value *CreatePtrDiff(Value *LHS, Value *RHS, const Twine &Name = "") { - assert(LHS->getType() == RHS->getType() && - "Pointer subtraction operand types must match!"); - PointerType *ArgType = cast<PointerType>(LHS->getType()); - Value *LHS_int = CreatePtrToInt(LHS, Type::getInt64Ty(Context)); - Value *RHS_int = CreatePtrToInt(RHS, Type::getInt64Ty(Context)); - Value *Difference = CreateSub(LHS_int, RHS_int); - return CreateExactSDiv(Difference, - ConstantExpr::getSizeOf(ArgType->getElementType()), - Name); - } -}; - -} - -#endif diff --git a/include/llvm/Support/InstVisitor.h b/include/llvm/Support/InstVisitor.h index 52de8f6..109b3cf 100644 --- a/include/llvm/Support/InstVisitor.h +++ b/include/llvm/Support/InstVisitor.h @@ -13,6 +13,8 @@ #include "llvm/Function.h" #include "llvm/Instructions.h" +#include "llvm/Intrinsics.h" +#include "llvm/IntrinsicInst.h" #include "llvm/Module.h" #include "llvm/Support/CallSite.h" #include "llvm/Support/ErrorHandling.h" @@ -145,14 +147,17 @@ public: // visitMul to proxy to visitBinaryOperator for instance in case the user does // not need this generality. // - // The one problem case we have to handle here though is that the PHINode - // class and opcode name are the exact same. Because of this, we cannot - // define visitPHINode (the inst version) to forward to visitPHINode (the - // generic version) without multiply defined symbols and recursion. To handle - // this, we do not autoexpand "Other" instructions, we do it manually. - // + // These functions can also implement fan-out, when a single opcode and + // instruction have multiple more specific Instruction subclasses. The Call + // instruction currently supports this. We implement that by redirecting that + // instruction to a special delegation helper. #define HANDLE_INST(NUM, OPCODE, CLASS) \ - RetTy visit##OPCODE(CLASS &I) { DELEGATE(CLASS); } + RetTy visit##OPCODE(CLASS &I) { \ + if (NUM == Instruction::Call) \ + return delegateCallInst(I); \ + else \ + DELEGATE(CLASS); \ + } #include "llvm/Instruction.def" // Specific Instruction type classes... note that all of the casts are @@ -195,6 +200,17 @@ public: RetTy visitInsertValueInst(InsertValueInst &I) { DELEGATE(Instruction); } RetTy visitLandingPadInst(LandingPadInst &I) { DELEGATE(Instruction); } + // Handle the special instrinsic instruction classes. + RetTy visitDbgDeclareInst(DbgDeclareInst &I) { DELEGATE(DbgInfoIntrinsic);} + RetTy visitDbgValueInst(DbgValueInst &I) { DELEGATE(DbgInfoIntrinsic);} + RetTy visitDbgInfoIntrinsic(DbgInfoIntrinsic &I) { DELEGATE(IntrinsicInst); } + RetTy visitMemSetInst(MemSetInst &I) { DELEGATE(MemIntrinsic); } + RetTy visitMemCpyInst(MemCpyInst &I) { DELEGATE(MemTransferInst); } + RetTy visitMemMoveInst(MemMoveInst &I) { DELEGATE(MemTransferInst); } + RetTy visitMemTransferInst(MemTransferInst &I) { DELEGATE(MemIntrinsic); } + RetTy visitMemIntrinsic(MemIntrinsic &I) { DELEGATE(IntrinsicInst); } + RetTy visitIntrinsicInst(IntrinsicInst &I) { DELEGATE(CallInst); } + // Call and Invoke are slightly different as they delegate first through // a generic CallSite visitor. RetTy visitCallInst(CallInst &I) { @@ -234,6 +250,29 @@ public: // Note that you MUST override this function if your return type is not void. // void visitInstruction(Instruction &I) {} // Ignore unhandled instructions + +private: + // Special helper function to delegate to CallInst subclass visitors. + RetTy delegateCallInst(CallInst &I) { + if (const Function *F = I.getCalledFunction()) { + switch ((Intrinsic::ID)F->getIntrinsicID()) { + default: DELEGATE(IntrinsicInst); + case Intrinsic::dbg_declare: DELEGATE(DbgDeclareInst); + case Intrinsic::dbg_value: DELEGATE(DbgValueInst); + case Intrinsic::memcpy: DELEGATE(MemCpyInst); + case Intrinsic::memmove: DELEGATE(MemMoveInst); + case Intrinsic::memset: DELEGATE(MemSetInst); + case Intrinsic::not_intrinsic: break; + } + } + DELEGATE(CallInst); + } + + // An overload that will never actually be called, it is used only from dead + // code in the dispatching from opcodes to instruction subclasses. + RetTy delegateCallInst(Instruction &I) { + llvm_unreachable("delegateCallInst called for non-CallInst"); + } }; #undef DELEGATE diff --git a/include/llvm/Support/IntegersSubset.h b/include/llvm/Support/IntegersSubset.h new file mode 100644 index 0000000..bb9e769 --- /dev/null +++ b/include/llvm/Support/IntegersSubset.h @@ -0,0 +1,541 @@ +//===-- llvm/IntegersSubset.h - The subset of integers ----------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// This file contains class that implements constant set of ranges: +/// [<Low0,High0>,...,<LowN,HighN>]. Initially, this class was created for +/// SwitchInst and was used for case value representation that may contain +/// multiple ranges for a single successor. +// +//===----------------------------------------------------------------------===// + +#ifndef CONSTANTRANGESSET_H_ +#define CONSTANTRANGESSET_H_ + +#include <list> + +#include "llvm/Constants.h" +#include "llvm/DerivedTypes.h" +#include "llvm/LLVMContext.h" + +namespace llvm { + + // The IntItem is a wrapper for APInt. + // 1. It determines sign of integer, it allows to use + // comparison operators >,<,>=,<=, and as result we got shorter and cleaner + // constructions. + // 2. It helps to implement PR1255 (case ranges) as a series of small patches. + // 3. Currently we can interpret IntItem both as ConstantInt and as APInt. + // It allows to provide SwitchInst methods that works with ConstantInt for + // non-updated passes. And it allows to use APInt interface for new methods. + // 4. IntItem can be easily replaced with APInt. + + // The set of macros that allows to propagate APInt operators to the IntItem. + +#define INT_ITEM_DEFINE_COMPARISON(op,func) \ + bool operator op (const APInt& RHS) const { \ + return getAPIntValue().func(RHS); \ + } + +#define INT_ITEM_DEFINE_UNARY_OP(op) \ + IntItem operator op () const { \ + APInt res = op(getAPIntValue()); \ + Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ + return IntItem(cast<ConstantInt>(NewVal)); \ + } + +#define INT_ITEM_DEFINE_BINARY_OP(op) \ + IntItem operator op (const APInt& RHS) const { \ + APInt res = getAPIntValue() op RHS; \ + Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ + return IntItem(cast<ConstantInt>(NewVal)); \ + } + +#define INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(op) \ + IntItem& operator op (const APInt& RHS) {\ + APInt res = getAPIntValue();\ + res op RHS; \ + Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ + ConstantIntVal = cast<ConstantInt>(NewVal); \ + return *this; \ + } + +#define INT_ITEM_DEFINE_PREINCDEC(op) \ + IntItem& operator op () { \ + APInt res = getAPIntValue(); \ + op(res); \ + Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ + ConstantIntVal = cast<ConstantInt>(NewVal); \ + return *this; \ + } + +#define INT_ITEM_DEFINE_POSTINCDEC(op) \ + IntItem& operator op (int) { \ + APInt res = getAPIntValue();\ + op(res); \ + Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); \ + OldConstantIntVal = ConstantIntVal; \ + ConstantIntVal = cast<ConstantInt>(NewVal); \ + return IntItem(OldConstantIntVal); \ + } + +#define INT_ITEM_DEFINE_OP_STANDARD_INT(RetTy, op, IntTy) \ + RetTy operator op (IntTy RHS) const { \ + return (*this) op APInt(getAPIntValue().getBitWidth(), RHS); \ + } + +class IntItem { + ConstantInt *ConstantIntVal; + const APInt* APIntVal; + IntItem(const ConstantInt *V) : + ConstantIntVal(const_cast<ConstantInt*>(V)), + APIntVal(&ConstantIntVal->getValue()){} + const APInt& getAPIntValue() const { + return *APIntVal; + } +public: + + IntItem() {} + + operator const APInt&() const { + return getAPIntValue(); + } + + // Propagate APInt operators. + // Note, that + // /,/=,>>,>>= are not implemented in APInt. + // <<= is implemented for unsigned RHS, but not implemented for APInt RHS. + + INT_ITEM_DEFINE_COMPARISON(<, ult) + INT_ITEM_DEFINE_COMPARISON(>, ugt) + INT_ITEM_DEFINE_COMPARISON(<=, ule) + INT_ITEM_DEFINE_COMPARISON(>=, uge) + + INT_ITEM_DEFINE_COMPARISON(==, eq) + INT_ITEM_DEFINE_OP_STANDARD_INT(bool,==,uint64_t) + + INT_ITEM_DEFINE_COMPARISON(!=, ne) + INT_ITEM_DEFINE_OP_STANDARD_INT(bool,!=,uint64_t) + + INT_ITEM_DEFINE_BINARY_OP(*) + INT_ITEM_DEFINE_BINARY_OP(+) + INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,+,uint64_t) + INT_ITEM_DEFINE_BINARY_OP(-) + INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,-,uint64_t) + INT_ITEM_DEFINE_BINARY_OP(<<) + INT_ITEM_DEFINE_OP_STANDARD_INT(IntItem,<<,unsigned) + INT_ITEM_DEFINE_BINARY_OP(&) + INT_ITEM_DEFINE_BINARY_OP(^) + INT_ITEM_DEFINE_BINARY_OP(|) + + INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(*=) + INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(+=) + INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(-=) + INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(&=) + INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(^=) + INT_ITEM_DEFINE_ASSIGNMENT_BY_OP(|=) + + // Special case for <<= + IntItem& operator <<= (unsigned RHS) { + APInt res = getAPIntValue(); + res <<= RHS; + Constant *NewVal = ConstantInt::get(ConstantIntVal->getContext(), res); + ConstantIntVal = cast<ConstantInt>(NewVal); + return *this; + } + + INT_ITEM_DEFINE_UNARY_OP(-) + INT_ITEM_DEFINE_UNARY_OP(~) + + INT_ITEM_DEFINE_PREINCDEC(++) + INT_ITEM_DEFINE_PREINCDEC(--) + + // The set of workarounds, since currently we use ConstantInt implemented + // integer. + + static IntItem fromConstantInt(const ConstantInt *V) { + return IntItem(V); + } + static IntItem fromType(Type* Ty, const APInt& V) { + ConstantInt *C = cast<ConstantInt>(ConstantInt::get(Ty, V)); + return fromConstantInt(C); + } + static IntItem withImplLikeThis(const IntItem& LikeThis, const APInt& V) { + ConstantInt *C = cast<ConstantInt>(ConstantInt::get( + LikeThis.ConstantIntVal->getContext(), V)); + return fromConstantInt(C); + } + ConstantInt *toConstantInt() const { + return ConstantIntVal; + } +}; + +template<class IntType> +class IntRange { +protected: + IntType Low; + IntType High; + bool IsEmpty : 1; + bool IsSingleNumber : 1; + +public: + typedef IntRange<IntType> self; + typedef std::pair<self, self> SubRes; + + IntRange() : IsEmpty(true) {} + IntRange(const self &RHS) : + Low(RHS.Low), High(RHS.High), + IsEmpty(RHS.IsEmpty), IsSingleNumber(RHS.IsSingleNumber) {} + IntRange(const IntType &C) : + Low(C), High(C), IsEmpty(false), IsSingleNumber(true) {} + + IntRange(const IntType &L, const IntType &H) : Low(L), High(H), + IsEmpty(false), IsSingleNumber(Low == High) {} + + bool isEmpty() const { return IsEmpty; } + bool isSingleNumber() const { return IsSingleNumber; } + + const IntType& getLow() const { + assert(!IsEmpty && "Range is empty."); + return Low; + } + const IntType& getHigh() const { + assert(!IsEmpty && "Range is empty."); + return High; + } + + bool operator<(const self &RHS) const { + assert(!IsEmpty && "Left range is empty."); + assert(!RHS.IsEmpty && "Right range is empty."); + if (Low == RHS.Low) { + if (High > RHS.High) + return true; + return false; + } + if (Low < RHS.Low) + return true; + return false; + } + + bool operator==(const self &RHS) const { + assert(!IsEmpty && "Left range is empty."); + assert(!RHS.IsEmpty && "Right range is empty."); + return Low == RHS.Low && High == RHS.High; + } + + bool operator!=(const self &RHS) const { + return !operator ==(RHS); + } + + static bool LessBySize(const self &LHS, const self &RHS) { + return (LHS.High - LHS.Low) < (RHS.High - RHS.Low); + } + + bool isInRange(const IntType &IntVal) const { + assert(!IsEmpty && "Range is empty."); + return IntVal >= Low && IntVal <= High; + } + + SubRes sub(const self &RHS) const { + SubRes Res; + + // RHS is either more global and includes this range or + // if it doesn't intersected with this range. + if (!isInRange(RHS.Low) && !isInRange(RHS.High)) { + + // If RHS more global (it is enough to check + // only one border in this case. + if (RHS.isInRange(Low)) + return std::make_pair(self(Low, High), self()); + + return Res; + } + + if (Low < RHS.Low) { + Res.first.Low = Low; + IntType NewHigh = RHS.Low; + --NewHigh; + Res.first.High = NewHigh; + } + if (High > RHS.High) { + IntType NewLow = RHS.High; + ++NewLow; + Res.second.Low = NewLow; + Res.second.High = High; + } + return Res; + } + }; + +//===----------------------------------------------------------------------===// +/// IntegersSubsetGeneric - class that implements the subset of integers. It +/// consists from ranges and single numbers. +template <class IntTy> +class IntegersSubsetGeneric { +public: + // Use Chris Lattner idea, that was initially described here: + // http://lists.cs.uiuc.edu/pipermail/llvm-commits/Week-of-Mon-20120213/136954.html + // In short, for more compact memory consumption we can store flat + // numbers collection, and define range as pair of indices. + // In that case we can safe some memory on 32 bit machines. + typedef std::vector<IntTy> FlatCollectionTy; + typedef std::pair<IntTy*, IntTy*> RangeLinkTy; + typedef std::vector<RangeLinkTy> RangeLinksTy; + typedef typename RangeLinksTy::const_iterator RangeLinksConstIt; + + typedef IntegersSubsetGeneric<IntTy> self; + +protected: + + FlatCollectionTy FlatCollection; + RangeLinksTy RangeLinks; + + bool IsSingleNumber; + bool IsSingleNumbersOnly; + +public: + + template<class RangesCollectionTy> + explicit IntegersSubsetGeneric(const RangesCollectionTy& Links) { + assert(Links.size() && "Empty ranges are not allowed."); + + // In case of big set of single numbers consumes additional RAM space, + // but allows to avoid additional reallocation. + FlatCollection.reserve(Links.size() * 2); + RangeLinks.reserve(Links.size()); + IsSingleNumbersOnly = true; + for (typename RangesCollectionTy::const_iterator i = Links.begin(), + e = Links.end(); i != e; ++i) { + RangeLinkTy RangeLink; + FlatCollection.push_back(i->getLow()); + RangeLink.first = &FlatCollection.back(); + if (i->getLow() != i->getHigh()) { + FlatCollection.push_back(i->getHigh()); + IsSingleNumbersOnly = false; + } + RangeLink.second = &FlatCollection.back(); + RangeLinks.push_back(RangeLink); + } + IsSingleNumber = IsSingleNumbersOnly && RangeLinks.size() == 1; + } + + IntegersSubsetGeneric(const self& RHS) { + *this = RHS; + } + + self& operator=(const self& RHS) { + FlatCollection.clear(); + RangeLinks.clear(); + FlatCollection.reserve(RHS.RangeLinks.size() * 2); + RangeLinks.reserve(RHS.RangeLinks.size()); + for (RangeLinksConstIt i = RHS.RangeLinks.begin(), e = RHS.RangeLinks.end(); + i != e; ++i) { + RangeLinkTy RangeLink; + FlatCollection.push_back(*(i->first)); + RangeLink.first = &FlatCollection.back(); + if (i->first != i->second) + FlatCollection.push_back(*(i->second)); + RangeLink.second = &FlatCollection.back(); + RangeLinks.push_back(RangeLink); + } + IsSingleNumber = RHS.IsSingleNumber; + IsSingleNumbersOnly = RHS.IsSingleNumbersOnly; + return *this; + } + + typedef IntRange<IntTy> Range; + + /// Checks is the given constant satisfies this case. Returns + /// true if it equals to one of contained values or belongs to the one of + /// contained ranges. + bool isSatisfies(const IntTy &CheckingVal) const { + if (IsSingleNumber) + return FlatCollection.front() == CheckingVal; + if (IsSingleNumbersOnly) + return std::find(FlatCollection.begin(), + FlatCollection.end(), + CheckingVal) != FlatCollection.end(); + + for (unsigned i = 0, e = getNumItems(); i < e; ++i) { + if (RangeLinks[i].first == RangeLinks[i].second) { + if (*RangeLinks[i].first == CheckingVal) + return true; + } else if (*RangeLinks[i].first <= CheckingVal && + *RangeLinks[i].second >= CheckingVal) + return true; + } + return false; + } + + /// Returns set's item with given index. + Range getItem(unsigned idx) const { + const RangeLinkTy &Link = RangeLinks[idx]; + if (Link.first != Link.second) + return Range(*Link.first, *Link.second); + else + return Range(*Link.first); + } + + /// Return number of items (ranges) stored in set. + unsigned getNumItems() const { + return RangeLinks.size(); + } + + /// Returns true if whole subset contains single element. + bool isSingleNumber() const { + return IsSingleNumber; + } + + /// Returns true if whole subset contains only single numbers, no ranges. + bool isSingleNumbersOnly() const { + return IsSingleNumbersOnly; + } + + /// Does the same like getItem(idx).isSingleNumber(), but + /// works faster, since we avoid creation of temporary range object. + bool isSingleNumber(unsigned idx) const { + return RangeLinks[idx].first == RangeLinks[idx].second; + } + + /// Returns set the size, that equals number of all values + sizes of all + /// ranges. + /// Ranges set is considered as flat numbers collection. + /// E.g.: for range [<0>, <1>, <4,8>] the size will 7; + /// for range [<0>, <1>, <5>] the size will 3 + unsigned getSize() const { + APInt sz(((const APInt&)getItem(0).getLow()).getBitWidth(), 0); + for (unsigned i = 0, e = getNumItems(); i != e; ++i) { + const APInt &Low = getItem(i).getLow(); + const APInt &High = getItem(i).getHigh(); + APInt S = High - Low + 1; + sz += S; + } + return sz.getZExtValue(); + } + + /// Allows to access single value even if it belongs to some range. + /// Ranges set is considered as flat numbers collection. + /// [<1>, <4,8>] is considered as [1,4,5,6,7,8] + /// For range [<1>, <4,8>] getSingleValue(3) returns 6. + APInt getSingleValue(unsigned idx) const { + APInt sz(((const APInt&)getItem(0).getLow()).getBitWidth(), 0); + for (unsigned i = 0, e = getNumItems(); i != e; ++i) { + const APInt &Low = getItem(i).getLow(); + const APInt &High = getItem(i).getHigh(); + APInt S = High - Low + 1; + APInt oldSz = sz; + sz += S; + if (sz.ugt(idx)) { + APInt Res = Low; + APInt Offset(oldSz.getBitWidth(), idx); + Offset -= oldSz; + Res += Offset; + return Res; + } + } + assert(0 && "Index exceeds high border."); + return sz; + } + + /// Does the same as getSingleValue, but works only if subset contains + /// single numbers only. + const IntTy& getSingleNumber(unsigned idx) const { + assert(IsSingleNumbersOnly && "This method works properly if subset " + "contains single numbers only."); + return FlatCollection[idx]; + } +}; + +//===----------------------------------------------------------------------===// +/// IntegersSubset - currently is extension of IntegersSubsetGeneric +/// that also supports conversion to/from Constant* object. +class IntegersSubset : public IntegersSubsetGeneric<IntItem> { + + typedef IntegersSubsetGeneric<IntItem> ParentTy; + + Constant *Holder; + + static unsigned getNumItemsFromConstant(Constant *C) { + return cast<ArrayType>(C->getType())->getNumElements(); + } + + static Range getItemFromConstant(Constant *C, unsigned idx) { + const Constant *CV = C->getAggregateElement(idx); + + unsigned NumEls = cast<VectorType>(CV->getType())->getNumElements(); + switch (NumEls) { + case 1: + return Range(IntItem::fromConstantInt( + cast<ConstantInt>(CV->getAggregateElement(0U))), + IntItem::fromConstantInt(cast<ConstantInt>( + cast<ConstantInt>(CV->getAggregateElement(0U))))); + case 2: + return Range(IntItem::fromConstantInt( + cast<ConstantInt>(CV->getAggregateElement(0U))), + IntItem::fromConstantInt( + cast<ConstantInt>(CV->getAggregateElement(1)))); + default: + assert(0 && "Only pairs and single numbers are allowed here."); + return Range(); + } + } + + std::vector<Range> rangesFromConstant(Constant *C) { + unsigned NumItems = getNumItemsFromConstant(C); + std::vector<Range> r; + r.reserve(NumItems); + for (unsigned i = 0, e = NumItems; i != e; ++i) + r.push_back(getItemFromConstant(C, i)); + return r; + } + +public: + + explicit IntegersSubset(Constant *C) : ParentTy(rangesFromConstant(C)), + Holder(C) {} + + IntegersSubset(const IntegersSubset& RHS) : + ParentTy(*(const ParentTy *)&RHS), // FIXME: tweak for msvc. + Holder(RHS.Holder) {} + + template<class RangesCollectionTy> + explicit IntegersSubset(const RangesCollectionTy& Src) : ParentTy(Src) { + std::vector<Constant*> Elts; + Elts.reserve(Src.size()); + for (typename RangesCollectionTy::const_iterator i = Src.begin(), + e = Src.end(); i != e; ++i) { + const Range &R = *i; + std::vector<Constant*> r; + if (R.isSingleNumber()) { + r.reserve(2); + // FIXME: Since currently we have ConstantInt based numbers + // use hack-conversion of IntItem to ConstantInt + r.push_back(R.getLow().toConstantInt()); + r.push_back(R.getHigh().toConstantInt()); + } else { + r.reserve(1); + r.push_back(R.getLow().toConstantInt()); + } + Constant *CV = ConstantVector::get(r); + Elts.push_back(CV); + } + ArrayType *ArrTy = + ArrayType::get(Elts.front()->getType(), (uint64_t)Elts.size()); + Holder = ConstantArray::get(ArrTy, Elts); + } + + operator Constant*() { return Holder; } + operator const Constant*() const { return Holder; } + Constant *operator->() { return Holder; } + const Constant *operator->() const { return Holder; } +}; + +} + +#endif /* CONSTANTRANGESSET_H_ */ diff --git a/include/llvm/Support/IntegersSubsetMapping.h b/include/llvm/Support/IntegersSubsetMapping.h new file mode 100644 index 0000000..cab18dc --- /dev/null +++ b/include/llvm/Support/IntegersSubsetMapping.h @@ -0,0 +1,580 @@ +//===- IntegersSubsetMapping.h - Mapping subset ==> Successor ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// @file +/// IntegersSubsetMapping is mapping from A to B, where +/// Items in A is subsets of integers, +/// Items in B some pointers (Successors). +/// If user which to add another subset for successor that is already +/// exists in mapping, IntegersSubsetMapping merges existing subset with +/// added one. +// +//===----------------------------------------------------------------------===// + +#ifndef CRSBUILDER_H_ +#define CRSBUILDER_H_ + +#include "llvm/Support/IntegersSubset.h" +#include <list> +#include <map> +#include <vector> + +namespace llvm { + +template <class SuccessorClass, + class IntegersSubsetTy = IntegersSubset, + class IntTy = IntItem> +class IntegersSubsetMapping { + // FIXME: To much similar iterators typedefs, similar names. + // - Rename RangeIterator to the cluster iterator. + // - Remove unused "add" methods. + // - Class contents needs cleaning. +public: + + typedef IntRange<IntTy> RangeTy; + + struct RangeEx : public RangeTy { + RangeEx() : Weight(1) {} + RangeEx(const RangeTy &R) : RangeTy(R), Weight(1) {} + RangeEx(const IntTy &C) : RangeTy(C), Weight(1) {} + RangeEx(const IntTy &L, const IntTy &H) : RangeTy(L, H), Weight(1) {} + RangeEx(const IntTy &L, const IntTy &H, unsigned W) : + RangeTy(L, H), Weight(W) {} + unsigned Weight; + }; + + typedef std::pair<RangeEx, SuccessorClass*> Cluster; + + typedef std::list<RangeTy> RangesCollection; + typedef typename RangesCollection::iterator RangesCollectionIt; + typedef typename RangesCollection::const_iterator RangesCollectionConstIt; + typedef IntegersSubsetMapping<SuccessorClass, IntegersSubsetTy, IntTy> self; + +protected: + + typedef std::list<Cluster> CaseItems; + typedef typename CaseItems::iterator CaseItemIt; + typedef typename CaseItems::const_iterator CaseItemConstIt; + + // TODO: Change unclean CRS prefixes to SubsetMap for example. + typedef std::map<SuccessorClass*, RangesCollection > CRSMap; + typedef typename CRSMap::iterator CRSMapIt; + + struct ClustersCmp { + bool operator()(const Cluster &C1, const Cluster &C2) { + return C1.first < C2.first; + } + }; + + CaseItems Items; + bool Sorted; + + bool isIntersected(CaseItemIt& LItem, CaseItemIt& RItem) { + return LItem->first.getHigh() >= RItem->first.getLow(); + } + + bool isJoinable(CaseItemIt& LItem, CaseItemIt& RItem) { + if (LItem->second != RItem->second) { + assert(!isIntersected(LItem, RItem) && + "Intersected items with different successors!"); + return false; + } + APInt RLow = RItem->first.getLow(); + if (RLow != APInt::getNullValue(RLow.getBitWidth())) + --RLow; + return LItem->first.getHigh() >= RLow; + } + + void sort() { + if (!Sorted) { + std::vector<Cluster> clustersVector; + clustersVector.reserve(Items.size()); + clustersVector.insert(clustersVector.begin(), Items.begin(), Items.end()); + std::sort(clustersVector.begin(), clustersVector.end(), ClustersCmp()); + Items.clear(); + Items.insert(Items.begin(), clustersVector.begin(), clustersVector.end()); + Sorted = true; + } + } + + enum DiffProcessState { + L_OPENED, + INTERSECT_OPENED, + R_OPENED, + ALL_IS_CLOSED + }; + + class DiffStateMachine { + + DiffProcessState State; + IntTy OpenPt; + SuccessorClass *CurrentLSuccessor; + SuccessorClass *CurrentRSuccessor; + + self *LeftMapping; + self *IntersectionMapping; + self *RightMapping; + + public: + + typedef + IntegersSubsetMapping<SuccessorClass, IntegersSubsetTy, IntTy> MappingTy; + + DiffStateMachine(MappingTy *L, + MappingTy *Intersection, + MappingTy *R) : + State(ALL_IS_CLOSED), + LeftMapping(L), + IntersectionMapping(Intersection), + RightMapping(R) + {} + + void onLOpen(const IntTy &Pt, SuccessorClass *S) { + switch (State) { + case R_OPENED: + if (Pt > OpenPt/*Don't add empty ranges.*/ && RightMapping) + RightMapping->add(OpenPt, Pt-1, CurrentRSuccessor); + State = INTERSECT_OPENED; + break; + case ALL_IS_CLOSED: + State = L_OPENED; + break; + default: + assert(0 && "Got unexpected point."); + break; + } + CurrentLSuccessor = S; + OpenPt = Pt; + } + + void onLClose(const IntTy &Pt) { + switch (State) { + case L_OPENED: + assert(Pt >= OpenPt && + "Subset is not sorted or contains overlapped ranges"); + if (LeftMapping) + LeftMapping->add(OpenPt, Pt, CurrentLSuccessor); + State = ALL_IS_CLOSED; + break; + case INTERSECT_OPENED: + if (IntersectionMapping) + IntersectionMapping->add(OpenPt, Pt, CurrentLSuccessor); + OpenPt = Pt + 1; + State = R_OPENED; + break; + default: + assert(0 && "Got unexpected point."); + break; + } + } + + void onROpen(const IntTy &Pt, SuccessorClass *S) { + switch (State) { + case L_OPENED: + if (Pt > OpenPt && LeftMapping) + LeftMapping->add(OpenPt, Pt-1, CurrentLSuccessor); + State = INTERSECT_OPENED; + break; + case ALL_IS_CLOSED: + State = R_OPENED; + break; + default: + assert(0 && "Got unexpected point."); + break; + } + CurrentRSuccessor = S; + OpenPt = Pt; + } + + void onRClose(const IntTy &Pt) { + switch (State) { + case R_OPENED: + assert(Pt >= OpenPt && + "Subset is not sorted or contains overlapped ranges"); + if (RightMapping) + RightMapping->add(OpenPt, Pt, CurrentRSuccessor); + State = ALL_IS_CLOSED; + break; + case INTERSECT_OPENED: + if (IntersectionMapping) + IntersectionMapping->add(OpenPt, Pt, CurrentLSuccessor); + OpenPt = Pt + 1; + State = L_OPENED; + break; + default: + assert(0 && "Got unexpected point."); + break; + } + } + + void onLROpen(const IntTy &Pt, + SuccessorClass *LS, + SuccessorClass *RS) { + switch (State) { + case ALL_IS_CLOSED: + State = INTERSECT_OPENED; + break; + default: + assert(0 && "Got unexpected point."); + break; + } + CurrentLSuccessor = LS; + CurrentRSuccessor = RS; + OpenPt = Pt; + } + + void onLRClose(const IntTy &Pt) { + switch (State) { + case INTERSECT_OPENED: + if (IntersectionMapping) + IntersectionMapping->add(OpenPt, Pt, CurrentLSuccessor); + State = ALL_IS_CLOSED; + break; + default: + assert(0 && "Got unexpected point."); + break; + } + } + + bool isLOpened() { return State == L_OPENED; } + bool isROpened() { return State == R_OPENED; } + }; + +public: + + // Don't public CaseItems itself. Don't allow edit the Items directly. + // Just present the user way to iterate over the internal collection + // sharing iterator, begin() and end(). Editing should be controlled by + // factory. + typedef CaseItemIt RangeIterator; + + typedef std::pair<SuccessorClass*, IntegersSubsetTy> Case; + typedef std::list<Case> Cases; + typedef typename Cases::iterator CasesIt; + + IntegersSubsetMapping() { + Sorted = false; + } + + bool verify() { + RangeIterator DummyErrItem; + return verify(DummyErrItem); + } + + bool verify(RangeIterator& errItem) { + if (Items.empty()) + return true; + sort(); + for (CaseItemIt j = Items.begin(), i = j++, e = Items.end(); + j != e; i = j++) { + if (isIntersected(i, j) && i->second != j->second) { + errItem = j; + return false; + } + } + return true; + } + + bool isOverlapped(self &RHS) { + if (Items.empty() || RHS.empty()) + return true; + + for (CaseItemIt L = Items.begin(), R = RHS.Items.begin(), + el = Items.end(), er = RHS.Items.end(); L != el && R != er;) { + + const RangeTy &LRange = L->first; + const RangeTy &RRange = R->first; + + if (LRange.getLow() > RRange.getLow()) { + if (RRange.isSingleNumber() || LRange.getLow() > RRange.getHigh()) + ++R; + else + return true; + } else if (LRange.getLow() < RRange.getLow()) { + if (LRange.isSingleNumber() || LRange.getHigh() < RRange.getLow()) + ++L; + else + return true; + } else // iRange.getLow() == jRange.getLow() + return true; + } + return false; + } + + + void optimize() { + if (Items.size() < 2) + return; + sort(); + CaseItems OldItems = Items; + Items.clear(); + const IntTy *Low = &OldItems.begin()->first.getLow(); + const IntTy *High = &OldItems.begin()->first.getHigh(); + unsigned Weight = 1; + SuccessorClass *Successor = OldItems.begin()->second; + for (CaseItemIt j = OldItems.begin(), i = j++, e = OldItems.end(); + j != e; i = j++) { + if (isJoinable(i, j)) { + const IntTy *CurHigh = &j->first.getHigh(); + ++Weight; + if (*CurHigh > *High) + High = CurHigh; + } else { + RangeEx R(*Low, *High, Weight); + add(R, Successor); + Low = &j->first.getLow(); + High = &j->first.getHigh(); + Weight = 1; + Successor = j->second; + } + } + RangeEx R(*Low, *High, Weight); + add(R, Successor); + // We recollected the Items, but we kept it sorted. + Sorted = true; + } + + /// Adds a constant value. + void add(const IntTy &C, SuccessorClass *S = 0) { + RangeTy R(C); + add(R, S); + } + + /// Adds a range. + void add(const IntTy &Low, const IntTy &High, SuccessorClass *S = 0) { + RangeTy R(Low, High); + add(R, S); + } + void add(const RangeTy &R, SuccessorClass *S = 0) { + RangeEx REx = R; + add(REx, S); + } + void add(const RangeEx &R, SuccessorClass *S = 0) { + Items.push_back(std::make_pair(R, S)); + Sorted = false; + } + + /// Adds all ranges and values from given ranges set to the current + /// mapping. + void add(const IntegersSubsetTy &CRS, SuccessorClass *S = 0) { + for (unsigned i = 0, e = CRS.getNumItems(); i < e; ++i) { + RangeTy R = CRS.getItem(i); + add(R, S); + } + } + + void add(self& RHS) { + Items.insert(Items.end(), RHS.Items.begin(), RHS.Items.end()); + } + + void add(self& RHS, SuccessorClass *S) { + for (CaseItemIt i = RHS.Items.begin(), e = RHS.Items.end(); i != e; ++i) + add(i->first, S); + } + + void add(const RangesCollection& RHS, SuccessorClass *S = 0) { + for (RangesCollectionConstIt i = RHS.begin(), e = RHS.end(); i != e; ++i) + add(*i, S); + } + + /// Removes items from set. + void removeItem(RangeIterator i) { Items.erase(i); } + + /// Moves whole case from current mapping to the NewMapping object. + void detachCase(self& NewMapping, SuccessorClass *Succ) { + for (CaseItemIt i = Items.begin(); i != Items.end();) + if (i->second == Succ) { + NewMapping.add(i->first, i->second); + Items.erase(i++); + } else + ++i; + } + + /// Removes all clusters for given successor. + void removeCase(SuccessorClass *Succ) { + for (CaseItemIt i = Items.begin(); i != Items.end();) + if (i->second == Succ) { + Items.erase(i++); + } else + ++i; + } + + /// Find successor that satisfies given value. + SuccessorClass *findSuccessor(const IntTy& Val) { + for (CaseItemIt i = Items.begin(); i != Items.end(); ++i) { + if (i->first.isInRange(Val)) + return i->second; + } + return 0; + } + + /// Calculates the difference between this mapping and RHS. + /// THIS without RHS is placed into LExclude, + /// RHS without THIS is placed into RExclude, + /// THIS intersect RHS is placed into Intersection. + void diff(self *LExclude, self *Intersection, self *RExclude, + const self& RHS) { + + DiffStateMachine Machine(LExclude, Intersection, RExclude); + + CaseItemConstIt L = Items.begin(), R = RHS.Items.begin(); + while (L != Items.end() && R != RHS.Items.end()) { + const Cluster &LCluster = *L; + const RangeEx &LRange = LCluster.first; + const Cluster &RCluster = *R; + const RangeEx &RRange = RCluster.first; + + if (LRange.getHigh() < RRange.getLow()) { + Machine.onLOpen(LRange.getLow(), LCluster.second); + Machine.onLClose(LRange.getHigh()); + ++L; + continue; + } + + if (LRange.getLow() > RRange.getHigh()) { + Machine.onROpen(RRange.getLow(), RCluster.second); + Machine.onRClose(RRange.getHigh()); + ++R; + continue; + } + + if (LRange.getLow() < RRange.getLow()) { + // May be opened in previous iteration. + if (!Machine.isLOpened()) + Machine.onLOpen(LRange.getLow(), LCluster.second); + Machine.onROpen(RRange.getLow(), RCluster.second); + } + else if (RRange.getLow() < LRange.getLow()) { + if (!Machine.isROpened()) + Machine.onROpen(RRange.getLow(), RCluster.second); + Machine.onLOpen(LRange.getLow(), LCluster.second); + } + else + Machine.onLROpen(LRange.getLow(), LCluster.second, RCluster.second); + + if (LRange.getHigh() < RRange.getHigh()) { + Machine.onLClose(LRange.getHigh()); + ++L; + while(L != Items.end() && L->first.getHigh() < RRange.getHigh()) { + Machine.onLOpen(L->first.getLow(), L->second); + Machine.onLClose(L->first.getHigh()); + ++L; + } + } + else if (RRange.getHigh() < LRange.getHigh()) { + Machine.onRClose(RRange.getHigh()); + ++R; + while(R != RHS.Items.end() && R->first.getHigh() < LRange.getHigh()) { + Machine.onROpen(R->first.getLow(), R->second); + Machine.onRClose(R->first.getHigh()); + ++R; + } + } + else { + Machine.onLRClose(LRange.getHigh()); + ++L; + ++R; + } + } + + if (L != Items.end()) { + if (Machine.isLOpened()) { + Machine.onLClose(L->first.getHigh()); + ++L; + } + if (LExclude) + while (L != Items.end()) { + LExclude->add(L->first, L->second); + ++L; + } + } else if (R != RHS.Items.end()) { + if (Machine.isROpened()) { + Machine.onRClose(R->first.getHigh()); + ++R; + } + if (RExclude) + while (R != RHS.Items.end()) { + RExclude->add(R->first, R->second); + ++R; + } + } + } + + /// Builds the finalized case objects. + void getCases(Cases& TheCases, bool PreventMerging = false) { + //FIXME: PreventMerging is a temporary parameter. + //Currently a set of passes is still knows nothing about + //switches with case ranges, and if these passes meet switch + //with complex case that crashs the application. + if (PreventMerging) { + for (RangeIterator i = this->begin(); i != this->end(); ++i) { + RangesCollection SingleRange; + SingleRange.push_back(i->first); + TheCases.push_back(std::make_pair(i->second, + IntegersSubsetTy(SingleRange))); + } + return; + } + CRSMap TheCRSMap; + for (RangeIterator i = this->begin(); i != this->end(); ++i) + TheCRSMap[i->second].push_back(i->first); + for (CRSMapIt i = TheCRSMap.begin(), e = TheCRSMap.end(); i != e; ++i) + TheCases.push_back(std::make_pair(i->first, IntegersSubsetTy(i->second))); + } + + /// Builds the finalized case objects ignoring successor values, as though + /// all ranges belongs to the same successor. + IntegersSubsetTy getCase() { + RangesCollection Ranges; + for (RangeIterator i = this->begin(); i != this->end(); ++i) + Ranges.push_back(i->first); + return IntegersSubsetTy(Ranges); + } + + /// Returns pointer to value of case if it is single-numbered or 0 + /// in another case. + const IntTy* getCaseSingleNumber(SuccessorClass *Succ) { + const IntTy* Res = 0; + for (CaseItemIt i = Items.begin(); i != Items.end(); ++i) + if (i->second == Succ) { + if (!i->first.isSingleNumber()) + return 0; + if (Res) + return 0; + else + Res = &(i->first.getLow()); + } + return Res; + } + + /// Returns true if there is no ranges and values inside. + bool empty() const { return Items.empty(); } + + void clear() { + Items.clear(); + // Don't reset Sorted flag: + // 1. For empty mapping it matters nothing. + // 2. After first item will added Sorted flag will cleared. + } + + // Returns number of clusters + unsigned size() const { + return Items.size(); + } + + RangeIterator begin() { return Items.begin(); } + RangeIterator end() { return Items.end(); } +}; + +class BasicBlock; +typedef IntegersSubsetMapping<BasicBlock> IntegersSubsetToBB; + +} + +#endif /* CRSBUILDER_H_ */ diff --git a/include/llvm/Support/LEB128.h b/include/llvm/Support/LEB128.h new file mode 100644 index 0000000..00c7eea --- /dev/null +++ b/include/llvm/Support/LEB128.h @@ -0,0 +1,58 @@ +//===- llvm/Support/LEB128.h - [SU]LEB128 utility functions -----*- 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 some utility functions for encoding SLEB128 and +// ULEB128 values. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SYSTEM_LEB128_H +#define LLVM_SYSTEM_LEB128_H + +#include <llvm/Support/raw_ostream.h> + +namespace llvm { + +/// Utility function to encode a SLEB128 value. +static inline void encodeSLEB128(int64_t Value, raw_ostream &OS) { + bool More; + do { + uint8_t Byte = Value & 0x7f; + // NOTE: this assumes that this signed shift is an arithmetic right shift. + Value >>= 7; + More = !((((Value == 0 ) && ((Byte & 0x40) == 0)) || + ((Value == -1) && ((Byte & 0x40) != 0)))); + if (More) + Byte |= 0x80; // Mark this byte that that more bytes will follow. + OS << char(Byte); + } while (More); +} + +/// Utility function to encode a ULEB128 value. +static inline void encodeULEB128(uint64_t Value, raw_ostream &OS, + unsigned Padding = 0) { + do { + uint8_t Byte = Value & 0x7f; + Value >>= 7; + if (Value != 0 || Padding != 0) + Byte |= 0x80; // Mark this byte that that more bytes will follow. + OS << char(Byte); + } while (Value != 0); + + // Pad with 0x80 and emit a null byte at the end. + if (Padding != 0) { + for (; Padding != 1; --Padding) + OS << '\x80'; + OS << '\x00'; + } +} + +} // namespace llvm + +#endif // LLVM_SYSTEM_LEB128_H diff --git a/include/llvm/Support/MDBuilder.h b/include/llvm/Support/MDBuilder.h deleted file mode 100644 index 40f028a..0000000 --- a/include/llvm/Support/MDBuilder.h +++ /dev/null @@ -1,118 +0,0 @@ -//===---- llvm/Support/MDBuilder.h - Builder for LLVM metadata --*- 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 MDBuilder class, which is used as a convenient way to -// create LLVM metadata with a consistent and simplified interface. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_MDBUILDER_H -#define LLVM_SUPPORT_MDBUILDER_H - -#include "llvm/Constants.h" -#include "llvm/DerivedTypes.h" -#include "llvm/LLVMContext.h" -#include "llvm/Metadata.h" -#include "llvm/ADT/APInt.h" - -namespace llvm { - - class MDBuilder { - LLVMContext &Context; - - public: - MDBuilder(LLVMContext &context) : Context(context) {} - - /// \brief Return the given string as metadata. - MDString *createString(StringRef Str) { - return MDString::get(Context, Str); - } - - //===------------------------------------------------------------------===// - // FPMath metadata. - //===------------------------------------------------------------------===// - - /// \brief Return metadata with the given settings. The special value 0.0 - /// for the Accuracy parameter indicates the default (maximal precision) - /// setting. - MDNode *createFPMath(float Accuracy) { - if (Accuracy == 0.0) - return 0; - assert(Accuracy > 0.0 && "Invalid fpmath accuracy!"); - Value *Op = ConstantFP::get(Type::getFloatTy(Context), Accuracy); - return MDNode::get(Context, Op); - } - - - //===------------------------------------------------------------------===// - // Range metadata. - //===------------------------------------------------------------------===// - - /// \brief Return metadata describing the range [Lo, Hi). - MDNode *createRange(const APInt &Lo, const APInt &Hi) { - assert(Lo.getBitWidth() == Hi.getBitWidth() && "Mismatched bitwidths!"); - // If the range is everything then it is useless. - if (Hi == Lo) - return 0; - - // Return the range [Lo, Hi). - Type *Ty = IntegerType::get(Context, Lo.getBitWidth()); - Value *Range[2] = { ConstantInt::get(Ty, Lo), ConstantInt::get(Ty, Hi) }; - return MDNode::get(Context, Range); - } - - - //===------------------------------------------------------------------===// - // TBAA metadata. - //===------------------------------------------------------------------===// - - /// \brief Return metadata appropriate for a TBAA root node. Each returned - /// node is distinct from all other metadata and will never be identified - /// (uniqued) with anything else. - MDNode *createAnonymousTBAARoot() { - // To ensure uniqueness the root node is self-referential. - MDNode *Dummy = MDNode::getTemporary(Context, ArrayRef<Value*>()); - MDNode *Root = MDNode::get(Context, Dummy); - // At this point we have - // !0 = metadata !{} <- dummy - // !1 = metadata !{metadata !0} <- root - // Replace the dummy operand with the root node itself and delete the dummy. - Root->replaceOperandWith(0, Root); - MDNode::deleteTemporary(Dummy); - // We now have - // !1 = metadata !{metadata !1} <- self-referential root - return Root; - } - - /// \brief Return metadata appropriate for a TBAA root node with the given - /// name. This may be identified (uniqued) with other roots with the same - /// name. - MDNode *createTBAARoot(StringRef Name) { - return MDNode::get(Context, createString(Name)); - } - - /// \brief Return metadata for a non-root TBAA node with the given name, - /// parent in the TBAA tree, and value for 'pointsToConstantMemory'. - MDNode *createTBAANode(StringRef Name, MDNode *Parent, - bool isConstant = false) { - if (isConstant) { - Constant *Flags = ConstantInt::get(Type::getInt64Ty(Context), 1); - Value *Ops[3] = { createString(Name), Parent, Flags }; - return MDNode::get(Context, Ops); - } else { - Value *Ops[2] = { createString(Name), Parent }; - return MDNode::get(Context, Ops); - } - } - - }; - -} // end namespace llvm - -#endif diff --git a/include/llvm/Support/MachO.h b/include/llvm/Support/MachO.h index 44a7a79..7f28c3f 100644 --- a/include/llvm/Support/MachO.h +++ b/include/llvm/Support/MachO.h @@ -174,50 +174,50 @@ namespace llvm { RebaseTypePointer = 1u, // REBASE_TYPE_POINTER RebaseTypeTextAbsolute32 = 2u, // REBASE_TYPE_TEXT_ABSOLUTE32 - RebaseTypeTextPCRelative32 = 3u, // REBASE_TYPE_TEXT_PCREL32 + RebaseTypeTextPCRelative32 = 3u, // REBASE_TYPE_TEXT_PCREL32 RebaseOpcodeMask = 0xF0u, // REBASE_OPCODE_MASK RebaseImmediateMask = 0x0Fu, // REBASE_IMMEDIATE_MASK RebaseOpcodeDone = 0x00u, // REBASE_OPCODE_DONE RebaseOpcodeSetTypeImmediate = 0x10u, // REBASE_OPCODE_SET_TYPE_IMM - RebaseOpcodeSetSegmentAndOffsetULEB = 0x20u, // REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB + RebaseOpcodeSetSegmentAndOffsetULEB = 0x20u, // REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB RebaseOpcodeAddAddressULEB = 0x30u, // REBASE_OPCODE_ADD_ADDR_ULEB - RebaseOpcodeAddAddressImmediateScaled = 0x40u, // REBASE_OPCODE_ADD_ADDR_IMM_SCALED - RebaseOpcodeDoRebaseImmediateTimes = 0x50u, // REBASE_OPCODE_DO_REBASE_IMM_TIMES + RebaseOpcodeAddAddressImmediateScaled = 0x40u, // REBASE_OPCODE_ADD_ADDR_IMM_SCALED + RebaseOpcodeDoRebaseImmediateTimes = 0x50u, // REBASE_OPCODE_DO_REBASE_IMM_TIMES RebaseOpcodeDoRebaseULEBTimes = 0x60u, // REBASE_OPCODE_DO_REBASE_ULEB_TIMES RebaseOpcodeDoRebaseAddAddressULEB = 0x70u, // REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB RebaseOpcodeDoRebaseULEBTimesSkippingULEB = 0x80u, // REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB BindTypePointer = 1u, // BIND_TYPE_POINTER - BindTypeTextAbsolute32 = 2u, // BIND_TYPE_TEXT_ABSOLUTE32 - BindTypeTextPCRelative32 = 3u, // BIND_TYPE_TEXT_PCREL32 + BindTypeTextAbsolute32 = 2u, // BIND_TYPE_TEXT_ABSOLUTE32 + BindTypeTextPCRelative32 = 3u, // BIND_TYPE_TEXT_PCREL32 BindSpecialDylibSelf = 0u, // BIND_SPECIAL_DYLIB_SELF BindSpecialDylibMainExecutable = -1u, // BIND_SPECIAL_DYLIB_MAIN_EXECUTABLE BindSpecialDylibFlatLookup = -2u, // BIND_SPECIAL_DYLIB_FLAT_LOOKUP BindSymbolFlagsWeakImport = 0x1u, // BIND_SYMBOL_FLAGS_WEAK_IMPORT - BindSymbolFlagsNonWeakDefinition = 0x8u, // BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION + BindSymbolFlagsNonWeakDefinition = 0x8u, // BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION BindOpcodeMask = 0xF0u, // BIND_OPCODE_MASK BindImmediateMask = 0x0Fu, // BIND_IMMEDIATE_MASK BindOpcodeDone = 0x00u, // BIND_OPCODE_DONE BindOpcodeSetDylibOrdinalImmediate = 0x10u, // BIND_OPCODE_SET_DYLIB_ORDINAL_IMM BindOpcodeSetDylibOrdinalULEB = 0x20u, // BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB - BindOpcodeSetDylibSpecialImmediate = 0x30u, // BIND_OPCODE_SET_DYLIB_SPECIAL_IMM - BindOpcodeSetSymbolTrailingFlagsImmediate = 0x40u, // BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM - BindOpcodeSetTypeImmediate = 0x50u, // BIND_OPCODE_SET_TYPE_IMM + BindOpcodeSetDylibSpecialImmediate = 0x30u, // BIND_OPCODE_SET_DYLIB_SPECIAL_IMM + BindOpcodeSetSymbolTrailingFlagsImmediate = 0x40u, // BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM + BindOpcodeSetTypeImmediate = 0x50u, // BIND_OPCODE_SET_TYPE_IMM BindOpcodeSetAppendSLEB = 0x60u, // BIND_OPCODE_SET_ADDEND_SLEB BindOpcodeSetSegmentAndOffsetULEB = 0x70u, // BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB BindOpcodeAddAddressULEB = 0x80u, // BIND_OPCODE_ADD_ADDR_ULEB BindOpcodeDoBind = 0x90u, // BIND_OPCODE_DO_BIND - BindOpcodeDoBindAddAddressULEB = 0xA0u, // BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB - BindOpcodeDoBindAddAddressImmediateScaled = 0xB0u, // BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED + BindOpcodeDoBindAddAddressULEB = 0xA0u, // BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB + BindOpcodeDoBindAddAddressImmediateScaled = 0xB0u, // BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED BindOpcodeDoBindULEBTimesSkippingULEB = 0xC0u, // BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB ExportSymbolFlagsKindMask = 0x03u, // EXPORT_SYMBOL_FLAGS_KIND_MASK - ExportSymbolFlagsKindRegular = 0x00u, // EXPORT_SYMBOL_FLAGS_KIND_REGULAR + ExportSymbolFlagsKindRegular = 0x00u, // EXPORT_SYMBOL_FLAGS_KIND_REGULAR ExportSymbolFlagsKindThreadLocal = 0x01u, // EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL ExportSymbolFlagsWeakDefinition = 0x04u, // EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION ExportSymbolFlagsIndirectDefinition = 0x08u, // EXPORT_SYMBOL_FLAGS_INDIRECT_DEFINITION @@ -227,7 +227,7 @@ namespace llvm { // Constant masks for the "n_type" field in llvm::MachO::nlist and // llvm::MachO::nlist_64 NlistMaskStab = 0xe0, // N_STAB - NlistMaskPrivateExternal = 0x10, // N_PEXT + NlistMaskPrivateExternal = 0x10, // N_PEXT NlistMaskType = 0x0e, // N_TYPE NlistMaskExternal = 0x01, // N_EXT @@ -249,35 +249,35 @@ namespace llvm { // Constant values for the "n_type" field in llvm::MachO::nlist and // llvm::MachO::nlist_64 when "(n_type & NlistMaskStab) != 0" - StabGlobalSymbol = 0x20u, // N_GSYM - StabFunctionName = 0x22u, // N_FNAME - StabFunction = 0x24u, // N_FUN - StabStaticSymbol = 0x26u, // N_STSYM - StabLocalCommon = 0x28u, // N_LCSYM + StabGlobalSymbol = 0x20u, // N_GSYM + StabFunctionName = 0x22u, // N_FNAME + StabFunction = 0x24u, // N_FUN + StabStaticSymbol = 0x26u, // N_STSYM + StabLocalCommon = 0x28u, // N_LCSYM StabBeginSymbol = 0x2Eu, // N_BNSYM - StabSourceFileOptions = 0x3Cu, // N_OPT - StabRegisterSymbol = 0x40u, // N_RSYM - StabSourceLine = 0x44u, // N_SLINE + StabSourceFileOptions = 0x3Cu, // N_OPT + StabRegisterSymbol = 0x40u, // N_RSYM + StabSourceLine = 0x44u, // N_SLINE StabEndSymbol = 0x4Eu, // N_ENSYM - StabStructureType = 0x60u, // N_SSYM - StabSourceFileName = 0x64u, // N_SO - StabObjectFileName = 0x66u, // N_OSO - StabLocalSymbol = 0x80u, // N_LSYM - StabBeginIncludeFileName = 0x82u, // N_BINCL - StabIncludeFileName = 0x84u, // N_SOL + StabStructureType = 0x60u, // N_SSYM + StabSourceFileName = 0x64u, // N_SO + StabObjectFileName = 0x66u, // N_OSO + StabLocalSymbol = 0x80u, // N_LSYM + StabBeginIncludeFileName = 0x82u, // N_BINCL + StabIncludeFileName = 0x84u, // N_SOL StabCompilerParameters = 0x86u, // N_PARAMS StabCompilerVersion = 0x88u, // N_VERSION StabCompilerOptLevel = 0x8Au, // N_OLEVEL - StabParameter = 0xA0u, // N_PSYM - StabEndIncludeFile = 0xA2u, // N_EINCL - StabAlternateEntry = 0xA4u, // N_ENTRY - StabLeftBracket = 0xC0u, // N_LBRAC - StabDeletedIncludeFile = 0xC2u, // N_EXCL - StabRightBracket = 0xE0u, // N_RBRAC - StabBeginCommon = 0xE2u, // N_BCOMM - StabEndCommon = 0xE4u, // N_ECOMM - StabEndCommonLocal = 0xE8u, // N_ECOML - StabLength = 0xFEu // N_LENG + StabParameter = 0xA0u, // N_PSYM + StabEndIncludeFile = 0xA2u, // N_EINCL + StabAlternateEntry = 0xA4u, // N_ENTRY + StabLeftBracket = 0xC0u, // N_LBRAC + StabDeletedIncludeFile = 0xC2u, // N_EXCL + StabRightBracket = 0xE0u, // N_RBRAC + StabBeginCommon = 0xE2u, // N_BCOMM + StabEndCommon = 0xE4u, // N_ECOMM + StabEndCommonLocal = 0xE8u, // N_ECOML + StabLength = 0xFEu // N_LENG }; @@ -490,12 +490,12 @@ namespace llvm { uint32_t nextrel; uint32_t locreloff; uint32_t nlocrel; - }; + }; struct dylib_table_of_contents { uint32_t symbol_index; uint32_t module_index; - }; + }; struct dylib_module { uint32_t module_name; @@ -511,7 +511,7 @@ namespace llvm { uint32_t ninit_nterm; uint32_t objc_module_info_addr; uint32_t objc_module_info_size; - }; + }; struct dylib_module_64 { uint32_t module_name; diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index d085c94..4005161 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -414,14 +414,14 @@ int IsInf(double d); /// MinAlign - A and B are either alignments or offsets. Return the minimum /// alignment that may be assumed after adding the two together. -static inline uint64_t MinAlign(uint64_t A, uint64_t B) { +inline uint64_t MinAlign(uint64_t A, uint64_t B) { // The largest power of 2 that divides both A and B. return (A | B) & -(A | B); } /// NextPowerOf2 - Returns the next power of two (in 64-bits) /// that is strictly greater than A. Returns zero on overflow. -static inline uint64_t NextPowerOf2(uint64_t A) { +inline uint64_t NextPowerOf2(uint64_t A) { A |= (A >> 1); A |= (A >> 2); A |= (A >> 4); diff --git a/include/llvm/Support/PathV2.h b/include/llvm/Support/PathV2.h index 6d38c95..8d79709 100644 --- a/include/llvm/Support/PathV2.h +++ b/include/llvm/Support/PathV2.h @@ -47,9 +47,9 @@ namespace path { /// C:\foo\bar => C:,/,foo,bar /// class const_iterator { - StringRef Path; //< The entire path. - StringRef Component; //< The current component. Not necessarily in Path. - size_t Position; //< The iterators current position within Path. + StringRef Path; ///< The entire path. + StringRef Component; ///< The current component. Not necessarily in Path. + size_t Position; ///< The iterators current position within Path. // An end iterator has Position = Path.size() + 1. friend const_iterator begin(StringRef path); diff --git a/include/llvm/Support/Process.h b/include/llvm/Support/Process.h index d796b79..088897c 100644 --- a/include/llvm/Support/Process.h +++ b/include/llvm/Support/Process.h @@ -1,4 +1,4 @@ -//===- llvm/Support/Process.h ------------------------------------*- C++ -*-===// +//===- llvm/Support/Process.h -----------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -97,6 +97,10 @@ namespace sys { /// the user rather than being put on a pipe or stored in a file. static bool FileDescriptorIsDisplayed(int fd); + /// This function determines if the given file descriptor is displayd and + /// supports colors. + static bool FileDescriptorHasColors(int fd); + /// This function determines the number of columns in the window /// if standard output is connected to a "tty" or "console" /// window. If standard output is not connected to a tty or @@ -142,6 +146,10 @@ namespace sys { /// Resets the terminals colors, or returns an escape sequence to do so. static const char *ResetColor(); + + /// Get the result of a process wide random number generator. The + /// generator will be automatically seeded in non-deterministic fashion. + static unsigned GetRandomNumber(); /// @} }; } diff --git a/include/llvm/Support/SMLoc.h b/include/llvm/Support/SMLoc.h index d48bfcc..1bf810b 100644 --- a/include/llvm/Support/SMLoc.h +++ b/include/llvm/Support/SMLoc.h @@ -24,7 +24,6 @@ class SMLoc { const char *Ptr; public: SMLoc() : Ptr(0) {} - SMLoc(const SMLoc &RHS) : Ptr(RHS.Ptr) {} bool isValid() const { return Ptr != 0; } @@ -48,7 +47,7 @@ public: SMLoc Start, End; SMRange() {} - SMRange(SMLoc Start, SMLoc End) : Start(Start), End(End) { + SMRange(SMLoc St, SMLoc En) : Start(St), End(En) { assert(Start.isValid() == End.isValid() && "Start and end should either both be valid or both be invalid!"); } diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index 76967db..8949a3a 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -123,7 +123,14 @@ public: /// FindLineNumber - Find the line number for the specified location in the /// specified file. This is not a fast method. - unsigned FindLineNumber(SMLoc Loc, int BufferID = -1) const; + unsigned FindLineNumber(SMLoc Loc, int BufferID = -1) const { + return getLineAndColumn(Loc, BufferID).first; + } + + /// getLineAndColumn - Find the line and column number for the specified + /// location in the specified file. This is not a fast method. + std::pair<unsigned, unsigned> + getLineAndColumn(SMLoc Loc, int BufferID = -1) const; /// PrintMessage - Emit a message about the specified location with the /// specified string. @@ -169,9 +176,9 @@ public: SMDiagnostic() : SM(0), LineNo(0), ColumnNo(0), Kind(SourceMgr::DK_Error) {} // Diagnostic with no location (e.g. file not found, command line arg error). - SMDiagnostic(const std::string &filename, SourceMgr::DiagKind Kind, + SMDiagnostic(const std::string &filename, SourceMgr::DiagKind Knd, const std::string &Msg) - : SM(0), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Kind), + : SM(0), Filename(filename), LineNo(-1), ColumnNo(-1), Kind(Knd), Message(Msg) {} // Diagnostic with a location. diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index 8808130..c0be8f1 100644 --- a/include/llvm/Support/TargetRegistry.h +++ b/include/llvm/Support/TargetRegistry.h @@ -108,6 +108,7 @@ namespace llvm { const MCRegisterInfo &MRI, const MCSubtargetInfo &STI); typedef MCCodeEmitter *(*MCCodeEmitterCtorTy)(const MCInstrInfo &II, + const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx); typedef MCStreamer *(*MCObjectStreamerCtorTy)(const Target &T, @@ -405,11 +406,12 @@ namespace llvm { /// createMCCodeEmitter - Create a target specific code emitter. MCCodeEmitter *createMCCodeEmitter(const MCInstrInfo &II, + const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx) const { if (!MCCodeEmitterCtorFn) return 0; - return MCCodeEmitterCtorFn(II, STI, Ctx); + return MCCodeEmitterCtorFn(II, MRI, STI, Ctx); } /// createMCObjectStreamer - Create a target specific MCStreamer. @@ -510,6 +512,21 @@ namespace llvm { static const Target *lookupTarget(const std::string &Triple, std::string &Error); + /// lookupTarget - Lookup a target based on an architecture name + /// and a target triple. If the architecture name is non-empty, + /// then the lookup is done by architecture. Otherwise, the target + /// triple is used. + /// + /// \param ArchName - The architecture to use for finding a target. + /// \param TheTriple - The triple to use for finding a target. The + /// triple is updated with canonical architecture name if a lookup + /// by architecture is done. + /// \param Error - On failure, an error string describing why no target was + /// found. + static const Target *lookupTarget(const std::string &ArchName, + Triple &TheTriple, + std::string &Error); + /// getClosestTargetForJIT - Pick the best target that is compatible with /// the current host. If no close target can be found, this returns null /// and sets the Error string to a reason. @@ -1129,6 +1146,7 @@ namespace llvm { private: static MCCodeEmitter *Allocator(const MCInstrInfo &II, + const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, MCContext &Ctx) { return new MCCodeEmitterImpl(); diff --git a/include/llvm/Support/ThreadLocal.h b/include/llvm/Support/ThreadLocal.h index 15350a7..62ec90a 100644 --- a/include/llvm/Support/ThreadLocal.h +++ b/include/llvm/Support/ThreadLocal.h @@ -15,6 +15,7 @@ #define LLVM_SYSTEM_THREAD_LOCAL_H #include "llvm/Support/Threading.h" +#include "llvm/Support/DataTypes.h" #include <cassert> namespace llvm { @@ -22,7 +23,15 @@ namespace llvm { // ThreadLocalImpl - Common base class of all ThreadLocal instantiations. // YOU SHOULD NEVER USE THIS DIRECTLY. class ThreadLocalImpl { - void* data; + typedef uint64_t ThreadLocalDataTy; + /// \brief Platform-specific thread local data. + /// + /// This is embedded in the class and we avoid malloc'ing/free'ing it, + /// to make this class more safe for use along with CrashRecoveryContext. + union { + char data[sizeof(ThreadLocalDataTy)]; + ThreadLocalDataTy align_data; + }; public: ThreadLocalImpl(); virtual ~ThreadLocalImpl(); diff --git a/include/llvm/Support/TypeBuilder.h b/include/llvm/Support/TypeBuilder.h deleted file mode 100644 index c756069..0000000 --- a/include/llvm/Support/TypeBuilder.h +++ /dev/null @@ -1,399 +0,0 @@ -//===---- llvm/Support/TypeBuilder.h - Builder for LLVM types ---*- 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 TypeBuilder class, which is used as a convenient way to -// create LLVM types with a consistent and simplified interface. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_SUPPORT_TYPEBUILDER_H -#define LLVM_SUPPORT_TYPEBUILDER_H - -#include "llvm/DerivedTypes.h" -#include "llvm/LLVMContext.h" -#include <limits.h> - -namespace llvm { - -/// TypeBuilder - This provides a uniform API for looking up types -/// known at compile time. To support cross-compilation, we define a -/// series of tag types in the llvm::types namespace, like i<N>, -/// ieee_float, ppc_fp128, etc. TypeBuilder<T, false> allows T to be -/// any of these, a native C type (whose size may depend on the host -/// compiler), or a pointer, function, or struct type built out of -/// these. TypeBuilder<T, true> removes native C types from this set -/// to guarantee that its result is suitable for cross-compilation. -/// We define the primitive types, pointer types, and functions up to -/// 5 arguments here, but to use this class with your own types, -/// you'll need to specialize it. For example, say you want to call a -/// function defined externally as: -/// -/// struct MyType { -/// int32 a; -/// int32 *b; -/// void *array[1]; // Intended as a flexible array. -/// }; -/// int8 AFunction(struct MyType *value); -/// -/// You'll want to use -/// Function::Create(TypeBuilder<types::i<8>(MyType*), true>::get(), ...) -/// to declare the function, but when you first try this, your compiler will -/// complain that TypeBuilder<MyType, true>::get() doesn't exist. To fix this, -/// write: -/// -/// namespace llvm { -/// template<bool xcompile> class TypeBuilder<MyType, xcompile> { -/// public: -/// static StructType *get(LLVMContext &Context) { -/// // If you cache this result, be sure to cache it separately -/// // for each LLVMContext. -/// return StructType::get( -/// TypeBuilder<types::i<32>, xcompile>::get(Context), -/// TypeBuilder<types::i<32>*, xcompile>::get(Context), -/// TypeBuilder<types::i<8>*[], xcompile>::get(Context), -/// NULL); -/// } -/// -/// // You may find this a convenient place to put some constants -/// // to help with getelementptr. They don't have any effect on -/// // the operation of TypeBuilder. -/// enum Fields { -/// FIELD_A, -/// FIELD_B, -/// FIELD_ARRAY -/// }; -/// } -/// } // namespace llvm -/// -/// TypeBuilder cannot handle recursive types or types you only know at runtime. -/// If you try to give it a recursive type, it will deadlock, infinitely -/// recurse, or do something similarly undesirable. -template<typename T, bool cross_compilable> class TypeBuilder {}; - -// Types for use with cross-compilable TypeBuilders. These correspond -// exactly with an LLVM-native type. -namespace types { -/// i<N> corresponds to the LLVM IntegerType with N bits. -template<uint32_t num_bits> class i {}; - -// The following classes represent the LLVM floating types. -class ieee_float {}; -class ieee_double {}; -class x86_fp80 {}; -class fp128 {}; -class ppc_fp128 {}; -// X86 MMX. -class x86_mmx {}; -} // namespace types - -// LLVM doesn't have const or volatile types. -template<typename T, bool cross> class TypeBuilder<const T, cross> - : public TypeBuilder<T, cross> {}; -template<typename T, bool cross> class TypeBuilder<volatile T, cross> - : public TypeBuilder<T, cross> {}; -template<typename T, bool cross> class TypeBuilder<const volatile T, cross> - : public TypeBuilder<T, cross> {}; - -// Pointers -template<typename T, bool cross> class TypeBuilder<T*, cross> { -public: - static PointerType *get(LLVMContext &Context) { - return PointerType::getUnqual(TypeBuilder<T,cross>::get(Context)); - } -}; - -/// There is no support for references -template<typename T, bool cross> class TypeBuilder<T&, cross> {}; - -// Arrays -template<typename T, size_t N, bool cross> class TypeBuilder<T[N], cross> { -public: - static ArrayType *get(LLVMContext &Context) { - return ArrayType::get(TypeBuilder<T, cross>::get(Context), N); - } -}; -/// LLVM uses an array of length 0 to represent an unknown-length array. -template<typename T, bool cross> class TypeBuilder<T[], cross> { -public: - static ArrayType *get(LLVMContext &Context) { - return ArrayType::get(TypeBuilder<T, cross>::get(Context), 0); - } -}; - -// Define the C integral types only for TypeBuilder<T, false>. -// -// C integral types do not have a defined size. It would be nice to use the -// stdint.h-defined typedefs that do have defined sizes, but we'd run into the -// following problem: -// -// On an ILP32 machine, stdint.h might define: -// -// typedef int int32_t; -// typedef long long int64_t; -// typedef long size_t; -// -// If we defined TypeBuilder<int32_t> and TypeBuilder<int64_t>, then any use of -// TypeBuilder<size_t> would fail. We couldn't define TypeBuilder<size_t> in -// addition to the defined-size types because we'd get duplicate definitions on -// platforms where stdint.h instead defines: -// -// typedef int int32_t; -// typedef long long int64_t; -// typedef int size_t; -// -// So we define all the primitive C types and nothing else. -#define DEFINE_INTEGRAL_TYPEBUILDER(T) \ -template<> class TypeBuilder<T, false> { \ -public: \ - static IntegerType *get(LLVMContext &Context) { \ - return IntegerType::get(Context, sizeof(T) * CHAR_BIT); \ - } \ -}; \ -template<> class TypeBuilder<T, true> { \ - /* We provide a definition here so users don't accidentally */ \ - /* define these types to work. */ \ -} -DEFINE_INTEGRAL_TYPEBUILDER(char); -DEFINE_INTEGRAL_TYPEBUILDER(signed char); -DEFINE_INTEGRAL_TYPEBUILDER(unsigned char); -DEFINE_INTEGRAL_TYPEBUILDER(short); -DEFINE_INTEGRAL_TYPEBUILDER(unsigned short); -DEFINE_INTEGRAL_TYPEBUILDER(int); -DEFINE_INTEGRAL_TYPEBUILDER(unsigned int); -DEFINE_INTEGRAL_TYPEBUILDER(long); -DEFINE_INTEGRAL_TYPEBUILDER(unsigned long); -#ifdef _MSC_VER -DEFINE_INTEGRAL_TYPEBUILDER(__int64); -DEFINE_INTEGRAL_TYPEBUILDER(unsigned __int64); -#else /* _MSC_VER */ -DEFINE_INTEGRAL_TYPEBUILDER(long long); -DEFINE_INTEGRAL_TYPEBUILDER(unsigned long long); -#endif /* _MSC_VER */ -#undef DEFINE_INTEGRAL_TYPEBUILDER - -template<uint32_t num_bits, bool cross> -class TypeBuilder<types::i<num_bits>, cross> { -public: - static IntegerType *get(LLVMContext &C) { - return IntegerType::get(C, num_bits); - } -}; - -template<> class TypeBuilder<float, false> { -public: - static Type *get(LLVMContext& C) { - return Type::getFloatTy(C); - } -}; -template<> class TypeBuilder<float, true> {}; - -template<> class TypeBuilder<double, false> { -public: - static Type *get(LLVMContext& C) { - return Type::getDoubleTy(C); - } -}; -template<> class TypeBuilder<double, true> {}; - -template<bool cross> class TypeBuilder<types::ieee_float, cross> { -public: - static Type *get(LLVMContext& C) { return Type::getFloatTy(C); } -}; -template<bool cross> class TypeBuilder<types::ieee_double, cross> { -public: - static Type *get(LLVMContext& C) { return Type::getDoubleTy(C); } -}; -template<bool cross> class TypeBuilder<types::x86_fp80, cross> { -public: - static Type *get(LLVMContext& C) { return Type::getX86_FP80Ty(C); } -}; -template<bool cross> class TypeBuilder<types::fp128, cross> { -public: - static Type *get(LLVMContext& C) { return Type::getFP128Ty(C); } -}; -template<bool cross> class TypeBuilder<types::ppc_fp128, cross> { -public: - static Type *get(LLVMContext& C) { return Type::getPPC_FP128Ty(C); } -}; -template<bool cross> class TypeBuilder<types::x86_mmx, cross> { -public: - static Type *get(LLVMContext& C) { return Type::getX86_MMXTy(C); } -}; - -template<bool cross> class TypeBuilder<void, cross> { -public: - static Type *get(LLVMContext &C) { - return Type::getVoidTy(C); - } -}; - -/// void* is disallowed in LLVM types, but it occurs often enough in C code that -/// we special case it. -template<> class TypeBuilder<void*, false> - : public TypeBuilder<types::i<8>*, false> {}; -template<> class TypeBuilder<const void*, false> - : public TypeBuilder<types::i<8>*, false> {}; -template<> class TypeBuilder<volatile void*, false> - : public TypeBuilder<types::i<8>*, false> {}; -template<> class TypeBuilder<const volatile void*, false> - : public TypeBuilder<types::i<8>*, false> {}; - -template<typename R, bool cross> class TypeBuilder<R(), cross> { -public: - static FunctionType *get(LLVMContext &Context) { - return FunctionType::get(TypeBuilder<R, cross>::get(Context), false); - } -}; -template<typename R, typename A1, bool cross> class TypeBuilder<R(A1), cross> { -public: - static FunctionType *get(LLVMContext &Context) { - Type *params[] = { - TypeBuilder<A1, cross>::get(Context), - }; - return FunctionType::get(TypeBuilder<R, cross>::get(Context), - params, false); - } -}; -template<typename R, typename A1, typename A2, bool cross> -class TypeBuilder<R(A1, A2), cross> { -public: - static FunctionType *get(LLVMContext &Context) { - Type *params[] = { - TypeBuilder<A1, cross>::get(Context), - TypeBuilder<A2, cross>::get(Context), - }; - return FunctionType::get(TypeBuilder<R, cross>::get(Context), - params, false); - } -}; -template<typename R, typename A1, typename A2, typename A3, bool cross> -class TypeBuilder<R(A1, A2, A3), cross> { -public: - static FunctionType *get(LLVMContext &Context) { - Type *params[] = { - TypeBuilder<A1, cross>::get(Context), - TypeBuilder<A2, cross>::get(Context), - TypeBuilder<A3, cross>::get(Context), - }; - return FunctionType::get(TypeBuilder<R, cross>::get(Context), - params, false); - } -}; - -template<typename R, typename A1, typename A2, typename A3, typename A4, - bool cross> -class TypeBuilder<R(A1, A2, A3, A4), cross> { -public: - static FunctionType *get(LLVMContext &Context) { - Type *params[] = { - TypeBuilder<A1, cross>::get(Context), - TypeBuilder<A2, cross>::get(Context), - TypeBuilder<A3, cross>::get(Context), - TypeBuilder<A4, cross>::get(Context), - }; - return FunctionType::get(TypeBuilder<R, cross>::get(Context), - params, false); - } -}; - -template<typename R, typename A1, typename A2, typename A3, typename A4, - typename A5, bool cross> -class TypeBuilder<R(A1, A2, A3, A4, A5), cross> { -public: - static FunctionType *get(LLVMContext &Context) { - Type *params[] = { - TypeBuilder<A1, cross>::get(Context), - TypeBuilder<A2, cross>::get(Context), - TypeBuilder<A3, cross>::get(Context), - TypeBuilder<A4, cross>::get(Context), - TypeBuilder<A5, cross>::get(Context), - }; - return FunctionType::get(TypeBuilder<R, cross>::get(Context), - params, false); - } -}; - -template<typename R, bool cross> class TypeBuilder<R(...), cross> { -public: - static FunctionType *get(LLVMContext &Context) { - return FunctionType::get(TypeBuilder<R, cross>::get(Context), true); - } -}; -template<typename R, typename A1, bool cross> -class TypeBuilder<R(A1, ...), cross> { -public: - static FunctionType *get(LLVMContext &Context) { - Type *params[] = { - TypeBuilder<A1, cross>::get(Context), - }; - return FunctionType::get(TypeBuilder<R, cross>::get(Context), params, true); - } -}; -template<typename R, typename A1, typename A2, bool cross> -class TypeBuilder<R(A1, A2, ...), cross> { -public: - static FunctionType *get(LLVMContext &Context) { - Type *params[] = { - TypeBuilder<A1, cross>::get(Context), - TypeBuilder<A2, cross>::get(Context), - }; - return FunctionType::get(TypeBuilder<R, cross>::get(Context), - params, true); - } -}; -template<typename R, typename A1, typename A2, typename A3, bool cross> -class TypeBuilder<R(A1, A2, A3, ...), cross> { -public: - static FunctionType *get(LLVMContext &Context) { - Type *params[] = { - TypeBuilder<A1, cross>::get(Context), - TypeBuilder<A2, cross>::get(Context), - TypeBuilder<A3, cross>::get(Context), - }; - return FunctionType::get(TypeBuilder<R, cross>::get(Context), - params, true); - } -}; - -template<typename R, typename A1, typename A2, typename A3, typename A4, - bool cross> -class TypeBuilder<R(A1, A2, A3, A4, ...), cross> { -public: - static FunctionType *get(LLVMContext &Context) { - Type *params[] = { - TypeBuilder<A1, cross>::get(Context), - TypeBuilder<A2, cross>::get(Context), - TypeBuilder<A3, cross>::get(Context), - TypeBuilder<A4, cross>::get(Context), - }; - return FunctionType::get(TypeBuilder<R, cross>::get(Context), - params, true); - } -}; - -template<typename R, typename A1, typename A2, typename A3, typename A4, - typename A5, bool cross> -class TypeBuilder<R(A1, A2, A3, A4, A5, ...), cross> { -public: - static FunctionType *get(LLVMContext &Context) { - Type *params[] = { - TypeBuilder<A1, cross>::get(Context), - TypeBuilder<A2, cross>::get(Context), - TypeBuilder<A3, cross>::get(Context), - TypeBuilder<A4, cross>::get(Context), - TypeBuilder<A5, cross>::get(Context), - }; - return FunctionType::get(TypeBuilder<R, cross>::get(Context), - params, true); - } -}; - -} // namespace llvm - -#endif diff --git a/include/llvm/Support/ValueHandle.h b/include/llvm/Support/ValueHandle.h index b7210b2..61e21b8 100644 --- a/include/llvm/Support/ValueHandle.h +++ b/include/llvm/Support/ValueHandle.h @@ -110,11 +110,12 @@ protected: V != DenseMapInfo<Value *>::getTombstoneKey(); } -private: +public: // Callbacks made from Value. static void ValueIsDeleted(Value *V); static void ValueIsRAUWd(Value *Old, Value *New); +private: // Internal implementation details. ValueHandleBase **getPrevPtr() const { return PrevPair.getPointer(); } HandleBaseKind getKind() const { return PrevPair.getInt(); } @@ -367,7 +368,7 @@ protected: CallbackVH(const CallbackVH &RHS) : ValueHandleBase(Callback, RHS) {} - virtual ~CallbackVH(); + virtual ~CallbackVH() {} void setValPtr(Value *P) { ValueHandleBase::operator=(P); @@ -389,15 +390,13 @@ public: /// /// All implementations must remove the reference from this object to the /// Value that's being destroyed. - virtual void deleted() { - setValPtr(NULL); - } + virtual void deleted(); /// Called when this->getValPtr()->replaceAllUsesWith(new_value) is called, /// _before_ any of the uses have actually been replaced. If WeakVH were /// implemented as a CallbackVH, it would use this method to call /// setValPtr(new_value). AssertingVH would do nothing in this method. - virtual void allUsesReplacedWith(Value *) {} + virtual void allUsesReplacedWith(Value *); }; // Specialize simplify_type to allow CallbackVH to participate in diff --git a/include/llvm/Support/YAMLParser.h b/include/llvm/Support/YAMLParser.h index 47206b3..98910eb 100644 --- a/include/llvm/Support/YAMLParser.h +++ b/include/llvm/Support/YAMLParser.h @@ -130,7 +130,7 @@ public: void setError(const Twine &Message, Token &Location) const; bool failed() const; - virtual void skip() {}; + virtual void skip() {} unsigned int getType() const { return TypeID; } static inline bool classof(const Node *) { return true; } @@ -336,7 +336,7 @@ public: enum MappingType { MT_Block, MT_Flow, - MT_Inline //< An inline mapping node is used for "[key: value]". + MT_Inline ///< An inline mapping node is used for "[key: value]". }; MappingNode(OwningPtr<Document> &D, StringRef Anchor, MappingType MT) @@ -513,37 +513,44 @@ private: /// @brief Iterator abstraction for Documents over a Stream. class document_iterator { public: - document_iterator() : Doc(NullDoc) {} - document_iterator(OwningPtr<Document> &D) : Doc(D) {} + document_iterator() : Doc(0) {} + document_iterator(OwningPtr<Document> &D) : Doc(&D) {} bool operator ==(const document_iterator &Other) { - return Doc == Other.Doc; + if (isAtEnd() || Other.isAtEnd()) + return isAtEnd() && Other.isAtEnd(); + + return *Doc == *Other.Doc; } bool operator !=(const document_iterator &Other) { return !(*this == Other); } document_iterator operator ++() { - if (!Doc->skip()) { - Doc.reset(0); + assert(Doc != 0 && "incrementing iterator past the end."); + if (!(*Doc)->skip()) { + Doc->reset(0); } else { - Stream &S = Doc->stream; - Doc.reset(new Document(S)); + Stream &S = (*Doc)->stream; + Doc->reset(new Document(S)); } return *this; } Document &operator *() { - return *Doc; + return *Doc->get(); } OwningPtr<Document> &operator ->() { - return Doc; + return *Doc; } private: - static OwningPtr<Document> NullDoc; - OwningPtr<Document> &Doc; + bool isAtEnd() const { + return Doc == 0 || *Doc == 0; + } + + OwningPtr<Document> *Doc; }; } diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index 6c5d478..5de749a 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -230,6 +230,9 @@ public: /// rather than being put on a pipe or stored in a file. virtual bool is_displayed() const { return false; } + /// This function determines if this stream is displayed and supports colors. + virtual bool has_colors() const { return is_displayed(); } + //===--------------------------------------------------------------------===// // Subclass Interface //===--------------------------------------------------------------------===// @@ -386,10 +389,12 @@ public: virtual bool is_displayed() const; + virtual bool has_colors() const; + /// has_error - Return the value of the flag in this raw_fd_ostream indicating /// whether an output error has been encountered. /// This doesn't implicitly flush any pending output. Also, it doesn't - /// guarantee to detect all errors unless the the stream has been closed. + /// guarantee to detect all errors unless the stream has been closed. bool has_error() const { return Error; } diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h index a3a551f..7b97547 100644 --- a/include/llvm/Support/type_traits.h +++ b/include/llvm/Support/type_traits.h @@ -21,6 +21,11 @@ #include <cstddef> #include <utility> +#ifndef __has_feature +#define LLVM_DEFINED_HAS_FEATURE +#define __has_feature(x) 0 +#endif + // This is actually the conforming implementation which works with abstract // classes. However, enough compilers have trouble with it that most will use // the one in boost/type_traits/object_traits.hpp. This implementation actually @@ -58,9 +63,15 @@ struct is_class /// type can be copied around with memcpy instead of running ctors etc. template <typename T> struct isPodLike { +#if __has_feature(is_trivially_copyable) + // If the compiler supports the is_trivially_copyable trait use it, as it + // matches the definition of isPodLike closely. + static const bool value = __is_trivially_copyable(T); +#else // If we don't know anything else, we can (at least) assume that all non-class // types are PODs. static const bool value = !is_class<T>::value; +#endif }; // std::pair's are pod-like if their elements are. @@ -202,4 +213,8 @@ struct conditional<false, T, F> { typedef F type; }; } +#ifdef LLVM_DEFINED_HAS_FEATURE +#undef __has_feature +#endif + #endif |