// 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 ir::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 ir::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 ir::Instruction* argInst = get_def_use_mgr()->GetDef(*iid);
      if (IsOpaqueType(argInst->type_id())) return false;
    }
    ++icnt;
    return true;
  });
}

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

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

InlineOpaquePass::InlineOpaquePass() {}

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

}  // namespace opt
}  // namespace spvtools
