15ffd83dbSDimitry Andric //===-------- PPCELFStreamer.cpp - ELF Object Output ---------------------===//
25ffd83dbSDimitry Andric //
35ffd83dbSDimitry Andric // The LLVM Compiler Infrastructure
45ffd83dbSDimitry Andric //
55ffd83dbSDimitry Andric // This file is distributed under the University of Illinois Open Source
65ffd83dbSDimitry Andric // License. See LICENSE.TXT for details.
75ffd83dbSDimitry Andric //
85ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
95ffd83dbSDimitry Andric //
105ffd83dbSDimitry Andric // This is a custom MCELFStreamer for PowerPC.
115ffd83dbSDimitry Andric //
125ffd83dbSDimitry Andric // The purpose of the custom ELF streamer is to allow us to intercept
135ffd83dbSDimitry Andric // instructions as they are being emitted and align all 8 byte instructions
145ffd83dbSDimitry Andric // to a 64 byte boundary if required (by adding a 4 byte nop). This is important
155ffd83dbSDimitry Andric // because 8 byte instructions are not allowed to cross 64 byte boundaries
165ffd83dbSDimitry Andric // and by aliging anything that is within 4 bytes of the boundary we can
175ffd83dbSDimitry Andric // guarantee that the 8 byte instructions do not cross that boundary.
185ffd83dbSDimitry Andric //
195ffd83dbSDimitry Andric //===----------------------------------------------------------------------===//
205ffd83dbSDimitry Andric
215ffd83dbSDimitry Andric
225ffd83dbSDimitry Andric #include "PPCELFStreamer.h"
23*af732203SDimitry Andric #include "PPCFixupKinds.h"
245ffd83dbSDimitry Andric #include "PPCInstrInfo.h"
255ffd83dbSDimitry Andric #include "PPCMCCodeEmitter.h"
265ffd83dbSDimitry Andric #include "llvm/BinaryFormat/ELF.h"
275ffd83dbSDimitry Andric #include "llvm/MC/MCAsmBackend.h"
285ffd83dbSDimitry Andric #include "llvm/MC/MCAssembler.h"
295ffd83dbSDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
305ffd83dbSDimitry Andric #include "llvm/MC/MCContext.h"
315ffd83dbSDimitry Andric #include "llvm/MC/MCInst.h"
325ffd83dbSDimitry Andric #include "llvm/MC/MCInstrDesc.h"
335ffd83dbSDimitry Andric #include "llvm/MC/MCObjectWriter.h"
345ffd83dbSDimitry Andric #include "llvm/MC/MCSymbolELF.h"
355ffd83dbSDimitry Andric #include "llvm/Support/Casting.h"
365ffd83dbSDimitry Andric #include "llvm/Support/SourceMgr.h"
375ffd83dbSDimitry Andric
385ffd83dbSDimitry Andric using namespace llvm;
395ffd83dbSDimitry Andric
PPCELFStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> OW,std::unique_ptr<MCCodeEmitter> Emitter)405ffd83dbSDimitry Andric PPCELFStreamer::PPCELFStreamer(MCContext &Context,
415ffd83dbSDimitry Andric std::unique_ptr<MCAsmBackend> MAB,
425ffd83dbSDimitry Andric std::unique_ptr<MCObjectWriter> OW,
435ffd83dbSDimitry Andric std::unique_ptr<MCCodeEmitter> Emitter)
445ffd83dbSDimitry Andric : MCELFStreamer(Context, std::move(MAB), std::move(OW),
455ffd83dbSDimitry Andric std::move(Emitter)), LastLabel(NULL) {
465ffd83dbSDimitry Andric }
475ffd83dbSDimitry Andric
emitPrefixedInstruction(const MCInst & Inst,const MCSubtargetInfo & STI)485ffd83dbSDimitry Andric void PPCELFStreamer::emitPrefixedInstruction(const MCInst &Inst,
495ffd83dbSDimitry Andric const MCSubtargetInfo &STI) {
505ffd83dbSDimitry Andric // Prefixed instructions must not cross a 64-byte boundary (i.e. prefix is
515ffd83dbSDimitry Andric // before the boundary and the remaining 4-bytes are after the boundary). In
525ffd83dbSDimitry Andric // order to achieve this, a nop is added prior to any such boundary-crossing
535ffd83dbSDimitry Andric // prefixed instruction. Align to 64 bytes if possible but add a maximum of 4
545ffd83dbSDimitry Andric // bytes when trying to do that. If alignment requires adding more than 4
555ffd83dbSDimitry Andric // bytes then the instruction won't be aligned. When emitting a code alignment
565ffd83dbSDimitry Andric // a new fragment is created for this alignment. This fragment will contain
575ffd83dbSDimitry Andric // all of the nops required as part of the alignment operation. In the cases
585ffd83dbSDimitry Andric // when no nops are added then The fragment is still created but it remains
595ffd83dbSDimitry Andric // empty.
605ffd83dbSDimitry Andric emitCodeAlignment(64, 4);
615ffd83dbSDimitry Andric
625ffd83dbSDimitry Andric // Emit the instruction.
635ffd83dbSDimitry Andric // Since the previous emit created a new fragment then adding this instruction
645ffd83dbSDimitry Andric // also forces the addition of a new fragment. Inst is now the first
655ffd83dbSDimitry Andric // instruction in that new fragment.
665ffd83dbSDimitry Andric MCELFStreamer::emitInstruction(Inst, STI);
675ffd83dbSDimitry Andric
685ffd83dbSDimitry Andric // The above instruction is forced to start a new fragment because it
695ffd83dbSDimitry Andric // comes after a code alignment fragment. Get that new fragment.
705ffd83dbSDimitry Andric MCFragment *InstructionFragment = getCurrentFragment();
715ffd83dbSDimitry Andric SMLoc InstLoc = Inst.getLoc();
725ffd83dbSDimitry Andric // Check if there was a last label emitted.
735ffd83dbSDimitry Andric if (LastLabel && !LastLabel->isUnset() && LastLabelLoc.isValid() &&
745ffd83dbSDimitry Andric InstLoc.isValid()) {
755ffd83dbSDimitry Andric const SourceMgr *SourceManager = getContext().getSourceManager();
765ffd83dbSDimitry Andric unsigned InstLine = SourceManager->FindLineNumber(InstLoc);
775ffd83dbSDimitry Andric unsigned LabelLine = SourceManager->FindLineNumber(LastLabelLoc);
785ffd83dbSDimitry Andric // If the Label and the Instruction are on the same line then move the
795ffd83dbSDimitry Andric // label to the top of the fragment containing the aligned instruction that
805ffd83dbSDimitry Andric // was just added.
815ffd83dbSDimitry Andric if (InstLine == LabelLine) {
825ffd83dbSDimitry Andric AssignFragment(LastLabel, InstructionFragment);
835ffd83dbSDimitry Andric LastLabel->setOffset(0);
845ffd83dbSDimitry Andric }
855ffd83dbSDimitry Andric }
865ffd83dbSDimitry Andric }
875ffd83dbSDimitry Andric
emitInstruction(const MCInst & Inst,const MCSubtargetInfo & STI)885ffd83dbSDimitry Andric void PPCELFStreamer::emitInstruction(const MCInst &Inst,
895ffd83dbSDimitry Andric const MCSubtargetInfo &STI) {
905ffd83dbSDimitry Andric PPCMCCodeEmitter *Emitter =
915ffd83dbSDimitry Andric static_cast<PPCMCCodeEmitter*>(getAssembler().getEmitterPtr());
925ffd83dbSDimitry Andric
93*af732203SDimitry Andric // If the instruction is a part of the GOT to PC-Rel link time optimization
94*af732203SDimitry Andric // instruction pair, return a value, otherwise return None. A true returned
95*af732203SDimitry Andric // value means the instruction is the PLDpc and a false value means it is
96*af732203SDimitry Andric // the user instruction.
97*af732203SDimitry Andric Optional<bool> IsPartOfGOTToPCRelPair = isPartOfGOTToPCRelPair(Inst, STI);
98*af732203SDimitry Andric
99*af732203SDimitry Andric // User of the GOT-indirect address.
100*af732203SDimitry Andric // For example, the load that will get the relocation as follows:
101*af732203SDimitry Andric // .reloc .Lpcrel1-8,R_PPC64_PCREL_OPT,.-(.Lpcrel1-8)
102*af732203SDimitry Andric // lwa 3, 4(3)
103*af732203SDimitry Andric if (IsPartOfGOTToPCRelPair.hasValue() && !IsPartOfGOTToPCRelPair.getValue())
104*af732203SDimitry Andric emitGOTToPCRelReloc(Inst);
105*af732203SDimitry Andric
1065ffd83dbSDimitry Andric // Special handling is only for prefixed instructions.
1075ffd83dbSDimitry Andric if (!Emitter->isPrefixedInstruction(Inst)) {
1085ffd83dbSDimitry Andric MCELFStreamer::emitInstruction(Inst, STI);
1095ffd83dbSDimitry Andric return;
1105ffd83dbSDimitry Andric }
1115ffd83dbSDimitry Andric emitPrefixedInstruction(Inst, STI);
112*af732203SDimitry Andric
113*af732203SDimitry Andric // Producer of the GOT-indirect address.
114*af732203SDimitry Andric // For example, the prefixed load from the got that will get the label as
115*af732203SDimitry Andric // follows:
116*af732203SDimitry Andric // pld 3, vec@got@pcrel(0), 1
117*af732203SDimitry Andric // .Lpcrel1:
118*af732203SDimitry Andric if (IsPartOfGOTToPCRelPair.hasValue() && IsPartOfGOTToPCRelPair.getValue())
119*af732203SDimitry Andric emitGOTToPCRelLabel(Inst);
1205ffd83dbSDimitry Andric }
1215ffd83dbSDimitry Andric
emitLabel(MCSymbol * Symbol,SMLoc Loc)1225ffd83dbSDimitry Andric void PPCELFStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
1235ffd83dbSDimitry Andric LastLabel = Symbol;
1245ffd83dbSDimitry Andric LastLabelLoc = Loc;
1255ffd83dbSDimitry Andric MCELFStreamer::emitLabel(Symbol);
1265ffd83dbSDimitry Andric }
1275ffd83dbSDimitry Andric
128*af732203SDimitry Andric // This linker time GOT PC Relative optimization relocation will look like this:
129*af732203SDimitry Andric // pld <reg> symbol@got@pcrel
130*af732203SDimitry Andric // <Label###>:
131*af732203SDimitry Andric // .reloc Label###-8,R_PPC64_PCREL_OPT,.-(Label###-8)
132*af732203SDimitry Andric // load <loadedreg>, 0(<reg>)
133*af732203SDimitry Andric // The reason we place the label after the PLDpc instruction is that there
134*af732203SDimitry Andric // may be an alignment nop before it since prefixed instructions must not
135*af732203SDimitry Andric // cross a 64-byte boundary (please see
136*af732203SDimitry Andric // PPCELFStreamer::emitPrefixedInstruction()). When referring to the
137*af732203SDimitry Andric // label, we subtract the width of a prefixed instruction (8 bytes) to ensure
138*af732203SDimitry Andric // we refer to the PLDpc.
emitGOTToPCRelReloc(const MCInst & Inst)139*af732203SDimitry Andric void PPCELFStreamer::emitGOTToPCRelReloc(const MCInst &Inst) {
140*af732203SDimitry Andric // Get the last operand which contains the symbol.
141*af732203SDimitry Andric const MCOperand &Operand = Inst.getOperand(Inst.getNumOperands() - 1);
142*af732203SDimitry Andric assert(Operand.isExpr() && "Expecting an MCExpr.");
143*af732203SDimitry Andric // Cast the last operand to MCSymbolRefExpr to get the symbol.
144*af732203SDimitry Andric const MCExpr *Expr = Operand.getExpr();
145*af732203SDimitry Andric const MCSymbolRefExpr *SymExpr = static_cast<const MCSymbolRefExpr *>(Expr);
146*af732203SDimitry Andric assert(SymExpr->getKind() == MCSymbolRefExpr::VK_PPC_PCREL_OPT &&
147*af732203SDimitry Andric "Expecting a symbol of type VK_PPC_PCREL_OPT");
148*af732203SDimitry Andric MCSymbol *LabelSym =
149*af732203SDimitry Andric getContext().getOrCreateSymbol(SymExpr->getSymbol().getName());
150*af732203SDimitry Andric const MCExpr *LabelExpr = MCSymbolRefExpr::create(LabelSym, getContext());
151*af732203SDimitry Andric const MCExpr *Eight = MCConstantExpr::create(8, getContext());
152*af732203SDimitry Andric // SubExpr is just Label###-8
153*af732203SDimitry Andric const MCExpr *SubExpr =
154*af732203SDimitry Andric MCBinaryExpr::createSub(LabelExpr, Eight, getContext());
155*af732203SDimitry Andric MCSymbol *CurrentLocation = getContext().createTempSymbol();
156*af732203SDimitry Andric const MCExpr *CurrentLocationExpr =
157*af732203SDimitry Andric MCSymbolRefExpr::create(CurrentLocation, getContext());
158*af732203SDimitry Andric // SubExpr2 is .-(Label###-8)
159*af732203SDimitry Andric const MCExpr *SubExpr2 =
160*af732203SDimitry Andric MCBinaryExpr::createSub(CurrentLocationExpr, SubExpr, getContext());
161*af732203SDimitry Andric
162*af732203SDimitry Andric MCDataFragment *DF = static_cast<MCDataFragment *>(LabelSym->getFragment());
163*af732203SDimitry Andric assert(DF && "Expecting a valid data fragment.");
164*af732203SDimitry Andric MCFixupKind FixupKind = static_cast<MCFixupKind>(FirstLiteralRelocationKind +
165*af732203SDimitry Andric ELF::R_PPC64_PCREL_OPT);
166*af732203SDimitry Andric DF->getFixups().push_back(
167*af732203SDimitry Andric MCFixup::create(LabelSym->getOffset() - 8, SubExpr2,
168*af732203SDimitry Andric FixupKind, Inst.getLoc()));
169*af732203SDimitry Andric emitLabel(CurrentLocation, Inst.getLoc());
170*af732203SDimitry Andric }
171*af732203SDimitry Andric
172*af732203SDimitry Andric // Emit the label that immediately follows the PLDpc for a link time GOT PC Rel
173*af732203SDimitry Andric // optimization.
emitGOTToPCRelLabel(const MCInst & Inst)174*af732203SDimitry Andric void PPCELFStreamer::emitGOTToPCRelLabel(const MCInst &Inst) {
175*af732203SDimitry Andric // Get the last operand which contains the symbol.
176*af732203SDimitry Andric const MCOperand &Operand = Inst.getOperand(Inst.getNumOperands() - 1);
177*af732203SDimitry Andric assert(Operand.isExpr() && "Expecting an MCExpr.");
178*af732203SDimitry Andric // Cast the last operand to MCSymbolRefExpr to get the symbol.
179*af732203SDimitry Andric const MCExpr *Expr = Operand.getExpr();
180*af732203SDimitry Andric const MCSymbolRefExpr *SymExpr = static_cast<const MCSymbolRefExpr *>(Expr);
181*af732203SDimitry Andric assert(SymExpr->getKind() == MCSymbolRefExpr::VK_PPC_PCREL_OPT &&
182*af732203SDimitry Andric "Expecting a symbol of type VK_PPC_PCREL_OPT");
183*af732203SDimitry Andric MCSymbol *LabelSym =
184*af732203SDimitry Andric getContext().getOrCreateSymbol(SymExpr->getSymbol().getName());
185*af732203SDimitry Andric emitLabel(LabelSym, Inst.getLoc());
186*af732203SDimitry Andric }
187*af732203SDimitry Andric
188*af732203SDimitry Andric // This funciton checks if the parameter Inst is part of the setup for a link
189*af732203SDimitry Andric // time GOT PC Relative optimization. For example in this situation:
190*af732203SDimitry Andric // <MCInst PLDpc <MCOperand Reg:282> <MCOperand Expr:(glob_double@got@pcrel)>
191*af732203SDimitry Andric // <MCOperand Imm:0> <MCOperand Expr:(.Lpcrel@<<invalid>>)>>
192*af732203SDimitry Andric // <MCInst SOME_LOAD <MCOperand Reg:22> <MCOperand Imm:0> <MCOperand Reg:282>
193*af732203SDimitry Andric // <MCOperand Expr:(.Lpcrel@<<invalid>>)>>
194*af732203SDimitry Andric // The above is a pair of such instructions and this function will not return
195*af732203SDimitry Andric // None for either one of them. In both cases we are looking for the last
196*af732203SDimitry Andric // operand <MCOperand Expr:(.Lpcrel@<<invalid>>)> which needs to be an MCExpr
197*af732203SDimitry Andric // and has the flag MCSymbolRefExpr::VK_PPC_PCREL_OPT. After that we just look
198*af732203SDimitry Andric // at the opcode and in the case of PLDpc we will return true. For the load
199*af732203SDimitry Andric // (or store) this function will return false indicating it has found the second
200*af732203SDimitry Andric // instruciton in the pair.
isPartOfGOTToPCRelPair(const MCInst & Inst,const MCSubtargetInfo & STI)201*af732203SDimitry Andric Optional<bool> llvm::isPartOfGOTToPCRelPair(const MCInst &Inst,
202*af732203SDimitry Andric const MCSubtargetInfo &STI) {
203*af732203SDimitry Andric // Need at least two operands.
204*af732203SDimitry Andric if (Inst.getNumOperands() < 2)
205*af732203SDimitry Andric return None;
206*af732203SDimitry Andric
207*af732203SDimitry Andric unsigned LastOp = Inst.getNumOperands() - 1;
208*af732203SDimitry Andric // The last operand needs to be an MCExpr and it needs to have a variant kind
209*af732203SDimitry Andric // of VK_PPC_PCREL_OPT. If it does not satisfy these conditions it is not a
210*af732203SDimitry Andric // link time GOT PC Rel opt instruction and we can ignore it and return None.
211*af732203SDimitry Andric const MCOperand &Operand = Inst.getOperand(LastOp);
212*af732203SDimitry Andric if (!Operand.isExpr())
213*af732203SDimitry Andric return None;
214*af732203SDimitry Andric
215*af732203SDimitry Andric // Check for the variant kind VK_PPC_PCREL_OPT in this expression.
216*af732203SDimitry Andric const MCExpr *Expr = Operand.getExpr();
217*af732203SDimitry Andric const MCSymbolRefExpr *SymExpr = static_cast<const MCSymbolRefExpr *>(Expr);
218*af732203SDimitry Andric if (!SymExpr || SymExpr->getKind() != MCSymbolRefExpr::VK_PPC_PCREL_OPT)
219*af732203SDimitry Andric return None;
220*af732203SDimitry Andric
221*af732203SDimitry Andric return (Inst.getOpcode() == PPC::PLDpc);
222*af732203SDimitry Andric }
223*af732203SDimitry Andric
createPPCELFStreamer(MCContext & Context,std::unique_ptr<MCAsmBackend> MAB,std::unique_ptr<MCObjectWriter> OW,std::unique_ptr<MCCodeEmitter> Emitter)2245ffd83dbSDimitry Andric MCELFStreamer *llvm::createPPCELFStreamer(
2255ffd83dbSDimitry Andric MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
2265ffd83dbSDimitry Andric std::unique_ptr<MCObjectWriter> OW,
2275ffd83dbSDimitry Andric std::unique_ptr<MCCodeEmitter> Emitter) {
2285ffd83dbSDimitry Andric return new PPCELFStreamer(Context, std::move(MAB), std::move(OW),
2295ffd83dbSDimitry Andric std::move(Emitter));
2305ffd83dbSDimitry Andric }
231