15460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===- MipsLDBackend.cpp --------------------------------------------------===//
25460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
35460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//                     The MCLinker Project
45460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
55460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// This file is distributed under the University of Illinois Open Source
65460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// License. See LICENSE.TXT for details.
75460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//
85460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
9cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include "Mips.h"
10d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include "MipsGNUInfo.h"
11cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include "MipsELFDynamic.h"
1287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include "MipsLA25Stub.h"
13cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao#include "MipsLDBackend.h"
14d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao#include "MipsRelocator.h"
15cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/IRBuilder.h"
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerConfig.h"
1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Module.h"
19cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/Fragment/AlignFragment.h"
2037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/FillFragment.h"
2137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/BranchIslandFactory.h"
2237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDContext.h"
2337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/StubFactory.h"
2437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/ELFFileFormat.h"
25cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/LD/ELFSegment.h"
26cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/LD/ELFSegmentFactory.h"
2737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/MC/Attribute.h"
2837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Object/ObjectBuilder.h"
2937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MemoryRegion.h"
3037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MemoryArea.h"
3137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h"
3237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/TargetRegistry.h"
3337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Target/OutputRelocSection.h"
3437b74a387bb3993387029859c2d9d051c41c724eStephen Hines
355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/ADT/Triple.h>
36cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include <llvm/Object/ELFTypes.h>
3787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <llvm/Support/Casting.h>
385460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao#include <llvm/Support/ELF.h>
3987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <llvm/Support/Host.h>
40cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include <llvm/Support/MipsABIFlags.h>
41cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
42cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include <vector>
435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
4622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
4722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao// MipsGNULDBackend
4822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
49d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei LiaoMipsGNULDBackend::MipsGNULDBackend(const LinkerConfig& pConfig,
50d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao                                   MipsGNUInfo* pInfo)
5137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : GNULDBackend(pConfig, pInfo),
5237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pRelocator(NULL),
5337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pGOT(NULL),
5437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pPLT(NULL),
5537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pGOTPLT(NULL),
5637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pInfo(*pInfo),
5737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pRelPlt(NULL),
5837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pRelDyn(NULL),
5937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pDynamic(NULL),
60cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      m_pAbiFlags(NULL),
6137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pGOTSymbol(NULL),
6237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pPLTSymbol(NULL),
6337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      m_pGpDispSymbol(NULL) {
6437b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
6537b74a387bb3993387029859c2d9d051c41c724eStephen Hines
6637b74a387bb3993387029859c2d9d051c41c724eStephen HinesMipsGNULDBackend::~MipsGNULDBackend() {
67d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  delete m_pRelocator;
6887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  delete m_pPLT;
6987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  delete m_pRelPlt;
7022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  delete m_pRelDyn;
7122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  delete m_pDynamic;
725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
7487f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsGNULDBackend::needsLA25Stub(Relocation::Type pType,
7537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                     const mcld::ResolveInfo* pSym) {
7687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (config().isCodeIndep())
7787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
7822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
7987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (llvm::ELF::R_MIPS_26 != pType)
8087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
8122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
8287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pSym->isLocal())
8387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
8487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
8587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
8687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
8787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
8837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid MipsGNULDBackend::addNonPICBranchSym(ResolveInfo* rsym) {
8987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_HasNonPICBranchSyms.insert(rsym);
9087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
9187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
9237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsGNULDBackend::hasNonPICBranch(const ResolveInfo* rsym) const {
9387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return m_HasNonPICBranchSyms.count(rsym);
9487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
9587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
9687f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsGNULDBackend::initTargetSections(Module& pModule,
9737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                          ObjectBuilder& pBuilder) {
9887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (LinkerConfig::Object == config().codeGenType())
9987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
10087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
10187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ELFFileFormat* file_format = getOutputFormat();
10287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
10387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize .rel.plt
10487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& relplt = file_format->getRelPlt();
10587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pRelPlt = new OutputRelocSection(pModule, relplt);
10687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
10787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize .rel.dyn
10887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& reldyn = file_format->getRelDyn();
10987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pRelDyn = new OutputRelocSection(pModule, reldyn);
110cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
111cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // initialize .sdata
112cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  m_psdata = pBuilder.CreateSection(
113cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      ".sdata", LDFileFormat::Target, llvm::ELF::SHT_PROGBITS,
114cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE | llvm::ELF::SHF_MIPS_GPREL,
115cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      4);
116cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
117cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // initialize .MIPS.abiflags
118cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  m_pAbiFlags = pBuilder.CreateSection(".MIPS.abiflags", LDFileFormat::Target,
119cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                                       llvm::ELF::SHT_MIPS_ABIFLAGS,
120cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                                       llvm::ELF::SHF_ALLOC, 4);
1215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
12337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid MipsGNULDBackend::initTargetSymbols(IRBuilder& pBuilder, Module& pModule) {
1245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // Define the symbol _GLOBAL_OFFSET_TABLE_ if there is a symbol with the
1255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // same name in input
1266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
12737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      "_GLOBAL_OFFSET_TABLE_",
12837b74a387bb3993387029859c2d9d051c41c724eStephen Hines      ResolveInfo::Object,
12937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      ResolveInfo::Define,
13037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      ResolveInfo::Local,
13137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0x0,                  // size
13237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0x0,                  // value
13337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      FragmentRef::Null(),  // FragRef
13437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      ResolveInfo::Hidden);
1355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
13687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Define the symbol _PROCEDURE_LINKAGE_TABLE_ if there is a symbol with the
13787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // same name in input
13837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  m_pPLTSymbol = pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
13937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      "_PROCEDURE_LINKAGE_TABLE_",
14037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      ResolveInfo::Object,
14137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      ResolveInfo::Define,
14237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      ResolveInfo::Local,
14337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0x0,                  // size
14437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0x0,                  // value
14537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      FragmentRef::Null(),  // FragRef
14637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      ResolveInfo::Hidden);
14737b74a387bb3993387029859c2d9d051c41c724eStephen Hines
14837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  m_pGpDispSymbol =
14937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Resolve>(
15037b74a387bb3993387029859c2d9d051c41c724eStephen Hines          "_gp_disp",
15137b74a387bb3993387029859c2d9d051c41c724eStephen Hines          ResolveInfo::Section,
15237b74a387bb3993387029859c2d9d051c41c724eStephen Hines          ResolveInfo::Define,
15337b74a387bb3993387029859c2d9d051c41c724eStephen Hines          ResolveInfo::Absolute,
15437b74a387bb3993387029859c2d9d051c41c724eStephen Hines          0x0,                  // size
15537b74a387bb3993387029859c2d9d051c41c724eStephen Hines          0x0,                  // value
15637b74a387bb3993387029859c2d9d051c41c724eStephen Hines          FragmentRef::Null(),  // FragRef
15737b74a387bb3993387029859c2d9d051c41c724eStephen Hines          ResolveInfo::Default);
1580dea6bc96bb52346737966839ac68644f7939f58Stephen Hines
15937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  pBuilder.AddSymbol<IRBuilder::AsReferred, IRBuilder::Unresolve>(
16037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      "_gp",
16137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      ResolveInfo::NoType,
16237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      ResolveInfo::Define,
16337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      ResolveInfo::Absolute,
16437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0x0,                  // size
16537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      0x0,                  // value
16637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      FragmentRef::Null(),  // FragRef
16737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      ResolveInfo::Default);
16837b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
16937b74a387bb3993387029859c2d9d051c41c724eStephen Hines
17037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst Relocator* MipsGNULDBackend::getRelocator() const {
17137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pRelocator != NULL);
1720dea6bc96bb52346737966839ac68644f7939f58Stephen Hines  return m_pRelocator;
1735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
17537b74a387bb3993387029859c2d9d051c41c724eStephen HinesRelocator* MipsGNULDBackend::getRelocator() {
17637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pRelocator != NULL);
177d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao  return m_pRelocator;
1785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1795460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
18037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid MipsGNULDBackend::doPreLayout(IRBuilder& pBuilder) {
1816f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  // initialize .dynamic data
18237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (!config().isCodeStatic() && m_pDynamic == NULL)
1836f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pDynamic = new MipsELFDynamic(*this, config());
184cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao
185cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (m_pAbiInfo.hasValue())
186cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    m_pAbiFlags->setSize(m_pAbiInfo->size());
187cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
18822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // set .got size
1895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // when building shared object, the .got section is must.
19022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (LinkerConfig::Object != config().codeGenType()) {
19137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (LinkerConfig::DynObj == config().codeGenType() || m_pGOT->hasGOT1() ||
19237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        m_pGOTSymbol != NULL) {
193f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines      m_pGOT->finalizeScanning(*m_pRelDyn);
19422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao      m_pGOT->finalizeSectionSize();
195f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
1966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      defineGOTSymbol(pBuilder);
19722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    }
19822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
19987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (m_pGOTPLT->hasGOT1()) {
20087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_pGOTPLT->finalizeSectionSize();
20187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
20287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      defineGOTPLTSymbol(pBuilder);
20387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
20487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
20587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (m_pPLT->hasPLT1())
20687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      m_pPLT->finalizeSectionSize();
20787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
208d0fbbb227051be16931a1aa9b4a7722ac039c698Shih-wei Liao    ELFFileFormat* file_format = getOutputFormat();
20987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
21087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // set .rel.plt size
21187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (!m_pRelPlt->empty()) {
21237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      assert(
21337b74a387bb3993387029859c2d9d051c41c724eStephen Hines          !config().isCodeStatic() &&
21437b74a387bb3993387029859c2d9d051c41c724eStephen Hines          "static linkage should not result in a dynamic relocation section");
21537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      file_format->getRelPlt().setSize(m_pRelPlt->numOfRelocs() *
21637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       getRelEntrySize());
21787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
21887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
21922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    // set .rel.dyn size
2206f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    if (!m_pRelDyn->empty()) {
22137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      assert(
22237b74a387bb3993387029859c2d9d051c41c724eStephen Hines          !config().isCodeStatic() &&
22337b74a387bb3993387029859c2d9d051c41c724eStephen Hines          "static linkage should not result in a dynamic relocation section");
22437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      file_format->getRelDyn().setSize(m_pRelDyn->numOfRelocs() *
22537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                       getRelEntrySize());
2266f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    }
2275460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2285460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2296f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines
23037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid MipsGNULDBackend::doPostLayout(Module& pModule, IRBuilder& pBuilder) {
23137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  const ELFFileFormat* format = getOutputFormat();
23287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
23387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (format->hasGOTPLT()) {
23437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    assert(m_pGOTPLT != NULL && "doPostLayout failed, m_pGOTPLT is NULL!");
23587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_pGOTPLT->applyAllGOTPLT(m_pPLT->addr());
23687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
23787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
23887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (format->hasPLT()) {
23937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    assert(m_pPLT != NULL && "doPostLayout failed, m_pPLT is NULL!");
24087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_pPLT->applyAllPLT(*m_pGOTPLT);
24187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
24287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
24387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pInfo.setABIVersion(m_pPLT && m_pPLT->hasPLT1() ? 1 : 0);
2445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// dynamic - the dynamic section of the target machine.
2475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Use co-variant return type to return its own dynamic section.
24837b74a387bb3993387029859c2d9d051c41c724eStephen HinesMipsELFDynamic& MipsGNULDBackend::dynamic() {
24937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pDynamic != NULL);
2505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pDynamic;
2515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
2535460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// dynamic - the dynamic section of the target machine.
2545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// Use co-variant return type to return its own dynamic section.
25537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst MipsELFDynamic& MipsGNULDBackend::dynamic() const {
25637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pDynamic != NULL);
2575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pDynamic;
2585460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
2595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
26022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaouint64_t MipsGNULDBackend::emitSectionData(const LDSection& pSection,
26137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                           MemoryRegion& pRegion) const {
2625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  assert(pRegion.size() && "Size of MemoryRegion is zero!");
2635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
26422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const ELFFileFormat* file_format = getOutputFormat();
2655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
26687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasGOT() && (&pSection == &(file_format->getGOT()))) {
26787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return m_pGOT->emit(pRegion);
26887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
26987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
27087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasPLT() && (&pSection == &(file_format->getPLT()))) {
27187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return m_pPLT->emit(pRegion);
27287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
27387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
27487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasGOTPLT() && (&pSection == &(file_format->getGOTPLT()))) {
27587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return m_pGOTPLT->emit(pRegion);
2765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
2775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
278cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (&pSection == m_pAbiFlags && m_pAbiInfo.hasValue())
279cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return MipsAbiFlags::emit(*m_pAbiInfo, pRegion);
280cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
281cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (&pSection == m_psdata && m_psdata->hasSectionData()) {
282cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    const SectionData* sect_data = pSection.getSectionData();
283cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    SectionData::const_iterator frag_iter, frag_end = sect_data->end();
284cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    uint8_t* out_offset = pRegion.begin();
285cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    for (frag_iter = sect_data->begin(); frag_iter != frag_end; ++frag_iter) {
286cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      size_t size = frag_iter->size();
287cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      switch (frag_iter->getKind()) {
288cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        case Fragment::Fillment: {
289cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          const FillFragment& fill_frag = llvm::cast<FillFragment>(*frag_iter);
290cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          if (fill_frag.getValueSize() == 0) {
291cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines            // virtual fillment, ignore it.
292cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines            break;
293cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          }
294cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          memset(out_offset, fill_frag.getValue(), fill_frag.size());
295cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          break;
296cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        }
297cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        case Fragment::Region: {
298cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          const RegionFragment& region_frag =
299cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines              llvm::cast<RegionFragment>(*frag_iter);
300cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          const char* start = region_frag.getRegion().begin();
301cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          memcpy(out_offset, start, size);
302cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          break;
303cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        }
304cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        case Fragment::Alignment: {
305cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          const AlignFragment& align_frag =
306cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines              llvm::cast<AlignFragment>(*frag_iter);
307cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          uint64_t count = size / align_frag.getValueSize();
308cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          switch (align_frag.getValueSize()) {
309cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines            case 1u:
310cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines              std::memset(out_offset, align_frag.getValue(), count);
311cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines              break;
312cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines            default:
313cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines              llvm::report_fatal_error(
314cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                  "unsupported value size for align fragment emission yet.\n");
315cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines              break;
316cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          }  // end switch
317cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          break;
318cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        }
319cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        case Fragment::Null: {
320cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          assert(0x0 == size);
321cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          break;
322cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        }
323cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        default:
324cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          llvm::report_fatal_error("unsupported fragment type.\n");
325cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          break;
326cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      }  // end switch
327cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      out_offset += size;
328cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    }
329cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return pRegion.size();
330cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
331cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
33237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  fatal(diag::unrecognized_output_sectoin) << pSection.name()
33337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                           << "mclinker@googlegroups.com";
3345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return 0;
3355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
33737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsGNULDBackend::hasEntryInStrTab(const LDSymbol& pSym) const {
33837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  return ResolveInfo::Section != pSym.type() || m_pGpDispSymbol == &pSym;
339f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines}
34022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
341f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hinesnamespace {
34237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstruct DynsymGOTCompare {
34337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  const MipsGOT& m_pGOT;
34422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
34537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  explicit DynsymGOTCompare(const MipsGOT& pGOT) : m_pGOT(pGOT) {}
34622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
34737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  bool operator()(const LDSymbol* X, const LDSymbol* Y) const {
34837b74a387bb3993387029859c2d9d051c41c724eStephen Hines    return m_pGOT.dynSymOrderCompare(X, Y);
34937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }
35037b74a387bb3993387029859c2d9d051c41c724eStephen Hines};
35137b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // anonymous namespace
3525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
35337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid MipsGNULDBackend::orderSymbolTable(Module& pModule) {
3542bf3f881f79c4d883f379e63725e788c310739a3Pirama Arumuga Nainar  if (config().options().hasGNUHash()) {
355f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // The MIPS ABI and .gnu.hash require .dynsym to be sorted
356f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // in different ways. The MIPS ABI requires a mapping between
357f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // the GOT and the symbol table. At the same time .gnu.hash
358f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    // needs symbols to be grouped by hash code.
359f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    llvm::errs() << ".gnu.hash is incompatible with the MIPS ABI\n";
3605460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
3615460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
362f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  Module::SymbolTable& symbols = pModule.getSymbolTable();
3635460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
36437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  std::stable_sort(
36537b74a387bb3993387029859c2d9d051c41c724eStephen Hines      symbols.dynamicBegin(), symbols.dynamicEnd(), DynsymGOTCompare(*m_pGOT));
3665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
3675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
36837b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
36937b74a387bb3993387029859c2d9d051c41c724eStephen Hines
37087f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesnamespace llvm {
37187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesnamespace ELF {
37287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// SHT_MIPS_OPTIONS section's block descriptor.
37387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstruct Elf_Options {
37437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  unsigned char kind;  // Determines interpretation of variable
37537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                       // part of descriptor. See ODK_xxx enumeration.
37637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  unsigned char size;  // Byte size of descriptor, including this header.
37737b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Elf64_Half section;  // Section header index of section affected,
37837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                       // or 0 for global options.
37937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Elf64_Word info;     // Kind-specific information.
38087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines};
38187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
38287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Content of ODK_REGINFO block in SHT_MIPS_OPTIONS section on 32 bit ABI.
38387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstruct Elf32_RegInfo {
38437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Elf32_Word ri_gprmask;     // Mask of general purpose registers used.
38537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Elf32_Word ri_cprmask[4];  // Mask of co-processor registers used.
38637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Elf32_Addr ri_gp_value;    // GP register value for this object file.
38787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines};
38887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
38987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Content of ODK_REGINFO block in SHT_MIPS_OPTIONS section on 64 bit ABI.
39087f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesstruct Elf64_RegInfo {
39137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Elf32_Word ri_gprmask;     // Mask of general purpose registers used.
39237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Elf32_Word ri_pad;         // Padding.
39337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Elf32_Word ri_cprmask[4];  // Mask of co-processor registers used.
39437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Elf64_Addr ri_gp_value;    // GP register value for this object file.
39587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines};
39687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
39737b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace ELF
39837b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace llvm
39937b74a387bb3993387029859c2d9d051c41c724eStephen Hines
40037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
40187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
402cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesstatic const char* ArchName(uint64_t flagBits) {
403cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  switch (flagBits) {
404cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    case llvm::ELF::EF_MIPS_ARCH_1:
405cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      return "mips1";
406cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    case llvm::ELF::EF_MIPS_ARCH_2:
407cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      return "mips2";
408cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    case llvm::ELF::EF_MIPS_ARCH_3:
409cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      return "mips3";
410cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    case llvm::ELF::EF_MIPS_ARCH_4:
411cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      return "mips4";
412cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    case llvm::ELF::EF_MIPS_ARCH_5:
413cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      return "mips5";
414cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    case llvm::ELF::EF_MIPS_ARCH_32:
415cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      return "mips32";
416cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    case llvm::ELF::EF_MIPS_ARCH_64:
417cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      return "mips64";
418cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    case llvm::ELF::EF_MIPS_ARCH_32R2:
419cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      return "mips32r2";
420cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    case llvm::ELF::EF_MIPS_ARCH_64R2:
421cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      return "mips64r2";
422cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    case llvm::ELF::EF_MIPS_ARCH_32R6:
423cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      return "mips32r6";
424cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    case llvm::ELF::EF_MIPS_ARCH_64R6:
425cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      return "mips64r6";
426cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    default:
427cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      return "Unknown Arch";
428cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
429cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines}
430cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
431cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesvoid MipsGNULDBackend::mergeFlags(Input& pInput, const char* ELF_hdr) {
432cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  bool isTarget64Bit = config().targets().triple().isArch64Bit();
433cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  bool isInput64Bit = ELF_hdr[llvm::ELF::EI_CLASS] == llvm::ELF::ELFCLASS64;
43487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
435cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (isTarget64Bit != isInput64Bit) {
436cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    fatal(diag::error_Mips_incompatible_class)
437cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        << (isTarget64Bit ? "ELFCLASS64" : "ELFCLASS32")
438cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        << (isInput64Bit ? "ELFCLASS64" : "ELFCLASS32") << pInput.name();
439cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return;
440cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
441cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
442cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  m_ElfFlagsMap[&pInput] =
443cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      isInput64Bit ?
444cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          reinterpret_cast<const llvm::ELF::Elf64_Ehdr*>(ELF_hdr)->e_flags :
445cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          reinterpret_cast<const llvm::ELF::Elf32_Ehdr*>(ELF_hdr)->e_flags;
446cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines}
447cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
448cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesbool MipsGNULDBackend::readSection(Input& pInput, SectionData& pSD) {
449cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if ((pSD.getSection().flag() & llvm::ELF::SHF_MIPS_GPREL) ||
450cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      (pSD.getSection().type() == llvm::ELF::SHT_MIPS_ABIFLAGS)) {
45187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    uint64_t offset = pInput.fileOffset() + pSD.getSection().offset();
45287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    uint64_t size = pSD.getSection().size();
45387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
45487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    Fragment* frag = IRBuilder::CreateRegion(pInput, offset, size);
45587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    ObjectBuilder::AppendFragment(*frag, pSD);
45687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return true;
45787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
45887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
45987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pSD.getSection().type() == llvm::ELF::SHT_MIPS_OPTIONS) {
46087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    uint32_t offset = pInput.fileOffset() + pSD.getSection().offset();
46187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    uint32_t size = pSD.getSection().size();
46287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
46387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    llvm::StringRef region = pInput.memArea()->request(offset, size);
46487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (region.size() > 0) {
46587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      const llvm::ELF::Elf_Options* optb =
46637b74a387bb3993387029859c2d9d051c41c724eStephen Hines          reinterpret_cast<const llvm::ELF::Elf_Options*>(region.begin());
46787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      const llvm::ELF::Elf_Options* opte =
46837b74a387bb3993387029859c2d9d051c41c724eStephen Hines          reinterpret_cast<const llvm::ELF::Elf_Options*>(region.begin() +
46937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                          size);
47087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
47137b74a387bb3993387029859c2d9d051c41c724eStephen Hines      for (const llvm::ELF::Elf_Options* opt = optb; opt < opte;
47237b74a387bb3993387029859c2d9d051c41c724eStephen Hines           opt += opt->size) {
47387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        switch (opt->kind) {
47487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          default:
47587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            // Nothing to do.
47687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            break;
47787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          case llvm::ELF::ODK_REGINFO:
47887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            if (config().targets().triple().isArch32Bit()) {
47987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              const llvm::ELF::Elf32_RegInfo* reg =
48037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                  reinterpret_cast<const llvm::ELF::Elf32_RegInfo*>(opt + 1);
48187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              m_GP0Map[&pInput] = reg->ri_gp_value;
48237b74a387bb3993387029859c2d9d051c41c724eStephen Hines            } else {
48387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              const llvm::ELF::Elf64_RegInfo* reg =
48437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                  reinterpret_cast<const llvm::ELF::Elf64_RegInfo*>(opt + 1);
48587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              m_GP0Map[&pInput] = reg->ri_gp_value;
48687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            }
48787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            break;
48887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        }
48987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
49087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
49187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
49287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return true;
49387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
49487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
49587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return GNULDBackend::readSection(pInput, pSD);
49687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
49787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
49837b74a387bb3993387029859c2d9d051c41c724eStephen HinesMipsGOT& MipsGNULDBackend::getGOT() {
49937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pGOT != NULL);
5005460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pGOT;
5015460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5025460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
50337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst MipsGOT& MipsGNULDBackend::getGOT() const {
50437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pGOT != NULL);
5055460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pGOT;
5065460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5075460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
50837b74a387bb3993387029859c2d9d051c41c724eStephen HinesMipsPLT& MipsGNULDBackend::getPLT() {
50937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pPLT != NULL);
51087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *m_pPLT;
51187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
51287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
51337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst MipsPLT& MipsGNULDBackend::getPLT() const {
51437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pPLT != NULL);
51587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *m_pPLT;
51687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
51787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
51837b74a387bb3993387029859c2d9d051c41c724eStephen HinesMipsGOTPLT& MipsGNULDBackend::getGOTPLT() {
51937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pGOTPLT != NULL);
52087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *m_pGOTPLT;
52187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
52287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
52337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst MipsGOTPLT& MipsGNULDBackend::getGOTPLT() const {
52437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pGOTPLT != NULL);
52587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *m_pGOTPLT;
52687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
52787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
52837b74a387bb3993387029859c2d9d051c41c724eStephen HinesOutputRelocSection& MipsGNULDBackend::getRelPLT() {
52937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pRelPlt != NULL);
53087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *m_pRelPlt;
53187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
53287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
53337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst OutputRelocSection& MipsGNULDBackend::getRelPLT() const {
53437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pRelPlt != NULL);
53587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return *m_pRelPlt;
53687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
53787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
53837b74a387bb3993387029859c2d9d051c41c724eStephen HinesOutputRelocSection& MipsGNULDBackend::getRelDyn() {
53937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pRelDyn != NULL);
5405460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pRelDyn;
5415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
54337b74a387bb3993387029859c2d9d051c41c724eStephen Hinesconst OutputRelocSection& MipsGNULDBackend::getRelDyn() const {
54437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(m_pRelDyn != NULL);
5455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return *m_pRelDyn;
5465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
54837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesunsigned int MipsGNULDBackend::getTargetSectionOrder(
54937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const LDSection& pSectHdr) const {
55022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  const ELFFileFormat* file_format = getOutputFormat();
5515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
55287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasGOT() && (&pSectHdr == &file_format->getGOT()))
55387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return SHO_DATA;
55487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
55587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasGOTPLT() && (&pSectHdr == &file_format->getGOTPLT()))
5565460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return SHO_DATA;
5575460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
55887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (file_format->hasPLT() && (&pSectHdr == &file_format->getPLT()))
55987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return SHO_PLT;
56087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
561cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (&pSectHdr == m_psdata)
562cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return SHO_SMALL_DATA;
563cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
564cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (&pSectHdr == m_pAbiFlags)
565cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return SHO_RO_NOTE;
566cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
5675460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return SHO_UNDEFINED;
5685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5705460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// finalizeSymbol - finalize the symbol value
57137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsGNULDBackend::finalizeTargetSymbols() {
57237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (m_pGpDispSymbol != NULL)
573f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    m_pGpDispSymbol->setValue(m_pGOT->getGPDispAddress());
574f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
575affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  return true;
5765460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
5775460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5785460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// allocateCommonSymbols - allocate common symbols in the corresponding
57922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// sections. This is called at pre-layout stage.
5805460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// FIXME: Mips needs to allocate small common symbol
58137b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsGNULDBackend::allocateCommonSymbols(Module& pModule) {
58222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  SymbolCategory& symbol_list = pModule.getSymbolTable();
5835460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5846f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines  if (symbol_list.emptyCommons() && symbol_list.emptyFiles() &&
5856f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines      symbol_list.emptyLocals() && symbol_list.emptyLocalDyns())
5865460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    return true;
5875460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
588affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  SymbolCategory::iterator com_sym, com_end;
5895460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
5905460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // FIXME: If the order of common symbols is defined, then sort common symbols
5915460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // std::sort(com_sym, com_end, some kind of order);
5925460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
59322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // get corresponding BSS LDSection
59422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  ELFFileFormat* file_format = getOutputFormat();
59522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection& bss_sect = file_format->getBSS();
59622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  LDSection& tbss_sect = file_format->getTBSS();
5975460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
598cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao  // get or create corresponding BSS SectionData
59922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  SectionData* bss_sect_data = NULL;
60022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (bss_sect.hasSectionData())
60122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    bss_sect_data = bss_sect.getSectionData();
60222add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
60322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    bss_sect_data = IRBuilder::CreateSectionData(bss_sect);
60422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao
60522add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  SectionData* tbss_sect_data = NULL;
60622add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  if (tbss_sect.hasSectionData())
60722add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    tbss_sect_data = tbss_sect.getSectionData();
60822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  else
60922add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao    tbss_sect_data = IRBuilder::CreateSectionData(tbss_sect);
6105460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
611affc150dc44fab1911775a49636d0ce85333b634Zonr Chang  // remember original BSS size
61237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  uint64_t bss_offset = bss_sect.size();
61322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  uint64_t tbss_offset = tbss_sect.size();
6145460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // allocate all local common symbols
6165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  com_end = symbol_list.localEnd();
617affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
6185460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for (com_sym = symbol_list.localBegin(); com_sym != com_end; ++com_sym) {
6195460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    if (ResolveInfo::Common == (*com_sym)->desc()) {
6205460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // We have to reset the description of the symbol here. When doing
6215460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // incremental linking, the output relocatable object may have common
6225460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // symbols. Therefore, we can not treat common symbols as normal symbols
6235460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // when emitting the regular name pools. We must change the symbols'
6245460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      // description here.
6255460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao      (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
626cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao      Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
627affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
628affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
629affc150dc44fab1911775a49636d0ce85333b634Zonr Chang        // allocate TLS common symbol in tbss section
63037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        tbss_offset += ObjectBuilder::AppendFragment(
63137b74a387bb3993387029859c2d9d051c41c724eStephen Hines            *frag, *tbss_sect_data, (*com_sym)->value());
632551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        ObjectBuilder::UpdateSectionAlign(tbss_sect, (*com_sym)->value());
63387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
63437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      } else {
63537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        // FIXME: how to identify small and large common symbols?
63637b74a387bb3993387029859c2d9d051c41c724eStephen Hines        bss_offset += ObjectBuilder::AppendFragment(
63737b74a387bb3993387029859c2d9d051c41c724eStephen Hines            *frag, *bss_sect_data, (*com_sym)->value());
638551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines        ObjectBuilder::UpdateSectionAlign(bss_sect, (*com_sym)->value());
63987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
640affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      }
6415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    }
6425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
6435460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
6445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  // allocate all global common symbols
6455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  com_end = symbol_list.commonEnd();
6465460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  for (com_sym = symbol_list.commonBegin(); com_sym != com_end; ++com_sym) {
6475460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // We have to reset the description of the symbol here. When doing
6485460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // incremental linking, the output relocatable object may have common
6495460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // symbols. Therefore, we can not treat common symbols as normal symbols
6505460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // when emitting the regular name pools. We must change the symbols'
6515460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    // description here.
6525460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    (*com_sym)->resolveInfo()->setDesc(ResolveInfo::Define);
653cedee4b38f4786845183be7f5916dd520a170ae0Shih-wei Liao    Fragment* frag = new FillFragment(0x0, 1, (*com_sym)->size());
654affc150dc44fab1911775a49636d0ce85333b634Zonr Chang
655affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    if (ResolveInfo::ThreadLocal == (*com_sym)->type()) {
656affc150dc44fab1911775a49636d0ce85333b634Zonr Chang      // allocate TLS common symbol in tbss section
65737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      tbss_offset += ObjectBuilder::AppendFragment(
65837b74a387bb3993387029859c2d9d051c41c724eStephen Hines          *frag, *tbss_sect_data, (*com_sym)->value());
659551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      ObjectBuilder::UpdateSectionAlign(tbss_sect, (*com_sym)->value());
66087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
66137b74a387bb3993387029859c2d9d051c41c724eStephen Hines    } else {
66237b74a387bb3993387029859c2d9d051c41c724eStephen Hines      // FIXME: how to identify small and large common symbols?
66337b74a387bb3993387029859c2d9d051c41c724eStephen Hines      bss_offset += ObjectBuilder::AppendFragment(
66437b74a387bb3993387029859c2d9d051c41c724eStephen Hines          *frag, *bss_sect_data, (*com_sym)->value());
665551ae4ebd3e9d137ea668fb83ae4a55b8cfba451Stephen Hines      ObjectBuilder::UpdateSectionAlign(bss_sect, (*com_sym)->value());
66687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      (*com_sym)->setFragmentRef(FragmentRef::Create(*frag, 0));
667affc150dc44fab1911775a49636d0ce85333b634Zonr Chang    }
6685460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
6695460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
67022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  bss_sect.setSize(bss_offset);
67122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  tbss_sect.setSize(tbss_offset);
6725460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  symbol_list.changeCommonsToGlobal();
6735460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  return true;
6745460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
6755460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
676cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesuint64_t MipsGNULDBackend::getTPOffset(const Input& pInput) const {
677cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  return m_TpOffsetMap.lookup(&pInput);
678cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines}
679cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
680cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesuint64_t MipsGNULDBackend::getDTPOffset(const Input& pInput) const {
681cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  return m_DtpOffsetMap.lookup(&pInput);
682cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines}
683cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
68437b74a387bb3993387029859c2d9d051c41c724eStephen Hinesuint64_t MipsGNULDBackend::getGP0(const Input& pInput) const {
68587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return m_GP0Map.lookup(&pInput);
68687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
68787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
68837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid MipsGNULDBackend::defineGOTSymbol(IRBuilder& pBuilder) {
689f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // If we do not reserve any GOT entries, we do not need to re-define GOT
690f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  // symbol.
691f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines  if (!m_pGOT->hasGOT1())
692f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines    return;
693f7ac0f19a1c8d0ad14bcf6456ce368b830fea886Stephen Hines
69422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao  // define symbol _GLOBAL_OFFSET_TABLE_
69537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (m_pGOTSymbol != NULL) {
6966f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
69737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        "_GLOBAL_OFFSET_TABLE_",
69837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Object,
69937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Define,
70037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Local,
70137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,  // size
70237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,  // value
70337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        FragmentRef::Create(*(m_pGOT->begin()), 0x0),
70437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Hidden);
70537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
7066f75755c9204b1d8817ae5a65a2f7e5af0ec3f70Stephen Hines    m_pGOTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
70737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        "_GLOBAL_OFFSET_TABLE_",
70837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Object,
70937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Define,
71037b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Local,
71137b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,  // size
71237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,  // value
71337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        FragmentRef::Create(*(m_pGOT->begin()), 0x0),
71437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Hidden);
7155460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
7165460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
7175460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
71837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid MipsGNULDBackend::defineGOTPLTSymbol(IRBuilder& pBuilder) {
71987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // define symbol _PROCEDURE_LINKAGE_TABLE_
72037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (m_pPLTSymbol != NULL) {
72187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Unresolve>(
72237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        "_PROCEDURE_LINKAGE_TABLE_",
72337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Object,
72437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Define,
72537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Local,
72637b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,  // size
72737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,  // value
72837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        FragmentRef::Create(*(m_pPLT->begin()), 0x0),
72937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Hidden);
73037b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
73187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_pPLTSymbol = pBuilder.AddSymbol<IRBuilder::Force, IRBuilder::Resolve>(
73237b74a387bb3993387029859c2d9d051c41c724eStephen Hines        "_PROCEDURE_LINKAGE_TABLE_",
73337b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Object,
73437b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Define,
73537b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Local,
73637b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,  // size
73737b74a387bb3993387029859c2d9d051c41c724eStephen Hines        0x0,  // value
73837b74a387bb3993387029859c2d9d051c41c724eStephen Hines        FragmentRef::Create(*(m_pPLT->begin()), 0x0),
73937b74a387bb3993387029859c2d9d051c41c724eStephen Hines        ResolveInfo::Hidden);
74087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
74187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
74287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
74322add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// doCreateProgramHdrs - backend can implement this function to create the
74422add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao/// target-dependent segments
74537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid MipsGNULDBackend::doCreateProgramHdrs(Module& pModule) {
746cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (!m_pAbiFlags || m_pAbiFlags->size() == 0)
747cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return;
748cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
749cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // create PT_MIPS_ABIFLAGS segment
750cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  ELFSegmentFactory::iterator sit =
751cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      elfSegmentTable().find(llvm::ELF::PT_INTERP, 0x0, 0x0);
752cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (sit == elfSegmentTable().end())
753cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    sit = elfSegmentTable().find(llvm::ELF::PT_PHDR, 0x0, 0x0);
754cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (sit == elfSegmentTable().end())
755cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    sit = elfSegmentTable().begin();
756cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  else
757cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    ++sit;
758cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
759cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  ELFSegment* abiSeg = elfSegmentTable().insert(sit,
760cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                                                llvm::ELF::PT_MIPS_ABIFLAGS,
761cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                                                llvm::ELF::PF_R);
762cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  abiSeg->setAlign(8);
763cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  abiSeg->append(m_pAbiFlags);
7645460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
7655460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
76637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsGNULDBackend::relaxRelocation(IRBuilder& pBuilder, Relocation& pRel) {
76787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t sym_value = 0x0;
76887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
76987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSymbol* symbol = pRel.symInfo()->outSymbol();
77087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (symbol->hasFragRef()) {
77187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    uint64_t value = symbol->fragRef()->getOutputOffset();
77287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    uint64_t addr = symbol->fragRef()->frag()->getParent()->getSection().addr();
77387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    sym_value = addr + value;
77487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
77587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
77637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  Stub* stub = getStubFactory()->create(
77737b74a387bb3993387029859c2d9d051c41c724eStephen Hines      pRel, sym_value, pBuilder, *getBRIslandFactory());
77887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
77937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (stub == NULL)
78087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
78187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
78237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(stub->symInfo() != NULL);
783cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // reset the branch target of the reloc to this stub instead
784cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  pRel.setSymInfo(stub->symInfo());
785cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
78687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // increase the size of .symtab and .strtab
78787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& symtab = getOutputFormat()->getSymTab();
78887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& strtab = getOutputFormat()->getStrTab();
78987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  symtab.setSize(symtab.size() + sizeof(llvm::ELF::Elf32_Sym));
79087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  strtab.setSize(strtab.size() + stub->symInfo()->nameSize() + 1);
79187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
79287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
79387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
79487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
79537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsGNULDBackend::doRelax(Module& pModule,
79637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                               IRBuilder& pBuilder,
79737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                               bool& pFinished) {
79837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(getStubFactory() != NULL && getBRIslandFactory() != NULL);
79987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
80087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  bool isRelaxed = false;
80187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
80287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (Module::obj_iterator input = pModule.obj_begin();
80337b74a387bb3993387029859c2d9d051c41c724eStephen Hines       input != pModule.obj_end();
80437b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++input) {
80587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    LDContext* context = (*input)->context();
80687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
80787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    for (LDContext::sect_iterator rs = context->relocSectBegin();
80837b74a387bb3993387029859c2d9d051c41c724eStephen Hines         rs != context->relocSectEnd();
80937b74a387bb3993387029859c2d9d051c41c724eStephen Hines         ++rs) {
81087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      LDSection* sec = *rs;
81187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
81287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (LDFileFormat::Ignore == sec->kind() || !sec->hasRelocData())
81387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        continue;
81487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
81587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      for (RelocData::iterator reloc = sec->getRelocData()->begin();
81637b74a387bb3993387029859c2d9d051c41c724eStephen Hines           reloc != sec->getRelocData()->end();
81737b74a387bb3993387029859c2d9d051c41c724eStephen Hines           ++reloc) {
81887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (llvm::ELF::R_MIPS_26 != reloc->type())
81987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          continue;
82087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
82187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        if (relaxRelocation(pBuilder, *llvm::cast<Relocation>(reloc)))
82287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          isRelaxed = true;
82387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
82487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
82587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
82687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
82787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // find the first fragment w/ invalid offset due to stub insertion
828cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  std::vector<Fragment*> invalid_frags;
82987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pFinished = true;
83087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (BranchIslandFactory::iterator ii = getBRIslandFactory()->begin(),
83187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                     ie = getBRIslandFactory()->end();
83237b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ii != ie;
83337b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++ii) {
83487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    BranchIsland& island = *ii;
835cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    if (island.size() > stubGroupSize()) {
836cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      error(diag::err_no_space_to_place_stubs) << stubGroupSize();
837cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      return false;
838cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    }
839cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
840cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    if (island.numOfStubs() == 0) {
841cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      continue;
842cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    }
843cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
844cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    Fragment* exit = &*island.end();
845cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    if (exit == island.begin()->getParent()->end()) {
846cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      continue;
847cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    }
84887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
84987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if ((island.offset() + island.size()) > exit->getOffset()) {
850cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      if (invalid_frags.empty() ||
851cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          (invalid_frags.back()->getParent() != island.getParent())) {
852cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        invalid_frags.push_back(exit);
853cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        pFinished = false;
854cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      }
855cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      continue;
85687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
85787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
85887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
85987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // reset the offset of invalid fragments
860cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  for (auto it = invalid_frags.begin(), ie = invalid_frags.end(); it != ie;
861cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines       ++it) {
862cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    Fragment* invalid = *it;
863cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    while (invalid != NULL) {
864cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      invalid->setOffset(invalid->getPrevNode()->getOffset() +
865cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                         invalid->getPrevNode()->size());
866cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      invalid = invalid->getNextNode();
867cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    }
86887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
86987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
870cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // reset the size of section that has stubs inserted.
871cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (isRelaxed) {
872cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    SectionData* prev = NULL;
873cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    for (BranchIslandFactory::iterator island = getBRIslandFactory()->begin(),
874cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                                       island_end = getBRIslandFactory()->end();
875cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines         island != island_end;
876cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines         ++island) {
877cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      SectionData* sd = (*island).begin()->getParent();
878cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      if ((*island).numOfStubs() != 0) {
879cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        if (sd != prev) {
880cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          sd->getSection().setSize(sd->back().getOffset() + sd->back().size());
881cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        }
882cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      }
883cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      prev = sd;
884cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    }
885cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
88687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
88787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return isRelaxed;
88887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
88987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
89037b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool MipsGNULDBackend::initTargetStubs() {
89137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (getStubFactory() == NULL)
89287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
89387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
89487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  getStubFactory()->addPrototype(new MipsLA25Stub(*this));
89587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
89687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
89787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
89887f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf32_Rel& pRel,
89987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Relocation::Type& pType,
90087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t& pSymIdx,
90137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      uint32_t& pOffset) const {
90287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return GNULDBackend::readRelocation(pRel, pType, pSymIdx, pOffset);
90387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
90487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
90587f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf32_Rela& pRel,
90687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Relocation::Type& pType,
90787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t& pSymIdx,
90887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t& pOffset,
90937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      int32_t& pAddend) const {
91087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return GNULDBackend::readRelocation(pRel, pType, pSymIdx, pOffset, pAddend);
91187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
91287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
91387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf64_Rel& pRel,
91487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Relocation::Type& pType,
91587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t& pSymIdx,
91637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      uint64_t& pOffset) const {
91787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t r_info = 0x0;
91887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (llvm::sys::IsLittleEndianHost) {
91987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pOffset = pRel.r_offset;
92037b74a387bb3993387029859c2d9d051c41c724eStephen Hines    r_info = pRel.r_info;
92137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
92287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pOffset = mcld::bswap64(pRel.r_offset);
92337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    r_info = mcld::bswap64(pRel.r_info);
92487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
92587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
92687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // MIPS 64 little endian (we do not support big endian now)
92787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // has a "special" encoding of r_info relocation
92887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // field. Instead of one 64 bit little endian number, it is a little
92987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // endian 32 bit number followed by a 32 bit big endian number.
93087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pType = mcld::bswap32(r_info >> 32);
93187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pSymIdx = r_info & 0xffffffff;
93287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
93387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
93487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
93587f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesbool MipsGNULDBackend::readRelocation(const llvm::ELF::Elf64_Rela& pRel,
93687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Relocation::Type& pType,
93787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t& pSymIdx,
93887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint64_t& pOffset,
93937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      int64_t& pAddend) const {
94087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t r_info = 0x0;
94187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (llvm::sys::IsLittleEndianHost) {
94287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pOffset = pRel.r_offset;
94337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    r_info = pRel.r_info;
94487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pAddend = pRel.r_addend;
94537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } else {
94687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pOffset = mcld::bswap64(pRel.r_offset);
94737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    r_info = mcld::bswap64(pRel.r_info);
94887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    pAddend = mcld::bswap64(pRel.r_addend);
94987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
95087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
95187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pType = mcld::bswap32(r_info >> 32);
95287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pSymIdx = r_info & 0xffffffff;
95387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
95487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
95587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
95687f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsGNULDBackend::emitRelocation(llvm::ELF::Elf32_Rel& pRel,
95787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Relocation::Type pType,
95887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t pSymIdx,
95937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      uint32_t pOffset) const {
96087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  GNULDBackend::emitRelocation(pRel, pType, pSymIdx, pOffset);
96187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
96287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
96387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsGNULDBackend::emitRelocation(llvm::ELF::Elf32_Rela& pRel,
96487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Relocation::Type pType,
96587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t pSymIdx,
96687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t pOffset,
96737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      int32_t pAddend) const {
96887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  GNULDBackend::emitRelocation(pRel, pType, pSymIdx, pOffset, pAddend);
96987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
97087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
97187f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsGNULDBackend::emitRelocation(llvm::ELF::Elf64_Rel& pRel,
97287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Relocation::Type pType,
97387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t pSymIdx,
97437b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      uint64_t pOffset) const {
97587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t r_info = mcld::bswap32(pType);
97687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  r_info <<= 32;
97787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  r_info |= pSymIdx;
97887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
97987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pRel.r_info = r_info;
98087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pRel.r_offset = pOffset;
98187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
98287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
98387f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid MipsGNULDBackend::emitRelocation(llvm::ELF::Elf64_Rela& pRel,
98487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      Relocation::Type pType,
98587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint32_t pSymIdx,
98687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                      uint64_t pOffset,
98737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      int64_t pAddend) const {
98887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t r_info = mcld::bswap32(pType);
98987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  r_info <<= 32;
99087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  r_info |= pSymIdx;
99187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
99287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pRel.r_info = r_info;
99387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pRel.r_offset = pOffset;
99487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  pRel.r_addend = pAddend;
99587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
99687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
997cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesnamespace {
998cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesstruct ISATreeEdge {
999cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  unsigned child;
1000cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  unsigned parent;
1001cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines};
1002cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines}
1003cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1004cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesstatic ISATreeEdge isaTree[] = {
1005cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    // MIPS32R6 and MIPS64R6 are not compatible with other extensions
1006cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1007cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    // MIPS64 extensions.
1008cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    {llvm::ELF::EF_MIPS_ARCH_64R2, llvm::ELF::EF_MIPS_ARCH_64},
1009cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    // MIPS V extensions.
1010cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    {llvm::ELF::EF_MIPS_ARCH_64, llvm::ELF::EF_MIPS_ARCH_5},
1011cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    // MIPS IV extensions.
1012cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    {llvm::ELF::EF_MIPS_ARCH_5, llvm::ELF::EF_MIPS_ARCH_4},
1013cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    // MIPS III extensions.
1014cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    {llvm::ELF::EF_MIPS_ARCH_4, llvm::ELF::EF_MIPS_ARCH_3},
1015cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    // MIPS32 extensions.
1016cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    {llvm::ELF::EF_MIPS_ARCH_32R2, llvm::ELF::EF_MIPS_ARCH_32},
1017cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    // MIPS II extensions.
1018cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    {llvm::ELF::EF_MIPS_ARCH_3, llvm::ELF::EF_MIPS_ARCH_2},
1019cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    {llvm::ELF::EF_MIPS_ARCH_32, llvm::ELF::EF_MIPS_ARCH_2},
1020cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    // MIPS I extensions.
1021cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    {llvm::ELF::EF_MIPS_ARCH_2, llvm::ELF::EF_MIPS_ARCH_1},
1022cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines};
1023cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1024cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesstatic bool isIsaMatched(uint32_t base, uint32_t ext) {
1025cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (base == ext)
1026cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return true;
1027cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (base == llvm::ELF::EF_MIPS_ARCH_32 &&
1028cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      isIsaMatched(llvm::ELF::EF_MIPS_ARCH_64, ext))
1029cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return true;
1030cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (base == llvm::ELF::EF_MIPS_ARCH_32R2 &&
1031cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      isIsaMatched(llvm::ELF::EF_MIPS_ARCH_64R2, ext))
1032cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return true;
1033cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  for (const auto &edge : isaTree) {
1034cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    if (ext == edge.child) {
1035cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      ext = edge.parent;
1036cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      if (ext == base)
1037cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        return true;
1038cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    }
1039cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
1040cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  return false;
1041cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines}
1042cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1043cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesstatic bool getAbiFlags(const Input& pInput, uint64_t elfFlags, bool& hasFlags,
1044cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                        MipsAbiFlags& pFlags) {
1045cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  MipsAbiFlags pElfFlags = {};
1046cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (!MipsAbiFlags::fillByElfFlags(pInput, elfFlags, pElfFlags))
1047cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return false;
1048cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1049cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  const LDContext* ctx = pInput.context();
1050cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  for (auto it = ctx->sectBegin(), ie = ctx->sectEnd(); it != ie; ++it)
1051cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    if ((*it)->type() == llvm::ELF::SHT_MIPS_ABIFLAGS) {
1052cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      if (!MipsAbiFlags::fillBySection(pInput, **it, pFlags))
1053cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        return false;
1054cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      if (!MipsAbiFlags::isCompatible(pInput, pElfFlags, pFlags))
1055cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        return false;
1056cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      hasFlags = true;
1057cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      return true;
1058cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    }
1059cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1060cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  pFlags = pElfFlags;
1061cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  return true;
1062cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines}
1063cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1064cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesstatic const char* getNanName(uint64_t flags) {
1065cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  return flags & llvm::ELF::EF_MIPS_NAN2008 ? "2008" : "legacy";
1066cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines}
1067cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1068cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesstatic bool mergeElfFlags(const Input& pInput, uint64_t& oldElfFlags,
1069cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                          uint64_t newElfFlags) {
1070cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // PIC code is inherently CPIC and may not set CPIC flag explicitly.
1071cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // Ensure that this flag will exist in the linked file.
1072cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (newElfFlags & llvm::ELF::EF_MIPS_PIC)
1073cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    newElfFlags |= llvm::ELF::EF_MIPS_CPIC;
1074cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1075cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (newElfFlags & llvm::ELF::EF_MIPS_ARCH_ASE_M16) {
1076cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    error(diag::error_Mips_m16_unsupported) << pInput.name();
1077cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return false;
1078cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
1079cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1080cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (!oldElfFlags) {
1081cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    oldElfFlags = newElfFlags;
1082cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return true;
1083cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
1084cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1085cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  uint64_t newPic =
1086cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      newElfFlags & (llvm::ELF::EF_MIPS_PIC | llvm::ELF::EF_MIPS_CPIC);
1087cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  uint64_t oldPic =
1088cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      oldElfFlags & (llvm::ELF::EF_MIPS_PIC | llvm::ELF::EF_MIPS_CPIC);
1089cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1090cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // Check PIC / CPIC flags compatibility.
1091cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if ((newPic != 0) != (oldPic != 0))
1092cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    warning(diag::warn_Mips_abicalls_linking) << pInput.name();
1093cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1094cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (!(newPic & llvm::ELF::EF_MIPS_PIC))
1095cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    oldElfFlags &= ~llvm::ELF::EF_MIPS_PIC;
1096cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (newPic)
1097cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    oldElfFlags |= llvm::ELF::EF_MIPS_CPIC;
1098cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1099cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // Check ISA compatibility.
1100cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  uint64_t newArch = newElfFlags & llvm::ELF::EF_MIPS_ARCH;
1101cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  uint64_t oldArch = oldElfFlags & llvm::ELF::EF_MIPS_ARCH;
1102cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (!isIsaMatched(newArch, oldArch)) {
1103cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    if (!isIsaMatched(oldArch, newArch)) {
1104cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      error(diag::error_Mips_inconsistent_arch)
1105cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines          << ArchName(oldArch) << ArchName(newArch) << pInput.name();
1106cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      return false;
1107cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    }
1108cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    oldElfFlags &= ~llvm::ELF::EF_MIPS_ARCH;
1109cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    oldElfFlags |= newArch;
1110cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
1111cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1112cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // Check ABI compatibility.
1113cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  uint32_t newAbi = newElfFlags & llvm::ELF::EF_MIPS_ABI;
1114cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  uint32_t oldAbi = oldElfFlags & llvm::ELF::EF_MIPS_ABI;
1115cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (newAbi != oldAbi && newAbi && oldAbi) {
1116cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    error(diag::error_Mips_inconsistent_abi) << pInput.name();
1117cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return false;
1118cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
1119cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1120cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // Check -mnan flags compatibility.
1121cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if ((newElfFlags & llvm::ELF::EF_MIPS_NAN2008) !=
1122cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      (oldElfFlags & llvm::ELF::EF_MIPS_NAN2008)) {
1123cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    // Linking -mnan=2008 and -mnan=legacy modules
1124cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    error(diag::error_Mips_inconsistent_mnan)
1125cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines        << getNanName(oldElfFlags) << getNanName(newElfFlags) << pInput.name();
1126cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return false;
1127cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
1128cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1129cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // Check ASE compatibility.
1130cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  uint64_t newAse = newElfFlags & llvm::ELF::EF_MIPS_ARCH_ASE;
1131cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  uint64_t oldAse = oldElfFlags & llvm::ELF::EF_MIPS_ARCH_ASE;
1132cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (newAse != oldAse)
1133cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    oldElfFlags |= newAse;
1134cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1135cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // Check FP64 compatibility.
1136cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if ((newElfFlags & llvm::ELF::EF_MIPS_FP64) !=
1137cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      (oldElfFlags & llvm::ELF::EF_MIPS_FP64)) {
1138cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    // Linking -mnan=2008 and -mnan=legacy modules
1139cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    error(diag::error_Mips_inconsistent_fp64) << pInput.name();
1140cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    return false;
1141cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
1142cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1143cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  oldElfFlags |= newElfFlags & llvm::ELF::EF_MIPS_NOREORDER;
1144cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  oldElfFlags |= newElfFlags & llvm::ELF::EF_MIPS_MICROMIPS;
1145cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  oldElfFlags |= newElfFlags & llvm::ELF::EF_MIPS_NAN2008;
1146cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  oldElfFlags |= newElfFlags & llvm::ELF::EF_MIPS_32BITMODE;
1147cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1148cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  return true;
1149cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines}
1150cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1151cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesvoid MipsGNULDBackend::saveTPOffset(const Input& pInput) {
1152cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  const LDContext* ctx = pInput.context();
1153cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  for (auto it = ctx->sectBegin(), ie = ctx->sectEnd(); it != ie; ++it) {
1154cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    LDSection* sect = *it;
1155cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    if (sect->flag() & llvm::ELF::SHF_TLS) {
1156cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      m_TpOffsetMap[&pInput] = sect->addr() + 0x7000;
1157cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      m_DtpOffsetMap[&pInput] = sect->addr() + 0x8000;
1158cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      break;
1159cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    }
1160cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
1161cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines}
1162cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1163cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesvoid MipsGNULDBackend::preMergeSections(Module& pModule) {
1164cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  uint64_t elfFlags = 0;
1165cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  bool hasAbiFlags = false;
1166cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  MipsAbiFlags abiFlags = {};
1167cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  for (const Input *input : pModule.getObjectList()) {
1168cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    if (input->type() != Input::Object)
1169cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      continue;
1170cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1171cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    uint64_t newElfFlags = m_ElfFlagsMap[input];
1172cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1173cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    MipsAbiFlags newAbiFlags = {};
1174cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    if (!getAbiFlags(*input, newElfFlags, hasAbiFlags, newAbiFlags))
1175cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      continue;
1176cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1177cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    if (!mergeElfFlags(*input, elfFlags, newElfFlags))
1178cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      continue;
1179cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1180cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    if (!MipsAbiFlags::merge(*input, abiFlags, newAbiFlags))
1181cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      continue;
1182cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1183cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    saveTPOffset(*input);
1184cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
1185cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1186cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  m_pInfo.setElfFlags(elfFlags);
1187cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (hasAbiFlags)
1188cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    m_pAbiInfo = abiFlags;
1189cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines}
1190cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1191cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesbool MipsGNULDBackend::mergeSection(Module& pModule, const Input& pInput,
1192cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                                    LDSection& pSection) {
1193cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (pSection.flag() & llvm::ELF::SHF_MIPS_GPREL) {
1194cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    SectionData* sd = NULL;
1195cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    if (!m_psdata->hasSectionData()) {
1196cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      sd = IRBuilder::CreateSectionData(*m_psdata);
1197cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines      m_psdata->setSectionData(sd);
1198cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    }
1199cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    sd = m_psdata->getSectionData();
1200cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    moveSectionData(*pSection.getSectionData(), *sd);
1201cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  } else if (pSection.type() == llvm::ELF::SHT_MIPS_ABIFLAGS) {
1202cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    // Nothing to do because we handle all .MIPS.abiflags sections
1203cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    // in the preMergeSections method.
1204cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  } else {
1205cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    ObjectBuilder builder(pModule);
1206cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    builder.MergeSection(pInput, pSection);
1207cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
1208cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  return true;
1209cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines}
1210cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1211cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesvoid MipsGNULDBackend::moveSectionData(SectionData& pFrom, SectionData& pTo) {
1212cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  assert(&pFrom != &pTo && "Cannot move section data to itself!");
1213cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1214cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  uint64_t offset = pTo.getSection().size();
1215cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  AlignFragment* align = NULL;
1216cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  if (pFrom.getSection().align() > 1) {
1217cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    // if the align constraint is larger than 1, append an alignment
1218cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    unsigned int alignment = pFrom.getSection().align();
1219cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    align = new AlignFragment(/*alignment*/ alignment,
1220cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                              /*the filled value*/ 0x0,
1221cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                              /*the size of filled value*/ 1u,
1222cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines                              /*max bytes to emit*/ alignment - 1);
1223cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    align->setOffset(offset);
1224cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    align->setParent(&pTo);
1225cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    pTo.getFragmentList().push_back(align);
1226cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    offset += align->size();
1227cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
1228cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1229cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // move fragments from pFrom to pTO
1230cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  SectionData::FragmentListType& from_list = pFrom.getFragmentList();
1231cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  SectionData::FragmentListType& to_list = pTo.getFragmentList();
1232cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  SectionData::FragmentListType::iterator frag, fragEnd = from_list.end();
1233cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  for (frag = from_list.begin(); frag != fragEnd; ++frag) {
1234cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    frag->setParent(&pTo);
1235cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    frag->setOffset(offset);
1236cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines    offset += frag->size();
1237cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  }
1238cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  to_list.splice(to_list.end(), from_list);
1239cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
1240cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  // set up pTo's header
1241cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines  pTo.getSection().setSize(offset);
1242cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines}
1243cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines
124487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
124587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Mips32GNULDBackend
124687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
124787f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMips32GNULDBackend::Mips32GNULDBackend(const LinkerConfig& pConfig,
124887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                       MipsGNUInfo* pInfo)
124937b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : MipsGNULDBackend(pConfig, pInfo) {
125037b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
125187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
125237b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool Mips32GNULDBackend::initRelocator() {
125337b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (m_pRelocator == NULL)
125487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_pRelocator = new Mips32Relocator(*this, config());
125587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
125687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
125787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
125887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
125987f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid Mips32GNULDBackend::initTargetSections(Module& pModule,
126037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                            ObjectBuilder& pBuilder) {
126187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  MipsGNULDBackend::initTargetSections(pModule, pBuilder);
126287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
126387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (LinkerConfig::Object == config().codeGenType())
126487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
126587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
126687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ELFFileFormat* fileFormat = getOutputFormat();
126787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
126887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize .got
126987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& got = fileFormat->getGOT();
127087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pGOT = new Mips32GOT(got);
127187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
127287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize .got.plt
127387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& gotplt = fileFormat->getGOTPLT();
127487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pGOTPLT = new MipsGOTPLT(gotplt);
127587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
127687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize .plt
127787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& plt = fileFormat->getPLT();
127887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pPLT = new MipsPLT(plt);
127987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
128087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
128137b74a387bb3993387029859c2d9d051c41c724eStephen Hinessize_t Mips32GNULDBackend::getRelEntrySize() {
128287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return 8;
128387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
128487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
128537b74a387bb3993387029859c2d9d051c41c724eStephen Hinessize_t Mips32GNULDBackend::getRelaEntrySize() {
128687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return 12;
128787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
128887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
128987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
129087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// Mips64GNULDBackend
129187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
129287f34658dec9097d987d254a990ea7f311bfc95fStephen HinesMips64GNULDBackend::Mips64GNULDBackend(const LinkerConfig& pConfig,
129387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                       MipsGNUInfo* pInfo)
129437b74a387bb3993387029859c2d9d051c41c724eStephen Hines    : MipsGNULDBackend(pConfig, pInfo) {
129537b74a387bb3993387029859c2d9d051c41c724eStephen Hines}
129687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
129737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool Mips64GNULDBackend::initRelocator() {
129837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (m_pRelocator == NULL)
129987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    m_pRelocator = new Mips64Relocator(*this, config());
130087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
130187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
130287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
130387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
130487f34658dec9097d987d254a990ea7f311bfc95fStephen Hinesvoid Mips64GNULDBackend::initTargetSections(Module& pModule,
130537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                            ObjectBuilder& pBuilder) {
130687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  MipsGNULDBackend::initTargetSections(pModule, pBuilder);
130787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
130887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (LinkerConfig::Object == config().codeGenType())
130987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return;
131087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
131187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ELFFileFormat* fileFormat = getOutputFormat();
131287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
131387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize .got
131487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& got = fileFormat->getGOT();
131587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pGOT = new Mips64GOT(got);
131687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
131787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize .got.plt
131887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& gotplt = fileFormat->getGOTPLT();
131987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pGOTPLT = new MipsGOTPLT(gotplt);
132087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
132187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // initialize .plt
132287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  LDSection& plt = fileFormat->getPLT();
132387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_pPLT = new MipsPLT(plt);
132487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
132587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
132637b74a387bb3993387029859c2d9d051c41c724eStephen Hinessize_t Mips64GNULDBackend::getRelEntrySize() {
132787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return 16;
132887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
132987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
133037b74a387bb3993387029859c2d9d051c41c724eStephen Hinessize_t Mips64GNULDBackend::getRelaEntrySize() {
133187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return 24;
133287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
133387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
13345460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao//===----------------------------------------------------------------------===//
13355460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao/// createMipsLDBackend - the help funtion to create corresponding MipsLDBackend
13365460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao///
133737b74a387bb3993387029859c2d9d051c41c724eStephen Hinesstatic TargetLDBackend* createMipsLDBackend(const LinkerConfig& pConfig) {
133887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  const llvm::Triple& triple = pConfig.targets().triple();
133987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
134087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (triple.isOSDarwin()) {
13415460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert(0 && "MachO linker is not supported yet");
13425460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
134387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (triple.isOSWindows()) {
13445460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao    assert(0 && "COFF linker is not supported yet");
13455460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  }
134687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
134787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  llvm::Triple::ArchType arch = triple.getArch();
134887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
134987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (llvm::Triple::mips64el == arch)
135087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return new Mips64GNULDBackend(pConfig, new MipsGNUInfo(triple));
135187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
135237b74a387bb3993387029859c2d9d051c41c724eStephen Hines  assert(arch == llvm::Triple::mipsel);
135387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return new Mips32GNULDBackend(pConfig, new MipsGNUInfo(triple));
13545460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
13555460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao
135637b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
135737b74a387bb3993387029859c2d9d051c41c724eStephen Hines
135822add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
13595460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao// Force static initialization.
136022add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liao//===----------------------------------------------------------------------===//
136122add6ff3426df1a85089fe6a6e1597ee3b6f300Shih-wei Liaoextern "C" void MCLDInitializeMipsLDBackend() {
13625460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao  mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMipselTarget,
136337b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                mcld::createMipsLDBackend);
136487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  mcld::TargetRegistry::RegisterTargetLDBackend(mcld::TheMips64elTarget,
136537b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                mcld::createMipsLDBackend);
13665460a1f25d9ddecb5c70667267d66d51af177a99Shih-wei Liao}
1367