LLVM 17.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
21#include "PPCELFStreamer.h"
22#include "PPCFixupKinds.h"
23#include "PPCInstrInfo.h"
24#include "PPCMCCodeEmitter.h"
27#include "llvm/MC/MCAssembler.h"
29#include "llvm/MC/MCContext.h"
30#include "llvm/MC/MCInst.h"
31#include "llvm/MC/MCInstrDesc.h"
33#include "llvm/MC/MCSymbolELF.h"
36
37using namespace llvm;
38
40 std::unique_ptr<MCAsmBackend> MAB,
41 std::unique_ptr<MCObjectWriter> OW,
42 std::unique_ptr<MCCodeEmitter> Emitter)
43 : MCELFStreamer(Context, std::move(MAB), std::move(OW), std::move(Emitter)),
44 LastLabel(nullptr) {}
45
46void PPCELFStreamer::emitPrefixedInstruction(const MCInst &Inst,
47 const MCSubtargetInfo &STI) {
48 // Prefixed instructions must not cross a 64-byte boundary (i.e. prefix is
49 // before the boundary and the remaining 4-bytes are after the boundary). In
50 // order to achieve this, a nop is added prior to any such boundary-crossing
51 // prefixed instruction. Align to 64 bytes if possible but add a maximum of 4
52 // bytes when trying to do that. If alignment requires adding more than 4
53 // bytes then the instruction won't be aligned. When emitting a code alignment
54 // a new fragment is created for this alignment. This fragment will contain
55 // all of the nops required as part of the alignment operation. In the cases
56 // when no nops are added then The fragment is still created but it remains
57 // empty.
58 emitCodeAlignment(Align(64), &STI, 4);
59
60 // Emit the instruction.
61 // Since the previous emit created a new fragment then adding this instruction
62 // also forces the addition of a new fragment. Inst is now the first
63 // instruction in that new fragment.
65
66 // The above instruction is forced to start a new fragment because it
67 // comes after a code alignment fragment. Get that new fragment.
68 MCFragment *InstructionFragment = getCurrentFragment();
69 SMLoc InstLoc = Inst.getLoc();
70 // Check if there was a last label emitted.
71 if (LastLabel && !LastLabel->isUnset() && LastLabelLoc.isValid() &&
72 InstLoc.isValid()) {
73 const SourceMgr *SourceManager = getContext().getSourceManager();
74 unsigned InstLine = SourceManager->FindLineNumber(InstLoc);
75 unsigned LabelLine = SourceManager->FindLineNumber(LastLabelLoc);
76 // If the Label and the Instruction are on the same line then move the
77 // label to the top of the fragment containing the aligned instruction that
78 // was just added.
79 if (InstLine == LabelLine) {
80 assignFragment(LastLabel, InstructionFragment);
81 LastLabel->setOffset(0);
82 }
83 }
84}
85
87 const MCSubtargetInfo &STI) {
90
91 // If the instruction is a part of the GOT to PC-Rel link time optimization
92 // instruction pair, return a value, otherwise return std::nullopt. A true
93 // returned value means the instruction is the PLDpc and a false value means
94 // it is the user instruction.
95 std::optional<bool> IsPartOfGOTToPCRelPair =
96 isPartOfGOTToPCRelPair(Inst, STI);
97
98 // User of the GOT-indirect address.
99 // For example, the load that will get the relocation as follows:
100 // .reloc .Lpcrel1-8,R_PPC64_PCREL_OPT,.-(.Lpcrel1-8)
101 // lwa 3, 4(3)
102 if (IsPartOfGOTToPCRelPair && !*IsPartOfGOTToPCRelPair)
103 emitGOTToPCRelReloc(Inst);
104
105 // Special handling is only for prefixed instructions.
106 if (!Emitter->isPrefixedInstruction(Inst)) {
108 return;
109 }
110 emitPrefixedInstruction(Inst, STI);
111
112 // Producer of the GOT-indirect address.
113 // For example, the prefixed load from the got that will get the label as
114 // follows:
115 // pld 3, vec@got@pcrel(0), 1
116 // .Lpcrel1:
117 if (IsPartOfGOTToPCRelPair && *IsPartOfGOTToPCRelPair)
118 emitGOTToPCRelLabel(Inst);
119}
120
122 LastLabel = Symbol;
123 LastLabelLoc = Loc;
125}
126
127// This linker time GOT PC Relative optimization relocation will look like this:
128// pld <reg> symbol@got@pcrel
129// <Label###>:
130// .reloc Label###-8,R_PPC64_PCREL_OPT,.-(Label###-8)
131// load <loadedreg>, 0(<reg>)
132// The reason we place the label after the PLDpc instruction is that there
133// may be an alignment nop before it since prefixed instructions must not
134// cross a 64-byte boundary (please see
135// PPCELFStreamer::emitPrefixedInstruction()). When referring to the
136// label, we subtract the width of a prefixed instruction (8 bytes) to ensure
137// we refer to the PLDpc.
138void PPCELFStreamer::emitGOTToPCRelReloc(const MCInst &Inst) {
139 // Get the last operand which contains the symbol.
140 const MCOperand &Operand = Inst.getOperand(Inst.getNumOperands() - 1);
141 assert(Operand.isExpr() && "Expecting an MCExpr.");
142 // Cast the last operand to MCSymbolRefExpr to get the symbol.
143 const MCExpr *Expr = Operand.getExpr();
144 const MCSymbolRefExpr *SymExpr = static_cast<const MCSymbolRefExpr *>(Expr);
146 "Expecting a symbol of type VK_PPC_PCREL_OPT");
147 MCSymbol *LabelSym =
149 const MCExpr *LabelExpr = MCSymbolRefExpr::create(LabelSym, getContext());
150 const MCExpr *Eight = MCConstantExpr::create(8, getContext());
151 // SubExpr is just Label###-8
152 const MCExpr *SubExpr =
153 MCBinaryExpr::createSub(LabelExpr, Eight, getContext());
154 MCSymbol *CurrentLocation = getContext().createTempSymbol();
155 const MCExpr *CurrentLocationExpr =
156 MCSymbolRefExpr::create(CurrentLocation, getContext());
157 // SubExpr2 is .-(Label###-8)
158 const MCExpr *SubExpr2 =
159 MCBinaryExpr::createSub(CurrentLocationExpr, SubExpr, getContext());
160
161 MCDataFragment *DF = static_cast<MCDataFragment *>(LabelSym->getFragment());
162 assert(DF && "Expecting a valid data fragment.");
163 MCFixupKind FixupKind = static_cast<MCFixupKind>(FirstLiteralRelocationKind +
164 ELF::R_PPC64_PCREL_OPT);
165 DF->getFixups().push_back(
166 MCFixup::create(LabelSym->getOffset() - 8, SubExpr2,
167 FixupKind, Inst.getLoc()));
168 emitLabel(CurrentLocation, Inst.getLoc());
169}
170
171// Emit the label that immediately follows the PLDpc for a link time GOT PC Rel
172// optimization.
173void PPCELFStreamer::emitGOTToPCRelLabel(const MCInst &Inst) {
174 // Get the last operand which contains the symbol.
175 const MCOperand &Operand = Inst.getOperand(Inst.getNumOperands() - 1);
176 assert(Operand.isExpr() && "Expecting an MCExpr.");
177 // Cast the last operand to MCSymbolRefExpr to get the symbol.
178 const MCExpr *Expr = Operand.getExpr();
179 const MCSymbolRefExpr *SymExpr = static_cast<const MCSymbolRefExpr *>(Expr);
181 "Expecting a symbol of type VK_PPC_PCREL_OPT");
182 MCSymbol *LabelSym =
184 emitLabel(LabelSym, Inst.getLoc());
185}
186
187// This function checks if the parameter Inst is part of the setup for a link
188// time GOT PC Relative optimization. For example in this situation:
189// <MCInst PLDpc <MCOperand Reg:282> <MCOperand Expr:(glob_double@got@pcrel)>
190// <MCOperand Imm:0> <MCOperand Expr:(.Lpcrel@<<invalid>>)>>
191// <MCInst SOME_LOAD <MCOperand Reg:22> <MCOperand Imm:0> <MCOperand Reg:282>
192// <MCOperand Expr:(.Lpcrel@<<invalid>>)>>
193// The above is a pair of such instructions and this function will not return
194// std::nullopt for either one of them. In both cases we are looking for the
195// last operand <MCOperand Expr:(.Lpcrel@<<invalid>>)> which needs to be an
196// MCExpr and has the flag MCSymbolRefExpr::VK_PPC_PCREL_OPT. After that we just
197// look at the opcode and in the case of PLDpc we will return true. For the load
198// (or store) this function will return false indicating it has found the second
199// instruciton in the pair.
200std::optional<bool> llvm::isPartOfGOTToPCRelPair(const MCInst &Inst,
201 const MCSubtargetInfo &STI) {
202 // Need at least two operands.
203 if (Inst.getNumOperands() < 2)
204 return std::nullopt;
205
206 unsigned LastOp = Inst.getNumOperands() - 1;
207 // The last operand needs to be an MCExpr and it needs to have a variant kind
208 // of VK_PPC_PCREL_OPT. If it does not satisfy these conditions it is not a
209 // link time GOT PC Rel opt instruction and we can ignore it and return
210 // std::nullopt.
211 const MCOperand &Operand = Inst.getOperand(LastOp);
212 if (!Operand.isExpr())
213 return std::nullopt;
214
215 // Check for the variant kind VK_PPC_PCREL_OPT in this expression.
216 const MCExpr *Expr = Operand.getExpr();
217 const MCSymbolRefExpr *SymExpr = static_cast<const MCSymbolRefExpr *>(Expr);
218 if (!SymExpr || SymExpr->getKind() != MCSymbolRefExpr::VK_PPC_PCREL_OPT)
219 return std::nullopt;
220
221 return (Inst.getOpcode() == PPC::PLDpc);
222}
223
225 MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
226 std::unique_ptr<MCObjectWriter> OW,
227 std::unique_ptr<MCCodeEmitter> Emitter) {
228 return new PPCELFStreamer(Context, std::move(MAB), std::move(OW),
229 std::move(Emitter));
230}
dxil DXContainer Global Emitter
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
LLVMContext & Context
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
MCCodeEmitter * getEmitterPtr() const
Definition: MCAssembler.h:325
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition: MCExpr.h:610
static const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition: MCExpr.cpp:194
Context object for machine code objects.
Definition: MCContext.h:76
MCSymbol * createTempSymbol()
Create a temporary symbol with a unique name.
Definition: MCContext.cpp:318
const SourceMgr * getSourceManager() const
Definition: MCContext.h:435
MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Definition: MCContext.cpp:201
Fragment for data and encoded instructions.
Definition: MCFragment.h:241
void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc()) override
Emit a label for Symbol into the current section.
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:35
static MCFixup create(uint32_t Offset, const MCExpr *Value, MCFixupKind Kind, SMLoc Loc=SMLoc())
Definition: MCFixup.h:87
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
unsigned getNumOperands() const
Definition: MCInst.h:208
SMLoc getLoc() const
Definition: MCInst.h:204
unsigned getOpcode() const
Definition: MCInst.h:198
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:206
MCAssembler & getAssembler()
void emitInstruction(const MCInst &Inst, const MCSubtargetInfo &STI) override
Emit the given Instruction into the current section.
MCFragment * getCurrentFragment() const
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:36
const MCExpr * getExpr() const
Definition: MCInst.h:114
bool isExpr() const
Definition: MCInst.h:65
void assignFragment(MCSymbol *Symbol, MCFragment *Fragment)
Sets the symbol's section.
Definition: MCStreamer.cpp:414
MCContext & getContext() const
Definition: MCStreamer.h:297
Generic base class for all target subtargets.
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:192
const MCSymbol & getSymbol() const
Definition: MCExpr.h:399
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:386
VariantKind getKind() const
Definition: MCExpr.h:401
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:203
void setOffset(uint64_t Value)
Definition: MCSymbol.h:331
bool isUnset() const
Definition: MCSymbol.h:323
uint64_t getOffset() const
Definition: MCSymbol.h:325
MCFragment * getFragment(bool SetUsed=true) const
Definition: MCSymbol.h:395
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:23
bool isValid() const
Definition: SMLoc.h:29
This owns the files read by a parser, handles include stacks, and handles diagnostic wrangling.
Definition: SourceMgr.h:31
unsigned FindLineNumber(SMLoc Loc, unsigned BufferID=0) const
Find the line number for the specified location in the specified file.
Definition: SourceMgr.h:196
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:21
@ FirstLiteralRelocationKind
The range [FirstLiteralRelocationKind, MaxTargetFixupKind) is used for relocations coming from ....
Definition: MCFixup.h:50
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:1946
MCELFStreamer * createPPCELFStreamer(MCContext &Context, std::unique_ptr< MCAsmBackend > MAB, std::unique_ptr< MCObjectWriter > OW, std::unique_ptr< MCCodeEmitter > Emitter)
std::optional< bool > isPartOfGOTToPCRelPair(const MCInst &Inst, const MCSubtargetInfo &STI)
Definition: BitVector.h:858
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39