LLVM 23.0.0git
PPCELFStreamer.cpp
Go to the documentation of this file.
1//===-------- PPCELFStreamer.cpp - ELF 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 MCELFStreamer for PowerPC.
10//
11// The purpose of the custom ELF 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 aliging 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 "PPCELFStreamer.h"
21#include "PPCMCAsmInfo.h"
22#include "PPCMCCodeEmitter.h"
23#include "PPCMCTargetDesc.h"
26#include "llvm/MC/MCAssembler.h"
28#include "llvm/MC/MCContext.h"
29#include "llvm/MC/MCInst.h"
30#include "llvm/MC/MCInstrDesc.h"
33
34using namespace llvm;
35
37 std::unique_ptr<MCAsmBackend> MAB,
38 std::unique_ptr<MCObjectWriter> OW,
39 std::unique_ptr<MCCodeEmitter> Emitter)
40 : MCELFStreamer(Context, std::move(MAB), std::move(OW), std::move(Emitter)),
41 LastLabel(nullptr) {}
42
43void PPCELFStreamer::emitPrefixedInstruction(const MCInst &Inst,
44 const MCSubtargetInfo &STI) {
45 // Prefixed instructions must not cross a 64-byte boundary (i.e. prefix is
46 // before the boundary and the remaining 4-bytes are after the boundary). In
47 // order to achieve this, a nop is added prior to any such boundary-crossing
48 // prefixed instruction. Align to 64 bytes if possible but add a maximum of 4
49 // bytes when trying to do that. If alignment requires adding more than 4
50 // bytes then the instruction won't be aligned. When emitting a code alignment
51 // a new fragment is created for this alignment. This fragment will contain
52 // all of the nops required as part of the alignment operation. In the cases
53 // when no nops are added then The fragment is still created but it remains
54 // empty.
55 emitCodeAlignment(Align(64), &STI, 4);
56
57 // Emit the instruction.
58 // Since the previous emit created a new fragment then adding this instruction
59 // also forces the addition of a new fragment. Inst is now the first
60 // instruction in that new fragment.
62
63 // The above instruction is forced to start a new fragment because it
64 // comes after a code alignment fragment. Get that new fragment.
65 MCFragment *InstructionFragment = getCurrentFragment();
66 SMLoc InstLoc = Inst.getLoc();
67 // Check if there was a last label emitted.
68 if (LastLabel && LastLabel->isDefined() && LastLabelLoc.isValid() &&
69 InstLoc.isValid()) {
70 const SourceMgr *SourceManager = getContext().getSourceManager();
71 unsigned InstLine = SourceManager->FindLineNumber(InstLoc);
72 unsigned LabelLine = SourceManager->FindLineNumber(LastLabelLoc);
73 // If the Label and the Instruction are on the same line then move the
74 // label to the top of the fragment containing the aligned instruction that
75 // was just added.
76 if (InstLine == LabelLine) {
77 LastLabel->setFragment(InstructionFragment);
78 LastLabel->setOffset(0);
79 }
80 }
81}
82
84 const MCSubtargetInfo &STI) {
85 auto &Emitter = static_cast<PPCMCCodeEmitter &>(getAssembler().getEmitter());
86
87 // If the instruction is a part of the GOT to PC-Rel link time optimization
88 // instruction pair, return a value, otherwise return std::nullopt. A true
89 // returned value means the instruction is the PLDpc and a false value means
90 // it is the user instruction.
91 std::optional<bool> IsPartOfGOTToPCRelPair =
92 isPartOfGOTToPCRelPair(Inst, STI);
93
94 // User of the GOT-indirect address.
95 // For example, the load that will get the relocation as follows:
96 // .reloc .Lpcrel1-8,R_PPC64_PCREL_OPT,.-(.Lpcrel1-8)
97 // lwa 3, 4(3)
98 if (IsPartOfGOTToPCRelPair && !*IsPartOfGOTToPCRelPair)
99 emitGOTToPCRelReloc(Inst);
100
101 // Special handling is only for prefixed instructions.
102 if (!Emitter.isPrefixedInstruction(Inst)) {
104 return;
105 }
106 emitPrefixedInstruction(Inst, STI);
107
108 // Producer of the GOT-indirect address.
109 // For example, the prefixed load from the got that will get the label as
110 // follows:
111 // pld 3, vec@got@pcrel(0), 1
112 // .Lpcrel1:
113 if (IsPartOfGOTToPCRelPair && *IsPartOfGOTToPCRelPair)
114 emitGOTToPCRelLabel(Inst);
115}
116
118 LastLabel = Symbol;
119 LastLabelLoc = Loc;
121}
122
123// This linker time GOT PC Relative optimization relocation will look like this:
124// pld <reg> symbol@got@pcrel
125// <Label###>:
126// .reloc Label###-8,R_PPC64_PCREL_OPT,.-(Label###-8)
127// load <loadedreg>, 0(<reg>)
128// The reason we place the label after the PLDpc instruction is that there
129// may be an alignment nop before it since prefixed instructions must not
130// cross a 64-byte boundary (please see
131// PPCELFStreamer::emitPrefixedInstruction()). When referring to the
132// label, we subtract the width of a prefixed instruction (8 bytes) to ensure
133// we refer to the PLDpc.
134void PPCELFStreamer::emitGOTToPCRelReloc(const MCInst &Inst) {
135 // Get the last operand which contains the symbol.
136 const MCOperand &Operand = Inst.getOperand(Inst.getNumOperands() - 1);
137 assert(Operand.isExpr() && "Expecting an MCExpr.");
138 // Cast the last operand to MCSymbolRefExpr to get the symbol.
139 const MCExpr *Expr = Operand.getExpr();
140 const MCSymbolRefExpr *SymExpr = static_cast<const MCSymbolRefExpr *>(Expr);
142 "Expecting a symbol of type VK_PCREL_OPT");
143 MCSymbol *LabelSym =
145 const MCExpr *LabelExpr = MCSymbolRefExpr::create(LabelSym, getContext());
146 const MCExpr *Eight = MCConstantExpr::create(8, getContext());
147 // SubExpr is just Label###-8
148 const MCExpr *SubExpr =
149 MCBinaryExpr::createSub(LabelExpr, Eight, getContext());
150 MCSymbol *CurrentLocation = getContext().createTempSymbol();
151 const MCExpr *CurrentLocationExpr =
152 MCSymbolRefExpr::create(CurrentLocation, getContext());
153 // SubExpr2 is .-(Label###-8)
154 const MCExpr *SubExpr2 =
155 MCBinaryExpr::createSub(CurrentLocationExpr, SubExpr, getContext());
156
157 MCFragment *F = LabelSym->getFragment();
158 F->addFixup(
159 MCFixup::create(LabelSym->getOffset() - 8, SubExpr2,
160 FirstLiteralRelocationKind + ELF::R_PPC64_PCREL_OPT));
161 emitLabel(CurrentLocation, Inst.getLoc());
162}
163
164// Emit the label that immediately follows the PLDpc for a link time GOT PC Rel
165// optimization.
166void PPCELFStreamer::emitGOTToPCRelLabel(const MCInst &Inst) {
167 // Get the last operand which contains the symbol.
168 const MCOperand &Operand = Inst.getOperand(Inst.getNumOperands() - 1);
169 assert(Operand.isExpr() && "Expecting an MCExpr.");
170 // Cast the last operand to MCSymbolRefExpr to get the symbol.
171 const MCExpr *Expr = Operand.getExpr();
172 const MCSymbolRefExpr *SymExpr = static_cast<const MCSymbolRefExpr *>(Expr);
174 "Expecting a symbol of type VK_PCREL_OPT");
175 MCSymbol *LabelSym =
177 emitLabel(LabelSym, Inst.getLoc());
178}
179
180// This function checks if the parameter Inst is part of the setup for a link
181// time GOT PC Relative optimization. For example in this situation:
182// <MCInst PLDpc <MCOperand Reg:282> <MCOperand Expr:(glob_double@got@pcrel)>
183// <MCOperand Imm:0> <MCOperand Expr:(.Lpcrel@<<invalid>>)>>
184// <MCInst SOME_LOAD <MCOperand Reg:22> <MCOperand Imm:0> <MCOperand Reg:282>
185// <MCOperand Expr:(.Lpcrel@<<invalid>>)>>
186// The above is a pair of such instructions and this function will not return
187// std::nullopt for either one of them. In both cases we are looking for the
188// last operand <MCOperand Expr:(.Lpcrel@<<invalid>>)> which needs to be an
189// MCExpr and has the flag PPC::S_PCREL_OPT. After that we just
190// look at the opcode and in the case of PLDpc we will return true. For the load
191// (or store) this function will return false indicating it has found the second
192// instruciton in the pair.
193std::optional<bool> llvm::isPartOfGOTToPCRelPair(const MCInst &Inst,
194 const MCSubtargetInfo &STI) {
195 // Need at least two operands.
196 if (Inst.getNumOperands() < 2)
197 return std::nullopt;
198
199 unsigned LastOp = Inst.getNumOperands() - 1;
200 // The last operand needs to be an MCExpr and it needs to have a variant kind
201 // of VK_PCREL_OPT. If it does not satisfy these conditions it is not a
202 // link time GOT PC Rel opt instruction and we can ignore it and return
203 // std::nullopt.
204 const MCOperand &Operand = Inst.getOperand(LastOp);
205 if (!Operand.isExpr())
206 return std::nullopt;
207
208 // Check for the variant kind VK_PCREL_OPT in this expression.
209 const MCExpr *Expr = Operand.getExpr();
210 const MCSymbolRefExpr *SymExpr = static_cast<const MCSymbolRefExpr *>(Expr);
211 if (!SymExpr || getSpecifier(SymExpr) != PPC::S_PCREL_OPT)
212 return std::nullopt;
213
214 return (Inst.getOpcode() == PPC::PLDpc);
215}
216
219 std::unique_ptr<MCAsmBackend> &&MAB,
220 std::unique_ptr<MCObjectWriter> &&OW,
221 std::unique_ptr<MCCodeEmitter> &&Emitter) {
222 return new PPCELFStreamer(C, std::move(MAB), std::move(OW),
223 std::move(Emitter));
224}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
dxil DXContainer Global Emitter
#define F(x, y, z)
Definition MD5.cpp:54
#define T
MCCodeEmitter & getEmitter() const
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:428
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Context object for machine code objects.
Definition MCContext.h:83
LLVM_ABI MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
const SourceMgr * getSourceManager() const
Definition MCContext.h:401
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc()) override
Emit a label for Symbol into the current section.
MCELFStreamer(MCContext &Context, std::unique_ptr< MCAsmBackend > TAB, std::unique_ptr< MCObjectWriter > OW, std::unique_ptr< MCCodeEmitter > Emitter)
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, bool PCRel=false)
Consider bit fields if we need more flags.
Definition MCFixup.h:86
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
unsigned getNumOperands() const
Definition MCInst.h:212
SMLoc getLoc() const
Definition MCInst.h:208
unsigned getOpcode() const
Definition MCInst.h:202
const MCOperand & getOperand(unsigned i) const
Definition MCInst.h:210
MCAssembler & getAssembler()
void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override
Emit the given Instruction into the current section.
void emitCodeAlignment(Align ByteAlignment, const MCSubtargetInfo *STI, unsigned MaxBytesToEmit=0) override
Emit nops until the byte alignment ByteAlignment is reached.
Instances of this class represent operands of the MCInst class.
Definition MCInst.h:40
const MCExpr * getExpr() const
Definition MCInst.h:118
bool isExpr() const
Definition MCInst.h:69
Streaming machine code generation interface.
Definition MCStreamer.h:221
MCFragment * getCurrentFragment() const
Definition MCStreamer.h:438
MCContext & getContext() const
Definition MCStreamer.h:322
Generic base class for all target subtargets.
Represent a reference to a symbol from inside an expression.
Definition MCExpr.h:190
const MCSymbol & getSymbol() const
Definition MCExpr.h:227
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:214
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
bool isDefined() const
isDefined - Check if this symbol is defined (i.e., it has an address).
Definition MCSymbol.h:233
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
void setFragment(MCFragment *F) const
Mark the symbol as defined in the fragment F.
Definition MCSymbol.h:257
void setOffset(uint64_t Value)
Definition MCSymbol.h:294
MCFragment * getFragment() const
Definition MCSymbol.h:345
uint64_t getOffset() const
Definition MCSymbol.h:289
void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override
Emit the given Instruction into the current section.
PPCELFStreamer(MCContext &Context, std::unique_ptr< MCAsmBackend > MAB, std::unique_ptr< MCObjectWriter > OW, std::unique_ptr< MCCodeEmitter > Emitter)
void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc()) override
Emit a label for Symbol into the current section.
Represents a location in source code.
Definition SMLoc.h:22
constexpr bool isValid() const
Definition SMLoc.h:28
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
Definition SourceMgr.h:37
unsigned FindLineNumber(SMLoc Loc, unsigned BufferID=0) const
Find the line number for the specified location in the specified file.
Definition SourceMgr.h:212
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
@ FirstLiteralRelocationKind
Definition MCFixup.h:29
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1917
static uint16_t getSpecifier(const MCSymbolRefExpr *SRE)
std::optional< bool > isPartOfGOTToPCRelPair(const MCInst &Inst, const MCSubtargetInfo &STI)
MCStreamer * createPPCELFStreamer(const Triple &, MCContext &, std::unique_ptr< MCAsmBackend > &&MAB, std::unique_ptr< MCObjectWriter > &&OW, std::unique_ptr< MCCodeEmitter > &&Emitter)
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:870
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39