//===-- ELFWriter.cpp - Target-independent ELF Writer code ----------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the target-independent ELF writer.  This file writes out
// the ELF file in the following order:
//
//  #1. ELF Header
//  #2. '.text' section
//  #3. '.data' section
//  #4. '.bss' section  (conceptual position in file)
//  ...
//  #X. '.shstrtab' section
//  #Y. Section Table
//
// The entries in the section table are laid out as:
//  #0. Null entry [required]
//  #1. ".text" entry - the program code
//  #2. ".data" entry - global variables with initializers.     [ if needed ]
//  #3. ".bss" entry  - global variables without initializers.  [ if needed ]
//  ...
//  #N. ".shstrtab" entry - String table for the section names.
//
//===----------------------------------------------------------------------===//

#define DEBUG_TYPE "elfwriter"
#include "ELF.h"
#include "ELFWriter.h"
#include "ELFCodeEmitter.h"
#include "llvm/Constants.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/DerivedTypes.h"
#include "llvm/CodeGen/BinaryObject.h"
#include "llvm/CodeGen/MachineCodeEmitter.h"
#include "llvm/CodeGen/ObjectCodeEmitter.h"
#include "llvm/CodeGen/MachineCodeEmitter.h"
#include "llvm/CodeGen/MachineConstantPool.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCSectionELF.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/Target/Mangler.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetELFWriterInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetLoweringObjectFile.h"
#include "llvm/Target/TargetMachine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/ADT/SmallString.h"
using namespace llvm;

char ELFWriter::ID = 0;

//===----------------------------------------------------------------------===//
//                          ELFWriter Implementation
//===----------------------------------------------------------------------===//

ELFWriter::ELFWriter(raw_ostream &o, TargetMachine &tm)
  : MachineFunctionPass(&ID), O(o), TM(tm),
    OutContext(*new MCContext()),
    TLOF(TM.getTargetLowering()->getObjFileLowering()),
    is64Bit(TM.getTargetData()->getPointerSizeInBits() == 64),
    isLittleEndian(TM.getTargetData()->isLittleEndian()),
    ElfHdr(isLittleEndian, is64Bit) {

  MAI = TM.getMCAsmInfo();
  TEW = TM.getELFWriterInfo();

  // Create the object code emitter object for this target.
  ElfCE = new ELFCodeEmitter(*this);

  // Inital number of sections
  NumSections = 0;
}

ELFWriter::~ELFWriter() {
  delete ElfCE;
  delete &OutContext;

  while(!SymbolList.empty()) {
    delete SymbolList.back(); 
    SymbolList.pop_back();
  }

  while(!PrivateSyms.empty()) {
    delete PrivateSyms.back(); 
    PrivateSyms.pop_back();
  }

  while(!SectionList.empty()) {
    delete SectionList.back(); 
    SectionList.pop_back();
  }

  // Release the name mangler object.
  delete Mang; Mang = 0;
}

// doInitialization - Emit the file header and all of the global variables for
// the module to the ELF file.
bool ELFWriter::doInitialization(Module &M) {
  // Initialize TargetLoweringObjectFile.
  const_cast<TargetLoweringObjectFile&>(TLOF).Initialize(OutContext, TM);
  
  Mang = new Mangler(*MAI);

  // ELF Header
  // ----------
  // Fields e_shnum e_shstrndx are only known after all section have
  // been emitted. They locations in the ouput buffer are recorded so
  // to be patched up later.
  //
  // Note
  // ----
  // emitWord method behaves differently for ELF32 and ELF64, writing
  // 4 bytes in the former and 8 in the last for *_off and *_addr elf types

  ElfHdr.emitByte(0x7f); // e_ident[EI_MAG0]
  ElfHdr.emitByte('E');  // e_ident[EI_MAG1]
  ElfHdr.emitByte('L');  // e_ident[EI_MAG2]
  ElfHdr.emitByte('F');  // e_ident[EI_MAG3]

  ElfHdr.emitByte(TEW->getEIClass()); // e_ident[EI_CLASS]
  ElfHdr.emitByte(TEW->getEIData());  // e_ident[EI_DATA]
  ElfHdr.emitByte(EV_CURRENT);        // e_ident[EI_VERSION]
  ElfHdr.emitAlignment(16);           // e_ident[EI_NIDENT-EI_PAD]

  ElfHdr.emitWord16(ET_REL);             // e_type
  ElfHdr.emitWord16(TEW->getEMachine()); // e_machine = target
  ElfHdr.emitWord32(EV_CURRENT);         // e_version
  ElfHdr.emitWord(0);                    // e_entry, no entry point in .o file
  ElfHdr.emitWord(0);                    // e_phoff, no program header for .o
  ELFHdr_e_shoff_Offset = ElfHdr.size();
  ElfHdr.emitWord(0);                    // e_shoff = sec hdr table off in bytes
  ElfHdr.emitWord32(TEW->getEFlags());   // e_flags = whatever the target wants
  ElfHdr.emitWord16(TEW->getHdrSize());  // e_ehsize = ELF header size
  ElfHdr.emitWord16(0);                  // e_phentsize = prog header entry size
  ElfHdr.emitWord16(0);                  // e_phnum = # prog header entries = 0

  // e_shentsize = Section header entry size
  ElfHdr.emitWord16(TEW->getSHdrSize());

  // e_shnum     = # of section header ents
  ELFHdr_e_shnum_Offset = ElfHdr.size();
  ElfHdr.emitWord16(0); // Placeholder

  // e_shstrndx  = Section # of '.shstrtab'
  ELFHdr_e_shstrndx_Offset = ElfHdr.size();
  ElfHdr.emitWord16(0); // Placeholder

  // Add the null section, which is required to be first in the file.
  getNullSection();

  // The first entry in the symtab is the null symbol and the second
  // is a local symbol containing the module/file name
  SymbolList.push_back(new ELFSym());
  SymbolList.push_back(ELFSym::getFileSym());

  return false;
}

