//===- ReduceArguments.cpp - Specialized Delta Pass -----------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file implements a function which calls the Generic Delta pass in order
// to reduce uninteresting Arguments from defined functions.
//
//===----------------------------------------------------------------------===//

#include "ReduceBasicBlocks.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Value.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/raw_ostream.h"
#include <vector>

using namespace llvm;

/// Replaces BB Terminator with one that only contains Chunk BBs
static void replaceBranchTerminator(BasicBlock &BB,
                                    std::set<BasicBlock *> BBsToKeep) {
  auto Term = BB.getTerminator();
  std::vector<BasicBlock *> ChunkSucessors;
  for (auto Succ : successors(&BB))
    if (BBsToKeep.count(Succ))
      ChunkSucessors.push_back(Succ);

  // BB only references Chunk BBs
  if (ChunkSucessors.size() == Term->getNumSuccessors())
    return;

  bool IsBranch = isa<BranchInst>(Term);
  Value *Address = nullptr;
  if (auto IndBI = dyn_cast<IndirectBrInst>(Term))
    Address = IndBI->getAddress();

  Term->eraseFromParent();

  if (ChunkSucessors.empty()) {
    ReturnInst::Create(BB.getContext(), nullptr, &BB);
    return;
  }

  if (IsBranch)
    BranchInst::Create(ChunkSucessors[0], &BB);

  if (Address) {
    auto NewIndBI =
        IndirectBrInst::Create(Address, ChunkSucessors.size(), &BB);
    for (auto Dest : ChunkSucessors)
      NewIndBI->addDestination(Dest);
  }
}

/// Removes uninteresting BBs from switch, if the default case ends up being
/// uninteresting, the switch is replaced with a void return (since it has to be
/// replace with something)
static void removeUninterestingBBsFromSwitch(SwitchInst &SwInst,
                                             std::set<BasicBlock *> BBsToKeep) {
  if (!BBsToKeep.count(SwInst.getDefaultDest())) {
    ReturnInst::Create(SwInst.getContext(), nullptr, SwInst.getParent());
    SwInst.eraseFromParent();
  } else
    for (int I = 0, E = SwInst.getNumCases(); I != E; ++I) {
      auto Case = SwInst.case_begin() + I;
      if (!BBsToKeep.count(Case->getCaseSuccessor())) {
        SwInst.removeCase(Case);
        --I;
        --E;
      }
    }
}

/// Removes out-of-chunk arguments from functions, and modifies their calls
/// accordingly. It also removes allocations of out-of-chunk arguments.
static void extractBasicBlocksFromModule(std::vector<Chunk> ChunksToKeep,
                                         Module *Program) {
  int I = 0, BBCount = 0;
  std::set<BasicBlock *> BBsToKeep;

  for (auto &F : *Program)
    for (auto &BB : F)
      if (I < (int)ChunksToKeep.size()) {
        if (ChunksToKeep[I].contains(++BBCount))
          BBsToKeep.insert(&BB);
        if (ChunksToKeep[I].end == BBCount)
          ++I;
      }

  std::vector<BasicBlock *> BBsToDelete;
  for (auto &F : *Program)
    for (auto &BB : F) {
      if (!BBsToKeep.count(&BB)) {
        BBsToDelete.push_back(&BB);
        // Remove out-of-chunk BB from successor phi nodes
        for (auto *Succ : successors(&BB))
          Succ->removePredecessor(&BB);
      }
    }

  // Replace terminators that reference out-of-chunk BBs
  for (auto &F : *Program)
    for (auto &BB : F) {
      if (auto *SwInst = dyn_cast<SwitchInst>(BB.getTerminator()))
        removeUninterestingBBsFromSwitch(*SwInst, BBsToKeep);
      else
        replaceBranchTerminator(BB, BBsToKeep);
    }

  // Replace out-of-chunk switch uses
  for (auto &BB : BBsToDelete) {
    // Instructions might be referenced in other BBs
    for (auto &I : *BB)
      I.replaceAllUsesWith(UndefValue::get(I.getType()));
    BB->eraseFromParent();
  }
}

/// Counts the amount of basic blocks and prints their name & respective index
static int countBasicBlocks(Module *Program) {
  // TODO: Silence index with --quiet flag
  outs() << "----------------------------\n";
  int BBCount = 0;
  for (auto &F : *Program)
    for (auto &BB : F) {
      if (BB.hasName())
        outs() << "\t" << ++BBCount << ": " << BB.getName() << "\n";
      else
        outs() << "\t" << ++BBCount << ": Unnamed\n";
    }

  return BBCount;
}

void llvm::reduceBasicBlocksDeltaPass(TestRunner &Test) {
  outs() << "*** Reducing Basic Blocks...\n";
  int BBCount = countBasicBlocks(Test.getProgram());
  runDeltaPass(Test, BBCount, extractBasicBlocksFromModule);
}
