//===-- RustGCPrinter.cpp - Rust garbage collection map printer -----------===
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===
//
// This file defines the emitter for the Rust garbage collection stack maps.
//
//===----------------------------------------------------------------------===

#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/CodeGen/GCs.h"
#include "llvm/CodeGen/AsmPrinter.h"
#include "llvm/CodeGen/GCMetadataPrinter.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FormattedStream.h"
#include <cctype>
#include <map>

using namespace llvm;

namespace {
  enum RustGCMetaType {
    RGCMT_DestIndex,  // Type descriptor index -> type descriptor.
    RGCMT_SrcIndex,   // Value -> type descriptor index.
    RGCMT_Static      // Value with static type descriptor.
  };

  class RustGCMetadataPrinter : public GCMetadataPrinter {
  private:
    std::pair<RustGCMetaType,const Constant *>
      GetGCMetadataForRoot(const GCRoot &Root);
    void EmitGCMetadata(AsmPrinter &AP, MCStreamer &Out, GCRoot &Root);
    bool HandleDestIndex(const GCRoot &Root);
  public:
    void beginAssembly(AsmPrinter &AP) {};
    void finishAssembly(AsmPrinter &AP);
  };

  struct OrderedSymbol {
    unsigned Index;
    MCSymbol *Sym;

    OrderedSymbol(unsigned I, MCSymbol *S) : Index(I), Sym(S) {}

    static OrderedSymbol make(unsigned I, MCSymbol *S) {
      OrderedSymbol OS(I, S);
      return OS;
    }
  };
}

static GCMetadataPrinterRegistry::Add<RustGCMetadataPrinter>
X("rust", "Rust GC metadata printer");


typedef std::vector< std::pair< MCSymbol *,std::vector<GCRoot> > > RootMap;

std::pair<RustGCMetaType,const Constant *>
RustGCMetadataPrinter::GetGCMetadataForRoot(const GCRoot &Root) {
  const GlobalVariable *GCMetaVar =
    cast<const GlobalVariable>(Root.Metadata->stripPointerCasts());

  const Constant *GCMetaInit = GCMetaVar->getInitializer();
  if (isa<ConstantAggregateZero>(GCMetaInit)) {
    // "zeroinitializer": expand to (0, 0).
    IntegerType *I32 = IntegerType::get(GCMetaInit->getContext(), 32);
    ConstantInt *Zero = ConstantInt::get(I32, 0);
    return std::make_pair(RGCMT_DestIndex, Zero);
  }

  const ConstantStruct *GCMeta =
    cast<const ConstantStruct>(GCMetaVar->getInitializer());

  RustGCMetaType GCMetaType = (RustGCMetaType)
    (cast<const ConstantInt>(GCMeta->getOperand(0))->getZExtValue());
  const Constant *Payload = cast<const Constant>(GCMeta->getOperand(1));
  return std::make_pair(GCMetaType, Payload);
}

void RustGCMetadataPrinter::EmitGCMetadata(AsmPrinter &AP, MCStreamer &Out,
                                           GCRoot &Root) {
  int WordSize = AP.TM.getTargetData()->getPointerSize();

  std::pair<RustGCMetaType,const Constant *> Pair =
    GetGCMetadataForRoot(Root);
  const GlobalValue *Tydesc = 0;

  switch (Pair.first) {
  case RGCMT_DestIndex: // Dest index.
    assert(0 && "Dest index should not be here!");
  case RGCMT_SrcIndex:
    // TODO: Use the mapping to find the tydesc frame offset.
    Out.EmitIntValue(1, WordSize, 0);
    Out.EmitIntValue(0, WordSize, 0);
    return;
  case 2: // Static type descriptor.
    Out.EmitIntValue(0, WordSize, 0);
    Tydesc = cast<const GlobalValue>(Pair.second);
    break;
  }

  MCSymbol *TydescSym = AP.Mang->getSymbol(Tydesc);
  Out.EmitSymbolValue(TydescSym, WordSize, 0);
}

// Records the destination index of a type descriptor in the type descriptor
// map, if this GC root is a destination index. Returns true if the GC root is
// a destination index and false otherwise.
bool RustGCMetadataPrinter::HandleDestIndex(const GCRoot &Root) {
  std::pair<RustGCMetaType,const Constant *> Pair =
    GetGCMetadataForRoot(Root);
  return Pair.first == RGCMT_DestIndex; // TODO
}

void RustGCMetadataPrinter::finishAssembly(AsmPrinter &AP) {
  MCStreamer &Out = AP.OutStreamer;

  // Use the data section.
  Out.SwitchSection(AP.getObjFileLowering().getDataSection());

  // Iterate over each function.
  RootMap Map;

  iterator FI = begin(), FE = end();
  while (FI != FE) {
    GCFunctionInfo &GCFI = **FI;

    // Iterate over each safe point.
    GCFunctionInfo::iterator SPI = GCFI.begin(), SPE = GCFI.end();
    while (SPI != SPE) {
      std::vector<GCRoot> Roots;

      // Iterate over each live root.
      GCFunctionInfo::live_iterator LI = GCFI.live_begin(SPI);
      GCFunctionInfo::live_iterator LE = GCFI.live_end(SPI);
      while (LI != LE) {
        if (!HandleDestIndex(*LI))
          Roots.push_back(*LI);
        ++LI;
      }

      Map.push_back(std::make_pair(SPI->Label, Roots));
      ++SPI;
    }
    ++FI;
  }

  // Write out the map.
  Out.AddBlankLine();

  int WordSize = AP.TM.getTargetData()->getPointerSize();

  MCSymbol *SafePointSym = AP.GetExternalSymbolSymbol("rust_gc_safe_points");
  Out.EmitSymbolAttribute(SafePointSym, MCSA_Global);
  Out.EmitLabel(SafePointSym);
  Out.EmitIntValue(Map.size(), WordSize, 0);

  std::vector<MCSymbol *> FrameMapLabels;

  RootMap::iterator MI = Map.begin(), ME = Map.end();
  unsigned i = 0;
  while (MI != ME) {
    Out.EmitSymbolValue(MI->first, WordSize, 0);
    MCSymbol *FrameMapLabel = AP.GetTempSymbol("rust_frame_map_label", i);
    Out.EmitSymbolValue(FrameMapLabel, WordSize, 0);
    FrameMapLabels.push_back(FrameMapLabel);
    ++MI, ++i;
  }

  MI = Map.begin(), i = 0;
  while (MI != ME) {
    Out.EmitLabel(FrameMapLabels[i]);

    std::vector<GCRoot> &Roots = MI->second;
    Out.EmitIntValue(Roots.size(), WordSize, 0);

    std::vector<GCRoot>::iterator RI = Roots.begin(), RE = Roots.end();
    while (RI != RE) {
      Out.EmitIntValue(RI->StackOffset, WordSize, 0);
      EmitGCMetadata(AP, Out, *RI);
      ++RI;
    }

    ++MI, ++i;
  }
}