// AddPendingGlobalSymbol - Add a global to be processed and to
// the global symbol lookup, use a zero index because the table
// index will be determined later.
void ELFWriter::AddPendingGlobalSymbol(const GlobalValue *GV, 
                                       bool AddToLookup /* = false */) {
  PendingGlobals.insert(GV);
  if (AddToLookup) 
    GblSymLookup[GV] = 0;
}

// AddPendingExternalSymbol - Add the external to be processed
// and to the external symbol lookup, use a zero index because
// the symbol table index will be determined later.
void ELFWriter::AddPendingExternalSymbol(const char *External) {
  PendingExternals.insert(External);
  ExtSymLookup[External] = 0;
}

ELFSection &ELFWriter::getDataSection() {
  const MCSectionELF *Data = (const MCSectionELF *)TLOF.getDataSection();
  return getSection(Data->getSectionName(), Data->getType(), 
                    Data->getFlags(), 4);
}

ELFSection &ELFWriter::getBSSSection() {
  const MCSectionELF *BSS = (const MCSectionELF *)TLOF.getBSSSection();
  return getSection(BSS->getSectionName(), BSS->getType(), BSS->getFlags(), 4);
}

// getCtorSection - Get the static constructor section
ELFSection &ELFWriter::getCtorSection() {
  const MCSectionELF *Ctor = (const MCSectionELF *)TLOF.getStaticCtorSection();
  return getSection(Ctor->getSectionName(), Ctor->getType(), Ctor->getFlags()); 
}

// getDtorSection - Get the static destructor section
ELFSection &ELFWriter::getDtorSection() {
  const MCSectionELF *Dtor = (const MCSectionELF *)TLOF.getStaticDtorSection();
  return getSection(Dtor->getSectionName(), Dtor->getType(), Dtor->getFlags());
}

// getTextSection - Get the text section for the specified function
ELFSection &ELFWriter::getTextSection(Function *F) {
  const MCSectionELF *Text = 
    (const MCSectionELF *)TLOF.SectionForGlobal(F, Mang, TM);
  return getSection(Text->getSectionName(), Text->getType(), Text->getFlags());
}

// getJumpTableSection - Get a read only section for constants when 
// emitting jump tables. TODO: add PIC support
ELFSection &ELFWriter::getJumpTableSection() {
  const MCSectionELF *JT = 
    (const MCSectionELF *)TLOF.getSectionForConstant(SectionKind::getReadOnly());
  return getSection(JT->getSectionName(), JT->getType(), JT->getFlags(),
                    TM.getTargetData()->getPointerABIAlignment());
}

// getConstantPoolSection - Get a constant pool section based on the machine 
// constant pool entry type and relocation info.
ELFSection &ELFWriter::getConstantPoolSection(MachineConstantPoolEntry &CPE) {
  SectionKind Kind;
  switch (CPE.getRelocationInfo()) {
  default: llvm_unreachable("Unknown section kind");
  case 2: Kind = SectionKind::getReadOnlyWithRel(); break;
  case 1:
    Kind = SectionKind::getReadOnlyWithRelLocal();
    break;
  case 0:
    switch (TM.getTargetData()->getTypeAllocSize(CPE.getType())) {
    case 4:  Kind = SectionKind::getMergeableConst4(); break;
    case 8:  Kind = SectionKind::getMergeableConst8(); break;
    case 16: Kind = SectionKind::getMergeableConst16(); break;
    default: Kind = SectionKind::getMergeableConst(); break;
    }
  }

  const MCSectionELF *CPSect = 
    (const MCSectionELF *)TLOF.getSectionForConstant(Kind);
  return getSection(CPSect->getSectionName(), CPSect->getType(), 
                    CPSect->getFlags(), CPE.getAlignment());
}

// getRelocSection - Return the relocation section of section 'S'. 'RelA' 
// is true if the relocation section contains entries with addends.
ELFSection &ELFWriter::getRelocSection(ELFSection &S) {
  unsigned SectionType = TEW->hasRelocationAddend() ?
                ELFSection::SHT_RELA : ELFSection::SHT_REL;

  std::string SectionName(".rel");
  if (TEW->hasRelocationAddend())
    SectionName.append("a");
  SectionName.append(S.getName());

  return getSection(SectionName, SectionType, 0, TEW->getPrefELFAlignment());
}

// getGlobalELFVisibility - Returns the ELF specific visibility type
unsigned ELFWriter::getGlobalELFVisibility(const GlobalValue *GV) {
  switch (GV->getVisibility()) {
  default:
    llvm_unreachable("unknown visibility type");
  case GlobalValue::DefaultVisibility:
    return ELFSym::STV_DEFAULT;
  case GlobalValue::HiddenVisibility:
    return ELFSym::STV_HIDDEN;
  case GlobalValue::ProtectedVisibility:
    return ELFSym::STV_PROTECTED;
  }
  return 0;
}

// getGlobalELFBinding - Returns the ELF specific binding type
unsigned ELFWriter::getGlobalELFBinding(const GlobalValue *GV) {
  if (GV->hasInternalLinkage())
    return ELFSym::STB_LOCAL;

  if (GV->isWeakForLinker() && !GV->hasCommonLinkage())
    return ELFSym::STB_WEAK;

  return ELFSym::STB_GLOBAL;
}

