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
28using namespace llvm;
29
30PPCXCOFFStreamer::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
37void 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(ByteAlignment: Align(64), STI: &STI, MaxBytesToEmit: 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
54void 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(MI: Inst)) {
61 MCXCOFFStreamer::emitInstruction(Inst, STI);
62 return;
63 }
64 emitPrefixedInstruction(Inst, STI);
65}
66
67MCStreamer *
68llvm::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