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 (Subtarget->isTargetELF() ? ARM::S_TARGET1 : ARM::S_None), OutContext);
101
102 OutStreamer->emitValue(E, Size);
103}
104
106 if (PromotedGlobals.count(GV))
107 // The global was promoted into a constant pool. It should not be emitted.
108 return;
110}
111
112/// runOnMachineFunction - This uses the emitInstruction()
113/// method to print assembly for each instruction.
114///
116 AFI = MF.getInfo<ARMFunctionInfo>();
117 MCP = MF.getConstantPool();
118 Subtarget = &MF.getSubtarget<ARMSubtarget>();
119
121 const Function &F = MF.getFunction();
122 const TargetMachine& TM = MF.getTarget();
123
124 // Collect all globals that had their storage promoted to a constant pool.
125 // Functions are emitted before variables, so this accumulates promoted
126 // globals from all functions in PromotedGlobals.
127 PromotedGlobals.insert_range(AFI->getGlobalsPromotedToConstantPool());
128
129 // Calculate this function's optimization goal.
130 unsigned OptimizationGoal;
131 if (F.hasOptNone())
132 // For best debugging illusion, speed and small size sacrificed
133 OptimizationGoal = 6;
134 else if (F.hasMinSize())
135 // Aggressively for small size, speed and debug illusion sacrificed
136 OptimizationGoal = 4;
137 else if (F.hasOptSize())
138 // For small size, but speed and debugging illusion preserved
139 OptimizationGoal = 3;
140 else if (TM.getOptLevel() == CodeGenOptLevel::Aggressive)
141 // Aggressively for speed, small size and debug illusion sacrificed
142 OptimizationGoal = 2;
143 else if (TM.getOptLevel() > CodeGenOptLevel::None)
144 // For speed, but small size and good debug illusion preserved
145 OptimizationGoal = 1;
146 else // TM.getOptLevel() == CodeGenOptLevel::None
147 // For good debugging, but speed and small size preserved
148 OptimizationGoal = 5;
149
150 // Combine a new optimization goal with existing ones.
151 if (OptimizationGoals == -1) // uninitialized goals
152 OptimizationGoals = OptimizationGoal;
153 else if (OptimizationGoals != (int)OptimizationGoal) // conflicting goals
154 OptimizationGoals = 0;
155
156 if (Subtarget->isTargetCOFF()) {
157 bool Local = F.hasLocalLinkage();
161
162 OutStreamer->beginCOFFSymbolDef(CurrentFnSym);
163 OutStreamer->emitCOFFSymbolStorageClass(Scl);
164 OutStreamer->emitCOFFSymbolType(Type);
165 OutStreamer->endCOFFSymbolDef();
166 }
167
168 // Emit the rest of the function body.
170
171 // Emit the XRay table for this function.
173
174 // If we need V4T thumb mode Register Indirect Jump pads, emit them.
175 // These are created per function, rather than per TU, since it's
176 // relatively easy to exceed the thumb branch range within a TU.
177 if (! ThumbIndirectPads.empty()) {
178 auto &TS =
179 static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());
180 TS.emitCode16();
182 for (std::pair<unsigned, MCSymbol *> &TIP : ThumbIndirectPads) {
183 OutStreamer->emitLabel(TIP.second);
185 .addReg(TIP.first)
186 // Add predicate operands.
188 .addReg(0));
189 }
190 ThumbIndirectPads.clear();
191 }
192
193 // We didn't modify anything.
194 return false;
195}
196
198 raw_ostream &O) {
199 assert(MO.isGlobal() && "caller should check MO.isGlobal");
200 unsigned TF = MO.getTargetFlags();
201 if (TF & ARMII::MO_LO16)
202 O << ":lower16:";
203 else if (TF & ARMII::MO_HI16)
204 O << ":upper16:";
205 else if (TF & ARMII::MO_LO_0_7)
206 O << ":lower0_7:";
207 else if (TF & ARMII::MO_LO_8_15)
208 O << ":lower8_15:";
209 else if (TF & ARMII::MO_HI_0_7)
210 O << ":upper0_7:";
211 else if (TF & ARMII::MO_HI_8_15)
212 O << ":upper8_15:";
213
214 GetARMGVSymbol(MO.getGlobal(), TF)->print(O, MAI);
215 printOffset(MO.getOffset(), O);
216}
217
219 raw_ostream &O) {
220 const MachineOperand &MO = MI->getOperand(OpNum);
221
222 switch (MO.getType()) {
223 default: llvm_unreachable("<unknown operand type>");
225 Register Reg = MO.getReg();
226 assert(Reg.isPhysical());
227 assert(!MO.getSubReg() && "Subregs should be eliminated!");
228 if(ARM::GPRPairRegClass.contains(Reg)) {
229 const MachineFunction &MF = *MI->getParent()->getParent();
230 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
231 Reg = TRI->getSubReg(Reg, ARM::gsub_0);
232 }
234 break;
235 }
237 O << '#';
238 unsigned TF = MO.getTargetFlags();
239 if (TF == ARMII::MO_LO16)
240 O << ":lower16:";
241 else if (TF == ARMII::MO_HI16)
242 O << ":upper16:";
243 else if (TF == ARMII::MO_LO_0_7)
244 O << ":lower0_7:";
245 else if (TF == ARMII::MO_LO_8_15)
246 O << ":lower8_15:";
247 else if (TF == ARMII::MO_HI_0_7)
248 O << ":upper0_7:";
249 else if (TF == ARMII::MO_HI_8_15)
250 O << ":upper8_15:";
251 O << MO.getImm();
252 break;
253 }
255 MO.getMBB()->getSymbol()->print(O, MAI);
256 return;
258 PrintSymbolOperand(MO, O);
259 break;
260 }
262 if (Subtarget->genExecuteOnly())
263 llvm_unreachable("execute-only should not generate constant pools");
264 GetCPISymbol(MO.getIndex())->print(O, MAI);
265 break;
266 }
267}
268
270 // The AsmPrinter::GetCPISymbol superclass method tries to use CPID as
271 // indexes in MachineConstantPool, which isn't in sync with indexes used here.
272 const DataLayout &DL = getDataLayout();
273 return OutContext.getOrCreateSymbol(Twine(DL.getPrivateGlobalPrefix()) +
274 "CPI" + Twine(getFunctionNumber()) + "_" +
275 Twine(CPID));
276}
277
278//===--------------------------------------------------------------------===//
279
280MCSymbol *ARMAsmPrinter::
281GetARMJTIPICJumpTableLabel(unsigned uid) const {
282 const DataLayout &DL = getDataLayout();
283 SmallString<60> Name;
284 raw_svector_ostream(Name) << DL.getPrivateGlobalPrefix() << "JTI"
285 << getFunctionNumber() << '_' << uid;
286 return OutContext.getOrCreateSymbol(Name);
287}
288
290 const char *ExtraCode, raw_ostream &O) {
291 // Does this asm operand have a single letter operand modifier?
292 if (ExtraCode && ExtraCode[0]) {
293 if (ExtraCode[1] != 0) return true; // Unknown modifier.
294
295 switch (ExtraCode[0]) {
296 default:
297 // See if this is a generic print operand
298 return AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O);
299 case 'P': // Print a VFP double precision register.
300 case 'q': // Print a NEON quad precision register.
301 printOperand(MI, OpNum, O);
302 return false;
303 case 'y': // Print a VFP single precision register as indexed double.
304 if (MI->getOperand(OpNum).isReg()) {
305 MCRegister Reg = MI->getOperand(OpNum).getReg().asMCReg();
306 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
307 // Find the 'd' register that has this 's' register as a sub-register,
308 // and determine the lane number.
309 for (MCPhysReg SR : TRI->superregs(Reg)) {
310 if (!ARM::DPRRegClass.contains(SR))
311 continue;
312 bool Lane0 = TRI->getSubReg(SR, ARM::ssub_0) == Reg;
313 O << ARMInstPrinter::getRegisterName(SR) << (Lane0 ? "[0]" : "[1]");
314 return false;
315 }
316 }
317 return true;
318 case 'B': // Bitwise inverse of integer or symbol without a preceding #.
319 if (!MI->getOperand(OpNum).isImm())
320 return true;
321 O << ~(MI->getOperand(OpNum).getImm());
322 return false;
323 case 'L': // The low 16 bits of an immediate constant.
324 if (!MI->getOperand(OpNum).isImm())
325 return true;
326 O << (MI->getOperand(OpNum).getImm() & 0xffff);
327 return false;
328 case 'M': { // A register range suitable for LDM/STM.
329 if (!MI->getOperand(OpNum).isReg())
330 return true;
331 const MachineOperand &MO = MI->getOperand(OpNum);
332 Register RegBegin = MO.getReg();
333 // This takes advantage of the 2 operand-ness of ldm/stm and that we've
334 // already got the operands in registers that are operands to the
335 // inline asm statement.
336 O << "{";
337 if (ARM::GPRPairRegClass.contains(RegBegin)) {
338 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
339 Register Reg0 = TRI->getSubReg(RegBegin, ARM::gsub_0);
340 O << ARMInstPrinter::getRegisterName(Reg0) << ", ";
341 RegBegin = TRI->getSubReg(RegBegin, ARM::gsub_1);
342 }
343 O << ARMInstPrinter::getRegisterName(RegBegin);
344
345 // FIXME: The register allocator not only may not have given us the
346 // registers in sequence, but may not be in ascending registers. This
347 // will require changes in the register allocator that'll need to be
348 // propagated down here if the operands change.
349 unsigned RegOps = OpNum + 1;
350 while (MI->getOperand(RegOps).isReg()) {
351 O << ", "
352 << ARMInstPrinter::getRegisterName(MI->getOperand(RegOps).getReg());
353 RegOps++;
354 }
355
356 O << "}";
357
358 return false;
359 }
360 case 'R': // The most significant register of a pair.
361 case 'Q': { // The least significant register of a pair.
362 if (OpNum == 0)
363 return true;
364 const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1);
365 if (!FlagsOP.isImm())
366 return true;
367 InlineAsm::Flag F(FlagsOP.getImm());
368
369 // This operand may not be the one that actually provides the register. If
370 // it's tied to a previous one then we should refer instead to that one
371 // for registers and their classes.
372 unsigned TiedIdx;
373 if (F.isUseOperandTiedToDef(TiedIdx)) {
374 for (OpNum = InlineAsm::MIOp_FirstOperand; TiedIdx; --TiedIdx) {
375 unsigned OpFlags = MI->getOperand(OpNum).getImm();
376 const InlineAsm::Flag F(OpFlags);
377 OpNum += F.getNumOperandRegisters() + 1;
378 }
379 F = InlineAsm::Flag(MI->getOperand(OpNum).getImm());
380
381 // Later code expects OpNum to be pointing at the register rather than
382 // the flags.
383 OpNum += 1;
384 }
385
386 const unsigned NumVals = F.getNumOperandRegisters();
387 unsigned RC;
388 bool FirstHalf;
389 const ARMBaseTargetMachine &ATM =
390 static_cast<const ARMBaseTargetMachine &>(TM);
391
392 // 'Q' should correspond to the low order register and 'R' to the high
393 // order register. Whether this corresponds to the upper or lower half
394 // depends on the endianess mode.
395 if (ExtraCode[0] == 'Q')
396 FirstHalf = ATM.isLittleEndian();
397 else
398 // ExtraCode[0] == 'R'.
399 FirstHalf = !ATM.isLittleEndian();
400 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
401 if (F.hasRegClassConstraint(RC) &&
402 ARM::GPRPairRegClass.hasSubClassEq(TRI->getRegClass(RC))) {
403 if (NumVals != 1)
404 return true;
405 const MachineOperand &MO = MI->getOperand(OpNum);
406 if (!MO.isReg())
407 return true;
408 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
409 Register Reg =
410 TRI->getSubReg(MO.getReg(), FirstHalf ? ARM::gsub_0 : ARM::gsub_1);
412 return false;
413 }
414 if (NumVals != 2)
415 return true;
416 unsigned RegOp = FirstHalf ? OpNum : OpNum + 1;
417 if (RegOp >= MI->getNumOperands())
418 return true;
419 const MachineOperand &MO = MI->getOperand(RegOp);
420 if (!MO.isReg())
421 return true;
422 Register Reg = MO.getReg();
424 return false;
425 }
426
427 case 'e': // The low doubleword register of a NEON quad register.
428 case 'f': { // The high doubleword register of a NEON quad register.
429 if (!MI->getOperand(OpNum).isReg())
430 return true;
431 Register Reg = MI->getOperand(OpNum).getReg();
432 if (!ARM::QPRRegClass.contains(Reg))
433 return true;
434 const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
436 TRI->getSubReg(Reg, ExtraCode[0] == 'e' ? ARM::dsub_0 : ARM::dsub_1);
438 return false;
439 }
440
441 // This modifier is not yet supported.
442 case 'h': // A range of VFP/NEON registers suitable for VLD1/VST1.
443 return true;
444 case 'H': { // The highest-numbered register of a pair.
445 const MachineOperand &MO = MI->getOperand(OpNum);
446 if (!MO.isReg())
447 return true;
448 const MachineFunction &MF = *MI->getParent()->getParent();
449 const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
450 Register Reg = MO.getReg();
451 if(!ARM::GPRPairRegClass.contains(Reg))
452 return false;
453 Reg = TRI->getSubReg(Reg, ARM::gsub_1);
455 return false;
456 }
457 }
458 }
459
460 printOperand(MI, OpNum, O);
461 return false;
462}
463
465 unsigned OpNum, const char *ExtraCode,
466 raw_ostream &O) {
467 // Does this asm operand have a single letter operand modifier?
468 if (ExtraCode && ExtraCode[0]) {
469 if (ExtraCode[1] != 0) return true; // Unknown modifier.
470
471 switch (ExtraCode[0]) {
472 case 'A': // A memory operand for a VLD1/VST1 instruction.
473 default: return true; // Unknown modifier.
474 case 'm': // The base register of a memory operand.
475 if (!MI->getOperand(OpNum).isReg())
476 return true;
477 O << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg());
478 return false;
479 }
480 }
481
482 const MachineOperand &MO = MI->getOperand(OpNum);
483 assert(MO.isReg() && "unexpected inline asm memory operand");
484 O << "[" << ARMInstPrinter::getRegisterName(MO.getReg()) << "]";
485 return false;
486}
487
488static bool isThumb(const MCSubtargetInfo& STI) {
489 return STI.hasFeature(ARM::ModeThumb);
490}
491
493 const MCSubtargetInfo *EndInfo) const {
494 // If either end mode is unknown (EndInfo == NULL) or different than
495 // the start mode, then restore the start mode.
496 const bool WasThumb = isThumb(StartInfo);
497 if (!EndInfo || WasThumb != isThumb(*EndInfo)) {
498 auto &TS =
499 static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());
500 if (WasThumb)
501 TS.emitCode16();
502 else
503 TS.emitCode32();
504 }
505}
506
508 const Triple &TT = TM.getTargetTriple();
509 auto &TS =
510 static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());
511 // Use unified assembler syntax.
513
514 // Emit ARM Build Attributes
515 if (TT.isOSBinFormatELF())
516 emitAttributes();
517
518 // Use the triple's architecture and subarchitecture to determine
519 // if we're thumb for the purposes of the top level code16 state.
520 if (!M.getModuleInlineAsm().empty() && TT.isThumb())
521 TS.emitCode16();
522}
523
524static void
527 // L_foo$stub:
528 OutStreamer.emitLabel(StubLabel);
529 // .indirect_symbol _foo
531
532 if (MCSym.getInt())
533 // External to current translation unit.
534 OutStreamer.emitIntValue(0, 4/*size*/);
535 else
536 // Internal to current translation unit.
537 //
538 // When we place the LSDA into the TEXT section, the type info
539 // pointers need to be indirect and pc-rel. We accomplish this by
540 // using NLPs; however, sometimes the types are local to the file.
541 // We need to fill in the value for the NLP in those cases.
542 OutStreamer.emitValue(
543 MCSymbolRefExpr::create(MCSym.getPointer(), OutStreamer.getContext()),
544 4 /*size*/);
545}
546
547
549 const Triple &TT = TM.getTargetTriple();
550 if (TT.isOSBinFormatMachO()) {
551 // All darwin targets use mach-o.
552 const TargetLoweringObjectFileMachO &TLOFMacho =
554 MachineModuleInfoMachO &MMIMacho =
555 MMI->getObjFileInfo<MachineModuleInfoMachO>();
556
557 // Output non-lazy-pointers for external and common global variables.
559
560 if (!Stubs.empty()) {
561 // Switch with ".non_lazy_symbol_pointer" directive.
562 OutStreamer->switchSection(TLOFMacho.getNonLazySymbolPointerSection());
564
565 for (auto &Stub : Stubs)
566 emitNonLazySymbolPointer(*OutStreamer, Stub.first, Stub.second);
567
568 Stubs.clear();
569 OutStreamer->addBlankLine();
570 }
571
572 Stubs = MMIMacho.GetThreadLocalGVStubList();
573 if (!Stubs.empty()) {
574 // Switch with ".non_lazy_symbol_pointer" directive.
575 OutStreamer->switchSection(TLOFMacho.getThreadLocalPointerSection());
577
578 for (auto &Stub : Stubs)
579 emitNonLazySymbolPointer(*OutStreamer, Stub.first, Stub.second);
580
581 Stubs.clear();
582 OutStreamer->addBlankLine();
583 }
584
585 // Funny Darwin hack: This flag tells the linker that no global symbols
586 // contain code that falls through to other global symbols (e.g. the obvious
587 // implementation of multiple entry points). If this doesn't occur, the
588 // linker can safely perform dead code stripping. Since LLVM never
589 // generates code that does this, it is always safe to set.
590 OutStreamer->emitSubsectionsViaSymbols();
591 }
592
593 // The last attribute to be emitted is ABI_optimization_goals
594 MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
595 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
596
597 if (OptimizationGoals > 0 &&
598 (Subtarget->isTargetAEABI() || Subtarget->isTargetGNUAEABI() ||
599 Subtarget->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 if (Subtarget->isTargetMachO()) {
888 bool IsIndirect =
889 (TargetFlags & ARMII::MO_NONLAZY) && Subtarget->isGVIndirectSymbol(GV);
890
891 if (!IsIndirect)
892 return getSymbol(GV);
893
894 // FIXME: Remove this when Darwin transition to @GOT like syntax.
895 MCSymbol *MCSym = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
896 MachineModuleInfoMachO &MMIMachO =
897 MMI->getObjFileInfo<MachineModuleInfoMachO>();
899 GV->isThreadLocal() ? MMIMachO.getThreadLocalGVStubEntry(MCSym)
900 : MMIMachO.getGVStubEntry(MCSym);
901
902 if (!StubSym.getPointer())
904 !GV->hasInternalLinkage());
905 return MCSym;
906 } else if (Subtarget->isTargetCOFF()) {
907 assert(Subtarget->isTargetWindows() &&
908 "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 (Subtarget->isTargetELF()) {
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 = Subtarget->isTargetMachO() ? ARMII::MO_NONLAZY : 0;
982 MCSym = GetARMGVSymbol(GV, TF);
983 } else if (ACPV->isMachineBasicBlock()) {
984 const MachineBasicBlock *MBB = cast<ARMConstantPoolMBB>(ACPV)->getMBB();
985 MCSym = MBB->getSymbol();
986 } else {
987 assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
988 auto Sym = cast<ARMConstantPoolSymbol>(ACPV)->getSymbol();
989 MCSym = GetExternalSymbolSymbol(Sym);
990 }
991
992 // Create an MCSymbol for the reference.
993 const MCExpr *Expr = MCSymbolRefExpr::create(
995
996 if (ACPV->getPCAdjustment()) {
997 MCSymbol *PCLabel =
998 getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
999 ACPV->getLabelId(), OutContext);
1000 const MCExpr *PCRelExpr = MCSymbolRefExpr::create(PCLabel, OutContext);
1001 PCRelExpr =
1002 MCBinaryExpr::createAdd(PCRelExpr,
1004 OutContext),
1005 OutContext);
1006 if (ACPV->mustAddCurrentAddress()) {
1007 // We want "(<expr> - .)", but MC doesn't have a concept of the '.'
1008 // label, so just emit a local label end reference that instead.
1009 MCSymbol *DotSym = OutContext.createTempSymbol();
1010 OutStreamer->emitLabel(DotSym);
1011 const MCExpr *DotExpr = MCSymbolRefExpr::create(DotSym, OutContext);
1012 PCRelExpr = MCBinaryExpr::createSub(PCRelExpr, DotExpr, OutContext);
1013 }
1014 Expr = MCBinaryExpr::createSub(Expr, PCRelExpr, OutContext);
1015 }
1016 OutStreamer->emitValue(Expr, Size);
1017}
1018
1020 const MachineOperand &MO1 = MI->getOperand(1);
1021 unsigned JTI = MO1.getIndex();
1022
1023 // Make sure the Thumb jump table is 4-byte aligned. This will be a nop for
1024 // ARM mode tables.
1025 emitAlignment(Align(4));
1026
1027 // Emit a label for the jump table.
1028 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);
1029 OutStreamer->emitLabel(JTISymbol);
1030
1031 // Mark the jump table as data-in-code.
1032 OutStreamer->emitDataRegion(MCDR_DataRegionJT32);
1033
1034 // Emit each entry of the table.
1035 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
1036 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
1037 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1038
1039 for (MachineBasicBlock *MBB : JTBBs) {
1040 // Construct an MCExpr for the entry. We want a value of the form:
1041 // (BasicBlockAddr - TableBeginAddr)
1042 //
1043 // For example, a table with entries jumping to basic blocks BB0 and BB1
1044 // would look like:
1045 // LJTI_0_0:
1046 // .word (LBB0 - LJTI_0_0)
1047 // .word (LBB1 - LJTI_0_0)
1048 const MCExpr *Expr = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
1049
1050 if (isPositionIndependent() || Subtarget->isROPI())
1051 Expr = MCBinaryExpr::createSub(Expr, MCSymbolRefExpr::create(JTISymbol,
1052 OutContext),
1053 OutContext);
1054 // If we're generating a table of Thumb addresses in static relocation
1055 // model, we need to add one to keep interworking correctly.
1056 else if (AFI->isThumbFunction())
1058 OutContext);
1059 OutStreamer->emitValue(Expr, 4);
1060 }
1061 // Mark the end of jump table data-in-code region.
1062 OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
1063}
1064
1066 const MachineOperand &MO1 = MI->getOperand(1);
1067 unsigned JTI = MO1.getIndex();
1068
1069 // Make sure the Thumb jump table is 4-byte aligned. This will be a nop for
1070 // ARM mode tables.
1071 emitAlignment(Align(4));
1072
1073 // Emit a label for the jump table.
1074 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);
1075 OutStreamer->emitLabel(JTISymbol);
1076
1077 // Emit each entry of the table.
1078 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
1079 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
1080 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1081
1082 for (MachineBasicBlock *MBB : JTBBs) {
1083 const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::create(MBB->getSymbol(),
1084 OutContext);
1085 // If this isn't a TBB or TBH, the entries are direct branch instructions.
1087 .addExpr(MBBSymbolExpr)
1088 .addImm(ARMCC::AL)
1089 .addReg(0));
1090 }
1091}
1092
1094 unsigned OffsetWidth) {
1095 assert((OffsetWidth == 1 || OffsetWidth == 2) && "invalid tbb/tbh width");
1096 const MachineOperand &MO1 = MI->getOperand(1);
1097 unsigned JTI = MO1.getIndex();
1098
1099 if (Subtarget->isThumb1Only())
1100 emitAlignment(Align(4));
1101
1102 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);
1103 OutStreamer->emitLabel(JTISymbol);
1104
1105 // Emit each entry of the table.
1106 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
1107 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
1108 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1109
1110 // Mark the jump table as data-in-code.
1111 OutStreamer->emitDataRegion(OffsetWidth == 1 ? MCDR_DataRegionJT8
1113
1114 for (auto *MBB : JTBBs) {
1115 const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::create(MBB->getSymbol(),
1116 OutContext);
1117 // Otherwise it's an offset from the dispatch instruction. Construct an
1118 // MCExpr for the entry. We want a value of the form:
1119 // (BasicBlockAddr - TBBInstAddr + 4) / 2
1120 //
1121 // For example, a TBB table with entries jumping to basic blocks BB0 and BB1
1122 // would look like:
1123 // LJTI_0_0:
1124 // .byte (LBB0 - (LCPI0_0 + 4)) / 2
1125 // .byte (LBB1 - (LCPI0_0 + 4)) / 2
1126 // where LCPI0_0 is a label defined just before the TBB instruction using
1127 // this table.
1128 MCSymbol *TBInstPC = GetCPISymbol(MI->getOperand(0).getImm());
1129 const MCExpr *Expr = MCBinaryExpr::createAdd(
1132 Expr = MCBinaryExpr::createSub(MBBSymbolExpr, Expr, OutContext);
1134 OutContext);
1135 OutStreamer->emitValue(Expr, OffsetWidth);
1136 }
1137 // Mark the end of jump table data-in-code region. 32-bit offsets use
1138 // actual branch instructions here, so we don't mark those as a data-region
1139 // at all.
1140 OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
1141
1142 // Make sure the next instruction is 2-byte aligned.
1143 emitAlignment(Align(2));
1144}
1145
1146std::tuple<const MCSymbol *, uint64_t, const MCSymbol *,
1149 const MachineInstr *BranchInstr,
1150 const MCSymbol *BranchLabel) const {
1152 const MCSymbol *BaseLabel;
1153 uint64_t BaseOffset = 0;
1154 switch (BranchInstr->getOpcode()) {
1155 case ARM::BR_JTadd:
1156 case ARM::BR_JTr:
1157 case ARM::tBR_JTr:
1158 // Word relative to the jump table address.
1160 BaseLabel = GetARMJTIPICJumpTableLabel(JTI);
1161 break;
1162 case ARM::tTBH_JT:
1163 case ARM::t2TBH_JT:
1164 // half-word shifted left, relative to *after* the branch instruction.
1166 BranchLabel = GetCPISymbol(BranchInstr->getOperand(3).getImm());
1167 BaseLabel = BranchLabel;
1168 BaseOffset = 4;
1169 break;
1170 case ARM::tTBB_JT:
1171 case ARM::t2TBB_JT:
1172 // byte shifted left, relative to *after* the branch instruction.
1174 BranchLabel = GetCPISymbol(BranchInstr->getOperand(3).getImm());
1175 BaseLabel = BranchLabel;
1176 BaseOffset = 4;
1177 break;
1178 case ARM::t2BR_JT:
1179 // Direct jump.
1180 BaseLabel = nullptr;
1182 break;
1183 default:
1184 llvm_unreachable("Unknown jump table instruction");
1185 }
1186
1187 return std::make_tuple(BaseLabel, BaseOffset, BranchLabel, EntrySize);
1188}
1189
1190void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) {
1192 "Only instruction which are involved into frame setup code are allowed");
1193
1194 MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
1195 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
1196 const MachineFunction &MF = *MI->getParent()->getParent();
1197 const TargetRegisterInfo *TargetRegInfo =
1199 const MachineRegisterInfo &MachineRegInfo = MF.getRegInfo();
1200
1201 Register FramePtr = TargetRegInfo->getFrameRegister(MF);
1202 unsigned Opc = MI->getOpcode();
1203 unsigned SrcReg, DstReg;
1204
1205 switch (Opc) {
1206 case ARM::tPUSH:
1207 // special case: tPUSH does not have src/dst regs.
1208 SrcReg = DstReg = ARM::SP;
1209 break;
1210 case ARM::tLDRpci:
1211 case ARM::t2MOVi16:
1212 case ARM::t2MOVTi16:
1213 case ARM::tMOVi8:
1214 case ARM::tADDi8:
1215 case ARM::tLSLri:
1216 // special cases:
1217 // 1) for Thumb1 code we sometimes materialize the constant via constpool
1218 // load.
1219 // 2) for Thumb1 execute only code we materialize the constant via the
1220 // following pattern:
1221 // movs r3, #:upper8_15:<const>
1222 // lsls r3, #8
1223 // adds r3, #:upper0_7:<const>
1224 // lsls r3, #8
1225 // adds r3, #:lower8_15:<const>
1226 // lsls r3, #8
1227 // adds r3, #:lower0_7:<const>
1228 // So we need to special-case MOVS, ADDS and LSLS, and keep track of
1229 // where we are in the sequence with the simplest of state machines.
1230 // 3) for Thumb2 execute only code we materialize the constant via
1231 // immediate constants in 2 separate instructions (MOVW/MOVT).
1232 SrcReg = ~0U;
1233 DstReg = MI->getOperand(0).getReg();
1234 break;
1235 case ARM::VMRS:
1236 SrcReg = ARM::FPSCR;
1237 DstReg = MI->getOperand(0).getReg();
1238 break;
1239 case ARM::VMRS_FPEXC:
1240 SrcReg = ARM::FPEXC;
1241 DstReg = MI->getOperand(0).getReg();
1242 break;
1243 default:
1244 SrcReg = MI->getOperand(1).getReg();
1245 DstReg = MI->getOperand(0).getReg();
1246 break;
1247 }
1248
1249 // Try to figure out the unwinding opcode out of src / dst regs.
1250 if (MI->mayStore()) {
1251 // Register saves.
1252 assert(DstReg == ARM::SP &&
1253 "Only stack pointer as a destination reg is supported");
1254
1256 // Skip src & dst reg, and pred ops.
1257 unsigned StartOp = 2 + 2;
1258 // Use all the operands.
1259 unsigned NumOffset = 0;
1260 // Amount of SP adjustment folded into a push, before the
1261 // registers are stored (pad at higher addresses).
1262 unsigned PadBefore = 0;
1263 // Amount of SP adjustment folded into a push, after the
1264 // registers are stored (pad at lower addresses).
1265 unsigned PadAfter = 0;
1266
1267 switch (Opc) {
1268 default:
1269 MI->print(errs());
1270 llvm_unreachable("Unsupported opcode for unwinding information");
1271 case ARM::tPUSH:
1272 // Special case here: no src & dst reg, but two extra imp ops.
1273 StartOp = 2; NumOffset = 2;
1274 [[fallthrough]];
1275 case ARM::STMDB_UPD:
1276 case ARM::t2STMDB_UPD:
1277 case ARM::VSTMDDB_UPD:
1278 assert(SrcReg == ARM::SP &&
1279 "Only stack pointer as a source reg is supported");
1280 for (unsigned i = StartOp, NumOps = MI->getNumOperands() - NumOffset;
1281 i != NumOps; ++i) {
1282 const MachineOperand &MO = MI->getOperand(i);
1283 // Actually, there should never be any impdef stuff here. Skip it
1284 // temporary to workaround PR11902.
1285 if (MO.isImplicit())
1286 continue;
1287 // Registers, pushed as a part of folding an SP update into the
1288 // push instruction are marked as undef and should not be
1289 // restored when unwinding, because the function can modify the
1290 // corresponding stack slots.
1291 if (MO.isUndef()) {
1292 assert(RegList.empty() &&
1293 "Pad registers must come before restored ones");
1294 unsigned Width =
1295 TargetRegInfo->getRegSizeInBits(MO.getReg(), MachineRegInfo) / 8;
1296 PadAfter += Width;
1297 continue;
1298 }
1299 // Check for registers that are remapped (for a Thumb1 prologue that
1300 // saves high registers).
1301 Register Reg = MO.getReg();
1302 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(Reg))
1303 Reg = RemappedReg;
1304 RegList.push_back(Reg);
1305 }
1306 break;
1307 case ARM::STR_PRE_IMM:
1308 case ARM::STR_PRE_REG:
1309 case ARM::t2STR_PRE:
1310 assert(MI->getOperand(2).getReg() == ARM::SP &&
1311 "Only stack pointer as a source reg is supported");
1312 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(SrcReg))
1313 SrcReg = RemappedReg;
1314
1315 RegList.push_back(SrcReg);
1316 break;
1317 case ARM::t2STRD_PRE:
1318 assert(MI->getOperand(3).getReg() == ARM::SP &&
1319 "Only stack pointer as a source reg is supported");
1320 SrcReg = MI->getOperand(1).getReg();
1321 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(SrcReg))
1322 SrcReg = RemappedReg;
1323 RegList.push_back(SrcReg);
1324 SrcReg = MI->getOperand(2).getReg();
1325 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(SrcReg))
1326 SrcReg = RemappedReg;
1327 RegList.push_back(SrcReg);
1328 PadBefore = -MI->getOperand(4).getImm() - 8;
1329 break;
1330 }
1331 if (MAI->getExceptionHandlingType() == ExceptionHandling::ARM) {
1332 if (PadBefore)
1333 ATS.emitPad(PadBefore);
1334 ATS.emitRegSave(RegList, Opc == ARM::VSTMDDB_UPD);
1335 // Account for the SP adjustment, folded into the push.
1336 if (PadAfter)
1337 ATS.emitPad(PadAfter);
1338 }
1339 } else {
1340 // Changes of stack / frame pointer.
1341 if (SrcReg == ARM::SP) {
1342 int64_t Offset = 0;
1343 switch (Opc) {
1344 default:
1345 MI->print(errs());
1346 llvm_unreachable("Unsupported opcode for unwinding information");
1347 case ARM::tLDRspi:
1348 // Used to restore LR in a prologue which uses it as a temporary, has
1349 // no effect on unwind tables.
1350 return;
1351 case ARM::MOVr:
1352 case ARM::tMOVr:
1353 Offset = 0;
1354 break;
1355 case ARM::ADDri:
1356 case ARM::t2ADDri:
1357 case ARM::t2ADDri12:
1358 case ARM::t2ADDspImm:
1359 case ARM::t2ADDspImm12:
1360 Offset = -MI->getOperand(2).getImm();
1361 break;
1362 case ARM::SUBri:
1363 case ARM::t2SUBri:
1364 case ARM::t2SUBri12:
1365 case ARM::t2SUBspImm:
1366 case ARM::t2SUBspImm12:
1367 Offset = MI->getOperand(2).getImm();
1368 break;
1369 case ARM::tSUBspi:
1370 Offset = MI->getOperand(2).getImm()*4;
1371 break;
1372 case ARM::tADDspi:
1373 case ARM::tADDrSPi:
1374 Offset = -MI->getOperand(2).getImm()*4;
1375 break;
1376 case ARM::tADDhirr:
1377 Offset =
1378 -AFI->EHPrologueOffsetInRegs.lookup(MI->getOperand(2).getReg());
1379 break;
1380 }
1381
1382 if (MAI->getExceptionHandlingType() == ExceptionHandling::ARM) {
1383 if (DstReg == FramePtr && FramePtr != ARM::SP)
1384 // Set-up of the frame pointer. Positive values correspond to "add"
1385 // instruction.
1386 ATS.emitSetFP(FramePtr, ARM::SP, -Offset);
1387 else if (DstReg == ARM::SP) {
1388 // Change of SP by an offset. Positive values correspond to "sub"
1389 // instruction.
1390 ATS.emitPad(Offset);
1391 } else {
1392 // Move of SP to a register. Positive values correspond to an "add"
1393 // instruction.
1394 ATS.emitMovSP(DstReg, -Offset);
1395 }
1396 }
1397 } else if (DstReg == ARM::SP) {
1398 MI->print(errs());
1399 llvm_unreachable("Unsupported opcode for unwinding information");
1400 } else {
1401 int64_t Offset = 0;
1402 switch (Opc) {
1403 case ARM::tMOVr:
1404 // If a Thumb1 function spills r8-r11, we copy the values to low
1405 // registers before pushing them. Record the copy so we can emit the
1406 // correct ".save" later.
1407 AFI->EHPrologueRemappedRegs[DstReg] = SrcReg;
1408 break;
1409 case ARM::VMRS:
1410 case ARM::VMRS_FPEXC:
1411 // If a function spills FPSCR or FPEXC, we copy the values to low
1412 // registers before pushing them. However, we can't issue annotations
1413 // for FP status registers because ".save" requires GPR registers, and
1414 // ".vsave" requires DPR registers, so don't record the copy and simply
1415 // emit annotations for the source registers used for the store.
1416 break;
1417 case ARM::tLDRpci: {
1418 // Grab the constpool index and check, whether it corresponds to
1419 // original or cloned constpool entry.
1420 unsigned CPI = MI->getOperand(1).getIndex();
1421 const MachineConstantPool *MCP = MF.getConstantPool();
1422 if (CPI >= MCP->getConstants().size())
1423 CPI = AFI->getOriginalCPIdx(CPI);
1424 assert(CPI != -1U && "Invalid constpool index");
1425
1426 // Derive the actual offset.
1427 const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI];
1428 assert(!CPE.isMachineConstantPoolEntry() && "Invalid constpool entry");
1429 Offset = cast<ConstantInt>(CPE.Val.ConstVal)->getSExtValue();
1430 AFI->EHPrologueOffsetInRegs[DstReg] = Offset;
1431 break;
1432 }
1433 case ARM::t2MOVi16:
1434 Offset = MI->getOperand(1).getImm();
1435 AFI->EHPrologueOffsetInRegs[DstReg] = Offset;
1436 break;
1437 case ARM::t2MOVTi16:
1438 Offset = MI->getOperand(2).getImm();
1439 AFI->EHPrologueOffsetInRegs[DstReg] |= (Offset << 16);
1440 break;
1441 case ARM::tMOVi8:
1442 Offset = MI->getOperand(2).getImm();
1443 AFI->EHPrologueOffsetInRegs[DstReg] = Offset;
1444 break;
1445 case ARM::tLSLri:
1446 assert(MI->getOperand(3).getImm() == 8 &&
1447 "The shift amount is not equal to 8");
1448 assert(MI->getOperand(2).getReg() == MI->getOperand(0).getReg() &&
1449 "The source register is not equal to the destination register");
1450 AFI->EHPrologueOffsetInRegs[DstReg] <<= 8;
1451 break;
1452 case ARM::tADDi8:
1453 assert(MI->getOperand(2).getReg() == MI->getOperand(0).getReg() &&
1454 "The source register is not equal to the destination register");
1455 Offset = MI->getOperand(3).getImm();
1456 AFI->EHPrologueOffsetInRegs[DstReg] += Offset;
1457 break;
1458 case ARM::t2PAC:
1459 case ARM::t2PACBTI:
1460 AFI->EHPrologueRemappedRegs[ARM::R12] = ARM::RA_AUTH_CODE;
1461 break;
1462 default:
1463 MI->print(errs());
1464 llvm_unreachable("Unsupported opcode for unwinding information");
1465 }
1466 }
1467 }
1468}
1469
1470// Simple pseudo-instructions have their lowering (with expansion to real
1471// instructions) auto-generated.
1472#include "ARMGenMCPseudoLowering.inc"
1473
1474// Helper function to check if a register is live (used as an implicit operand)
1475// in the given call instruction.
1477 for (const MachineOperand &MO : Call.implicit_operands()) {
1478 if (MO.isReg() && MO.getReg() == Reg && MO.isUse()) {
1479 return true;
1480 }
1481 }
1482 return false;
1483}
1484
1485void ARMAsmPrinter::EmitKCFI_CHECK_ARM32(Register AddrReg, int64_t Type,
1486 const MachineInstr &Call,
1487 int64_t PrefixNops) {
1488 // Choose scratch register: r12 primary, r3 if target is r12.
1489 unsigned ScratchReg = ARM::R12;
1490 if (AddrReg == ARM::R12) {
1491 ScratchReg = ARM::R3;
1492 }
1493
1494 // Calculate ESR for ARM mode (16-bit): 0x8000 | (scratch_reg << 5) | addr_reg
1495 // Note: scratch_reg is always 0x1F since the EOR sequence clobbers it.
1496 const ARMBaseRegisterInfo *TRI = static_cast<const ARMBaseRegisterInfo *>(
1497 MF->getSubtarget().getRegisterInfo());
1498 unsigned AddrIndex = TRI->getEncodingValue(AddrReg);
1499 unsigned ESR = 0x8000 | (31 << 5) | (AddrIndex & 31);
1500
1501 // Check if r3 is live and needs to be spilled.
1502 bool NeedSpillR3 =
1503 (ScratchReg == ARM::R3) && isRegisterLiveInCall(Call, ARM::R3);
1504
1505 // If we need to spill r3, push it first.
1506 if (NeedSpillR3) {
1507 // push {r3}
1508 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::STMDB_UPD)
1509 .addReg(ARM::SP)
1510 .addReg(ARM::SP)
1511 .addImm(ARMCC::AL)
1512 .addReg(0)
1513 .addReg(ARM::R3));
1514 }
1515
1516 // Clear bit 0 of target address to handle Thumb function pointers.
1517 // In 32-bit ARM, function pointers may have the low bit set to indicate
1518 // Thumb state when ARM/Thumb interworking is enabled (ARMv4T and later).
1519 // We need to clear it to avoid an alignment fault when loading.
1520 // bic scratch, target, #1
1521 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::BICri)
1522 .addReg(ScratchReg)
1523 .addReg(AddrReg)
1524 .addImm(1)
1525 .addImm(ARMCC::AL)
1526 .addReg(0)
1527 .addReg(0));
1528
1529 // ldr scratch, [scratch, #-(PrefixNops * 4 + 4)]
1530 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12)
1531 .addReg(ScratchReg)
1532 .addReg(ScratchReg)
1533 .addImm(-(PrefixNops * 4 + 4))
1534 .addImm(ARMCC::AL)
1535 .addReg(0));
1536
1537 // Each EOR instruction XORs one byte of the type, shifted to its position.
1538 for (int i = 0; i < 4; i++) {
1539 uint8_t byte = (Type >> (i * 8)) & 0xFF;
1540 uint32_t imm = byte << (i * 8);
1541 bool isLast = (i == 3);
1542
1543 // Encode as ARM modified immediate.
1544 int SOImmVal = ARM_AM::getSOImmVal(imm);
1545 assert(SOImmVal != -1 &&
1546 "Cannot encode immediate as ARM modified immediate");
1547
1548 // eor[s] scratch, scratch, #imm (last one sets flags with CPSR)
1550 MCInstBuilder(ARM::EORri)
1551 .addReg(ScratchReg)
1552 .addReg(ScratchReg)
1553 .addImm(SOImmVal)
1554 .addImm(ARMCC::AL)
1555 .addReg(0)
1556 .addReg(isLast ? ARM::CPSR : ARM::NoRegister));
1557 }
1558
1559 // If we spilled r3, restore it immediately after the comparison.
1560 // This must happen before the branch so r3 is valid on both paths.
1561 if (NeedSpillR3) {
1562 // pop {r3}
1563 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDMIA_UPD)
1564 .addReg(ARM::SP)
1565 .addReg(ARM::SP)
1566 .addImm(ARMCC::AL)
1567 .addReg(0)
1568 .addReg(ARM::R3));
1569 }
1570
1571 // beq .Lpass (branch if types match, i.e., scratch is zero)
1572 MCSymbol *Pass = OutContext.createTempSymbol();
1574 MCInstBuilder(ARM::Bcc)
1576 .addImm(ARMCC::EQ)
1577 .addReg(ARM::CPSR));
1578
1579 // udf #ESR (trap with encoded diagnostic)
1580 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::UDF).addImm(ESR));
1581
1582 OutStreamer->emitLabel(Pass);
1583}
1584
1585void ARMAsmPrinter::EmitKCFI_CHECK_Thumb2(Register AddrReg, int64_t Type,
1586 const MachineInstr &Call,
1587 int64_t PrefixNops) {
1588 // Choose scratch register: r12 primary, r3 if target is r12.
1589 unsigned ScratchReg = ARM::R12;
1590 if (AddrReg == ARM::R12) {
1591 ScratchReg = ARM::R3;
1592 }
1593
1594 // Calculate ESR for Thumb mode (8-bit): 0x80 | addr_reg
1595 // Bit 7: KCFI trap indicator
1596 // Bits 6-5: Reserved
1597 // Bits 4-0: Address register encoding
1598 const ARMBaseRegisterInfo *TRI = static_cast<const ARMBaseRegisterInfo *>(
1599 MF->getSubtarget().getRegisterInfo());
1600 unsigned AddrIndex = TRI->getEncodingValue(AddrReg);
1601 unsigned ESR = 0x80 | (AddrIndex & 0x1F);
1602
1603 // Check if r3 is live and needs to be spilled.
1604 bool NeedSpillR3 =
1605 (ScratchReg == ARM::R3) && isRegisterLiveInCall(Call, ARM::R3);
1606
1607 // If we need to spill r3, push it first.
1608 if (NeedSpillR3) {
1609 // push {r3}
1611 *OutStreamer,
1612 MCInstBuilder(ARM::tPUSH).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));
1613 }
1614
1615 // Clear bit 0 of target address to handle Thumb function pointers.
1616 // In 32-bit ARM, function pointers may have the low bit set to indicate
1617 // Thumb state when ARM/Thumb interworking is enabled (ARMv4T and later).
1618 // We need to clear it to avoid an alignment fault when loading.
1619 // bic scratch, target, #1
1620 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2BICri)
1621 .addReg(ScratchReg)
1622 .addReg(AddrReg)
1623 .addImm(1)
1624 .addImm(ARMCC::AL)
1625 .addReg(0)
1626 .addReg(0));
1627
1628 // ldr scratch, [scratch, #-(PrefixNops * 4 + 4)]
1629 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi8)
1630 .addReg(ScratchReg)
1631 .addReg(ScratchReg)
1632 .addImm(-(PrefixNops * 4 + 4))
1633 .addImm(ARMCC::AL)
1634 .addReg(0));
1635
1636 // Each EOR instruction XORs one byte of the type, shifted to its position.
1637 for (int i = 0; i < 4; i++) {
1638 uint8_t byte = (Type >> (i * 8)) & 0xFF;
1639 uint32_t imm = byte << (i * 8);
1640 bool isLast = (i == 3);
1641
1642 // Verify the immediate can be encoded as Thumb2 modified immediate.
1643 assert(ARM_AM::getT2SOImmVal(imm) != -1 &&
1644 "Cannot encode immediate as Thumb2 modified immediate");
1645
1646 // eor[s] scratch, scratch, #imm (last one sets flags with CPSR)
1648 MCInstBuilder(ARM::t2EORri)
1649 .addReg(ScratchReg)
1650 .addReg(ScratchReg)
1651 .addImm(imm)
1652 .addImm(ARMCC::AL)
1653 .addReg(0)
1654 .addReg(isLast ? ARM::CPSR : ARM::NoRegister));
1655 }
1656
1657 // If we spilled r3, restore it immediately after the comparison.
1658 // This must happen before the branch so r3 is valid on both paths.
1659 if (NeedSpillR3) {
1660 // pop {r3}
1662 *OutStreamer,
1663 MCInstBuilder(ARM::tPOP).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));
1664 }
1665
1666 // beq .Lpass (branch if types match, i.e., scratch is zero)
1667 MCSymbol *Pass = OutContext.createTempSymbol();
1669 MCInstBuilder(ARM::t2Bcc)
1671 .addImm(ARMCC::EQ)
1672 .addReg(ARM::CPSR));
1673
1674 // udf #ESR (trap with encoded diagnostic)
1675 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tUDF).addImm(ESR));
1676
1677 OutStreamer->emitLabel(Pass);
1678}
1679
1680void ARMAsmPrinter::EmitKCFI_CHECK_Thumb1(Register AddrReg, int64_t Type,
1681 const MachineInstr &Call,
1682 int64_t PrefixNops) {
1683 // For Thumb1, use R2 unconditionally as scratch register (a low register
1684 // required for tLDRi). R3 is used for building the type hash.
1685 unsigned ScratchReg = ARM::R2;
1686 unsigned TempReg = ARM::R3;
1687
1688 // Check if r3 is live and needs to be spilled.
1689 bool NeedSpillR3 = isRegisterLiveInCall(Call, ARM::R3);
1690
1691 // Spill r3 if needed
1692 if (NeedSpillR3) {
1694 *OutStreamer,
1695 MCInstBuilder(ARM::tPUSH).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));
1696 }
1697
1698 // Check if r2 is live and needs to be spilled.
1699 bool NeedSpillR2 = isRegisterLiveInCall(Call, ARM::R2);
1700
1701 // Push R2 if it's live
1702 if (NeedSpillR2) {
1704 *OutStreamer,
1705 MCInstBuilder(ARM::tPUSH).addImm(ARMCC::AL).addReg(0).addReg(ARM::R2));
1706 }
1707
1708 // Clear bit 0 from target address
1709 // TempReg (R3) is used first as helper for BIC, then later for building type
1710 // hash.
1711
1712 // movs temp, #1
1713 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVi8)
1714 .addReg(TempReg)
1715 .addReg(ARM::CPSR)
1716 .addImm(1)
1717 .addImm(ARMCC::AL)
1718 .addReg(0));
1719
1720 // mov scratch, target
1721 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr)
1722 .addReg(ScratchReg)
1723 .addReg(AddrReg)
1724 .addImm(ARMCC::AL));
1725
1726 // bics scratch, temp (scratch = scratch & ~temp)
1727 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBIC)
1728 .addReg(ScratchReg)
1729 .addReg(ARM::CPSR)
1730 .addReg(ScratchReg)
1731 .addReg(TempReg)
1732 .addImm(ARMCC::AL)
1733 .addReg(0));
1734
1735 // Load type hash. Thumb1 doesn't support negative offsets, so subtract.
1736 int offset = PrefixNops * 4 + 4;
1737
1738 // subs scratch, #offset
1739 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tSUBi8)
1740 .addReg(ScratchReg)
1741 .addReg(ARM::CPSR)
1742 .addReg(ScratchReg)
1743 .addImm(offset)
1744 .addImm(ARMCC::AL)
1745 .addReg(0));
1746
1747 // ldr scratch, [scratch, #0]
1748 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi)
1749 .addReg(ScratchReg)
1750 .addReg(ScratchReg)
1751 .addImm(0)
1752 .addImm(ARMCC::AL)
1753 .addReg(0));
1754
1755 // Load expected type inline (instead of EOR sequence)
1756 //
1757 // This creates the 32-bit value byte-by-byte in the temp register:
1758 // movs temp, #byte3 (high byte)
1759 // lsls temp, temp, #8
1760 // adds temp, #byte2
1761 // lsls temp, temp, #8
1762 // adds temp, #byte1
1763 // lsls temp, temp, #8
1764 // adds temp, #byte0 (low byte)
1765
1766 uint8_t byte0 = (Type >> 0) & 0xFF;
1767 uint8_t byte1 = (Type >> 8) & 0xFF;
1768 uint8_t byte2 = (Type >> 16) & 0xFF;
1769 uint8_t byte3 = (Type >> 24) & 0xFF;
1770
1771 // movs temp, #byte3 (start with high byte)
1772 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVi8)
1773 .addReg(TempReg)
1774 .addReg(ARM::CPSR)
1775 .addImm(byte3)
1776 .addImm(ARMCC::AL)
1777 .addReg(0));
1778
1779 // lsls temp, temp, #8
1780 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)
1781 .addReg(TempReg)
1782 .addReg(ARM::CPSR)
1783 .addReg(TempReg)
1784 .addImm(8)
1785 .addImm(ARMCC::AL)
1786 .addReg(0));
1787
1788 // adds temp, #byte2
1789 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi8)
1790 .addReg(TempReg)
1791 .addReg(ARM::CPSR)
1792 .addReg(TempReg)
1793 .addImm(byte2)
1794 .addImm(ARMCC::AL)
1795 .addReg(0));
1796
1797 // lsls temp, temp, #8
1798 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)
1799 .addReg(TempReg)
1800 .addReg(ARM::CPSR)
1801 .addReg(TempReg)
1802 .addImm(8)
1803 .addImm(ARMCC::AL)
1804 .addReg(0));
1805
1806 // adds temp, #byte1
1807 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi8)
1808 .addReg(TempReg)
1809 .addReg(ARM::CPSR)
1810 .addReg(TempReg)
1811 .addImm(byte1)
1812 .addImm(ARMCC::AL)
1813 .addReg(0));
1814
1815 // lsls temp, temp, #8
1816 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)
1817 .addReg(TempReg)
1818 .addReg(ARM::CPSR)
1819 .addReg(TempReg)
1820 .addImm(8)
1821 .addImm(ARMCC::AL)
1822 .addReg(0));
1823
1824 // adds temp, #byte0 (low byte)
1825 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi8)
1826 .addReg(TempReg)
1827 .addReg(ARM::CPSR)
1828 .addReg(TempReg)
1829 .addImm(byte0)
1830 .addImm(ARMCC::AL)
1831 .addReg(0));
1832
1833 // cmp scratch, temp
1834 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tCMPr)
1835 .addReg(ScratchReg)
1836 .addReg(TempReg)
1837 .addImm(ARMCC::AL)
1838 .addReg(0));
1839
1840 // Restore registers if spilled (pop in reverse order of push: R2, then R3)
1841 if (NeedSpillR2) {
1842 // pop {r2}
1844 *OutStreamer,
1845 MCInstBuilder(ARM::tPOP).addImm(ARMCC::AL).addReg(0).addReg(ARM::R2));
1846 }
1847
1848 // Restore r3 if spilled
1849 if (NeedSpillR3) {
1850 // pop {r3}
1852 *OutStreamer,
1853 MCInstBuilder(ARM::tPOP).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));
1854 }
1855
1856 // beq .Lpass (branch if types match, i.e., scratch == temp)
1857 MCSymbol *Pass = OutContext.createTempSymbol();
1859 MCInstBuilder(ARM::tBcc)
1861 .addImm(ARMCC::EQ)
1862 .addReg(ARM::CPSR));
1863
1864 // bkpt #0 (trap with encoded diagnostic)
1865 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBKPT).addImm(0));
1866
1867 OutStreamer->emitLabel(Pass);
1868}
1869
1871 Register AddrReg = MI.getOperand(0).getReg();
1872 const int64_t Type = MI.getOperand(1).getImm();
1873
1874 // Get the call instruction that follows this KCFI_CHECK.
1875 assert(std::next(MI.getIterator())->isCall() &&
1876 "KCFI_CHECK not followed by a call instruction");
1877 const MachineInstr &Call = *std::next(MI.getIterator());
1878
1879 // Adjust the offset for patchable-function-prefix.
1880 int64_t PrefixNops = 0;
1881 MI.getMF()
1882 ->getFunction()
1883 .getFnAttribute("patchable-function-prefix")
1884 .getValueAsString()
1885 .getAsInteger(10, PrefixNops);
1886
1887 // Emit the appropriate instruction sequence based on the opcode variant.
1888 switch (MI.getOpcode()) {
1889 case ARM::KCFI_CHECK_ARM:
1890 EmitKCFI_CHECK_ARM32(AddrReg, Type, Call, PrefixNops);
1891 break;
1892 case ARM::KCFI_CHECK_Thumb2:
1893 EmitKCFI_CHECK_Thumb2(AddrReg, Type, Call, PrefixNops);
1894 break;
1895 case ARM::KCFI_CHECK_Thumb1:
1896 EmitKCFI_CHECK_Thumb1(AddrReg, Type, Call, PrefixNops);
1897 break;
1898 default:
1899 llvm_unreachable("Unexpected KCFI_CHECK opcode");
1900 }
1901}
1902
1904 ARM_MC::verifyInstructionPredicates(MI->getOpcode(),
1905 getSubtargetInfo().getFeatureBits());
1906
1907 const DataLayout &DL = getDataLayout();
1908 MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
1909 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
1910
1911 // If we just ended a constant pool, mark it as such.
1912 if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) {
1913 OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
1914 InConstantPool = false;
1915 }
1916
1917 // Emit unwinding stuff for frame-related instructions
1918 if (Subtarget->isTargetEHABICompatible() &&
1919 MI->getFlag(MachineInstr::FrameSetup))
1920 EmitUnwindingInstruction(MI);
1921
1922 // Do any auto-generated pseudo lowerings.
1923 if (MCInst OutInst; lowerPseudoInstExpansion(MI, OutInst)) {
1924 EmitToStreamer(*OutStreamer, OutInst);
1925 return;
1926 }
1927
1928 assert(!convertAddSubFlagsOpcode(MI->getOpcode()) &&
1929 "Pseudo flag setting opcode should be expanded early");
1930
1931 // Check for manual lowerings.
1932 unsigned Opc = MI->getOpcode();
1933 switch (Opc) {
1934 case ARM::t2MOVi32imm: llvm_unreachable("Should be lowered by thumb2it pass");
1935 case ARM::DBG_VALUE: llvm_unreachable("Should be handled by generic printing");
1936 case ARM::KCFI_CHECK_ARM:
1937 case ARM::KCFI_CHECK_Thumb2:
1938 case ARM::KCFI_CHECK_Thumb1:
1940 return;
1941 case ARM::LEApcrel:
1942 case ARM::tLEApcrel:
1943 case ARM::t2LEApcrel: {
1944 // FIXME: Need to also handle globals and externals
1945 MCSymbol *CPISymbol = GetCPISymbol(MI->getOperand(1).getIndex());
1946 EmitToStreamer(*OutStreamer, MCInstBuilder(MI->getOpcode() ==
1947 ARM::t2LEApcrel ? ARM::t2ADR
1948 : (MI->getOpcode() == ARM::tLEApcrel ? ARM::tADR
1949 : ARM::ADR))
1950 .addReg(MI->getOperand(0).getReg())
1952 // Add predicate operands.
1953 .addImm(MI->getOperand(2).getImm())
1954 .addReg(MI->getOperand(3).getReg()));
1955 return;
1956 }
1957 case ARM::LEApcrelJT:
1958 case ARM::tLEApcrelJT:
1959 case ARM::t2LEApcrelJT: {
1960 MCSymbol *JTIPICSymbol =
1961 GetARMJTIPICJumpTableLabel(MI->getOperand(1).getIndex());
1962 EmitToStreamer(*OutStreamer, MCInstBuilder(MI->getOpcode() ==
1963 ARM::t2LEApcrelJT ? ARM::t2ADR
1964 : (MI->getOpcode() == ARM::tLEApcrelJT ? ARM::tADR
1965 : ARM::ADR))
1966 .addReg(MI->getOperand(0).getReg())
1968 // Add predicate operands.
1969 .addImm(MI->getOperand(2).getImm())
1970 .addReg(MI->getOperand(3).getReg()));
1971 return;
1972 }
1973 // Darwin call instructions are just normal call instructions with different
1974 // clobber semantics (they clobber R9).
1975 case ARM::BX_CALL: {
1977 .addReg(ARM::LR)
1978 .addReg(ARM::PC)
1979 // Add predicate operands.
1980 .addImm(ARMCC::AL)
1981 .addReg(0)
1982 // Add 's' bit operand (always reg0 for this)
1983 .addReg(0));
1984
1985 assert(Subtarget->hasV4TOps());
1987 .addReg(MI->getOperand(0).getReg()));
1988 return;
1989 }
1990 case ARM::tBX_CALL: {
1991 if (Subtarget->hasV5TOps())
1992 llvm_unreachable("Expected BLX to be selected for v5t+");
1993
1994 // On ARM v4t, when doing a call from thumb mode, we need to ensure
1995 // that the saved lr has its LSB set correctly (the arch doesn't
1996 // have blx).
1997 // So here we generate a bl to a small jump pad that does bx rN.
1998 // The jump pads are emitted after the function body.
1999
2000 Register TReg = MI->getOperand(0).getReg();
2001 MCSymbol *TRegSym = nullptr;
2002 for (std::pair<unsigned, MCSymbol *> &TIP : ThumbIndirectPads) {
2003 if (TIP.first == TReg) {
2004 TRegSym = TIP.second;
2005 break;
2006 }
2007 }
2008
2009 if (!TRegSym) {
2010 TRegSym = OutContext.createTempSymbol();
2011 ThumbIndirectPads.push_back(std::make_pair(TReg, TRegSym));
2012 }
2013
2014 // Create a link-saving branch to the Reg Indirect Jump Pad.
2016 // Predicate comes first here.
2017 .addImm(ARMCC::AL).addReg(0)
2018 .addExpr(MCSymbolRefExpr::create(TRegSym, OutContext)));
2019 return;
2020 }
2021 case ARM::BMOVPCRX_CALL: {
2023 .addReg(ARM::LR)
2024 .addReg(ARM::PC)
2025 // Add predicate operands.
2026 .addImm(ARMCC::AL)
2027 .addReg(0)
2028 // Add 's' bit operand (always reg0 for this)
2029 .addReg(0));
2030
2032 .addReg(ARM::PC)
2033 .addReg(MI->getOperand(0).getReg())
2034 // Add predicate operands.
2036 .addReg(0)
2037 // Add 's' bit operand (always reg0 for this)
2038 .addReg(0));
2039 return;
2040 }
2041 case ARM::BMOVPCB_CALL: {
2043 .addReg(ARM::LR)
2044 .addReg(ARM::PC)
2045 // Add predicate operands.
2046 .addImm(ARMCC::AL)
2047 .addReg(0)
2048 // Add 's' bit operand (always reg0 for this)
2049 .addReg(0));
2050
2051 const MachineOperand &Op = MI->getOperand(0);
2052 const GlobalValue *GV = Op.getGlobal();
2053 const unsigned TF = Op.getTargetFlags();
2054 MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
2055 const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext);
2057 .addExpr(GVSymExpr)
2058 // Add predicate operands.
2059 .addImm(ARMCC::AL)
2060 .addReg(0));
2061 return;
2062 }
2063 case ARM::MOVi16_ga_pcrel:
2064 case ARM::t2MOVi16_ga_pcrel: {
2065 MCInst TmpInst;
2066 TmpInst.setOpcode(Opc == ARM::MOVi16_ga_pcrel? ARM::MOVi16 : ARM::t2MOVi16);
2067 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
2068
2069 unsigned TF = MI->getOperand(1).getTargetFlags();
2070 const GlobalValue *GV = MI->getOperand(1).getGlobal();
2071 MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
2072 const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext);
2073
2074 MCSymbol *LabelSym =
2075 getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
2076 MI->getOperand(2).getImm(), OutContext);
2077 const MCExpr *LabelSymExpr= MCSymbolRefExpr::create(LabelSym, OutContext);
2078 unsigned PCAdj = (Opc == ARM::MOVi16_ga_pcrel) ? 8 : 4;
2079 const MCExpr *PCRelExpr = ARM::createLower16(
2081 GVSymExpr,
2082 MCBinaryExpr::createAdd(LabelSymExpr,
2084 OutContext),
2085 OutContext),
2086 OutContext);
2087 TmpInst.addOperand(MCOperand::createExpr(PCRelExpr));
2088
2089 // Add predicate operands.
2091 TmpInst.addOperand(MCOperand::createReg(0));
2092 // Add 's' bit operand (always reg0 for this)
2093 TmpInst.addOperand(MCOperand::createReg(0));
2094 EmitToStreamer(*OutStreamer, TmpInst);
2095 return;
2096 }
2097 case ARM::MOVTi16_ga_pcrel:
2098 case ARM::t2MOVTi16_ga_pcrel: {
2099 MCInst TmpInst;
2100 TmpInst.setOpcode(Opc == ARM::MOVTi16_ga_pcrel
2101 ? ARM::MOVTi16 : ARM::t2MOVTi16);
2102 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
2103 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(1).getReg()));
2104
2105 unsigned TF = MI->getOperand(2).getTargetFlags();
2106 const GlobalValue *GV = MI->getOperand(2).getGlobal();
2107 MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
2108 const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext);
2109
2110 MCSymbol *LabelSym =
2111 getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
2112 MI->getOperand(3).getImm(), OutContext);
2113 const MCExpr *LabelSymExpr= MCSymbolRefExpr::create(LabelSym, OutContext);
2114 unsigned PCAdj = (Opc == ARM::MOVTi16_ga_pcrel) ? 8 : 4;
2115 const MCExpr *PCRelExpr = ARM::createUpper16(
2117 GVSymExpr,
2118 MCBinaryExpr::createAdd(LabelSymExpr,
2120 OutContext),
2121 OutContext),
2122 OutContext);
2123 TmpInst.addOperand(MCOperand::createExpr(PCRelExpr));
2124 // Add predicate operands.
2126 TmpInst.addOperand(MCOperand::createReg(0));
2127 // Add 's' bit operand (always reg0 for this)
2128 TmpInst.addOperand(MCOperand::createReg(0));
2129 EmitToStreamer(*OutStreamer, TmpInst);
2130 return;
2131 }
2132 case ARM::t2BFi:
2133 case ARM::t2BFic:
2134 case ARM::t2BFLi:
2135 case ARM::t2BFr:
2136 case ARM::t2BFLr: {
2137 // This is a Branch Future instruction.
2138
2139 const MCExpr *BranchLabel = MCSymbolRefExpr::create(
2140 getBFLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
2141 MI->getOperand(0).getIndex(), OutContext),
2142 OutContext);
2143
2144 auto MCInst = MCInstBuilder(Opc).addExpr(BranchLabel);
2145 if (MI->getOperand(1).isReg()) {
2146 // For BFr/BFLr
2147 MCInst.addReg(MI->getOperand(1).getReg());
2148 } else {
2149 // For BFi/BFLi/BFic
2150 const MCExpr *BranchTarget;
2151 if (MI->getOperand(1).isMBB())
2152 BranchTarget = MCSymbolRefExpr::create(
2153 MI->getOperand(1).getMBB()->getSymbol(), OutContext);
2154 else if (MI->getOperand(1).isGlobal()) {
2155 const GlobalValue *GV = MI->getOperand(1).getGlobal();
2156 BranchTarget = MCSymbolRefExpr::create(
2157 GetARMGVSymbol(GV, MI->getOperand(1).getTargetFlags()), OutContext);
2158 } else if (MI->getOperand(1).isSymbol()) {
2159 BranchTarget = MCSymbolRefExpr::create(
2160 GetExternalSymbolSymbol(MI->getOperand(1).getSymbolName()),
2161 OutContext);
2162 } else
2163 llvm_unreachable("Unhandled operand kind in Branch Future instruction");
2164
2165 MCInst.addExpr(BranchTarget);
2166 }
2167
2168 if (Opc == ARM::t2BFic) {
2169 const MCExpr *ElseLabel = MCSymbolRefExpr::create(
2170 getBFLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
2171 MI->getOperand(2).getIndex(), OutContext),
2172 OutContext);
2173 MCInst.addExpr(ElseLabel);
2174 MCInst.addImm(MI->getOperand(3).getImm());
2175 } else {
2176 MCInst.addImm(MI->getOperand(2).getImm())
2177 .addReg(MI->getOperand(3).getReg());
2178 }
2179
2181 return;
2182 }
2183 case ARM::t2BF_LabelPseudo: {
2184 // This is a pseudo op for a label used by a branch future instruction
2185
2186 // Emit the label.
2187 OutStreamer->emitLabel(getBFLabel(DL.getPrivateGlobalPrefix(),
2189 MI->getOperand(0).getIndex(), OutContext));
2190 return;
2191 }
2192 case ARM::tPICADD: {
2193 // This is a pseudo op for a label + instruction sequence, which looks like:
2194 // LPC0:
2195 // add r0, pc
2196 // This adds the address of LPC0 to r0.
2197
2198 // Emit the label.
2199 OutStreamer->emitLabel(getPICLabel(DL.getPrivateGlobalPrefix(),
2201 MI->getOperand(2).getImm(), OutContext));
2202
2203 // Form and emit the add.
2205 .addReg(MI->getOperand(0).getReg())
2206 .addReg(MI->getOperand(0).getReg())
2207 .addReg(ARM::PC)
2208 // Add predicate operands.
2210 .addReg(0));
2211 return;
2212 }
2213 case ARM::PICADD: {
2214 // This is a pseudo op for a label + instruction sequence, which looks like:
2215 // LPC0:
2216 // add r0, pc, r0
2217 // This adds the address of LPC0 to r0.
2218
2219 // Emit the label.
2220 OutStreamer->emitLabel(getPICLabel(DL.getPrivateGlobalPrefix(),
2222 MI->getOperand(2).getImm(), OutContext));
2223
2224 // Form and emit the add.
2226 .addReg(MI->getOperand(0).getReg())
2227 .addReg(ARM::PC)
2228 .addReg(MI->getOperand(1).getReg())
2229 // Add predicate operands.
2230 .addImm(MI->getOperand(3).getImm())
2231 .addReg(MI->getOperand(4).getReg())
2232 // Add 's' bit operand (always reg0 for this)
2233 .addReg(0));
2234 return;
2235 }
2236 case ARM::PICSTR:
2237 case ARM::PICSTRB:
2238 case ARM::PICSTRH:
2239 case ARM::PICLDR:
2240 case ARM::PICLDRB:
2241 case ARM::PICLDRH:
2242 case ARM::PICLDRSB:
2243 case ARM::PICLDRSH: {
2244 // This is a pseudo op for a label + instruction sequence, which looks like:
2245 // LPC0:
2246 // OP r0, [pc, r0]
2247 // The LCP0 label is referenced by a constant pool entry in order to get
2248 // a PC-relative address at the ldr instruction.
2249
2250 // Emit the label.
2251 OutStreamer->emitLabel(getPICLabel(DL.getPrivateGlobalPrefix(),
2253 MI->getOperand(2).getImm(), OutContext));
2254
2255 // Form and emit the load
2256 unsigned Opcode;
2257 switch (MI->getOpcode()) {
2258 default:
2259 llvm_unreachable("Unexpected opcode!");
2260 case ARM::PICSTR: Opcode = ARM::STRrs; break;
2261 case ARM::PICSTRB: Opcode = ARM::STRBrs; break;
2262 case ARM::PICSTRH: Opcode = ARM::STRH; break;
2263 case ARM::PICLDR: Opcode = ARM::LDRrs; break;
2264 case ARM::PICLDRB: Opcode = ARM::LDRBrs; break;
2265 case ARM::PICLDRH: Opcode = ARM::LDRH; break;
2266 case ARM::PICLDRSB: Opcode = ARM::LDRSB; break;
2267 case ARM::PICLDRSH: Opcode = ARM::LDRSH; break;
2268 }
2270 .addReg(MI->getOperand(0).getReg())
2271 .addReg(ARM::PC)
2272 .addReg(MI->getOperand(1).getReg())
2273 .addImm(0)
2274 // Add predicate operands.
2275 .addImm(MI->getOperand(3).getImm())
2276 .addReg(MI->getOperand(4).getReg()));
2277
2278 return;
2279 }
2280 case ARM::CONSTPOOL_ENTRY: {
2281 if (Subtarget->genExecuteOnly())
2282 llvm_unreachable("execute-only should not generate constant pools");
2283
2284 /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool
2285 /// in the function. The first operand is the ID# for this instruction, the
2286 /// second is the index into the MachineConstantPool that this is, the third
2287 /// is the size in bytes of this constant pool entry.
2288 /// The required alignment is specified on the basic block holding this MI.
2289 unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
2290 unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
2291
2292 // If this is the first entry of the pool, mark it.
2293 if (!InConstantPool) {
2294 OutStreamer->emitDataRegion(MCDR_DataRegion);
2295 InConstantPool = true;
2296 }
2297
2298 OutStreamer->emitLabel(GetCPISymbol(LabelId));
2299
2300 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
2301 if (MCPE.isMachineConstantPoolEntry())
2303 else
2305 return;
2306 }
2307 case ARM::JUMPTABLE_ADDRS:
2309 return;
2310 case ARM::JUMPTABLE_INSTS:
2312 return;
2313 case ARM::JUMPTABLE_TBB:
2314 case ARM::JUMPTABLE_TBH:
2315 emitJumpTableTBInst(MI, MI->getOpcode() == ARM::JUMPTABLE_TBB ? 1 : 2);
2316 return;
2317 case ARM::t2BR_JT: {
2319 .addReg(ARM::PC)
2320 .addReg(MI->getOperand(0).getReg())
2321 // Add predicate operands.
2323 .addReg(0));
2324 return;
2325 }
2326 case ARM::t2TBB_JT:
2327 case ARM::t2TBH_JT: {
2328 unsigned Opc = MI->getOpcode() == ARM::t2TBB_JT ? ARM::t2TBB : ARM::t2TBH;
2329 // Lower and emit the PC label, then the instruction itself.
2330 OutStreamer->emitLabel(GetCPISymbol(MI->getOperand(3).getImm()));
2332 .addReg(MI->getOperand(0).getReg())
2333 .addReg(MI->getOperand(1).getReg())
2334 // Add predicate operands.
2336 .addReg(0));
2337 return;
2338 }
2339 case ARM::tTBB_JT:
2340 case ARM::tTBH_JT: {
2341
2342 bool Is8Bit = MI->getOpcode() == ARM::tTBB_JT;
2343 Register Base = MI->getOperand(0).getReg();
2344 Register Idx = MI->getOperand(1).getReg();
2345 assert(MI->getOperand(1).isKill() && "We need the index register as scratch!");
2346
2347 // Multiply up idx if necessary.
2348 if (!Is8Bit)
2350 .addReg(Idx)
2351 .addReg(ARM::CPSR)
2352 .addReg(Idx)
2353 .addImm(1)
2354 // Add predicate operands.
2355 .addImm(ARMCC::AL)
2356 .addReg(0));
2357
2358 if (Base == ARM::PC) {
2359 // TBB [base, idx] =
2360 // ADDS idx, idx, base
2361 // LDRB idx, [idx, #4] ; or LDRH if TBH
2362 // LSLS idx, #1
2363 // ADDS pc, pc, idx
2364
2365 // When using PC as the base, it's important that there is no padding
2366 // between the last ADDS and the start of the jump table. The jump table
2367 // is 4-byte aligned, so we ensure we're 4 byte aligned here too.
2368 //
2369 // FIXME: Ideally we could vary the LDRB index based on the padding
2370 // between the sequence and jump table, however that relies on MCExprs
2371 // for load indexes which are currently not supported.
2372 OutStreamer->emitCodeAlignment(Align(4), &getSubtargetInfo());
2374 .addReg(Idx)
2375 .addReg(Idx)
2376 .addReg(Base)
2377 // Add predicate operands.
2378 .addImm(ARMCC::AL)
2379 .addReg(0));
2380
2381 unsigned Opc = Is8Bit ? ARM::tLDRBi : ARM::tLDRHi;
2383 .addReg(Idx)
2384 .addReg(Idx)
2385 .addImm(Is8Bit ? 4 : 2)
2386 // Add predicate operands.
2387 .addImm(ARMCC::AL)
2388 .addReg(0));
2389 } else {
2390 // TBB [base, idx] =
2391 // LDRB idx, [base, idx] ; or LDRH if TBH
2392 // LSLS idx, #1
2393 // ADDS pc, pc, idx
2394
2395 unsigned Opc = Is8Bit ? ARM::tLDRBr : ARM::tLDRHr;
2397 .addReg(Idx)
2398 .addReg(Base)
2399 .addReg(Idx)
2400 // Add predicate operands.
2401 .addImm(ARMCC::AL)
2402 .addReg(0));
2403 }
2404
2406 .addReg(Idx)
2407 .addReg(ARM::CPSR)
2408 .addReg(Idx)
2409 .addImm(1)
2410 // Add predicate operands.
2411 .addImm(ARMCC::AL)
2412 .addReg(0));
2413
2414 OutStreamer->emitLabel(GetCPISymbol(MI->getOperand(3).getImm()));
2416 .addReg(ARM::PC)
2417 .addReg(ARM::PC)
2418 .addReg(Idx)
2419 // Add predicate operands.
2420 .addImm(ARMCC::AL)
2421 .addReg(0));
2422 return;
2423 }
2424 case ARM::tBR_JTr:
2425 case ARM::BR_JTr: {
2426 // mov pc, target
2427 MCInst TmpInst;
2428 unsigned Opc = MI->getOpcode() == ARM::BR_JTr ?
2429 ARM::MOVr : ARM::tMOVr;
2430 TmpInst.setOpcode(Opc);
2431 TmpInst.addOperand(MCOperand::createReg(ARM::PC));
2432 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
2433 // Add predicate operands.
2435 TmpInst.addOperand(MCOperand::createReg(0));
2436 // Add 's' bit operand (always reg0 for this)
2437 if (Opc == ARM::MOVr)
2438 TmpInst.addOperand(MCOperand::createReg(0));
2439 EmitToStreamer(*OutStreamer, TmpInst);
2440 return;
2441 }
2442 case ARM::BR_JTm_i12: {
2443 // ldr pc, target
2444 MCInst TmpInst;
2445 TmpInst.setOpcode(ARM::LDRi12);
2446 TmpInst.addOperand(MCOperand::createReg(ARM::PC));
2447 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
2448 TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm()));
2449 // Add predicate operands.
2451 TmpInst.addOperand(MCOperand::createReg(0));
2452 EmitToStreamer(*OutStreamer, TmpInst);
2453 return;
2454 }
2455 case ARM::BR_JTm_rs: {
2456 // ldr pc, target
2457 MCInst TmpInst;
2458 TmpInst.setOpcode(ARM::LDRrs);
2459 TmpInst.addOperand(MCOperand::createReg(ARM::PC));
2460 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
2461 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(1).getReg()));
2462 TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm()));
2463 // Add predicate operands.
2465 TmpInst.addOperand(MCOperand::createReg(0));
2466 EmitToStreamer(*OutStreamer, TmpInst);
2467 return;
2468 }
2469 case ARM::BR_JTadd: {
2470 // add pc, target, idx
2472 .addReg(ARM::PC)
2473 .addReg(MI->getOperand(0).getReg())
2474 .addReg(MI->getOperand(1).getReg())
2475 // Add predicate operands.
2477 .addReg(0)
2478 // Add 's' bit operand (always reg0 for this)
2479 .addReg(0));
2480 return;
2481 }
2482 case ARM::SPACE:
2483 OutStreamer->emitZeros(MI->getOperand(1).getImm());
2484 return;
2485 case ARM::TRAP: {
2486 // Non-Darwin binutils don't yet support the "trap" mnemonic.
2487 // FIXME: Remove this special case when they do.
2488 if (!Subtarget->isTargetMachO()) {
2489 uint32_t Val = 0xe7ffdefeUL;
2490 OutStreamer->AddComment("trap");
2491 ATS.emitInst(Val);
2492 return;
2493 }
2494 break;
2495 }
2496 case ARM::tTRAP: {
2497 // Non-Darwin binutils don't yet support the "trap" mnemonic.
2498 // FIXME: Remove this special case when they do.
2499 if (!Subtarget->isTargetMachO()) {
2500 uint16_t Val = 0xdefe;
2501 OutStreamer->AddComment("trap");
2502 ATS.emitInst(Val, 'n');
2503 return;
2504 }
2505 break;
2506 }
2507 case ARM::t2Int_eh_sjlj_setjmp:
2508 case ARM::t2Int_eh_sjlj_setjmp_nofp:
2509 case ARM::tInt_eh_sjlj_setjmp: {
2510 // Two incoming args: GPR:$src, GPR:$val
2511 // mov $val, pc
2512 // adds $val, #7
2513 // str $val, [$src, #4]
2514 // movs r0, #0
2515 // b LSJLJEH
2516 // movs r0, #1
2517 // LSJLJEH:
2518 Register SrcReg = MI->getOperand(0).getReg();
2519 Register ValReg = MI->getOperand(1).getReg();
2520 MCSymbol *Label = OutContext.createTempSymbol("SJLJEH");
2521 OutStreamer->AddComment("eh_setjmp begin");
2523 .addReg(ValReg)
2524 .addReg(ARM::PC)
2525 // Predicate.
2526 .addImm(ARMCC::AL)
2527 .addReg(0));
2528
2530 .addReg(ValReg)
2531 // 's' bit operand
2532 .addReg(ARM::CPSR)
2533 .addReg(ValReg)
2534 .addImm(7)
2535 // Predicate.
2536 .addImm(ARMCC::AL)
2537 .addReg(0));
2538
2540 .addReg(ValReg)
2541 .addReg(SrcReg)
2542 // The offset immediate is #4. The operand value is scaled by 4 for the
2543 // tSTR instruction.
2544 .addImm(1)
2545 // Predicate.
2546 .addImm(ARMCC::AL)
2547 .addReg(0));
2548
2550 .addReg(ARM::R0)
2551 .addReg(ARM::CPSR)
2552 .addImm(0)
2553 // Predicate.
2554 .addImm(ARMCC::AL)
2555 .addReg(0));
2556
2557 const MCExpr *SymbolExpr = MCSymbolRefExpr::create(Label, OutContext);
2559 .addExpr(SymbolExpr)
2560 .addImm(ARMCC::AL)
2561 .addReg(0));
2562
2563 OutStreamer->AddComment("eh_setjmp end");
2565 .addReg(ARM::R0)
2566 .addReg(ARM::CPSR)
2567 .addImm(1)
2568 // Predicate.
2569 .addImm(ARMCC::AL)
2570 .addReg(0));
2571
2572 OutStreamer->emitLabel(Label);
2573 return;
2574 }
2575
2576 case ARM::Int_eh_sjlj_setjmp_nofp:
2577 case ARM::Int_eh_sjlj_setjmp: {
2578 // Two incoming args: GPR:$src, GPR:$val
2579 // add $val, pc, #8
2580 // str $val, [$src, #+4]
2581 // mov r0, #0
2582 // add pc, pc, #0
2583 // mov r0, #1
2584 Register SrcReg = MI->getOperand(0).getReg();
2585 Register ValReg = MI->getOperand(1).getReg();
2586
2587 OutStreamer->AddComment("eh_setjmp begin");
2589 .addReg(ValReg)
2590 .addReg(ARM::PC)
2591 .addImm(8)
2592 // Predicate.
2593 .addImm(ARMCC::AL)
2594 .addReg(0)
2595 // 's' bit operand (always reg0 for this).
2596 .addReg(0));
2597
2599 .addReg(ValReg)
2600 .addReg(SrcReg)
2601 .addImm(4)
2602 // Predicate.
2603 .addImm(ARMCC::AL)
2604 .addReg(0));
2605
2607 .addReg(ARM::R0)
2608 .addImm(0)
2609 // Predicate.
2610 .addImm(ARMCC::AL)
2611 .addReg(0)
2612 // 's' bit operand (always reg0 for this).
2613 .addReg(0));
2614
2616 .addReg(ARM::PC)
2617 .addReg(ARM::PC)
2618 .addImm(0)
2619 // Predicate.
2620 .addImm(ARMCC::AL)
2621 .addReg(0)
2622 // 's' bit operand (always reg0 for this).
2623 .addReg(0));
2624
2625 OutStreamer->AddComment("eh_setjmp end");
2627 .addReg(ARM::R0)
2628 .addImm(1)
2629 // Predicate.
2630 .addImm(ARMCC::AL)
2631 .addReg(0)
2632 // 's' bit operand (always reg0 for this).
2633 .addReg(0));
2634 return;
2635 }
2636 case ARM::Int_eh_sjlj_longjmp: {
2637 // ldr sp, [$src, #8]
2638 // ldr $scratch, [$src, #4]
2639 // ldr r7, [$src]
2640 // bx $scratch
2641 Register SrcReg = MI->getOperand(0).getReg();
2642 Register ScratchReg = MI->getOperand(1).getReg();
2644 .addReg(ARM::SP)
2645 .addReg(SrcReg)
2646 .addImm(8)
2647 // Predicate.
2648 .addImm(ARMCC::AL)
2649 .addReg(0));
2650
2652 .addReg(ScratchReg)
2653 .addReg(SrcReg)
2654 .addImm(4)
2655 // Predicate.
2656 .addImm(ARMCC::AL)
2657 .addReg(0));
2658
2659 const MachineFunction &MF = *MI->getParent()->getParent();
2660 const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>();
2661
2662 if (STI.isTargetDarwin() || STI.isTargetWindows()) {
2663 // These platforms always use the same frame register
2665 .addReg(STI.getFramePointerReg())
2666 .addReg(SrcReg)
2667 .addImm(0)
2668 // Predicate.
2670 .addReg(0));
2671 } else {
2672 // If the calling code might use either R7 or R11 as
2673 // frame pointer register, restore it into both.
2675 .addReg(ARM::R7)
2676 .addReg(SrcReg)
2677 .addImm(0)
2678 // Predicate.
2679 .addImm(ARMCC::AL)
2680 .addReg(0));
2682 .addReg(ARM::R11)
2683 .addReg(SrcReg)
2684 .addImm(0)
2685 // Predicate.
2686 .addImm(ARMCC::AL)
2687 .addReg(0));
2688 }
2689
2690 assert(Subtarget->hasV4TOps());
2692 .addReg(ScratchReg)
2693 // Predicate.
2694 .addImm(ARMCC::AL)
2695 .addReg(0));
2696 return;
2697 }
2698 case ARM::tInt_eh_sjlj_longjmp: {
2699 // ldr $scratch, [$src, #8]
2700 // mov sp, $scratch
2701 // ldr $scratch, [$src, #4]
2702 // ldr r7, [$src]
2703 // bx $scratch
2704 Register SrcReg = MI->getOperand(0).getReg();
2705 Register ScratchReg = MI->getOperand(1).getReg();
2706
2707 const MachineFunction &MF = *MI->getParent()->getParent();
2708 const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>();
2709
2711 .addReg(ScratchReg)
2712 .addReg(SrcReg)
2713 // The offset immediate is #8. The operand value is scaled by 4 for the
2714 // tLDR instruction.
2715 .addImm(2)
2716 // Predicate.
2717 .addImm(ARMCC::AL)
2718 .addReg(0));
2719
2721 .addReg(ARM::SP)
2722 .addReg(ScratchReg)
2723 // Predicate.
2724 .addImm(ARMCC::AL)
2725 .addReg(0));
2726
2728 .addReg(ScratchReg)
2729 .addReg(SrcReg)
2730 .addImm(1)
2731 // Predicate.
2732 .addImm(ARMCC::AL)
2733 .addReg(0));
2734
2735 if (STI.isTargetDarwin() || STI.isTargetWindows()) {
2736 // These platforms always use the same frame register
2738 .addReg(STI.getFramePointerReg())
2739 .addReg(SrcReg)
2740 .addImm(0)
2741 // Predicate.
2743 .addReg(0));
2744 } else {
2745 // If the calling code might use either R7 or R11 as
2746 // frame pointer register, restore it into both.
2748 .addReg(ARM::R7)
2749 .addReg(SrcReg)
2750 .addImm(0)
2751 // Predicate.
2752 .addImm(ARMCC::AL)
2753 .addReg(0));
2755 .addReg(ARM::R11)
2756 .addReg(SrcReg)
2757 .addImm(0)
2758 // Predicate.
2759 .addImm(ARMCC::AL)
2760 .addReg(0));
2761 }
2762
2764 .addReg(ScratchReg)
2765 // Predicate.
2766 .addImm(ARMCC::AL)
2767 .addReg(0));
2768 return;
2769 }
2770 case ARM::tInt_WIN_eh_sjlj_longjmp: {
2771 // ldr.w r11, [$src, #0]
2772 // ldr.w sp, [$src, #8]
2773 // ldr.w pc, [$src, #4]
2774
2775 Register SrcReg = MI->getOperand(0).getReg();
2776
2778 .addReg(ARM::R11)
2779 .addReg(SrcReg)
2780 .addImm(0)
2781 // Predicate
2782 .addImm(ARMCC::AL)
2783 .addReg(0));
2785 .addReg(ARM::SP)
2786 .addReg(SrcReg)
2787 .addImm(8)
2788 // Predicate
2789 .addImm(ARMCC::AL)
2790 .addReg(0));
2792 .addReg(ARM::PC)
2793 .addReg(SrcReg)
2794 .addImm(4)
2795 // Predicate
2796 .addImm(ARMCC::AL)
2797 .addReg(0));
2798 return;
2799 }
2800 case ARM::PATCHABLE_FUNCTION_ENTER:
2802 return;
2803 case ARM::PATCHABLE_FUNCTION_EXIT:
2805 return;
2806 case ARM::PATCHABLE_TAIL_CALL:
2808 return;
2809 case ARM::SpeculationBarrierISBDSBEndBB: {
2810 // Print DSB SYS + ISB
2811 MCInst TmpInstDSB;
2812 TmpInstDSB.setOpcode(ARM::DSB);
2813 TmpInstDSB.addOperand(MCOperand::createImm(0xf));
2814 EmitToStreamer(*OutStreamer, TmpInstDSB);
2815 MCInst TmpInstISB;
2816 TmpInstISB.setOpcode(ARM::ISB);
2817 TmpInstISB.addOperand(MCOperand::createImm(0xf));
2818 EmitToStreamer(*OutStreamer, TmpInstISB);
2819 return;
2820 }
2821 case ARM::t2SpeculationBarrierISBDSBEndBB: {
2822 // Print DSB SYS + ISB
2823 MCInst TmpInstDSB;
2824 TmpInstDSB.setOpcode(ARM::t2DSB);
2825 TmpInstDSB.addOperand(MCOperand::createImm(0xf));
2827 TmpInstDSB.addOperand(MCOperand::createReg(0));
2828 EmitToStreamer(*OutStreamer, TmpInstDSB);
2829 MCInst TmpInstISB;
2830 TmpInstISB.setOpcode(ARM::t2ISB);
2831 TmpInstISB.addOperand(MCOperand::createImm(0xf));
2833 TmpInstISB.addOperand(MCOperand::createReg(0));
2834 EmitToStreamer(*OutStreamer, TmpInstISB);
2835 return;
2836 }
2837 case ARM::SpeculationBarrierSBEndBB: {
2838 // Print SB
2839 MCInst TmpInstSB;
2840 TmpInstSB.setOpcode(ARM::SB);
2841 EmitToStreamer(*OutStreamer, TmpInstSB);
2842 return;
2843 }
2844 case ARM::t2SpeculationBarrierSBEndBB: {
2845 // Print SB
2846 MCInst TmpInstSB;
2847 TmpInstSB.setOpcode(ARM::t2SB);
2848 EmitToStreamer(*OutStreamer, TmpInstSB);
2849 return;
2850 }
2851
2852 case ARM::SEH_StackAlloc:
2853 ATS.emitARMWinCFIAllocStack(MI->getOperand(0).getImm(),
2854 MI->getOperand(1).getImm());
2855 return;
2856
2857 case ARM::SEH_SaveRegs:
2858 case ARM::SEH_SaveRegs_Ret:
2859 ATS.emitARMWinCFISaveRegMask(MI->getOperand(0).getImm(),
2860 MI->getOperand(1).getImm());
2861 return;
2862
2863 case ARM::SEH_SaveSP:
2864 ATS.emitARMWinCFISaveSP(MI->getOperand(0).getImm());
2865 return;
2866
2867 case ARM::SEH_SaveFRegs:
2868 ATS.emitARMWinCFISaveFRegs(MI->getOperand(0).getImm(),
2869 MI->getOperand(1).getImm());
2870 return;
2871
2872 case ARM::SEH_SaveLR:
2873 ATS.emitARMWinCFISaveLR(MI->getOperand(0).getImm());
2874 return;
2875
2876 case ARM::SEH_Nop:
2877 case ARM::SEH_Nop_Ret:
2878 ATS.emitARMWinCFINop(MI->getOperand(0).getImm());
2879 return;
2880
2881 case ARM::SEH_PrologEnd:
2882 ATS.emitARMWinCFIPrologEnd(/*Fragment=*/false);
2883 return;
2884
2885 case ARM::SEH_EpilogStart:
2887 return;
2888
2889 case ARM::SEH_EpilogEnd:
2891 return;
2892 }
2893
2894 MCInst TmpInst;
2895 LowerARMMachineInstrToMCInst(MI, TmpInst, *this);
2896
2897 EmitToStreamer(*OutStreamer, TmpInst);
2898}
2899
2900char ARMAsmPrinter::ID = 0;
2901
2902INITIALIZE_PASS(ARMAsmPrinter, "arm-asm-printer", "ARM Assembly Printer", false,
2903 false)
2904
2905//===----------------------------------------------------------------------===//
2906// Target Registry Stuff
2907//===----------------------------------------------------------------------===//
2908
2909// Force static initialization.
2910extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
2911LLVMInitializeARMAsmPrinter() {
2916}
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:55
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)
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:219
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:33
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:19
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:477
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,...