| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134 |
- // Copyright (c) 2019 Google LLC
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- #include "fix_storage_class.h"
- #include "source/opt/instruction.h"
- #include "source/opt/ir_context.h"
- namespace spvtools {
- namespace opt {
- Pass::Status FixStorageClass::Process() {
- bool modified = false;
- get_module()->ForEachInst([this, &modified](Instruction* inst) {
- if (inst->opcode() == SpvOpVariable) {
- std::vector<Instruction*> uses;
- get_def_use_mgr()->ForEachUser(
- inst, [&uses](Instruction* use) { uses.push_back(use); });
- for (Instruction* use : uses) {
- modified |= PropagateStorageClass(
- use, static_cast<SpvStorageClass>(inst->GetSingleWordInOperand(0)));
- }
- }
- });
- return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
- }
- bool FixStorageClass::PropagateStorageClass(Instruction* inst,
- SpvStorageClass storage_class) {
- if (!IsPointerResultType(inst)) {
- return false;
- }
- if (IsPointerToStorageClass(inst, storage_class)) {
- return false;
- }
- switch (inst->opcode()) {
- case SpvOpAccessChain:
- case SpvOpPtrAccessChain:
- case SpvOpInBoundsAccessChain:
- case SpvOpCopyObject:
- case SpvOpPhi:
- case SpvOpSelect:
- FixInstruction(inst, storage_class);
- return true;
- case SpvOpFunctionCall:
- // We cannot be sure of the actual connection between the storage class
- // of the parameter and the storage class of the result, so we should not
- // do anything. If the result type needs to be fixed, the function call
- // should be inlined.
- return false;
- case SpvOpImageTexelPointer:
- case SpvOpLoad:
- case SpvOpStore:
- case SpvOpCopyMemory:
- case SpvOpCopyMemorySized:
- case SpvOpVariable:
- case SpvOpBitcast:
- // Nothing to change for these opcode. The result type is the same
- // regardless of the storage class of the operand.
- return false;
- default:
- assert(false &&
- "Not expecting instruction to have a pointer result type.");
- return false;
- }
- }
- void FixStorageClass::FixInstruction(Instruction* inst,
- SpvStorageClass storage_class) {
- assert(IsPointerResultType(inst) &&
- "The result type of the instruction must be a pointer.");
- ChangeResultStorageClass(inst, storage_class);
- std::vector<Instruction*> uses;
- get_def_use_mgr()->ForEachUser(
- inst, [&uses](Instruction* use) { uses.push_back(use); });
- for (Instruction* use : uses) {
- PropagateStorageClass(use, storage_class);
- }
- }
- void FixStorageClass::ChangeResultStorageClass(
- Instruction* inst, SpvStorageClass storage_class) const {
- analysis::TypeManager* type_mgr = context()->get_type_mgr();
- Instruction* result_type_inst = get_def_use_mgr()->GetDef(inst->type_id());
- assert(result_type_inst->opcode() == SpvOpTypePointer);
- uint32_t pointee_type_id = result_type_inst->GetSingleWordInOperand(1);
- uint32_t new_result_type_id =
- type_mgr->FindPointerToType(pointee_type_id, storage_class);
- inst->SetResultType(new_result_type_id);
- context()->UpdateDefUse(inst);
- }
- bool FixStorageClass::IsPointerResultType(Instruction* inst) {
- if (inst->type_id() == 0) {
- return false;
- }
- const analysis::Type* ret_type =
- context()->get_type_mgr()->GetType(inst->type_id());
- return ret_type->AsPointer() != nullptr;
- }
- bool FixStorageClass::IsPointerToStorageClass(Instruction* inst,
- SpvStorageClass storage_class) {
- analysis::TypeManager* type_mgr = context()->get_type_mgr();
- analysis::Type* pType = type_mgr->GetType(inst->type_id());
- const analysis::Pointer* result_type = pType->AsPointer();
- if (result_type == nullptr) {
- return false;
- }
- return (result_type->storage_class() == storage_class);
- }
- // namespace opt
- } // namespace opt
- } // namespace spvtools
|