1c5707112e7635d1dd2f2cc9c4f42e79a51302ccaJia Liu//===-- MipsELFObjectWriter.cpp - Mips ELF Writer -------------------------===//
2090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola//
3090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola//                     The LLVM Compiler Infrastructure
4090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola//
5090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola// This file is distributed under the University of Illinois Open Source
6090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola// License. See LICENSE.TXT for details.
7090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola//
8090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola//===----------------------------------------------------------------------===//
9090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola
1037ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka#include "MCTargetDesc/MipsBaseInfo.h"
11090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "MCTargetDesc/MipsFixupKinds.h"
12090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "MCTargetDesc/MipsMCTargetDesc.h"
132c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar#include "llvm/ADT/STLExtras.h"
1437ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka#include "llvm/MC/MCAssembler.h"
15ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines#include "llvm/MC/MCELF.h"
16090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "llvm/MC/MCELFObjectWriter.h"
17090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "llvm/MC/MCExpr.h"
18090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "llvm/MC/MCSection.h"
19090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "llvm/MC/MCValue.h"
20090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola#include "llvm/Support/ErrorHandling.h"
2137ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka#include <list>
22090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola
23090445967f0b5988446faffefd1d0722f982bc7aRafael Espindolausing namespace llvm;
24090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola
25090445967f0b5988446faffefd1d0722f982bc7aRafael Espindolanamespace {
262c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// A helper structure based on ELFRelocationEntry, used for sorting entries in
272c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// the relocation table.
282c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainarstruct MipsRelocationEntry {
292c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  MipsRelocationEntry(const ELFRelocationEntry &R)
302c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar      : R(R), SortOffset(R.Offset), HasMatchingHi(false) {}
312c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  const ELFRelocationEntry R;
322c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  // SortOffset equals R.Offset except for the *HI16 relocations, for which it
332c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  // will be set based on the R.Offset of the matching *LO16 relocation.
342c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  int64_t SortOffset;
352c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  // True when this is a *LO16 relocation chosen as a match for a *HI16
362c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  // relocation.
372c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  bool HasMatchingHi;
382c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar};
392c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
40090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  class MipsELFObjectWriter : public MCELFObjectTargetWriter {
41090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  public:
42b889e0cd2fea4afee623d5be603b912b955a2ecaAkira Hatanaka    MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI,
43b889e0cd2fea4afee623d5be603b912b955a2ecaAkira Hatanaka                        bool _isN64, bool IsLittleEndian);
44090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola
452c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    ~MipsELFObjectWriter() override;
46090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola
4736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
4836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                          bool IsPCRel) const override;
4937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines    bool needsRelocateWithSymbol(const MCSymbolData &SD,
5037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                                 unsigned Type) const override;
512c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    virtual void sortRelocs(const MCAssembler &Asm,
522c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar                            std::vector<ELFRelocationEntry> &Relocs) override;
53090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  };
54090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola}
55090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola
5693ee286e8d949147f8df7f093c9bd8529a99102dJack CarterMipsELFObjectWriter::MipsELFObjectWriter(bool _is64Bit, uint8_t OSABI,
57b889e0cd2fea4afee623d5be603b912b955a2ecaAkira Hatanaka                                         bool _isN64, bool IsLittleEndian)
584c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar    : MCELFObjectTargetWriter(_is64Bit, OSABI, ELF::EM_MIPS,
594c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar                              /*HasRelocationAddend*/ _isN64,
604c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar                              /*IsN64*/ _isN64) {}
61090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola
62090445967f0b5988446faffefd1d0722f982bc7aRafael EspindolaMipsELFObjectWriter::~MipsELFObjectWriter() {}
63090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola
64090445967f0b5988446faffefd1d0722f982bc7aRafael Espindolaunsigned MipsELFObjectWriter::GetRelocType(const MCValue &Target,
65090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola                                           const MCFixup &Fixup,
6636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                           bool IsPCRel) const {
67090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  // determine the type of the relocation
68090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  unsigned Type = (unsigned)ELF::R_MIPS_NONE;
69090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  unsigned Kind = (unsigned)Fixup.getKind();
70090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola
71090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  switch (Kind) {
72090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  default:
73090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    llvm_unreachable("invalid fixup kind!");
744c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  case Mips::fixup_Mips_32:
75090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  case FK_Data_4:
76090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    Type = ELF::R_MIPS_32;
77090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    break;
784c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  case Mips::fixup_Mips_64:
79e2245bab3ca29dc2142d8f254005f4ae7c40cde2Jack Carter  case FK_Data_8:
80e2245bab3ca29dc2142d8f254005f4ae7c40cde2Jack Carter    Type = ELF::R_MIPS_64;
81e2245bab3ca29dc2142d8f254005f4ae7c40cde2Jack Carter    break;
82090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  case FK_GPRel_4:
83096d617796228293810cb0443c6617b33c5afdc5Jack Carter    if (isN64()) {
84096d617796228293810cb0443c6617b33c5afdc5Jack Carter      Type = setRType((unsigned)ELF::R_MIPS_GPREL32, Type);
85096d617796228293810cb0443c6617b33c5afdc5Jack Carter      Type = setRType2((unsigned)ELF::R_MIPS_64, Type);
86096d617796228293810cb0443c6617b33c5afdc5Jack Carter      Type = setRType3((unsigned)ELF::R_MIPS_NONE, Type);
87096d617796228293810cb0443c6617b33c5afdc5Jack Carter    }
88096d617796228293810cb0443c6617b33c5afdc5Jack Carter    else
89096d617796228293810cb0443c6617b33c5afdc5Jack Carter      Type = ELF::R_MIPS_GPREL32;
90090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    break;
91090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  case Mips::fixup_Mips_GPREL16:
92090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    Type = ELF::R_MIPS_GPREL16;
93090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    break;
94090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  case Mips::fixup_Mips_26:
95090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    Type = ELF::R_MIPS_26;
96090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    break;
97090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  case Mips::fixup_Mips_CALL16:
98090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    Type = ELF::R_MIPS_CALL16;
99090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    break;
100090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  case Mips::fixup_Mips_GOT_Global:
101090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  case Mips::fixup_Mips_GOT_Local:
102090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    Type = ELF::R_MIPS_GOT16;
103090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    break;
104090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  case Mips::fixup_Mips_HI16:
105090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    Type = ELF::R_MIPS_HI16;
106090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    break;
107090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  case Mips::fixup_Mips_LO16:
108090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    Type = ELF::R_MIPS_LO16;
109090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    break;
110090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  case Mips::fixup_Mips_TLSGD:
111090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    Type = ELF::R_MIPS_TLS_GD;
112090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    break;
113090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  case Mips::fixup_Mips_GOTTPREL:
114090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    Type = ELF::R_MIPS_TLS_GOTTPREL;
115090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    break;
116090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  case Mips::fixup_Mips_TPREL_HI:
117090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    Type = ELF::R_MIPS_TLS_TPREL_HI16;
118090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    break;
119090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  case Mips::fixup_Mips_TPREL_LO:
120090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    Type = ELF::R_MIPS_TLS_TPREL_LO16;
121090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    break;
122090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  case Mips::fixup_Mips_TLSLDM:
123090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    Type = ELF::R_MIPS_TLS_LDM;
124090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    break;
125090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  case Mips::fixup_Mips_DTPREL_HI:
126090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    Type = ELF::R_MIPS_TLS_DTPREL_HI16;
127090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    break;
128090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  case Mips::fixup_Mips_DTPREL_LO:
129090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    Type = ELF::R_MIPS_TLS_DTPREL_LO16;
130090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    break;
131090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  case Mips::fixup_Mips_Branch_PCRel:
132090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  case Mips::fixup_Mips_PC16:
133090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    Type = ELF::R_MIPS_PC16;
134090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola    break;
1350140e55393c4403ab240c386501cdc5e438dcc0eJack Carter  case Mips::fixup_Mips_GOT_PAGE:
1360140e55393c4403ab240c386501cdc5e438dcc0eJack Carter    Type = ELF::R_MIPS_GOT_PAGE;
1370140e55393c4403ab240c386501cdc5e438dcc0eJack Carter    break;
1380140e55393c4403ab240c386501cdc5e438dcc0eJack Carter  case Mips::fixup_Mips_GOT_OFST:
1390140e55393c4403ab240c386501cdc5e438dcc0eJack Carter    Type = ELF::R_MIPS_GOT_OFST;
1400140e55393c4403ab240c386501cdc5e438dcc0eJack Carter    break;
141fd506efec628819f7e6fad8016a9dbb5d8612b8bJack Carter  case Mips::fixup_Mips_GOT_DISP:
142fd506efec628819f7e6fad8016a9dbb5d8612b8bJack Carter    Type = ELF::R_MIPS_GOT_DISP;
143fd506efec628819f7e6fad8016a9dbb5d8612b8bJack Carter    break;
1440140e55393c4403ab240c386501cdc5e438dcc0eJack Carter  case Mips::fixup_Mips_GPOFF_HI:
1450140e55393c4403ab240c386501cdc5e438dcc0eJack Carter    Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type);
1460140e55393c4403ab240c386501cdc5e438dcc0eJack Carter    Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type);
1470140e55393c4403ab240c386501cdc5e438dcc0eJack Carter    Type = setRType3((unsigned)ELF::R_MIPS_HI16, Type);
1480140e55393c4403ab240c386501cdc5e438dcc0eJack Carter    break;
1490140e55393c4403ab240c386501cdc5e438dcc0eJack Carter  case Mips::fixup_Mips_GPOFF_LO:
1500140e55393c4403ab240c386501cdc5e438dcc0eJack Carter    Type = setRType((unsigned)ELF::R_MIPS_GPREL16, Type);
1510140e55393c4403ab240c386501cdc5e438dcc0eJack Carter    Type = setRType2((unsigned)ELF::R_MIPS_SUB, Type);
1520140e55393c4403ab240c386501cdc5e438dcc0eJack Carter    Type = setRType3((unsigned)ELF::R_MIPS_LO16, Type);
1530140e55393c4403ab240c386501cdc5e438dcc0eJack Carter    break;
154fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter  case Mips::fixup_Mips_HIGHER:
155fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter    Type = ELF::R_MIPS_HIGHER;
156fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter    break;
157fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter  case Mips::fixup_Mips_HIGHEST:
158fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter    Type = ELF::R_MIPS_HIGHEST;
159fc54d9e47a1276650f14f38e7d037c9b58c8dc2dJack Carter    break;
160198ad916d736047f8a439f19dee25cee917df8a9Jack Carter  case Mips::fixup_Mips_GOT_HI16:
161198ad916d736047f8a439f19dee25cee917df8a9Jack Carter    Type = ELF::R_MIPS_GOT_HI16;
162198ad916d736047f8a439f19dee25cee917df8a9Jack Carter    break;
163198ad916d736047f8a439f19dee25cee917df8a9Jack Carter  case Mips::fixup_Mips_GOT_LO16:
164198ad916d736047f8a439f19dee25cee917df8a9Jack Carter    Type = ELF::R_MIPS_GOT_LO16;
165198ad916d736047f8a439f19dee25cee917df8a9Jack Carter    break;
166198ad916d736047f8a439f19dee25cee917df8a9Jack Carter  case Mips::fixup_Mips_CALL_HI16:
167198ad916d736047f8a439f19dee25cee917df8a9Jack Carter    Type = ELF::R_MIPS_CALL_HI16;
168198ad916d736047f8a439f19dee25cee917df8a9Jack Carter    break;
169198ad916d736047f8a439f19dee25cee917df8a9Jack Carter  case Mips::fixup_Mips_CALL_LO16:
170198ad916d736047f8a439f19dee25cee917df8a9Jack Carter    Type = ELF::R_MIPS_CALL_LO16;
171198ad916d736047f8a439f19dee25cee917df8a9Jack Carter    break;
1721aaf43c2a2ec0fd4c8dbfe56558237219c5f8af7Zoran Jovanovic  case Mips::fixup_MICROMIPS_26_S1:
1731aaf43c2a2ec0fd4c8dbfe56558237219c5f8af7Zoran Jovanovic    Type = ELF::R_MICROMIPS_26_S1;
1741aaf43c2a2ec0fd4c8dbfe56558237219c5f8af7Zoran Jovanovic    break;
1750082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic  case Mips::fixup_MICROMIPS_HI16:
1760082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    Type = ELF::R_MICROMIPS_HI16;
1770082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    break;
1780082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic  case Mips::fixup_MICROMIPS_LO16:
1790082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    Type = ELF::R_MICROMIPS_LO16;
1800082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    break;
1810082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic  case Mips::fixup_MICROMIPS_GOT16:
1820082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    Type = ELF::R_MICROMIPS_GOT16;
1830082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    break;
184ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines  case Mips::fixup_MICROMIPS_PC7_S1:
185ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    Type = ELF::R_MICROMIPS_PC7_S1;
186ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    break;
187ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines  case Mips::fixup_MICROMIPS_PC10_S1:
188ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    Type = ELF::R_MICROMIPS_PC10_S1;
189ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    break;
1905c042162beb3c2dd556e00aab84c4278a69cd5b1Zoran Jovanovic  case Mips::fixup_MICROMIPS_PC16_S1:
1915c042162beb3c2dd556e00aab84c4278a69cd5b1Zoran Jovanovic    Type = ELF::R_MICROMIPS_PC16_S1;
1925c042162beb3c2dd556e00aab84c4278a69cd5b1Zoran Jovanovic    break;
1930082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic  case Mips::fixup_MICROMIPS_CALL16:
1940082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    Type = ELF::R_MICROMIPS_CALL16;
1950082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    break;
1960082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic  case Mips::fixup_MICROMIPS_GOT_DISP:
1970082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    Type = ELF::R_MICROMIPS_GOT_DISP;
1980082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    break;
1990082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic  case Mips::fixup_MICROMIPS_GOT_PAGE:
2000082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    Type = ELF::R_MICROMIPS_GOT_PAGE;
2010082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    break;
2020082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic  case Mips::fixup_MICROMIPS_GOT_OFST:
2030082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    Type = ELF::R_MICROMIPS_GOT_OFST;
2040082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    break;
20536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::fixup_MICROMIPS_TLS_GD:
20636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Type = ELF::R_MICROMIPS_TLS_GD;
20736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    break;
20836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case Mips::fixup_MICROMIPS_TLS_LDM:
20936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    Type = ELF::R_MICROMIPS_TLS_LDM;
21036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    break;
2110082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic  case Mips::fixup_MICROMIPS_TLS_DTPREL_HI16:
2120082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    Type = ELF::R_MICROMIPS_TLS_DTPREL_HI16;
2130082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    break;
2140082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic  case Mips::fixup_MICROMIPS_TLS_DTPREL_LO16:
2150082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    Type = ELF::R_MICROMIPS_TLS_DTPREL_LO16;
2160082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    break;
2170082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic  case Mips::fixup_MICROMIPS_TLS_TPREL_HI16:
2180082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    Type = ELF::R_MICROMIPS_TLS_TPREL_HI16;
2190082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    break;
2200082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic  case Mips::fixup_MICROMIPS_TLS_TPREL_LO16:
2210082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    Type = ELF::R_MICROMIPS_TLS_TPREL_LO16;
2220082717cb537e2d1424f755a49510fa9f9e67071Zoran Jovanovic    break;
223c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  case Mips::fixup_MIPS_PC19_S2:
224c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    Type = ELF::R_MIPS_PC19_S2;
225c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    break;
226c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines  case Mips::fixup_MIPS_PC18_S3:
227c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    Type = ELF::R_MIPS_PC18_S3;
228c6a4f5e819217e1e12c458aed8e7b122e23a3a58Stephen Hines    break;
229dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case Mips::fixup_MIPS_PC21_S2:
230dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Type = ELF::R_MIPS_PC21_S2;
231dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    break;
232dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case Mips::fixup_MIPS_PC26_S2:
233dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Type = ELF::R_MIPS_PC26_S2;
234dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    break;
235dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case Mips::fixup_MIPS_PCHI16:
236dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Type = ELF::R_MIPS_PCHI16;
237dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    break;
238dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines  case Mips::fixup_MIPS_PCLO16:
239dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Type = ELF::R_MIPS_PCLO16;
240dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    break;
241090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  }
242090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  return Type;
243090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola}
244090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola
2452c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// Sort entries by SortOffset in descending order.
2462c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// When there are more *HI16 relocs paired with one *LO16 reloc, the 2nd rule
2472c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// sorts them in ascending order of R.Offset.
2482c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainarstatic int cmpRelMips(const MipsRelocationEntry *AP,
2492c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar                      const MipsRelocationEntry *BP) {
2502c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  const MipsRelocationEntry &A = *AP;
2512c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  const MipsRelocationEntry &B = *BP;
2522c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  if (A.SortOffset != B.SortOffset)
2532c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    return B.SortOffset - A.SortOffset;
2542c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  if (A.R.Offset != B.R.Offset)
2552c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    return A.R.Offset - B.R.Offset;
2562c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  if (B.R.Type != A.R.Type)
2572c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    return B.R.Type - A.R.Type;
2582c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  //llvm_unreachable("ELFRelocs might be unstable!");
2592c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  return 0;
2602c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar}
2612c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
2622c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// For the given Reloc.Type, return the matching relocation type, as in the
2632c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// table below.
2642c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainarstatic unsigned getMatchingLoType(const MCAssembler &Asm,
2652c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar                                  const ELFRelocationEntry &Reloc) {
2662c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  unsigned Type = Reloc.Type;
2672c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  if (Type == ELF::R_MIPS_HI16)
2682c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    return ELF::R_MIPS_LO16;
2692c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  if (Type == ELF::R_MICROMIPS_HI16)
2702c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    return ELF::R_MICROMIPS_LO16;
2712c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  if (Type == ELF::R_MIPS16_HI16)
2722c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    return ELF::R_MIPS16_LO16;
2732c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
2742c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  const MCSymbolData &SD = Asm.getSymbolData(*Reloc.Symbol);
2752c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
2762c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  if (MCELF::GetBinding(SD) != ELF::STB_LOCAL)
2772c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    return ELF::R_MIPS_NONE;
2782c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
2792c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  if (Type == ELF::R_MIPS_GOT16)
2802c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    return ELF::R_MIPS_LO16;
2812c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  if (Type == ELF::R_MICROMIPS_GOT16)
2822c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    return ELF::R_MICROMIPS_LO16;
2832c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  if (Type == ELF::R_MIPS16_GOT16)
2842c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    return ELF::R_MIPS16_LO16;
2852c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
2862c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  return ELF::R_MIPS_NONE;
2872c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar}
2882c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
2892c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// Return true if First needs a matching *LO16, its matching *LO16 type equals
2902c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// Second's type and both relocations are against the same symbol.
2912c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainarstatic bool areMatchingHiAndLo(const MCAssembler &Asm,
2922c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar                               const ELFRelocationEntry &First,
2932c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar                               const ELFRelocationEntry &Second) {
2942c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  return getMatchingLoType(Asm, First) != ELF::R_MIPS_NONE &&
2952c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar         getMatchingLoType(Asm, First) == Second.Type &&
2962c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar         First.Symbol && First.Symbol == Second.Symbol;
2972c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar}
2982c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
2992c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// Return true if MipsRelocs[Index] is a *LO16 preceded by a matching *HI16.
3002c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainarstatic bool
3012c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga NainarisPrecededByMatchingHi(const MCAssembler &Asm, uint32_t Index,
3022c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar                       std::vector<MipsRelocationEntry> &MipsRelocs) {
3032c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  return Index < MipsRelocs.size() - 1 &&
3042c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar         areMatchingHiAndLo(Asm, MipsRelocs[Index + 1].R, MipsRelocs[Index].R);
3052c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar}
3062c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
3072c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// Return true if MipsRelocs[Index] is a *LO16 not preceded by a matching *HI16
3082c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// and not chosen by a *HI16 as a match.
3092c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainarstatic bool isFreeLo(const MCAssembler &Asm, uint32_t Index,
3102c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar                     std::vector<MipsRelocationEntry> &MipsRelocs) {
3112c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  return Index < MipsRelocs.size() && !MipsRelocs[Index].HasMatchingHi &&
3122c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar         !isPrecededByMatchingHi(Asm, Index, MipsRelocs);
3132c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar}
3142c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
3152c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// Lo is chosen as a match for Hi, set their fields accordingly.
3162c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// Mips instructions have fixed length of at least two bytes (two for
3172c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// micromips/mips16, four for mips32/64), so we can set HI's SortOffset to
3182c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// matching LO's Offset minus one to simplify the sorting function.
3192c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainarstatic void setMatch(MipsRelocationEntry &Hi, MipsRelocationEntry &Lo) {
3202c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  Lo.HasMatchingHi = true;
3212c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  Hi.SortOffset = Lo.R.Offset - 1;
3222c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar}
3232c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
3242c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// We sort relocation table entries by offset, except for one additional rule
3252c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// required by MIPS ABI: every *HI16 relocation must be immediately followed by
3262c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// the corresponding *LO16 relocation. We also support a GNU extension that
3272c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// allows more *HI16s paired with one *LO16.
3282c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar//
3292c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// *HI16 relocations and their matching *LO16 are:
3302c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar//
3312c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// +---------------------------------------------+-------------------+
3322c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// |               *HI16                         |  matching *LO16   |
3332c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// |---------------------------------------------+-------------------|
3342c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// |  R_MIPS_HI16, local R_MIPS_GOT16            |    R_MIPS_LO16    |
3352c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// |  R_MICROMIPS_HI16, local R_MICROMIPS_GOT16  | R_MICROMIPS_LO16  |
3362c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// |  R_MIPS16_HI16, local R_MIPS16_GOT16        |  R_MIPS16_LO16    |
3372c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// +---------------------------------------------+-------------------+
3382c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar//
3392c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// (local R_*_GOT16 meaning R_*_GOT16 against the local symbol.)
3402c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar//
3412c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// To handle *HI16 and *LO16 relocations, the linker needs a combined addend
3422c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// ("AHL") calculated from both *HI16 ("AHI") and *LO16 ("ALO") relocations:
3432c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// AHL = (AHI << 16) + (short)ALO;
3442c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar//
3452c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// We are reusing gnu as sorting algorithm so we are emitting the relocation
3462c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// table sorted the same way as gnu as would sort it, for easier comparison of
3472c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// the generated .o files.
3482c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar//
3492c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// The logic is:
3502c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// search the table (starting from the highest offset and going back to zero)
3512c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// for all *HI16 relocations that don't have a matching *LO16.
3522c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// For every such HI, find a matching LO with highest offset that isn't already
3532c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// matched with another HI. If there are no free LOs, match it with the first
3542c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// found (starting from lowest offset).
3552c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// When there are more HIs matched with one LO, sort them in descending order by
3562c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// offset.
3572c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar//
3582c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// In other words, when searching for a matching LO:
3592c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// - don't look for a 'better' match for the HIs that are already followed by a
3602c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar//   matching LO;
3612c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// - prefer LOs without a pair;
3622c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar// - prefer LOs with higher offset;
3632c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainarvoid MipsELFObjectWriter::sortRelocs(const MCAssembler &Asm,
3642c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar                                     std::vector<ELFRelocationEntry> &Relocs) {
3652c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  if (Relocs.size() < 2)
3662c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    return;
3672c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
3682c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  // The default function sorts entries by Offset in descending order.
3692c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  MCELFObjectTargetWriter::sortRelocs(Asm, Relocs);
3702c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
3712c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  // Init MipsRelocs from Relocs.
3722c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  std::vector<MipsRelocationEntry> MipsRelocs;
3732c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  for (unsigned I = 0, E = Relocs.size(); I != E; ++I)
3742c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    MipsRelocs.push_back(MipsRelocationEntry(Relocs[I]));
3752c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
3762c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  // Find a matching LO for all HIs that need it.
3772c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  for (int32_t I = 0, E = MipsRelocs.size(); I != E; ++I) {
3782c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    if (getMatchingLoType(Asm, MipsRelocs[I].R) == ELF::R_MIPS_NONE ||
3792c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar        (I > 0 && isPrecededByMatchingHi(Asm, I - 1, MipsRelocs)))
3802c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar      continue;
3812c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
3822c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    int32_t MatchedLoIndex = -1;
3832c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
3842c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    // Search the list in the ascending order of Offset.
3852c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    for (int32_t J = MipsRelocs.size() - 1, N = -1; J != N; --J) {
3862c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar      // check for a match
3872c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar      if (areMatchingHiAndLo(Asm, MipsRelocs[I].R, MipsRelocs[J].R) &&
3882c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar          (MatchedLoIndex == -1 || // first match
3892c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar           // or we already have a match,
3902c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar           // but this one is with higher offset and it's free
3912c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar           (MatchedLoIndex > J && isFreeLo(Asm, J, MipsRelocs))))
3922c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar        MatchedLoIndex = J;
3932c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    }
3942c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
3952c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    if (MatchedLoIndex != -1)
3962c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar      // We have a match.
3972c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar      setMatch(MipsRelocs[I], MipsRelocs[MatchedLoIndex]);
3982c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  }
3992c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
4002c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  // SortOffsets are calculated, call the sorting function.
4012c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  array_pod_sort(MipsRelocs.begin(), MipsRelocs.end(), cmpRelMips);
4022c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
4032c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  // Copy sorted MipsRelocs back to Relocs.
4042c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar  for (unsigned I = 0, E = MipsRelocs.size(); I != E; ++I)
4052c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar    Relocs[I] = MipsRelocs[I].R;
4062c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar}
4072c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar
40836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hinesbool
40937ed9c199ca639565f6ce88105f9e39e898d82d0Stephen HinesMipsELFObjectWriter::needsRelocateWithSymbol(const MCSymbolData &SD,
41037ed9c199ca639565f6ce88105f9e39e898d82d0Stephen Hines                                             unsigned Type) const {
411ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines  // FIXME: This is extremely conservative. This really needs to use a
41236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // whitelist with a clear explanation for why each realocation needs to
41336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // point to the symbol, not to the section.
41436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  switch (Type) {
41536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  default:
41636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
41736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
41836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case ELF::R_MIPS_GOT16:
41936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case ELF::R_MIPS16_GOT16:
42036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case ELF::R_MICROMIPS_GOT16:
42136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    llvm_unreachable("Should have been handled already");
42236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
42336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // These relocations might be paired with another relocation. The pairing is
42436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // done by the static linker by matching the symbol. Since we only see one
42536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // relocation at a time, we have to force them to relocate with a symbol to
42636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // avoid ending up with a pair where one points to a section and another
42736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  // points to a symbol.
42836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case ELF::R_MIPS_HI16:
42936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case ELF::R_MIPS16_HI16:
43036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case ELF::R_MICROMIPS_HI16:
43136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case ELF::R_MIPS_LO16:
43236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case ELF::R_MIPS16_LO16:
43336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case ELF::R_MICROMIPS_LO16:
43436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    return true;
43536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
43636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case ELF::R_MIPS_32:
437ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    if (MCELF::getOther(SD) & (ELF::STO_MIPS_MICROMIPS >> 2))
438ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines      return true;
439ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines    // falltrough
440ebe69fe11e48d322045d5949c83283927a0d790bStephen Hines  case ELF::R_MIPS_26:
44136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case ELF::R_MIPS_64:
44236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines  case ELF::R_MIPS_GPREL16:
44337ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka    return false;
44437ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka  }
44537ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka}
44637ac18ef2f13a8060b745e6d3c4622bafdd4f47bAkira Hatanaka
4472c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga NainarMCObjectWriter *llvm::createMipsELFObjectWriter(raw_pwrite_stream &OS,
4482c3e0051c31c3f5b2328b447eadf1cf9c4427442Pirama Arumuga Nainar                                                uint8_t OSABI,
449a551a48402385cf3f4b754dc72264b2f0974b1a6Akira Hatanaka                                                bool IsLittleEndian,
450a551a48402385cf3f4b754dc72264b2f0974b1a6Akira Hatanaka                                                bool Is64Bit) {
4514c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar  MCELFObjectTargetWriter *MOTW =
4524c5e43da7792f75567b693105cc53e3f1992ad98Pirama Arumuga Nainar      new MipsELFObjectWriter(Is64Bit, OSABI, Is64Bit, IsLittleEndian);
453090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola  return createELFObjectWriter(MOTW, OS, IsLittleEndian);
454090445967f0b5988446faffefd1d0722f982bc7aRafael Espindola}
455