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