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