//===-- lib/CodeGen/ELFCodeEmitter.cpp ------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "elfce"

#include "ELF.h"
#include "ELFWriter.h"
#include "ELFCodeEmitter.h"
#include "llvm/Constants.h"
#include "llvm/DerivedTypes.h"
#include "llvm/Function.h"
#include "llvm/CodeGen/BinaryObject.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
#include "llvm/CodeGen/MachineRelocation.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetELFWriterInfo.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"

//===----------------------------------------------------------------------===//
//                       ELFCodeEmitter Implementation
//===----------------------------------------------------------------------===//

namespace llvm {

/// startFunction - This callback is invoked when a new machine function is
/// about to be emitted.
void ELFCodeEmitter::startFunction(MachineFunction &MF) {
  DEBUG(dbgs() << "processing function: "
        << MF.getFunction()->getName() << "\n");

  // Get the ELF Section that this function belongs in.
  ES = &EW.getTextSection(MF.getFunction());

  // Set the desired binary object to be used by the code emitters
  setBinaryObject(ES);

  // Get the function alignment in bytes
  unsigned Align = (1 << MF.getAlignment());

  // The function must start on its required alignment
  ES->emitAlignment(Align);

  // Update the section alignment if needed.
  ES->Align = std::max(ES->Align, Align);

  // Record the function start offset
  FnStartOff = ES->getCurrentPCOffset();

  // Emit constant pool and jump tables to their appropriate sections.
  // They need to be emitted before the function because in some targets
  // the later may reference JT or CP entry address.
  emitConstantPool(MF.getConstantPool());
  if (MF.getJumpTableInfo())
    emitJumpTables(MF.getJumpTableInfo());
}

/// finishFunction - This callback is invoked after the function is completely
/// finished.
bool ELFCodeEmitter::finishFunction(MachineFunction &MF) {
  // Add a symbol to represent the function.
  const Function *F = MF.getFunction();
  ELFSym *FnSym = ELFSym::getGV(F, EW.getGlobalELFBinding(F), ELF::STT_FUNC,
                                EW.getGlobalELFVisibility(F));
  FnSym->SectionIdx = ES->SectionIdx;
  FnSym->Size = ES->getCurrentPCOffset()-FnStartOff;
  EW.AddPendingGlobalSymbol(F, true);

  // Offset from start of Section
  FnSym->Value = FnStartOff;

  if (!F->hasPrivateLinkage())
    EW.SymbolList.push_back(FnSym);

  // Patch up Jump Table Section relocations to use the real MBBs offsets
  // now that the MBB label offsets inside the function are known.
  if (MF.getJumpTableInfo()) {
    ELFSection &JTSection = EW.getJumpTableSection();
    for (std::vector<MachineRelocation>::iterator MRI = JTRelocations.begin(),
         MRE = JTRelocations.end(); MRI != MRE; ++MRI) {
      MachineRelocation &MR = *MRI;
      uintptr_t MBBOffset = getMachineBasicBlockAddress(MR.getBasicBlock());
      MR.setResultPointer((void*)MBBOffset);
      MR.setConstantVal(ES->SectionIdx);
      JTSection.addRelocation(MR);
    }
  }

  // If we have emitted any relocations to function-specific objects such as
  // basic blocks, constant pools entries, or jump tables, record their
  // addresses now so that we can rewrite them with the correct addresses later
  for (unsigned i = 0, e = Relocations.size(); i != e; ++i) {
    MachineRelocation &MR = Relocations[i];
    intptr_t Addr;
    if (MR.isGlobalValue()) {
      EW.AddPendingGlobalSymbol(MR.getGlobalValue());
    } else if (MR.isExternalSymbol()) {
      EW.AddPendingExternalSymbol(MR.getExternalSymbol());
    } else if (MR.isBasicBlock()) {
      Addr = getMachineBasicBlockAddress(MR.getBasicBlock());
      MR.setConstantVal(ES->SectionIdx);
      MR.setResultPointer((void*)Addr);
    } else if (MR.isConstantPoolIndex()) {
      Addr = getConstantPoolEntryAddress(MR.getConstantPoolIndex());
      MR.setConstantVal(CPSections[MR.getConstantPoolIndex()]);
      MR.setResultPointer((void*)Addr);
    } else if (MR.isJumpTableIndex()) {
      ELFSection &JTSection = EW.getJumpTableSection();
      Addr = getJumpTableEntryAddress(MR.getJumpTableIndex());
      MR.setConstantVal(JTSection.SectionIdx);
      MR.setResultPointer((void*)Addr);
    } else {
      llvm_unreachable("Unhandled relocation type");
    }
    ES->addRelocation(MR);
  }

  // Clear per-function data structures.
  JTRelocations.clear();
  Relocations.clear();
  CPLocations.clear();
  CPSections.clear();
  JTLocations.clear();
  MBBLocations.clear();
  return false;
}

/// emitConstantPool - For each constant pool entry, figure out which section
/// the constant should live in and emit the constant
void ELFCodeEmitter::emitConstantPool(MachineConstantPool *MCP) {
  const std::vector<MachineConstantPoolEntry> &CP = MCP->getConstants();
  if (CP.empty()) return;

  // TODO: handle PIC codegen
  assert(TM.getRelocationModel() != Reloc::PIC_ &&
         "PIC codegen not yet handled for elf constant pools!");

  for (unsigned i = 0, e = CP.size(); i != e; ++i) {
    MachineConstantPoolEntry CPE = CP[i];

    // Record the constant pool location and the section index
    ELFSection &CstPool = EW.getConstantPoolSection(CPE);
    CPLocations.push_back(CstPool.size());
    CPSections.push_back(CstPool.SectionIdx);

    if (CPE.isMachineConstantPoolEntry())
      assert("CPE.isMachineConstantPoolEntry not supported yet");

    // Emit the constant to constant pool section
    EW.EmitGlobalConstant(CPE.Val.ConstVal, CstPool);
  }
}

/// emitJumpTables - Emit all the jump tables for a given jump table info
/// record to the appropriate section.
void ELFCodeEmitter::emitJumpTables(MachineJumpTableInfo *MJTI) {
  const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
  if (JT.empty()) return;

  // FIXME: handle PIC codegen
  assert(TM.getRelocationModel() != Reloc::PIC_ &&
         "PIC codegen not yet handled for elf jump tables!");

  const TargetELFWriterInfo *TEW = TM.getELFWriterInfo();
  unsigned EntrySize = 4; //MJTI->getEntrySize();

  // Get the ELF Section to emit the jump table
  ELFSection &JTSection = EW.getJumpTableSection();

  // For each JT, record its offset from the start of the section
  for (unsigned i = 0, e = JT.size(); i != e; ++i) {
    const std::vector<MachineBasicBlock*> &MBBs = JT[i].MBBs;

    // Record JT 'i' offset in the JT section
    JTLocations.push_back(JTSection.size());

    // Each MBB entry in the Jump table section has a relocation entry
    // against the current text section.
    for (unsigned mi = 0, me = MBBs.size(); mi != me; ++mi) {
      unsigned MachineRelTy = TEW->getAbsoluteLabelMachineRelTy();
      MachineRelocation MR =
        MachineRelocation::getBB(JTSection.size(), MachineRelTy, MBBs[mi]);

      // Add the relocation to the Jump Table section
      JTRelocations.push_back(MR);

      // Output placeholder for MBB in the JT section
      for (unsigned s=0; s < EntrySize; ++s)
        JTSection.emitByte(0);
    }
  }
}

} // end namespace llvm
