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/ARMInstPrinter.h"
21#include "MCTargetDesc/ARMMCAsmInfo.h"
22#include "TargetInfo/ARMTargetInfo.h"
23#include "llvm/ADT/SmallString.h"
24#include "llvm/BinaryFormat/COFF.h"
25#include "llvm/CodeGen/MachineJumpTableInfo.h"
26#include "llvm/CodeGen/MachineModuleInfoImpls.h"
27#include "llvm/IR/Constants.h"
28#include "llvm/IR/DataLayout.h"
29#include "llvm/IR/Mangler.h"
30#include "llvm/IR/Module.h"
31#include "llvm/IR/Type.h"
32#include "llvm/MC/MCAsmInfo.h"
33#include "llvm/MC/MCAssembler.h"
34#include "llvm/MC/MCContext.h"
35#include "llvm/MC/MCELFStreamer.h"
36#include "llvm/MC/MCInst.h"
37#include "llvm/MC/MCInstBuilder.h"
38#include "llvm/MC/MCObjectStreamer.h"
39#include "llvm/MC/MCStreamer.h"
40#include "llvm/MC/MCSymbol.h"
41#include "llvm/MC/TargetRegistry.h"
42#include "llvm/Support/ARMBuildAttributes.h"
43#include "llvm/Support/Compiler.h"
44#include "llvm/Support/Debug.h"
45#include "llvm/Support/ErrorHandling.h"
46#include "llvm/Support/raw_ostream.h"
47#include "llvm/Target/TargetMachine.h"
48using namespace llvm;
49
50#define DEBUG_TYPE "asm-printer"
51
52ARMAsmPrinter::ARMAsmPrinter(TargetMachine &TM,
53 std::unique_ptr<MCStreamer> Streamer)
54 : AsmPrinter(TM, std::move(Streamer), ID), AFI(nullptr), MCP(nullptr),
55 InConstantPool(false), OptimizationGoals(-1) {}
56
57const ARMBaseTargetMachine &ARMAsmPrinter::getTM() const {
58 return static_cast<const ARMBaseTargetMachine &>(TM);
59}
60
61void ARMAsmPrinter::emitFunctionBodyEnd() {
62 // Make sure to terminate any constant pools that were at the end
63 // of the function.
64 if (!InConstantPool)
65 return;
66 InConstantPool = false;
67 OutStreamer->emitDataRegion(Kind: MCDR_DataRegionEnd);
68}
69
70void ARMAsmPrinter::emitFunctionEntryLabel() {
71 auto &TS =
72 static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());
73 if (AFI->isThumbFunction()) {
74 TS.emitCode16();
75 TS.emitThumbFunc(Symbol: CurrentFnSym);
76 } else {
77 TS.emitCode32();
78 }
79
80 // Emit symbol for CMSE non-secure entry point
81 if (AFI->isCmseNSEntryFunction()) {
82 MCSymbol *S =
83 OutContext.getOrCreateSymbol(Name: "__acle_se_" + CurrentFnSym->getName());
84 emitLinkage(GV: &MF->getFunction(), GVSym: S);
85 OutStreamer->emitSymbolAttribute(Symbol: S, Attribute: MCSA_ELF_TypeFunction);
86 OutStreamer->emitLabel(Symbol: S);
87 }
88 AsmPrinter::emitFunctionEntryLabel();
89}
90
91void ARMAsmPrinter::emitXXStructor(const DataLayout &DL, const Constant *CV) {
92 uint64_t Size = getDataLayout().getTypeAllocSize(Ty: CV->getType());
93 assert(Size && "C++ constructor pointer had zero size!");
94
95 const GlobalValue *GV = dyn_cast<GlobalValue>(Val: CV->stripPointerCasts());
96 assert(GV && "C++ constructor pointer was not a GlobalValue!");
97
98 const MCExpr *E = MCSymbolRefExpr::create(
99 Symbol: GetARMGVSymbol(GV, TargetFlags: ARMII::MO_NO_FLAG),
100 specifier: (TM.getTargetTriple().isOSBinFormatELF() ? ARM::S_TARGET1 : ARM::S_None),
101 Ctx&: OutContext);
102
103 OutStreamer->emitValue(Value: E, Size);
104}
105
106// An alias to a cmse entry function should also emit a `__acle_se_` symbol.
107void ARMAsmPrinter::emitCMSEVeneerAlias(const GlobalAlias &GA) {
108 const Function *BaseFn = dyn_cast_or_null<Function>(Val: GA.getAliaseeObject());
109 if (!BaseFn || !BaseFn->hasFnAttribute(Kind: "cmse_nonsecure_entry"))
110 return;
111
112 MCSymbol *AliasSym = getSymbol(GV: &GA);
113 MCSymbol *FnSym = getSymbol(GV: BaseFn);
114
115 MCSymbol *SEAliasSym =
116 OutContext.getOrCreateSymbol(Name: Twine("__acle_se_") + AliasSym->getName());
117 MCSymbol *SEBaseSym =
118 OutContext.getOrCreateSymbol(Name: Twine("__acle_se_") + FnSym->getName());
119
120 // Mirror alias linkage/visibility onto the veneer-alias symbol.
121 emitLinkage(GV: &GA, GVSym: SEAliasSym);
122 OutStreamer->emitSymbolAttribute(Symbol: SEAliasSym, Attribute: MCSA_ELF_TypeFunction);
123 emitVisibility(Sym: SEAliasSym, Visibility: GA.getVisibility());
124
125 // emit "__acle_se_<alias> = __acle_se_<aliasee>"
126 const MCExpr *SEExpr = MCSymbolRefExpr::create(Symbol: SEBaseSym, Ctx&: OutContext);
127 OutStreamer->emitAssignment(Symbol: SEAliasSym, Value: SEExpr);
128}
129
130void ARMAsmPrinter::emitGlobalAlias(const Module &M, const GlobalAlias &GA) {
131 AsmPrinter::emitGlobalAlias(M, GA);
132 emitCMSEVeneerAlias(GA);
133}
134
135void ARMAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
136 if (PromotedGlobals.count(Ptr: GV))
137 // The global was promoted into a constant pool. It should not be emitted.
138 return;
139 AsmPrinter::emitGlobalVariable(GV);
140}
141
142/// runOnMachineFunction - This uses the emitInstruction()
143/// method to print assembly for each instruction.
144///
145bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
146 AFI = MF.getInfo<ARMFunctionInfo>();
147 MCP = MF.getConstantPool();
148
149 SetupMachineFunction(MF);
150 const Function &F = MF.getFunction();
151 const TargetMachine& TM = MF.getTarget();
152
153 // Collect all globals that had their storage promoted to a constant pool.
154 // Functions are emitted before variables, so this accumulates promoted
155 // globals from all functions in PromotedGlobals.
156 PromotedGlobals.insert_range(R&: AFI->getGlobalsPromotedToConstantPool());
157
158 // Calculate this function's optimization goal.
159 unsigned OptimizationGoal;
160 if (F.hasOptNone())
161 // For best debugging illusion, speed and small size sacrificed
162 OptimizationGoal = 6;
163 else if (F.hasMinSize())
164 // Aggressively for small size, speed and debug illusion sacrificed
165 OptimizationGoal = 4;
166 else if (F.hasOptSize())
167 // For small size, but speed and debugging illusion preserved
168 OptimizationGoal = 3;
169 else if (TM.getOptLevel() == CodeGenOptLevel::Aggressive)
170 // Aggressively for speed, small size and debug illusion sacrificed
171 OptimizationGoal = 2;
172 else if (TM.getOptLevel() > CodeGenOptLevel::None)
173 // For speed, but small size and good debug illusion preserved
174 OptimizationGoal = 1;
175 else // TM.getOptLevel() == CodeGenOptLevel::None
176 // For good debugging, but speed and small size preserved
177 OptimizationGoal = 5;
178
179 // Combine a new optimization goal with existing ones.
180 if (OptimizationGoals == -1) // uninitialized goals
181 OptimizationGoals = OptimizationGoal;
182 else if (OptimizationGoals != (int)OptimizationGoal) // conflicting goals
183 OptimizationGoals = 0;
184
185 if (TM.getTargetTriple().isOSBinFormatCOFF()) {
186 bool Local = F.hasLocalLinkage();
187 COFF::SymbolStorageClass Scl =
188 Local ? COFF::IMAGE_SYM_CLASS_STATIC : COFF::IMAGE_SYM_CLASS_EXTERNAL;
189 int Type = COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT;
190
191 OutStreamer->beginCOFFSymbolDef(Symbol: CurrentFnSym);
192 OutStreamer->emitCOFFSymbolStorageClass(StorageClass: Scl);
193 OutStreamer->emitCOFFSymbolType(Type);
194 OutStreamer->endCOFFSymbolDef();
195 }
196
197 // Emit the rest of the function body.
198 emitFunctionBody();
199
200 // Emit the XRay table for this function.
201 emitXRayTable();
202
203 // If we need V4T thumb mode Register Indirect Jump pads, emit them.
204 // These are created per function, rather than per TU, since it's
205 // relatively easy to exceed the thumb branch range within a TU.
206 if (! ThumbIndirectPads.empty()) {
207 auto &TS =
208 static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());
209 TS.emitCode16();
210 emitAlignment(Alignment: Align(2));
211 for (std::pair<unsigned, MCSymbol *> &TIP : ThumbIndirectPads) {
212 OutStreamer->emitLabel(Symbol: TIP.second);
213 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tBX)
214 .addReg(Reg: TIP.first)
215 // Add predicate operands.
216 .addImm(Val: ARMCC::AL)
217 .addReg(Reg: 0));
218 }
219 ThumbIndirectPads.clear();
220 }
221
222 // We didn't modify anything.
223 return false;
224}
225
226void ARMAsmPrinter::PrintSymbolOperand(const MachineOperand &MO,
227 raw_ostream &O) {
228 assert(MO.isGlobal() && "caller should check MO.isGlobal");
229 unsigned TF = MO.getTargetFlags();
230 if (TF & ARMII::MO_LO16)
231 O << ":lower16:";
232 else if (TF & ARMII::MO_HI16)
233 O << ":upper16:";
234 else if (TF & ARMII::MO_LO_0_7)
235 O << ":lower0_7:";
236 else if (TF & ARMII::MO_LO_8_15)
237 O << ":lower8_15:";
238 else if (TF & ARMII::MO_HI_0_7)
239 O << ":upper0_7:";
240 else if (TF & ARMII::MO_HI_8_15)
241 O << ":upper8_15:";
242
243 GetARMGVSymbol(GV: MO.getGlobal(), TargetFlags: TF)->print(OS&: O, MAI);
244 printOffset(Offset: MO.getOffset(), OS&: O);
245}
246
247void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
248 raw_ostream &O) {
249 const MachineOperand &MO = MI->getOperand(i: OpNum);
250
251 switch (MO.getType()) {
252 default: llvm_unreachable("<unknown operand type>");
253 case MachineOperand::MO_Register: {
254 Register Reg = MO.getReg();
255 assert(Reg.isPhysical());
256 assert(!MO.getSubReg() && "Subregs should be eliminated!");
257 if(ARM::GPRPairRegClass.contains(Reg)) {
258 const MachineFunction &MF = *MI->getParent()->getParent();
259 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
260 Reg = TRI->getSubReg(Reg, Idx: ARM::gsub_0);
261 }
262 O << ARMInstPrinter::getRegisterName(Reg);
263 break;
264 }
265 case MachineOperand::MO_Immediate: {
266 O << '#';
267 unsigned TF = MO.getTargetFlags();
268 if (TF == ARMII::MO_LO16)
269 O << ":lower16:";
270 else if (TF == ARMII::MO_HI16)
271 O << ":upper16:";
272 else if (TF == ARMII::MO_LO_0_7)
273 O << ":lower0_7:";
274 else if (TF == ARMII::MO_LO_8_15)
275 O << ":lower8_15:";
276 else if (TF == ARMII::MO_HI_0_7)
277 O << ":upper0_7:";
278 else if (TF == ARMII::MO_HI_8_15)
279 O << ":upper8_15:";
280 O << MO.getImm();
281 break;
282 }
283 case MachineOperand::MO_MachineBasicBlock:
284 MO.getMBB()->getSymbol()->print(OS&: O, MAI);
285 return;
286 case MachineOperand::MO_GlobalAddress: {
287 PrintSymbolOperand(MO, O);
288 break;
289 }
290 case MachineOperand::MO_ConstantPoolIndex:
291 assert(!MF->getSubtarget<ARMSubtarget>().genExecuteOnly() &&
292 "execute-only should not generate constant pools");
293 GetCPISymbol(CPID: MO.getIndex())->print(OS&: O, MAI);
294 break;
295 }
296}
297
298MCSymbol *ARMAsmPrinter::GetCPISymbol(unsigned CPID) const {
299 // The AsmPrinter::GetCPISymbol superclass method tries to use CPID as
300 // indexes in MachineConstantPool, which isn't in sync with indexes used here.
301 const DataLayout &DL = getDataLayout();
302 return OutContext.getOrCreateSymbol(Name: Twine(DL.getInternalSymbolPrefix()) +
303 "CPI" + Twine(getFunctionNumber()) + "_" +
304 Twine(CPID));
305}
306
307//===--------------------------------------------------------------------===//
308
309MCSymbol *ARMAsmPrinter::
310GetARMJTIPICJumpTableLabel(unsigned uid) const {
311 const DataLayout &DL = getDataLayout();
312 SmallString<60> Name;
313 raw_svector_ostream(Name) << DL.getInternalSymbolPrefix() << "JTI"
314 << getFunctionNumber() << '_' << uid;
315 return OutContext.getOrCreateSymbol(Name);
316}
317
318bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
319 const char *ExtraCode, raw_ostream &O) {
320 // Does this asm operand have a single letter operand modifier?
321 if (ExtraCode && ExtraCode[0]) {
322 if (ExtraCode[1] != 0) return true; // Unknown modifier.
323
324 switch (ExtraCode[0]) {
325 default:
326 // See if this is a generic print operand
327 return AsmPrinter::PrintAsmOperand(MI, OpNo: OpNum, ExtraCode, OS&: O);
328 case 'P': // Print a VFP double precision register.
329 case 'q': // Print a NEON quad precision register.
330 printOperand(MI, OpNum, O);
331 return false;
332 case 'y': // Print a VFP single precision register as indexed double.
333 if (MI->getOperand(i: OpNum).isReg()) {
334 MCRegister Reg = MI->getOperand(i: OpNum).getReg().asMCReg();
335 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
336 // Find the 'd' register that has this 's' register as a sub-register,
337 // and determine the lane number.
338 for (MCPhysReg SR : TRI->superregs(Reg)) {
339 if (!ARM::DPRRegClass.contains(Reg: SR))
340 continue;
341 bool Lane0 = TRI->getSubReg(Reg: SR, Idx: ARM::ssub_0) == Reg;
342 O << ARMInstPrinter::getRegisterName(Reg: SR) << (Lane0 ? "[0]" : "[1]");
343 return false;
344 }
345 }
346 return true;
347 case 'B': // Bitwise inverse of integer or symbol without a preceding #.
348 if (!MI->getOperand(i: OpNum).isImm())
349 return true;
350 O << ~(MI->getOperand(i: OpNum).getImm());
351 return false;
352 case 'L': // The low 16 bits of an immediate constant.
353 if (!MI->getOperand(i: OpNum).isImm())
354 return true;
355 O << (MI->getOperand(i: OpNum).getImm() & 0xffff);
356 return false;
357 case 'M': { // A register range suitable for LDM/STM.
358 if (!MI->getOperand(i: OpNum).isReg())
359 return true;
360 const MachineOperand &MO = MI->getOperand(i: OpNum);
361 Register RegBegin = MO.getReg();
362 // This takes advantage of the 2 operand-ness of ldm/stm and that we've
363 // already got the operands in registers that are operands to the
364 // inline asm statement.
365 O << "{";
366 if (ARM::GPRPairRegClass.contains(Reg: RegBegin)) {
367 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
368 Register Reg0 = TRI->getSubReg(Reg: RegBegin, Idx: ARM::gsub_0);
369 O << ARMInstPrinter::getRegisterName(Reg: Reg0) << ", ";
370 RegBegin = TRI->getSubReg(Reg: RegBegin, Idx: ARM::gsub_1);
371 }
372 O << ARMInstPrinter::getRegisterName(Reg: RegBegin);
373
374 // FIXME: The register allocator not only may not have given us the
375 // registers in sequence, but may not be in ascending registers. This
376 // will require changes in the register allocator that'll need to be
377 // propagated down here if the operands change.
378 unsigned RegOps = OpNum + 1;
379 while (MI->getOperand(i: RegOps).isReg()) {
380 O << ", "
381 << ARMInstPrinter::getRegisterName(Reg: MI->getOperand(i: RegOps).getReg());
382 RegOps++;
383 }
384
385 O << "}";
386
387 return false;
388 }
389 case 'R': // The most significant register of a pair.
390 case 'Q': { // The least significant register of a pair.
391 if (OpNum == 0)
392 return true;
393 const MachineOperand &FlagsOP = MI->getOperand(i: OpNum - 1);
394 if (!FlagsOP.isImm())
395 return true;
396 InlineAsm::Flag F(FlagsOP.getImm());
397
398 // This operand may not be the one that actually provides the register. If
399 // it's tied to a previous one then we should refer instead to that one
400 // for registers and their classes.
401 unsigned TiedIdx;
402 if (F.isUseOperandTiedToDef(Idx&: TiedIdx)) {
403 for (OpNum = InlineAsm::MIOp_FirstOperand; TiedIdx; --TiedIdx) {
404 unsigned OpFlags = MI->getOperand(i: OpNum).getImm();
405 const InlineAsm::Flag F(OpFlags);
406 OpNum += F.getNumOperandRegisters() + 1;
407 }
408 F = InlineAsm::Flag(MI->getOperand(i: OpNum).getImm());
409
410 // Later code expects OpNum to be pointing at the register rather than
411 // the flags.
412 OpNum += 1;
413 }
414
415 const unsigned NumVals = F.getNumOperandRegisters();
416 unsigned RC;
417 bool FirstHalf;
418 const ARMBaseTargetMachine &ATM =
419 static_cast<const ARMBaseTargetMachine &>(TM);
420
421 // 'Q' should correspond to the low order register and 'R' to the high
422 // order register. Whether this corresponds to the upper or lower half
423 // depends on the endianness mode.
424 if (ExtraCode[0] == 'Q')
425 FirstHalf = ATM.isLittleEndian();
426 else
427 // ExtraCode[0] == 'R'.
428 FirstHalf = !ATM.isLittleEndian();
429 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
430 if (F.hasRegClassConstraint(RC) &&
431 ARM::GPRPairRegClass.hasSubClassEq(RC: TRI->getRegClass(i: RC))) {
432 if (NumVals != 1)
433 return true;
434 const MachineOperand &MO = MI->getOperand(i: OpNum);
435 if (!MO.isReg())
436 return true;
437 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
438 Register Reg =
439 TRI->getSubReg(Reg: MO.getReg(), Idx: FirstHalf ? ARM::gsub_0 : ARM::gsub_1);
440 O << ARMInstPrinter::getRegisterName(Reg);
441 return false;
442 }
443 if (NumVals != 2)
444 return true;
445 unsigned RegOp = FirstHalf ? OpNum : OpNum + 1;
446 if (RegOp >= MI->getNumOperands())
447 return true;
448 const MachineOperand &MO = MI->getOperand(i: RegOp);
449 if (!MO.isReg())
450 return true;
451 Register Reg = MO.getReg();
452 O << ARMInstPrinter::getRegisterName(Reg);
453 return false;
454 }
455
456 case 'e': // The low doubleword register of a NEON quad register.
457 case 'f': { // The high doubleword register of a NEON quad register.
458 if (!MI->getOperand(i: OpNum).isReg())
459 return true;
460 Register Reg = MI->getOperand(i: OpNum).getReg();
461 if (!ARM::QPRRegClass.contains(Reg))
462 return true;
463 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
464 Register SubReg =
465 TRI->getSubReg(Reg, Idx: ExtraCode[0] == 'e' ? ARM::dsub_0 : ARM::dsub_1);
466 O << ARMInstPrinter::getRegisterName(Reg: SubReg);
467 return false;
468 }
469
470 // This modifier is not yet supported.
471 case 'h': // A range of VFP/NEON registers suitable for VLD1/VST1.
472 return true;
473 case 'H': { // The highest-numbered register of a pair.
474 const MachineOperand &MO = MI->getOperand(i: OpNum);
475 if (!MO.isReg())
476 return true;
477 const MachineFunction &MF = *MI->getParent()->getParent();
478 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
479 Register Reg = MO.getReg();
480 if(!ARM::GPRPairRegClass.contains(Reg))
481 return false;
482 Reg = TRI->getSubReg(Reg, Idx: ARM::gsub_1);
483 O << ARMInstPrinter::getRegisterName(Reg);
484 return false;
485 }
486 }
487 }
488
489 printOperand(MI, OpNum, O);
490 return false;
491}
492
493bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
494 unsigned OpNum, const char *ExtraCode,
495 raw_ostream &O) {
496 // Does this asm operand have a single letter operand modifier?
497 if (ExtraCode && ExtraCode[0]) {
498 if (ExtraCode[1] != 0) return true; // Unknown modifier.
499
500 switch (ExtraCode[0]) {
501 case 'A': // A memory operand for a VLD1/VST1 instruction.
502 default: return true; // Unknown modifier.
503 case 'm': // The base register of a memory operand.
504 if (!MI->getOperand(i: OpNum).isReg())
505 return true;
506 O << ARMInstPrinter::getRegisterName(Reg: MI->getOperand(i: OpNum).getReg());
507 return false;
508 }
509 }
510
511 const MachineOperand &MO = MI->getOperand(i: OpNum);
512 assert(MO.isReg() && "unexpected inline asm memory operand");
513 O << "[" << ARMInstPrinter::getRegisterName(Reg: MO.getReg()) << "]";
514 return false;
515}
516
517static bool isThumb(const MCSubtargetInfo& STI) {
518 return STI.hasFeature(Feature: ARM::ModeThumb);
519}
520
521void ARMAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
522 const MCSubtargetInfo *EndInfo,
523 const MachineInstr *MI) {
524 // If either end mode is unknown (EndInfo == NULL) or different than
525 // the start mode, then restore the start mode.
526 const bool WasThumb = isThumb(STI: StartInfo);
527 if (!EndInfo || WasThumb != isThumb(STI: *EndInfo)) {
528 auto &TS =
529 static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());
530 if (WasThumb)
531 TS.emitCode16();
532 else
533 TS.emitCode32();
534 }
535}
536
537void ARMAsmPrinter::emitStartOfAsmFile(Module &M) {
538 const Triple &TT = TM.getTargetTriple();
539 auto &TS =
540 static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());
541 // Use unified assembler syntax.
542 TS.emitSyntaxUnified();
543
544 // Emit ARM Build Attributes
545 if (TT.isOSBinFormatELF())
546 emitAttributes();
547
548 // Use the triple's architecture and subarchitecture to determine
549 // if we're thumb for the purposes of the top level code16 state.
550 if (!M.getModuleInlineAsm().empty() && TT.isThumb())
551 TS.emitCode16();
552}
553
554static void
555emitNonLazySymbolPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel,
556 MachineModuleInfoImpl::StubValueTy &MCSym) {
557 // L_foo$stub:
558 OutStreamer.emitLabel(Symbol: StubLabel);
559 // .indirect_symbol _foo
560 OutStreamer.emitSymbolAttribute(Symbol: MCSym.getPointer(), Attribute: MCSA_IndirectSymbol);
561
562 if (MCSym.getInt())
563 // External to current translation unit.
564 OutStreamer.emitIntValue(Value: 0, Size: 4/*size*/);
565 else
566 // Internal to current translation unit.
567 //
568 // When we place the LSDA into the TEXT section, the type info
569 // pointers need to be indirect and pc-rel. We accomplish this by
570 // using NLPs; however, sometimes the types are local to the file.
571 // We need to fill in the value for the NLP in those cases.
572 OutStreamer.emitValue(
573 Value: MCSymbolRefExpr::create(Symbol: MCSym.getPointer(), Ctx&: OutStreamer.getContext()),
574 Size: 4 /*size*/);
575}
576
577
578void ARMAsmPrinter::emitEndOfAsmFile(Module &M) {
579 const Triple &TT = TM.getTargetTriple();
580 if (TT.isOSBinFormatMachO()) {
581 // All darwin targets use mach-o.
582 const TargetLoweringObjectFileMachO &TLOFMacho =
583 static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
584 MachineModuleInfoMachO &MMIMacho =
585 MMI->getObjFileInfo<MachineModuleInfoMachO>();
586
587 // Output non-lazy-pointers for external and common global variables.
588 MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList();
589
590 if (!Stubs.empty()) {
591 // Switch with ".non_lazy_symbol_pointer" directive.
592 OutStreamer->switchSection(Section: TLOFMacho.getNonLazySymbolPointerSection());
593 emitAlignment(Alignment: Align(4));
594
595 for (auto &Stub : Stubs)
596 emitNonLazySymbolPointer(OutStreamer&: *OutStreamer, StubLabel: Stub.first, MCSym&: Stub.second);
597
598 Stubs.clear();
599 OutStreamer->addBlankLine();
600 }
601
602 Stubs = MMIMacho.GetThreadLocalGVStubList();
603 if (!Stubs.empty()) {
604 // Switch with ".non_lazy_symbol_pointer" directive.
605 OutStreamer->switchSection(Section: TLOFMacho.getThreadLocalPointerSection());
606 emitAlignment(Alignment: Align(4));
607
608 for (auto &Stub : Stubs)
609 emitNonLazySymbolPointer(OutStreamer&: *OutStreamer, StubLabel: Stub.first, MCSym&: Stub.second);
610
611 Stubs.clear();
612 OutStreamer->addBlankLine();
613 }
614
615 // Funny Darwin hack: This flag tells the linker that no global symbols
616 // contain code that falls through to other global symbols (e.g. the obvious
617 // implementation of multiple entry points). If this doesn't occur, the
618 // linker can safely perform dead code stripping. Since LLVM never
619 // generates code that does this, it is always safe to set.
620 OutStreamer->emitSubsectionsViaSymbols();
621 }
622
623 // The last attribute to be emitted is ABI_optimization_goals
624 MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
625 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
626
627 if (OptimizationGoals > 0 &&
628 (TT.isTargetAEABI() || TT.isTargetGNUAEABI() || TT.isTargetMuslAEABI()))
629 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_optimization_goals, Value: OptimizationGoals);
630 OptimizationGoals = -1;
631
632 ATS.finishAttributeSection();
633}
634
635//===----------------------------------------------------------------------===//
636// Helper routines for emitStartOfAsmFile() and emitEndOfAsmFile()
637// FIXME:
638// The following seem like one-off assembler flags, but they actually need
639// to appear in the .ARM.attributes section in ELF.
640// Instead of subclassing the MCELFStreamer, we do the work here.
641
642// Returns true if all function definitions have the same function attribute
643// value. It also returns true when the module has no functions.
644static bool checkFunctionsAttributeConsistency(const Module &M, StringRef Attr,
645 StringRef Value) {
646 return !any_of(Range: M, P: [&](const Function &F) {
647 if (F.isDeclaration())
648 return false;
649 return F.getFnAttribute(Kind: Attr).getValueAsString() != Value;
650 });
651}
652// Returns true if all functions definitions have the same denormal mode.
653// It also returns true when the module has no functions.
654static bool checkDenormalAttributeConsistency(const Module &M,
655 DenormalFPEnv Value) {
656 return !any_of(Range: M, P: [&](const Function &F) {
657 if (F.isDeclaration())
658 return false;
659 return F.getDenormalFPEnv() != Value;
660 });
661}
662
663// Returns true if any function definition in the module has the strictfp
664// attribute, which taints the whole module: such code may change the FP
665// rounding mode at run time.
666static bool checkModuleHasStrictFP(const Module &M) {
667 return any_of(Range: M, P: [](const Function &F) {
668 return !F.isDeclaration() && F.isStrictFP();
669 });
670}
671
672// Returns true if all functions have different denormal modes.
673static bool checkDenormalAttributeInconsistency(const Module &M) {
674 auto F = M.functions().begin();
675 auto E = M.functions().end();
676 if (F == E)
677 return false;
678 DenormalFPEnv Value = F->getDenormalFPEnv();
679 ++F;
680 return std::any_of(first: F, last: E, pred: [&](const Function &F) {
681 return !F.isDeclaration() && F.getDenormalFPEnv() != Value;
682 });
683}
684
685void ARMAsmPrinter::emitAttributes() {
686 MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
687 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
688
689 ATS.emitTextAttribute(Attribute: ARMBuildAttrs::conformance, String: "2.09");
690
691 ATS.switchVendor(Vendor: "aeabi");
692
693 // Compute ARM ELF Attributes based on the default subtarget that
694 // we'd have constructed. The existing ARM behavior isn't LTO clean
695 // anyhow.
696 // FIXME: For ifunc related functions we could iterate over and look
697 // for a feature string that doesn't match the default one.
698 const Triple &TT = TM.getTargetTriple();
699 StringRef CPU = TM.getTargetCPU();
700 StringRef FS = TM.getTargetFeatureString();
701 std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU);
702 if (!FS.empty()) {
703 if (!ArchFS.empty())
704 ArchFS = (Twine(ArchFS) + "," + FS).str();
705 else
706 ArchFS = std::string(FS);
707 }
708 const ARMBaseTargetMachine &ATM =
709 static_cast<const ARMBaseTargetMachine &>(TM);
710 FloatABI::ABIType FloatABI = ATM.getFloatABI(M: *MMI->getModule());
711 ARM::ARMABI ABI = ATM.getEffectiveABI(M: *MMI->getModule());
712 const ARMSubtarget STI(TT, std::string(CPU), ArchFS, ATM,
713 ATM.isLittleEndian(), FloatABI, ABI);
714
715 // Emit build attributes for the available hardware.
716 ATS.emitTargetAttributes(STI);
717
718 // RW data addressing.
719 if (isPositionIndependent()) {
720 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_PCS_RW_data,
721 Value: ARMBuildAttrs::AddressRWPCRel);
722 } else if (STI.isRWPI()) {
723 // RWPI specific attributes.
724 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_PCS_RW_data,
725 Value: ARMBuildAttrs::AddressRWSBRel);
726 }
727
728 // RO data addressing.
729 if (isPositionIndependent() || STI.isROPI()) {
730 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_PCS_RO_data,
731 Value: ARMBuildAttrs::AddressROPCRel);
732 }
733
734 // GOT use.
735 if (isPositionIndependent()) {
736 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_PCS_GOT_use,
737 Value: ARMBuildAttrs::AddressGOT);
738 } else {
739 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_PCS_GOT_use,
740 Value: ARMBuildAttrs::AddressDirect);
741 }
742
743 // Set FP Denormals.
744 if (auto *DM = mdconst::extract_or_null<ConstantInt>(
745 MD: MMI->getModule()->getModuleFlag(Key: "arm-eabi-fp-denormal"))) {
746 if (unsigned TagVal = DM->getZExtValue())
747 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_FP_denormal, Value: TagVal);
748 } else if (checkDenormalAttributeConsistency(M: *MMI->getModule(),
749 Value: DenormalMode::getPreserveSign()))
750 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_FP_denormal,
751 Value: ARMBuildAttrs::PreserveFPSign);
752 else if (checkDenormalAttributeConsistency(M: *MMI->getModule(),
753 Value: DenormalMode::getPositiveZero()))
754 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_FP_denormal,
755 Value: ARMBuildAttrs::PositiveZero);
756 else if (checkDenormalAttributeInconsistency(M: *MMI->getModule()) ||
757 checkDenormalAttributeConsistency(M: *MMI->getModule(),
758 Value: DenormalMode::getIEEE()))
759 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_FP_denormal,
760 Value: ARMBuildAttrs::IEEEDenormals);
761 else {
762 if (!STI.hasVFP2Base()) {
763 // When the target doesn't have an FPU (by design or
764 // intention), the assumptions made on the software support
765 // mirror that of the equivalent hardware support *if it
766 // existed*. For v7 and better we indicate that denormals are
767 // flushed preserving sign, and for V6 we indicate that
768 // denormals are flushed to positive zero.
769 if (STI.hasV7Ops())
770 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_FP_denormal,
771 Value: ARMBuildAttrs::PreserveFPSign);
772 } else if (STI.hasVFP3Base()) {
773 // In VFPv4, VFPv4U, VFPv3, or VFPv3U, it is preserved. That is,
774 // the sign bit of the zero matches the sign bit of the input or
775 // result that is being flushed to zero.
776 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_FP_denormal,
777 Value: ARMBuildAttrs::PreserveFPSign);
778 }
779 // For VFPv2 implementations it is implementation defined as
780 // to whether denormals are flushed to positive zero or to
781 // whatever the sign of zero is (ARM v7AR ARM 2.7.5). Historically
782 // LLVM has chosen to flush this to positive zero (most likely for
783 // GCC compatibility), so that's the chosen value here (the
784 // absence of its emission implies zero).
785 }
786
787 // Set FP exceptions and rounding
788 if (auto *Ex = mdconst::extract_or_null<ConstantInt>(
789 MD: MMI->getModule()->getModuleFlag(Key: "arm-eabi-fp-exceptions"))) {
790 if (unsigned TagVal = Ex->getZExtValue())
791 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_FP_exceptions, Value: TagVal);
792 } else if (checkFunctionsAttributeConsistency(M: *MMI->getModule(),
793 Attr: "no-trapping-math", Value: "true"))
794 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_FP_exceptions,
795 Value: ARMBuildAttrs::Not_Allowed);
796 else {
797 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_FP_exceptions, Value: ARMBuildAttrs::Allowed);
798
799 // If any function may change the FP rounding mode at run time the code
800 // cannot assume the default rounding, so emit the rounding attribute.
801 if (checkModuleHasStrictFP(M: *MMI->getModule()))
802 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_FP_rounding, Value: ARMBuildAttrs::Allowed);
803 }
804
805 // Generate ABI tags from module flags.
806 if (auto *NumModel = mdconst::extract_or_null<ConstantInt>(
807 MD: MMI->getModule()->getModuleFlag(Key: "arm-eabi-fp-number-model"))) {
808 if (unsigned TagVal = NumModel->getZExtValue())
809 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_FP_number_model, Value: TagVal);
810 } else
811 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_FP_number_model,
812 Value: ARMBuildAttrs::AllowIEEE754);
813
814 // FIXME: add more flags to ARMBuildAttributes.h
815 // 8-bytes alignment stuff.
816 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_align_needed, Value: 1);
817 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_align_preserved, Value: 1);
818
819 // Hard float. Use both S and D registers and conform to AAPCS-VFP.
820 if (STI.isAAPCS_ABI() && STI.isTargetHardFloat())
821 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_VFP_args, Value: ARMBuildAttrs::HardFPAAPCS);
822
823 // FIXME: To support emitting this build attribute as GCC does, the
824 // -mfp16-format option and associated plumbing must be
825 // supported. For now the __fp16 type is exposed by default, so this
826 // attribute should be emitted with value 1.
827 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_FP_16bit_format,
828 Value: ARMBuildAttrs::FP16FormatIEEE);
829
830 if (const Module *SourceModule = MMI->getModule()) {
831 // ABI_PCS_wchar_t to indicate wchar_t width
832 // FIXME: There is no way to emit value 0 (wchar_t prohibited).
833 int WCharWidth = TM.getTargetTriple().getDefaultWCharSize();
834 if (auto WCharWidthValue = mdconst::extract_or_null<ConstantInt>(
835 MD: SourceModule->getModuleFlag(Key: "wchar_size")))
836 WCharWidth = WCharWidthValue->getZExtValue();
837 assert((WCharWidth == 2 || WCharWidth == 4) &&
838 "wchar_t width must be 2 or 4 bytes");
839 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_PCS_wchar_t, Value: WCharWidth);
840
841 // ABI_enum_size to indicate enum width
842 // FIXME: There is no way to emit value 0 (enums prohibited) or value 3
843 // (all enums contain a value needing 32 bits to encode).
844 if (auto EnumWidthValue = mdconst::extract_or_null<ConstantInt>(
845 MD: SourceModule->getModuleFlag(Key: "min_enum_size"))) {
846 int EnumWidth = EnumWidthValue->getZExtValue();
847 assert((EnumWidth == 1 || EnumWidth == 4) &&
848 "Minimum enum width must be 1 or 4 bytes");
849 int EnumBuildAttr = EnumWidth == 1 ? 1 : 2;
850 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_enum_size, Value: EnumBuildAttr);
851 }
852
853 auto *PACValue = mdconst::extract_or_null<ConstantInt>(
854 MD: SourceModule->getModuleFlag(Key: "sign-return-address"));
855 if (PACValue && PACValue->isOne()) {
856 // If "+pacbti" is used as an architecture extension,
857 // Tag_PAC_extension is emitted in
858 // ARMTargetStreamer::emitTargetAttributes().
859 if (!STI.hasPACBTI()) {
860 ATS.emitAttribute(Attribute: ARMBuildAttrs::PAC_extension,
861 Value: ARMBuildAttrs::AllowPACInNOPSpace);
862 }
863 ATS.emitAttribute(Attribute: ARMBuildAttrs::PACRET_use, Value: ARMBuildAttrs::PACRETUsed);
864 }
865
866 auto *BTIValue = mdconst::extract_or_null<ConstantInt>(
867 MD: SourceModule->getModuleFlag(Key: "branch-target-enforcement"));
868 if (BTIValue && !BTIValue->isZero()) {
869 // If "+pacbti" is used as an architecture extension,
870 // Tag_BTI_extension is emitted in
871 // ARMTargetStreamer::emitTargetAttributes().
872 if (!STI.hasPACBTI()) {
873 ATS.emitAttribute(Attribute: ARMBuildAttrs::BTI_extension,
874 Value: ARMBuildAttrs::AllowBTIInNOPSpace);
875 }
876 ATS.emitAttribute(Attribute: ARMBuildAttrs::BTI_use, Value: ARMBuildAttrs::BTIUsed);
877 }
878 }
879
880 // We currently do not support using R9 as the TLS pointer.
881 if (STI.isRWPI())
882 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_PCS_R9_use,
883 Value: ARMBuildAttrs::R9IsSB);
884 else if (STI.isR9Reserved())
885 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_PCS_R9_use,
886 Value: ARMBuildAttrs::R9Reserved);
887 else
888 ATS.emitAttribute(Attribute: ARMBuildAttrs::ABI_PCS_R9_use,
889 Value: ARMBuildAttrs::R9IsGPR);
890}
891
892//===----------------------------------------------------------------------===//
893
894static MCSymbol *getBFLabel(StringRef Prefix, unsigned FunctionNumber,
895 unsigned LabelId, MCContext &Ctx) {
896
897 MCSymbol *Label = Ctx.getOrCreateSymbol(Name: Twine(Prefix)
898 + "BF" + Twine(FunctionNumber) + "_" + Twine(LabelId));
899 return Label;
900}
901
902static MCSymbol *getPICLabel(StringRef Prefix, unsigned FunctionNumber,
903 unsigned LabelId, MCContext &Ctx) {
904
905 MCSymbol *Label = Ctx.getOrCreateSymbol(Name: Twine(Prefix)
906 + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId));
907 return Label;
908}
909
910static uint8_t getModifierSpecifier(ARMCP::ARMCPModifier Modifier) {
911 switch (Modifier) {
912 case ARMCP::no_modifier:
913 return ARM::S_None;
914 case ARMCP::TLSGD:
915 return ARM::S_TLSGD;
916 case ARMCP::TPOFF:
917 return ARM::S_TPOFF;
918 case ARMCP::GOTTPOFF:
919 return ARM::S_GOTTPOFF;
920 case ARMCP::SBREL:
921 return ARM::S_SBREL;
922 case ARMCP::GOT_PREL:
923 return ARM::S_GOT_PREL;
924 case ARMCP::SECREL:
925 return ARM::S_COFF_SECREL;
926 }
927 llvm_unreachable("Invalid ARMCPModifier!");
928}
929
930MCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV,
931 unsigned char TargetFlags) {
932 const Triple &TT = TM.getTargetTriple();
933 if (TT.isOSBinFormatMachO()) {
934 bool IsIndirect =
935 (TargetFlags & ARMII::MO_NONLAZY) && getTM().isGVIndirectSymbol(GV);
936
937 if (!IsIndirect)
938 return getSymbol(GV);
939
940 // FIXME: Remove this when Darwin transition to @GOT like syntax.
941 MCSymbol *MCSym = getSymbolWithGlobalValueBase(GV, Suffix: "$non_lazy_ptr");
942 MachineModuleInfoMachO &MMIMachO =
943 MMI->getObjFileInfo<MachineModuleInfoMachO>();
944 MachineModuleInfoImpl::StubValueTy &StubSym =
945 GV->isThreadLocal() ? MMIMachO.getThreadLocalGVStubEntry(Sym: MCSym)
946 : MMIMachO.getGVStubEntry(Sym: MCSym);
947
948 if (!StubSym.getPointer())
949 StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(GV),
950 !GV->hasInternalLinkage());
951 return MCSym;
952 } else if (TT.isOSBinFormatCOFF()) {
953 assert(TT.isOSWindows() && "Windows is the only supported COFF target");
954
955 bool IsIndirect =
956 (TargetFlags & (ARMII::MO_DLLIMPORT | ARMII::MO_COFFSTUB));
957 if (!IsIndirect)
958 return getSymbol(GV);
959
960 SmallString<128> Name;
961 if (TargetFlags & ARMII::MO_DLLIMPORT)
962 Name = "__imp_";
963 else if (TargetFlags & ARMII::MO_COFFSTUB)
964 Name = ".refptr.";
965 getNameWithPrefix(Name, GV);
966
967 MCSymbol *MCSym = OutContext.getOrCreateSymbol(Name);
968
969 if (TargetFlags & ARMII::MO_COFFSTUB) {
970 MachineModuleInfoCOFF &MMICOFF =
971 MMI->getObjFileInfo<MachineModuleInfoCOFF>();
972 MachineModuleInfoImpl::StubValueTy &StubSym =
973 MMICOFF.getGVStubEntry(Sym: MCSym);
974
975 if (!StubSym.getPointer())
976 StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(GV), true);
977 }
978
979 return MCSym;
980 } else if (TT.isOSBinFormatELF()) {
981 return getSymbolPreferLocal(GV: *GV);
982 }
983 llvm_unreachable("unexpected target");
984}
985
986void ARMAsmPrinter::emitMachineConstantPoolValue(
987 MachineConstantPoolValue *MCPV) {
988 const DataLayout &DL = getDataLayout();
989 int Size = DL.getTypeAllocSize(Ty: MCPV->getType());
990
991 ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);
992
993 if (ACPV->isPromotedGlobal()) {
994 // This constant pool entry is actually a global whose storage has been
995 // promoted into the constant pool. This global may be referenced still
996 // by debug information, and due to the way AsmPrinter is set up, the debug
997 // info is immutable by the time we decide to promote globals to constant
998 // pools. Because of this, we need to ensure we emit a symbol for the global
999 // with private linkage (the default) so debug info can refer to it.
1000 //
1001 // However, if this global is promoted into several functions we must ensure
1002 // we don't try and emit duplicate symbols!
1003 auto *ACPC = cast<ARMConstantPoolConstant>(Val: ACPV);
1004 for (const auto *GV : ACPC->promotedGlobals()) {
1005 if (!EmittedPromotedGlobalLabels.count(Ptr: GV)) {
1006 MCSymbol *GVSym = getSymbol(GV);
1007 OutStreamer->emitLabel(Symbol: GVSym);
1008 EmittedPromotedGlobalLabels.insert(Ptr: GV);
1009 }
1010 }
1011 return emitGlobalConstant(DL, CV: ACPC->getPromotedGlobalInit());
1012 }
1013
1014 MCSymbol *MCSym;
1015 if (ACPV->isLSDA()) {
1016 MCSym = getMBBExceptionSym(MBB: MF->front());
1017 } else if (ACPV->isBlockAddress()) {
1018 const BlockAddress *BA =
1019 cast<ARMConstantPoolConstant>(Val: ACPV)->getBlockAddress();
1020 MCSym = GetBlockAddressSymbol(BA);
1021 } else if (ACPV->isGlobalValue()) {
1022 const GlobalValue *GV = cast<ARMConstantPoolConstant>(Val: ACPV)->getGV();
1023
1024 // On Darwin, const-pool entries may get the "FOO$non_lazy_ptr" mangling, so
1025 // flag the global as MO_NONLAZY.
1026 unsigned char TF =
1027 TM.getTargetTriple().isOSBinFormatMachO() ? ARMII::MO_NONLAZY : 0;
1028 MCSym = GetARMGVSymbol(GV, TargetFlags: TF);
1029
1030 // For dso_local weak symbols in ELF PIC mode, the assembler would eagerly
1031 // resolve a PC-relative expression like sym-(LPC+8) when the symbol and
1032 // reference are in the same section, preventing the linker from overriding
1033 // a weak definition with a non-weak definition from another section. Use a
1034 // .reloc directive rather than a fixup to force the generation of a
1035 // relocation (R_ARM_REL32) so the linker can perform the override. This is
1036 // restricted to dso_local, non-TLS symbols: a preemptible/external weak
1037 // symbol (e.g. an extern_weak reference) must use the GOT, as R_ARM_REL32
1038 // against an external symbol cannot be used when making a shared object;
1039 // and TLS symbols require TLS-specific relocations, not R_ARM_REL32.
1040 if (GV->isWeakForLinker() && GV->isDSOLocal() && !GV->isThreadLocal() &&
1041 TM.getTargetTriple().isOSBinFormatELF() && TM.isPositionIndependent() &&
1042 ACPV->getPCAdjustment() != 0) {
1043 MCSymbol *CPILabel = OutContext.createTempSymbol();
1044 OutStreamer->emitLabel(Symbol: CPILabel);
1045 // Emit local-only expression: CPILabel - (LPC+PCAdj)
1046 const MCExpr *LocalExpr = MCSymbolRefExpr::create(Symbol: CPILabel, Ctx&: OutContext);
1047 MCSymbol *PCLabel =
1048 getPICLabel(Prefix: DL.getInternalSymbolPrefix(), FunctionNumber: getFunctionNumber(),
1049 LabelId: ACPV->getLabelId(), Ctx&: OutContext);
1050 const MCExpr *PCRelExpr = MCSymbolRefExpr::create(Symbol: PCLabel, Ctx&: OutContext);
1051 PCRelExpr = MCBinaryExpr::createAdd(
1052 LHS: PCRelExpr,
1053 RHS: MCConstantExpr::create(Value: ACPV->getPCAdjustment(), Ctx&: OutContext),
1054 Ctx&: OutContext);
1055 LocalExpr = MCBinaryExpr::createSub(LHS: LocalExpr, RHS: PCRelExpr, Ctx&: OutContext);
1056 OutStreamer->emitValue(Value: LocalExpr, Size);
1057 // Emit .reloc to force linker resolution of the weak symbol.
1058 const MCExpr *CPIExpr = MCSymbolRefExpr::create(Symbol: CPILabel, Ctx&: OutContext);
1059 const MCExpr *SymExpr = MCSymbolRefExpr::create(Symbol: MCSym, Ctx&: OutContext);
1060 OutStreamer->emitRelocDirective(Offset: *CPIExpr, Name: "R_ARM_REL32", Expr: SymExpr,
1061 Loc: SMLoc());
1062 return;
1063 }
1064 } else if (ACPV->isMachineBasicBlock()) {
1065 const MachineBasicBlock *MBB = cast<ARMConstantPoolMBB>(Val: ACPV)->getMBB();
1066 MCSym = MBB->getSymbol();
1067 } else {
1068 assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
1069 auto Sym = cast<ARMConstantPoolSymbol>(Val: ACPV)->getSymbol();
1070 MCSym = GetExternalSymbolSymbol(Sym);
1071 }
1072
1073 // Create an MCSymbol for the reference.
1074 const MCExpr *Expr = MCSymbolRefExpr::create(
1075 Symbol: MCSym, specifier: getModifierSpecifier(Modifier: ACPV->getModifier()), Ctx&: OutContext);
1076
1077 if (ACPV->getPCAdjustment()) {
1078 MCSymbol *PCLabel =
1079 getPICLabel(Prefix: DL.getInternalSymbolPrefix(), FunctionNumber: getFunctionNumber(),
1080 LabelId: ACPV->getLabelId(), Ctx&: OutContext);
1081 const MCExpr *PCRelExpr = MCSymbolRefExpr::create(Symbol: PCLabel, Ctx&: OutContext);
1082 PCRelExpr =
1083 MCBinaryExpr::createAdd(LHS: PCRelExpr,
1084 RHS: MCConstantExpr::create(Value: ACPV->getPCAdjustment(),
1085 Ctx&: OutContext),
1086 Ctx&: OutContext);
1087 if (ACPV->mustAddCurrentAddress()) {
1088 // We want "(<expr> - .)", but MC doesn't have a concept of the '.'
1089 // label, so just emit a local label end reference that instead.
1090 MCSymbol *DotSym = OutContext.createTempSymbol();
1091 OutStreamer->emitLabel(Symbol: DotSym);
1092 const MCExpr *DotExpr = MCSymbolRefExpr::create(Symbol: DotSym, Ctx&: OutContext);
1093 PCRelExpr = MCBinaryExpr::createSub(LHS: PCRelExpr, RHS: DotExpr, Ctx&: OutContext);
1094 }
1095 Expr = MCBinaryExpr::createSub(LHS: Expr, RHS: PCRelExpr, Ctx&: OutContext);
1096 }
1097 OutStreamer->emitValue(Value: Expr, Size);
1098}
1099
1100void ARMAsmPrinter::emitJumpTableAddrs(const MachineInstr *MI) {
1101 const MachineOperand &MO1 = MI->getOperand(i: 1);
1102 unsigned JTI = MO1.getIndex();
1103
1104 // Make sure the Thumb jump table is 4-byte aligned. This will be a nop for
1105 // ARM mode tables.
1106 emitAlignment(Alignment: Align(4));
1107
1108 // Emit a label for the jump table.
1109 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(uid: JTI);
1110 OutStreamer->emitLabel(Symbol: JTISymbol);
1111
1112 // Mark the jump table as data-in-code.
1113 OutStreamer->emitDataRegion(Kind: MCDR_DataRegionJT32);
1114
1115 // Emit each entry of the table.
1116 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
1117 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
1118 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1119
1120 for (MachineBasicBlock *MBB : JTBBs) {
1121 // Construct an MCExpr for the entry. We want a value of the form:
1122 // (BasicBlockAddr - TableBeginAddr)
1123 //
1124 // For example, a table with entries jumping to basic blocks BB0 and BB1
1125 // would look like:
1126 // LJTI_0_0:
1127 // .word (LBB0 - LJTI_0_0)
1128 // .word (LBB1 - LJTI_0_0)
1129 const MCExpr *Expr = MCSymbolRefExpr::create(Symbol: MBB->getSymbol(), Ctx&: OutContext);
1130
1131 const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();
1132 if (isPositionIndependent() || STI.isROPI())
1133 Expr = MCBinaryExpr::createSub(LHS: Expr, RHS: MCSymbolRefExpr::create(Symbol: JTISymbol,
1134 Ctx&: OutContext),
1135 Ctx&: OutContext);
1136 // If we're generating a table of Thumb addresses in static relocation
1137 // model, we need to add one to keep interworking correctly.
1138 else if (AFI->isThumbFunction())
1139 Expr = MCBinaryExpr::createAdd(LHS: Expr, RHS: MCConstantExpr::create(Value: 1,Ctx&: OutContext),
1140 Ctx&: OutContext);
1141 OutStreamer->emitValue(Value: Expr, Size: 4);
1142 }
1143 // Mark the end of jump table data-in-code region.
1144 OutStreamer->emitDataRegion(Kind: MCDR_DataRegionEnd);
1145}
1146
1147void ARMAsmPrinter::emitJumpTableInsts(const MachineInstr *MI) {
1148 const MachineOperand &MO1 = MI->getOperand(i: 1);
1149 unsigned JTI = MO1.getIndex();
1150
1151 // Make sure the Thumb jump table is 4-byte aligned. This will be a nop for
1152 // ARM mode tables.
1153 emitAlignment(Alignment: Align(4));
1154
1155 // Emit a label for the jump table.
1156 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(uid: JTI);
1157 OutStreamer->emitLabel(Symbol: JTISymbol);
1158
1159 // Emit each entry of the table.
1160 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
1161 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
1162 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1163
1164 for (MachineBasicBlock *MBB : JTBBs) {
1165 const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::create(Symbol: MBB->getSymbol(),
1166 Ctx&: OutContext);
1167 // If this isn't a TBB or TBH, the entries are direct branch instructions.
1168 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::t2B)
1169 .addExpr(Val: MBBSymbolExpr)
1170 .addImm(Val: ARMCC::AL)
1171 .addReg(Reg: 0));
1172 }
1173}
1174
1175void ARMAsmPrinter::emitJumpTableTBInst(const MachineInstr *MI,
1176 unsigned OffsetWidth) {
1177 assert((OffsetWidth == 1 || OffsetWidth == 2) && "invalid tbb/tbh width");
1178 const MachineOperand &MO1 = MI->getOperand(i: 1);
1179 unsigned JTI = MO1.getIndex();
1180
1181 const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();
1182 if (STI.isThumb1Only())
1183 emitAlignment(Alignment: Align(4));
1184
1185 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(uid: JTI);
1186 OutStreamer->emitLabel(Symbol: JTISymbol);
1187
1188 // Emit each entry of the table.
1189 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
1190 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
1191 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1192
1193 // Mark the jump table as data-in-code.
1194 OutStreamer->emitDataRegion(Kind: OffsetWidth == 1 ? MCDR_DataRegionJT8
1195 : MCDR_DataRegionJT16);
1196
1197 for (auto *MBB : JTBBs) {
1198 const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::create(Symbol: MBB->getSymbol(),
1199 Ctx&: OutContext);
1200 // Otherwise it's an offset from the dispatch instruction. Construct an
1201 // MCExpr for the entry. We want a value of the form:
1202 // (BasicBlockAddr - TBBInstAddr + 4) / 2
1203 //
1204 // For example, a TBB table with entries jumping to basic blocks BB0 and BB1
1205 // would look like:
1206 // LJTI_0_0:
1207 // .byte (LBB0 - (LCPI0_0 + 4)) / 2
1208 // .byte (LBB1 - (LCPI0_0 + 4)) / 2
1209 // where LCPI0_0 is a label defined just before the TBB instruction using
1210 // this table.
1211 MCSymbol *TBInstPC = GetCPISymbol(CPID: MI->getOperand(i: 0).getImm());
1212 const MCExpr *Expr = MCBinaryExpr::createAdd(
1213 LHS: MCSymbolRefExpr::create(Symbol: TBInstPC, Ctx&: OutContext),
1214 RHS: MCConstantExpr::create(Value: 4, Ctx&: OutContext), Ctx&: OutContext);
1215 Expr = MCBinaryExpr::createSub(LHS: MBBSymbolExpr, RHS: Expr, Ctx&: OutContext);
1216 Expr = MCBinaryExpr::createDiv(LHS: Expr, RHS: MCConstantExpr::create(Value: 2, Ctx&: OutContext),
1217 Ctx&: OutContext);
1218 OutStreamer->emitValue(Value: Expr, Size: OffsetWidth);
1219 }
1220 // Mark the end of jump table data-in-code region. 32-bit offsets use
1221 // actual branch instructions here, so we don't mark those as a data-region
1222 // at all.
1223 OutStreamer->emitDataRegion(Kind: MCDR_DataRegionEnd);
1224
1225 // Make sure the next instruction is 2-byte aligned.
1226 emitAlignment(Alignment: Align(2));
1227}
1228
1229std::tuple<const MCSymbol *, uint64_t, const MCSymbol *,
1230 codeview::JumpTableEntrySize>
1231ARMAsmPrinter::getCodeViewJumpTableInfo(int JTI,
1232 const MachineInstr *BranchInstr,
1233 const MCSymbol *BranchLabel) const {
1234 codeview::JumpTableEntrySize EntrySize;
1235 const MCSymbol *BaseLabel;
1236 uint64_t BaseOffset = 0;
1237 switch (BranchInstr->getOpcode()) {
1238 case ARM::BR_JTadd:
1239 case ARM::BR_JTr:
1240 case ARM::tBR_JTr:
1241 // Word relative to the jump table address.
1242 EntrySize = codeview::JumpTableEntrySize::UInt32;
1243 BaseLabel = GetARMJTIPICJumpTableLabel(uid: JTI);
1244 break;
1245 case ARM::tTBH_JT:
1246 case ARM::t2TBH_JT:
1247 // half-word shifted left, relative to *after* the branch instruction.
1248 EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft;
1249 BranchLabel = GetCPISymbol(CPID: BranchInstr->getOperand(i: 3).getImm());
1250 BaseLabel = BranchLabel;
1251 BaseOffset = 4;
1252 break;
1253 case ARM::tTBB_JT:
1254 case ARM::t2TBB_JT:
1255 // byte shifted left, relative to *after* the branch instruction.
1256 EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft;
1257 BranchLabel = GetCPISymbol(CPID: BranchInstr->getOperand(i: 3).getImm());
1258 BaseLabel = BranchLabel;
1259 BaseOffset = 4;
1260 break;
1261 case ARM::t2BR_JT:
1262 // Direct jump.
1263 BaseLabel = nullptr;
1264 EntrySize = codeview::JumpTableEntrySize::Pointer;
1265 break;
1266 default:
1267 llvm_unreachable("Unknown jump table instruction");
1268 }
1269
1270 return std::make_tuple(args&: BaseLabel, args&: BaseOffset, args&: BranchLabel, args&: EntrySize);
1271}
1272
1273void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) {
1274 assert(MI->getFlag(MachineInstr::FrameSetup) &&
1275 "Only instruction which are involved into frame setup code are allowed");
1276
1277 MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
1278 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
1279 const MachineFunction &MF = *MI->getParent()->getParent();
1280 const TargetRegisterInfo *TargetRegInfo =
1281 MF.getSubtarget().getRegisterInfo();
1282 const MachineRegisterInfo &MachineRegInfo = MF.getRegInfo();
1283
1284 Register FramePtr = TargetRegInfo->getFrameRegister(MF);
1285 unsigned Opc = MI->getOpcode();
1286 unsigned SrcReg, DstReg;
1287
1288 switch (Opc) {
1289 case ARM::tPUSH:
1290 // special case: tPUSH does not have src/dst regs.
1291 SrcReg = DstReg = ARM::SP;
1292 break;
1293 case ARM::tLDRpci:
1294 case ARM::t2MOVi16:
1295 case ARM::t2MOVTi16:
1296 case ARM::tMOVi8:
1297 case ARM::tADDi8:
1298 case ARM::tLSLri:
1299 // special cases:
1300 // 1) for Thumb1 code we sometimes materialize the constant via constpool
1301 // load.
1302 // 2) for Thumb1 execute only code we materialize the constant via the
1303 // following pattern:
1304 // movs r3, #:upper8_15:<const>
1305 // lsls r3, #8
1306 // adds r3, #:upper0_7:<const>
1307 // lsls r3, #8
1308 // adds r3, #:lower8_15:<const>
1309 // lsls r3, #8
1310 // adds r3, #:lower0_7:<const>
1311 // So we need to special-case MOVS, ADDS and LSLS, and keep track of
1312 // where we are in the sequence with the simplest of state machines.
1313 // 3) for Thumb2 execute only code we materialize the constant via
1314 // immediate constants in 2 separate instructions (MOVW/MOVT).
1315 SrcReg = ~0U;
1316 DstReg = MI->getOperand(i: 0).getReg();
1317 break;
1318 case ARM::VMRS:
1319 SrcReg = ARM::FPSCR;
1320 DstReg = MI->getOperand(i: 0).getReg();
1321 break;
1322 case ARM::VMRS_FPEXC:
1323 SrcReg = ARM::FPEXC;
1324 DstReg = MI->getOperand(i: 0).getReg();
1325 break;
1326 default:
1327 SrcReg = MI->getOperand(i: 1).getReg();
1328 DstReg = MI->getOperand(i: 0).getReg();
1329 break;
1330 }
1331
1332 // Try to figure out the unwinding opcode out of src / dst regs.
1333 if (MI->mayStore()) {
1334 // Register saves.
1335 assert(DstReg == ARM::SP &&
1336 "Only stack pointer as a destination reg is supported");
1337
1338 SmallVector<MCRegister, 4> RegList;
1339 // Skip src & dst reg, and pred ops.
1340 unsigned StartOp = 2 + 2;
1341 // Use all the operands.
1342 unsigned NumOffset = 0;
1343 // Amount of SP adjustment folded into a push, before the
1344 // registers are stored (pad at higher addresses).
1345 unsigned PadBefore = 0;
1346 // Amount of SP adjustment folded into a push, after the
1347 // registers are stored (pad at lower addresses).
1348 unsigned PadAfter = 0;
1349
1350 switch (Opc) {
1351 default:
1352 MI->print(OS&: errs());
1353 llvm_unreachable("Unsupported opcode for unwinding information");
1354 case ARM::tPUSH:
1355 // Special case here: no src & dst reg, but two extra imp ops.
1356 StartOp = 2; NumOffset = 2;
1357 [[fallthrough]];
1358 case ARM::STMDB_UPD:
1359 case ARM::t2STMDB_UPD:
1360 case ARM::VSTMDDB_UPD:
1361 assert(SrcReg == ARM::SP &&
1362 "Only stack pointer as a source reg is supported");
1363 for (unsigned i = StartOp, NumOps = MI->getNumOperands() - NumOffset;
1364 i != NumOps; ++i) {
1365 const MachineOperand &MO = MI->getOperand(i);
1366 // Actually, there should never be any impdef stuff here. Skip it
1367 // temporary to workaround PR11902.
1368 if (MO.isImplicit())
1369 continue;
1370 // Registers, pushed as a part of folding an SP update into the
1371 // push instruction are marked as undef and should not be
1372 // restored when unwinding, because the function can modify the
1373 // corresponding stack slots.
1374 if (MO.isUndef()) {
1375 assert(RegList.empty() &&
1376 "Pad registers must come before restored ones");
1377 unsigned Width =
1378 TargetRegInfo->getRegSizeInBits(Reg: MO.getReg(), MRI: MachineRegInfo) / 8;
1379 PadAfter += Width;
1380 continue;
1381 }
1382 // Check for registers that are remapped (for a Thumb1 prologue that
1383 // saves high registers).
1384 Register Reg = MO.getReg();
1385 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(Val: Reg))
1386 Reg = RemappedReg;
1387 RegList.push_back(Elt: Reg);
1388 }
1389 break;
1390 case ARM::STR_PRE_IMM:
1391 case ARM::STR_PRE_REG:
1392 case ARM::t2STR_PRE:
1393 assert(MI->getOperand(2).getReg() == ARM::SP &&
1394 "Only stack pointer as a source reg is supported");
1395 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(Val: SrcReg))
1396 SrcReg = RemappedReg;
1397
1398 RegList.push_back(Elt: SrcReg);
1399 break;
1400 case ARM::t2STRD_PRE:
1401 assert(MI->getOperand(3).getReg() == ARM::SP &&
1402 "Only stack pointer as a source reg is supported");
1403 SrcReg = MI->getOperand(i: 1).getReg();
1404 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(Val: SrcReg))
1405 SrcReg = RemappedReg;
1406 RegList.push_back(Elt: SrcReg);
1407 SrcReg = MI->getOperand(i: 2).getReg();
1408 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(Val: SrcReg))
1409 SrcReg = RemappedReg;
1410 RegList.push_back(Elt: SrcReg);
1411 PadBefore = -MI->getOperand(i: 4).getImm() - 8;
1412 break;
1413 }
1414 if (MAI.getExceptionHandlingType() == ExceptionHandling::ARM) {
1415 if (PadBefore)
1416 ATS.emitPad(Offset: PadBefore);
1417 ATS.emitRegSave(RegList, isVector: Opc == ARM::VSTMDDB_UPD);
1418 // Account for the SP adjustment, folded into the push.
1419 if (PadAfter)
1420 ATS.emitPad(Offset: PadAfter);
1421 }
1422 } else {
1423 // Changes of stack / frame pointer.
1424 if (SrcReg == ARM::SP) {
1425 int64_t Offset = 0;
1426 switch (Opc) {
1427 default:
1428 MI->print(OS&: errs());
1429 llvm_unreachable("Unsupported opcode for unwinding information");
1430 case ARM::tLDRspi:
1431 // Used to restore LR in a prologue which uses it as a temporary, has
1432 // no effect on unwind tables.
1433 return;
1434 case ARM::MOVr:
1435 case ARM::tMOVr:
1436 Offset = 0;
1437 break;
1438 case ARM::ADDri:
1439 case ARM::t2ADDri:
1440 case ARM::t2ADDri12:
1441 case ARM::t2ADDspImm:
1442 case ARM::t2ADDspImm12:
1443 Offset = -MI->getOperand(i: 2).getImm();
1444 break;
1445 case ARM::SUBri:
1446 case ARM::t2SUBri:
1447 case ARM::t2SUBri12:
1448 case ARM::t2SUBspImm:
1449 case ARM::t2SUBspImm12:
1450 Offset = MI->getOperand(i: 2).getImm();
1451 break;
1452 case ARM::tSUBspi:
1453 Offset = MI->getOperand(i: 2).getImm()*4;
1454 break;
1455 case ARM::tADDspi:
1456 case ARM::tADDrSPi:
1457 Offset = -MI->getOperand(i: 2).getImm()*4;
1458 break;
1459 case ARM::tADDhirr:
1460 Offset =
1461 -AFI->EHPrologueOffsetInRegs.lookup(Val: MI->getOperand(i: 2).getReg());
1462 break;
1463 }
1464
1465 if (MAI.getExceptionHandlingType() == ExceptionHandling::ARM) {
1466 if (DstReg == FramePtr && FramePtr != ARM::SP)
1467 // Set-up of the frame pointer. Positive values correspond to "add"
1468 // instruction.
1469 ATS.emitSetFP(FpReg: FramePtr, SpReg: ARM::SP, Offset: -Offset);
1470 else if (DstReg == ARM::SP) {
1471 // Change of SP by an offset. Positive values correspond to "sub"
1472 // instruction.
1473 ATS.emitPad(Offset);
1474 } else {
1475 // Move of SP to a register. Positive values correspond to an "add"
1476 // instruction.
1477 ATS.emitMovSP(Reg: DstReg, Offset: -Offset);
1478 }
1479 }
1480 } else if (DstReg == ARM::SP) {
1481 MI->print(OS&: errs());
1482 llvm_unreachable("Unsupported opcode for unwinding information");
1483 } else {
1484 int64_t Offset = 0;
1485 switch (Opc) {
1486 case ARM::tMOVr:
1487 // If a Thumb1 function spills r8-r11, we copy the values to low
1488 // registers before pushing them. Record the copy so we can emit the
1489 // correct ".save" later.
1490 AFI->EHPrologueRemappedRegs[DstReg] = SrcReg;
1491 break;
1492 case ARM::VMRS:
1493 case ARM::VMRS_FPEXC:
1494 // If a function spills FPSCR or FPEXC, we copy the values to low
1495 // registers before pushing them. However, we can't issue annotations
1496 // for FP status registers because ".save" requires GPR registers, and
1497 // ".vsave" requires DPR registers, so don't record the copy and simply
1498 // emit annotations for the source registers used for the store.
1499 break;
1500 case ARM::tLDRpci: {
1501 // Grab the constpool index and check, whether it corresponds to
1502 // original or cloned constpool entry.
1503 unsigned CPI = MI->getOperand(i: 1).getIndex();
1504 const MachineConstantPool *MCP = MF.getConstantPool();
1505 if (CPI >= MCP->getConstants().size())
1506 CPI = AFI->getOriginalCPIdx(CloneIdx: CPI);
1507 assert(CPI != -1U && "Invalid constpool index");
1508
1509 // Derive the actual offset.
1510 const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI];
1511 assert(!CPE.isMachineConstantPoolEntry() && "Invalid constpool entry");
1512 Offset = cast<ConstantInt>(Val: CPE.Val.ConstVal)->getSExtValue();
1513 AFI->EHPrologueOffsetInRegs[DstReg] = Offset;
1514 break;
1515 }
1516 case ARM::t2MOVi16:
1517 Offset = MI->getOperand(i: 1).getImm();
1518 AFI->EHPrologueOffsetInRegs[DstReg] = Offset;
1519 break;
1520 case ARM::t2MOVTi16:
1521 Offset = MI->getOperand(i: 2).getImm();
1522 AFI->EHPrologueOffsetInRegs[DstReg] |= (Offset << 16);
1523 break;
1524 case ARM::tMOVi8:
1525 Offset = MI->getOperand(i: 2).getImm();
1526 AFI->EHPrologueOffsetInRegs[DstReg] = Offset;
1527 break;
1528 case ARM::tLSLri:
1529 assert(MI->getOperand(3).getImm() == 8 &&
1530 "The shift amount is not equal to 8");
1531 assert(MI->getOperand(2).getReg() == MI->getOperand(0).getReg() &&
1532 "The source register is not equal to the destination register");
1533 AFI->EHPrologueOffsetInRegs[DstReg] <<= 8;
1534 break;
1535 case ARM::tADDi8:
1536 assert(MI->getOperand(2).getReg() == MI->getOperand(0).getReg() &&
1537 "The source register is not equal to the destination register");
1538 Offset = MI->getOperand(i: 3).getImm();
1539 AFI->EHPrologueOffsetInRegs[DstReg] += Offset;
1540 break;
1541 case ARM::t2PAC:
1542 case ARM::t2PACBTI:
1543 AFI->EHPrologueRemappedRegs[ARM::R12] = ARM::RA_AUTH_CODE;
1544 break;
1545 default:
1546 MI->print(OS&: errs());
1547 llvm_unreachable("Unsupported opcode for unwinding information");
1548 }
1549 }
1550 }
1551}
1552
1553// Simple pseudo-instructions have their lowering (with expansion to real
1554// instructions) auto-generated.
1555#include "ARMGenMCPseudoLowering.inc"
1556
1557// Helper function to check if a register is live (used as an implicit operand)
1558// in the given call instruction.
1559static bool isRegisterLiveInCall(const MachineInstr &Call, MCRegister Reg) {
1560 for (const MachineOperand &MO : Call.implicit_operands()) {
1561 if (MO.isReg() && MO.getReg() == Reg && MO.isUse()) {
1562 return true;
1563 }
1564 }
1565 return false;
1566}
1567
1568void ARMAsmPrinter::EmitKCFI_CHECK_ARM32(Register AddrReg, int64_t Type,
1569 const MachineInstr &Call,
1570 int64_t PrefixNops) {
1571 // Choose scratch register: r12 primary, r3 if target is r12.
1572 unsigned ScratchReg = ARM::R12;
1573 if (AddrReg == ARM::R12) {
1574 ScratchReg = ARM::R3;
1575 }
1576
1577 // Calculate ESR for ARM mode (16-bit): 0x8000 | (scratch_reg << 5) | addr_reg
1578 // Note: scratch_reg is always 0x1F since the EOR sequence clobbers it.
1579 const ARMBaseRegisterInfo *TRI = static_cast<const ARMBaseRegisterInfo *>(
1580 MF->getSubtarget().getRegisterInfo());
1581 unsigned AddrIndex = TRI->getEncodingValue(Reg: AddrReg);
1582 unsigned ESR = 0x8000 | (31 << 5) | (AddrIndex & 31);
1583
1584 // Check if r3 is live and needs to be spilled.
1585 bool NeedSpillR3 =
1586 (ScratchReg == ARM::R3) && isRegisterLiveInCall(Call, Reg: ARM::R3);
1587
1588 // If we need to spill r3, push it first.
1589 if (NeedSpillR3) {
1590 // push {r3}
1591 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::STMDB_UPD)
1592 .addReg(Reg: ARM::SP)
1593 .addReg(Reg: ARM::SP)
1594 .addImm(Val: ARMCC::AL)
1595 .addReg(Reg: 0)
1596 .addReg(Reg: ARM::R3));
1597 }
1598
1599 // Clear bit 0 of target address to handle Thumb function pointers.
1600 // In 32-bit ARM, function pointers may have the low bit set to indicate
1601 // Thumb state when ARM/Thumb interworking is enabled (ARMv4T and later).
1602 // We need to clear it to avoid an alignment fault when loading.
1603 // bic scratch, target, #1
1604 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::BICri)
1605 .addReg(Reg: ScratchReg)
1606 .addReg(Reg: AddrReg)
1607 .addImm(Val: 1)
1608 .addImm(Val: ARMCC::AL)
1609 .addReg(Reg: 0)
1610 .addReg(Reg: 0));
1611
1612 // ldr scratch, [scratch, #-(PrefixNops * 4 + 4)]
1613 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::LDRi12)
1614 .addReg(Reg: ScratchReg)
1615 .addReg(Reg: ScratchReg)
1616 .addImm(Val: -(PrefixNops * 4 + 4))
1617 .addImm(Val: ARMCC::AL)
1618 .addReg(Reg: 0));
1619
1620 // Each EOR instruction XORs one byte of the type, shifted to its position.
1621 for (int i = 0; i < 4; i++) {
1622 uint8_t byte = (Type >> (i * 8)) & 0xFF;
1623 uint32_t imm = byte << (i * 8);
1624 bool isLast = (i == 3);
1625
1626 // Encode as ARM modified immediate.
1627 int SOImmVal = ARM_AM::getSOImmVal(Arg: imm);
1628 assert(SOImmVal != -1 &&
1629 "Cannot encode immediate as ARM modified immediate");
1630
1631 // eor[s] scratch, scratch, #imm (last one sets flags with CPSR)
1632 EmitToStreamer(S&: *OutStreamer,
1633 Inst: MCInstBuilder(ARM::EORri)
1634 .addReg(Reg: ScratchReg)
1635 .addReg(Reg: ScratchReg)
1636 .addImm(Val: SOImmVal)
1637 .addImm(Val: ARMCC::AL)
1638 .addReg(Reg: 0)
1639 .addReg(Reg: isLast ? ARM::CPSR : ARM::NoRegister));
1640 }
1641
1642 // If we spilled r3, restore it immediately after the comparison.
1643 // This must happen before the branch so r3 is valid on both paths.
1644 if (NeedSpillR3) {
1645 // pop {r3}
1646 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::LDMIA_UPD)
1647 .addReg(Reg: ARM::SP)
1648 .addReg(Reg: ARM::SP)
1649 .addImm(Val: ARMCC::AL)
1650 .addReg(Reg: 0)
1651 .addReg(Reg: ARM::R3));
1652 }
1653
1654 // beq .Lpass (branch if types match, i.e., scratch is zero)
1655 MCSymbol *Pass = OutContext.createTempSymbol();
1656 EmitToStreamer(S&: *OutStreamer,
1657 Inst: MCInstBuilder(ARM::Bcc)
1658 .addExpr(Val: MCSymbolRefExpr::create(Symbol: Pass, Ctx&: OutContext))
1659 .addImm(Val: ARMCC::EQ)
1660 .addReg(Reg: ARM::CPSR));
1661
1662 // udf #ESR (trap with encoded diagnostic)
1663 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::UDF).addImm(Val: ESR));
1664
1665 OutStreamer->emitLabel(Symbol: Pass);
1666}
1667
1668void ARMAsmPrinter::EmitKCFI_CHECK_Thumb2(Register AddrReg, int64_t Type,
1669 const MachineInstr &Call,
1670 int64_t PrefixNops) {
1671 // Choose scratch register: r12 primary, r3 if target is r12.
1672 unsigned ScratchReg = ARM::R12;
1673 if (AddrReg == ARM::R12) {
1674 ScratchReg = ARM::R3;
1675 }
1676
1677 // Calculate ESR for Thumb mode (8-bit): 0x80 | addr_reg
1678 // Bit 7: KCFI trap indicator
1679 // Bits 6-5: Reserved
1680 // Bits 4-0: Address register encoding
1681 const ARMBaseRegisterInfo *TRI = static_cast<const ARMBaseRegisterInfo *>(
1682 MF->getSubtarget().getRegisterInfo());
1683 unsigned AddrIndex = TRI->getEncodingValue(Reg: AddrReg);
1684 unsigned ESR = 0x80 | (AddrIndex & 0x1F);
1685
1686 // Check if r3 is live and needs to be spilled.
1687 bool NeedSpillR3 =
1688 (ScratchReg == ARM::R3) && isRegisterLiveInCall(Call, Reg: ARM::R3);
1689
1690 // If we need to spill r3, push it first.
1691 if (NeedSpillR3) {
1692 // push {r3}
1693 EmitToStreamer(
1694 S&: *OutStreamer,
1695 Inst: MCInstBuilder(ARM::tPUSH).addImm(Val: ARMCC::AL).addReg(Reg: 0).addReg(Reg: ARM::R3));
1696 }
1697
1698 // Clear bit 0 of target address to handle Thumb function pointers.
1699 // In 32-bit ARM, function pointers may have the low bit set to indicate
1700 // Thumb state when ARM/Thumb interworking is enabled (ARMv4T and later).
1701 // We need to clear it to avoid an alignment fault when loading.
1702 // bic scratch, target, #1
1703 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::t2BICri)
1704 .addReg(Reg: ScratchReg)
1705 .addReg(Reg: AddrReg)
1706 .addImm(Val: 1)
1707 .addImm(Val: ARMCC::AL)
1708 .addReg(Reg: 0)
1709 .addReg(Reg: 0));
1710
1711 // ldr scratch, [scratch, #-(PrefixNops * 4 + 4)]
1712 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::t2LDRi8)
1713 .addReg(Reg: ScratchReg)
1714 .addReg(Reg: ScratchReg)
1715 .addImm(Val: -(PrefixNops * 4 + 4))
1716 .addImm(Val: ARMCC::AL)
1717 .addReg(Reg: 0));
1718
1719 // Each EOR instruction XORs one byte of the type, shifted to its position.
1720 for (int i = 0; i < 4; i++) {
1721 uint8_t byte = (Type >> (i * 8)) & 0xFF;
1722 uint32_t imm = byte << (i * 8);
1723 bool isLast = (i == 3);
1724
1725 // Verify the immediate can be encoded as Thumb2 modified immediate.
1726 assert(ARM_AM::getT2SOImmVal(imm) != -1 &&
1727 "Cannot encode immediate as Thumb2 modified immediate");
1728
1729 // eor[s] scratch, scratch, #imm (last one sets flags with CPSR)
1730 EmitToStreamer(S&: *OutStreamer,
1731 Inst: MCInstBuilder(ARM::t2EORri)
1732 .addReg(Reg: ScratchReg)
1733 .addReg(Reg: ScratchReg)
1734 .addImm(Val: imm)
1735 .addImm(Val: ARMCC::AL)
1736 .addReg(Reg: 0)
1737 .addReg(Reg: isLast ? ARM::CPSR : ARM::NoRegister));
1738 }
1739
1740 // If we spilled r3, restore it immediately after the comparison.
1741 // This must happen before the branch so r3 is valid on both paths.
1742 if (NeedSpillR3) {
1743 // pop {r3}
1744 EmitToStreamer(
1745 S&: *OutStreamer,
1746 Inst: MCInstBuilder(ARM::tPOP).addImm(Val: ARMCC::AL).addReg(Reg: 0).addReg(Reg: ARM::R3));
1747 }
1748
1749 // beq .Lpass (branch if types match, i.e., scratch is zero)
1750 MCSymbol *Pass = OutContext.createTempSymbol();
1751 EmitToStreamer(S&: *OutStreamer,
1752 Inst: MCInstBuilder(ARM::t2Bcc)
1753 .addExpr(Val: MCSymbolRefExpr::create(Symbol: Pass, Ctx&: OutContext))
1754 .addImm(Val: ARMCC::EQ)
1755 .addReg(Reg: ARM::CPSR));
1756
1757 // udf #ESR (trap with encoded diagnostic)
1758 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tUDF).addImm(Val: ESR));
1759
1760 OutStreamer->emitLabel(Symbol: Pass);
1761}
1762
1763void ARMAsmPrinter::EmitKCFI_CHECK_Thumb1(Register AddrReg, int64_t Type,
1764 const MachineInstr &Call,
1765 int64_t PrefixNops) {
1766 // For Thumb1, use R2 unconditionally as scratch register (a low register
1767 // required for tLDRi). R3 is used for building the type hash.
1768 unsigned ScratchReg = ARM::R2;
1769 unsigned TempReg = ARM::R3;
1770
1771 // Check if r3 is live and needs to be spilled.
1772 bool NeedSpillR3 = isRegisterLiveInCall(Call, Reg: ARM::R3);
1773
1774 // Spill r3 if needed
1775 if (NeedSpillR3) {
1776 EmitToStreamer(
1777 S&: *OutStreamer,
1778 Inst: MCInstBuilder(ARM::tPUSH).addImm(Val: ARMCC::AL).addReg(Reg: 0).addReg(Reg: ARM::R3));
1779 }
1780
1781 // Check if r2 is live and needs to be spilled.
1782 bool NeedSpillR2 = isRegisterLiveInCall(Call, Reg: ARM::R2);
1783
1784 // Push R2 if it's live
1785 if (NeedSpillR2) {
1786 EmitToStreamer(
1787 S&: *OutStreamer,
1788 Inst: MCInstBuilder(ARM::tPUSH).addImm(Val: ARMCC::AL).addReg(Reg: 0).addReg(Reg: ARM::R2));
1789 }
1790
1791 // Clear bit 0 from target address
1792 // TempReg (R3) is used first as helper for BIC, then later for building type
1793 // hash.
1794
1795 // movs temp, #1
1796 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tMOVi8)
1797 .addReg(Reg: TempReg)
1798 .addReg(Reg: ARM::CPSR)
1799 .addImm(Val: 1)
1800 .addImm(Val: ARMCC::AL)
1801 .addReg(Reg: 0));
1802
1803 // mov scratch, target
1804 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tMOVr)
1805 .addReg(Reg: ScratchReg)
1806 .addReg(Reg: AddrReg)
1807 .addImm(Val: ARMCC::AL));
1808
1809 // bics scratch, temp (scratch = scratch & ~temp)
1810 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tBIC)
1811 .addReg(Reg: ScratchReg)
1812 .addReg(Reg: ARM::CPSR)
1813 .addReg(Reg: ScratchReg)
1814 .addReg(Reg: TempReg)
1815 .addImm(Val: ARMCC::AL)
1816 .addReg(Reg: 0));
1817
1818 // Load type hash. Thumb1 doesn't support negative offsets, so subtract.
1819 int offset = PrefixNops * 4 + 4;
1820
1821 // subs scratch, #offset
1822 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tSUBi8)
1823 .addReg(Reg: ScratchReg)
1824 .addReg(Reg: ARM::CPSR)
1825 .addReg(Reg: ScratchReg)
1826 .addImm(Val: offset)
1827 .addImm(Val: ARMCC::AL)
1828 .addReg(Reg: 0));
1829
1830 // ldr scratch, [scratch, #0]
1831 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tLDRi)
1832 .addReg(Reg: ScratchReg)
1833 .addReg(Reg: ScratchReg)
1834 .addImm(Val: 0)
1835 .addImm(Val: ARMCC::AL)
1836 .addReg(Reg: 0));
1837
1838 // Load expected type inline (instead of EOR sequence)
1839 //
1840 // This creates the 32-bit value byte-by-byte in the temp register:
1841 // movs temp, #byte3 (high byte)
1842 // lsls temp, temp, #8
1843 // adds temp, #byte2
1844 // lsls temp, temp, #8
1845 // adds temp, #byte1
1846 // lsls temp, temp, #8
1847 // adds temp, #byte0 (low byte)
1848
1849 uint8_t byte0 = (Type >> 0) & 0xFF;
1850 uint8_t byte1 = (Type >> 8) & 0xFF;
1851 uint8_t byte2 = (Type >> 16) & 0xFF;
1852 uint8_t byte3 = (Type >> 24) & 0xFF;
1853
1854 // movs temp, #byte3 (start with high byte)
1855 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tMOVi8)
1856 .addReg(Reg: TempReg)
1857 .addReg(Reg: ARM::CPSR)
1858 .addImm(Val: byte3)
1859 .addImm(Val: ARMCC::AL)
1860 .addReg(Reg: 0));
1861
1862 // lsls temp, temp, #8
1863 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tLSLri)
1864 .addReg(Reg: TempReg)
1865 .addReg(Reg: ARM::CPSR)
1866 .addReg(Reg: TempReg)
1867 .addImm(Val: 8)
1868 .addImm(Val: ARMCC::AL)
1869 .addReg(Reg: 0));
1870
1871 // adds temp, #byte2
1872 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tADDi8)
1873 .addReg(Reg: TempReg)
1874 .addReg(Reg: ARM::CPSR)
1875 .addReg(Reg: TempReg)
1876 .addImm(Val: byte2)
1877 .addImm(Val: ARMCC::AL)
1878 .addReg(Reg: 0));
1879
1880 // lsls temp, temp, #8
1881 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tLSLri)
1882 .addReg(Reg: TempReg)
1883 .addReg(Reg: ARM::CPSR)
1884 .addReg(Reg: TempReg)
1885 .addImm(Val: 8)
1886 .addImm(Val: ARMCC::AL)
1887 .addReg(Reg: 0));
1888
1889 // adds temp, #byte1
1890 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tADDi8)
1891 .addReg(Reg: TempReg)
1892 .addReg(Reg: ARM::CPSR)
1893 .addReg(Reg: TempReg)
1894 .addImm(Val: byte1)
1895 .addImm(Val: ARMCC::AL)
1896 .addReg(Reg: 0));
1897
1898 // lsls temp, temp, #8
1899 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tLSLri)
1900 .addReg(Reg: TempReg)
1901 .addReg(Reg: ARM::CPSR)
1902 .addReg(Reg: TempReg)
1903 .addImm(Val: 8)
1904 .addImm(Val: ARMCC::AL)
1905 .addReg(Reg: 0));
1906
1907 // adds temp, #byte0 (low byte)
1908 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tADDi8)
1909 .addReg(Reg: TempReg)
1910 .addReg(Reg: ARM::CPSR)
1911 .addReg(Reg: TempReg)
1912 .addImm(Val: byte0)
1913 .addImm(Val: ARMCC::AL)
1914 .addReg(Reg: 0));
1915
1916 // cmp scratch, temp
1917 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tCMPr)
1918 .addReg(Reg: ScratchReg)
1919 .addReg(Reg: TempReg)
1920 .addImm(Val: ARMCC::AL)
1921 .addReg(Reg: 0));
1922
1923 // Restore registers if spilled (pop in reverse order of push: R2, then R3)
1924 if (NeedSpillR2) {
1925 // pop {r2}
1926 EmitToStreamer(
1927 S&: *OutStreamer,
1928 Inst: MCInstBuilder(ARM::tPOP).addImm(Val: ARMCC::AL).addReg(Reg: 0).addReg(Reg: ARM::R2));
1929 }
1930
1931 // Restore r3 if spilled
1932 if (NeedSpillR3) {
1933 // pop {r3}
1934 EmitToStreamer(
1935 S&: *OutStreamer,
1936 Inst: MCInstBuilder(ARM::tPOP).addImm(Val: ARMCC::AL).addReg(Reg: 0).addReg(Reg: ARM::R3));
1937 }
1938
1939 // beq .Lpass (branch if types match, i.e., scratch == temp)
1940 MCSymbol *Pass = OutContext.createTempSymbol();
1941 EmitToStreamer(S&: *OutStreamer,
1942 Inst: MCInstBuilder(ARM::tBcc)
1943 .addExpr(Val: MCSymbolRefExpr::create(Symbol: Pass, Ctx&: OutContext))
1944 .addImm(Val: ARMCC::EQ)
1945 .addReg(Reg: ARM::CPSR));
1946
1947 // bkpt #0 (trap with encoded diagnostic)
1948 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tBKPT).addImm(Val: 0));
1949
1950 OutStreamer->emitLabel(Symbol: Pass);
1951}
1952
1953void ARMAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
1954 Register AddrReg = MI.getOperand(i: 0).getReg();
1955 const int64_t Type = MI.getOperand(i: 1).getImm();
1956
1957 // Get the call instruction that follows this KCFI_CHECK.
1958 assert(std::next(MI.getIterator())->isCall() &&
1959 "KCFI_CHECK not followed by a call instruction");
1960 const MachineInstr &Call = *std::next(x: MI.getIterator());
1961
1962 // Adjust the offset for patchable-function-prefix.
1963 int64_t PrefixNops = MI.getMF()->getFunction().getFnAttributeAsParsedInteger(
1964 Kind: "patchable-function-prefix");
1965
1966 // Emit the appropriate instruction sequence based on the opcode variant.
1967 switch (MI.getOpcode()) {
1968 case ARM::KCFI_CHECK_ARM:
1969 EmitKCFI_CHECK_ARM32(AddrReg, Type, Call, PrefixNops);
1970 break;
1971 case ARM::KCFI_CHECK_Thumb2:
1972 EmitKCFI_CHECK_Thumb2(AddrReg, Type, Call, PrefixNops);
1973 break;
1974 case ARM::KCFI_CHECK_Thumb1:
1975 EmitKCFI_CHECK_Thumb1(AddrReg, Type, Call, PrefixNops);
1976 break;
1977 default:
1978 llvm_unreachable("Unexpected KCFI_CHECK opcode");
1979 }
1980}
1981
1982void ARMAsmPrinter::emitInstruction(const MachineInstr *MI) {
1983 ARM_MC::verifyInstructionPredicates(Opcode: MI->getOpcode(),
1984 Features: getSubtargetInfo().getFeatureBits());
1985
1986 const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();
1987 const DataLayout &DL = getDataLayout();
1988 MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
1989 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
1990
1991 // If we just ended a constant pool, mark it as such.
1992 if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) {
1993 OutStreamer->emitDataRegion(Kind: MCDR_DataRegionEnd);
1994 InConstantPool = false;
1995 }
1996
1997 // Emit unwinding stuff for frame-related instructions
1998 if (TM.getTargetTriple().isTargetEHABICompatible() &&
1999 MI->getFlag(Flag: MachineInstr::FrameSetup))
2000 EmitUnwindingInstruction(MI);
2001
2002 // Do any auto-generated pseudo lowerings.
2003 if (MCInst OutInst; lowerPseudoInstExpansion(MI, Inst&: OutInst)) {
2004 EmitToStreamer(S&: *OutStreamer, Inst: OutInst);
2005 return;
2006 }
2007
2008 assert(!convertAddSubFlagsOpcode(MI->getOpcode()) &&
2009 "Pseudo flag setting opcode should be expanded early");
2010
2011 // Check for manual lowerings.
2012 unsigned Opc = MI->getOpcode();
2013 switch (Opc) {
2014 case ARM::t2MOVi32imm: llvm_unreachable("Should be lowered by thumb2it pass");
2015 case ARM::DBG_VALUE: llvm_unreachable("Should be handled by generic printing");
2016 case ARM::KCFI_CHECK_ARM:
2017 case ARM::KCFI_CHECK_Thumb2:
2018 case ARM::KCFI_CHECK_Thumb1:
2019 LowerKCFI_CHECK(MI: *MI);
2020 return;
2021 case ARM::LEApcrel:
2022 case ARM::tLEApcrel:
2023 case ARM::t2LEApcrel: {
2024 // FIXME: Need to also handle globals and externals
2025 MCSymbol *CPISymbol = GetCPISymbol(CPID: MI->getOperand(i: 1).getIndex());
2026 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(MI->getOpcode() ==
2027 ARM::t2LEApcrel ? ARM::t2ADR
2028 : (MI->getOpcode() == ARM::tLEApcrel ? ARM::tADR
2029 : ARM::ADR))
2030 .addReg(Reg: MI->getOperand(i: 0).getReg())
2031 .addExpr(Val: MCSymbolRefExpr::create(Symbol: CPISymbol, Ctx&: OutContext))
2032 // Add predicate operands.
2033 .addImm(Val: MI->getOperand(i: 2).getImm())
2034 .addReg(Reg: MI->getOperand(i: 3).getReg()));
2035 return;
2036 }
2037 case ARM::LEApcrelJT:
2038 case ARM::tLEApcrelJT:
2039 case ARM::t2LEApcrelJT: {
2040 MCSymbol *JTIPICSymbol =
2041 GetARMJTIPICJumpTableLabel(uid: MI->getOperand(i: 1).getIndex());
2042 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(MI->getOpcode() ==
2043 ARM::t2LEApcrelJT ? ARM::t2ADR
2044 : (MI->getOpcode() == ARM::tLEApcrelJT ? ARM::tADR
2045 : ARM::ADR))
2046 .addReg(Reg: MI->getOperand(i: 0).getReg())
2047 .addExpr(Val: MCSymbolRefExpr::create(Symbol: JTIPICSymbol, Ctx&: OutContext))
2048 // Add predicate operands.
2049 .addImm(Val: MI->getOperand(i: 2).getImm())
2050 .addReg(Reg: MI->getOperand(i: 3).getReg()));
2051 return;
2052 }
2053 // Darwin call instructions are just normal call instructions with different
2054 // clobber semantics (they clobber R9).
2055 case ARM::BX_CALL: {
2056 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::MOVr)
2057 .addReg(Reg: ARM::LR)
2058 .addReg(Reg: ARM::PC)
2059 // Add predicate operands.
2060 .addImm(Val: ARMCC::AL)
2061 .addReg(Reg: 0)
2062 // Add 's' bit operand (always reg0 for this)
2063 .addReg(Reg: 0));
2064
2065 assert(STI.hasV4TOps() && "Expected V4TOps for BX call");
2066 EmitToStreamer(S&: *OutStreamer,
2067 Inst: MCInstBuilder(ARM::BX).addReg(Reg: MI->getOperand(i: 0).getReg()));
2068 return;
2069 }
2070 case ARM::tBX_CALL: {
2071 assert(!STI.hasV5TOps() && "Expected BLX to be selected for v5t+");
2072
2073 // On ARM v4t, when doing a call from thumb mode, we need to ensure
2074 // that the saved lr has its LSB set correctly (the arch doesn't
2075 // have blx).
2076 // So here we generate a bl to a small jump pad that does bx rN.
2077 // The jump pads are emitted after the function body.
2078
2079 Register TReg = MI->getOperand(i: 0).getReg();
2080 MCSymbol *TRegSym = nullptr;
2081 for (std::pair<unsigned, MCSymbol *> &TIP : ThumbIndirectPads) {
2082 if (TIP.first == TReg) {
2083 TRegSym = TIP.second;
2084 break;
2085 }
2086 }
2087
2088 if (!TRegSym) {
2089 TRegSym = OutContext.createTempSymbol();
2090 ThumbIndirectPads.push_back(Elt: std::make_pair(x&: TReg, y&: TRegSym));
2091 }
2092
2093 // Create a link-saving branch to the Reg Indirect Jump Pad.
2094 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tBL)
2095 // Predicate comes first here.
2096 .addImm(Val: ARMCC::AL).addReg(Reg: 0)
2097 .addExpr(Val: MCSymbolRefExpr::create(Symbol: TRegSym, Ctx&: OutContext)));
2098 return;
2099 }
2100 case ARM::BMOVPCRX_CALL: {
2101 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::MOVr)
2102 .addReg(Reg: ARM::LR)
2103 .addReg(Reg: ARM::PC)
2104 // Add predicate operands.
2105 .addImm(Val: ARMCC::AL)
2106 .addReg(Reg: 0)
2107 // Add 's' bit operand (always reg0 for this)
2108 .addReg(Reg: 0));
2109
2110 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::MOVr)
2111 .addReg(Reg: ARM::PC)
2112 .addReg(Reg: MI->getOperand(i: 0).getReg())
2113 // Add predicate operands.
2114 .addImm(Val: ARMCC::AL)
2115 .addReg(Reg: 0)
2116 // Add 's' bit operand (always reg0 for this)
2117 .addReg(Reg: 0));
2118 return;
2119 }
2120 case ARM::BMOVPCB_CALL: {
2121 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::MOVr)
2122 .addReg(Reg: ARM::LR)
2123 .addReg(Reg: ARM::PC)
2124 // Add predicate operands.
2125 .addImm(Val: ARMCC::AL)
2126 .addReg(Reg: 0)
2127 // Add 's' bit operand (always reg0 for this)
2128 .addReg(Reg: 0));
2129
2130 const MachineOperand &Op = MI->getOperand(i: 0);
2131 const GlobalValue *GV = Op.getGlobal();
2132 const unsigned TF = Op.getTargetFlags();
2133 MCSymbol *GVSym = GetARMGVSymbol(GV, TargetFlags: TF);
2134 const MCExpr *GVSymExpr = MCSymbolRefExpr::create(Symbol: GVSym, Ctx&: OutContext);
2135 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::Bcc)
2136 .addExpr(Val: GVSymExpr)
2137 // Add predicate operands.
2138 .addImm(Val: ARMCC::AL)
2139 .addReg(Reg: 0));
2140 return;
2141 }
2142 case ARM::MOVi16_ga_pcrel:
2143 case ARM::t2MOVi16_ga_pcrel: {
2144 MCInst TmpInst;
2145 TmpInst.setOpcode(Opc == ARM::MOVi16_ga_pcrel? ARM::MOVi16 : ARM::t2MOVi16);
2146 TmpInst.addOperand(Op: MCOperand::createReg(Reg: MI->getOperand(i: 0).getReg()));
2147
2148 unsigned TF = MI->getOperand(i: 1).getTargetFlags();
2149 const GlobalValue *GV = MI->getOperand(i: 1).getGlobal();
2150 MCSymbol *GVSym = GetARMGVSymbol(GV, TargetFlags: TF);
2151 const MCExpr *GVSymExpr = MCSymbolRefExpr::create(Symbol: GVSym, Ctx&: OutContext);
2152
2153 MCSymbol *LabelSym =
2154 getPICLabel(Prefix: DL.getInternalSymbolPrefix(), FunctionNumber: getFunctionNumber(),
2155 LabelId: MI->getOperand(i: 2).getImm(), Ctx&: OutContext);
2156 const MCExpr *LabelSymExpr= MCSymbolRefExpr::create(Symbol: LabelSym, Ctx&: OutContext);
2157 unsigned PCAdj = (Opc == ARM::MOVi16_ga_pcrel) ? 8 : 4;
2158 const MCExpr *PCRelExpr = ARM::createLower16(
2159 Expr: MCBinaryExpr::createSub(
2160 LHS: GVSymExpr,
2161 RHS: MCBinaryExpr::createAdd(LHS: LabelSymExpr,
2162 RHS: MCConstantExpr::create(Value: PCAdj, Ctx&: OutContext),
2163 Ctx&: OutContext),
2164 Ctx&: OutContext),
2165 Ctx&: OutContext);
2166 TmpInst.addOperand(Op: MCOperand::createExpr(Val: PCRelExpr));
2167
2168 // Add predicate operands.
2169 TmpInst.addOperand(Op: MCOperand::createImm(Val: ARMCC::AL));
2170 TmpInst.addOperand(Op: MCOperand::createReg(Reg: 0));
2171 // Add 's' bit operand (always reg0 for this)
2172 TmpInst.addOperand(Op: MCOperand::createReg(Reg: 0));
2173 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
2174 return;
2175 }
2176 case ARM::MOVTi16_ga_pcrel:
2177 case ARM::t2MOVTi16_ga_pcrel: {
2178 MCInst TmpInst;
2179 TmpInst.setOpcode(Opc == ARM::MOVTi16_ga_pcrel
2180 ? ARM::MOVTi16 : ARM::t2MOVTi16);
2181 TmpInst.addOperand(Op: MCOperand::createReg(Reg: MI->getOperand(i: 0).getReg()));
2182 TmpInst.addOperand(Op: MCOperand::createReg(Reg: MI->getOperand(i: 1).getReg()));
2183
2184 unsigned TF = MI->getOperand(i: 2).getTargetFlags();
2185 const GlobalValue *GV = MI->getOperand(i: 2).getGlobal();
2186 MCSymbol *GVSym = GetARMGVSymbol(GV, TargetFlags: TF);
2187 const MCExpr *GVSymExpr = MCSymbolRefExpr::create(Symbol: GVSym, Ctx&: OutContext);
2188
2189 MCSymbol *LabelSym =
2190 getPICLabel(Prefix: DL.getInternalSymbolPrefix(), FunctionNumber: getFunctionNumber(),
2191 LabelId: MI->getOperand(i: 3).getImm(), Ctx&: OutContext);
2192 const MCExpr *LabelSymExpr= MCSymbolRefExpr::create(Symbol: LabelSym, Ctx&: OutContext);
2193 unsigned PCAdj = (Opc == ARM::MOVTi16_ga_pcrel) ? 8 : 4;
2194 const MCExpr *PCRelExpr = ARM::createUpper16(
2195 Expr: MCBinaryExpr::createSub(
2196 LHS: GVSymExpr,
2197 RHS: MCBinaryExpr::createAdd(LHS: LabelSymExpr,
2198 RHS: MCConstantExpr::create(Value: PCAdj, Ctx&: OutContext),
2199 Ctx&: OutContext),
2200 Ctx&: OutContext),
2201 Ctx&: OutContext);
2202 TmpInst.addOperand(Op: MCOperand::createExpr(Val: PCRelExpr));
2203 // Add predicate operands.
2204 TmpInst.addOperand(Op: MCOperand::createImm(Val: ARMCC::AL));
2205 TmpInst.addOperand(Op: MCOperand::createReg(Reg: 0));
2206 // Add 's' bit operand (always reg0 for this)
2207 TmpInst.addOperand(Op: MCOperand::createReg(Reg: 0));
2208 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
2209 return;
2210 }
2211 case ARM::t2BFi:
2212 case ARM::t2BFic:
2213 case ARM::t2BFLi:
2214 case ARM::t2BFr:
2215 case ARM::t2BFLr: {
2216 // This is a Branch Future instruction.
2217
2218 const MCExpr *BranchLabel = MCSymbolRefExpr::create(
2219 Symbol: getBFLabel(Prefix: DL.getInternalSymbolPrefix(), FunctionNumber: getFunctionNumber(),
2220 LabelId: MI->getOperand(i: 0).getIndex(), Ctx&: OutContext),
2221 Ctx&: OutContext);
2222
2223 auto MCInst = MCInstBuilder(Opc).addExpr(Val: BranchLabel);
2224 if (MI->getOperand(i: 1).isReg()) {
2225 // For BFr/BFLr
2226 MCInst.addReg(Reg: MI->getOperand(i: 1).getReg());
2227 } else {
2228 // For BFi/BFLi/BFic
2229 const MCExpr *BranchTarget;
2230 if (MI->getOperand(i: 1).isMBB())
2231 BranchTarget = MCSymbolRefExpr::create(
2232 Symbol: MI->getOperand(i: 1).getMBB()->getSymbol(), Ctx&: OutContext);
2233 else if (MI->getOperand(i: 1).isGlobal()) {
2234 const GlobalValue *GV = MI->getOperand(i: 1).getGlobal();
2235 BranchTarget = MCSymbolRefExpr::create(
2236 Symbol: GetARMGVSymbol(GV, TargetFlags: MI->getOperand(i: 1).getTargetFlags()), Ctx&: OutContext);
2237 } else if (MI->getOperand(i: 1).isSymbol()) {
2238 BranchTarget = MCSymbolRefExpr::create(
2239 Symbol: GetExternalSymbolSymbol(Sym: MI->getOperand(i: 1).getSymbolName()),
2240 Ctx&: OutContext);
2241 } else
2242 llvm_unreachable("Unhandled operand kind in Branch Future instruction");
2243
2244 MCInst.addExpr(Val: BranchTarget);
2245 }
2246
2247 if (Opc == ARM::t2BFic) {
2248 const MCExpr *ElseLabel = MCSymbolRefExpr::create(
2249 Symbol: getBFLabel(Prefix: DL.getInternalSymbolPrefix(), FunctionNumber: getFunctionNumber(),
2250 LabelId: MI->getOperand(i: 2).getIndex(), Ctx&: OutContext),
2251 Ctx&: OutContext);
2252 MCInst.addExpr(Val: ElseLabel);
2253 MCInst.addImm(Val: MI->getOperand(i: 3).getImm());
2254 } else {
2255 MCInst.addImm(Val: MI->getOperand(i: 2).getImm())
2256 .addReg(Reg: MI->getOperand(i: 3).getReg());
2257 }
2258
2259 EmitToStreamer(S&: *OutStreamer, Inst: MCInst);
2260 return;
2261 }
2262 case ARM::t2BF_LabelPseudo: {
2263 // This is a pseudo op for a label used by a branch future instruction
2264
2265 // Emit the label.
2266 OutStreamer->emitLabel(
2267 Symbol: getBFLabel(Prefix: DL.getInternalSymbolPrefix(), FunctionNumber: getFunctionNumber(),
2268 LabelId: MI->getOperand(i: 0).getIndex(), Ctx&: OutContext));
2269 return;
2270 }
2271 case ARM::tPICADD: {
2272 // This is a pseudo op for a label + instruction sequence, which looks like:
2273 // LPC0:
2274 // add r0, pc
2275 // This adds the address of LPC0 to r0.
2276
2277 // Emit the label.
2278 OutStreamer->emitLabel(Symbol: getPICLabel(Prefix: DL.getInternalSymbolPrefix(),
2279 FunctionNumber: getFunctionNumber(),
2280 LabelId: MI->getOperand(i: 2).getImm(), Ctx&: OutContext));
2281
2282 // Form and emit the add.
2283 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tADDhirr)
2284 .addReg(Reg: MI->getOperand(i: 0).getReg())
2285 .addReg(Reg: MI->getOperand(i: 0).getReg())
2286 .addReg(Reg: ARM::PC)
2287 // Add predicate operands.
2288 .addImm(Val: ARMCC::AL)
2289 .addReg(Reg: 0));
2290 return;
2291 }
2292 case ARM::PICADD: {
2293 // This is a pseudo op for a label + instruction sequence, which looks like:
2294 // LPC0:
2295 // add r0, pc, r0
2296 // This adds the address of LPC0 to r0.
2297
2298 // Emit the label.
2299 OutStreamer->emitLabel(Symbol: getPICLabel(Prefix: DL.getInternalSymbolPrefix(),
2300 FunctionNumber: getFunctionNumber(),
2301 LabelId: MI->getOperand(i: 2).getImm(), Ctx&: OutContext));
2302
2303 // Form and emit the add.
2304 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::ADDrr)
2305 .addReg(Reg: MI->getOperand(i: 0).getReg())
2306 .addReg(Reg: ARM::PC)
2307 .addReg(Reg: MI->getOperand(i: 1).getReg())
2308 // Add predicate operands.
2309 .addImm(Val: MI->getOperand(i: 3).getImm())
2310 .addReg(Reg: MI->getOperand(i: 4).getReg())
2311 // Add 's' bit operand (always reg0 for this)
2312 .addReg(Reg: 0));
2313 return;
2314 }
2315 case ARM::PICSTR:
2316 case ARM::PICSTRB:
2317 case ARM::PICSTRH:
2318 case ARM::PICLDR:
2319 case ARM::PICLDRB:
2320 case ARM::PICLDRH:
2321 case ARM::PICLDRSB:
2322 case ARM::PICLDRSH: {
2323 // This is a pseudo op for a label + instruction sequence, which looks like:
2324 // LPC0:
2325 // OP r0, [pc, r0]
2326 // The LCP0 label is referenced by a constant pool entry in order to get
2327 // a PC-relative address at the ldr instruction.
2328
2329 // Emit the label.
2330 OutStreamer->emitLabel(Symbol: getPICLabel(Prefix: DL.getInternalSymbolPrefix(),
2331 FunctionNumber: getFunctionNumber(),
2332 LabelId: MI->getOperand(i: 2).getImm(), Ctx&: OutContext));
2333
2334 // Form and emit the load
2335 unsigned Opcode;
2336 switch (MI->getOpcode()) {
2337 default:
2338 llvm_unreachable("Unexpected opcode!");
2339 case ARM::PICSTR: Opcode = ARM::STRrs; break;
2340 case ARM::PICSTRB: Opcode = ARM::STRBrs; break;
2341 case ARM::PICSTRH: Opcode = ARM::STRH; break;
2342 case ARM::PICLDR: Opcode = ARM::LDRrs; break;
2343 case ARM::PICLDRB: Opcode = ARM::LDRBrs; break;
2344 case ARM::PICLDRH: Opcode = ARM::LDRH; break;
2345 case ARM::PICLDRSB: Opcode = ARM::LDRSB; break;
2346 case ARM::PICLDRSH: Opcode = ARM::LDRSH; break;
2347 }
2348 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(Opcode)
2349 .addReg(Reg: MI->getOperand(i: 0).getReg())
2350 .addReg(Reg: ARM::PC)
2351 .addReg(Reg: MI->getOperand(i: 1).getReg())
2352 .addImm(Val: 0)
2353 // Add predicate operands.
2354 .addImm(Val: MI->getOperand(i: 3).getImm())
2355 .addReg(Reg: MI->getOperand(i: 4).getReg()));
2356
2357 return;
2358 }
2359 case ARM::CONSTPOOL_ENTRY: {
2360 assert(!STI.genExecuteOnly() &&
2361 "execute-only should not generate constant pools");
2362
2363 /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool
2364 /// in the function. The first operand is the ID# for this instruction, the
2365 /// second is the index into the MachineConstantPool that this is, the third
2366 /// is the size in bytes of this constant pool entry.
2367 /// The required alignment is specified on the basic block holding this MI.
2368 unsigned LabelId = (unsigned)MI->getOperand(i: 0).getImm();
2369 unsigned CPIdx = (unsigned)MI->getOperand(i: 1).getIndex();
2370
2371 // If this is the first entry of the pool, mark it.
2372 if (!InConstantPool) {
2373 OutStreamer->emitDataRegion(Kind: MCDR_DataRegion);
2374 InConstantPool = true;
2375 }
2376
2377 OutStreamer->emitLabel(Symbol: GetCPISymbol(CPID: LabelId));
2378
2379 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
2380 if (MCPE.isMachineConstantPoolEntry())
2381 emitMachineConstantPoolValue(MCPV: MCPE.Val.MachineCPVal);
2382 else
2383 emitGlobalConstant(DL, CV: MCPE.Val.ConstVal);
2384 return;
2385 }
2386 case ARM::JUMPTABLE_ADDRS:
2387 emitJumpTableAddrs(MI);
2388 return;
2389 case ARM::JUMPTABLE_INSTS:
2390 emitJumpTableInsts(MI);
2391 return;
2392 case ARM::JUMPTABLE_TBB:
2393 case ARM::JUMPTABLE_TBH:
2394 emitJumpTableTBInst(MI, OffsetWidth: MI->getOpcode() == ARM::JUMPTABLE_TBB ? 1 : 2);
2395 return;
2396 case ARM::t2BR_JT: {
2397 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tMOVr)
2398 .addReg(Reg: ARM::PC)
2399 .addReg(Reg: MI->getOperand(i: 0).getReg())
2400 // Add predicate operands.
2401 .addImm(Val: ARMCC::AL)
2402 .addReg(Reg: 0));
2403 return;
2404 }
2405 case ARM::t2TBB_JT:
2406 case ARM::t2TBH_JT: {
2407 unsigned Opc = MI->getOpcode() == ARM::t2TBB_JT ? ARM::t2TBB : ARM::t2TBH;
2408 // Lower and emit the PC label, then the instruction itself.
2409 OutStreamer->emitLabel(Symbol: GetCPISymbol(CPID: MI->getOperand(i: 3).getImm()));
2410 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(Opc)
2411 .addReg(Reg: MI->getOperand(i: 0).getReg())
2412 .addReg(Reg: MI->getOperand(i: 1).getReg())
2413 // Add predicate operands.
2414 .addImm(Val: ARMCC::AL)
2415 .addReg(Reg: 0));
2416 return;
2417 }
2418 case ARM::tTBB_JT:
2419 case ARM::tTBH_JT: {
2420
2421 bool Is8Bit = MI->getOpcode() == ARM::tTBB_JT;
2422 Register Base = MI->getOperand(i: 0).getReg();
2423 Register Idx = MI->getOperand(i: 1).getReg();
2424 assert(MI->getOperand(1).isKill() && "We need the index register as scratch!");
2425
2426 // Multiply up idx if necessary.
2427 if (!Is8Bit)
2428 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tLSLri)
2429 .addReg(Reg: Idx)
2430 .addReg(Reg: ARM::CPSR)
2431 .addReg(Reg: Idx)
2432 .addImm(Val: 1)
2433 // Add predicate operands.
2434 .addImm(Val: ARMCC::AL)
2435 .addReg(Reg: 0));
2436
2437 if (Base == ARM::PC) {
2438 // TBB [base, idx] =
2439 // ADDS idx, idx, base
2440 // LDRB idx, [idx, #4] ; or LDRH if TBH
2441 // LSLS idx, #1
2442 // ADDS pc, pc, idx
2443
2444 // When using PC as the base, it's important that there is no padding
2445 // between the last ADDS and the start of the jump table. The jump table
2446 // is 4-byte aligned, so we ensure we're 4 byte aligned here too.
2447 //
2448 // FIXME: Ideally we could vary the LDRB index based on the padding
2449 // between the sequence and jump table, however that relies on MCExprs
2450 // for load indexes which are currently not supported.
2451 OutStreamer->emitCodeAlignment(Alignment: Align(4), STI: getSubtargetInfo());
2452 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tADDhirr)
2453 .addReg(Reg: Idx)
2454 .addReg(Reg: Idx)
2455 .addReg(Reg: Base)
2456 // Add predicate operands.
2457 .addImm(Val: ARMCC::AL)
2458 .addReg(Reg: 0));
2459
2460 unsigned Opc = Is8Bit ? ARM::tLDRBi : ARM::tLDRHi;
2461 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(Opc)
2462 .addReg(Reg: Idx)
2463 .addReg(Reg: Idx)
2464 .addImm(Val: Is8Bit ? 4 : 2)
2465 // Add predicate operands.
2466 .addImm(Val: ARMCC::AL)
2467 .addReg(Reg: 0));
2468 } else {
2469 // TBB [base, idx] =
2470 // LDRB idx, [base, idx] ; or LDRH if TBH
2471 // LSLS idx, #1
2472 // ADDS pc, pc, idx
2473
2474 unsigned Opc = Is8Bit ? ARM::tLDRBr : ARM::tLDRHr;
2475 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(Opc)
2476 .addReg(Reg: Idx)
2477 .addReg(Reg: Base)
2478 .addReg(Reg: Idx)
2479 // Add predicate operands.
2480 .addImm(Val: ARMCC::AL)
2481 .addReg(Reg: 0));
2482 }
2483
2484 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tLSLri)
2485 .addReg(Reg: Idx)
2486 .addReg(Reg: ARM::CPSR)
2487 .addReg(Reg: Idx)
2488 .addImm(Val: 1)
2489 // Add predicate operands.
2490 .addImm(Val: ARMCC::AL)
2491 .addReg(Reg: 0));
2492
2493 OutStreamer->emitLabel(Symbol: GetCPISymbol(CPID: MI->getOperand(i: 3).getImm()));
2494 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tADDhirr)
2495 .addReg(Reg: ARM::PC)
2496 .addReg(Reg: ARM::PC)
2497 .addReg(Reg: Idx)
2498 // Add predicate operands.
2499 .addImm(Val: ARMCC::AL)
2500 .addReg(Reg: 0));
2501 return;
2502 }
2503 case ARM::tBR_JTr:
2504 case ARM::BR_JTr: {
2505 // mov pc, target
2506 MCInst TmpInst;
2507 unsigned Opc = MI->getOpcode() == ARM::BR_JTr ?
2508 ARM::MOVr : ARM::tMOVr;
2509 TmpInst.setOpcode(Opc);
2510 TmpInst.addOperand(Op: MCOperand::createReg(Reg: ARM::PC));
2511 TmpInst.addOperand(Op: MCOperand::createReg(Reg: MI->getOperand(i: 0).getReg()));
2512 // Add predicate operands.
2513 TmpInst.addOperand(Op: MCOperand::createImm(Val: ARMCC::AL));
2514 TmpInst.addOperand(Op: MCOperand::createReg(Reg: 0));
2515 // Add 's' bit operand (always reg0 for this)
2516 if (Opc == ARM::MOVr)
2517 TmpInst.addOperand(Op: MCOperand::createReg(Reg: 0));
2518 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
2519 return;
2520 }
2521 case ARM::BR_JTm_i12: {
2522 // ldr pc, target
2523 MCInst TmpInst;
2524 TmpInst.setOpcode(ARM::LDRi12);
2525 TmpInst.addOperand(Op: MCOperand::createReg(Reg: ARM::PC));
2526 TmpInst.addOperand(Op: MCOperand::createReg(Reg: MI->getOperand(i: 0).getReg()));
2527 TmpInst.addOperand(Op: MCOperand::createImm(Val: MI->getOperand(i: 2).getImm()));
2528 // Add predicate operands.
2529 TmpInst.addOperand(Op: MCOperand::createImm(Val: ARMCC::AL));
2530 TmpInst.addOperand(Op: MCOperand::createReg(Reg: 0));
2531 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
2532 return;
2533 }
2534 case ARM::BR_JTm_rs: {
2535 // ldr pc, target
2536 MCInst TmpInst;
2537 TmpInst.setOpcode(ARM::LDRrs);
2538 TmpInst.addOperand(Op: MCOperand::createReg(Reg: ARM::PC));
2539 TmpInst.addOperand(Op: MCOperand::createReg(Reg: MI->getOperand(i: 0).getReg()));
2540 TmpInst.addOperand(Op: MCOperand::createReg(Reg: MI->getOperand(i: 1).getReg()));
2541 TmpInst.addOperand(Op: MCOperand::createImm(Val: MI->getOperand(i: 2).getImm()));
2542 // Add predicate operands.
2543 TmpInst.addOperand(Op: MCOperand::createImm(Val: ARMCC::AL));
2544 TmpInst.addOperand(Op: MCOperand::createReg(Reg: 0));
2545 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
2546 return;
2547 }
2548 case ARM::BR_JTadd: {
2549 // add pc, target, idx
2550 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::ADDrr)
2551 .addReg(Reg: ARM::PC)
2552 .addReg(Reg: MI->getOperand(i: 0).getReg())
2553 .addReg(Reg: MI->getOperand(i: 1).getReg())
2554 // Add predicate operands.
2555 .addImm(Val: ARMCC::AL)
2556 .addReg(Reg: 0)
2557 // Add 's' bit operand (always reg0 for this)
2558 .addReg(Reg: 0));
2559 return;
2560 }
2561 case ARM::SPACE:
2562 OutStreamer->emitZeros(NumBytes: MI->getOperand(i: 1).getImm());
2563 return;
2564 case ARM::TRAP: {
2565 // Non-Darwin binutils don't yet support the "trap" mnemonic.
2566 // FIXME: Remove this special case when they do.
2567 if (!TM.getTargetTriple().isOSBinFormatMachO()) {
2568 uint32_t Val = 0xe7ffdefeUL;
2569 OutStreamer->AddComment(T: "trap");
2570 ATS.emitInst(Inst: Val);
2571 return;
2572 }
2573 break;
2574 }
2575 case ARM::tTRAP: {
2576 // Non-Darwin binutils don't yet support the "trap" mnemonic.
2577 // FIXME: Remove this special case when they do.
2578 if (!TM.getTargetTriple().isOSBinFormatMachO()) {
2579 uint16_t Val = 0xdefe;
2580 OutStreamer->AddComment(T: "trap");
2581 ATS.emitInst(Inst: Val, Suffix: 'n');
2582 return;
2583 }
2584 break;
2585 }
2586 case ARM::t2Int_eh_sjlj_setjmp:
2587 case ARM::t2Int_eh_sjlj_setjmp_nofp:
2588 case ARM::tInt_eh_sjlj_setjmp: {
2589 // Two incoming args: GPR:$src, GPR:$val
2590 // mov $val, pc
2591 // adds $val, #7
2592 // str $val, [$src, #4]
2593 // movs r0, #0
2594 // b LSJLJEH
2595 // movs r0, #1
2596 // LSJLJEH:
2597 Register SrcReg = MI->getOperand(i: 0).getReg();
2598 Register ValReg = MI->getOperand(i: 1).getReg();
2599 MCSymbol *Label = OutContext.createTempSymbol(Name: "SJLJEH");
2600 OutStreamer->AddComment(T: "eh_setjmp begin");
2601 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tMOVr)
2602 .addReg(Reg: ValReg)
2603 .addReg(Reg: ARM::PC)
2604 // Predicate.
2605 .addImm(Val: ARMCC::AL)
2606 .addReg(Reg: 0));
2607
2608 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tADDi3)
2609 .addReg(Reg: ValReg)
2610 // 's' bit operand
2611 .addReg(Reg: ARM::CPSR)
2612 .addReg(Reg: ValReg)
2613 .addImm(Val: 7)
2614 // Predicate.
2615 .addImm(Val: ARMCC::AL)
2616 .addReg(Reg: 0));
2617
2618 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tSTRi)
2619 .addReg(Reg: ValReg)
2620 .addReg(Reg: SrcReg)
2621 // The offset immediate is #4. The operand value is scaled by 4 for the
2622 // tSTR instruction.
2623 .addImm(Val: 1)
2624 // Predicate.
2625 .addImm(Val: ARMCC::AL)
2626 .addReg(Reg: 0));
2627
2628 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tMOVi8)
2629 .addReg(Reg: ARM::R0)
2630 .addReg(Reg: ARM::CPSR)
2631 .addImm(Val: 0)
2632 // Predicate.
2633 .addImm(Val: ARMCC::AL)
2634 .addReg(Reg: 0));
2635
2636 const MCExpr *SymbolExpr = MCSymbolRefExpr::create(Symbol: Label, Ctx&: OutContext);
2637 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tB)
2638 .addExpr(Val: SymbolExpr)
2639 .addImm(Val: ARMCC::AL)
2640 .addReg(Reg: 0));
2641
2642 OutStreamer->AddComment(T: "eh_setjmp end");
2643 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tMOVi8)
2644 .addReg(Reg: ARM::R0)
2645 .addReg(Reg: ARM::CPSR)
2646 .addImm(Val: 1)
2647 // Predicate.
2648 .addImm(Val: ARMCC::AL)
2649 .addReg(Reg: 0));
2650
2651 OutStreamer->emitLabel(Symbol: Label);
2652 return;
2653 }
2654
2655 case ARM::Int_eh_sjlj_setjmp_nofp:
2656 case ARM::Int_eh_sjlj_setjmp: {
2657 // Two incoming args: GPR:$src, GPR:$val
2658 // add $val, pc, #8
2659 // str $val, [$src, #+4]
2660 // mov r0, #0
2661 // add pc, pc, #0
2662 // mov r0, #1
2663 Register SrcReg = MI->getOperand(i: 0).getReg();
2664 Register ValReg = MI->getOperand(i: 1).getReg();
2665
2666 OutStreamer->AddComment(T: "eh_setjmp begin");
2667 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::ADDri)
2668 .addReg(Reg: ValReg)
2669 .addReg(Reg: ARM::PC)
2670 .addImm(Val: 8)
2671 // Predicate.
2672 .addImm(Val: ARMCC::AL)
2673 .addReg(Reg: 0)
2674 // 's' bit operand (always reg0 for this).
2675 .addReg(Reg: 0));
2676
2677 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::STRi12)
2678 .addReg(Reg: ValReg)
2679 .addReg(Reg: SrcReg)
2680 .addImm(Val: 4)
2681 // Predicate.
2682 .addImm(Val: ARMCC::AL)
2683 .addReg(Reg: 0));
2684
2685 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::MOVi)
2686 .addReg(Reg: ARM::R0)
2687 .addImm(Val: 0)
2688 // Predicate.
2689 .addImm(Val: ARMCC::AL)
2690 .addReg(Reg: 0)
2691 // 's' bit operand (always reg0 for this).
2692 .addReg(Reg: 0));
2693
2694 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::ADDri)
2695 .addReg(Reg: ARM::PC)
2696 .addReg(Reg: ARM::PC)
2697 .addImm(Val: 0)
2698 // Predicate.
2699 .addImm(Val: ARMCC::AL)
2700 .addReg(Reg: 0)
2701 // 's' bit operand (always reg0 for this).
2702 .addReg(Reg: 0));
2703
2704 OutStreamer->AddComment(T: "eh_setjmp end");
2705 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::MOVi)
2706 .addReg(Reg: ARM::R0)
2707 .addImm(Val: 1)
2708 // Predicate.
2709 .addImm(Val: ARMCC::AL)
2710 .addReg(Reg: 0)
2711 // 's' bit operand (always reg0 for this).
2712 .addReg(Reg: 0));
2713 return;
2714 }
2715 case ARM::Int_eh_sjlj_longjmp: {
2716 // ldr sp, [$src, #8]
2717 // ldr $scratch, [$src, #4]
2718 // ldr r7, [$src]
2719 // bx $scratch
2720 Register SrcReg = MI->getOperand(i: 0).getReg();
2721 Register ScratchReg = MI->getOperand(i: 1).getReg();
2722 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::LDRi12)
2723 .addReg(Reg: ARM::SP)
2724 .addReg(Reg: SrcReg)
2725 .addImm(Val: 8)
2726 // Predicate.
2727 .addImm(Val: ARMCC::AL)
2728 .addReg(Reg: 0));
2729
2730 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::LDRi12)
2731 .addReg(Reg: ScratchReg)
2732 .addReg(Reg: SrcReg)
2733 .addImm(Val: 4)
2734 // Predicate.
2735 .addImm(Val: ARMCC::AL)
2736 .addReg(Reg: 0));
2737
2738 if (STI.isTargetDarwin() || STI.isTargetWindows()) {
2739 // These platforms always use the same frame register
2740 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::LDRi12)
2741 .addReg(Reg: STI.getFramePointerReg())
2742 .addReg(Reg: SrcReg)
2743 .addImm(Val: 0)
2744 // Predicate.
2745 .addImm(Val: ARMCC::AL)
2746 .addReg(Reg: 0));
2747 } else {
2748 // If the calling code might use either R7 or R11 as
2749 // frame pointer register, restore it into both.
2750 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::LDRi12)
2751 .addReg(Reg: ARM::R7)
2752 .addReg(Reg: SrcReg)
2753 .addImm(Val: 0)
2754 // Predicate.
2755 .addImm(Val: ARMCC::AL)
2756 .addReg(Reg: 0));
2757 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::LDRi12)
2758 .addReg(Reg: ARM::R11)
2759 .addReg(Reg: SrcReg)
2760 .addImm(Val: 0)
2761 // Predicate.
2762 .addImm(Val: ARMCC::AL)
2763 .addReg(Reg: 0));
2764 }
2765
2766 assert(STI.hasV4TOps());
2767 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::BX)
2768 .addReg(Reg: ScratchReg)
2769 // Predicate.
2770 .addImm(Val: ARMCC::AL)
2771 .addReg(Reg: 0));
2772 return;
2773 }
2774 case ARM::tInt_eh_sjlj_longjmp: {
2775 // ldr $scratch, [$src, #8]
2776 // mov sp, $scratch
2777 // ldr $scratch, [$src, #4]
2778 // ldr r7, [$src]
2779 // bx $scratch
2780 Register SrcReg = MI->getOperand(i: 0).getReg();
2781 Register ScratchReg = MI->getOperand(i: 1).getReg();
2782
2783 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tLDRi)
2784 .addReg(Reg: ScratchReg)
2785 .addReg(Reg: SrcReg)
2786 // The offset immediate is #8. The operand value is scaled by 4 for the
2787 // tLDR instruction.
2788 .addImm(Val: 2)
2789 // Predicate.
2790 .addImm(Val: ARMCC::AL)
2791 .addReg(Reg: 0));
2792
2793 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tMOVr)
2794 .addReg(Reg: ARM::SP)
2795 .addReg(Reg: ScratchReg)
2796 // Predicate.
2797 .addImm(Val: ARMCC::AL)
2798 .addReg(Reg: 0));
2799
2800 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tLDRi)
2801 .addReg(Reg: ScratchReg)
2802 .addReg(Reg: SrcReg)
2803 .addImm(Val: 1)
2804 // Predicate.
2805 .addImm(Val: ARMCC::AL)
2806 .addReg(Reg: 0));
2807
2808 if (STI.isTargetDarwin() || STI.isTargetWindows()) {
2809 // These platforms always use the same frame register
2810 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tLDRi)
2811 .addReg(Reg: STI.getFramePointerReg())
2812 .addReg(Reg: SrcReg)
2813 .addImm(Val: 0)
2814 // Predicate.
2815 .addImm(Val: ARMCC::AL)
2816 .addReg(Reg: 0));
2817 } else {
2818 // If the calling code might use either R7 or R11 as
2819 // frame pointer register, restore it into both.
2820 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tLDRi)
2821 .addReg(Reg: ARM::R7)
2822 .addReg(Reg: SrcReg)
2823 .addImm(Val: 0)
2824 // Predicate.
2825 .addImm(Val: ARMCC::AL)
2826 .addReg(Reg: 0));
2827 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tLDRi)
2828 .addReg(Reg: ARM::R11)
2829 .addReg(Reg: SrcReg)
2830 .addImm(Val: 0)
2831 // Predicate.
2832 .addImm(Val: ARMCC::AL)
2833 .addReg(Reg: 0));
2834 }
2835
2836 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::tBX)
2837 .addReg(Reg: ScratchReg)
2838 // Predicate.
2839 .addImm(Val: ARMCC::AL)
2840 .addReg(Reg: 0));
2841 return;
2842 }
2843 case ARM::tInt_WIN_eh_sjlj_longjmp: {
2844 // ldr.w r11, [$src, #0]
2845 // ldr.w sp, [$src, #8]
2846 // ldr.w pc, [$src, #4]
2847
2848 Register SrcReg = MI->getOperand(i: 0).getReg();
2849
2850 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::t2LDRi12)
2851 .addReg(Reg: ARM::R11)
2852 .addReg(Reg: SrcReg)
2853 .addImm(Val: 0)
2854 // Predicate
2855 .addImm(Val: ARMCC::AL)
2856 .addReg(Reg: 0));
2857 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::t2LDRi12)
2858 .addReg(Reg: ARM::SP)
2859 .addReg(Reg: SrcReg)
2860 .addImm(Val: 8)
2861 // Predicate
2862 .addImm(Val: ARMCC::AL)
2863 .addReg(Reg: 0));
2864 EmitToStreamer(S&: *OutStreamer, Inst: MCInstBuilder(ARM::t2LDRi12)
2865 .addReg(Reg: ARM::PC)
2866 .addReg(Reg: SrcReg)
2867 .addImm(Val: 4)
2868 // Predicate
2869 .addImm(Val: ARMCC::AL)
2870 .addReg(Reg: 0));
2871 return;
2872 }
2873 case ARM::PATCHABLE_FUNCTION_ENTER:
2874 LowerPATCHABLE_FUNCTION_ENTER(MI: *MI);
2875 return;
2876 case ARM::PATCHABLE_FUNCTION_EXIT:
2877 LowerPATCHABLE_FUNCTION_EXIT(MI: *MI);
2878 return;
2879 case ARM::PATCHABLE_TAIL_CALL:
2880 LowerPATCHABLE_TAIL_CALL(MI: *MI);
2881 return;
2882 case ARM::SpeculationBarrierISBDSBEndBB: {
2883 // Print DSB SYS + ISB
2884 MCInst TmpInstDSB;
2885 TmpInstDSB.setOpcode(ARM::DSB);
2886 TmpInstDSB.addOperand(Op: MCOperand::createImm(Val: 0xf));
2887 EmitToStreamer(S&: *OutStreamer, Inst: TmpInstDSB);
2888 MCInst TmpInstISB;
2889 TmpInstISB.setOpcode(ARM::ISB);
2890 TmpInstISB.addOperand(Op: MCOperand::createImm(Val: 0xf));
2891 EmitToStreamer(S&: *OutStreamer, Inst: TmpInstISB);
2892 return;
2893 }
2894 case ARM::t2SpeculationBarrierISBDSBEndBB: {
2895 // Print DSB SYS + ISB
2896 MCInst TmpInstDSB;
2897 TmpInstDSB.setOpcode(ARM::t2DSB);
2898 TmpInstDSB.addOperand(Op: MCOperand::createImm(Val: 0xf));
2899 TmpInstDSB.addOperand(Op: MCOperand::createImm(Val: ARMCC::AL));
2900 TmpInstDSB.addOperand(Op: MCOperand::createReg(Reg: 0));
2901 EmitToStreamer(S&: *OutStreamer, Inst: TmpInstDSB);
2902 MCInst TmpInstISB;
2903 TmpInstISB.setOpcode(ARM::t2ISB);
2904 TmpInstISB.addOperand(Op: MCOperand::createImm(Val: 0xf));
2905 TmpInstISB.addOperand(Op: MCOperand::createImm(Val: ARMCC::AL));
2906 TmpInstISB.addOperand(Op: MCOperand::createReg(Reg: 0));
2907 EmitToStreamer(S&: *OutStreamer, Inst: TmpInstISB);
2908 return;
2909 }
2910 case ARM::SpeculationBarrierSBEndBB: {
2911 // Print SB
2912 MCInst TmpInstSB;
2913 TmpInstSB.setOpcode(ARM::SB);
2914 EmitToStreamer(S&: *OutStreamer, Inst: TmpInstSB);
2915 return;
2916 }
2917 case ARM::t2SpeculationBarrierSBEndBB: {
2918 // Print SB
2919 MCInst TmpInstSB;
2920 TmpInstSB.setOpcode(ARM::t2SB);
2921 EmitToStreamer(S&: *OutStreamer, Inst: TmpInstSB);
2922 return;
2923 }
2924
2925 case ARM::SEH_StackAlloc:
2926 ATS.emitARMWinCFIAllocStack(Size: MI->getOperand(i: 0).getImm(),
2927 Wide: MI->getOperand(i: 1).getImm());
2928 return;
2929
2930 case ARM::SEH_SaveRegs:
2931 case ARM::SEH_SaveRegs_Ret:
2932 ATS.emitARMWinCFISaveRegMask(Mask: MI->getOperand(i: 0).getImm(),
2933 Wide: MI->getOperand(i: 1).getImm());
2934 return;
2935
2936 case ARM::SEH_SaveSP:
2937 ATS.emitARMWinCFISaveSP(Reg: MI->getOperand(i: 0).getImm());
2938 return;
2939
2940 case ARM::SEH_SaveFRegs:
2941 ATS.emitARMWinCFISaveFRegs(First: MI->getOperand(i: 0).getImm(),
2942 Last: MI->getOperand(i: 1).getImm());
2943 return;
2944
2945 case ARM::SEH_SaveLR:
2946 ATS.emitARMWinCFISaveLR(Offset: MI->getOperand(i: 0).getImm());
2947 return;
2948
2949 case ARM::SEH_Nop:
2950 case ARM::SEH_Nop_Ret:
2951 ATS.emitARMWinCFINop(Wide: MI->getOperand(i: 0).getImm());
2952 return;
2953
2954 case ARM::SEH_PrologEnd:
2955 ATS.emitARMWinCFIPrologEnd(/*Fragment=*/false);
2956 return;
2957
2958 case ARM::SEH_EpilogStart:
2959 ATS.emitARMWinCFIEpilogStart(Condition: ARMCC::AL);
2960 return;
2961
2962 case ARM::SEH_EpilogEnd:
2963 ATS.emitARMWinCFIEpilogEnd();
2964 return;
2965 }
2966
2967 MCInst TmpInst;
2968 LowerARMMachineInstrToMCInst(MI, OutMI&: TmpInst, AP&: *this);
2969
2970 EmitToStreamer(S&: *OutStreamer, Inst: TmpInst);
2971}
2972
2973char ARMAsmPrinter::ID = 0;
2974
2975INITIALIZE_PASS(ARMAsmPrinter, "arm-asm-printer", "ARM Assembly Printer", false,
2976 false)
2977
2978//===----------------------------------------------------------------------===//
2979// Target Registry Stuff
2980//===----------------------------------------------------------------------===//
2981
2982// Force static initialization.
2983extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
2984LLVMInitializeARMAsmPrinter() {
2985 RegisterAsmPrinter<ARMAsmPrinter> X(getTheARMLETarget());
2986 RegisterAsmPrinter<ARMAsmPrinter> Y(getTheARMBETarget());
2987 RegisterAsmPrinter<ARMAsmPrinter> A(getTheThumbLETarget());
2988 RegisterAsmPrinter<ARMAsmPrinter> B(getTheThumbBETarget());
2989}
2990