// 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 <utility>

namespace spvtools {
namespace opt {
namespace {

const uint32_t kTypePointerTypeIdInIdx = 1;

}  // anonymous namespace

bool InlineOpaquePass::IsOpaqueType(uint32_t typeId) {
  const Instruction* typeInst = get_def_use_mgr()->GetDef(typeId);
  switch (typeInst->opcode()) {
    case SpvOpTypeSampler:
    case SpvOpTypeImage:
    case SpvOpTypeSampledImage:
      return true;
    case SpvOpTypePointer:
      return IsOpaqueType(
          typeInst->GetSingleWordInOperand(kTypePointerTypeIdInIdx));
    default:
      break;
  }
  // TODO(greg-lunarg): Handle arrays containing opaque type
  if (typeInst->opcode() != SpvOpTypeStruct) 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;
  });
}

bool 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)) {
        // Inline call.
        std::vector<std::unique_ptr<BasicBlock>> newBlocks;
        std::vector<std::unique_ptr<Instruction>> newVars;
        GenInlineCode(&newBlocks, &newVars, ii, bi);
        // 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();
        bi = bi.InsertBefore(&newBlocks);
        // Insert new function variables.
        if (newVars.size() > 0)
          func->begin()->begin().InsertBefore(std::move(newVars));
        // Restart inlining at beginning of calling block.
        ii = bi->begin();
        modified = true;
      } else {
        ++ii;
      }
    }
  }
  return modified;
}

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

Pass::Status InlineOpaquePass::ProcessImpl() {
  // Do opaque inlining on each function in entry point call tree
  ProcessFunction pfn = [this](Function* fp) { return InlineOpaque(fp); };
  bool modified = context()->ProcessEntryPointCallTree(pfn);
  return modified ? Status::SuccessWithChange : Status::SuccessWithoutChange;
}

InlineOpaquePass::InlineOpaquePass() = default;

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

}  // namespace opt
}  // namespace spvtools