// getGlobalELFType - Returns the ELF specific type for a global
unsigned ELFWriter::getGlobalELFType(const GlobalValue *GV) {
  if (GV->isDeclaration())
    return ELFSym::STT_NOTYPE;

  if (isa<Function>(GV))
    return ELFSym::STT_FUNC;

  return ELFSym::STT_OBJECT;
}

// IsELFUndefSym - True if the global value must be marked as a symbol
// which points to a SHN_UNDEF section. This means that the symbol has
// no definition on the module.
static bool IsELFUndefSym(const GlobalValue *GV) {
  return GV->isDeclaration() || (isa<Function>(GV));
}

// AddToSymbolList - Update the symbol lookup and If the symbol is 
// private add it to PrivateSyms list, otherwise to SymbolList. 
void ELFWriter::AddToSymbolList(ELFSym *GblSym) {
  assert(GblSym->isGlobalValue() && "Symbol must be a global value");

  const GlobalValue *GV = GblSym->getGlobalValue(); 
  if (GV->hasPrivateLinkage()) {
    // For a private symbols, keep track of the index inside 
    // the private list since it will never go to the symbol 
    // table and won't be patched up later.
    PrivateSyms.push_back(GblSym);
    GblSymLookup[GV] = PrivateSyms.size()-1;
  } else {
    // Non private symbol are left with zero indices until 
    // they are patched up during the symbol table emition 
    // (where the indicies are created).
    SymbolList.push_back(GblSym);
    GblSymLookup[GV] = 0;
  }
}

// EmitGlobal - Choose the right section for global and emit it
void ELFWriter::EmitGlobal(const GlobalValue *GV) {

  // Check if the referenced symbol is already emitted
  if (GblSymLookup.find(GV) != GblSymLookup.end())
    return;

  // Handle ELF Bind, Visibility and Type for the current symbol
  unsigned SymBind = getGlobalELFBinding(GV);
  unsigned SymType = getGlobalELFType(GV);
  bool IsUndefSym = IsELFUndefSym(GV);

  ELFSym *GblSym = IsUndefSym ? ELFSym::getUndefGV(GV, SymBind)
    : ELFSym::getGV(GV, SymBind, SymType, getGlobalELFVisibility(GV));

  if (!IsUndefSym) {
    assert(isa<GlobalVariable>(GV) && "GV not a global variable!");
    const GlobalVariable *GVar = dyn_cast<GlobalVariable>(GV);

    // Handle special llvm globals
    if (EmitSpecialLLVMGlobal(GVar))
      return;

    // Get the ELF section where this global belongs from TLOF
    const MCSectionELF *S = 
      (const MCSectionELF *)TLOF.SectionForGlobal(GV, Mang, TM);
    ELFSection &ES = 
      getSection(S->getSectionName(), S->getType(), S->getFlags());
    SectionKind Kind = S->getKind();

    // The symbol align should update the section alignment if needed
    const TargetData *TD = TM.getTargetData();
    unsigned Align = TD->getPreferredAlignment(GVar);
    unsigned Size = TD->getTypeAllocSize(GVar->getInitializer()->getType());
    GblSym->Size = Size;

    if (S->HasCommonSymbols()) { // Symbol must go to a common section
      GblSym->SectionIdx = ELFSection::SHN_COMMON;

      // A new linkonce section is created for each global in the
      // common section, the default alignment is 1 and the symbol
      // value contains its alignment.
      ES.Align = 1;
      GblSym->Value = Align;

    } else if (Kind.isBSS() || Kind.isThreadBSS()) { // Symbol goes to BSS.
      GblSym->SectionIdx = ES.SectionIdx;

      // Update the size with alignment and the next object can
      // start in the right offset in the section
      if (Align) ES.Size = (ES.Size + Align-1) & ~(Align-1);
      ES.Align = std::max(ES.Align, Align);

      // GblSym->Value should contain the virtual offset inside the section.
      // Virtual because the BSS space is not allocated on ELF objects
      GblSym->Value = ES.Size;
      ES.Size += Size;

    } else { // The symbol must go to some kind of data section
      GblSym->SectionIdx = ES.SectionIdx;

      // GblSym->Value should contain the symbol offset inside the section,
      // and all symbols should start on their required alignment boundary
      ES.Align = std::max(ES.Align, Align);
      ES.emitAlignment(Align);
      GblSym->Value = ES.size();

      // Emit the global to the data section 'ES'
      EmitGlobalConstant(GVar->getInitializer(), ES);
    }
  }

  AddToSymbolList(GblSym);
}

void ELFWriter::EmitGlobalConstantStruct(const ConstantStruct *CVS,
                                         ELFSection &GblS) {

  // Print the fields in successive locations. Pad to align if needed!
  const TargetData *TD = TM.getTargetData();
  unsigned Size = TD->getTypeAllocSize(CVS->getType());
  const StructLayout *cvsLayout = TD->getStructLayout(CVS->getType());
  uint64_t sizeSoFar = 0;
  for (unsigned i = 0, e = CVS->getNumOperands(); i != e; ++i) {
    const Constant* field = CVS->getOperand(i);

    // Check if padding is needed and insert one or more 0s.
    uint64_t fieldSize = TD->getTypeAllocSize(field->getType());
    uint64_t padSize = ((i == e-1 ? Size : cvsLayout->getElementOffset(i+1))
                        - cvsLayout->getElementOffset(i)) - fieldSize;
    sizeSoFar += fieldSize + padSize;

    // Now print the actual field value.
    EmitGlobalConstant(field, GblS);

    // Insert padding - this may include padding to increase the size of the
    // current field up to the ABI size (if the struct is not packed) as well
    // as padding to ensure that the next field starts at the right offset.
    GblS.emitZeros(padSize);
  }
  assert(sizeSoFar == cvsLayout->getSizeInBytes() &&
         "Layout of constant struct may be incorrect!");
}

