//===-- SlotIndexes.cpp - Slot Indexes Pass  ------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "slotindexes"

#include "llvm/CodeGen/SlotIndexes.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Target/TargetInstrInfo.h"

using namespace llvm;


// Yep - these are thread safe. See the header for details. 
namespace {


  class EmptyIndexListEntry : public IndexListEntry {
  public:
    EmptyIndexListEntry() : IndexListEntry(EMPTY_KEY) {}
  };

  class TombstoneIndexListEntry : public IndexListEntry {
  public:
    TombstoneIndexListEntry() : IndexListEntry(TOMBSTONE_KEY) {}
  };

  // The following statics are thread safe. They're read only, and you
  // can't step from them to any other list entries.
  ManagedStatic<EmptyIndexListEntry> IndexListEntryEmptyKey;
  ManagedStatic<TombstoneIndexListEntry> IndexListEntryTombstoneKey;
}

char SlotIndexes::ID = 0;
INITIALIZE_PASS(SlotIndexes, "slotindexes",
                "Slot index numbering", false, false);

IndexListEntry* IndexListEntry::getEmptyKeyEntry() {
  return &*IndexListEntryEmptyKey;
}

IndexListEntry* IndexListEntry::getTombstoneKeyEntry() {
  return &*IndexListEntryTombstoneKey;
}


void SlotIndexes::getAnalysisUsage(AnalysisUsage &au) const {
  au.setPreservesAll();
  MachineFunctionPass::getAnalysisUsage(au);
}

void SlotIndexes::releaseMemory() {
  mi2iMap.clear();
  mbb2IdxMap.clear();
  idx2MBBMap.clear();
  terminatorGaps.clear();
  clearList();
}

bool SlotIndexes::runOnMachineFunction(MachineFunction &fn) {

  // Compute numbering as follows:
  // Grab an iterator to the start of the index list.
  // Iterate over all MBBs, and within each MBB all MIs, keeping the MI
  // iterator in lock-step (though skipping it over indexes which have
  // null pointers in the instruction field).
  // At each iteration assert that the instruction pointed to in the index
  // is the same one pointed to by the MI iterator. This 

  // FIXME: This can be simplified. The mi2iMap_, Idx2MBBMap, etc. should
  // only need to be set up once after the first numbering is computed.

  mf = &fn;
  initList();

  // Check that the list contains only the sentinal.
  assert(indexListHead->getNext() == 0 &&
         "Index list non-empty at initial numbering?");
  assert(idx2MBBMap.empty() &&
         "Index -> MBB mapping non-empty at initial numbering?");
  assert(mbb2IdxMap.empty() &&
         "MBB -> Index mapping non-empty at initial numbering?");
  assert(mi2iMap.empty() &&
         "MachineInstr -> Index mapping non-empty at initial numbering?");

  functionSize = 0;
  unsigned index = 0;

  push_back(createEntry(0, index));

  // Iterate over the function.
  for (MachineFunction::iterator mbbItr = mf->begin(), mbbEnd = mf->end();
       mbbItr != mbbEnd; ++mbbItr) {
    MachineBasicBlock *mbb = &*mbbItr;

    // Insert an index for the MBB start.
    SlotIndex blockStartIndex(back(), SlotIndex::LOAD);

    index += SlotIndex::NUM;

    for (MachineBasicBlock::iterator miItr = mbb->begin(), miEnd = mbb->end();
         miItr != miEnd; ++miItr) {
      MachineInstr *mi = miItr;
      if (mi->isDebugValue())
        continue;

      if (miItr == mbb->getFirstTerminator()) {
        push_back(createEntry(0, index));
        terminatorGaps.insert(
          std::make_pair(mbb, SlotIndex(back(), SlotIndex::PHI_BIT)));
        index += SlotIndex::NUM;
      }

      // Insert a store index for the instr.
      push_back(createEntry(mi, index));

      // Save this base index in the maps.
      mi2iMap.insert(
        std::make_pair(mi, SlotIndex(back(), SlotIndex::LOAD)));
 
      ++functionSize;

      unsigned Slots = mi->getDesc().getNumDefs();
      if (Slots == 0)
        Slots = 1;

      index += (Slots + 1) * SlotIndex::NUM;
    }

    if (mbb->getFirstTerminator() == mbb->end()) {
      push_back(createEntry(0, index));
      terminatorGaps.insert(
        std::make_pair(mbb, SlotIndex(back(), SlotIndex::PHI_BIT)));
      index += SlotIndex::NUM;
    }

    // One blank instruction at the end.
    push_back(createEntry(0, index));    

    SlotIndex blockEndIndex(back(), SlotIndex::LOAD);
    mbb2IdxMap.insert(
      std::make_pair(mbb, std::make_pair(blockStartIndex, blockEndIndex)));

    idx2MBBMap.push_back(IdxMBBPair(blockStartIndex, mbb));
  }

  // Sort the Idx2MBBMap
  std::sort(idx2MBBMap.begin(), idx2MBBMap.end(), Idx2MBBCompare());

  DEBUG(dump());

  // And we're done!
  return false;
}

void SlotIndexes::renumberIndexes() {

  // Renumber updates the index of every element of the index list.
  // If all instrs in the function have been allocated an index (which has been
  // placed in the index list in the order of instruction iteration) then the
  // resulting numbering will match what would have been generated by the
  // pass during the initial numbering of the function if the new instructions
  // had been present.

  functionSize = 0;
  unsigned index = 0;

  for (IndexListEntry *curEntry = front(); curEntry != getTail();
       curEntry = curEntry->getNext()) {

    curEntry->setIndex(index);

    if (curEntry->getInstr() == 0) {
      // MBB start entry or terminator gap. Just step index by 1.
      index += SlotIndex::NUM;
    }
    else {
      ++functionSize;
      unsigned Slots = curEntry->getInstr()->getDesc().getNumDefs();
      if (Slots == 0)
        Slots = 1;

      index += (Slots + 1) * SlotIndex::NUM;
    }
  }
}

void SlotIndexes::dump() const {
  for (const IndexListEntry *itr = front(); itr != getTail();
       itr = itr->getNext()) {
    dbgs() << itr->getIndex() << " ";

    if (itr->getInstr() != 0) {
      dbgs() << *itr->getInstr();
    } else {
      dbgs() << "\n";
    }
  }

  for (MBB2IdxMap::const_iterator itr = mbb2IdxMap.begin();
       itr != mbb2IdxMap.end(); ++itr) {
    dbgs() << "MBB " << itr->first->getNumber() << " (" << itr->first << ") - ["
           << itr->second.first << ", " << itr->second.second << "]\n";
  }
}

// Print a SlotIndex to a raw_ostream.
void SlotIndex::print(raw_ostream &os) const {
  os << entry().getIndex();
  if (isPHI())
    os << "*";
  else
    os << "LudS"[getSlot()];
}

// Dump a SlotIndex to stderr.
void SlotIndex::dump() const {
  print(dbgs());
  dbgs() << "\n";
}

