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