void ELFWriter::EmitGlobalConstant(const Constant *CV, ELFSection &GblS) {
  const TargetData *TD = TM.getTargetData();
  unsigned Size = TD->getTypeAllocSize(CV->getType());

  if (const ConstantArray *CVA = dyn_cast<ConstantArray>(CV)) {
    for (unsigned i = 0, e = CVA->getNumOperands(); i != e; ++i)
      EmitGlobalConstant(CVA->getOperand(i), GblS);
    return;
  } else if (isa<ConstantAggregateZero>(CV)) {
    GblS.emitZeros(Size);
    return;
  } else if (const ConstantStruct *CVS = dyn_cast<ConstantStruct>(CV)) {
    EmitGlobalConstantStruct(CVS, GblS);
    return;
  } else if (const ConstantFP *CFP = dyn_cast<ConstantFP>(CV)) {
    APInt Val = CFP->getValueAPF().bitcastToAPInt();
    if (CFP->getType()->isDoubleTy())
      GblS.emitWord64(Val.getZExtValue());
    else if (CFP->getType()->isFloatTy())
      GblS.emitWord32(Val.getZExtValue());
    else if (CFP->getType()->isX86_FP80Ty()) {
      unsigned PadSize = TD->getTypeAllocSize(CFP->getType())-
                         TD->getTypeStoreSize(CFP->getType());
      GblS.emitWordFP80(Val.getRawData(), PadSize);
    } else if (CFP->getType()->isPPC_FP128Ty())
      llvm_unreachable("PPC_FP128Ty global emission not implemented");
    return;
  } else if (const ConstantInt *CI = dyn_cast<ConstantInt>(CV)) {
    if (Size == 1)
      GblS.emitByte(CI->getZExtValue());
    else if (Size == 2) 
      GblS.emitWord16(CI->getZExtValue());
    else if (Size == 4)
      GblS.emitWord32(CI->getZExtValue());
    else 
      EmitGlobalConstantLargeInt(CI, GblS);
    return;
  } else if (const ConstantVector *CP = dyn_cast<ConstantVector>(CV)) {
    const VectorType *PTy = CP->getType();
    for (unsigned I = 0, E = PTy->getNumElements(); I < E; ++I)
      EmitGlobalConstant(CP->getOperand(I), GblS);
    return;
  } else if (const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV)) {
    // Resolve a constant expression which returns a (Constant, Offset)
    // pair. If 'Res.first' is a GlobalValue, emit a relocation with 
    // the offset 'Res.second', otherwise emit a global constant like
    // it is always done for not contant expression types.
    CstExprResTy Res = ResolveConstantExpr(CE);
    const Constant *Op = Res.first;

    if (isa<GlobalValue>(Op))
      EmitGlobalDataRelocation(cast<const GlobalValue>(Op), 
                               TD->getTypeAllocSize(Op->getType()), 
                               GblS, Res.second);
    else
      EmitGlobalConstant(Op, GblS);

    return;
  } else if (CV->getType()->getTypeID() == Type::PointerTyID) {
    // Fill the data entry with zeros or emit a relocation entry
    if (isa<ConstantPointerNull>(CV))
      GblS.emitZeros(Size);
    else 
      EmitGlobalDataRelocation(cast<const GlobalValue>(CV), 
                               Size, GblS);
    return;
  } else if (const GlobalValue *GV = dyn_cast<GlobalValue>(CV)) {
    // This is a constant address for a global variable or function and
    // therefore must be referenced using a relocation entry.
    EmitGlobalDataRelocation(GV, Size, GblS);
    return;
  }

  std::string msg;
  raw_string_ostream ErrorMsg(msg);
  ErrorMsg << "Constant unimp for type: " << *CV->getType();
  llvm_report_error(ErrorMsg.str());
}

