1 // Copyright 2020 The Tint Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #ifndef SRC_SEM_TYPE_MANAGER_H_ 16 #define SRC_SEM_TYPE_MANAGER_H_ 17 18 #include <string> 19 #include <unordered_map> 20 #include <utility> 21 22 #include "src/block_allocator.h" 23 #include "src/sem/type.h" 24 25 namespace tint { 26 namespace sem { 27 28 /// The type manager holds all the pointers to the known types. 29 class Manager { 30 public: 31 /// Iterator is the type returned by begin() and end() 32 using Iterator = BlockAllocator<sem::Type>::ConstIterator; 33 34 /// Constructor 35 Manager(); 36 37 /// Move constructor 38 Manager(Manager&&); 39 40 /// Move assignment operator 41 /// @param rhs the Manager to move 42 /// @return this Manager 43 Manager& operator=(Manager&& rhs); 44 45 /// Destructor 46 ~Manager(); 47 48 /// Get the given type `T` from the type manager 49 /// @param args the arguments to pass to the type constructor 50 /// @return the pointer to the registered type 51 template <typename T, typename... ARGS> Get(ARGS &&...args)52 T* Get(ARGS&&... args) { 53 // Note: We do not use std::forward here, as we may need to use the 54 // arguments again for the call to Create<T>() below. 55 auto name = T(args...).type_name(); 56 auto it = by_name_.find(name); 57 if (it != by_name_.end()) { 58 return static_cast<T*>(it->second); 59 } 60 61 auto* type = types_.Create<T>(std::forward<ARGS>(args)...); 62 by_name_.emplace(name, type); 63 return type; 64 } 65 66 /// Wrap returns a new Manager created with the types of `inner`. 67 /// The Manager returned by Wrap is intended to temporarily extend the types 68 /// of an existing immutable Manager. 69 /// As the copied types are owned by `inner`, `inner` must not be destructed 70 /// or assigned while using the returned Manager. 71 /// TODO(bclayton) - Evaluate whether there are safer alternatives to this 72 /// function. See crbug.com/tint/460. 73 /// @param inner the immutable Manager to extend 74 /// @return the Manager that wraps `inner` Wrap(const Manager & inner)75 static Manager Wrap(const Manager& inner) { 76 Manager out; 77 out.by_name_ = inner.by_name_; 78 return out; 79 } 80 81 /// Returns the type map 82 /// @returns the mapping from name string to type. types()83 const std::unordered_map<std::string, sem::Type*>& types() const { 84 return by_name_; 85 } 86 87 /// @returns an iterator to the beginning of the types begin()88 Iterator begin() const { return types_.Objects().begin(); } 89 /// @returns an iterator to the end of the types end()90 Iterator end() const { return types_.Objects().end(); } 91 92 private: 93 std::unordered_map<std::string, sem::Type*> by_name_; 94 BlockAllocator<sem::Type> types_; 95 }; 96 97 } // namespace sem 98 } // namespace tint 99 100 #endif // SRC_SEM_TYPE_MANAGER_H_ 101