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/BinaryFormat/XCOFF.h" |
23 | #include "llvm/MC/MCAsmBackend.h" |
24 | #include "llvm/MC/MCAssembler.h" |
25 | #include "llvm/MC/MCCodeEmitter.h" |
26 | #include "llvm/MC/MCDirectives.h" |
27 | #include "llvm/MC/MCObjectWriter.h" |
28 | #include "llvm/MC/MCSectionXCOFF.h" |
29 | #include "llvm/MC/MCSymbolXCOFF.h" |
30 | #include "llvm/MC/TargetRegistry.h" |
31 | |
32 | using namespace llvm; |
33 | |
34 | PPCXCOFFStreamer::PPCXCOFFStreamer(MCContext &Context, |
35 | std::unique_ptr<MCAsmBackend> MAB, |
36 | std::unique_ptr<MCObjectWriter> OW, |
37 | std::unique_ptr<MCCodeEmitter> Emitter) |
38 | : MCXCOFFStreamer(Context, std::move(MAB), std::move(OW), |
39 | std::move(Emitter)) {} |
40 | |
41 | void PPCXCOFFStreamer::emitPrefixedInstruction(const MCInst &Inst, |
42 | const MCSubtargetInfo &STI) { |
43 | // Prefixed instructions must not cross a 64-byte boundary (i.e. prefix is |
44 | // before the boundary and the remaining 4-bytes are after the boundary). In |
45 | // order to achieve this, a nop is added prior to any such boundary-crossing |
46 | // prefixed instruction. Align to 64 bytes if possible but add a maximum of 4 |
47 | // bytes when trying to do that. If alignment requires adding more than 4 |
48 | // bytes then the instruction won't be aligned. |
49 | emitCodeAlignment(ByteAlignment: Align(64), STI: &STI, MaxBytesToEmit: 4); |
50 | |
51 | // Emit the instruction. |
52 | // Since the previous emit created a new fragment then adding this instruction |
53 | // also forces the addition of a new fragment. Inst is now the first |
54 | // instruction in that new fragment. |
55 | MCXCOFFStreamer::emitInstruction(Inst, STI); |
56 | } |
57 | |
58 | void PPCXCOFFStreamer::emitInstruction(const MCInst &Inst, |
59 | const MCSubtargetInfo &STI) { |
60 | PPCMCCodeEmitter *Emitter = |
61 | static_cast<PPCMCCodeEmitter *>(getAssembler().getEmitterPtr()); |
62 | |
63 | // Special handling is only for prefixed instructions. |
64 | if (!Emitter->isPrefixedInstruction(MI: Inst)) { |
65 | MCXCOFFStreamer::emitInstruction(Inst, STI); |
66 | return; |
67 | } |
68 | emitPrefixedInstruction(Inst, STI); |
69 | } |
70 | |
71 | MCXCOFFStreamer * |
72 | llvm::createPPCXCOFFStreamer(MCContext &Context, |
73 | std::unique_ptr<MCAsmBackend> MAB, |
74 | std::unique_ptr<MCObjectWriter> OW, |
75 | std::unique_ptr<MCCodeEmitter> Emitter) { |
76 | return new PPCXCOFFStreamer(Context, std::move(MAB), std::move(OW), |
77 | std::move(Emitter)); |
78 | } |
79 | |