// ResolveConstantExpr - Resolve the constant expression until it stop
// yielding other constant expressions.
CstExprResTy ELFWriter::ResolveConstantExpr(const Constant *CV) {
  const TargetData *TD = TM.getTargetData();
  
  // There ins't constant expression inside others anymore
  if (!isa<ConstantExpr>(CV))
    return std::make_pair(CV, 0);

  const ConstantExpr *CE = dyn_cast<ConstantExpr>(CV);
  switch (CE->getOpcode()) {
  case Instruction::BitCast:
    return ResolveConstantExpr(CE->getOperand(0));
  
  case Instruction::GetElementPtr: {
    const Constant *ptrVal = CE->getOperand(0);
    SmallVector<Value*, 8> idxVec(CE->op_begin()+1, CE->op_end());
    int64_t Offset = TD->getIndexedOffset(ptrVal->getType(), &idxVec[0],
                                          idxVec.size());
    return std::make_pair(ptrVal, Offset);
  }
  case Instruction::IntToPtr: {
    Constant *Op = CE->getOperand(0);
    Op = ConstantExpr::getIntegerCast(Op, TD->getIntPtrType(CV->getContext()),
                                      false/*ZExt*/);
    return ResolveConstantExpr(Op);
  }
  case Instruction::PtrToInt: {
    Constant *Op = CE->getOperand(0);
    const Type *Ty = CE->getType();

    // We can emit the pointer value into this slot if the slot is an
    // integer slot greater or equal to the size of the pointer.
    if (TD->getTypeAllocSize(Ty) == TD->getTypeAllocSize(Op->getType()))
      return ResolveConstantExpr(Op);

    llvm_unreachable("Integer size less then pointer size");
  }
  case Instruction::Add:
  case Instruction::Sub: {
    // Only handle cases where there's a constant expression with GlobalValue
    // as first operand and ConstantInt as second, which are the cases we can
    // solve direclty using a relocation entry. GlobalValue=Op0, CstInt=Op1
    // 1)  Instruction::Add  => (global) + CstInt
    // 2)  Instruction::Sub  => (global) + -CstInt
    const Constant *Op0 = CE->getOperand(0); 
    const Constant *Op1 = CE->getOperand(1); 
    assert(isa<ConstantInt>(Op1) && "Op1 must be a ConstantInt");

    CstExprResTy Res = ResolveConstantExpr(Op0);
    assert(isa<GlobalValue>(Res.first) && "Op0 must be a GlobalValue");

    const APInt &RHS = cast<ConstantInt>(Op1)->getValue();
    switch (CE->getOpcode()) {
    case Instruction::Add: 
      return std::make_pair(Res.first, RHS.getSExtValue());
    case Instruction::Sub:
      return std::make_pair(Res.first, (-RHS).getSExtValue());
    }
  }
  }

  std::string msg(CE->getOpcodeName());
  raw_string_ostream ErrorMsg(msg);
  ErrorMsg << ": Unsupported ConstantExpr type";
  llvm_report_error(ErrorMsg.str());

  return std::make_pair(CV, 0); // silence warning
}

void ELFWriter::EmitGlobalDataRelocation(const GlobalValue *GV, unsigned Size,
                                         ELFSection &GblS, int64_t Offset) {
  // Create the relocation entry for the global value
  MachineRelocation MR =
    MachineRelocation::getGV(GblS.getCurrentPCOffset(),
                             TEW->getAbsoluteLabelMachineRelTy(),
                             const_cast<GlobalValue*>(GV),
                             Offset);

  // Fill the data entry with zeros
  GblS.emitZeros(Size);

  // Add the relocation entry for the current data section
  GblS.addRelocation(MR);
}

void ELFWriter::EmitGlobalConstantLargeInt(const ConstantInt *CI, 
                                           ELFSection &S) {
  const TargetData *TD = TM.getTargetData();
  unsigned BitWidth = CI->getBitWidth();
  assert(isPowerOf2_32(BitWidth) &&
         "Non-power-of-2-sized integers not handled!");

  const uint64_t *RawData = CI->getValue().getRawData();
  uint64_t Val = 0;
  for (unsigned i = 0, e = BitWidth / 64; i != e; ++i) {
    Val = (TD->isBigEndian()) ? RawData[e - i - 1] : RawData[i];
    S.emitWord64(Val);
  }
}

/// EmitSpecialLLVMGlobal - Check to see if the specified global is a
/// special global used by LLVM.  If so, emit it and return true, otherwise
/// do nothing and return false.
bool ELFWriter::EmitSpecialLLVMGlobal(const GlobalVariable *GV) {
  if (GV->getName() == "llvm.used")
    llvm_unreachable("not implemented yet");

  // Ignore debug and non-emitted data.  This handles llvm.compiler.used.
  if (GV->getSection() == "llvm.metadata" ||
      GV->hasAvailableExternallyLinkage())
    return true;
  
  if (!GV->hasAppendingLinkage()) return false;

  assert(GV->hasInitializer() && "Not a special LLVM global!");
  
  const TargetData *TD = TM.getTargetData();
  unsigned Align = TD->getPointerPrefAlignment();
  if (GV->getName() == "llvm.global_ctors") {
    ELFSection &Ctor = getCtorSection();
    Ctor.emitAlignment(Align);
    EmitXXStructorList(GV->getInitializer(), Ctor);
    return true;
  } 
  
  if (GV->getName() == "llvm.global_dtors") {
    ELFSection &Dtor = getDtorSection();
    Dtor.emitAlignment(Align);
    EmitXXStructorList(GV->getInitializer(), Dtor);
    return true;
  }
  
  return false;
}

/// EmitXXStructorList - Emit the ctor or dtor list.  This just emits out the 
/// function pointers, ignoring the init priority.
void ELFWriter::EmitXXStructorList(Constant *List, ELFSection &Xtor) {
  // Should be an array of '{ int, void ()* }' structs.  The first value is the
  // init priority, which we ignore.
  if (!isa<ConstantArray>(List)) return;
  ConstantArray *InitList = cast<ConstantArray>(List);
  for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i)
    if (ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i))){
      if (CS->getNumOperands() != 2) return;  // Not array of 2-element structs.

      if (CS->getOperand(1)->isNullValue())
        return;  // Found a null terminator, exit printing.
      // Emit the function pointer.
      EmitGlobalConstant(CS->getOperand(1), Xtor);
    }
}

bool ELFWriter::runOnMachineFunction(MachineFunction &MF) {
  // Nothing to do here, this is all done through the ElfCE object above.
  return false;
}

