File: | lib/Target/ARM/ARMAsmPrinter.cpp |
Warning: | line 371, column 14 The left operand of '==' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | // | |||
10 | // This file contains a printer that converts from our internal representation | |||
11 | // of machine-dependent LLVM code to GAS-format ARM assembly language. | |||
12 | // | |||
13 | //===----------------------------------------------------------------------===// | |||
14 | ||||
15 | #include "ARMAsmPrinter.h" | |||
16 | #include "ARM.h" | |||
17 | #include "ARMConstantPoolValue.h" | |||
18 | #include "ARMMachineFunctionInfo.h" | |||
19 | #include "ARMTargetMachine.h" | |||
20 | #include "ARMTargetObjectFile.h" | |||
21 | #include "InstPrinter/ARMInstPrinter.h" | |||
22 | #include "MCTargetDesc/ARMAddressingModes.h" | |||
23 | #include "MCTargetDesc/ARMMCExpr.h" | |||
24 | #include "llvm/ADT/SetVector.h" | |||
25 | #include "llvm/ADT/SmallString.h" | |||
26 | #include "llvm/BinaryFormat/COFF.h" | |||
27 | #include "llvm/CodeGen/MachineFunctionPass.h" | |||
28 | #include "llvm/CodeGen/MachineJumpTableInfo.h" | |||
29 | #include "llvm/CodeGen/MachineModuleInfoImpls.h" | |||
30 | #include "llvm/IR/Constants.h" | |||
31 | #include "llvm/IR/DataLayout.h" | |||
32 | #include "llvm/IR/Mangler.h" | |||
33 | #include "llvm/IR/Module.h" | |||
34 | #include "llvm/IR/Type.h" | |||
35 | #include "llvm/MC/MCAsmInfo.h" | |||
36 | #include "llvm/MC/MCAssembler.h" | |||
37 | #include "llvm/MC/MCContext.h" | |||
38 | #include "llvm/MC/MCELFStreamer.h" | |||
39 | #include "llvm/MC/MCInst.h" | |||
40 | #include "llvm/MC/MCInstBuilder.h" | |||
41 | #include "llvm/MC/MCObjectStreamer.h" | |||
42 | #include "llvm/MC/MCStreamer.h" | |||
43 | #include "llvm/MC/MCSymbol.h" | |||
44 | #include "llvm/Support/ARMBuildAttributes.h" | |||
45 | #include "llvm/Support/Debug.h" | |||
46 | #include "llvm/Support/ErrorHandling.h" | |||
47 | #include "llvm/Support/TargetParser.h" | |||
48 | #include "llvm/Support/TargetRegistry.h" | |||
49 | #include "llvm/Support/raw_ostream.h" | |||
50 | #include "llvm/Target/TargetMachine.h" | |||
51 | using namespace llvm; | |||
52 | ||||
53 | #define DEBUG_TYPE"asm-printer" "asm-printer" | |||
54 | ||||
55 | ARMAsmPrinter::ARMAsmPrinter(TargetMachine &TM, | |||
56 | std::unique_ptr<MCStreamer> Streamer) | |||
57 | : AsmPrinter(TM, std::move(Streamer)), AFI(nullptr), MCP(nullptr), | |||
58 | InConstantPool(false), OptimizationGoals(-1) {} | |||
59 | ||||
60 | void ARMAsmPrinter::EmitFunctionBodyEnd() { | |||
61 | // Make sure to terminate any constant pools that were at the end | |||
62 | // of the function. | |||
63 | if (!InConstantPool) | |||
64 | return; | |||
65 | InConstantPool = false; | |||
66 | OutStreamer->EmitDataRegion(MCDR_DataRegionEnd); | |||
67 | } | |||
68 | ||||
69 | void ARMAsmPrinter::EmitFunctionEntryLabel() { | |||
70 | if (AFI->isThumbFunction()) { | |||
71 | OutStreamer->EmitAssemblerFlag(MCAF_Code16); | |||
72 | OutStreamer->EmitThumbFunc(CurrentFnSym); | |||
73 | } else { | |||
74 | OutStreamer->EmitAssemblerFlag(MCAF_Code32); | |||
75 | } | |||
76 | OutStreamer->EmitLabel(CurrentFnSym); | |||
77 | } | |||
78 | ||||
79 | void ARMAsmPrinter::EmitXXStructor(const DataLayout &DL, const Constant *CV) { | |||
80 | uint64_t Size = getDataLayout().getTypeAllocSize(CV->getType()); | |||
81 | assert(Size && "C++ constructor pointer had zero size!")(static_cast <bool> (Size && "C++ constructor pointer had zero size!" ) ? void (0) : __assert_fail ("Size && \"C++ constructor pointer had zero size!\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 81, __extension__ __PRETTY_FUNCTION__)); | |||
82 | ||||
83 | const GlobalValue *GV = dyn_cast<GlobalValue>(CV->stripPointerCasts()); | |||
84 | assert(GV && "C++ constructor pointer was not a GlobalValue!")(static_cast <bool> (GV && "C++ constructor pointer was not a GlobalValue!" ) ? void (0) : __assert_fail ("GV && \"C++ constructor pointer was not a GlobalValue!\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 84, __extension__ __PRETTY_FUNCTION__)); | |||
85 | ||||
86 | const MCExpr *E = MCSymbolRefExpr::create(GetARMGVSymbol(GV, | |||
87 | ARMII::MO_NO_FLAG), | |||
88 | (Subtarget->isTargetELF() | |||
89 | ? MCSymbolRefExpr::VK_ARM_TARGET1 | |||
90 | : MCSymbolRefExpr::VK_None), | |||
91 | OutContext); | |||
92 | ||||
93 | OutStreamer->EmitValue(E, Size); | |||
94 | } | |||
95 | ||||
96 | void ARMAsmPrinter::EmitGlobalVariable(const GlobalVariable *GV) { | |||
97 | if (PromotedGlobals.count(GV)) | |||
98 | // The global was promoted into a constant pool. It should not be emitted. | |||
99 | return; | |||
100 | AsmPrinter::EmitGlobalVariable(GV); | |||
101 | } | |||
102 | ||||
103 | /// runOnMachineFunction - This uses the EmitInstruction() | |||
104 | /// method to print assembly for each instruction. | |||
105 | /// | |||
106 | bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { | |||
107 | AFI = MF.getInfo<ARMFunctionInfo>(); | |||
108 | MCP = MF.getConstantPool(); | |||
109 | Subtarget = &MF.getSubtarget<ARMSubtarget>(); | |||
110 | ||||
111 | SetupMachineFunction(MF); | |||
112 | const Function &F = MF.getFunction(); | |||
113 | const TargetMachine& TM = MF.getTarget(); | |||
114 | ||||
115 | // Collect all globals that had their storage promoted to a constant pool. | |||
116 | // Functions are emitted before variables, so this accumulates promoted | |||
117 | // globals from all functions in PromotedGlobals. | |||
118 | for (auto *GV : AFI->getGlobalsPromotedToConstantPool()) | |||
119 | PromotedGlobals.insert(GV); | |||
120 | ||||
121 | // Calculate this function's optimization goal. | |||
122 | unsigned OptimizationGoal; | |||
123 | if (F.hasFnAttribute(Attribute::OptimizeNone)) | |||
124 | // For best debugging illusion, speed and small size sacrificed | |||
125 | OptimizationGoal = 6; | |||
126 | else if (F.optForMinSize()) | |||
127 | // Aggressively for small size, speed and debug illusion sacrificed | |||
128 | OptimizationGoal = 4; | |||
129 | else if (F.optForSize()) | |||
130 | // For small size, but speed and debugging illusion preserved | |||
131 | OptimizationGoal = 3; | |||
132 | else if (TM.getOptLevel() == CodeGenOpt::Aggressive) | |||
133 | // Aggressively for speed, small size and debug illusion sacrificed | |||
134 | OptimizationGoal = 2; | |||
135 | else if (TM.getOptLevel() > CodeGenOpt::None) | |||
136 | // For speed, but small size and good debug illusion preserved | |||
137 | OptimizationGoal = 1; | |||
138 | else // TM.getOptLevel() == CodeGenOpt::None | |||
139 | // For good debugging, but speed and small size preserved | |||
140 | OptimizationGoal = 5; | |||
141 | ||||
142 | // Combine a new optimization goal with existing ones. | |||
143 | if (OptimizationGoals == -1) // uninitialized goals | |||
144 | OptimizationGoals = OptimizationGoal; | |||
145 | else if (OptimizationGoals != (int)OptimizationGoal) // conflicting goals | |||
146 | OptimizationGoals = 0; | |||
147 | ||||
148 | if (Subtarget->isTargetCOFF()) { | |||
149 | bool Internal = F.hasInternalLinkage(); | |||
150 | COFF::SymbolStorageClass Scl = Internal ? COFF::IMAGE_SYM_CLASS_STATIC | |||
151 | : COFF::IMAGE_SYM_CLASS_EXTERNAL; | |||
152 | int Type = COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT; | |||
153 | ||||
154 | OutStreamer->BeginCOFFSymbolDef(CurrentFnSym); | |||
155 | OutStreamer->EmitCOFFSymbolStorageClass(Scl); | |||
156 | OutStreamer->EmitCOFFSymbolType(Type); | |||
157 | OutStreamer->EndCOFFSymbolDef(); | |||
158 | } | |||
159 | ||||
160 | // Emit the rest of the function body. | |||
161 | EmitFunctionBody(); | |||
162 | ||||
163 | // Emit the XRay table for this function. | |||
164 | emitXRayTable(); | |||
165 | ||||
166 | // If we need V4T thumb mode Register Indirect Jump pads, emit them. | |||
167 | // These are created per function, rather than per TU, since it's | |||
168 | // relatively easy to exceed the thumb branch range within a TU. | |||
169 | if (! ThumbIndirectPads.empty()) { | |||
170 | OutStreamer->EmitAssemblerFlag(MCAF_Code16); | |||
171 | EmitAlignment(1); | |||
172 | for (std::pair<unsigned, MCSymbol *> &TIP : ThumbIndirectPads) { | |||
173 | OutStreamer->EmitLabel(TIP.second); | |||
174 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBX) | |||
175 | .addReg(TIP.first) | |||
176 | // Add predicate operands. | |||
177 | .addImm(ARMCC::AL) | |||
178 | .addReg(0)); | |||
179 | } | |||
180 | ThumbIndirectPads.clear(); | |||
181 | } | |||
182 | ||||
183 | // We didn't modify anything. | |||
184 | return false; | |||
185 | } | |||
186 | ||||
187 | void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, | |||
188 | raw_ostream &O) { | |||
189 | const MachineOperand &MO = MI->getOperand(OpNum); | |||
190 | unsigned TF = MO.getTargetFlags(); | |||
191 | ||||
192 | switch (MO.getType()) { | |||
193 | default: llvm_unreachable("<unknown operand type>")::llvm::llvm_unreachable_internal("<unknown operand type>" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 193); | |||
194 | case MachineOperand::MO_Register: { | |||
195 | unsigned Reg = MO.getReg(); | |||
196 | assert(TargetRegisterInfo::isPhysicalRegister(Reg))(static_cast <bool> (TargetRegisterInfo::isPhysicalRegister (Reg)) ? void (0) : __assert_fail ("TargetRegisterInfo::isPhysicalRegister(Reg)" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 196, __extension__ __PRETTY_FUNCTION__)); | |||
197 | assert(!MO.getSubReg() && "Subregs should be eliminated!")(static_cast <bool> (!MO.getSubReg() && "Subregs should be eliminated!" ) ? void (0) : __assert_fail ("!MO.getSubReg() && \"Subregs should be eliminated!\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 197, __extension__ __PRETTY_FUNCTION__)); | |||
198 | if(ARM::GPRPairRegClass.contains(Reg)) { | |||
199 | const MachineFunction &MF = *MI->getParent()->getParent(); | |||
200 | const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); | |||
201 | Reg = TRI->getSubReg(Reg, ARM::gsub_0); | |||
202 | } | |||
203 | O << ARMInstPrinter::getRegisterName(Reg); | |||
204 | break; | |||
205 | } | |||
206 | case MachineOperand::MO_Immediate: { | |||
207 | int64_t Imm = MO.getImm(); | |||
208 | O << '#'; | |||
209 | if (TF == ARMII::MO_LO16) | |||
210 | O << ":lower16:"; | |||
211 | else if (TF == ARMII::MO_HI16) | |||
212 | O << ":upper16:"; | |||
213 | O << Imm; | |||
214 | break; | |||
215 | } | |||
216 | case MachineOperand::MO_MachineBasicBlock: | |||
217 | MO.getMBB()->getSymbol()->print(O, MAI); | |||
218 | return; | |||
219 | case MachineOperand::MO_GlobalAddress: { | |||
220 | const GlobalValue *GV = MO.getGlobal(); | |||
221 | if (TF & ARMII::MO_LO16) | |||
222 | O << ":lower16:"; | |||
223 | else if (TF & ARMII::MO_HI16) | |||
224 | O << ":upper16:"; | |||
225 | GetARMGVSymbol(GV, TF)->print(O, MAI); | |||
226 | ||||
227 | printOffset(MO.getOffset(), O); | |||
228 | break; | |||
229 | } | |||
230 | case MachineOperand::MO_ConstantPoolIndex: | |||
231 | if (Subtarget->genExecuteOnly()) | |||
232 | llvm_unreachable("execute-only should not generate constant pools")::llvm::llvm_unreachable_internal("execute-only should not generate constant pools" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 232); | |||
233 | GetCPISymbol(MO.getIndex())->print(O, MAI); | |||
234 | break; | |||
235 | } | |||
236 | } | |||
237 | ||||
238 | MCSymbol *ARMAsmPrinter::GetCPISymbol(unsigned CPID) const { | |||
239 | // The AsmPrinter::GetCPISymbol superclass method tries to use CPID as | |||
240 | // indexes in MachineConstantPool, which isn't in sync with indexes used here. | |||
241 | const DataLayout &DL = getDataLayout(); | |||
242 | return OutContext.getOrCreateSymbol(Twine(DL.getPrivateGlobalPrefix()) + | |||
243 | "CPI" + Twine(getFunctionNumber()) + "_" + | |||
244 | Twine(CPID)); | |||
245 | } | |||
246 | ||||
247 | //===--------------------------------------------------------------------===// | |||
248 | ||||
249 | MCSymbol *ARMAsmPrinter:: | |||
250 | GetARMJTIPICJumpTableLabel(unsigned uid) const { | |||
251 | const DataLayout &DL = getDataLayout(); | |||
252 | SmallString<60> Name; | |||
253 | raw_svector_ostream(Name) << DL.getPrivateGlobalPrefix() << "JTI" | |||
254 | << getFunctionNumber() << '_' << uid; | |||
255 | return OutContext.getOrCreateSymbol(Name); | |||
256 | } | |||
257 | ||||
258 | bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, | |||
259 | unsigned AsmVariant, const char *ExtraCode, | |||
260 | raw_ostream &O) { | |||
261 | // Does this asm operand have a single letter operand modifier? | |||
262 | if (ExtraCode && ExtraCode[0]) { | |||
| ||||
263 | if (ExtraCode[1] != 0) return true; // Unknown modifier. | |||
264 | ||||
265 | switch (ExtraCode[0]) { | |||
266 | default: | |||
267 | // See if this is a generic print operand | |||
268 | return AsmPrinter::PrintAsmOperand(MI, OpNum, AsmVariant, ExtraCode, O); | |||
269 | case 'a': // Print as a memory address. | |||
270 | if (MI->getOperand(OpNum).isReg()) { | |||
271 | O << "[" | |||
272 | << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg()) | |||
273 | << "]"; | |||
274 | return false; | |||
275 | } | |||
276 | LLVM_FALLTHROUGH[[clang::fallthrough]]; | |||
277 | case 'c': // Don't print "#" before an immediate operand. | |||
278 | if (!MI->getOperand(OpNum).isImm()) | |||
279 | return true; | |||
280 | O << MI->getOperand(OpNum).getImm(); | |||
281 | return false; | |||
282 | case 'P': // Print a VFP double precision register. | |||
283 | case 'q': // Print a NEON quad precision register. | |||
284 | printOperand(MI, OpNum, O); | |||
285 | return false; | |||
286 | case 'y': // Print a VFP single precision register as indexed double. | |||
287 | if (MI->getOperand(OpNum).isReg()) { | |||
288 | unsigned Reg = MI->getOperand(OpNum).getReg(); | |||
289 | const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); | |||
290 | // Find the 'd' register that has this 's' register as a sub-register, | |||
291 | // and determine the lane number. | |||
292 | for (MCSuperRegIterator SR(Reg, TRI); SR.isValid(); ++SR) { | |||
293 | if (!ARM::DPRRegClass.contains(*SR)) | |||
294 | continue; | |||
295 | bool Lane0 = TRI->getSubReg(*SR, ARM::ssub_0) == Reg; | |||
296 | O << ARMInstPrinter::getRegisterName(*SR) << (Lane0 ? "[0]" : "[1]"); | |||
297 | return false; | |||
298 | } | |||
299 | } | |||
300 | return true; | |||
301 | case 'B': // Bitwise inverse of integer or symbol without a preceding #. | |||
302 | if (!MI->getOperand(OpNum).isImm()) | |||
303 | return true; | |||
304 | O << ~(MI->getOperand(OpNum).getImm()); | |||
305 | return false; | |||
306 | case 'L': // The low 16 bits of an immediate constant. | |||
307 | if (!MI->getOperand(OpNum).isImm()) | |||
308 | return true; | |||
309 | O << (MI->getOperand(OpNum).getImm() & 0xffff); | |||
310 | return false; | |||
311 | case 'M': { // A register range suitable for LDM/STM. | |||
312 | if (!MI->getOperand(OpNum).isReg()) | |||
313 | return true; | |||
314 | const MachineOperand &MO = MI->getOperand(OpNum); | |||
315 | unsigned RegBegin = MO.getReg(); | |||
316 | // This takes advantage of the 2 operand-ness of ldm/stm and that we've | |||
317 | // already got the operands in registers that are operands to the | |||
318 | // inline asm statement. | |||
319 | O << "{"; | |||
320 | if (ARM::GPRPairRegClass.contains(RegBegin)) { | |||
321 | const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); | |||
322 | unsigned Reg0 = TRI->getSubReg(RegBegin, ARM::gsub_0); | |||
323 | O << ARMInstPrinter::getRegisterName(Reg0) << ", "; | |||
324 | RegBegin = TRI->getSubReg(RegBegin, ARM::gsub_1); | |||
325 | } | |||
326 | O << ARMInstPrinter::getRegisterName(RegBegin); | |||
327 | ||||
328 | // FIXME: The register allocator not only may not have given us the | |||
329 | // registers in sequence, but may not be in ascending registers. This | |||
330 | // will require changes in the register allocator that'll need to be | |||
331 | // propagated down here if the operands change. | |||
332 | unsigned RegOps = OpNum + 1; | |||
333 | while (MI->getOperand(RegOps).isReg()) { | |||
334 | O << ", " | |||
335 | << ARMInstPrinter::getRegisterName(MI->getOperand(RegOps).getReg()); | |||
336 | RegOps++; | |||
337 | } | |||
338 | ||||
339 | O << "}"; | |||
340 | ||||
341 | return false; | |||
342 | } | |||
343 | case 'R': // The most significant register of a pair. | |||
344 | case 'Q': { // The least significant register of a pair. | |||
345 | if (OpNum == 0) | |||
346 | return true; | |||
347 | const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1); | |||
348 | if (!FlagsOP.isImm()) | |||
349 | return true; | |||
350 | unsigned Flags = FlagsOP.getImm(); | |||
351 | ||||
352 | // This operand may not be the one that actually provides the register. If | |||
353 | // it's tied to a previous one then we should refer instead to that one | |||
354 | // for registers and their classes. | |||
355 | unsigned TiedIdx; | |||
356 | if (InlineAsm::isUseOperandTiedToDef(Flags, TiedIdx)) { | |||
357 | for (OpNum = InlineAsm::MIOp_FirstOperand; TiedIdx; --TiedIdx) { | |||
358 | unsigned OpFlags = MI->getOperand(OpNum).getImm(); | |||
359 | OpNum += InlineAsm::getNumOperandRegisters(OpFlags) + 1; | |||
360 | } | |||
361 | Flags = MI->getOperand(OpNum).getImm(); | |||
362 | ||||
363 | // Later code expects OpNum to be pointing at the register rather than | |||
364 | // the flags. | |||
365 | OpNum += 1; | |||
366 | } | |||
367 | ||||
368 | unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags); | |||
369 | unsigned RC; | |||
370 | InlineAsm::hasRegClassConstraint(Flags, RC); | |||
371 | if (RC == ARM::GPRPairRegClassID) { | |||
| ||||
372 | if (NumVals != 1) | |||
373 | return true; | |||
374 | const MachineOperand &MO = MI->getOperand(OpNum); | |||
375 | if (!MO.isReg()) | |||
376 | return true; | |||
377 | const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); | |||
378 | unsigned Reg = TRI->getSubReg(MO.getReg(), ExtraCode[0] == 'Q' ? | |||
379 | ARM::gsub_0 : ARM::gsub_1); | |||
380 | O << ARMInstPrinter::getRegisterName(Reg); | |||
381 | return false; | |||
382 | } | |||
383 | if (NumVals != 2) | |||
384 | return true; | |||
385 | unsigned RegOp = ExtraCode[0] == 'Q' ? OpNum : OpNum + 1; | |||
386 | if (RegOp >= MI->getNumOperands()) | |||
387 | return true; | |||
388 | const MachineOperand &MO = MI->getOperand(RegOp); | |||
389 | if (!MO.isReg()) | |||
390 | return true; | |||
391 | unsigned Reg = MO.getReg(); | |||
392 | O << ARMInstPrinter::getRegisterName(Reg); | |||
393 | return false; | |||
394 | } | |||
395 | ||||
396 | case 'e': // The low doubleword register of a NEON quad register. | |||
397 | case 'f': { // The high doubleword register of a NEON quad register. | |||
398 | if (!MI->getOperand(OpNum).isReg()) | |||
399 | return true; | |||
400 | unsigned Reg = MI->getOperand(OpNum).getReg(); | |||
401 | if (!ARM::QPRRegClass.contains(Reg)) | |||
402 | return true; | |||
403 | const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); | |||
404 | unsigned SubReg = TRI->getSubReg(Reg, ExtraCode[0] == 'e' ? | |||
405 | ARM::dsub_0 : ARM::dsub_1); | |||
406 | O << ARMInstPrinter::getRegisterName(SubReg); | |||
407 | return false; | |||
408 | } | |||
409 | ||||
410 | // This modifier is not yet supported. | |||
411 | case 'h': // A range of VFP/NEON registers suitable for VLD1/VST1. | |||
412 | return true; | |||
413 | case 'H': { // The highest-numbered register of a pair. | |||
414 | const MachineOperand &MO = MI->getOperand(OpNum); | |||
415 | if (!MO.isReg()) | |||
416 | return true; | |||
417 | const MachineFunction &MF = *MI->getParent()->getParent(); | |||
418 | const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); | |||
419 | unsigned Reg = MO.getReg(); | |||
420 | if(!ARM::GPRPairRegClass.contains(Reg)) | |||
421 | return false; | |||
422 | Reg = TRI->getSubReg(Reg, ARM::gsub_1); | |||
423 | O << ARMInstPrinter::getRegisterName(Reg); | |||
424 | return false; | |||
425 | } | |||
426 | } | |||
427 | } | |||
428 | ||||
429 | printOperand(MI, OpNum, O); | |||
430 | return false; | |||
431 | } | |||
432 | ||||
433 | bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, | |||
434 | unsigned OpNum, unsigned AsmVariant, | |||
435 | const char *ExtraCode, | |||
436 | raw_ostream &O) { | |||
437 | // Does this asm operand have a single letter operand modifier? | |||
438 | if (ExtraCode && ExtraCode[0]) { | |||
439 | if (ExtraCode[1] != 0) return true; // Unknown modifier. | |||
440 | ||||
441 | switch (ExtraCode[0]) { | |||
442 | case 'A': // A memory operand for a VLD1/VST1 instruction. | |||
443 | default: return true; // Unknown modifier. | |||
444 | case 'm': // The base register of a memory operand. | |||
445 | if (!MI->getOperand(OpNum).isReg()) | |||
446 | return true; | |||
447 | O << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg()); | |||
448 | return false; | |||
449 | } | |||
450 | } | |||
451 | ||||
452 | const MachineOperand &MO = MI->getOperand(OpNum); | |||
453 | assert(MO.isReg() && "unexpected inline asm memory operand")(static_cast <bool> (MO.isReg() && "unexpected inline asm memory operand" ) ? void (0) : __assert_fail ("MO.isReg() && \"unexpected inline asm memory operand\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 453, __extension__ __PRETTY_FUNCTION__)); | |||
454 | O << "[" << ARMInstPrinter::getRegisterName(MO.getReg()) << "]"; | |||
455 | return false; | |||
456 | } | |||
457 | ||||
458 | static bool isThumb(const MCSubtargetInfo& STI) { | |||
459 | return STI.getFeatureBits()[ARM::ModeThumb]; | |||
460 | } | |||
461 | ||||
462 | void ARMAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, | |||
463 | const MCSubtargetInfo *EndInfo) const { | |||
464 | // If either end mode is unknown (EndInfo == NULL) or different than | |||
465 | // the start mode, then restore the start mode. | |||
466 | const bool WasThumb = isThumb(StartInfo); | |||
467 | if (!EndInfo || WasThumb != isThumb(*EndInfo)) { | |||
468 | OutStreamer->EmitAssemblerFlag(WasThumb ? MCAF_Code16 : MCAF_Code32); | |||
469 | } | |||
470 | } | |||
471 | ||||
472 | void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) { | |||
473 | const Triple &TT = TM.getTargetTriple(); | |||
474 | // Use unified assembler syntax. | |||
475 | OutStreamer->EmitAssemblerFlag(MCAF_SyntaxUnified); | |||
476 | ||||
477 | // Emit ARM Build Attributes | |||
478 | if (TT.isOSBinFormatELF()) | |||
479 | emitAttributes(); | |||
480 | ||||
481 | // Use the triple's architecture and subarchitecture to determine | |||
482 | // if we're thumb for the purposes of the top level code16 assembler | |||
483 | // flag. | |||
484 | if (!M.getModuleInlineAsm().empty() && TT.isThumb()) | |||
485 | OutStreamer->EmitAssemblerFlag(MCAF_Code16); | |||
486 | } | |||
487 | ||||
488 | static void | |||
489 | emitNonLazySymbolPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel, | |||
490 | MachineModuleInfoImpl::StubValueTy &MCSym) { | |||
491 | // L_foo$stub: | |||
492 | OutStreamer.EmitLabel(StubLabel); | |||
493 | // .indirect_symbol _foo | |||
494 | OutStreamer.EmitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol); | |||
495 | ||||
496 | if (MCSym.getInt()) | |||
497 | // External to current translation unit. | |||
498 | OutStreamer.EmitIntValue(0, 4/*size*/); | |||
499 | else | |||
500 | // Internal to current translation unit. | |||
501 | // | |||
502 | // When we place the LSDA into the TEXT section, the type info | |||
503 | // pointers need to be indirect and pc-rel. We accomplish this by | |||
504 | // using NLPs; however, sometimes the types are local to the file. | |||
505 | // We need to fill in the value for the NLP in those cases. | |||
506 | OutStreamer.EmitValue( | |||
507 | MCSymbolRefExpr::create(MCSym.getPointer(), OutStreamer.getContext()), | |||
508 | 4 /*size*/); | |||
509 | } | |||
510 | ||||
511 | ||||
512 | void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { | |||
513 | const Triple &TT = TM.getTargetTriple(); | |||
514 | if (TT.isOSBinFormatMachO()) { | |||
515 | // All darwin targets use mach-o. | |||
516 | const TargetLoweringObjectFileMachO &TLOFMacho = | |||
517 | static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); | |||
518 | MachineModuleInfoMachO &MMIMacho = | |||
519 | MMI->getObjFileInfo<MachineModuleInfoMachO>(); | |||
520 | ||||
521 | // Output non-lazy-pointers for external and common global variables. | |||
522 | MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList(); | |||
523 | ||||
524 | if (!Stubs.empty()) { | |||
525 | // Switch with ".non_lazy_symbol_pointer" directive. | |||
526 | OutStreamer->SwitchSection(TLOFMacho.getNonLazySymbolPointerSection()); | |||
527 | EmitAlignment(2); | |||
528 | ||||
529 | for (auto &Stub : Stubs) | |||
530 | emitNonLazySymbolPointer(*OutStreamer, Stub.first, Stub.second); | |||
531 | ||||
532 | Stubs.clear(); | |||
533 | OutStreamer->AddBlankLine(); | |||
534 | } | |||
535 | ||||
536 | Stubs = MMIMacho.GetThreadLocalGVStubList(); | |||
537 | if (!Stubs.empty()) { | |||
538 | // Switch with ".non_lazy_symbol_pointer" directive. | |||
539 | OutStreamer->SwitchSection(TLOFMacho.getThreadLocalPointerSection()); | |||
540 | EmitAlignment(2); | |||
541 | ||||
542 | for (auto &Stub : Stubs) | |||
543 | emitNonLazySymbolPointer(*OutStreamer, Stub.first, Stub.second); | |||
544 | ||||
545 | Stubs.clear(); | |||
546 | OutStreamer->AddBlankLine(); | |||
547 | } | |||
548 | ||||
549 | // Funny Darwin hack: This flag tells the linker that no global symbols | |||
550 | // contain code that falls through to other global symbols (e.g. the obvious | |||
551 | // implementation of multiple entry points). If this doesn't occur, the | |||
552 | // linker can safely perform dead code stripping. Since LLVM never | |||
553 | // generates code that does this, it is always safe to set. | |||
554 | OutStreamer->EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); | |||
555 | } | |||
556 | ||||
557 | // The last attribute to be emitted is ABI_optimization_goals | |||
558 | MCTargetStreamer &TS = *OutStreamer->getTargetStreamer(); | |||
559 | ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS); | |||
560 | ||||
561 | if (OptimizationGoals > 0 && | |||
562 | (Subtarget->isTargetAEABI() || Subtarget->isTargetGNUAEABI() || | |||
563 | Subtarget->isTargetMuslAEABI())) | |||
564 | ATS.emitAttribute(ARMBuildAttrs::ABI_optimization_goals, OptimizationGoals); | |||
565 | OptimizationGoals = -1; | |||
566 | ||||
567 | ATS.finishAttributeSection(); | |||
568 | } | |||
569 | ||||
570 | //===----------------------------------------------------------------------===// | |||
571 | // Helper routines for EmitStartOfAsmFile() and EmitEndOfAsmFile() | |||
572 | // FIXME: | |||
573 | // The following seem like one-off assembler flags, but they actually need | |||
574 | // to appear in the .ARM.attributes section in ELF. | |||
575 | // Instead of subclassing the MCELFStreamer, we do the work here. | |||
576 | ||||
577 | // Returns true if all functions have the same function attribute value. | |||
578 | // It also returns true when the module has no functions. | |||
579 | static bool checkFunctionsAttributeConsistency(const Module &M, StringRef Attr, | |||
580 | StringRef Value) { | |||
581 | return !any_of(M, [&](const Function &F) { | |||
582 | return F.getFnAttribute(Attr).getValueAsString() != Value; | |||
583 | }); | |||
584 | } | |||
585 | ||||
586 | void ARMAsmPrinter::emitAttributes() { | |||
587 | MCTargetStreamer &TS = *OutStreamer->getTargetStreamer(); | |||
588 | ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS); | |||
589 | ||||
590 | ATS.emitTextAttribute(ARMBuildAttrs::conformance, "2.09"); | |||
591 | ||||
592 | ATS.switchVendor("aeabi"); | |||
593 | ||||
594 | // Compute ARM ELF Attributes based on the default subtarget that | |||
595 | // we'd have constructed. The existing ARM behavior isn't LTO clean | |||
596 | // anyhow. | |||
597 | // FIXME: For ifunc related functions we could iterate over and look | |||
598 | // for a feature string that doesn't match the default one. | |||
599 | const Triple &TT = TM.getTargetTriple(); | |||
600 | StringRef CPU = TM.getTargetCPU(); | |||
601 | StringRef FS = TM.getTargetFeatureString(); | |||
602 | std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU); | |||
603 | if (!FS.empty()) { | |||
604 | if (!ArchFS.empty()) | |||
605 | ArchFS = (Twine(ArchFS) + "," + FS).str(); | |||
606 | else | |||
607 | ArchFS = FS; | |||
608 | } | |||
609 | const ARMBaseTargetMachine &ATM = | |||
610 | static_cast<const ARMBaseTargetMachine &>(TM); | |||
611 | const ARMSubtarget STI(TT, CPU, ArchFS, ATM, ATM.isLittleEndian()); | |||
612 | ||||
613 | // Emit build attributes for the available hardware. | |||
614 | ATS.emitTargetAttributes(STI); | |||
615 | ||||
616 | // RW data addressing. | |||
617 | if (isPositionIndependent()) { | |||
618 | ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_RW_data, | |||
619 | ARMBuildAttrs::AddressRWPCRel); | |||
620 | } else if (STI.isRWPI()) { | |||
621 | // RWPI specific attributes. | |||
622 | ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_RW_data, | |||
623 | ARMBuildAttrs::AddressRWSBRel); | |||
624 | } | |||
625 | ||||
626 | // RO data addressing. | |||
627 | if (isPositionIndependent() || STI.isROPI()) { | |||
628 | ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_RO_data, | |||
629 | ARMBuildAttrs::AddressROPCRel); | |||
630 | } | |||
631 | ||||
632 | // GOT use. | |||
633 | if (isPositionIndependent()) { | |||
634 | ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_GOT_use, | |||
635 | ARMBuildAttrs::AddressGOT); | |||
636 | } else { | |||
637 | ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_GOT_use, | |||
638 | ARMBuildAttrs::AddressDirect); | |||
639 | } | |||
640 | ||||
641 | // Set FP Denormals. | |||
642 | if (checkFunctionsAttributeConsistency(*MMI->getModule(), | |||
643 | "denormal-fp-math", | |||
644 | "preserve-sign") || | |||
645 | TM.Options.FPDenormalMode == FPDenormal::PreserveSign) | |||
646 | ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, | |||
647 | ARMBuildAttrs::PreserveFPSign); | |||
648 | else if (checkFunctionsAttributeConsistency(*MMI->getModule(), | |||
649 | "denormal-fp-math", | |||
650 | "positive-zero") || | |||
651 | TM.Options.FPDenormalMode == FPDenormal::PositiveZero) | |||
652 | ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, | |||
653 | ARMBuildAttrs::PositiveZero); | |||
654 | else if (!TM.Options.UnsafeFPMath) | |||
655 | ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, | |||
656 | ARMBuildAttrs::IEEEDenormals); | |||
657 | else { | |||
658 | if (!STI.hasVFP2()) { | |||
659 | // When the target doesn't have an FPU (by design or | |||
660 | // intention), the assumptions made on the software support | |||
661 | // mirror that of the equivalent hardware support *if it | |||
662 | // existed*. For v7 and better we indicate that denormals are | |||
663 | // flushed preserving sign, and for V6 we indicate that | |||
664 | // denormals are flushed to positive zero. | |||
665 | if (STI.hasV7Ops()) | |||
666 | ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, | |||
667 | ARMBuildAttrs::PreserveFPSign); | |||
668 | } else if (STI.hasVFP3()) { | |||
669 | // In VFPv4, VFPv4U, VFPv3, or VFPv3U, it is preserved. That is, | |||
670 | // the sign bit of the zero matches the sign bit of the input or | |||
671 | // result that is being flushed to zero. | |||
672 | ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, | |||
673 | ARMBuildAttrs::PreserveFPSign); | |||
674 | } | |||
675 | // For VFPv2 implementations it is implementation defined as | |||
676 | // to whether denormals are flushed to positive zero or to | |||
677 | // whatever the sign of zero is (ARM v7AR ARM 2.7.5). Historically | |||
678 | // LLVM has chosen to flush this to positive zero (most likely for | |||
679 | // GCC compatibility), so that's the chosen value here (the | |||
680 | // absence of its emission implies zero). | |||
681 | } | |||
682 | ||||
683 | // Set FP exceptions and rounding | |||
684 | if (checkFunctionsAttributeConsistency(*MMI->getModule(), | |||
685 | "no-trapping-math", "true") || | |||
686 | TM.Options.NoTrappingFPMath) | |||
687 | ATS.emitAttribute(ARMBuildAttrs::ABI_FP_exceptions, | |||
688 | ARMBuildAttrs::Not_Allowed); | |||
689 | else if (!TM.Options.UnsafeFPMath) { | |||
690 | ATS.emitAttribute(ARMBuildAttrs::ABI_FP_exceptions, ARMBuildAttrs::Allowed); | |||
691 | ||||
692 | // If the user has permitted this code to choose the IEEE 754 | |||
693 | // rounding at run-time, emit the rounding attribute. | |||
694 | if (TM.Options.HonorSignDependentRoundingFPMathOption) | |||
695 | ATS.emitAttribute(ARMBuildAttrs::ABI_FP_rounding, ARMBuildAttrs::Allowed); | |||
696 | } | |||
697 | ||||
698 | // TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath is the | |||
699 | // equivalent of GCC's -ffinite-math-only flag. | |||
700 | if (TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath) | |||
701 | ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model, | |||
702 | ARMBuildAttrs::Allowed); | |||
703 | else | |||
704 | ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model, | |||
705 | ARMBuildAttrs::AllowIEEE754); | |||
706 | ||||
707 | // FIXME: add more flags to ARMBuildAttributes.h | |||
708 | // 8-bytes alignment stuff. | |||
709 | ATS.emitAttribute(ARMBuildAttrs::ABI_align_needed, 1); | |||
710 | ATS.emitAttribute(ARMBuildAttrs::ABI_align_preserved, 1); | |||
711 | ||||
712 | // Hard float. Use both S and D registers and conform to AAPCS-VFP. | |||
713 | if (STI.isAAPCS_ABI() && TM.Options.FloatABIType == FloatABI::Hard) | |||
714 | ATS.emitAttribute(ARMBuildAttrs::ABI_VFP_args, ARMBuildAttrs::HardFPAAPCS); | |||
715 | ||||
716 | // FIXME: To support emitting this build attribute as GCC does, the | |||
717 | // -mfp16-format option and associated plumbing must be | |||
718 | // supported. For now the __fp16 type is exposed by default, so this | |||
719 | // attribute should be emitted with value 1. | |||
720 | ATS.emitAttribute(ARMBuildAttrs::ABI_FP_16bit_format, | |||
721 | ARMBuildAttrs::FP16FormatIEEE); | |||
722 | ||||
723 | if (MMI) { | |||
724 | if (const Module *SourceModule = MMI->getModule()) { | |||
725 | // ABI_PCS_wchar_t to indicate wchar_t width | |||
726 | // FIXME: There is no way to emit value 0 (wchar_t prohibited). | |||
727 | if (auto WCharWidthValue = mdconst::extract_or_null<ConstantInt>( | |||
728 | SourceModule->getModuleFlag("wchar_size"))) { | |||
729 | int WCharWidth = WCharWidthValue->getZExtValue(); | |||
730 | assert((WCharWidth == 2 || WCharWidth == 4) &&(static_cast <bool> ((WCharWidth == 2 || WCharWidth == 4 ) && "wchar_t width must be 2 or 4 bytes") ? void (0) : __assert_fail ("(WCharWidth == 2 || WCharWidth == 4) && \"wchar_t width must be 2 or 4 bytes\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 731, __extension__ __PRETTY_FUNCTION__)) | |||
731 | "wchar_t width must be 2 or 4 bytes")(static_cast <bool> ((WCharWidth == 2 || WCharWidth == 4 ) && "wchar_t width must be 2 or 4 bytes") ? void (0) : __assert_fail ("(WCharWidth == 2 || WCharWidth == 4) && \"wchar_t width must be 2 or 4 bytes\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 731, __extension__ __PRETTY_FUNCTION__)); | |||
732 | ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_wchar_t, WCharWidth); | |||
733 | } | |||
734 | ||||
735 | // ABI_enum_size to indicate enum width | |||
736 | // FIXME: There is no way to emit value 0 (enums prohibited) or value 3 | |||
737 | // (all enums contain a value needing 32 bits to encode). | |||
738 | if (auto EnumWidthValue = mdconst::extract_or_null<ConstantInt>( | |||
739 | SourceModule->getModuleFlag("min_enum_size"))) { | |||
740 | int EnumWidth = EnumWidthValue->getZExtValue(); | |||
741 | assert((EnumWidth == 1 || EnumWidth == 4) &&(static_cast <bool> ((EnumWidth == 1 || EnumWidth == 4) && "Minimum enum width must be 1 or 4 bytes") ? void (0) : __assert_fail ("(EnumWidth == 1 || EnumWidth == 4) && \"Minimum enum width must be 1 or 4 bytes\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 742, __extension__ __PRETTY_FUNCTION__)) | |||
742 | "Minimum enum width must be 1 or 4 bytes")(static_cast <bool> ((EnumWidth == 1 || EnumWidth == 4) && "Minimum enum width must be 1 or 4 bytes") ? void (0) : __assert_fail ("(EnumWidth == 1 || EnumWidth == 4) && \"Minimum enum width must be 1 or 4 bytes\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 742, __extension__ __PRETTY_FUNCTION__)); | |||
743 | int EnumBuildAttr = EnumWidth == 1 ? 1 : 2; | |||
744 | ATS.emitAttribute(ARMBuildAttrs::ABI_enum_size, EnumBuildAttr); | |||
745 | } | |||
746 | } | |||
747 | } | |||
748 | ||||
749 | // We currently do not support using R9 as the TLS pointer. | |||
750 | if (STI.isRWPI()) | |||
751 | ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use, | |||
752 | ARMBuildAttrs::R9IsSB); | |||
753 | else if (STI.isR9Reserved()) | |||
754 | ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use, | |||
755 | ARMBuildAttrs::R9Reserved); | |||
756 | else | |||
757 | ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use, | |||
758 | ARMBuildAttrs::R9IsGPR); | |||
759 | } | |||
760 | ||||
761 | //===----------------------------------------------------------------------===// | |||
762 | ||||
763 | static MCSymbol *getPICLabel(StringRef Prefix, unsigned FunctionNumber, | |||
764 | unsigned LabelId, MCContext &Ctx) { | |||
765 | ||||
766 | MCSymbol *Label = Ctx.getOrCreateSymbol(Twine(Prefix) | |||
767 | + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId)); | |||
768 | return Label; | |||
769 | } | |||
770 | ||||
771 | static MCSymbolRefExpr::VariantKind | |||
772 | getModifierVariantKind(ARMCP::ARMCPModifier Modifier) { | |||
773 | switch (Modifier) { | |||
774 | case ARMCP::no_modifier: | |||
775 | return MCSymbolRefExpr::VK_None; | |||
776 | case ARMCP::TLSGD: | |||
777 | return MCSymbolRefExpr::VK_TLSGD; | |||
778 | case ARMCP::TPOFF: | |||
779 | return MCSymbolRefExpr::VK_TPOFF; | |||
780 | case ARMCP::GOTTPOFF: | |||
781 | return MCSymbolRefExpr::VK_GOTTPOFF; | |||
782 | case ARMCP::SBREL: | |||
783 | return MCSymbolRefExpr::VK_ARM_SBREL; | |||
784 | case ARMCP::GOT_PREL: | |||
785 | return MCSymbolRefExpr::VK_ARM_GOT_PREL; | |||
786 | case ARMCP::SECREL: | |||
787 | return MCSymbolRefExpr::VK_SECREL; | |||
788 | } | |||
789 | llvm_unreachable("Invalid ARMCPModifier!")::llvm::llvm_unreachable_internal("Invalid ARMCPModifier!", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 789); | |||
790 | } | |||
791 | ||||
792 | MCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV, | |||
793 | unsigned char TargetFlags) { | |||
794 | if (Subtarget->isTargetMachO()) { | |||
795 | bool IsIndirect = | |||
796 | (TargetFlags & ARMII::MO_NONLAZY) && Subtarget->isGVIndirectSymbol(GV); | |||
797 | ||||
798 | if (!IsIndirect) | |||
799 | return getSymbol(GV); | |||
800 | ||||
801 | // FIXME: Remove this when Darwin transition to @GOT like syntax. | |||
802 | MCSymbol *MCSym = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); | |||
803 | MachineModuleInfoMachO &MMIMachO = | |||
804 | MMI->getObjFileInfo<MachineModuleInfoMachO>(); | |||
805 | MachineModuleInfoImpl::StubValueTy &StubSym = | |||
806 | GV->isThreadLocal() ? MMIMachO.getThreadLocalGVStubEntry(MCSym) | |||
807 | : MMIMachO.getGVStubEntry(MCSym); | |||
808 | ||||
809 | if (!StubSym.getPointer()) | |||
810 | StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(GV), | |||
811 | !GV->hasInternalLinkage()); | |||
812 | return MCSym; | |||
813 | } else if (Subtarget->isTargetCOFF()) { | |||
814 | assert(Subtarget->isTargetWindows() &&(static_cast <bool> (Subtarget->isTargetWindows() && "Windows is the only supported COFF target") ? void (0) : __assert_fail ("Subtarget->isTargetWindows() && \"Windows is the only supported COFF target\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 815, __extension__ __PRETTY_FUNCTION__)) | |||
815 | "Windows is the only supported COFF target")(static_cast <bool> (Subtarget->isTargetWindows() && "Windows is the only supported COFF target") ? void (0) : __assert_fail ("Subtarget->isTargetWindows() && \"Windows is the only supported COFF target\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 815, __extension__ __PRETTY_FUNCTION__)); | |||
816 | ||||
817 | bool IsIndirect = (TargetFlags & ARMII::MO_DLLIMPORT); | |||
818 | if (!IsIndirect) | |||
819 | return getSymbol(GV); | |||
820 | ||||
821 | SmallString<128> Name; | |||
822 | Name = "__imp_"; | |||
823 | getNameWithPrefix(Name, GV); | |||
824 | ||||
825 | return OutContext.getOrCreateSymbol(Name); | |||
826 | } else if (Subtarget->isTargetELF()) { | |||
827 | return getSymbol(GV); | |||
828 | } | |||
829 | llvm_unreachable("unexpected target")::llvm::llvm_unreachable_internal("unexpected target", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 829); | |||
830 | } | |||
831 | ||||
832 | void ARMAsmPrinter:: | |||
833 | EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { | |||
834 | const DataLayout &DL = getDataLayout(); | |||
835 | int Size = DL.getTypeAllocSize(MCPV->getType()); | |||
836 | ||||
837 | ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV); | |||
838 | ||||
839 | if (ACPV->isPromotedGlobal()) { | |||
840 | // This constant pool entry is actually a global whose storage has been | |||
841 | // promoted into the constant pool. This global may be referenced still | |||
842 | // by debug information, and due to the way AsmPrinter is set up, the debug | |||
843 | // info is immutable by the time we decide to promote globals to constant | |||
844 | // pools. Because of this, we need to ensure we emit a symbol for the global | |||
845 | // with private linkage (the default) so debug info can refer to it. | |||
846 | // | |||
847 | // However, if this global is promoted into several functions we must ensure | |||
848 | // we don't try and emit duplicate symbols! | |||
849 | auto *ACPC = cast<ARMConstantPoolConstant>(ACPV); | |||
850 | for (const auto *GV : ACPC->promotedGlobals()) { | |||
851 | if (!EmittedPromotedGlobalLabels.count(GV)) { | |||
852 | MCSymbol *GVSym = getSymbol(GV); | |||
853 | OutStreamer->EmitLabel(GVSym); | |||
854 | EmittedPromotedGlobalLabels.insert(GV); | |||
855 | } | |||
856 | } | |||
857 | return EmitGlobalConstant(DL, ACPC->getPromotedGlobalInit()); | |||
858 | } | |||
859 | ||||
860 | MCSymbol *MCSym; | |||
861 | if (ACPV->isLSDA()) { | |||
862 | MCSym = getCurExceptionSym(); | |||
863 | } else if (ACPV->isBlockAddress()) { | |||
864 | const BlockAddress *BA = | |||
865 | cast<ARMConstantPoolConstant>(ACPV)->getBlockAddress(); | |||
866 | MCSym = GetBlockAddressSymbol(BA); | |||
867 | } else if (ACPV->isGlobalValue()) { | |||
868 | const GlobalValue *GV = cast<ARMConstantPoolConstant>(ACPV)->getGV(); | |||
869 | ||||
870 | // On Darwin, const-pool entries may get the "FOO$non_lazy_ptr" mangling, so | |||
871 | // flag the global as MO_NONLAZY. | |||
872 | unsigned char TF = Subtarget->isTargetMachO() ? ARMII::MO_NONLAZY : 0; | |||
873 | MCSym = GetARMGVSymbol(GV, TF); | |||
874 | } else if (ACPV->isMachineBasicBlock()) { | |||
875 | const MachineBasicBlock *MBB = cast<ARMConstantPoolMBB>(ACPV)->getMBB(); | |||
876 | MCSym = MBB->getSymbol(); | |||
877 | } else { | |||
878 | assert(ACPV->isExtSymbol() && "unrecognized constant pool value")(static_cast <bool> (ACPV->isExtSymbol() && "unrecognized constant pool value" ) ? void (0) : __assert_fail ("ACPV->isExtSymbol() && \"unrecognized constant pool value\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 878, __extension__ __PRETTY_FUNCTION__)); | |||
879 | auto Sym = cast<ARMConstantPoolSymbol>(ACPV)->getSymbol(); | |||
880 | MCSym = GetExternalSymbolSymbol(Sym); | |||
881 | } | |||
882 | ||||
883 | // Create an MCSymbol for the reference. | |||
884 | const MCExpr *Expr = | |||
885 | MCSymbolRefExpr::create(MCSym, getModifierVariantKind(ACPV->getModifier()), | |||
886 | OutContext); | |||
887 | ||||
888 | if (ACPV->getPCAdjustment()) { | |||
889 | MCSymbol *PCLabel = | |||
890 | getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(), | |||
891 | ACPV->getLabelId(), OutContext); | |||
892 | const MCExpr *PCRelExpr = MCSymbolRefExpr::create(PCLabel, OutContext); | |||
893 | PCRelExpr = | |||
894 | MCBinaryExpr::createAdd(PCRelExpr, | |||
895 | MCConstantExpr::create(ACPV->getPCAdjustment(), | |||
896 | OutContext), | |||
897 | OutContext); | |||
898 | if (ACPV->mustAddCurrentAddress()) { | |||
899 | // We want "(<expr> - .)", but MC doesn't have a concept of the '.' | |||
900 | // label, so just emit a local label end reference that instead. | |||
901 | MCSymbol *DotSym = OutContext.createTempSymbol(); | |||
902 | OutStreamer->EmitLabel(DotSym); | |||
903 | const MCExpr *DotExpr = MCSymbolRefExpr::create(DotSym, OutContext); | |||
904 | PCRelExpr = MCBinaryExpr::createSub(PCRelExpr, DotExpr, OutContext); | |||
905 | } | |||
906 | Expr = MCBinaryExpr::createSub(Expr, PCRelExpr, OutContext); | |||
907 | } | |||
908 | OutStreamer->EmitValue(Expr, Size); | |||
909 | } | |||
910 | ||||
911 | void ARMAsmPrinter::EmitJumpTableAddrs(const MachineInstr *MI) { | |||
912 | const MachineOperand &MO1 = MI->getOperand(1); | |||
913 | unsigned JTI = MO1.getIndex(); | |||
914 | ||||
915 | // Make sure the Thumb jump table is 4-byte aligned. This will be a nop for | |||
916 | // ARM mode tables. | |||
917 | EmitAlignment(2); | |||
918 | ||||
919 | // Emit a label for the jump table. | |||
920 | MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI); | |||
921 | OutStreamer->EmitLabel(JTISymbol); | |||
922 | ||||
923 | // Mark the jump table as data-in-code. | |||
924 | OutStreamer->EmitDataRegion(MCDR_DataRegionJT32); | |||
925 | ||||
926 | // Emit each entry of the table. | |||
927 | const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); | |||
928 | const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); | |||
929 | const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; | |||
930 | ||||
931 | for (MachineBasicBlock *MBB : JTBBs) { | |||
932 | // Construct an MCExpr for the entry. We want a value of the form: | |||
933 | // (BasicBlockAddr - TableBeginAddr) | |||
934 | // | |||
935 | // For example, a table with entries jumping to basic blocks BB0 and BB1 | |||
936 | // would look like: | |||
937 | // LJTI_0_0: | |||
938 | // .word (LBB0 - LJTI_0_0) | |||
939 | // .word (LBB1 - LJTI_0_0) | |||
940 | const MCExpr *Expr = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext); | |||
941 | ||||
942 | if (isPositionIndependent() || Subtarget->isROPI()) | |||
943 | Expr = MCBinaryExpr::createSub(Expr, MCSymbolRefExpr::create(JTISymbol, | |||
944 | OutContext), | |||
945 | OutContext); | |||
946 | // If we're generating a table of Thumb addresses in static relocation | |||
947 | // model, we need to add one to keep interworking correctly. | |||
948 | else if (AFI->isThumbFunction()) | |||
949 | Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(1,OutContext), | |||
950 | OutContext); | |||
951 | OutStreamer->EmitValue(Expr, 4); | |||
952 | } | |||
953 | // Mark the end of jump table data-in-code region. | |||
954 | OutStreamer->EmitDataRegion(MCDR_DataRegionEnd); | |||
955 | } | |||
956 | ||||
957 | void ARMAsmPrinter::EmitJumpTableInsts(const MachineInstr *MI) { | |||
958 | const MachineOperand &MO1 = MI->getOperand(1); | |||
959 | unsigned JTI = MO1.getIndex(); | |||
960 | ||||
961 | // Make sure the Thumb jump table is 4-byte aligned. This will be a nop for | |||
962 | // ARM mode tables. | |||
963 | EmitAlignment(2); | |||
964 | ||||
965 | // Emit a label for the jump table. | |||
966 | MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI); | |||
967 | OutStreamer->EmitLabel(JTISymbol); | |||
968 | ||||
969 | // Emit each entry of the table. | |||
970 | const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); | |||
971 | const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); | |||
972 | const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; | |||
973 | ||||
974 | for (MachineBasicBlock *MBB : JTBBs) { | |||
975 | const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::create(MBB->getSymbol(), | |||
976 | OutContext); | |||
977 | // If this isn't a TBB or TBH, the entries are direct branch instructions. | |||
978 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2B) | |||
979 | .addExpr(MBBSymbolExpr) | |||
980 | .addImm(ARMCC::AL) | |||
981 | .addReg(0)); | |||
982 | } | |||
983 | } | |||
984 | ||||
985 | void ARMAsmPrinter::EmitJumpTableTBInst(const MachineInstr *MI, | |||
986 | unsigned OffsetWidth) { | |||
987 | assert((OffsetWidth == 1 || OffsetWidth == 2) && "invalid tbb/tbh width")(static_cast <bool> ((OffsetWidth == 1 || OffsetWidth == 2) && "invalid tbb/tbh width") ? void (0) : __assert_fail ("(OffsetWidth == 1 || OffsetWidth == 2) && \"invalid tbb/tbh width\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 987, __extension__ __PRETTY_FUNCTION__)); | |||
988 | const MachineOperand &MO1 = MI->getOperand(1); | |||
989 | unsigned JTI = MO1.getIndex(); | |||
990 | ||||
991 | if (Subtarget->isThumb1Only()) | |||
992 | EmitAlignment(2); | |||
993 | ||||
994 | MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI); | |||
995 | OutStreamer->EmitLabel(JTISymbol); | |||
996 | ||||
997 | // Emit each entry of the table. | |||
998 | const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); | |||
999 | const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); | |||
1000 | const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; | |||
1001 | ||||
1002 | // Mark the jump table as data-in-code. | |||
1003 | OutStreamer->EmitDataRegion(OffsetWidth == 1 ? MCDR_DataRegionJT8 | |||
1004 | : MCDR_DataRegionJT16); | |||
1005 | ||||
1006 | for (auto MBB : JTBBs) { | |||
1007 | const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::create(MBB->getSymbol(), | |||
1008 | OutContext); | |||
1009 | // Otherwise it's an offset from the dispatch instruction. Construct an | |||
1010 | // MCExpr for the entry. We want a value of the form: | |||
1011 | // (BasicBlockAddr - TBBInstAddr + 4) / 2 | |||
1012 | // | |||
1013 | // For example, a TBB table with entries jumping to basic blocks BB0 and BB1 | |||
1014 | // would look like: | |||
1015 | // LJTI_0_0: | |||
1016 | // .byte (LBB0 - (LCPI0_0 + 4)) / 2 | |||
1017 | // .byte (LBB1 - (LCPI0_0 + 4)) / 2 | |||
1018 | // where LCPI0_0 is a label defined just before the TBB instruction using | |||
1019 | // this table. | |||
1020 | MCSymbol *TBInstPC = GetCPISymbol(MI->getOperand(0).getImm()); | |||
1021 | const MCExpr *Expr = MCBinaryExpr::createAdd( | |||
1022 | MCSymbolRefExpr::create(TBInstPC, OutContext), | |||
1023 | MCConstantExpr::create(4, OutContext), OutContext); | |||
1024 | Expr = MCBinaryExpr::createSub(MBBSymbolExpr, Expr, OutContext); | |||
1025 | Expr = MCBinaryExpr::createDiv(Expr, MCConstantExpr::create(2, OutContext), | |||
1026 | OutContext); | |||
1027 | OutStreamer->EmitValue(Expr, OffsetWidth); | |||
1028 | } | |||
1029 | // Mark the end of jump table data-in-code region. 32-bit offsets use | |||
1030 | // actual branch instructions here, so we don't mark those as a data-region | |||
1031 | // at all. | |||
1032 | OutStreamer->EmitDataRegion(MCDR_DataRegionEnd); | |||
1033 | ||||
1034 | // Make sure the next instruction is 2-byte aligned. | |||
1035 | EmitAlignment(1); | |||
1036 | } | |||
1037 | ||||
1038 | void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) { | |||
1039 | assert(MI->getFlag(MachineInstr::FrameSetup) &&(static_cast <bool> (MI->getFlag(MachineInstr::FrameSetup ) && "Only instruction which are involved into frame setup code are allowed" ) ? void (0) : __assert_fail ("MI->getFlag(MachineInstr::FrameSetup) && \"Only instruction which are involved into frame setup code are allowed\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1040, __extension__ __PRETTY_FUNCTION__)) | |||
1040 | "Only instruction which are involved into frame setup code are allowed")(static_cast <bool> (MI->getFlag(MachineInstr::FrameSetup ) && "Only instruction which are involved into frame setup code are allowed" ) ? void (0) : __assert_fail ("MI->getFlag(MachineInstr::FrameSetup) && \"Only instruction which are involved into frame setup code are allowed\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1040, __extension__ __PRETTY_FUNCTION__)); | |||
1041 | ||||
1042 | MCTargetStreamer &TS = *OutStreamer->getTargetStreamer(); | |||
1043 | ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS); | |||
1044 | const MachineFunction &MF = *MI->getParent()->getParent(); | |||
1045 | const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo(); | |||
1046 | const ARMFunctionInfo &AFI = *MF.getInfo<ARMFunctionInfo>(); | |||
1047 | ||||
1048 | unsigned FramePtr = RegInfo->getFrameRegister(MF); | |||
1049 | unsigned Opc = MI->getOpcode(); | |||
1050 | unsigned SrcReg, DstReg; | |||
1051 | ||||
1052 | if (Opc == ARM::tPUSH || Opc == ARM::tLDRpci) { | |||
1053 | // Two special cases: | |||
1054 | // 1) tPUSH does not have src/dst regs. | |||
1055 | // 2) for Thumb1 code we sometimes materialize the constant via constpool | |||
1056 | // load. Yes, this is pretty fragile, but for now I don't see better | |||
1057 | // way... :( | |||
1058 | SrcReg = DstReg = ARM::SP; | |||
1059 | } else { | |||
1060 | SrcReg = MI->getOperand(1).getReg(); | |||
1061 | DstReg = MI->getOperand(0).getReg(); | |||
1062 | } | |||
1063 | ||||
1064 | // Try to figure out the unwinding opcode out of src / dst regs. | |||
1065 | if (MI->mayStore()) { | |||
1066 | // Register saves. | |||
1067 | assert(DstReg == ARM::SP &&(static_cast <bool> (DstReg == ARM::SP && "Only stack pointer as a destination reg is supported" ) ? void (0) : __assert_fail ("DstReg == ARM::SP && \"Only stack pointer as a destination reg is supported\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1068, __extension__ __PRETTY_FUNCTION__)) | |||
1068 | "Only stack pointer as a destination reg is supported")(static_cast <bool> (DstReg == ARM::SP && "Only stack pointer as a destination reg is supported" ) ? void (0) : __assert_fail ("DstReg == ARM::SP && \"Only stack pointer as a destination reg is supported\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1068, __extension__ __PRETTY_FUNCTION__)); | |||
1069 | ||||
1070 | SmallVector<unsigned, 4> RegList; | |||
1071 | // Skip src & dst reg, and pred ops. | |||
1072 | unsigned StartOp = 2 + 2; | |||
1073 | // Use all the operands. | |||
1074 | unsigned NumOffset = 0; | |||
1075 | // Amount of SP adjustment folded into a push. | |||
1076 | unsigned Pad = 0; | |||
1077 | ||||
1078 | switch (Opc) { | |||
1079 | default: | |||
1080 | MI->print(errs()); | |||
1081 | llvm_unreachable("Unsupported opcode for unwinding information")::llvm::llvm_unreachable_internal("Unsupported opcode for unwinding information" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1081); | |||
1082 | case ARM::tPUSH: | |||
1083 | // Special case here: no src & dst reg, but two extra imp ops. | |||
1084 | StartOp = 2; NumOffset = 2; | |||
1085 | LLVM_FALLTHROUGH[[clang::fallthrough]]; | |||
1086 | case ARM::STMDB_UPD: | |||
1087 | case ARM::t2STMDB_UPD: | |||
1088 | case ARM::VSTMDDB_UPD: | |||
1089 | assert(SrcReg == ARM::SP &&(static_cast <bool> (SrcReg == ARM::SP && "Only stack pointer as a source reg is supported" ) ? void (0) : __assert_fail ("SrcReg == ARM::SP && \"Only stack pointer as a source reg is supported\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1090, __extension__ __PRETTY_FUNCTION__)) | |||
1090 | "Only stack pointer as a source reg is supported")(static_cast <bool> (SrcReg == ARM::SP && "Only stack pointer as a source reg is supported" ) ? void (0) : __assert_fail ("SrcReg == ARM::SP && \"Only stack pointer as a source reg is supported\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1090, __extension__ __PRETTY_FUNCTION__)); | |||
1091 | for (unsigned i = StartOp, NumOps = MI->getNumOperands() - NumOffset; | |||
1092 | i != NumOps; ++i) { | |||
1093 | const MachineOperand &MO = MI->getOperand(i); | |||
1094 | // Actually, there should never be any impdef stuff here. Skip it | |||
1095 | // temporary to workaround PR11902. | |||
1096 | if (MO.isImplicit()) | |||
1097 | continue; | |||
1098 | // Registers, pushed as a part of folding an SP update into the | |||
1099 | // push instruction are marked as undef and should not be | |||
1100 | // restored when unwinding, because the function can modify the | |||
1101 | // corresponding stack slots. | |||
1102 | if (MO.isUndef()) { | |||
1103 | assert(RegList.empty() &&(static_cast <bool> (RegList.empty() && "Pad registers must come before restored ones" ) ? void (0) : __assert_fail ("RegList.empty() && \"Pad registers must come before restored ones\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1104, __extension__ __PRETTY_FUNCTION__)) | |||
1104 | "Pad registers must come before restored ones")(static_cast <bool> (RegList.empty() && "Pad registers must come before restored ones" ) ? void (0) : __assert_fail ("RegList.empty() && \"Pad registers must come before restored ones\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1104, __extension__ __PRETTY_FUNCTION__)); | |||
1105 | Pad += 4; | |||
1106 | continue; | |||
1107 | } | |||
1108 | RegList.push_back(MO.getReg()); | |||
1109 | } | |||
1110 | break; | |||
1111 | case ARM::STR_PRE_IMM: | |||
1112 | case ARM::STR_PRE_REG: | |||
1113 | case ARM::t2STR_PRE: | |||
1114 | assert(MI->getOperand(2).getReg() == ARM::SP &&(static_cast <bool> (MI->getOperand(2).getReg() == ARM ::SP && "Only stack pointer as a source reg is supported" ) ? void (0) : __assert_fail ("MI->getOperand(2).getReg() == ARM::SP && \"Only stack pointer as a source reg is supported\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1115, __extension__ __PRETTY_FUNCTION__)) | |||
1115 | "Only stack pointer as a source reg is supported")(static_cast <bool> (MI->getOperand(2).getReg() == ARM ::SP && "Only stack pointer as a source reg is supported" ) ? void (0) : __assert_fail ("MI->getOperand(2).getReg() == ARM::SP && \"Only stack pointer as a source reg is supported\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1115, __extension__ __PRETTY_FUNCTION__)); | |||
1116 | RegList.push_back(SrcReg); | |||
1117 | break; | |||
1118 | } | |||
1119 | if (MAI->getExceptionHandlingType() == ExceptionHandling::ARM) { | |||
1120 | ATS.emitRegSave(RegList, Opc == ARM::VSTMDDB_UPD); | |||
1121 | // Account for the SP adjustment, folded into the push. | |||
1122 | if (Pad) | |||
1123 | ATS.emitPad(Pad); | |||
1124 | } | |||
1125 | } else { | |||
1126 | // Changes of stack / frame pointer. | |||
1127 | if (SrcReg == ARM::SP) { | |||
1128 | int64_t Offset = 0; | |||
1129 | switch (Opc) { | |||
1130 | default: | |||
1131 | MI->print(errs()); | |||
1132 | llvm_unreachable("Unsupported opcode for unwinding information")::llvm::llvm_unreachable_internal("Unsupported opcode for unwinding information" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1132); | |||
1133 | case ARM::MOVr: | |||
1134 | case ARM::tMOVr: | |||
1135 | Offset = 0; | |||
1136 | break; | |||
1137 | case ARM::ADDri: | |||
1138 | case ARM::t2ADDri: | |||
1139 | Offset = -MI->getOperand(2).getImm(); | |||
1140 | break; | |||
1141 | case ARM::SUBri: | |||
1142 | case ARM::t2SUBri: | |||
1143 | Offset = MI->getOperand(2).getImm(); | |||
1144 | break; | |||
1145 | case ARM::tSUBspi: | |||
1146 | Offset = MI->getOperand(2).getImm()*4; | |||
1147 | break; | |||
1148 | case ARM::tADDspi: | |||
1149 | case ARM::tADDrSPi: | |||
1150 | Offset = -MI->getOperand(2).getImm()*4; | |||
1151 | break; | |||
1152 | case ARM::tLDRpci: { | |||
1153 | // Grab the constpool index and check, whether it corresponds to | |||
1154 | // original or cloned constpool entry. | |||
1155 | unsigned CPI = MI->getOperand(1).getIndex(); | |||
1156 | const MachineConstantPool *MCP = MF.getConstantPool(); | |||
1157 | if (CPI >= MCP->getConstants().size()) | |||
1158 | CPI = AFI.getOriginalCPIdx(CPI); | |||
1159 | assert(CPI != -1U && "Invalid constpool index")(static_cast <bool> (CPI != -1U && "Invalid constpool index" ) ? void (0) : __assert_fail ("CPI != -1U && \"Invalid constpool index\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1159, __extension__ __PRETTY_FUNCTION__)); | |||
1160 | ||||
1161 | // Derive the actual offset. | |||
1162 | const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI]; | |||
1163 | assert(!CPE.isMachineConstantPoolEntry() && "Invalid constpool entry")(static_cast <bool> (!CPE.isMachineConstantPoolEntry() && "Invalid constpool entry") ? void (0) : __assert_fail ("!CPE.isMachineConstantPoolEntry() && \"Invalid constpool entry\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1163, __extension__ __PRETTY_FUNCTION__)); | |||
1164 | // FIXME: Check for user, it should be "add" instruction! | |||
1165 | Offset = -cast<ConstantInt>(CPE.Val.ConstVal)->getSExtValue(); | |||
1166 | break; | |||
1167 | } | |||
1168 | } | |||
1169 | ||||
1170 | if (MAI->getExceptionHandlingType() == ExceptionHandling::ARM) { | |||
1171 | if (DstReg == FramePtr && FramePtr != ARM::SP) | |||
1172 | // Set-up of the frame pointer. Positive values correspond to "add" | |||
1173 | // instruction. | |||
1174 | ATS.emitSetFP(FramePtr, ARM::SP, -Offset); | |||
1175 | else if (DstReg == ARM::SP) { | |||
1176 | // Change of SP by an offset. Positive values correspond to "sub" | |||
1177 | // instruction. | |||
1178 | ATS.emitPad(Offset); | |||
1179 | } else { | |||
1180 | // Move of SP to a register. Positive values correspond to an "add" | |||
1181 | // instruction. | |||
1182 | ATS.emitMovSP(DstReg, -Offset); | |||
1183 | } | |||
1184 | } | |||
1185 | } else if (DstReg == ARM::SP) { | |||
1186 | MI->print(errs()); | |||
1187 | llvm_unreachable("Unsupported opcode for unwinding information")::llvm::llvm_unreachable_internal("Unsupported opcode for unwinding information" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1187); | |||
1188 | } | |||
1189 | else { | |||
1190 | MI->print(errs()); | |||
1191 | llvm_unreachable("Unsupported opcode for unwinding information")::llvm::llvm_unreachable_internal("Unsupported opcode for unwinding information" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1191); | |||
1192 | } | |||
1193 | } | |||
1194 | } | |||
1195 | ||||
1196 | // Simple pseudo-instructions have their lowering (with expansion to real | |||
1197 | // instructions) auto-generated. | |||
1198 | #include "ARMGenMCPseudoLowering.inc" | |||
1199 | ||||
1200 | void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) { | |||
1201 | const DataLayout &DL = getDataLayout(); | |||
1202 | MCTargetStreamer &TS = *OutStreamer->getTargetStreamer(); | |||
1203 | ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS); | |||
1204 | ||||
1205 | const MachineFunction &MF = *MI->getParent()->getParent(); | |||
1206 | const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>(); | |||
1207 | unsigned FramePtr = STI.useR7AsFramePointer() ? ARM::R7 : ARM::R11; | |||
1208 | ||||
1209 | // If we just ended a constant pool, mark it as such. | |||
1210 | if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) { | |||
1211 | OutStreamer->EmitDataRegion(MCDR_DataRegionEnd); | |||
1212 | InConstantPool = false; | |||
1213 | } | |||
1214 | ||||
1215 | // Emit unwinding stuff for frame-related instructions | |||
1216 | if (Subtarget->isTargetEHABICompatible() && | |||
1217 | MI->getFlag(MachineInstr::FrameSetup)) | |||
1218 | EmitUnwindingInstruction(MI); | |||
1219 | ||||
1220 | // Do any auto-generated pseudo lowerings. | |||
1221 | if (emitPseudoExpansionLowering(*OutStreamer, MI)) | |||
1222 | return; | |||
1223 | ||||
1224 | assert(!convertAddSubFlagsOpcode(MI->getOpcode()) &&(static_cast <bool> (!convertAddSubFlagsOpcode(MI->getOpcode ()) && "Pseudo flag setting opcode should be expanded early" ) ? void (0) : __assert_fail ("!convertAddSubFlagsOpcode(MI->getOpcode()) && \"Pseudo flag setting opcode should be expanded early\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1225, __extension__ __PRETTY_FUNCTION__)) | |||
1225 | "Pseudo flag setting opcode should be expanded early")(static_cast <bool> (!convertAddSubFlagsOpcode(MI->getOpcode ()) && "Pseudo flag setting opcode should be expanded early" ) ? void (0) : __assert_fail ("!convertAddSubFlagsOpcode(MI->getOpcode()) && \"Pseudo flag setting opcode should be expanded early\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1225, __extension__ __PRETTY_FUNCTION__)); | |||
1226 | ||||
1227 | // Check for manual lowerings. | |||
1228 | unsigned Opc = MI->getOpcode(); | |||
1229 | switch (Opc) { | |||
1230 | case ARM::t2MOVi32imm: llvm_unreachable("Should be lowered by thumb2it pass")::llvm::llvm_unreachable_internal("Should be lowered by thumb2it pass" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1230); | |||
1231 | case ARM::DBG_VALUE: llvm_unreachable("Should be handled by generic printing")::llvm::llvm_unreachable_internal("Should be handled by generic printing" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1231); | |||
1232 | case ARM::LEApcrel: | |||
1233 | case ARM::tLEApcrel: | |||
1234 | case ARM::t2LEApcrel: { | |||
1235 | // FIXME: Need to also handle globals and externals | |||
1236 | MCSymbol *CPISymbol = GetCPISymbol(MI->getOperand(1).getIndex()); | |||
1237 | EmitToStreamer(*OutStreamer, MCInstBuilder(MI->getOpcode() == | |||
1238 | ARM::t2LEApcrel ? ARM::t2ADR | |||
1239 | : (MI->getOpcode() == ARM::tLEApcrel ? ARM::tADR | |||
1240 | : ARM::ADR)) | |||
1241 | .addReg(MI->getOperand(0).getReg()) | |||
1242 | .addExpr(MCSymbolRefExpr::create(CPISymbol, OutContext)) | |||
1243 | // Add predicate operands. | |||
1244 | .addImm(MI->getOperand(2).getImm()) | |||
1245 | .addReg(MI->getOperand(3).getReg())); | |||
1246 | return; | |||
1247 | } | |||
1248 | case ARM::LEApcrelJT: | |||
1249 | case ARM::tLEApcrelJT: | |||
1250 | case ARM::t2LEApcrelJT: { | |||
1251 | MCSymbol *JTIPICSymbol = | |||
1252 | GetARMJTIPICJumpTableLabel(MI->getOperand(1).getIndex()); | |||
1253 | EmitToStreamer(*OutStreamer, MCInstBuilder(MI->getOpcode() == | |||
1254 | ARM::t2LEApcrelJT ? ARM::t2ADR | |||
1255 | : (MI->getOpcode() == ARM::tLEApcrelJT ? ARM::tADR | |||
1256 | : ARM::ADR)) | |||
1257 | .addReg(MI->getOperand(0).getReg()) | |||
1258 | .addExpr(MCSymbolRefExpr::create(JTIPICSymbol, OutContext)) | |||
1259 | // Add predicate operands. | |||
1260 | .addImm(MI->getOperand(2).getImm()) | |||
1261 | .addReg(MI->getOperand(3).getReg())); | |||
1262 | return; | |||
1263 | } | |||
1264 | // Darwin call instructions are just normal call instructions with different | |||
1265 | // clobber semantics (they clobber R9). | |||
1266 | case ARM::BX_CALL: { | |||
1267 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVr) | |||
1268 | .addReg(ARM::LR) | |||
1269 | .addReg(ARM::PC) | |||
1270 | // Add predicate operands. | |||
1271 | .addImm(ARMCC::AL) | |||
1272 | .addReg(0) | |||
1273 | // Add 's' bit operand (always reg0 for this) | |||
1274 | .addReg(0)); | |||
1275 | ||||
1276 | assert(Subtarget->hasV4TOps())(static_cast <bool> (Subtarget->hasV4TOps()) ? void ( 0) : __assert_fail ("Subtarget->hasV4TOps()", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1276, __extension__ __PRETTY_FUNCTION__)); | |||
1277 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::BX) | |||
1278 | .addReg(MI->getOperand(0).getReg())); | |||
1279 | return; | |||
1280 | } | |||
1281 | case ARM::tBX_CALL: { | |||
1282 | if (Subtarget->hasV5TOps()) | |||
1283 | llvm_unreachable("Expected BLX to be selected for v5t+")::llvm::llvm_unreachable_internal("Expected BLX to be selected for v5t+" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1283); | |||
1284 | ||||
1285 | // On ARM v4t, when doing a call from thumb mode, we need to ensure | |||
1286 | // that the saved lr has its LSB set correctly (the arch doesn't | |||
1287 | // have blx). | |||
1288 | // So here we generate a bl to a small jump pad that does bx rN. | |||
1289 | // The jump pads are emitted after the function body. | |||
1290 | ||||
1291 | unsigned TReg = MI->getOperand(0).getReg(); | |||
1292 | MCSymbol *TRegSym = nullptr; | |||
1293 | for (std::pair<unsigned, MCSymbol *> &TIP : ThumbIndirectPads) { | |||
1294 | if (TIP.first == TReg) { | |||
1295 | TRegSym = TIP.second; | |||
1296 | break; | |||
1297 | } | |||
1298 | } | |||
1299 | ||||
1300 | if (!TRegSym) { | |||
1301 | TRegSym = OutContext.createTempSymbol(); | |||
1302 | ThumbIndirectPads.push_back(std::make_pair(TReg, TRegSym)); | |||
1303 | } | |||
1304 | ||||
1305 | // Create a link-saving branch to the Reg Indirect Jump Pad. | |||
1306 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBL) | |||
1307 | // Predicate comes first here. | |||
1308 | .addImm(ARMCC::AL).addReg(0) | |||
1309 | .addExpr(MCSymbolRefExpr::create(TRegSym, OutContext))); | |||
1310 | return; | |||
1311 | } | |||
1312 | case ARM::BMOVPCRX_CALL: { | |||
1313 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVr) | |||
1314 | .addReg(ARM::LR) | |||
1315 | .addReg(ARM::PC) | |||
1316 | // Add predicate operands. | |||
1317 | .addImm(ARMCC::AL) | |||
1318 | .addReg(0) | |||
1319 | // Add 's' bit operand (always reg0 for this) | |||
1320 | .addReg(0)); | |||
1321 | ||||
1322 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVr) | |||
1323 | .addReg(ARM::PC) | |||
1324 | .addReg(MI->getOperand(0).getReg()) | |||
1325 | // Add predicate operands. | |||
1326 | .addImm(ARMCC::AL) | |||
1327 | .addReg(0) | |||
1328 | // Add 's' bit operand (always reg0 for this) | |||
1329 | .addReg(0)); | |||
1330 | return; | |||
1331 | } | |||
1332 | case ARM::BMOVPCB_CALL: { | |||
1333 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVr) | |||
1334 | .addReg(ARM::LR) | |||
1335 | .addReg(ARM::PC) | |||
1336 | // Add predicate operands. | |||
1337 | .addImm(ARMCC::AL) | |||
1338 | .addReg(0) | |||
1339 | // Add 's' bit operand (always reg0 for this) | |||
1340 | .addReg(0)); | |||
1341 | ||||
1342 | const MachineOperand &Op = MI->getOperand(0); | |||
1343 | const GlobalValue *GV = Op.getGlobal(); | |||
1344 | const unsigned TF = Op.getTargetFlags(); | |||
1345 | MCSymbol *GVSym = GetARMGVSymbol(GV, TF); | |||
1346 | const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext); | |||
1347 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::Bcc) | |||
1348 | .addExpr(GVSymExpr) | |||
1349 | // Add predicate operands. | |||
1350 | .addImm(ARMCC::AL) | |||
1351 | .addReg(0)); | |||
1352 | return; | |||
1353 | } | |||
1354 | case ARM::MOVi16_ga_pcrel: | |||
1355 | case ARM::t2MOVi16_ga_pcrel: { | |||
1356 | MCInst TmpInst; | |||
1357 | TmpInst.setOpcode(Opc == ARM::MOVi16_ga_pcrel? ARM::MOVi16 : ARM::t2MOVi16); | |||
1358 | TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); | |||
1359 | ||||
1360 | unsigned TF = MI->getOperand(1).getTargetFlags(); | |||
1361 | const GlobalValue *GV = MI->getOperand(1).getGlobal(); | |||
1362 | MCSymbol *GVSym = GetARMGVSymbol(GV, TF); | |||
1363 | const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext); | |||
1364 | ||||
1365 | MCSymbol *LabelSym = | |||
1366 | getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(), | |||
1367 | MI->getOperand(2).getImm(), OutContext); | |||
1368 | const MCExpr *LabelSymExpr= MCSymbolRefExpr::create(LabelSym, OutContext); | |||
1369 | unsigned PCAdj = (Opc == ARM::MOVi16_ga_pcrel) ? 8 : 4; | |||
1370 | const MCExpr *PCRelExpr = | |||
1371 | ARMMCExpr::createLower16(MCBinaryExpr::createSub(GVSymExpr, | |||
1372 | MCBinaryExpr::createAdd(LabelSymExpr, | |||
1373 | MCConstantExpr::create(PCAdj, OutContext), | |||
1374 | OutContext), OutContext), OutContext); | |||
1375 | TmpInst.addOperand(MCOperand::createExpr(PCRelExpr)); | |||
1376 | ||||
1377 | // Add predicate operands. | |||
1378 | TmpInst.addOperand(MCOperand::createImm(ARMCC::AL)); | |||
1379 | TmpInst.addOperand(MCOperand::createReg(0)); | |||
1380 | // Add 's' bit operand (always reg0 for this) | |||
1381 | TmpInst.addOperand(MCOperand::createReg(0)); | |||
1382 | EmitToStreamer(*OutStreamer, TmpInst); | |||
1383 | return; | |||
1384 | } | |||
1385 | case ARM::MOVTi16_ga_pcrel: | |||
1386 | case ARM::t2MOVTi16_ga_pcrel: { | |||
1387 | MCInst TmpInst; | |||
1388 | TmpInst.setOpcode(Opc == ARM::MOVTi16_ga_pcrel | |||
1389 | ? ARM::MOVTi16 : ARM::t2MOVTi16); | |||
1390 | TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); | |||
1391 | TmpInst.addOperand(MCOperand::createReg(MI->getOperand(1).getReg())); | |||
1392 | ||||
1393 | unsigned TF = MI->getOperand(2).getTargetFlags(); | |||
1394 | const GlobalValue *GV = MI->getOperand(2).getGlobal(); | |||
1395 | MCSymbol *GVSym = GetARMGVSymbol(GV, TF); | |||
1396 | const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext); | |||
1397 | ||||
1398 | MCSymbol *LabelSym = | |||
1399 | getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(), | |||
1400 | MI->getOperand(3).getImm(), OutContext); | |||
1401 | const MCExpr *LabelSymExpr= MCSymbolRefExpr::create(LabelSym, OutContext); | |||
1402 | unsigned PCAdj = (Opc == ARM::MOVTi16_ga_pcrel) ? 8 : 4; | |||
1403 | const MCExpr *PCRelExpr = | |||
1404 | ARMMCExpr::createUpper16(MCBinaryExpr::createSub(GVSymExpr, | |||
1405 | MCBinaryExpr::createAdd(LabelSymExpr, | |||
1406 | MCConstantExpr::create(PCAdj, OutContext), | |||
1407 | OutContext), OutContext), OutContext); | |||
1408 | TmpInst.addOperand(MCOperand::createExpr(PCRelExpr)); | |||
1409 | // Add predicate operands. | |||
1410 | TmpInst.addOperand(MCOperand::createImm(ARMCC::AL)); | |||
1411 | TmpInst.addOperand(MCOperand::createReg(0)); | |||
1412 | // Add 's' bit operand (always reg0 for this) | |||
1413 | TmpInst.addOperand(MCOperand::createReg(0)); | |||
1414 | EmitToStreamer(*OutStreamer, TmpInst); | |||
1415 | return; | |||
1416 | } | |||
1417 | case ARM::tPICADD: { | |||
1418 | // This is a pseudo op for a label + instruction sequence, which looks like: | |||
1419 | // LPC0: | |||
1420 | // add r0, pc | |||
1421 | // This adds the address of LPC0 to r0. | |||
1422 | ||||
1423 | // Emit the label. | |||
1424 | OutStreamer->EmitLabel(getPICLabel(DL.getPrivateGlobalPrefix(), | |||
1425 | getFunctionNumber(), | |||
1426 | MI->getOperand(2).getImm(), OutContext)); | |||
1427 | ||||
1428 | // Form and emit the add. | |||
1429 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDhirr) | |||
1430 | .addReg(MI->getOperand(0).getReg()) | |||
1431 | .addReg(MI->getOperand(0).getReg()) | |||
1432 | .addReg(ARM::PC) | |||
1433 | // Add predicate operands. | |||
1434 | .addImm(ARMCC::AL) | |||
1435 | .addReg(0)); | |||
1436 | return; | |||
1437 | } | |||
1438 | case ARM::PICADD: { | |||
1439 | // This is a pseudo op for a label + instruction sequence, which looks like: | |||
1440 | // LPC0: | |||
1441 | // add r0, pc, r0 | |||
1442 | // This adds the address of LPC0 to r0. | |||
1443 | ||||
1444 | // Emit the label. | |||
1445 | OutStreamer->EmitLabel(getPICLabel(DL.getPrivateGlobalPrefix(), | |||
1446 | getFunctionNumber(), | |||
1447 | MI->getOperand(2).getImm(), OutContext)); | |||
1448 | ||||
1449 | // Form and emit the add. | |||
1450 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::ADDrr) | |||
1451 | .addReg(MI->getOperand(0).getReg()) | |||
1452 | .addReg(ARM::PC) | |||
1453 | .addReg(MI->getOperand(1).getReg()) | |||
1454 | // Add predicate operands. | |||
1455 | .addImm(MI->getOperand(3).getImm()) | |||
1456 | .addReg(MI->getOperand(4).getReg()) | |||
1457 | // Add 's' bit operand (always reg0 for this) | |||
1458 | .addReg(0)); | |||
1459 | return; | |||
1460 | } | |||
1461 | case ARM::PICSTR: | |||
1462 | case ARM::PICSTRB: | |||
1463 | case ARM::PICSTRH: | |||
1464 | case ARM::PICLDR: | |||
1465 | case ARM::PICLDRB: | |||
1466 | case ARM::PICLDRH: | |||
1467 | case ARM::PICLDRSB: | |||
1468 | case ARM::PICLDRSH: { | |||
1469 | // This is a pseudo op for a label + instruction sequence, which looks like: | |||
1470 | // LPC0: | |||
1471 | // OP r0, [pc, r0] | |||
1472 | // The LCP0 label is referenced by a constant pool entry in order to get | |||
1473 | // a PC-relative address at the ldr instruction. | |||
1474 | ||||
1475 | // Emit the label. | |||
1476 | OutStreamer->EmitLabel(getPICLabel(DL.getPrivateGlobalPrefix(), | |||
1477 | getFunctionNumber(), | |||
1478 | MI->getOperand(2).getImm(), OutContext)); | |||
1479 | ||||
1480 | // Form and emit the load | |||
1481 | unsigned Opcode; | |||
1482 | switch (MI->getOpcode()) { | |||
1483 | default: | |||
1484 | llvm_unreachable("Unexpected opcode!")::llvm::llvm_unreachable_internal("Unexpected opcode!", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1484); | |||
1485 | case ARM::PICSTR: Opcode = ARM::STRrs; break; | |||
1486 | case ARM::PICSTRB: Opcode = ARM::STRBrs; break; | |||
1487 | case ARM::PICSTRH: Opcode = ARM::STRH; break; | |||
1488 | case ARM::PICLDR: Opcode = ARM::LDRrs; break; | |||
1489 | case ARM::PICLDRB: Opcode = ARM::LDRBrs; break; | |||
1490 | case ARM::PICLDRH: Opcode = ARM::LDRH; break; | |||
1491 | case ARM::PICLDRSB: Opcode = ARM::LDRSB; break; | |||
1492 | case ARM::PICLDRSH: Opcode = ARM::LDRSH; break; | |||
1493 | } | |||
1494 | EmitToStreamer(*OutStreamer, MCInstBuilder(Opcode) | |||
1495 | .addReg(MI->getOperand(0).getReg()) | |||
1496 | .addReg(ARM::PC) | |||
1497 | .addReg(MI->getOperand(1).getReg()) | |||
1498 | .addImm(0) | |||
1499 | // Add predicate operands. | |||
1500 | .addImm(MI->getOperand(3).getImm()) | |||
1501 | .addReg(MI->getOperand(4).getReg())); | |||
1502 | ||||
1503 | return; | |||
1504 | } | |||
1505 | case ARM::CONSTPOOL_ENTRY: { | |||
1506 | if (Subtarget->genExecuteOnly()) | |||
1507 | llvm_unreachable("execute-only should not generate constant pools")::llvm::llvm_unreachable_internal("execute-only should not generate constant pools" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1507); | |||
1508 | ||||
1509 | /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool | |||
1510 | /// in the function. The first operand is the ID# for this instruction, the | |||
1511 | /// second is the index into the MachineConstantPool that this is, the third | |||
1512 | /// is the size in bytes of this constant pool entry. | |||
1513 | /// The required alignment is specified on the basic block holding this MI. | |||
1514 | unsigned LabelId = (unsigned)MI->getOperand(0).getImm(); | |||
1515 | unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); | |||
1516 | ||||
1517 | // If this is the first entry of the pool, mark it. | |||
1518 | if (!InConstantPool) { | |||
1519 | OutStreamer->EmitDataRegion(MCDR_DataRegion); | |||
1520 | InConstantPool = true; | |||
1521 | } | |||
1522 | ||||
1523 | OutStreamer->EmitLabel(GetCPISymbol(LabelId)); | |||
1524 | ||||
1525 | const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; | |||
1526 | if (MCPE.isMachineConstantPoolEntry()) | |||
1527 | EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal); | |||
1528 | else | |||
1529 | EmitGlobalConstant(DL, MCPE.Val.ConstVal); | |||
1530 | return; | |||
1531 | } | |||
1532 | case ARM::JUMPTABLE_ADDRS: | |||
1533 | EmitJumpTableAddrs(MI); | |||
1534 | return; | |||
1535 | case ARM::JUMPTABLE_INSTS: | |||
1536 | EmitJumpTableInsts(MI); | |||
1537 | return; | |||
1538 | case ARM::JUMPTABLE_TBB: | |||
1539 | case ARM::JUMPTABLE_TBH: | |||
1540 | EmitJumpTableTBInst(MI, MI->getOpcode() == ARM::JUMPTABLE_TBB ? 1 : 2); | |||
1541 | return; | |||
1542 | case ARM::t2BR_JT: { | |||
1543 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr) | |||
1544 | .addReg(ARM::PC) | |||
1545 | .addReg(MI->getOperand(0).getReg()) | |||
1546 | // Add predicate operands. | |||
1547 | .addImm(ARMCC::AL) | |||
1548 | .addReg(0)); | |||
1549 | return; | |||
1550 | } | |||
1551 | case ARM::t2TBB_JT: | |||
1552 | case ARM::t2TBH_JT: { | |||
1553 | unsigned Opc = MI->getOpcode() == ARM::t2TBB_JT ? ARM::t2TBB : ARM::t2TBH; | |||
1554 | // Lower and emit the PC label, then the instruction itself. | |||
1555 | OutStreamer->EmitLabel(GetCPISymbol(MI->getOperand(3).getImm())); | |||
1556 | EmitToStreamer(*OutStreamer, MCInstBuilder(Opc) | |||
1557 | .addReg(MI->getOperand(0).getReg()) | |||
1558 | .addReg(MI->getOperand(1).getReg()) | |||
1559 | // Add predicate operands. | |||
1560 | .addImm(ARMCC::AL) | |||
1561 | .addReg(0)); | |||
1562 | return; | |||
1563 | } | |||
1564 | case ARM::tTBB_JT: | |||
1565 | case ARM::tTBH_JT: { | |||
1566 | ||||
1567 | bool Is8Bit = MI->getOpcode() == ARM::tTBB_JT; | |||
1568 | unsigned Base = MI->getOperand(0).getReg(); | |||
1569 | unsigned Idx = MI->getOperand(1).getReg(); | |||
1570 | assert(MI->getOperand(1).isKill() && "We need the index register as scratch!")(static_cast <bool> (MI->getOperand(1).isKill() && "We need the index register as scratch!") ? void (0) : __assert_fail ("MI->getOperand(1).isKill() && \"We need the index register as scratch!\"" , "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1570, __extension__ __PRETTY_FUNCTION__)); | |||
1571 | ||||
1572 | // Multiply up idx if necessary. | |||
1573 | if (!Is8Bit) | |||
1574 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri) | |||
1575 | .addReg(Idx) | |||
1576 | .addReg(ARM::CPSR) | |||
1577 | .addReg(Idx) | |||
1578 | .addImm(1) | |||
1579 | // Add predicate operands. | |||
1580 | .addImm(ARMCC::AL) | |||
1581 | .addReg(0)); | |||
1582 | ||||
1583 | if (Base == ARM::PC) { | |||
1584 | // TBB [base, idx] = | |||
1585 | // ADDS idx, idx, base | |||
1586 | // LDRB idx, [idx, #4] ; or LDRH if TBH | |||
1587 | // LSLS idx, #1 | |||
1588 | // ADDS pc, pc, idx | |||
1589 | ||||
1590 | // When using PC as the base, it's important that there is no padding | |||
1591 | // between the last ADDS and the start of the jump table. The jump table | |||
1592 | // is 4-byte aligned, so we ensure we're 4 byte aligned here too. | |||
1593 | // | |||
1594 | // FIXME: Ideally we could vary the LDRB index based on the padding | |||
1595 | // between the sequence and jump table, however that relies on MCExprs | |||
1596 | // for load indexes which are currently not supported. | |||
1597 | OutStreamer->EmitCodeAlignment(4); | |||
1598 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDhirr) | |||
1599 | .addReg(Idx) | |||
1600 | .addReg(Idx) | |||
1601 | .addReg(Base) | |||
1602 | // Add predicate operands. | |||
1603 | .addImm(ARMCC::AL) | |||
1604 | .addReg(0)); | |||
1605 | ||||
1606 | unsigned Opc = Is8Bit ? ARM::tLDRBi : ARM::tLDRHi; | |||
1607 | EmitToStreamer(*OutStreamer, MCInstBuilder(Opc) | |||
1608 | .addReg(Idx) | |||
1609 | .addReg(Idx) | |||
1610 | .addImm(Is8Bit ? 4 : 2) | |||
1611 | // Add predicate operands. | |||
1612 | .addImm(ARMCC::AL) | |||
1613 | .addReg(0)); | |||
1614 | } else { | |||
1615 | // TBB [base, idx] = | |||
1616 | // LDRB idx, [base, idx] ; or LDRH if TBH | |||
1617 | // LSLS idx, #1 | |||
1618 | // ADDS pc, pc, idx | |||
1619 | ||||
1620 | unsigned Opc = Is8Bit ? ARM::tLDRBr : ARM::tLDRHr; | |||
1621 | EmitToStreamer(*OutStreamer, MCInstBuilder(Opc) | |||
1622 | .addReg(Idx) | |||
1623 | .addReg(Base) | |||
1624 | .addReg(Idx) | |||
1625 | // Add predicate operands. | |||
1626 | .addImm(ARMCC::AL) | |||
1627 | .addReg(0)); | |||
1628 | } | |||
1629 | ||||
1630 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri) | |||
1631 | .addReg(Idx) | |||
1632 | .addReg(ARM::CPSR) | |||
1633 | .addReg(Idx) | |||
1634 | .addImm(1) | |||
1635 | // Add predicate operands. | |||
1636 | .addImm(ARMCC::AL) | |||
1637 | .addReg(0)); | |||
1638 | ||||
1639 | OutStreamer->EmitLabel(GetCPISymbol(MI->getOperand(3).getImm())); | |||
1640 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDhirr) | |||
1641 | .addReg(ARM::PC) | |||
1642 | .addReg(ARM::PC) | |||
1643 | .addReg(Idx) | |||
1644 | // Add predicate operands. | |||
1645 | .addImm(ARMCC::AL) | |||
1646 | .addReg(0)); | |||
1647 | return; | |||
1648 | } | |||
1649 | case ARM::tBR_JTr: | |||
1650 | case ARM::BR_JTr: { | |||
1651 | // mov pc, target | |||
1652 | MCInst TmpInst; | |||
1653 | unsigned Opc = MI->getOpcode() == ARM::BR_JTr ? | |||
1654 | ARM::MOVr : ARM::tMOVr; | |||
1655 | TmpInst.setOpcode(Opc); | |||
1656 | TmpInst.addOperand(MCOperand::createReg(ARM::PC)); | |||
1657 | TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); | |||
1658 | // Add predicate operands. | |||
1659 | TmpInst.addOperand(MCOperand::createImm(ARMCC::AL)); | |||
1660 | TmpInst.addOperand(MCOperand::createReg(0)); | |||
1661 | // Add 's' bit operand (always reg0 for this) | |||
1662 | if (Opc == ARM::MOVr) | |||
1663 | TmpInst.addOperand(MCOperand::createReg(0)); | |||
1664 | EmitToStreamer(*OutStreamer, TmpInst); | |||
1665 | return; | |||
1666 | } | |||
1667 | case ARM::BR_JTm_i12: { | |||
1668 | // ldr pc, target | |||
1669 | MCInst TmpInst; | |||
1670 | TmpInst.setOpcode(ARM::LDRi12); | |||
1671 | TmpInst.addOperand(MCOperand::createReg(ARM::PC)); | |||
1672 | TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); | |||
1673 | TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm())); | |||
1674 | // Add predicate operands. | |||
1675 | TmpInst.addOperand(MCOperand::createImm(ARMCC::AL)); | |||
1676 | TmpInst.addOperand(MCOperand::createReg(0)); | |||
1677 | EmitToStreamer(*OutStreamer, TmpInst); | |||
1678 | return; | |||
1679 | } | |||
1680 | case ARM::BR_JTm_rs: { | |||
1681 | // ldr pc, target | |||
1682 | MCInst TmpInst; | |||
1683 | TmpInst.setOpcode(ARM::LDRrs); | |||
1684 | TmpInst.addOperand(MCOperand::createReg(ARM::PC)); | |||
1685 | TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); | |||
1686 | TmpInst.addOperand(MCOperand::createReg(MI->getOperand(1).getReg())); | |||
1687 | TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm())); | |||
1688 | // Add predicate operands. | |||
1689 | TmpInst.addOperand(MCOperand::createImm(ARMCC::AL)); | |||
1690 | TmpInst.addOperand(MCOperand::createReg(0)); | |||
1691 | EmitToStreamer(*OutStreamer, TmpInst); | |||
1692 | return; | |||
1693 | } | |||
1694 | case ARM::BR_JTadd: { | |||
1695 | // add pc, target, idx | |||
1696 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::ADDrr) | |||
1697 | .addReg(ARM::PC) | |||
1698 | .addReg(MI->getOperand(0).getReg()) | |||
1699 | .addReg(MI->getOperand(1).getReg()) | |||
1700 | // Add predicate operands. | |||
1701 | .addImm(ARMCC::AL) | |||
1702 | .addReg(0) | |||
1703 | // Add 's' bit operand (always reg0 for this) | |||
1704 | .addReg(0)); | |||
1705 | return; | |||
1706 | } | |||
1707 | case ARM::SPACE: | |||
1708 | OutStreamer->EmitZeros(MI->getOperand(1).getImm()); | |||
1709 | return; | |||
1710 | case ARM::TRAP: { | |||
1711 | // Non-Darwin binutils don't yet support the "trap" mnemonic. | |||
1712 | // FIXME: Remove this special case when they do. | |||
1713 | if (!Subtarget->isTargetMachO()) { | |||
1714 | uint32_t Val = 0xe7ffdefeUL; | |||
1715 | OutStreamer->AddComment("trap"); | |||
1716 | ATS.emitInst(Val); | |||
1717 | return; | |||
1718 | } | |||
1719 | break; | |||
1720 | } | |||
1721 | case ARM::TRAPNaCl: { | |||
1722 | uint32_t Val = 0xe7fedef0UL; | |||
1723 | OutStreamer->AddComment("trap"); | |||
1724 | ATS.emitInst(Val); | |||
1725 | return; | |||
1726 | } | |||
1727 | case ARM::tTRAP: { | |||
1728 | // Non-Darwin binutils don't yet support the "trap" mnemonic. | |||
1729 | // FIXME: Remove this special case when they do. | |||
1730 | if (!Subtarget->isTargetMachO()) { | |||
1731 | uint16_t Val = 0xdefe; | |||
1732 | OutStreamer->AddComment("trap"); | |||
1733 | ATS.emitInst(Val, 'n'); | |||
1734 | return; | |||
1735 | } | |||
1736 | break; | |||
1737 | } | |||
1738 | case ARM::t2Int_eh_sjlj_setjmp: | |||
1739 | case ARM::t2Int_eh_sjlj_setjmp_nofp: | |||
1740 | case ARM::tInt_eh_sjlj_setjmp: { | |||
1741 | // Two incoming args: GPR:$src, GPR:$val | |||
1742 | // mov $val, pc | |||
1743 | // adds $val, #7 | |||
1744 | // str $val, [$src, #4] | |||
1745 | // movs r0, #0 | |||
1746 | // b LSJLJEH | |||
1747 | // movs r0, #1 | |||
1748 | // LSJLJEH: | |||
1749 | unsigned SrcReg = MI->getOperand(0).getReg(); | |||
1750 | unsigned ValReg = MI->getOperand(1).getReg(); | |||
1751 | MCSymbol *Label = OutContext.createTempSymbol("SJLJEH", false, true); | |||
1752 | OutStreamer->AddComment("eh_setjmp begin"); | |||
1753 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr) | |||
1754 | .addReg(ValReg) | |||
1755 | .addReg(ARM::PC) | |||
1756 | // Predicate. | |||
1757 | .addImm(ARMCC::AL) | |||
1758 | .addReg(0)); | |||
1759 | ||||
1760 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi3) | |||
1761 | .addReg(ValReg) | |||
1762 | // 's' bit operand | |||
1763 | .addReg(ARM::CPSR) | |||
1764 | .addReg(ValReg) | |||
1765 | .addImm(7) | |||
1766 | // Predicate. | |||
1767 | .addImm(ARMCC::AL) | |||
1768 | .addReg(0)); | |||
1769 | ||||
1770 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tSTRi) | |||
1771 | .addReg(ValReg) | |||
1772 | .addReg(SrcReg) | |||
1773 | // The offset immediate is #4. The operand value is scaled by 4 for the | |||
1774 | // tSTR instruction. | |||
1775 | .addImm(1) | |||
1776 | // Predicate. | |||
1777 | .addImm(ARMCC::AL) | |||
1778 | .addReg(0)); | |||
1779 | ||||
1780 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVi8) | |||
1781 | .addReg(ARM::R0) | |||
1782 | .addReg(ARM::CPSR) | |||
1783 | .addImm(0) | |||
1784 | // Predicate. | |||
1785 | .addImm(ARMCC::AL) | |||
1786 | .addReg(0)); | |||
1787 | ||||
1788 | const MCExpr *SymbolExpr = MCSymbolRefExpr::create(Label, OutContext); | |||
1789 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tB) | |||
1790 | .addExpr(SymbolExpr) | |||
1791 | .addImm(ARMCC::AL) | |||
1792 | .addReg(0)); | |||
1793 | ||||
1794 | OutStreamer->AddComment("eh_setjmp end"); | |||
1795 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVi8) | |||
1796 | .addReg(ARM::R0) | |||
1797 | .addReg(ARM::CPSR) | |||
1798 | .addImm(1) | |||
1799 | // Predicate. | |||
1800 | .addImm(ARMCC::AL) | |||
1801 | .addReg(0)); | |||
1802 | ||||
1803 | OutStreamer->EmitLabel(Label); | |||
1804 | return; | |||
1805 | } | |||
1806 | ||||
1807 | case ARM::Int_eh_sjlj_setjmp_nofp: | |||
1808 | case ARM::Int_eh_sjlj_setjmp: { | |||
1809 | // Two incoming args: GPR:$src, GPR:$val | |||
1810 | // add $val, pc, #8 | |||
1811 | // str $val, [$src, #+4] | |||
1812 | // mov r0, #0 | |||
1813 | // add pc, pc, #0 | |||
1814 | // mov r0, #1 | |||
1815 | unsigned SrcReg = MI->getOperand(0).getReg(); | |||
1816 | unsigned ValReg = MI->getOperand(1).getReg(); | |||
1817 | ||||
1818 | OutStreamer->AddComment("eh_setjmp begin"); | |||
1819 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::ADDri) | |||
1820 | .addReg(ValReg) | |||
1821 | .addReg(ARM::PC) | |||
1822 | .addImm(8) | |||
1823 | // Predicate. | |||
1824 | .addImm(ARMCC::AL) | |||
1825 | .addReg(0) | |||
1826 | // 's' bit operand (always reg0 for this). | |||
1827 | .addReg(0)); | |||
1828 | ||||
1829 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::STRi12) | |||
1830 | .addReg(ValReg) | |||
1831 | .addReg(SrcReg) | |||
1832 | .addImm(4) | |||
1833 | // Predicate. | |||
1834 | .addImm(ARMCC::AL) | |||
1835 | .addReg(0)); | |||
1836 | ||||
1837 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVi) | |||
1838 | .addReg(ARM::R0) | |||
1839 | .addImm(0) | |||
1840 | // Predicate. | |||
1841 | .addImm(ARMCC::AL) | |||
1842 | .addReg(0) | |||
1843 | // 's' bit operand (always reg0 for this). | |||
1844 | .addReg(0)); | |||
1845 | ||||
1846 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::ADDri) | |||
1847 | .addReg(ARM::PC) | |||
1848 | .addReg(ARM::PC) | |||
1849 | .addImm(0) | |||
1850 | // Predicate. | |||
1851 | .addImm(ARMCC::AL) | |||
1852 | .addReg(0) | |||
1853 | // 's' bit operand (always reg0 for this). | |||
1854 | .addReg(0)); | |||
1855 | ||||
1856 | OutStreamer->AddComment("eh_setjmp end"); | |||
1857 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVi) | |||
1858 | .addReg(ARM::R0) | |||
1859 | .addImm(1) | |||
1860 | // Predicate. | |||
1861 | .addImm(ARMCC::AL) | |||
1862 | .addReg(0) | |||
1863 | // 's' bit operand (always reg0 for this). | |||
1864 | .addReg(0)); | |||
1865 | return; | |||
1866 | } | |||
1867 | case ARM::Int_eh_sjlj_longjmp: { | |||
1868 | // ldr sp, [$src, #8] | |||
1869 | // ldr $scratch, [$src, #4] | |||
1870 | // ldr r7, [$src] | |||
1871 | // bx $scratch | |||
1872 | unsigned SrcReg = MI->getOperand(0).getReg(); | |||
1873 | unsigned ScratchReg = MI->getOperand(1).getReg(); | |||
1874 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12) | |||
1875 | .addReg(ARM::SP) | |||
1876 | .addReg(SrcReg) | |||
1877 | .addImm(8) | |||
1878 | // Predicate. | |||
1879 | .addImm(ARMCC::AL) | |||
1880 | .addReg(0)); | |||
1881 | ||||
1882 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12) | |||
1883 | .addReg(ScratchReg) | |||
1884 | .addReg(SrcReg) | |||
1885 | .addImm(4) | |||
1886 | // Predicate. | |||
1887 | .addImm(ARMCC::AL) | |||
1888 | .addReg(0)); | |||
1889 | ||||
1890 | if (STI.isTargetDarwin() || STI.isTargetWindows()) { | |||
1891 | // These platforms always use the same frame register | |||
1892 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12) | |||
1893 | .addReg(FramePtr) | |||
1894 | .addReg(SrcReg) | |||
1895 | .addImm(0) | |||
1896 | // Predicate. | |||
1897 | .addImm(ARMCC::AL) | |||
1898 | .addReg(0)); | |||
1899 | } else { | |||
1900 | // If the calling code might use either R7 or R11 as | |||
1901 | // frame pointer register, restore it into both. | |||
1902 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12) | |||
1903 | .addReg(ARM::R7) | |||
1904 | .addReg(SrcReg) | |||
1905 | .addImm(0) | |||
1906 | // Predicate. | |||
1907 | .addImm(ARMCC::AL) | |||
1908 | .addReg(0)); | |||
1909 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12) | |||
1910 | .addReg(ARM::R11) | |||
1911 | .addReg(SrcReg) | |||
1912 | .addImm(0) | |||
1913 | // Predicate. | |||
1914 | .addImm(ARMCC::AL) | |||
1915 | .addReg(0)); | |||
1916 | } | |||
1917 | ||||
1918 | assert(Subtarget->hasV4TOps())(static_cast <bool> (Subtarget->hasV4TOps()) ? void ( 0) : __assert_fail ("Subtarget->hasV4TOps()", "/build/llvm-toolchain-snapshot-7~svn338205/lib/Target/ARM/ARMAsmPrinter.cpp" , 1918, __extension__ __PRETTY_FUNCTION__)); | |||
1919 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::BX) | |||
1920 | .addReg(ScratchReg) | |||
1921 | // Predicate. | |||
1922 | .addImm(ARMCC::AL) | |||
1923 | .addReg(0)); | |||
1924 | return; | |||
1925 | } | |||
1926 | case ARM::tInt_eh_sjlj_longjmp: { | |||
1927 | // ldr $scratch, [$src, #8] | |||
1928 | // mov sp, $scratch | |||
1929 | // ldr $scratch, [$src, #4] | |||
1930 | // ldr r7, [$src] | |||
1931 | // bx $scratch | |||
1932 | unsigned SrcReg = MI->getOperand(0).getReg(); | |||
1933 | unsigned ScratchReg = MI->getOperand(1).getReg(); | |||
1934 | ||||
1935 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi) | |||
1936 | .addReg(ScratchReg) | |||
1937 | .addReg(SrcReg) | |||
1938 | // The offset immediate is #8. The operand value is scaled by 4 for the | |||
1939 | // tLDR instruction. | |||
1940 | .addImm(2) | |||
1941 | // Predicate. | |||
1942 | .addImm(ARMCC::AL) | |||
1943 | .addReg(0)); | |||
1944 | ||||
1945 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr) | |||
1946 | .addReg(ARM::SP) | |||
1947 | .addReg(ScratchReg) | |||
1948 | // Predicate. | |||
1949 | .addImm(ARMCC::AL) | |||
1950 | .addReg(0)); | |||
1951 | ||||
1952 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi) | |||
1953 | .addReg(ScratchReg) | |||
1954 | .addReg(SrcReg) | |||
1955 | .addImm(1) | |||
1956 | // Predicate. | |||
1957 | .addImm(ARMCC::AL) | |||
1958 | .addReg(0)); | |||
1959 | ||||
1960 | if (STI.isTargetDarwin() || STI.isTargetWindows()) { | |||
1961 | // These platforms always use the same frame register | |||
1962 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi) | |||
1963 | .addReg(FramePtr) | |||
1964 | .addReg(SrcReg) | |||
1965 | .addImm(0) | |||
1966 | // Predicate. | |||
1967 | .addImm(ARMCC::AL) | |||
1968 | .addReg(0)); | |||
1969 | } else { | |||
1970 | // If the calling code might use either R7 or R11 as | |||
1971 | // frame pointer register, restore it into both. | |||
1972 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi) | |||
1973 | .addReg(ARM::R7) | |||
1974 | .addReg(SrcReg) | |||
1975 | .addImm(0) | |||
1976 | // Predicate. | |||
1977 | .addImm(ARMCC::AL) | |||
1978 | .addReg(0)); | |||
1979 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi) | |||
1980 | .addReg(ARM::R11) | |||
1981 | .addReg(SrcReg) | |||
1982 | .addImm(0) | |||
1983 | // Predicate. | |||
1984 | .addImm(ARMCC::AL) | |||
1985 | .addReg(0)); | |||
1986 | } | |||
1987 | ||||
1988 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBX) | |||
1989 | .addReg(ScratchReg) | |||
1990 | // Predicate. | |||
1991 | .addImm(ARMCC::AL) | |||
1992 | .addReg(0)); | |||
1993 | return; | |||
1994 | } | |||
1995 | case ARM::tInt_WIN_eh_sjlj_longjmp: { | |||
1996 | // ldr.w r11, [$src, #0] | |||
1997 | // ldr.w sp, [$src, #8] | |||
1998 | // ldr.w pc, [$src, #4] | |||
1999 | ||||
2000 | unsigned SrcReg = MI->getOperand(0).getReg(); | |||
2001 | ||||
2002 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi12) | |||
2003 | .addReg(ARM::R11) | |||
2004 | .addReg(SrcReg) | |||
2005 | .addImm(0) | |||
2006 | // Predicate | |||
2007 | .addImm(ARMCC::AL) | |||
2008 | .addReg(0)); | |||
2009 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi12) | |||
2010 | .addReg(ARM::SP) | |||
2011 | .addReg(SrcReg) | |||
2012 | .addImm(8) | |||
2013 | // Predicate | |||
2014 | .addImm(ARMCC::AL) | |||
2015 | .addReg(0)); | |||
2016 | EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi12) | |||
2017 | .addReg(ARM::PC) | |||
2018 | .addReg(SrcReg) | |||
2019 | .addImm(4) | |||
2020 | // Predicate | |||
2021 | .addImm(ARMCC::AL) | |||
2022 | .addReg(0)); | |||
2023 | return; | |||
2024 | } | |||
2025 | case ARM::PATCHABLE_FUNCTION_ENTER: | |||
2026 | LowerPATCHABLE_FUNCTION_ENTER(*MI); | |||
2027 | return; | |||
2028 | case ARM::PATCHABLE_FUNCTION_EXIT: | |||
2029 | LowerPATCHABLE_FUNCTION_EXIT(*MI); | |||
2030 | return; | |||
2031 | case ARM::PATCHABLE_TAIL_CALL: | |||
2032 | LowerPATCHABLE_TAIL_CALL(*MI); | |||
2033 | return; | |||
2034 | } | |||
2035 | ||||
2036 | MCInst TmpInst; | |||
2037 | LowerARMMachineInstrToMCInst(MI, TmpInst, *this); | |||
2038 | ||||
2039 | EmitToStreamer(*OutStreamer, TmpInst); | |||
2040 | } | |||
2041 | ||||
2042 | //===----------------------------------------------------------------------===// | |||
2043 | // Target Registry Stuff | |||
2044 | //===----------------------------------------------------------------------===// | |||
2045 | ||||
2046 | // Force static initialization. | |||
2047 | extern "C" void LLVMInitializeARMAsmPrinter() { | |||
2048 | RegisterAsmPrinter<ARMAsmPrinter> X(getTheARMLETarget()); | |||
2049 | RegisterAsmPrinter<ARMAsmPrinter> Y(getTheARMBETarget()); | |||
2050 | RegisterAsmPrinter<ARMAsmPrinter> A(getTheThumbLETarget()); | |||
2051 | RegisterAsmPrinter<ARMAsmPrinter> B(getTheThumbBETarget()); | |||
2052 | } |
1 | //===- llvm/InlineAsm.h - Class to represent inline asm strings -*- C++ -*-===// |
2 | // |
3 | // The LLVM Compiler Infrastructure |
4 | // |
5 | // This file is distributed under the University of Illinois Open Source |
6 | // License. See LICENSE.TXT for details. |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | // |
10 | // This class represents the inline asm strings, which are Value*'s that are |
11 | // used as the callee operand of call instructions. InlineAsm's are uniqued |
12 | // like constants, and created via InlineAsm::get(...). |
13 | // |
14 | //===----------------------------------------------------------------------===// |
15 | |
16 | #ifndef LLVM_IR_INLINEASM_H |
17 | #define LLVM_IR_INLINEASM_H |
18 | |
19 | #include "llvm/ADT/StringRef.h" |
20 | #include "llvm/IR/Value.h" |
21 | #include <cassert> |
22 | #include <string> |
23 | #include <vector> |
24 | |
25 | namespace llvm { |
26 | |
27 | class FunctionType; |
28 | class PointerType; |
29 | template <class ConstantClass> class ConstantUniqueMap; |
30 | |
31 | class InlineAsm final : public Value { |
32 | public: |
33 | enum AsmDialect { |
34 | AD_ATT, |
35 | AD_Intel |
36 | }; |
37 | |
38 | private: |
39 | friend struct InlineAsmKeyType; |
40 | friend class ConstantUniqueMap<InlineAsm>; |
41 | |
42 | std::string AsmString, Constraints; |
43 | FunctionType *FTy; |
44 | bool HasSideEffects; |
45 | bool IsAlignStack; |
46 | AsmDialect Dialect; |
47 | |
48 | InlineAsm(FunctionType *Ty, const std::string &AsmString, |
49 | const std::string &Constraints, bool hasSideEffects, |
50 | bool isAlignStack, AsmDialect asmDialect); |
51 | |
52 | /// When the ConstantUniqueMap merges two types and makes two InlineAsms |
53 | /// identical, it destroys one of them with this method. |
54 | void destroyConstant(); |
55 | |
56 | public: |
57 | InlineAsm(const InlineAsm &) = delete; |
58 | InlineAsm &operator=(const InlineAsm &) = delete; |
59 | |
60 | /// InlineAsm::get - Return the specified uniqued inline asm string. |
61 | /// |
62 | static InlineAsm *get(FunctionType *Ty, StringRef AsmString, |
63 | StringRef Constraints, bool hasSideEffects, |
64 | bool isAlignStack = false, |
65 | AsmDialect asmDialect = AD_ATT); |
66 | |
67 | bool hasSideEffects() const { return HasSideEffects; } |
68 | bool isAlignStack() const { return IsAlignStack; } |
69 | AsmDialect getDialect() const { return Dialect; } |
70 | |
71 | /// getType - InlineAsm's are always pointers. |
72 | /// |
73 | PointerType *getType() const { |
74 | return reinterpret_cast<PointerType*>(Value::getType()); |
75 | } |
76 | |
77 | /// getFunctionType - InlineAsm's are always pointers to functions. |
78 | /// |
79 | FunctionType *getFunctionType() const; |
80 | |
81 | const std::string &getAsmString() const { return AsmString; } |
82 | const std::string &getConstraintString() const { return Constraints; } |
83 | |
84 | /// Verify - This static method can be used by the parser to check to see if |
85 | /// the specified constraint string is legal for the type. This returns true |
86 | /// if legal, false if not. |
87 | /// |
88 | static bool Verify(FunctionType *Ty, StringRef Constraints); |
89 | |
90 | // Constraint String Parsing |
91 | enum ConstraintPrefix { |
92 | isInput, // 'x' |
93 | isOutput, // '=x' |
94 | isClobber // '~x' |
95 | }; |
96 | |
97 | using ConstraintCodeVector = std::vector<std::string>; |
98 | |
99 | struct SubConstraintInfo { |
100 | /// MatchingInput - If this is not -1, this is an output constraint where an |
101 | /// input constraint is required to match it (e.g. "0"). The value is the |
102 | /// constraint number that matches this one (for example, if this is |
103 | /// constraint #0 and constraint #4 has the value "0", this will be 4). |
104 | int MatchingInput = -1; |
105 | |
106 | /// Code - The constraint code, either the register name (in braces) or the |
107 | /// constraint letter/number. |
108 | ConstraintCodeVector Codes; |
109 | |
110 | /// Default constructor. |
111 | SubConstraintInfo() = default; |
112 | }; |
113 | |
114 | using SubConstraintInfoVector = std::vector<SubConstraintInfo>; |
115 | struct ConstraintInfo; |
116 | using ConstraintInfoVector = std::vector<ConstraintInfo>; |
117 | |
118 | struct ConstraintInfo { |
119 | /// Type - The basic type of the constraint: input/output/clobber |
120 | /// |
121 | ConstraintPrefix Type = isInput; |
122 | |
123 | /// isEarlyClobber - "&": output operand writes result before inputs are all |
124 | /// read. This is only ever set for an output operand. |
125 | bool isEarlyClobber = false; |
126 | |
127 | /// MatchingInput - If this is not -1, this is an output constraint where an |
128 | /// input constraint is required to match it (e.g. "0"). The value is the |
129 | /// constraint number that matches this one (for example, if this is |
130 | /// constraint #0 and constraint #4 has the value "0", this will be 4). |
131 | int MatchingInput = -1; |
132 | |
133 | /// hasMatchingInput - Return true if this is an output constraint that has |
134 | /// a matching input constraint. |
135 | bool hasMatchingInput() const { return MatchingInput != -1; } |
136 | |
137 | /// isCommutative - This is set to true for a constraint that is commutative |
138 | /// with the next operand. |
139 | bool isCommutative = false; |
140 | |
141 | /// isIndirect - True if this operand is an indirect operand. This means |
142 | /// that the address of the source or destination is present in the call |
143 | /// instruction, instead of it being returned or passed in explicitly. This |
144 | /// is represented with a '*' in the asm string. |
145 | bool isIndirect = false; |
146 | |
147 | /// Code - The constraint code, either the register name (in braces) or the |
148 | /// constraint letter/number. |
149 | ConstraintCodeVector Codes; |
150 | |
151 | /// isMultipleAlternative - '|': has multiple-alternative constraints. |
152 | bool isMultipleAlternative = false; |
153 | |
154 | /// multipleAlternatives - If there are multiple alternative constraints, |
155 | /// this array will contain them. Otherwise it will be empty. |
156 | SubConstraintInfoVector multipleAlternatives; |
157 | |
158 | /// The currently selected alternative constraint index. |
159 | unsigned currentAlternativeIndex = 0; |
160 | |
161 | /// Default constructor. |
162 | ConstraintInfo() = default; |
163 | |
164 | /// Parse - Analyze the specified string (e.g. "=*&{eax}") and fill in the |
165 | /// fields in this structure. If the constraint string is not understood, |
166 | /// return true, otherwise return false. |
167 | bool Parse(StringRef Str, ConstraintInfoVector &ConstraintsSoFar); |
168 | |
169 | /// selectAlternative - Point this constraint to the alternative constraint |
170 | /// indicated by the index. |
171 | void selectAlternative(unsigned index); |
172 | }; |
173 | |
174 | /// ParseConstraints - Split up the constraint string into the specific |
175 | /// constraints and their prefixes. If this returns an empty vector, and if |
176 | /// the constraint string itself isn't empty, there was an error parsing. |
177 | static ConstraintInfoVector ParseConstraints(StringRef ConstraintString); |
178 | |
179 | /// ParseConstraints - Parse the constraints of this inlineasm object, |
180 | /// returning them the same way that ParseConstraints(str) does. |
181 | ConstraintInfoVector ParseConstraints() const { |
182 | return ParseConstraints(Constraints); |
183 | } |
184 | |
185 | // Methods for support type inquiry through isa, cast, and dyn_cast: |
186 | static bool classof(const Value *V) { |
187 | return V->getValueID() == Value::InlineAsmVal; |
188 | } |
189 | |
190 | // These are helper methods for dealing with flags in the INLINEASM SDNode |
191 | // in the backend. |
192 | // |
193 | // The encoding of the flag word is currently: |
194 | // Bits 2-0 - A Kind_* value indicating the kind of the operand. |
195 | // Bits 15-3 - The number of SDNode operands associated with this inline |
196 | // assembly operand. |
197 | // If bit 31 is set: |
198 | // Bit 30-16 - The operand number that this operand must match. |
199 | // When bits 2-0 are Kind_Mem, the Constraint_* value must be |
200 | // obtained from the flags for this operand number. |
201 | // Else if bits 2-0 are Kind_Mem: |
202 | // Bit 30-16 - A Constraint_* value indicating the original constraint |
203 | // code. |
204 | // Else: |
205 | // Bit 30-16 - The register class ID to use for the operand. |
206 | |
207 | enum : uint32_t { |
208 | // Fixed operands on an INLINEASM SDNode. |
209 | Op_InputChain = 0, |
210 | Op_AsmString = 1, |
211 | Op_MDNode = 2, |
212 | Op_ExtraInfo = 3, // HasSideEffects, IsAlignStack, AsmDialect. |
213 | Op_FirstOperand = 4, |
214 | |
215 | // Fixed operands on an INLINEASM MachineInstr. |
216 | MIOp_AsmString = 0, |
217 | MIOp_ExtraInfo = 1, // HasSideEffects, IsAlignStack, AsmDialect. |
218 | MIOp_FirstOperand = 2, |
219 | |
220 | // Interpretation of the MIOp_ExtraInfo bit field. |
221 | Extra_HasSideEffects = 1, |
222 | Extra_IsAlignStack = 2, |
223 | Extra_AsmDialect = 4, |
224 | Extra_MayLoad = 8, |
225 | Extra_MayStore = 16, |
226 | Extra_IsConvergent = 32, |
227 | |
228 | // Inline asm operands map to multiple SDNode / MachineInstr operands. |
229 | // The first operand is an immediate describing the asm operand, the low |
230 | // bits is the kind: |
231 | Kind_RegUse = 1, // Input register, "r". |
232 | Kind_RegDef = 2, // Output register, "=r". |
233 | Kind_RegDefEarlyClobber = 3, // Early-clobber output register, "=&r". |
234 | Kind_Clobber = 4, // Clobbered register, "~r". |
235 | Kind_Imm = 5, // Immediate. |
236 | Kind_Mem = 6, // Memory operand, "m". |
237 | |
238 | // Memory constraint codes. |
239 | // These could be tablegenerated but there's little need to do that since |
240 | // there's plenty of space in the encoding to support the union of all |
241 | // constraint codes for all targets. |
242 | Constraint_Unknown = 0, |
243 | Constraint_es, |
244 | Constraint_i, |
245 | Constraint_m, |
246 | Constraint_o, |
247 | Constraint_v, |
248 | Constraint_Q, |
249 | Constraint_R, |
250 | Constraint_S, |
251 | Constraint_T, |
252 | Constraint_Um, |
253 | Constraint_Un, |
254 | Constraint_Uq, |
255 | Constraint_Us, |
256 | Constraint_Ut, |
257 | Constraint_Uv, |
258 | Constraint_Uy, |
259 | Constraint_X, |
260 | Constraint_Z, |
261 | Constraint_ZC, |
262 | Constraint_Zy, |
263 | Constraints_Max = Constraint_Zy, |
264 | Constraints_ShiftAmount = 16, |
265 | |
266 | Flag_MatchingOperand = 0x80000000 |
267 | }; |
268 | |
269 | static unsigned getFlagWord(unsigned Kind, unsigned NumOps) { |
270 | assert(((NumOps << 3) & ~0xffff) == 0 && "Too many inline asm operands!")(static_cast <bool> (((NumOps << 3) & ~0xffff ) == 0 && "Too many inline asm operands!") ? void (0) : __assert_fail ("((NumOps << 3) & ~0xffff) == 0 && \"Too many inline asm operands!\"" , "/build/llvm-toolchain-snapshot-7~svn338205/include/llvm/IR/InlineAsm.h" , 270, __extension__ __PRETTY_FUNCTION__)); |
271 | assert(Kind >= Kind_RegUse && Kind <= Kind_Mem && "Invalid Kind")(static_cast <bool> (Kind >= Kind_RegUse && Kind <= Kind_Mem && "Invalid Kind") ? void (0) : __assert_fail ("Kind >= Kind_RegUse && Kind <= Kind_Mem && \"Invalid Kind\"" , "/build/llvm-toolchain-snapshot-7~svn338205/include/llvm/IR/InlineAsm.h" , 271, __extension__ __PRETTY_FUNCTION__)); |
272 | return Kind | (NumOps << 3); |
273 | } |
274 | |
275 | static bool isRegDefKind(unsigned Flag){ return getKind(Flag) == Kind_RegDef;} |
276 | static bool isImmKind(unsigned Flag) { return getKind(Flag) == Kind_Imm; } |
277 | static bool isMemKind(unsigned Flag) { return getKind(Flag) == Kind_Mem; } |
278 | static bool isRegDefEarlyClobberKind(unsigned Flag) { |
279 | return getKind(Flag) == Kind_RegDefEarlyClobber; |
280 | } |
281 | static bool isClobberKind(unsigned Flag) { |
282 | return getKind(Flag) == Kind_Clobber; |
283 | } |
284 | |
285 | /// getFlagWordForMatchingOp - Augment an existing flag word returned by |
286 | /// getFlagWord with information indicating that this input operand is tied |
287 | /// to a previous output operand. |
288 | static unsigned getFlagWordForMatchingOp(unsigned InputFlag, |
289 | unsigned MatchedOperandNo) { |
290 | assert(MatchedOperandNo <= 0x7fff && "Too big matched operand")(static_cast <bool> (MatchedOperandNo <= 0x7fff && "Too big matched operand") ? void (0) : __assert_fail ("MatchedOperandNo <= 0x7fff && \"Too big matched operand\"" , "/build/llvm-toolchain-snapshot-7~svn338205/include/llvm/IR/InlineAsm.h" , 290, __extension__ __PRETTY_FUNCTION__)); |
291 | assert((InputFlag & ~0xffff) == 0 && "High bits already contain data")(static_cast <bool> ((InputFlag & ~0xffff) == 0 && "High bits already contain data") ? void (0) : __assert_fail ("(InputFlag & ~0xffff) == 0 && \"High bits already contain data\"" , "/build/llvm-toolchain-snapshot-7~svn338205/include/llvm/IR/InlineAsm.h" , 291, __extension__ __PRETTY_FUNCTION__)); |
292 | return InputFlag | Flag_MatchingOperand | (MatchedOperandNo << 16); |
293 | } |
294 | |
295 | /// getFlagWordForRegClass - Augment an existing flag word returned by |
296 | /// getFlagWord with the required register class for the following register |
297 | /// operands. |
298 | /// A tied use operand cannot have a register class, use the register class |
299 | /// from the def operand instead. |
300 | static unsigned getFlagWordForRegClass(unsigned InputFlag, unsigned RC) { |
301 | // Store RC + 1, reserve the value 0 to mean 'no register class'. |
302 | ++RC; |
303 | assert(!isImmKind(InputFlag) && "Immediates cannot have a register class")(static_cast <bool> (!isImmKind(InputFlag) && "Immediates cannot have a register class" ) ? void (0) : __assert_fail ("!isImmKind(InputFlag) && \"Immediates cannot have a register class\"" , "/build/llvm-toolchain-snapshot-7~svn338205/include/llvm/IR/InlineAsm.h" , 303, __extension__ __PRETTY_FUNCTION__)); |
304 | assert(!isMemKind(InputFlag) && "Memory operand cannot have a register class")(static_cast <bool> (!isMemKind(InputFlag) && "Memory operand cannot have a register class" ) ? void (0) : __assert_fail ("!isMemKind(InputFlag) && \"Memory operand cannot have a register class\"" , "/build/llvm-toolchain-snapshot-7~svn338205/include/llvm/IR/InlineAsm.h" , 304, __extension__ __PRETTY_FUNCTION__)); |
305 | assert(RC <= 0x7fff && "Too large register class ID")(static_cast <bool> (RC <= 0x7fff && "Too large register class ID" ) ? void (0) : __assert_fail ("RC <= 0x7fff && \"Too large register class ID\"" , "/build/llvm-toolchain-snapshot-7~svn338205/include/llvm/IR/InlineAsm.h" , 305, __extension__ __PRETTY_FUNCTION__)); |
306 | assert((InputFlag & ~0xffff) == 0 && "High bits already contain data")(static_cast <bool> ((InputFlag & ~0xffff) == 0 && "High bits already contain data") ? void (0) : __assert_fail ("(InputFlag & ~0xffff) == 0 && \"High bits already contain data\"" , "/build/llvm-toolchain-snapshot-7~svn338205/include/llvm/IR/InlineAsm.h" , 306, __extension__ __PRETTY_FUNCTION__)); |
307 | return InputFlag | (RC << 16); |
308 | } |
309 | |
310 | /// Augment an existing flag word returned by getFlagWord with the constraint |
311 | /// code for a memory constraint. |
312 | static unsigned getFlagWordForMem(unsigned InputFlag, unsigned Constraint) { |
313 | assert(isMemKind(InputFlag) && "InputFlag is not a memory constraint!")(static_cast <bool> (isMemKind(InputFlag) && "InputFlag is not a memory constraint!" ) ? void (0) : __assert_fail ("isMemKind(InputFlag) && \"InputFlag is not a memory constraint!\"" , "/build/llvm-toolchain-snapshot-7~svn338205/include/llvm/IR/InlineAsm.h" , 313, __extension__ __PRETTY_FUNCTION__)); |
314 | assert(Constraint <= 0x7fff && "Too large a memory constraint ID")(static_cast <bool> (Constraint <= 0x7fff && "Too large a memory constraint ID") ? void (0) : __assert_fail ("Constraint <= 0x7fff && \"Too large a memory constraint ID\"" , "/build/llvm-toolchain-snapshot-7~svn338205/include/llvm/IR/InlineAsm.h" , 314, __extension__ __PRETTY_FUNCTION__)); |
315 | assert(Constraint <= Constraints_Max && "Unknown constraint ID")(static_cast <bool> (Constraint <= Constraints_Max && "Unknown constraint ID") ? void (0) : __assert_fail ("Constraint <= Constraints_Max && \"Unknown constraint ID\"" , "/build/llvm-toolchain-snapshot-7~svn338205/include/llvm/IR/InlineAsm.h" , 315, __extension__ __PRETTY_FUNCTION__)); |
316 | assert((InputFlag & ~0xffff) == 0 && "High bits already contain data")(static_cast <bool> ((InputFlag & ~0xffff) == 0 && "High bits already contain data") ? void (0) : __assert_fail ("(InputFlag & ~0xffff) == 0 && \"High bits already contain data\"" , "/build/llvm-toolchain-snapshot-7~svn338205/include/llvm/IR/InlineAsm.h" , 316, __extension__ __PRETTY_FUNCTION__)); |
317 | return InputFlag | (Constraint << Constraints_ShiftAmount); |
318 | } |
319 | |
320 | static unsigned convertMemFlagWordToMatchingFlagWord(unsigned InputFlag) { |
321 | assert(isMemKind(InputFlag))(static_cast <bool> (isMemKind(InputFlag)) ? void (0) : __assert_fail ("isMemKind(InputFlag)", "/build/llvm-toolchain-snapshot-7~svn338205/include/llvm/IR/InlineAsm.h" , 321, __extension__ __PRETTY_FUNCTION__)); |
322 | return InputFlag & ~(0x7fff << Constraints_ShiftAmount); |
323 | } |
324 | |
325 | static unsigned getKind(unsigned Flags) { |
326 | return Flags & 7; |
327 | } |
328 | |
329 | static unsigned getMemoryConstraintID(unsigned Flag) { |
330 | assert(isMemKind(Flag))(static_cast <bool> (isMemKind(Flag)) ? void (0) : __assert_fail ("isMemKind(Flag)", "/build/llvm-toolchain-snapshot-7~svn338205/include/llvm/IR/InlineAsm.h" , 330, __extension__ __PRETTY_FUNCTION__)); |
331 | return (Flag >> Constraints_ShiftAmount) & 0x7fff; |
332 | } |
333 | |
334 | /// getNumOperandRegisters - Extract the number of registers field from the |
335 | /// inline asm operand flag. |
336 | static unsigned getNumOperandRegisters(unsigned Flag) { |
337 | return (Flag & 0xffff) >> 3; |
338 | } |
339 | |
340 | /// isUseOperandTiedToDef - Return true if the flag of the inline asm |
341 | /// operand indicates it is an use operand that's matched to a def operand. |
342 | static bool isUseOperandTiedToDef(unsigned Flag, unsigned &Idx) { |
343 | if ((Flag & Flag_MatchingOperand) == 0) |
344 | return false; |
345 | Idx = (Flag & ~Flag_MatchingOperand) >> 16; |
346 | return true; |
347 | } |
348 | |
349 | /// hasRegClassConstraint - Returns true if the flag contains a register |
350 | /// class constraint. Sets RC to the register class ID. |
351 | static bool hasRegClassConstraint(unsigned Flag, unsigned &RC) { |
352 | if (Flag & Flag_MatchingOperand) |
353 | return false; |
354 | unsigned High = Flag >> 16; |
355 | // getFlagWordForRegClass() uses 0 to mean no register class, and otherwise |
356 | // stores RC + 1. |
357 | if (!High) |
358 | return false; |
359 | RC = High - 1; |
360 | return true; |
361 | } |
362 | }; |
363 | |
364 | } // end namespace llvm |
365 | |
366 | #endif // LLVM_IR_INLINEASM_H |