File: | llvm/include/llvm/MC/SectionKind.h |
Warning: | line 159, column 33 The left operand of '==' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- PPCAsmPrinter.cpp - Print machine instrs to PowerPC assembly ------===// | |||
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 file contains a printer that converts from our internal representation | |||
10 | // of machine-dependent LLVM code to PowerPC assembly language. This printer is | |||
11 | // the output mechanism used by `llc'. | |||
12 | // | |||
13 | // Documentation at http://developer.apple.com/documentation/DeveloperTools/ | |||
14 | // Reference/Assembler/ASMIntroduction/chapter_1_section_1.html | |||
15 | // | |||
16 | //===----------------------------------------------------------------------===// | |||
17 | ||||
18 | #include "MCTargetDesc/PPCInstPrinter.h" | |||
19 | #include "MCTargetDesc/PPCMCExpr.h" | |||
20 | #include "MCTargetDesc/PPCMCTargetDesc.h" | |||
21 | #include "MCTargetDesc/PPCPredicates.h" | |||
22 | #include "PPC.h" | |||
23 | #include "PPCInstrInfo.h" | |||
24 | #include "PPCMachineFunctionInfo.h" | |||
25 | #include "PPCSubtarget.h" | |||
26 | #include "PPCTargetMachine.h" | |||
27 | #include "PPCTargetStreamer.h" | |||
28 | #include "TargetInfo/PowerPCTargetInfo.h" | |||
29 | #include "llvm/ADT/MapVector.h" | |||
30 | #include "llvm/ADT/StringRef.h" | |||
31 | #include "llvm/ADT/Triple.h" | |||
32 | #include "llvm/ADT/Twine.h" | |||
33 | #include "llvm/BinaryFormat/ELF.h" | |||
34 | #include "llvm/BinaryFormat/MachO.h" | |||
35 | #include "llvm/CodeGen/AsmPrinter.h" | |||
36 | #include "llvm/CodeGen/MachineBasicBlock.h" | |||
37 | #include "llvm/CodeGen/MachineFunction.h" | |||
38 | #include "llvm/CodeGen/MachineInstr.h" | |||
39 | #include "llvm/CodeGen/MachineModuleInfoImpls.h" | |||
40 | #include "llvm/CodeGen/MachineOperand.h" | |||
41 | #include "llvm/CodeGen/MachineRegisterInfo.h" | |||
42 | #include "llvm/CodeGen/StackMaps.h" | |||
43 | #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" | |||
44 | #include "llvm/IR/DataLayout.h" | |||
45 | #include "llvm/IR/GlobalValue.h" | |||
46 | #include "llvm/IR/GlobalVariable.h" | |||
47 | #include "llvm/IR/Module.h" | |||
48 | #include "llvm/MC/MCAsmInfo.h" | |||
49 | #include "llvm/MC/MCContext.h" | |||
50 | #include "llvm/MC/MCExpr.h" | |||
51 | #include "llvm/MC/MCInst.h" | |||
52 | #include "llvm/MC/MCInstBuilder.h" | |||
53 | #include "llvm/MC/MCSectionELF.h" | |||
54 | #include "llvm/MC/MCSectionMachO.h" | |||
55 | #include "llvm/MC/MCSectionXCOFF.h" | |||
56 | #include "llvm/MC/MCStreamer.h" | |||
57 | #include "llvm/MC/MCSymbol.h" | |||
58 | #include "llvm/MC/MCSymbolELF.h" | |||
59 | #include "llvm/MC/MCSymbolXCOFF.h" | |||
60 | #include "llvm/MC/SectionKind.h" | |||
61 | #include "llvm/Support/Casting.h" | |||
62 | #include "llvm/Support/CodeGen.h" | |||
63 | #include "llvm/Support/Debug.h" | |||
64 | #include "llvm/Support/ErrorHandling.h" | |||
65 | #include "llvm/Support/TargetRegistry.h" | |||
66 | #include "llvm/Support/raw_ostream.h" | |||
67 | #include "llvm/Target/TargetMachine.h" | |||
68 | #include <algorithm> | |||
69 | #include <cassert> | |||
70 | #include <cstdint> | |||
71 | #include <memory> | |||
72 | #include <new> | |||
73 | ||||
74 | using namespace llvm; | |||
75 | ||||
76 | #define DEBUG_TYPE"asmprinter" "asmprinter" | |||
77 | ||||
78 | namespace { | |||
79 | ||||
80 | class PPCAsmPrinter : public AsmPrinter { | |||
81 | protected: | |||
82 | MapVector<const MCSymbol *, MCSymbol *> TOC; | |||
83 | const PPCSubtarget *Subtarget = nullptr; | |||
84 | StackMaps SM; | |||
85 | ||||
86 | virtual MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO); | |||
87 | ||||
88 | public: | |||
89 | explicit PPCAsmPrinter(TargetMachine &TM, | |||
90 | std::unique_ptr<MCStreamer> Streamer) | |||
91 | : AsmPrinter(TM, std::move(Streamer)), SM(*this) {} | |||
92 | ||||
93 | StringRef getPassName() const override { return "PowerPC Assembly Printer"; } | |||
94 | ||||
95 | MCSymbol *lookUpOrCreateTOCEntry(const MCSymbol *Sym); | |||
96 | ||||
97 | bool doInitialization(Module &M) override { | |||
98 | if (!TOC.empty()) | |||
99 | TOC.clear(); | |||
100 | return AsmPrinter::doInitialization(M); | |||
101 | } | |||
102 | ||||
103 | void emitInstruction(const MachineInstr *MI) override; | |||
104 | ||||
105 | /// This function is for PrintAsmOperand and PrintAsmMemoryOperand, | |||
106 | /// invoked by EmitMSInlineAsmStr and EmitGCCInlineAsmStr only. | |||
107 | /// The \p MI would be INLINEASM ONLY. | |||
108 | void printOperand(const MachineInstr *MI, unsigned OpNo, raw_ostream &O); | |||
109 | ||||
110 | void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override; | |||
111 | bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, | |||
112 | const char *ExtraCode, raw_ostream &O) override; | |||
113 | bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, | |||
114 | const char *ExtraCode, raw_ostream &O) override; | |||
115 | ||||
116 | void emitEndOfAsmFile(Module &M) override; | |||
117 | ||||
118 | void LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI); | |||
119 | void LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI); | |||
120 | void EmitTlsCall(const MachineInstr *MI, MCSymbolRefExpr::VariantKind VK); | |||
121 | bool runOnMachineFunction(MachineFunction &MF) override { | |||
122 | Subtarget = &MF.getSubtarget<PPCSubtarget>(); | |||
123 | bool Changed = AsmPrinter::runOnMachineFunction(MF); | |||
124 | emitXRayTable(); | |||
125 | return Changed; | |||
126 | } | |||
127 | }; | |||
128 | ||||
129 | /// PPCLinuxAsmPrinter - PowerPC assembly printer, customized for Linux | |||
130 | class PPCLinuxAsmPrinter : public PPCAsmPrinter { | |||
131 | public: | |||
132 | explicit PPCLinuxAsmPrinter(TargetMachine &TM, | |||
133 | std::unique_ptr<MCStreamer> Streamer) | |||
134 | : PPCAsmPrinter(TM, std::move(Streamer)) {} | |||
135 | ||||
136 | StringRef getPassName() const override { | |||
137 | return "Linux PPC Assembly Printer"; | |||
138 | } | |||
139 | ||||
140 | void emitStartOfAsmFile(Module &M) override; | |||
141 | void emitEndOfAsmFile(Module &) override; | |||
142 | ||||
143 | void emitFunctionEntryLabel() override; | |||
144 | ||||
145 | void emitFunctionBodyStart() override; | |||
146 | void emitFunctionBodyEnd() override; | |||
147 | void emitInstruction(const MachineInstr *MI) override; | |||
148 | }; | |||
149 | ||||
150 | class PPCAIXAsmPrinter : public PPCAsmPrinter { | |||
151 | private: | |||
152 | static void ValidateGV(const GlobalVariable *GV); | |||
153 | protected: | |||
154 | MCSymbol *getMCSymbolForTOCPseudoMO(const MachineOperand &MO) override; | |||
155 | ||||
156 | public: | |||
157 | PPCAIXAsmPrinter(TargetMachine &TM, std::unique_ptr<MCStreamer> Streamer) | |||
158 | : PPCAsmPrinter(TM, std::move(Streamer)) {} | |||
159 | ||||
160 | StringRef getPassName() const override { return "AIX PPC Assembly Printer"; } | |||
161 | ||||
162 | void SetupMachineFunction(MachineFunction &MF) override; | |||
163 | ||||
164 | const MCExpr *lowerConstant(const Constant *CV) override; | |||
165 | ||||
166 | void emitGlobalVariable(const GlobalVariable *GV) override; | |||
167 | ||||
168 | void emitFunctionDescriptor() override; | |||
169 | ||||
170 | void emitEndOfAsmFile(Module &) override; | |||
171 | }; | |||
172 | ||||
173 | } // end anonymous namespace | |||
174 | ||||
175 | void PPCAsmPrinter::PrintSymbolOperand(const MachineOperand &MO, | |||
176 | raw_ostream &O) { | |||
177 | // Computing the address of a global symbol, not calling it. | |||
178 | const GlobalValue *GV = MO.getGlobal(); | |||
179 | getSymbol(GV)->print(O, MAI); | |||
180 | printOffset(MO.getOffset(), O); | |||
181 | } | |||
182 | ||||
183 | void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo, | |||
184 | raw_ostream &O) { | |||
185 | const DataLayout &DL = getDataLayout(); | |||
186 | const MachineOperand &MO = MI->getOperand(OpNo); | |||
187 | ||||
188 | switch (MO.getType()) { | |||
189 | case MachineOperand::MO_Register: { | |||
190 | // The MI is INLINEASM ONLY and UseVSXReg is always false. | |||
191 | const char *RegName = PPCInstPrinter::getRegisterName(MO.getReg()); | |||
192 | ||||
193 | // Linux assembler (Others?) does not take register mnemonics. | |||
194 | // FIXME - What about special registers used in mfspr/mtspr? | |||
195 | O << PPCRegisterInfo::stripRegisterPrefix(RegName); | |||
196 | return; | |||
197 | } | |||
198 | case MachineOperand::MO_Immediate: | |||
199 | O << MO.getImm(); | |||
200 | return; | |||
201 | ||||
202 | case MachineOperand::MO_MachineBasicBlock: | |||
203 | MO.getMBB()->getSymbol()->print(O, MAI); | |||
204 | return; | |||
205 | case MachineOperand::MO_ConstantPoolIndex: | |||
206 | O << DL.getPrivateGlobalPrefix() << "CPI" << getFunctionNumber() << '_' | |||
207 | << MO.getIndex(); | |||
208 | return; | |||
209 | case MachineOperand::MO_BlockAddress: | |||
210 | GetBlockAddressSymbol(MO.getBlockAddress())->print(O, MAI); | |||
211 | return; | |||
212 | case MachineOperand::MO_GlobalAddress: { | |||
213 | PrintSymbolOperand(MO, O); | |||
214 | return; | |||
215 | } | |||
216 | ||||
217 | default: | |||
218 | O << "<unknown operand type: " << (unsigned)MO.getType() << ">"; | |||
219 | return; | |||
220 | } | |||
221 | } | |||
222 | ||||
223 | /// PrintAsmOperand - Print out an operand for an inline asm expression. | |||
224 | /// | |||
225 | bool PPCAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, | |||
226 | const char *ExtraCode, raw_ostream &O) { | |||
227 | // Does this asm operand have a single letter operand modifier? | |||
228 | if (ExtraCode && ExtraCode[0]) { | |||
229 | if (ExtraCode[1] != 0) return true; // Unknown modifier. | |||
230 | ||||
231 | switch (ExtraCode[0]) { | |||
232 | default: | |||
233 | // See if this is a generic print operand | |||
234 | return AsmPrinter::PrintAsmOperand(MI, OpNo, ExtraCode, O); | |||
235 | case 'L': // Write second word of DImode reference. | |||
236 | // Verify that this operand has two consecutive registers. | |||
237 | if (!MI->getOperand(OpNo).isReg() || | |||
238 | OpNo+1 == MI->getNumOperands() || | |||
239 | !MI->getOperand(OpNo+1).isReg()) | |||
240 | return true; | |||
241 | ++OpNo; // Return the high-part. | |||
242 | break; | |||
243 | case 'I': | |||
244 | // Write 'i' if an integer constant, otherwise nothing. Used to print | |||
245 | // addi vs add, etc. | |||
246 | if (MI->getOperand(OpNo).isImm()) | |||
247 | O << "i"; | |||
248 | return false; | |||
249 | case 'x': | |||
250 | if(!MI->getOperand(OpNo).isReg()) | |||
251 | return true; | |||
252 | // This operand uses VSX numbering. | |||
253 | // If the operand is a VMX register, convert it to a VSX register. | |||
254 | Register Reg = MI->getOperand(OpNo).getReg(); | |||
255 | if (PPCInstrInfo::isVRRegister(Reg)) | |||
256 | Reg = PPC::VSX32 + (Reg - PPC::V0); | |||
257 | else if (PPCInstrInfo::isVFRegister(Reg)) | |||
258 | Reg = PPC::VSX32 + (Reg - PPC::VF0); | |||
259 | const char *RegName; | |||
260 | RegName = PPCInstPrinter::getRegisterName(Reg); | |||
261 | RegName = PPCRegisterInfo::stripRegisterPrefix(RegName); | |||
262 | O << RegName; | |||
263 | return false; | |||
264 | } | |||
265 | } | |||
266 | ||||
267 | printOperand(MI, OpNo, O); | |||
268 | return false; | |||
269 | } | |||
270 | ||||
271 | // At the moment, all inline asm memory operands are a single register. | |||
272 | // In any case, the output of this routine should always be just one | |||
273 | // assembler operand. | |||
274 | ||||
275 | bool PPCAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, | |||
276 | const char *ExtraCode, | |||
277 | raw_ostream &O) { | |||
278 | if (ExtraCode && ExtraCode[0]) { | |||
279 | if (ExtraCode[1] != 0) return true; // Unknown modifier. | |||
280 | ||||
281 | switch (ExtraCode[0]) { | |||
282 | default: return true; // Unknown modifier. | |||
283 | case 'y': { // A memory reference for an X-form instruction | |||
284 | O << "0, "; | |||
285 | printOperand(MI, OpNo, O); | |||
286 | return false; | |||
287 | } | |||
288 | case 'U': // Print 'u' for update form. | |||
289 | case 'X': // Print 'x' for indexed form. | |||
290 | { | |||
291 | // FIXME: Currently for PowerPC memory operands are always loaded | |||
292 | // into a register, so we never get an update or indexed form. | |||
293 | // This is bad even for offset forms, since even if we know we | |||
294 | // have a value in -16(r1), we will generate a load into r<n> | |||
295 | // and then load from 0(r<n>). Until that issue is fixed, | |||
296 | // tolerate 'U' and 'X' but don't output anything. | |||
297 | assert(MI->getOperand(OpNo).isReg())((MI->getOperand(OpNo).isReg()) ? static_cast<void> ( 0) : __assert_fail ("MI->getOperand(OpNo).isReg()", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 297, __PRETTY_FUNCTION__)); | |||
298 | return false; | |||
299 | } | |||
300 | } | |||
301 | } | |||
302 | ||||
303 | assert(MI->getOperand(OpNo).isReg())((MI->getOperand(OpNo).isReg()) ? static_cast<void> ( 0) : __assert_fail ("MI->getOperand(OpNo).isReg()", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 303, __PRETTY_FUNCTION__)); | |||
304 | O << "0("; | |||
305 | printOperand(MI, OpNo, O); | |||
306 | O << ")"; | |||
307 | return false; | |||
308 | } | |||
309 | ||||
310 | /// lookUpOrCreateTOCEntry -- Given a symbol, look up whether a TOC entry | |||
311 | /// exists for it. If not, create one. Then return a symbol that references | |||
312 | /// the TOC entry. | |||
313 | MCSymbol *PPCAsmPrinter::lookUpOrCreateTOCEntry(const MCSymbol *Sym) { | |||
314 | MCSymbol *&TOCEntry = TOC[Sym]; | |||
315 | if (!TOCEntry) | |||
316 | TOCEntry = createTempSymbol("C"); | |||
317 | return TOCEntry; | |||
318 | } | |||
319 | ||||
320 | void PPCAsmPrinter::emitEndOfAsmFile(Module &M) { | |||
321 | emitStackMaps(SM); | |||
322 | } | |||
323 | ||||
324 | void PPCAsmPrinter::LowerSTACKMAP(StackMaps &SM, const MachineInstr &MI) { | |||
325 | unsigned NumNOPBytes = MI.getOperand(1).getImm(); | |||
326 | ||||
327 | auto &Ctx = OutStreamer->getContext(); | |||
328 | MCSymbol *MILabel = Ctx.createTempSymbol(); | |||
329 | OutStreamer->emitLabel(MILabel); | |||
330 | ||||
331 | SM.recordStackMap(*MILabel, MI); | |||
332 | assert(NumNOPBytes % 4 == 0 && "Invalid number of NOP bytes requested!")((NumNOPBytes % 4 == 0 && "Invalid number of NOP bytes requested!" ) ? static_cast<void> (0) : __assert_fail ("NumNOPBytes % 4 == 0 && \"Invalid number of NOP bytes requested!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 332, __PRETTY_FUNCTION__)); | |||
333 | ||||
334 | // Scan ahead to trim the shadow. | |||
335 | const MachineBasicBlock &MBB = *MI.getParent(); | |||
336 | MachineBasicBlock::const_iterator MII(MI); | |||
337 | ++MII; | |||
338 | while (NumNOPBytes > 0) { | |||
339 | if (MII == MBB.end() || MII->isCall() || | |||
340 | MII->getOpcode() == PPC::DBG_VALUE || | |||
341 | MII->getOpcode() == TargetOpcode::PATCHPOINT || | |||
342 | MII->getOpcode() == TargetOpcode::STACKMAP) | |||
343 | break; | |||
344 | ++MII; | |||
345 | NumNOPBytes -= 4; | |||
346 | } | |||
347 | ||||
348 | // Emit nops. | |||
349 | for (unsigned i = 0; i < NumNOPBytes; i += 4) | |||
350 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP)); | |||
351 | } | |||
352 | ||||
353 | // Lower a patchpoint of the form: | |||
354 | // [<def>], <id>, <numBytes>, <target>, <numArgs> | |||
355 | void PPCAsmPrinter::LowerPATCHPOINT(StackMaps &SM, const MachineInstr &MI) { | |||
356 | auto &Ctx = OutStreamer->getContext(); | |||
357 | MCSymbol *MILabel = Ctx.createTempSymbol(); | |||
358 | OutStreamer->emitLabel(MILabel); | |||
359 | ||||
360 | SM.recordPatchPoint(*MILabel, MI); | |||
361 | PatchPointOpers Opers(&MI); | |||
362 | ||||
363 | unsigned EncodedBytes = 0; | |||
364 | const MachineOperand &CalleeMO = Opers.getCallTarget(); | |||
365 | ||||
366 | if (CalleeMO.isImm()) { | |||
367 | int64_t CallTarget = CalleeMO.getImm(); | |||
368 | if (CallTarget) { | |||
369 | assert((CallTarget & 0xFFFFFFFFFFFF) == CallTarget &&(((CallTarget & 0xFFFFFFFFFFFF) == CallTarget && "High 16 bits of call target should be zero." ) ? static_cast<void> (0) : __assert_fail ("(CallTarget & 0xFFFFFFFFFFFF) == CallTarget && \"High 16 bits of call target should be zero.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 370, __PRETTY_FUNCTION__)) | |||
370 | "High 16 bits of call target should be zero.")(((CallTarget & 0xFFFFFFFFFFFF) == CallTarget && "High 16 bits of call target should be zero." ) ? static_cast<void> (0) : __assert_fail ("(CallTarget & 0xFFFFFFFFFFFF) == CallTarget && \"High 16 bits of call target should be zero.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 370, __PRETTY_FUNCTION__)); | |||
371 | Register ScratchReg = MI.getOperand(Opers.getNextScratchIdx()).getReg(); | |||
372 | EncodedBytes = 0; | |||
373 | // Materialize the jump address: | |||
374 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI8) | |||
375 | .addReg(ScratchReg) | |||
376 | .addImm((CallTarget >> 32) & 0xFFFF)); | |||
377 | ++EncodedBytes; | |||
378 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::RLDIC) | |||
379 | .addReg(ScratchReg) | |||
380 | .addReg(ScratchReg) | |||
381 | .addImm(32).addImm(16)); | |||
382 | ++EncodedBytes; | |||
383 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ORIS8) | |||
384 | .addReg(ScratchReg) | |||
385 | .addReg(ScratchReg) | |||
386 | .addImm((CallTarget >> 16) & 0xFFFF)); | |||
387 | ++EncodedBytes; | |||
388 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ORI8) | |||
389 | .addReg(ScratchReg) | |||
390 | .addReg(ScratchReg) | |||
391 | .addImm(CallTarget & 0xFFFF)); | |||
392 | ||||
393 | // Save the current TOC pointer before the remote call. | |||
394 | int TOCSaveOffset = Subtarget->getFrameLowering()->getTOCSaveOffset(); | |||
395 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::STD) | |||
396 | .addReg(PPC::X2) | |||
397 | .addImm(TOCSaveOffset) | |||
398 | .addReg(PPC::X1)); | |||
399 | ++EncodedBytes; | |||
400 | ||||
401 | // If we're on ELFv1, then we need to load the actual function pointer | |||
402 | // from the function descriptor. | |||
403 | if (!Subtarget->isELFv2ABI()) { | |||
404 | // Load the new TOC pointer and the function address, but not r11 | |||
405 | // (needing this is rare, and loading it here would prevent passing it | |||
406 | // via a 'nest' parameter. | |||
407 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD) | |||
408 | .addReg(PPC::X2) | |||
409 | .addImm(8) | |||
410 | .addReg(ScratchReg)); | |||
411 | ++EncodedBytes; | |||
412 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD) | |||
413 | .addReg(ScratchReg) | |||
414 | .addImm(0) | |||
415 | .addReg(ScratchReg)); | |||
416 | ++EncodedBytes; | |||
417 | } | |||
418 | ||||
419 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTCTR8) | |||
420 | .addReg(ScratchReg)); | |||
421 | ++EncodedBytes; | |||
422 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BCTRL8)); | |||
423 | ++EncodedBytes; | |||
424 | ||||
425 | // Restore the TOC pointer after the call. | |||
426 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD) | |||
427 | .addReg(PPC::X2) | |||
428 | .addImm(TOCSaveOffset) | |||
429 | .addReg(PPC::X1)); | |||
430 | ++EncodedBytes; | |||
431 | } | |||
432 | } else if (CalleeMO.isGlobal()) { | |||
433 | const GlobalValue *GValue = CalleeMO.getGlobal(); | |||
434 | MCSymbol *MOSymbol = getSymbol(GValue); | |||
435 | const MCExpr *SymVar = MCSymbolRefExpr::create(MOSymbol, OutContext); | |||
436 | ||||
437 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL8_NOP) | |||
438 | .addExpr(SymVar)); | |||
439 | EncodedBytes += 2; | |||
440 | } | |||
441 | ||||
442 | // Each instruction is 4 bytes. | |||
443 | EncodedBytes *= 4; | |||
444 | ||||
445 | // Emit padding. | |||
446 | unsigned NumBytes = Opers.getNumPatchBytes(); | |||
447 | assert(NumBytes >= EncodedBytes &&((NumBytes >= EncodedBytes && "Patchpoint can't request size less than the length of a call." ) ? static_cast<void> (0) : __assert_fail ("NumBytes >= EncodedBytes && \"Patchpoint can't request size less than the length of a call.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 448, __PRETTY_FUNCTION__)) | |||
448 | "Patchpoint can't request size less than the length of a call.")((NumBytes >= EncodedBytes && "Patchpoint can't request size less than the length of a call." ) ? static_cast<void> (0) : __assert_fail ("NumBytes >= EncodedBytes && \"Patchpoint can't request size less than the length of a call.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 448, __PRETTY_FUNCTION__)); | |||
449 | assert((NumBytes - EncodedBytes) % 4 == 0 &&(((NumBytes - EncodedBytes) % 4 == 0 && "Invalid number of NOP bytes requested!" ) ? static_cast<void> (0) : __assert_fail ("(NumBytes - EncodedBytes) % 4 == 0 && \"Invalid number of NOP bytes requested!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 450, __PRETTY_FUNCTION__)) | |||
450 | "Invalid number of NOP bytes requested!")(((NumBytes - EncodedBytes) % 4 == 0 && "Invalid number of NOP bytes requested!" ) ? static_cast<void> (0) : __assert_fail ("(NumBytes - EncodedBytes) % 4 == 0 && \"Invalid number of NOP bytes requested!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 450, __PRETTY_FUNCTION__)); | |||
451 | for (unsigned i = EncodedBytes; i < NumBytes; i += 4) | |||
452 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP)); | |||
453 | } | |||
454 | ||||
455 | /// EmitTlsCall -- Given a GETtls[ld]ADDR[32] instruction, print a | |||
456 | /// call to __tls_get_addr to the current output stream. | |||
457 | void PPCAsmPrinter::EmitTlsCall(const MachineInstr *MI, | |||
458 | MCSymbolRefExpr::VariantKind VK) { | |||
459 | StringRef Name = "__tls_get_addr"; | |||
460 | MCSymbol *TlsGetAddr = OutContext.getOrCreateSymbol(Name); | |||
461 | MCSymbolRefExpr::VariantKind Kind = MCSymbolRefExpr::VK_None; | |||
462 | const Module *M = MF->getFunction().getParent(); | |||
463 | ||||
464 | assert(MI->getOperand(0).isReg() &&((MI->getOperand(0).isReg() && ((Subtarget->isPPC64 () && MI->getOperand(0).getReg() == PPC::X3) || (! Subtarget->isPPC64() && MI->getOperand(0).getReg () == PPC::R3)) && "GETtls[ld]ADDR[32] must define GPR3" ) ? static_cast<void> (0) : __assert_fail ("MI->getOperand(0).isReg() && ((Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::X3) || (!Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::R3)) && \"GETtls[ld]ADDR[32] must define GPR3\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 467, __PRETTY_FUNCTION__)) | |||
465 | ((Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::X3) ||((MI->getOperand(0).isReg() && ((Subtarget->isPPC64 () && MI->getOperand(0).getReg() == PPC::X3) || (! Subtarget->isPPC64() && MI->getOperand(0).getReg () == PPC::R3)) && "GETtls[ld]ADDR[32] must define GPR3" ) ? static_cast<void> (0) : __assert_fail ("MI->getOperand(0).isReg() && ((Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::X3) || (!Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::R3)) && \"GETtls[ld]ADDR[32] must define GPR3\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 467, __PRETTY_FUNCTION__)) | |||
466 | (!Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::R3)) &&((MI->getOperand(0).isReg() && ((Subtarget->isPPC64 () && MI->getOperand(0).getReg() == PPC::X3) || (! Subtarget->isPPC64() && MI->getOperand(0).getReg () == PPC::R3)) && "GETtls[ld]ADDR[32] must define GPR3" ) ? static_cast<void> (0) : __assert_fail ("MI->getOperand(0).isReg() && ((Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::X3) || (!Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::R3)) && \"GETtls[ld]ADDR[32] must define GPR3\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 467, __PRETTY_FUNCTION__)) | |||
467 | "GETtls[ld]ADDR[32] must define GPR3")((MI->getOperand(0).isReg() && ((Subtarget->isPPC64 () && MI->getOperand(0).getReg() == PPC::X3) || (! Subtarget->isPPC64() && MI->getOperand(0).getReg () == PPC::R3)) && "GETtls[ld]ADDR[32] must define GPR3" ) ? static_cast<void> (0) : __assert_fail ("MI->getOperand(0).isReg() && ((Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::X3) || (!Subtarget->isPPC64() && MI->getOperand(0).getReg() == PPC::R3)) && \"GETtls[ld]ADDR[32] must define GPR3\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 467, __PRETTY_FUNCTION__)); | |||
468 | assert(MI->getOperand(1).isReg() &&((MI->getOperand(1).isReg() && ((Subtarget->isPPC64 () && MI->getOperand(1).getReg() == PPC::X3) || (! Subtarget->isPPC64() && MI->getOperand(1).getReg () == PPC::R3)) && "GETtls[ld]ADDR[32] must read GPR3" ) ? static_cast<void> (0) : __assert_fail ("MI->getOperand(1).isReg() && ((Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::X3) || (!Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::R3)) && \"GETtls[ld]ADDR[32] must read GPR3\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 471, __PRETTY_FUNCTION__)) | |||
469 | ((Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::X3) ||((MI->getOperand(1).isReg() && ((Subtarget->isPPC64 () && MI->getOperand(1).getReg() == PPC::X3) || (! Subtarget->isPPC64() && MI->getOperand(1).getReg () == PPC::R3)) && "GETtls[ld]ADDR[32] must read GPR3" ) ? static_cast<void> (0) : __assert_fail ("MI->getOperand(1).isReg() && ((Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::X3) || (!Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::R3)) && \"GETtls[ld]ADDR[32] must read GPR3\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 471, __PRETTY_FUNCTION__)) | |||
470 | (!Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::R3)) &&((MI->getOperand(1).isReg() && ((Subtarget->isPPC64 () && MI->getOperand(1).getReg() == PPC::X3) || (! Subtarget->isPPC64() && MI->getOperand(1).getReg () == PPC::R3)) && "GETtls[ld]ADDR[32] must read GPR3" ) ? static_cast<void> (0) : __assert_fail ("MI->getOperand(1).isReg() && ((Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::X3) || (!Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::R3)) && \"GETtls[ld]ADDR[32] must read GPR3\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 471, __PRETTY_FUNCTION__)) | |||
471 | "GETtls[ld]ADDR[32] must read GPR3")((MI->getOperand(1).isReg() && ((Subtarget->isPPC64 () && MI->getOperand(1).getReg() == PPC::X3) || (! Subtarget->isPPC64() && MI->getOperand(1).getReg () == PPC::R3)) && "GETtls[ld]ADDR[32] must read GPR3" ) ? static_cast<void> (0) : __assert_fail ("MI->getOperand(1).isReg() && ((Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::X3) || (!Subtarget->isPPC64() && MI->getOperand(1).getReg() == PPC::R3)) && \"GETtls[ld]ADDR[32] must read GPR3\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 471, __PRETTY_FUNCTION__)); | |||
472 | ||||
473 | if (Subtarget->is32BitELFABI() && isPositionIndependent()) | |||
474 | Kind = MCSymbolRefExpr::VK_PLT; | |||
475 | ||||
476 | const MCExpr *TlsRef = | |||
477 | MCSymbolRefExpr::create(TlsGetAddr, Kind, OutContext); | |||
478 | ||||
479 | // Add 32768 offset to the symbol so we follow up the latest GOT/PLT ABI. | |||
480 | if (Kind == MCSymbolRefExpr::VK_PLT && Subtarget->isSecurePlt() && | |||
481 | M->getPICLevel() == PICLevel::BigPIC) | |||
482 | TlsRef = MCBinaryExpr::createAdd( | |||
483 | TlsRef, MCConstantExpr::create(32768, OutContext), OutContext); | |||
484 | const MachineOperand &MO = MI->getOperand(2); | |||
485 | const GlobalValue *GValue = MO.getGlobal(); | |||
486 | MCSymbol *MOSymbol = getSymbol(GValue); | |||
487 | const MCExpr *SymVar = MCSymbolRefExpr::create(MOSymbol, VK, OutContext); | |||
488 | EmitToStreamer(*OutStreamer, | |||
489 | MCInstBuilder(Subtarget->isPPC64() ? | |||
490 | PPC::BL8_NOP_TLS : PPC::BL_TLS) | |||
491 | .addExpr(TlsRef) | |||
492 | .addExpr(SymVar)); | |||
493 | } | |||
494 | ||||
495 | /// Map a machine operand for a TOC pseudo-machine instruction to its | |||
496 | /// corresponding MCSymbol. | |||
497 | MCSymbol *PPCAsmPrinter::getMCSymbolForTOCPseudoMO(const MachineOperand &MO) { | |||
498 | switch (MO.getType()) { | |||
499 | case MachineOperand::MO_GlobalAddress: | |||
500 | return getSymbol(MO.getGlobal()); | |||
501 | case MachineOperand::MO_ConstantPoolIndex: | |||
502 | return GetCPISymbol(MO.getIndex()); | |||
503 | case MachineOperand::MO_JumpTableIndex: | |||
504 | return GetJTISymbol(MO.getIndex()); | |||
505 | case MachineOperand::MO_BlockAddress: | |||
506 | return GetBlockAddressSymbol(MO.getBlockAddress()); | |||
507 | default: | |||
508 | llvm_unreachable("Unexpected operand type to get symbol.")::llvm::llvm_unreachable_internal("Unexpected operand type to get symbol." , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 508); | |||
509 | } | |||
510 | } | |||
511 | ||||
512 | /// EmitInstruction -- Print out a single PowerPC MI in Darwin syntax to | |||
513 | /// the current output stream. | |||
514 | /// | |||
515 | void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) { | |||
516 | MCInst TmpInst; | |||
517 | const bool IsPPC64 = Subtarget->isPPC64(); | |||
518 | const bool IsAIX = Subtarget->isAIXABI(); | |||
519 | const Module *M = MF->getFunction().getParent(); | |||
520 | PICLevel::Level PL = M->getPICLevel(); | |||
521 | ||||
522 | #ifndef NDEBUG | |||
523 | // Validate that SPE and FPU are mutually exclusive in codegen | |||
524 | if (!MI->isInlineAsm()) { | |||
525 | for (const MachineOperand &MO: MI->operands()) { | |||
526 | if (MO.isReg()) { | |||
527 | Register Reg = MO.getReg(); | |||
528 | if (Subtarget->hasSPE()) { | |||
529 | if (PPC::F4RCRegClass.contains(Reg) || | |||
530 | PPC::F8RCRegClass.contains(Reg) || | |||
531 | PPC::QBRCRegClass.contains(Reg) || | |||
532 | PPC::QFRCRegClass.contains(Reg) || | |||
533 | PPC::QSRCRegClass.contains(Reg) || | |||
534 | PPC::VFRCRegClass.contains(Reg) || | |||
535 | PPC::VRRCRegClass.contains(Reg) || | |||
536 | PPC::VSFRCRegClass.contains(Reg) || | |||
537 | PPC::VSSRCRegClass.contains(Reg) | |||
538 | ) | |||
539 | llvm_unreachable("SPE targets cannot have FPRegs!")::llvm::llvm_unreachable_internal("SPE targets cannot have FPRegs!" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 539); | |||
540 | } else { | |||
541 | if (PPC::SPERCRegClass.contains(Reg)) | |||
542 | llvm_unreachable("SPE register found in FPU-targeted code!")::llvm::llvm_unreachable_internal("SPE register found in FPU-targeted code!" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 542); | |||
543 | } | |||
544 | } | |||
545 | } | |||
546 | } | |||
547 | #endif | |||
548 | // Lower multi-instruction pseudo operations. | |||
549 | switch (MI->getOpcode()) { | |||
550 | default: break; | |||
551 | case TargetOpcode::DBG_VALUE: | |||
552 | llvm_unreachable("Should be handled target independently")::llvm::llvm_unreachable_internal("Should be handled target independently" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 552); | |||
553 | case TargetOpcode::STACKMAP: | |||
554 | return LowerSTACKMAP(SM, *MI); | |||
555 | case TargetOpcode::PATCHPOINT: | |||
556 | return LowerPATCHPOINT(SM, *MI); | |||
557 | ||||
558 | case PPC::MoveGOTtoLR: { | |||
559 | // Transform %lr = MoveGOTtoLR | |||
560 | // Into this: bl _GLOBAL_OFFSET_TABLE_@local-4 | |||
561 | // _GLOBAL_OFFSET_TABLE_@local-4 (instruction preceding | |||
562 | // _GLOBAL_OFFSET_TABLE_) has exactly one instruction: | |||
563 | // blrl | |||
564 | // This will return the pointer to _GLOBAL_OFFSET_TABLE_@local | |||
565 | MCSymbol *GOTSymbol = | |||
566 | OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_")); | |||
567 | const MCExpr *OffsExpr = | |||
568 | MCBinaryExpr::createSub(MCSymbolRefExpr::create(GOTSymbol, | |||
569 | MCSymbolRefExpr::VK_PPC_LOCAL, | |||
570 | OutContext), | |||
571 | MCConstantExpr::create(4, OutContext), | |||
572 | OutContext); | |||
573 | ||||
574 | // Emit the 'bl'. | |||
575 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL).addExpr(OffsExpr)); | |||
576 | return; | |||
577 | } | |||
578 | case PPC::MovePCtoLR: | |||
579 | case PPC::MovePCtoLR8: { | |||
580 | // Transform %lr = MovePCtoLR | |||
581 | // Into this, where the label is the PIC base: | |||
582 | // bl L1$pb | |||
583 | // L1$pb: | |||
584 | MCSymbol *PICBase = MF->getPICBaseSymbol(); | |||
585 | ||||
586 | // Emit the 'bl'. | |||
587 | EmitToStreamer(*OutStreamer, | |||
588 | MCInstBuilder(PPC::BL) | |||
589 | // FIXME: We would like an efficient form for this, so we | |||
590 | // don't have to do a lot of extra uniquing. | |||
591 | .addExpr(MCSymbolRefExpr::create(PICBase, OutContext))); | |||
592 | ||||
593 | // Emit the label. | |||
594 | OutStreamer->emitLabel(PICBase); | |||
595 | return; | |||
596 | } | |||
597 | case PPC::UpdateGBR: { | |||
598 | // Transform %rd = UpdateGBR(%rt, %ri) | |||
599 | // Into: lwz %rt, .L0$poff - .L0$pb(%ri) | |||
600 | // add %rd, %rt, %ri | |||
601 | // or into (if secure plt mode is on): | |||
602 | // addis r30, r30, {.LTOC,_GLOBAL_OFFSET_TABLE} - .L0$pb@ha | |||
603 | // addi r30, r30, {.LTOC,_GLOBAL_OFFSET_TABLE} - .L0$pb@l | |||
604 | // Get the offset from the GOT Base Register to the GOT | |||
605 | LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); | |||
606 | if (Subtarget->isSecurePlt() && isPositionIndependent() ) { | |||
607 | unsigned PICR = TmpInst.getOperand(0).getReg(); | |||
608 | MCSymbol *BaseSymbol = OutContext.getOrCreateSymbol( | |||
609 | M->getPICLevel() == PICLevel::SmallPIC ? "_GLOBAL_OFFSET_TABLE_" | |||
610 | : ".LTOC"); | |||
611 | const MCExpr *PB = | |||
612 | MCSymbolRefExpr::create(MF->getPICBaseSymbol(), OutContext); | |||
613 | ||||
614 | const MCExpr *DeltaExpr = MCBinaryExpr::createSub( | |||
615 | MCSymbolRefExpr::create(BaseSymbol, OutContext), PB, OutContext); | |||
616 | ||||
617 | const MCExpr *DeltaHi = PPCMCExpr::createHa(DeltaExpr, OutContext); | |||
618 | EmitToStreamer( | |||
619 | *OutStreamer, | |||
620 | MCInstBuilder(PPC::ADDIS).addReg(PICR).addReg(PICR).addExpr(DeltaHi)); | |||
621 | ||||
622 | const MCExpr *DeltaLo = PPCMCExpr::createLo(DeltaExpr, OutContext); | |||
623 | EmitToStreamer( | |||
624 | *OutStreamer, | |||
625 | MCInstBuilder(PPC::ADDI).addReg(PICR).addReg(PICR).addExpr(DeltaLo)); | |||
626 | return; | |||
627 | } else { | |||
628 | MCSymbol *PICOffset = | |||
629 | MF->getInfo<PPCFunctionInfo>()->getPICOffsetSymbol(); | |||
630 | TmpInst.setOpcode(PPC::LWZ); | |||
631 | const MCExpr *Exp = | |||
632 | MCSymbolRefExpr::create(PICOffset, MCSymbolRefExpr::VK_None, OutContext); | |||
633 | const MCExpr *PB = | |||
634 | MCSymbolRefExpr::create(MF->getPICBaseSymbol(), | |||
635 | MCSymbolRefExpr::VK_None, | |||
636 | OutContext); | |||
637 | const MCOperand TR = TmpInst.getOperand(1); | |||
638 | const MCOperand PICR = TmpInst.getOperand(0); | |||
639 | ||||
640 | // Step 1: lwz %rt, .L$poff - .L$pb(%ri) | |||
641 | TmpInst.getOperand(1) = | |||
642 | MCOperand::createExpr(MCBinaryExpr::createSub(Exp, PB, OutContext)); | |||
643 | TmpInst.getOperand(0) = TR; | |||
644 | TmpInst.getOperand(2) = PICR; | |||
645 | EmitToStreamer(*OutStreamer, TmpInst); | |||
646 | ||||
647 | TmpInst.setOpcode(PPC::ADD4); | |||
648 | TmpInst.getOperand(0) = PICR; | |||
649 | TmpInst.getOperand(1) = TR; | |||
650 | TmpInst.getOperand(2) = PICR; | |||
651 | EmitToStreamer(*OutStreamer, TmpInst); | |||
652 | return; | |||
653 | } | |||
654 | } | |||
655 | case PPC::LWZtoc: { | |||
656 | // Transform %rN = LWZtoc @op1, %r2 | |||
657 | LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); | |||
658 | ||||
659 | // Change the opcode to LWZ. | |||
660 | TmpInst.setOpcode(PPC::LWZ); | |||
661 | ||||
662 | const MachineOperand &MO = MI->getOperand(1); | |||
663 | assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&(((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress ()) && "Invalid operand for LWZtoc.") ? static_cast< void> (0) : __assert_fail ("(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && \"Invalid operand for LWZtoc.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 664, __PRETTY_FUNCTION__)) | |||
664 | "Invalid operand for LWZtoc.")(((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress ()) && "Invalid operand for LWZtoc.") ? static_cast< void> (0) : __assert_fail ("(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && \"Invalid operand for LWZtoc.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 664, __PRETTY_FUNCTION__)); | |||
665 | ||||
666 | // Map the operand to its corresponding MCSymbol. | |||
667 | const MCSymbol *const MOSymbol = getMCSymbolForTOCPseudoMO(MO); | |||
668 | ||||
669 | // Create a reference to the GOT entry for the symbol. The GOT entry will be | |||
670 | // synthesized later. | |||
671 | if (PL == PICLevel::SmallPIC && !IsAIX) { | |||
672 | const MCExpr *Exp = | |||
673 | MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_GOT, | |||
674 | OutContext); | |||
675 | TmpInst.getOperand(1) = MCOperand::createExpr(Exp); | |||
676 | EmitToStreamer(*OutStreamer, TmpInst); | |||
677 | return; | |||
678 | } | |||
679 | ||||
680 | // Otherwise, use the TOC. 'TOCEntry' is a label used to reference the | |||
681 | // storage allocated in the TOC which contains the address of | |||
682 | // 'MOSymbol'. Said TOC entry will be synthesized later. | |||
683 | MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol); | |||
684 | const MCExpr *Exp = | |||
685 | MCSymbolRefExpr::create(TOCEntry, MCSymbolRefExpr::VK_None, OutContext); | |||
686 | ||||
687 | // AIX uses the label directly as the lwz displacement operand for | |||
688 | // references into the toc section. The displacement value will be generated | |||
689 | // relative to the toc-base. | |||
690 | if (IsAIX) { | |||
691 | assert(((TM.getCodeModel() == CodeModel::Small && "This pseudo should only be selected for 32-bit small code model." ) ? static_cast<void> (0) : __assert_fail ("TM.getCodeModel() == CodeModel::Small && \"This pseudo should only be selected for 32-bit small code model.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 693, __PRETTY_FUNCTION__)) | |||
692 | TM.getCodeModel() == CodeModel::Small &&((TM.getCodeModel() == CodeModel::Small && "This pseudo should only be selected for 32-bit small code model." ) ? static_cast<void> (0) : __assert_fail ("TM.getCodeModel() == CodeModel::Small && \"This pseudo should only be selected for 32-bit small code model.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 693, __PRETTY_FUNCTION__)) | |||
693 | "This pseudo should only be selected for 32-bit small code model.")((TM.getCodeModel() == CodeModel::Small && "This pseudo should only be selected for 32-bit small code model." ) ? static_cast<void> (0) : __assert_fail ("TM.getCodeModel() == CodeModel::Small && \"This pseudo should only be selected for 32-bit small code model.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 693, __PRETTY_FUNCTION__)); | |||
694 | TmpInst.getOperand(1) = MCOperand::createExpr(Exp); | |||
695 | EmitToStreamer(*OutStreamer, TmpInst); | |||
696 | return; | |||
697 | } | |||
698 | ||||
699 | // Create an explicit subtract expression between the local symbol and | |||
700 | // '.LTOC' to manifest the toc-relative offset. | |||
701 | const MCExpr *PB = MCSymbolRefExpr::create( | |||
702 | OutContext.getOrCreateSymbol(Twine(".LTOC")), OutContext); | |||
703 | Exp = MCBinaryExpr::createSub(Exp, PB, OutContext); | |||
704 | TmpInst.getOperand(1) = MCOperand::createExpr(Exp); | |||
705 | EmitToStreamer(*OutStreamer, TmpInst); | |||
706 | return; | |||
707 | } | |||
708 | case PPC::LDtocJTI: | |||
709 | case PPC::LDtocCPT: | |||
710 | case PPC::LDtocBA: | |||
711 | case PPC::LDtoc: { | |||
712 | // Transform %x3 = LDtoc @min1, %x2 | |||
713 | LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); | |||
714 | ||||
715 | // Change the opcode to LD. | |||
716 | TmpInst.setOpcode(PPC::LD); | |||
717 | ||||
718 | const MachineOperand &MO = MI->getOperand(1); | |||
719 | assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&(((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress ()) && "Invalid operand!") ? static_cast<void> ( 0) : __assert_fail ("(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && \"Invalid operand!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 720, __PRETTY_FUNCTION__)) | |||
720 | "Invalid operand!")(((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress ()) && "Invalid operand!") ? static_cast<void> ( 0) : __assert_fail ("(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && \"Invalid operand!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 720, __PRETTY_FUNCTION__)); | |||
721 | ||||
722 | // Map the machine operand to its corresponding MCSymbol, then map the | |||
723 | // global address operand to be a reference to the TOC entry we will | |||
724 | // synthesize later. | |||
725 | MCSymbol *TOCEntry = | |||
726 | lookUpOrCreateTOCEntry(getMCSymbolForTOCPseudoMO(MO)); | |||
727 | ||||
728 | const MCSymbolRefExpr::VariantKind VK = | |||
729 | IsAIX ? MCSymbolRefExpr::VK_None : MCSymbolRefExpr::VK_PPC_TOC; | |||
730 | const MCExpr *Exp = | |||
731 | MCSymbolRefExpr::create(TOCEntry, VK, OutContext); | |||
732 | TmpInst.getOperand(1) = MCOperand::createExpr(Exp); | |||
733 | EmitToStreamer(*OutStreamer, TmpInst); | |||
734 | return; | |||
735 | } | |||
736 | case PPC::ADDIStocHA: { | |||
737 | assert((IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel::Large) &&(((IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel ::Large) && "This pseudo should only be selected for 32-bit large code model on" " AIX.") ? static_cast<void> (0) : __assert_fail ("(IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel::Large) && \"This pseudo should only be selected for 32-bit large code model on\" \" AIX.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 739, __PRETTY_FUNCTION__)) | |||
738 | "This pseudo should only be selected for 32-bit large code model on"(((IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel ::Large) && "This pseudo should only be selected for 32-bit large code model on" " AIX.") ? static_cast<void> (0) : __assert_fail ("(IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel::Large) && \"This pseudo should only be selected for 32-bit large code model on\" \" AIX.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 739, __PRETTY_FUNCTION__)) | |||
739 | " AIX.")(((IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel ::Large) && "This pseudo should only be selected for 32-bit large code model on" " AIX.") ? static_cast<void> (0) : __assert_fail ("(IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel::Large) && \"This pseudo should only be selected for 32-bit large code model on\" \" AIX.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 739, __PRETTY_FUNCTION__)); | |||
740 | ||||
741 | // Transform %rd = ADDIStocHA %rA, @sym(%r2) | |||
742 | LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); | |||
743 | ||||
744 | // Change the opcode to ADDIS. | |||
745 | TmpInst.setOpcode(PPC::ADDIS); | |||
746 | ||||
747 | const MachineOperand &MO = MI->getOperand(2); | |||
748 | assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&(((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress ()) && "Invalid operand for ADDIStocHA.") ? static_cast <void> (0) : __assert_fail ("(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && \"Invalid operand for ADDIStocHA.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 749, __PRETTY_FUNCTION__)) | |||
749 | "Invalid operand for ADDIStocHA.")(((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress ()) && "Invalid operand for ADDIStocHA.") ? static_cast <void> (0) : __assert_fail ("(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && \"Invalid operand for ADDIStocHA.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 749, __PRETTY_FUNCTION__)); | |||
750 | ||||
751 | // Map the machine operand to its corresponding MCSymbol. | |||
752 | MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO); | |||
753 | ||||
754 | // Always use TOC on AIX. Map the global address operand to be a reference | |||
755 | // to the TOC entry we will synthesize later. 'TOCEntry' is a label used to | |||
756 | // reference the storage allocated in the TOC which contains the address of | |||
757 | // 'MOSymbol'. | |||
758 | MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol); | |||
759 | const MCExpr *Exp = MCSymbolRefExpr::create(TOCEntry, | |||
760 | MCSymbolRefExpr::VK_PPC_U, | |||
761 | OutContext); | |||
762 | TmpInst.getOperand(2) = MCOperand::createExpr(Exp); | |||
763 | EmitToStreamer(*OutStreamer, TmpInst); | |||
764 | return; | |||
765 | } | |||
766 | case PPC::LWZtocL: { | |||
767 | assert(IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel::Large &&((IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel ::Large && "This pseudo should only be selected for 32-bit large code model on" " AIX.") ? static_cast<void> (0) : __assert_fail ("IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel::Large && \"This pseudo should only be selected for 32-bit large code model on\" \" AIX.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 769, __PRETTY_FUNCTION__)) | |||
768 | "This pseudo should only be selected for 32-bit large code model on"((IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel ::Large && "This pseudo should only be selected for 32-bit large code model on" " AIX.") ? static_cast<void> (0) : __assert_fail ("IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel::Large && \"This pseudo should only be selected for 32-bit large code model on\" \" AIX.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 769, __PRETTY_FUNCTION__)) | |||
769 | " AIX.")((IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel ::Large && "This pseudo should only be selected for 32-bit large code model on" " AIX.") ? static_cast<void> (0) : __assert_fail ("IsAIX && !IsPPC64 && TM.getCodeModel() == CodeModel::Large && \"This pseudo should only be selected for 32-bit large code model on\" \" AIX.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 769, __PRETTY_FUNCTION__)); | |||
770 | ||||
771 | // Transform %rd = LWZtocL @sym, %rs. | |||
772 | LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); | |||
773 | ||||
774 | // Change the opcode to lwz. | |||
775 | TmpInst.setOpcode(PPC::LWZ); | |||
776 | ||||
777 | const MachineOperand &MO = MI->getOperand(1); | |||
778 | assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&(((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress ()) && "Invalid operand for LWZtocL.") ? static_cast< void> (0) : __assert_fail ("(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && \"Invalid operand for LWZtocL.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 779, __PRETTY_FUNCTION__)) | |||
779 | "Invalid operand for LWZtocL.")(((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress ()) && "Invalid operand for LWZtocL.") ? static_cast< void> (0) : __assert_fail ("(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && \"Invalid operand for LWZtocL.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 779, __PRETTY_FUNCTION__)); | |||
780 | ||||
781 | // Map the machine operand to its corresponding MCSymbol. | |||
782 | MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO); | |||
783 | ||||
784 | // Always use TOC on AIX. Map the global address operand to be a reference | |||
785 | // to the TOC entry we will synthesize later. 'TOCEntry' is a label used to | |||
786 | // reference the storage allocated in the TOC which contains the address of | |||
787 | // 'MOSymbol'. | |||
788 | MCSymbol *TOCEntry = lookUpOrCreateTOCEntry(MOSymbol); | |||
789 | const MCExpr *Exp = MCSymbolRefExpr::create(TOCEntry, | |||
790 | MCSymbolRefExpr::VK_PPC_L, | |||
791 | OutContext); | |||
792 | TmpInst.getOperand(1) = MCOperand::createExpr(Exp); | |||
793 | EmitToStreamer(*OutStreamer, TmpInst); | |||
794 | return; | |||
795 | } | |||
796 | case PPC::ADDIStocHA8: { | |||
797 | // Transform %xd = ADDIStocHA8 %x2, @sym | |||
798 | LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); | |||
799 | ||||
800 | // Change the opcode to ADDIS8. If the global address is the address of | |||
801 | // an external symbol, is a jump table address, is a block address, or is a | |||
802 | // constant pool index with large code model enabled, then generate a TOC | |||
803 | // entry and reference that. Otherwise, reference the symbol directly. | |||
804 | TmpInst.setOpcode(PPC::ADDIS8); | |||
805 | ||||
806 | const MachineOperand &MO = MI->getOperand(2); | |||
807 | assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) &&(((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress ()) && "Invalid operand for ADDIStocHA8!") ? static_cast <void> (0) : __assert_fail ("(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && \"Invalid operand for ADDIStocHA8!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 808, __PRETTY_FUNCTION__)) | |||
808 | "Invalid operand for ADDIStocHA8!")(((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress ()) && "Invalid operand for ADDIStocHA8!") ? static_cast <void> (0) : __assert_fail ("(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && \"Invalid operand for ADDIStocHA8!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 808, __PRETTY_FUNCTION__)); | |||
809 | ||||
810 | const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO); | |||
811 | ||||
812 | const bool GlobalToc = | |||
813 | MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal()); | |||
814 | if (GlobalToc || MO.isJTI() || MO.isBlockAddress() || | |||
815 | (MO.isCPI() && TM.getCodeModel() == CodeModel::Large)) | |||
816 | MOSymbol = lookUpOrCreateTOCEntry(MOSymbol); | |||
817 | ||||
818 | const MCSymbolRefExpr::VariantKind VK = | |||
819 | IsAIX ? MCSymbolRefExpr::VK_PPC_U : MCSymbolRefExpr::VK_PPC_TOC_HA; | |||
820 | ||||
821 | const MCExpr *Exp = | |||
822 | MCSymbolRefExpr::create(MOSymbol, VK, OutContext); | |||
823 | ||||
824 | if (!MO.isJTI() && MO.getOffset()) | |||
825 | Exp = MCBinaryExpr::createAdd(Exp, | |||
826 | MCConstantExpr::create(MO.getOffset(), | |||
827 | OutContext), | |||
828 | OutContext); | |||
829 | ||||
830 | TmpInst.getOperand(2) = MCOperand::createExpr(Exp); | |||
831 | EmitToStreamer(*OutStreamer, TmpInst); | |||
832 | return; | |||
833 | } | |||
834 | case PPC::LDtocL: { | |||
835 | // Transform %xd = LDtocL @sym, %xs | |||
836 | LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); | |||
837 | ||||
838 | // Change the opcode to LD. If the global address is the address of | |||
839 | // an external symbol, is a jump table address, is a block address, or is | |||
840 | // a constant pool index with large code model enabled, then generate a | |||
841 | // TOC entry and reference that. Otherwise, reference the symbol directly. | |||
842 | TmpInst.setOpcode(PPC::LD); | |||
843 | ||||
844 | const MachineOperand &MO = MI->getOperand(1); | |||
845 | assert((MO.isGlobal() || MO.isCPI() || MO.isJTI() ||(((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress ()) && "Invalid operand for LDtocL!") ? static_cast< void> (0) : __assert_fail ("(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && \"Invalid operand for LDtocL!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 847, __PRETTY_FUNCTION__)) | |||
846 | MO.isBlockAddress()) &&(((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress ()) && "Invalid operand for LDtocL!") ? static_cast< void> (0) : __assert_fail ("(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && \"Invalid operand for LDtocL!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 847, __PRETTY_FUNCTION__)) | |||
847 | "Invalid operand for LDtocL!")(((MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress ()) && "Invalid operand for LDtocL!") ? static_cast< void> (0) : __assert_fail ("(MO.isGlobal() || MO.isCPI() || MO.isJTI() || MO.isBlockAddress()) && \"Invalid operand for LDtocL!\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 847, __PRETTY_FUNCTION__)); | |||
848 | ||||
849 | LLVM_DEBUG(assert(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("asmprinter")) { (((!MO.isGlobal() || Subtarget->isGVIndirectSymbol (MO.getGlobal())) && "LDtocL used on symbol that could be accessed directly is " "invalid. Must match ADDIStocHA8.") ? static_cast<void> (0) : __assert_fail ("(!MO.isGlobal() || Subtarget->isGVIndirectSymbol(MO.getGlobal())) && \"LDtocL used on symbol that could be accessed directly is \" \"invalid. Must match ADDIStocHA8.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 852, __PRETTY_FUNCTION__)); } } while (false) | |||
850 | (!MO.isGlobal() || Subtarget->isGVIndirectSymbol(MO.getGlobal())) &&do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("asmprinter")) { (((!MO.isGlobal() || Subtarget->isGVIndirectSymbol (MO.getGlobal())) && "LDtocL used on symbol that could be accessed directly is " "invalid. Must match ADDIStocHA8.") ? static_cast<void> (0) : __assert_fail ("(!MO.isGlobal() || Subtarget->isGVIndirectSymbol(MO.getGlobal())) && \"LDtocL used on symbol that could be accessed directly is \" \"invalid. Must match ADDIStocHA8.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 852, __PRETTY_FUNCTION__)); } } while (false) | |||
851 | "LDtocL used on symbol that could be accessed directly is "do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("asmprinter")) { (((!MO.isGlobal() || Subtarget->isGVIndirectSymbol (MO.getGlobal())) && "LDtocL used on symbol that could be accessed directly is " "invalid. Must match ADDIStocHA8.") ? static_cast<void> (0) : __assert_fail ("(!MO.isGlobal() || Subtarget->isGVIndirectSymbol(MO.getGlobal())) && \"LDtocL used on symbol that could be accessed directly is \" \"invalid. Must match ADDIStocHA8.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 852, __PRETTY_FUNCTION__)); } } while (false) | |||
852 | "invalid. Must match ADDIStocHA8."))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("asmprinter")) { (((!MO.isGlobal() || Subtarget->isGVIndirectSymbol (MO.getGlobal())) && "LDtocL used on symbol that could be accessed directly is " "invalid. Must match ADDIStocHA8.") ? static_cast<void> (0) : __assert_fail ("(!MO.isGlobal() || Subtarget->isGVIndirectSymbol(MO.getGlobal())) && \"LDtocL used on symbol that could be accessed directly is \" \"invalid. Must match ADDIStocHA8.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 852, __PRETTY_FUNCTION__)); } } while (false); | |||
853 | ||||
854 | const MCSymbol *MOSymbol = getMCSymbolForTOCPseudoMO(MO); | |||
855 | ||||
856 | if (!MO.isCPI() || TM.getCodeModel() == CodeModel::Large) | |||
857 | MOSymbol = lookUpOrCreateTOCEntry(MOSymbol); | |||
858 | ||||
859 | const MCSymbolRefExpr::VariantKind VK = | |||
860 | IsAIX ? MCSymbolRefExpr::VK_PPC_L : MCSymbolRefExpr::VK_PPC_TOC_LO; | |||
861 | const MCExpr *Exp = | |||
862 | MCSymbolRefExpr::create(MOSymbol, VK, OutContext); | |||
863 | TmpInst.getOperand(1) = MCOperand::createExpr(Exp); | |||
864 | EmitToStreamer(*OutStreamer, TmpInst); | |||
865 | return; | |||
866 | } | |||
867 | case PPC::ADDItocL: { | |||
868 | // Transform %xd = ADDItocL %xs, @sym | |||
869 | LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); | |||
870 | ||||
871 | // Change the opcode to ADDI8. If the global address is external, then | |||
872 | // generate a TOC entry and reference that. Otherwise, reference the | |||
873 | // symbol directly. | |||
874 | TmpInst.setOpcode(PPC::ADDI8); | |||
875 | ||||
876 | const MachineOperand &MO = MI->getOperand(2); | |||
877 | assert((MO.isGlobal() || MO.isCPI()) && "Invalid operand for ADDItocL.")(((MO.isGlobal() || MO.isCPI()) && "Invalid operand for ADDItocL." ) ? static_cast<void> (0) : __assert_fail ("(MO.isGlobal() || MO.isCPI()) && \"Invalid operand for ADDItocL.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 877, __PRETTY_FUNCTION__)); | |||
878 | ||||
879 | LLVM_DEBUG(assert(do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("asmprinter")) { ((!(MO.isGlobal() && Subtarget-> isGVIndirectSymbol(MO.getGlobal())) && "Interposable definitions must use indirect access." ) ? static_cast<void> (0) : __assert_fail ("!(MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal())) && \"Interposable definitions must use indirect access.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 881, __PRETTY_FUNCTION__)); } } while (false) | |||
880 | !(MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal())) &&do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("asmprinter")) { ((!(MO.isGlobal() && Subtarget-> isGVIndirectSymbol(MO.getGlobal())) && "Interposable definitions must use indirect access." ) ? static_cast<void> (0) : __assert_fail ("!(MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal())) && \"Interposable definitions must use indirect access.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 881, __PRETTY_FUNCTION__)); } } while (false) | |||
881 | "Interposable definitions must use indirect access."))do { if (::llvm::DebugFlag && ::llvm::isCurrentDebugType ("asmprinter")) { ((!(MO.isGlobal() && Subtarget-> isGVIndirectSymbol(MO.getGlobal())) && "Interposable definitions must use indirect access." ) ? static_cast<void> (0) : __assert_fail ("!(MO.isGlobal() && Subtarget->isGVIndirectSymbol(MO.getGlobal())) && \"Interposable definitions must use indirect access.\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 881, __PRETTY_FUNCTION__)); } } while (false); | |||
882 | ||||
883 | const MCExpr *Exp = | |||
884 | MCSymbolRefExpr::create(getMCSymbolForTOCPseudoMO(MO), | |||
885 | MCSymbolRefExpr::VK_PPC_TOC_LO, OutContext); | |||
886 | TmpInst.getOperand(2) = MCOperand::createExpr(Exp); | |||
887 | EmitToStreamer(*OutStreamer, TmpInst); | |||
888 | return; | |||
889 | } | |||
890 | case PPC::ADDISgotTprelHA: { | |||
891 | // Transform: %xd = ADDISgotTprelHA %x2, @sym | |||
892 | // Into: %xd = ADDIS8 %x2, sym@got@tlsgd@ha | |||
893 | assert(IsPPC64 && "Not supported for 32-bit PowerPC")((IsPPC64 && "Not supported for 32-bit PowerPC") ? static_cast <void> (0) : __assert_fail ("IsPPC64 && \"Not supported for 32-bit PowerPC\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 893, __PRETTY_FUNCTION__)); | |||
894 | const MachineOperand &MO = MI->getOperand(2); | |||
895 | const GlobalValue *GValue = MO.getGlobal(); | |||
896 | MCSymbol *MOSymbol = getSymbol(GValue); | |||
897 | const MCExpr *SymGotTprel = | |||
898 | MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TPREL_HA, | |||
899 | OutContext); | |||
900 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8) | |||
901 | .addReg(MI->getOperand(0).getReg()) | |||
902 | .addReg(MI->getOperand(1).getReg()) | |||
903 | .addExpr(SymGotTprel)); | |||
904 | return; | |||
905 | } | |||
906 | case PPC::LDgotTprelL: | |||
907 | case PPC::LDgotTprelL32: { | |||
908 | // Transform %xd = LDgotTprelL @sym, %xs | |||
909 | LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); | |||
910 | ||||
911 | // Change the opcode to LD. | |||
912 | TmpInst.setOpcode(IsPPC64 ? PPC::LD : PPC::LWZ); | |||
913 | const MachineOperand &MO = MI->getOperand(1); | |||
914 | const GlobalValue *GValue = MO.getGlobal(); | |||
915 | MCSymbol *MOSymbol = getSymbol(GValue); | |||
916 | const MCExpr *Exp = MCSymbolRefExpr::create( | |||
917 | MOSymbol, IsPPC64 ? MCSymbolRefExpr::VK_PPC_GOT_TPREL_LO | |||
918 | : MCSymbolRefExpr::VK_PPC_GOT_TPREL, | |||
919 | OutContext); | |||
920 | TmpInst.getOperand(1) = MCOperand::createExpr(Exp); | |||
921 | EmitToStreamer(*OutStreamer, TmpInst); | |||
922 | return; | |||
923 | } | |||
924 | ||||
925 | case PPC::PPC32PICGOT: { | |||
926 | MCSymbol *GOTSymbol = OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_")); | |||
927 | MCSymbol *GOTRef = OutContext.createTempSymbol(); | |||
928 | MCSymbol *NextInstr = OutContext.createTempSymbol(); | |||
929 | ||||
930 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::BL) | |||
931 | // FIXME: We would like an efficient form for this, so we don't have to do | |||
932 | // a lot of extra uniquing. | |||
933 | .addExpr(MCSymbolRefExpr::create(NextInstr, OutContext))); | |||
934 | const MCExpr *OffsExpr = | |||
935 | MCBinaryExpr::createSub(MCSymbolRefExpr::create(GOTSymbol, OutContext), | |||
936 | MCSymbolRefExpr::create(GOTRef, OutContext), | |||
937 | OutContext); | |||
938 | OutStreamer->emitLabel(GOTRef); | |||
939 | OutStreamer->emitValue(OffsExpr, 4); | |||
940 | OutStreamer->emitLabel(NextInstr); | |||
941 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR) | |||
942 | .addReg(MI->getOperand(0).getReg())); | |||
943 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LWZ) | |||
944 | .addReg(MI->getOperand(1).getReg()) | |||
945 | .addImm(0) | |||
946 | .addReg(MI->getOperand(0).getReg())); | |||
947 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD4) | |||
948 | .addReg(MI->getOperand(0).getReg()) | |||
949 | .addReg(MI->getOperand(1).getReg()) | |||
950 | .addReg(MI->getOperand(0).getReg())); | |||
951 | return; | |||
952 | } | |||
953 | case PPC::PPC32GOT: { | |||
954 | MCSymbol *GOTSymbol = | |||
955 | OutContext.getOrCreateSymbol(StringRef("_GLOBAL_OFFSET_TABLE_")); | |||
956 | const MCExpr *SymGotTlsL = MCSymbolRefExpr::create( | |||
957 | GOTSymbol, MCSymbolRefExpr::VK_PPC_LO, OutContext); | |||
958 | const MCExpr *SymGotTlsHA = MCSymbolRefExpr::create( | |||
959 | GOTSymbol, MCSymbolRefExpr::VK_PPC_HA, OutContext); | |||
960 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LI) | |||
961 | .addReg(MI->getOperand(0).getReg()) | |||
962 | .addExpr(SymGotTlsL)); | |||
963 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS) | |||
964 | .addReg(MI->getOperand(0).getReg()) | |||
965 | .addReg(MI->getOperand(0).getReg()) | |||
966 | .addExpr(SymGotTlsHA)); | |||
967 | return; | |||
968 | } | |||
969 | case PPC::ADDIStlsgdHA: { | |||
970 | // Transform: %xd = ADDIStlsgdHA %x2, @sym | |||
971 | // Into: %xd = ADDIS8 %x2, sym@got@tlsgd@ha | |||
972 | assert(IsPPC64 && "Not supported for 32-bit PowerPC")((IsPPC64 && "Not supported for 32-bit PowerPC") ? static_cast <void> (0) : __assert_fail ("IsPPC64 && \"Not supported for 32-bit PowerPC\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 972, __PRETTY_FUNCTION__)); | |||
973 | const MachineOperand &MO = MI->getOperand(2); | |||
974 | const GlobalValue *GValue = MO.getGlobal(); | |||
975 | MCSymbol *MOSymbol = getSymbol(GValue); | |||
976 | const MCExpr *SymGotTlsGD = | |||
977 | MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSGD_HA, | |||
978 | OutContext); | |||
979 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8) | |||
980 | .addReg(MI->getOperand(0).getReg()) | |||
981 | .addReg(MI->getOperand(1).getReg()) | |||
982 | .addExpr(SymGotTlsGD)); | |||
983 | return; | |||
984 | } | |||
985 | case PPC::ADDItlsgdL: | |||
986 | // Transform: %xd = ADDItlsgdL %xs, @sym | |||
987 | // Into: %xd = ADDI8 %xs, sym@got@tlsgd@l | |||
988 | case PPC::ADDItlsgdL32: { | |||
989 | // Transform: %rd = ADDItlsgdL32 %rs, @sym | |||
990 | // Into: %rd = ADDI %rs, sym@got@tlsgd | |||
991 | const MachineOperand &MO = MI->getOperand(2); | |||
992 | const GlobalValue *GValue = MO.getGlobal(); | |||
993 | MCSymbol *MOSymbol = getSymbol(GValue); | |||
994 | const MCExpr *SymGotTlsGD = MCSymbolRefExpr::create( | |||
995 | MOSymbol, IsPPC64 ? MCSymbolRefExpr::VK_PPC_GOT_TLSGD_LO | |||
996 | : MCSymbolRefExpr::VK_PPC_GOT_TLSGD, | |||
997 | OutContext); | |||
998 | EmitToStreamer(*OutStreamer, | |||
999 | MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI) | |||
1000 | .addReg(MI->getOperand(0).getReg()) | |||
1001 | .addReg(MI->getOperand(1).getReg()) | |||
1002 | .addExpr(SymGotTlsGD)); | |||
1003 | return; | |||
1004 | } | |||
1005 | case PPC::GETtlsADDR: | |||
1006 | // Transform: %x3 = GETtlsADDR %x3, @sym | |||
1007 | // Into: BL8_NOP_TLS __tls_get_addr(sym at tlsgd) | |||
1008 | case PPC::GETtlsADDR32: { | |||
1009 | // Transform: %r3 = GETtlsADDR32 %r3, @sym | |||
1010 | // Into: BL_TLS __tls_get_addr(sym at tlsgd)@PLT | |||
1011 | EmitTlsCall(MI, MCSymbolRefExpr::VK_PPC_TLSGD); | |||
1012 | return; | |||
1013 | } | |||
1014 | case PPC::ADDIStlsldHA: { | |||
1015 | // Transform: %xd = ADDIStlsldHA %x2, @sym | |||
1016 | // Into: %xd = ADDIS8 %x2, sym@got@tlsld@ha | |||
1017 | assert(IsPPC64 && "Not supported for 32-bit PowerPC")((IsPPC64 && "Not supported for 32-bit PowerPC") ? static_cast <void> (0) : __assert_fail ("IsPPC64 && \"Not supported for 32-bit PowerPC\"" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 1017, __PRETTY_FUNCTION__)); | |||
1018 | const MachineOperand &MO = MI->getOperand(2); | |||
1019 | const GlobalValue *GValue = MO.getGlobal(); | |||
1020 | MCSymbol *MOSymbol = getSymbol(GValue); | |||
1021 | const MCExpr *SymGotTlsLD = | |||
1022 | MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_GOT_TLSLD_HA, | |||
1023 | OutContext); | |||
1024 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS8) | |||
1025 | .addReg(MI->getOperand(0).getReg()) | |||
1026 | .addReg(MI->getOperand(1).getReg()) | |||
1027 | .addExpr(SymGotTlsLD)); | |||
1028 | return; | |||
1029 | } | |||
1030 | case PPC::ADDItlsldL: | |||
1031 | // Transform: %xd = ADDItlsldL %xs, @sym | |||
1032 | // Into: %xd = ADDI8 %xs, sym@got@tlsld@l | |||
1033 | case PPC::ADDItlsldL32: { | |||
1034 | // Transform: %rd = ADDItlsldL32 %rs, @sym | |||
1035 | // Into: %rd = ADDI %rs, sym@got@tlsld | |||
1036 | const MachineOperand &MO = MI->getOperand(2); | |||
1037 | const GlobalValue *GValue = MO.getGlobal(); | |||
1038 | MCSymbol *MOSymbol = getSymbol(GValue); | |||
1039 | const MCExpr *SymGotTlsLD = MCSymbolRefExpr::create( | |||
1040 | MOSymbol, IsPPC64 ? MCSymbolRefExpr::VK_PPC_GOT_TLSLD_LO | |||
1041 | : MCSymbolRefExpr::VK_PPC_GOT_TLSLD, | |||
1042 | OutContext); | |||
1043 | EmitToStreamer(*OutStreamer, | |||
1044 | MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI) | |||
1045 | .addReg(MI->getOperand(0).getReg()) | |||
1046 | .addReg(MI->getOperand(1).getReg()) | |||
1047 | .addExpr(SymGotTlsLD)); | |||
1048 | return; | |||
1049 | } | |||
1050 | case PPC::GETtlsldADDR: | |||
1051 | // Transform: %x3 = GETtlsldADDR %x3, @sym | |||
1052 | // Into: BL8_NOP_TLS __tls_get_addr(sym at tlsld) | |||
1053 | case PPC::GETtlsldADDR32: { | |||
1054 | // Transform: %r3 = GETtlsldADDR32 %r3, @sym | |||
1055 | // Into: BL_TLS __tls_get_addr(sym at tlsld)@PLT | |||
1056 | EmitTlsCall(MI, MCSymbolRefExpr::VK_PPC_TLSLD); | |||
1057 | return; | |||
1058 | } | |||
1059 | case PPC::ADDISdtprelHA: | |||
1060 | // Transform: %xd = ADDISdtprelHA %xs, @sym | |||
1061 | // Into: %xd = ADDIS8 %xs, sym@dtprel@ha | |||
1062 | case PPC::ADDISdtprelHA32: { | |||
1063 | // Transform: %rd = ADDISdtprelHA32 %rs, @sym | |||
1064 | // Into: %rd = ADDIS %rs, sym@dtprel@ha | |||
1065 | const MachineOperand &MO = MI->getOperand(2); | |||
1066 | const GlobalValue *GValue = MO.getGlobal(); | |||
1067 | MCSymbol *MOSymbol = getSymbol(GValue); | |||
1068 | const MCExpr *SymDtprel = | |||
1069 | MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_DTPREL_HA, | |||
1070 | OutContext); | |||
1071 | EmitToStreamer( | |||
1072 | *OutStreamer, | |||
1073 | MCInstBuilder(IsPPC64 ? PPC::ADDIS8 : PPC::ADDIS) | |||
1074 | .addReg(MI->getOperand(0).getReg()) | |||
1075 | .addReg(MI->getOperand(1).getReg()) | |||
1076 | .addExpr(SymDtprel)); | |||
1077 | return; | |||
1078 | } | |||
1079 | case PPC::ADDIdtprelL: | |||
1080 | // Transform: %xd = ADDIdtprelL %xs, @sym | |||
1081 | // Into: %xd = ADDI8 %xs, sym@dtprel@l | |||
1082 | case PPC::ADDIdtprelL32: { | |||
1083 | // Transform: %rd = ADDIdtprelL32 %rs, @sym | |||
1084 | // Into: %rd = ADDI %rs, sym@dtprel@l | |||
1085 | const MachineOperand &MO = MI->getOperand(2); | |||
1086 | const GlobalValue *GValue = MO.getGlobal(); | |||
1087 | MCSymbol *MOSymbol = getSymbol(GValue); | |||
1088 | const MCExpr *SymDtprel = | |||
1089 | MCSymbolRefExpr::create(MOSymbol, MCSymbolRefExpr::VK_PPC_DTPREL_LO, | |||
1090 | OutContext); | |||
1091 | EmitToStreamer(*OutStreamer, | |||
1092 | MCInstBuilder(IsPPC64 ? PPC::ADDI8 : PPC::ADDI) | |||
1093 | .addReg(MI->getOperand(0).getReg()) | |||
1094 | .addReg(MI->getOperand(1).getReg()) | |||
1095 | .addExpr(SymDtprel)); | |||
1096 | return; | |||
1097 | } | |||
1098 | case PPC::MFOCRF: | |||
1099 | case PPC::MFOCRF8: | |||
1100 | if (!Subtarget->hasMFOCRF()) { | |||
1101 | // Transform: %r3 = MFOCRF %cr7 | |||
1102 | // Into: %r3 = MFCR ;; cr7 | |||
1103 | unsigned NewOpcode = | |||
1104 | MI->getOpcode() == PPC::MFOCRF ? PPC::MFCR : PPC::MFCR8; | |||
1105 | OutStreamer->AddComment(PPCInstPrinter:: | |||
1106 | getRegisterName(MI->getOperand(1).getReg())); | |||
1107 | EmitToStreamer(*OutStreamer, MCInstBuilder(NewOpcode) | |||
1108 | .addReg(MI->getOperand(0).getReg())); | |||
1109 | return; | |||
1110 | } | |||
1111 | break; | |||
1112 | case PPC::MTOCRF: | |||
1113 | case PPC::MTOCRF8: | |||
1114 | if (!Subtarget->hasMFOCRF()) { | |||
1115 | // Transform: %cr7 = MTOCRF %r3 | |||
1116 | // Into: MTCRF mask, %r3 ;; cr7 | |||
1117 | unsigned NewOpcode = | |||
1118 | MI->getOpcode() == PPC::MTOCRF ? PPC::MTCRF : PPC::MTCRF8; | |||
1119 | unsigned Mask = 0x80 >> OutContext.getRegisterInfo() | |||
1120 | ->getEncodingValue(MI->getOperand(0).getReg()); | |||
1121 | OutStreamer->AddComment(PPCInstPrinter:: | |||
1122 | getRegisterName(MI->getOperand(0).getReg())); | |||
1123 | EmitToStreamer(*OutStreamer, MCInstBuilder(NewOpcode) | |||
1124 | .addImm(Mask) | |||
1125 | .addReg(MI->getOperand(1).getReg())); | |||
1126 | return; | |||
1127 | } | |||
1128 | break; | |||
1129 | case PPC::LD: | |||
1130 | case PPC::STD: | |||
1131 | case PPC::LWA_32: | |||
1132 | case PPC::LWA: { | |||
1133 | // Verify alignment is legal, so we don't create relocations | |||
1134 | // that can't be supported. | |||
1135 | // FIXME: This test is currently disabled for Darwin. The test | |||
1136 | // suite shows a handful of test cases that fail this check for | |||
1137 | // Darwin. Those need to be investigated before this sanity test | |||
1138 | // can be enabled for those subtargets. | |||
1139 | unsigned OpNum = (MI->getOpcode() == PPC::STD) ? 2 : 1; | |||
1140 | const MachineOperand &MO = MI->getOperand(OpNum); | |||
1141 | if (MO.isGlobal() && MO.getGlobal()->getAlignment() < 4) | |||
1142 | llvm_unreachable("Global must be word-aligned for LD, STD, LWA!")::llvm::llvm_unreachable_internal("Global must be word-aligned for LD, STD, LWA!" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 1142); | |||
1143 | // Now process the instruction normally. | |||
1144 | break; | |||
1145 | } | |||
1146 | } | |||
1147 | ||||
1148 | LowerPPCMachineInstrToMCInst(MI, TmpInst, *this); | |||
1149 | EmitToStreamer(*OutStreamer, TmpInst); | |||
1150 | } | |||
1151 | ||||
1152 | void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) { | |||
1153 | if (!Subtarget->isPPC64()) | |||
1154 | return PPCAsmPrinter::emitInstruction(MI); | |||
1155 | ||||
1156 | switch (MI->getOpcode()) { | |||
1157 | default: | |||
1158 | return PPCAsmPrinter::emitInstruction(MI); | |||
1159 | case TargetOpcode::PATCHABLE_FUNCTION_ENTER: { | |||
1160 | // .begin: | |||
1161 | // b .end # lis 0, FuncId[16..32] | |||
1162 | // nop # li 0, FuncId[0..15] | |||
1163 | // std 0, -8(1) | |||
1164 | // mflr 0 | |||
1165 | // bl __xray_FunctionEntry | |||
1166 | // mtlr 0 | |||
1167 | // .end: | |||
1168 | // | |||
1169 | // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number | |||
1170 | // of instructions change. | |||
1171 | MCSymbol *BeginOfSled = OutContext.createTempSymbol(); | |||
1172 | MCSymbol *EndOfSled = OutContext.createTempSymbol(); | |||
1173 | OutStreamer->emitLabel(BeginOfSled); | |||
1174 | EmitToStreamer(*OutStreamer, | |||
1175 | MCInstBuilder(PPC::B).addExpr( | |||
1176 | MCSymbolRefExpr::create(EndOfSled, OutContext))); | |||
1177 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP)); | |||
1178 | EmitToStreamer( | |||
1179 | *OutStreamer, | |||
1180 | MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1)); | |||
1181 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0)); | |||
1182 | EmitToStreamer(*OutStreamer, | |||
1183 | MCInstBuilder(PPC::BL8_NOP) | |||
1184 | .addExpr(MCSymbolRefExpr::create( | |||
1185 | OutContext.getOrCreateSymbol("__xray_FunctionEntry"), | |||
1186 | OutContext))); | |||
1187 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0)); | |||
1188 | OutStreamer->emitLabel(EndOfSled); | |||
1189 | recordSled(BeginOfSled, *MI, SledKind::FUNCTION_ENTER); | |||
1190 | break; | |||
1191 | } | |||
1192 | case TargetOpcode::PATCHABLE_RET: { | |||
1193 | unsigned RetOpcode = MI->getOperand(0).getImm(); | |||
1194 | MCInst RetInst; | |||
1195 | RetInst.setOpcode(RetOpcode); | |||
1196 | for (const auto &MO : | |||
1197 | make_range(std::next(MI->operands_begin()), MI->operands_end())) { | |||
1198 | MCOperand MCOp; | |||
1199 | if (LowerPPCMachineOperandToMCOperand(MO, MCOp, *this)) | |||
1200 | RetInst.addOperand(MCOp); | |||
1201 | } | |||
1202 | ||||
1203 | bool IsConditional; | |||
1204 | if (RetOpcode == PPC::BCCLR) { | |||
1205 | IsConditional = true; | |||
1206 | } else if (RetOpcode == PPC::TCRETURNdi8 || RetOpcode == PPC::TCRETURNri8 || | |||
1207 | RetOpcode == PPC::TCRETURNai8) { | |||
1208 | break; | |||
1209 | } else if (RetOpcode == PPC::BLR8 || RetOpcode == PPC::TAILB8) { | |||
1210 | IsConditional = false; | |||
1211 | } else { | |||
1212 | EmitToStreamer(*OutStreamer, RetInst); | |||
1213 | break; | |||
1214 | } | |||
1215 | ||||
1216 | MCSymbol *FallthroughLabel; | |||
1217 | if (IsConditional) { | |||
1218 | // Before: | |||
1219 | // bgtlr cr0 | |||
1220 | // | |||
1221 | // After: | |||
1222 | // ble cr0, .end | |||
1223 | // .p2align 3 | |||
1224 | // .begin: | |||
1225 | // blr # lis 0, FuncId[16..32] | |||
1226 | // nop # li 0, FuncId[0..15] | |||
1227 | // std 0, -8(1) | |||
1228 | // mflr 0 | |||
1229 | // bl __xray_FunctionExit | |||
1230 | // mtlr 0 | |||
1231 | // blr | |||
1232 | // .end: | |||
1233 | // | |||
1234 | // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number | |||
1235 | // of instructions change. | |||
1236 | FallthroughLabel = OutContext.createTempSymbol(); | |||
1237 | EmitToStreamer( | |||
1238 | *OutStreamer, | |||
1239 | MCInstBuilder(PPC::BCC) | |||
1240 | .addImm(PPC::InvertPredicate( | |||
1241 | static_cast<PPC::Predicate>(MI->getOperand(1).getImm()))) | |||
1242 | .addReg(MI->getOperand(2).getReg()) | |||
1243 | .addExpr(MCSymbolRefExpr::create(FallthroughLabel, OutContext))); | |||
1244 | RetInst = MCInst(); | |||
1245 | RetInst.setOpcode(PPC::BLR8); | |||
1246 | } | |||
1247 | // .p2align 3 | |||
1248 | // .begin: | |||
1249 | // b(lr)? # lis 0, FuncId[16..32] | |||
1250 | // nop # li 0, FuncId[0..15] | |||
1251 | // std 0, -8(1) | |||
1252 | // mflr 0 | |||
1253 | // bl __xray_FunctionExit | |||
1254 | // mtlr 0 | |||
1255 | // b(lr)? | |||
1256 | // | |||
1257 | // Update compiler-rt/lib/xray/xray_powerpc64.cc accordingly when number | |||
1258 | // of instructions change. | |||
1259 | OutStreamer->emitCodeAlignment(8); | |||
1260 | MCSymbol *BeginOfSled = OutContext.createTempSymbol(); | |||
1261 | OutStreamer->emitLabel(BeginOfSled); | |||
1262 | EmitToStreamer(*OutStreamer, RetInst); | |||
1263 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::NOP)); | |||
1264 | EmitToStreamer( | |||
1265 | *OutStreamer, | |||
1266 | MCInstBuilder(PPC::STD).addReg(PPC::X0).addImm(-8).addReg(PPC::X1)); | |||
1267 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MFLR8).addReg(PPC::X0)); | |||
1268 | EmitToStreamer(*OutStreamer, | |||
1269 | MCInstBuilder(PPC::BL8_NOP) | |||
1270 | .addExpr(MCSymbolRefExpr::create( | |||
1271 | OutContext.getOrCreateSymbol("__xray_FunctionExit"), | |||
1272 | OutContext))); | |||
1273 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::MTLR8).addReg(PPC::X0)); | |||
1274 | EmitToStreamer(*OutStreamer, RetInst); | |||
1275 | if (IsConditional) | |||
1276 | OutStreamer->emitLabel(FallthroughLabel); | |||
1277 | recordSled(BeginOfSled, *MI, SledKind::FUNCTION_EXIT); | |||
1278 | break; | |||
1279 | } | |||
1280 | case TargetOpcode::PATCHABLE_FUNCTION_EXIT: | |||
1281 | llvm_unreachable("PATCHABLE_FUNCTION_EXIT should never be emitted")::llvm::llvm_unreachable_internal("PATCHABLE_FUNCTION_EXIT should never be emitted" , "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 1281); | |||
1282 | case TargetOpcode::PATCHABLE_TAIL_CALL: | |||
1283 | // TODO: Define a trampoline `__xray_FunctionTailExit` and differentiate a | |||
1284 | // normal function exit from a tail exit. | |||
1285 | llvm_unreachable("Tail call is handled in the normal case. See comments "::llvm::llvm_unreachable_internal("Tail call is handled in the normal case. See comments " "around this assert.", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 1286) | |||
1286 | "around this assert.")::llvm::llvm_unreachable_internal("Tail call is handled in the normal case. See comments " "around this assert.", "/build/llvm-toolchain-snapshot-11~++20200309111110+2c36c23f347/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp" , 1286); | |||
1287 | } | |||
1288 | } | |||
1289 | ||||
1290 | void PPCLinuxAsmPrinter::emitStartOfAsmFile(Module &M) { | |||
1291 | if (static_cast<const PPCTargetMachine &>(TM).isELFv2ABI()) { | |||
1292 | PPCTargetStreamer *TS = | |||
1293 | static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer()); | |||
1294 | ||||
1295 | if (TS) | |||
1296 | TS->emitAbiVersion(2); | |||
1297 | } | |||
1298 | ||||
1299 | if (static_cast<const PPCTargetMachine &>(TM).isPPC64() || | |||
1300 | !isPositionIndependent()) | |||
1301 | return AsmPrinter::emitStartOfAsmFile(M); | |||
1302 | ||||
1303 | if (M.getPICLevel() == PICLevel::SmallPIC) | |||
1304 | return AsmPrinter::emitStartOfAsmFile(M); | |||
1305 | ||||
1306 | OutStreamer->SwitchSection(OutContext.getELFSection( | |||
1307 | ".got2", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC)); | |||
1308 | ||||
1309 | MCSymbol *TOCSym = OutContext.getOrCreateSymbol(Twine(".LTOC")); | |||
1310 | MCSymbol *CurrentPos = OutContext.createTempSymbol(); | |||
1311 | ||||
1312 | OutStreamer->emitLabel(CurrentPos); | |||
1313 | ||||
1314 | // The GOT pointer points to the middle of the GOT, in order to reference the | |||
1315 | // entire 64kB range. 0x8000 is the midpoint. | |||
1316 | const MCExpr *tocExpr = | |||
1317 | MCBinaryExpr::createAdd(MCSymbolRefExpr::create(CurrentPos, OutContext), | |||
1318 | MCConstantExpr::create(0x8000, OutContext), | |||
1319 | OutContext); | |||
1320 | ||||
1321 | OutStreamer->emitAssignment(TOCSym, tocExpr); | |||
1322 | ||||
1323 | OutStreamer->SwitchSection(getObjFileLowering().getTextSection()); | |||
1324 | } | |||
1325 | ||||
1326 | void PPCLinuxAsmPrinter::emitFunctionEntryLabel() { | |||
1327 | // linux/ppc32 - Normal entry label. | |||
1328 | if (!Subtarget->isPPC64() && | |||
1329 | (!isPositionIndependent() || | |||
1330 | MF->getFunction().getParent()->getPICLevel() == PICLevel::SmallPIC)) | |||
1331 | return AsmPrinter::emitFunctionEntryLabel(); | |||
1332 | ||||
1333 | if (!Subtarget->isPPC64()) { | |||
1334 | const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>(); | |||
1335 | if (PPCFI->usesPICBase() && !Subtarget->isSecurePlt()) { | |||
1336 | MCSymbol *RelocSymbol = PPCFI->getPICOffsetSymbol(); | |||
1337 | MCSymbol *PICBase = MF->getPICBaseSymbol(); | |||
1338 | OutStreamer->emitLabel(RelocSymbol); | |||
1339 | ||||
1340 | const MCExpr *OffsExpr = | |||
1341 | MCBinaryExpr::createSub( | |||
1342 | MCSymbolRefExpr::create(OutContext.getOrCreateSymbol(Twine(".LTOC")), | |||
1343 | OutContext), | |||
1344 | MCSymbolRefExpr::create(PICBase, OutContext), | |||
1345 | OutContext); | |||
1346 | OutStreamer->emitValue(OffsExpr, 4); | |||
1347 | OutStreamer->emitLabel(CurrentFnSym); | |||
1348 | return; | |||
1349 | } else | |||
1350 | return AsmPrinter::emitFunctionEntryLabel(); | |||
1351 | } | |||
1352 | ||||
1353 | // ELFv2 ABI - Normal entry label. | |||
1354 | if (Subtarget->isELFv2ABI()) { | |||
1355 | // In the Large code model, we allow arbitrary displacements between | |||
1356 | // the text section and its associated TOC section. We place the | |||
1357 | // full 8-byte offset to the TOC in memory immediately preceding | |||
1358 | // the function global entry point. | |||
1359 | if (TM.getCodeModel() == CodeModel::Large | |||
1360 | && !MF->getRegInfo().use_empty(PPC::X2)) { | |||
1361 | const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>(); | |||
1362 | ||||
1363 | MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC.")); | |||
1364 | MCSymbol *GlobalEPSymbol = PPCFI->getGlobalEPSymbol(); | |||
1365 | const MCExpr *TOCDeltaExpr = | |||
1366 | MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCSymbol, OutContext), | |||
1367 | MCSymbolRefExpr::create(GlobalEPSymbol, | |||
1368 | OutContext), | |||
1369 | OutContext); | |||
1370 | ||||
1371 | OutStreamer->emitLabel(PPCFI->getTOCOffsetSymbol()); | |||
1372 | OutStreamer->emitValue(TOCDeltaExpr, 8); | |||
1373 | } | |||
1374 | return AsmPrinter::emitFunctionEntryLabel(); | |||
1375 | } | |||
1376 | ||||
1377 | // Emit an official procedure descriptor. | |||
1378 | MCSectionSubPair Current = OutStreamer->getCurrentSection(); | |||
1379 | MCSectionELF *Section = OutStreamer->getContext().getELFSection( | |||
1380 | ".opd", ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); | |||
1381 | OutStreamer->SwitchSection(Section); | |||
1382 | OutStreamer->emitLabel(CurrentFnSym); | |||
1383 | OutStreamer->emitValueToAlignment(8); | |||
1384 | MCSymbol *Symbol1 = CurrentFnSymForSize; | |||
1385 | // Generates a R_PPC64_ADDR64 (from FK_DATA_8) relocation for the function | |||
1386 | // entry point. | |||
1387 | OutStreamer->emitValue(MCSymbolRefExpr::create(Symbol1, OutContext), | |||
1388 | 8 /*size*/); | |||
1389 | MCSymbol *Symbol2 = OutContext.getOrCreateSymbol(StringRef(".TOC.")); | |||
1390 | // Generates a R_PPC64_TOC relocation for TOC base insertion. | |||
1391 | OutStreamer->emitValue( | |||
1392 | MCSymbolRefExpr::create(Symbol2, MCSymbolRefExpr::VK_PPC_TOCBASE, OutContext), | |||
1393 | 8/*size*/); | |||
1394 | // Emit a null environment pointer. | |||
1395 | OutStreamer->emitIntValue(0, 8 /* size */); | |||
1396 | OutStreamer->SwitchSection(Current.first, Current.second); | |||
1397 | } | |||
1398 | ||||
1399 | void PPCLinuxAsmPrinter::emitEndOfAsmFile(Module &M) { | |||
1400 | const DataLayout &DL = getDataLayout(); | |||
1401 | ||||
1402 | bool isPPC64 = DL.getPointerSizeInBits() == 64; | |||
1403 | ||||
1404 | PPCTargetStreamer &TS = | |||
1405 | static_cast<PPCTargetStreamer &>(*OutStreamer->getTargetStreamer()); | |||
1406 | ||||
1407 | if (!TOC.empty()) { | |||
1408 | const char *Name = isPPC64 ? ".toc" : ".got2"; | |||
1409 | MCSectionELF *Section = OutContext.getELFSection( | |||
1410 | Name, ELF::SHT_PROGBITS, ELF::SHF_WRITE | ELF::SHF_ALLOC); | |||
1411 | OutStreamer->SwitchSection(Section); | |||
1412 | if (!isPPC64) | |||
1413 | OutStreamer->emitValueToAlignment(4); | |||
1414 | ||||
1415 | for (const auto &TOCMapPair : TOC) { | |||
1416 | const MCSymbol *const TOCEntryTarget = TOCMapPair.first; | |||
1417 | MCSymbol *const TOCEntryLabel = TOCMapPair.second; | |||
1418 | ||||
1419 | OutStreamer->emitLabel(TOCEntryLabel); | |||
1420 | if (isPPC64) | |||
1421 | TS.emitTCEntry(*TOCEntryTarget); | |||
1422 | else | |||
1423 | OutStreamer->emitSymbolValue(TOCEntryTarget, 4); | |||
1424 | } | |||
1425 | } | |||
1426 | ||||
1427 | PPCAsmPrinter::emitEndOfAsmFile(M); | |||
1428 | } | |||
1429 | ||||
1430 | /// EmitFunctionBodyStart - Emit a global entry point prefix for ELFv2. | |||
1431 | void PPCLinuxAsmPrinter::emitFunctionBodyStart() { | |||
1432 | // In the ELFv2 ABI, in functions that use the TOC register, we need to | |||
1433 | // provide two entry points. The ABI guarantees that when calling the | |||
1434 | // local entry point, r2 is set up by the caller to contain the TOC base | |||
1435 | // for this function, and when calling the global entry point, r12 is set | |||
1436 | // up by the caller to hold the address of the global entry point. We | |||
1437 | // thus emit a prefix sequence along the following lines: | |||
1438 | // | |||
1439 | // func: | |||
1440 | // .Lfunc_gepNN: | |||
1441 | // # global entry point | |||
1442 | // addis r2,r12,(.TOC.-.Lfunc_gepNN)@ha | |||
1443 | // addi r2,r2,(.TOC.-.Lfunc_gepNN)@l | |||
1444 | // .Lfunc_lepNN: | |||
1445 | // .localentry func, .Lfunc_lepNN-.Lfunc_gepNN | |||
1446 | // # local entry point, followed by function body | |||
1447 | // | |||
1448 | // For the Large code model, we create | |||
1449 | // | |||
1450 | // .Lfunc_tocNN: | |||
1451 | // .quad .TOC.-.Lfunc_gepNN # done by EmitFunctionEntryLabel | |||
1452 | // func: | |||
1453 | // .Lfunc_gepNN: | |||
1454 | // # global entry point | |||
1455 | // ld r2,.Lfunc_tocNN-.Lfunc_gepNN(r12) | |||
1456 | // add r2,r2,r12 | |||
1457 | // .Lfunc_lepNN: | |||
1458 | // .localentry func, .Lfunc_lepNN-.Lfunc_gepNN | |||
1459 | // # local entry point, followed by function body | |||
1460 | // | |||
1461 | // This ensures we have r2 set up correctly while executing the function | |||
1462 | // body, no matter which entry point is called. | |||
1463 | if (Subtarget->isELFv2ABI() | |||
1464 | // Only do all that if the function uses r2 in the first place. | |||
1465 | && !MF->getRegInfo().use_empty(PPC::X2)) { | |||
1466 | // Note: The logic here must be synchronized with the code in the | |||
1467 | // branch-selection pass which sets the offset of the first block in the | |||
1468 | // function. This matters because it affects the alignment. | |||
1469 | const PPCFunctionInfo *PPCFI = MF->getInfo<PPCFunctionInfo>(); | |||
1470 | ||||
1471 | MCSymbol *GlobalEntryLabel = PPCFI->getGlobalEPSymbol(); | |||
1472 | OutStreamer->emitLabel(GlobalEntryLabel); | |||
1473 | const MCSymbolRefExpr *GlobalEntryLabelExp = | |||
1474 | MCSymbolRefExpr::create(GlobalEntryLabel, OutContext); | |||
1475 | ||||
1476 | if (TM.getCodeModel() != CodeModel::Large) { | |||
1477 | MCSymbol *TOCSymbol = OutContext.getOrCreateSymbol(StringRef(".TOC.")); | |||
1478 | const MCExpr *TOCDeltaExpr = | |||
1479 | MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCSymbol, OutContext), | |||
1480 | GlobalEntryLabelExp, OutContext); | |||
1481 | ||||
1482 | const MCExpr *TOCDeltaHi = PPCMCExpr::createHa(TOCDeltaExpr, OutContext); | |||
1483 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDIS) | |||
1484 | .addReg(PPC::X2) | |||
1485 | .addReg(PPC::X12) | |||
1486 | .addExpr(TOCDeltaHi)); | |||
1487 | ||||
1488 | const MCExpr *TOCDeltaLo = PPCMCExpr::createLo(TOCDeltaExpr, OutContext); | |||
1489 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADDI) | |||
1490 | .addReg(PPC::X2) | |||
1491 | .addReg(PPC::X2) | |||
1492 | .addExpr(TOCDeltaLo)); | |||
1493 | } else { | |||
1494 | MCSymbol *TOCOffset = PPCFI->getTOCOffsetSymbol(); | |||
1495 | const MCExpr *TOCOffsetDeltaExpr = | |||
1496 | MCBinaryExpr::createSub(MCSymbolRefExpr::create(TOCOffset, OutContext), | |||
1497 | GlobalEntryLabelExp, OutContext); | |||
1498 | ||||
1499 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::LD) | |||
1500 | .addReg(PPC::X2) | |||
1501 | .addExpr(TOCOffsetDeltaExpr) | |||
1502 | .addReg(PPC::X12)); | |||
1503 | EmitToStreamer(*OutStreamer, MCInstBuilder(PPC::ADD8) | |||
1504 | .addReg(PPC::X2) | |||
1505 | .addReg(PPC::X2) | |||
1506 | .addReg(PPC::X12)); | |||
1507 | } | |||
1508 | ||||
1509 | MCSymbol *LocalEntryLabel = PPCFI->getLocalEPSymbol(); | |||
1510 | OutStreamer->emitLabel(LocalEntryLabel); | |||
1511 | const MCSymbolRefExpr *LocalEntryLabelExp = | |||
1512 | MCSymbolRefExpr::create(LocalEntryLabel, OutContext); | |||
1513 | const MCExpr *LocalOffsetExp = | |||
1514 | MCBinaryExpr::createSub(LocalEntryLabelExp, | |||
1515 | GlobalEntryLabelExp, OutContext); | |||
1516 | ||||
1517 | PPCTargetStreamer *TS = | |||
1518 | static_cast<PPCTargetStreamer *>(OutStreamer->getTargetStreamer()); | |||
1519 | ||||
1520 | if (TS) | |||
1521 | TS->emitLocalEntry(cast<MCSymbolELF>(CurrentFnSym), LocalOffsetExp); | |||
1522 | } | |||
1523 | } | |||
1524 | ||||
1525 | /// EmitFunctionBodyEnd - Print the traceback table before the .size | |||
1526 | /// directive. | |||
1527 | /// | |||
1528 | void PPCLinuxAsmPrinter::emitFunctionBodyEnd() { | |||
1529 | // Only the 64-bit target requires a traceback table. For now, | |||
1530 | // we only emit the word of zeroes that GDB requires to find | |||
1531 | // the end of the function, and zeroes for the eight-byte | |||
1532 | // mandatory fields. | |||
1533 | // FIXME: We should fill in the eight-byte mandatory fields as described in | |||
1534 | // the PPC64 ELF ABI (this is a low-priority item because GDB does not | |||
1535 | // currently make use of these fields). | |||
1536 | if (Subtarget->isPPC64()) { | |||
1537 | OutStreamer->emitIntValue(0, 4/*size*/); | |||
1538 | OutStreamer->emitIntValue(0, 8/*size*/); | |||
1539 | } | |||
1540 | } | |||
1541 | ||||
1542 | void PPCAIXAsmPrinter::SetupMachineFunction(MachineFunction &MF) { | |||
1543 | // Get the function descriptor symbol. | |||
1544 | CurrentFnDescSym = getSymbol(&MF.getFunction()); | |||
1545 | // Set the alignment and the containing csect. | |||
1546 | MCSectionXCOFF *FnDescSec = cast<MCSectionXCOFF>( | |||
1547 | getObjFileLowering().getSectionForFunctionDescriptor(CurrentFnDescSym)); | |||
1548 | FnDescSec->setAlignment(Align(Subtarget->isPPC64() ? 8 : 4)); | |||
1549 | cast<MCSymbolXCOFF>(CurrentFnDescSym)->setContainingCsect(FnDescSec); | |||
1550 | ||||
1551 | return AsmPrinter::SetupMachineFunction(MF); | |||
1552 | } | |||
1553 | ||||
1554 | void PPCAIXAsmPrinter::ValidateGV(const GlobalVariable *GV) { | |||
1555 | // Early error checking limiting what is supported. | |||
1556 | if (GV->isThreadLocal()) | |||
1557 | report_fatal_error("Thread local not yet supported on AIX."); | |||
1558 | ||||
1559 | if (GV->hasSection()) | |||
1560 | report_fatal_error("Custom section for Data not yet supported."); | |||
1561 | ||||
1562 | if (GV->hasComdat()) | |||
1563 | report_fatal_error("COMDAT not yet supported by AIX."); | |||
1564 | } | |||
1565 | ||||
1566 | const MCExpr *PPCAIXAsmPrinter::lowerConstant(const Constant *CV) { | |||
1567 | if (const Function *F = dyn_cast<Function>(CV)) { | |||
1568 | MCSymbolXCOFF *FSym = cast<MCSymbolXCOFF>(getSymbol(F)); | |||
1569 | if (!FSym->hasContainingCsect()) { | |||
1570 | MCSectionXCOFF *Csect = cast<MCSectionXCOFF>( | |||
1571 | F->isDeclaration() | |||
1572 | ? getObjFileLowering().getSectionForExternalReference(F, TM) | |||
1573 | : getObjFileLowering().getSectionForFunctionDescriptor(FSym)); | |||
1574 | FSym->setContainingCsect(Csect); | |||
1575 | } | |||
1576 | return MCSymbolRefExpr::create( | |||
1577 | FSym->getContainingCsect()->getQualNameSymbol(), OutContext); | |||
1578 | } | |||
1579 | return PPCAsmPrinter::lowerConstant(CV); | |||
1580 | } | |||
1581 | ||||
1582 | static bool isSpecialLLVMGlobalArrayForStaticInit(const GlobalVariable *GV) { | |||
1583 | return StringSwitch<bool>(GV->getName()) | |||
1584 | .Cases("llvm.global_ctors", "llvm.global_dtors", true) | |||
1585 | .Default(false); | |||
1586 | } | |||
1587 | ||||
1588 | void PPCAIXAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { | |||
1589 | ValidateGV(GV); | |||
1590 | ||||
1591 | // TODO: Update the handling of global arrays for static init when we support | |||
1592 | // the ".ref" directive. | |||
1593 | // Otherwise, we can skip these arrays, because the AIX linker collects | |||
1594 | // static init functions simply based on their name. | |||
1595 | if (isSpecialLLVMGlobalArrayForStaticInit(GV)) | |||
| ||||
1596 | return; | |||
1597 | ||||
1598 | // Create the symbol, set its storage class. | |||
1599 | MCSymbolXCOFF *GVSym = cast<MCSymbolXCOFF>(getSymbol(GV)); | |||
1600 | GVSym->setStorageClass( | |||
1601 | TargetLoweringObjectFileXCOFF::getStorageClassForGlobal(GV)); | |||
1602 | ||||
1603 | SectionKind GVKind; | |||
1604 | ||||
1605 | // Create the containing csect and set it. We set it for externals as well, | |||
1606 | // since this may not have been set elsewhere depending on how they are used. | |||
1607 | MCSectionXCOFF *Csect = cast<MCSectionXCOFF>( | |||
1608 | GV->isDeclaration() | |||
1609 | ? getObjFileLowering().getSectionForExternalReference(GV, TM) | |||
1610 | : getObjFileLowering().SectionForGlobal( | |||
1611 | GV, GVKind = getObjFileLowering().getKindForGlobal(GV, TM), | |||
1612 | TM)); | |||
1613 | GVSym->setContainingCsect(Csect); | |||
1614 | ||||
1615 | // External global variables are already handled. | |||
1616 | if (GV->isDeclaration()) | |||
1617 | return; | |||
1618 | ||||
1619 | if (!GVKind.isGlobalWriteableData() && !GVKind.isReadOnly()) | |||
1620 | report_fatal_error("Encountered a global variable kind that is " | |||
1621 | "not supported yet."); | |||
1622 | ||||
1623 | // Switch to the containing csect. | |||
1624 | OutStreamer->SwitchSection(Csect); | |||
1625 | ||||
1626 | const DataLayout &DL = GV->getParent()->getDataLayout(); | |||
1627 | ||||
1628 | // Handle common symbols. | |||
1629 | if (GVKind.isCommon() || GVKind.isBSSLocal()) { | |||
1630 | unsigned Align = | |||
1631 | GV->getAlignment() ? GV->getAlignment() : DL.getPreferredAlignment(GV); | |||
1632 | uint64_t Size = DL.getTypeAllocSize(GV->getType()->getElementType()); | |||
1633 | ||||
1634 | if (GVKind.isBSSLocal()) | |||
1635 | OutStreamer->emitXCOFFLocalCommonSymbol( | |||
1636 | GVSym, Size, Csect->getQualNameSymbol(), Align); | |||
1637 | else | |||
1638 | OutStreamer->emitCommonSymbol(Csect->getQualNameSymbol(), Size, Align); | |||
1639 | return; | |||
1640 | } | |||
1641 | ||||
1642 | MCSymbol *EmittedInitSym = GVSym; | |||
1643 | emitLinkage(GV, EmittedInitSym); | |||
1644 | emitAlignment(getGVAlignment(GV, DL), GV); | |||
1645 | OutStreamer->emitLabel(EmittedInitSym); | |||
1646 | emitGlobalConstant(GV->getParent()->getDataLayout(), GV->getInitializer()); | |||
1647 | } | |||
1648 | ||||
1649 | void PPCAIXAsmPrinter::emitFunctionDescriptor() { | |||
1650 | const DataLayout &DL = getDataLayout(); | |||
1651 | const unsigned PointerSize = DL.getPointerSizeInBits() == 64 ? 8 : 4; | |||
1652 | ||||
1653 | MCSectionSubPair Current = OutStreamer->getCurrentSection(); | |||
1654 | // Emit function descriptor. | |||
1655 | OutStreamer->SwitchSection( | |||
1656 | cast<MCSymbolXCOFF>(CurrentFnDescSym)->getContainingCsect()); | |||
1657 | OutStreamer->emitLabel(CurrentFnDescSym); | |||
1658 | // Emit function entry point address. | |||
1659 | OutStreamer->emitValue(MCSymbolRefExpr::create(CurrentFnSym, OutContext), | |||
1660 | PointerSize); | |||
1661 | // Emit TOC base address. | |||
1662 | const MCSymbol *TOCBaseSym = | |||
1663 | cast<MCSectionXCOFF>(getObjFileLowering().getTOCBaseSection()) | |||
1664 | ->getQualNameSymbol(); | |||
1665 | OutStreamer->emitValue(MCSymbolRefExpr::create(TOCBaseSym, OutContext), | |||
1666 | PointerSize); | |||
1667 | // Emit a null environment pointer. | |||
1668 | OutStreamer->emitIntValue(0, PointerSize); | |||
1669 | ||||
1670 | OutStreamer->SwitchSection(Current.first, Current.second); | |||
1671 | } | |||
1672 | ||||
1673 | void PPCAIXAsmPrinter::emitEndOfAsmFile(Module &M) { | |||
1674 | // If there are no functions in this module, we will never need to reference | |||
1675 | // the TOC base. | |||
1676 | if (M.empty()) | |||
1677 | return; | |||
1678 | ||||
1679 | // Switch to section to emit TOC base. | |||
1680 | OutStreamer->SwitchSection(getObjFileLowering().getTOCBaseSection()); | |||
1681 | ||||
1682 | PPCTargetStreamer &TS = | |||
1683 | static_cast<PPCTargetStreamer &>(*OutStreamer->getTargetStreamer()); | |||
1684 | ||||
1685 | const unsigned EntryByteSize = Subtarget->isPPC64() ? 8 : 4; | |||
1686 | const unsigned TOCEntriesByteSize = TOC.size() * EntryByteSize; | |||
1687 | // TODO: If TOC entries' size is larger than 32768, then we run out of | |||
1688 | // positive displacement to reach the TOC entry. We need to decide how to | |||
1689 | // handle entries' size larger than that later. | |||
1690 | if (TOCEntriesByteSize > 32767) { | |||
1691 | report_fatal_error("Handling of TOC entry displacement larger than 32767 " | |||
1692 | "is not yet implemented."); | |||
1693 | } | |||
1694 | ||||
1695 | for (auto &I : TOC) { | |||
1696 | // Setup the csect for the current TC entry. | |||
1697 | MCSectionXCOFF *TCEntry = cast<MCSectionXCOFF>( | |||
1698 | getObjFileLowering().getSectionForTOCEntry(I.first)); | |||
1699 | cast<MCSymbolXCOFF>(I.second)->setContainingCsect(TCEntry); | |||
1700 | OutStreamer->SwitchSection(TCEntry); | |||
1701 | ||||
1702 | OutStreamer->emitLabel(I.second); | |||
1703 | TS.emitTCEntry(*I.first); | |||
1704 | } | |||
1705 | } | |||
1706 | ||||
1707 | MCSymbol * | |||
1708 | PPCAIXAsmPrinter::getMCSymbolForTOCPseudoMO(const MachineOperand &MO) { | |||
1709 | const GlobalObject *GO = nullptr; | |||
1710 | ||||
1711 | // If the MO is a function or certain kind of globals, we want to make sure to | |||
1712 | // refer to the csect symbol, otherwise we can just do the default handling. | |||
1713 | if (MO.getType() != MachineOperand::MO_GlobalAddress || | |||
1714 | !(GO = dyn_cast<const GlobalObject>(MO.getGlobal()))) | |||
1715 | return PPCAsmPrinter::getMCSymbolForTOCPseudoMO(MO); | |||
1716 | ||||
1717 | // Do an early error check for globals we don't support. This will go away | |||
1718 | // eventually. | |||
1719 | const auto *GV = dyn_cast<const GlobalVariable>(GO); | |||
1720 | if (GV) { | |||
1721 | ValidateGV(GV); | |||
1722 | } | |||
1723 | ||||
1724 | MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(getSymbol(GO)); | |||
1725 | ||||
1726 | // If the global object is a global variable without initializer or is a | |||
1727 | // declaration of a function, then XSym is an external referenced symbol. | |||
1728 | // Hence we may need to explictly create a MCSectionXCOFF for it so that we | |||
1729 | // can return its symbol later. | |||
1730 | if (GO->isDeclaration()) { | |||
1731 | return cast<MCSectionXCOFF>( | |||
1732 | getObjFileLowering().getSectionForExternalReference(GO, TM)) | |||
1733 | ->getQualNameSymbol(); | |||
1734 | } | |||
1735 | ||||
1736 | // Handle initialized global variables and defined functions. | |||
1737 | SectionKind GOKind = getObjFileLowering().getKindForGlobal(GO, TM); | |||
1738 | ||||
1739 | if (GOKind.isText()) { | |||
1740 | // If the MO is a function, we want to make sure to refer to the function | |||
1741 | // descriptor csect. | |||
1742 | return cast<MCSectionXCOFF>( | |||
1743 | getObjFileLowering().getSectionForFunctionDescriptor(XSym)) | |||
1744 | ->getQualNameSymbol(); | |||
1745 | } else if (GOKind.isCommon() || GOKind.isBSSLocal()) { | |||
1746 | // If the operand is a common then we should refer to the csect symbol. | |||
1747 | return cast<MCSectionXCOFF>( | |||
1748 | getObjFileLowering().SectionForGlobal(GO, GOKind, TM)) | |||
1749 | ->getQualNameSymbol(); | |||
1750 | } | |||
1751 | ||||
1752 | // Other global variables are refered to by labels inside of a single csect, | |||
1753 | // so refer to the label directly. | |||
1754 | return getSymbol(GV); | |||
1755 | } | |||
1756 | ||||
1757 | /// createPPCAsmPrinterPass - Returns a pass that prints the PPC assembly code | |||
1758 | /// for a MachineFunction to the given output stream, in a format that the | |||
1759 | /// Darwin assembler can deal with. | |||
1760 | /// | |||
1761 | static AsmPrinter * | |||
1762 | createPPCAsmPrinterPass(TargetMachine &tm, | |||
1763 | std::unique_ptr<MCStreamer> &&Streamer) { | |||
1764 | if (tm.getTargetTriple().isOSAIX()) | |||
1765 | return new PPCAIXAsmPrinter(tm, std::move(Streamer)); | |||
1766 | ||||
1767 | return new PPCLinuxAsmPrinter(tm, std::move(Streamer)); | |||
1768 | } | |||
1769 | ||||
1770 | // Force static initialization. | |||
1771 | extern "C" LLVM_EXTERNAL_VISIBILITY__attribute__ ((visibility("default"))) void LLVMInitializePowerPCAsmPrinter() { | |||
1772 | TargetRegistry::RegisterAsmPrinter(getThePPC32Target(), | |||
1773 | createPPCAsmPrinterPass); | |||
1774 | TargetRegistry::RegisterAsmPrinter(getThePPC64Target(), | |||
1775 | createPPCAsmPrinterPass); | |||
1776 | TargetRegistry::RegisterAsmPrinter(getThePPC64LETarget(), | |||
1777 | createPPCAsmPrinterPass); | |||
1778 | } |
1 | //===-- llvm/MC/SectionKind.h - Classification of sections ------*- C++ -*-===// | |||
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 | #ifndef LLVM_MC_SECTIONKIND_H | |||
10 | #define LLVM_MC_SECTIONKIND_H | |||
11 | ||||
12 | namespace llvm { | |||
13 | ||||
14 | /// SectionKind - This is a simple POD value that classifies the properties of | |||
15 | /// a section. A section is classified into the deepest possible | |||
16 | /// classification, and then the target maps them onto their sections based on | |||
17 | /// what capabilities they have. | |||
18 | /// | |||
19 | /// The comments below describe these as if they were an inheritance hierarchy | |||
20 | /// in order to explain the predicates below. | |||
21 | /// | |||
22 | class SectionKind { | |||
23 | enum Kind { | |||
24 | /// Metadata - Debug info sections or other metadata. | |||
25 | Metadata, | |||
26 | ||||
27 | /// Text - Text section, used for functions and other executable code. | |||
28 | Text, | |||
29 | ||||
30 | /// ExecuteOnly, Text section that is not readable. | |||
31 | ExecuteOnly, | |||
32 | ||||
33 | /// ReadOnly - Data that is never written to at program runtime by the | |||
34 | /// program or the dynamic linker. Things in the top-level readonly | |||
35 | /// SectionKind are not mergeable. | |||
36 | ReadOnly, | |||
37 | ||||
38 | /// MergableCString - Any null-terminated string which allows merging. | |||
39 | /// These values are known to end in a nul value of the specified size, | |||
40 | /// not otherwise contain a nul value, and be mergable. This allows the | |||
41 | /// linker to unique the strings if it so desires. | |||
42 | ||||
43 | /// Mergeable1ByteCString - 1 byte mergable, null terminated, string. | |||
44 | Mergeable1ByteCString, | |||
45 | ||||
46 | /// Mergeable2ByteCString - 2 byte mergable, null terminated, string. | |||
47 | Mergeable2ByteCString, | |||
48 | ||||
49 | /// Mergeable4ByteCString - 4 byte mergable, null terminated, string. | |||
50 | Mergeable4ByteCString, | |||
51 | ||||
52 | /// MergeableConst - These are sections for merging fixed-length | |||
53 | /// constants together. For example, this can be used to unique | |||
54 | /// constant pool entries etc. | |||
55 | ||||
56 | /// MergeableConst4 - This is a section used by 4-byte constants, | |||
57 | /// for example, floats. | |||
58 | MergeableConst4, | |||
59 | ||||
60 | /// MergeableConst8 - This is a section used by 8-byte constants, | |||
61 | /// for example, doubles. | |||
62 | MergeableConst8, | |||
63 | ||||
64 | /// MergeableConst16 - This is a section used by 16-byte constants, | |||
65 | /// for example, vectors. | |||
66 | MergeableConst16, | |||
67 | ||||
68 | /// MergeableConst32 - This is a section used by 32-byte constants, | |||
69 | /// for example, vectors. | |||
70 | MergeableConst32, | |||
71 | ||||
72 | /// Writeable - This is the base of all segments that need to be written | |||
73 | /// to during program runtime. | |||
74 | ||||
75 | /// ThreadLocal - This is the base of all TLS segments. All TLS | |||
76 | /// objects must be writeable, otherwise there is no reason for them to | |||
77 | /// be thread local! | |||
78 | ||||
79 | /// ThreadBSS - Zero-initialized TLS data objects. | |||
80 | ThreadBSS, | |||
81 | ||||
82 | /// ThreadData - Initialized TLS data objects. | |||
83 | ThreadData, | |||
84 | ||||
85 | /// GlobalWriteableData - Writeable data that is global (not thread | |||
86 | /// local). | |||
87 | ||||
88 | /// BSS - Zero initialized writeable data. | |||
89 | BSS, | |||
90 | ||||
91 | /// BSSLocal - This is BSS (zero initialized and writable) data | |||
92 | /// which has local linkage. | |||
93 | BSSLocal, | |||
94 | ||||
95 | /// BSSExtern - This is BSS data with normal external linkage. | |||
96 | BSSExtern, | |||
97 | ||||
98 | /// Common - Data with common linkage. These represent tentative | |||
99 | /// definitions, which always have a zero initializer and are never | |||
100 | /// marked 'constant'. | |||
101 | Common, | |||
102 | ||||
103 | /// This is writeable data that has a non-zero initializer. | |||
104 | Data, | |||
105 | ||||
106 | /// ReadOnlyWithRel - These are global variables that are never | |||
107 | /// written to by the program, but that have relocations, so they | |||
108 | /// must be stuck in a writeable section so that the dynamic linker | |||
109 | /// can write to them. If it chooses to, the dynamic linker can | |||
110 | /// mark the pages these globals end up on as read-only after it is | |||
111 | /// done with its relocation phase. | |||
112 | ReadOnlyWithRel | |||
113 | } K : 8; | |||
114 | public: | |||
115 | ||||
116 | bool isMetadata() const { return K == Metadata; } | |||
117 | ||||
118 | bool isText() const { return K == Text || K == ExecuteOnly; } | |||
119 | ||||
120 | bool isExecuteOnly() const { return K == ExecuteOnly; } | |||
121 | ||||
122 | bool isReadOnly() const { | |||
123 | return K == ReadOnly || isMergeableCString() || | |||
124 | isMergeableConst(); | |||
125 | } | |||
126 | ||||
127 | bool isMergeableCString() const { | |||
128 | return K == Mergeable1ByteCString || K == Mergeable2ByteCString || | |||
129 | K == Mergeable4ByteCString; | |||
130 | } | |||
131 | bool isMergeable1ByteCString() const { return K == Mergeable1ByteCString; } | |||
132 | bool isMergeable2ByteCString() const { return K == Mergeable2ByteCString; } | |||
133 | bool isMergeable4ByteCString() const { return K == Mergeable4ByteCString; } | |||
134 | ||||
135 | bool isMergeableConst() const { | |||
136 | return K == MergeableConst4 || K == MergeableConst8 || | |||
137 | K == MergeableConst16 || K == MergeableConst32; | |||
138 | } | |||
139 | bool isMergeableConst4() const { return K == MergeableConst4; } | |||
140 | bool isMergeableConst8() const { return K == MergeableConst8; } | |||
141 | bool isMergeableConst16() const { return K == MergeableConst16; } | |||
142 | bool isMergeableConst32() const { return K == MergeableConst32; } | |||
143 | ||||
144 | bool isWriteable() const { | |||
145 | return isThreadLocal() || isGlobalWriteableData(); | |||
146 | } | |||
147 | ||||
148 | bool isThreadLocal() const { | |||
149 | return K == ThreadData || K == ThreadBSS; | |||
150 | } | |||
151 | ||||
152 | bool isThreadBSS() const { return K == ThreadBSS; } | |||
153 | bool isThreadData() const { return K == ThreadData; } | |||
154 | ||||
155 | bool isGlobalWriteableData() const { | |||
156 | return isBSS() || isCommon() || isData() || isReadOnlyWithRel(); | |||
157 | } | |||
158 | ||||
159 | bool isBSS() const { return K == BSS || K == BSSLocal || K == BSSExtern; } | |||
| ||||
160 | bool isBSSLocal() const { return K == BSSLocal; } | |||
161 | bool isBSSExtern() const { return K == BSSExtern; } | |||
162 | ||||
163 | bool isCommon() const { return K == Common; } | |||
164 | ||||
165 | bool isData() const { return K == Data; } | |||
166 | ||||
167 | bool isReadOnlyWithRel() const { | |||
168 | return K == ReadOnlyWithRel; | |||
169 | } | |||
170 | private: | |||
171 | static SectionKind get(Kind K) { | |||
172 | SectionKind Res; | |||
173 | Res.K = K; | |||
174 | return Res; | |||
175 | } | |||
176 | public: | |||
177 | ||||
178 | static SectionKind getMetadata() { return get(Metadata); } | |||
179 | static SectionKind getText() { return get(Text); } | |||
180 | static SectionKind getExecuteOnly() { return get(ExecuteOnly); } | |||
181 | static SectionKind getReadOnly() { return get(ReadOnly); } | |||
182 | static SectionKind getMergeable1ByteCString() { | |||
183 | return get(Mergeable1ByteCString); | |||
184 | } | |||
185 | static SectionKind getMergeable2ByteCString() { | |||
186 | return get(Mergeable2ByteCString); | |||
187 | } | |||
188 | static SectionKind getMergeable4ByteCString() { | |||
189 | return get(Mergeable4ByteCString); | |||
190 | } | |||
191 | static SectionKind getMergeableConst4() { return get(MergeableConst4); } | |||
192 | static SectionKind getMergeableConst8() { return get(MergeableConst8); } | |||
193 | static SectionKind getMergeableConst16() { return get(MergeableConst16); } | |||
194 | static SectionKind getMergeableConst32() { return get(MergeableConst32); } | |||
195 | static SectionKind getThreadBSS() { return get(ThreadBSS); } | |||
196 | static SectionKind getThreadData() { return get(ThreadData); } | |||
197 | static SectionKind getBSS() { return get(BSS); } | |||
198 | static SectionKind getBSSLocal() { return get(BSSLocal); } | |||
199 | static SectionKind getBSSExtern() { return get(BSSExtern); } | |||
200 | static SectionKind getCommon() { return get(Common); } | |||
201 | static SectionKind getData() { return get(Data); } | |||
202 | static SectionKind getReadOnlyWithRel() { return get(ReadOnlyWithRel); } | |||
203 | }; | |||
204 | ||||
205 | } // end namespace llvm | |||
206 | ||||
207 | #endif |