xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp (revision 5ffd83dbcc34f10e07f6d3e968ae6365869615f4)
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