//===-------- PPCELFStreamer.cpp - ELF Object Output ---------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This is a custom MCELFStreamer for PowerPC. // // The purpose of the custom ELF streamer is to allow us to intercept // instructions as they are being emitted and align all 8 byte instructions // to a 64 byte boundary if required (by adding a 4 byte nop). This is important // because 8 byte instructions are not allowed to cross 64 byte boundaries // and by aliging anything that is within 4 bytes of the boundary we can // guarantee that the 8 byte instructions do not cross that boundary. // //===----------------------------------------------------------------------===// #include "PPCELFStreamer.h" #include "PPCFixupKinds.h" #include "PPCMCCodeEmitter.h" #include "PPCMCTargetDesc.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/MCAsmBackend.h" #include "llvm/MC/MCAssembler.h" #include "llvm/MC/MCCodeEmitter.h" #include "llvm/MC/MCContext.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCInstrDesc.h" #include "llvm/MC/MCObjectWriter.h" #include "llvm/MC/MCSymbolELF.h" #include "llvm/Support/Casting.h" #include "llvm/Support/SourceMgr.h" usingnamespacellvm; PPCELFStreamer::PPCELFStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB, std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter) : … { … } void PPCELFStreamer::emitPrefixedInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) { … } void PPCELFStreamer::emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) { … } void PPCELFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) { … } // This linker time GOT PC Relative optimization relocation will look like this: // pld <reg> symbol@got@pcrel // <Label###>: // .reloc Label###-8,R_PPC64_PCREL_OPT,.-(Label###-8) // load <loadedreg>, 0(<reg>) // The reason we place the label after the PLDpc instruction is that there // may be an alignment nop before it since prefixed instructions must not // cross a 64-byte boundary (please see // PPCELFStreamer::emitPrefixedInstruction()). When referring to the // label, we subtract the width of a prefixed instruction (8 bytes) to ensure // we refer to the PLDpc. void PPCELFStreamer::emitGOTToPCRelReloc(const MCInst &Inst) { … } // Emit the label that immediately follows the PLDpc for a link time GOT PC Rel // optimization. void PPCELFStreamer::emitGOTToPCRelLabel(const MCInst &Inst) { … } // This function checks if the parameter Inst is part of the setup for a link // time GOT PC Relative optimization. For example in this situation: // <MCInst PLDpc <MCOperand Reg:282> <MCOperand Expr:(glob_double@got@pcrel)> // <MCOperand Imm:0> <MCOperand Expr:(.Lpcrel@<<invalid>>)>> // <MCInst SOME_LOAD <MCOperand Reg:22> <MCOperand Imm:0> <MCOperand Reg:282> // <MCOperand Expr:(.Lpcrel@<<invalid>>)>> // The above is a pair of such instructions and this function will not return // std::nullopt for either one of them. In both cases we are looking for the // last operand <MCOperand Expr:(.Lpcrel@<<invalid>>)> which needs to be an // MCExpr and has the flag MCSymbolRefExpr::VK_PPC_PCREL_OPT. After that we just // look at the opcode and in the case of PLDpc we will return true. For the load // (or store) this function will return false indicating it has found the second // instruciton in the pair. std::optional<bool> llvm::isPartOfGOTToPCRelPair(const MCInst &Inst, const MCSubtargetInfo &STI) { … } MCELFStreamer *llvm::createPPCELFStreamer( MCContext &Context, std::unique_ptr<MCAsmBackend> MAB, std::unique_ptr<MCObjectWriter> OW, std::unique_ptr<MCCodeEmitter> Emitter) { … }