Home | History | Annotate | Download | only in opt
      1 // Copyright (c) 2016 Google Inc.
      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 #include "source/opt/module.h"
     16 
     17 #include <algorithm>
     18 #include <cstring>
     19 #include <ostream>
     20 
     21 #include "source/operand.h"
     22 #include "source/opt/ir_context.h"
     23 #include "source/opt/reflect.h"
     24 
     25 namespace spvtools {
     26 namespace opt {
     27 
     28 uint32_t Module::TakeNextIdBound() {
     29   if (context()) {
     30     if (id_bound() >= context()->max_id_bound()) {
     31       return 0;
     32     }
     33   } else if (id_bound() >= kDefaultMaxIdBound) {
     34     return 0;
     35   }
     36 
     37   return header_.bound++;
     38 }
     39 
     40 std::vector<Instruction*> Module::GetTypes() {
     41   std::vector<Instruction*> type_insts;
     42   for (auto& inst : types_values_) {
     43     if (IsTypeInst(inst.opcode())) type_insts.push_back(&inst);
     44   }
     45   return type_insts;
     46 }
     47 
     48 std::vector<const Instruction*> Module::GetTypes() const {
     49   std::vector<const Instruction*> type_insts;
     50   for (auto& inst : types_values_) {
     51     if (IsTypeInst(inst.opcode())) type_insts.push_back(&inst);
     52   }
     53   return type_insts;
     54 }
     55 
     56 std::vector<Instruction*> Module::GetConstants() {
     57   std::vector<Instruction*> const_insts;
     58   for (auto& inst : types_values_) {
     59     if (IsConstantInst(inst.opcode())) const_insts.push_back(&inst);
     60   }
     61   return const_insts;
     62 }
     63 
     64 std::vector<const Instruction*> Module::GetConstants() const {
     65   std::vector<const Instruction*> const_insts;
     66   for (auto& inst : types_values_) {
     67     if (IsConstantInst(inst.opcode())) const_insts.push_back(&inst);
     68   }
     69   return const_insts;
     70 }
     71 
     72 uint32_t Module::GetGlobalValue(SpvOp opcode) const {
     73   for (auto& inst : types_values_) {
     74     if (inst.opcode() == opcode) return inst.result_id();
     75   }
     76   return 0;
     77 }
     78 
     79 void Module::AddGlobalValue(SpvOp opcode, uint32_t result_id,
     80                             uint32_t type_id) {
     81   std::unique_ptr<Instruction> newGlobal(
     82       new Instruction(context(), opcode, type_id, result_id, {}));
     83   AddGlobalValue(std::move(newGlobal));
     84 }
     85 
     86 void Module::ForEachInst(const std::function<void(Instruction*)>& f,
     87                          bool run_on_debug_line_insts) {
     88 #define DELEGATE(list) list.ForEachInst(f, run_on_debug_line_insts)
     89   DELEGATE(capabilities_);
     90   DELEGATE(extensions_);
     91   DELEGATE(ext_inst_imports_);
     92   if (memory_model_) memory_model_->ForEachInst(f, run_on_debug_line_insts);
     93   DELEGATE(entry_points_);
     94   DELEGATE(execution_modes_);
     95   DELEGATE(debugs1_);
     96   DELEGATE(debugs2_);
     97   DELEGATE(debugs3_);
     98   DELEGATE(annotations_);
     99   DELEGATE(types_values_);
    100   for (auto& i : functions_) i->ForEachInst(f, run_on_debug_line_insts);
    101 #undef DELEGATE
    102 }
    103 
    104 void Module::ForEachInst(const std::function<void(const Instruction*)>& f,
    105                          bool run_on_debug_line_insts) const {
    106 #define DELEGATE(i) i.ForEachInst(f, run_on_debug_line_insts)
    107   for (auto& i : capabilities_) DELEGATE(i);
    108   for (auto& i : extensions_) DELEGATE(i);
    109   for (auto& i : ext_inst_imports_) DELEGATE(i);
    110   if (memory_model_)
    111     static_cast<const Instruction*>(memory_model_.get())
    112         ->ForEachInst(f, run_on_debug_line_insts);
    113   for (auto& i : entry_points_) DELEGATE(i);
    114   for (auto& i : execution_modes_) DELEGATE(i);
    115   for (auto& i : debugs1_) DELEGATE(i);
    116   for (auto& i : debugs2_) DELEGATE(i);
    117   for (auto& i : debugs3_) DELEGATE(i);
    118   for (auto& i : annotations_) DELEGATE(i);
    119   for (auto& i : types_values_) DELEGATE(i);
    120   for (auto& i : functions_) {
    121     static_cast<const Function*>(i.get())->ForEachInst(f,
    122                                                        run_on_debug_line_insts);
    123   }
    124 #undef DELEGATE
    125 }
    126 
    127 void Module::ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const {
    128   binary->push_back(header_.magic_number);
    129   binary->push_back(header_.version);
    130   // TODO(antiagainst): should we change the generator number?
    131   binary->push_back(header_.generator);
    132   binary->push_back(header_.bound);
    133   binary->push_back(header_.reserved);
    134 
    135   auto write_inst = [binary, skip_nop](const Instruction* i) {
    136     if (!(skip_nop && i->IsNop())) i->ToBinaryWithoutAttachedDebugInsts(binary);
    137   };
    138   ForEachInst(write_inst, true);
    139 }
    140 
    141 uint32_t Module::ComputeIdBound() const {
    142   uint32_t highest = 0;
    143 
    144   ForEachInst(
    145       [&highest](const Instruction* inst) {
    146         for (const auto& operand : *inst) {
    147           if (spvIsIdType(operand.type)) {
    148             highest = std::max(highest, operand.words[0]);
    149           }
    150         }
    151       },
    152       true /* scan debug line insts as well */);
    153 
    154   return highest + 1;
    155 }
    156 
    157 bool Module::HasExplicitCapability(uint32_t cap) {
    158   for (auto& ci : capabilities_) {
    159     uint32_t tcap = ci.GetSingleWordOperand(0);
    160     if (tcap == cap) {
    161       return true;
    162     }
    163   }
    164   return false;
    165 }
    166 
    167 uint32_t Module::GetExtInstImportId(const char* extstr) {
    168   for (auto& ei : ext_inst_imports_)
    169     if (!strcmp(extstr,
    170                 reinterpret_cast<const char*>(&(ei.GetInOperand(0).words[0]))))
    171       return ei.result_id();
    172   return 0;
    173 }
    174 
    175 std::ostream& operator<<(std::ostream& str, const Module& module) {
    176   module.ForEachInst([&str](const Instruction* inst) {
    177     str << *inst;
    178     if (inst->opcode() != SpvOpFunctionEnd) {
    179       str << std::endl;
    180     }
    181   });
    182   return str;
    183 }
    184 
    185 }  // namespace opt
    186 }  // namespace spvtools
    187