// 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 "inline_opaque_pass.h"

namespace spvtools {
namespace opt {

namespace {

const uint32_t kTypePointerTypeIdInIdx = 1;

}  // anonymous namespace

bool InlineOpaquePass::IsOpaqueType(uint32_t typeId) {
  const opt::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 opt::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 opt::Instruction* argInst = get_def_use_mgr()->GetDef(*iid);
      if (IsOpaqueType(argInst->type_id())) return false;
    }
    ++icnt;
    return true;
  });
}

bool InlineOpaquePass::InlineOpaque(opt::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<opt::BasicBlock>> newBlocks;
        std::vector<std::unique_ptr<opt::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(opt::IRContext* c) { InitializeInline(c); }

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

InlineOpaquePass::InlineOpaquePass() {}

Pass::Status InlineOpaquePass::Process(opt::IRContext* c) {
  Initialize(c);
  return ProcessImpl();
}

}  // namespace opt
}  // namespace spvtools
