// Copyright (c) 2017 The Khronos Group Inc.
// Copyright (c) 2017 Valve Corporation
// Copyright (c) 2017 LunarG Inc.
//
// 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 "source/opt/inline_opaque_pass.h"

#include <iterator>
#include <utility>

namespace spvtools {
namespace opt {
namespace {
constexpr uint32_t kTypePointerTypeIdInIdx = 1;
}  // namespace

bool InlineOpaquePass::IsOpaqueType(uint32_t typeId) {
  const Instruction* typeInst = get_def_use_mgr()->GetDef(typeId);
  switch (typeInst->opcode()) {
    case spv::Op::OpTypeSampler:
    case spv::Op::OpTypeImage:
    case spv::Op::OpTypeSampledImage:
      return true;
    case spv::Op::OpTypePointer:
      return IsOpaqueType(
          typeInst->GetSingleWordInOperand(kTypePointerTypeIdInIdx));
    default:
      break;
  }
  // TODO(greg-lunarg): Handle arrays containing opaque type
  if (typeInst->opcode() != spv::Op::OpTypeStruct) return false;
  // Return true if any member is opaque
  return !typeInst->WhileEachInId([this](const uint32_t* tid) {
    if (IsOpaqueType(*tid)) return false;
    return true;
  });
}

bool InlineOpaquePass::HasOpaqueArgsOrReturn(const Instruction* callInst) {
  // Check return type
  if (IsOpaqueType(callInst->type_id())) return true;
  // Check args
  int icnt = 0;
  return !callInst->WhileEachInId([&icnt, this](const uint32_t* iid) {
    if (icnt > 0) {
      const Instruction* argInst = get_def_use_mgr()->GetDef(*iid);
      if (IsOpaqueType(argInst->type_id())) return false;
    }
    ++icnt;
    return true;
  });
}

Pass::Status InlineOpaquePass::InlineOpaque(Function* func) {
  bool modified = false;
  // Using block iterators here because of block erasures and insertions.
  for (auto bi = func->begin(); bi != func->end(); ++bi) {
    for (auto ii = bi->begin(); ii != bi->end();) {
      if (IsInlinableFunctionCall(&*ii) && HasOpaqueArgsOrReturn(&*ii)) {
        // Save instruction before the call to avoid redundant re-scanning.
        Instruction* prev_inst =
            (ii == bi->begin()) ? nullptr : &*std::prev(ii);

        // Inline call.
        std::vector<std::unique_ptr<BasicBlock>> newBlocks;
        std::vector<std::unique_ptr<Instruction>> newVars;
        if (!GenInlineCode(&newBlocks, &newVars, ii, bi)) {
          return Status::Failure;
        }

        // If call block is replaced with more than one block, point
        // succeeding phis at new last block.
        if (newBlocks.size() > 1) UpdateSucceedingPhis(newBlocks);
        // Replace old calling block with new block(s).
        bi = bi.Erase();

        for (auto& bb : newBlocks) {
          bb->SetParent(func);
        }
        bi = bi.InsertBefore(&newBlocks);
        // Insert new function variables.
        if (newVars.size() > 0)
          func->begin()->begin().InsertBefore(std::move(newVars));
        // Restart inlining at the first instruction of the inlined code.
        ii = prev_inst ? ++InstructionList::iterator(prev_inst) : bi->begin();
        modified = true;
      } else {
        ++ii;
      }
    }
  }

  if (modified) {
    FixDebugDeclares(func);
  }

  return (modified ? Status::SuccessWithChange : Status::SuccessWithoutChange);
}

void InlineOpaquePass::Initialize() { InitializeInline(); }

Pass::Status InlineOpaquePass::ProcessImpl() {
  Status status = Status::SuccessWithoutChange;
  // Do opaque inlining on each function in entry point call tree
  ProcessFunction pfn = [&status, this](Function* fp) {
    status = CombineStatus(status, InlineOpaque(fp));
    return false;
  };
  context()->ProcessReachableCallTree(pfn);
  return status;
}

InlineOpaquePass::InlineOpaquePass() = default;

Pass::Status InlineOpaquePass::Process() {
  Initialize();
  return ProcessImpl();
}

}  // namespace opt
}  // namespace spvtools
