1 /* 2 * Copyright 2017, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "pass_queue.h" 18 19 #include "module.h" 20 21 namespace android { 22 namespace spirit { 23 24 bool PassQueue::append(Pass *pass) { 25 mPasses.push_back(pass); 26 mPassSet.insert(pass); 27 return true; 28 } 29 30 Module *PassQueue::run(Module *module, int *error) { 31 if (mPasses.empty()) { 32 return module; 33 } 34 35 // A unique ptr to keep intermediate modules from leaking 36 std::unique_ptr<Module> tempModule; 37 38 for (auto pass : mPasses) { 39 int intermediateError = 0; 40 Module* newModule = pass->run(module, &intermediateError); 41 // Some passes modify the input module in place, while others create a new 42 // module. Release memory only when it is necessary. 43 if (newModule != module) { 44 tempModule.reset(newModule); 45 } 46 module = newModule; 47 if (intermediateError) { 48 if (error) { 49 *error = intermediateError; 50 } 51 return nullptr; 52 } 53 if (!module || !module->resolveIds()) { 54 if (error) { 55 *error = -1; 56 } 57 return nullptr; 58 } 59 } 60 61 if (tempModule == nullptr) { 62 return module; 63 } 64 65 return tempModule.release(); 66 } 67 68 std::vector<uint32_t> PassQueue::run(const std::vector<uint32_t> &spirvWords, 69 int *error) { 70 if (mPasses.empty()) { 71 return spirvWords; 72 } 73 74 Module *module = Deserialize<Module>(spirvWords); 75 if (!module || !module->resolveIds()) { 76 return std::vector<uint32_t>(); 77 } 78 79 return runAndSerialize(module, error); 80 } 81 82 std::vector<uint32_t> PassQueue::runAndSerialize(Module *module, int *error) { 83 const int n = mPasses.size(); 84 if (n < 1) { 85 return Serialize<Module>(module); 86 } 87 88 // A unique ptr to keep intermediate modules from leaking 89 std::unique_ptr<Module> tempModule; 90 91 for (int i = 0; i < n - 1; i++) { 92 int intermediateError = 0; 93 Module *newModule = mPasses[i]->run(module, &intermediateError); 94 // Some passes modify the input module in place, while others create a new 95 // module. Release memory only when it is necessary. 96 if (newModule != module) { 97 tempModule.reset(newModule); 98 } 99 module = newModule; 100 if (intermediateError) { 101 if (error) { 102 *error = intermediateError; 103 } 104 return std::vector<uint32_t>(); 105 } 106 if (!module || !module->resolveIds()) { 107 if (error) { 108 *error = -1; 109 } 110 return std::vector<uint32_t>(); 111 } 112 } 113 return mPasses[n - 1]->runAndSerialize(module, error); 114 } 115 116 } // namespace spirit 117 } // namespace android 118