13f30b6202dd5ad6ff66959131d216405850ed152Yang Ni/*
23f30b6202dd5ad6ff66959131d216405850ed152Yang Ni * Copyright 2017, The Android Open Source Project
33f30b6202dd5ad6ff66959131d216405850ed152Yang Ni *
43f30b6202dd5ad6ff66959131d216405850ed152Yang Ni * Licensed under the Apache License, Version 2.0 (the "License");
53f30b6202dd5ad6ff66959131d216405850ed152Yang Ni * you may not use this file except in compliance with the License.
63f30b6202dd5ad6ff66959131d216405850ed152Yang Ni * You may obtain a copy of the License at
73f30b6202dd5ad6ff66959131d216405850ed152Yang Ni *
83f30b6202dd5ad6ff66959131d216405850ed152Yang Ni *     http://www.apache.org/licenses/LICENSE-2.0
93f30b6202dd5ad6ff66959131d216405850ed152Yang Ni *
103f30b6202dd5ad6ff66959131d216405850ed152Yang Ni * Unless required by applicable law or agreed to in writing, software
113f30b6202dd5ad6ff66959131d216405850ed152Yang Ni * distributed under the License is distributed on an "AS IS" BASIS,
123f30b6202dd5ad6ff66959131d216405850ed152Yang Ni * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133f30b6202dd5ad6ff66959131d216405850ed152Yang Ni * See the License for the specific language governing permissions and
143f30b6202dd5ad6ff66959131d216405850ed152Yang Ni * limitations under the License.
153f30b6202dd5ad6ff66959131d216405850ed152Yang Ni */
163f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
173f30b6202dd5ad6ff66959131d216405850ed152Yang Ni#include "pass_queue.h"
183f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
193f30b6202dd5ad6ff66959131d216405850ed152Yang Ni#include "module.h"
203f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
213f30b6202dd5ad6ff66959131d216405850ed152Yang Ninamespace android {
223f30b6202dd5ad6ff66959131d216405850ed152Yang Ninamespace spirit {
233f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
243f30b6202dd5ad6ff66959131d216405850ed152Yang Nibool PassQueue::append(Pass *pass) {
253f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  mPasses.push_back(pass);
263f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  mPassSet.insert(pass);
273f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  return true;
283f30b6202dd5ad6ff66959131d216405850ed152Yang Ni}
293f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
303f30b6202dd5ad6ff66959131d216405850ed152Yang NiModule *PassQueue::run(Module *module, int *error) {
313f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  if (mPasses.empty()) {
323f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    return module;
333f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  }
343f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
353f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  // A unique ptr to keep intermediate modules from leaking
363f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  std::unique_ptr<Module> tempModule;
373f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
383f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  for (auto pass : mPasses) {
393f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    int intermediateError = 0;
403f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    Module* newModule = pass->run(module, &intermediateError);
413f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    // Some passes modify the input module in place, while others create a new
423f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    // module. Release memory only when it is necessary.
433f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    if (newModule != module) {
443f30b6202dd5ad6ff66959131d216405850ed152Yang Ni      tempModule.reset(newModule);
453f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    }
463f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    module = newModule;
473f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    if (intermediateError) {
483f30b6202dd5ad6ff66959131d216405850ed152Yang Ni      if (error) {
493f30b6202dd5ad6ff66959131d216405850ed152Yang Ni        *error = intermediateError;
503f30b6202dd5ad6ff66959131d216405850ed152Yang Ni      }
513f30b6202dd5ad6ff66959131d216405850ed152Yang Ni      return nullptr;
523f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    }
533f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    if (!module || !module->resolveIds()) {
543f30b6202dd5ad6ff66959131d216405850ed152Yang Ni      if (error) {
553f30b6202dd5ad6ff66959131d216405850ed152Yang Ni        *error = -1;
563f30b6202dd5ad6ff66959131d216405850ed152Yang Ni      }
573f30b6202dd5ad6ff66959131d216405850ed152Yang Ni      return nullptr;
583f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    }
593f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  }
603f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
613f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  if (tempModule == nullptr) {
623f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    return module;
633f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  }
643f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
653f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  return tempModule.release();
663f30b6202dd5ad6ff66959131d216405850ed152Yang Ni}
673f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
683f30b6202dd5ad6ff66959131d216405850ed152Yang Nistd::vector<uint32_t> PassQueue::run(const std::vector<uint32_t> &spirvWords,
693f30b6202dd5ad6ff66959131d216405850ed152Yang Ni                                     int *error) {
703f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  if (mPasses.empty()) {
713f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    return spirvWords;
723f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  }
733f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
743e5fbb6faf66488ba49c9d2396350ae567dba315Yang Ni  Module *module = Deserialize<Module>(spirvWords);
753f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  if (!module || !module->resolveIds()) {
763f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    return std::vector<uint32_t>();
773f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  }
783f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
793f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  return runAndSerialize(module, error);
803f30b6202dd5ad6ff66959131d216405850ed152Yang Ni}
813f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
823f30b6202dd5ad6ff66959131d216405850ed152Yang Nistd::vector<uint32_t> PassQueue::runAndSerialize(Module *module, int *error) {
833f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  const int n = mPasses.size();
843f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  if (n < 1) {
853e5fbb6faf66488ba49c9d2396350ae567dba315Yang Ni    return Serialize<Module>(module);
863f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  }
873f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
883f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  // A unique ptr to keep intermediate modules from leaking
893f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  std::unique_ptr<Module> tempModule;
903f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
913f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  for (int i = 0; i < n - 1; i++) {
923f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    int intermediateError = 0;
933f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    Module *newModule = mPasses[i]->run(module, &intermediateError);
943f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    // Some passes modify the input module in place, while others create a new
953f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    // module. Release memory only when it is necessary.
963f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    if (newModule != module) {
973f30b6202dd5ad6ff66959131d216405850ed152Yang Ni      tempModule.reset(newModule);
983f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    }
993f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    module = newModule;
1003f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    if (intermediateError) {
1013f30b6202dd5ad6ff66959131d216405850ed152Yang Ni      if (error) {
1023f30b6202dd5ad6ff66959131d216405850ed152Yang Ni        *error = intermediateError;
1033f30b6202dd5ad6ff66959131d216405850ed152Yang Ni      }
1043f30b6202dd5ad6ff66959131d216405850ed152Yang Ni      return std::vector<uint32_t>();
1053f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    }
1063f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    if (!module || !module->resolveIds()) {
1073f30b6202dd5ad6ff66959131d216405850ed152Yang Ni      if (error) {
1083f30b6202dd5ad6ff66959131d216405850ed152Yang Ni        *error = -1;
1093f30b6202dd5ad6ff66959131d216405850ed152Yang Ni      }
1103f30b6202dd5ad6ff66959131d216405850ed152Yang Ni      return std::vector<uint32_t>();
1113f30b6202dd5ad6ff66959131d216405850ed152Yang Ni    }
1123f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  }
1133f30b6202dd5ad6ff66959131d216405850ed152Yang Ni  return mPasses[n - 1]->runAndSerialize(module, error);
1143f30b6202dd5ad6ff66959131d216405850ed152Yang Ni}
1153f30b6202dd5ad6ff66959131d216405850ed152Yang Ni
1163f30b6202dd5ad6ff66959131d216405850ed152Yang Ni} // namespace spirit
1173f30b6202dd5ad6ff66959131d216405850ed152Yang Ni} // namespace android
118