20
20
21
21
22
22
#include " PPCELFStreamer.h"
23
+ #include " PPCFixupKinds.h"
23
24
#include " PPCInstrInfo.h"
24
25
#include " PPCMCCodeEmitter.h"
25
26
#include " llvm/BinaryFormat/ELF.h"
@@ -89,12 +90,33 @@ void PPCELFStreamer::emitInstruction(const MCInst &Inst,
89
90
PPCMCCodeEmitter *Emitter =
90
91
static_cast <PPCMCCodeEmitter*>(getAssembler ().getEmitterPtr ());
91
92
93
+ // If the instruction is a part of the GOT to PC-Rel link time optimization
94
+ // instruction pair, return a value, otherwise return None. A true returned
95
+ // value means the instruction is the PLDpc and a false value means it is
96
+ // the user instruction.
97
+ Optional<bool > IsPartOfGOTToPCRelPair = isPartOfGOTToPCRelPair (Inst, STI);
98
+
99
+ // User of the GOT-indirect address.
100
+ // For example, the load that will get the relocation as follows:
101
+ // .reloc .Lpcrel1-8,R_PPC64_PCREL_OPT,.-(.Lpcrel1-8)
102
+ // lwa 3, 4(3)
103
+ if (IsPartOfGOTToPCRelPair.hasValue () && !IsPartOfGOTToPCRelPair.getValue ())
104
+ emitGOTToPCRelReloc (Inst);
105
+
92
106
// Special handling is only for prefixed instructions.
93
107
if (!Emitter->isPrefixedInstruction (Inst)) {
94
108
MCELFStreamer::emitInstruction (Inst, STI);
95
109
return ;
96
110
}
97
111
emitPrefixedInstruction (Inst, STI);
112
+
113
+ // Producer of the GOT-indirect address.
114
+ // For example, the prefixed load from the got that will get the label as
115
+ // follows:
116
+ // pld 3, vec@got@pcrel(0), 1
117
+ // .Lpcrel1:
118
+ if (IsPartOfGOTToPCRelPair.hasValue () && IsPartOfGOTToPCRelPair.getValue ())
119
+ emitGOTToPCRelLabel (Inst);
98
120
}
99
121
100
122
void PPCELFStreamer::emitLabel (MCSymbol *Symbol, SMLoc Loc) {
@@ -103,6 +125,102 @@ void PPCELFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
103
125
MCELFStreamer::emitLabel (Symbol);
104
126
}
105
127
128
+ // This linker time GOT PC Relative optimization relocation will look like this:
129
+ // pld <reg> symbol@got@pcrel
130
+ // <Label###>:
131
+ // .reloc Label###-8,R_PPC64_PCREL_OPT,.-(Label###-8)
132
+ // load <loadedreg>, 0(<reg>)
133
+ // The reason we place the label after the PLDpc instruction is that there
134
+ // may be an alignment nop before it since prefixed instructions must not
135
+ // cross a 64-byte boundary (please see
136
+ // PPCELFStreamer::emitPrefixedInstruction()). When referring to the
137
+ // label, we subtract the width of a prefixed instruction (8 bytes) to ensure
138
+ // we refer to the PLDpc.
139
+ void PPCELFStreamer::emitGOTToPCRelReloc (const MCInst &Inst) {
140
+ // Get the last operand which contains the symbol.
141
+ const MCOperand &Operand = Inst.getOperand (Inst.getNumOperands () - 1 );
142
+ assert (Operand.isExpr () && " Expecting an MCExpr." );
143
+ // Cast the last operand to MCSymbolRefExpr to get the symbol.
144
+ const MCExpr *Expr = Operand.getExpr ();
145
+ const MCSymbolRefExpr *SymExpr = static_cast <const MCSymbolRefExpr *>(Expr);
146
+ assert (SymExpr->getKind () == MCSymbolRefExpr::VK_PPC_PCREL_OPT &&
147
+ " Expecting a symbol of type VK_PPC_PCREL_OPT" );
148
+ MCSymbol *LabelSym =
149
+ getContext ().getOrCreateSymbol (SymExpr->getSymbol ().getName ());
150
+ const MCExpr *LabelExpr = MCSymbolRefExpr::create (LabelSym, getContext ());
151
+ const MCExpr *Eight = MCConstantExpr::create (8 , getContext ());
152
+ // SubExpr is just Label###-8
153
+ const MCExpr *SubExpr =
154
+ MCBinaryExpr::createSub (LabelExpr, Eight, getContext ());
155
+ MCSymbol *CurrentLocation = getContext ().createTempSymbol ();
156
+ const MCExpr *CurrentLocationExpr =
157
+ MCSymbolRefExpr::create (CurrentLocation, getContext ());
158
+ // SubExpr2 is .-(Label###-8)
159
+ const MCExpr *SubExpr2 =
160
+ MCBinaryExpr::createSub (CurrentLocationExpr, SubExpr, getContext ());
161
+
162
+ MCDataFragment *DF = static_cast <MCDataFragment *>(LabelSym->getFragment ());
163
+ assert (DF && " Expecting a valid data fragment." );
164
+ MCFixupKind FixupKind = static_cast <MCFixupKind>(FirstLiteralRelocationKind +
165
+ ELF::R_PPC64_PCREL_OPT);
166
+ DF->getFixups ().push_back (
167
+ MCFixup::create (LabelSym->getOffset () - 8 , SubExpr2,
168
+ FixupKind, Inst.getLoc ()));
169
+ emitLabel (CurrentLocation, Inst.getLoc ());
170
+ }
171
+
172
+ // Emit the label that immediately follows the PLDpc for a link time GOT PC Rel
173
+ // optimization.
174
+ void PPCELFStreamer::emitGOTToPCRelLabel (const MCInst &Inst) {
175
+ // Get the last operand which contains the symbol.
176
+ const MCOperand &Operand = Inst.getOperand (Inst.getNumOperands () - 1 );
177
+ assert (Operand.isExpr () && " Expecting an MCExpr." );
178
+ // Cast the last operand to MCSymbolRefExpr to get the symbol.
179
+ const MCExpr *Expr = Operand.getExpr ();
180
+ const MCSymbolRefExpr *SymExpr = static_cast <const MCSymbolRefExpr *>(Expr);
181
+ assert (SymExpr->getKind () == MCSymbolRefExpr::VK_PPC_PCREL_OPT &&
182
+ " Expecting a symbol of type VK_PPC_PCREL_OPT" );
183
+ MCSymbol *LabelSym =
184
+ getContext ().getOrCreateSymbol (SymExpr->getSymbol ().getName ());
185
+ emitLabel (LabelSym, Inst.getLoc ());
186
+ }
187
+
188
+ // This funciton checks if the parameter Inst is part of the setup for a link
189
+ // time GOT PC Relative optimization. For example in this situation:
190
+ // <MCInst PLDpc <MCOperand Reg:282> <MCOperand Expr:(glob_double@got@pcrel)>
191
+ // <MCOperand Imm:0> <MCOperand Expr:(.Lpcrel@<<invalid>>)>>
192
+ // <MCInst SOME_LOAD <MCOperand Reg:22> <MCOperand Imm:0> <MCOperand Reg:282>
193
+ // <MCOperand Expr:(.Lpcrel@<<invalid>>)>>
194
+ // The above is a pair of such instructions and this function will not return
195
+ // None for either one of them. In both cases we are looking for the last
196
+ // operand <MCOperand Expr:(.Lpcrel@<<invalid>>)> which needs to be an MCExpr
197
+ // and has the flag MCSymbolRefExpr::VK_PPC_PCREL_OPT. After that we just look
198
+ // at the opcode and in the case of PLDpc we will return true. For the load
199
+ // (or store) this function will return false indicating it has found the second
200
+ // instruciton in the pair.
201
+ Optional<bool > llvm::isPartOfGOTToPCRelPair (const MCInst &Inst,
202
+ const MCSubtargetInfo &STI) {
203
+ // Need at least two operands.
204
+ if (Inst.getNumOperands () < 2 )
205
+ return None;
206
+
207
+ unsigned LastOp = Inst.getNumOperands () - 1 ;
208
+ // The last operand needs to be an MCExpr and it needs to have a variant kind
209
+ // of VK_PPC_PCREL_OPT. If it does not satisfy these conditions it is not a
210
+ // link time GOT PC Rel opt instruction and we can ignore it and return None.
211
+ const MCOperand &Operand = Inst.getOperand (LastOp);
212
+ if (!Operand.isExpr ())
213
+ return None;
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 None;
220
+
221
+ return (Inst.getOpcode () == PPC::PLDpc);
222
+ }
223
+
106
224
MCELFStreamer *llvm::createPPCELFStreamer (
107
225
MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
108
226
std::unique_ptr<MCObjectWriter> OW,
0 commit comments