xref: /freebsd/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCXCOFFStreamer.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-------- PPCXCOFFStreamer.cpp - XCOFF Object Output ------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This is a custom MCXCOFFStreamer for PowerPC.
10 //
11 // The purpose of the custom XCOFF streamer is to allow us to intercept
12 // instructions as they are being emitted and align all 8 byte instructions
13 // to a 64 byte boundary if required (by adding a 4 byte nop). This is important
14 // because 8 byte instructions are not allowed to cross 64 byte boundaries
15 // and by aligning anything that is within 4 bytes of the boundary we can
16 // guarantee that the 8 byte instructions do not cross that boundary.
17 //
18 //===----------------------------------------------------------------------===//
19 
20 #include "PPCXCOFFStreamer.h"
21 #include "PPCMCCodeEmitter.h"
22 #include "llvm/MC/MCAsmBackend.h"
23 #include "llvm/MC/MCAssembler.h"
24 #include "llvm/MC/MCCodeEmitter.h"
25 #include "llvm/MC/MCObjectWriter.h"
26 #include "llvm/MC/TargetRegistry.h"
27 
28 using namespace llvm;
29 
PPCXCOFFStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> OW,std::unique_ptr<MCCodeEmitter> Emitter)30 PPCXCOFFStreamer::PPCXCOFFStreamer(MCContext &Context,
31                                    std::unique_ptr<MCAsmBackend> MAB,
32                                    std::unique_ptr<MCObjectWriter> OW,
33                                    std::unique_ptr<MCCodeEmitter> Emitter)
34     : MCXCOFFStreamer(Context, std::move(MAB), std::move(OW),
35                       std::move(Emitter)) {}
36 
emitPrefixedInstruction(const MCInst & Inst,const MCSubtargetInfo & STI)37 void PPCXCOFFStreamer::emitPrefixedInstruction(const MCInst &Inst,
38                                                const MCSubtargetInfo &STI) {
39   // Prefixed instructions must not cross a 64-byte boundary (i.e. prefix is
40   // before the boundary and the remaining 4-bytes are after the boundary). In
41   // order to achieve this, a nop is added prior to any such boundary-crossing
42   // prefixed instruction. Align to 64 bytes if possible but add a maximum of 4
43   // bytes when trying to do that. If alignment requires adding more than 4
44   // bytes then the instruction won't be aligned.
45   emitCodeAlignment(Align(64), &STI, 4);
46 
47   // Emit the instruction.
48   // Since the previous emit created a new fragment then adding this instruction
49   // also forces the addition of a new fragment. Inst is now the first
50   // instruction in that new fragment.
51   MCXCOFFStreamer::emitInstruction(Inst, STI);
52 }
53 
emitInstruction(const MCInst & Inst,const MCSubtargetInfo & STI)54 void PPCXCOFFStreamer::emitInstruction(const MCInst &Inst,
55                                        const MCSubtargetInfo &STI) {
56   PPCMCCodeEmitter *Emitter =
57       static_cast<PPCMCCodeEmitter *>(getAssembler().getEmitterPtr());
58 
59   // Special handling is only for prefixed instructions.
60   if (!Emitter->isPrefixedInstruction(Inst)) {
61     MCXCOFFStreamer::emitInstruction(Inst, STI);
62     return;
63   }
64   emitPrefixedInstruction(Inst, STI);
65 }
66 
67 MCStreamer *
createPPCXCOFFStreamer(const Triple &,MCContext & C,std::unique_ptr<MCAsmBackend> && MAB,std::unique_ptr<MCObjectWriter> && OW,std::unique_ptr<MCCodeEmitter> && Emitter)68 llvm::createPPCXCOFFStreamer(const Triple &, MCContext &C,
69                              std::unique_ptr<MCAsmBackend> &&MAB,
70                              std::unique_ptr<MCObjectWriter> &&OW,
71                              std::unique_ptr<MCCodeEmitter> &&Emitter) {
72   return new PPCXCOFFStreamer(C, std::move(MAB), std::move(OW),
73                               std::move(Emitter));
74 }
75