/// doFinalization - Now that the module has been completely processed, emit
/// the ELF file to 'O'.
bool ELFWriter::doFinalization(Module &M) {
  // Emit .data section placeholder
  getDataSection();

  // Emit .bss section placeholder
  getBSSSection();

  // Build and emit data, bss and "common" sections.
  for (Module::global_iterator I = M.global_begin(), E = M.global_end();
       I != E; ++I)
    EmitGlobal(I);

  // Emit all pending globals
  for (PendingGblsIter I = PendingGlobals.begin(), E = PendingGlobals.end();
       I != E; ++I)
    EmitGlobal(*I);

  // Emit all pending externals
  for (PendingExtsIter I = PendingExternals.begin(), E = PendingExternals.end();
       I != E; ++I)
    SymbolList.push_back(ELFSym::getExtSym(*I));

  // Emit a symbol for each section created until now, skip null section
  for (unsigned i = 1, e = SectionList.size(); i < e; ++i) {
    ELFSection &ES = *SectionList[i];
    ELFSym *SectionSym = ELFSym::getSectionSym();
    SectionSym->SectionIdx = ES.SectionIdx;
    SymbolList.push_back(SectionSym);
    ES.Sym = SymbolList.back();
  }

  // Emit string table
  EmitStringTable(M.getModuleIdentifier());

  // Emit the symbol table now, if non-empty.
  EmitSymbolTable();

  // Emit the relocation sections.
  EmitRelocations();

  // Emit the sections string table.
  EmitSectionTableStringTable();

  // Dump the sections and section table to the .o file.
  OutputSectionsAndSectionTable();

  return false;
}

// RelocateField - Patch relocatable field with 'Offset' in 'BO'
// using a 'Value' of known 'Size'
void ELFWriter::RelocateField(BinaryObject &BO, uint32_t Offset,
                              int64_t Value, unsigned Size) {
  if (Size == 32)
    BO.fixWord32(Value, Offset);
  else if (Size == 64)
    BO.fixWord64(Value, Offset);
  else
    llvm_unreachable("don't know howto patch relocatable field");
}

/// EmitRelocations - Emit relocations
void ELFWriter::EmitRelocations() {

  // True if the target uses the relocation entry to hold the addend,
  // otherwise the addend is written directly to the relocatable field.
  bool HasRelA = TEW->hasRelocationAddend();

  // Create Relocation sections for each section which needs it.
  for (unsigned i=0, e=SectionList.size(); i != e; ++i) {
    ELFSection &S = *SectionList[i];

    // This section does not have relocations
    if (!S.hasRelocations()) continue;
    ELFSection &RelSec = getRelocSection(S);

    // 'Link' - Section hdr idx of the associated symbol table
    // 'Info' - Section hdr idx of the section to which the relocation applies
    ELFSection &SymTab = getSymbolTableSection();
    RelSec.Link = SymTab.SectionIdx;
    RelSec.Info = S.SectionIdx;
    RelSec.EntSize = TEW->getRelocationEntrySize();

    // Get the relocations from Section
    std::vector<MachineRelocation> Relos = S.getRelocations();
    for (std::vector<MachineRelocation>::iterator MRI = Relos.begin(),
         MRE = Relos.end(); MRI != MRE; ++MRI) {
      MachineRelocation &MR = *MRI;

      // Relocatable field offset from the section start
      unsigned RelOffset = MR.getMachineCodeOffset();

      // Symbol index in the symbol table
      unsigned SymIdx = 0;

      // Target specific relocation field type and size
      unsigned RelType = TEW->getRelocationType(MR.getRelocationType());
      unsigned RelTySize = TEW->getRelocationTySize(RelType);
      int64_t Addend = 0;

      // There are several machine relocations types, and each one of
      // them needs a different approach to retrieve the symbol table index.
      if (MR.isGlobalValue()) {
        const GlobalValue *G = MR.getGlobalValue();
        int64_t GlobalOffset = MR.getConstantVal();
        SymIdx = GblSymLookup[G];
        if (G->hasPrivateLinkage()) {
          // If the target uses a section offset in the relocation:
          // SymIdx + Addend = section sym for global + section offset
          unsigned SectionIdx = PrivateSyms[SymIdx]->SectionIdx;
          Addend = PrivateSyms[SymIdx]->Value + GlobalOffset;
          SymIdx = SectionList[SectionIdx]->getSymbolTableIndex();
        } else {
          Addend = TEW->getDefaultAddendForRelTy(RelType, GlobalOffset);
        }
      } else if (MR.isExternalSymbol()) {
        const char *ExtSym = MR.getExternalSymbol();
        SymIdx = ExtSymLookup[ExtSym];
        Addend = TEW->getDefaultAddendForRelTy(RelType);
      } else {
        // Get the symbol index for the section symbol
        unsigned SectionIdx = MR.getConstantVal();
        SymIdx = SectionList[SectionIdx]->getSymbolTableIndex();

        // The symbol offset inside the section
        int64_t SymOffset = (int64_t)MR.getResultPointer();

        // For pc relative relocations where symbols are defined in the same
        // section they are referenced, ignore the relocation entry and patch
        // the relocatable field with the symbol offset directly.
        if (S.SectionIdx == SectionIdx && TEW->isPCRelativeRel(RelType)) {
          int64_t Value = TEW->computeRelocation(SymOffset, RelOffset, RelType);
          RelocateField(S, RelOffset, Value, RelTySize);
          continue;
        }

        Addend = TEW->getDefaultAddendForRelTy(RelType, SymOffset);
      }

      // The target without addend on the relocation symbol must be
      // patched in the relocation place itself to contain the addend
      // otherwise write zeros to make sure there is no garbage there
      RelocateField(S, RelOffset, HasRelA ? 0 : Addend, RelTySize);

      // Get the relocation entry and emit to the relocation section
      ELFRelocation Rel(RelOffset, SymIdx, RelType, HasRelA, Addend);
      EmitRelocation(RelSec, Rel, HasRelA);
    }
  }
}

