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