1 // Copyright 2021 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_STRUCT_H_ 16 #define SRC_SEM_STRUCT_H_ 17 18 #include <stdint.h> 19 20 #include <string> 21 #include <unordered_set> 22 #include <vector> 23 24 #include "src/ast/storage_class.h" 25 #include "src/ast/struct.h" 26 #include "src/sem/node.h" 27 #include "src/sem/type.h" 28 #include "src/symbol.h" 29 30 namespace tint { 31 32 // Forward declarations 33 namespace ast { 34 class StructMember; 35 } // namespace ast 36 37 namespace sem { 38 39 // Forward declarations 40 class StructMember; 41 class Type; 42 43 /// A vector of StructMember pointers. 44 using StructMemberList = std::vector<const StructMember*>; 45 46 /// Metadata to capture how a structure is used in a shader module. 47 enum class PipelineStageUsage { 48 kVertexInput, 49 kVertexOutput, 50 kFragmentInput, 51 kFragmentOutput, 52 kComputeInput, 53 kComputeOutput, 54 }; 55 56 /// Struct holds the semantic information for structures. 57 class Struct : public Castable<Struct, Type> { 58 public: 59 /// Constructor 60 /// @param declaration the AST structure declaration 61 /// @param name the name of the structure 62 /// @param members the structure members 63 /// @param align the byte alignment of the structure 64 /// @param size the byte size of the structure 65 /// @param size_no_padding size of the members without the end of structure 66 /// alignment padding 67 Struct(const ast::Struct* declaration, 68 Symbol name, 69 StructMemberList members, 70 uint32_t align, 71 uint32_t size, 72 uint32_t size_no_padding); 73 74 /// Destructor 75 ~Struct() override; 76 77 /// @returns the struct Declaration()78 const ast::Struct* Declaration() const { return declaration_; } 79 80 /// @returns the name of the structure Name()81 Symbol Name() const { return name_; } 82 83 /// @returns the members of the structure Members()84 const StructMemberList& Members() const { return members_; } 85 86 /// @param name the member name to look for 87 /// @returns the member with the given name, or nullptr if it was not found. 88 const StructMember* FindMember(Symbol name) const; 89 90 /// @returns the byte alignment of the structure 91 /// @note this may differ from the alignment of a structure member of this 92 /// structure type, if the member is annotated with the `[[align(n)]]` 93 /// decoration. 94 uint32_t Align() const override; 95 96 /// @returns the byte size of the structure 97 /// @note this may differ from the size of a structure member of this 98 /// structure type, if the member is annotated with the `[[size(n)]]` 99 /// decoration. 100 uint32_t Size() const override; 101 102 /// @returns the byte size of the members without the end of structure 103 /// alignment padding SizeNoPadding()104 uint32_t SizeNoPadding() const { return size_no_padding_; } 105 106 /// Adds the StorageClass usage to the structure. 107 /// @param usage the storage usage AddUsage(ast::StorageClass usage)108 void AddUsage(ast::StorageClass usage) { 109 storage_class_usage_.emplace(usage); 110 } 111 112 /// @returns the set of storage class uses of this structure StorageClassUsage()113 const std::unordered_set<ast::StorageClass>& StorageClassUsage() const { 114 return storage_class_usage_; 115 } 116 117 /// @param usage the ast::StorageClass usage type to query 118 /// @returns true iff this structure has been used as the given storage class UsedAs(ast::StorageClass usage)119 bool UsedAs(ast::StorageClass usage) const { 120 return storage_class_usage_.count(usage) > 0; 121 } 122 123 /// @returns true iff this structure has been used by storage class that's 124 /// host-shareable. IsHostShareable()125 bool IsHostShareable() const { 126 for (auto sc : storage_class_usage_) { 127 if (ast::IsHostShareable(sc)) { 128 return true; 129 } 130 } 131 return false; 132 } 133 134 /// Adds the pipeline stage usage to the structure. 135 /// @param usage the storage usage AddUsage(PipelineStageUsage usage)136 void AddUsage(PipelineStageUsage usage) { 137 pipeline_stage_uses_.emplace(usage); 138 } 139 140 /// @returns the set of entry point uses of this structure PipelineStageUses()141 const std::unordered_set<PipelineStageUsage>& PipelineStageUses() const { 142 return pipeline_stage_uses_; 143 } 144 145 /// @returns true if the struct has a block decoration IsBlockDecorated()146 bool IsBlockDecorated() const { return declaration_->IsBlockDecorated(); } 147 148 /// @returns the name for the type 149 std::string type_name() const override; 150 151 /// @param symbols the program's symbol table 152 /// @returns the name for this type that closely resembles how it would be 153 /// declared in WGSL. 154 std::string FriendlyName(const SymbolTable& symbols) const override; 155 156 /// @returns true if constructible as per 157 /// https://gpuweb.github.io/gpuweb/wgsl/#constructible-types 158 bool IsConstructible() const override; 159 160 private: 161 uint64_t LargestMemberBaseAlignment(MemoryLayout mem_layout) const; 162 163 ast::Struct const* const declaration_; 164 const Symbol name_; 165 const StructMemberList members_; 166 const uint32_t align_; 167 const uint32_t size_; 168 const uint32_t size_no_padding_; 169 std::unordered_set<ast::StorageClass> storage_class_usage_; 170 std::unordered_set<PipelineStageUsage> pipeline_stage_uses_; 171 bool constructible_; 172 }; 173 174 /// StructMember holds the semantic information for structure members. 175 class StructMember : public Castable<StructMember, Node> { 176 public: 177 /// Constructor 178 /// @param declaration the AST declaration node 179 /// @param name the name of the structure 180 /// @param type the type of the member 181 /// @param index the index of the member in the structure 182 /// @param offset the byte offset from the base of the structure 183 /// @param align the byte alignment of the member 184 /// @param size the byte size of the member 185 StructMember(const ast::StructMember* declaration, 186 Symbol name, 187 sem::Type* type, 188 uint32_t index, 189 uint32_t offset, 190 uint32_t align, 191 uint32_t size); 192 193 /// Destructor 194 ~StructMember() override; 195 196 /// @returns the AST declaration node Declaration()197 const ast::StructMember* Declaration() const { return declaration_; } 198 199 /// @returns the name of the structure Name()200 Symbol Name() const { return name_; } 201 202 /// @returns the type of the member Type()203 sem::Type* Type() const { return type_; } 204 205 /// @returns the member index Index()206 uint32_t Index() const { return index_; } 207 208 /// @returns byte offset from base of structure Offset()209 uint32_t Offset() const { return offset_; } 210 211 /// @returns the alignment of the member in bytes Align()212 uint32_t Align() const { return align_; } 213 214 /// @returns byte size Size()215 uint32_t Size() const { return size_; } 216 217 private: 218 const ast::StructMember* const declaration_; 219 const Symbol name_; 220 sem::Type* const type_; 221 const uint32_t index_; 222 const uint32_t offset_; 223 const uint32_t align_; 224 const uint32_t size_; 225 }; 226 227 } // namespace sem 228 } // namespace tint 229 230 #endif // SRC_SEM_STRUCT_H_ 231