/// EmitRelocation - Write relocation 'Rel' to the relocation section 'Rel'
void ELFWriter::EmitRelocation(BinaryObject &RelSec, ELFRelocation &Rel,
                               bool HasRelA) {
  RelSec.emitWord(Rel.getOffset());
  RelSec.emitWord(Rel.getInfo(is64Bit));
  if (HasRelA)
    RelSec.emitWord(Rel.getAddend());
}

/// EmitSymbol - Write symbol 'Sym' to the symbol table 'SymbolTable'
void ELFWriter::EmitSymbol(BinaryObject &SymbolTable, ELFSym &Sym) {
  if (is64Bit) {
    SymbolTable.emitWord32(Sym.NameIdx);
    SymbolTable.emitByte(Sym.Info);
    SymbolTable.emitByte(Sym.Other);
    SymbolTable.emitWord16(Sym.SectionIdx);
    SymbolTable.emitWord64(Sym.Value);
    SymbolTable.emitWord64(Sym.Size);
  } else {
    SymbolTable.emitWord32(Sym.NameIdx);
    SymbolTable.emitWord32(Sym.Value);
    SymbolTable.emitWord32(Sym.Size);
    SymbolTable.emitByte(Sym.Info);
    SymbolTable.emitByte(Sym.Other);
    SymbolTable.emitWord16(Sym.SectionIdx);
  }
}

/// EmitSectionHeader - Write section 'Section' header in 'SHdrTab'
/// Section Header Table
void ELFWriter::EmitSectionHeader(BinaryObject &SHdrTab,
                                  const ELFSection &SHdr) {
  SHdrTab.emitWord32(SHdr.NameIdx);
  SHdrTab.emitWord32(SHdr.Type);
  if (is64Bit) {
    SHdrTab.emitWord64(SHdr.Flags);
    SHdrTab.emitWord(SHdr.Addr);
    SHdrTab.emitWord(SHdr.Offset);
    SHdrTab.emitWord64(SHdr.Size);
    SHdrTab.emitWord32(SHdr.Link);
    SHdrTab.emitWord32(SHdr.Info);
    SHdrTab.emitWord64(SHdr.Align);
    SHdrTab.emitWord64(SHdr.EntSize);
  } else {
    SHdrTab.emitWord32(SHdr.Flags);
    SHdrTab.emitWord(SHdr.Addr);
    SHdrTab.emitWord(SHdr.Offset);
    SHdrTab.emitWord32(SHdr.Size);
    SHdrTab.emitWord32(SHdr.Link);
    SHdrTab.emitWord32(SHdr.Info);
    SHdrTab.emitWord32(SHdr.Align);
    SHdrTab.emitWord32(SHdr.EntSize);
  }
}

/// EmitStringTable - If the current symbol table is non-empty, emit the string
/// table for it
void ELFWriter::EmitStringTable(const std::string &ModuleName) {
  if (!SymbolList.size()) return;  // Empty symbol table.
  ELFSection &StrTab = getStringTableSection();

  // Set the zero'th symbol to a null byte, as required.
  StrTab.emitByte(0);

  // Walk on the symbol list and write symbol names into the string table.
  unsigned Index = 1;
  for (ELFSymIter I=SymbolList.begin(), E=SymbolList.end(); I != E; ++I) {
    ELFSym &Sym = *(*I);

    std::string Name;
    if (Sym.isGlobalValue()) {
      SmallString<40> NameStr;
      Mang->getNameWithPrefix(NameStr, Sym.getGlobalValue(), false);
      Name.append(NameStr.begin(), NameStr.end());
    } else if (Sym.isExternalSym())
      Name.append(Sym.getExternalSymbol());
    else if (Sym.isFileType())
      Name.append(ModuleName);

    if (Name.empty()) {
      Sym.NameIdx = 0;
    } else {
      Sym.NameIdx = Index;
      StrTab.emitString(Name);

      // Keep track of the number of bytes emitted to this section.
      Index += Name.size()+1;
    }
  }
  assert(Index == StrTab.size());
  StrTab.Size = Index;
}

// SortSymbols - On the symbol table local symbols must come before
// all other symbols with non-local bindings. The return value is
// the position of the first non local symbol.
unsigned ELFWriter::SortSymbols() {
  unsigned FirstNonLocalSymbol;
  std::vector<ELFSym*> LocalSyms, OtherSyms;

  for (ELFSymIter I=SymbolList.begin(), E=SymbolList.end(); I != E; ++I) {
    if ((*I)->isLocalBind())
      LocalSyms.push_back(*I);
    else
      OtherSyms.push_back(*I);
  }
  SymbolList.clear();
  FirstNonLocalSymbol = LocalSyms.size();

  for (unsigned i = 0; i < FirstNonLocalSymbol; ++i)
    SymbolList.push_back(LocalSyms[i]);

  for (ELFSymIter I=OtherSyms.begin(), E=OtherSyms.end(); I != E; ++I)
    SymbolList.push_back(*I);

  LocalSyms.clear();
  OtherSyms.clear();

  return FirstNonLocalSymbol;
}

