diff options
Diffstat (limited to 'include/llvm')
-rw-r--r-- | include/llvm/ADT/IntrusiveRefCntPtr.h | 7 | ||||
-rw-r--r-- | include/llvm/ADT/PriorityWorklist.h | 39 | ||||
-rw-r--r-- | include/llvm/Analysis/Loads.h | 18 | ||||
-rw-r--r-- | include/llvm/CodeGen/AsmPrinter.h | 5 | ||||
-rw-r--r-- | include/llvm/CodeGen/MachineDominators.h | 4 | ||||
-rw-r--r-- | include/llvm/DebugInfo/DWARF/DWARFDebugLine.h | 6 | ||||
-rw-r--r-- | include/llvm/IR/IntrinsicsAMDGPU.td | 7 | ||||
-rw-r--r-- | include/llvm/IR/IntrinsicsX86.td | 124 | ||||
-rw-r--r-- | include/llvm/Support/FileSystem.h | 18 | ||||
-rw-r--r-- | include/llvm/Support/YAMLTraits.h | 98 |
10 files changed, 169 insertions, 157 deletions
diff --git a/include/llvm/ADT/IntrusiveRefCntPtr.h b/include/llvm/ADT/IntrusiveRefCntPtr.h index 559fb40773aa..a77cf04ea4d1 100644 --- a/include/llvm/ADT/IntrusiveRefCntPtr.h +++ b/include/llvm/ADT/IntrusiveRefCntPtr.h @@ -21,8 +21,8 @@ // class MyClass : public RefCountedBase<MyClass> {}; // // void foo() { -// // Objects that inherit from RefCountedBase should always be instantiated -// // on the heap, never on the stack. +// // Constructing an IntrusiveRefCntPtr increases the pointee's refcount by +// // 1 (from 0 in this case). // IntrusiveRefCntPtr<MyClass> Ptr1(new MyClass()); // // // Copying an IntrusiveRefCntPtr increases the pointee's refcount by 1. @@ -68,9 +68,6 @@ namespace llvm { /// calls to Release() and Retain(), which increment and decrement the object's /// refcount, respectively. When a Release() call decrements the refcount to 0, /// the object deletes itself. -/// -/// Objects that inherit from RefCountedBase should always be allocated with -/// operator new. template <class Derived> class RefCountedBase { mutable unsigned RefCount = 0; diff --git a/include/llvm/ADT/PriorityWorklist.h b/include/llvm/ADT/PriorityWorklist.h index c0b4709e98f8..3198dd438700 100644 --- a/include/llvm/ADT/PriorityWorklist.h +++ b/include/llvm/ADT/PriorityWorklist.h @@ -18,6 +18,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/Sequence.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include <algorithm> @@ -107,6 +108,39 @@ public: return false; } + /// Insert a sequence of new elements into the PriorityWorklist. + template <typename SequenceT> + typename std::enable_if<!std::is_convertible<SequenceT, T>::value>::type + insert(SequenceT &&Input) { + if (std::begin(Input) == std::end(Input)) + // Nothing to do for an empty input sequence. + return; + + // First pull the input sequence into the vector as a bulk append + // operation. + ptrdiff_t StartIndex = V.size(); + V.insert(V.end(), std::begin(Input), std::end(Input)); + // Now walk backwards fixing up the index map and deleting any duplicates. + for (ptrdiff_t i = V.size() - 1; i >= StartIndex; --i) { + auto InsertResult = M.insert({V[i], i}); + if (InsertResult.second) + continue; + + // If the existing index is before this insert's start, nuke that one and + // move it up. + ptrdiff_t &Index = InsertResult.first->second; + if (Index < StartIndex) { + V[Index] = T(); + Index = i; + continue; + } + + // Otherwise the existing one comes first so just clear out the value in + // this slot. + V[i] = T(); + } + } + /// Remove the last element of the PriorityWorklist. void pop_back() { assert(!empty() && "Cannot remove an element when empty!"); @@ -169,6 +203,11 @@ public: return true; } + /// Reverse the items in the PriorityWorklist. + /// + /// This does an in-place reversal. Other kinds of reverse aren't easy to + /// support in the face of the worklist semantics. + /// Completely clear the PriorityWorklist void clear() { M.clear(); diff --git a/include/llvm/Analysis/Loads.h b/include/llvm/Analysis/Loads.h index 139bf3c2116f..e167f36219d2 100644 --- a/include/llvm/Analysis/Loads.h +++ b/include/llvm/Analysis/Loads.h @@ -23,10 +23,9 @@ namespace llvm { class DataLayout; class MDNode; -/// isDereferenceablePointer - Return true if this is always a dereferenceable -/// pointer. If the context instruction is specified perform context-sensitive -/// analysis and return true if the pointer is dereferenceable at the -/// specified instruction. +/// Return true if this is always a dereferenceable pointer. If the context +/// instruction is specified perform context-sensitive analysis and return true +/// if the pointer is dereferenceable at the specified instruction. bool isDereferenceablePointer(const Value *V, const DataLayout &DL, const Instruction *CtxI = nullptr, const DominatorTree *DT = nullptr); @@ -40,8 +39,7 @@ bool isDereferenceableAndAlignedPointer(const Value *V, unsigned Align, const Instruction *CtxI = nullptr, const DominatorTree *DT = nullptr); -/// isSafeToLoadUnconditionally - Return true if we know that executing a load -/// from this value cannot trap. +/// Return true if we know that executing a load from this value cannot trap. /// /// If DT and ScanFrom are specified this method performs context-sensitive /// analysis and returns true if it is safe to load immediately before ScanFrom. @@ -54,12 +52,12 @@ bool isSafeToLoadUnconditionally(Value *V, unsigned Align, Instruction *ScanFrom = nullptr, const DominatorTree *DT = nullptr); -/// DefMaxInstsToScan - the default number of maximum instructions -/// to scan in the block, used by FindAvailableLoadedValue(). +/// The default number of maximum instructions to scan in the block, used by +/// FindAvailableLoadedValue(). extern cl::opt<unsigned> DefMaxInstsToScan; -/// \brief Scan backwards to see if we have the value of the given load -/// available locally within a small number of instructions. +/// Scan backwards to see if we have the value of the given load available +/// locally within a small number of instructions. /// /// You can use this function to scan across multiple blocks: after you call /// this function, if ScanFrom points at the beginning of the block, it's safe diff --git a/include/llvm/CodeGen/AsmPrinter.h b/include/llvm/CodeGen/AsmPrinter.h index c1be46ddd7b5..be8822df3dba 100644 --- a/include/llvm/CodeGen/AsmPrinter.h +++ b/include/llvm/CodeGen/AsmPrinter.h @@ -208,6 +208,8 @@ public: SledKind Kind; bool AlwaysInstrument; const class Function *Fn; + + void emit(int, MCStreamer *, const MCSymbol *) const; }; // All the sleds to be emitted. @@ -216,6 +218,9 @@ public: // Helper function to record a given XRay sled. void recordSled(MCSymbol *Sled, const MachineInstr &MI, SledKind Kind); + /// Emit a table with all XRay instrumentation points. + void emitXRayTable(); + //===------------------------------------------------------------------===// // MachineFunctionPass Implementation. //===------------------------------------------------------------------===// diff --git a/include/llvm/CodeGen/MachineDominators.h b/include/llvm/CodeGen/MachineDominators.h index 76e1df89169e..21ecef587aa5 100644 --- a/include/llvm/CodeGen/MachineDominators.h +++ b/include/llvm/CodeGen/MachineDominators.h @@ -59,6 +59,9 @@ class MachineDominatorTree : public MachineFunctionPass { /// such as BB == elt.NewBB. mutable SmallSet<MachineBasicBlock *, 32> NewBBs; + /// The DominatorTreeBase that is used to compute a normal dominator tree + DominatorTreeBase<MachineBasicBlock>* DT; + /// \brief Apply all the recorded critical edges to the DT. /// This updates the underlying DT information in a way that uses /// the fast query path of DT as much as possible. @@ -68,7 +71,6 @@ class MachineDominatorTree : public MachineFunctionPass { public: static char ID; // Pass ID, replacement for typeid - DominatorTreeBase<MachineBasicBlock>* DT; MachineDominatorTree(); diff --git a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h index ca9a6c822876..878f1c76ebf6 100644 --- a/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h +++ b/include/llvm/DebugInfo/DWARF/DWARFDebugLine.h @@ -116,12 +116,12 @@ public: // An unsigned integer indicating the identity of the source file // corresponding to a machine instruction. uint16_t File; - // An unsigned integer whose value encodes the applicable instruction set - // architecture for the current instruction. - uint8_t Isa; // An unsigned integer representing the DWARF path discriminator value // for this location. uint32_t Discriminator; + // An unsigned integer whose value encodes the applicable instruction set + // architecture for the current instruction. + uint8_t Isa; // A boolean indicating that the current instruction is the beginning of a // statement. uint8_t IsStmt:1, diff --git a/include/llvm/IR/IntrinsicsAMDGPU.td b/include/llvm/IR/IntrinsicsAMDGPU.td index 078959ce15d0..07d5b5ea40dc 100644 --- a/include/llvm/IR/IntrinsicsAMDGPU.td +++ b/include/llvm/IR/IntrinsicsAMDGPU.td @@ -104,6 +104,13 @@ def int_amdgcn_dispatch_id : // Instruction Intrinsics //===----------------------------------------------------------------------===// +// The first parameter is s_sendmsg immediate (i16), +// the second one is copied to m0 +def int_amdgcn_s_sendmsg : GCCBuiltin<"__builtin_amdgcn_s_sendmsg">, + Intrinsic <[], [llvm_i32_ty, llvm_i32_ty], []>; +def int_amdgcn_s_sendmsghalt : GCCBuiltin<"__builtin_amdgcn_s_sendmsghalt">, + Intrinsic <[], [llvm_i32_ty, llvm_i32_ty], []>; + def int_amdgcn_s_barrier : GCCBuiltin<"__builtin_amdgcn_s_barrier">, Intrinsic<[], [], [IntrConvergent]>; diff --git a/include/llvm/IR/IntrinsicsX86.td b/include/llvm/IR/IntrinsicsX86.td index 3a496cb6645c..85966af9c820 100644 --- a/include/llvm/IR/IntrinsicsX86.td +++ b/include/llvm/IR/IntrinsicsX86.td @@ -2063,130 +2063,6 @@ let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; } -// Vector extract and insert -let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". - def int_x86_avx512_mask_vextractf32x4_512 : - GCCBuiltin<"__builtin_ia32_extractf32x4_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v16f32_ty, llvm_i32_ty, - llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vextracti32x4_512 : - GCCBuiltin<"__builtin_ia32_extracti32x4_mask">, - Intrinsic<[llvm_v4i32_ty], [llvm_v16i32_ty, llvm_i32_ty, - llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vextractf32x4_256 : - GCCBuiltin<"__builtin_ia32_extractf32x4_256_mask">, - Intrinsic<[llvm_v4f32_ty], [llvm_v8f32_ty, llvm_i32_ty, - llvm_v4f32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vextracti32x4_256 : - GCCBuiltin<"__builtin_ia32_extracti32x4_256_mask">, - Intrinsic<[llvm_v4i32_ty], [llvm_v8i32_ty, llvm_i32_ty, - llvm_v4i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vextractf64x2_256 : - GCCBuiltin<"__builtin_ia32_extractf64x2_256_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v4f64_ty, llvm_i32_ty, - llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vextracti64x2_256 : - GCCBuiltin<"__builtin_ia32_extracti64x2_256_mask">, - Intrinsic<[llvm_v2i64_ty], [llvm_v4i64_ty, llvm_i32_ty, - llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vextractf64x2_512 : - GCCBuiltin<"__builtin_ia32_extractf64x2_512_mask">, - Intrinsic<[llvm_v2f64_ty], [llvm_v8f64_ty, llvm_i32_ty, - llvm_v2f64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vextracti64x2_512 : - GCCBuiltin<"__builtin_ia32_extracti64x2_512_mask">, - Intrinsic<[llvm_v2i64_ty], [llvm_v8i64_ty, llvm_i32_ty, - llvm_v2i64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vextractf32x8_512 : - GCCBuiltin<"__builtin_ia32_extractf32x8_mask">, - Intrinsic<[llvm_v8f32_ty], [llvm_v16f32_ty, llvm_i32_ty, - llvm_v8f32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vextracti32x8_512 : - GCCBuiltin<"__builtin_ia32_extracti32x8_mask">, - Intrinsic<[llvm_v8i32_ty],[llvm_v16i32_ty, llvm_i32_ty, - llvm_v8i32_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vextractf64x4_512 : - GCCBuiltin<"__builtin_ia32_extractf64x4_mask">, - Intrinsic<[llvm_v4f64_ty], [llvm_v8f64_ty, llvm_i32_ty, - llvm_v4f64_ty, llvm_i8_ty], [IntrNoMem]>; - def int_x86_avx512_mask_vextracti64x4_512 : - GCCBuiltin<"__builtin_ia32_extracti64x4_mask">, - Intrinsic<[llvm_v4i64_ty], [llvm_v8i64_ty, llvm_i32_ty, - llvm_v4i64_ty, llvm_i8_ty], [IntrNoMem]>; - - def int_x86_avx512_mask_insertf32x4_256 : - GCCBuiltin<"__builtin_ia32_insertf32x4_256_mask">, - Intrinsic<[llvm_v8f32_ty], - [llvm_v8f32_ty, llvm_v4f32_ty, llvm_i32_ty, llvm_v8f32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_insertf32x4_512 : - GCCBuiltin<"__builtin_ia32_insertf32x4_mask">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v4f32_ty, llvm_i32_ty, llvm_v16f32_ty, llvm_i16_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_insertf32x8_512 : - GCCBuiltin<"__builtin_ia32_insertf32x8_mask">, - Intrinsic<[llvm_v16f32_ty], - [llvm_v16f32_ty, llvm_v8f32_ty, llvm_i32_ty, llvm_v16f32_ty, llvm_i16_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_insertf64x2_256 : - GCCBuiltin<"__builtin_ia32_insertf64x2_256_mask">, - Intrinsic<[llvm_v4f64_ty], - [llvm_v4f64_ty, llvm_v2f64_ty, llvm_i32_ty, llvm_v4f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_insertf64x2_512 : - GCCBuiltin<"__builtin_ia32_insertf64x2_512_mask">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v2f64_ty, llvm_i32_ty, llvm_v8f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_insertf64x4_512 : - GCCBuiltin<"__builtin_ia32_insertf64x4_mask">, - Intrinsic<[llvm_v8f64_ty], - [llvm_v8f64_ty, llvm_v4f64_ty, llvm_i32_ty, llvm_v8f64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_inserti32x4_256 : - GCCBuiltin<"__builtin_ia32_inserti32x4_256_mask">, - Intrinsic<[llvm_v8i32_ty], - [llvm_v8i32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_v8i32_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_inserti32x4_512 : - GCCBuiltin<"__builtin_ia32_inserti32x4_mask">, - Intrinsic<[llvm_v16i32_ty], - [llvm_v16i32_ty, llvm_v4i32_ty, llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_inserti32x8_512 : - GCCBuiltin<"__builtin_ia32_inserti32x8_mask">, - Intrinsic<[llvm_v16i32_ty], - [llvm_v16i32_ty, llvm_v8i32_ty, llvm_i32_ty, llvm_v16i32_ty, llvm_i16_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_inserti64x2_256 : - GCCBuiltin<"__builtin_ia32_inserti64x2_256_mask">, - Intrinsic<[llvm_v4i64_ty], - [llvm_v4i64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_v4i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_inserti64x2_512 : - GCCBuiltin<"__builtin_ia32_inserti64x2_512_mask">, - Intrinsic<[llvm_v8i64_ty], - [llvm_v8i64_ty, llvm_v2i64_ty, llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], - [IntrNoMem]>; - - def int_x86_avx512_mask_inserti64x4_512 : - GCCBuiltin<"__builtin_ia32_inserti64x4_mask">, - Intrinsic<[llvm_v8i64_ty], - [llvm_v8i64_ty, llvm_v4i64_ty, llvm_i32_ty, llvm_v8i64_ty, llvm_i8_ty], - [IntrNoMem]>; -} - // Conditional load ops let TargetPrefix = "x86" in { // All intrinsics start with "llvm.x86.". def int_x86_avx2_maskload_d : GCCBuiltin<"__builtin_ia32_maskloadd">, diff --git a/include/llvm/Support/FileSystem.h b/include/llvm/Support/FileSystem.h index 9d8d8c3ffb5c..347f21108913 100644 --- a/include/llvm/Support/FileSystem.h +++ b/include/llvm/Support/FileSystem.h @@ -769,17 +769,13 @@ namespace detail { std::error_code directory_iterator_increment(DirIterState &); std::error_code directory_iterator_destruct(DirIterState &); - /// DirIterState - Keeps state for the directory_iterator. It is reference - /// counted in order to preserve InputIterator semantics on copy. - struct DirIterState : public RefCountedBase<DirIterState> { - DirIterState() - : IterationHandle(0) {} - + /// Keeps state for the directory_iterator. + struct DirIterState { ~DirIterState() { directory_iterator_destruct(*this); } - intptr_t IterationHandle; + intptr_t IterationHandle = 0; directory_entry CurrentEntry; }; } // end namespace detail @@ -788,23 +784,23 @@ namespace detail { /// operator++ because we need an error_code. If it's really needed we can make /// it call report_fatal_error on error. class directory_iterator { - IntrusiveRefCntPtr<detail::DirIterState> State; + std::shared_ptr<detail::DirIterState> State; public: explicit directory_iterator(const Twine &path, std::error_code &ec) { - State = new detail::DirIterState; + State = std::make_shared<detail::DirIterState>(); SmallString<128> path_storage; ec = detail::directory_iterator_construct(*State, path.toStringRef(path_storage)); } explicit directory_iterator(const directory_entry &de, std::error_code &ec) { - State = new detail::DirIterState; + State = std::make_shared<detail::DirIterState>(); ec = detail::directory_iterator_construct(*State, de.path()); } /// Construct end iterator. - directory_iterator() : State(nullptr) {} + directory_iterator() = default; // No operator++ because we need error_code. directory_iterator &increment(std::error_code &ec) { diff --git a/include/llvm/Support/YAMLTraits.h b/include/llvm/Support/YAMLTraits.h index 38acb36942bc..cbba9c08275a 100644 --- a/include/llvm/Support/YAMLTraits.h +++ b/include/llvm/Support/YAMLTraits.h @@ -209,6 +209,15 @@ struct DocumentListTraits { // static T::value_type& element(IO &io, T &seq, size_t index); }; +/// This class should be specialized by any type that needs to be converted +/// to/from a YAML mapping in the case where the names of the keys are not known +/// in advance, e.g. a string map. +template <typename T> +struct CustomMappingTraits { + // static void inputOne(IO &io, StringRef key, T &elem); + // static void output(IO &io, T &elem); +}; + // Only used for better diagnostics of missing traits template <typename T> struct MissingTrait; @@ -358,6 +367,23 @@ public: static bool const value = (sizeof(test<SequenceTraits<T>>(nullptr)) == 1); }; +// Test if CustomMappingTraits<T> is defined on type T. +template <class T> +struct has_CustomMappingTraits +{ + typedef void (*Signature_input)(IO &io, StringRef key, T &v); + + template <typename U> + static char test(SameType<Signature_input, &U::inputOne>*); + + template <typename U> + static double test(...); + +public: + static bool const value = + (sizeof(test<CustomMappingTraits<T>>(nullptr)) == 1); +}; + // has_FlowTraits<int> will cause an error with some compilers because // it subclasses int. Using this wrapper only instantiates the // real has_FlowTraits only if the template type is a class. @@ -493,6 +519,7 @@ struct missingTraits !has_BlockScalarTraits<T>::value && !has_MappingTraits<T, Context>::value && !has_SequenceTraits<T>::value && + !has_CustomMappingTraits<T>::value && !has_DocumentListTraits<T>::value> {}; template <typename T, typename Context> @@ -531,6 +558,7 @@ public: virtual void endMapping() = 0; virtual bool preflightKey(const char*, bool, bool, bool &, void *&) = 0; virtual void postflightKey(void*) = 0; + virtual std::vector<StringRef> keys() = 0; virtual void beginFlowMapping() = 0; virtual void endFlowMapping() = 0; @@ -819,6 +847,21 @@ yamlize(IO &io, T &Val, bool, Context &Ctx) { } template <typename T> +typename std::enable_if<has_CustomMappingTraits<T>::value, void>::type +yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) { + if ( io.outputting() ) { + io.beginMapping(); + CustomMappingTraits<T>::output(io, Val); + io.endMapping(); + } else { + io.beginMapping(); + for (StringRef key : io.keys()) + CustomMappingTraits<T>::inputOne(io, key, Val); + io.endMapping(); + } +} + +template <typename T> typename std::enable_if<missingTraits<T, EmptyContext>::value, void>::type yamlize(IO &io, T &Val, bool, EmptyContext &Ctx) { char missing_yaml_trait_for_type[sizeof(MissingTrait<T>)]; @@ -1074,6 +1117,7 @@ private: void endMapping() override; bool preflightKey(const char *, bool, bool, bool &, void *&) override; void postflightKey(void *) override; + std::vector<StringRef> keys() override; void beginFlowMapping() override; void endFlowMapping() override; unsigned beginSequence() override; @@ -1154,10 +1198,8 @@ private: typedef llvm::StringMap<std::unique_ptr<HNode>> NameToNode; - bool isValidKey(StringRef key); - NameToNode Mapping; - llvm::SmallVector<const char*, 6> ValidKeys; + llvm::SmallVector<std::string, 6> ValidKeys; }; class SequenceHNode : public HNode { @@ -1215,6 +1257,7 @@ public: void endMapping() override; bool preflightKey(const char *key, bool, bool, bool &, void *&) override; void postflightKey(void *) override; + std::vector<StringRef> keys() override; void beginFlowMapping() override; void endFlowMapping() override; unsigned beginSequence() override; @@ -1384,6 +1427,17 @@ operator>>(Input &In, T &Val) { return In; } +// Define non-member operator>> so that Input can stream in a string map. +template <typename T> +inline +typename std::enable_if<has_CustomMappingTraits<T>::value, Input &>::type +operator>>(Input &In, T &Val) { + EmptyContext Ctx; + if (In.setCurrentDocument()) + yamlize(In, Val, true, Ctx); + return In; +} + // Provide better error message about types missing a trait specialization template <typename T> inline typename std::enable_if<missingTraits<T, EmptyContext>::value, @@ -1457,6 +1511,21 @@ operator<<(Output &Out, T &Val) { return Out; } +// Define non-member operator<< so that Output can stream out a string map. +template <typename T> +inline +typename std::enable_if<has_CustomMappingTraits<T>::value, Output &>::type +operator<<(Output &Out, T &Val) { + EmptyContext Ctx; + Out.beginDocuments(); + if (Out.preflightDocument(0)) { + yamlize(Out, Val, true, Ctx); + Out.postflightDocument(); + } + Out.endDocuments(); + return Out; +} + // Provide better error message about types missing a trait specialization template <typename T> inline typename std::enable_if<missingTraits<T, EmptyContext>::value, @@ -1476,6 +1545,18 @@ template <typename T> struct SequenceTraitsImpl { } }; +/// Implementation of CustomMappingTraits for std::map<std::string, T>. +template <typename T> struct StdMapStringCustomMappingTraitsImpl { + typedef std::map<std::string, T> map_type; + static void inputOne(IO &io, StringRef key, map_type &v) { + io.mapRequired(key.str().c_str(), v[key]); + } + static void output(IO &io, map_type &v) { + for (auto &p : v) + io.mapRequired(p.first.c_str(), p.second); + } +}; + } // end namespace yaml } // end namespace llvm @@ -1530,4 +1611,15 @@ template <typename T> struct SequenceTraitsImpl { } \ } +/// Utility for declaring that std::map<std::string, _type> should be considered +/// a YAML map. +#define LLVM_YAML_IS_STRING_MAP(_type) \ + namespace llvm { \ + namespace yaml { \ + template <> \ + struct CustomMappingTraits<std::map<std::string, _type>> \ + : public StdMapStringCustomMappingTraitsImpl<_type> {}; \ + } \ + } + #endif // LLVM_SUPPORT_YAMLTRAITS_H |