xref: /freebsd/contrib/llvm-project/llvm/lib/Target/PowerPC/MCTargetDesc/PPCELFStreamer.cpp (revision 5e801ac66d24704442eba426ed13c3effb8a34e7)
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"
25 #include "llvm/BinaryFormat/ELF.h"
26 #include "llvm/MC/MCAsmBackend.h"
27 #include "llvm/MC/MCAssembler.h"
28 #include "llvm/MC/MCCodeEmitter.h"
29 #include "llvm/MC/MCContext.h"
30 #include "llvm/MC/MCInst.h"
31 #include "llvm/MC/MCInstrDesc.h"
32 #include "llvm/MC/MCObjectWriter.h"
33 #include "llvm/MC/MCSymbolELF.h"
34 #include "llvm/Support/Casting.h"
35 #include "llvm/Support/SourceMgr.h"
36 
37 using namespace llvm;
38 
39 PPCELFStreamer::PPCELFStreamer(MCContext &Context,
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),
44                     std::move(Emitter)), LastLabel(NULL) {
45 }
46 
47 void PPCELFStreamer::emitPrefixedInstruction(const MCInst &Inst,
48                                              const MCSubtargetInfo &STI) {
49   // Prefixed instructions must not cross a 64-byte boundary (i.e. prefix is
50   // before the boundary and the remaining 4-bytes are after the boundary). In
51   // order to achieve this, a nop is added prior to any such boundary-crossing
52   // prefixed instruction. Align to 64 bytes if possible but add a maximum of 4
53   // bytes when trying to do that. If alignment requires adding more than 4
54   // bytes then the instruction won't be aligned. When emitting a code alignment
55   // a new fragment is created for this alignment. This fragment will contain
56   // all of the nops required as part of the alignment operation. In the cases
57   // when no nops are added then The fragment is still created but it remains
58   // empty.
59   emitCodeAlignment(64, &STI, 4);
60 
61   // Emit the instruction.
62   // Since the previous emit created a new fragment then adding this instruction
63   // also forces the addition of a new fragment. Inst is now the first
64   // instruction in that new fragment.
65   MCELFStreamer::emitInstruction(Inst, STI);
66 
67   // The above instruction is forced to start a new fragment because it
68   // comes after a code alignment fragment. Get that new fragment.
69   MCFragment *InstructionFragment = getCurrentFragment();
70   SMLoc InstLoc = Inst.getLoc();
71   // Check if there was a last label emitted.
72   if (LastLabel && !LastLabel->isUnset() && LastLabelLoc.isValid() &&
73       InstLoc.isValid()) {
74     const SourceMgr *SourceManager = getContext().getSourceManager();
75     unsigned InstLine = SourceManager->FindLineNumber(InstLoc);
76     unsigned LabelLine = SourceManager->FindLineNumber(LastLabelLoc);
77     // If the Label and the Instruction are on the same line then move the
78     // label to the top of the fragment containing the aligned instruction that
79     // was just added.
80     if (InstLine == LabelLine) {
81       AssignFragment(LastLabel, InstructionFragment);
82       LastLabel->setOffset(0);
83     }
84   }
85 }
86 
87 void PPCELFStreamer::emitInstruction(const MCInst &Inst,
88                                      const MCSubtargetInfo &STI) {
89   PPCMCCodeEmitter *Emitter =
90       static_cast<PPCMCCodeEmitter*>(getAssembler().getEmitterPtr());
91 
92   // If the instruction is a part of the GOT to PC-Rel link time optimization
93   // instruction pair, return a value, otherwise return None. A true returned
94   // value means the instruction is the PLDpc and a false value means it is
95   // the user instruction.
96   Optional<bool> IsPartOfGOTToPCRelPair = 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.hasValue() && !IsPartOfGOTToPCRelPair.getValue())
103     emitGOTToPCRelReloc(Inst);
104 
105   // Special handling is only for prefixed instructions.
106   if (!Emitter->isPrefixedInstruction(Inst)) {
107     MCELFStreamer::emitInstruction(Inst, STI);
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.hasValue() && IsPartOfGOTToPCRelPair.getValue())
118     emitGOTToPCRelLabel(Inst);
119 }
120 
121 void PPCELFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
122   LastLabel = Symbol;
123   LastLabelLoc = Loc;
124   MCELFStreamer::emitLabel(Symbol);
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.
138 void 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);
145   assert(SymExpr->getKind() == MCSymbolRefExpr::VK_PPC_PCREL_OPT &&
146          "Expecting a symbol of type VK_PPC_PCREL_OPT");
147   MCSymbol *LabelSym =
148       getContext().getOrCreateSymbol(SymExpr->getSymbol().getName());
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.
173 void 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);
180   assert(SymExpr->getKind() == MCSymbolRefExpr::VK_PPC_PCREL_OPT &&
181          "Expecting a symbol of type VK_PPC_PCREL_OPT");
182   MCSymbol *LabelSym =
183       getContext().getOrCreateSymbol(SymExpr->getSymbol().getName());
184   emitLabel(LabelSym, Inst.getLoc());
185 }
186 
187 // This funciton 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 // None for either one of them. In both cases we are looking for the last
195 // operand <MCOperand Expr:(.Lpcrel@<<invalid>>)> which needs to be an MCExpr
196 // and has the flag MCSymbolRefExpr::VK_PPC_PCREL_OPT. After that we just look
197 // 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.
200 Optional<bool> llvm::isPartOfGOTToPCRelPair(const MCInst &Inst,
201                                             const MCSubtargetInfo &STI) {
202   // Need at least two operands.
203   if (Inst.getNumOperands() < 2)
204     return None;
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 None.
210   const MCOperand &Operand = Inst.getOperand(LastOp);
211   if (!Operand.isExpr())
212     return None;
213 
214   // Check for the variant kind VK_PPC_PCREL_OPT in this expression.
215   const MCExpr *Expr = Operand.getExpr();
216   const MCSymbolRefExpr *SymExpr = static_cast<const MCSymbolRefExpr *>(Expr);
217   if (!SymExpr || SymExpr->getKind() != MCSymbolRefExpr::VK_PPC_PCREL_OPT)
218     return None;
219 
220   return (Inst.getOpcode() == PPC::PLDpc);
221 }
222 
223 MCELFStreamer *llvm::createPPCELFStreamer(
224     MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
225     std::unique_ptr<MCObjectWriter> OW,
226     std::unique_ptr<MCCodeEmitter> Emitter) {
227   return new PPCELFStreamer(Context, std::move(MAB), std::move(OW),
228                             std::move(Emitter));
229 }
230