/// EmitSymbolTable - Emit the symbol table itself.
void ELFWriter::EmitSymbolTable() {
  if (!SymbolList.size()) return;  // Empty symbol table.

  // Now that we have emitted the string table and know the offset into the
  // string table of each symbol, emit the symbol table itself.
  ELFSection &SymTab = getSymbolTableSection();
  SymTab.Align = TEW->getPrefELFAlignment();

  // Section Index of .strtab.
  SymTab.Link = getStringTableSection().SectionIdx;

  // Size of each symtab entry.
  SymTab.EntSize = TEW->getSymTabEntrySize();

  // Reorder the symbol table with local symbols first!
  unsigned FirstNonLocalSymbol = SortSymbols();

  // Emit all the symbols to the symbol table.
  for (unsigned i = 0, e = SymbolList.size(); i < e; ++i) {
    ELFSym &Sym = *SymbolList[i];

    // Emit symbol to the symbol table
    EmitSymbol(SymTab, Sym);

    // Record the symbol table index for each symbol
    if (Sym.isGlobalValue())
      GblSymLookup[Sym.getGlobalValue()] = i;
    else if (Sym.isExternalSym())
      ExtSymLookup[Sym.getExternalSymbol()] = i;

    // Keep track on the symbol index into the symbol table
    Sym.SymTabIdx = i;
  }

  // One greater than the symbol table index of the last local symbol
  SymTab.Info = FirstNonLocalSymbol;
  SymTab.Size = SymTab.size();
}

/// EmitSectionTableStringTable - This method adds and emits a section for the
/// ELF Section Table string table: the string table that holds all of the
/// section names.
void ELFWriter::EmitSectionTableStringTable() {
  // First step: add the section for the string table to the list of sections:
  ELFSection &SHStrTab = getSectionHeaderStringTableSection();

  // Now that we know which section number is the .shstrtab section, update the
  // e_shstrndx entry in the ELF header.
  ElfHdr.fixWord16(SHStrTab.SectionIdx, ELFHdr_e_shstrndx_Offset);

  // Set the NameIdx of each section in the string table and emit the bytes for
  // the string table.
  unsigned Index = 0;

  for (ELFSectionIter I=SectionList.begin(), E=SectionList.end(); I != E; ++I) {
    ELFSection &S = *(*I);
    // Set the index into the table.  Note if we have lots of entries with
    // common suffixes, we could memoize them here if we cared.
    S.NameIdx = Index;
    SHStrTab.emitString(S.getName());

    // Keep track of the number of bytes emitted to this section.
    Index += S.getName().size()+1;
  }

  // Set the size of .shstrtab now that we know what it is.
  assert(Index == SHStrTab.size());
  SHStrTab.Size = Index;
}

/// OutputSectionsAndSectionTable - Now that we have constructed the file header
/// and all of the sections, emit these to the ostream destination and emit the
/// SectionTable.
void ELFWriter::OutputSectionsAndSectionTable() {
  // Pass #1: Compute the file offset for each section.
  size_t FileOff = ElfHdr.size();   // File header first.

  // Adjust alignment of all section if needed, skip the null section.
  for (unsigned i=1, e=SectionList.size(); i < e; ++i) {
    ELFSection &ES = *SectionList[i];
    if (!ES.size()) {
      ES.Offset = FileOff;
      continue;
    }

    // Update Section size
    if (!ES.Size)
      ES.Size = ES.size();

    // Align FileOff to whatever the alignment restrictions of the section are.
    if (ES.Align)
      FileOff = (FileOff+ES.Align-1) & ~(ES.Align-1);

    ES.Offset = FileOff;
    FileOff += ES.Size;
  }

  // Align Section Header.
  unsigned TableAlign = TEW->getPrefELFAlignment();
  FileOff = (FileOff+TableAlign-1) & ~(TableAlign-1);

  // Now that we know where all of the sections will be emitted, set the e_shnum
  // entry in the ELF header.
  ElfHdr.fixWord16(NumSections, ELFHdr_e_shnum_Offset);

  // Now that we know the offset in the file of the section table, update the
  // e_shoff address in the ELF header.
  ElfHdr.fixWord(FileOff, ELFHdr_e_shoff_Offset);

  // Now that we know all of the data in the file header, emit it and all of the
  // sections!
  O.write((char *)&ElfHdr.getData()[0], ElfHdr.size());
  FileOff = ElfHdr.size();

  // Section Header Table blob
  BinaryObject SHdrTable(isLittleEndian, is64Bit);

  // Emit all of sections to the file and build the section header table.
  for (ELFSectionIter I=SectionList.begin(), E=SectionList.end(); I != E; ++I) {
    ELFSection &S = *(*I);
    DEBUG(dbgs() << "SectionIdx: " << S.SectionIdx << ", Name: " << S.getName()
                 << ", Size: " << S.Size << ", Offset: " << S.Offset
                 << ", SectionData Size: " << S.size() << "\n");

    // Align FileOff to whatever the alignment restrictions of the section are.
    if (S.size()) {
      if (S.Align)  {
        for (size_t NewFileOff = (FileOff+S.Align-1) & ~(S.Align-1);
             FileOff != NewFileOff; ++FileOff)
          O << (char)0xAB;
      }
      O.write((char *)&S.getData()[0], S.Size);
      FileOff += S.Size;
    }

    EmitSectionHeader(SHdrTable, S);
  }

  // Align output for the section table.
  for (size_t NewFileOff = (FileOff+TableAlign-1) & ~(TableAlign-1);
       FileOff != NewFileOff; ++FileOff)
    O << (char)0xAB;

  // Emit the section table itself.
  O.write((char *)&SHdrTable.getData()[0], SHdrTable.size());
}
