Home | History | Annotate | Line # | Download | only in MCTargetDesc
      1 //===-------- PPCELFStreamer.cpp - ELF Object Output ---------------------===//
      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 // This is a custom MCELFStreamer for PowerPC.
     11 //
     12 // The purpose of the custom ELF streamer is to allow us to intercept
     13 // instructions as they are being emitted and align all 8 byte instructions
     14 // to a 64 byte boundary if required (by adding a 4 byte nop). This is important
     15 // because 8 byte instructions are not allowed to cross 64 byte boundaries
     16 // and by aliging anything that is within 4 bytes of the boundary we can
     17 // guarantee that the 8 byte instructions do not cross that boundary.
     18 //
     19 //===----------------------------------------------------------------------===//
     20 
     21 
     22 #include "PPCELFStreamer.h"
     23 #include "PPCFixupKinds.h"
     24 #include "PPCInstrInfo.h"
     25 #include "PPCMCCodeEmitter.h"
     26 #include "llvm/BinaryFormat/ELF.h"
     27 #include "llvm/MC/MCAsmBackend.h"
     28 #include "llvm/MC/MCAssembler.h"
     29 #include "llvm/MC/MCCodeEmitter.h"
     30 #include "llvm/MC/MCContext.h"
     31 #include "llvm/MC/MCInst.h"
     32 #include "llvm/MC/MCInstrDesc.h"
     33 #include "llvm/MC/MCObjectWriter.h"
     34 #include "llvm/MC/MCSymbolELF.h"
     35 #include "llvm/Support/Casting.h"
     36 #include "llvm/Support/SourceMgr.h"
     37 
     38 using namespace llvm;
     39 
     40 PPCELFStreamer::PPCELFStreamer(MCContext &Context,
     41                                std::unique_ptr<MCAsmBackend> MAB,
     42                                std::unique_ptr<MCObjectWriter> OW,
     43                                std::unique_ptr<MCCodeEmitter> Emitter)
     44     : MCELFStreamer(Context, std::move(MAB), std::move(OW),
     45                     std::move(Emitter)), LastLabel(NULL) {
     46 }
     47 
     48 void PPCELFStreamer::emitPrefixedInstruction(const MCInst &Inst,
     49                                              const MCSubtargetInfo &STI) {
     50   // Prefixed instructions must not cross a 64-byte boundary (i.e. prefix is
     51   // before the boundary and the remaining 4-bytes are after the boundary). In
     52   // order to achieve this, a nop is added prior to any such boundary-crossing
     53   // prefixed instruction. Align to 64 bytes if possible but add a maximum of 4
     54   // bytes when trying to do that. If alignment requires adding more than 4
     55   // bytes then the instruction won't be aligned. When emitting a code alignment
     56   // a new fragment is created for this alignment. This fragment will contain
     57   // all of the nops required as part of the alignment operation. In the cases
     58   // when no nops are added then The fragment is still created but it remains
     59   // empty.
     60   emitCodeAlignment(64, 4);
     61 
     62   // Emit the instruction.
     63   // Since the previous emit created a new fragment then adding this instruction
     64   // also forces the addition of a new fragment. Inst is now the first
     65   // instruction in that new fragment.
     66   MCELFStreamer::emitInstruction(Inst, STI);
     67 
     68   // The above instruction is forced to start a new fragment because it
     69   // comes after a code alignment fragment. Get that new fragment.
     70   MCFragment *InstructionFragment = getCurrentFragment();
     71   SMLoc InstLoc = Inst.getLoc();
     72   // Check if there was a last label emitted.
     73   if (LastLabel && !LastLabel->isUnset() && LastLabelLoc.isValid() &&
     74       InstLoc.isValid()) {
     75     const SourceMgr *SourceManager = getContext().getSourceManager();
     76     unsigned InstLine = SourceManager->FindLineNumber(InstLoc);
     77     unsigned LabelLine = SourceManager->FindLineNumber(LastLabelLoc);
     78     // If the Label and the Instruction are on the same line then move the
     79     // label to the top of the fragment containing the aligned instruction that
     80     // was just added.
     81     if (InstLine == LabelLine) {
     82       AssignFragment(LastLabel, InstructionFragment);
     83       LastLabel->setOffset(0);
     84     }
     85   }
     86 }
     87 
     88 void PPCELFStreamer::emitInstruction(const MCInst &Inst,
     89                                      const MCSubtargetInfo &STI) {
     90   PPCMCCodeEmitter *Emitter =
     91       static_cast<PPCMCCodeEmitter*>(getAssembler().getEmitterPtr());
     92 
     93   // If the instruction is a part of the GOT to PC-Rel link time optimization
     94   // instruction pair, return a value, otherwise return None. A true returned
     95   // value means the instruction is the PLDpc and a false value means it is
     96   // the user instruction.
     97   Optional<bool> IsPartOfGOTToPCRelPair = isPartOfGOTToPCRelPair(Inst, STI);
     98 
     99   // User of the GOT-indirect address.
    100   // For example, the load that will get the relocation as follows:
    101   // .reloc .Lpcrel1-8,R_PPC64_PCREL_OPT,.-(.Lpcrel1-8)
    102   //  lwa 3, 4(3)
    103   if (IsPartOfGOTToPCRelPair.hasValue() && !IsPartOfGOTToPCRelPair.getValue())
    104     emitGOTToPCRelReloc(Inst);
    105 
    106   // Special handling is only for prefixed instructions.
    107   if (!Emitter->isPrefixedInstruction(Inst)) {
    108     MCELFStreamer::emitInstruction(Inst, STI);
    109     return;
    110   }
    111   emitPrefixedInstruction(Inst, STI);
    112 
    113   // Producer of the GOT-indirect address.
    114   // For example, the prefixed load from the got that will get the label as
    115   // follows:
    116   //  pld 3, vec@got@pcrel(0), 1
    117   // .Lpcrel1:
    118   if (IsPartOfGOTToPCRelPair.hasValue() && IsPartOfGOTToPCRelPair.getValue())
    119     emitGOTToPCRelLabel(Inst);
    120 }
    121 
    122 void PPCELFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
    123   LastLabel = Symbol;
    124   LastLabelLoc = Loc;
    125   MCELFStreamer::emitLabel(Symbol);
    126 }
    127 
    128 // This linker time GOT PC Relative optimization relocation will look like this:
    129 //   pld <reg> symbol@got@pcrel
    130 // <Label###>:
    131 //   .reloc Label###-8,R_PPC64_PCREL_OPT,.-(Label###-8)
    132 //   load <loadedreg>, 0(<reg>)
    133 // The reason we place the label after the PLDpc instruction is that there
    134 // may be an alignment nop before it since prefixed instructions must not
    135 // cross a 64-byte boundary (please see
    136 // PPCELFStreamer::emitPrefixedInstruction()). When referring to the
    137 // label, we subtract the width of a prefixed instruction (8 bytes) to ensure
    138 // we refer to the PLDpc.
    139 void PPCELFStreamer::emitGOTToPCRelReloc(const MCInst &Inst) {
    140   // Get the last operand which contains the symbol.
    141   const MCOperand &Operand = Inst.getOperand(Inst.getNumOperands() - 1);
    142   assert(Operand.isExpr() && "Expecting an MCExpr.");
    143   // Cast the last operand to MCSymbolRefExpr to get the symbol.
    144   const MCExpr *Expr = Operand.getExpr();
    145   const MCSymbolRefExpr *SymExpr = static_cast<const MCSymbolRefExpr *>(Expr);
    146   assert(SymExpr->getKind() == MCSymbolRefExpr::VK_PPC_PCREL_OPT &&
    147          "Expecting a symbol of type VK_PPC_PCREL_OPT");
    148   MCSymbol *LabelSym =
    149       getContext().getOrCreateSymbol(SymExpr->getSymbol().getName());
    150   const MCExpr *LabelExpr = MCSymbolRefExpr::create(LabelSym, getContext());
    151   const MCExpr *Eight = MCConstantExpr::create(8, getContext());
    152   // SubExpr is just Label###-8
    153   const MCExpr *SubExpr =
    154       MCBinaryExpr::createSub(LabelExpr, Eight, getContext());
    155   MCSymbol *CurrentLocation = getContext().createTempSymbol();
    156   const MCExpr *CurrentLocationExpr =
    157       MCSymbolRefExpr::create(CurrentLocation, getContext());
    158   // SubExpr2 is .-(Label###-8)
    159   const MCExpr *SubExpr2 =
    160       MCBinaryExpr::createSub(CurrentLocationExpr, SubExpr, getContext());
    161 
    162   MCDataFragment *DF = static_cast<MCDataFragment *>(LabelSym->getFragment());
    163   assert(DF && "Expecting a valid data fragment.");
    164   MCFixupKind FixupKind = static_cast<MCFixupKind>(FirstLiteralRelocationKind +
    165                                                    ELF::R_PPC64_PCREL_OPT);
    166   DF->getFixups().push_back(
    167       MCFixup::create(LabelSym->getOffset() - 8, SubExpr2,
    168                       FixupKind, Inst.getLoc()));
    169   emitLabel(CurrentLocation, Inst.getLoc());
    170 }
    171 
    172 // Emit the label that immediately follows the PLDpc for a link time GOT PC Rel
    173 // optimization.
    174 void PPCELFStreamer::emitGOTToPCRelLabel(const MCInst &Inst) {
    175   // Get the last operand which contains the symbol.
    176   const MCOperand &Operand = Inst.getOperand(Inst.getNumOperands() - 1);
    177   assert(Operand.isExpr() && "Expecting an MCExpr.");
    178   // Cast the last operand to MCSymbolRefExpr to get the symbol.
    179   const MCExpr *Expr = Operand.getExpr();
    180   const MCSymbolRefExpr *SymExpr = static_cast<const MCSymbolRefExpr *>(Expr);
    181   assert(SymExpr->getKind() == MCSymbolRefExpr::VK_PPC_PCREL_OPT &&
    182          "Expecting a symbol of type VK_PPC_PCREL_OPT");
    183   MCSymbol *LabelSym =
    184       getContext().getOrCreateSymbol(SymExpr->getSymbol().getName());
    185   emitLabel(LabelSym, Inst.getLoc());
    186 }
    187 
    188 // This funciton checks if the parameter Inst is part of the setup for a link
    189 // time GOT PC Relative optimization. For example in this situation:
    190 // <MCInst PLDpc <MCOperand Reg:282> <MCOperand Expr:(glob_double@got@pcrel)>
    191 //   <MCOperand Imm:0> <MCOperand Expr:(.Lpcrel@<<invalid>>)>>
    192 // <MCInst SOME_LOAD <MCOperand Reg:22> <MCOperand Imm:0> <MCOperand Reg:282>
    193 //   <MCOperand Expr:(.Lpcrel@<<invalid>>)>>
    194 // The above is a pair of such instructions and this function will not return
    195 // None for either one of them. In both cases we are looking for the last
    196 // operand <MCOperand Expr:(.Lpcrel@<<invalid>>)> which needs to be an MCExpr
    197 // and has the flag MCSymbolRefExpr::VK_PPC_PCREL_OPT. After that we just look
    198 // at the opcode and in the case of PLDpc we will return true. For the load
    199 // (or store) this function will return false indicating it has found the second
    200 // instruciton in the pair.
    201 Optional<bool> llvm::isPartOfGOTToPCRelPair(const MCInst &Inst,
    202                                             const MCSubtargetInfo &STI) {
    203   // Need at least two operands.
    204   if (Inst.getNumOperands() < 2)
    205     return None;
    206 
    207   unsigned LastOp = Inst.getNumOperands() - 1;
    208   // The last operand needs to be an MCExpr and it needs to have a variant kind
    209   // of VK_PPC_PCREL_OPT. If it does not satisfy these conditions it is not a
    210   // link time GOT PC Rel opt instruction and we can ignore it and return None.
    211   const MCOperand &Operand = Inst.getOperand(LastOp);
    212   if (!Operand.isExpr())
    213     return None;
    214 
    215   // Check for the variant kind VK_PPC_PCREL_OPT in this expression.
    216   const MCExpr *Expr = Operand.getExpr();
    217   const MCSymbolRefExpr *SymExpr = static_cast<const MCSymbolRefExpr *>(Expr);
    218   if (!SymExpr || SymExpr->getKind() != MCSymbolRefExpr::VK_PPC_PCREL_OPT)
    219     return None;
    220 
    221   return (Inst.getOpcode() == PPC::PLDpc);
    222 }
    223 
    224 MCELFStreamer *llvm::createPPCELFStreamer(
    225     MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
    226     std::unique_ptr<MCObjectWriter> OW,
    227     std::unique_ptr<MCCodeEmitter> Emitter) {
    228   return new PPCELFStreamer(Context, std::move(MAB), std::move(OW),
    229                             std::move(Emitter));
    230 }
    231