Home | History | Annotate | Download | only in MCTargetDesc
      1 //===-- PPCELFObjectWriter.cpp - PPC ELF Writer ---------------------------===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "MCTargetDesc/PPCMCTargetDesc.h"
     11 #include "MCTargetDesc/PPCFixupKinds.h"
     12 #include "MCTargetDesc/PPCMCExpr.h"
     13 #include "llvm/ADT/STLExtras.h"
     14 #include "llvm/MC/MCELFObjectWriter.h"
     15 #include "llvm/MC/MCExpr.h"
     16 #include "llvm/MC/MCValue.h"
     17 #include "llvm/Support/ErrorHandling.h"
     18 
     19 using namespace llvm;
     20 
     21 namespace {
     22   class PPCELFObjectWriter : public MCELFObjectTargetWriter {
     23   public:
     24     PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI);
     25 
     26     virtual ~PPCELFObjectWriter();
     27   protected:
     28     virtual unsigned getRelocTypeInner(const MCValue &Target,
     29                                        const MCFixup &Fixup,
     30                                        bool IsPCRel) const;
     31     unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup,
     32                           bool IsPCRel) const override;
     33   };
     34 }
     35 
     36 PPCELFObjectWriter::PPCELFObjectWriter(bool Is64Bit, uint8_t OSABI)
     37   : MCELFObjectTargetWriter(Is64Bit, OSABI,
     38                             Is64Bit ?  ELF::EM_PPC64 : ELF::EM_PPC,
     39                             /*HasRelocationAddend*/ true) {}
     40 
     41 PPCELFObjectWriter::~PPCELFObjectWriter() {
     42 }
     43 
     44 static MCSymbolRefExpr::VariantKind getAccessVariant(const MCValue &Target,
     45                                                      const MCFixup &Fixup) {
     46   const MCExpr *Expr = Fixup.getValue();
     47 
     48   if (Expr->getKind() != MCExpr::Target)
     49     return Target.getAccessVariant();
     50 
     51   switch (cast<PPCMCExpr>(Expr)->getKind()) {
     52   case PPCMCExpr::VK_PPC_None:
     53     return MCSymbolRefExpr::VK_None;
     54   case PPCMCExpr::VK_PPC_LO:
     55     return MCSymbolRefExpr::VK_PPC_LO;
     56   case PPCMCExpr::VK_PPC_HI:
     57     return MCSymbolRefExpr::VK_PPC_HI;
     58   case PPCMCExpr::VK_PPC_HA:
     59     return MCSymbolRefExpr::VK_PPC_HA;
     60   case PPCMCExpr::VK_PPC_HIGHERA:
     61     return MCSymbolRefExpr::VK_PPC_HIGHERA;
     62   case PPCMCExpr::VK_PPC_HIGHER:
     63     return MCSymbolRefExpr::VK_PPC_HIGHER;
     64   case PPCMCExpr::VK_PPC_HIGHEST:
     65     return MCSymbolRefExpr::VK_PPC_HIGHEST;
     66   case PPCMCExpr::VK_PPC_HIGHESTA:
     67     return MCSymbolRefExpr::VK_PPC_HIGHESTA;
     68   }
     69   llvm_unreachable("unknown PPCMCExpr kind");
     70 }
     71 
     72 unsigned PPCELFObjectWriter::getRelocTypeInner(const MCValue &Target,
     73                                                const MCFixup &Fixup,
     74                                                bool IsPCRel) const
     75 {
     76   MCSymbolRefExpr::VariantKind Modifier = getAccessVariant(Target, Fixup);
     77 
     78   // determine the type of the relocation
     79   unsigned Type;
     80   if (IsPCRel) {
     81     switch ((unsigned)Fixup.getKind()) {
     82     default:
     83       llvm_unreachable("Unimplemented");
     84     case PPC::fixup_ppc_br24:
     85     case PPC::fixup_ppc_br24abs:
     86       Type = ELF::R_PPC_REL24;
     87       break;
     88     case PPC::fixup_ppc_brcond14:
     89     case PPC::fixup_ppc_brcond14abs:
     90       Type = ELF::R_PPC_REL14;
     91       break;
     92     case PPC::fixup_ppc_half16:
     93       switch (Modifier) {
     94       default: llvm_unreachable("Unsupported Modifier");
     95       case MCSymbolRefExpr::VK_None:
     96         Type = ELF::R_PPC_REL16;
     97         break;
     98       case MCSymbolRefExpr::VK_PPC_LO:
     99         Type = ELF::R_PPC_REL16_LO;
    100         break;
    101       case MCSymbolRefExpr::VK_PPC_HI:
    102         Type = ELF::R_PPC_REL16_HI;
    103         break;
    104       case MCSymbolRefExpr::VK_PPC_HA:
    105         Type = ELF::R_PPC_REL16_HA;
    106         break;
    107       }
    108       break;
    109     case FK_Data_4:
    110     case FK_PCRel_4:
    111       Type = ELF::R_PPC_REL32;
    112       break;
    113     case FK_Data_8:
    114     case FK_PCRel_8:
    115       Type = ELF::R_PPC64_REL64;
    116       break;
    117     }
    118   } else {
    119     switch ((unsigned)Fixup.getKind()) {
    120       default: llvm_unreachable("invalid fixup kind!");
    121     case PPC::fixup_ppc_br24abs:
    122       Type = ELF::R_PPC_ADDR24;
    123       break;
    124     case PPC::fixup_ppc_brcond14abs:
    125       Type = ELF::R_PPC_ADDR14; // XXX: or BRNTAKEN?_
    126       break;
    127     case PPC::fixup_ppc_half16:
    128       switch (Modifier) {
    129       default: llvm_unreachable("Unsupported Modifier");
    130       case MCSymbolRefExpr::VK_None:
    131         Type = ELF::R_PPC_ADDR16;
    132         break;
    133       case MCSymbolRefExpr::VK_PPC_LO:
    134         Type = ELF::R_PPC_ADDR16_LO;
    135         break;
    136       case MCSymbolRefExpr::VK_PPC_HI:
    137         Type = ELF::R_PPC_ADDR16_HI;
    138         break;
    139       case MCSymbolRefExpr::VK_PPC_HA:
    140         Type = ELF::R_PPC_ADDR16_HA;
    141         break;
    142       case MCSymbolRefExpr::VK_PPC_HIGHER:
    143         Type = ELF::R_PPC64_ADDR16_HIGHER;
    144         break;
    145       case MCSymbolRefExpr::VK_PPC_HIGHERA:
    146         Type = ELF::R_PPC64_ADDR16_HIGHERA;
    147         break;
    148       case MCSymbolRefExpr::VK_PPC_HIGHEST:
    149         Type = ELF::R_PPC64_ADDR16_HIGHEST;
    150         break;
    151       case MCSymbolRefExpr::VK_PPC_HIGHESTA:
    152         Type = ELF::R_PPC64_ADDR16_HIGHESTA;
    153         break;
    154       case MCSymbolRefExpr::VK_GOT:
    155         Type = ELF::R_PPC_GOT16;
    156         break;
    157       case MCSymbolRefExpr::VK_PPC_GOT_LO:
    158         Type = ELF::R_PPC_GOT16_LO;
    159         break;
    160       case MCSymbolRefExpr::VK_PPC_GOT_HI:
    161         Type = ELF::R_PPC_GOT16_HI;
    162         break;
    163       case MCSymbolRefExpr::VK_PPC_GOT_HA:
    164         Type = ELF::R_PPC_GOT16_HA;
    165         break;
    166       case MCSymbolRefExpr::VK_PPC_TOC:
    167         Type = ELF::R_PPC64_TOC16;
    168         break;
    169       case MCSymbolRefExpr::VK_PPC_TOC_LO:
    170         Type = ELF::R_PPC64_TOC16_LO;
    171         break;
    172       case MCSymbolRefExpr::VK_PPC_TOC_HI:
    173         Type = ELF::R_PPC64_TOC16_HI;
    174         break;
    175       case MCSymbolRefExpr::VK_PPC_TOC_HA:
    176         Type = ELF::R_PPC64_TOC16_HA;
    177         break;
    178       case MCSymbolRefExpr::VK_PPC_TPREL:
    179         Type = ELF::R_PPC_TPREL16;
    180         break;
    181       case MCSymbolRefExpr::VK_PPC_TPREL_LO:
    182         Type = ELF::R_PPC_TPREL16_LO;
    183         break;
    184       case MCSymbolRefExpr::VK_PPC_TPREL_HI:
    185         Type = ELF::R_PPC_TPREL16_HI;
    186         break;
    187       case MCSymbolRefExpr::VK_PPC_TPREL_HA:
    188         Type = ELF::R_PPC_TPREL16_HA;
    189         break;
    190       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHER:
    191         Type = ELF::R_PPC64_TPREL16_HIGHER;
    192         break;
    193       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHERA:
    194         Type = ELF::R_PPC64_TPREL16_HIGHERA;
    195         break;
    196       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHEST:
    197         Type = ELF::R_PPC64_TPREL16_HIGHEST;
    198         break;
    199       case MCSymbolRefExpr::VK_PPC_TPREL_HIGHESTA:
    200         Type = ELF::R_PPC64_TPREL16_HIGHESTA;
    201         break;
    202       case MCSymbolRefExpr::VK_PPC_DTPREL:
    203         Type = ELF::R_PPC64_DTPREL16;
    204         break;
    205       case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
    206         Type = ELF::R_PPC64_DTPREL16_LO;
    207         break;
    208       case MCSymbolRefExpr::VK_PPC_DTPREL_HI:
    209         Type = ELF::R_PPC64_DTPREL16_HI;
    210         break;
    211       case MCSymbolRefExpr::VK_PPC_DTPREL_HA:
    212         Type = ELF::R_PPC64_DTPREL16_HA;
    213         break;
    214       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHER:
    215         Type = ELF::R_PPC64_DTPREL16_HIGHER;
    216         break;
    217       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHERA:
    218         Type = ELF::R_PPC64_DTPREL16_HIGHERA;
    219         break;
    220       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHEST:
    221         Type = ELF::R_PPC64_DTPREL16_HIGHEST;
    222         break;
    223       case MCSymbolRefExpr::VK_PPC_DTPREL_HIGHESTA:
    224         Type = ELF::R_PPC64_DTPREL16_HIGHESTA;
    225         break;
    226       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD:
    227         Type = ELF::R_PPC64_GOT_TLSGD16;
    228         break;
    229       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO:
    230         Type = ELF::R_PPC64_GOT_TLSGD16_LO;
    231         break;
    232       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HI:
    233         Type = ELF::R_PPC64_GOT_TLSGD16_HI;
    234         break;
    235       case MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA:
    236         Type = ELF::R_PPC64_GOT_TLSGD16_HA;
    237         break;
    238       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD:
    239         Type = ELF::R_PPC64_GOT_TLSLD16;
    240         break;
    241       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO:
    242         Type = ELF::R_PPC64_GOT_TLSLD16_LO;
    243         break;
    244       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HI:
    245         Type = ELF::R_PPC64_GOT_TLSLD16_HI;
    246         break;
    247       case MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA:
    248         Type = ELF::R_PPC64_GOT_TLSLD16_HA;
    249         break;
    250       case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
    251         /* We don't have R_PPC64_GOT_TPREL16, but since GOT offsets
    252            are always 4-aligned, we can use R_PPC64_GOT_TPREL16_DS.  */
    253         Type = ELF::R_PPC64_GOT_TPREL16_DS;
    254         break;
    255       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
    256         /* We don't have R_PPC64_GOT_TPREL16_LO, but since GOT offsets
    257            are always 4-aligned, we can use R_PPC64_GOT_TPREL16_LO_DS.  */
    258         Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
    259         break;
    260       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HI:
    261         Type = ELF::R_PPC64_GOT_TPREL16_HI;
    262         break;
    263       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
    264         /* We don't have R_PPC64_GOT_DTPREL16, but since GOT offsets
    265            are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_DS.  */
    266         Type = ELF::R_PPC64_GOT_DTPREL16_DS;
    267         break;
    268       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
    269         /* We don't have R_PPC64_GOT_DTPREL16_LO, but since GOT offsets
    270            are always 4-aligned, we can use R_PPC64_GOT_DTPREL16_LO_DS.  */
    271         Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
    272         break;
    273       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA:
    274         Type = ELF::R_PPC64_GOT_TPREL16_HA;
    275         break;
    276       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HI:
    277         Type = ELF::R_PPC64_GOT_DTPREL16_HI;
    278         break;
    279       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_HA:
    280         Type = ELF::R_PPC64_GOT_DTPREL16_HA;
    281         break;
    282       }
    283       break;
    284     case PPC::fixup_ppc_half16ds:
    285       switch (Modifier) {
    286       default: llvm_unreachable("Unsupported Modifier");
    287       case MCSymbolRefExpr::VK_None:
    288         Type = ELF::R_PPC64_ADDR16_DS;
    289         break;
    290       case MCSymbolRefExpr::VK_PPC_LO:
    291         Type = ELF::R_PPC64_ADDR16_LO_DS;
    292         break;
    293       case MCSymbolRefExpr::VK_GOT:
    294         Type = ELF::R_PPC64_GOT16_DS;
    295 	break;
    296       case MCSymbolRefExpr::VK_PPC_GOT_LO:
    297         Type = ELF::R_PPC64_GOT16_LO_DS;
    298         break;
    299       case MCSymbolRefExpr::VK_PPC_TOC:
    300         Type = ELF::R_PPC64_TOC16_DS;
    301 	break;
    302       case MCSymbolRefExpr::VK_PPC_TOC_LO:
    303         Type = ELF::R_PPC64_TOC16_LO_DS;
    304         break;
    305       case MCSymbolRefExpr::VK_PPC_TPREL:
    306         Type = ELF::R_PPC64_TPREL16_DS;
    307         break;
    308       case MCSymbolRefExpr::VK_PPC_TPREL_LO:
    309         Type = ELF::R_PPC64_TPREL16_LO_DS;
    310         break;
    311       case MCSymbolRefExpr::VK_PPC_DTPREL:
    312         Type = ELF::R_PPC64_DTPREL16_DS;
    313         break;
    314       case MCSymbolRefExpr::VK_PPC_DTPREL_LO:
    315         Type = ELF::R_PPC64_DTPREL16_LO_DS;
    316         break;
    317       case MCSymbolRefExpr::VK_PPC_GOT_TPREL:
    318         Type = ELF::R_PPC64_GOT_TPREL16_DS;
    319         break;
    320       case MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO:
    321         Type = ELF::R_PPC64_GOT_TPREL16_LO_DS;
    322         break;
    323       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL:
    324         Type = ELF::R_PPC64_GOT_DTPREL16_DS;
    325         break;
    326       case MCSymbolRefExpr::VK_PPC_GOT_DTPREL_LO:
    327         Type = ELF::R_PPC64_GOT_DTPREL16_LO_DS;
    328         break;
    329       }
    330       break;
    331     case PPC::fixup_ppc_nofixup:
    332       switch (Modifier) {
    333       default: llvm_unreachable("Unsupported Modifier");
    334       case MCSymbolRefExpr::VK_PPC_TLSGD:
    335         Type = ELF::R_PPC64_TLSGD;
    336         break;
    337       case MCSymbolRefExpr::VK_PPC_TLSLD:
    338         Type = ELF::R_PPC64_TLSLD;
    339         break;
    340       case MCSymbolRefExpr::VK_PPC_TLS:
    341         Type = ELF::R_PPC64_TLS;
    342         break;
    343       }
    344       break;
    345     case FK_Data_8:
    346       switch (Modifier) {
    347       default: llvm_unreachable("Unsupported Modifier");
    348       case MCSymbolRefExpr::VK_PPC_TOCBASE:
    349         Type = ELF::R_PPC64_TOC;
    350         break;
    351       case MCSymbolRefExpr::VK_None:
    352         Type = ELF::R_PPC64_ADDR64;
    353 	break;
    354       case MCSymbolRefExpr::VK_PPC_DTPMOD:
    355         Type = ELF::R_PPC64_DTPMOD64;
    356 	break;
    357       case MCSymbolRefExpr::VK_PPC_TPREL:
    358         Type = ELF::R_PPC64_TPREL64;
    359 	break;
    360       case MCSymbolRefExpr::VK_PPC_DTPREL:
    361         Type = ELF::R_PPC64_DTPREL64;
    362 	break;
    363       }
    364       break;
    365     case FK_Data_4:
    366       Type = ELF::R_PPC_ADDR32;
    367       break;
    368     case FK_Data_2:
    369       Type = ELF::R_PPC_ADDR16;
    370       break;
    371     }
    372   }
    373   return Type;
    374 }
    375 
    376 unsigned PPCELFObjectWriter::GetRelocType(const MCValue &Target,
    377                                           const MCFixup &Fixup,
    378                                           bool IsPCRel) const {
    379   return getRelocTypeInner(Target, Fixup, IsPCRel);
    380 }
    381 
    382 MCObjectWriter *llvm::createPPCELFObjectWriter(raw_ostream &OS,
    383                                                bool Is64Bit,
    384                                                bool IsLittleEndian,
    385                                                uint8_t OSABI) {
    386   MCELFObjectTargetWriter *MOTW = new PPCELFObjectWriter(Is64Bit, OSABI);
    387   return createELFObjectWriter(MOTW, OS, IsLittleEndian);
    388 }
    389