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