diff options
Diffstat (limited to 'include/llvm/Support')
64 files changed, 3106 insertions, 2595 deletions
diff --git a/include/llvm/Support/ARMBuildAttributes.h b/include/llvm/Support/ARMBuildAttributes.h index 96a8219bfb85..fc14cb2d0b0c 100644 --- a/include/llvm/Support/ARMBuildAttributes.h +++ b/include/llvm/Support/ARMBuildAttributes.h @@ -100,13 +100,13 @@ enum CPUArch { v5TEJ = 5, // e.g. ARM926EJ_S v6 = 6, // e.g. ARM1136J_S v6KZ = 7, // e.g. ARM1176JZ_S - v6T2 = 8, // e.g. ARM1156T2F_S - v6K = 9, // e.g. ARM1136J_S + v6T2 = 8, // e.g. ARM1156T2_S + v6K = 9, // e.g. ARM1176JZ_S v7 = 10, // e.g. Cortex A8, Cortex M3 v6_M = 11, // e.g. Cortex M1 v6S_M = 12, // v6_M with the System extensions v7E_M = 13, // v7_M with DSP extensions - v8 = 14 // v8, AArch32 + v8 = 14, // v8,v8.1a AArch32 }; enum CPUArchProfile { // (=7), uleb128 @@ -145,6 +145,7 @@ enum { AllowNeon = 1, // SIMDv1 was permitted AllowNeon2 = 2, // SIMDv2 was permitted (Half-precision FP, MAC operations) AllowNeonARMv8 = 3, // ARM v8-A SIMD was permitted + AllowNeonARMv8_1a = 4,// ARM v8.1-A SIMD was permitted (RDMA) // Tag_ABI_PCS_R9_use, (=14), uleb128 R9IsGPR = 0, // R9 used as v6 (just another callee-saved register) diff --git a/include/llvm/Support/AlignOf.h b/include/llvm/Support/AlignOf.h index 061d5acf2322..574b514aef39 100644 --- a/include/llvm/Support/AlignOf.h +++ b/include/llvm/Support/AlignOf.h @@ -22,6 +22,14 @@ namespace llvm { template <typename T> struct AlignmentCalcImpl { char x; +#if defined(_MSC_VER) +// Disables "structure was padded due to __declspec(align())" warnings that are +// generated by any class using AlignOf<T> with a manually specified alignment. +// Although the warning is disabled in the LLVM project we need this pragma +// as AlignOf.h is a published support header that's available for use +// out-of-tree, and we would like that to compile cleanly at /W4. +#pragma warning(suppress : 4324) +#endif T t; private: AlignmentCalcImpl() {} // Never instantiate. @@ -190,12 +198,12 @@ union SizerImpl { } // end namespace detail /// \brief This union template exposes a suitably aligned and sized character -/// array member which can hold elements of any of up to four types. +/// array member which can hold elements of any of up to ten types. /// /// These types may be arrays, structs, or any other types. The goal is to /// expose a char array buffer member which can be used as suitable storage for -/// a placement new of any of these types. Support for more than seven types can -/// be added at the cost of more boiler plate. +/// a placement new of any of these types. Support for more than ten types can +/// be added at the cost of more boilerplate. template <typename T1, typename T2 = char, typename T3 = char, typename T4 = char, typename T5 = char, typename T6 = char, typename T7 = char, diff --git a/include/llvm/Support/Allocator.h b/include/llvm/Support/Allocator.h index de317719714d..f9b5cf22f97d 100644 --- a/include/llvm/Support/Allocator.h +++ b/include/llvm/Support/Allocator.h @@ -148,7 +148,7 @@ public: : CurPtr(nullptr), End(nullptr), BytesAllocated(0), Allocator(std::forward<T &&>(Allocator)) {} - // Manually implement a move constructor as we must clear the old allocators + // Manually implement a move constructor as we must clear the old allocator's // slabs as a matter of correctness. BumpPtrAllocatorImpl(BumpPtrAllocatorImpl &&Old) : CurPtr(Old.CurPtr), End(Old.End), Slabs(std::move(Old.Slabs)), @@ -187,6 +187,9 @@ public: /// \brief Deallocate all but the current slab and reset the current pointer /// to the beginning of it, freeing all memory allocated so far. void Reset() { + DeallocateCustomSizedSlabs(); + CustomSizedSlabs.clear(); + if (Slabs.empty()) return; @@ -195,15 +198,14 @@ public: CurPtr = (char *)Slabs.front(); End = CurPtr + SlabSize; - // Deallocate all but the first slab, and all custome sized slabs. + // Deallocate all but the first slab, and deallocate all custom-sized slabs. DeallocateSlabs(std::next(Slabs.begin()), Slabs.end()); Slabs.erase(std::next(Slabs.begin()), Slabs.end()); - DeallocateCustomSizedSlabs(); - CustomSizedSlabs.clear(); } /// \brief Allocate space at the specified alignment. - LLVM_ATTRIBUTE_RETURNS_NONNULL void *Allocate(size_t Size, size_t Alignment) { + LLVM_ATTRIBUTE_RETURNS_NONNULL LLVM_ATTRIBUTE_RETURNS_NOALIAS void * + Allocate(size_t Size, size_t Alignment) { assert(Alignment > 0 && "0-byte alignnment is not allowed. Use 1 instead."); // Keep track of how many bytes we've allocated. @@ -319,14 +321,6 @@ private: for (; I != E; ++I) { size_t AllocatedSlabSize = computeSlabSize(std::distance(Slabs.begin(), I)); -#ifndef NDEBUG - // Poison the memory so stale pointers crash sooner. Note we must - // preserve the Size and NextPtr fields at the beginning. - if (AllocatedSlabSize != 0) { - sys::Memory::setRangeWritable(*I, AllocatedSlabSize); - memset(*I, 0xCD, AllocatedSlabSize); - } -#endif Allocator.Deallocate(*I, AllocatedSlabSize); } } @@ -336,12 +330,6 @@ private: for (auto &PtrAndSize : CustomSizedSlabs) { void *Ptr = PtrAndSize.first; size_t Size = PtrAndSize.second; -#ifndef NDEBUG - // Poison the memory so stale pointers crash sooner. Note we must - // preserve the Size and NextPtr fields at the beginning. - sys::Memory::setRangeWritable(Ptr, Size); - memset(Ptr, 0xCD, Size); -#endif Allocator.Deallocate(Ptr, Size); } } diff --git a/include/llvm/Support/BranchProbability.h b/include/llvm/Support/BranchProbability.h index 9aab6ace6e3f..a6429dd22a3b 100644 --- a/include/llvm/Support/BranchProbability.h +++ b/include/llvm/Support/BranchProbability.h @@ -31,7 +31,7 @@ class BranchProbability { public: BranchProbability(uint32_t n, uint32_t d) : N(n), D(d) { - assert(d > 0 && "Denomiator cannot be 0!"); + assert(d > 0 && "Denominator cannot be 0!"); assert(n <= d && "Probability cannot be bigger than 1!"); } diff --git a/include/llvm/Support/COFF.h b/include/llvm/Support/COFF.h index 150bce50d9ae..7f54822d503f 100644 --- a/include/llvm/Support/COFF.h +++ b/include/llvm/Support/COFF.h @@ -664,16 +664,16 @@ namespace COFF { } }; - enum CodeViewLineTableIdentifiers { - DEBUG_SECTION_MAGIC = 0x4, - DEBUG_SYMBOL_SUBSECTION = 0xF1, - DEBUG_LINE_TABLE_SUBSECTION = 0xF2, + enum CodeViewIdentifiers { + DEBUG_SECTION_MAGIC = 0x4, + DEBUG_SYMBOL_SUBSECTION = 0xF1, + DEBUG_LINE_TABLE_SUBSECTION = 0xF2, DEBUG_STRING_TABLE_SUBSECTION = 0xF3, - DEBUG_INDEX_SUBSECTION = 0xF4, + DEBUG_INDEX_SUBSECTION = 0xF4, // Symbol subsections are split into records of different types. DEBUG_SYMBOL_TYPE_PROC_START = 0x1147, - DEBUG_SYMBOL_TYPE_PROC_END = 0x114F + DEBUG_SYMBOL_TYPE_PROC_END = 0x114F }; inline bool isReservedSectionNumber(int32_t SectionNumber) { diff --git a/include/llvm/Support/COM.h b/include/llvm/Support/COM.h new file mode 100644 index 000000000000..a2d5a7a68ba9 --- /dev/null +++ b/include/llvm/Support/COM.h @@ -0,0 +1,36 @@ +//===- llvm/Support/COM.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// Provides a library for accessing COM functionality of the Host OS. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_COM_H +#define LLVM_SUPPORT_COM_H + +namespace llvm { +namespace sys { + +enum class COMThreadingMode { SingleThreaded, MultiThreaded }; + +class InitializeCOMRAII { +public: + explicit InitializeCOMRAII(COMThreadingMode Threading, + bool SpeedOverMemory = false); + ~InitializeCOMRAII(); + +private: + InitializeCOMRAII(const InitializeCOMRAII &) = delete; + void operator=(const InitializeCOMRAII &) = delete; +}; +} +} + +#endif diff --git a/include/llvm/Support/CommandLine.h b/include/llvm/Support/CommandLine.h index 1c06bf5f8c07..bd1d1cb6dc97 100644 --- a/include/llvm/Support/CommandLine.h +++ b/include/llvm/Support/CommandLine.h @@ -20,6 +20,7 @@ #ifndef LLVM_SUPPORT_COMMANDLINE_H #define LLVM_SUPPORT_COMMANDLINE_H +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/Twine.h" @@ -72,8 +73,17 @@ void AddExtraVersionPrinter(void (*func)()); // (Currently not perfect, but best-effort.) void PrintOptionValues(); -// MarkOptionsChanged - Internal helper function. -void MarkOptionsChanged(); +// Forward declaration - AddLiteralOption needs to be up here to make gcc happy. +class Option; + +/// \brief Adds a new option for parsing and provides the option it refers to. +/// +/// \param O pointer to the option +/// \param Name the string name for the option to handle during parsing +/// +/// Literal options are used by some parsers to register special option values. +/// This is how the PassNameParser registers pass names for opt. +void AddLiteralOption(Option &O, const char *Name); //===----------------------------------------------------------------------===// // Flags permitted to be passed to command line arguments @@ -191,13 +201,13 @@ class Option { unsigned Misc : 3; unsigned Position; // Position of last occurrence of the option unsigned AdditionalVals; // Greater than 0 for multi-valued option. - Option *NextRegistered; // Singly linked list of registered options. public: const char *ArgStr; // The argument string itself (ex: "help", "o") const char *HelpStr; // The descriptive text message for -help const char *ValueStr; // String describing what the value of this option is OptionCategory *Category; // The Category this option belongs to + bool FullyInitialized; // Has addArguemnt been called? inline enum NumOccurrencesFlag getNumOccurrencesFlag() const { return (enum NumOccurrencesFlag)Occurrences; @@ -221,7 +231,7 @@ public: //-------------------------------------------------------------------------=== // Accessor functions set by OptionModifiers // - void setArgStr(const char *S) { ArgStr = S; } + void setArgStr(const char *S); void setDescription(const char *S) { HelpStr = S; } void setValueStr(const char *S) { ValueStr = S; } void setNumOccurrencesFlag(enum NumOccurrencesFlag Val) { Occurrences = Val; } @@ -237,8 +247,8 @@ protected: enum OptionHidden Hidden) : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0), HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0), Position(0), - AdditionalVals(0), NextRegistered(nullptr), ArgStr(""), HelpStr(""), - ValueStr(""), Category(&GeneralCategory) {} + AdditionalVals(0), ArgStr(""), HelpStr(""), ValueStr(""), + Category(&GeneralCategory), FullyInitialized(false) {} inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; } @@ -253,8 +263,6 @@ public: /// For testing purposes only. void removeArgument(); - Option *getNextRegisteredOption() const { return NextRegistered; } - // Return the width of the option tag for printing... virtual size_t getOptionWidth() const = 0; @@ -344,9 +352,14 @@ struct cat { // Support value comparison outside the template. struct GenericOptionValue { - virtual ~GenericOptionValue() {} virtual bool compare(const GenericOptionValue &V) const = 0; +protected: + ~GenericOptionValue() = default; + GenericOptionValue() = default; + GenericOptionValue(const GenericOptionValue&) = default; + GenericOptionValue &operator=(const GenericOptionValue &) = default; + private: virtual void anchor(); }; @@ -372,6 +385,9 @@ struct OptionValueBase : public GenericOptionValue { bool compare(const GenericOptionValue & /*V*/) const override { return false; } + +protected: + ~OptionValueBase() = default; }; // Simple copy of the option value. @@ -379,6 +395,11 @@ template <class DataType> class OptionValueCopy : public GenericOptionValue { DataType Value; bool Valid; +protected: + ~OptionValueCopy() = default; + OptionValueCopy(const OptionValueCopy&) = default; + OptionValueCopy &operator=(const OptionValueCopy&) = default; + public: OptionValueCopy() : Valid(false) {} @@ -409,12 +430,19 @@ public: template <class DataType> struct OptionValueBase<DataType, false> : OptionValueCopy<DataType> { typedef DataType WrapperType; + +protected: + ~OptionValueBase() = default; + OptionValueBase() = default; + OptionValueBase(const OptionValueBase&) = default; + OptionValueBase &operator=(const OptionValueBase&) = default; }; // Top-level option class. template <class DataType> -struct OptionValue : OptionValueBase<DataType, std::is_class<DataType>::value> { - OptionValue() {} +struct OptionValue final + : OptionValueBase<DataType, std::is_class<DataType>::value> { + OptionValue() = default; OptionValue(const DataType &V) { this->setValue(V); } // Some options may take their value from a different data type. @@ -427,7 +455,8 @@ struct OptionValue : OptionValueBase<DataType, std::is_class<DataType>::value> { // Other safe-to-copy-by-value common option types. enum boolOrDefault { BOU_UNSET, BOU_TRUE, BOU_FALSE }; template <> -struct OptionValue<cl::boolOrDefault> : OptionValueCopy<cl::boolOrDefault> { +struct OptionValue<cl::boolOrDefault> final + : OptionValueCopy<cl::boolOrDefault> { typedef cl::boolOrDefault WrapperType; OptionValue() {} @@ -442,7 +471,8 @@ private: void anchor() override; }; -template <> struct OptionValue<std::string> : OptionValueCopy<std::string> { +template <> +struct OptionValue<std::string> final : OptionValueCopy<std::string> { typedef StringRef WrapperType; OptionValue() {} @@ -531,6 +561,8 @@ protected: }; public: + generic_parser_base(Option &O) : Owner(O) {} + virtual ~generic_parser_base() {} // Base class should have virtual-dtor // getNumOptions - Virtual function implemented by generic subclass to @@ -569,18 +601,13 @@ public: printGenericOptionDiff(O, V, Default, GlobalWidth); } - void initialize(Option &O) { - // All of the modifiers for the option have been processed by now, so the - // argstr field should be stable, copy it down now. - // - hasArgStr = O.hasArgStr(); - } + void initialize() {} void getExtraOptionNames(SmallVectorImpl<const char *> &OptionNames) { // If there has been no argstr specified, that means that we need to add an // argument for every possible option. This ensures that our options are // vectored to us. - if (!hasArgStr) + if (!Owner.hasArgStr()) for (unsigned i = 0, e = getNumOptions(); i != e; ++i) OptionNames.push_back(getOption(i)); } @@ -597,7 +624,7 @@ public: // // If this is the case, we cannot allow a value. // - if (hasArgStr) + if (Owner.hasArgStr()) return ValueRequired; else return ValueDisallowed; @@ -609,7 +636,7 @@ public: unsigned findOption(const char *Name); protected: - bool hasArgStr; + Option &Owner; }; // Default parser implementation - This implementation depends on having a @@ -629,6 +656,7 @@ protected: SmallVector<OptionInfo, 8> Values; public: + parser(Option &O) : generic_parser_base(O) {} typedef DataType parser_data_type; // Implement virtual functions needed by generic_parser_base @@ -646,7 +674,7 @@ public: // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, DataType &V) { StringRef ArgVal; - if (hasArgStr) + if (Owner.hasArgStr()) ArgVal = Arg; else ArgVal = ArgName; @@ -667,7 +695,7 @@ public: assert(findOption(Name) == Values.size() && "Option already exists!"); OptionInfo X(Name, static_cast<DataType>(V), HelpStr); Values.push_back(X); - MarkOptionsChanged(); + AddLiteralOption(Owner, Name); } /// removeLiteralOption - Remove the specified option. @@ -684,7 +712,8 @@ public: // class basic_parser_impl { // non-template implementation of basic_parser<t> public: - virtual ~basic_parser_impl() {} + basic_parser_impl(Option &O) {} + enum ValueExpected getValueExpectedFlagDefault() const { return ValueRequired; @@ -692,7 +721,7 @@ public: void getExtraOptionNames(SmallVectorImpl<const char *> &) {} - void initialize(Option &) {} + void initialize() {} // Return the width of the option tag for printing... size_t getOptionWidth(const Option &O) const; @@ -713,6 +742,7 @@ public: virtual void anchor(); protected: + ~basic_parser_impl() = default; // A helper for basic_parser::printOptionDiff. void printOptionName(const Option &O, size_t GlobalWidth) const; }; @@ -722,21 +752,26 @@ protected: // template <class DataType> class basic_parser : public basic_parser_impl { public: + basic_parser(Option &O) : basic_parser_impl(O) {} typedef DataType parser_data_type; typedef OptionValue<DataType> OptVal; + +protected: + // Workaround Clang PR22793 + ~basic_parser() {} }; //-------------------------------------------------- // parser<bool> // -template <> class parser<bool> : public basic_parser<bool> { - const char *ArgStr; - +template <> class parser<bool> final : public basic_parser<bool> { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, bool &Val); - template <class Opt> void initialize(Opt &O) { ArgStr = O.ArgStr; } + void initialize() {} enum ValueExpected getValueExpectedFlagDefault() const { return ValueOptional; @@ -756,8 +791,11 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<bool>); //-------------------------------------------------- // parser<boolOrDefault> -template <> class parser<boolOrDefault> : public basic_parser<boolOrDefault> { +template <> +class parser<boolOrDefault> final : public basic_parser<boolOrDefault> { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, boolOrDefault &Val); @@ -780,8 +818,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<boolOrDefault>); //-------------------------------------------------- // parser<int> // -template <> class parser<int> : public basic_parser<int> { +template <> class parser<int> final : public basic_parser<int> { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, int &Val); @@ -800,8 +840,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<int>); //-------------------------------------------------- // parser<unsigned> // -template <> class parser<unsigned> : public basic_parser<unsigned> { +template <> class parser<unsigned> final : public basic_parser<unsigned> { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned &Val); @@ -821,8 +863,11 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned>); // parser<unsigned long long> // template <> -class parser<unsigned long long> : public basic_parser<unsigned long long> { +class parser<unsigned long long> final + : public basic_parser<unsigned long long> { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, unsigned long long &Val); @@ -842,8 +887,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<unsigned long long>); //-------------------------------------------------- // parser<double> // -template <> class parser<double> : public basic_parser<double> { +template <> class parser<double> final : public basic_parser<double> { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, double &Val); @@ -862,8 +909,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<double>); //-------------------------------------------------- // parser<float> // -template <> class parser<float> : public basic_parser<float> { +template <> class parser<float> final : public basic_parser<float> { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &O, StringRef ArgName, StringRef Arg, float &Val); @@ -882,8 +931,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<float>); //-------------------------------------------------- // parser<std::string> // -template <> class parser<std::string> : public basic_parser<std::string> { +template <> class parser<std::string> final : public basic_parser<std::string> { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &, StringRef, StringRef Arg, std::string &Value) { Value = Arg.str(); @@ -905,8 +956,10 @@ EXTERN_TEMPLATE_INSTANTIATION(class basic_parser<std::string>); //-------------------------------------------------- // parser<char> // -template <> class parser<char> : public basic_parser<char> { +template <> class parser<char> final : public basic_parser<char> { public: + parser(Option &O) : basic_parser(O) {} + // parse - Return true on error. bool parse(Option &, StringRef, StringRef Arg, char &Value) { Value = Arg[0]; @@ -942,7 +995,7 @@ void printOptionDiff(const Option &O, const generic_parser_base &P, const DT &V, // This is instantiated for basic parsers when the parsed value has a different // type than the option value. e.g. HelpPrinter. template <class ParserDT, class ValDT> struct OptionDiffPrinter { - void print(const Option &O, const parser<ParserDT> P, const ValDT & /*V*/, + void print(const Option &O, const parser<ParserDT> &P, const ValDT & /*V*/, const OptionValue<ValDT> & /*Default*/, size_t GlobalWidth) { P.printOptionNoValue(O, GlobalWidth); } @@ -951,7 +1004,7 @@ template <class ParserDT, class ValDT> struct OptionDiffPrinter { // This is instantiated for basic parsers when the parsed value has the same // type as the option value. template <class DT> struct OptionDiffPrinter<DT, DT> { - void print(const Option &O, const parser<DT> P, const DT &V, + void print(const Option &O, const parser<DT> &P, const DT &V, const OptionValue<DT> &Default, size_t GlobalWidth) { P.printOptionDiff(O, V, Default, GlobalWidth); } @@ -1015,8 +1068,14 @@ template <> struct applicator<MiscFlags> { static void opt(MiscFlags MF, Option &O) { O.setMiscFlag(MF); } }; -// apply method - Apply a modifier to an option in a type safe way. -template <class Mod, class Opt> void apply(const Mod &M, Opt *O) { +// apply method - Apply modifiers to an option in a type safe way. +template <class Opt, class Mod, class... Mods> +void apply(Opt *O, const Mod &M, const Mods &... Ms) { + applicator<Mod>::opt(M, *O); + apply(O, Ms...); +} + +template <class Opt, class Mod> void apply(Opt *O, const Mod &M) { applicator<Mod>::opt(M, *O); } @@ -1166,9 +1225,13 @@ class opt : public Option, void done() { addArgument(); - Parser.initialize(*this); + Parser.initialize(); } + // Command line options should not be copyable + opt(const opt &) = delete; + opt &operator=(const opt &) = delete; + public: // setInitialValue - Used by the cl::init modifier... void setInitialValue(const DataType &V) { this->setValue(V, true); } @@ -1180,95 +1243,10 @@ public: return this->getValue(); } - // One option... - template <class M0t> - explicit opt(const M0t &M0) - : Option(Optional, NotHidden) { - apply(M0, this); - done(); - } - - // Two options... - template <class M0t, class M1t> - opt(const M0t &M0, const M1t &M1) - : Option(Optional, NotHidden) { - apply(M0, this); - apply(M1, this); - done(); - } - - // Three options... - template <class M0t, class M1t, class M2t> - opt(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(Optional, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - done(); - } - // Four options... - template <class M0t, class M1t, class M2t, class M3t> - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(Optional, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - done(); - } - // Five options... - template <class M0t, class M1t, class M2t, class M3t, class M4t> - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4) - : Option(Optional, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - done(); - } - // Six options... - template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t> - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4, - const M5t &M5) - : Option(Optional, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - apply(M5, this); - done(); - } - // Seven options... - template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t, - class M6t> - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4, - const M5t &M5, const M6t &M6) - : Option(Optional, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - apply(M5, this); - apply(M6, this); - done(); - } - // Eight options... - template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t, - class M6t, class M7t> - opt(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, const M4t &M4, - const M5t &M5, const M6t &M6, const M7t &M7) - : Option(Optional, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - apply(M5, this); - apply(M6, this); - apply(M7, this); + template <class... Mods> + explicit opt(const Mods &... Ms) + : Option(Optional, NotHidden), Parser(*this) { + apply(this, Ms...); done(); } }; @@ -1361,9 +1339,13 @@ class list : public Option, public list_storage<DataType, Storage> { void done() { addArgument(); - Parser.initialize(*this); + Parser.initialize(); } + // Command line options should not be copyable + list(const list &) = delete; + list &operator=(const list &) = delete; + public: ParserClass &getParser() { return Parser; } @@ -1374,94 +1356,10 @@ public: void setNumAdditionalVals(unsigned n) { Option::setNumAdditionalVals(n); } - // One option... - template <class M0t> - explicit list(const M0t &M0) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - done(); - } - // Two options... - template <class M0t, class M1t> - list(const M0t &M0, const M1t &M1) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - done(); - } - // Three options... - template <class M0t, class M1t, class M2t> - list(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - done(); - } - // Four options... - template <class M0t, class M1t, class M2t, class M3t> - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - done(); - } - // Five options... - template <class M0t, class M1t, class M2t, class M3t, class M4t> - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - done(); - } - // Six options... - template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t> - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - apply(M5, this); - done(); - } - // Seven options... - template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t, - class M6t> - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - apply(M5, this); - apply(M6, this); - done(); - } - // Eight options... - template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t, - class M6t, class M7t> - list(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, const M7t &M7) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - apply(M5, this); - apply(M6, this); - apply(M7, this); + template <class... Mods> + explicit list(const Mods &... Ms) + : Option(ZeroOrMore, NotHidden), Parser(*this) { + apply(this, Ms...); done(); } }; @@ -1581,9 +1479,13 @@ class bits : public Option, public bits_storage<DataType, Storage> { void done() { addArgument(); - Parser.initialize(*this); + Parser.initialize(); } + // Command line options should not be copyable + bits(const bits &) = delete; + bits &operator=(const bits &) = delete; + public: ParserClass &getParser() { return Parser; } @@ -1592,94 +1494,10 @@ public: return Positions[optnum]; } - // One option... - template <class M0t> - explicit bits(const M0t &M0) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - done(); - } - // Two options... - template <class M0t, class M1t> - bits(const M0t &M0, const M1t &M1) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - done(); - } - // Three options... - template <class M0t, class M1t, class M2t> - bits(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - done(); - } - // Four options... - template <class M0t, class M1t, class M2t, class M3t> - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - done(); - } - // Five options... - template <class M0t, class M1t, class M2t, class M3t, class M4t> - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - done(); - } - // Six options... - template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t> - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - apply(M5, this); - done(); - } - // Seven options... - template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t, - class M6t> - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - apply(M5, this); - apply(M6, this); - done(); - } - // Eight options... - template <class M0t, class M1t, class M2t, class M3t, class M4t, class M5t, - class M6t, class M7t> - bits(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3, - const M4t &M4, const M5t &M5, const M6t &M6, const M7t &M7) - : Option(ZeroOrMore, NotHidden) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); - apply(M4, this); - apply(M5, this); - apply(M6, this); - apply(M7, this); + template <class... Mods> + explicit bits(const Mods &... Ms) + : Option(ZeroOrMore, NotHidden), Parser(*this) { + apply(this, Ms...); done(); } }; @@ -1718,6 +1536,10 @@ class alias : public Option { addArgument(); } + // Command line options should not be copyable + alias(const alias &) = delete; + alias &operator=(const alias &) = delete; + public: void setAliasFor(Option &O) { if (AliasFor) @@ -1725,38 +1547,10 @@ public: AliasFor = &O; } - // One option... - template <class M0t> - explicit alias(const M0t &M0) - : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); - done(); - } - // Two options... - template <class M0t, class M1t> - alias(const M0t &M0, const M1t &M1) - : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); - apply(M1, this); - done(); - } - // Three options... - template <class M0t, class M1t, class M2t> - alias(const M0t &M0, const M1t &M1, const M2t &M2) - : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - done(); - } - // Four options... - template <class M0t, class M1t, class M2t, class M3t> - alias(const M0t &M0, const M1t &M1, const M2t &M2, const M3t &M3) + template <class... Mods> + explicit alias(const Mods &... Ms) : Option(Optional, Hidden), AliasFor(nullptr) { - apply(M0, this); - apply(M1, this); - apply(M2, this); - apply(M3, this); + apply(this, Ms...); done(); } }; @@ -1795,9 +1589,7 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false); /// \brief Use this to get a StringMap to all registered named options /// (e.g. -help). Note \p Map Should be an empty StringMap. /// -/// \param [out] Map will be filled with mappings where the key is the -/// Option argument string (e.g. "help") and value is the corresponding -/// Option*. +/// \return A reference to the StringMap used by the cl APIs to parse options. /// /// Access to unnamed arguments (i.e. positional) are not provided because /// it is expected that the client already has access to these. @@ -1805,8 +1597,7 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false); /// Typical usage: /// \code /// main(int argc,char* argv[]) { -/// StringMap<llvm::cl::Option*> opts; -/// llvm::cl::getRegisteredOptions(opts); +/// StringMap<llvm::cl::Option*> &opts = llvm::cl::getRegisteredOptions(); /// assert(opts.count("help") == 1) /// opts["help"]->setDescription("Show alphabetical help information") /// // More code @@ -1818,7 +1609,11 @@ void PrintHelpMessage(bool Hidden = false, bool Categorized = false); /// This interface is useful for modifying options in libraries that are out of /// the control of the client. The options should be modified before calling /// llvm::cl::ParseCommandLineOptions(). -void getRegisteredOptions(StringMap<Option *> &Map); +/// +/// Hopefully this API can be depricated soon. Any situation where options need +/// to be modified by tools or libraries should be handled by sane APIs rather +/// than just handing around a global list. +StringMap<Option *> &getRegisteredOptions(); //===----------------------------------------------------------------------===// // Standalone command line processing utilities. @@ -1889,6 +1684,24 @@ bool ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer, SmallVectorImpl<const char *> &Argv, bool MarkEOLs = false); +/// \brief Mark all options not part of this category as cl::ReallyHidden. +/// +/// \param Category the category of options to keep displaying +/// +/// Some tools (like clang-format) like to be able to hide all options that are +/// not specific to the tool. This function allows a tool to specify a single +/// option category to display in the -help output. +void HideUnrelatedOptions(cl::OptionCategory &Category); + +/// \brief Mark all options not part of the categories as cl::ReallyHidden. +/// +/// \param Categories the categories of options to keep displaying. +/// +/// Some tools (like clang-format) like to be able to hide all options that are +/// not specific to the tool. This function allows a tool to specify a single +/// option category to display in the -help output. +void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories); + } // End namespace cl } // End namespace llvm diff --git a/include/llvm/Support/Compiler.h b/include/llvm/Support/Compiler.h index d008fec89d64..c81fbaff9dba 100644 --- a/include/llvm/Support/Compiler.h +++ b/include/llvm/Support/Compiler.h @@ -52,14 +52,14 @@ /// \macro LLVM_MSC_PREREQ /// \brief Is the compiler MSVC of at least the specified version? /// The common \param version values to check for are: -/// * 1700: Microsoft Visual Studio 2012 / 11.0 /// * 1800: Microsoft Visual Studio 2013 / 12.0 +/// * 1900: Microsoft Visual Studio 2015 / 14.0 #ifdef _MSC_VER #define LLVM_MSC_PREREQ(version) (_MSC_VER >= (version)) -// We require at least MSVC 2012. -#if !LLVM_MSC_PREREQ(1700) -#error LLVM requires at least MSVC 2012. +// We require at least MSVC 2013. +#if !LLVM_MSC_PREREQ(1800) +#error LLVM requires at least MSVC 2013. #endif #else @@ -72,54 +72,26 @@ #define LLVM_NOEXCEPT #endif -/// \brief Does the compiler support r-value reference *this? +/// \brief Does the compiler support ref-qualifiers for *this? /// -/// Sadly, this is separate from just r-value reference support because GCC -/// implemented this later than everything else. +/// Sadly, this is separate from just rvalue reference support because GCC +/// and MSVC implemented this later than everything else. #if __has_feature(cxx_rvalue_references) || LLVM_GNUC_PREREQ(4, 8, 1) #define LLVM_HAS_RVALUE_REFERENCE_THIS 1 #else #define LLVM_HAS_RVALUE_REFERENCE_THIS 0 #endif -/// \macro LLVM_HAS_VARIADIC_TEMPLATES -/// \brief Does this compiler support variadic templates. +/// Expands to '&' if ref-qualifiers for *this are supported. /// -/// Implies LLVM_HAS_RVALUE_REFERENCES and the existence of std::forward. -#if __has_feature(cxx_variadic_templates) || LLVM_MSC_PREREQ(1800) -# define LLVM_HAS_VARIADIC_TEMPLATES 1 -#else -# define LLVM_HAS_VARIADIC_TEMPLATES 0 -#endif - -/// Expands to '&' if r-value references are supported. -/// -/// This can be used to provide l-value/r-value overrides of member functions. -/// The r-value override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS +/// This can be used to provide lvalue/rvalue overrides of member functions. +/// The rvalue override should be guarded by LLVM_HAS_RVALUE_REFERENCE_THIS #if LLVM_HAS_RVALUE_REFERENCE_THIS #define LLVM_LVALUE_FUNCTION & #else #define LLVM_LVALUE_FUNCTION #endif -/// LLVM_DELETED_FUNCTION - Expands to = delete if the compiler supports it. -/// Use to mark functions as uncallable. Member functions with this should -/// be declared private so that some behavior is kept in C++03 mode. -/// -/// class DontCopy { -/// private: -/// DontCopy(const DontCopy&) LLVM_DELETED_FUNCTION; -/// DontCopy &operator =(const DontCopy&) LLVM_DELETED_FUNCTION; -/// public: -/// ... -/// }; -#if __has_feature(cxx_deleted_functions) || \ - defined(__GXX_EXPERIMENTAL_CXX0X__) || LLVM_MSC_PREREQ(1800) -#define LLVM_DELETED_FUNCTION = delete -#else -#define LLVM_DELETED_FUNCTION -#endif - #if __has_feature(cxx_constexpr) || defined(__GXX_EXPERIMENTAL_CXX0X__) # define LLVM_CONSTEXPR constexpr #else @@ -251,6 +223,16 @@ #define LLVM_ATTRIBUTE_RETURNS_NONNULL #endif +/// \macro LLVM_ATTRIBUTE_RETURNS_NOALIAS Used to mark a function as returning a +/// pointer that does not alias any other valid pointer. +#ifdef __GNUC__ +#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __attribute__((__malloc__)) +#elif defined(_MSC_VER) +#define LLVM_ATTRIBUTE_RETURNS_NOALIAS __declspec(restrict) +#else +#define LLVM_ATTRIBUTE_RETURNS_NOALIAS +#endif + /// LLVM_EXTENSION - Support compilers where we have a keyword to suppress /// pedantic diagnostics. #ifdef __GNUC__ @@ -287,6 +269,12 @@ /// which causes the program to exit abnormally. #if __has_builtin(__builtin_trap) || LLVM_GNUC_PREREQ(4, 3, 0) # define LLVM_BUILTIN_TRAP __builtin_trap() +#elif defined(_MSC_VER) +// The __debugbreak intrinsic is supported by MSVC, does not require forward +// declarations involving platform-specific typedefs (unlike RaiseException), +// results in a call to vectored exception handlers, and encodes to a short +// instruction that still causes the trapping behavior we want. +# define LLVM_BUILTIN_TRAP __debugbreak() #else # define LLVM_BUILTIN_TRAP *(volatile int*)0x11 = 0 #endif @@ -303,6 +291,37 @@ # define LLVM_ASSUME_ALIGNED(p, a) (p) #endif +/// \macro LLVM_ALIGNAS +/// \brief Used to specify a minimum alignment for a structure or variable. The +/// alignment must be a constant integer. Use LLVM_PTR_SIZE to compute +/// alignments in terms of the size of a pointer. +/// +/// Note that __declspec(align) has special quirks, it's not legal to pass a +/// structure with __declspec(align) as a formal parameter. +#ifdef _MSC_VER +# define LLVM_ALIGNAS(x) __declspec(align(x)) +#elif __GNUC__ && !__has_feature(cxx_alignas) && !LLVM_GNUC_PREREQ(4, 8, 0) +# define LLVM_ALIGNAS(x) __attribute__((aligned(x))) +#else +# define LLVM_ALIGNAS(x) alignas(x) +#endif + +/// \macro LLVM_PTR_SIZE +/// \brief A constant integer equivalent to the value of sizeof(void*). +/// Generally used in combination with LLVM_ALIGNAS or when doing computation in +/// the preprocessor. +#ifdef __SIZEOF_POINTER__ +# define LLVM_PTR_SIZE __SIZEOF_POINTER__ +#elif defined(_WIN64) +# define LLVM_PTR_SIZE 8 +#elif defined(_WIN32) +# define LLVM_PTR_SIZE 4 +#elif defined(_MSC_VER) +# error "could not determine LLVM_PTR_SIZE as a constant int for MSVC" +#else +# define LLVM_PTR_SIZE sizeof(void *) +#endif + /// \macro LLVM_FUNCTION_NAME /// \brief Expands to __func__ on compilers which support it. Otherwise, /// expands to a compiler-dependent replacement. @@ -344,26 +363,6 @@ # define LLVM_IS_UNALIGNED_ACCESS_FAST 0 #endif -/// \macro LLVM_EXPLICIT -/// \brief Expands to explicit on compilers which support explicit conversion -/// operators. Otherwise expands to nothing. -#if __has_feature(cxx_explicit_conversions) || \ - defined(__GXX_EXPERIMENTAL_CXX0X__) || LLVM_MSC_PREREQ(1800) -#define LLVM_EXPLICIT explicit -#else -#define LLVM_EXPLICIT -#endif - -/// \brief Does the compiler support generalized initializers (using braced -/// lists and std::initializer_list). While clang may claim it supports general -/// initializers, if we're using MSVC's headers, we might not have a usable -/// std::initializer list type from the STL. Disable this for now. -#if __has_feature(cxx_generalized_initializers) && !defined(_MSC_VER) -#define LLVM_HAS_INITIALIZER_LISTS 1 -#else -#define LLVM_HAS_INITIALIZER_LISTS 0 -#endif - /// \brief Mark debug helper function definitions like dump() that should not be /// stripped from debug builds. // FIXME: Move this to a private config.h as it's not usable in public headers. @@ -373,4 +372,33 @@ #define LLVM_DUMP_METHOD LLVM_ATTRIBUTE_NOINLINE #endif +/// \macro LLVM_THREAD_LOCAL +/// \brief A thread-local storage specifier which can be used with globals, +/// extern globals, and static globals. +/// +/// This is essentially an extremely restricted analog to C++11's thread_local +/// support, and uses that when available. However, it falls back on +/// platform-specific or vendor-provided extensions when necessary. These +/// extensions don't support many of the C++11 thread_local's features. You +/// should only use this for PODs that you can statically initialize to +/// some constant value. In almost all circumstances this is most appropriate +/// for use with a pointer, integer, or small aggregation of pointers and +/// integers. +#if LLVM_ENABLE_THREADS +#if __has_feature(cxx_thread_local) +#define LLVM_THREAD_LOCAL thread_local +#elif defined(_MSC_VER) +// MSVC supports this with a __declspec. +#define LLVM_THREAD_LOCAL __declspec(thread) +#else +// Clang, GCC, and other compatible compilers used __thread prior to C++11 and +// we only need the restricted functionality that provides. +#define LLVM_THREAD_LOCAL __thread +#endif +#else // !LLVM_ENABLE_THREADS +// If threading is disabled entirely, this compiles to nothing and you get +// a normal global variable. +#define LLVM_THREAD_LOCAL +#endif + #endif diff --git a/include/llvm/Support/Compression.h b/include/llvm/Support/Compression.h index 88727fa3fcfc..28274d67aad2 100644 --- a/include/llvm/Support/Compression.h +++ b/include/llvm/Support/Compression.h @@ -14,12 +14,10 @@ #ifndef LLVM_SUPPORT_COMPRESSION_H #define LLVM_SUPPORT_COMPRESSION_H -#include "llvm/ADT/SmallVector.h" #include "llvm/Support/DataTypes.h" -#include <memory> namespace llvm { - +template <typename T> class SmallVectorImpl; class StringRef; namespace zlib { diff --git a/include/llvm/Support/ConvertUTF.h b/include/llvm/Support/ConvertUTF.h index a184d0df2132..38952ec99e61 100644 --- a/include/llvm/Support/ConvertUTF.h +++ b/include/llvm/Support/ConvertUTF.h @@ -251,6 +251,14 @@ bool hasUTF16ByteOrderMark(ArrayRef<char> SrcBytes); */ bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out); +/** + * Converts a UTF-8 string into a UTF-16 string with native endianness. + * + * \returns true on success + */ +bool convertUTF8ToUTF16String(StringRef SrcUTF8, + SmallVectorImpl<UTF16> &DstUTF16); + } /* end namespace llvm */ #endif diff --git a/include/llvm/Support/CrashRecoveryContext.h b/include/llvm/Support/CrashRecoveryContext.h index 1f3965c8ade4..c08c3c1f0d21 100644 --- a/include/llvm/Support/CrashRecoveryContext.h +++ b/include/llvm/Support/CrashRecoveryContext.h @@ -14,8 +14,6 @@ #include <string> namespace llvm { -class StringRef; - class CrashRecoveryContextCleanup; /// \brief Crash recovery helper object. diff --git a/include/llvm/Support/DataExtractor.h b/include/llvm/Support/DataExtractor.h index 48235d4145bd..3ffa9bc90dd1 100644 --- a/include/llvm/Support/DataExtractor.h +++ b/include/llvm/Support/DataExtractor.h @@ -10,7 +10,6 @@ #ifndef LLVM_SUPPORT_DATAEXTRACTOR_H #define LLVM_SUPPORT_DATAEXTRACTOR_H -#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" diff --git a/include/llvm/Support/Debug.h b/include/llvm/Support/Debug.h index e93e6ca34498..fff4f986a6c0 100644 --- a/include/llvm/Support/Debug.h +++ b/include/llvm/Support/Debug.h @@ -28,9 +28,8 @@ #ifndef LLVM_SUPPORT_DEBUG_H #define LLVM_SUPPORT_DEBUG_H -#include "llvm/Support/raw_ostream.h" - namespace llvm { +class raw_ostream; #ifndef NDEBUG /// DebugFlag - This boolean is set to true if the '-debug' command line option diff --git a/include/llvm/Support/Dwarf.def b/include/llvm/Support/Dwarf.def new file mode 100644 index 000000000000..4b923b897e6f --- /dev/null +++ b/include/llvm/Support/Dwarf.def @@ -0,0 +1,350 @@ +//===- llvm/Support/Dwarf.def - Dwarf definitions ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Macros for running through Dwarf enumerators. +// +//===----------------------------------------------------------------------===// + +// TODO: Add other DW-based macros. +#if !(defined HANDLE_DW_TAG || defined HANDLE_DW_OP || \ + defined HANDLE_DW_LANG || defined HANDLE_DW_ATE || \ + defined HANDLE_DW_VIRTUALITY) +#error "Missing macro definition of HANDLE_DW*" +#endif + +#ifndef HANDLE_DW_TAG +#define HANDLE_DW_TAG(ID, NAME) +#endif + +#ifndef HANDLE_DW_OP +#define HANDLE_DW_OP(ID, NAME) +#endif + +#ifndef HANDLE_DW_LANG +#define HANDLE_DW_LANG(ID, NAME) +#endif + +#ifndef HANDLE_DW_ATE +#define HANDLE_DW_ATE(ID, NAME) +#endif + +#ifndef HANDLE_DW_VIRTUALITY +#define HANDLE_DW_VIRTUALITY(ID, NAME) +#endif + +HANDLE_DW_TAG(0x0001, array_type) +HANDLE_DW_TAG(0x0002, class_type) +HANDLE_DW_TAG(0x0003, entry_point) +HANDLE_DW_TAG(0x0004, enumeration_type) +HANDLE_DW_TAG(0x0005, formal_parameter) +HANDLE_DW_TAG(0x0008, imported_declaration) +HANDLE_DW_TAG(0x000a, label) +HANDLE_DW_TAG(0x000b, lexical_block) +HANDLE_DW_TAG(0x000d, member) +HANDLE_DW_TAG(0x000f, pointer_type) +HANDLE_DW_TAG(0x0010, reference_type) +HANDLE_DW_TAG(0x0011, compile_unit) +HANDLE_DW_TAG(0x0012, string_type) +HANDLE_DW_TAG(0x0013, structure_type) +HANDLE_DW_TAG(0x0015, subroutine_type) +HANDLE_DW_TAG(0x0016, typedef) +HANDLE_DW_TAG(0x0017, union_type) +HANDLE_DW_TAG(0x0018, unspecified_parameters) +HANDLE_DW_TAG(0x0019, variant) +HANDLE_DW_TAG(0x001a, common_block) +HANDLE_DW_TAG(0x001b, common_inclusion) +HANDLE_DW_TAG(0x001c, inheritance) +HANDLE_DW_TAG(0x001d, inlined_subroutine) +HANDLE_DW_TAG(0x001e, module) +HANDLE_DW_TAG(0x001f, ptr_to_member_type) +HANDLE_DW_TAG(0x0020, set_type) +HANDLE_DW_TAG(0x0021, subrange_type) +HANDLE_DW_TAG(0x0022, with_stmt) +HANDLE_DW_TAG(0x0023, access_declaration) +HANDLE_DW_TAG(0x0024, base_type) +HANDLE_DW_TAG(0x0025, catch_block) +HANDLE_DW_TAG(0x0026, const_type) +HANDLE_DW_TAG(0x0027, constant) +HANDLE_DW_TAG(0x0028, enumerator) +HANDLE_DW_TAG(0x0029, file_type) +HANDLE_DW_TAG(0x002a, friend) +HANDLE_DW_TAG(0x002b, namelist) +HANDLE_DW_TAG(0x002c, namelist_item) +HANDLE_DW_TAG(0x002d, packed_type) +HANDLE_DW_TAG(0x002e, subprogram) +HANDLE_DW_TAG(0x002f, template_type_parameter) +HANDLE_DW_TAG(0x0030, template_value_parameter) +HANDLE_DW_TAG(0x0031, thrown_type) +HANDLE_DW_TAG(0x0032, try_block) +HANDLE_DW_TAG(0x0033, variant_part) +HANDLE_DW_TAG(0x0034, variable) +HANDLE_DW_TAG(0x0035, volatile_type) +HANDLE_DW_TAG(0x0036, dwarf_procedure) +HANDLE_DW_TAG(0x0037, restrict_type) +HANDLE_DW_TAG(0x0038, interface_type) +HANDLE_DW_TAG(0x0039, namespace) +HANDLE_DW_TAG(0x003a, imported_module) +HANDLE_DW_TAG(0x003b, unspecified_type) +HANDLE_DW_TAG(0x003c, partial_unit) +HANDLE_DW_TAG(0x003d, imported_unit) +HANDLE_DW_TAG(0x003f, condition) +HANDLE_DW_TAG(0x0040, shared_type) +HANDLE_DW_TAG(0x0041, type_unit) +HANDLE_DW_TAG(0x0042, rvalue_reference_type) +HANDLE_DW_TAG(0x0043, template_alias) + +// Mock tags we use as discriminators. +HANDLE_DW_TAG(0x0100, auto_variable) // Tag for local (auto) variables. +HANDLE_DW_TAG(0x0101, arg_variable) // Tag for argument variables. + +// New in DWARF v5. +HANDLE_DW_TAG(0x0044, coarray_type) +HANDLE_DW_TAG(0x0045, generic_subrange) +HANDLE_DW_TAG(0x0046, dynamic_type) + +// User-defined tags. +HANDLE_DW_TAG(0x4081, MIPS_loop) +HANDLE_DW_TAG(0x4101, format_label) +HANDLE_DW_TAG(0x4102, function_template) +HANDLE_DW_TAG(0x4103, class_template) +HANDLE_DW_TAG(0x4106, GNU_template_template_param) +HANDLE_DW_TAG(0x4107, GNU_template_parameter_pack) +HANDLE_DW_TAG(0x4108, GNU_formal_parameter_pack) +HANDLE_DW_TAG(0x4200, APPLE_property) + +HANDLE_DW_OP(0x03, addr) +HANDLE_DW_OP(0x06, deref) +HANDLE_DW_OP(0x08, const1u) +HANDLE_DW_OP(0x09, const1s) +HANDLE_DW_OP(0x0a, const2u) +HANDLE_DW_OP(0x0b, const2s) +HANDLE_DW_OP(0x0c, const4u) +HANDLE_DW_OP(0x0d, const4s) +HANDLE_DW_OP(0x0e, const8u) +HANDLE_DW_OP(0x0f, const8s) +HANDLE_DW_OP(0x10, constu) +HANDLE_DW_OP(0x11, consts) +HANDLE_DW_OP(0x12, dup) +HANDLE_DW_OP(0x13, drop) +HANDLE_DW_OP(0x14, over) +HANDLE_DW_OP(0x15, pick) +HANDLE_DW_OP(0x16, swap) +HANDLE_DW_OP(0x17, rot) +HANDLE_DW_OP(0x18, xderef) +HANDLE_DW_OP(0x19, abs) +HANDLE_DW_OP(0x1a, and) +HANDLE_DW_OP(0x1b, div) +HANDLE_DW_OP(0x1c, minus) +HANDLE_DW_OP(0x1d, mod) +HANDLE_DW_OP(0x1e, mul) +HANDLE_DW_OP(0x1f, neg) +HANDLE_DW_OP(0x20, not) +HANDLE_DW_OP(0x21, or ) +HANDLE_DW_OP(0x22, plus) +HANDLE_DW_OP(0x23, plus_uconst) +HANDLE_DW_OP(0x24, shl) +HANDLE_DW_OP(0x25, shr) +HANDLE_DW_OP(0x26, shra) +HANDLE_DW_OP(0x27, xor) +HANDLE_DW_OP(0x2f, skip) +HANDLE_DW_OP(0x28, bra) +HANDLE_DW_OP(0x29, eq) +HANDLE_DW_OP(0x2a, ge) +HANDLE_DW_OP(0x2b, gt) +HANDLE_DW_OP(0x2c, le) +HANDLE_DW_OP(0x2d, lt) +HANDLE_DW_OP(0x2e, ne) +HANDLE_DW_OP(0x30, lit0) +HANDLE_DW_OP(0x31, lit1) +HANDLE_DW_OP(0x32, lit2) +HANDLE_DW_OP(0x33, lit3) +HANDLE_DW_OP(0x34, lit4) +HANDLE_DW_OP(0x35, lit5) +HANDLE_DW_OP(0x36, lit6) +HANDLE_DW_OP(0x37, lit7) +HANDLE_DW_OP(0x38, lit8) +HANDLE_DW_OP(0x39, lit9) +HANDLE_DW_OP(0x3a, lit10) +HANDLE_DW_OP(0x3b, lit11) +HANDLE_DW_OP(0x3c, lit12) +HANDLE_DW_OP(0x3d, lit13) +HANDLE_DW_OP(0x3e, lit14) +HANDLE_DW_OP(0x3f, lit15) +HANDLE_DW_OP(0x40, lit16) +HANDLE_DW_OP(0x41, lit17) +HANDLE_DW_OP(0x42, lit18) +HANDLE_DW_OP(0x43, lit19) +HANDLE_DW_OP(0x44, lit20) +HANDLE_DW_OP(0x45, lit21) +HANDLE_DW_OP(0x46, lit22) +HANDLE_DW_OP(0x47, lit23) +HANDLE_DW_OP(0x48, lit24) +HANDLE_DW_OP(0x49, lit25) +HANDLE_DW_OP(0x4a, lit26) +HANDLE_DW_OP(0x4b, lit27) +HANDLE_DW_OP(0x4c, lit28) +HANDLE_DW_OP(0x4d, lit29) +HANDLE_DW_OP(0x4e, lit30) +HANDLE_DW_OP(0x4f, lit31) +HANDLE_DW_OP(0x50, reg0) +HANDLE_DW_OP(0x51, reg1) +HANDLE_DW_OP(0x52, reg2) +HANDLE_DW_OP(0x53, reg3) +HANDLE_DW_OP(0x54, reg4) +HANDLE_DW_OP(0x55, reg5) +HANDLE_DW_OP(0x56, reg6) +HANDLE_DW_OP(0x57, reg7) +HANDLE_DW_OP(0x58, reg8) +HANDLE_DW_OP(0x59, reg9) +HANDLE_DW_OP(0x5a, reg10) +HANDLE_DW_OP(0x5b, reg11) +HANDLE_DW_OP(0x5c, reg12) +HANDLE_DW_OP(0x5d, reg13) +HANDLE_DW_OP(0x5e, reg14) +HANDLE_DW_OP(0x5f, reg15) +HANDLE_DW_OP(0x60, reg16) +HANDLE_DW_OP(0x61, reg17) +HANDLE_DW_OP(0x62, reg18) +HANDLE_DW_OP(0x63, reg19) +HANDLE_DW_OP(0x64, reg20) +HANDLE_DW_OP(0x65, reg21) +HANDLE_DW_OP(0x66, reg22) +HANDLE_DW_OP(0x67, reg23) +HANDLE_DW_OP(0x68, reg24) +HANDLE_DW_OP(0x69, reg25) +HANDLE_DW_OP(0x6a, reg26) +HANDLE_DW_OP(0x6b, reg27) +HANDLE_DW_OP(0x6c, reg28) +HANDLE_DW_OP(0x6d, reg29) +HANDLE_DW_OP(0x6e, reg30) +HANDLE_DW_OP(0x6f, reg31) +HANDLE_DW_OP(0x70, breg0) +HANDLE_DW_OP(0x71, breg1) +HANDLE_DW_OP(0x72, breg2) +HANDLE_DW_OP(0x73, breg3) +HANDLE_DW_OP(0x74, breg4) +HANDLE_DW_OP(0x75, breg5) +HANDLE_DW_OP(0x76, breg6) +HANDLE_DW_OP(0x77, breg7) +HANDLE_DW_OP(0x78, breg8) +HANDLE_DW_OP(0x79, breg9) +HANDLE_DW_OP(0x7a, breg10) +HANDLE_DW_OP(0x7b, breg11) +HANDLE_DW_OP(0x7c, breg12) +HANDLE_DW_OP(0x7d, breg13) +HANDLE_DW_OP(0x7e, breg14) +HANDLE_DW_OP(0x7f, breg15) +HANDLE_DW_OP(0x80, breg16) +HANDLE_DW_OP(0x81, breg17) +HANDLE_DW_OP(0x82, breg18) +HANDLE_DW_OP(0x83, breg19) +HANDLE_DW_OP(0x84, breg20) +HANDLE_DW_OP(0x85, breg21) +HANDLE_DW_OP(0x86, breg22) +HANDLE_DW_OP(0x87, breg23) +HANDLE_DW_OP(0x88, breg24) +HANDLE_DW_OP(0x89, breg25) +HANDLE_DW_OP(0x8a, breg26) +HANDLE_DW_OP(0x8b, breg27) +HANDLE_DW_OP(0x8c, breg28) +HANDLE_DW_OP(0x8d, breg29) +HANDLE_DW_OP(0x8e, breg30) +HANDLE_DW_OP(0x8f, breg31) +HANDLE_DW_OP(0x90, regx) +HANDLE_DW_OP(0x91, fbreg) +HANDLE_DW_OP(0x92, bregx) +HANDLE_DW_OP(0x93, piece) +HANDLE_DW_OP(0x94, deref_size) +HANDLE_DW_OP(0x95, xderef_size) +HANDLE_DW_OP(0x96, nop) +HANDLE_DW_OP(0x97, push_object_address) +HANDLE_DW_OP(0x98, call2) +HANDLE_DW_OP(0x99, call4) +HANDLE_DW_OP(0x9a, call_ref) +HANDLE_DW_OP(0x9b, form_tls_address) +HANDLE_DW_OP(0x9c, call_frame_cfa) +HANDLE_DW_OP(0x9d, bit_piece) +HANDLE_DW_OP(0x9e, implicit_value) +HANDLE_DW_OP(0x9f, stack_value) + +// Extensions for GNU-style thread-local storage. +HANDLE_DW_OP(0xe0, GNU_push_tls_address) + +// Extensions for Fission proposal. +HANDLE_DW_OP(0xfb, GNU_addr_index) +HANDLE_DW_OP(0xfc, GNU_const_index) + +// DWARF languages. +HANDLE_DW_LANG(0x0001, C89) +HANDLE_DW_LANG(0x0002, C) +HANDLE_DW_LANG(0x0003, Ada83) +HANDLE_DW_LANG(0x0004, C_plus_plus) +HANDLE_DW_LANG(0x0005, Cobol74) +HANDLE_DW_LANG(0x0006, Cobol85) +HANDLE_DW_LANG(0x0007, Fortran77) +HANDLE_DW_LANG(0x0008, Fortran90) +HANDLE_DW_LANG(0x0009, Pascal83) +HANDLE_DW_LANG(0x000a, Modula2) +HANDLE_DW_LANG(0x000b, Java) +HANDLE_DW_LANG(0x000c, C99) +HANDLE_DW_LANG(0x000d, Ada95) +HANDLE_DW_LANG(0x000e, Fortran95) +HANDLE_DW_LANG(0x000f, PLI) +HANDLE_DW_LANG(0x0010, ObjC) +HANDLE_DW_LANG(0x0011, ObjC_plus_plus) +HANDLE_DW_LANG(0x0012, UPC) +HANDLE_DW_LANG(0x0013, D) + +// New in DWARF 5: +HANDLE_DW_LANG(0x0014, Python) +HANDLE_DW_LANG(0x0015, OpenCL) +HANDLE_DW_LANG(0x0016, Go) +HANDLE_DW_LANG(0x0017, Modula3) +HANDLE_DW_LANG(0x0018, Haskell) +HANDLE_DW_LANG(0x0019, C_plus_plus_03) +HANDLE_DW_LANG(0x001a, C_plus_plus_11) +HANDLE_DW_LANG(0x001b, OCaml) +HANDLE_DW_LANG(0x001c, Rust) +HANDLE_DW_LANG(0x001d, C11) +HANDLE_DW_LANG(0x001e, Swift) +HANDLE_DW_LANG(0x001f, Julia) +HANDLE_DW_LANG(0x0020, Dylan) +HANDLE_DW_LANG(0x0021, C_plus_plus_14) +HANDLE_DW_LANG(0x0022, Fortran03) +HANDLE_DW_LANG(0x0023, Fortran08) +HANDLE_DW_LANG(0x8001, Mips_Assembler) + +// DWARF attribute type encodings. +HANDLE_DW_ATE(0x01, address) +HANDLE_DW_ATE(0x02, boolean) +HANDLE_DW_ATE(0x03, complex_float) +HANDLE_DW_ATE(0x04, float) +HANDLE_DW_ATE(0x05, signed) +HANDLE_DW_ATE(0x06, signed_char) +HANDLE_DW_ATE(0x07, unsigned) +HANDLE_DW_ATE(0x08, unsigned_char) +HANDLE_DW_ATE(0x09, imaginary_float) +HANDLE_DW_ATE(0x0a, packed_decimal) +HANDLE_DW_ATE(0x0b, numeric_string) +HANDLE_DW_ATE(0x0c, edited) +HANDLE_DW_ATE(0x0d, signed_fixed) +HANDLE_DW_ATE(0x0e, unsigned_fixed) +HANDLE_DW_ATE(0x0f, decimal_float) +HANDLE_DW_ATE(0x10, UTF) + +// DWARF virtuality codes. +HANDLE_DW_VIRTUALITY(0x00, none) +HANDLE_DW_VIRTUALITY(0x01, virtual) +HANDLE_DW_VIRTUALITY(0x02, pure_virtual) + +#undef HANDLE_DW_TAG +#undef HANDLE_DW_OP +#undef HANDLE_DW_LANG +#undef HANDLE_DW_ATE +#undef HANDLE_DW_VIRTUALITY diff --git a/include/llvm/Support/Dwarf.h b/include/llvm/Support/Dwarf.h index 47b00b1f09d8..c3d94d19f919 100644 --- a/include/llvm/Support/Dwarf.h +++ b/include/llvm/Support/Dwarf.h @@ -20,6 +20,7 @@ #ifndef LLVM_SUPPORT_DWARF_H #define LLVM_SUPPORT_DWARF_H +#include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" @@ -36,15 +37,11 @@ namespace dwarf { // enumeration base type. enum LLVMConstants : uint32_t { - // llvm mock tags - DW_TAG_invalid = ~0U, // Tag for invalid results. - - DW_TAG_auto_variable = 0x100, // Tag for local (auto) variables. - DW_TAG_arg_variable = 0x101, // Tag for argument variables. - DW_TAG_expression = 0x102, // Tag for complex address expressions. - - DW_TAG_user_base = 0x1000, // Recommended base for user tags. + // LLVM mock tags (see also llvm/Support/Dwarf.def). + DW_TAG_invalid = ~0U, // Tag for invalid results. + DW_VIRTUALITY_invalid = ~0U, // Virtuality for invalid results. + // Other constants. DWARF_VERSION = 4, // Default dwarf version we output. DW_PUBTYPES_VERSION = 2, // Section version number for .debug_pubtypes. DW_PUBNAMES_VERSION = 2, // Section version number for .debug_pubnames. @@ -57,82 +54,11 @@ const uint32_t DW_CIE_ID = UINT32_MAX; const uint64_t DW64_CIE_ID = UINT64_MAX; enum Tag : uint16_t { - DW_TAG_array_type = 0x01, - DW_TAG_class_type = 0x02, - DW_TAG_entry_point = 0x03, - DW_TAG_enumeration_type = 0x04, - DW_TAG_formal_parameter = 0x05, - DW_TAG_imported_declaration = 0x08, - DW_TAG_label = 0x0a, - DW_TAG_lexical_block = 0x0b, - DW_TAG_member = 0x0d, - DW_TAG_pointer_type = 0x0f, - DW_TAG_reference_type = 0x10, - DW_TAG_compile_unit = 0x11, - DW_TAG_string_type = 0x12, - DW_TAG_structure_type = 0x13, - DW_TAG_subroutine_type = 0x15, - DW_TAG_typedef = 0x16, - DW_TAG_union_type = 0x17, - DW_TAG_unspecified_parameters = 0x18, - DW_TAG_variant = 0x19, - DW_TAG_common_block = 0x1a, - DW_TAG_common_inclusion = 0x1b, - DW_TAG_inheritance = 0x1c, - DW_TAG_inlined_subroutine = 0x1d, - DW_TAG_module = 0x1e, - DW_TAG_ptr_to_member_type = 0x1f, - DW_TAG_set_type = 0x20, - DW_TAG_subrange_type = 0x21, - DW_TAG_with_stmt = 0x22, - DW_TAG_access_declaration = 0x23, - DW_TAG_base_type = 0x24, - DW_TAG_catch_block = 0x25, - DW_TAG_const_type = 0x26, - DW_TAG_constant = 0x27, - DW_TAG_enumerator = 0x28, - DW_TAG_file_type = 0x29, - DW_TAG_friend = 0x2a, - DW_TAG_namelist = 0x2b, - DW_TAG_namelist_item = 0x2c, - DW_TAG_packed_type = 0x2d, - DW_TAG_subprogram = 0x2e, - DW_TAG_template_type_parameter = 0x2f, - DW_TAG_template_value_parameter = 0x30, - DW_TAG_thrown_type = 0x31, - DW_TAG_try_block = 0x32, - DW_TAG_variant_part = 0x33, - DW_TAG_variable = 0x34, - DW_TAG_volatile_type = 0x35, - DW_TAG_dwarf_procedure = 0x36, - DW_TAG_restrict_type = 0x37, - DW_TAG_interface_type = 0x38, - DW_TAG_namespace = 0x39, - DW_TAG_imported_module = 0x3a, - DW_TAG_unspecified_type = 0x3b, - DW_TAG_partial_unit = 0x3c, - DW_TAG_imported_unit = 0x3d, - DW_TAG_condition = 0x3f, - DW_TAG_shared_type = 0x40, - DW_TAG_type_unit = 0x41, - DW_TAG_rvalue_reference_type = 0x42, - DW_TAG_template_alias = 0x43, - - // New in DWARF 5: - DW_TAG_coarray_type = 0x44, - DW_TAG_generic_subrange = 0x45, - DW_TAG_dynamic_type = 0x46, - - DW_TAG_MIPS_loop = 0x4081, - DW_TAG_format_label = 0x4101, - DW_TAG_function_template = 0x4102, - DW_TAG_class_template = 0x4103, - DW_TAG_GNU_template_template_param = 0x4106, - DW_TAG_GNU_template_parameter_pack = 0x4107, - DW_TAG_GNU_formal_parameter_pack = 0x4108, +#define HANDLE_DW_TAG(ID, NAME) DW_TAG_##NAME = ID, +#include "llvm/Support/Dwarf.def" DW_TAG_lo_user = 0x4080, - DW_TAG_APPLE_property = 0x4200, - DW_TAG_hi_user = 0xffff + DW_TAG_hi_user = 0xffff, + DW_TAG_user_base = 0x1000 // Recommended base for user tags. }; inline bool isType(Tag T) { @@ -359,194 +285,23 @@ enum Form : uint16_t { // Extensions for Fission proposal DW_FORM_GNU_addr_index = 0x1f01, - DW_FORM_GNU_str_index = 0x1f02 + DW_FORM_GNU_str_index = 0x1f02, + + // Alternate debug sections proposal (output of "dwz" tool). + DW_FORM_GNU_ref_alt = 0x1f20, + DW_FORM_GNU_strp_alt = 0x1f21 }; enum LocationAtom { - // Operation encodings - DW_OP_addr = 0x03, - DW_OP_deref = 0x06, - DW_OP_const1u = 0x08, - DW_OP_const1s = 0x09, - DW_OP_const2u = 0x0a, - DW_OP_const2s = 0x0b, - DW_OP_const4u = 0x0c, - DW_OP_const4s = 0x0d, - DW_OP_const8u = 0x0e, - DW_OP_const8s = 0x0f, - DW_OP_constu = 0x10, - DW_OP_consts = 0x11, - DW_OP_dup = 0x12, - DW_OP_drop = 0x13, - DW_OP_over = 0x14, - DW_OP_pick = 0x15, - DW_OP_swap = 0x16, - DW_OP_rot = 0x17, - DW_OP_xderef = 0x18, - DW_OP_abs = 0x19, - DW_OP_and = 0x1a, - DW_OP_div = 0x1b, - DW_OP_minus = 0x1c, - DW_OP_mod = 0x1d, - DW_OP_mul = 0x1e, - DW_OP_neg = 0x1f, - DW_OP_not = 0x20, - DW_OP_or = 0x21, - DW_OP_plus = 0x22, - DW_OP_plus_uconst = 0x23, - DW_OP_shl = 0x24, - DW_OP_shr = 0x25, - DW_OP_shra = 0x26, - DW_OP_xor = 0x27, - DW_OP_skip = 0x2f, - DW_OP_bra = 0x28, - DW_OP_eq = 0x29, - DW_OP_ge = 0x2a, - DW_OP_gt = 0x2b, - DW_OP_le = 0x2c, - DW_OP_lt = 0x2d, - DW_OP_ne = 0x2e, - DW_OP_lit0 = 0x30, - DW_OP_lit1 = 0x31, - DW_OP_lit2 = 0x32, - DW_OP_lit3 = 0x33, - DW_OP_lit4 = 0x34, - DW_OP_lit5 = 0x35, - DW_OP_lit6 = 0x36, - DW_OP_lit7 = 0x37, - DW_OP_lit8 = 0x38, - DW_OP_lit9 = 0x39, - DW_OP_lit10 = 0x3a, - DW_OP_lit11 = 0x3b, - DW_OP_lit12 = 0x3c, - DW_OP_lit13 = 0x3d, - DW_OP_lit14 = 0x3e, - DW_OP_lit15 = 0x3f, - DW_OP_lit16 = 0x40, - DW_OP_lit17 = 0x41, - DW_OP_lit18 = 0x42, - DW_OP_lit19 = 0x43, - DW_OP_lit20 = 0x44, - DW_OP_lit21 = 0x45, - DW_OP_lit22 = 0x46, - DW_OP_lit23 = 0x47, - DW_OP_lit24 = 0x48, - DW_OP_lit25 = 0x49, - DW_OP_lit26 = 0x4a, - DW_OP_lit27 = 0x4b, - DW_OP_lit28 = 0x4c, - DW_OP_lit29 = 0x4d, - DW_OP_lit30 = 0x4e, - DW_OP_lit31 = 0x4f, - DW_OP_reg0 = 0x50, - DW_OP_reg1 = 0x51, - DW_OP_reg2 = 0x52, - DW_OP_reg3 = 0x53, - DW_OP_reg4 = 0x54, - DW_OP_reg5 = 0x55, - DW_OP_reg6 = 0x56, - DW_OP_reg7 = 0x57, - DW_OP_reg8 = 0x58, - DW_OP_reg9 = 0x59, - DW_OP_reg10 = 0x5a, - DW_OP_reg11 = 0x5b, - DW_OP_reg12 = 0x5c, - DW_OP_reg13 = 0x5d, - DW_OP_reg14 = 0x5e, - DW_OP_reg15 = 0x5f, - DW_OP_reg16 = 0x60, - DW_OP_reg17 = 0x61, - DW_OP_reg18 = 0x62, - DW_OP_reg19 = 0x63, - DW_OP_reg20 = 0x64, - DW_OP_reg21 = 0x65, - DW_OP_reg22 = 0x66, - DW_OP_reg23 = 0x67, - DW_OP_reg24 = 0x68, - DW_OP_reg25 = 0x69, - DW_OP_reg26 = 0x6a, - DW_OP_reg27 = 0x6b, - DW_OP_reg28 = 0x6c, - DW_OP_reg29 = 0x6d, - DW_OP_reg30 = 0x6e, - DW_OP_reg31 = 0x6f, - DW_OP_breg0 = 0x70, - DW_OP_breg1 = 0x71, - DW_OP_breg2 = 0x72, - DW_OP_breg3 = 0x73, - DW_OP_breg4 = 0x74, - DW_OP_breg5 = 0x75, - DW_OP_breg6 = 0x76, - DW_OP_breg7 = 0x77, - DW_OP_breg8 = 0x78, - DW_OP_breg9 = 0x79, - DW_OP_breg10 = 0x7a, - DW_OP_breg11 = 0x7b, - DW_OP_breg12 = 0x7c, - DW_OP_breg13 = 0x7d, - DW_OP_breg14 = 0x7e, - DW_OP_breg15 = 0x7f, - DW_OP_breg16 = 0x80, - DW_OP_breg17 = 0x81, - DW_OP_breg18 = 0x82, - DW_OP_breg19 = 0x83, - DW_OP_breg20 = 0x84, - DW_OP_breg21 = 0x85, - DW_OP_breg22 = 0x86, - DW_OP_breg23 = 0x87, - DW_OP_breg24 = 0x88, - DW_OP_breg25 = 0x89, - DW_OP_breg26 = 0x8a, - DW_OP_breg27 = 0x8b, - DW_OP_breg28 = 0x8c, - DW_OP_breg29 = 0x8d, - DW_OP_breg30 = 0x8e, - DW_OP_breg31 = 0x8f, - DW_OP_regx = 0x90, - DW_OP_fbreg = 0x91, - DW_OP_bregx = 0x92, - DW_OP_piece = 0x93, - DW_OP_deref_size = 0x94, - DW_OP_xderef_size = 0x95, - DW_OP_nop = 0x96, - DW_OP_push_object_address = 0x97, - DW_OP_call2 = 0x98, - DW_OP_call4 = 0x99, - DW_OP_call_ref = 0x9a, - DW_OP_form_tls_address = 0x9b, - DW_OP_call_frame_cfa = 0x9c, - DW_OP_bit_piece = 0x9d, - DW_OP_implicit_value = 0x9e, - DW_OP_stack_value = 0x9f, +#define HANDLE_DW_OP(ID, NAME) DW_OP_##NAME = ID, +#include "llvm/Support/Dwarf.def" DW_OP_lo_user = 0xe0, - DW_OP_hi_user = 0xff, - - // Extensions for GNU-style thread-local storage. - DW_OP_GNU_push_tls_address = 0xe0, - - // Extensions for Fission proposal. - DW_OP_GNU_addr_index = 0xfb, - DW_OP_GNU_const_index = 0xfc + DW_OP_hi_user = 0xff }; enum TypeKind { - // Encoding attribute values - DW_ATE_address = 0x01, - DW_ATE_boolean = 0x02, - DW_ATE_complex_float = 0x03, - DW_ATE_float = 0x04, - DW_ATE_signed = 0x05, - DW_ATE_signed_char = 0x06, - DW_ATE_unsigned = 0x07, - DW_ATE_unsigned_char = 0x08, - DW_ATE_imaginary_float = 0x09, - DW_ATE_packed_decimal = 0x0a, - DW_ATE_numeric_string = 0x0b, - DW_ATE_edited = 0x0c, - DW_ATE_signed_fixed = 0x0d, - DW_ATE_unsigned_fixed = 0x0e, - DW_ATE_decimal_float = 0x0f, - DW_ATE_UTF = 0x10, +#define HANDLE_DW_ATE(ID, NAME) DW_ATE_##NAME = ID, +#include "llvm/Support/Dwarf.def" DW_ATE_lo_user = 0x80, DW_ATE_hi_user = 0xff }; @@ -584,45 +339,15 @@ enum VisibilityAttribute { }; enum VirtualityAttribute { - // Virtuality codes - DW_VIRTUALITY_none = 0x00, - DW_VIRTUALITY_virtual = 0x01, - DW_VIRTUALITY_pure_virtual = 0x02 +#define HANDLE_DW_VIRTUALITY(ID, NAME) DW_VIRTUALITY_##NAME = ID, +#include "llvm/Support/Dwarf.def" + DW_VIRTUALITY_max = 0x02 }; enum SourceLanguage { - // Language names - DW_LANG_C89 = 0x0001, - DW_LANG_C = 0x0002, - DW_LANG_Ada83 = 0x0003, - DW_LANG_C_plus_plus = 0x0004, - DW_LANG_Cobol74 = 0x0005, - DW_LANG_Cobol85 = 0x0006, - DW_LANG_Fortran77 = 0x0007, - DW_LANG_Fortran90 = 0x0008, - DW_LANG_Pascal83 = 0x0009, - DW_LANG_Modula2 = 0x000a, - DW_LANG_Java = 0x000b, - DW_LANG_C99 = 0x000c, - DW_LANG_Ada95 = 0x000d, - DW_LANG_Fortran95 = 0x000e, - DW_LANG_PLI = 0x000f, - DW_LANG_ObjC = 0x0010, - DW_LANG_ObjC_plus_plus = 0x0011, - DW_LANG_UPC = 0x0012, - DW_LANG_D = 0x0013, - // New in DWARF 5: - DW_LANG_Python = 0x0014, - DW_LANG_OpenCL = 0x0015, - DW_LANG_Go = 0x0016, - DW_LANG_Modula3 = 0x0017, - DW_LANG_Haskell = 0x0018, - DW_LANG_C_plus_plus_03 = 0x0019, - DW_LANG_C_plus_plus_11 = 0x001a, - DW_LANG_OCaml = 0x001b, - +#define HANDLE_DW_LANG(ID, NAME) DW_LANG_##NAME = ID, +#include "llvm/Support/Dwarf.def" DW_LANG_lo_user = 0x8000, - DW_LANG_Mips_Assembler = 0x8001, DW_LANG_hi_user = 0xffff }; @@ -859,6 +584,22 @@ const char *GDBIndexEntryKindString(GDBIndexEntryKind Kind); const char *GDBIndexEntryLinkageString(GDBIndexEntryLinkage Linkage); /// @} +/// \defgroup DwarfConstantsParsing Dwarf constants parsing functions +/// +/// These functions map their strings back to the corresponding enumeration +/// value or return 0 if there is none, except for these exceptions: +/// +/// \li \a getTag() returns \a DW_TAG_invalid on invalid input. +/// \li \a getVirtuality() returns \a DW_VIRTUALITY_invalid on invalid input. +/// +/// @{ +unsigned getTag(StringRef TagString); +unsigned getOperationEncoding(StringRef OperationEncodingString); +unsigned getVirtuality(StringRef VirtualityString); +unsigned getLanguage(StringRef LanguageString); +unsigned getAttributeEncoding(StringRef EncodingString); +/// @} + /// \brief Returns the symbolic string representing Val when used as a value /// for attribute Attr. const char *AttributeValueString(uint16_t Attr, unsigned Val); diff --git a/include/llvm/Support/ELF.h b/include/llvm/Support/ELF.h index 3d49205fa168..8b915ff0581d 100644 --- a/include/llvm/Support/ELF.h +++ b/include/llvm/Support/ELF.h @@ -344,6 +344,7 @@ enum { ELFOSABI_NSK = 14, // Hewlett-Packard Non-Stop Kernel ELFOSABI_AROS = 15, // AROS ELFOSABI_FENIXOS = 16, // FenixOS + ELFOSABI_CLOUDABI = 17, // Nuxi CloudABI ELFOSABI_C6000_ELFABI = 64, // Bare-metal TMS320C6000 ELFOSABI_C6000_LINUX = 65, // Linux TMS320C6000 ELFOSABI_ARM = 97, // ARM @@ -431,22 +432,50 @@ enum : unsigned { EF_MIPS_NOREORDER = 0x00000001, // Don't reorder instructions EF_MIPS_PIC = 0x00000002, // Position independent code EF_MIPS_CPIC = 0x00000004, // Call object with Position independent code - EF_MIPS_ABI2 = 0x00000020, - EF_MIPS_32BITMODE = 0x00000100, + EF_MIPS_ABI2 = 0x00000020, // File uses N32 ABI + EF_MIPS_32BITMODE = 0x00000100, // Code compiled for a 64-bit machine + // in 32-bit mode + EF_MIPS_FP64 = 0x00000200, // Code compiled for a 32-bit machine + // but uses 64-bit FP registers EF_MIPS_NAN2008 = 0x00000400, // Uses IEE 754-2008 NaN encoding // ABI flags - EF_MIPS_ABI_O32 = 0x00001000, // This file follows the first MIPS 32 bit ABI + EF_MIPS_ABI_O32 = 0x00001000, // This file follows the first MIPS 32 bit ABI EF_MIPS_ABI_O64 = 0x00002000, // O32 ABI extended for 64-bit architecture. EF_MIPS_ABI_EABI32 = 0x00003000, // EABI in 32 bit mode. EF_MIPS_ABI_EABI64 = 0x00004000, // EABI in 64 bit mode. EF_MIPS_ABI = 0x0000f000, // Mask for selecting EF_MIPS_ABI_ variant. - //ARCH_ASE + // MIPS machine variant + EF_MIPS_MACH_3900 = 0x00810000, // Toshiba R3900 + EF_MIPS_MACH_4010 = 0x00820000, // LSI R4010 + EF_MIPS_MACH_4100 = 0x00830000, // NEC VR4100 + EF_MIPS_MACH_4650 = 0x00850000, // MIPS R4650 + EF_MIPS_MACH_4120 = 0x00870000, // NEC VR4120 + EF_MIPS_MACH_4111 = 0x00880000, // NEC VR4111/VR4181 + EF_MIPS_MACH_SB1 = 0x008a0000, // Broadcom SB-1 + EF_MIPS_MACH_OCTEON = 0x008b0000, // Cavium Networks Octeon + EF_MIPS_MACH_XLR = 0x008c0000, // RMI Xlr + EF_MIPS_MACH_OCTEON2 = 0x008d0000, // Cavium Networks Octeon2 + EF_MIPS_MACH_OCTEON3 = 0x008e0000, // Cavium Networks Octeon3 + EF_MIPS_MACH_5400 = 0x00910000, // NEC VR5400 + EF_MIPS_MACH_5900 = 0x00920000, // MIPS R5900 + EF_MIPS_MACH_5500 = 0x00980000, // NEC VR5500 + EF_MIPS_MACH_9000 = 0x00990000, // Unknown + EF_MIPS_MACH_LS2E = 0x00a00000, // ST Microelectronics Loongson 2E + EF_MIPS_MACH_LS2F = 0x00a10000, // ST Microelectronics Loongson 2F + EF_MIPS_MACH_LS3A = 0x00a20000, // Loongson 3A + EF_MIPS_MACH = 0x00ff0000, // EF_MIPS_MACH_xxx selection mask + + // ARCH_ASE EF_MIPS_MICROMIPS = 0x02000000, // microMIPS EF_MIPS_ARCH_ASE_M16 = 0x04000000, // Has Mips-16 ISA extensions - //ARCH + EF_MIPS_ARCH_ASE_MDMX = + 0x08000000, // Has MDMX multimedia extensions + EF_MIPS_ARCH_ASE = 0x0f000000, // Mask for EF_MIPS_ARCH_ASE_xxx flags + + // ARCH EF_MIPS_ARCH_1 = 0x00000000, // MIPS1 instruction set EF_MIPS_ARCH_2 = 0x10000000, // MIPS2 instruction set EF_MIPS_ARCH_3 = 0x20000000, // MIPS3 instruction set @@ -454,8 +483,8 @@ enum : unsigned { EF_MIPS_ARCH_5 = 0x40000000, // MIPS5 instruction set EF_MIPS_ARCH_32 = 0x50000000, // MIPS32 instruction set per linux not elf.h EF_MIPS_ARCH_64 = 0x60000000, // MIPS64 instruction set per linux not elf.h - EF_MIPS_ARCH_32R2 = 0x70000000, // mips32r2 - EF_MIPS_ARCH_64R2 = 0x80000000, // mips64r2 + EF_MIPS_ARCH_32R2 = 0x70000000, // mips32r2, mips32r3, mips32r5 + EF_MIPS_ARCH_64R2 = 0x80000000, // mips64r2, mips64r3, mips64r5 EF_MIPS_ARCH_32R6 = 0x90000000, // mips32r6 EF_MIPS_ARCH_64R6 = 0xa0000000, // mips64r6 EF_MIPS_ARCH = 0xf0000000 // Mask for applying EF_MIPS_ARCH_ variant @@ -475,6 +504,22 @@ enum { STO_MIPS_MIPS16 = 0xf0 // MIPS Specific ISA for Mips16 }; +// .MIPS.options section descriptor kinds +enum { + ODK_NULL = 0, // Undefined + ODK_REGINFO = 1, // Register usage information + ODK_EXCEPTIONS = 2, // Exception processing options + ODK_PAD = 3, // Section padding options + ODK_HWPATCH = 4, // Hardware patches applied + ODK_FILL = 5, // Linker fill value + ODK_TAGS = 6, // Space for tool identification + ODK_HWAND = 7, // Hardware AND patches applied + ODK_HWOR = 8, // Hardware OR patches applied + ODK_GP_GROUP = 9, // GP group to use for text/data sections + ODK_IDENT = 10, // ID information + ODK_PAGESIZE = 11 // Page size information +}; + // Hexagon Specific e_flags // Release 5 ABI enum { @@ -761,6 +806,7 @@ enum { STB_LOCAL = 0, // Local symbol, not visible outside obj file containing def STB_GLOBAL = 1, // Global symbol, visible to all object files being combined STB_WEAK = 2, // Weak symbol, like global but lower-precedence + STB_GNU_UNIQUE = 10, STB_LOOS = 10, // Lowest operating system-specific binding type STB_HIOS = 12, // Highest operating system-specific binding type STB_LOPROC = 13, // Lowest processor-specific binding type @@ -795,6 +841,14 @@ enum { STN_UNDEF = 0 }; +// Special relocation symbols used in the MIPS64 ELF relocation entries +enum { + RSS_UNDEF = 0, // None + RSS_GP = 1, // Value of gp + RSS_GP0 = 2, // Value of gp used to create object being relocated + RSS_LOC = 3 // Address of location being relocated +}; + // Relocation entry, without explicit addend. struct Elf32_Rel { Elf32_Addr r_offset; // Location (file byte offset, or program virtual addr) @@ -1114,7 +1168,16 @@ enum { 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. + DF_1_DISPRELPND = 0x00010000, // Disp reloc applied at run-time. + DF_1_NODIRECT = 0x00020000, // Object has no-direct binding. + DF_1_IGNMULDEF = 0x00040000, + DF_1_NOKSYMS = 0x00080000, + DF_1_NOHDR = 0x00100000, + DF_1_EDITED = 0x00200000, // Object is modified after built. + DF_1_NORELOC = 0x00400000, + DF_1_SYMINTPOSE = 0x00800000, // Object has individual interposers. + DF_1_GLOBAUDIT = 0x01000000, // Global auditing required. + DF_1_SINGLETON = 0x02000000 // Singleton symbols are used. }; // DT_MIPS_FLAGS values. diff --git a/include/llvm/Support/ELFRelocs/Mips.def b/include/llvm/Support/ELFRelocs/Mips.def index dc573464dcf2..77e7f8e8712b 100644 --- a/include/llvm/Support/ELFRelocs/Mips.def +++ b/include/llvm/Support/ELFRelocs/Mips.def @@ -108,5 +108,10 @@ ELF_RELOC(R_MICROMIPS_TLS_TPREL_HI16, 169) ELF_RELOC(R_MICROMIPS_TLS_TPREL_LO16, 170) ELF_RELOC(R_MICROMIPS_GPREL7_S2, 172) ELF_RELOC(R_MICROMIPS_PC23_S2, 173) +ELF_RELOC(R_MICROMIPS_PC21_S2, 174) +ELF_RELOC(R_MICROMIPS_PC26_S2, 175) +ELF_RELOC(R_MICROMIPS_PC18_S3, 176) +ELF_RELOC(R_MICROMIPS_PC19_S2, 177) ELF_RELOC(R_MIPS_NUM, 218) ELF_RELOC(R_MIPS_PC32, 248) +ELF_RELOC(R_MIPS_EH, 249) diff --git a/include/llvm/Support/Endian.h b/include/llvm/Support/Endian.h index 47b82fdc4975..e9fe22e5eda8 100644 --- a/include/llvm/Support/Endian.h +++ b/include/llvm/Support/Endian.h @@ -58,8 +58,9 @@ inline value_type read(const void *memory) { /// Read a value of a particular endianness from a buffer, and increment the /// buffer past that value. -template<typename value_type, endianness endian, std::size_t alignment> -inline value_type readNext(const unsigned char *&memory) { +template<typename value_type, endianness endian, std::size_t alignment, + typename CharT> +inline value_type readNext(const CharT *&memory) { value_type ret = read<value_type, endian, alignment>(memory); memory += sizeof(value_type); return ret; @@ -195,7 +196,23 @@ typedef detail::packed_endian_specific_integral <int32_t, native, unaligned> unaligned_int32_t; typedef detail::packed_endian_specific_integral <int64_t, native, unaligned> unaligned_int64_t; -} // end namespace llvm + +namespace endian { +inline uint16_t read16le(const void *p) { return *(const ulittle16_t *)p; } +inline uint32_t read32le(const void *p) { return *(const ulittle32_t *)p; } +inline uint64_t read64le(const void *p) { return *(const ulittle64_t *)p; } +inline uint16_t read16be(const void *p) { return *(const ubig16_t *)p; } +inline uint32_t read32be(const void *p) { return *(const ubig32_t *)p; } +inline uint64_t read64be(const void *p) { return *(const ubig64_t *)p; } + +inline void write16le(void *p, uint16_t v) { *(ulittle16_t *)p = v; } +inline void write32le(void *p, uint32_t v) { *(ulittle32_t *)p = v; } +inline void write64le(void *p, uint64_t v) { *(ulittle64_t *)p = v; } +inline void write16be(void *p, uint16_t v) { *(ubig16_t *)p = v; } +inline void write32be(void *p, uint32_t v) { *(ubig32_t *)p = v; } +inline void write64be(void *p, uint64_t v) { *(ubig64_t *)p = v; } +} // end namespace endian } // end namespace support +} // end namespace llvm #endif diff --git a/include/llvm/Support/EndianStream.h b/include/llvm/Support/EndianStream.h index 94f372f020b4..d44a9b3b7ce8 100644 --- a/include/llvm/Support/EndianStream.h +++ b/include/llvm/Support/EndianStream.h @@ -31,6 +31,31 @@ template <endianness endian> struct Writer { OS.write((const char *)&Val, sizeof(value_type)); } }; + +template <> +template <> +inline void Writer<little>::write<float>(float Val) { + write(FloatToBits(Val)); +} + +template <> +template <> +inline void Writer<little>::write<double>(double Val) { + write(DoubleToBits(Val)); +} + +template <> +template <> +inline void Writer<big>::write<float>(float Val) { + write(FloatToBits(Val)); +} + +template <> +template <> +inline void Writer<big>::write<double>(double Val) { + write(DoubleToBits(Val)); +} + } // end namespace endian } // end namespace support diff --git a/include/llvm/Support/ErrorOr.h b/include/llvm/Support/ErrorOr.h index 84763deea0f9..589404f9b4ee 100644 --- a/include/llvm/Support/ErrorOr.h +++ b/include/llvm/Support/ErrorOr.h @@ -168,7 +168,7 @@ public: } /// \brief Return false if there is an error. - LLVM_EXPLICIT operator bool() const { + explicit operator bool() const { return !HasError; } @@ -281,8 +281,8 @@ template <class T, class E> typename std::enable_if<std::is_error_code_enum<E>::value || std::is_error_condition_enum<E>::value, bool>::type -operator==(ErrorOr<T> &Err, E Code) { - return std::error_code(Err) == Code; +operator==(const ErrorOr<T> &Err, E Code) { + return Err.getError() == Code; } } // end namespace llvm diff --git a/include/llvm/Support/FileOutputBuffer.h b/include/llvm/Support/FileOutputBuffer.h index 9f02a16e3d65..fd8879c84622 100644 --- a/include/llvm/Support/FileOutputBuffer.h +++ b/include/llvm/Support/FileOutputBuffer.h @@ -74,8 +74,8 @@ public: ~FileOutputBuffer(); private: - FileOutputBuffer(const FileOutputBuffer &) LLVM_DELETED_FUNCTION; - FileOutputBuffer &operator=(const FileOutputBuffer &) LLVM_DELETED_FUNCTION; + FileOutputBuffer(const FileOutputBuffer &) = delete; + FileOutputBuffer &operator=(const FileOutputBuffer &) = delete; FileOutputBuffer(std::unique_ptr<llvm::sys::fs::mapped_file_region> R, StringRef Path, StringRef TempPath); diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index b60c1b07043b..a736c324f8aa 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -120,7 +120,7 @@ class UniqueID { uint64_t File; public: - UniqueID() {} + UniqueID() = default; UniqueID(uint64_t Device, uint64_t File) : Device(Device), File(File) {} bool operator==(const UniqueID &Other) const { return Device == Other.Device && File == Other.File; @@ -241,6 +241,7 @@ struct file_magic { macho_bundle, ///< Mach-O Bundle file macho_dynamically_linked_shared_lib_stub, ///< Mach-O Shared lib stub macho_dsym_companion, ///< Mach-O dSYM companion file + macho_kext_bundle, ///< Mach-O kext bundle file macho_universal_binary, ///< Mach-O universal binary coff_object, ///< COFF object file coff_import_library, ///< COFF import library @@ -624,9 +625,9 @@ std::error_code getUniqueID(const Twine Path, UniqueID &Result); /// This class represents a memory mapped file. It is based on /// boost::iostreams::mapped_file. class mapped_file_region { - mapped_file_region() LLVM_DELETED_FUNCTION; - mapped_file_region(mapped_file_region&) LLVM_DELETED_FUNCTION; - mapped_file_region &operator =(mapped_file_region&) LLVM_DELETED_FUNCTION; + mapped_file_region() = delete; + mapped_file_region(mapped_file_region&) = delete; + mapped_file_region &operator =(mapped_file_region&) = delete; public: enum mapmode { diff --git a/include/llvm/Support/FileUtilities.h b/include/llvm/Support/FileUtilities.h index 3f2f176eb469..2ee2c60b9964 100644 --- a/include/llvm/Support/FileUtilities.h +++ b/include/llvm/Support/FileUtilities.h @@ -51,7 +51,7 @@ namespace llvm { ~FileRemover() { if (DeleteIt) { // Ignore problems deleting the file. - sys::fs::remove(Filename.str()); + sys::fs::remove(Filename); } } @@ -61,7 +61,7 @@ namespace llvm { void setFile(const Twine& filename, bool deleteIt = true) { if (DeleteIt) { // Ignore problems deleting the file. - sys::fs::remove(Filename.str()); + sys::fs::remove(Filename); } Filename.clear(); diff --git a/include/llvm/Support/Format.h b/include/llvm/Support/Format.h index 5d599e96ec3a..4319a3ba2745 100644 --- a/include/llvm/Support/Format.h +++ b/include/llvm/Support/Format.h @@ -23,18 +23,12 @@ #ifndef LLVM_SUPPORT_FORMAT_H #define LLVM_SUPPORT_FORMAT_H +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/DataTypes.h" #include <cassert> #include <cstdio> -#ifdef _MSC_VER -// FIXME: This define is wrong: -// - _snprintf does not guarantee that trailing null is always added - if -// there is no space for null, it does not report any error. -// - According to C++ standard, snprintf should be visible in the 'std' -// namespace - this define makes this impossible. -#define snprintf _snprintf -#endif +#include <tuple> namespace llvm { @@ -43,7 +37,8 @@ namespace llvm { class format_object_base { protected: const char *Fmt; - ~format_object_base() {} // Disallow polymorphic deletion. + ~format_object_base() = default; // Disallow polymorphic deletion. + format_object_base(const format_object_base &) = default; virtual void home(); // Out of line virtual method. /// Call snprintf() for this object, on the given buffer and size. @@ -80,101 +75,26 @@ public: /// printed, this synthesizes the string into a temporary buffer provided and /// returns whether or not it is big enough. -template <typename T> -class format_object1 final : public format_object_base { - T Val; -public: - format_object1(const char *fmt, const T &val) - : format_object_base(fmt), Val(val) { - } - - int snprint(char *Buffer, unsigned BufferSize) const override { - return snprintf(Buffer, BufferSize, Fmt, Val); - } -}; - -template <typename T1, typename T2> -class format_object2 final : public format_object_base { - T1 Val1; - T2 Val2; -public: - format_object2(const char *fmt, const T1 &val1, const T2 &val2) - : format_object_base(fmt), Val1(val1), Val2(val2) { - } - - int snprint(char *Buffer, unsigned BufferSize) const override { - return snprintf(Buffer, BufferSize, Fmt, Val1, Val2); - } -}; - -template <typename T1, typename T2, typename T3> -class format_object3 final : public format_object_base { - T1 Val1; - T2 Val2; - T3 Val3; -public: - format_object3(const char *fmt, const T1 &val1, const T2 &val2,const T3 &val3) - : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3) { - } - - int snprint(char *Buffer, unsigned BufferSize) const override { - return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3); - } -}; - -template <typename T1, typename T2, typename T3, typename T4> -class format_object4 final : public format_object_base { - T1 Val1; - T2 Val2; - T3 Val3; - T4 Val4; -public: - format_object4(const char *fmt, const T1 &val1, const T2 &val2, - const T3 &val3, const T4 &val4) - : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4) { - } +template <typename... Ts> +class format_object final : public format_object_base { + std::tuple<Ts...> Vals; - int snprint(char *Buffer, unsigned BufferSize) const override { - return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4); - } -}; - -template <typename T1, typename T2, typename T3, typename T4, typename T5> -class format_object5 final : public format_object_base { - T1 Val1; - T2 Val2; - T3 Val3; - T4 Val4; - T5 Val5; -public: - format_object5(const char *fmt, const T1 &val1, const T2 &val2, - const T3 &val3, const T4 &val4, const T5 &val5) - : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4), - Val5(val5) { - } - - int snprint(char *Buffer, unsigned BufferSize) const override { - return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5); + template <std::size_t... Is> + int snprint_tuple(char *Buffer, unsigned BufferSize, + index_sequence<Is...>) const { +#ifdef _MSC_VER + return _snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...); +#else + return snprintf(Buffer, BufferSize, Fmt, std::get<Is>(Vals)...); +#endif } -}; -template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6> -class format_object6 final : public format_object_base { - T1 Val1; - T2 Val2; - T3 Val3; - T4 Val4; - T5 Val5; - T6 Val6; public: - format_object6(const char *Fmt, const T1 &Val1, const T2 &Val2, - const T3 &Val3, const T4 &Val4, const T5 &Val5, const T6 &Val6) - : format_object_base(Fmt), Val1(Val1), Val2(Val2), Val3(Val3), Val4(Val4), - Val5(Val5), Val6(Val6) { } + format_object(const char *fmt, const Ts &... vals) + : format_object_base(fmt), Vals(vals...) {} int snprint(char *Buffer, unsigned BufferSize) const override { - return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5, Val6); + return snprint_tuple(Buffer, BufferSize, index_sequence_for<Ts...>()); } }; @@ -187,44 +107,9 @@ public: /// OS << format("%0.4f", myfloat) << '\n'; /// \endcode -template <typename T> -inline format_object1<T> format(const char *Fmt, const T &Val) { - return format_object1<T>(Fmt, Val); -} - -template <typename T1, typename T2> -inline format_object2<T1, T2> format(const char *Fmt, const T1 &Val1, - const T2 &Val2) { - return format_object2<T1, T2>(Fmt, Val1, Val2); -} - -template <typename T1, typename T2, typename T3> - inline format_object3<T1, T2, T3> format(const char *Fmt, const T1 &Val1, - const T2 &Val2, const T3 &Val3) { - return format_object3<T1, T2, T3>(Fmt, Val1, Val2, Val3); -} - -template <typename T1, typename T2, typename T3, typename T4> -inline format_object4<T1, T2, T3, T4> format(const char *Fmt, const T1 &Val1, - const T2 &Val2, const T3 &Val3, - const T4 &Val4) { - return format_object4<T1, T2, T3, T4>(Fmt, Val1, Val2, Val3, Val4); -} - -template <typename T1, typename T2, typename T3, typename T4, typename T5> -inline format_object5<T1, T2, T3, T4, T5> format(const char *Fmt,const T1 &Val1, - const T2 &Val2, const T3 &Val3, - const T4 &Val4, const T5 &Val5) { - return format_object5<T1, T2, T3, T4, T5>(Fmt, Val1, Val2, Val3, Val4, Val5); -} - -template <typename T1, typename T2, typename T3, typename T4, typename T5, - typename T6> -inline format_object6<T1, T2, T3, T4, T5, T6> -format(const char *Fmt, const T1 &Val1, const T2 &Val2, const T3 &Val3, - const T4 &Val4, const T5 &Val5, const T6 &Val6) { - return format_object6<T1, T2, T3, T4, T5, T6>(Fmt, Val1, Val2, Val3, Val4, - Val5, Val6); +template <typename... Ts> +inline format_object<Ts...> format(const char *Fmt, const Ts &... Vals) { + return format_object<Ts...>(Fmt, Vals...); } /// This is a helper class used for left_justify() and right_justify(). @@ -259,21 +144,38 @@ class FormattedNumber { unsigned Width; bool Hex; bool Upper; + bool HexPrefix; friend class raw_ostream; public: - FormattedNumber(uint64_t HV, int64_t DV, unsigned W, bool H, bool U) - : HexValue(HV), DecValue(DV), Width(W), Hex(H), Upper(U) { } + FormattedNumber(uint64_t HV, int64_t DV, unsigned W, bool H, bool U, + bool Prefix) + : HexValue(HV), DecValue(DV), Width(W), Hex(H), Upper(U), + HexPrefix(Prefix) {} }; /// format_hex - Output \p N as a fixed width hexadecimal. If number will not /// fit in width, full number is still printed. Examples: -/// OS << format_hex(255, 4) => 0xff -/// OS << format_hex(255, 4, true) => 0xFF -/// OS << format_hex(255, 6) => 0x00ff -/// OS << format_hex(255, 2) => 0xff -inline FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false) { +/// OS << format_hex(255, 4) => 0xff +/// OS << format_hex(255, 4, true) => 0xFF +/// OS << format_hex(255, 6) => 0x00ff +/// OS << format_hex(255, 2) => 0xff +inline FormattedNumber format_hex(uint64_t N, unsigned Width, + bool Upper = false) { + assert(Width <= 18 && "hex width must be <= 18"); + return FormattedNumber(N, 0, Width, true, Upper, true); +} + +/// format_hex_no_prefix - Output \p N as a fixed width hexadecimal. Does not +/// prepend '0x' to the outputted string. If number will not fit in width, +/// full number is still printed. Examples: +/// OS << format_hex_no_prefix(255, 4) => ff +/// OS << format_hex_no_prefix(255, 4, true) => FF +/// OS << format_hex_no_prefix(255, 6) => 00ff +/// OS << format_hex_no_prefix(255, 2) => ff +inline FormattedNumber format_hex_no_prefix(uint64_t N, unsigned Width, + bool Upper = false) { assert(Width <= 18 && "hex width must be <= 18"); - return FormattedNumber(N, 0, Width, true, Upper); + return FormattedNumber(N, 0, Width, true, Upper, false); } /// format_decimal - Output \p N as a right justified, fixed-width decimal. If @@ -283,7 +185,7 @@ inline FormattedNumber format_hex(uint64_t N, unsigned Width, bool Upper=false) /// OS << format_decimal(-1, 3) => " -1" /// OS << format_decimal(12345, 3) => "12345" inline FormattedNumber format_decimal(int64_t N, unsigned Width) { - return FormattedNumber(0, N, Width, false, false); + return FormattedNumber(0, N, Width, false, false, false); } diff --git a/include/llvm/Support/FormattedStream.h b/include/llvm/Support/FormattedStream.h index 8137daaff1f8..4a135cd23174 100644 --- a/include/llvm/Support/FormattedStream.h +++ b/include/llvm/Support/FormattedStream.h @@ -25,27 +25,11 @@ namespace llvm { /// boundaries and querying the number of lines written to the stream. /// class formatted_raw_ostream : public raw_ostream { -public: - /// DELETE_STREAM - Tell the destructor to delete the held stream. - /// - static const bool DELETE_STREAM = true; - - /// PRESERVE_STREAM - Tell the destructor to not delete the held - /// stream. - /// - static const bool PRESERVE_STREAM = false; - -private: /// TheStream - The real stream we output to. We set it to be /// unbuffered, since we're already doing our own buffering. /// raw_ostream *TheStream; - /// DeleteStream - Do we need to delete TheStream in the - /// destructor? - /// - bool DeleteStream; - /// Position - The current output column and line of the data that's /// been flushed and the portion of the buffer that's been /// scanned. The line and column scheme is zero-based. @@ -73,6 +57,24 @@ private: /// void ComputePosition(const char *Ptr, size_t size); + void setStream(raw_ostream &Stream) { + releaseStream(); + + TheStream = &Stream; + + // This formatted_raw_ostream inherits from raw_ostream, so it'll do its + // own buffering, and it doesn't need or want TheStream to do another + // layer of buffering underneath. Resize the buffer to what TheStream + // had been using, and tell TheStream not to do its own buffering. + if (size_t BufferSize = TheStream->GetBufferSize()) + SetBufferSize(BufferSize); + else + SetUnbuffered(); + TheStream->SetUnbuffered(); + + Scanned = nullptr; + } + public: /// formatted_raw_ostream - Open the specified file for /// writing. If an error occurs, information about the error is @@ -84,39 +86,19 @@ public: /// so it doesn't want another layer of buffering to be happening /// underneath it. /// - formatted_raw_ostream(raw_ostream &Stream, bool Delete = false) - : raw_ostream(), TheStream(nullptr), DeleteStream(false), Position(0, 0) { - setStream(Stream, Delete); + formatted_raw_ostream(raw_ostream &Stream) + : TheStream(nullptr), Position(0, 0) { + setStream(Stream); } - explicit formatted_raw_ostream() - : raw_ostream(), TheStream(nullptr), DeleteStream(false), Position(0, 0) { + explicit formatted_raw_ostream() : TheStream(nullptr), Position(0, 0) { Scanned = nullptr; } - ~formatted_raw_ostream() { + ~formatted_raw_ostream() override { flush(); releaseStream(); } - void setStream(raw_ostream &Stream, bool Delete = false) { - releaseStream(); - - TheStream = &Stream; - DeleteStream = Delete; - - // This formatted_raw_ostream inherits from raw_ostream, so it'll do its - // own buffering, and it doesn't need or want TheStream to do another - // layer of buffering underneath. Resize the buffer to what TheStream - // had been using, and tell TheStream not to do its own buffering. - if (size_t BufferSize = TheStream->GetBufferSize()) - SetBufferSize(BufferSize); - else - SetUnbuffered(); - TheStream->SetUnbuffered(); - - Scanned = nullptr; - } - /// PadToColumn - Align the output to some column number. If the current /// column is already equal to or more than NewCol, PadToColumn inserts one /// space. @@ -151,13 +133,11 @@ public: private: void releaseStream() { - // Delete the stream if needed. Otherwise, transfer the buffer - // settings from this raw_ostream back to the underlying stream. + // Transfer the buffer settings from this raw_ostream back to the underlying + // stream. if (!TheStream) return; - if (DeleteStream) - delete TheStream; - else if (size_t BufferSize = GetBufferSize()) + if (size_t BufferSize = GetBufferSize()) TheStream->SetBufferSize(BufferSize); else TheStream->SetUnbuffered(); diff --git a/include/llvm/Support/GCOV.h b/include/llvm/Support/GCOV.h index e378602c7bb3..c2e34bd3eaeb 100644 --- a/include/llvm/Support/GCOV.h +++ b/include/llvm/Support/GCOV.h @@ -19,6 +19,7 @@ #include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/iterator.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/raw_ostream.h" @@ -29,10 +30,7 @@ class GCOVBlock; class FileInfo; namespace GCOV { - enum GCOVVersion { - V402, - V404 - }; +enum GCOVVersion { V402, V404 }; } // end GCOV namespace /// GCOVOptions - A struct for passing gcov options between functions. @@ -56,7 +54,7 @@ struct GCOVOptions { class GCOVBuffer { public: GCOVBuffer(MemoryBuffer *B) : Buffer(B), Cursor(0) {} - + /// readGCNOFormat - Check GCNO signature is valid at the beginning of buffer. bool readGCNOFormat() { StringRef File = Buffer->getBuffer().slice(0, 4); @@ -81,7 +79,7 @@ public: /// readGCOVVersion - Read GCOV version. bool readGCOVVersion(GCOV::GCOVVersion &Version) { - StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor+4); + StringRef VersionStr = Buffer->getBuffer().slice(Cursor, Cursor + 4); if (VersionStr == "*204") { Cursor += 4; Version = GCOV::V402; @@ -99,10 +97,9 @@ public: /// readFunctionTag - If cursor points to a function tag then increment the /// cursor and return true otherwise return false. 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') { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' || + Tag[3] != '\1') { return false; } Cursor += 4; @@ -112,10 +109,9 @@ public: /// readBlockTag - If cursor points to a block tag then increment the /// cursor and return true otherwise return false. 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') { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x41' || + Tag[3] != '\x01') { return false; } Cursor += 4; @@ -125,10 +121,9 @@ public: /// readEdgeTag - If cursor points to an edge tag then increment the /// cursor and return true otherwise return false. 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') { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x43' || + Tag[3] != '\x01') { return false; } Cursor += 4; @@ -138,10 +133,9 @@ public: /// readLineTag - If cursor points to a line tag then increment the /// cursor and return true otherwise return false. 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') { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\x45' || + Tag[3] != '\x01') { return false; } Cursor += 4; @@ -151,10 +145,9 @@ public: /// readArcTag - If cursor points to an gcda arc tag then increment the /// cursor and return true otherwise return false. 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') { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\xa1' || + Tag[3] != '\1') { return false; } Cursor += 4; @@ -164,10 +157,9 @@ public: /// readObjectTag - If cursor points to an object summary tag then increment /// the cursor and return true otherwise return false. bool readObjectTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); - if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\0' || Tag[3] != '\xa1') { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' || + Tag[3] != '\xa1') { return false; } Cursor += 4; @@ -177,10 +169,9 @@ public: /// readProgramTag - If cursor points to a program summary tag then increment /// the cursor and return true otherwise return false. bool readProgramTag() { - StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor+4); - if (Tag.empty() || - Tag[0] != '\0' || Tag[1] != '\0' || - Tag[2] != '\0' || Tag[3] != '\xa3') { + StringRef Tag = Buffer->getBuffer().slice(Cursor, Cursor + 4); + if (Tag.empty() || Tag[0] != '\0' || Tag[1] != '\0' || Tag[2] != '\0' || + Tag[3] != '\xa3') { return false; } Cursor += 4; @@ -188,11 +179,11 @@ public: } bool readInt(uint32_t &Val) { - if (Buffer->getBuffer().size() < Cursor+4) { - errs() << "Unexpected end of memory buffer: " << Cursor+4 << ".\n"; + if (Buffer->getBuffer().size() < Cursor + 4) { + errs() << "Unexpected end of memory buffer: " << Cursor + 4 << ".\n"; return false; } - StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor+4); + StringRef Str = Buffer->getBuffer().slice(Cursor, Cursor + 4); Cursor += 4; Val = *(const uint32_t *)(Str.data()); return true; @@ -200,7 +191,8 @@ public: bool readInt64(uint64_t &Val) { uint32_t Lo, Hi; - if (!readInt(Lo) || !readInt(Hi)) return false; + if (!readInt(Lo) || !readInt(Hi)) + return false; Val = ((uint64_t)Hi << 32) | Lo; return true; } @@ -210,19 +202,21 @@ public: // Keep reading until we find a non-zero length. This emulates gcov's // behaviour, which appears to do the same. while (Len == 0) - if (!readInt(Len)) return false; + if (!readInt(Len)) + return false; Len *= 4; - if (Buffer->getBuffer().size() < Cursor+Len) { - errs() << "Unexpected end of memory buffer: " << Cursor+Len << ".\n"; + if (Buffer->getBuffer().size() < Cursor + Len) { + errs() << "Unexpected end of memory buffer: " << Cursor + Len << ".\n"; return false; } - Str = Buffer->getBuffer().slice(Cursor, Cursor+Len).split('\0').first; + Str = Buffer->getBuffer().slice(Cursor, Cursor + Len).split('\0').first; Cursor += Len; return true; } uint64_t getCursor() const { return Cursor; } - void advanceCursor(uint32_t n) { Cursor += n*4; } + void advanceCursor(uint32_t n) { Cursor += n * 4; } + private: MemoryBuffer *Buffer; uint64_t Cursor; @@ -232,13 +226,15 @@ private: /// (.gcno and .gcda). class GCOVFile { public: - GCOVFile() : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0), - ProgramCount(0) {} + GCOVFile() + : GCNOInitialized(false), Checksum(0), Functions(), RunCount(0), + ProgramCount(0) {} bool readGCNO(GCOVBuffer &Buffer); bool readGCDA(GCOVBuffer &Buffer); uint32_t getChecksum() const { return Checksum; } void dump() const; void collectLineCounts(FileInfo &FI); + private: bool GCNOInitialized; GCOV::GCOVVersion Version; @@ -260,8 +256,8 @@ struct GCOVEdge { /// GCOVFunction - Collects function information. class GCOVFunction { public: - typedef SmallVectorImpl<std::unique_ptr<GCOVBlock>>::const_iterator - BlockIterator; + typedef pointee_iterator<SmallVectorImpl< + std::unique_ptr<GCOVBlock>>::const_iterator> BlockIterator; GCOVFunction(GCOVFile &P) : Parent(P), Ident(0), LineNumber(0) {} bool readGCNO(GCOVBuffer &Buffer, GCOV::GCOVVersion Version); @@ -274,9 +270,13 @@ public: BlockIterator block_begin() const { return Blocks.begin(); } BlockIterator block_end() const { return Blocks.end(); } + iterator_range<BlockIterator> blocks() const { + return make_range(block_begin(), block_end()); + } void dump() const; void collectLineCounts(FileInfo &FI); + private: GCOVFile &Parent; uint32_t Ident; @@ -291,7 +291,7 @@ private: /// GCOVBlock - Collects block information. class GCOVBlock { struct EdgeWeight { - EdgeWeight(GCOVBlock *D): Dst(D), Count(0) {} + EdgeWeight(GCOVBlock *D) : Dst(D), Count(0) {} GCOVBlock *Dst; uint64_t Count; @@ -302,11 +302,13 @@ class GCOVBlock { return E1->Dst.Number < E2->Dst.Number; } }; + public: typedef SmallVectorImpl<GCOVEdge *>::const_iterator EdgeIterator; - GCOVBlock(GCOVFunction &P, uint32_t N) : Parent(P), Number(N), Counter(0), - DstEdgesAreSorted(true), SrcEdges(), DstEdges(), Lines() {} + GCOVBlock(GCOVFunction &P, uint32_t N) + : Parent(P), Number(N), Counter(0), DstEdgesAreSorted(true), SrcEdges(), + DstEdges(), Lines() {} ~GCOVBlock(); const GCOVFunction &getParent() const { return Parent; } void addLine(uint32_t N) { Lines.push_back(N); } @@ -331,11 +333,19 @@ public: EdgeIterator src_begin() const { return SrcEdges.begin(); } EdgeIterator src_end() const { return SrcEdges.end(); } + iterator_range<EdgeIterator> srcs() const { + return make_range(src_begin(), src_end()); + } + EdgeIterator dst_begin() const { return DstEdges.begin(); } EdgeIterator dst_end() const { return DstEdges.end(); } + iterator_range<EdgeIterator> dsts() const { + return make_range(dst_begin(), dst_end()); + } void dump() const; void collectLineCounts(FileInfo &FI); + private: GCOVFunction &Parent; uint32_t Number; @@ -347,8 +357,10 @@ private: }; class FileInfo { - // It is unlikely--but possible--for multiple functions to be on the same line. - // Therefore this typedef allows LineData.Functions to store multiple functions + // It is unlikely--but possible--for multiple functions to be on the same + // line. + // Therefore this typedef allows LineData.Functions to store multiple + // functions // per instance. This is rare, however, so optimize for the common case. typedef SmallVector<const GCOVFunction *, 1> FunctionVector; typedef DenseMap<uint32_t, FunctionVector> FunctionLines; @@ -363,9 +375,9 @@ class FileInfo { }; struct GCOVCoverage { - GCOVCoverage(StringRef Name) : - Name(Name), LogicalLines(0), LinesExec(0), Branches(0), BranchesExec(0), - BranchesTaken(0) {} + GCOVCoverage(StringRef Name) + : Name(Name), LogicalLines(0), LinesExec(0), Branches(0), + BranchesExec(0), BranchesTaken(0) {} StringRef Name; @@ -376,30 +388,31 @@ class FileInfo { uint32_t BranchesExec; uint32_t BranchesTaken; }; + public: - FileInfo(const GCOVOptions &Options) : - Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {} + FileInfo(const GCOVOptions &Options) + : Options(Options), LineInfo(), RunCount(0), ProgramCount(0) {} void addBlockLine(StringRef Filename, uint32_t Line, const GCOVBlock *Block) { if (Line > LineInfo[Filename].LastLine) LineInfo[Filename].LastLine = Line; - LineInfo[Filename].Blocks[Line-1].push_back(Block); + LineInfo[Filename].Blocks[Line - 1].push_back(Block); } void addFunctionLine(StringRef Filename, uint32_t Line, const GCOVFunction *Function) { if (Line > LineInfo[Filename].LastLine) LineInfo[Filename].LastLine = Line; - LineInfo[Filename].Functions[Line-1].push_back(Function); + LineInfo[Filename].Functions[Line - 1].push_back(Function); } void setRunCount(uint32_t Runs) { RunCount = Runs; } void setProgramCount(uint32_t Programs) { ProgramCount = Programs; } - void print(StringRef MainFilename, StringRef GCNOFile, StringRef GCDAFile); + void print(raw_ostream &OS, StringRef MainFilename, StringRef GCNOFile, + StringRef GCDAFile); private: std::string getCoveragePath(StringRef Filename, StringRef MainFilename); std::unique_ptr<raw_ostream> openCoveragePath(StringRef CoveragePath); - void printFunctionSummary(raw_ostream &OS, - const FunctionVector &Funcs) const; + void printFunctionSummary(raw_ostream &OS, const FunctionVector &Funcs) const; void printBlockInfo(raw_ostream &OS, const GCOVBlock &Block, uint32_t LineIndex, uint32_t &BlockNo) const; void printBranchInfo(raw_ostream &OS, const GCOVBlock &Block, @@ -407,23 +420,21 @@ private: void printUncondBranchInfo(raw_ostream &OS, uint32_t &EdgeNo, uint64_t Count) const; - void printCoverage(const GCOVCoverage &Coverage) const; - void printFuncCoverage() const; - void printFileCoverage() const; + void printCoverage(raw_ostream &OS, const GCOVCoverage &Coverage) const; + void printFuncCoverage(raw_ostream &OS) const; + void printFileCoverage(raw_ostream &OS) const; const GCOVOptions &Options; StringMap<LineData> LineInfo; uint32_t RunCount; uint32_t ProgramCount; - typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4> - FileCoverageList; + typedef SmallVector<std::pair<std::string, GCOVCoverage>, 4> FileCoverageList; typedef MapVector<const GCOVFunction *, GCOVCoverage> FuncCoverageMap; FileCoverageList FileCoverages; FuncCoverageMap FuncCoverages; }; - } #endif diff --git a/include/llvm/Support/GenericDomTree.h b/include/llvm/Support/GenericDomTree.h index fde56135a962..63678bb98bb1 100644 --- a/include/llvm/Support/GenericDomTree.h +++ b/include/llvm/Support/GenericDomTree.h @@ -21,6 +21,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" @@ -93,8 +94,9 @@ public: DomTreeNodeBase(NodeT *BB, DomTreeNodeBase<NodeT> *iDom) : TheBB(BB), IDom(iDom), DFSNumIn(-1), DFSNumOut(-1) {} - DomTreeNodeBase<NodeT> *addChild(DomTreeNodeBase<NodeT> *C) { - Children.push_back(C); + std::unique_ptr<DomTreeNodeBase<NodeT>> + addChild(std::unique_ptr<DomTreeNodeBase<NodeT>> C) { + Children.push_back(C.get()); return C; } @@ -182,8 +184,8 @@ void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType> &DT, /// This class is a generic template over graph nodes. It is instantiated for /// various graphs in the LLVM IR or in the code generator. template <class NodeT> class DominatorTreeBase : public DominatorBase<NodeT> { - DominatorTreeBase(const DominatorTreeBase &) LLVM_DELETED_FUNCTION; - DominatorTreeBase &operator=(const DominatorTreeBase &) LLVM_DELETED_FUNCTION; + DominatorTreeBase(const DominatorTreeBase &) = delete; + DominatorTreeBase &operator=(const DominatorTreeBase &) = delete; bool dominatedBySlowTreeWalk(const DomTreeNodeBase<NodeT> *A, const DomTreeNodeBase<NodeT> *B) const { @@ -210,7 +212,8 @@ template <class NodeT> class DominatorTreeBase : public DominatorBase<NodeT> { } protected: - typedef DenseMap<NodeT *, DomTreeNodeBase<NodeT> *> DomTreeNodeMapType; + typedef DenseMap<NodeT *, std::unique_ptr<DomTreeNodeBase<NodeT>>> + DomTreeNodeMapType; DomTreeNodeMapType DomTreeNodes; DomTreeNodeBase<NodeT> *RootNode; @@ -235,15 +238,13 @@ protected: DenseMap<NodeT *, InfoRec> Info; void reset() { - for (typename DomTreeNodeMapType::iterator I = this->DomTreeNodes.begin(), - E = DomTreeNodes.end(); - I != E; ++I) - delete I->second; DomTreeNodes.clear(); IDoms.clear(); this->Roots.clear(); Vertex.clear(); RootNode = nullptr; + DFSInfoValid = false; + SlowQueries = 0; } // NewBB is split and now it has one successor. Update dominator tree to @@ -314,7 +315,6 @@ protected: public: explicit DominatorTreeBase(bool isPostDom) : DominatorBase<NodeT>(isPostDom), DFSInfoValid(false), SlowQueries(0) {} - ~DominatorTreeBase() { reset(); } DominatorTreeBase(DominatorTreeBase &&Arg) : DominatorBase<NodeT>( @@ -358,10 +358,10 @@ public: if (OI == OtherDomTreeNodes.end()) return true; - DomTreeNodeBase<NodeT> *MyNd = I->second; - DomTreeNodeBase<NodeT> *OtherNd = OI->second; + DomTreeNodeBase<NodeT> &MyNd = *I->second; + DomTreeNodeBase<NodeT> &OtherNd = *OI->second; - if (MyNd->compare(OtherNd)) + if (MyNd.compare(&OtherNd)) return true; } @@ -374,7 +374,10 @@ public: /// block. This is the same as using operator[] on this class. /// DomTreeNodeBase<NodeT> *getNode(NodeT *BB) const { - return DomTreeNodes.lookup(BB); + auto I = DomTreeNodes.find(BB); + if (I != DomTreeNodes.end()) + return I->second.get(); + return nullptr; } DomTreeNodeBase<NodeT> *operator[](NodeT *BB) const { return getNode(BB); } @@ -555,8 +558,8 @@ public: DomTreeNodeBase<NodeT> *IDomNode = getNode(DomBB); assert(IDomNode && "Not immediate dominator specified for block!"); DFSInfoValid = false; - return DomTreeNodes[BB] = - IDomNode->addChild(new DomTreeNodeBase<NodeT>(BB, IDomNode)); + return (DomTreeNodes[BB] = IDomNode->addChild( + llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))).get(); } /// changeImmediateDominator - This method is used to update the dominator @@ -593,15 +596,6 @@ public: } DomTreeNodes.erase(BB); - delete Node; - } - - /// removeNode - Removes a node from the dominator tree. Block must not - /// dominate any other blocks. Invalidates any node pointing to removed - /// block. - void removeNode(NodeT *BB) { - assert(getNode(BB) && "Removing node that isn't in dominator tree."); - DomTreeNodes.erase(BB); } /// splitBlock - BB is split and now it has one successor. Update dominator @@ -645,9 +639,38 @@ protected: friend void Calculate(DominatorTreeBase<typename GraphTraits<N>::NodeType> &DT, FuncT &F); + + DomTreeNodeBase<NodeT> *getNodeForBlock(NodeT *BB) { + if (DomTreeNodeBase<NodeT> *Node = getNode(BB)) + return Node; + + // Haven't calculated this node yet? Get or calculate the node for the + // immediate dominator. + NodeT *IDom = getIDom(BB); + + assert(IDom || this->DomTreeNodes[nullptr]); + DomTreeNodeBase<NodeT> *IDomNode = getNodeForBlock(IDom); + + // Add a new tree node for this NodeT, and link it as a child of + // IDomNode + return (this->DomTreeNodes[BB] = IDomNode->addChild( + llvm::make_unique<DomTreeNodeBase<NodeT>>(BB, IDomNode))).get(); + } + + NodeT *getIDom(NodeT *BB) const { return IDoms.lookup(BB); } + + void addRoot(NodeT *BB) { this->Roots.push_back(BB); } + +public: /// updateDFSNumbers - Assign In and Out numbers to the nodes while walking /// dominator tree in dfs order. void updateDFSNumbers() const { + + if (DFSInfoValid) { + SlowQueries = 0; + return; + } + unsigned DFSNum = 0; SmallVector<std::pair<const DomTreeNodeBase<NodeT> *, @@ -690,28 +713,6 @@ protected: DFSInfoValid = true; } - DomTreeNodeBase<NodeT> *getNodeForBlock(NodeT *BB) { - if (DomTreeNodeBase<NodeT> *Node = getNode(BB)) - return Node; - - // Haven't calculated this node yet? Get or calculate the node for the - // immediate dominator. - NodeT *IDom = getIDom(BB); - - assert(IDom || this->DomTreeNodes[nullptr]); - DomTreeNodeBase<NodeT> *IDomNode = getNodeForBlock(IDom); - - // Add a new tree node for this NodeT, and link it as a child of - // IDomNode - DomTreeNodeBase<NodeT> *C = new DomTreeNodeBase<NodeT>(BB, IDomNode); - return this->DomTreeNodes[BB] = IDomNode->addChild(C); - } - - NodeT *getIDom(NodeT *BB) const { return IDoms.lookup(BB); } - - void addRoot(NodeT *BB) { this->Roots.push_back(BB); } - -public: /// recalculate - compute a dominator tree for the given function template <class FT> void recalculate(FT &F) { typedef GraphTraits<FT *> TraitsTy; diff --git a/include/llvm/Support/GenericDomTreeConstruction.h b/include/llvm/Support/GenericDomTreeConstruction.h index ad4f8a9f429a..7c065f939256 100644 --- a/include/llvm/Support/GenericDomTreeConstruction.h +++ b/include/llvm/Support/GenericDomTreeConstruction.h @@ -251,15 +251,18 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT, // an infinite loop. typename GraphT::NodeType* Root = !MultipleRoots ? DT.Roots[0] : nullptr; - DT.DomTreeNodes[Root] = DT.RootNode = - new DomTreeNodeBase<typename GraphT::NodeType>(Root, nullptr); + DT.RootNode = + (DT.DomTreeNodes[Root] = + llvm::make_unique<DomTreeNodeBase<typename GraphT::NodeType>>( + Root, nullptr)).get(); // Loop over all of the reachable blocks in the function... for (unsigned i = 2; i <= N; ++i) { typename GraphT::NodeType* W = DT.Vertex[i]; - DomTreeNodeBase<typename GraphT::NodeType> *BBNode = DT.DomTreeNodes[W]; - if (BBNode) continue; // Haven't calculated this node yet? + // Don't replace this with 'count', the insertion side effect is important + if (DT.DomTreeNodes[W]) + continue; // Haven't calculated this node yet? typename GraphT::NodeType* ImmDom = DT.getIDom(W); @@ -271,15 +274,16 @@ void Calculate(DominatorTreeBase<typename GraphTraits<NodeT>::NodeType>& DT, // Add a new tree node for this BasicBlock, and link it as a child of // IDomNode - DomTreeNodeBase<typename GraphT::NodeType> *C = - new DomTreeNodeBase<typename GraphT::NodeType>(W, IDomNode); - DT.DomTreeNodes[W] = IDomNode->addChild(C); + DT.DomTreeNodes[W] = IDomNode->addChild( + llvm::make_unique<DomTreeNodeBase<typename GraphT::NodeType>>( + W, IDomNode)); } // Free temporary memory used to construct idom's DT.IDoms.clear(); DT.Info.clear(); - std::vector<typename GraphT::NodeType*>().swap(DT.Vertex); + DT.Vertex.clear(); + DT.Vertex.shrink_to_fit(); DT.updateDFSNumbers(); } diff --git a/include/llvm/Support/GraphWriter.h b/include/llvm/Support/GraphWriter.h index 2f02aa7a1c19..7d1c273c988d 100644 --- a/include/llvm/Support/GraphWriter.h +++ b/include/llvm/Support/GraphWriter.h @@ -24,10 +24,9 @@ #define LLVM_SUPPORT_GRAPHWRITER_H #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/Twine.h" #include "llvm/Support/DOTGraphTraits.h" -#include "llvm/Support/Path.h" #include "llvm/Support/raw_ostream.h" -#include <cassert> #include <vector> namespace llvm { diff --git a/include/llvm/Support/LockFileManager.h b/include/llvm/Support/LockFileManager.h index 61c65dabae3c..8e88d4279bd8 100644 --- a/include/llvm/Support/LockFileManager.h +++ b/include/llvm/Support/LockFileManager.h @@ -57,8 +57,8 @@ private: Optional<std::pair<std::string, int> > Owner; Optional<std::error_code> Error; - LockFileManager(const LockFileManager &) LLVM_DELETED_FUNCTION; - LockFileManager &operator=(const LockFileManager &) LLVM_DELETED_FUNCTION; + LockFileManager(const LockFileManager &) = delete; + LockFileManager &operator=(const LockFileManager &) = delete; static Optional<std::pair<std::string, int> > readLockFile(StringRef LockFileName); @@ -77,6 +77,10 @@ public: /// \brief For a shared lock, wait until the owner releases the lock. WaitForUnlockResult waitForUnlock(); + + /// \brief Remove the lock file. This may delete a different lock file than + /// the one previously read if there is a race. + std::error_code unsafeRemoveLockFile(); }; } // end namespace llvm diff --git a/include/llvm/Support/MathExtras.h b/include/llvm/Support/MathExtras.h index 698363614ac5..e3166165a483 100644 --- a/include/llvm/Support/MathExtras.h +++ b/include/llvm/Support/MathExtras.h @@ -24,6 +24,10 @@ #include <intrin.h> #endif +#ifdef __ANDROID_NDK__ +#include <android/api-level.h> +#endif + namespace llvm { /// \brief The behavior an operation has on an input of 0. enum ZeroBehavior { @@ -35,78 +39,66 @@ enum ZeroBehavior { ZB_Width }; -/// \brief Count number of 0's from the least significant bit to the most -/// stopping at the first 1. -/// -/// Only unsigned integral types are allowed. -/// -/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are -/// valid arguments. -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, std::size_t>::type -countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { - (void)ZB; - - if (!Val) - return std::numeric_limits<T>::digits; - if (Val & 0x1) - return 0; - - // Bisection method. - std::size_t ZeroBits = 0; - T Shift = std::numeric_limits<T>::digits >> 1; - T Mask = std::numeric_limits<T>::max() >> Shift; - while (Shift) { - if ((Val & Mask) == 0) { - Val >>= Shift; - ZeroBits |= Shift; +namespace detail { +template <typename T, std::size_t SizeOfT> struct TrailingZerosCounter { + static std::size_t count(T Val, ZeroBehavior) { + if (!Val) + return std::numeric_limits<T>::digits; + if (Val & 0x1) + return 0; + + // Bisection method. + std::size_t ZeroBits = 0; + T Shift = std::numeric_limits<T>::digits >> 1; + T Mask = std::numeric_limits<T>::max() >> Shift; + while (Shift) { + if ((Val & Mask) == 0) { + Val >>= Shift; + ZeroBits |= Shift; + } + Shift >>= 1; + Mask >>= Shift; } - Shift >>= 1; - Mask >>= Shift; + return ZeroBits; } - return ZeroBits; -} - -// Disable signed. -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, std::size_t>::type -countTrailingZeros(T, ZeroBehavior = ZB_Width) LLVM_DELETED_FUNCTION; +}; #if __GNUC__ >= 4 || _MSC_VER -template <> -inline std::size_t countTrailingZeros<uint32_t>(uint32_t Val, ZeroBehavior ZB) { - if (ZB != ZB_Undefined && Val == 0) - return 32; +template <typename T> struct TrailingZerosCounter<T, 4> { + static std::size_t count(T Val, ZeroBehavior ZB) { + if (ZB != ZB_Undefined && Val == 0) + return 32; #if __has_builtin(__builtin_ctz) || LLVM_GNUC_PREREQ(4, 0, 0) - return __builtin_ctz(Val); + return __builtin_ctz(Val); #elif _MSC_VER - unsigned long Index; - _BitScanForward(&Index, Val); - return Index; + unsigned long Index; + _BitScanForward(&Index, Val); + return Index; #endif -} + } +}; #if !defined(_MSC_VER) || defined(_M_X64) -template <> -inline std::size_t countTrailingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) { - if (ZB != ZB_Undefined && Val == 0) - return 64; +template <typename T> struct TrailingZerosCounter<T, 8> { + static std::size_t count(T Val, ZeroBehavior ZB) { + if (ZB != ZB_Undefined && Val == 0) + return 64; #if __has_builtin(__builtin_ctzll) || LLVM_GNUC_PREREQ(4, 0, 0) - return __builtin_ctzll(Val); + return __builtin_ctzll(Val); #elif _MSC_VER - unsigned long Index; - _BitScanForward64(&Index, Val); - return Index; + unsigned long Index; + _BitScanForward64(&Index, Val); + return Index; #endif -} + } +}; #endif #endif +} // namespace detail -/// \brief Count number of 0's from the most significant bit to the least +/// \brief Count number of 0's from the least significant bit to the most /// stopping at the first 1. /// /// Only unsigned integral types are allowed. @@ -114,63 +106,81 @@ inline std::size_t countTrailingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) { /// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are /// valid arguments. template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, std::size_t>::type -countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { - (void)ZB; - - if (!Val) - return std::numeric_limits<T>::digits; - - // Bisection method. - std::size_t ZeroBits = 0; - for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) { - T Tmp = Val >> Shift; - if (Tmp) - Val = Tmp; - else - ZeroBits |= Shift; +std::size_t countTrailingZeros(T Val, ZeroBehavior ZB = ZB_Width) { + static_assert(std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + "Only unsigned integral types are allowed."); + return detail::TrailingZerosCounter<T, sizeof(T)>::count(Val, ZB); +} + +namespace detail { +template <typename T, std::size_t SizeOfT> struct LeadingZerosCounter { + static std::size_t count(T Val, ZeroBehavior) { + if (!Val) + return std::numeric_limits<T>::digits; + + // Bisection method. + std::size_t ZeroBits = 0; + for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) { + T Tmp = Val >> Shift; + if (Tmp) + Val = Tmp; + else + ZeroBits |= Shift; + } + return ZeroBits; } - return ZeroBits; -} - -// Disable signed. -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, std::size_t>::type -countLeadingZeros(T, ZeroBehavior = ZB_Width) LLVM_DELETED_FUNCTION; +}; #if __GNUC__ >= 4 || _MSC_VER -template <> -inline std::size_t countLeadingZeros<uint32_t>(uint32_t Val, ZeroBehavior ZB) { - if (ZB != ZB_Undefined && Val == 0) - return 32; +template <typename T> struct LeadingZerosCounter<T, 4> { + static std::size_t count(T Val, ZeroBehavior ZB) { + if (ZB != ZB_Undefined && Val == 0) + return 32; #if __has_builtin(__builtin_clz) || LLVM_GNUC_PREREQ(4, 0, 0) - return __builtin_clz(Val); + return __builtin_clz(Val); #elif _MSC_VER - unsigned long Index; - _BitScanReverse(&Index, Val); - return Index ^ 31; + unsigned long Index; + _BitScanReverse(&Index, Val); + return Index ^ 31; #endif -} + } +}; #if !defined(_MSC_VER) || defined(_M_X64) -template <> -inline std::size_t countLeadingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) { - if (ZB != ZB_Undefined && Val == 0) - return 64; +template <typename T> struct LeadingZerosCounter<T, 8> { + static std::size_t count(T Val, ZeroBehavior ZB) { + if (ZB != ZB_Undefined && Val == 0) + return 64; #if __has_builtin(__builtin_clzll) || LLVM_GNUC_PREREQ(4, 0, 0) - return __builtin_clzll(Val); + return __builtin_clzll(Val); #elif _MSC_VER - unsigned long Index; - _BitScanReverse64(&Index, Val); - return Index ^ 63; + unsigned long Index; + _BitScanReverse64(&Index, Val); + return Index ^ 63; #endif -} + } +}; #endif #endif +} // namespace detail + +/// \brief Count number of 0's from the most significant bit to the least +/// stopping at the first 1. +/// +/// Only unsigned integral types are allowed. +/// +/// \param ZB the behavior on an input of 0. Only ZB_Width and ZB_Undefined are +/// valid arguments. +template <typename T> +std::size_t countLeadingZeros(T Val, ZeroBehavior ZB = ZB_Width) { + static_assert(std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + "Only unsigned integral types are allowed."); + return detail::LeadingZerosCounter<T, sizeof(T)>::count(Val, ZB); +} /// \brief Get the index of the first set bit starting from the least /// significant bit. @@ -179,22 +189,13 @@ inline std::size_t countLeadingZeros<uint64_t>(uint64_t Val, ZeroBehavior ZB) { /// /// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are /// valid arguments. -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, T>::type -findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { +template <typename T> T findFirstSet(T Val, ZeroBehavior ZB = ZB_Max) { if (ZB == ZB_Max && Val == 0) return std::numeric_limits<T>::max(); return countTrailingZeros(Val, ZB_Undefined); } -// Disable signed. -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, T>::type -findFirstSet(T, ZeroBehavior = ZB_Max) LLVM_DELETED_FUNCTION; - /// \brief Get the index of the last set bit starting from the least /// significant bit. /// @@ -202,10 +203,7 @@ findFirstSet(T, ZeroBehavior = ZB_Max) LLVM_DELETED_FUNCTION; /// /// \param ZB the behavior on an input of 0. Only ZB_Max and ZB_Undefined are /// valid arguments. -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - !std::numeric_limits<T>::is_signed, T>::type -findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { +template <typename T> T findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { if (ZB == ZB_Max && Val == 0) return std::numeric_limits<T>::max(); @@ -215,12 +213,6 @@ findLastSet(T Val, ZeroBehavior ZB = ZB_Max) { (std::numeric_limits<T>::digits - 1); } -// Disable signed. -template <typename T> -typename std::enable_if<std::numeric_limits<T>::is_integer && - std::numeric_limits<T>::is_signed, T>::type -findLastSet(T, ZeroBehavior = ZB_Max) LLVM_DELETED_FUNCTION; - /// \brief Macro compressed bit reversal table for 256 bits. /// /// http://graphics.stanford.edu/~seander/bithacks.html#BitReverseTable @@ -330,31 +322,31 @@ inline bool isIntN(unsigned N, int64_t x) { return N >= 64 || (-(INT64_C(1)<<(N-1)) <= x && x < (INT64_C(1)<<(N-1))); } -/// isMask_32 - This function returns true if the argument is a sequence of ones -/// starting at the least significant bit with the remainder zero (32 bit -/// version). Ex. isMask_32(0x0000FFFFU) == true. +/// isMask_32 - This function returns true if the argument is a non-empty +/// sequence of ones starting at the least significant bit with the remainder +/// zero (32 bit version). Ex. isMask_32(0x0000FFFFU) == true. inline bool isMask_32(uint32_t Value) { return Value && ((Value + 1) & Value) == 0; } -/// isMask_64 - This function returns true if the argument is a sequence of ones -/// starting at the least significant bit with the remainder zero (64 bit -/// version). +/// isMask_64 - This function returns true if the argument is a non-empty +/// sequence of ones starting at the least significant bit with the remainder +/// zero (64 bit version). inline bool isMask_64(uint64_t Value) { return Value && ((Value + 1) & Value) == 0; } /// isShiftedMask_32 - This function returns true if the argument contains a -/// sequence of ones with the remainder zero (32 bit version.) +/// non-empty sequence of ones with the remainder zero (32 bit version.) /// Ex. isShiftedMask_32(0x0000FF00U) == true. inline bool isShiftedMask_32(uint32_t Value) { - return isMask_32((Value - 1) | Value); + return Value && isMask_32((Value - 1) | Value); } /// isShiftedMask_64 - This function returns true if the argument contains a -/// sequence of ones with the remainder zero (64 bit version.) +/// non-empty sequence of ones with the remainder zero (64 bit version.) inline bool isShiftedMask_64(uint64_t Value) { - return isMask_64((Value - 1) | Value); + return Value && isMask_64((Value - 1) | Value); } /// isPowerOf2_32 - This function returns true if the argument is a power of @@ -387,61 +379,86 @@ inline uint64_t ByteSwap_64(uint64_t Value) { return sys::SwapByteOrder_64(Value); } -/// CountLeadingOnes_32 - this function performs the operation of -/// counting the number of ones from the most significant bit to the first zero -/// bit. Ex. CountLeadingOnes_32(0xFF0FFF00) == 8. -/// Returns 32 if the word is all ones. -inline unsigned CountLeadingOnes_32(uint32_t Value) { - return countLeadingZeros(~Value); -} - -/// CountLeadingOnes_64 - This function performs the operation -/// of counting the number of ones from the most significant bit to the first -/// zero bit (64 bit edition.) -/// Returns 64 if the word is all ones. -inline unsigned CountLeadingOnes_64(uint64_t Value) { - return countLeadingZeros(~Value); -} - -/// CountTrailingOnes_32 - this function performs the operation of -/// counting the number of ones from the least significant bit to the first zero -/// bit. Ex. CountTrailingOnes_32(0x00FF00FF) == 8. -/// Returns 32 if the word is all ones. -inline unsigned CountTrailingOnes_32(uint32_t Value) { - return countTrailingZeros(~Value); +/// \brief Count the number of ones from the most significant bit to the first +/// zero bit. +/// +/// Ex. CountLeadingOnes(0xFF0FFF00) == 8. +/// Only unsigned integral types are allowed. +/// +/// \param ZB the behavior on an input of all ones. Only ZB_Width and +/// ZB_Undefined are valid arguments. +template <typename T> +std::size_t countLeadingOnes(T Value, ZeroBehavior ZB = ZB_Width) { + static_assert(std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + "Only unsigned integral types are allowed."); + return countLeadingZeros(~Value, ZB); } -/// CountTrailingOnes_64 - This function performs the operation -/// of counting the number of ones from the least significant bit to the first -/// zero bit (64 bit edition.) -/// Returns 64 if the word is all ones. -inline unsigned CountTrailingOnes_64(uint64_t Value) { - return countTrailingZeros(~Value); -} +/// \brief Count the number of ones from the least significant bit to the first +/// zero bit. +/// +/// Ex. countTrailingOnes(0x00FF00FF) == 8. +/// Only unsigned integral types are allowed. +/// +/// \param ZB the behavior on an input of all ones. Only ZB_Width and +/// ZB_Undefined are valid arguments. +template <typename T> +std::size_t countTrailingOnes(T Value, ZeroBehavior ZB = ZB_Width) { + static_assert(std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + "Only unsigned integral types are allowed."); + return countTrailingZeros(~Value, ZB); +} + +namespace detail { +template <typename T, std::size_t SizeOfT> struct PopulationCounter { + static unsigned count(T Value) { + // Generic version, forward to 32 bits. + static_assert(SizeOfT <= 4, "Not implemented!"); +#if __GNUC__ >= 4 + return __builtin_popcount(Value); +#else + uint32_t v = Value; + v = v - ((v >> 1) & 0x55555555); + v = (v & 0x33333333) + ((v >> 2) & 0x33333333); + return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; +#endif + } +}; -/// CountPopulation_32 - this function counts the number of set bits in a value. -/// Ex. CountPopulation(0xF000F000) = 8 -/// Returns 0 if the word is zero. -inline unsigned CountPopulation_32(uint32_t Value) { +template <typename T> struct PopulationCounter<T, 8> { + static unsigned count(T Value) { #if __GNUC__ >= 4 - return __builtin_popcount(Value); + return __builtin_popcountll(Value); #else - uint32_t v = Value - ((Value >> 1) & 0x55555555); - v = (v & 0x33333333) + ((v >> 2) & 0x33333333); - return ((v + (v >> 4) & 0xF0F0F0F) * 0x1010101) >> 24; + uint64_t v = Value; + v = v - ((v >> 1) & 0x5555555555555555ULL); + v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); + v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; + return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); #endif + } +}; +} // namespace detail + +/// \brief Count the number of set bits in a value. +/// Ex. countPopulation(0xF000F000) = 8 +/// Returns 0 if the word is zero. +template <typename T> +inline unsigned countPopulation(T Value) { + static_assert(std::numeric_limits<T>::is_integer && + !std::numeric_limits<T>::is_signed, + "Only unsigned integral types are allowed."); + return detail::PopulationCounter<T, sizeof(T)>::count(Value); } -/// CountPopulation_64 - this function counts the number of set bits in a value, -/// (64 bit edition.) -inline unsigned CountPopulation_64(uint64_t Value) { -#if __GNUC__ >= 4 - return __builtin_popcountll(Value); +/// Log2 - This function returns the log base 2 of the specified value +inline double Log2(double Value) { +#if defined(__ANDROID_API__) && __ANDROID_API__ < 18 + return __builtin_log(Value) / __builtin_log(2.0); #else - uint64_t v = Value - ((Value >> 1) & 0x5555555555555555ULL); - v = (v & 0x3333333333333333ULL) + ((v >> 2) & 0x3333333333333333ULL); - v = (v + (v >> 4)) & 0x0F0F0F0F0F0F0F0FULL; - return unsigned((uint64_t)(v * 0x0101010101010101ULL) >> 56); + return log2(Value); #endif } @@ -530,14 +547,6 @@ inline uint32_t FloatToBits(float Float) { return T.I; } -/// Platform-independent wrappers for the C99 isnan() function. -int IsNAN(float f); -int IsNAN(double d); - -/// Platform-independent wrappers for the C99 isinf() function. -int IsInf(float f); -int IsInf(double d); - /// MinAlign - A and B are either alignments or offsets. Return the minimum /// alignment that may be assumed after adding the two together. inline uint64_t MinAlign(uint64_t A, uint64_t B) { @@ -608,13 +617,6 @@ inline uint64_t OffsetToAlignment(uint64_t Value, uint64_t Align) { return RoundUpToAlignment(Value, Align) - Value; } -/// abs64 - absolute value of a 64-bit int. Not all environments support -/// "abs" on whatever their name for the 64-bit int type is. The absolute -/// value of the largest negative number is undefined, as with "abs". -inline int64_t abs64(int64_t x) { - return (x < 0) ? -x : x; -} - /// SignExtend32 - Sign extend B-bit number x to 32-bit int. /// Usage int32_t r = SignExtend32<5>(x); template <unsigned B> inline int32_t SignExtend32(uint32_t x) { diff --git a/include/llvm/Support/MemoryBuffer.h b/include/llvm/Support/MemoryBuffer.h index e2f8d7e90fef..35a7bdb004a9 100644 --- a/include/llvm/Support/MemoryBuffer.h +++ b/include/llvm/Support/MemoryBuffer.h @@ -17,11 +17,9 @@ #include "llvm-c/Support.h" #include "llvm/ADT/Twine.h" #include "llvm/Support/CBindingWrapping.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/ErrorOr.h" #include <memory> -#include <system_error> namespace llvm { class MemoryBufferRef; @@ -40,8 +38,8 @@ class MemoryBuffer { const char *BufferStart; // Start of the buffer. const char *BufferEnd; // End of the buffer. - MemoryBuffer(const MemoryBuffer &) LLVM_DELETED_FUNCTION; - MemoryBuffer &operator=(const MemoryBuffer &) LLVM_DELETED_FUNCTION; + MemoryBuffer(const MemoryBuffer &) = delete; + MemoryBuffer &operator=(const MemoryBuffer &) = delete; protected: MemoryBuffer() {} void init(const char *BufStart, const char *BufEnd, diff --git a/include/llvm/Support/MipsABIFlags.h b/include/llvm/Support/MipsABIFlags.h new file mode 100644 index 000000000000..93f6b416ba88 --- /dev/null +++ b/include/llvm/Support/MipsABIFlags.h @@ -0,0 +1,102 @@ +//===--- MipsABIFlags.h - MIPS ABI flags ----------------------------------===// +// +// 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 constants for the ABI flags structure contained +// in the .MIPS.abiflags section. +// +// https://dmz-portal.mips.com/wiki/MIPS_O32_ABI_-_FR0_and_FR1_Interlinking +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_MIPSABIFLAGS_H +#define LLVM_SUPPORT_MIPSABIFLAGS_H + +namespace llvm { +namespace Mips { + +// Values for the xxx_size bytes of an ABI flags structure. +enum AFL_REG { + AFL_REG_NONE = 0x00, // No registers + AFL_REG_32 = 0x01, // 32-bit registers + AFL_REG_64 = 0x02, // 64-bit registers + AFL_REG_128 = 0x03 // 128-bit registers +}; + +// Masks for the ases word of an ABI flags structure. +enum AFL_ASE { + AFL_ASE_DSP = 0x00000001, // DSP ASE + AFL_ASE_DSPR2 = 0x00000002, // DSP R2 ASE + AFL_ASE_EVA = 0x00000004, // Enhanced VA Scheme + AFL_ASE_MCU = 0x00000008, // MCU (MicroController) ASE + AFL_ASE_MDMX = 0x00000010, // MDMX ASE + AFL_ASE_MIPS3D = 0x00000020, // MIPS-3D ASE + AFL_ASE_MT = 0x00000040, // MT ASE + AFL_ASE_SMARTMIPS = 0x00000080, // SmartMIPS ASE + AFL_ASE_VIRT = 0x00000100, // VZ ASE + AFL_ASE_MSA = 0x00000200, // MSA ASE + AFL_ASE_MIPS16 = 0x00000400, // MIPS16 ASE + AFL_ASE_MICROMIPS = 0x00000800, // MICROMIPS ASE + AFL_ASE_XPA = 0x00001000 // XPA ASE +}; + +// Values for the isa_ext word of an ABI flags structure. +enum AFL_EXT { + AFL_EXT_NONE = 0, // None + AFL_EXT_XLR = 1, // RMI Xlr instruction + AFL_EXT_OCTEON2 = 2, // Cavium Networks Octeon2 + AFL_EXT_OCTEONP = 3, // Cavium Networks OcteonP + AFL_EXT_LOONGSON_3A = 4, // Loongson 3A + AFL_EXT_OCTEON = 5, // Cavium Networks Octeon + AFL_EXT_5900 = 6, // MIPS R5900 instruction + AFL_EXT_4650 = 7, // MIPS R4650 instruction + AFL_EXT_4010 = 8, // LSI R4010 instruction + AFL_EXT_4100 = 9, // NEC VR4100 instruction + AFL_EXT_3900 = 10, // Toshiba R3900 instruction + AFL_EXT_10000 = 11, // MIPS R10000 instruction + AFL_EXT_SB1 = 12, // Broadcom SB-1 instruction + AFL_EXT_4111 = 13, // NEC VR4111/VR4181 instruction + AFL_EXT_4120 = 14, // NEC VR4120 instruction + AFL_EXT_5400 = 15, // NEC VR5400 instruction + AFL_EXT_5500 = 16, // NEC VR5500 instruction + AFL_EXT_LOONGSON_2E = 17, // ST Microelectronics Loongson 2E + AFL_EXT_LOONGSON_2F = 18, // ST Microelectronics Loongson 2F + AFL_EXT_OCTEON3 = 19 // Cavium Networks Octeon3 +}; + +// Values for the flags1 word of an ABI flags structure. +enum AFL_FLAGS1 { AFL_FLAGS1_ODDSPREG = 1 }; + +// MIPS object attribute tags +enum { + Tag_GNU_MIPS_ABI_FP = 4, // Floating-point ABI used by this object file + Tag_GNU_MIPS_ABI_MSA = 8, // MSA ABI used by this object file +}; + +// Values for the fp_abi word of an ABI flags structure +// and for the Tag_GNU_MIPS_ABI_FP attribute tag. +enum Val_GNU_MIPS_ABI_FP { + Val_GNU_MIPS_ABI_FP_ANY = 0, // not tagged + Val_GNU_MIPS_ABI_FP_DOUBLE = 1, // hard float / -mdouble-float + Val_GNU_MIPS_ABI_FP_SINGLE = 2, // hard float / -msingle-float + Val_GNU_MIPS_ABI_FP_SOFT = 3, // soft float + Val_GNU_MIPS_ABI_FP_OLD_64 = 4, // -mips32r2 -mfp64 + Val_GNU_MIPS_ABI_FP_XX = 5, // -mfpxx + Val_GNU_MIPS_ABI_FP_64 = 6, // -mips32r2 -mfp64 + Val_GNU_MIPS_ABI_FP_64A = 7 // -mips32r2 -mfp64 -mno-odd-spreg +}; + +// Values for the Tag_GNU_MIPS_ABI_MSA attribute tag. +enum Val_GNU_MIPS_ABI_MSA { + Val_GNU_MIPS_ABI_MSA_ANY = 0, // not tagged + Val_GNU_MIPS_ABI_MSA_128 = 1 // 128-bit MSA +}; +} +} + +#endif diff --git a/include/llvm/Support/Mutex.h b/include/llvm/Support/Mutex.h index 97dd50115322..0f4e61af4439 100644 --- a/include/llvm/Support/Mutex.h +++ b/include/llvm/Support/Mutex.h @@ -70,14 +70,16 @@ namespace llvm /// @name Platform Dependent Data /// @{ private: +#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0 void* data_; ///< We don't know what the data will be +#endif /// @} /// @name Do Not Implement /// @{ private: - MutexImpl(const MutexImpl &) LLVM_DELETED_FUNCTION; - void operator=(const MutexImpl &) LLVM_DELETED_FUNCTION; + MutexImpl(const MutexImpl &) = delete; + void operator=(const MutexImpl &) = delete; /// @} }; diff --git a/include/llvm/Support/MutexGuard.h b/include/llvm/Support/MutexGuard.h index b9f941dab323..07b64b611960 100644 --- a/include/llvm/Support/MutexGuard.h +++ b/include/llvm/Support/MutexGuard.h @@ -26,8 +26,8 @@ namespace llvm { /// @brief Guard a section of code with a Mutex. class MutexGuard { sys::Mutex &M; - MutexGuard(const MutexGuard &) LLVM_DELETED_FUNCTION; - void operator=(const MutexGuard &) LLVM_DELETED_FUNCTION; + MutexGuard(const MutexGuard &) = delete; + void operator=(const MutexGuard &) = delete; public: MutexGuard(sys::Mutex &m) : M(m) { M.lock(); } ~MutexGuard() { M.unlock(); } diff --git a/include/llvm/Support/OnDiskHashTable.h b/include/llvm/Support/OnDiskHashTable.h index 52f133ccff68..0f097f287286 100644 --- a/include/llvm/Support/OnDiskHashTable.h +++ b/include/llvm/Support/OnDiskHashTable.h @@ -75,13 +75,10 @@ template <typename Info> class OnDiskChainedHashTableGenerator { llvm::SpecificBumpPtrAllocator<Item> BA; /// \brief A linked list of values in a particular hash bucket. - class Bucket { - public: + struct Bucket { offset_type Off; - Item *Head; unsigned Length; - - Bucket() {} + Item *Head; }; Bucket *Buckets; diff --git a/include/llvm/Support/Options.h b/include/llvm/Support/Options.h index 4fd1bff358fd..2742d3907c62 100644 --- a/include/llvm/Support/Options.h +++ b/include/llvm/Support/Options.h @@ -61,7 +61,7 @@ char OptionKey<ValT, Base, Mem>::ID = 0; /// The OptionRegistry is responsible for managing lifetimes of the options and /// provides interfaces for option registration and reading values from options. /// This object is a singleton, only one instance should ever exist so that all -/// options are registered in teh same place. +/// options are registered in the same place. class OptionRegistry { private: DenseMap<void *, cl::Option *> Options; diff --git a/include/llvm/Support/PrettyStackTrace.h b/include/llvm/Support/PrettyStackTrace.h index 914141ad3c4b..96afb60d8e51 100644 --- a/include/llvm/Support/PrettyStackTrace.h +++ b/include/llvm/Support/PrettyStackTrace.h @@ -30,8 +30,8 @@ namespace llvm { /// virtual stack trace. This gets dumped out if the program crashes. class PrettyStackTraceEntry { const PrettyStackTraceEntry *NextEntry; - PrettyStackTraceEntry(const PrettyStackTraceEntry &) LLVM_DELETED_FUNCTION; - void operator=(const PrettyStackTraceEntry&) LLVM_DELETED_FUNCTION; + PrettyStackTraceEntry(const PrettyStackTraceEntry &) = delete; + void operator=(const PrettyStackTraceEntry&) = delete; public: PrettyStackTraceEntry(); virtual ~PrettyStackTraceEntry(); diff --git a/include/llvm/Support/Program.h b/include/llvm/Support/Program.h index 40dc60fa30d6..b89a0f73ec68 100644 --- a/include/llvm/Support/Program.h +++ b/include/llvm/Support/Program.h @@ -16,10 +16,11 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/ErrorOr.h" -#include "llvm/Support/Path.h" #include <system_error> namespace llvm { +class StringRef; + namespace sys { /// This is the OS-specific separator for PATH like environment variables: diff --git a/include/llvm/Support/RWMutex.h b/include/llvm/Support/RWMutex.h index b80b8557576b..4be931337765 100644 --- a/include/llvm/Support/RWMutex.h +++ b/include/llvm/Support/RWMutex.h @@ -70,14 +70,16 @@ namespace llvm /// @name Platform Dependent Data /// @{ private: +#if defined(LLVM_ENABLE_THREADS) && LLVM_ENABLE_THREADS != 0 void* data_; ///< We don't know what the data will be +#endif /// @} /// @name Do Not Implement /// @{ private: - RWMutexImpl(const RWMutexImpl & original) LLVM_DELETED_FUNCTION; - void operator=(const RWMutexImpl &) LLVM_DELETED_FUNCTION; + RWMutexImpl(const RWMutexImpl & original) = delete; + void operator=(const RWMutexImpl &) = delete; /// @} }; diff --git a/include/llvm/Support/RandomNumberGenerator.h b/include/llvm/Support/RandomNumberGenerator.h index 7ada34f075e4..7446558f0c88 100644 --- a/include/llvm/Support/RandomNumberGenerator.h +++ b/include/llvm/Support/RandomNumberGenerator.h @@ -48,10 +48,8 @@ private: std::mt19937_64 Generator; // Noncopyable. - RandomNumberGenerator(const RandomNumberGenerator &other) - LLVM_DELETED_FUNCTION; - RandomNumberGenerator & - operator=(const RandomNumberGenerator &other) LLVM_DELETED_FUNCTION; + RandomNumberGenerator(const RandomNumberGenerator &other) = delete; + RandomNumberGenerator &operator=(const RandomNumberGenerator &other) = delete; friend class Module; }; diff --git a/include/llvm/Support/Regex.h b/include/llvm/Support/Regex.h index bf533ca1aa60..31b35ed0cad6 100644 --- a/include/llvm/Support/Regex.h +++ b/include/llvm/Support/Regex.h @@ -17,7 +17,6 @@ #ifndef LLVM_SUPPORT_REGEX_H #define LLVM_SUPPORT_REGEX_H -#include "llvm/Support/Compiler.h" #include <string> struct llvm_regex; @@ -46,7 +45,7 @@ namespace llvm { /// Compiles the given regular expression \p Regex. Regex(StringRef Regex, unsigned Flags = NoFlags); - Regex(const Regex &) LLVM_DELETED_FUNCTION; + Regex(const Regex &) = delete; Regex &operator=(Regex regex) { std::swap(preg, regex.preg); std::swap(error, regex.error); diff --git a/include/llvm/Support/Registry.h b/include/llvm/Support/Registry.h index e21269b2f1d5..95c4e96f7f29 100644 --- a/include/llvm/Support/Registry.h +++ b/include/llvm/Support/Registry.h @@ -14,6 +14,7 @@ #ifndef LLVM_SUPPORT_REGISTRY_H #define LLVM_SUPPORT_REGISTRY_H +#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/Compiler.h" #include <memory> @@ -41,7 +42,7 @@ namespace llvm { /// is necessary to define an alternate traits class. template <typename T> class RegistryTraits { - RegistryTraits() LLVM_DELETED_FUNCTION; + RegistryTraits() = delete; public: typedef SimpleRegistryEntry<T> entry; @@ -67,7 +68,7 @@ namespace llvm { class iterator; private: - Registry() LLVM_DELETED_FUNCTION; + Registry() = delete; static void Announce(const entry &E) { for (listener *Cur = ListenerHead; Cur; Cur = Cur->Next) @@ -120,6 +121,10 @@ namespace llvm { static iterator begin() { return iterator(Head); } static iterator end() { return iterator(nullptr); } + static iterator_range<iterator> entries() { + return iterator_range<iterator>(begin(), end()); + } + /// Abstract base class for registry listeners, which are informed when new /// entries are added to the registry. Simply subclass and instantiate: diff --git a/include/llvm/Support/ScaledNumber.h b/include/llvm/Support/ScaledNumber.h index a1c4c80c356f..0a4262b7eec5 100644 --- a/include/llvm/Support/ScaledNumber.h +++ b/include/llvm/Support/ScaledNumber.h @@ -514,7 +514,7 @@ public: : Digits(Digits), Scale(Scale) {} private: - ScaledNumber(const std::pair<uint64_t, int16_t> &X) + ScaledNumber(const std::pair<DigitsT, int16_t> &X) : Digits(X.first), Scale(X.second) {} public: @@ -670,14 +670,7 @@ public: return ScaledNumbers::compare(Digits, Scale, X.Digits, X.Scale); } int compareTo(uint64_t N) const { - ScaledNumber Scaled = get(N); - int Compare = compare(Scaled); - if (Width == 64 || Compare != 0) - return Compare; - - // Check for precision loss. We know *this == RoundTrip. - uint64_t RoundTrip = Scaled.template toInt<uint64_t>(); - return N == RoundTrip ? 0 : RoundTrip < N ? -1 : 1; + return ScaledNumbers::compare<uint64_t>(Digits, Scale, N, 0); } int compareTo(int64_t N) const { return N < 0 ? 1 : compareTo(uint64_t(N)); } @@ -732,11 +725,21 @@ SCALED_NUMBER_BOP(+, += ) SCALED_NUMBER_BOP(-, -= ) SCALED_NUMBER_BOP(*, *= ) SCALED_NUMBER_BOP(/, /= ) -SCALED_NUMBER_BOP(<<, <<= ) -SCALED_NUMBER_BOP(>>, >>= ) #undef SCALED_NUMBER_BOP template <class DigitsT> +ScaledNumber<DigitsT> operator<<(const ScaledNumber<DigitsT> &L, + int16_t Shift) { + return ScaledNumber<DigitsT>(L) <<= Shift; +} + +template <class DigitsT> +ScaledNumber<DigitsT> operator>>(const ScaledNumber<DigitsT> &L, + int16_t Shift) { + return ScaledNumber<DigitsT>(L) >>= Shift; +} + +template <class DigitsT> raw_ostream &operator<<(raw_ostream &OS, const ScaledNumber<DigitsT> &X) { return X.print(OS, 10); } diff --git a/include/llvm/Support/Signals.h b/include/llvm/Support/Signals.h index 6cbc1f6854a6..7e165d7f3a42 100644 --- a/include/llvm/Support/Signals.h +++ b/include/llvm/Support/Signals.h @@ -15,10 +15,12 @@ #ifndef LLVM_SUPPORT_SIGNALS_H #define LLVM_SUPPORT_SIGNALS_H -#include "llvm/Support/Path.h" -#include <cstdio> +#include <string> namespace llvm { +class StringRef; +class raw_ostream; + namespace sys { /// This function runs all the registered interrupt handlers, including the @@ -37,10 +39,13 @@ namespace sys { /// When an error signal (such as SIBABRT or SIGSEGV) is delivered to the /// process, print a stack trace and then exit. /// @brief Print a stack trace if a fatal signal occurs. - void PrintStackTraceOnErrorSignal(); + void PrintStackTraceOnErrorSignal(bool DisableCrashReporting = false); + + /// Disable all system dialog boxes that appear when the process crashes. + void DisableSystemDialogsOnCrash(); - /// \brief Print the stack trace using the given \c FILE object. - void PrintStackTrace(FILE *); + /// \brief Print the stack trace using the given \c raw_ostream object. + void PrintStackTrace(raw_ostream &OS); /// AddSignalHandler - Add a function to be called when an abort/kill signal /// is delivered to the process. The handler can have a cookie passed to it diff --git a/include/llvm/Support/SourceMgr.h b/include/llvm/Support/SourceMgr.h index f9e114b67cb4..d492748e7781 100644 --- a/include/llvm/Support/SourceMgr.h +++ b/include/llvm/Support/SourceMgr.h @@ -73,8 +73,8 @@ private: bool isValidBufferID(unsigned i) const { return i && i <= Buffers.size(); } - SourceMgr(const SourceMgr&) LLVM_DELETED_FUNCTION; - void operator=(const SourceMgr&) LLVM_DELETED_FUNCTION; + SourceMgr(const SourceMgr&) = delete; + void operator=(const SourceMgr&) = delete; public: SourceMgr() : LineNoCache(nullptr), DiagHandler(nullptr), DiagContext(nullptr) {} diff --git a/include/llvm/Support/SpecialCaseList.h b/include/llvm/Support/SpecialCaseList.h index 313212e59dd2..ce693c501312 100644 --- a/include/llvm/Support/SpecialCaseList.h +++ b/include/llvm/Support/SpecialCaseList.h @@ -49,6 +49,8 @@ #define LLVM_SUPPORT_SPECIALCASELIST_H #include "llvm/ADT/StringMap.h" +#include <string> +#include <vector> namespace llvm { class MemoryBuffer; @@ -57,18 +59,18 @@ class StringRef; class SpecialCaseList { public: - /// Parses the special case list from a file. If Path is empty, returns - /// an empty special case list. On failure, returns 0 and writes an error - /// message to string. - static std::unique_ptr<SpecialCaseList> create(StringRef Path, - std::string &Error); + /// Parses the special case list entries from files. On failure, returns + /// 0 and writes an error message to string. + static std::unique_ptr<SpecialCaseList> + create(const std::vector<std::string> &Paths, std::string &Error); /// Parses the special case list from a memory buffer. On failure, returns /// 0 and writes an error message to string. static std::unique_ptr<SpecialCaseList> create(const MemoryBuffer *MB, - std::string &Error); - /// Parses the special case list from a file. On failure, reports a fatal - /// error. - static std::unique_ptr<SpecialCaseList> createOrDie(StringRef Path); + std::string &Error); + /// Parses the special case list entries from files. On failure, reports a + /// fatal error. + static std::unique_ptr<SpecialCaseList> + createOrDie(const std::vector<std::string> &Paths); ~SpecialCaseList(); @@ -81,15 +83,19 @@ public: StringRef Category = StringRef()) const; private: - SpecialCaseList(SpecialCaseList const &) LLVM_DELETED_FUNCTION; - SpecialCaseList &operator=(SpecialCaseList const &) LLVM_DELETED_FUNCTION; + SpecialCaseList(SpecialCaseList const &) = delete; + SpecialCaseList &operator=(SpecialCaseList const &) = delete; struct Entry; - StringMap<StringMap<Entry> > Entries; + StringMap<StringMap<Entry>> Entries; + StringMap<StringMap<std::string>> Regexps; + bool IsCompiled; SpecialCaseList(); /// Parses just-constructed SpecialCaseList entries from a memory buffer. bool parse(const MemoryBuffer *MB, std::string &Error); + /// compile() should be called once, after parsing all the memory buffers. + void compile(); }; } // namespace llvm diff --git a/include/llvm/Support/StreamingMemoryObject.h b/include/llvm/Support/StreamingMemoryObject.h index 66ed521a411c..932e635cd072 100644 --- a/include/llvm/Support/StreamingMemoryObject.h +++ b/include/llvm/Support/StreamingMemoryObject.h @@ -14,7 +14,6 @@ #include "llvm/Support/DataStream.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryObject.h" -#include <cassert> #include <memory> #include <vector> @@ -30,11 +29,12 @@ public: uint64_t readBytes(uint8_t *Buf, uint64_t Size, uint64_t Address) const override; const uint8_t *getPointer(uint64_t address, uint64_t size) const override { - // This could be fixed by ensuring the bytes are fetched and making a copy, - // requiring that the bitcode size be known, or otherwise ensuring that - // the memory doesn't go away/get reallocated, but it's - // not currently necessary. Users that need the pointer don't stream. - llvm_unreachable("getPointer in streaming memory objects not allowed"); + // FIXME: This could be fixed by ensuring the bytes are fetched and + // making a copy, requiring that the bitcode size be known, or + // otherwise ensuring that the memory doesn't go away/get reallocated, + // but it's not currently necessary. Users that need the pointer (any + // that need Blobs) don't stream. + report_fatal_error("getPointer in streaming memory objects not allowed"); return nullptr; } bool isValidAddress(uint64_t address) const override; @@ -59,30 +59,31 @@ private: mutable size_t ObjectSize; // 0 if unknown, set if wrapper seen or EOF reached mutable bool EOFReached; - // Fetch enough bytes such that Pos can be read or EOF is reached - // (i.e. BytesRead > Pos). Return true if Pos can be read. - // Unlike most of the functions in BitcodeReader, returns true on success. - // Most of the requests will be small, but we fetch at kChunkSize bytes - // at a time to avoid making too many potentially expensive GetBytes calls + // Fetch enough bytes such that Pos can be read (i.e. BytesRead > + // Pos). Returns true if Pos can be read. Unlike most of the + // functions in BitcodeReader, returns true on success. Most of the + // requests will be small, but we fetch at kChunkSize bytes at a + // time to avoid making too many potentially expensive GetBytes + // calls. bool fetchToPos(size_t Pos) const { - if (EOFReached) - return Pos < ObjectSize; while (Pos >= BytesRead) { + if (EOFReached) + return false; Bytes.resize(BytesRead + BytesSkipped + kChunkSize); size_t bytes = Streamer->GetBytes(&Bytes[BytesRead + BytesSkipped], kChunkSize); BytesRead += bytes; - if (bytes != kChunkSize) { // reached EOF/ran out of bytes - ObjectSize = BytesRead; + if (bytes == 0) { // reached EOF/ran out of bytes + if (ObjectSize == 0) + ObjectSize = BytesRead; EOFReached = true; - break; } } - return Pos < BytesRead; + return !ObjectSize || Pos < ObjectSize; } - StreamingMemoryObject(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION; - void operator=(const StreamingMemoryObject&) LLVM_DELETED_FUNCTION; + StreamingMemoryObject(const StreamingMemoryObject&) = delete; + void operator=(const StreamingMemoryObject&) = delete; }; MemoryObject *getNonStreamedMemoryObject( diff --git a/include/llvm/Support/StringPool.h b/include/llvm/Support/StringPool.h index b51974c946e0..2ec0c3b76c11 100644 --- a/include/llvm/Support/StringPool.h +++ b/include/llvm/Support/StringPool.h @@ -30,9 +30,7 @@ #define LLVM_SUPPORT_STRINGPOOL_H #include "llvm/ADT/StringMap.h" -#include "llvm/Support/Compiler.h" #include <cassert> -#include <new> namespace llvm { @@ -129,7 +127,7 @@ namespace llvm { } inline const char *operator*() const { return begin(); } - inline LLVM_EXPLICIT operator bool() const { return S != nullptr; } + inline explicit operator bool() const { return S != nullptr; } inline bool operator==(const PooledStringPtr &That) const { return S == That.S; } inline bool operator!=(const PooledStringPtr &That) const { return S != That.S; } diff --git a/include/llvm/Support/SwapByteOrder.h b/include/llvm/Support/SwapByteOrder.h index 9c5a3c59122e..7761fa1d7e01 100644 --- a/include/llvm/Support/SwapByteOrder.h +++ b/include/llvm/Support/SwapByteOrder.h @@ -94,6 +94,26 @@ inline signed long long getSwappedBytes(signed long long C) { return SwapByteOrder_64(C); } +inline float getSwappedBytes(float C) { + union { + uint32_t i; + float f; + } in, out; + in.f = C; + out.i = SwapByteOrder_32(in.i); + return out.f; +} + +inline double getSwappedBytes(double C) { + union { + uint64_t i; + double d; + } in, out; + in.d = C; + out.i = SwapByteOrder_64(in.i); + return out.d; +} + template<typename T> inline void swapByteOrder(T &Value) { Value = getSwappedBytes(Value); diff --git a/include/llvm/Support/SystemUtils.h b/include/llvm/Support/SystemUtils.h index d2d08b234272..2997b1b0c9cf 100644 --- a/include/llvm/Support/SystemUtils.h +++ b/include/llvm/Support/SystemUtils.h @@ -15,8 +15,6 @@ #ifndef LLVM_SUPPORT_SYSTEMUTILS_H #define LLVM_SUPPORT_SYSTEMUTILS_H -#include <string> - namespace llvm { class raw_ostream; diff --git a/include/llvm/Support/TargetParser.h b/include/llvm/Support/TargetParser.h new file mode 100644 index 000000000000..ca626f271d51 --- /dev/null +++ b/include/llvm/Support/TargetParser.h @@ -0,0 +1,155 @@ +//===-- TargetParser - Parser for target features ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a target parser to recognise hardware features such as +// FPU/CPU/ARCH names as well as specific support such as HDIV, etc. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_TARGETPARSER_H +#define LLVM_SUPPORT_TARGETPARSER_H + +namespace llvm { + class StringRef; + +// Target specific information into their own namespaces. These should be +// generated from TableGen because the information is already there, and there +// is where new information about targets will be added. +// FIXME: To TableGen this we need to make some table generated files available +// even if the back-end is not compiled with LLVM, plus we need to create a new +// back-end to TableGen to create these clean tables. +namespace ARM { + // FPU names. + enum FPUKind { + FK_INVALID = 0, + FK_VFP, + FK_VFPV2, + FK_VFPV3, + FK_VFPV3_D16, + FK_VFPV4, + FK_VFPV4_D16, + FK_FPV5_D16, + FK_FP_ARMV8, + FK_NEON, + FK_NEON_VFPV4, + FK_NEON_FP_ARMV8, + FK_CRYPTO_NEON_FP_ARMV8, + FK_SOFTVFP, + FK_LAST + }; + + // Arch names. + enum ArchKind { + AK_INVALID = 0, + AK_ARMV2, + AK_ARMV2A, + AK_ARMV3, + AK_ARMV3M, + AK_ARMV4, + AK_ARMV4T, + AK_ARMV5, + AK_ARMV5T, + AK_ARMV5TE, + AK_ARMV6, + AK_ARMV6J, + AK_ARMV6K, + AK_ARMV6T2, + AK_ARMV6Z, + AK_ARMV6ZK, + AK_ARMV6M, + AK_ARMV7, + AK_ARMV7A, + AK_ARMV7R, + AK_ARMV7M, + AK_ARMV8A, + AK_ARMV8_1A, + // Non-standard Arch names. + AK_IWMMXT, + AK_IWMMXT2, + AK_XSCALE, + AK_ARMV5E, + AK_ARMV5TEJ, + AK_ARMV6SM, + AK_ARMV6HL, + AK_ARMV7L, + AK_ARMV7HL, + AK_ARMV7S, + AK_ARMV7EM, + AK_LAST + }; + + // Arch extension modifiers for CPUs. + enum ArchExtKind { + AEK_INVALID = 0, + AEK_CRC, + AEK_CRYPTO, + AEK_FP, + AEK_HWDIV, + AEK_MP, + AEK_SEC, + AEK_VIRT, + AEK_LAST + }; + + // ISA kinds. + enum ISAKind { + IK_INVALID = 0, + IK_ARM, + IK_THUMB, + IK_AARCH64 + }; + + // Endianness + // FIXME: BE8 vs. BE32? + enum EndianKind { + EK_INVALID = 0, + EK_LITTLE, + EK_BIG + }; + + // v6/v7/v8 Profile + enum ProfileKind { + PK_INVALID = 0, + PK_A, + PK_R, + PK_M + }; +} // namespace ARM + +// Target Parsers, one per architecture. +class ARMTargetParser { + static StringRef getFPUSynonym(StringRef FPU); + static StringRef getArchSynonym(StringRef Arch); + +public: + static StringRef getCanonicalArchName(StringRef Arch); + + // Information by ID + static const char * getFPUName(unsigned FPUKind); + static const char * getArchName(unsigned ArchKind); + static unsigned getArchDefaultCPUArch(unsigned ArchKind); + static const char * getArchDefaultCPUName(unsigned ArchKind); + static const char * getArchExtName(unsigned ArchExtKind); + static const char * getDefaultCPU(StringRef Arch); + + // Parser + static unsigned parseFPU(StringRef FPU); + static unsigned parseArch(StringRef Arch); + static unsigned parseArchExt(StringRef ArchExt); + static unsigned parseCPUArch(StringRef CPU); + static unsigned parseArchISA(StringRef Arch); + static unsigned parseArchEndian(StringRef Arch); + static unsigned parseArchProfile(StringRef Arch); + static unsigned parseArchVersion(StringRef Arch); + +}; + +} // namespace llvm + +#endif diff --git a/include/llvm/Support/TargetRegistry.h b/include/llvm/Support/TargetRegistry.h index 8ac4b904bb88..408e908aa04c 100644 --- a/include/llvm/Support/TargetRegistry.h +++ b/include/llvm/Support/TargetRegistry.h @@ -22,1133 +22,1161 @@ #include "llvm-c/Disassembler.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/CodeGen.h" +#include "llvm/Support/FormattedStream.h" #include <cassert> +#include <memory> #include <string> namespace llvm { - class AsmPrinter; - class Module; - class MCAssembler; - class MCAsmBackend; - class MCAsmInfo; - class MCAsmParser; - class MCCodeEmitter; - class MCCodeGenInfo; - class MCContext; - class MCDisassembler; - class MCInstrAnalysis; - class MCInstPrinter; - class MCInstrInfo; - class MCRegisterInfo; - class MCStreamer; - class MCSubtargetInfo; - class MCSymbolizer; - class MCRelocationInfo; - class MCTargetAsmParser; - class MCTargetOptions; - class TargetMachine; - class TargetOptions; - class raw_ostream; - class formatted_raw_ostream; - - MCStreamer *createNullStreamer(MCContext &Ctx); - MCStreamer *createAsmStreamer(MCContext &Ctx, formatted_raw_ostream &OS, - bool isVerboseAsm, bool useDwarfDirectory, - MCInstPrinter *InstPrint, MCCodeEmitter *CE, - MCAsmBackend *TAB, bool ShowInst); - - MCRelocationInfo *createMCRelocationInfo(StringRef TT, MCContext &Ctx); - - MCSymbolizer *createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo, - LLVMSymbolLookupCallback SymbolLookUp, - void *DisInfo, - MCContext *Ctx, - MCRelocationInfo *RelInfo); - - /// Target - Wrapper for Target specific information. - /// - /// For registration purposes, this is a POD type so that targets can be - /// registered without the use of static constructors. - /// - /// Targets should implement a single global instance of this class (which - /// will be zero initialized), and pass that instance to the TargetRegistry as - /// part of their initialization. - class Target { - public: - friend struct TargetRegistry; - - typedef bool (*ArchMatchFnTy)(Triple::ArchType Arch); - - typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const MCRegisterInfo &MRI, - StringRef TT); - typedef MCCodeGenInfo *(*MCCodeGenInfoCtorFnTy)(StringRef TT, - Reloc::Model RM, - CodeModel::Model CM, - CodeGenOpt::Level OL); - typedef MCInstrInfo *(*MCInstrInfoCtorFnTy)(void); - typedef MCInstrAnalysis *(*MCInstrAnalysisCtorFnTy)(const MCInstrInfo*Info); - typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(StringRef TT); - typedef MCSubtargetInfo *(*MCSubtargetInfoCtorFnTy)(StringRef TT, - StringRef CPU, - StringRef Features); - typedef TargetMachine *(*TargetMachineCtorTy)(const Target &T, - StringRef TT, - StringRef CPU, - StringRef Features, - const TargetOptions &Options, - Reloc::Model RM, +class AsmPrinter; +class MCAsmBackend; +class MCAsmInfo; +class MCAsmParser; +class MCCodeEmitter; +class MCCodeGenInfo; +class MCContext; +class MCDisassembler; +class MCInstrAnalysis; +class MCInstPrinter; +class MCInstrInfo; +class MCRegisterInfo; +class MCStreamer; +class MCSubtargetInfo; +class MCSymbolizer; +class MCRelocationInfo; +class MCTargetAsmParser; +class MCTargetOptions; +class MCTargetStreamer; +class TargetMachine; +class TargetOptions; +class raw_ostream; +class raw_pwrite_stream; +class formatted_raw_ostream; + +MCStreamer *createNullStreamer(MCContext &Ctx); +MCStreamer *createAsmStreamer(MCContext &Ctx, + std::unique_ptr<formatted_raw_ostream> OS, + bool isVerboseAsm, bool useDwarfDirectory, + MCInstPrinter *InstPrint, MCCodeEmitter *CE, + MCAsmBackend *TAB, bool ShowInst); + +/// Takes ownership of \p TAB and \p CE. +MCStreamer *createELFStreamer(MCContext &Ctx, MCAsmBackend &TAB, + raw_pwrite_stream &OS, MCCodeEmitter *CE, + bool RelaxAll); +MCStreamer *createMachOStreamer(MCContext &Ctx, MCAsmBackend &TAB, + raw_pwrite_stream &OS, MCCodeEmitter *CE, + bool RelaxAll, bool DWARFMustBeAtTheEnd, + bool LabelSections = false); + +MCRelocationInfo *createMCRelocationInfo(StringRef TT, MCContext &Ctx); + +MCSymbolizer *createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp, + void *DisInfo, MCContext *Ctx, + std::unique_ptr<MCRelocationInfo> &&RelInfo); + +/// Target - Wrapper for Target specific information. +/// +/// For registration purposes, this is a POD type so that targets can be +/// registered without the use of static constructors. +/// +/// Targets should implement a single global instance of this class (which +/// will be zero initialized), and pass that instance to the TargetRegistry as +/// part of their initialization. +class Target { +public: + friend struct TargetRegistry; + + typedef bool (*ArchMatchFnTy)(Triple::ArchType Arch); + + typedef MCAsmInfo *(*MCAsmInfoCtorFnTy)(const MCRegisterInfo &MRI, + StringRef TT); + typedef MCCodeGenInfo *(*MCCodeGenInfoCtorFnTy)(StringRef TT, Reloc::Model RM, CodeModel::Model CM, CodeGenOpt::Level OL); - typedef AsmPrinter *(*AsmPrinterCtorTy)(TargetMachine &TM, - MCStreamer &Streamer); - typedef MCAsmBackend *(*MCAsmBackendCtorTy)(const Target &T, - const MCRegisterInfo &MRI, - StringRef TT, - StringRef CPU); - typedef MCTargetAsmParser *(*MCAsmParserCtorTy)( - MCSubtargetInfo &STI, - MCAsmParser &P, - const MCInstrInfo &MII, - const MCTargetOptions &Options); - typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T, - const MCSubtargetInfo &STI, - MCContext &Ctx); - typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Target &T, - unsigned SyntaxVariant, - const MCAsmInfo &MAI, - const MCInstrInfo &MII, - const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI); - typedef MCCodeEmitter *(*MCCodeEmitterCtorTy)(const MCInstrInfo &II, - const MCRegisterInfo &MRI, + typedef MCInstrInfo *(*MCInstrInfoCtorFnTy)(void); + typedef MCInstrAnalysis *(*MCInstrAnalysisCtorFnTy)(const MCInstrInfo *Info); + typedef MCRegisterInfo *(*MCRegInfoCtorFnTy)(StringRef TT); + typedef MCSubtargetInfo *(*MCSubtargetInfoCtorFnTy)(StringRef TT, + StringRef CPU, + StringRef Features); + typedef TargetMachine *(*TargetMachineCtorTy)( + const Target &T, StringRef TT, StringRef CPU, StringRef Features, + const TargetOptions &Options, Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL); + // If it weren't for layering issues (this header is in llvm/Support, but + // depends on MC?) this should take the Streamer by value rather than rvalue + // reference. + typedef AsmPrinter *(*AsmPrinterCtorTy)( + TargetMachine &TM, std::unique_ptr<MCStreamer> &&Streamer); + typedef MCAsmBackend *(*MCAsmBackendCtorTy)(const Target &T, + const MCRegisterInfo &MRI, + StringRef TT, StringRef CPU); + typedef MCTargetAsmParser *(*MCAsmParserCtorTy)( + MCSubtargetInfo &STI, MCAsmParser &P, const MCInstrInfo &MII, + const MCTargetOptions &Options); + typedef MCDisassembler *(*MCDisassemblerCtorTy)(const Target &T, const MCSubtargetInfo &STI, MCContext &Ctx); - typedef MCStreamer *(*MCObjectStreamerCtorTy)( - const Target &T, StringRef TT, MCContext &Ctx, MCAsmBackend &TAB, - raw_ostream &_OS, MCCodeEmitter *_Emitter, const MCSubtargetInfo &STI, - bool RelaxAll); - typedef MCStreamer *(*AsmStreamerCtorTy)(MCContext &Ctx, - formatted_raw_ostream &OS, - bool isVerboseAsm, - bool useDwarfDirectory, - MCInstPrinter *InstPrint, - MCCodeEmitter *CE, - MCAsmBackend *TAB, - bool ShowInst); - typedef MCStreamer *(*NullStreamerCtorTy)(MCContext &Ctx); - typedef MCRelocationInfo *(*MCRelocationInfoCtorTy)(StringRef TT, - MCContext &Ctx); - typedef MCSymbolizer *(*MCSymbolizerCtorTy)(StringRef TT, - LLVMOpInfoCallback GetOpInfo, - LLVMSymbolLookupCallback SymbolLookUp, - void *DisInfo, - MCContext *Ctx, - MCRelocationInfo *RelInfo); - - private: - /// Next - The next registered target in the linked list, maintained by the - /// TargetRegistry. - Target *Next; - - /// The target function for checking if an architecture is supported. - ArchMatchFnTy ArchMatchFn; - - /// Name - The target name. - const char *Name; - - /// ShortDesc - A short description of the target. - const char *ShortDesc; - - /// HasJIT - Whether this target supports the JIT. - bool HasJIT; - - /// MCAsmInfoCtorFn - Constructor function for this target's MCAsmInfo, if - /// registered. - MCAsmInfoCtorFnTy MCAsmInfoCtorFn; - - /// MCCodeGenInfoCtorFn - Constructor function for this target's - /// MCCodeGenInfo, if registered. - MCCodeGenInfoCtorFnTy MCCodeGenInfoCtorFn; - - /// MCInstrInfoCtorFn - Constructor function for this target's MCInstrInfo, - /// if registered. - MCInstrInfoCtorFnTy MCInstrInfoCtorFn; - - /// MCInstrAnalysisCtorFn - Constructor function for this target's - /// MCInstrAnalysis, if registered. - MCInstrAnalysisCtorFnTy MCInstrAnalysisCtorFn; - - /// MCRegInfoCtorFn - Constructor function for this target's MCRegisterInfo, - /// if registered. - MCRegInfoCtorFnTy MCRegInfoCtorFn; - - /// MCSubtargetInfoCtorFn - Constructor function for this target's - /// MCSubtargetInfo, if registered. - MCSubtargetInfoCtorFnTy MCSubtargetInfoCtorFn; - - /// TargetMachineCtorFn - Construction function for this target's - /// TargetMachine, if registered. - TargetMachineCtorTy TargetMachineCtorFn; - - /// MCAsmBackendCtorFn - Construction function for this target's - /// MCAsmBackend, if registered. - MCAsmBackendCtorTy MCAsmBackendCtorFn; - - /// MCAsmParserCtorFn - Construction function for this target's - /// MCTargetAsmParser, if registered. - MCAsmParserCtorTy MCAsmParserCtorFn; - - /// AsmPrinterCtorFn - Construction function for this target's AsmPrinter, - /// if registered. - AsmPrinterCtorTy AsmPrinterCtorFn; - - /// MCDisassemblerCtorFn - Construction function for this target's - /// MCDisassembler, if registered. - MCDisassemblerCtorTy MCDisassemblerCtorFn; - - /// MCInstPrinterCtorFn - Construction function for this target's - /// MCInstPrinter, if registered. - MCInstPrinterCtorTy MCInstPrinterCtorFn; - - /// MCCodeEmitterCtorFn - Construction function for this target's - /// CodeEmitter, if registered. - MCCodeEmitterCtorTy MCCodeEmitterCtorFn; - - /// MCObjectStreamerCtorFn - Construction function for this target's - /// MCObjectStreamer, if registered. - MCObjectStreamerCtorTy MCObjectStreamerCtorFn; - - /// AsmStreamerCtorFn - Construction function for this target's - /// AsmStreamer, if registered (default = llvm::createAsmStreamer). - AsmStreamerCtorTy AsmStreamerCtorFn; - - /// Construction function for this target's NullStreamer, if registered - /// (default = llvm::createNullStreamer). - NullStreamerCtorTy NullStreamerCtorFn; - - /// MCRelocationInfoCtorFn - Construction function for this target's - /// MCRelocationInfo, if registered (default = llvm::createMCRelocationInfo) - MCRelocationInfoCtorTy MCRelocationInfoCtorFn; - - /// MCSymbolizerCtorFn - Construction function for this target's - /// MCSymbolizer, if registered (default = llvm::createMCSymbolizer) - MCSymbolizerCtorTy MCSymbolizerCtorFn; + typedef MCInstPrinter *(*MCInstPrinterCtorTy)(const Triple &T, + unsigned SyntaxVariant, + const MCAsmInfo &MAI, + const MCInstrInfo &MII, + const MCRegisterInfo &MRI); + typedef MCCodeEmitter *(*MCCodeEmitterCtorTy)(const MCInstrInfo &II, + const MCRegisterInfo &MRI, + MCContext &Ctx); + typedef MCStreamer *(*ELFStreamerCtorTy)(const Triple &T, MCContext &Ctx, + MCAsmBackend &TAB, + raw_pwrite_stream &OS, + MCCodeEmitter *Emitter, + bool RelaxAll); + typedef MCStreamer *(*MachOStreamerCtorTy)(MCContext &Ctx, MCAsmBackend &TAB, + raw_pwrite_stream &OS, + MCCodeEmitter *Emitter, + bool RelaxAll, + bool DWARFMustBeAtTheEnd); + typedef MCStreamer *(*COFFStreamerCtorTy)(MCContext &Ctx, MCAsmBackend &TAB, + raw_pwrite_stream &OS, + MCCodeEmitter *Emitter, + bool RelaxAll); + typedef MCTargetStreamer *(*NullTargetStreamerCtorTy)(MCStreamer &S); + typedef MCTargetStreamer *(*AsmTargetStreamerCtorTy)( + MCStreamer &S, formatted_raw_ostream &OS, MCInstPrinter *InstPrint, + bool IsVerboseAsm); + typedef MCTargetStreamer *(*ObjectTargetStreamerCtorTy)( + MCStreamer &S, const MCSubtargetInfo &STI); + typedef MCRelocationInfo *(*MCRelocationInfoCtorTy)(StringRef TT, + MCContext &Ctx); + typedef MCSymbolizer *(*MCSymbolizerCtorTy)( + StringRef TT, LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp, void *DisInfo, MCContext *Ctx, + std::unique_ptr<MCRelocationInfo> &&RelInfo); + +private: + /// Next - The next registered target in the linked list, maintained by the + /// TargetRegistry. + Target *Next; + + /// The target function for checking if an architecture is supported. + ArchMatchFnTy ArchMatchFn; + + /// Name - The target name. + const char *Name; + + /// ShortDesc - A short description of the target. + const char *ShortDesc; + + /// HasJIT - Whether this target supports the JIT. + bool HasJIT; + + /// MCAsmInfoCtorFn - Constructor function for this target's MCAsmInfo, if + /// registered. + MCAsmInfoCtorFnTy MCAsmInfoCtorFn; + + /// MCCodeGenInfoCtorFn - Constructor function for this target's + /// MCCodeGenInfo, if registered. + MCCodeGenInfoCtorFnTy MCCodeGenInfoCtorFn; + + /// MCInstrInfoCtorFn - Constructor function for this target's MCInstrInfo, + /// if registered. + MCInstrInfoCtorFnTy MCInstrInfoCtorFn; + + /// MCInstrAnalysisCtorFn - Constructor function for this target's + /// MCInstrAnalysis, if registered. + MCInstrAnalysisCtorFnTy MCInstrAnalysisCtorFn; + + /// MCRegInfoCtorFn - Constructor function for this target's MCRegisterInfo, + /// if registered. + MCRegInfoCtorFnTy MCRegInfoCtorFn; + + /// MCSubtargetInfoCtorFn - Constructor function for this target's + /// MCSubtargetInfo, if registered. + MCSubtargetInfoCtorFnTy MCSubtargetInfoCtorFn; + + /// TargetMachineCtorFn - Construction function for this target's + /// TargetMachine, if registered. + TargetMachineCtorTy TargetMachineCtorFn; + + /// MCAsmBackendCtorFn - Construction function for this target's + /// MCAsmBackend, if registered. + MCAsmBackendCtorTy MCAsmBackendCtorFn; + + /// MCAsmParserCtorFn - Construction function for this target's + /// MCTargetAsmParser, if registered. + MCAsmParserCtorTy MCAsmParserCtorFn; + + /// AsmPrinterCtorFn - Construction function for this target's AsmPrinter, + /// if registered. + AsmPrinterCtorTy AsmPrinterCtorFn; + + /// MCDisassemblerCtorFn - Construction function for this target's + /// MCDisassembler, if registered. + MCDisassemblerCtorTy MCDisassemblerCtorFn; + + /// MCInstPrinterCtorFn - Construction function for this target's + /// MCInstPrinter, if registered. + MCInstPrinterCtorTy MCInstPrinterCtorFn; + + /// MCCodeEmitterCtorFn - Construction function for this target's + /// CodeEmitter, if registered. + MCCodeEmitterCtorTy MCCodeEmitterCtorFn; + + // Construction functions for the various object formats, if registered. + COFFStreamerCtorTy COFFStreamerCtorFn; + MachOStreamerCtorTy MachOStreamerCtorFn; + ELFStreamerCtorTy ELFStreamerCtorFn; + + /// Construction function for this target's null TargetStreamer, if + /// registered (default = nullptr). + NullTargetStreamerCtorTy NullTargetStreamerCtorFn; + + /// Construction function for this target's asm TargetStreamer, if + /// registered (default = nullptr). + AsmTargetStreamerCtorTy AsmTargetStreamerCtorFn; + + /// Construction function for this target's obj TargetStreamer, if + /// registered (default = nullptr). + ObjectTargetStreamerCtorTy ObjectTargetStreamerCtorFn; + + /// MCRelocationInfoCtorFn - Construction function for this target's + /// MCRelocationInfo, if registered (default = llvm::createMCRelocationInfo) + MCRelocationInfoCtorTy MCRelocationInfoCtorFn; - public: - Target() - : AsmStreamerCtorFn(nullptr), NullStreamerCtorFn(nullptr), - MCRelocationInfoCtorFn(nullptr), MCSymbolizerCtorFn(nullptr) {} - - /// @name Target Information - /// @{ - - // getNext - Return the next registered target. - const Target *getNext() const { return Next; } - - /// getName - Get the target name. - const char *getName() const { return Name; } - - /// getShortDescription - Get a short description of the target. - const char *getShortDescription() const { return ShortDesc; } - - /// @} - /// @name Feature Predicates - /// @{ - - /// hasJIT - Check if this targets supports the just-in-time compilation. - bool hasJIT() const { return HasJIT; } - - /// hasTargetMachine - Check if this target supports code generation. - bool hasTargetMachine() const { return TargetMachineCtorFn != nullptr; } - - /// hasMCAsmBackend - Check if this target supports .o generation. - bool hasMCAsmBackend() const { return MCAsmBackendCtorFn != nullptr; } - - /// @} - /// @name Feature Constructors - /// @{ - - /// createMCAsmInfo - Create a MCAsmInfo implementation for the specified - /// target triple. - /// - /// \param Triple This argument is used to determine the target machine - /// feature set; it should always be provided. Generally this should be - /// either the target triple from the module, or the target triple of the - /// host if that does not exist. - MCAsmInfo *createMCAsmInfo(const MCRegisterInfo &MRI, - StringRef Triple) const { - if (!MCAsmInfoCtorFn) - return nullptr; - return MCAsmInfoCtorFn(MRI, Triple); - } + /// MCSymbolizerCtorFn - Construction function for this target's + /// MCSymbolizer, if registered (default = llvm::createMCSymbolizer) + MCSymbolizerCtorTy MCSymbolizerCtorFn; - /// createMCCodeGenInfo - Create a MCCodeGenInfo implementation. - /// - MCCodeGenInfo *createMCCodeGenInfo(StringRef Triple, Reloc::Model RM, - CodeModel::Model CM, - CodeGenOpt::Level OL) const { - if (!MCCodeGenInfoCtorFn) - return nullptr; - return MCCodeGenInfoCtorFn(Triple, RM, CM, OL); - } +public: + Target() + : COFFStreamerCtorFn(nullptr), MachOStreamerCtorFn(nullptr), + ELFStreamerCtorFn(nullptr), NullTargetStreamerCtorFn(nullptr), + AsmTargetStreamerCtorFn(nullptr), ObjectTargetStreamerCtorFn(nullptr), + MCRelocationInfoCtorFn(nullptr), MCSymbolizerCtorFn(nullptr) {} - /// createMCInstrInfo - Create a MCInstrInfo implementation. - /// - MCInstrInfo *createMCInstrInfo() const { - if (!MCInstrInfoCtorFn) - return nullptr; - return MCInstrInfoCtorFn(); - } + /// @name Target Information + /// @{ - /// createMCInstrAnalysis - Create a MCInstrAnalysis implementation. - /// - MCInstrAnalysis *createMCInstrAnalysis(const MCInstrInfo *Info) const { - if (!MCInstrAnalysisCtorFn) - return nullptr; - return MCInstrAnalysisCtorFn(Info); - } + // getNext - Return the next registered target. + const Target *getNext() const { return Next; } - /// createMCRegInfo - Create a MCRegisterInfo implementation. - /// - MCRegisterInfo *createMCRegInfo(StringRef Triple) const { - if (!MCRegInfoCtorFn) - return nullptr; - return MCRegInfoCtorFn(Triple); - } + /// getName - Get the target name. + const char *getName() const { return Name; } - /// createMCSubtargetInfo - Create a MCSubtargetInfo implementation. - /// - /// \param Triple This argument is used to determine the target machine - /// feature set; it should always be provided. Generally this should be - /// either the target triple from the module, or the target triple of the - /// host if that does not exist. - /// \param CPU This specifies the name of the target CPU. - /// \param Features This specifies the string representation of the - /// additional target features. - MCSubtargetInfo *createMCSubtargetInfo(StringRef Triple, StringRef CPU, - StringRef Features) const { - if (!MCSubtargetInfoCtorFn) - return nullptr; - return MCSubtargetInfoCtorFn(Triple, CPU, Features); - } + /// getShortDescription - Get a short description of the target. + const char *getShortDescription() const { return ShortDesc; } - /// createTargetMachine - Create a target specific machine implementation - /// for the specified \p Triple. - /// - /// \param Triple This argument is used to determine the target machine - /// feature set; it should always be provided. Generally this should be - /// either the target triple from the module, or the target triple of the - /// host if that does not exist. - TargetMachine *createTargetMachine(StringRef Triple, StringRef CPU, - StringRef Features, const TargetOptions &Options, - Reloc::Model RM = Reloc::Default, - CodeModel::Model CM = CodeModel::Default, - CodeGenOpt::Level OL = CodeGenOpt::Default) const { - if (!TargetMachineCtorFn) - return nullptr; - return TargetMachineCtorFn(*this, Triple, CPU, Features, Options, - RM, CM, OL); - } + /// @} + /// @name Feature Predicates + /// @{ - /// createMCAsmBackend - Create a target specific assembly parser. - /// - /// \param Triple The target triple string. - MCAsmBackend *createMCAsmBackend(const MCRegisterInfo &MRI, - StringRef Triple, StringRef CPU) const { - if (!MCAsmBackendCtorFn) - return nullptr; - return MCAsmBackendCtorFn(*this, MRI, Triple, CPU); - } + /// hasJIT - Check if this targets supports the just-in-time compilation. + bool hasJIT() const { return HasJIT; } - /// createMCAsmParser - Create a target specific assembly parser. - /// - /// \param Parser The target independent parser implementation to use for - /// parsing and lexing. - MCTargetAsmParser *createMCAsmParser( - MCSubtargetInfo &STI, - MCAsmParser &Parser, - const MCInstrInfo &MII, - const MCTargetOptions &Options) const { - if (!MCAsmParserCtorFn) - return nullptr; - return MCAsmParserCtorFn(STI, Parser, MII, Options); - } + /// hasTargetMachine - Check if this target supports code generation. + bool hasTargetMachine() const { return TargetMachineCtorFn != nullptr; } - /// createAsmPrinter - Create a target specific assembly printer pass. This - /// takes ownership of the MCStreamer object. - AsmPrinter *createAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) const{ - if (!AsmPrinterCtorFn) - return nullptr; - return AsmPrinterCtorFn(TM, Streamer); - } + /// hasMCAsmBackend - Check if this target supports .o generation. + bool hasMCAsmBackend() const { return MCAsmBackendCtorFn != nullptr; } - MCDisassembler *createMCDisassembler(const MCSubtargetInfo &STI, - MCContext &Ctx) const { - if (!MCDisassemblerCtorFn) - return nullptr; - return MCDisassemblerCtorFn(*this, STI, Ctx); - } + /// @} + /// @name Feature Constructors + /// @{ - MCInstPrinter *createMCInstPrinter(unsigned SyntaxVariant, - const MCAsmInfo &MAI, - const MCInstrInfo &MII, - const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI) const { - if (!MCInstPrinterCtorFn) - return nullptr; - return MCInstPrinterCtorFn(*this, SyntaxVariant, MAI, MII, MRI, STI); - } + /// createMCAsmInfo - Create a MCAsmInfo implementation for the specified + /// target triple. + /// + /// \param Triple This argument is used to determine the target machine + /// feature set; it should always be provided. Generally this should be + /// either the target triple from the module, or the target triple of the + /// host if that does not exist. + MCAsmInfo *createMCAsmInfo(const MCRegisterInfo &MRI, + StringRef Triple) const { + if (!MCAsmInfoCtorFn) + return nullptr; + return MCAsmInfoCtorFn(MRI, Triple); + } + + /// createMCCodeGenInfo - Create a MCCodeGenInfo implementation. + /// + MCCodeGenInfo *createMCCodeGenInfo(StringRef Triple, Reloc::Model RM, + CodeModel::Model CM, + CodeGenOpt::Level OL) const { + if (!MCCodeGenInfoCtorFn) + return nullptr; + return MCCodeGenInfoCtorFn(Triple, RM, CM, OL); + } + + /// createMCInstrInfo - Create a MCInstrInfo implementation. + /// + MCInstrInfo *createMCInstrInfo() const { + if (!MCInstrInfoCtorFn) + return nullptr; + return MCInstrInfoCtorFn(); + } + /// createMCInstrAnalysis - Create a MCInstrAnalysis implementation. + /// + MCInstrAnalysis *createMCInstrAnalysis(const MCInstrInfo *Info) const { + if (!MCInstrAnalysisCtorFn) + return nullptr; + return MCInstrAnalysisCtorFn(Info); + } - /// createMCCodeEmitter - Create a target specific code emitter. - MCCodeEmitter *createMCCodeEmitter(const MCInstrInfo &II, - const MCRegisterInfo &MRI, - const MCSubtargetInfo &STI, + /// createMCRegInfo - Create a MCRegisterInfo implementation. + /// + MCRegisterInfo *createMCRegInfo(StringRef Triple) const { + if (!MCRegInfoCtorFn) + return nullptr; + return MCRegInfoCtorFn(Triple); + } + + /// createMCSubtargetInfo - Create a MCSubtargetInfo implementation. + /// + /// \param Triple This argument is used to determine the target machine + /// feature set; it should always be provided. Generally this should be + /// either the target triple from the module, or the target triple of the + /// host if that does not exist. + /// \param CPU This specifies the name of the target CPU. + /// \param Features This specifies the string representation of the + /// additional target features. + MCSubtargetInfo *createMCSubtargetInfo(StringRef Triple, StringRef CPU, + StringRef Features) const { + if (!MCSubtargetInfoCtorFn) + return nullptr; + return MCSubtargetInfoCtorFn(Triple, CPU, Features); + } + + /// createTargetMachine - Create a target specific machine implementation + /// for the specified \p Triple. + /// + /// \param Triple This argument is used to determine the target machine + /// feature set; it should always be provided. Generally this should be + /// either the target triple from the module, or the target triple of the + /// host if that does not exist. + TargetMachine * + createTargetMachine(StringRef Triple, StringRef CPU, StringRef Features, + const TargetOptions &Options, + Reloc::Model RM = Reloc::Default, + CodeModel::Model CM = CodeModel::Default, + CodeGenOpt::Level OL = CodeGenOpt::Default) const { + if (!TargetMachineCtorFn) + return nullptr; + return TargetMachineCtorFn(*this, Triple, CPU, Features, Options, RM, CM, + OL); + } + + /// createMCAsmBackend - Create a target specific assembly parser. + /// + /// \param Triple The target triple string. + MCAsmBackend *createMCAsmBackend(const MCRegisterInfo &MRI, StringRef Triple, + StringRef CPU) const { + if (!MCAsmBackendCtorFn) + return nullptr; + return MCAsmBackendCtorFn(*this, MRI, Triple, CPU); + } + + /// createMCAsmParser - Create a target specific assembly parser. + /// + /// \param Parser The target independent parser implementation to use for + /// parsing and lexing. + MCTargetAsmParser *createMCAsmParser(MCSubtargetInfo &STI, + MCAsmParser &Parser, + const MCInstrInfo &MII, + const MCTargetOptions &Options) const { + if (!MCAsmParserCtorFn) + return nullptr; + return MCAsmParserCtorFn(STI, Parser, MII, Options); + } + + /// createAsmPrinter - Create a target specific assembly printer pass. This + /// takes ownership of the MCStreamer object. + AsmPrinter *createAsmPrinter(TargetMachine &TM, + std::unique_ptr<MCStreamer> &&Streamer) const { + if (!AsmPrinterCtorFn) + return nullptr; + return AsmPrinterCtorFn(TM, std::move(Streamer)); + } + + MCDisassembler *createMCDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx) const { - if (!MCCodeEmitterCtorFn) - return nullptr; - return MCCodeEmitterCtorFn(II, MRI, STI, Ctx); - } + if (!MCDisassemblerCtorFn) + return nullptr; + return MCDisassemblerCtorFn(*this, STI, Ctx); + } + + MCInstPrinter *createMCInstPrinter(const Triple &T, unsigned SyntaxVariant, + const MCAsmInfo &MAI, + const MCInstrInfo &MII, + const MCRegisterInfo &MRI) const { + if (!MCInstPrinterCtorFn) + return nullptr; + return MCInstPrinterCtorFn(T, SyntaxVariant, MAI, MII, MRI); + } + + /// createMCCodeEmitter - Create a target specific code emitter. + MCCodeEmitter *createMCCodeEmitter(const MCInstrInfo &II, + const MCRegisterInfo &MRI, + MCContext &Ctx) const { + if (!MCCodeEmitterCtorFn) + return nullptr; + return MCCodeEmitterCtorFn(II, MRI, Ctx); + } + + /// Create a target specific MCStreamer. + /// + /// \param T The target triple. + /// \param Ctx The target context. + /// \param TAB The target assembler backend object. Takes ownership. + /// \param OS The stream object. + /// \param Emitter The target independent assembler object.Takes ownership. + /// \param RelaxAll Relax all fixups? + MCStreamer *createMCObjectStreamer(const Triple &T, MCContext &Ctx, + MCAsmBackend &TAB, raw_pwrite_stream &OS, + MCCodeEmitter *Emitter, + const MCSubtargetInfo &STI, bool RelaxAll, + bool DWARFMustBeAtTheEnd) const { + MCStreamer *S; + switch (T.getObjectFormat()) { + default: + llvm_unreachable("Unknown object format"); + case Triple::COFF: + assert(T.isOSWindows() && "only Windows COFF is supported"); + S = COFFStreamerCtorFn(Ctx, TAB, OS, Emitter, RelaxAll); + break; + case Triple::MachO: + if (MachOStreamerCtorFn) + S = MachOStreamerCtorFn(Ctx, TAB, OS, Emitter, RelaxAll, + DWARFMustBeAtTheEnd); + else + S = createMachOStreamer(Ctx, TAB, OS, Emitter, RelaxAll, + DWARFMustBeAtTheEnd); + break; + case Triple::ELF: + if (ELFStreamerCtorFn) + S = ELFStreamerCtorFn(T, Ctx, TAB, OS, Emitter, RelaxAll); + else + S = createELFStreamer(Ctx, TAB, OS, Emitter, RelaxAll); + break; + } + if (ObjectTargetStreamerCtorFn) + ObjectTargetStreamerCtorFn(*S, STI); + return S; + } + + MCStreamer *createAsmStreamer(MCContext &Ctx, + std::unique_ptr<formatted_raw_ostream> OS, + bool IsVerboseAsm, bool UseDwarfDirectory, + MCInstPrinter *InstPrint, MCCodeEmitter *CE, + MCAsmBackend *TAB, bool ShowInst) const { + formatted_raw_ostream &OSRef = *OS; + MCStreamer *S = llvm::createAsmStreamer(Ctx, std::move(OS), IsVerboseAsm, + UseDwarfDirectory, InstPrint, CE, + TAB, ShowInst); + createAsmTargetStreamer(*S, OSRef, InstPrint, IsVerboseAsm); + return S; + } + + MCTargetStreamer *createAsmTargetStreamer(MCStreamer &S, + formatted_raw_ostream &OS, + MCInstPrinter *InstPrint, + bool IsVerboseAsm) const { + if (AsmTargetStreamerCtorFn) + return AsmTargetStreamerCtorFn(S, OS, InstPrint, IsVerboseAsm); + return nullptr; + } + + MCStreamer *createNullStreamer(MCContext &Ctx) const { + MCStreamer *S = llvm::createNullStreamer(Ctx); + createNullTargetStreamer(*S); + return S; + } + + MCTargetStreamer *createNullTargetStreamer(MCStreamer &S) const { + if (NullTargetStreamerCtorFn) + return NullTargetStreamerCtorFn(S); + return nullptr; + } + + /// createMCRelocationInfo - Create a target specific MCRelocationInfo. + /// + /// \param TT The target triple. + /// \param Ctx The target context. + MCRelocationInfo *createMCRelocationInfo(StringRef TT, MCContext &Ctx) const { + MCRelocationInfoCtorTy Fn = MCRelocationInfoCtorFn + ? MCRelocationInfoCtorFn + : llvm::createMCRelocationInfo; + return Fn(TT, Ctx); + } + + /// createMCSymbolizer - Create a target specific MCSymbolizer. + /// + /// \param TT The target triple. + /// \param GetOpInfo The function to get the symbolic information for + /// operands. + /// \param SymbolLookUp The function to lookup a symbol name. + /// \param DisInfo The pointer to the block of symbolic information for above + /// call + /// back. + /// \param Ctx The target context. + /// \param RelInfo The relocation information for this target. Takes + /// ownership. + MCSymbolizer * + createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo, + LLVMSymbolLookupCallback SymbolLookUp, void *DisInfo, + MCContext *Ctx, + std::unique_ptr<MCRelocationInfo> &&RelInfo) const { + MCSymbolizerCtorTy Fn = + MCSymbolizerCtorFn ? MCSymbolizerCtorFn : llvm::createMCSymbolizer; + return Fn(TT, GetOpInfo, SymbolLookUp, DisInfo, Ctx, std::move(RelInfo)); + } + + /// @} +}; + +/// TargetRegistry - Generic interface to target specific features. +struct TargetRegistry { + // FIXME: Make this a namespace, probably just move all the Register* + // functions into Target (currently they all just set members on the Target + // anyway, and Target friends this class so those functions can... + // function). + TargetRegistry() = delete; + + class iterator + : public std::iterator<std::forward_iterator_tag, Target, ptrdiff_t> { + const Target *Current; + explicit iterator(Target *T) : Current(T) {} + friend struct TargetRegistry; - /// createMCObjectStreamer - Create a target specific MCStreamer. - /// - /// \param TT The target triple. - /// \param Ctx The target context. - /// \param TAB The target assembler backend object. Takes ownership. - /// \param _OS The stream object. - /// \param _Emitter The target independent assembler object.Takes ownership. - /// \param RelaxAll Relax all fixups? - MCStreamer *createMCObjectStreamer(StringRef TT, MCContext &Ctx, - MCAsmBackend &TAB, raw_ostream &_OS, - MCCodeEmitter *_Emitter, - const MCSubtargetInfo &STI, - bool RelaxAll) const { - if (!MCObjectStreamerCtorFn) - return nullptr; - return MCObjectStreamerCtorFn(*this, TT, Ctx, TAB, _OS, _Emitter, STI, - RelaxAll); - } + public: + iterator() : Current(nullptr) {} - /// createAsmStreamer - Create a target specific MCStreamer. - MCStreamer *createAsmStreamer(MCContext &Ctx, - formatted_raw_ostream &OS, - bool isVerboseAsm, - bool useDwarfDirectory, - MCInstPrinter *InstPrint, - MCCodeEmitter *CE, - MCAsmBackend *TAB, - bool ShowInst) const { - if (AsmStreamerCtorFn) - return AsmStreamerCtorFn(Ctx, OS, isVerboseAsm, useDwarfDirectory, - InstPrint, CE, TAB, ShowInst); - return llvm::createAsmStreamer(Ctx, OS, isVerboseAsm, useDwarfDirectory, - InstPrint, CE, TAB, ShowInst); - } + bool operator==(const iterator &x) const { return Current == x.Current; } + bool operator!=(const iterator &x) const { return !operator==(x); } - MCStreamer *createNullStreamer(MCContext &Ctx) const { - if (NullStreamerCtorFn) - return NullStreamerCtorFn(Ctx); - return llvm::createNullStreamer(Ctx); + // Iterator traversal: forward iteration only + iterator &operator++() { // Preincrement + assert(Current && "Cannot increment end iterator!"); + Current = Current->getNext(); + return *this; } - - /// createMCRelocationInfo - Create a target specific MCRelocationInfo. - /// - /// \param TT The target triple. - /// \param Ctx The target context. - MCRelocationInfo * - createMCRelocationInfo(StringRef TT, MCContext &Ctx) const { - MCRelocationInfoCtorTy Fn = MCRelocationInfoCtorFn - ? MCRelocationInfoCtorFn - : llvm::createMCRelocationInfo; - return Fn(TT, Ctx); + iterator operator++(int) { // Postincrement + iterator tmp = *this; + ++*this; + return tmp; } - /// createMCSymbolizer - Create a target specific MCSymbolizer. - /// - /// \param TT The target triple. - /// \param GetOpInfo The function to get the symbolic information for operands. - /// \param SymbolLookUp The function to lookup a symbol name. - /// \param DisInfo The pointer to the block of symbolic information for above call - /// back. - /// \param Ctx The target context. - /// \param RelInfo The relocation information for this target. Takes ownership. - MCSymbolizer * - createMCSymbolizer(StringRef TT, LLVMOpInfoCallback GetOpInfo, - LLVMSymbolLookupCallback SymbolLookUp, - void *DisInfo, - MCContext *Ctx, MCRelocationInfo *RelInfo) const { - MCSymbolizerCtorTy Fn = - MCSymbolizerCtorFn ? MCSymbolizerCtorFn : llvm::createMCSymbolizer; - return Fn(TT, GetOpInfo, SymbolLookUp, DisInfo, Ctx, RelInfo); + const Target &operator*() const { + assert(Current && "Cannot dereference end iterator!"); + return *Current; } - /// @} + const Target *operator->() const { return &operator*(); } }; - /// TargetRegistry - Generic interface to target specific features. - struct TargetRegistry { - class iterator { - const Target *Current; - explicit iterator(Target *T) : Current(T) {} - friend struct TargetRegistry; - public: - iterator() : Current(nullptr) {} - - bool operator==(const iterator &x) const { - return Current == x.Current; - } - bool operator!=(const iterator &x) const { - return !operator==(x); - } - - // Iterator traversal: forward iteration only - iterator &operator++() { // Preincrement - assert(Current && "Cannot increment end iterator!"); - Current = Current->getNext(); - return *this; - } - iterator operator++(int) { // Postincrement - iterator tmp = *this; - ++*this; - return tmp; - } - - const Target &operator*() const { - assert(Current && "Cannot dereference end iterator!"); - return *Current; - } - - const Target *operator->() const { - return &operator*(); - } - }; - - /// printRegisteredTargetsForVersion - Print the registered targets - /// appropriately for inclusion in a tool's version output. - static void printRegisteredTargetsForVersion(); - - /// @name Registry Access - /// @{ - - static iterator begin(); - - static iterator end() { return iterator(); } - - /// lookupTarget - Lookup a target based on a target triple. - /// - /// \param Triple - The triple to use for finding a target. - /// \param Error - On failure, an error string describing why no target was - /// found. - 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); - - /// @} - /// @name Target Registration - /// @{ - - /// RegisterTarget - Register the given target. Attempts to register a - /// target which has already been registered will be ignored. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Name - The target name. This should be a static string. - /// @param ShortDesc - A short target description. This should be a static - /// string. - /// @param ArchMatchFn - The arch match checking function for this target. - /// @param HasJIT - Whether the target supports JIT code - /// generation. - static void RegisterTarget(Target &T, - const char *Name, - const char *ShortDesc, - Target::ArchMatchFnTy ArchMatchFn, - bool HasJIT = false); - - /// RegisterMCAsmInfo - Register a MCAsmInfo implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct a MCAsmInfo for the target. - static void RegisterMCAsmInfo(Target &T, Target::MCAsmInfoCtorFnTy Fn) { - T.MCAsmInfoCtorFn = Fn; - } - - /// RegisterMCCodeGenInfo - Register a MCCodeGenInfo implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct a MCCodeGenInfo for the target. - static void RegisterMCCodeGenInfo(Target &T, - Target::MCCodeGenInfoCtorFnTy Fn) { - T.MCCodeGenInfoCtorFn = Fn; - } - - /// RegisterMCInstrInfo - Register a MCInstrInfo implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct a MCInstrInfo for the target. - static void RegisterMCInstrInfo(Target &T, Target::MCInstrInfoCtorFnTy Fn) { - T.MCInstrInfoCtorFn = Fn; - } - - /// RegisterMCInstrAnalysis - Register a MCInstrAnalysis implementation for - /// the given target. - static void RegisterMCInstrAnalysis(Target &T, - Target::MCInstrAnalysisCtorFnTy Fn) { - T.MCInstrAnalysisCtorFn = Fn; - } - - /// RegisterMCRegInfo - Register a MCRegisterInfo implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct a MCRegisterInfo for the target. - static void RegisterMCRegInfo(Target &T, Target::MCRegInfoCtorFnTy Fn) { - T.MCRegInfoCtorFn = Fn; - } - - /// RegisterMCSubtargetInfo - Register a MCSubtargetInfo implementation for - /// the given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct a MCSubtargetInfo for the target. - static void RegisterMCSubtargetInfo(Target &T, - Target::MCSubtargetInfoCtorFnTy Fn) { - T.MCSubtargetInfoCtorFn = Fn; - } - - /// RegisterTargetMachine - Register a TargetMachine implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct a TargetMachine for the target. - static void RegisterTargetMachine(Target &T, - Target::TargetMachineCtorTy Fn) { - T.TargetMachineCtorFn = Fn; - } - - /// RegisterMCAsmBackend - Register a MCAsmBackend implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an AsmBackend for the target. - static void RegisterMCAsmBackend(Target &T, Target::MCAsmBackendCtorTy Fn) { - T.MCAsmBackendCtorFn = Fn; - } - - /// RegisterMCAsmParser - Register a MCTargetAsmParser implementation for - /// the given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an MCTargetAsmParser for the target. - static void RegisterMCAsmParser(Target &T, Target::MCAsmParserCtorTy Fn) { - T.MCAsmParserCtorFn = Fn; - } - - /// RegisterAsmPrinter - Register an AsmPrinter implementation for the given - /// target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an AsmPrinter for the target. - static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn) { - T.AsmPrinterCtorFn = Fn; - } - - /// RegisterMCDisassembler - Register a MCDisassembler implementation for - /// the given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an MCDisassembler for the target. - static void RegisterMCDisassembler(Target &T, - Target::MCDisassemblerCtorTy Fn) { - T.MCDisassemblerCtorFn = Fn; - } + /// printRegisteredTargetsForVersion - Print the registered targets + /// appropriately for inclusion in a tool's version output. + static void printRegisteredTargetsForVersion(); - /// RegisterMCInstPrinter - Register a MCInstPrinter implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an MCInstPrinter for the target. - static void RegisterMCInstPrinter(Target &T, - Target::MCInstPrinterCtorTy Fn) { - T.MCInstPrinterCtorFn = Fn; - } + /// @name Registry Access + /// @{ - /// RegisterMCCodeEmitter - Register a MCCodeEmitter implementation for the - /// given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an MCCodeEmitter for the target. - static void RegisterMCCodeEmitter(Target &T, - Target::MCCodeEmitterCtorTy Fn) { - T.MCCodeEmitterCtorFn = Fn; - } + static iterator_range<iterator> targets(); - /// RegisterMCObjectStreamer - Register a object code MCStreamer - /// implementation for the given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an MCStreamer for the target. - static void RegisterMCObjectStreamer(Target &T, - Target::MCObjectStreamerCtorTy Fn) { - T.MCObjectStreamerCtorFn = Fn; - } - - /// RegisterAsmStreamer - Register an assembly MCStreamer implementation - /// for the given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an MCStreamer for the target. - static void RegisterAsmStreamer(Target &T, Target::AsmStreamerCtorTy Fn) { - T.AsmStreamerCtorFn = Fn; - } - - static void RegisterNullStreamer(Target &T, Target::NullStreamerCtorTy Fn) { - T.NullStreamerCtorFn = Fn; - } - - /// RegisterMCRelocationInfo - Register an MCRelocationInfo - /// implementation for the given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an MCRelocationInfo for the target. - static void RegisterMCRelocationInfo(Target &T, - Target::MCRelocationInfoCtorTy Fn) { - T.MCRelocationInfoCtorFn = Fn; - } - - /// RegisterMCSymbolizer - Register an MCSymbolizer - /// implementation for the given target. - /// - /// Clients are responsible for ensuring that registration doesn't occur - /// while another thread is attempting to access the registry. Typically - /// this is done by initializing all targets at program startup. - /// - /// @param T - The target being registered. - /// @param Fn - A function to construct an MCSymbolizer for the target. - static void RegisterMCSymbolizer(Target &T, - Target::MCSymbolizerCtorTy Fn) { - T.MCSymbolizerCtorFn = Fn; - } - - /// @} - }; - - - //===--------------------------------------------------------------------===// - - /// RegisterTarget - Helper template for registering a target, for use in the - /// target's initialization function. Usage: + /// lookupTarget - Lookup a target based on a target triple. /// + /// \param Triple - The triple to use for finding a target. + /// \param Error - On failure, an error string describing why no target was + /// found. + 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. /// - /// Target TheFooTarget; // The global target instance. + /// \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); + + /// @} + /// @name Target Registration + /// @{ + + /// RegisterTarget - Register the given target. Attempts to register a + /// target which has already been registered will be ignored. /// - /// extern "C" void LLVMInitializeFooTargetInfo() { - /// RegisterTarget<Triple::foo> X(TheFooTarget, "foo", "Foo description"); - /// } - template<Triple::ArchType TargetArchType = Triple::UnknownArch, - bool HasJIT = false> - struct RegisterTarget { - RegisterTarget(Target &T, const char *Name, const char *Desc) { - TargetRegistry::RegisterTarget(T, Name, Desc, &getArchMatch, HasJIT); - } - - static bool getArchMatch(Triple::ArchType Arch) { - return Arch == TargetArchType; - } - }; - - /// RegisterMCAsmInfo - Helper template for registering a target assembly info - /// implementation. This invokes the static "Create" method on the class to - /// actually do the construction. Usage: + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCAsmInfo<FooMCAsmInfo> X(TheFooTarget); - /// } - template<class MCAsmInfoImpl> - struct RegisterMCAsmInfo { - RegisterMCAsmInfo(Target &T) { - TargetRegistry::RegisterMCAsmInfo(T, &Allocator); - } - private: - static MCAsmInfo *Allocator(const MCRegisterInfo &/*MRI*/, StringRef TT) { - return new MCAsmInfoImpl(TT); - } - - }; - - /// RegisterMCAsmInfoFn - Helper template for registering a target assembly info - /// implementation. This invokes the specified function to do the - /// construction. Usage: + /// @param T - The target being registered. + /// @param Name - The target name. This should be a static string. + /// @param ShortDesc - A short target description. This should be a static + /// string. + /// @param ArchMatchFn - The arch match checking function for this target. + /// @param HasJIT - Whether the target supports JIT code + /// generation. + static void RegisterTarget(Target &T, const char *Name, const char *ShortDesc, + Target::ArchMatchFnTy ArchMatchFn, + bool HasJIT = false); + + /// RegisterMCAsmInfo - Register a MCAsmInfo implementation for the + /// given target. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCAsmInfoFn X(TheFooTarget, TheFunction); - /// } - struct RegisterMCAsmInfoFn { - RegisterMCAsmInfoFn(Target &T, Target::MCAsmInfoCtorFnTy Fn) { - TargetRegistry::RegisterMCAsmInfo(T, Fn); - } - }; - - /// RegisterMCCodeGenInfo - Helper template for registering a target codegen info - /// implementation. This invokes the static "Create" method on the class - /// to actually do the construction. Usage: + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCCodeGenInfo<FooMCCodeGenInfo> X(TheFooTarget); - /// } - template<class MCCodeGenInfoImpl> - struct RegisterMCCodeGenInfo { - RegisterMCCodeGenInfo(Target &T) { - TargetRegistry::RegisterMCCodeGenInfo(T, &Allocator); - } - private: - static MCCodeGenInfo *Allocator(StringRef /*TT*/, Reloc::Model /*RM*/, - CodeModel::Model /*CM*/, - CodeGenOpt::Level /*OL*/) { - return new MCCodeGenInfoImpl(); - } - }; - - /// RegisterMCCodeGenInfoFn - Helper template for registering a target codegen - /// info implementation. This invokes the specified function to do the - /// construction. Usage: + /// @param T - The target being registered. + /// @param Fn - A function to construct a MCAsmInfo for the target. + static void RegisterMCAsmInfo(Target &T, Target::MCAsmInfoCtorFnTy Fn) { + T.MCAsmInfoCtorFn = Fn; + } + + /// RegisterMCCodeGenInfo - Register a MCCodeGenInfo implementation for the + /// given target. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCCodeGenInfoFn X(TheFooTarget, TheFunction); - /// } - struct RegisterMCCodeGenInfoFn { - RegisterMCCodeGenInfoFn(Target &T, Target::MCCodeGenInfoCtorFnTy Fn) { - TargetRegistry::RegisterMCCodeGenInfo(T, Fn); - } - }; - - /// RegisterMCInstrInfo - Helper template for registering a target instruction - /// info implementation. This invokes the static "Create" method on the class - /// to actually do the construction. Usage: + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCInstrInfo<FooMCInstrInfo> X(TheFooTarget); - /// } - template<class MCInstrInfoImpl> - struct RegisterMCInstrInfo { - RegisterMCInstrInfo(Target &T) { - TargetRegistry::RegisterMCInstrInfo(T, &Allocator); - } - private: - static MCInstrInfo *Allocator() { - return new MCInstrInfoImpl(); - } - }; - - /// RegisterMCInstrInfoFn - Helper template for registering a target - /// instruction info implementation. This invokes the specified function to - /// do the construction. Usage: + /// @param T - The target being registered. + /// @param Fn - A function to construct a MCCodeGenInfo for the target. + static void RegisterMCCodeGenInfo(Target &T, + Target::MCCodeGenInfoCtorFnTy Fn) { + T.MCCodeGenInfoCtorFn = Fn; + } + + /// RegisterMCInstrInfo - Register a MCInstrInfo implementation for the + /// given target. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCInstrInfoFn X(TheFooTarget, TheFunction); - /// } - struct RegisterMCInstrInfoFn { - RegisterMCInstrInfoFn(Target &T, Target::MCInstrInfoCtorFnTy Fn) { - TargetRegistry::RegisterMCInstrInfo(T, Fn); - } - }; - - /// RegisterMCInstrAnalysis - Helper template for registering a target - /// instruction analyzer implementation. This invokes the static "Create" - /// method on the class to actually do the construction. Usage: + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCInstrAnalysis<FooMCInstrAnalysis> X(TheFooTarget); - /// } - template<class MCInstrAnalysisImpl> - struct RegisterMCInstrAnalysis { - RegisterMCInstrAnalysis(Target &T) { - TargetRegistry::RegisterMCInstrAnalysis(T, &Allocator); - } - private: - static MCInstrAnalysis *Allocator(const MCInstrInfo *Info) { - return new MCInstrAnalysisImpl(Info); - } - }; - - /// RegisterMCInstrAnalysisFn - Helper template for registering a target - /// instruction analyzer implementation. This invokes the specified function - /// to do the construction. Usage: + /// @param T - The target being registered. + /// @param Fn - A function to construct a MCInstrInfo for the target. + static void RegisterMCInstrInfo(Target &T, Target::MCInstrInfoCtorFnTy Fn) { + T.MCInstrInfoCtorFn = Fn; + } + + /// RegisterMCInstrAnalysis - Register a MCInstrAnalysis implementation for + /// the given target. + static void RegisterMCInstrAnalysis(Target &T, + Target::MCInstrAnalysisCtorFnTy Fn) { + T.MCInstrAnalysisCtorFn = Fn; + } + + /// RegisterMCRegInfo - Register a MCRegisterInfo implementation for the + /// given target. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCInstrAnalysisFn X(TheFooTarget, TheFunction); - /// } - struct RegisterMCInstrAnalysisFn { - RegisterMCInstrAnalysisFn(Target &T, Target::MCInstrAnalysisCtorFnTy Fn) { - TargetRegistry::RegisterMCInstrAnalysis(T, Fn); - } - }; - - /// RegisterMCRegInfo - Helper template for registering a target register info - /// implementation. This invokes the static "Create" method on the class to - /// actually do the construction. Usage: + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCRegInfo<FooMCRegInfo> X(TheFooTarget); - /// } - template<class MCRegisterInfoImpl> - struct RegisterMCRegInfo { - RegisterMCRegInfo(Target &T) { - TargetRegistry::RegisterMCRegInfo(T, &Allocator); - } - private: - static MCRegisterInfo *Allocator(StringRef /*TT*/) { - return new MCRegisterInfoImpl(); - } - }; - - /// RegisterMCRegInfoFn - Helper template for registering a target register - /// info implementation. This invokes the specified function to do the - /// construction. Usage: + /// @param T - The target being registered. + /// @param Fn - A function to construct a MCRegisterInfo for the target. + static void RegisterMCRegInfo(Target &T, Target::MCRegInfoCtorFnTy Fn) { + T.MCRegInfoCtorFn = Fn; + } + + /// RegisterMCSubtargetInfo - Register a MCSubtargetInfo implementation for + /// the given target. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCRegInfoFn X(TheFooTarget, TheFunction); - /// } - struct RegisterMCRegInfoFn { - RegisterMCRegInfoFn(Target &T, Target::MCRegInfoCtorFnTy Fn) { - TargetRegistry::RegisterMCRegInfo(T, Fn); - } - }; - - /// RegisterMCSubtargetInfo - Helper template for registering a target - /// subtarget info implementation. This invokes the static "Create" method - /// on the class to actually do the construction. Usage: + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCSubtargetInfo<FooMCSubtargetInfo> X(TheFooTarget); - /// } - template<class MCSubtargetInfoImpl> - struct RegisterMCSubtargetInfo { - RegisterMCSubtargetInfo(Target &T) { - TargetRegistry::RegisterMCSubtargetInfo(T, &Allocator); - } - private: - static MCSubtargetInfo *Allocator(StringRef /*TT*/, StringRef /*CPU*/, - StringRef /*FS*/) { - return new MCSubtargetInfoImpl(); - } - }; - - /// RegisterMCSubtargetInfoFn - Helper template for registering a target - /// subtarget info implementation. This invokes the specified function to - /// do the construction. Usage: + /// @param T - The target being registered. + /// @param Fn - A function to construct a MCSubtargetInfo for the target. + static void RegisterMCSubtargetInfo(Target &T, + Target::MCSubtargetInfoCtorFnTy Fn) { + T.MCSubtargetInfoCtorFn = Fn; + } + + /// RegisterTargetMachine - Register a TargetMachine implementation for the + /// given target. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterMCSubtargetInfoFn X(TheFooTarget, TheFunction); - /// } - struct RegisterMCSubtargetInfoFn { - RegisterMCSubtargetInfoFn(Target &T, Target::MCSubtargetInfoCtorFnTy Fn) { - TargetRegistry::RegisterMCSubtargetInfo(T, Fn); - } - }; - - /// RegisterTargetMachine - Helper template for registering a target machine - /// implementation, for use in the target machine initialization - /// function. Usage: + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. /// - /// extern "C" void LLVMInitializeFooTarget() { - /// extern Target TheFooTarget; - /// RegisterTargetMachine<FooTargetMachine> X(TheFooTarget); - /// } - template<class TargetMachineImpl> - struct RegisterTargetMachine { - RegisterTargetMachine(Target &T) { - TargetRegistry::RegisterTargetMachine(T, &Allocator); - } - - private: - static TargetMachine *Allocator(const Target &T, StringRef TT, - StringRef CPU, StringRef FS, - const TargetOptions &Options, - Reloc::Model RM, - CodeModel::Model CM, - CodeGenOpt::Level OL) { - return new TargetMachineImpl(T, TT, CPU, FS, Options, RM, CM, OL); - } - }; - - /// RegisterMCAsmBackend - Helper template for registering a target specific - /// assembler backend. Usage: + /// @param T - The target being registered. + /// @param Fn - A function to construct a TargetMachine for the target. + static void RegisterTargetMachine(Target &T, Target::TargetMachineCtorTy Fn) { + T.TargetMachineCtorFn = Fn; + } + + /// RegisterMCAsmBackend - Register a MCAsmBackend implementation for the + /// given target. /// - /// extern "C" void LLVMInitializeFooMCAsmBackend() { - /// extern Target TheFooTarget; - /// RegisterMCAsmBackend<FooAsmLexer> X(TheFooTarget); - /// } - template<class MCAsmBackendImpl> - struct RegisterMCAsmBackend { - RegisterMCAsmBackend(Target &T) { - TargetRegistry::RegisterMCAsmBackend(T, &Allocator); - } - - private: - static MCAsmBackend *Allocator(const Target &T, - const MCRegisterInfo &MRI, - StringRef Triple, StringRef CPU) { - return new MCAsmBackendImpl(T, MRI, Triple, CPU); - } - }; - - /// RegisterMCAsmParser - Helper template for registering a target specific - /// assembly parser, for use in the target machine initialization - /// function. Usage: + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. /// - /// extern "C" void LLVMInitializeFooMCAsmParser() { - /// extern Target TheFooTarget; - /// RegisterMCAsmParser<FooAsmParser> X(TheFooTarget); - /// } - template<class MCAsmParserImpl> - struct RegisterMCAsmParser { - RegisterMCAsmParser(Target &T) { - TargetRegistry::RegisterMCAsmParser(T, &Allocator); - } - - private: - static MCTargetAsmParser *Allocator(MCSubtargetInfo &STI, MCAsmParser &P, - const MCInstrInfo &MII, - const MCTargetOptions &Options) { - return new MCAsmParserImpl(STI, P, MII, Options); - } - }; - - /// RegisterAsmPrinter - Helper template for registering a target specific - /// assembly printer, for use in the target machine initialization - /// function. Usage: + /// @param T - The target being registered. + /// @param Fn - A function to construct an AsmBackend for the target. + static void RegisterMCAsmBackend(Target &T, Target::MCAsmBackendCtorTy Fn) { + T.MCAsmBackendCtorFn = Fn; + } + + /// RegisterMCAsmParser - Register a MCTargetAsmParser implementation for + /// the given target. /// - /// extern "C" void LLVMInitializeFooAsmPrinter() { - /// extern Target TheFooTarget; - /// RegisterAsmPrinter<FooAsmPrinter> X(TheFooTarget); - /// } - template<class AsmPrinterImpl> - struct RegisterAsmPrinter { - RegisterAsmPrinter(Target &T) { - TargetRegistry::RegisterAsmPrinter(T, &Allocator); - } - - private: - static AsmPrinter *Allocator(TargetMachine &TM, MCStreamer &Streamer) { - return new AsmPrinterImpl(TM, Streamer); - } - }; - - /// RegisterMCCodeEmitter - Helper template for registering a target specific - /// machine code emitter, for use in the target initialization - /// function. Usage: + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. /// - /// extern "C" void LLVMInitializeFooMCCodeEmitter() { - /// extern Target TheFooTarget; - /// RegisterMCCodeEmitter<FooCodeEmitter> X(TheFooTarget); - /// } - template<class MCCodeEmitterImpl> - struct RegisterMCCodeEmitter { - RegisterMCCodeEmitter(Target &T) { - TargetRegistry::RegisterMCCodeEmitter(T, &Allocator); - } - - private: - static MCCodeEmitter *Allocator(const MCInstrInfo &/*II*/, - const MCRegisterInfo &/*MRI*/, - const MCSubtargetInfo &/*STI*/, - MCContext &/*Ctx*/) { - return new MCCodeEmitterImpl(); - } - }; - + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCTargetAsmParser for the target. + static void RegisterMCAsmParser(Target &T, Target::MCAsmParserCtorTy Fn) { + T.MCAsmParserCtorFn = Fn; + } + + /// RegisterAsmPrinter - Register an AsmPrinter implementation for the given + /// target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an AsmPrinter for the target. + static void RegisterAsmPrinter(Target &T, Target::AsmPrinterCtorTy Fn) { + T.AsmPrinterCtorFn = Fn; + } + + /// RegisterMCDisassembler - Register a MCDisassembler implementation for + /// the given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCDisassembler for the target. + static void RegisterMCDisassembler(Target &T, + Target::MCDisassemblerCtorTy Fn) { + T.MCDisassemblerCtorFn = Fn; + } + + /// RegisterMCInstPrinter - Register a MCInstPrinter implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCInstPrinter for the target. + static void RegisterMCInstPrinter(Target &T, Target::MCInstPrinterCtorTy Fn) { + T.MCInstPrinterCtorFn = Fn; + } + + /// RegisterMCCodeEmitter - Register a MCCodeEmitter implementation for the + /// given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCCodeEmitter for the target. + static void RegisterMCCodeEmitter(Target &T, Target::MCCodeEmitterCtorTy Fn) { + T.MCCodeEmitterCtorFn = Fn; + } + + static void RegisterCOFFStreamer(Target &T, Target::COFFStreamerCtorTy Fn) { + T.COFFStreamerCtorFn = Fn; + } + + static void RegisterMachOStreamer(Target &T, Target::MachOStreamerCtorTy Fn) { + T.MachOStreamerCtorFn = Fn; + } + + static void RegisterELFStreamer(Target &T, Target::ELFStreamerCtorTy Fn) { + T.ELFStreamerCtorFn = Fn; + } + + static void RegisterNullTargetStreamer(Target &T, + Target::NullTargetStreamerCtorTy Fn) { + T.NullTargetStreamerCtorFn = Fn; + } + + static void RegisterAsmTargetStreamer(Target &T, + Target::AsmTargetStreamerCtorTy Fn) { + T.AsmTargetStreamerCtorFn = Fn; + } + + static void + RegisterObjectTargetStreamer(Target &T, + Target::ObjectTargetStreamerCtorTy Fn) { + T.ObjectTargetStreamerCtorFn = Fn; + } + + /// RegisterMCRelocationInfo - Register an MCRelocationInfo + /// implementation for the given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCRelocationInfo for the target. + static void RegisterMCRelocationInfo(Target &T, + Target::MCRelocationInfoCtorTy Fn) { + T.MCRelocationInfoCtorFn = Fn; + } + + /// RegisterMCSymbolizer - Register an MCSymbolizer + /// implementation for the given target. + /// + /// Clients are responsible for ensuring that registration doesn't occur + /// while another thread is attempting to access the registry. Typically + /// this is done by initializing all targets at program startup. + /// + /// @param T - The target being registered. + /// @param Fn - A function to construct an MCSymbolizer for the target. + static void RegisterMCSymbolizer(Target &T, Target::MCSymbolizerCtorTy Fn) { + T.MCSymbolizerCtorFn = Fn; + } + + /// @} +}; + +//===--------------------------------------------------------------------===// + +/// RegisterTarget - Helper template for registering a target, for use in the +/// target's initialization function. Usage: +/// +/// +/// Target TheFooTarget; // The global target instance. +/// +/// extern "C" void LLVMInitializeFooTargetInfo() { +/// RegisterTarget<Triple::foo> X(TheFooTarget, "foo", "Foo description"); +/// } +template <Triple::ArchType TargetArchType = Triple::UnknownArch, + bool HasJIT = false> +struct RegisterTarget { + RegisterTarget(Target &T, const char *Name, const char *Desc) { + TargetRegistry::RegisterTarget(T, Name, Desc, &getArchMatch, HasJIT); + } + + static bool getArchMatch(Triple::ArchType Arch) { + return Arch == TargetArchType; + } +}; + +/// RegisterMCAsmInfo - Helper template for registering a target assembly info +/// implementation. This invokes the static "Create" method on the class to +/// actually do the construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCAsmInfo<FooMCAsmInfo> X(TheFooTarget); +/// } +template <class MCAsmInfoImpl> struct RegisterMCAsmInfo { + RegisterMCAsmInfo(Target &T) { + TargetRegistry::RegisterMCAsmInfo(T, &Allocator); + } + +private: + static MCAsmInfo *Allocator(const MCRegisterInfo & /*MRI*/, StringRef TT) { + return new MCAsmInfoImpl(TT); + } +}; + +/// RegisterMCAsmInfoFn - Helper template for registering a target assembly info +/// implementation. This invokes the specified function to do the +/// construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCAsmInfoFn X(TheFooTarget, TheFunction); +/// } +struct RegisterMCAsmInfoFn { + RegisterMCAsmInfoFn(Target &T, Target::MCAsmInfoCtorFnTy Fn) { + TargetRegistry::RegisterMCAsmInfo(T, Fn); + } +}; + +/// RegisterMCCodeGenInfo - Helper template for registering a target codegen +/// info +/// implementation. This invokes the static "Create" method on the class +/// to actually do the construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCCodeGenInfo<FooMCCodeGenInfo> X(TheFooTarget); +/// } +template <class MCCodeGenInfoImpl> struct RegisterMCCodeGenInfo { + RegisterMCCodeGenInfo(Target &T) { + TargetRegistry::RegisterMCCodeGenInfo(T, &Allocator); + } + +private: + static MCCodeGenInfo *Allocator(StringRef /*TT*/, Reloc::Model /*RM*/, + CodeModel::Model /*CM*/, + CodeGenOpt::Level /*OL*/) { + return new MCCodeGenInfoImpl(); + } +}; + +/// RegisterMCCodeGenInfoFn - Helper template for registering a target codegen +/// info implementation. This invokes the specified function to do the +/// construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCCodeGenInfoFn X(TheFooTarget, TheFunction); +/// } +struct RegisterMCCodeGenInfoFn { + RegisterMCCodeGenInfoFn(Target &T, Target::MCCodeGenInfoCtorFnTy Fn) { + TargetRegistry::RegisterMCCodeGenInfo(T, Fn); + } +}; + +/// RegisterMCInstrInfo - Helper template for registering a target instruction +/// info implementation. This invokes the static "Create" method on the class +/// to actually do the construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCInstrInfo<FooMCInstrInfo> X(TheFooTarget); +/// } +template <class MCInstrInfoImpl> struct RegisterMCInstrInfo { + RegisterMCInstrInfo(Target &T) { + TargetRegistry::RegisterMCInstrInfo(T, &Allocator); + } + +private: + static MCInstrInfo *Allocator() { return new MCInstrInfoImpl(); } +}; + +/// RegisterMCInstrInfoFn - Helper template for registering a target +/// instruction info implementation. This invokes the specified function to +/// do the construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCInstrInfoFn X(TheFooTarget, TheFunction); +/// } +struct RegisterMCInstrInfoFn { + RegisterMCInstrInfoFn(Target &T, Target::MCInstrInfoCtorFnTy Fn) { + TargetRegistry::RegisterMCInstrInfo(T, Fn); + } +}; + +/// RegisterMCInstrAnalysis - Helper template for registering a target +/// instruction analyzer implementation. This invokes the static "Create" +/// method on the class to actually do the construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCInstrAnalysis<FooMCInstrAnalysis> X(TheFooTarget); +/// } +template <class MCInstrAnalysisImpl> struct RegisterMCInstrAnalysis { + RegisterMCInstrAnalysis(Target &T) { + TargetRegistry::RegisterMCInstrAnalysis(T, &Allocator); + } + +private: + static MCInstrAnalysis *Allocator(const MCInstrInfo *Info) { + return new MCInstrAnalysisImpl(Info); + } +}; + +/// RegisterMCInstrAnalysisFn - Helper template for registering a target +/// instruction analyzer implementation. This invokes the specified function +/// to do the construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCInstrAnalysisFn X(TheFooTarget, TheFunction); +/// } +struct RegisterMCInstrAnalysisFn { + RegisterMCInstrAnalysisFn(Target &T, Target::MCInstrAnalysisCtorFnTy Fn) { + TargetRegistry::RegisterMCInstrAnalysis(T, Fn); + } +}; + +/// RegisterMCRegInfo - Helper template for registering a target register info +/// implementation. This invokes the static "Create" method on the class to +/// actually do the construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCRegInfo<FooMCRegInfo> X(TheFooTarget); +/// } +template <class MCRegisterInfoImpl> struct RegisterMCRegInfo { + RegisterMCRegInfo(Target &T) { + TargetRegistry::RegisterMCRegInfo(T, &Allocator); + } + +private: + static MCRegisterInfo *Allocator(StringRef /*TT*/) { + return new MCRegisterInfoImpl(); + } +}; + +/// RegisterMCRegInfoFn - Helper template for registering a target register +/// info implementation. This invokes the specified function to do the +/// construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCRegInfoFn X(TheFooTarget, TheFunction); +/// } +struct RegisterMCRegInfoFn { + RegisterMCRegInfoFn(Target &T, Target::MCRegInfoCtorFnTy Fn) { + TargetRegistry::RegisterMCRegInfo(T, Fn); + } +}; + +/// RegisterMCSubtargetInfo - Helper template for registering a target +/// subtarget info implementation. This invokes the static "Create" method +/// on the class to actually do the construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCSubtargetInfo<FooMCSubtargetInfo> X(TheFooTarget); +/// } +template <class MCSubtargetInfoImpl> struct RegisterMCSubtargetInfo { + RegisterMCSubtargetInfo(Target &T) { + TargetRegistry::RegisterMCSubtargetInfo(T, &Allocator); + } + +private: + static MCSubtargetInfo *Allocator(StringRef /*TT*/, StringRef /*CPU*/, + StringRef /*FS*/) { + return new MCSubtargetInfoImpl(); + } +}; + +/// RegisterMCSubtargetInfoFn - Helper template for registering a target +/// subtarget info implementation. This invokes the specified function to +/// do the construction. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterMCSubtargetInfoFn X(TheFooTarget, TheFunction); +/// } +struct RegisterMCSubtargetInfoFn { + RegisterMCSubtargetInfoFn(Target &T, Target::MCSubtargetInfoCtorFnTy Fn) { + TargetRegistry::RegisterMCSubtargetInfo(T, Fn); + } +}; + +/// RegisterTargetMachine - Helper template for registering a target machine +/// implementation, for use in the target machine initialization +/// function. Usage: +/// +/// extern "C" void LLVMInitializeFooTarget() { +/// extern Target TheFooTarget; +/// RegisterTargetMachine<FooTargetMachine> X(TheFooTarget); +/// } +template <class TargetMachineImpl> struct RegisterTargetMachine { + RegisterTargetMachine(Target &T) { + TargetRegistry::RegisterTargetMachine(T, &Allocator); + } + +private: + static TargetMachine *Allocator(const Target &T, StringRef TT, StringRef CPU, + StringRef FS, const TargetOptions &Options, + Reloc::Model RM, CodeModel::Model CM, + CodeGenOpt::Level OL) { + return new TargetMachineImpl(T, TT, CPU, FS, Options, RM, CM, OL); + } +}; + +/// RegisterMCAsmBackend - Helper template for registering a target specific +/// assembler backend. Usage: +/// +/// extern "C" void LLVMInitializeFooMCAsmBackend() { +/// extern Target TheFooTarget; +/// RegisterMCAsmBackend<FooAsmLexer> X(TheFooTarget); +/// } +template <class MCAsmBackendImpl> struct RegisterMCAsmBackend { + RegisterMCAsmBackend(Target &T) { + TargetRegistry::RegisterMCAsmBackend(T, &Allocator); + } + +private: + static MCAsmBackend *Allocator(const Target &T, const MCRegisterInfo &MRI, + StringRef Triple, StringRef CPU) { + return new MCAsmBackendImpl(T, MRI, Triple, CPU); + } +}; + +/// RegisterMCAsmParser - Helper template for registering a target specific +/// assembly parser, for use in the target machine initialization +/// function. Usage: +/// +/// extern "C" void LLVMInitializeFooMCAsmParser() { +/// extern Target TheFooTarget; +/// RegisterMCAsmParser<FooAsmParser> X(TheFooTarget); +/// } +template <class MCAsmParserImpl> struct RegisterMCAsmParser { + RegisterMCAsmParser(Target &T) { + TargetRegistry::RegisterMCAsmParser(T, &Allocator); + } + +private: + static MCTargetAsmParser *Allocator(MCSubtargetInfo &STI, MCAsmParser &P, + const MCInstrInfo &MII, + const MCTargetOptions &Options) { + return new MCAsmParserImpl(STI, P, MII, Options); + } +}; + +/// RegisterAsmPrinter - Helper template for registering a target specific +/// assembly printer, for use in the target machine initialization +/// function. Usage: +/// +/// extern "C" void LLVMInitializeFooAsmPrinter() { +/// extern Target TheFooTarget; +/// RegisterAsmPrinter<FooAsmPrinter> X(TheFooTarget); +/// } +template <class AsmPrinterImpl> struct RegisterAsmPrinter { + RegisterAsmPrinter(Target &T) { + TargetRegistry::RegisterAsmPrinter(T, &Allocator); + } + +private: + static AsmPrinter *Allocator(TargetMachine &TM, + std::unique_ptr<MCStreamer> &&Streamer) { + return new AsmPrinterImpl(TM, std::move(Streamer)); + } +}; + +/// RegisterMCCodeEmitter - Helper template for registering a target specific +/// machine code emitter, for use in the target initialization +/// function. Usage: +/// +/// extern "C" void LLVMInitializeFooMCCodeEmitter() { +/// extern Target TheFooTarget; +/// RegisterMCCodeEmitter<FooCodeEmitter> X(TheFooTarget); +/// } +template <class MCCodeEmitterImpl> struct RegisterMCCodeEmitter { + RegisterMCCodeEmitter(Target &T) { + TargetRegistry::RegisterMCCodeEmitter(T, &Allocator); + } + +private: + static MCCodeEmitter *Allocator(const MCInstrInfo & /*II*/, + const MCRegisterInfo & /*MRI*/, + MCContext & /*Ctx*/) { + return new MCCodeEmitterImpl(); + } +}; } #endif diff --git a/include/llvm/Support/Timer.h b/include/llvm/Support/Timer.h index 45c182831b2a..2cd30e2aaf32 100644 --- a/include/llvm/Support/Timer.h +++ b/include/llvm/Support/Timer.h @@ -11,7 +11,6 @@ #define LLVM_SUPPORT_TIMER_H #include "llvm/ADT/StringRef.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" #include <cassert> #include <string> @@ -126,7 +125,7 @@ private: /// class TimeRegion { Timer *T; - TimeRegion(const TimeRegion &) LLVM_DELETED_FUNCTION; + TimeRegion(const TimeRegion &) = delete; public: explicit TimeRegion(Timer &t) : T(&t) { T->startTimer(); @@ -164,8 +163,8 @@ class TimerGroup { std::vector<std::pair<TimeRecord, std::string> > TimersToPrint; TimerGroup **Prev, *Next; // Doubly linked list of TimerGroup's. - TimerGroup(const TimerGroup &TG) LLVM_DELETED_FUNCTION; - void operator=(const TimerGroup &TG) LLVM_DELETED_FUNCTION; + TimerGroup(const TimerGroup &TG) = delete; + void operator=(const TimerGroup &TG) = delete; public: explicit TimerGroup(StringRef name); ~TimerGroup(); diff --git a/include/llvm/Support/ToolOutputFile.h b/include/llvm/Support/ToolOutputFile.h index d98e7bbd51d4..1be26c2cb58b 100644 --- a/include/llvm/Support/ToolOutputFile.h +++ b/include/llvm/Support/ToolOutputFile.h @@ -18,16 +18,16 @@ namespace llvm { -/// tool_output_file - This class contains a raw_fd_ostream and adds a -/// few extra features commonly needed for compiler-like tool output files: +/// This class contains a raw_fd_ostream and adds a few extra features commonly +/// needed for compiler-like tool output files: /// - The file is automatically deleted if the process is killed. /// - The file is automatically deleted when the tool_output_file /// object is destroyed unless the client calls keep(). class tool_output_file { - /// Installer - This class is declared before the raw_fd_ostream so that - /// it is constructed before the raw_fd_ostream is constructed and - /// destructed after the raw_fd_ostream is destructed. It installs - /// cleanups in its constructor and uninstalls them in its destructor. + /// This class is declared before the raw_fd_ostream so that it is constructed + /// before the raw_fd_ostream is constructed and destructed after the + /// raw_fd_ostream is destructed. It installs cleanups in its constructor and + /// uninstalls them in its destructor. class CleanupInstaller { /// The name of the file. std::string Filename; @@ -39,8 +39,7 @@ class tool_output_file { ~CleanupInstaller(); } Installer; - /// OS - The contained stream. This is intentionally declared after - /// Installer. + /// The contained stream. This is intentionally declared after Installer. raw_fd_ostream OS; public: @@ -51,11 +50,11 @@ public: tool_output_file(StringRef Filename, int FD); - /// os - Return the contained raw_fd_ostream. + /// Return the contained raw_fd_ostream. raw_fd_ostream &os() { return OS; } - /// keep - Indicate that the tool's job wrt this output file has been - /// successful and the file should not be deleted. + /// Indicate that the tool's job wrt this output file has been successful and + /// the file should not be deleted. void keep() { Installer.Keep = true; } }; diff --git a/include/llvm/Support/UnicodeCharRanges.h b/include/llvm/Support/UnicodeCharRanges.h index 79137bf35363..9f738dff1107 100644 --- a/include/llvm/Support/UnicodeCharRanges.h +++ b/include/llvm/Support/UnicodeCharRanges.h @@ -50,9 +50,13 @@ public: /// the UnicodeCharSet instance, and should not change. Array is validated by /// the constructor, so it makes sense to create as few UnicodeCharSet /// instances per each array of ranges, as possible. +#ifdef NDEBUG + LLVM_CONSTEXPR UnicodeCharSet(CharRanges Ranges) : Ranges(Ranges) {} +#else UnicodeCharSet(CharRanges Ranges) : Ranges(Ranges) { assert(rangesAreValid()); } +#endif /// \brief Returns true if the character set contains the Unicode code point /// \p C. diff --git a/include/llvm/Support/UniqueLock.h b/include/llvm/Support/UniqueLock.h index 5a4c273e83e2..529284d3868b 100644 --- a/include/llvm/Support/UniqueLock.h +++ b/include/llvm/Support/UniqueLock.h @@ -29,8 +29,8 @@ namespace llvm { MutexT *M; bool locked; - unique_lock(const unique_lock &) LLVM_DELETED_FUNCTION; - void operator=(const unique_lock &) LLVM_DELETED_FUNCTION; + unique_lock(const unique_lock &) = delete; + void operator=(const unique_lock &) = delete; public: unique_lock() : M(nullptr), locked(false) {} explicit unique_lock(MutexT &m) : M(&m), locked(true) { M->lock(); } diff --git a/include/llvm/Support/Watchdog.h b/include/llvm/Support/Watchdog.h index b58496b2fb8e..01e1d926eb95 100644 --- a/include/llvm/Support/Watchdog.h +++ b/include/llvm/Support/Watchdog.h @@ -29,8 +29,8 @@ namespace llvm { ~Watchdog(); private: // Noncopyable. - Watchdog(const Watchdog &other) LLVM_DELETED_FUNCTION; - Watchdog &operator=(const Watchdog &other) LLVM_DELETED_FUNCTION; + Watchdog(const Watchdog &other) = delete; + Watchdog &operator=(const Watchdog &other) = delete; }; } } diff --git a/include/llvm/Support/YAMLParser.h b/include/llvm/Support/YAMLParser.h index de6e6544e25b..0fbb7d2e6c7e 100644 --- a/include/llvm/Support/YAMLParser.h +++ b/include/llvm/Support/YAMLParser.h @@ -38,19 +38,18 @@ #ifndef LLVM_SUPPORT_YAMLPARSER_H #define LLVM_SUPPORT_YAMLPARSER_H -#include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SMLoc.h" #include <limits> #include <map> #include <utility> namespace llvm { +class MemoryBufferRef; class SourceMgr; -class raw_ostream; class Twine; +class raw_ostream; namespace yaml { @@ -77,9 +76,9 @@ std::string escape(StringRef Input); class Stream { public: /// \brief This keeps a reference to the string referenced by \p Input. - Stream(StringRef Input, SourceMgr &); + Stream(StringRef Input, SourceMgr &, bool ShowColors = true); - Stream(MemoryBufferRef InputBuffer, SourceMgr &); + Stream(MemoryBufferRef InputBuffer, SourceMgr &, bool ShowColors = true); ~Stream(); document_iterator begin(); @@ -108,6 +107,7 @@ public: enum NodeKind { NK_Null, NK_Scalar, + NK_BlockScalar, NK_KeyValue, NK_Mapping, NK_Sequence, @@ -159,7 +159,7 @@ protected: void operator delete(void *) throw() {} - virtual ~Node() {} + ~Node() = default; private: unsigned int TypeID; @@ -172,7 +172,7 @@ private: /// /// Example: /// !!null null -class NullNode : public Node { +class NullNode final : public Node { void anchor() override; public: @@ -187,7 +187,7 @@ public: /// /// Example: /// Adena -class ScalarNode : public Node { +class ScalarNode final : public Node { void anchor() override; public: @@ -223,6 +223,36 @@ private: SmallVectorImpl<char> &Storage) const; }; +/// \brief A block scalar node is an opaque datum that can be presented as a +/// series of zero or more Unicode scalar values. +/// +/// Example: +/// | +/// Hello +/// World +class BlockScalarNode final : public Node { + void anchor() override; + +public: + BlockScalarNode(std::unique_ptr<Document> &D, StringRef Anchor, StringRef Tag, + StringRef Value, StringRef RawVal) + : Node(NK_BlockScalar, D, Anchor, Tag), Value(Value) { + SMLoc Start = SMLoc::getFromPointer(RawVal.begin()); + SMLoc End = SMLoc::getFromPointer(RawVal.end()); + SourceRange = SMRange(Start, End); + } + + /// \brief Gets the value of this node as a StringRef. + StringRef getValue() const { return Value; } + + static inline bool classof(const Node *N) { + return N->getType() == NK_BlockScalar; + } + +private: + StringRef Value; +}; + /// \brief A key and value pair. While not technically a Node under the YAML /// representation graph, it is easier to treat them this way. /// @@ -230,7 +260,7 @@ private: /// /// Example: /// Section: .text -class KeyValueNode : public Node { +class KeyValueNode final : public Node { void anchor() override; public: @@ -254,7 +284,8 @@ public: void skip() override { getKey()->skip(); - getValue()->skip(); + if (Node *Val = getValue()) + Val->skip(); } static inline bool classof(const Node *N) { @@ -340,7 +371,7 @@ template <class CollectionType> void skip(CollectionType &C) { /// Example: /// Name: _main /// Scope: Global -class MappingNode : public Node { +class MappingNode final : public Node { void anchor() override; public: @@ -387,7 +418,7 @@ private: /// Example: /// - Hello /// - World -class SequenceNode : public Node { +class SequenceNode final : public Node { void anchor() override; public: @@ -440,7 +471,7 @@ private: /// /// Example: /// *AnchorName -class AliasNode : public Node { +class AliasNode final : public Node { void anchor() override; public: diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index 023dcee7d54c..3bdff2091809 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -46,6 +46,10 @@ struct MappingTraits { // static void mapping(IO &io, T &fields); // Optionally may provide: // static StringRef validate(IO &io, T &fields); + // + // The optional flow flag will cause generated YAML to use a flow mapping + // (e.g. { a: 0, b: 1 }): + // static const bool flow = true; }; @@ -117,6 +121,35 @@ struct ScalarTraits { }; +/// This class should be specialized by type that requires custom conversion +/// to/from a YAML literal block scalar. For example: +/// +/// template <> +/// struct BlockScalarTraits<MyType> { +/// static void output(const MyType &Value, void*, llvm::raw_ostream &Out) +/// { +/// // stream out custom formatting +/// Out << Val; +/// } +/// static StringRef input(StringRef Scalar, void*, MyType &Value) { +/// // parse scalar and set `value` +/// // return empty string on success, or error string +/// return StringRef(); +/// } +/// }; +template <typename T> +struct BlockScalarTraits { + // Must provide: + // + // Function to write the value as a string: + // static void output(const T &Value, void *ctx, llvm::raw_ostream &Out); + // + // Function to convert a string to a value. Returns the empty + // StringRef on success or an error string if string is malformed: + // static StringRef input(StringRef Scalar, void *ctxt, T &Value); +}; + + /// This class should be specialized by any type that needs to be converted /// to/from a YAML sequence. For example: /// @@ -220,6 +253,26 @@ public: }; +// Test if BlockScalarTraits<T> is defined on type T. +template <class T> +struct has_BlockScalarTraits +{ + typedef StringRef (*Signature_input)(StringRef, void *, T &); + typedef void (*Signature_output)(const T &, void *, llvm::raw_ostream &); + + template <typename U> + static char test(SameType<Signature_input, &U::input> *, + SameType<Signature_output, &U::output> *); + + template <typename U> + static double test(...); + +public: + static bool const value = + (sizeof(test<BlockScalarTraits<T>>(nullptr, nullptr)) == 1); +}; + + // Test if MappingTraits<T> is defined on type T. template <class T> struct has_MappingTraits @@ -406,6 +459,7 @@ struct missingTraits : public std::integral_constant<bool, !has_ScalarEnumerationTraits<T>::value && !has_ScalarBitSetTraits<T>::value && !has_ScalarTraits<T>::value + && !has_BlockScalarTraits<T>::value && !has_MappingTraits<T>::value && !has_SequenceTraits<T>::value && !has_DocumentListTraits<T>::value > {}; @@ -445,8 +499,12 @@ public: virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0; virtual void postflightKey(void*) = 0; + virtual void beginFlowMapping() = 0; + virtual void endFlowMapping() = 0; + virtual void beginEnumScalar() = 0; virtual bool matchEnumScalar(const char*, bool) = 0; + virtual bool matchEnumFallback() = 0; virtual void endEnumScalar() = 0; virtual bool beginBitSetScalar(bool &) = 0; @@ -454,6 +512,7 @@ public: virtual void endBitSetScalar() = 0; virtual void scalarString(StringRef &, bool) = 0; + virtual void blockScalarString(StringRef &) = 0; virtual void setError(const Twine &) = 0; @@ -472,6 +531,16 @@ public: } } + template <typename FBT, typename T> + void enumFallback(T &Val) { + if ( matchEnumFallback() ) { + // FIXME: Force integral conversion to allow strong typedefs to convert. + FBT Res = (uint64_t)Val; + yamlize(*this, Res, true); + Val = (uint64_t)Res; + } + } + template <typename T> void bitSetCase(T &Val, const char* Str, const T ConstVal) { if ( bitSetMatch(Str, outputting() && (Val & ConstVal) == ConstVal) ) { @@ -532,7 +601,7 @@ public: void mapOptional(const char* Key, T& Val, const T& Default) { this->processKeyWithDefault(Key, Val, Default, false); } - + private: template <typename T> void processKeyWithDefault(const char *Key, Optional<T> &Val, @@ -628,11 +697,32 @@ yamlize(IO &io, T &Val, bool) { } } +template <typename T> +typename std::enable_if<has_BlockScalarTraits<T>::value, void>::type +yamlize(IO &YamlIO, T &Val, bool) { + if (YamlIO.outputting()) { + std::string Storage; + llvm::raw_string_ostream Buffer(Storage); + BlockScalarTraits<T>::output(Val, YamlIO.getContext(), Buffer); + StringRef Str = Buffer.str(); + YamlIO.blockScalarString(Str); + } else { + StringRef Str; + YamlIO.blockScalarString(Str); + StringRef Result = + BlockScalarTraits<T>::input(Str, YamlIO.getContext(), Val); + if (!Result.empty()) + YamlIO.setError(llvm::Twine(Result)); + } +} template<typename T> typename std::enable_if<validatedMappingTraits<T>::value, void>::type yamlize(IO &io, T &Val, bool) { - io.beginMapping(); + if (has_FlowTraits<MappingTraits<T>>::value) + io.beginFlowMapping(); + else + io.beginMapping(); if (io.outputting()) { StringRef Err = MappingTraits<T>::validate(io, Val); if (!Err.empty()) { @@ -646,15 +736,24 @@ yamlize(IO &io, T &Val, bool) { if (!Err.empty()) io.setError(Err); } - io.endMapping(); + if (has_FlowTraits<MappingTraits<T>>::value) + io.endFlowMapping(); + else + io.endMapping(); } template<typename T> typename std::enable_if<unvalidatedMappingTraits<T>::value, void>::type yamlize(IO &io, T &Val, bool) { - io.beginMapping(); - MappingTraits<T>::mapping(io, Val); - io.endMapping(); + if (has_FlowTraits<MappingTraits<T>>::value) { + io.beginFlowMapping(); + MappingTraits<T>::mapping(io, Val); + io.endFlowMapping(); + } else { + io.beginMapping(); + MappingTraits<T>::mapping(io, Val); + io.endMapping(); + } } template<typename T> @@ -706,7 +805,7 @@ struct ScalarTraits<StringRef> { static StringRef input(StringRef, void*, StringRef &); static bool mustQuote(StringRef S) { return needsQuotes(S); } }; - + template<> struct ScalarTraits<std::string> { static void output(const std::string &, void*, llvm::raw_ostream &); @@ -877,7 +976,7 @@ public: void *Ctxt = nullptr, SourceMgr::DiagHandlerTy DiagHandler = nullptr, void *DiagHandlerCtxt = nullptr); - ~Input(); + ~Input() override; // Check if there was an syntax or semantic error during parsing. std::error_code error(); @@ -889,6 +988,8 @@ private: void endMapping() override; bool preflightKey(const char *, bool, bool, bool &, void *&) override; void postflightKey(void *) override; + void beginFlowMapping() override; + void endFlowMapping() override; unsigned beginSequence() override; void endSequence() override; bool preflightElement(unsigned index, void *&) override; @@ -899,11 +1000,13 @@ private: void endFlowSequence() override; void beginEnumScalar() override; bool matchEnumScalar(const char*, bool) override; + bool matchEnumFallback() override; void endEnumScalar() override; bool beginBitSetScalar(bool &) override; bool bitSetMatch(const char *, bool ) override; void endBitSetScalar() override; void scalarString(StringRef &, bool) override; + void blockScalarString(StringRef &) override; void setError(const Twine &message) override; bool canElideEmptySequence() override; @@ -935,7 +1038,8 @@ private: StringRef value() const { return _value; } static inline bool classof(const HNode *n) { - return ScalarNode::classof(n->_node); + return ScalarNode::classof(n->_node) || + BlockScalarNode::classof(n->_node); } static inline bool classof(const ScalarHNode *) { return true; } protected: @@ -943,7 +1047,7 @@ private: }; class MapHNode : public HNode { - virtual void anchor(); + void anchor() override; public: MapHNode(Node *n) : HNode(n) { } @@ -962,7 +1066,7 @@ private: }; class SequenceHNode : public HNode { - virtual void anchor(); + void anchor() override; public: SequenceHNode(Node *n) : HNode(n) { } @@ -1008,7 +1112,7 @@ private: class Output : public IO { public: Output(llvm::raw_ostream &, void *Ctxt=nullptr); - virtual ~Output(); + ~Output() override; bool outputting() override; bool mapTag(StringRef, bool) override; @@ -1016,6 +1120,8 @@ public: void endMapping() override; bool preflightKey(const char *key, bool, bool, bool &, void *&) override; void postflightKey(void *) override; + void beginFlowMapping() override; + void endFlowMapping() override; unsigned beginSequence() override; void endSequence() override; bool preflightElement(unsigned, void *&) override; @@ -1026,11 +1132,13 @@ public: void endFlowSequence() override; void beginEnumScalar() override; bool matchEnumScalar(const char*, bool) override; + bool matchEnumFallback() override; void endEnumScalar() override; bool beginBitSetScalar(bool &) override; bool bitSetMatch(const char *, bool ) override; void endBitSetScalar() override; void scalarString(StringRef &, bool) override; + void blockScalarString(StringRef &) override; void setError(const Twine &message) override; bool canElideEmptySequence() override; public: @@ -1047,13 +1155,22 @@ private: void newLineCheck(); void outputNewLine(); void paddedKey(StringRef key); - - enum InState { inSeq, inFlowSeq, inMapFirstKey, inMapOtherKey }; + void flowKey(StringRef Key); + + enum InState { + inSeq, + inFlowSeq, + inMapFirstKey, + inMapOtherKey, + inFlowMapFirstKey, + inFlowMapOtherKey + }; llvm::raw_ostream &Out; SmallVector<InState, 8> StateStack; int Column; int ColumnAtFlowStart; + int ColumnAtMapFlowStart; bool NeedBitValueComma; bool NeedFlowSequenceComma; bool EnumerationMatchFound; @@ -1163,6 +1280,16 @@ operator>>(Input &yin, T &docSeq) { return yin; } +// Define non-member operator>> so that Input can stream in a block scalar. +template <typename T> +inline +typename std::enable_if<has_BlockScalarTraits<T>::value, Input &>::type +operator>>(Input &In, T &Val) { + if (In.setCurrentDocument()) + yamlize(In, Val, true); + return In; +} + // Provide better error message about types missing a trait specialization template <typename T> inline @@ -1218,6 +1345,20 @@ operator<<(Output &yout, T &seq) { return yout; } +// Define non-member operator<< so that Output can stream out a block scalar. +template <typename T> +inline +typename std::enable_if<has_BlockScalarTraits<T>::value, Output &>::type +operator<<(Output &Out, T &Val) { + Out.beginDocuments(); + if (Out.preflightDocument(0)) { + yamlize(Out, Val, true); + Out.postflightDocument(); + } + Out.endDocuments(); + return Out; +} + // Provide better error message about types missing a trait specialization template <typename T> inline diff --git a/include/llvm/Support/circular_raw_ostream.h b/include/llvm/Support/circular_raw_ostream.h index ee7b89fe8c8d..19f9c2c4b155 100644 --- a/include/llvm/Support/circular_raw_ostream.h +++ b/include/llvm/Support/circular_raw_ostream.h @@ -107,30 +107,17 @@ namespace llvm /// management of it, etc. /// circular_raw_ostream(raw_ostream &Stream, const char *Header, - size_t BuffSize = 0, bool Owns = REFERENCE_ONLY) - : raw_ostream(/*unbuffered*/true), - TheStream(nullptr), - OwnsStream(Owns), - BufferSize(BuffSize), - BufferArray(nullptr), - Filled(false), - Banner(Header) { + size_t BuffSize = 0, bool Owns = REFERENCE_ONLY) + : raw_ostream(/*unbuffered*/ true), TheStream(nullptr), + OwnsStream(Owns), BufferSize(BuffSize), BufferArray(nullptr), + Filled(false), Banner(Header) { if (BufferSize != 0) BufferArray = new char[BufferSize]; Cur = BufferArray; setStream(Stream, Owns); } - explicit circular_raw_ostream() - : raw_ostream(/*unbuffered*/true), - TheStream(nullptr), - OwnsStream(REFERENCE_ONLY), - BufferArray(nullptr), - Filled(false), - Banner("") { - Cur = BufferArray; - } - ~circular_raw_ostream() { + ~circular_raw_ostream() override { flush(); flushBufferWithBanner(); releaseStream(); diff --git a/include/llvm/Support/raw_os_ostream.h b/include/llvm/Support/raw_os_ostream.h index 04cf3b6202c4..a983aeb90879 100644 --- a/include/llvm/Support/raw_os_ostream.h +++ b/include/llvm/Support/raw_os_ostream.h @@ -34,7 +34,7 @@ class raw_os_ostream : public raw_ostream { public: raw_os_ostream(std::ostream &O) : OS(O) {} - ~raw_os_ostream(); + ~raw_os_ostream() override; }; } // end llvm namespace diff --git a/include/llvm/Support/raw_ostream.h b/include/llvm/Support/raw_ostream.h index c9ef637940db..b59317112c44 100644 --- a/include/llvm/Support/raw_ostream.h +++ b/include/llvm/Support/raw_ostream.h @@ -14,32 +14,31 @@ #ifndef LLVM_SUPPORT_RAW_OSTREAM_H #define LLVM_SUPPORT_RAW_OSTREAM_H +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" #include <system_error> namespace llvm { - class format_object_base; - class FormattedString; - class FormattedNumber; - template <typename T> - class SmallVectorImpl; - - namespace sys { - namespace fs { - enum OpenFlags : unsigned; - } - } - -/// raw_ostream - This class implements an extremely fast bulk output stream -/// that can *only* output to a stream. It does not support seeking, reopening, -/// rewinding, line buffered disciplines etc. It is a simple buffer that outputs +class format_object_base; +class FormattedString; +class FormattedNumber; +template <typename T> class SmallVectorImpl; + +namespace sys { +namespace fs { +enum OpenFlags : unsigned; +} +} + +/// This class implements an extremely fast bulk output stream that can *only* +/// output to a stream. It does not support seeking, reopening, rewinding, line +/// buffered disciplines etc. It is a simple buffer that outputs /// a chunk at a time. class raw_ostream { private: - void operator=(const raw_ostream &) LLVM_DELETED_FUNCTION; - raw_ostream(const raw_ostream &) LLVM_DELETED_FUNCTION; + void operator=(const raw_ostream &) = delete; + raw_ostream(const raw_ostream &) = delete; /// The buffer is handled in such a way that the buffer is /// uninitialized, unbuffered, or out of space when OutBufCur >= @@ -81,8 +80,8 @@ public: SAVEDCOLOR }; - explicit raw_ostream(bool unbuffered=false) - : BufferMode(unbuffered ? Unbuffered : InternalBuffer) { + explicit raw_ostream(bool unbuffered = false) + : BufferMode(unbuffered ? Unbuffered : InternalBuffer) { // Start out ready to flush. OutBufStart = OutBufEnd = OutBufCur = nullptr; } @@ -96,12 +95,11 @@ public: // Configuration Interface //===--------------------------------------------------------------------===// - /// SetBuffered - Set the stream to be buffered, with an automatically - /// determined buffer size. + /// Set the stream to be buffered, with an automatically determined buffer + /// size. void SetBuffered(); - /// SetBufferSize - Set the stream to be buffered, using the - /// specified buffer size. + /// Set the stream to be buffered, using the specified buffer size. void SetBufferSize(size_t Size) { flush(); SetBufferAndMode(new char[Size], Size, InternalBuffer); @@ -117,10 +115,9 @@ public: return OutBufEnd - OutBufStart; } - /// SetUnbuffered - Set the stream to be unbuffered. When - /// unbuffered, the stream will flush after every write. This routine - /// will also flush the buffer immediately when the stream is being - /// set to unbuffered. + /// Set the stream to be unbuffered. When unbuffered, the stream will flush + /// after every write. This routine will also flush the buffer immediately + /// when the stream is being set to unbuffered. void SetUnbuffered() { flush(); SetBufferAndMode(nullptr, 0, Unbuffered); @@ -185,6 +182,10 @@ public: return write(Str.data(), Str.length()); } + raw_ostream &operator<<(const llvm::SmallVectorImpl<char> &Str) { + return write(Str.data(), Str.size()); + } + raw_ostream &operator<<(unsigned long N); raw_ostream &operator<<(long N); raw_ostream &operator<<(unsigned long long N); @@ -200,11 +201,11 @@ public: raw_ostream &operator<<(double N); - /// write_hex - Output \p N in hexadecimal, without any prefix or padding. + /// Output \p N in hexadecimal, without any prefix or padding. raw_ostream &write_hex(unsigned long long N); - /// write_escaped - Output \p Str, turning '\\', '\t', '\n', '"', and - /// anything that doesn't satisfy std::isprint into an escape sequence. + /// Output \p Str, turning '\\', '\t', '\n', '"', and anything that doesn't + /// satisfy std::isprint into an escape sequence. raw_ostream &write_escaped(StringRef Str, bool UseHexEscapes = false); raw_ostream &write(unsigned char C); @@ -259,8 +260,8 @@ public: //===--------------------------------------------------------------------===// private: - /// write_impl - The is the piece of the class that is implemented - /// by subclasses. This writes the \p Size bytes starting at + /// The is the piece of the class that is implemented by subclasses. This + /// writes the \p Size bytes starting at /// \p Ptr to the underlying stream. /// /// This function is guaranteed to only be called at a point at which it is @@ -277,51 +278,69 @@ private: // An out of line virtual method to provide a home for the class vtable. virtual void handle(); - /// current_pos - Return the current position within the stream, not - /// counting the bytes currently in the buffer. + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. virtual uint64_t current_pos() const = 0; protected: - /// SetBuffer - Use the provided buffer as the raw_ostream buffer. This is - /// intended for use only by subclasses which can arrange for the output to go - /// directly into the desired output buffer, instead of being copied on each - /// flush. + /// Use the provided buffer as the raw_ostream buffer. This is intended for + /// use only by subclasses which can arrange for the output to go directly + /// into the desired output buffer, instead of being copied on each flush. void SetBuffer(char *BufferStart, size_t Size) { SetBufferAndMode(BufferStart, Size, ExternalBuffer); } - /// preferred_buffer_size - Return an efficient buffer size for the - /// underlying output mechanism. + /// Return an efficient buffer size for the underlying output mechanism. virtual size_t preferred_buffer_size() const; - /// getBufferStart - Return the beginning of the current stream buffer, or 0 - /// if the stream is unbuffered. + /// Return the beginning of the current stream buffer, or 0 if the stream is + /// unbuffered. const char *getBufferStart() const { return OutBufStart; } //===--------------------------------------------------------------------===// // Private Interface //===--------------------------------------------------------------------===// private: - /// SetBufferAndMode - Install the given buffer and mode. + /// Install the given buffer and mode. void SetBufferAndMode(char *BufferStart, size_t Size, BufferKind Mode); - /// flush_nonempty - Flush the current buffer, which is known to be - /// non-empty. This outputs the currently buffered data and resets - /// the buffer to empty. + /// Flush the current buffer, which is known to be non-empty. This outputs the + /// currently buffered data and resets the buffer to empty. void flush_nonempty(); - /// copy_to_buffer - Copy data into the buffer. Size must not be - /// greater than the number of unused bytes in the buffer. + /// Copy data into the buffer. Size must not be greater than the number of + /// unused bytes in the buffer. void copy_to_buffer(const char *Ptr, size_t Size); }; +/// An abstract base class for streams implementations that also support a +/// pwrite operation. This is usefull for code that can mostly stream out data, +/// but needs to patch in a header that needs to know the output size. +class raw_pwrite_stream : public raw_ostream { + virtual void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) = 0; + +public: + explicit raw_pwrite_stream(bool Unbuffered = false) + : raw_ostream(Unbuffered) {} + void pwrite(const char *Ptr, size_t Size, uint64_t Offset) { +#ifndef NDBEBUG + uint64_t Pos = tell(); + // /dev/null always reports a pos of 0, so we cannot perform this check + // in that case. + if (Pos) + assert(Size + Offset <= Pos && "We don't support extending the stream"); +#endif + pwrite_impl(Ptr, Size, Offset); + } +}; + //===----------------------------------------------------------------------===// // File Output Streams //===----------------------------------------------------------------------===// -/// raw_fd_ostream - A raw_ostream that writes to a file descriptor. +/// A raw_ostream that writes to a file descriptor. /// -class raw_fd_ostream : public raw_ostream { +class raw_fd_ostream : public raw_pwrite_stream { int FD; bool ShouldClose; @@ -335,18 +354,21 @@ class raw_fd_ostream : public raw_ostream { uint64_t pos; - /// write_impl - See raw_ostream::write_impl. + bool SupportsSeeking; + + /// See raw_ostream::write_impl. void write_impl(const char *Ptr, size_t Size) override; - /// current_pos - Return the current position within the stream, not - /// counting the bytes currently in the buffer. + void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override; + + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. uint64_t current_pos() const override { return pos; } - /// preferred_buffer_size - Determine an efficient buffer size. + /// Determine an efficient buffer size. size_t preferred_buffer_size() const override; - /// error_detected - Set the flag indicating that an output error has - /// been encountered. + /// Set the flag indicating that an output error has been encountered. void error_detected() { Error = true; } public: @@ -363,22 +385,24 @@ public: raw_fd_ostream(StringRef Filename, std::error_code &EC, sys::fs::OpenFlags Flags); - /// raw_fd_ostream ctor - FD is the file descriptor that this writes to. If - /// ShouldClose is true, this closes the file when the stream is destroyed. + /// FD is the file descriptor that this writes to. If ShouldClose is true, + /// this closes the file when the stream is destroyed. raw_fd_ostream(int fd, bool shouldClose, bool unbuffered=false); - ~raw_fd_ostream(); + ~raw_fd_ostream() override; - /// close - Manually flush the stream and close the file. - /// Note that this does not call fsync. + /// Manually flush the stream and close the file. Note that this does not call + /// fsync. void close(); - /// seek - Flushes the stream and repositions the underlying file descriptor - /// position to the offset specified from the beginning of the file. + bool supportsSeeking() { return SupportsSeeking; } + + /// Flushes the stream and repositions the underlying file descriptor position + /// to the offset specified from the beginning of the file. uint64_t seek(uint64_t off); - /// SetUseAtomicWrite - Set the stream to attempt to use atomic writes for - /// individual output routines where possible. + /// Set the stream to attempt to use atomic writes for individual output + /// routines where possible. /// /// Note that because raw_ostream's are typically buffered, this flag is only /// sensible when used on unbuffered streams which will flush their output @@ -397,18 +421,18 @@ public: bool has_colors() const override; - /// has_error - Return the value of the flag in this raw_fd_ostream indicating - /// whether an output error has been encountered. + /// Return the value of the flag in this raw_fd_ostream indicating whether an + /// output error has been encountered. /// This doesn't implicitly flush any pending output. Also, it doesn't /// guarantee to detect all errors unless the stream has been closed. bool has_error() const { return Error; } - /// clear_error - Set the flag read by has_error() to false. If the error - /// flag is set at the time when this raw_ostream's destructor is called, - /// report_fatal_error is called to report the error. Use clear_error() - /// after handling the error to avoid this behavior. + /// Set the flag read by has_error() to false. If the error flag is set at the + /// time when this raw_ostream's destructor is called, report_fatal_error is + /// called to report the error. Use clear_error() after handling the error to + /// avoid this behavior. /// /// "Errors should never pass silently. /// Unless explicitly silenced." @@ -419,87 +443,106 @@ public: } }; -/// outs() - This returns a reference to a raw_ostream for standard output. -/// Use it like: outs() << "foo" << "bar"; +/// This returns a reference to a raw_ostream for standard output. Use it like: +/// outs() << "foo" << "bar"; raw_ostream &outs(); -/// errs() - This returns a reference to a raw_ostream for standard error. -/// Use it like: errs() << "foo" << "bar"; +/// This returns a reference to a raw_ostream for standard error. Use it like: +/// errs() << "foo" << "bar"; raw_ostream &errs(); -/// nulls() - This returns a reference to a raw_ostream which simply discards -/// output. +/// This returns a reference to a raw_ostream which simply discards output. raw_ostream &nulls(); //===----------------------------------------------------------------------===// // Output Stream Adaptors //===----------------------------------------------------------------------===// -/// raw_string_ostream - A raw_ostream that writes to an std::string. This is a -/// simple adaptor class. This class does not encounter output errors. +/// A raw_ostream that writes to an std::string. This is a simple adaptor +/// class. This class does not encounter output errors. class raw_string_ostream : public raw_ostream { std::string &OS; - /// write_impl - See raw_ostream::write_impl. + /// See raw_ostream::write_impl. void write_impl(const char *Ptr, size_t Size) override; - /// current_pos - Return the current position within the stream, not - /// counting the bytes currently in the buffer. + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. uint64_t current_pos() const override { return OS.size(); } public: explicit raw_string_ostream(std::string &O) : OS(O) {} - ~raw_string_ostream(); + ~raw_string_ostream() override; - /// str - Flushes the stream contents to the target string and returns - /// the string's reference. + /// Flushes the stream contents to the target string and returns the string's + /// reference. std::string& str() { flush(); return OS; } }; -/// raw_svector_ostream - A raw_ostream that writes to an SmallVector or -/// SmallString. This is a simple adaptor class. This class does not -/// encounter output errors. -class raw_svector_ostream : public raw_ostream { +/// A raw_ostream that writes to an SmallVector or SmallString. This is a +/// simple adaptor class. This class does not encounter output errors. +class raw_svector_ostream : public raw_pwrite_stream { SmallVectorImpl<char> &OS; - /// write_impl - See raw_ostream::write_impl. + /// See raw_ostream::write_impl. void write_impl(const char *Ptr, size_t Size) override; - /// current_pos - Return the current position within the stream, not - /// counting the bytes currently in the buffer. + void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override; + + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. uint64_t current_pos() const override; + +protected: + // Like the regular constructor, but doesn't call init. + explicit raw_svector_ostream(SmallVectorImpl<char> &O, unsigned); + void init(); + public: /// Construct a new raw_svector_ostream. /// /// \param O The vector to write to; this should generally have at least 128 /// bytes free to avoid any extraneous memory overhead. explicit raw_svector_ostream(SmallVectorImpl<char> &O); - ~raw_svector_ostream(); + ~raw_svector_ostream() override; - /// resync - This is called when the SmallVector we're appending to is changed - /// outside of the raw_svector_ostream's control. It is only safe to do this - /// if the raw_svector_ostream has previously been flushed. + + /// This is called when the SmallVector we're appending to is changed outside + /// of the raw_svector_ostream's control. It is only safe to do this if the + /// raw_svector_ostream has previously been flushed. void resync(); - /// str - Flushes the stream contents to the target vector and return a - /// StringRef for the vector contents. + /// Flushes the stream contents to the target vector and return a StringRef + /// for the vector contents. StringRef str(); }; -/// raw_null_ostream - A raw_ostream that discards all output. -class raw_null_ostream : public raw_ostream { - /// write_impl - See raw_ostream::write_impl. +/// A raw_ostream that discards all output. +class raw_null_ostream : public raw_pwrite_stream { + /// See raw_ostream::write_impl. void write_impl(const char *Ptr, size_t size) override; + void pwrite_impl(const char *Ptr, size_t Size, uint64_t Offset) override; - /// current_pos - Return the current position within the stream, not - /// counting the bytes currently in the buffer. + /// Return the current position within the stream, not counting the bytes + /// currently in the buffer. uint64_t current_pos() const override; public: explicit raw_null_ostream() {} - ~raw_null_ostream(); + ~raw_null_ostream() override; +}; + +class buffer_ostream : public raw_svector_ostream { + raw_ostream &OS; + SmallVector<char, 0> Buffer; + +public: + buffer_ostream(raw_ostream &OS) : raw_svector_ostream(Buffer, 0), OS(OS) { + init(); + } + ~buffer_ostream() { OS << str(); } }; } // end llvm namespace diff --git a/include/llvm/Support/type_traits.h b/include/llvm/Support/type_traits.h index 70953a9cb70e..45465aea004b 100644 --- a/include/llvm/Support/type_traits.h +++ b/include/llvm/Support/type_traits.h @@ -28,9 +28,17 @@ namespace llvm { /// type can be copied around with memcpy instead of running ctors etc. template <typename T> struct isPodLike { -#if __has_feature(is_trivially_copyable) + // std::is_trivially_copyable is available in libc++ with clang, libstdc++ + // that comes with GCC 5. +#if (__has_feature(is_trivially_copyable) && defined(_LIBCPP_VERSION)) || \ + (defined(__GNUC__) && __GNUC__ >= 5) // If the compiler supports the is_trivially_copyable trait use it, as it // matches the definition of isPodLike closely. + static const bool value = std::is_trivially_copyable<T>::value; +#elif __has_feature(is_trivially_copyable) + // Use the internal name if the compiler supports is_trivially_copyable but we + // don't know if the standard library does. This is the case for clang in + // conjunction with libstdc++ from GCC 4.x. 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 |