1*5ffd83dbSDimitry Andric //===-------- PPCELFStreamer.cpp - ELF Object Output ---------------------===// 2*5ffd83dbSDimitry Andric // 3*5ffd83dbSDimitry Andric // The LLVM Compiler Infrastructure 4*5ffd83dbSDimitry Andric // 5*5ffd83dbSDimitry Andric // This file is distributed under the University of Illinois Open Source 6*5ffd83dbSDimitry Andric // License. See LICENSE.TXT for details. 7*5ffd83dbSDimitry Andric // 8*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 9*5ffd83dbSDimitry Andric // 10*5ffd83dbSDimitry Andric // This is a custom MCELFStreamer for PowerPC. 11*5ffd83dbSDimitry Andric // 12*5ffd83dbSDimitry Andric // The purpose of the custom ELF streamer is to allow us to intercept 13*5ffd83dbSDimitry Andric // instructions as they are being emitted and align all 8 byte instructions 14*5ffd83dbSDimitry Andric // to a 64 byte boundary if required (by adding a 4 byte nop). This is important 15*5ffd83dbSDimitry Andric // because 8 byte instructions are not allowed to cross 64 byte boundaries 16*5ffd83dbSDimitry Andric // and by aliging anything that is within 4 bytes of the boundary we can 17*5ffd83dbSDimitry Andric // guarantee that the 8 byte instructions do not cross that boundary. 18*5ffd83dbSDimitry Andric // 19*5ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 20*5ffd83dbSDimitry Andric 21*5ffd83dbSDimitry Andric 22*5ffd83dbSDimitry Andric #include "PPCELFStreamer.h" 23*5ffd83dbSDimitry Andric #include "PPCInstrInfo.h" 24*5ffd83dbSDimitry Andric #include "PPCMCCodeEmitter.h" 25*5ffd83dbSDimitry Andric #include "llvm/BinaryFormat/ELF.h" 26*5ffd83dbSDimitry Andric #include "llvm/MC/MCAsmBackend.h" 27*5ffd83dbSDimitry Andric #include "llvm/MC/MCAssembler.h" 28*5ffd83dbSDimitry Andric #include "llvm/MC/MCCodeEmitter.h" 29*5ffd83dbSDimitry Andric #include "llvm/MC/MCContext.h" 30*5ffd83dbSDimitry Andric #include "llvm/MC/MCInst.h" 31*5ffd83dbSDimitry Andric #include "llvm/MC/MCInstrDesc.h" 32*5ffd83dbSDimitry Andric #include "llvm/MC/MCObjectWriter.h" 33*5ffd83dbSDimitry Andric #include "llvm/MC/MCSymbolELF.h" 34*5ffd83dbSDimitry Andric #include "llvm/Support/Casting.h" 35*5ffd83dbSDimitry Andric #include "llvm/Support/SourceMgr.h" 36*5ffd83dbSDimitry Andric 37*5ffd83dbSDimitry Andric using namespace llvm; 38*5ffd83dbSDimitry Andric 39*5ffd83dbSDimitry Andric PPCELFStreamer::PPCELFStreamer(MCContext &Context, 40*5ffd83dbSDimitry Andric std::unique_ptr<MCAsmBackend> MAB, 41*5ffd83dbSDimitry Andric std::unique_ptr<MCObjectWriter> OW, 42*5ffd83dbSDimitry Andric std::unique_ptr<MCCodeEmitter> Emitter) 43*5ffd83dbSDimitry Andric : MCELFStreamer(Context, std::move(MAB), std::move(OW), 44*5ffd83dbSDimitry Andric std::move(Emitter)), LastLabel(NULL) { 45*5ffd83dbSDimitry Andric } 46*5ffd83dbSDimitry Andric 47*5ffd83dbSDimitry Andric void PPCELFStreamer::emitPrefixedInstruction(const MCInst &Inst, 48*5ffd83dbSDimitry Andric const MCSubtargetInfo &STI) { 49*5ffd83dbSDimitry Andric // Prefixed instructions must not cross a 64-byte boundary (i.e. prefix is 50*5ffd83dbSDimitry Andric // before the boundary and the remaining 4-bytes are after the boundary). In 51*5ffd83dbSDimitry Andric // order to achieve this, a nop is added prior to any such boundary-crossing 52*5ffd83dbSDimitry Andric // prefixed instruction. Align to 64 bytes if possible but add a maximum of 4 53*5ffd83dbSDimitry Andric // bytes when trying to do that. If alignment requires adding more than 4 54*5ffd83dbSDimitry Andric // bytes then the instruction won't be aligned. When emitting a code alignment 55*5ffd83dbSDimitry Andric // a new fragment is created for this alignment. This fragment will contain 56*5ffd83dbSDimitry Andric // all of the nops required as part of the alignment operation. In the cases 57*5ffd83dbSDimitry Andric // when no nops are added then The fragment is still created but it remains 58*5ffd83dbSDimitry Andric // empty. 59*5ffd83dbSDimitry Andric emitCodeAlignment(64, 4); 60*5ffd83dbSDimitry Andric 61*5ffd83dbSDimitry Andric // Emit the instruction. 62*5ffd83dbSDimitry Andric // Since the previous emit created a new fragment then adding this instruction 63*5ffd83dbSDimitry Andric // also forces the addition of a new fragment. Inst is now the first 64*5ffd83dbSDimitry Andric // instruction in that new fragment. 65*5ffd83dbSDimitry Andric MCELFStreamer::emitInstruction(Inst, STI); 66*5ffd83dbSDimitry Andric 67*5ffd83dbSDimitry Andric // The above instruction is forced to start a new fragment because it 68*5ffd83dbSDimitry Andric // comes after a code alignment fragment. Get that new fragment. 69*5ffd83dbSDimitry Andric MCFragment *InstructionFragment = getCurrentFragment(); 70*5ffd83dbSDimitry Andric SMLoc InstLoc = Inst.getLoc(); 71*5ffd83dbSDimitry Andric // Check if there was a last label emitted. 72*5ffd83dbSDimitry Andric if (LastLabel && !LastLabel->isUnset() && LastLabelLoc.isValid() && 73*5ffd83dbSDimitry Andric InstLoc.isValid()) { 74*5ffd83dbSDimitry Andric const SourceMgr *SourceManager = getContext().getSourceManager(); 75*5ffd83dbSDimitry Andric unsigned InstLine = SourceManager->FindLineNumber(InstLoc); 76*5ffd83dbSDimitry Andric unsigned LabelLine = SourceManager->FindLineNumber(LastLabelLoc); 77*5ffd83dbSDimitry Andric // If the Label and the Instruction are on the same line then move the 78*5ffd83dbSDimitry Andric // label to the top of the fragment containing the aligned instruction that 79*5ffd83dbSDimitry Andric // was just added. 80*5ffd83dbSDimitry Andric if (InstLine == LabelLine) { 81*5ffd83dbSDimitry Andric AssignFragment(LastLabel, InstructionFragment); 82*5ffd83dbSDimitry Andric LastLabel->setOffset(0); 83*5ffd83dbSDimitry Andric } 84*5ffd83dbSDimitry Andric } 85*5ffd83dbSDimitry Andric } 86*5ffd83dbSDimitry Andric 87*5ffd83dbSDimitry Andric void PPCELFStreamer::emitInstruction(const MCInst &Inst, 88*5ffd83dbSDimitry Andric const MCSubtargetInfo &STI) { 89*5ffd83dbSDimitry Andric PPCMCCodeEmitter *Emitter = 90*5ffd83dbSDimitry Andric static_cast<PPCMCCodeEmitter*>(getAssembler().getEmitterPtr()); 91*5ffd83dbSDimitry Andric 92*5ffd83dbSDimitry Andric // Special handling is only for prefixed instructions. 93*5ffd83dbSDimitry Andric if (!Emitter->isPrefixedInstruction(Inst)) { 94*5ffd83dbSDimitry Andric MCELFStreamer::emitInstruction(Inst, STI); 95*5ffd83dbSDimitry Andric return; 96*5ffd83dbSDimitry Andric } 97*5ffd83dbSDimitry Andric emitPrefixedInstruction(Inst, STI); 98*5ffd83dbSDimitry Andric } 99*5ffd83dbSDimitry Andric 100*5ffd83dbSDimitry Andric void PPCELFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) { 101*5ffd83dbSDimitry Andric LastLabel = Symbol; 102*5ffd83dbSDimitry Andric LastLabelLoc = Loc; 103*5ffd83dbSDimitry Andric MCELFStreamer::emitLabel(Symbol); 104*5ffd83dbSDimitry Andric } 105*5ffd83dbSDimitry Andric 106*5ffd83dbSDimitry Andric MCELFStreamer *llvm::createPPCELFStreamer( 107*5ffd83dbSDimitry Andric MCContext &Context, std::unique_ptr<MCAsmBackend> MAB, 108*5ffd83dbSDimitry Andric std::unique_ptr<MCObjectWriter> OW, 109*5ffd83dbSDimitry Andric std::unique_ptr<MCCodeEmitter> Emitter) { 110*5ffd83dbSDimitry Andric return new PPCELFStreamer(Context, std::move(MAB), std::move(OW), 111*5ffd83dbSDimitry Andric std::move(Emitter)); 112*5ffd83dbSDimitry Andric } 113