15ffd83dbSDimitry Andric //===-------- PPCELFStreamer.cpp - ELF Object Output ---------------------===// 25ffd83dbSDimitry Andric // 3349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric // 95ffd83dbSDimitry Andric // This is a custom MCELFStreamer for PowerPC. 105ffd83dbSDimitry Andric // 115ffd83dbSDimitry Andric // The purpose of the custom ELF streamer is to allow us to intercept 125ffd83dbSDimitry Andric // instructions as they are being emitted and align all 8 byte instructions 135ffd83dbSDimitry Andric // to a 64 byte boundary if required (by adding a 4 byte nop). This is important 145ffd83dbSDimitry Andric // because 8 byte instructions are not allowed to cross 64 byte boundaries 155ffd83dbSDimitry Andric // and by aliging anything that is within 4 bytes of the boundary we can 165ffd83dbSDimitry Andric // guarantee that the 8 byte instructions do not cross that boundary. 175ffd83dbSDimitry Andric // 185ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 195ffd83dbSDimitry Andric 205ffd83dbSDimitry Andric #include "PPCELFStreamer.h" 21e8d8bef9SDimitry Andric #include "PPCFixupKinds.h" 225ffd83dbSDimitry Andric #include "PPCMCCodeEmitter.h" 235f757f3fSDimitry Andric #include "PPCMCTargetDesc.h" 245ffd83dbSDimitry Andric #include "llvm/BinaryFormat/ELF.h" 255ffd83dbSDimitry Andric #include "llvm/MC/MCAsmBackend.h" 265ffd83dbSDimitry Andric #include "llvm/MC/MCAssembler.h" 275ffd83dbSDimitry Andric #include "llvm/MC/MCCodeEmitter.h" 285ffd83dbSDimitry Andric #include "llvm/MC/MCContext.h" 295ffd83dbSDimitry Andric #include "llvm/MC/MCInst.h" 305ffd83dbSDimitry Andric #include "llvm/MC/MCInstrDesc.h" 315ffd83dbSDimitry Andric #include "llvm/MC/MCObjectWriter.h" 325ffd83dbSDimitry Andric #include "llvm/MC/MCSymbolELF.h" 335ffd83dbSDimitry Andric #include "llvm/Support/Casting.h" 345ffd83dbSDimitry Andric #include "llvm/Support/SourceMgr.h" 355ffd83dbSDimitry Andric 365ffd83dbSDimitry Andric using namespace llvm; 375ffd83dbSDimitry Andric 385ffd83dbSDimitry Andric PPCELFStreamer::PPCELFStreamer(MCContext &Context, 395ffd83dbSDimitry Andric std::unique_ptr<MCAsmBackend> MAB, 405ffd83dbSDimitry Andric std::unique_ptr<MCObjectWriter> OW, 415ffd83dbSDimitry Andric std::unique_ptr<MCCodeEmitter> Emitter) 4204eeddc0SDimitry Andric : MCELFStreamer(Context, std::move(MAB), std::move(OW), std::move(Emitter)), 4304eeddc0SDimitry Andric LastLabel(nullptr) {} 445ffd83dbSDimitry Andric 455ffd83dbSDimitry Andric void PPCELFStreamer::emitPrefixedInstruction(const MCInst &Inst, 465ffd83dbSDimitry Andric const MCSubtargetInfo &STI) { 475ffd83dbSDimitry Andric // Prefixed instructions must not cross a 64-byte boundary (i.e. prefix is 485ffd83dbSDimitry Andric // before the boundary and the remaining 4-bytes are after the boundary). In 495ffd83dbSDimitry Andric // order to achieve this, a nop is added prior to any such boundary-crossing 505ffd83dbSDimitry Andric // prefixed instruction. Align to 64 bytes if possible but add a maximum of 4 515ffd83dbSDimitry Andric // bytes when trying to do that. If alignment requires adding more than 4 525ffd83dbSDimitry Andric // bytes then the instruction won't be aligned. When emitting a code alignment 535ffd83dbSDimitry Andric // a new fragment is created for this alignment. This fragment will contain 545ffd83dbSDimitry Andric // all of the nops required as part of the alignment operation. In the cases 555ffd83dbSDimitry Andric // when no nops are added then The fragment is still created but it remains 565ffd83dbSDimitry Andric // empty. 57bdd1243dSDimitry Andric emitCodeAlignment(Align(64), &STI, 4); 585ffd83dbSDimitry Andric 595ffd83dbSDimitry Andric // Emit the instruction. 605ffd83dbSDimitry Andric // Since the previous emit created a new fragment then adding this instruction 615ffd83dbSDimitry Andric // also forces the addition of a new fragment. Inst is now the first 625ffd83dbSDimitry Andric // instruction in that new fragment. 635ffd83dbSDimitry Andric MCELFStreamer::emitInstruction(Inst, STI); 645ffd83dbSDimitry Andric 655ffd83dbSDimitry Andric // The above instruction is forced to start a new fragment because it 665ffd83dbSDimitry Andric // comes after a code alignment fragment. Get that new fragment. 675ffd83dbSDimitry Andric MCFragment *InstructionFragment = getCurrentFragment(); 685ffd83dbSDimitry Andric SMLoc InstLoc = Inst.getLoc(); 695ffd83dbSDimitry Andric // Check if there was a last label emitted. 705ffd83dbSDimitry Andric if (LastLabel && !LastLabel->isUnset() && LastLabelLoc.isValid() && 715ffd83dbSDimitry Andric InstLoc.isValid()) { 725ffd83dbSDimitry Andric const SourceMgr *SourceManager = getContext().getSourceManager(); 735ffd83dbSDimitry Andric unsigned InstLine = SourceManager->FindLineNumber(InstLoc); 745ffd83dbSDimitry Andric unsigned LabelLine = SourceManager->FindLineNumber(LastLabelLoc); 755ffd83dbSDimitry Andric // If the Label and the Instruction are on the same line then move the 765ffd83dbSDimitry Andric // label to the top of the fragment containing the aligned instruction that 775ffd83dbSDimitry Andric // was just added. 785ffd83dbSDimitry Andric if (InstLine == LabelLine) { 79*0fca6ea1SDimitry Andric LastLabel->setFragment(InstructionFragment); 805ffd83dbSDimitry Andric LastLabel->setOffset(0); 815ffd83dbSDimitry Andric } 825ffd83dbSDimitry Andric } 835ffd83dbSDimitry Andric } 845ffd83dbSDimitry Andric 855ffd83dbSDimitry Andric void PPCELFStreamer::emitInstruction(const MCInst &Inst, 865ffd83dbSDimitry Andric const MCSubtargetInfo &STI) { 875ffd83dbSDimitry Andric PPCMCCodeEmitter *Emitter = 885ffd83dbSDimitry Andric static_cast<PPCMCCodeEmitter*>(getAssembler().getEmitterPtr()); 895ffd83dbSDimitry Andric 90e8d8bef9SDimitry Andric // If the instruction is a part of the GOT to PC-Rel link time optimization 91bdd1243dSDimitry Andric // instruction pair, return a value, otherwise return std::nullopt. A true 92bdd1243dSDimitry Andric // returned value means the instruction is the PLDpc and a false value means 93bdd1243dSDimitry Andric // it is the user instruction. 94bdd1243dSDimitry Andric std::optional<bool> IsPartOfGOTToPCRelPair = 95bdd1243dSDimitry Andric isPartOfGOTToPCRelPair(Inst, STI); 96e8d8bef9SDimitry Andric 97e8d8bef9SDimitry Andric // User of the GOT-indirect address. 98e8d8bef9SDimitry Andric // For example, the load that will get the relocation as follows: 99e8d8bef9SDimitry Andric // .reloc .Lpcrel1-8,R_PPC64_PCREL_OPT,.-(.Lpcrel1-8) 100e8d8bef9SDimitry Andric // lwa 3, 4(3) 10181ad6265SDimitry Andric if (IsPartOfGOTToPCRelPair && !*IsPartOfGOTToPCRelPair) 102e8d8bef9SDimitry Andric emitGOTToPCRelReloc(Inst); 103e8d8bef9SDimitry Andric 1045ffd83dbSDimitry Andric // Special handling is only for prefixed instructions. 1055ffd83dbSDimitry Andric if (!Emitter->isPrefixedInstruction(Inst)) { 1065ffd83dbSDimitry Andric MCELFStreamer::emitInstruction(Inst, STI); 1075ffd83dbSDimitry Andric return; 1085ffd83dbSDimitry Andric } 1095ffd83dbSDimitry Andric emitPrefixedInstruction(Inst, STI); 110e8d8bef9SDimitry Andric 111e8d8bef9SDimitry Andric // Producer of the GOT-indirect address. 112e8d8bef9SDimitry Andric // For example, the prefixed load from the got that will get the label as 113e8d8bef9SDimitry Andric // follows: 114e8d8bef9SDimitry Andric // pld 3, vec@got@pcrel(0), 1 115e8d8bef9SDimitry Andric // .Lpcrel1: 11681ad6265SDimitry Andric if (IsPartOfGOTToPCRelPair && *IsPartOfGOTToPCRelPair) 117e8d8bef9SDimitry Andric emitGOTToPCRelLabel(Inst); 1185ffd83dbSDimitry Andric } 1195ffd83dbSDimitry Andric 1205ffd83dbSDimitry Andric void PPCELFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) { 1215ffd83dbSDimitry Andric LastLabel = Symbol; 1225ffd83dbSDimitry Andric LastLabelLoc = Loc; 1235ffd83dbSDimitry Andric MCELFStreamer::emitLabel(Symbol); 1245ffd83dbSDimitry Andric } 1255ffd83dbSDimitry Andric 126e8d8bef9SDimitry Andric // This linker time GOT PC Relative optimization relocation will look like this: 127e8d8bef9SDimitry Andric // pld <reg> symbol@got@pcrel 128e8d8bef9SDimitry Andric // <Label###>: 129e8d8bef9SDimitry Andric // .reloc Label###-8,R_PPC64_PCREL_OPT,.-(Label###-8) 130e8d8bef9SDimitry Andric // load <loadedreg>, 0(<reg>) 131e8d8bef9SDimitry Andric // The reason we place the label after the PLDpc instruction is that there 132e8d8bef9SDimitry Andric // may be an alignment nop before it since prefixed instructions must not 133e8d8bef9SDimitry Andric // cross a 64-byte boundary (please see 134e8d8bef9SDimitry Andric // PPCELFStreamer::emitPrefixedInstruction()). When referring to the 135e8d8bef9SDimitry Andric // label, we subtract the width of a prefixed instruction (8 bytes) to ensure 136e8d8bef9SDimitry Andric // we refer to the PLDpc. 137e8d8bef9SDimitry Andric void PPCELFStreamer::emitGOTToPCRelReloc(const MCInst &Inst) { 138e8d8bef9SDimitry Andric // Get the last operand which contains the symbol. 139e8d8bef9SDimitry Andric const MCOperand &Operand = Inst.getOperand(Inst.getNumOperands() - 1); 140e8d8bef9SDimitry Andric assert(Operand.isExpr() && "Expecting an MCExpr."); 141e8d8bef9SDimitry Andric // Cast the last operand to MCSymbolRefExpr to get the symbol. 142e8d8bef9SDimitry Andric const MCExpr *Expr = Operand.getExpr(); 143e8d8bef9SDimitry Andric const MCSymbolRefExpr *SymExpr = static_cast<const MCSymbolRefExpr *>(Expr); 144e8d8bef9SDimitry Andric assert(SymExpr->getKind() == MCSymbolRefExpr::VK_PPC_PCREL_OPT && 145e8d8bef9SDimitry Andric "Expecting a symbol of type VK_PPC_PCREL_OPT"); 146e8d8bef9SDimitry Andric MCSymbol *LabelSym = 147e8d8bef9SDimitry Andric getContext().getOrCreateSymbol(SymExpr->getSymbol().getName()); 148e8d8bef9SDimitry Andric const MCExpr *LabelExpr = MCSymbolRefExpr::create(LabelSym, getContext()); 149e8d8bef9SDimitry Andric const MCExpr *Eight = MCConstantExpr::create(8, getContext()); 150e8d8bef9SDimitry Andric // SubExpr is just Label###-8 151e8d8bef9SDimitry Andric const MCExpr *SubExpr = 152e8d8bef9SDimitry Andric MCBinaryExpr::createSub(LabelExpr, Eight, getContext()); 153e8d8bef9SDimitry Andric MCSymbol *CurrentLocation = getContext().createTempSymbol(); 154e8d8bef9SDimitry Andric const MCExpr *CurrentLocationExpr = 155e8d8bef9SDimitry Andric MCSymbolRefExpr::create(CurrentLocation, getContext()); 156e8d8bef9SDimitry Andric // SubExpr2 is .-(Label###-8) 157e8d8bef9SDimitry Andric const MCExpr *SubExpr2 = 158e8d8bef9SDimitry Andric MCBinaryExpr::createSub(CurrentLocationExpr, SubExpr, getContext()); 159e8d8bef9SDimitry Andric 160e8d8bef9SDimitry Andric MCDataFragment *DF = static_cast<MCDataFragment *>(LabelSym->getFragment()); 161e8d8bef9SDimitry Andric assert(DF && "Expecting a valid data fragment."); 162e8d8bef9SDimitry Andric MCFixupKind FixupKind = static_cast<MCFixupKind>(FirstLiteralRelocationKind + 163e8d8bef9SDimitry Andric ELF::R_PPC64_PCREL_OPT); 164e8d8bef9SDimitry Andric DF->getFixups().push_back( 165e8d8bef9SDimitry Andric MCFixup::create(LabelSym->getOffset() - 8, SubExpr2, 166e8d8bef9SDimitry Andric FixupKind, Inst.getLoc())); 167e8d8bef9SDimitry Andric emitLabel(CurrentLocation, Inst.getLoc()); 168e8d8bef9SDimitry Andric } 169e8d8bef9SDimitry Andric 170e8d8bef9SDimitry Andric // Emit the label that immediately follows the PLDpc for a link time GOT PC Rel 171e8d8bef9SDimitry Andric // optimization. 172e8d8bef9SDimitry Andric void PPCELFStreamer::emitGOTToPCRelLabel(const MCInst &Inst) { 173e8d8bef9SDimitry Andric // Get the last operand which contains the symbol. 174e8d8bef9SDimitry Andric const MCOperand &Operand = Inst.getOperand(Inst.getNumOperands() - 1); 175e8d8bef9SDimitry Andric assert(Operand.isExpr() && "Expecting an MCExpr."); 176e8d8bef9SDimitry Andric // Cast the last operand to MCSymbolRefExpr to get the symbol. 177e8d8bef9SDimitry Andric const MCExpr *Expr = Operand.getExpr(); 178e8d8bef9SDimitry Andric const MCSymbolRefExpr *SymExpr = static_cast<const MCSymbolRefExpr *>(Expr); 179e8d8bef9SDimitry Andric assert(SymExpr->getKind() == MCSymbolRefExpr::VK_PPC_PCREL_OPT && 180e8d8bef9SDimitry Andric "Expecting a symbol of type VK_PPC_PCREL_OPT"); 181e8d8bef9SDimitry Andric MCSymbol *LabelSym = 182e8d8bef9SDimitry Andric getContext().getOrCreateSymbol(SymExpr->getSymbol().getName()); 183e8d8bef9SDimitry Andric emitLabel(LabelSym, Inst.getLoc()); 184e8d8bef9SDimitry Andric } 185e8d8bef9SDimitry Andric 18606c3fb27SDimitry Andric // This function checks if the parameter Inst is part of the setup for a link 187e8d8bef9SDimitry Andric // time GOT PC Relative optimization. For example in this situation: 188e8d8bef9SDimitry Andric // <MCInst PLDpc <MCOperand Reg:282> <MCOperand Expr:(glob_double@got@pcrel)> 189e8d8bef9SDimitry Andric // <MCOperand Imm:0> <MCOperand Expr:(.Lpcrel@<<invalid>>)>> 190e8d8bef9SDimitry Andric // <MCInst SOME_LOAD <MCOperand Reg:22> <MCOperand Imm:0> <MCOperand Reg:282> 191e8d8bef9SDimitry Andric // <MCOperand Expr:(.Lpcrel@<<invalid>>)>> 192e8d8bef9SDimitry Andric // The above is a pair of such instructions and this function will not return 193bdd1243dSDimitry Andric // std::nullopt for either one of them. In both cases we are looking for the 194bdd1243dSDimitry Andric // last operand <MCOperand Expr:(.Lpcrel@<<invalid>>)> which needs to be an 195bdd1243dSDimitry Andric // MCExpr and has the flag MCSymbolRefExpr::VK_PPC_PCREL_OPT. After that we just 196bdd1243dSDimitry Andric // look at the opcode and in the case of PLDpc we will return true. For the load 197e8d8bef9SDimitry Andric // (or store) this function will return false indicating it has found the second 198e8d8bef9SDimitry Andric // instruciton in the pair. 199bdd1243dSDimitry Andric std::optional<bool> llvm::isPartOfGOTToPCRelPair(const MCInst &Inst, 200e8d8bef9SDimitry Andric const MCSubtargetInfo &STI) { 201e8d8bef9SDimitry Andric // Need at least two operands. 202e8d8bef9SDimitry Andric if (Inst.getNumOperands() < 2) 203bdd1243dSDimitry Andric return std::nullopt; 204e8d8bef9SDimitry Andric 205e8d8bef9SDimitry Andric unsigned LastOp = Inst.getNumOperands() - 1; 206e8d8bef9SDimitry Andric // The last operand needs to be an MCExpr and it needs to have a variant kind 207e8d8bef9SDimitry Andric // of VK_PPC_PCREL_OPT. If it does not satisfy these conditions it is not a 208bdd1243dSDimitry Andric // link time GOT PC Rel opt instruction and we can ignore it and return 209bdd1243dSDimitry Andric // std::nullopt. 210e8d8bef9SDimitry Andric const MCOperand &Operand = Inst.getOperand(LastOp); 211e8d8bef9SDimitry Andric if (!Operand.isExpr()) 212bdd1243dSDimitry Andric return std::nullopt; 213e8d8bef9SDimitry Andric 214e8d8bef9SDimitry Andric // Check for the variant kind VK_PPC_PCREL_OPT in this expression. 215e8d8bef9SDimitry Andric const MCExpr *Expr = Operand.getExpr(); 216e8d8bef9SDimitry Andric const MCSymbolRefExpr *SymExpr = static_cast<const MCSymbolRefExpr *>(Expr); 217e8d8bef9SDimitry Andric if (!SymExpr || SymExpr->getKind() != MCSymbolRefExpr::VK_PPC_PCREL_OPT) 218bdd1243dSDimitry Andric return std::nullopt; 219e8d8bef9SDimitry Andric 220e8d8bef9SDimitry Andric return (Inst.getOpcode() == PPC::PLDpc); 221e8d8bef9SDimitry Andric } 222e8d8bef9SDimitry Andric 2235ffd83dbSDimitry Andric MCELFStreamer *llvm::createPPCELFStreamer( 2245ffd83dbSDimitry Andric MCContext &Context, std::unique_ptr<MCAsmBackend> MAB, 2255ffd83dbSDimitry Andric std::unique_ptr<MCObjectWriter> OW, 2265ffd83dbSDimitry Andric std::unique_ptr<MCCodeEmitter> Emitter) { 2275ffd83dbSDimitry Andric return new PPCELFStreamer(Context, std::move(MAB), std::move(OW), 2285ffd83dbSDimitry Andric std::move(Emitter)); 2295ffd83dbSDimitry Andric } 230