1 //===-------- PPCELFStreamer.cpp - ELF Object Output ---------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This is a custom MCELFStreamer for PowerPC.
11 //
12 // The purpose of the custom ELF streamer is to allow us to intercept
13 // instructions as they are being emitted and align all 8 byte instructions
14 // to a 64 byte boundary if required (by adding a 4 byte nop). This is important
15 // because 8 byte instructions are not allowed to cross 64 byte boundaries
16 // and by aliging anything that is within 4 bytes of the boundary we can
17 // guarantee that the 8 byte instructions do not cross that boundary.
18 //
19 //===----------------------------------------------------------------------===//
20
21
22 #include "PPCELFStreamer.h"
23 #include "PPCFixupKinds.h"
24 #include "PPCInstrInfo.h"
25 #include "PPCMCCodeEmitter.h"
26 #include "llvm/BinaryFormat/ELF.h"
27 #include "llvm/MC/MCAsmBackend.h"
28 #include "llvm/MC/MCAssembler.h"
29 #include "llvm/MC/MCCodeEmitter.h"
30 #include "llvm/MC/MCContext.h"
31 #include "llvm/MC/MCInst.h"
32 #include "llvm/MC/MCInstrDesc.h"
33 #include "llvm/MC/MCObjectWriter.h"
34 #include "llvm/MC/MCSymbolELF.h"
35 #include "llvm/Support/Casting.h"
36 #include "llvm/Support/SourceMgr.h"
37
38 using namespace llvm;
39
PPCELFStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> OW,std::unique_ptr<MCCodeEmitter> Emitter)40 PPCELFStreamer::PPCELFStreamer(MCContext &Context,
41 std::unique_ptr<MCAsmBackend> MAB,
42 std::unique_ptr<MCObjectWriter> OW,
43 std::unique_ptr<MCCodeEmitter> Emitter)
44 : MCELFStreamer(Context, std::move(MAB), std::move(OW),
45 std::move(Emitter)), LastLabel(NULL) {
46 }
47
emitPrefixedInstruction(const MCInst & Inst,const MCSubtargetInfo & STI)48 void PPCELFStreamer::emitPrefixedInstruction(const MCInst &Inst,
49 const MCSubtargetInfo &STI) {
50 // Prefixed instructions must not cross a 64-byte boundary (i.e. prefix is
51 // before the boundary and the remaining 4-bytes are after the boundary). In
52 // order to achieve this, a nop is added prior to any such boundary-crossing
53 // prefixed instruction. Align to 64 bytes if possible but add a maximum of 4
54 // bytes when trying to do that. If alignment requires adding more than 4
55 // bytes then the instruction won't be aligned. When emitting a code alignment
56 // a new fragment is created for this alignment. This fragment will contain
57 // all of the nops required as part of the alignment operation. In the cases
58 // when no nops are added then The fragment is still created but it remains
59 // empty.
60 emitCodeAlignment(64, 4);
61
62 // Emit the instruction.
63 // Since the previous emit created a new fragment then adding this instruction
64 // also forces the addition of a new fragment. Inst is now the first
65 // instruction in that new fragment.
66 MCELFStreamer::emitInstruction(Inst, STI);
67
68 // The above instruction is forced to start a new fragment because it
69 // comes after a code alignment fragment. Get that new fragment.
70 MCFragment *InstructionFragment = getCurrentFragment();
71 SMLoc InstLoc = Inst.getLoc();
72 // Check if there was a last label emitted.
73 if (LastLabel && !LastLabel->isUnset() && LastLabelLoc.isValid() &&
74 InstLoc.isValid()) {
75 const SourceMgr *SourceManager = getContext().getSourceManager();
76 unsigned InstLine = SourceManager->FindLineNumber(InstLoc);
77 unsigned LabelLine = SourceManager->FindLineNumber(LastLabelLoc);
78 // If the Label and the Instruction are on the same line then move the
79 // label to the top of the fragment containing the aligned instruction that
80 // was just added.
81 if (InstLine == LabelLine) {
82 AssignFragment(LastLabel, InstructionFragment);
83 LastLabel->setOffset(0);
84 }
85 }
86 }
87
emitInstruction(const MCInst & Inst,const MCSubtargetInfo & STI)88 void PPCELFStreamer::emitInstruction(const MCInst &Inst,
89 const MCSubtargetInfo &STI) {
90 PPCMCCodeEmitter *Emitter =
91 static_cast<PPCMCCodeEmitter*>(getAssembler().getEmitterPtr());
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
106 // Special handling is only for prefixed instructions.
107 if (!Emitter->isPrefixedInstruction(Inst)) {
108 MCELFStreamer::emitInstruction(Inst, STI);
109 return;
110 }
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);
120 }
121
emitLabel(MCSymbol * Symbol,SMLoc Loc)122 void PPCELFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
123 LastLabel = Symbol;
124 LastLabelLoc = Loc;
125 MCELFStreamer::emitLabel(Symbol);
126 }
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.
emitGOTToPCRelReloc(const MCInst & Inst)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.
emitGOTToPCRelLabel(const MCInst & Inst)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.
isPartOfGOTToPCRelPair(const MCInst & Inst,const MCSubtargetInfo & STI)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
createPPCELFStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> OW,std::unique_ptr<MCCodeEmitter> Emitter)224 MCELFStreamer *llvm::createPPCELFStreamer(
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 }
231