1 // Copyright (c) 2019 Google LLC 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 SOURCE_OPT_FIX_STORAGE_CLASS_H_ 16 #define SOURCE_OPT_FIX_STORAGE_CLASS_H_ 17 18 #include <unordered_map> 19 20 #include "source/opt/ir_context.h" 21 #include "source/opt/module.h" 22 #include "source/opt/pass.h" 23 24 namespace spvtools { 25 namespace opt { 26 27 // This pass tries to fix validation error due to a mismatch of storage classes 28 // in instructions. There is no guarantee that all such error will be fixed, 29 // and it is possible that in fixing these errors, it could lead to other 30 // errors. 31 class FixStorageClass : public Pass { 32 public: name()33 const char* name() const override { return "fix-storage-class"; } 34 Status Process() override; 35 36 // Return the mask of preserved Analyses. GetPreservedAnalyses()37 IRContext::Analysis GetPreservedAnalyses() override { 38 return IRContext::kAnalysisDefUse | 39 IRContext::kAnalysisInstrToBlockMapping | 40 IRContext::kAnalysisCombinators | IRContext::kAnalysisCFG | 41 IRContext::kAnalysisDominatorAnalysis | 42 IRContext::kAnalysisLoopAnalysis | IRContext::kAnalysisNameMap | 43 IRContext::kAnalysisConstants | IRContext::kAnalysisTypes; 44 } 45 46 private: 47 // Changes the storage class of the result of |inst| to |storage_class| in 48 // appropriate, and propagates the change to the users of |inst| as well. 49 // Returns true of any changes were made. 50 // |seen| is used to track OpPhi instructions that should not be processed. 51 bool PropagateStorageClass(Instruction* inst, SpvStorageClass storage_class, 52 std::set<uint32_t>* seen); 53 54 // Changes the storage class of the result of |inst| to |storage_class|. 55 // Is it assumed that the result type of |inst| is a pointer type. 56 // Propagates the change to the users of |inst| as well. 57 // Returns true of any changes were made. 58 // |seen| is used to track OpPhi instructions that should not be processed by 59 // |PropagateStorageClass| 60 void FixInstructionStorageClass(Instruction* inst, 61 SpvStorageClass storage_class, 62 std::set<uint32_t>* seen); 63 64 // Changes the storage class of the result of |inst| to |storage_class|. The 65 // result type of |inst| must be a pointer. 66 void ChangeResultStorageClass(Instruction* inst, 67 SpvStorageClass storage_class) const; 68 69 // Returns true if the result type of |inst| is a pointer. 70 bool IsPointerResultType(Instruction* inst); 71 72 // Returns true if the result of |inst| is a pointer to storage class 73 // |storage_class|. 74 bool IsPointerToStorageClass(Instruction* inst, 75 SpvStorageClass storage_class); 76 77 // Change |inst| to match that operand |op_idx| now has type |type_id|, and 78 // adjust any uses of |inst| accordingly. Returns true if the code changed. 79 bool PropagateType(Instruction* inst, uint32_t type_id, uint32_t op_idx, 80 std::set<uint32_t>* seen); 81 82 // Changes the result type of |inst| to |new_type_id|. 83 bool ChangeResultType(Instruction* inst, uint32_t new_type_id); 84 85 // Returns the type id of the member of the type |id| that would be returned 86 // by following the indices of the access chain instruction |inst|. 87 uint32_t WalkAccessChainType(Instruction* inst, uint32_t id); 88 }; 89 90 } // namespace opt 91 } // namespace spvtools 92 93 #endif // SOURCE_OPT_FIX_STORAGE_CLASS_H_ 94