LLVM 24.0.0git
ARMAsmPrinter.cpp
Go to the documentation of this file.
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"
18#include "ARMTargetMachine.h"
19#include "ARMTargetObjectFile.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"
36#include "llvm/MC/MCInst.h"
39#include "llvm/MC/MCStreamer.h"
40#include "llvm/MC/MCSymbol.h"
44#include "llvm/Support/Debug.h"
48using namespace llvm;
49
50#define DEBUG_TYPE "asm-printer"
51
53 std::unique_ptr<MCStreamer> Streamer)
54 : AsmPrinter(TM, std::move(Streamer), ID), AFI(nullptr), MCP(nullptr),
55 InConstantPool(false), OptimizationGoals(-1) {}
56
58 return static_cast<const ARMBaseTargetMachine &>(TM);
59}
60
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(MCDR_DataRegionEnd);
68}
69
71 auto &TS =
72 static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());
73 if (AFI->isThumbFunction()) {
74 TS.emitCode16();
75 TS.emitThumbFunc(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("__acle_se_" + CurrentFnSym->getName());
84 emitLinkage(&MF->getFunction(), S);
85 OutStreamer->emitSymbolAttribute(S, MCSA_ELF_TypeFunction);
86 OutStreamer->emitLabel(S);
87 }
89}
90
92 uint64_t Size = getDataLayout().getTypeAllocSize(CV->getType());
93 assert(Size && "C++ constructor pointer had zero size!");
94
96 assert(GV && "C++ constructor pointer was not a GlobalValue!");
97
99 GetARMGVSymbol(GV, ARMII::MO_NO_FLAG),
100 (TM.getTargetTriple().isOSBinFormatELF() ? ARM::S_TARGET1 : ARM::S_None),
101 OutContext);
102
103 OutStreamer->emitValue(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) {
109 if (!BaseFn || !BaseFn->hasFnAttribute("cmse_nonsecure_entry"))
110 return;
111
112 MCSymbol *AliasSym = getSymbol(&GA);
113 MCSymbol *FnSym = getSymbol(BaseFn);
114
115 MCSymbol *SEAliasSym =
116 OutContext.getOrCreateSymbol(Twine("__acle_se_") + AliasSym->getName());
117 MCSymbol *SEBaseSym =
118 OutContext.getOrCreateSymbol(Twine("__acle_se_") + FnSym->getName());
119
120 // Mirror alias linkage/visibility onto the veneer-alias symbol.
121 emitLinkage(&GA, SEAliasSym);
122 OutStreamer->emitSymbolAttribute(SEAliasSym, MCSA_ELF_TypeFunction);
123 emitVisibility(SEAliasSym, GA.getVisibility());
124
125 // emit "__acle_se_<alias> = __acle_se_<aliasee>"
126 const MCExpr *SEExpr = MCSymbolRefExpr::create(SEBaseSym, OutContext);
127 OutStreamer->emitAssignment(SEAliasSym, SEExpr);
128}
129
132 emitCMSEVeneerAlias(GA);
133}
134
136 if (PromotedGlobals.count(GV))
137 // The global was promoted into a constant pool. It should not be emitted.
138 return;
140}
141
142/// runOnMachineFunction - This uses the emitInstruction()
143/// method to print assembly for each instruction.
144///
146 AFI = MF.getInfo<ARMFunctionInfo>();
147 MCP = MF.getConstantPool();
148
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(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();
190
191 OutStreamer->beginCOFFSymbolDef(CurrentFnSym);
192 OutStreamer->emitCOFFSymbolStorageClass(Scl);
193 OutStreamer->emitCOFFSymbolType(Type);
194 OutStreamer->endCOFFSymbolDef();
195 }
196
197 // Emit the rest of the function body.
199
200 // Emit the XRay table for this function.
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();
211 for (std::pair<unsigned, MCSymbol *> &TIP : ThumbIndirectPads) {
212 OutStreamer->emitLabel(TIP.second);
214 .addReg(TIP.first)
215 // Add predicate operands.
217 .addReg(0));
218 }
219 ThumbIndirectPads.clear();
220 }
221
222 // We didn't modify anything.
223 return false;
224}
225
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(MO.getGlobal(), TF)->print(O, MAI);
244 printOffset(MO.getOffset(), O);
245}
246
248 raw_ostream &O) {
249 const MachineOperand &MO = MI->getOperand(OpNum);
250
251 switch (MO.getType()) {
252 default: llvm_unreachable("<unknown operand type>");
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, ARM::gsub_0);
261 }
263 break;
264 }
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 }
284 MO.getMBB()->getSymbol()->print(O, MAI);
285 return;
287 PrintSymbolOperand(MO, O);
288 break;
289 }
291 assert(!MF->getSubtarget<ARMSubtarget>().genExecuteOnly() &&
292 "execute-only should not generate constant pools");
293 GetCPISymbol(MO.getIndex())->print(O, MAI);
294 break;
295 }
296}
297
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(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
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, OpNum, ExtraCode, 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(OpNum).isReg()) {
334 MCRegister Reg = MI->getOperand(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(SR))
340 continue;
341 bool Lane0 = TRI->getSubReg(SR, ARM::ssub_0) == Reg;
342 O << ARMInstPrinter::getRegisterName(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(OpNum).isImm())
349 return true;
350 O << ~(MI->getOperand(OpNum).getImm());
351 return false;
352 case 'L': // The low 16 bits of an immediate constant.
353 if (!MI->getOperand(OpNum).isImm())
354 return true;
355 O << (MI->getOperand(OpNum).getImm() & 0xffff);
356 return false;
357 case 'M': { // A register range suitable for LDM/STM.
358 if (!MI->getOperand(OpNum).isReg())
359 return true;
360 const MachineOperand &MO = MI->getOperand(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(RegBegin)) {
367 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
368 Register Reg0 = TRI->getSubReg(RegBegin, ARM::gsub_0);
369 O << ARMInstPrinter::getRegisterName(Reg0) << ", ";
370 RegBegin = TRI->getSubReg(RegBegin, ARM::gsub_1);
371 }
372 O << ARMInstPrinter::getRegisterName(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(RegOps).isReg()) {
380 O << ", "
381 << ARMInstPrinter::getRegisterName(MI->getOperand(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(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(TiedIdx)) {
403 for (OpNum = InlineAsm::MIOp_FirstOperand; TiedIdx; --TiedIdx) {
404 unsigned OpFlags = MI->getOperand(OpNum).getImm();
405 const InlineAsm::Flag F(OpFlags);
406 OpNum += F.getNumOperandRegisters() + 1;
407 }
408 F = InlineAsm::Flag(MI->getOperand(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(TRI->getRegClass(RC))) {
432 if (NumVals != 1)
433 return true;
434 const MachineOperand &MO = MI->getOperand(OpNum);
435 if (!MO.isReg())
436 return true;
437 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
438 Register Reg =
439 TRI->getSubReg(MO.getReg(), FirstHalf ? ARM::gsub_0 : ARM::gsub_1);
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(RegOp);
449 if (!MO.isReg())
450 return true;
451 Register Reg = MO.getReg();
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(OpNum).isReg())
459 return true;
460 Register Reg = MI->getOperand(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, ExtraCode[0] == 'e' ? ARM::dsub_0 : ARM::dsub_1);
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(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, ARM::gsub_1);
484 return false;
485 }
486 }
487 }
488
489 printOperand(MI, OpNum, O);
490 return false;
491}
492
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(OpNum).isReg())
505 return true;
506 O << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg());
507 return false;
508 }
509 }
510
511 const MachineOperand &MO = MI->getOperand(OpNum);
512 assert(MO.isReg() && "unexpected inline asm memory operand");
513 O << "[" << ARMInstPrinter::getRegisterName(MO.getReg()) << "]";
514 return false;
515}
516
517static bool isThumb(const MCSubtargetInfo& STI) {
518 return STI.hasFeature(ARM::ModeThumb);
519}
520
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(StartInfo);
527 if (!EndInfo || WasThumb != isThumb(*EndInfo)) {
528 auto &TS =
529 static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());
530 if (WasThumb)
531 TS.emitCode16();
532 else
533 TS.emitCode32();
534 }
535}
536
538 const Triple &TT = TM.getTargetTriple();
539 auto &TS =
540 static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());
541 // Use unified assembler syntax.
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
557 // L_foo$stub:
558 OutStreamer.emitLabel(StubLabel);
559 // .indirect_symbol _foo
561
562 if (MCSym.getInt())
563 // External to current translation unit.
564 OutStreamer.emitIntValue(0, 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 MCSymbolRefExpr::create(MCSym.getPointer(), OutStreamer.getContext()),
574 4 /*size*/);
575}
576
577
579 const Triple &TT = TM.getTargetTriple();
580 if (TT.isOSBinFormatMachO()) {
581 // All darwin targets use mach-o.
582 const TargetLoweringObjectFileMachO &TLOFMacho =
584 MachineModuleInfoMachO &MMIMacho =
585 MMI->getObjFileInfo<MachineModuleInfoMachO>();
586
587 // Output non-lazy-pointers for external and common global variables.
589
590 if (!Stubs.empty()) {
591 // Switch with ".non_lazy_symbol_pointer" directive.
592 OutStreamer->switchSection(TLOFMacho.getNonLazySymbolPointerSection());
594
595 for (auto &Stub : Stubs)
596 emitNonLazySymbolPointer(*OutStreamer, Stub.first, 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(TLOFMacho.getThreadLocalPointerSection());
607
608 for (auto &Stub : Stubs)
609 emitNonLazySymbolPointer(*OutStreamer, Stub.first, 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()))
630 OptimizationGoals = -1;
631
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.
646 return !any_of(M, [&](const Function &F) {
647 if (F.isDeclaration())
648 return false;
649 return F.getFnAttribute(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.
656 return !any_of(M, [&](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(M, [](const Function &F) {
668 return !F.isDeclaration() && F.isStrictFP();
669 });
670}
671
672// Returns true if all functions have different denormal modes.
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(F, E, [&](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
690
691 ATS.switchVendor("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(*MMI->getModule());
711 ARM::ARMABI ABI = ATM.getEffectiveABI(*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()) {
722 } else if (STI.isRWPI()) {
723 // RWPI specific attributes.
726 }
727
728 // RO data addressing.
729 if (isPositionIndependent() || STI.isROPI()) {
732 }
733
734 // GOT use.
735 if (isPositionIndependent()) {
738 } else {
741 }
742
743 // Set FP Denormals.
745 MMI->getModule()->getModuleFlag("arm-eabi-fp-denormal"))) {
746 if (unsigned TagVal = DM->getZExtValue())
748 } else if (checkDenormalAttributeConsistency(*MMI->getModule(),
752 else if (checkDenormalAttributeConsistency(*MMI->getModule(),
756 else if (checkDenormalAttributeInconsistency(*MMI->getModule()) ||
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())
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.
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
789 MMI->getModule()->getModuleFlag("arm-eabi-fp-exceptions"))) {
790 if (unsigned TagVal = Ex->getZExtValue())
792 } else if (checkFunctionsAttributeConsistency(*MMI->getModule(),
793 "no-trapping-math", "true"))
796 else {
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(*MMI->getModule()))
803 }
804
805 // Generate ABI tags from module flags.
806 if (auto *NumModel = mdconst::extract_or_null<ConstantInt>(
807 MMI->getModule()->getModuleFlag("arm-eabi-fp-number-model"))) {
808 if (unsigned TagVal = NumModel->getZExtValue())
810 } else
813
814 // FIXME: add more flags to ARMBuildAttributes.h
815 // 8-bytes alignment stuff.
818
819 // Hard float. Use both S and D registers and conform to AAPCS-VFP.
820 if (STI.isAAPCS_ABI() && STI.isTargetHardFloat())
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.
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 SourceModule->getModuleFlag("wchar_size")))
836 WCharWidth = WCharWidthValue->getZExtValue();
837 assert((WCharWidth == 2 || WCharWidth == 4) &&
838 "wchar_t width must be 2 or 4 bytes");
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 SourceModule->getModuleFlag("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;
851 }
852
854 SourceModule->getModuleFlag("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()) {
862 }
864 }
865
867 SourceModule->getModuleFlag("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()) {
875 }
877 }
878 }
879
880 // We currently do not support using R9 as the TLS pointer.
881 if (STI.isRWPI())
884 else if (STI.isR9Reserved())
887 else
890}
891
892//===----------------------------------------------------------------------===//
893
894static MCSymbol *getBFLabel(StringRef Prefix, unsigned FunctionNumber,
895 unsigned LabelId, MCContext &Ctx) {
896
897 MCSymbol *Label = Ctx.getOrCreateSymbol(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(Twine(Prefix)
906 + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId));
907 return Label;
908}
909
911 switch (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, "$non_lazy_ptr");
942 MachineModuleInfoMachO &MMIMachO =
943 MMI->getObjFileInfo<MachineModuleInfoMachO>();
945 GV->isThreadLocal() ? MMIMachO.getThreadLocalGVStubEntry(MCSym)
946 : MMIMachO.getGVStubEntry(MCSym);
947
948 if (!StubSym.getPointer())
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>();
973 MMICOFF.getGVStubEntry(MCSym);
974
975 if (!StubSym.getPointer())
977 }
978
979 return MCSym;
980 } else if (TT.isOSBinFormatELF()) {
981 return getSymbolPreferLocal(*GV);
982 }
983 llvm_unreachable("unexpected target");
984}
985
988 const DataLayout &DL = getDataLayout();
989 int Size = DL.getTypeAllocSize(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>(ACPV);
1004 for (const auto *GV : ACPC->promotedGlobals()) {
1005 if (!EmittedPromotedGlobalLabels.count(GV)) {
1006 MCSymbol *GVSym = getSymbol(GV);
1007 OutStreamer->emitLabel(GVSym);
1008 EmittedPromotedGlobalLabels.insert(GV);
1009 }
1010 }
1011 return emitGlobalConstant(DL, ACPC->getPromotedGlobalInit());
1012 }
1013
1014 MCSymbol *MCSym;
1015 if (ACPV->isLSDA()) {
1016 MCSym = getMBBExceptionSym(MF->front());
1017 } else if (ACPV->isBlockAddress()) {
1018 const BlockAddress *BA =
1019 cast<ARMConstantPoolConstant>(ACPV)->getBlockAddress();
1020 MCSym = GetBlockAddressSymbol(BA);
1021 } else if (ACPV->isGlobalValue()) {
1022 const GlobalValue *GV = cast<ARMConstantPoolConstant>(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, 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(CPILabel);
1045 // Emit local-only expression: CPILabel - (LPC+PCAdj)
1046 const MCExpr *LocalExpr = MCSymbolRefExpr::create(CPILabel, OutContext);
1047 MCSymbol *PCLabel =
1048 getPICLabel(DL.getInternalSymbolPrefix(), getFunctionNumber(),
1049 ACPV->getLabelId(), OutContext);
1050 const MCExpr *PCRelExpr = MCSymbolRefExpr::create(PCLabel, OutContext);
1051 PCRelExpr = MCBinaryExpr::createAdd(
1052 PCRelExpr,
1054 OutContext);
1055 LocalExpr = MCBinaryExpr::createSub(LocalExpr, PCRelExpr, OutContext);
1056 OutStreamer->emitValue(LocalExpr, Size);
1057 // Emit .reloc to force linker resolution of the weak symbol.
1058 const MCExpr *CPIExpr = MCSymbolRefExpr::create(CPILabel, OutContext);
1059 const MCExpr *SymExpr = MCSymbolRefExpr::create(MCSym, OutContext);
1060 OutStreamer->emitRelocDirective(*CPIExpr, "R_ARM_REL32", SymExpr,
1061 SMLoc());
1062 return;
1063 }
1064 } else if (ACPV->isMachineBasicBlock()) {
1065 const MachineBasicBlock *MBB = cast<ARMConstantPoolMBB>(ACPV)->getMBB();
1066 MCSym = MBB->getSymbol();
1067 } else {
1068 assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
1069 auto Sym = cast<ARMConstantPoolSymbol>(ACPV)->getSymbol();
1070 MCSym = GetExternalSymbolSymbol(Sym);
1071 }
1072
1073 // Create an MCSymbol for the reference.
1074 const MCExpr *Expr = MCSymbolRefExpr::create(
1076
1077 if (ACPV->getPCAdjustment()) {
1078 MCSymbol *PCLabel =
1079 getPICLabel(DL.getInternalSymbolPrefix(), getFunctionNumber(),
1080 ACPV->getLabelId(), OutContext);
1081 const MCExpr *PCRelExpr = MCSymbolRefExpr::create(PCLabel, OutContext);
1082 PCRelExpr =
1083 MCBinaryExpr::createAdd(PCRelExpr,
1085 OutContext),
1086 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(DotSym);
1092 const MCExpr *DotExpr = MCSymbolRefExpr::create(DotSym, OutContext);
1093 PCRelExpr = MCBinaryExpr::createSub(PCRelExpr, DotExpr, OutContext);
1094 }
1095 Expr = MCBinaryExpr::createSub(Expr, PCRelExpr, OutContext);
1096 }
1097 OutStreamer->emitValue(Expr, Size);
1098}
1099
1101 const MachineOperand &MO1 = MI->getOperand(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(Align(4));
1107
1108 // Emit a label for the jump table.
1109 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);
1110 OutStreamer->emitLabel(JTISymbol);
1111
1112 // Mark the jump table as data-in-code.
1113 OutStreamer->emitDataRegion(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(MBB->getSymbol(), OutContext);
1130
1131 const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();
1132 if (isPositionIndependent() || STI.isROPI())
1133 Expr = MCBinaryExpr::createSub(Expr, MCSymbolRefExpr::create(JTISymbol,
1134 OutContext),
1135 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())
1140 OutContext);
1141 OutStreamer->emitValue(Expr, 4);
1142 }
1143 // Mark the end of jump table data-in-code region.
1144 OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
1145}
1146
1148 const MachineOperand &MO1 = MI->getOperand(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(Align(4));
1154
1155 // Emit a label for the jump table.
1156 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);
1157 OutStreamer->emitLabel(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(MBB->getSymbol(),
1166 OutContext);
1167 // If this isn't a TBB or TBH, the entries are direct branch instructions.
1169 .addExpr(MBBSymbolExpr)
1170 .addImm(ARMCC::AL)
1171 .addReg(0));
1172 }
1173}
1174
1176 unsigned OffsetWidth) {
1177 assert((OffsetWidth == 1 || OffsetWidth == 2) && "invalid tbb/tbh width");
1178 const MachineOperand &MO1 = MI->getOperand(1);
1179 unsigned JTI = MO1.getIndex();
1180
1181 const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();
1182 if (STI.isThumb1Only())
1183 emitAlignment(Align(4));
1184
1185 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);
1186 OutStreamer->emitLabel(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(OffsetWidth == 1 ? MCDR_DataRegionJT8
1196
1197 for (auto *MBB : JTBBs) {
1198 const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::create(MBB->getSymbol(),
1199 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(MI->getOperand(0).getImm());
1212 const MCExpr *Expr = MCBinaryExpr::createAdd(
1215 Expr = MCBinaryExpr::createSub(MBBSymbolExpr, Expr, OutContext);
1217 OutContext);
1218 OutStreamer->emitValue(Expr, 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(MCDR_DataRegionEnd);
1224
1225 // Make sure the next instruction is 2-byte aligned.
1226 emitAlignment(Align(2));
1227}
1228
1229std::tuple<const MCSymbol *, uint64_t, const MCSymbol *,
1232 const MachineInstr *BranchInstr,
1233 const MCSymbol *BranchLabel) const {
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.
1243 BaseLabel = GetARMJTIPICJumpTableLabel(JTI);
1244 break;
1245 case ARM::tTBH_JT:
1246 case ARM::t2TBH_JT:
1247 // half-word shifted left, relative to *after* the branch instruction.
1249 BranchLabel = GetCPISymbol(BranchInstr->getOperand(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.
1257 BranchLabel = GetCPISymbol(BranchInstr->getOperand(3).getImm());
1258 BaseLabel = BranchLabel;
1259 BaseOffset = 4;
1260 break;
1261 case ARM::t2BR_JT:
1262 // Direct jump.
1263 BaseLabel = nullptr;
1265 break;
1266 default:
1267 llvm_unreachable("Unknown jump table instruction");
1268 }
1269
1270 return std::make_tuple(BaseLabel, BaseOffset, BranchLabel, EntrySize);
1271}
1272
1273void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) {
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 =
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(0).getReg();
1317 break;
1318 case ARM::VMRS:
1319 SrcReg = ARM::FPSCR;
1320 DstReg = MI->getOperand(0).getReg();
1321 break;
1322 case ARM::VMRS_FPEXC:
1323 SrcReg = ARM::FPEXC;
1324 DstReg = MI->getOperand(0).getReg();
1325 break;
1326 default:
1327 SrcReg = MI->getOperand(1).getReg();
1328 DstReg = MI->getOperand(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
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(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(MO.getReg(), 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(Reg))
1386 Reg = RemappedReg;
1387 RegList.push_back(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(SrcReg))
1396 SrcReg = RemappedReg;
1397
1398 RegList.push_back(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(1).getReg();
1404 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(SrcReg))
1405 SrcReg = RemappedReg;
1406 RegList.push_back(SrcReg);
1407 SrcReg = MI->getOperand(2).getReg();
1408 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(SrcReg))
1409 SrcReg = RemappedReg;
1410 RegList.push_back(SrcReg);
1411 PadBefore = -MI->getOperand(4).getImm() - 8;
1412 break;
1413 }
1414 if (MAI.getExceptionHandlingType() == ExceptionHandling::ARM) {
1415 if (PadBefore)
1416 ATS.emitPad(PadBefore);
1417 ATS.emitRegSave(RegList, Opc == ARM::VSTMDDB_UPD);
1418 // Account for the SP adjustment, folded into the push.
1419 if (PadAfter)
1420 ATS.emitPad(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(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(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(2).getImm();
1451 break;
1452 case ARM::tSUBspi:
1453 Offset = MI->getOperand(2).getImm()*4;
1454 break;
1455 case ARM::tADDspi:
1456 case ARM::tADDrSPi:
1457 Offset = -MI->getOperand(2).getImm()*4;
1458 break;
1459 case ARM::tADDhirr:
1460 Offset =
1461 -AFI->EHPrologueOffsetInRegs.lookup(MI->getOperand(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(FramePtr, ARM::SP, -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(DstReg, -Offset);
1478 }
1479 }
1480 } else if (DstReg == ARM::SP) {
1481 MI->print(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(1).getIndex();
1504 const MachineConstantPool *MCP = MF.getConstantPool();
1505 if (CPI >= MCP->getConstants().size())
1506 CPI = AFI->getOriginalCPIdx(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>(CPE.Val.ConstVal)->getSExtValue();
1513 AFI->EHPrologueOffsetInRegs[DstReg] = Offset;
1514 break;
1515 }
1516 case ARM::t2MOVi16:
1517 Offset = MI->getOperand(1).getImm();
1518 AFI->EHPrologueOffsetInRegs[DstReg] = Offset;
1519 break;
1520 case ARM::t2MOVTi16:
1521 Offset = MI->getOperand(2).getImm();
1522 AFI->EHPrologueOffsetInRegs[DstReg] |= (Offset << 16);
1523 break;
1524 case ARM::tMOVi8:
1525 Offset = MI->getOperand(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(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(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.
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(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, ARM::R3);
1587
1588 // If we need to spill r3, push it first.
1589 if (NeedSpillR3) {
1590 // push {r3}
1591 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::STMDB_UPD)
1592 .addReg(ARM::SP)
1593 .addReg(ARM::SP)
1594 .addImm(ARMCC::AL)
1595 .addReg(0)
1596 .addReg(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(*OutStreamer, MCInstBuilder(ARM::BICri)
1605 .addReg(ScratchReg)
1606 .addReg(AddrReg)
1607 .addImm(1)
1608 .addImm(ARMCC::AL)
1609 .addReg(0)
1610 .addReg(0));
1611
1612 // ldr scratch, [scratch, #-(PrefixNops * 4 + 4)]
1613 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12)
1614 .addReg(ScratchReg)
1615 .addReg(ScratchReg)
1616 .addImm(-(PrefixNops * 4 + 4))
1617 .addImm(ARMCC::AL)
1618 .addReg(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(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)
1633 MCInstBuilder(ARM::EORri)
1634 .addReg(ScratchReg)
1635 .addReg(ScratchReg)
1636 .addImm(SOImmVal)
1637 .addImm(ARMCC::AL)
1638 .addReg(0)
1639 .addReg(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(*OutStreamer, MCInstBuilder(ARM::LDMIA_UPD)
1647 .addReg(ARM::SP)
1648 .addReg(ARM::SP)
1649 .addImm(ARMCC::AL)
1650 .addReg(0)
1651 .addReg(ARM::R3));
1652 }
1653
1654 // beq .Lpass (branch if types match, i.e., scratch is zero)
1655 MCSymbol *Pass = OutContext.createTempSymbol();
1657 MCInstBuilder(ARM::Bcc)
1659 .addImm(ARMCC::EQ)
1660 .addReg(ARM::CPSR));
1661
1662 // udf #ESR (trap with encoded diagnostic)
1663 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::UDF).addImm(ESR));
1664
1665 OutStreamer->emitLabel(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(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, ARM::R3);
1689
1690 // If we need to spill r3, push it first.
1691 if (NeedSpillR3) {
1692 // push {r3}
1694 *OutStreamer,
1695 MCInstBuilder(ARM::tPUSH).addImm(ARMCC::AL).addReg(0).addReg(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(*OutStreamer, MCInstBuilder(ARM::t2BICri)
1704 .addReg(ScratchReg)
1705 .addReg(AddrReg)
1706 .addImm(1)
1707 .addImm(ARMCC::AL)
1708 .addReg(0)
1709 .addReg(0));
1710
1711 // ldr scratch, [scratch, #-(PrefixNops * 4 + 4)]
1712 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi8)
1713 .addReg(ScratchReg)
1714 .addReg(ScratchReg)
1715 .addImm(-(PrefixNops * 4 + 4))
1716 .addImm(ARMCC::AL)
1717 .addReg(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)
1731 MCInstBuilder(ARM::t2EORri)
1732 .addReg(ScratchReg)
1733 .addReg(ScratchReg)
1734 .addImm(imm)
1735 .addImm(ARMCC::AL)
1736 .addReg(0)
1737 .addReg(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}
1745 *OutStreamer,
1746 MCInstBuilder(ARM::tPOP).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));
1747 }
1748
1749 // beq .Lpass (branch if types match, i.e., scratch is zero)
1750 MCSymbol *Pass = OutContext.createTempSymbol();
1752 MCInstBuilder(ARM::t2Bcc)
1754 .addImm(ARMCC::EQ)
1755 .addReg(ARM::CPSR));
1756
1757 // udf #ESR (trap with encoded diagnostic)
1758 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tUDF).addImm(ESR));
1759
1760 OutStreamer->emitLabel(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, ARM::R3);
1773
1774 // Spill r3 if needed
1775 if (NeedSpillR3) {
1777 *OutStreamer,
1778 MCInstBuilder(ARM::tPUSH).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));
1779 }
1780
1781 // Check if r2 is live and needs to be spilled.
1782 bool NeedSpillR2 = isRegisterLiveInCall(Call, ARM::R2);
1783
1784 // Push R2 if it's live
1785 if (NeedSpillR2) {
1787 *OutStreamer,
1788 MCInstBuilder(ARM::tPUSH).addImm(ARMCC::AL).addReg(0).addReg(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(*OutStreamer, MCInstBuilder(ARM::tMOVi8)
1797 .addReg(TempReg)
1798 .addReg(ARM::CPSR)
1799 .addImm(1)
1800 .addImm(ARMCC::AL)
1801 .addReg(0));
1802
1803 // mov scratch, target
1804 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr)
1805 .addReg(ScratchReg)
1806 .addReg(AddrReg)
1807 .addImm(ARMCC::AL));
1808
1809 // bics scratch, temp (scratch = scratch & ~temp)
1810 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBIC)
1811 .addReg(ScratchReg)
1812 .addReg(ARM::CPSR)
1813 .addReg(ScratchReg)
1814 .addReg(TempReg)
1815 .addImm(ARMCC::AL)
1816 .addReg(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(*OutStreamer, MCInstBuilder(ARM::tSUBi8)
1823 .addReg(ScratchReg)
1824 .addReg(ARM::CPSR)
1825 .addReg(ScratchReg)
1826 .addImm(offset)
1827 .addImm(ARMCC::AL)
1828 .addReg(0));
1829
1830 // ldr scratch, [scratch, #0]
1831 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi)
1832 .addReg(ScratchReg)
1833 .addReg(ScratchReg)
1834 .addImm(0)
1835 .addImm(ARMCC::AL)
1836 .addReg(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(*OutStreamer, MCInstBuilder(ARM::tMOVi8)
1856 .addReg(TempReg)
1857 .addReg(ARM::CPSR)
1858 .addImm(byte3)
1859 .addImm(ARMCC::AL)
1860 .addReg(0));
1861
1862 // lsls temp, temp, #8
1863 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)
1864 .addReg(TempReg)
1865 .addReg(ARM::CPSR)
1866 .addReg(TempReg)
1867 .addImm(8)
1868 .addImm(ARMCC::AL)
1869 .addReg(0));
1870
1871 // adds temp, #byte2
1872 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi8)
1873 .addReg(TempReg)
1874 .addReg(ARM::CPSR)
1875 .addReg(TempReg)
1876 .addImm(byte2)
1877 .addImm(ARMCC::AL)
1878 .addReg(0));
1879
1880 // lsls temp, temp, #8
1881 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)
1882 .addReg(TempReg)
1883 .addReg(ARM::CPSR)
1884 .addReg(TempReg)
1885 .addImm(8)
1886 .addImm(ARMCC::AL)
1887 .addReg(0));
1888
1889 // adds temp, #byte1
1890 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi8)
1891 .addReg(TempReg)
1892 .addReg(ARM::CPSR)
1893 .addReg(TempReg)
1894 .addImm(byte1)
1895 .addImm(ARMCC::AL)
1896 .addReg(0));
1897
1898 // lsls temp, temp, #8
1899 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)
1900 .addReg(TempReg)
1901 .addReg(ARM::CPSR)
1902 .addReg(TempReg)
1903 .addImm(8)
1904 .addImm(ARMCC::AL)
1905 .addReg(0));
1906
1907 // adds temp, #byte0 (low byte)
1908 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi8)
1909 .addReg(TempReg)
1910 .addReg(ARM::CPSR)
1911 .addReg(TempReg)
1912 .addImm(byte0)
1913 .addImm(ARMCC::AL)
1914 .addReg(0));
1915
1916 // cmp scratch, temp
1917 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tCMPr)
1918 .addReg(ScratchReg)
1919 .addReg(TempReg)
1920 .addImm(ARMCC::AL)
1921 .addReg(0));
1922
1923 // Restore registers if spilled (pop in reverse order of push: R2, then R3)
1924 if (NeedSpillR2) {
1925 // pop {r2}
1927 *OutStreamer,
1928 MCInstBuilder(ARM::tPOP).addImm(ARMCC::AL).addReg(0).addReg(ARM::R2));
1929 }
1930
1931 // Restore r3 if spilled
1932 if (NeedSpillR3) {
1933 // pop {r3}
1935 *OutStreamer,
1936 MCInstBuilder(ARM::tPOP).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));
1937 }
1938
1939 // beq .Lpass (branch if types match, i.e., scratch == temp)
1940 MCSymbol *Pass = OutContext.createTempSymbol();
1942 MCInstBuilder(ARM::tBcc)
1944 .addImm(ARMCC::EQ)
1945 .addReg(ARM::CPSR));
1946
1947 // bkpt #0 (trap with encoded diagnostic)
1948 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBKPT).addImm(0));
1949
1950 OutStreamer->emitLabel(Pass);
1951}
1952
1954 Register AddrReg = MI.getOperand(0).getReg();
1955 const int64_t Type = MI.getOperand(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(MI.getIterator());
1961
1962 // Adjust the offset for patchable-function-prefix.
1963 int64_t PrefixNops = MI.getMF()->getFunction().getFnAttributeAsParsedInteger(
1964 "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
1983 ARM_MC::verifyInstructionPredicates(MI->getOpcode(),
1984 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(MCDR_DataRegionEnd);
1994 InConstantPool = false;
1995 }
1996
1997 // Emit unwinding stuff for frame-related instructions
1998 if (TM.getTargetTriple().isTargetEHABICompatible() &&
1999 MI->getFlag(MachineInstr::FrameSetup))
2000 EmitUnwindingInstruction(MI);
2001
2002 // Do any auto-generated pseudo lowerings.
2003 if (MCInst OutInst; lowerPseudoInstExpansion(MI, OutInst)) {
2004 EmitToStreamer(*OutStreamer, 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:
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(MI->getOperand(1).getIndex());
2026 EmitToStreamer(*OutStreamer, MCInstBuilder(MI->getOpcode() ==
2027 ARM::t2LEApcrel ? ARM::t2ADR
2028 : (MI->getOpcode() == ARM::tLEApcrel ? ARM::tADR
2029 : ARM::ADR))
2030 .addReg(MI->getOperand(0).getReg())
2032 // Add predicate operands.
2033 .addImm(MI->getOperand(2).getImm())
2034 .addReg(MI->getOperand(3).getReg()));
2035 return;
2036 }
2037 case ARM::LEApcrelJT:
2038 case ARM::tLEApcrelJT:
2039 case ARM::t2LEApcrelJT: {
2040 MCSymbol *JTIPICSymbol =
2041 GetARMJTIPICJumpTableLabel(MI->getOperand(1).getIndex());
2042 EmitToStreamer(*OutStreamer, MCInstBuilder(MI->getOpcode() ==
2043 ARM::t2LEApcrelJT ? ARM::t2ADR
2044 : (MI->getOpcode() == ARM::tLEApcrelJT ? ARM::tADR
2045 : ARM::ADR))
2046 .addReg(MI->getOperand(0).getReg())
2048 // Add predicate operands.
2049 .addImm(MI->getOperand(2).getImm())
2050 .addReg(MI->getOperand(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: {
2057 .addReg(ARM::LR)
2058 .addReg(ARM::PC)
2059 // Add predicate operands.
2060 .addImm(ARMCC::AL)
2061 .addReg(0)
2062 // Add 's' bit operand (always reg0 for this)
2063 .addReg(0));
2064
2065 assert(STI.hasV4TOps() && "Expected V4TOps for BX call");
2067 MCInstBuilder(ARM::BX).addReg(MI->getOperand(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(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(std::make_pair(TReg, TRegSym));
2091 }
2092
2093 // Create a link-saving branch to the Reg Indirect Jump Pad.
2095 // Predicate comes first here.
2096 .addImm(ARMCC::AL).addReg(0)
2097 .addExpr(MCSymbolRefExpr::create(TRegSym, OutContext)));
2098 return;
2099 }
2100 case ARM::BMOVPCRX_CALL: {
2102 .addReg(ARM::LR)
2103 .addReg(ARM::PC)
2104 // Add predicate operands.
2105 .addImm(ARMCC::AL)
2106 .addReg(0)
2107 // Add 's' bit operand (always reg0 for this)
2108 .addReg(0));
2109
2111 .addReg(ARM::PC)
2112 .addReg(MI->getOperand(0).getReg())
2113 // Add predicate operands.
2115 .addReg(0)
2116 // Add 's' bit operand (always reg0 for this)
2117 .addReg(0));
2118 return;
2119 }
2120 case ARM::BMOVPCB_CALL: {
2122 .addReg(ARM::LR)
2123 .addReg(ARM::PC)
2124 // Add predicate operands.
2125 .addImm(ARMCC::AL)
2126 .addReg(0)
2127 // Add 's' bit operand (always reg0 for this)
2128 .addReg(0));
2129
2130 const MachineOperand &Op = MI->getOperand(0);
2131 const GlobalValue *GV = Op.getGlobal();
2132 const unsigned TF = Op.getTargetFlags();
2133 MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
2134 const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext);
2136 .addExpr(GVSymExpr)
2137 // Add predicate operands.
2138 .addImm(ARMCC::AL)
2139 .addReg(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(MCOperand::createReg(MI->getOperand(0).getReg()));
2147
2148 unsigned TF = MI->getOperand(1).getTargetFlags();
2149 const GlobalValue *GV = MI->getOperand(1).getGlobal();
2150 MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
2151 const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext);
2152
2153 MCSymbol *LabelSym =
2154 getPICLabel(DL.getInternalSymbolPrefix(), getFunctionNumber(),
2155 MI->getOperand(2).getImm(), OutContext);
2156 const MCExpr *LabelSymExpr= MCSymbolRefExpr::create(LabelSym, OutContext);
2157 unsigned PCAdj = (Opc == ARM::MOVi16_ga_pcrel) ? 8 : 4;
2158 const MCExpr *PCRelExpr = ARM::createLower16(
2160 GVSymExpr,
2161 MCBinaryExpr::createAdd(LabelSymExpr,
2163 OutContext),
2164 OutContext),
2165 OutContext);
2166 TmpInst.addOperand(MCOperand::createExpr(PCRelExpr));
2167
2168 // Add predicate operands.
2170 TmpInst.addOperand(MCOperand::createReg(0));
2171 // Add 's' bit operand (always reg0 for this)
2172 TmpInst.addOperand(MCOperand::createReg(0));
2173 EmitToStreamer(*OutStreamer, 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(MCOperand::createReg(MI->getOperand(0).getReg()));
2182 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(1).getReg()));
2183
2184 unsigned TF = MI->getOperand(2).getTargetFlags();
2185 const GlobalValue *GV = MI->getOperand(2).getGlobal();
2186 MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
2187 const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext);
2188
2189 MCSymbol *LabelSym =
2190 getPICLabel(DL.getInternalSymbolPrefix(), getFunctionNumber(),
2191 MI->getOperand(3).getImm(), OutContext);
2192 const MCExpr *LabelSymExpr= MCSymbolRefExpr::create(LabelSym, OutContext);
2193 unsigned PCAdj = (Opc == ARM::MOVTi16_ga_pcrel) ? 8 : 4;
2194 const MCExpr *PCRelExpr = ARM::createUpper16(
2196 GVSymExpr,
2197 MCBinaryExpr::createAdd(LabelSymExpr,
2199 OutContext),
2200 OutContext),
2201 OutContext);
2202 TmpInst.addOperand(MCOperand::createExpr(PCRelExpr));
2203 // Add predicate operands.
2205 TmpInst.addOperand(MCOperand::createReg(0));
2206 // Add 's' bit operand (always reg0 for this)
2207 TmpInst.addOperand(MCOperand::createReg(0));
2208 EmitToStreamer(*OutStreamer, 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 getBFLabel(DL.getInternalSymbolPrefix(), getFunctionNumber(),
2220 MI->getOperand(0).getIndex(), OutContext),
2221 OutContext);
2222
2223 auto MCInst = MCInstBuilder(Opc).addExpr(BranchLabel);
2224 if (MI->getOperand(1).isReg()) {
2225 // For BFr/BFLr
2226 MCInst.addReg(MI->getOperand(1).getReg());
2227 } else {
2228 // For BFi/BFLi/BFic
2229 const MCExpr *BranchTarget;
2230 if (MI->getOperand(1).isMBB())
2231 BranchTarget = MCSymbolRefExpr::create(
2232 MI->getOperand(1).getMBB()->getSymbol(), OutContext);
2233 else if (MI->getOperand(1).isGlobal()) {
2234 const GlobalValue *GV = MI->getOperand(1).getGlobal();
2235 BranchTarget = MCSymbolRefExpr::create(
2236 GetARMGVSymbol(GV, MI->getOperand(1).getTargetFlags()), OutContext);
2237 } else if (MI->getOperand(1).isSymbol()) {
2238 BranchTarget = MCSymbolRefExpr::create(
2239 GetExternalSymbolSymbol(MI->getOperand(1).getSymbolName()),
2240 OutContext);
2241 } else
2242 llvm_unreachable("Unhandled operand kind in Branch Future instruction");
2243
2244 MCInst.addExpr(BranchTarget);
2245 }
2246
2247 if (Opc == ARM::t2BFic) {
2248 const MCExpr *ElseLabel = MCSymbolRefExpr::create(
2249 getBFLabel(DL.getInternalSymbolPrefix(), getFunctionNumber(),
2250 MI->getOperand(2).getIndex(), OutContext),
2251 OutContext);
2252 MCInst.addExpr(ElseLabel);
2253 MCInst.addImm(MI->getOperand(3).getImm());
2254 } else {
2255 MCInst.addImm(MI->getOperand(2).getImm())
2256 .addReg(MI->getOperand(3).getReg());
2257 }
2258
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 getBFLabel(DL.getInternalSymbolPrefix(), getFunctionNumber(),
2268 MI->getOperand(0).getIndex(), 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(getPICLabel(DL.getInternalSymbolPrefix(),
2280 MI->getOperand(2).getImm(), OutContext));
2281
2282 // Form and emit the add.
2284 .addReg(MI->getOperand(0).getReg())
2285 .addReg(MI->getOperand(0).getReg())
2286 .addReg(ARM::PC)
2287 // Add predicate operands.
2289 .addReg(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(getPICLabel(DL.getInternalSymbolPrefix(),
2301 MI->getOperand(2).getImm(), OutContext));
2302
2303 // Form and emit the add.
2305 .addReg(MI->getOperand(0).getReg())
2306 .addReg(ARM::PC)
2307 .addReg(MI->getOperand(1).getReg())
2308 // Add predicate operands.
2309 .addImm(MI->getOperand(3).getImm())
2310 .addReg(MI->getOperand(4).getReg())
2311 // Add 's' bit operand (always reg0 for this)
2312 .addReg(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(getPICLabel(DL.getInternalSymbolPrefix(),
2332 MI->getOperand(2).getImm(), 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 }
2349 .addReg(MI->getOperand(0).getReg())
2350 .addReg(ARM::PC)
2351 .addReg(MI->getOperand(1).getReg())
2352 .addImm(0)
2353 // Add predicate operands.
2354 .addImm(MI->getOperand(3).getImm())
2355 .addReg(MI->getOperand(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(0).getImm();
2369 unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
2370
2371 // If this is the first entry of the pool, mark it.
2372 if (!InConstantPool) {
2373 OutStreamer->emitDataRegion(MCDR_DataRegion);
2374 InConstantPool = true;
2375 }
2376
2377 OutStreamer->emitLabel(GetCPISymbol(LabelId));
2378
2379 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
2380 if (MCPE.isMachineConstantPoolEntry())
2382 else
2384 return;
2385 }
2386 case ARM::JUMPTABLE_ADDRS:
2388 return;
2389 case ARM::JUMPTABLE_INSTS:
2391 return;
2392 case ARM::JUMPTABLE_TBB:
2393 case ARM::JUMPTABLE_TBH:
2394 emitJumpTableTBInst(MI, MI->getOpcode() == ARM::JUMPTABLE_TBB ? 1 : 2);
2395 return;
2396 case ARM::t2BR_JT: {
2398 .addReg(ARM::PC)
2399 .addReg(MI->getOperand(0).getReg())
2400 // Add predicate operands.
2402 .addReg(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(GetCPISymbol(MI->getOperand(3).getImm()));
2411 .addReg(MI->getOperand(0).getReg())
2412 .addReg(MI->getOperand(1).getReg())
2413 // Add predicate operands.
2415 .addReg(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(0).getReg();
2423 Register Idx = MI->getOperand(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)
2429 .addReg(Idx)
2430 .addReg(ARM::CPSR)
2431 .addReg(Idx)
2432 .addImm(1)
2433 // Add predicate operands.
2434 .addImm(ARMCC::AL)
2435 .addReg(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(Align(4), getSubtargetInfo());
2453 .addReg(Idx)
2454 .addReg(Idx)
2455 .addReg(Base)
2456 // Add predicate operands.
2457 .addImm(ARMCC::AL)
2458 .addReg(0));
2459
2460 unsigned Opc = Is8Bit ? ARM::tLDRBi : ARM::tLDRHi;
2462 .addReg(Idx)
2463 .addReg(Idx)
2464 .addImm(Is8Bit ? 4 : 2)
2465 // Add predicate operands.
2466 .addImm(ARMCC::AL)
2467 .addReg(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;
2476 .addReg(Idx)
2477 .addReg(Base)
2478 .addReg(Idx)
2479 // Add predicate operands.
2480 .addImm(ARMCC::AL)
2481 .addReg(0));
2482 }
2483
2485 .addReg(Idx)
2486 .addReg(ARM::CPSR)
2487 .addReg(Idx)
2488 .addImm(1)
2489 // Add predicate operands.
2490 .addImm(ARMCC::AL)
2491 .addReg(0));
2492
2493 OutStreamer->emitLabel(GetCPISymbol(MI->getOperand(3).getImm()));
2495 .addReg(ARM::PC)
2496 .addReg(ARM::PC)
2497 .addReg(Idx)
2498 // Add predicate operands.
2499 .addImm(ARMCC::AL)
2500 .addReg(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(MCOperand::createReg(ARM::PC));
2511 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
2512 // Add predicate operands.
2514 TmpInst.addOperand(MCOperand::createReg(0));
2515 // Add 's' bit operand (always reg0 for this)
2516 if (Opc == ARM::MOVr)
2517 TmpInst.addOperand(MCOperand::createReg(0));
2518 EmitToStreamer(*OutStreamer, 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(MCOperand::createReg(ARM::PC));
2526 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
2527 TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm()));
2528 // Add predicate operands.
2530 TmpInst.addOperand(MCOperand::createReg(0));
2531 EmitToStreamer(*OutStreamer, 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(MCOperand::createReg(ARM::PC));
2539 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
2540 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(1).getReg()));
2541 TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm()));
2542 // Add predicate operands.
2544 TmpInst.addOperand(MCOperand::createReg(0));
2545 EmitToStreamer(*OutStreamer, TmpInst);
2546 return;
2547 }
2548 case ARM::BR_JTadd: {
2549 // add pc, target, idx
2551 .addReg(ARM::PC)
2552 .addReg(MI->getOperand(0).getReg())
2553 .addReg(MI->getOperand(1).getReg())
2554 // Add predicate operands.
2556 .addReg(0)
2557 // Add 's' bit operand (always reg0 for this)
2558 .addReg(0));
2559 return;
2560 }
2561 case ARM::SPACE:
2562 OutStreamer->emitZeros(MI->getOperand(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("trap");
2570 ATS.emitInst(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("trap");
2581 ATS.emitInst(Val, '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(0).getReg();
2598 Register ValReg = MI->getOperand(1).getReg();
2599 MCSymbol *Label = OutContext.createTempSymbol("SJLJEH");
2600 OutStreamer->AddComment("eh_setjmp begin");
2602 .addReg(ValReg)
2603 .addReg(ARM::PC)
2604 // Predicate.
2605 .addImm(ARMCC::AL)
2606 .addReg(0));
2607
2609 .addReg(ValReg)
2610 // 's' bit operand
2611 .addReg(ARM::CPSR)
2612 .addReg(ValReg)
2613 .addImm(7)
2614 // Predicate.
2615 .addImm(ARMCC::AL)
2616 .addReg(0));
2617
2619 .addReg(ValReg)
2620 .addReg(SrcReg)
2621 // The offset immediate is #4. The operand value is scaled by 4 for the
2622 // tSTR instruction.
2623 .addImm(1)
2624 // Predicate.
2625 .addImm(ARMCC::AL)
2626 .addReg(0));
2627
2629 .addReg(ARM::R0)
2630 .addReg(ARM::CPSR)
2631 .addImm(0)
2632 // Predicate.
2633 .addImm(ARMCC::AL)
2634 .addReg(0));
2635
2636 const MCExpr *SymbolExpr = MCSymbolRefExpr::create(Label, OutContext);
2638 .addExpr(SymbolExpr)
2639 .addImm(ARMCC::AL)
2640 .addReg(0));
2641
2642 OutStreamer->AddComment("eh_setjmp end");
2644 .addReg(ARM::R0)
2645 .addReg(ARM::CPSR)
2646 .addImm(1)
2647 // Predicate.
2648 .addImm(ARMCC::AL)
2649 .addReg(0));
2650
2651 OutStreamer->emitLabel(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(0).getReg();
2664 Register ValReg = MI->getOperand(1).getReg();
2665
2666 OutStreamer->AddComment("eh_setjmp begin");
2668 .addReg(ValReg)
2669 .addReg(ARM::PC)
2670 .addImm(8)
2671 // Predicate.
2672 .addImm(ARMCC::AL)
2673 .addReg(0)
2674 // 's' bit operand (always reg0 for this).
2675 .addReg(0));
2676
2678 .addReg(ValReg)
2679 .addReg(SrcReg)
2680 .addImm(4)
2681 // Predicate.
2682 .addImm(ARMCC::AL)
2683 .addReg(0));
2684
2686 .addReg(ARM::R0)
2687 .addImm(0)
2688 // Predicate.
2689 .addImm(ARMCC::AL)
2690 .addReg(0)
2691 // 's' bit operand (always reg0 for this).
2692 .addReg(0));
2693
2695 .addReg(ARM::PC)
2696 .addReg(ARM::PC)
2697 .addImm(0)
2698 // Predicate.
2699 .addImm(ARMCC::AL)
2700 .addReg(0)
2701 // 's' bit operand (always reg0 for this).
2702 .addReg(0));
2703
2704 OutStreamer->AddComment("eh_setjmp end");
2706 .addReg(ARM::R0)
2707 .addImm(1)
2708 // Predicate.
2709 .addImm(ARMCC::AL)
2710 .addReg(0)
2711 // 's' bit operand (always reg0 for this).
2712 .addReg(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(0).getReg();
2721 Register ScratchReg = MI->getOperand(1).getReg();
2723 .addReg(ARM::SP)
2724 .addReg(SrcReg)
2725 .addImm(8)
2726 // Predicate.
2727 .addImm(ARMCC::AL)
2728 .addReg(0));
2729
2731 .addReg(ScratchReg)
2732 .addReg(SrcReg)
2733 .addImm(4)
2734 // Predicate.
2735 .addImm(ARMCC::AL)
2736 .addReg(0));
2737
2738 if (STI.isTargetDarwin() || STI.isTargetWindows()) {
2739 // These platforms always use the same frame register
2741 .addReg(STI.getFramePointerReg())
2742 .addReg(SrcReg)
2743 .addImm(0)
2744 // Predicate.
2746 .addReg(0));
2747 } else {
2748 // If the calling code might use either R7 or R11 as
2749 // frame pointer register, restore it into both.
2751 .addReg(ARM::R7)
2752 .addReg(SrcReg)
2753 .addImm(0)
2754 // Predicate.
2755 .addImm(ARMCC::AL)
2756 .addReg(0));
2758 .addReg(ARM::R11)
2759 .addReg(SrcReg)
2760 .addImm(0)
2761 // Predicate.
2762 .addImm(ARMCC::AL)
2763 .addReg(0));
2764 }
2765
2766 assert(STI.hasV4TOps());
2768 .addReg(ScratchReg)
2769 // Predicate.
2770 .addImm(ARMCC::AL)
2771 .addReg(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(0).getReg();
2781 Register ScratchReg = MI->getOperand(1).getReg();
2782
2784 .addReg(ScratchReg)
2785 .addReg(SrcReg)
2786 // The offset immediate is #8. The operand value is scaled by 4 for the
2787 // tLDR instruction.
2788 .addImm(2)
2789 // Predicate.
2790 .addImm(ARMCC::AL)
2791 .addReg(0));
2792
2794 .addReg(ARM::SP)
2795 .addReg(ScratchReg)
2796 // Predicate.
2797 .addImm(ARMCC::AL)
2798 .addReg(0));
2799
2801 .addReg(ScratchReg)
2802 .addReg(SrcReg)
2803 .addImm(1)
2804 // Predicate.
2805 .addImm(ARMCC::AL)
2806 .addReg(0));
2807
2808 if (STI.isTargetDarwin() || STI.isTargetWindows()) {
2809 // These platforms always use the same frame register
2811 .addReg(STI.getFramePointerReg())
2812 .addReg(SrcReg)
2813 .addImm(0)
2814 // Predicate.
2816 .addReg(0));
2817 } else {
2818 // If the calling code might use either R7 or R11 as
2819 // frame pointer register, restore it into both.
2821 .addReg(ARM::R7)
2822 .addReg(SrcReg)
2823 .addImm(0)
2824 // Predicate.
2825 .addImm(ARMCC::AL)
2826 .addReg(0));
2828 .addReg(ARM::R11)
2829 .addReg(SrcReg)
2830 .addImm(0)
2831 // Predicate.
2832 .addImm(ARMCC::AL)
2833 .addReg(0));
2834 }
2835
2837 .addReg(ScratchReg)
2838 // Predicate.
2839 .addImm(ARMCC::AL)
2840 .addReg(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(0).getReg();
2849
2851 .addReg(ARM::R11)
2852 .addReg(SrcReg)
2853 .addImm(0)
2854 // Predicate
2855 .addImm(ARMCC::AL)
2856 .addReg(0));
2858 .addReg(ARM::SP)
2859 .addReg(SrcReg)
2860 .addImm(8)
2861 // Predicate
2862 .addImm(ARMCC::AL)
2863 .addReg(0));
2865 .addReg(ARM::PC)
2866 .addReg(SrcReg)
2867 .addImm(4)
2868 // Predicate
2869 .addImm(ARMCC::AL)
2870 .addReg(0));
2871 return;
2872 }
2873 case ARM::PATCHABLE_FUNCTION_ENTER:
2875 return;
2876 case ARM::PATCHABLE_FUNCTION_EXIT:
2878 return;
2879 case ARM::PATCHABLE_TAIL_CALL:
2881 return;
2882 case ARM::SpeculationBarrierISBDSBEndBB: {
2883 // Print DSB SYS + ISB
2884 MCInst TmpInstDSB;
2885 TmpInstDSB.setOpcode(ARM::DSB);
2886 TmpInstDSB.addOperand(MCOperand::createImm(0xf));
2887 EmitToStreamer(*OutStreamer, TmpInstDSB);
2888 MCInst TmpInstISB;
2889 TmpInstISB.setOpcode(ARM::ISB);
2890 TmpInstISB.addOperand(MCOperand::createImm(0xf));
2891 EmitToStreamer(*OutStreamer, TmpInstISB);
2892 return;
2893 }
2894 case ARM::t2SpeculationBarrierISBDSBEndBB: {
2895 // Print DSB SYS + ISB
2896 MCInst TmpInstDSB;
2897 TmpInstDSB.setOpcode(ARM::t2DSB);
2898 TmpInstDSB.addOperand(MCOperand::createImm(0xf));
2900 TmpInstDSB.addOperand(MCOperand::createReg(0));
2901 EmitToStreamer(*OutStreamer, TmpInstDSB);
2902 MCInst TmpInstISB;
2903 TmpInstISB.setOpcode(ARM::t2ISB);
2904 TmpInstISB.addOperand(MCOperand::createImm(0xf));
2906 TmpInstISB.addOperand(MCOperand::createReg(0));
2907 EmitToStreamer(*OutStreamer, TmpInstISB);
2908 return;
2909 }
2910 case ARM::SpeculationBarrierSBEndBB: {
2911 // Print SB
2912 MCInst TmpInstSB;
2913 TmpInstSB.setOpcode(ARM::SB);
2914 EmitToStreamer(*OutStreamer, TmpInstSB);
2915 return;
2916 }
2917 case ARM::t2SpeculationBarrierSBEndBB: {
2918 // Print SB
2919 MCInst TmpInstSB;
2920 TmpInstSB.setOpcode(ARM::t2SB);
2921 EmitToStreamer(*OutStreamer, TmpInstSB);
2922 return;
2923 }
2924
2925 case ARM::SEH_StackAlloc:
2926 ATS.emitARMWinCFIAllocStack(MI->getOperand(0).getImm(),
2927 MI->getOperand(1).getImm());
2928 return;
2929
2930 case ARM::SEH_SaveRegs:
2931 case ARM::SEH_SaveRegs_Ret:
2932 ATS.emitARMWinCFISaveRegMask(MI->getOperand(0).getImm(),
2933 MI->getOperand(1).getImm());
2934 return;
2935
2936 case ARM::SEH_SaveSP:
2937 ATS.emitARMWinCFISaveSP(MI->getOperand(0).getImm());
2938 return;
2939
2940 case ARM::SEH_SaveFRegs:
2941 ATS.emitARMWinCFISaveFRegs(MI->getOperand(0).getImm(),
2942 MI->getOperand(1).getImm());
2943 return;
2944
2945 case ARM::SEH_SaveLR:
2946 ATS.emitARMWinCFISaveLR(MI->getOperand(0).getImm());
2947 return;
2948
2949 case ARM::SEH_Nop:
2950 case ARM::SEH_Nop_Ret:
2951 ATS.emitARMWinCFINop(MI->getOperand(0).getImm());
2952 return;
2953
2954 case ARM::SEH_PrologEnd:
2955 ATS.emitARMWinCFIPrologEnd(/*Fragment=*/false);
2956 return;
2957
2958 case ARM::SEH_EpilogStart:
2960 return;
2961
2962 case ARM::SEH_EpilogEnd:
2964 return;
2965 }
2966
2967 MCInst TmpInst;
2968 LowerARMMachineInstrToMCInst(MI, TmpInst, *this);
2969
2970 EmitToStreamer(*OutStreamer, 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() {
2989}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isRegisterLiveInCall(const MachineInstr &Call, MCRegister Reg)
static void emitNonLazySymbolPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel, MachineModuleInfoImpl::StubValueTy &MCSym)
static uint8_t getModifierSpecifier(ARMCP::ARMCPModifier Modifier)
static MCSymbol * getPICLabel(StringRef Prefix, unsigned FunctionNumber, unsigned LabelId, MCContext &Ctx)
static bool checkDenormalAttributeInconsistency(const Module &M)
static bool checkDenormalAttributeConsistency(const Module &M, DenormalFPEnv Value)
static bool checkFunctionsAttributeConsistency(const Module &M, StringRef Attr, StringRef Value)
static bool checkModuleHasStrictFP(const Module &M)
static bool isThumb(const MCSubtargetInfo &STI)
static MCSymbol * getBFLabel(StringRef Prefix, unsigned FunctionNumber, unsigned LabelId, MCContext &Ctx)
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
#define X(NUM, ENUM, NAME)
Definition ELF.h:857
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ABI
Definition Compiler.h:215
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
This file contains the declarations for the subclasses of Constant, which represent the different fla...
static RegisterPass< DebugifyModulePass > DM("debugify", "Attach debug info to everything")
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
#define F(x, y, z)
Definition MD5.cpp:54
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:484
This file defines the SmallString class.
std::unique_ptr< MCStreamer > && Streamer
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static const unsigned FramePtr
void emitJumpTableAddrs(const MachineInstr *MI)
void emitJumpTableTBInst(const MachineInstr *MI, unsigned OffsetWidth)
void emitFunctionBodyEnd() override
Targets can override this to emit stuff after the last basic block in the function.
bool runOnMachineFunction(MachineFunction &F) override
runOnMachineFunction - This uses the emitInstruction() method to print assembly for each instruction.
MCSymbol * GetCPISymbol(unsigned CPID) const override
Return the symbol for the specified constant pool entry.
void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O)
void emitStartOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the start of their fi...
ARMAsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > Streamer)
void emitFunctionEntryLabel() override
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI)
void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override
EmitMachineConstantPoolValue - Print a machine constantpool value to the .s file.
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, const char *ExtraCode, raw_ostream &O) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
void emitXXStructor(const DataLayout &DL, const Constant *CV) override
Targets can override this to change how global constants that are part of a C++ static/global constru...
void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI)
void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI)
void emitEndOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the end of their file...
std::tuple< const MCSymbol *, uint64_t, const MCSymbol *, codeview::JumpTableEntrySize > getCodeViewJumpTableInfo(int JTI, const MachineInstr *BranchInstr, const MCSymbol *BranchLabel) const override
Gets information required to create a CodeView debug symbol for a jump table.
void emitJumpTableInsts(const MachineInstr *MI)
const ARMBaseTargetMachine & getTM() const
void emitGlobalVariable(const GlobalVariable *GV) override
Emit the specified global variable to the .s file.
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, const char *ExtraCode, raw_ostream &O) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
void emitInstruction(const MachineInstr *MI) override
Targets should implement this to emit instructions.
void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override
Print the MachineOperand as a symbol.
void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, const MCSubtargetInfo *EndInfo, const MachineInstr *MI) override
Let the target do anything it needs to do after emitting inlineasm.
void LowerKCFI_CHECK(const MachineInstr &MI)
void emitGlobalAlias(const Module &M, const GlobalAlias &GA) override
ARM::ARMABI getEffectiveABI(const Module &M) const
Returns the ABI in effect for M: the "target-abi" module flag if present, otherwise the legacy -targe...
bool isGVIndirectSymbol(const GlobalValue *GV) const
FloatABI::ABIType getFloatABI(const Module &M) const
Returns the floating-point ABI in effect for M: the "float-abi" module flag if present,...
ARMConstantPoolValue - ARM specific constantpool value.
unsigned char getPCAdjustment() const
ARMCP::ARMCPModifier getModifier() const
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
static const char * getRegisterName(MCRegister Reg, unsigned AltIdx=ARM::NoRegAltName)
bool isThumb1Only() const
MCPhysReg getFramePointerReg() const
bool isTargetWindows() const
bool isTargetDarwin() const
void emitTargetAttributes(const MCSubtargetInfo &STI)
Emit the build attributes that only depend on the hardware that we expect.
virtual void emitSetFP(MCRegister FpReg, MCRegister SpReg, int64_t Offset=0)
virtual void finishAttributeSection()
virtual void emitMovSP(MCRegister Reg, int64_t Offset=0)
virtual void emitARMWinCFISaveSP(unsigned Reg)
virtual void emitInst(uint32_t Inst, char Suffix='\0')
virtual void emitARMWinCFISaveLR(unsigned Offset)
virtual void emitTextAttribute(unsigned Attribute, StringRef String)
virtual void emitARMWinCFIAllocStack(unsigned Size, bool Wide)
virtual void emitARMWinCFISaveRegMask(unsigned Mask, bool Wide)
virtual void emitRegSave(const SmallVectorImpl< MCRegister > &RegList, bool isVector)
virtual void emitARMWinCFIEpilogEnd()
virtual void emitARMWinCFIPrologEnd(bool Fragment)
virtual void switchVendor(StringRef Vendor)
virtual void emitARMWinCFISaveFRegs(unsigned First, unsigned Last)
virtual void emitARMWinCFIEpilogStart(unsigned Condition)
virtual void emitPad(int64_t Offset)
virtual void emitAttribute(unsigned Attribute, unsigned Value)
virtual void emitARMWinCFINop(bool Wide)
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
MCSymbol * getSymbolWithGlobalValueBase(const GlobalValue *GV, StringRef Suffix) const
Return the MCSymbol for a private symbol with global value name as its base, with the specified suffi...
MCSymbol * getSymbol(const GlobalValue *GV) const
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
virtual void emitGlobalVariable(const GlobalVariable *GV)
Emit the specified global variable to the .s file.
TargetMachine & TM
Target machine description.
Definition AsmPrinter.h:94
void emitXRayTable()
Emit a table with all XRay instrumentation points.
virtual void emitGlobalAlias(const Module &M, const GlobalAlias &GA)
Align emitAlignment(Align Alignment, const GlobalObject *GV=nullptr, unsigned MaxBytesToEmit=0) const
Emit an alignment directive to the specified power of two boundary.
MCSymbol * getMBBExceptionSym(const MachineBasicBlock &MBB)
MachineFunction * MF
The current machine function.
Definition AsmPrinter.h:109
virtual void SetupMachineFunction(MachineFunction &MF)
This should be called when a new MachineFunction is being processed from runOnMachineFunction.
void emitFunctionBody()
This method emits the body and trailer for a function.
virtual void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const
This emits linkage information about GVSym based on GV, if this is supported by the target.
unsigned getFunctionNumber() const
Return a unique ID for the current function.
AsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > Streamer, char &ID=AsmPrinter::ID)
void printOffset(int64_t Offset, raw_ostream &OS) const
This is just convenient handler for printing offsets.
void emitGlobalConstant(const DataLayout &DL, const Constant *CV, AliasMapTy *AliasList=nullptr)
EmitGlobalConstant - Print a general LLVM constant to the .s file.
MCSymbol * getSymbolPreferLocal(const GlobalValue &GV) const
Similar to getSymbol() but preferred for references.
MCSymbol * CurrentFnSym
The symbol for the current function.
Definition AsmPrinter.h:128
MachineModuleInfo * MMI
This is a pointer to the current MachineModuleInfo.
Definition AsmPrinter.h:112
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition AsmPrinter.h:101
bool isPositionIndependent() const
void emitVisibility(MCSymbol *Sym, unsigned Visibility, bool IsDefinition=true) const
This emits visibility information about symbol, if this is supported by the target.
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:106
const MCAsmInfo & MAI
Target Asm Printer information.
Definition AsmPrinter.h:97
void getNameWithPrefix(SmallVectorImpl< char > &Name, const GlobalValue *GV) const
MCSymbol * GetBlockAddressSymbol(const BlockAddress *BA) const
Return the MCSymbol used to satisfy BlockAddress uses of the specified basic block.
const DataLayout & getDataLayout() const
Return information about data layout.
virtual void emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
MCSymbol * GetExternalSymbolSymbol(const Twine &Sym) const
Return the MCSymbol for the specified ExternalSymbol.
const MCSubtargetInfo & getSubtargetInfo() const
Return information about subtarget.
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
The address of a basic block.
Definition Constants.h:1088
This is an important base class in LLVM.
Definition Constant.h:43
const Constant * stripPointerCasts() const
Definition Constant.h:233
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:64
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:730
LLVM_ABI const GlobalObject * getAliaseeObject() const
Definition Globals.cpp:730
bool isDSOLocal() const
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
VisibilityTypes getVisibility() const
bool hasInternalLinkage() const
static bool isWeakForLinker(LinkageTypes Linkage)
Whether the definition of this global may be replaced at link time.
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:342
static const MCBinaryExpr * createDiv(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:352
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:427
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Context object for machine code objects.
Definition MCContext.h:83
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
MCInstBuilder & addReg(MCRegister Reg)
Add a new register operand.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
MCInstBuilder & addExpr(const MCExpr *Val)
Add a new MCExpr operand.
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
MCSection * getThreadLocalPointerSection() const
MCSection * getNonLazySymbolPointerSection() const
static MCOperand createExpr(const MCExpr *Val)
Definition MCInst.h:166
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
Streaming machine code generation interface.
Definition MCStreamer.h:222
virtual bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute)=0
Add the given Attribute to Symbol.
MCContext & getContext() const
Definition MCStreamer.h:326
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
virtual void emitIntValue(uint64_t Value, unsigned Size)
Special case of EmitValue that avoids the client having to pass in a MCExpr for constant integers.
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:213
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition MCSymbol.cpp:59
StringRef getName() const
getName - Get the symbol name.
Definition MCSymbol.h:188
Target specific streamer interface.
Definition MCStreamer.h:95
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
This class is a data container for one entry in a MachineConstantPool.
union llvm::MachineConstantPoolEntry::@004270020304201266316354007027341142157160323045 Val
The constant itself.
bool isMachineConstantPoolEntry() const
isMachineConstantPoolEntry - Return true if the MachineConstantPoolEntry is indeed a target specific ...
MachineConstantPoolValue * MachineCPVal
Abstract base class for all machine specific constantpool value subclasses.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
const std::vector< MachineJumpTableEntry > & getJumpTables() const
StubValueTy & getGVStubEntry(MCSymbol *Sym)
std::vector< std::pair< MCSymbol *, StubValueTy > > SymbolListTy
PointerIntPair< MCSymbol *, 1, bool > StubValueTy
MachineModuleInfoMachO - This is a MachineModuleInfoImpl implementation for MachO targets.
StubValueTy & getGVStubEntry(MCSymbol *Sym)
StubValueTy & getThreadLocalGVStubEntry(MCSymbol *Sym)
SymbolListTy GetGVStubList()
Accessor methods to return the set of stubs in sorted order.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
const GlobalValue * getGlobal() const
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
unsigned getTargetFlags() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
@ MO_Immediate
Immediate operand.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
@ MO_GlobalAddress
Address of a global value.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
int64_t getOffset() const
Return the offset from the symbol in this operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
Pass(PassKind K, char &pid)
Definition Pass.h:105
IntType getInt() const
PointerTy getPointer() const
Wrapper class representing virtual and physical registers.
Definition Register.h:20
Represents a location in source code.
Definition SMLoc.h:22
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Primary interface to the complete machine description for the target machine.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TypeSize getRegSizeInBits(const TargetRegisterClass &RC) const
Return the size in bits of a register from class RC.
virtual Register getFrameRegister(const MachineFunction &MF) const =0
Debug information queries.
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:48
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:46
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:257
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
A raw_ostream that writes to an SmallVector or SmallString.
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ SECREL
Thread Pointer Offset.
@ GOT_PREL
Thread Local Storage (General Dynamic Mode)
@ SBREL
Section Relative (Windows TLS)
@ GOTTPOFF
Global Offset Table, PC Relative.
@ TPOFF
Global Offset Table, Thread Pointer Offset.
@ MO_LO16
MO_LO16 - On a symbol operand, this represents a relocation containing lower 16 bit of the address.
@ MO_LO_0_7
MO_LO_0_7 - On a symbol operand, this represents a relocation containing bits 0 through 7 of the addr...
@ MO_LO_8_15
MO_LO_8_15 - On a symbol operand, this represents a relocation containing bits 8 through 15 of the ad...
@ MO_NONLAZY
MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which,...
@ MO_HI_8_15
MO_HI_8_15 - On a symbol operand, this represents a relocation containing bits 24 through 31 of the a...
@ MO_HI16
MO_HI16 - On a symbol operand, this represents a relocation containing higher 16 bit of the address.
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_HI_0_7
MO_HI_0_7 - On a symbol operand, this represents a relocation containing bits 16 through 23 of the ad...
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
std::string ParseARMTriple(const Triple &TT, StringRef CPU)
const MCSpecifierExpr * createLower16(const MCExpr *Expr, MCContext &Ctx)
const MCSpecifierExpr * createUpper16(const MCExpr *Expr, MCContext &Ctx)
SymbolStorageClass
Storage class tells where and what the symbol represents.
Definition COFF.h:218
@ IMAGE_SYM_CLASS_EXTERNAL
External symbol.
Definition COFF.h:224
@ IMAGE_SYM_CLASS_STATIC
Static.
Definition COFF.h:225
@ IMAGE_SYM_DTYPE_FUNCTION
A function that returns a base type.
Definition COFF.h:276
@ SCT_COMPLEX_TYPE_SHIFT
Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT))
Definition COFF.h:280
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
Definition Metadata.h:683
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:577
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
Target & getTheThumbBETarget()
@ MCDR_DataRegionEnd
.end_data_region
@ MCDR_DataRegion
.data_region
@ MCDR_DataRegionJT8
.data_region jt8
@ MCDR_DataRegionJT32
.data_region jt32
@ MCDR_DataRegionJT16
.data_region jt16
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, ARMAsmPrinter &AP)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
DWARFExpression::Operation Op
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1917
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
Target & getTheARMLETarget()
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
@ MCSA_IndirectSymbol
.indirect_symbol (MachO)
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
Target & getTheARMBETarget()
Target & getTheThumbLETarget()
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:878
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Represents the full denormal controls for a function, including the default mode and the f32 specific...
static constexpr DenormalMode getPositiveZero()
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...