| //===-------- PPCELFStreamer.cpp - ELF Object Output ---------------------===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // 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 "PPCInstrInfo.h" |
| #include "PPCMCCodeEmitter.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" |
| |
| using namespace llvm; |
| |
| PPCELFStreamer::PPCELFStreamer(MCContext &Context, |
| std::unique_ptr<MCAsmBackend> MAB, |
| std::unique_ptr<MCObjectWriter> OW, |
| std::unique_ptr<MCCodeEmitter> Emitter) |
| : MCELFStreamer(Context, std::move(MAB), std::move(OW), |
| std::move(Emitter)), LastLabel(NULL) { |
| } |
| |
| void PPCELFStreamer::emitPrefixedInstruction(const MCInst &Inst, |
| const MCSubtargetInfo &STI) { |
| // Prefixed instructions must not cross a 64-byte boundary (i.e. prefix is |
| // before the boundary and the remaining 4-bytes are after the boundary). In |
| // order to achieve this, a nop is added prior to any such boundary-crossing |
| // prefixed instruction. Align to 64 bytes if possible but add a maximum of 4 |
| // bytes when trying to do that. If alignment requires adding more than 4 |
| // bytes then the instruction won't be aligned. When emitting a code alignment |
| // a new fragment is created for this alignment. This fragment will contain |
| // all of the nops required as part of the alignment operation. In the cases |
| // when no nops are added then The fragment is still created but it remains |
| // empty. |
| emitCodeAlignment(64, 4); |
| |
| // Emit the instruction. |
| // Since the previous emit created a new fragment then adding this instruction |
| // also forces the addition of a new fragment. Inst is now the first |
| // instruction in that new fragment. |
| MCELFStreamer::emitInstruction(Inst, STI); |
| |
| // The above instruction is forced to start a new fragment because it |
| // comes after a code alignment fragment. Get that new fragment. |
| MCFragment *InstructionFragment = getCurrentFragment(); |
| SMLoc InstLoc = Inst.getLoc(); |
| // Check if there was a last label emitted. |
| if (LastLabel && !LastLabel->isUnset() && LastLabelLoc.isValid() && |
| InstLoc.isValid()) { |
| const SourceMgr *SourceManager = getContext().getSourceManager(); |
| unsigned InstLine = SourceManager->FindLineNumber(InstLoc); |
| unsigned LabelLine = SourceManager->FindLineNumber(LastLabelLoc); |
| // If the Label and the Instruction are on the same line then move the |
| // label to the top of the fragment containing the aligned instruction that |
| // was just added. |
| if (InstLine == LabelLine) { |
| AssignFragment(LastLabel, InstructionFragment); |
| LastLabel->setOffset(0); |
| } |
| } |
| } |
| |
| void PPCELFStreamer::emitInstruction(const MCInst &Inst, |
| const MCSubtargetInfo &STI) { |
| PPCMCCodeEmitter *Emitter = |
| static_cast<PPCMCCodeEmitter*>(getAssembler().getEmitterPtr()); |
| |
| // Special handling is only for prefixed instructions. |
| if (!Emitter->isPrefixedInstruction(Inst)) { |
| MCELFStreamer::emitInstruction(Inst, STI); |
| return; |
| } |
| emitPrefixedInstruction(Inst, STI); |
| } |
| |
| void PPCELFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) { |
| LastLabel = Symbol; |
| LastLabelLoc = Loc; |
| MCELFStreamer::emitLabel(Symbol); |
| } |
| |
| MCELFStreamer *llvm::createPPCELFStreamer( |
| MCContext &Context, std::unique_ptr<MCAsmBackend> MAB, |
| std::unique_ptr<MCObjectWriter> OW, |
| std::unique_ptr<MCCodeEmitter> Emitter) { |
| return new PPCELFStreamer(Context, std::move(MAB), std::move(OW), |
| std::move(Emitter)); |
| } |