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), AFI(nullptr), MCP(nullptr),
55 InConstantPool(false), OptimizationGoals(-1) {}
56
58 return static_cast<const ARMBaseTargetMachine &>(TM);
59}
60
62 // Make sure to terminate any constant pools that were at the end
63 // of the function.
64 if (!InConstantPool)
65 return;
66 InConstantPool = false;
67 OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
68}
69
71 auto &TS =
72 static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());
73 if (AFI->isThumbFunction()) {
74 TS.emitCode16();
75 TS.emitThumbFunc(CurrentFnSym);
76 } else {
77 TS.emitCode32();
78 }
79
80 // Emit symbol for CMSE non-secure entry point
81 if (AFI->isCmseNSEntryFunction()) {
82 MCSymbol *S =
83 OutContext.getOrCreateSymbol("__acle_se_" + CurrentFnSym->getName());
84 emitLinkage(&MF->getFunction(), S);
85 OutStreamer->emitSymbolAttribute(S, MCSA_ELF_TypeFunction);
86 OutStreamer->emitLabel(S);
87 }
89}
90
93 assert(Size && "C++ constructor pointer had zero size!");
94
96 assert(GV && "C++ constructor pointer was not a GlobalValue!");
97
99 GetARMGVSymbol(GV, ARMII::MO_NO_FLAG),
100 (TM.getTargetTriple().isOSBinFormatELF() ? ARM::S_TARGET1 : ARM::S_None),
101 OutContext);
102
103 OutStreamer->emitValue(E, Size);
104}
105
107 if (PromotedGlobals.count(GV))
108 // The global was promoted into a constant pool. It should not be emitted.
109 return;
111}
112
113/// runOnMachineFunction - This uses the emitInstruction()
114/// method to print assembly for each instruction.
115///
117 AFI = MF.getInfo<ARMFunctionInfo>();
118 MCP = MF.getConstantPool();
119
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 (TM.getTargetTriple().isOSBinFormatCOFF()) {
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 assert(!MF->getSubtarget<ARMSubtarget>().genExecuteOnly() &&
263 "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 (TT.isTargetAEABI() || TT.isTargetGNUAEABI() || TT.isTargetMuslAEABI()))
600 OptimizationGoals = -1;
601
603}
604
605//===----------------------------------------------------------------------===//
606// Helper routines for emitStartOfAsmFile() and emitEndOfAsmFile()
607// FIXME:
608// The following seem like one-off assembler flags, but they actually need
609// to appear in the .ARM.attributes section in ELF.
610// Instead of subclassing the MCELFStreamer, we do the work here.
611
612// Returns true if all function definitions have the same function attribute
613// value. It also returns true when the module has no functions.
616 return !any_of(M, [&](const Function &F) {
617 if (F.isDeclaration())
618 return false;
619 return F.getFnAttribute(Attr).getValueAsString() != Value;
620 });
621}
622// Returns true if all functions definitions have the same denormal mode.
623// It also returns true when the module has no functions.
626 return !any_of(M, [&](const Function &F) {
627 if (F.isDeclaration())
628 return false;
629 StringRef AttrVal = F.getFnAttribute(Attr).getValueAsString();
630 return parseDenormalFPAttribute(AttrVal) != Value;
631 });
632}
633
634// Returns true if all functions have different denormal modes.
636 auto F = M.functions().begin();
637 auto E = M.functions().end();
638 if (F == E)
639 return false;
640 DenormalMode Value = F->getDenormalModeRaw();
641 ++F;
642 return std::any_of(F, E, [&](const Function &F) {
643 return !F.isDeclaration() && F.getDenormalModeRaw() != Value;
644 });
645}
646
647void ARMAsmPrinter::emitAttributes() {
648 MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
649 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
650
652
653 ATS.switchVendor("aeabi");
654
655 // Compute ARM ELF Attributes based on the default subtarget that
656 // we'd have constructed. The existing ARM behavior isn't LTO clean
657 // anyhow.
658 // FIXME: For ifunc related functions we could iterate over and look
659 // for a feature string that doesn't match the default one.
660 const Triple &TT = TM.getTargetTriple();
661 StringRef CPU = TM.getTargetCPU();
662 StringRef FS = TM.getTargetFeatureString();
663 std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU);
664 if (!FS.empty()) {
665 if (!ArchFS.empty())
666 ArchFS = (Twine(ArchFS) + "," + FS).str();
667 else
668 ArchFS = std::string(FS);
669 }
670 const ARMBaseTargetMachine &ATM =
671 static_cast<const ARMBaseTargetMachine &>(TM);
672 const ARMSubtarget STI(TT, std::string(CPU), ArchFS, ATM,
673 ATM.isLittleEndian());
674
675 // Emit build attributes for the available hardware.
676 ATS.emitTargetAttributes(STI);
677
678 // RW data addressing.
679 if (isPositionIndependent()) {
682 } else if (STI.isRWPI()) {
683 // RWPI specific attributes.
686 }
687
688 // RO data addressing.
689 if (isPositionIndependent() || STI.isROPI()) {
692 }
693
694 // GOT use.
695 if (isPositionIndependent()) {
698 } else {
701 }
702
703 // Set FP Denormals.
704 if (checkDenormalAttributeConsistency(*MMI->getModule(), "denormal-fp-math",
708 else if (checkDenormalAttributeConsistency(*MMI->getModule(),
709 "denormal-fp-math",
713 else if (checkDenormalAttributeInconsistency(*MMI->getModule()) ||
715 *MMI->getModule(), "denormal-fp-math", DenormalMode::getIEEE()))
718 else {
719 if (!STI.hasVFP2Base()) {
720 // When the target doesn't have an FPU (by design or
721 // intention), the assumptions made on the software support
722 // mirror that of the equivalent hardware support *if it
723 // existed*. For v7 and better we indicate that denormals are
724 // flushed preserving sign, and for V6 we indicate that
725 // denormals are flushed to positive zero.
726 if (STI.hasV7Ops())
729 } else if (STI.hasVFP3Base()) {
730 // In VFPv4, VFPv4U, VFPv3, or VFPv3U, it is preserved. That is,
731 // the sign bit of the zero matches the sign bit of the input or
732 // result that is being flushed to zero.
735 }
736 // For VFPv2 implementations it is implementation defined as
737 // to whether denormals are flushed to positive zero or to
738 // whatever the sign of zero is (ARM v7AR ARM 2.7.5). Historically
739 // LLVM has chosen to flush this to positive zero (most likely for
740 // GCC compatibility), so that's the chosen value here (the
741 // absence of its emission implies zero).
742 }
743
744 // Set FP exceptions and rounding
745 if (checkFunctionsAttributeConsistency(*MMI->getModule(),
746 "no-trapping-math", "true") ||
747 TM.Options.NoTrappingFPMath)
750 else {
752
753 // If the user has permitted this code to choose the IEEE 754
754 // rounding at run-time, emit the rounding attribute.
755 if (TM.Options.HonorSignDependentRoundingFPMathOption)
757 }
758
759 // TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath is the
760 // equivalent of GCC's -ffinite-math-only flag.
761 if (TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath)
764 else
767
768 // FIXME: add more flags to ARMBuildAttributes.h
769 // 8-bytes alignment stuff.
772
773 // Hard float. Use both S and D registers and conform to AAPCS-VFP.
774 if (getTM().isAAPCS_ABI() && TM.Options.FloatABIType == FloatABI::Hard)
776
777 // FIXME: To support emitting this build attribute as GCC does, the
778 // -mfp16-format option and associated plumbing must be
779 // supported. For now the __fp16 type is exposed by default, so this
780 // attribute should be emitted with value 1.
783
784 if (const Module *SourceModule = MMI->getModule()) {
785 // ABI_PCS_wchar_t to indicate wchar_t width
786 // FIXME: There is no way to emit value 0 (wchar_t prohibited).
787 if (auto WCharWidthValue = mdconst::extract_or_null<ConstantInt>(
788 SourceModule->getModuleFlag("wchar_size"))) {
789 int WCharWidth = WCharWidthValue->getZExtValue();
790 assert((WCharWidth == 2 || WCharWidth == 4) &&
791 "wchar_t width must be 2 or 4 bytes");
793 }
794
795 // ABI_enum_size to indicate enum width
796 // FIXME: There is no way to emit value 0 (enums prohibited) or value 3
797 // (all enums contain a value needing 32 bits to encode).
798 if (auto EnumWidthValue = mdconst::extract_or_null<ConstantInt>(
799 SourceModule->getModuleFlag("min_enum_size"))) {
800 int EnumWidth = EnumWidthValue->getZExtValue();
801 assert((EnumWidth == 1 || EnumWidth == 4) &&
802 "Minimum enum width must be 1 or 4 bytes");
803 int EnumBuildAttr = EnumWidth == 1 ? 1 : 2;
805 }
806
808 SourceModule->getModuleFlag("sign-return-address"));
809 if (PACValue && PACValue->isOne()) {
810 // If "+pacbti" is used as an architecture extension,
811 // Tag_PAC_extension is emitted in
812 // ARMTargetStreamer::emitTargetAttributes().
813 if (!STI.hasPACBTI()) {
816 }
818 }
819
821 SourceModule->getModuleFlag("branch-target-enforcement"));
822 if (BTIValue && !BTIValue->isZero()) {
823 // If "+pacbti" is used as an architecture extension,
824 // Tag_BTI_extension is emitted in
825 // ARMTargetStreamer::emitTargetAttributes().
826 if (!STI.hasPACBTI()) {
829 }
831 }
832 }
833
834 // We currently do not support using R9 as the TLS pointer.
835 if (STI.isRWPI())
838 else if (STI.isR9Reserved())
841 else
844}
845
846//===----------------------------------------------------------------------===//
847
848static MCSymbol *getBFLabel(StringRef Prefix, unsigned FunctionNumber,
849 unsigned LabelId, MCContext &Ctx) {
850
851 MCSymbol *Label = Ctx.getOrCreateSymbol(Twine(Prefix)
852 + "BF" + Twine(FunctionNumber) + "_" + Twine(LabelId));
853 return Label;
854}
855
856static MCSymbol *getPICLabel(StringRef Prefix, unsigned FunctionNumber,
857 unsigned LabelId, MCContext &Ctx) {
858
859 MCSymbol *Label = Ctx.getOrCreateSymbol(Twine(Prefix)
860 + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId));
861 return Label;
862}
863
865 switch (Modifier) {
867 return ARM::S_None;
868 case ARMCP::TLSGD:
869 return ARM::S_TLSGD;
870 case ARMCP::TPOFF:
871 return ARM::S_TPOFF;
872 case ARMCP::GOTTPOFF:
873 return ARM::S_GOTTPOFF;
874 case ARMCP::SBREL:
875 return ARM::S_SBREL;
876 case ARMCP::GOT_PREL:
877 return ARM::S_GOT_PREL;
878 case ARMCP::SECREL:
879 return ARM::S_COFF_SECREL;
880 }
881 llvm_unreachable("Invalid ARMCPModifier!");
882}
883
884MCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV,
885 unsigned char TargetFlags) {
886 const Triple &TT = TM.getTargetTriple();
887 if (TT.isOSBinFormatMachO()) {
888 bool IsIndirect =
889 (TargetFlags & ARMII::MO_NONLAZY) && getTM().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 (TT.isOSBinFormatCOFF()) {
907 assert(TT.isOSWindows() && "Windows is the only supported COFF target");
908
909 bool IsIndirect =
910 (TargetFlags & (ARMII::MO_DLLIMPORT | ARMII::MO_COFFSTUB));
911 if (!IsIndirect)
912 return getSymbol(GV);
913
914 SmallString<128> Name;
915 if (TargetFlags & ARMII::MO_DLLIMPORT)
916 Name = "__imp_";
917 else if (TargetFlags & ARMII::MO_COFFSTUB)
918 Name = ".refptr.";
919 getNameWithPrefix(Name, GV);
920
921 MCSymbol *MCSym = OutContext.getOrCreateSymbol(Name);
922
923 if (TargetFlags & ARMII::MO_COFFSTUB) {
924 MachineModuleInfoCOFF &MMICOFF =
925 MMI->getObjFileInfo<MachineModuleInfoCOFF>();
927 MMICOFF.getGVStubEntry(MCSym);
928
929 if (!StubSym.getPointer())
931 }
932
933 return MCSym;
934 } else if (TT.isOSBinFormatELF()) {
935 return getSymbolPreferLocal(*GV);
936 }
937 llvm_unreachable("unexpected target");
938}
939
942 const DataLayout &DL = getDataLayout();
943 int Size = DL.getTypeAllocSize(MCPV->getType());
944
945 ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);
946
947 if (ACPV->isPromotedGlobal()) {
948 // This constant pool entry is actually a global whose storage has been
949 // promoted into the constant pool. This global may be referenced still
950 // by debug information, and due to the way AsmPrinter is set up, the debug
951 // info is immutable by the time we decide to promote globals to constant
952 // pools. Because of this, we need to ensure we emit a symbol for the global
953 // with private linkage (the default) so debug info can refer to it.
954 //
955 // However, if this global is promoted into several functions we must ensure
956 // we don't try and emit duplicate symbols!
957 auto *ACPC = cast<ARMConstantPoolConstant>(ACPV);
958 for (const auto *GV : ACPC->promotedGlobals()) {
959 if (!EmittedPromotedGlobalLabels.count(GV)) {
960 MCSymbol *GVSym = getSymbol(GV);
961 OutStreamer->emitLabel(GVSym);
962 EmittedPromotedGlobalLabels.insert(GV);
963 }
964 }
965 return emitGlobalConstant(DL, ACPC->getPromotedGlobalInit());
966 }
967
968 MCSymbol *MCSym;
969 if (ACPV->isLSDA()) {
970 MCSym = getMBBExceptionSym(MF->front());
971 } else if (ACPV->isBlockAddress()) {
972 const BlockAddress *BA =
973 cast<ARMConstantPoolConstant>(ACPV)->getBlockAddress();
974 MCSym = GetBlockAddressSymbol(BA);
975 } else if (ACPV->isGlobalValue()) {
976 const GlobalValue *GV = cast<ARMConstantPoolConstant>(ACPV)->getGV();
977
978 // On Darwin, const-pool entries may get the "FOO$non_lazy_ptr" mangling, so
979 // flag the global as MO_NONLAZY.
980 unsigned char TF =
981 TM.getTargetTriple().isOSBinFormatMachO() ? 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 const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();
1051 if (isPositionIndependent() || STI.isROPI())
1052 Expr = MCBinaryExpr::createSub(Expr, MCSymbolRefExpr::create(JTISymbol,
1053 OutContext),
1054 OutContext);
1055 // If we're generating a table of Thumb addresses in static relocation
1056 // model, we need to add one to keep interworking correctly.
1057 else if (AFI->isThumbFunction())
1059 OutContext);
1060 OutStreamer->emitValue(Expr, 4);
1061 }
1062 // Mark the end of jump table data-in-code region.
1063 OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
1064}
1065
1067 const MachineOperand &MO1 = MI->getOperand(1);
1068 unsigned JTI = MO1.getIndex();
1069
1070 // Make sure the Thumb jump table is 4-byte aligned. This will be a nop for
1071 // ARM mode tables.
1072 emitAlignment(Align(4));
1073
1074 // Emit a label for the jump table.
1075 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);
1076 OutStreamer->emitLabel(JTISymbol);
1077
1078 // Emit each entry of the table.
1079 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
1080 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
1081 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1082
1083 for (MachineBasicBlock *MBB : JTBBs) {
1084 const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::create(MBB->getSymbol(),
1085 OutContext);
1086 // If this isn't a TBB or TBH, the entries are direct branch instructions.
1088 .addExpr(MBBSymbolExpr)
1089 .addImm(ARMCC::AL)
1090 .addReg(0));
1091 }
1092}
1093
1095 unsigned OffsetWidth) {
1096 assert((OffsetWidth == 1 || OffsetWidth == 2) && "invalid tbb/tbh width");
1097 const MachineOperand &MO1 = MI->getOperand(1);
1098 unsigned JTI = MO1.getIndex();
1099
1100 const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();
1101 if (STI.isThumb1Only())
1102 emitAlignment(Align(4));
1103
1104 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);
1105 OutStreamer->emitLabel(JTISymbol);
1106
1107 // Emit each entry of the table.
1108 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
1109 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
1110 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1111
1112 // Mark the jump table as data-in-code.
1113 OutStreamer->emitDataRegion(OffsetWidth == 1 ? MCDR_DataRegionJT8
1115
1116 for (auto *MBB : JTBBs) {
1117 const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::create(MBB->getSymbol(),
1118 OutContext);
1119 // Otherwise it's an offset from the dispatch instruction. Construct an
1120 // MCExpr for the entry. We want a value of the form:
1121 // (BasicBlockAddr - TBBInstAddr + 4) / 2
1122 //
1123 // For example, a TBB table with entries jumping to basic blocks BB0 and BB1
1124 // would look like:
1125 // LJTI_0_0:
1126 // .byte (LBB0 - (LCPI0_0 + 4)) / 2
1127 // .byte (LBB1 - (LCPI0_0 + 4)) / 2
1128 // where LCPI0_0 is a label defined just before the TBB instruction using
1129 // this table.
1130 MCSymbol *TBInstPC = GetCPISymbol(MI->getOperand(0).getImm());
1131 const MCExpr *Expr = MCBinaryExpr::createAdd(
1134 Expr = MCBinaryExpr::createSub(MBBSymbolExpr, Expr, OutContext);
1136 OutContext);
1137 OutStreamer->emitValue(Expr, OffsetWidth);
1138 }
1139 // Mark the end of jump table data-in-code region. 32-bit offsets use
1140 // actual branch instructions here, so we don't mark those as a data-region
1141 // at all.
1142 OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
1143
1144 // Make sure the next instruction is 2-byte aligned.
1145 emitAlignment(Align(2));
1146}
1147
1148std::tuple<const MCSymbol *, uint64_t, const MCSymbol *,
1151 const MachineInstr *BranchInstr,
1152 const MCSymbol *BranchLabel) const {
1154 const MCSymbol *BaseLabel;
1155 uint64_t BaseOffset = 0;
1156 switch (BranchInstr->getOpcode()) {
1157 case ARM::BR_JTadd:
1158 case ARM::BR_JTr:
1159 case ARM::tBR_JTr:
1160 // Word relative to the jump table address.
1162 BaseLabel = GetARMJTIPICJumpTableLabel(JTI);
1163 break;
1164 case ARM::tTBH_JT:
1165 case ARM::t2TBH_JT:
1166 // half-word shifted left, relative to *after* the branch instruction.
1168 BranchLabel = GetCPISymbol(BranchInstr->getOperand(3).getImm());
1169 BaseLabel = BranchLabel;
1170 BaseOffset = 4;
1171 break;
1172 case ARM::tTBB_JT:
1173 case ARM::t2TBB_JT:
1174 // byte shifted left, relative to *after* the branch instruction.
1176 BranchLabel = GetCPISymbol(BranchInstr->getOperand(3).getImm());
1177 BaseLabel = BranchLabel;
1178 BaseOffset = 4;
1179 break;
1180 case ARM::t2BR_JT:
1181 // Direct jump.
1182 BaseLabel = nullptr;
1184 break;
1185 default:
1186 llvm_unreachable("Unknown jump table instruction");
1187 }
1188
1189 return std::make_tuple(BaseLabel, BaseOffset, BranchLabel, EntrySize);
1190}
1191
1192void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) {
1194 "Only instruction which are involved into frame setup code are allowed");
1195
1196 MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
1197 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
1198 const MachineFunction &MF = *MI->getParent()->getParent();
1199 const TargetRegisterInfo *TargetRegInfo =
1201 const MachineRegisterInfo &MachineRegInfo = MF.getRegInfo();
1202
1203 Register FramePtr = TargetRegInfo->getFrameRegister(MF);
1204 unsigned Opc = MI->getOpcode();
1205 unsigned SrcReg, DstReg;
1206
1207 switch (Opc) {
1208 case ARM::tPUSH:
1209 // special case: tPUSH does not have src/dst regs.
1210 SrcReg = DstReg = ARM::SP;
1211 break;
1212 case ARM::tLDRpci:
1213 case ARM::t2MOVi16:
1214 case ARM::t2MOVTi16:
1215 case ARM::tMOVi8:
1216 case ARM::tADDi8:
1217 case ARM::tLSLri:
1218 // special cases:
1219 // 1) for Thumb1 code we sometimes materialize the constant via constpool
1220 // load.
1221 // 2) for Thumb1 execute only code we materialize the constant via the
1222 // following pattern:
1223 // movs r3, #:upper8_15:<const>
1224 // lsls r3, #8
1225 // adds r3, #:upper0_7:<const>
1226 // lsls r3, #8
1227 // adds r3, #:lower8_15:<const>
1228 // lsls r3, #8
1229 // adds r3, #:lower0_7:<const>
1230 // So we need to special-case MOVS, ADDS and LSLS, and keep track of
1231 // where we are in the sequence with the simplest of state machines.
1232 // 3) for Thumb2 execute only code we materialize the constant via
1233 // immediate constants in 2 separate instructions (MOVW/MOVT).
1234 SrcReg = ~0U;
1235 DstReg = MI->getOperand(0).getReg();
1236 break;
1237 case ARM::VMRS:
1238 SrcReg = ARM::FPSCR;
1239 DstReg = MI->getOperand(0).getReg();
1240 break;
1241 case ARM::VMRS_FPEXC:
1242 SrcReg = ARM::FPEXC;
1243 DstReg = MI->getOperand(0).getReg();
1244 break;
1245 default:
1246 SrcReg = MI->getOperand(1).getReg();
1247 DstReg = MI->getOperand(0).getReg();
1248 break;
1249 }
1250
1251 // Try to figure out the unwinding opcode out of src / dst regs.
1252 if (MI->mayStore()) {
1253 // Register saves.
1254 assert(DstReg == ARM::SP &&
1255 "Only stack pointer as a destination reg is supported");
1256
1258 // Skip src & dst reg, and pred ops.
1259 unsigned StartOp = 2 + 2;
1260 // Use all the operands.
1261 unsigned NumOffset = 0;
1262 // Amount of SP adjustment folded into a push, before the
1263 // registers are stored (pad at higher addresses).
1264 unsigned PadBefore = 0;
1265 // Amount of SP adjustment folded into a push, after the
1266 // registers are stored (pad at lower addresses).
1267 unsigned PadAfter = 0;
1268
1269 switch (Opc) {
1270 default:
1271 MI->print(errs());
1272 llvm_unreachable("Unsupported opcode for unwinding information");
1273 case ARM::tPUSH:
1274 // Special case here: no src & dst reg, but two extra imp ops.
1275 StartOp = 2; NumOffset = 2;
1276 [[fallthrough]];
1277 case ARM::STMDB_UPD:
1278 case ARM::t2STMDB_UPD:
1279 case ARM::VSTMDDB_UPD:
1280 assert(SrcReg == ARM::SP &&
1281 "Only stack pointer as a source reg is supported");
1282 for (unsigned i = StartOp, NumOps = MI->getNumOperands() - NumOffset;
1283 i != NumOps; ++i) {
1284 const MachineOperand &MO = MI->getOperand(i);
1285 // Actually, there should never be any impdef stuff here. Skip it
1286 // temporary to workaround PR11902.
1287 if (MO.isImplicit())
1288 continue;
1289 // Registers, pushed as a part of folding an SP update into the
1290 // push instruction are marked as undef and should not be
1291 // restored when unwinding, because the function can modify the
1292 // corresponding stack slots.
1293 if (MO.isUndef()) {
1294 assert(RegList.empty() &&
1295 "Pad registers must come before restored ones");
1296 unsigned Width =
1297 TargetRegInfo->getRegSizeInBits(MO.getReg(), MachineRegInfo) / 8;
1298 PadAfter += Width;
1299 continue;
1300 }
1301 // Check for registers that are remapped (for a Thumb1 prologue that
1302 // saves high registers).
1303 Register Reg = MO.getReg();
1304 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(Reg))
1305 Reg = RemappedReg;
1306 RegList.push_back(Reg);
1307 }
1308 break;
1309 case ARM::STR_PRE_IMM:
1310 case ARM::STR_PRE_REG:
1311 case ARM::t2STR_PRE:
1312 assert(MI->getOperand(2).getReg() == ARM::SP &&
1313 "Only stack pointer as a source reg is supported");
1314 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(SrcReg))
1315 SrcReg = RemappedReg;
1316
1317 RegList.push_back(SrcReg);
1318 break;
1319 case ARM::t2STRD_PRE:
1320 assert(MI->getOperand(3).getReg() == ARM::SP &&
1321 "Only stack pointer as a source reg is supported");
1322 SrcReg = MI->getOperand(1).getReg();
1323 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(SrcReg))
1324 SrcReg = RemappedReg;
1325 RegList.push_back(SrcReg);
1326 SrcReg = MI->getOperand(2).getReg();
1327 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(SrcReg))
1328 SrcReg = RemappedReg;
1329 RegList.push_back(SrcReg);
1330 PadBefore = -MI->getOperand(4).getImm() - 8;
1331 break;
1332 }
1333 if (MAI->getExceptionHandlingType() == ExceptionHandling::ARM) {
1334 if (PadBefore)
1335 ATS.emitPad(PadBefore);
1336 ATS.emitRegSave(RegList, Opc == ARM::VSTMDDB_UPD);
1337 // Account for the SP adjustment, folded into the push.
1338 if (PadAfter)
1339 ATS.emitPad(PadAfter);
1340 }
1341 } else {
1342 // Changes of stack / frame pointer.
1343 if (SrcReg == ARM::SP) {
1344 int64_t Offset = 0;
1345 switch (Opc) {
1346 default:
1347 MI->print(errs());
1348 llvm_unreachable("Unsupported opcode for unwinding information");
1349 case ARM::tLDRspi:
1350 // Used to restore LR in a prologue which uses it as a temporary, has
1351 // no effect on unwind tables.
1352 return;
1353 case ARM::MOVr:
1354 case ARM::tMOVr:
1355 Offset = 0;
1356 break;
1357 case ARM::ADDri:
1358 case ARM::t2ADDri:
1359 case ARM::t2ADDri12:
1360 case ARM::t2ADDspImm:
1361 case ARM::t2ADDspImm12:
1362 Offset = -MI->getOperand(2).getImm();
1363 break;
1364 case ARM::SUBri:
1365 case ARM::t2SUBri:
1366 case ARM::t2SUBri12:
1367 case ARM::t2SUBspImm:
1368 case ARM::t2SUBspImm12:
1369 Offset = MI->getOperand(2).getImm();
1370 break;
1371 case ARM::tSUBspi:
1372 Offset = MI->getOperand(2).getImm()*4;
1373 break;
1374 case ARM::tADDspi:
1375 case ARM::tADDrSPi:
1376 Offset = -MI->getOperand(2).getImm()*4;
1377 break;
1378 case ARM::tADDhirr:
1379 Offset =
1380 -AFI->EHPrologueOffsetInRegs.lookup(MI->getOperand(2).getReg());
1381 break;
1382 }
1383
1384 if (MAI->getExceptionHandlingType() == ExceptionHandling::ARM) {
1385 if (DstReg == FramePtr && FramePtr != ARM::SP)
1386 // Set-up of the frame pointer. Positive values correspond to "add"
1387 // instruction.
1388 ATS.emitSetFP(FramePtr, ARM::SP, -Offset);
1389 else if (DstReg == ARM::SP) {
1390 // Change of SP by an offset. Positive values correspond to "sub"
1391 // instruction.
1392 ATS.emitPad(Offset);
1393 } else {
1394 // Move of SP to a register. Positive values correspond to an "add"
1395 // instruction.
1396 ATS.emitMovSP(DstReg, -Offset);
1397 }
1398 }
1399 } else if (DstReg == ARM::SP) {
1400 MI->print(errs());
1401 llvm_unreachable("Unsupported opcode for unwinding information");
1402 } else {
1403 int64_t Offset = 0;
1404 switch (Opc) {
1405 case ARM::tMOVr:
1406 // If a Thumb1 function spills r8-r11, we copy the values to low
1407 // registers before pushing them. Record the copy so we can emit the
1408 // correct ".save" later.
1409 AFI->EHPrologueRemappedRegs[DstReg] = SrcReg;
1410 break;
1411 case ARM::VMRS:
1412 case ARM::VMRS_FPEXC:
1413 // If a function spills FPSCR or FPEXC, we copy the values to low
1414 // registers before pushing them. However, we can't issue annotations
1415 // for FP status registers because ".save" requires GPR registers, and
1416 // ".vsave" requires DPR registers, so don't record the copy and simply
1417 // emit annotations for the source registers used for the store.
1418 break;
1419 case ARM::tLDRpci: {
1420 // Grab the constpool index and check, whether it corresponds to
1421 // original or cloned constpool entry.
1422 unsigned CPI = MI->getOperand(1).getIndex();
1423 const MachineConstantPool *MCP = MF.getConstantPool();
1424 if (CPI >= MCP->getConstants().size())
1425 CPI = AFI->getOriginalCPIdx(CPI);
1426 assert(CPI != -1U && "Invalid constpool index");
1427
1428 // Derive the actual offset.
1429 const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI];
1430 assert(!CPE.isMachineConstantPoolEntry() && "Invalid constpool entry");
1431 Offset = cast<ConstantInt>(CPE.Val.ConstVal)->getSExtValue();
1432 AFI->EHPrologueOffsetInRegs[DstReg] = Offset;
1433 break;
1434 }
1435 case ARM::t2MOVi16:
1436 Offset = MI->getOperand(1).getImm();
1437 AFI->EHPrologueOffsetInRegs[DstReg] = Offset;
1438 break;
1439 case ARM::t2MOVTi16:
1440 Offset = MI->getOperand(2).getImm();
1441 AFI->EHPrologueOffsetInRegs[DstReg] |= (Offset << 16);
1442 break;
1443 case ARM::tMOVi8:
1444 Offset = MI->getOperand(2).getImm();
1445 AFI->EHPrologueOffsetInRegs[DstReg] = Offset;
1446 break;
1447 case ARM::tLSLri:
1448 assert(MI->getOperand(3).getImm() == 8 &&
1449 "The shift amount is not equal to 8");
1450 assert(MI->getOperand(2).getReg() == MI->getOperand(0).getReg() &&
1451 "The source register is not equal to the destination register");
1452 AFI->EHPrologueOffsetInRegs[DstReg] <<= 8;
1453 break;
1454 case ARM::tADDi8:
1455 assert(MI->getOperand(2).getReg() == MI->getOperand(0).getReg() &&
1456 "The source register is not equal to the destination register");
1457 Offset = MI->getOperand(3).getImm();
1458 AFI->EHPrologueOffsetInRegs[DstReg] += Offset;
1459 break;
1460 case ARM::t2PAC:
1461 case ARM::t2PACBTI:
1462 AFI->EHPrologueRemappedRegs[ARM::R12] = ARM::RA_AUTH_CODE;
1463 break;
1464 default:
1465 MI->print(errs());
1466 llvm_unreachable("Unsupported opcode for unwinding information");
1467 }
1468 }
1469 }
1470}
1471
1472// Simple pseudo-instructions have their lowering (with expansion to real
1473// instructions) auto-generated.
1474#include "ARMGenMCPseudoLowering.inc"
1475
1476// Helper function to check if a register is live (used as an implicit operand)
1477// in the given call instruction.
1479 for (const MachineOperand &MO : Call.implicit_operands()) {
1480 if (MO.isReg() && MO.getReg() == Reg && MO.isUse()) {
1481 return true;
1482 }
1483 }
1484 return false;
1485}
1486
1487void ARMAsmPrinter::EmitKCFI_CHECK_ARM32(Register AddrReg, int64_t Type,
1488 const MachineInstr &Call,
1489 int64_t PrefixNops) {
1490 // Choose scratch register: r12 primary, r3 if target is r12.
1491 unsigned ScratchReg = ARM::R12;
1492 if (AddrReg == ARM::R12) {
1493 ScratchReg = ARM::R3;
1494 }
1495
1496 // Calculate ESR for ARM mode (16-bit): 0x8000 | (scratch_reg << 5) | addr_reg
1497 // Note: scratch_reg is always 0x1F since the EOR sequence clobbers it.
1498 const ARMBaseRegisterInfo *TRI = static_cast<const ARMBaseRegisterInfo *>(
1499 MF->getSubtarget().getRegisterInfo());
1500 unsigned AddrIndex = TRI->getEncodingValue(AddrReg);
1501 unsigned ESR = 0x8000 | (31 << 5) | (AddrIndex & 31);
1502
1503 // Check if r3 is live and needs to be spilled.
1504 bool NeedSpillR3 =
1505 (ScratchReg == ARM::R3) && isRegisterLiveInCall(Call, ARM::R3);
1506
1507 // If we need to spill r3, push it first.
1508 if (NeedSpillR3) {
1509 // push {r3}
1510 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::STMDB_UPD)
1511 .addReg(ARM::SP)
1512 .addReg(ARM::SP)
1513 .addImm(ARMCC::AL)
1514 .addReg(0)
1515 .addReg(ARM::R3));
1516 }
1517
1518 // Clear bit 0 of target address to handle Thumb function pointers.
1519 // In 32-bit ARM, function pointers may have the low bit set to indicate
1520 // Thumb state when ARM/Thumb interworking is enabled (ARMv4T and later).
1521 // We need to clear it to avoid an alignment fault when loading.
1522 // bic scratch, target, #1
1523 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::BICri)
1524 .addReg(ScratchReg)
1525 .addReg(AddrReg)
1526 .addImm(1)
1527 .addImm(ARMCC::AL)
1528 .addReg(0)
1529 .addReg(0));
1530
1531 // ldr scratch, [scratch, #-(PrefixNops * 4 + 4)]
1532 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12)
1533 .addReg(ScratchReg)
1534 .addReg(ScratchReg)
1535 .addImm(-(PrefixNops * 4 + 4))
1536 .addImm(ARMCC::AL)
1537 .addReg(0));
1538
1539 // Each EOR instruction XORs one byte of the type, shifted to its position.
1540 for (int i = 0; i < 4; i++) {
1541 uint8_t byte = (Type >> (i * 8)) & 0xFF;
1542 uint32_t imm = byte << (i * 8);
1543 bool isLast = (i == 3);
1544
1545 // Encode as ARM modified immediate.
1546 int SOImmVal = ARM_AM::getSOImmVal(imm);
1547 assert(SOImmVal != -1 &&
1548 "Cannot encode immediate as ARM modified immediate");
1549
1550 // eor[s] scratch, scratch, #imm (last one sets flags with CPSR)
1552 MCInstBuilder(ARM::EORri)
1553 .addReg(ScratchReg)
1554 .addReg(ScratchReg)
1555 .addImm(SOImmVal)
1556 .addImm(ARMCC::AL)
1557 .addReg(0)
1558 .addReg(isLast ? ARM::CPSR : ARM::NoRegister));
1559 }
1560
1561 // If we spilled r3, restore it immediately after the comparison.
1562 // This must happen before the branch so r3 is valid on both paths.
1563 if (NeedSpillR3) {
1564 // pop {r3}
1565 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDMIA_UPD)
1566 .addReg(ARM::SP)
1567 .addReg(ARM::SP)
1568 .addImm(ARMCC::AL)
1569 .addReg(0)
1570 .addReg(ARM::R3));
1571 }
1572
1573 // beq .Lpass (branch if types match, i.e., scratch is zero)
1574 MCSymbol *Pass = OutContext.createTempSymbol();
1576 MCInstBuilder(ARM::Bcc)
1578 .addImm(ARMCC::EQ)
1579 .addReg(ARM::CPSR));
1580
1581 // udf #ESR (trap with encoded diagnostic)
1582 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::UDF).addImm(ESR));
1583
1584 OutStreamer->emitLabel(Pass);
1585}
1586
1587void ARMAsmPrinter::EmitKCFI_CHECK_Thumb2(Register AddrReg, int64_t Type,
1588 const MachineInstr &Call,
1589 int64_t PrefixNops) {
1590 // Choose scratch register: r12 primary, r3 if target is r12.
1591 unsigned ScratchReg = ARM::R12;
1592 if (AddrReg == ARM::R12) {
1593 ScratchReg = ARM::R3;
1594 }
1595
1596 // Calculate ESR for Thumb mode (8-bit): 0x80 | addr_reg
1597 // Bit 7: KCFI trap indicator
1598 // Bits 6-5: Reserved
1599 // Bits 4-0: Address register encoding
1600 const ARMBaseRegisterInfo *TRI = static_cast<const ARMBaseRegisterInfo *>(
1601 MF->getSubtarget().getRegisterInfo());
1602 unsigned AddrIndex = TRI->getEncodingValue(AddrReg);
1603 unsigned ESR = 0x80 | (AddrIndex & 0x1F);
1604
1605 // Check if r3 is live and needs to be spilled.
1606 bool NeedSpillR3 =
1607 (ScratchReg == ARM::R3) && isRegisterLiveInCall(Call, ARM::R3);
1608
1609 // If we need to spill r3, push it first.
1610 if (NeedSpillR3) {
1611 // push {r3}
1613 *OutStreamer,
1614 MCInstBuilder(ARM::tPUSH).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));
1615 }
1616
1617 // Clear bit 0 of target address to handle Thumb function pointers.
1618 // In 32-bit ARM, function pointers may have the low bit set to indicate
1619 // Thumb state when ARM/Thumb interworking is enabled (ARMv4T and later).
1620 // We need to clear it to avoid an alignment fault when loading.
1621 // bic scratch, target, #1
1622 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2BICri)
1623 .addReg(ScratchReg)
1624 .addReg(AddrReg)
1625 .addImm(1)
1626 .addImm(ARMCC::AL)
1627 .addReg(0)
1628 .addReg(0));
1629
1630 // ldr scratch, [scratch, #-(PrefixNops * 4 + 4)]
1631 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi8)
1632 .addReg(ScratchReg)
1633 .addReg(ScratchReg)
1634 .addImm(-(PrefixNops * 4 + 4))
1635 .addImm(ARMCC::AL)
1636 .addReg(0));
1637
1638 // Each EOR instruction XORs one byte of the type, shifted to its position.
1639 for (int i = 0; i < 4; i++) {
1640 uint8_t byte = (Type >> (i * 8)) & 0xFF;
1641 uint32_t imm = byte << (i * 8);
1642 bool isLast = (i == 3);
1643
1644 // Verify the immediate can be encoded as Thumb2 modified immediate.
1645 assert(ARM_AM::getT2SOImmVal(imm) != -1 &&
1646 "Cannot encode immediate as Thumb2 modified immediate");
1647
1648 // eor[s] scratch, scratch, #imm (last one sets flags with CPSR)
1650 MCInstBuilder(ARM::t2EORri)
1651 .addReg(ScratchReg)
1652 .addReg(ScratchReg)
1653 .addImm(imm)
1654 .addImm(ARMCC::AL)
1655 .addReg(0)
1656 .addReg(isLast ? ARM::CPSR : ARM::NoRegister));
1657 }
1658
1659 // If we spilled r3, restore it immediately after the comparison.
1660 // This must happen before the branch so r3 is valid on both paths.
1661 if (NeedSpillR3) {
1662 // pop {r3}
1664 *OutStreamer,
1665 MCInstBuilder(ARM::tPOP).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));
1666 }
1667
1668 // beq .Lpass (branch if types match, i.e., scratch is zero)
1669 MCSymbol *Pass = OutContext.createTempSymbol();
1671 MCInstBuilder(ARM::t2Bcc)
1673 .addImm(ARMCC::EQ)
1674 .addReg(ARM::CPSR));
1675
1676 // udf #ESR (trap with encoded diagnostic)
1677 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tUDF).addImm(ESR));
1678
1679 OutStreamer->emitLabel(Pass);
1680}
1681
1682void ARMAsmPrinter::EmitKCFI_CHECK_Thumb1(Register AddrReg, int64_t Type,
1683 const MachineInstr &Call,
1684 int64_t PrefixNops) {
1685 // For Thumb1, use R2 unconditionally as scratch register (a low register
1686 // required for tLDRi). R3 is used for building the type hash.
1687 unsigned ScratchReg = ARM::R2;
1688 unsigned TempReg = ARM::R3;
1689
1690 // Check if r3 is live and needs to be spilled.
1691 bool NeedSpillR3 = isRegisterLiveInCall(Call, ARM::R3);
1692
1693 // Spill r3 if needed
1694 if (NeedSpillR3) {
1696 *OutStreamer,
1697 MCInstBuilder(ARM::tPUSH).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));
1698 }
1699
1700 // Check if r2 is live and needs to be spilled.
1701 bool NeedSpillR2 = isRegisterLiveInCall(Call, ARM::R2);
1702
1703 // Push R2 if it's live
1704 if (NeedSpillR2) {
1706 *OutStreamer,
1707 MCInstBuilder(ARM::tPUSH).addImm(ARMCC::AL).addReg(0).addReg(ARM::R2));
1708 }
1709
1710 // Clear bit 0 from target address
1711 // TempReg (R3) is used first as helper for BIC, then later for building type
1712 // hash.
1713
1714 // movs temp, #1
1715 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVi8)
1716 .addReg(TempReg)
1717 .addReg(ARM::CPSR)
1718 .addImm(1)
1719 .addImm(ARMCC::AL)
1720 .addReg(0));
1721
1722 // mov scratch, target
1723 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr)
1724 .addReg(ScratchReg)
1725 .addReg(AddrReg)
1726 .addImm(ARMCC::AL));
1727
1728 // bics scratch, temp (scratch = scratch & ~temp)
1729 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBIC)
1730 .addReg(ScratchReg)
1731 .addReg(ARM::CPSR)
1732 .addReg(ScratchReg)
1733 .addReg(TempReg)
1734 .addImm(ARMCC::AL)
1735 .addReg(0));
1736
1737 // Load type hash. Thumb1 doesn't support negative offsets, so subtract.
1738 int offset = PrefixNops * 4 + 4;
1739
1740 // subs scratch, #offset
1741 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tSUBi8)
1742 .addReg(ScratchReg)
1743 .addReg(ARM::CPSR)
1744 .addReg(ScratchReg)
1745 .addImm(offset)
1746 .addImm(ARMCC::AL)
1747 .addReg(0));
1748
1749 // ldr scratch, [scratch, #0]
1750 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi)
1751 .addReg(ScratchReg)
1752 .addReg(ScratchReg)
1753 .addImm(0)
1754 .addImm(ARMCC::AL)
1755 .addReg(0));
1756
1757 // Load expected type inline (instead of EOR sequence)
1758 //
1759 // This creates the 32-bit value byte-by-byte in the temp register:
1760 // movs temp, #byte3 (high byte)
1761 // lsls temp, temp, #8
1762 // adds temp, #byte2
1763 // lsls temp, temp, #8
1764 // adds temp, #byte1
1765 // lsls temp, temp, #8
1766 // adds temp, #byte0 (low byte)
1767
1768 uint8_t byte0 = (Type >> 0) & 0xFF;
1769 uint8_t byte1 = (Type >> 8) & 0xFF;
1770 uint8_t byte2 = (Type >> 16) & 0xFF;
1771 uint8_t byte3 = (Type >> 24) & 0xFF;
1772
1773 // movs temp, #byte3 (start with high byte)
1774 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVi8)
1775 .addReg(TempReg)
1776 .addReg(ARM::CPSR)
1777 .addImm(byte3)
1778 .addImm(ARMCC::AL)
1779 .addReg(0));
1780
1781 // lsls temp, temp, #8
1782 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)
1783 .addReg(TempReg)
1784 .addReg(ARM::CPSR)
1785 .addReg(TempReg)
1786 .addImm(8)
1787 .addImm(ARMCC::AL)
1788 .addReg(0));
1789
1790 // adds temp, #byte2
1791 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi8)
1792 .addReg(TempReg)
1793 .addReg(ARM::CPSR)
1794 .addReg(TempReg)
1795 .addImm(byte2)
1796 .addImm(ARMCC::AL)
1797 .addReg(0));
1798
1799 // lsls temp, temp, #8
1800 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)
1801 .addReg(TempReg)
1802 .addReg(ARM::CPSR)
1803 .addReg(TempReg)
1804 .addImm(8)
1805 .addImm(ARMCC::AL)
1806 .addReg(0));
1807
1808 // adds temp, #byte1
1809 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi8)
1810 .addReg(TempReg)
1811 .addReg(ARM::CPSR)
1812 .addReg(TempReg)
1813 .addImm(byte1)
1814 .addImm(ARMCC::AL)
1815 .addReg(0));
1816
1817 // lsls temp, temp, #8
1818 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)
1819 .addReg(TempReg)
1820 .addReg(ARM::CPSR)
1821 .addReg(TempReg)
1822 .addImm(8)
1823 .addImm(ARMCC::AL)
1824 .addReg(0));
1825
1826 // adds temp, #byte0 (low byte)
1827 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi8)
1828 .addReg(TempReg)
1829 .addReg(ARM::CPSR)
1830 .addReg(TempReg)
1831 .addImm(byte0)
1832 .addImm(ARMCC::AL)
1833 .addReg(0));
1834
1835 // cmp scratch, temp
1836 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tCMPr)
1837 .addReg(ScratchReg)
1838 .addReg(TempReg)
1839 .addImm(ARMCC::AL)
1840 .addReg(0));
1841
1842 // Restore registers if spilled (pop in reverse order of push: R2, then R3)
1843 if (NeedSpillR2) {
1844 // pop {r2}
1846 *OutStreamer,
1847 MCInstBuilder(ARM::tPOP).addImm(ARMCC::AL).addReg(0).addReg(ARM::R2));
1848 }
1849
1850 // Restore r3 if spilled
1851 if (NeedSpillR3) {
1852 // pop {r3}
1854 *OutStreamer,
1855 MCInstBuilder(ARM::tPOP).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));
1856 }
1857
1858 // beq .Lpass (branch if types match, i.e., scratch == temp)
1859 MCSymbol *Pass = OutContext.createTempSymbol();
1861 MCInstBuilder(ARM::tBcc)
1863 .addImm(ARMCC::EQ)
1864 .addReg(ARM::CPSR));
1865
1866 // bkpt #0 (trap with encoded diagnostic)
1867 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBKPT).addImm(0));
1868
1869 OutStreamer->emitLabel(Pass);
1870}
1871
1873 Register AddrReg = MI.getOperand(0).getReg();
1874 const int64_t Type = MI.getOperand(1).getImm();
1875
1876 // Get the call instruction that follows this KCFI_CHECK.
1877 assert(std::next(MI.getIterator())->isCall() &&
1878 "KCFI_CHECK not followed by a call instruction");
1879 const MachineInstr &Call = *std::next(MI.getIterator());
1880
1881 // Adjust the offset for patchable-function-prefix.
1882 int64_t PrefixNops = 0;
1883 MI.getMF()
1884 ->getFunction()
1885 .getFnAttribute("patchable-function-prefix")
1886 .getValueAsString()
1887 .getAsInteger(10, PrefixNops);
1888
1889 // Emit the appropriate instruction sequence based on the opcode variant.
1890 switch (MI.getOpcode()) {
1891 case ARM::KCFI_CHECK_ARM:
1892 EmitKCFI_CHECK_ARM32(AddrReg, Type, Call, PrefixNops);
1893 break;
1894 case ARM::KCFI_CHECK_Thumb2:
1895 EmitKCFI_CHECK_Thumb2(AddrReg, Type, Call, PrefixNops);
1896 break;
1897 case ARM::KCFI_CHECK_Thumb1:
1898 EmitKCFI_CHECK_Thumb1(AddrReg, Type, Call, PrefixNops);
1899 break;
1900 default:
1901 llvm_unreachable("Unexpected KCFI_CHECK opcode");
1902 }
1903}
1904
1906 ARM_MC::verifyInstructionPredicates(MI->getOpcode(),
1907 getSubtargetInfo().getFeatureBits());
1908
1909 const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();
1910 const DataLayout &DL = getDataLayout();
1911 MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
1912 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
1913
1914 // If we just ended a constant pool, mark it as such.
1915 if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) {
1916 OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
1917 InConstantPool = false;
1918 }
1919
1920 // Emit unwinding stuff for frame-related instructions
1921 if (TM.getTargetTriple().isTargetEHABICompatible() &&
1922 MI->getFlag(MachineInstr::FrameSetup))
1923 EmitUnwindingInstruction(MI);
1924
1925 // Do any auto-generated pseudo lowerings.
1926 if (MCInst OutInst; lowerPseudoInstExpansion(MI, OutInst)) {
1927 EmitToStreamer(*OutStreamer, OutInst);
1928 return;
1929 }
1930
1931 assert(!convertAddSubFlagsOpcode(MI->getOpcode()) &&
1932 "Pseudo flag setting opcode should be expanded early");
1933
1934 // Check for manual lowerings.
1935 unsigned Opc = MI->getOpcode();
1936 switch (Opc) {
1937 case ARM::t2MOVi32imm: llvm_unreachable("Should be lowered by thumb2it pass");
1938 case ARM::DBG_VALUE: llvm_unreachable("Should be handled by generic printing");
1939 case ARM::KCFI_CHECK_ARM:
1940 case ARM::KCFI_CHECK_Thumb2:
1941 case ARM::KCFI_CHECK_Thumb1:
1943 return;
1944 case ARM::LEApcrel:
1945 case ARM::tLEApcrel:
1946 case ARM::t2LEApcrel: {
1947 // FIXME: Need to also handle globals and externals
1948 MCSymbol *CPISymbol = GetCPISymbol(MI->getOperand(1).getIndex());
1949 EmitToStreamer(*OutStreamer, MCInstBuilder(MI->getOpcode() ==
1950 ARM::t2LEApcrel ? ARM::t2ADR
1951 : (MI->getOpcode() == ARM::tLEApcrel ? ARM::tADR
1952 : ARM::ADR))
1953 .addReg(MI->getOperand(0).getReg())
1955 // Add predicate operands.
1956 .addImm(MI->getOperand(2).getImm())
1957 .addReg(MI->getOperand(3).getReg()));
1958 return;
1959 }
1960 case ARM::LEApcrelJT:
1961 case ARM::tLEApcrelJT:
1962 case ARM::t2LEApcrelJT: {
1963 MCSymbol *JTIPICSymbol =
1964 GetARMJTIPICJumpTableLabel(MI->getOperand(1).getIndex());
1965 EmitToStreamer(*OutStreamer, MCInstBuilder(MI->getOpcode() ==
1966 ARM::t2LEApcrelJT ? ARM::t2ADR
1967 : (MI->getOpcode() == ARM::tLEApcrelJT ? ARM::tADR
1968 : ARM::ADR))
1969 .addReg(MI->getOperand(0).getReg())
1971 // Add predicate operands.
1972 .addImm(MI->getOperand(2).getImm())
1973 .addReg(MI->getOperand(3).getReg()));
1974 return;
1975 }
1976 // Darwin call instructions are just normal call instructions with different
1977 // clobber semantics (they clobber R9).
1978 case ARM::BX_CALL: {
1980 .addReg(ARM::LR)
1981 .addReg(ARM::PC)
1982 // Add predicate operands.
1983 .addImm(ARMCC::AL)
1984 .addReg(0)
1985 // Add 's' bit operand (always reg0 for this)
1986 .addReg(0));
1987
1988 assert(STI.hasV4TOps() && "Expected V4TOps for BX call");
1990 MCInstBuilder(ARM::BX).addReg(MI->getOperand(0).getReg()));
1991 return;
1992 }
1993 case ARM::tBX_CALL: {
1994 assert(!STI.hasV5TOps() && "Expected BLX to be selected for v5t+");
1995
1996 // On ARM v4t, when doing a call from thumb mode, we need to ensure
1997 // that the saved lr has its LSB set correctly (the arch doesn't
1998 // have blx).
1999 // So here we generate a bl to a small jump pad that does bx rN.
2000 // The jump pads are emitted after the function body.
2001
2002 Register TReg = MI->getOperand(0).getReg();
2003 MCSymbol *TRegSym = nullptr;
2004 for (std::pair<unsigned, MCSymbol *> &TIP : ThumbIndirectPads) {
2005 if (TIP.first == TReg) {
2006 TRegSym = TIP.second;
2007 break;
2008 }
2009 }
2010
2011 if (!TRegSym) {
2012 TRegSym = OutContext.createTempSymbol();
2013 ThumbIndirectPads.push_back(std::make_pair(TReg, TRegSym));
2014 }
2015
2016 // Create a link-saving branch to the Reg Indirect Jump Pad.
2018 // Predicate comes first here.
2019 .addImm(ARMCC::AL).addReg(0)
2020 .addExpr(MCSymbolRefExpr::create(TRegSym, OutContext)));
2021 return;
2022 }
2023 case ARM::BMOVPCRX_CALL: {
2025 .addReg(ARM::LR)
2026 .addReg(ARM::PC)
2027 // Add predicate operands.
2028 .addImm(ARMCC::AL)
2029 .addReg(0)
2030 // Add 's' bit operand (always reg0 for this)
2031 .addReg(0));
2032
2034 .addReg(ARM::PC)
2035 .addReg(MI->getOperand(0).getReg())
2036 // Add predicate operands.
2038 .addReg(0)
2039 // Add 's' bit operand (always reg0 for this)
2040 .addReg(0));
2041 return;
2042 }
2043 case ARM::BMOVPCB_CALL: {
2045 .addReg(ARM::LR)
2046 .addReg(ARM::PC)
2047 // Add predicate operands.
2048 .addImm(ARMCC::AL)
2049 .addReg(0)
2050 // Add 's' bit operand (always reg0 for this)
2051 .addReg(0));
2052
2053 const MachineOperand &Op = MI->getOperand(0);
2054 const GlobalValue *GV = Op.getGlobal();
2055 const unsigned TF = Op.getTargetFlags();
2056 MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
2057 const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext);
2059 .addExpr(GVSymExpr)
2060 // Add predicate operands.
2061 .addImm(ARMCC::AL)
2062 .addReg(0));
2063 return;
2064 }
2065 case ARM::MOVi16_ga_pcrel:
2066 case ARM::t2MOVi16_ga_pcrel: {
2067 MCInst TmpInst;
2068 TmpInst.setOpcode(Opc == ARM::MOVi16_ga_pcrel? ARM::MOVi16 : ARM::t2MOVi16);
2069 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
2070
2071 unsigned TF = MI->getOperand(1).getTargetFlags();
2072 const GlobalValue *GV = MI->getOperand(1).getGlobal();
2073 MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
2074 const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext);
2075
2076 MCSymbol *LabelSym =
2077 getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
2078 MI->getOperand(2).getImm(), OutContext);
2079 const MCExpr *LabelSymExpr= MCSymbolRefExpr::create(LabelSym, OutContext);
2080 unsigned PCAdj = (Opc == ARM::MOVi16_ga_pcrel) ? 8 : 4;
2081 const MCExpr *PCRelExpr = ARM::createLower16(
2083 GVSymExpr,
2084 MCBinaryExpr::createAdd(LabelSymExpr,
2086 OutContext),
2087 OutContext),
2088 OutContext);
2089 TmpInst.addOperand(MCOperand::createExpr(PCRelExpr));
2090
2091 // Add predicate operands.
2093 TmpInst.addOperand(MCOperand::createReg(0));
2094 // Add 's' bit operand (always reg0 for this)
2095 TmpInst.addOperand(MCOperand::createReg(0));
2096 EmitToStreamer(*OutStreamer, TmpInst);
2097 return;
2098 }
2099 case ARM::MOVTi16_ga_pcrel:
2100 case ARM::t2MOVTi16_ga_pcrel: {
2101 MCInst TmpInst;
2102 TmpInst.setOpcode(Opc == ARM::MOVTi16_ga_pcrel
2103 ? ARM::MOVTi16 : ARM::t2MOVTi16);
2104 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
2105 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(1).getReg()));
2106
2107 unsigned TF = MI->getOperand(2).getTargetFlags();
2108 const GlobalValue *GV = MI->getOperand(2).getGlobal();
2109 MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
2110 const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext);
2111
2112 MCSymbol *LabelSym =
2113 getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
2114 MI->getOperand(3).getImm(), OutContext);
2115 const MCExpr *LabelSymExpr= MCSymbolRefExpr::create(LabelSym, OutContext);
2116 unsigned PCAdj = (Opc == ARM::MOVTi16_ga_pcrel) ? 8 : 4;
2117 const MCExpr *PCRelExpr = ARM::createUpper16(
2119 GVSymExpr,
2120 MCBinaryExpr::createAdd(LabelSymExpr,
2122 OutContext),
2123 OutContext),
2124 OutContext);
2125 TmpInst.addOperand(MCOperand::createExpr(PCRelExpr));
2126 // Add predicate operands.
2128 TmpInst.addOperand(MCOperand::createReg(0));
2129 // Add 's' bit operand (always reg0 for this)
2130 TmpInst.addOperand(MCOperand::createReg(0));
2131 EmitToStreamer(*OutStreamer, TmpInst);
2132 return;
2133 }
2134 case ARM::t2BFi:
2135 case ARM::t2BFic:
2136 case ARM::t2BFLi:
2137 case ARM::t2BFr:
2138 case ARM::t2BFLr: {
2139 // This is a Branch Future instruction.
2140
2141 const MCExpr *BranchLabel = MCSymbolRefExpr::create(
2142 getBFLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
2143 MI->getOperand(0).getIndex(), OutContext),
2144 OutContext);
2145
2146 auto MCInst = MCInstBuilder(Opc).addExpr(BranchLabel);
2147 if (MI->getOperand(1).isReg()) {
2148 // For BFr/BFLr
2149 MCInst.addReg(MI->getOperand(1).getReg());
2150 } else {
2151 // For BFi/BFLi/BFic
2152 const MCExpr *BranchTarget;
2153 if (MI->getOperand(1).isMBB())
2154 BranchTarget = MCSymbolRefExpr::create(
2155 MI->getOperand(1).getMBB()->getSymbol(), OutContext);
2156 else if (MI->getOperand(1).isGlobal()) {
2157 const GlobalValue *GV = MI->getOperand(1).getGlobal();
2158 BranchTarget = MCSymbolRefExpr::create(
2159 GetARMGVSymbol(GV, MI->getOperand(1).getTargetFlags()), OutContext);
2160 } else if (MI->getOperand(1).isSymbol()) {
2161 BranchTarget = MCSymbolRefExpr::create(
2162 GetExternalSymbolSymbol(MI->getOperand(1).getSymbolName()),
2163 OutContext);
2164 } else
2165 llvm_unreachable("Unhandled operand kind in Branch Future instruction");
2166
2167 MCInst.addExpr(BranchTarget);
2168 }
2169
2170 if (Opc == ARM::t2BFic) {
2171 const MCExpr *ElseLabel = MCSymbolRefExpr::create(
2172 getBFLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
2173 MI->getOperand(2).getIndex(), OutContext),
2174 OutContext);
2175 MCInst.addExpr(ElseLabel);
2176 MCInst.addImm(MI->getOperand(3).getImm());
2177 } else {
2178 MCInst.addImm(MI->getOperand(2).getImm())
2179 .addReg(MI->getOperand(3).getReg());
2180 }
2181
2183 return;
2184 }
2185 case ARM::t2BF_LabelPseudo: {
2186 // This is a pseudo op for a label used by a branch future instruction
2187
2188 // Emit the label.
2189 OutStreamer->emitLabel(getBFLabel(DL.getPrivateGlobalPrefix(),
2191 MI->getOperand(0).getIndex(), OutContext));
2192 return;
2193 }
2194 case ARM::tPICADD: {
2195 // This is a pseudo op for a label + instruction sequence, which looks like:
2196 // LPC0:
2197 // add r0, pc
2198 // This adds the address of LPC0 to r0.
2199
2200 // Emit the label.
2201 OutStreamer->emitLabel(getPICLabel(DL.getPrivateGlobalPrefix(),
2203 MI->getOperand(2).getImm(), OutContext));
2204
2205 // Form and emit the add.
2207 .addReg(MI->getOperand(0).getReg())
2208 .addReg(MI->getOperand(0).getReg())
2209 .addReg(ARM::PC)
2210 // Add predicate operands.
2212 .addReg(0));
2213 return;
2214 }
2215 case ARM::PICADD: {
2216 // This is a pseudo op for a label + instruction sequence, which looks like:
2217 // LPC0:
2218 // add r0, pc, r0
2219 // This adds the address of LPC0 to r0.
2220
2221 // Emit the label.
2222 OutStreamer->emitLabel(getPICLabel(DL.getPrivateGlobalPrefix(),
2224 MI->getOperand(2).getImm(), OutContext));
2225
2226 // Form and emit the add.
2228 .addReg(MI->getOperand(0).getReg())
2229 .addReg(ARM::PC)
2230 .addReg(MI->getOperand(1).getReg())
2231 // Add predicate operands.
2232 .addImm(MI->getOperand(3).getImm())
2233 .addReg(MI->getOperand(4).getReg())
2234 // Add 's' bit operand (always reg0 for this)
2235 .addReg(0));
2236 return;
2237 }
2238 case ARM::PICSTR:
2239 case ARM::PICSTRB:
2240 case ARM::PICSTRH:
2241 case ARM::PICLDR:
2242 case ARM::PICLDRB:
2243 case ARM::PICLDRH:
2244 case ARM::PICLDRSB:
2245 case ARM::PICLDRSH: {
2246 // This is a pseudo op for a label + instruction sequence, which looks like:
2247 // LPC0:
2248 // OP r0, [pc, r0]
2249 // The LCP0 label is referenced by a constant pool entry in order to get
2250 // a PC-relative address at the ldr instruction.
2251
2252 // Emit the label.
2253 OutStreamer->emitLabel(getPICLabel(DL.getPrivateGlobalPrefix(),
2255 MI->getOperand(2).getImm(), OutContext));
2256
2257 // Form and emit the load
2258 unsigned Opcode;
2259 switch (MI->getOpcode()) {
2260 default:
2261 llvm_unreachable("Unexpected opcode!");
2262 case ARM::PICSTR: Opcode = ARM::STRrs; break;
2263 case ARM::PICSTRB: Opcode = ARM::STRBrs; break;
2264 case ARM::PICSTRH: Opcode = ARM::STRH; break;
2265 case ARM::PICLDR: Opcode = ARM::LDRrs; break;
2266 case ARM::PICLDRB: Opcode = ARM::LDRBrs; break;
2267 case ARM::PICLDRH: Opcode = ARM::LDRH; break;
2268 case ARM::PICLDRSB: Opcode = ARM::LDRSB; break;
2269 case ARM::PICLDRSH: Opcode = ARM::LDRSH; break;
2270 }
2272 .addReg(MI->getOperand(0).getReg())
2273 .addReg(ARM::PC)
2274 .addReg(MI->getOperand(1).getReg())
2275 .addImm(0)
2276 // Add predicate operands.
2277 .addImm(MI->getOperand(3).getImm())
2278 .addReg(MI->getOperand(4).getReg()));
2279
2280 return;
2281 }
2282 case ARM::CONSTPOOL_ENTRY: {
2283 assert(!STI.genExecuteOnly() &&
2284 "execute-only should not generate constant pools");
2285
2286 /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool
2287 /// in the function. The first operand is the ID# for this instruction, the
2288 /// second is the index into the MachineConstantPool that this is, the third
2289 /// is the size in bytes of this constant pool entry.
2290 /// The required alignment is specified on the basic block holding this MI.
2291 unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
2292 unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
2293
2294 // If this is the first entry of the pool, mark it.
2295 if (!InConstantPool) {
2296 OutStreamer->emitDataRegion(MCDR_DataRegion);
2297 InConstantPool = true;
2298 }
2299
2300 OutStreamer->emitLabel(GetCPISymbol(LabelId));
2301
2302 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
2303 if (MCPE.isMachineConstantPoolEntry())
2305 else
2307 return;
2308 }
2309 case ARM::JUMPTABLE_ADDRS:
2311 return;
2312 case ARM::JUMPTABLE_INSTS:
2314 return;
2315 case ARM::JUMPTABLE_TBB:
2316 case ARM::JUMPTABLE_TBH:
2317 emitJumpTableTBInst(MI, MI->getOpcode() == ARM::JUMPTABLE_TBB ? 1 : 2);
2318 return;
2319 case ARM::t2BR_JT: {
2321 .addReg(ARM::PC)
2322 .addReg(MI->getOperand(0).getReg())
2323 // Add predicate operands.
2325 .addReg(0));
2326 return;
2327 }
2328 case ARM::t2TBB_JT:
2329 case ARM::t2TBH_JT: {
2330 unsigned Opc = MI->getOpcode() == ARM::t2TBB_JT ? ARM::t2TBB : ARM::t2TBH;
2331 // Lower and emit the PC label, then the instruction itself.
2332 OutStreamer->emitLabel(GetCPISymbol(MI->getOperand(3).getImm()));
2334 .addReg(MI->getOperand(0).getReg())
2335 .addReg(MI->getOperand(1).getReg())
2336 // Add predicate operands.
2338 .addReg(0));
2339 return;
2340 }
2341 case ARM::tTBB_JT:
2342 case ARM::tTBH_JT: {
2343
2344 bool Is8Bit = MI->getOpcode() == ARM::tTBB_JT;
2345 Register Base = MI->getOperand(0).getReg();
2346 Register Idx = MI->getOperand(1).getReg();
2347 assert(MI->getOperand(1).isKill() && "We need the index register as scratch!");
2348
2349 // Multiply up idx if necessary.
2350 if (!Is8Bit)
2352 .addReg(Idx)
2353 .addReg(ARM::CPSR)
2354 .addReg(Idx)
2355 .addImm(1)
2356 // Add predicate operands.
2357 .addImm(ARMCC::AL)
2358 .addReg(0));
2359
2360 if (Base == ARM::PC) {
2361 // TBB [base, idx] =
2362 // ADDS idx, idx, base
2363 // LDRB idx, [idx, #4] ; or LDRH if TBH
2364 // LSLS idx, #1
2365 // ADDS pc, pc, idx
2366
2367 // When using PC as the base, it's important that there is no padding
2368 // between the last ADDS and the start of the jump table. The jump table
2369 // is 4-byte aligned, so we ensure we're 4 byte aligned here too.
2370 //
2371 // FIXME: Ideally we could vary the LDRB index based on the padding
2372 // between the sequence and jump table, however that relies on MCExprs
2373 // for load indexes which are currently not supported.
2374 OutStreamer->emitCodeAlignment(Align(4), &getSubtargetInfo());
2376 .addReg(Idx)
2377 .addReg(Idx)
2378 .addReg(Base)
2379 // Add predicate operands.
2380 .addImm(ARMCC::AL)
2381 .addReg(0));
2382
2383 unsigned Opc = Is8Bit ? ARM::tLDRBi : ARM::tLDRHi;
2385 .addReg(Idx)
2386 .addReg(Idx)
2387 .addImm(Is8Bit ? 4 : 2)
2388 // Add predicate operands.
2389 .addImm(ARMCC::AL)
2390 .addReg(0));
2391 } else {
2392 // TBB [base, idx] =
2393 // LDRB idx, [base, idx] ; or LDRH if TBH
2394 // LSLS idx, #1
2395 // ADDS pc, pc, idx
2396
2397 unsigned Opc = Is8Bit ? ARM::tLDRBr : ARM::tLDRHr;
2399 .addReg(Idx)
2400 .addReg(Base)
2401 .addReg(Idx)
2402 // Add predicate operands.
2403 .addImm(ARMCC::AL)
2404 .addReg(0));
2405 }
2406
2408 .addReg(Idx)
2409 .addReg(ARM::CPSR)
2410 .addReg(Idx)
2411 .addImm(1)
2412 // Add predicate operands.
2413 .addImm(ARMCC::AL)
2414 .addReg(0));
2415
2416 OutStreamer->emitLabel(GetCPISymbol(MI->getOperand(3).getImm()));
2418 .addReg(ARM::PC)
2419 .addReg(ARM::PC)
2420 .addReg(Idx)
2421 // Add predicate operands.
2422 .addImm(ARMCC::AL)
2423 .addReg(0));
2424 return;
2425 }
2426 case ARM::tBR_JTr:
2427 case ARM::BR_JTr: {
2428 // mov pc, target
2429 MCInst TmpInst;
2430 unsigned Opc = MI->getOpcode() == ARM::BR_JTr ?
2431 ARM::MOVr : ARM::tMOVr;
2432 TmpInst.setOpcode(Opc);
2433 TmpInst.addOperand(MCOperand::createReg(ARM::PC));
2434 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
2435 // Add predicate operands.
2437 TmpInst.addOperand(MCOperand::createReg(0));
2438 // Add 's' bit operand (always reg0 for this)
2439 if (Opc == ARM::MOVr)
2440 TmpInst.addOperand(MCOperand::createReg(0));
2441 EmitToStreamer(*OutStreamer, TmpInst);
2442 return;
2443 }
2444 case ARM::BR_JTm_i12: {
2445 // ldr pc, target
2446 MCInst TmpInst;
2447 TmpInst.setOpcode(ARM::LDRi12);
2448 TmpInst.addOperand(MCOperand::createReg(ARM::PC));
2449 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
2450 TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm()));
2451 // Add predicate operands.
2453 TmpInst.addOperand(MCOperand::createReg(0));
2454 EmitToStreamer(*OutStreamer, TmpInst);
2455 return;
2456 }
2457 case ARM::BR_JTm_rs: {
2458 // ldr pc, target
2459 MCInst TmpInst;
2460 TmpInst.setOpcode(ARM::LDRrs);
2461 TmpInst.addOperand(MCOperand::createReg(ARM::PC));
2462 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
2463 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(1).getReg()));
2464 TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm()));
2465 // Add predicate operands.
2467 TmpInst.addOperand(MCOperand::createReg(0));
2468 EmitToStreamer(*OutStreamer, TmpInst);
2469 return;
2470 }
2471 case ARM::BR_JTadd: {
2472 // add pc, target, idx
2474 .addReg(ARM::PC)
2475 .addReg(MI->getOperand(0).getReg())
2476 .addReg(MI->getOperand(1).getReg())
2477 // Add predicate operands.
2479 .addReg(0)
2480 // Add 's' bit operand (always reg0 for this)
2481 .addReg(0));
2482 return;
2483 }
2484 case ARM::SPACE:
2485 OutStreamer->emitZeros(MI->getOperand(1).getImm());
2486 return;
2487 case ARM::TRAP: {
2488 // Non-Darwin binutils don't yet support the "trap" mnemonic.
2489 // FIXME: Remove this special case when they do.
2490 if (!TM.getTargetTriple().isOSBinFormatMachO()) {
2491 uint32_t Val = 0xe7ffdefeUL;
2492 OutStreamer->AddComment("trap");
2493 ATS.emitInst(Val);
2494 return;
2495 }
2496 break;
2497 }
2498 case ARM::tTRAP: {
2499 // Non-Darwin binutils don't yet support the "trap" mnemonic.
2500 // FIXME: Remove this special case when they do.
2501 if (!TM.getTargetTriple().isOSBinFormatMachO()) {
2502 uint16_t Val = 0xdefe;
2503 OutStreamer->AddComment("trap");
2504 ATS.emitInst(Val, 'n');
2505 return;
2506 }
2507 break;
2508 }
2509 case ARM::t2Int_eh_sjlj_setjmp:
2510 case ARM::t2Int_eh_sjlj_setjmp_nofp:
2511 case ARM::tInt_eh_sjlj_setjmp: {
2512 // Two incoming args: GPR:$src, GPR:$val
2513 // mov $val, pc
2514 // adds $val, #7
2515 // str $val, [$src, #4]
2516 // movs r0, #0
2517 // b LSJLJEH
2518 // movs r0, #1
2519 // LSJLJEH:
2520 Register SrcReg = MI->getOperand(0).getReg();
2521 Register ValReg = MI->getOperand(1).getReg();
2522 MCSymbol *Label = OutContext.createTempSymbol("SJLJEH");
2523 OutStreamer->AddComment("eh_setjmp begin");
2525 .addReg(ValReg)
2526 .addReg(ARM::PC)
2527 // Predicate.
2528 .addImm(ARMCC::AL)
2529 .addReg(0));
2530
2532 .addReg(ValReg)
2533 // 's' bit operand
2534 .addReg(ARM::CPSR)
2535 .addReg(ValReg)
2536 .addImm(7)
2537 // Predicate.
2538 .addImm(ARMCC::AL)
2539 .addReg(0));
2540
2542 .addReg(ValReg)
2543 .addReg(SrcReg)
2544 // The offset immediate is #4. The operand value is scaled by 4 for the
2545 // tSTR instruction.
2546 .addImm(1)
2547 // Predicate.
2548 .addImm(ARMCC::AL)
2549 .addReg(0));
2550
2552 .addReg(ARM::R0)
2553 .addReg(ARM::CPSR)
2554 .addImm(0)
2555 // Predicate.
2556 .addImm(ARMCC::AL)
2557 .addReg(0));
2558
2559 const MCExpr *SymbolExpr = MCSymbolRefExpr::create(Label, OutContext);
2561 .addExpr(SymbolExpr)
2562 .addImm(ARMCC::AL)
2563 .addReg(0));
2564
2565 OutStreamer->AddComment("eh_setjmp end");
2567 .addReg(ARM::R0)
2568 .addReg(ARM::CPSR)
2569 .addImm(1)
2570 // Predicate.
2571 .addImm(ARMCC::AL)
2572 .addReg(0));
2573
2574 OutStreamer->emitLabel(Label);
2575 return;
2576 }
2577
2578 case ARM::Int_eh_sjlj_setjmp_nofp:
2579 case ARM::Int_eh_sjlj_setjmp: {
2580 // Two incoming args: GPR:$src, GPR:$val
2581 // add $val, pc, #8
2582 // str $val, [$src, #+4]
2583 // mov r0, #0
2584 // add pc, pc, #0
2585 // mov r0, #1
2586 Register SrcReg = MI->getOperand(0).getReg();
2587 Register ValReg = MI->getOperand(1).getReg();
2588
2589 OutStreamer->AddComment("eh_setjmp begin");
2591 .addReg(ValReg)
2592 .addReg(ARM::PC)
2593 .addImm(8)
2594 // Predicate.
2595 .addImm(ARMCC::AL)
2596 .addReg(0)
2597 // 's' bit operand (always reg0 for this).
2598 .addReg(0));
2599
2601 .addReg(ValReg)
2602 .addReg(SrcReg)
2603 .addImm(4)
2604 // Predicate.
2605 .addImm(ARMCC::AL)
2606 .addReg(0));
2607
2609 .addReg(ARM::R0)
2610 .addImm(0)
2611 // Predicate.
2612 .addImm(ARMCC::AL)
2613 .addReg(0)
2614 // 's' bit operand (always reg0 for this).
2615 .addReg(0));
2616
2618 .addReg(ARM::PC)
2619 .addReg(ARM::PC)
2620 .addImm(0)
2621 // Predicate.
2622 .addImm(ARMCC::AL)
2623 .addReg(0)
2624 // 's' bit operand (always reg0 for this).
2625 .addReg(0));
2626
2627 OutStreamer->AddComment("eh_setjmp end");
2629 .addReg(ARM::R0)
2630 .addImm(1)
2631 // Predicate.
2632 .addImm(ARMCC::AL)
2633 .addReg(0)
2634 // 's' bit operand (always reg0 for this).
2635 .addReg(0));
2636 return;
2637 }
2638 case ARM::Int_eh_sjlj_longjmp: {
2639 // ldr sp, [$src, #8]
2640 // ldr $scratch, [$src, #4]
2641 // ldr r7, [$src]
2642 // bx $scratch
2643 Register SrcReg = MI->getOperand(0).getReg();
2644 Register ScratchReg = MI->getOperand(1).getReg();
2646 .addReg(ARM::SP)
2647 .addReg(SrcReg)
2648 .addImm(8)
2649 // Predicate.
2650 .addImm(ARMCC::AL)
2651 .addReg(0));
2652
2654 .addReg(ScratchReg)
2655 .addReg(SrcReg)
2656 .addImm(4)
2657 // Predicate.
2658 .addImm(ARMCC::AL)
2659 .addReg(0));
2660
2661 if (STI.isTargetDarwin() || STI.isTargetWindows()) {
2662 // These platforms always use the same frame register
2664 .addReg(STI.getFramePointerReg())
2665 .addReg(SrcReg)
2666 .addImm(0)
2667 // Predicate.
2669 .addReg(0));
2670 } else {
2671 // If the calling code might use either R7 or R11 as
2672 // frame pointer register, restore it into both.
2674 .addReg(ARM::R7)
2675 .addReg(SrcReg)
2676 .addImm(0)
2677 // Predicate.
2678 .addImm(ARMCC::AL)
2679 .addReg(0));
2681 .addReg(ARM::R11)
2682 .addReg(SrcReg)
2683 .addImm(0)
2684 // Predicate.
2685 .addImm(ARMCC::AL)
2686 .addReg(0));
2687 }
2688
2689 assert(STI.hasV4TOps());
2691 .addReg(ScratchReg)
2692 // Predicate.
2693 .addImm(ARMCC::AL)
2694 .addReg(0));
2695 return;
2696 }
2697 case ARM::tInt_eh_sjlj_longjmp: {
2698 // ldr $scratch, [$src, #8]
2699 // mov sp, $scratch
2700 // ldr $scratch, [$src, #4]
2701 // ldr r7, [$src]
2702 // bx $scratch
2703 Register SrcReg = MI->getOperand(0).getReg();
2704 Register ScratchReg = MI->getOperand(1).getReg();
2705
2707 .addReg(ScratchReg)
2708 .addReg(SrcReg)
2709 // The offset immediate is #8. The operand value is scaled by 4 for the
2710 // tLDR instruction.
2711 .addImm(2)
2712 // Predicate.
2713 .addImm(ARMCC::AL)
2714 .addReg(0));
2715
2717 .addReg(ARM::SP)
2718 .addReg(ScratchReg)
2719 // Predicate.
2720 .addImm(ARMCC::AL)
2721 .addReg(0));
2722
2724 .addReg(ScratchReg)
2725 .addReg(SrcReg)
2726 .addImm(1)
2727 // Predicate.
2728 .addImm(ARMCC::AL)
2729 .addReg(0));
2730
2731 if (STI.isTargetDarwin() || STI.isTargetWindows()) {
2732 // These platforms always use the same frame register
2734 .addReg(STI.getFramePointerReg())
2735 .addReg(SrcReg)
2736 .addImm(0)
2737 // Predicate.
2739 .addReg(0));
2740 } else {
2741 // If the calling code might use either R7 or R11 as
2742 // frame pointer register, restore it into both.
2744 .addReg(ARM::R7)
2745 .addReg(SrcReg)
2746 .addImm(0)
2747 // Predicate.
2748 .addImm(ARMCC::AL)
2749 .addReg(0));
2751 .addReg(ARM::R11)
2752 .addReg(SrcReg)
2753 .addImm(0)
2754 // Predicate.
2755 .addImm(ARMCC::AL)
2756 .addReg(0));
2757 }
2758
2760 .addReg(ScratchReg)
2761 // Predicate.
2762 .addImm(ARMCC::AL)
2763 .addReg(0));
2764 return;
2765 }
2766 case ARM::tInt_WIN_eh_sjlj_longjmp: {
2767 // ldr.w r11, [$src, #0]
2768 // ldr.w sp, [$src, #8]
2769 // ldr.w pc, [$src, #4]
2770
2771 Register SrcReg = MI->getOperand(0).getReg();
2772
2774 .addReg(ARM::R11)
2775 .addReg(SrcReg)
2776 .addImm(0)
2777 // Predicate
2778 .addImm(ARMCC::AL)
2779 .addReg(0));
2781 .addReg(ARM::SP)
2782 .addReg(SrcReg)
2783 .addImm(8)
2784 // Predicate
2785 .addImm(ARMCC::AL)
2786 .addReg(0));
2788 .addReg(ARM::PC)
2789 .addReg(SrcReg)
2790 .addImm(4)
2791 // Predicate
2792 .addImm(ARMCC::AL)
2793 .addReg(0));
2794 return;
2795 }
2796 case ARM::PATCHABLE_FUNCTION_ENTER:
2798 return;
2799 case ARM::PATCHABLE_FUNCTION_EXIT:
2801 return;
2802 case ARM::PATCHABLE_TAIL_CALL:
2804 return;
2805 case ARM::SpeculationBarrierISBDSBEndBB: {
2806 // Print DSB SYS + ISB
2807 MCInst TmpInstDSB;
2808 TmpInstDSB.setOpcode(ARM::DSB);
2809 TmpInstDSB.addOperand(MCOperand::createImm(0xf));
2810 EmitToStreamer(*OutStreamer, TmpInstDSB);
2811 MCInst TmpInstISB;
2812 TmpInstISB.setOpcode(ARM::ISB);
2813 TmpInstISB.addOperand(MCOperand::createImm(0xf));
2814 EmitToStreamer(*OutStreamer, TmpInstISB);
2815 return;
2816 }
2817 case ARM::t2SpeculationBarrierISBDSBEndBB: {
2818 // Print DSB SYS + ISB
2819 MCInst TmpInstDSB;
2820 TmpInstDSB.setOpcode(ARM::t2DSB);
2821 TmpInstDSB.addOperand(MCOperand::createImm(0xf));
2823 TmpInstDSB.addOperand(MCOperand::createReg(0));
2824 EmitToStreamer(*OutStreamer, TmpInstDSB);
2825 MCInst TmpInstISB;
2826 TmpInstISB.setOpcode(ARM::t2ISB);
2827 TmpInstISB.addOperand(MCOperand::createImm(0xf));
2829 TmpInstISB.addOperand(MCOperand::createReg(0));
2830 EmitToStreamer(*OutStreamer, TmpInstISB);
2831 return;
2832 }
2833 case ARM::SpeculationBarrierSBEndBB: {
2834 // Print SB
2835 MCInst TmpInstSB;
2836 TmpInstSB.setOpcode(ARM::SB);
2837 EmitToStreamer(*OutStreamer, TmpInstSB);
2838 return;
2839 }
2840 case ARM::t2SpeculationBarrierSBEndBB: {
2841 // Print SB
2842 MCInst TmpInstSB;
2843 TmpInstSB.setOpcode(ARM::t2SB);
2844 EmitToStreamer(*OutStreamer, TmpInstSB);
2845 return;
2846 }
2847
2848 case ARM::SEH_StackAlloc:
2849 ATS.emitARMWinCFIAllocStack(MI->getOperand(0).getImm(),
2850 MI->getOperand(1).getImm());
2851 return;
2852
2853 case ARM::SEH_SaveRegs:
2854 case ARM::SEH_SaveRegs_Ret:
2855 ATS.emitARMWinCFISaveRegMask(MI->getOperand(0).getImm(),
2856 MI->getOperand(1).getImm());
2857 return;
2858
2859 case ARM::SEH_SaveSP:
2860 ATS.emitARMWinCFISaveSP(MI->getOperand(0).getImm());
2861 return;
2862
2863 case ARM::SEH_SaveFRegs:
2864 ATS.emitARMWinCFISaveFRegs(MI->getOperand(0).getImm(),
2865 MI->getOperand(1).getImm());
2866 return;
2867
2868 case ARM::SEH_SaveLR:
2869 ATS.emitARMWinCFISaveLR(MI->getOperand(0).getImm());
2870 return;
2871
2872 case ARM::SEH_Nop:
2873 case ARM::SEH_Nop_Ret:
2874 ATS.emitARMWinCFINop(MI->getOperand(0).getImm());
2875 return;
2876
2877 case ARM::SEH_PrologEnd:
2878 ATS.emitARMWinCFIPrologEnd(/*Fragment=*/false);
2879 return;
2880
2881 case ARM::SEH_EpilogStart:
2883 return;
2884
2885 case ARM::SEH_EpilogEnd:
2887 return;
2888 }
2889
2890 MCInst TmpInst;
2891 LowerARMMachineInstrToMCInst(MI, TmpInst, *this);
2892
2893 EmitToStreamer(*OutStreamer, TmpInst);
2894}
2895
2896char ARMAsmPrinter::ID = 0;
2897
2898INITIALIZE_PASS(ARMAsmPrinter, "arm-asm-printer", "ARM Assembly Printer", false,
2899 false)
2900
2901//===----------------------------------------------------------------------===//
2902// Target Registry Stuff
2903//===----------------------------------------------------------------------===//
2904
2905// Force static initialization.
2906extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
2907LLVMInitializeARMAsmPrinter() {
2912}
unsigned SubReg
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool isRegisterLiveInCall(const MachineInstr &Call, MCRegister Reg)
static void emitNonLazySymbolPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel, MachineModuleInfoImpl::StubValueTy &MCSym)
static uint8_t getModifierSpecifier(ARMCP::ARMCPModifier Modifier)
static MCSymbol * getPICLabel(StringRef Prefix, unsigned FunctionNumber, unsigned LabelId, MCContext &Ctx)
static bool checkDenormalAttributeInconsistency(const Module &M)
static bool checkFunctionsAttributeConsistency(const Module &M, StringRef Attr, StringRef Value)
static bool isThumb(const MCSubtargetInfo &STI)
static MCSymbol * getBFLabel(StringRef Prefix, unsigned FunctionNumber, unsigned LabelId, MCContext &Ctx)
static bool checkDenormalAttributeConsistency(const Module &M, StringRef Attr, DenormalMode Value)
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define LLVM_ABI
Definition Compiler.h:213
#define LLVM_EXTERNAL_VISIBILITY
Definition Compiler.h:132
This file contains the declarations for the subclasses of Constant, which represent the different fla...
IRTranslator LLVM IR MI
Module.h This file contains the declarations for the Module class.
const size_t AbstractManglingParser< Derived, Alloc >::NumOps
#define F(x, y, z)
Definition MD5.cpp:54
Machine Check Debug Module
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
static bool contains(SmallPtrSetImpl< ConstantExpr * > &Cache, ConstantExpr *Expr, Constant *C)
Definition Value.cpp:480
This file defines the SmallString class.
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
static TableGen::Emitter::OptClass< SkeletonEmitter > X("gen-skeleton-class", "Generate example skeleton class")
static const unsigned FramePtr
void emitJumpTableAddrs(const MachineInstr *MI)
void emitJumpTableTBInst(const MachineInstr *MI, unsigned OffsetWidth)
void emitFunctionBodyEnd() override
Targets can override this to emit stuff after the last basic block in the function.
bool runOnMachineFunction(MachineFunction &F) override
runOnMachineFunction - This uses the emitInstruction() method to print assembly for each instruction.
MCSymbol * GetCPISymbol(unsigned CPID) const override
Return the symbol for the specified constant pool entry.
void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O)
void emitStartOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the start of their fi...
ARMAsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > Streamer)
void emitFunctionEntryLabel() override
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, const MCSubtargetInfo *EndInfo) const override
Let the target do anything it needs to do after emitting inlineasm.
void LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI)
void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override
EmitMachineConstantPoolValue - Print a machine constantpool value to the .s file.
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, const char *ExtraCode, raw_ostream &O) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
void emitXXStructor(const DataLayout &DL, const Constant *CV) override
Targets can override this to change how global constants that are part of a C++ static/global constru...
void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI)
void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI)
void emitEndOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the end of their file...
std::tuple< const MCSymbol *, uint64_t, const MCSymbol *, codeview::JumpTableEntrySize > getCodeViewJumpTableInfo(int JTI, const MachineInstr *BranchInstr, const MCSymbol *BranchLabel) const override
Gets information required to create a CodeView debug symbol for a jump table.
void emitJumpTableInsts(const MachineInstr *MI)
const ARMBaseTargetMachine & getTM() const
void emitGlobalVariable(const GlobalVariable *GV) override
Emit the specified global variable to the .s file.
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, const char *ExtraCode, raw_ostream &O) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
void emitInstruction(const MachineInstr *MI) override
Targets should implement this to emit instructions.
void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override
Print the MachineOperand as a symbol.
void LowerKCFI_CHECK(const MachineInstr &MI)
bool isGVIndirectSymbol(const GlobalValue *GV) const
ARMConstantPoolValue - ARM specific constantpool value.
unsigned char getPCAdjustment() const
ARMCP::ARMCPModifier getModifier() const
ARMFunctionInfo - This class is derived from MachineFunctionInfo and contains private ARM-specific in...
static const char * getRegisterName(MCRegister Reg, unsigned AltIdx=ARM::NoRegAltName)
bool isThumb1Only() const
MCPhysReg getFramePointerReg() const
bool isTargetWindows() const
bool isTargetDarwin() const
void emitTargetAttributes(const MCSubtargetInfo &STI)
Emit the build attributes that only depend on the hardware that we expect.
virtual void emitSetFP(MCRegister FpReg, MCRegister SpReg, int64_t Offset=0)
virtual void finishAttributeSection()
virtual void emitMovSP(MCRegister Reg, int64_t Offset=0)
virtual void emitARMWinCFISaveSP(unsigned Reg)
virtual void emitInst(uint32_t Inst, char Suffix='\0')
virtual void emitARMWinCFISaveLR(unsigned Offset)
virtual void emitTextAttribute(unsigned Attribute, StringRef String)
virtual void emitARMWinCFIAllocStack(unsigned Size, bool Wide)
virtual void emitARMWinCFISaveRegMask(unsigned Mask, bool Wide)
virtual void emitRegSave(const SmallVectorImpl< MCRegister > &RegList, bool isVector)
virtual void emitARMWinCFIEpilogEnd()
virtual void emitARMWinCFIPrologEnd(bool Fragment)
virtual void switchVendor(StringRef Vendor)
virtual void emitARMWinCFISaveFRegs(unsigned First, unsigned Last)
virtual void emitARMWinCFIEpilogStart(unsigned Condition)
virtual void emitPad(int64_t Offset)
virtual void emitAttribute(unsigned Attribute, unsigned Value)
virtual void emitARMWinCFINop(bool Wide)
const TargetLoweringObjectFile & getObjFileLowering() const
Return information about object file lowering.
MCSymbol * getSymbolWithGlobalValueBase(const GlobalValue *GV, StringRef Suffix) const
Return the MCSymbol for a private symbol with global value name as its base, with the specified suffi...
MCSymbol * getSymbol(const GlobalValue *GV) const
void EmitToStreamer(MCStreamer &S, const MCInst &Inst)
virtual void emitGlobalVariable(const GlobalVariable *GV)
Emit the specified global variable to the .s file.
TargetMachine & TM
Target machine description.
Definition AsmPrinter.h:99
void emitXRayTable()
Emit a table with all XRay instrumentation points.
MCSymbol * getMBBExceptionSym(const MachineBasicBlock &MBB)
const MCAsmInfo * MAI
Target Asm Printer information.
Definition AsmPrinter.h:102
MachineFunction * MF
The current machine function.
Definition AsmPrinter.h:117
virtual void SetupMachineFunction(MachineFunction &MF)
This should be called when a new MachineFunction is being processed from runOnMachineFunction.
void emitFunctionBody()
This method emits the body and trailer for a function.
virtual void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const
This emits linkage information about GVSym based on GV, if this is supported by the target.
unsigned getFunctionNumber() const
Return a unique ID for the current function.
AsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > Streamer, char &ID=AsmPrinter::ID)
void printOffset(int64_t Offset, raw_ostream &OS) const
This is just convenient handler for printing offsets.
void emitGlobalConstant(const DataLayout &DL, const Constant *CV, AliasMapTy *AliasList=nullptr)
EmitGlobalConstant - Print a general LLVM constant to the .s file.
MCSymbol * getSymbolPreferLocal(const GlobalValue &GV) const
Similar to getSymbol() but preferred for references.
MCSymbol * CurrentFnSym
The symbol for the current function.
Definition AsmPrinter.h:136
MachineModuleInfo * MMI
This is a pointer to the current MachineModuleInfo.
Definition AsmPrinter.h:120
void emitAlignment(Align Alignment, const GlobalObject *GV=nullptr, unsigned MaxBytesToEmit=0) const
Emit an alignment directive to the specified power of two boundary.
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition AsmPrinter.h:106
bool isPositionIndependent() const
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:111
void getNameWithPrefix(SmallVectorImpl< char > &Name, const GlobalValue *GV) const
MCSymbol * GetBlockAddressSymbol(const BlockAddress *BA) const
Return the MCSymbol used to satisfy BlockAddress uses of the specified basic block.
const DataLayout & getDataLayout() const
Return information about data layout.
virtual void emitFunctionEntryLabel()
EmitFunctionEntryLabel - Emit the label that is the entrypoint for the function.
MCSymbol * GetExternalSymbolSymbol(const Twine &Sym) const
Return the MCSymbol for the specified ExternalSymbol.
const MCSubtargetInfo & getSubtargetInfo() const
Return information about subtarget.
virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, const char *ExtraCode, raw_ostream &OS)
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
The address of a basic block.
Definition Constants.h:899
This is an important base class in LLVM.
Definition Constant.h:43
const Constant * stripPointerCasts() const
Definition Constant.h:222
A parsed version of the target data layout string in and methods for querying it.
Definition DataLayout.h:63
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
bool isThreadLocal() const
If the value is "Thread Local", its value isn't shared by the threads.
bool hasInternalLinkage() const
static const MCBinaryExpr * createAdd(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:343
static const MCBinaryExpr * createDiv(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:353
static const MCBinaryExpr * createSub(const MCExpr *LHS, const MCExpr *RHS, MCContext &Ctx)
Definition MCExpr.h:428
static LLVM_ABI const MCConstantExpr * create(int64_t Value, MCContext &Ctx, bool PrintInHex=false, unsigned SizeInBytes=0)
Definition MCExpr.cpp:212
Context object for machine code objects.
Definition MCContext.h:83
LLVM_ABI MCSymbol * getOrCreateSymbol(const Twine &Name)
Lookup the symbol inside with the specified Name.
Base class for the full range of assembler expressions which are needed for parsing.
Definition MCExpr.h:34
MCInstBuilder & addReg(MCRegister Reg)
Add a new register operand.
MCInstBuilder & addImm(int64_t Val)
Add a new integer immediate operand.
MCInstBuilder & addExpr(const MCExpr *Val)
Add a new MCExpr operand.
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
MCSection * getThreadLocalPointerSection() const
MCSection * getNonLazySymbolPointerSection() const
static MCOperand createExpr(const MCExpr *Val)
Definition MCInst.h:166
static MCOperand createReg(MCRegister Reg)
Definition MCInst.h:138
static MCOperand createImm(int64_t Val)
Definition MCInst.h:145
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
Streaming machine code generation interface.
Definition MCStreamer.h:220
virtual bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute)=0
Add the given Attribute to Symbol.
MCContext & getContext() const
Definition MCStreamer.h:314
void emitValue(const MCExpr *Value, unsigned Size, SMLoc Loc=SMLoc())
virtual void emitLabel(MCSymbol *Symbol, SMLoc Loc=SMLoc())
Emit a label for Symbol into the current section.
virtual void emitIntValue(uint64_t Value, unsigned Size)
Special case of EmitValue that avoids the client having to pass in a MCExpr for constant integers.
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx, SMLoc Loc=SMLoc())
Definition MCExpr.h:214
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition MCSymbol.h:42
LLVM_ABI void print(raw_ostream &OS, const MCAsmInfo *MAI) const
print - Print the value to the stream OS.
Definition MCSymbol.cpp:59
Target specific streamer interface.
Definition MCStreamer.h:93
LLVM_ABI MCSymbol * getSymbol() const
Return the MCSymbol for this basic block.
This class is a data container for one entry in a MachineConstantPool.
union llvm::MachineConstantPoolEntry::@004270020304201266316354007027341142157160323045 Val
The constant itself.
bool isMachineConstantPoolEntry() const
isMachineConstantPoolEntry - Return true if the MachineConstantPoolEntry is indeed a target specific ...
MachineConstantPoolValue * MachineCPVal
Abstract base class for all machine specific constantpool value subclasses.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const MachineOperand & getOperand(unsigned i) const
const std::vector< MachineJumpTableEntry > & getJumpTables() const
StubValueTy & getGVStubEntry(MCSymbol *Sym)
std::vector< std::pair< MCSymbol *, StubValueTy > > SymbolListTy
PointerIntPair< MCSymbol *, 1, bool > StubValueTy
MachineModuleInfoMachO - This is a MachineModuleInfoImpl implementation for MachO targets.
StubValueTy & getGVStubEntry(MCSymbol *Sym)
StubValueTy & getThreadLocalGVStubEntry(MCSymbol *Sym)
SymbolListTy GetGVStubList()
Accessor methods to return the set of stubs in sorted order.
MachineOperand class - Representation of each machine instruction operand.
unsigned getSubReg() const
const GlobalValue * getGlobal() const
int64_t getImm() const
bool isReg() const
isReg - Tests if this is a MO_Register operand.
MachineBasicBlock * getMBB() const
bool isImm() const
isImm - Tests if this is a MO_Immediate operand.
unsigned getTargetFlags() const
bool isGlobal() const
isGlobal - Tests if this is a MO_GlobalAddress operand.
MachineOperandType getType() const
getType - Returns the MachineOperandType for this operand.
Register getReg() const
getReg - Returns the register number.
@ MO_Immediate
Immediate operand.
@ MO_ConstantPoolIndex
Address of indexed Constant in Constant Pool.
@ MO_GlobalAddress
Address of a global value.
@ MO_MachineBasicBlock
MachineBasicBlock reference.
@ MO_Register
Register operand.
int64_t getOffset() const
Return the offset from the symbol in this operand.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
virtual void print(raw_ostream &OS, const Module *M) const
print - Print out the internal state of the pass.
Definition Pass.cpp:140
Pass(PassKind K, char &pid)
Definition Pass.h:105
IntType getInt() const
PointerTy getPointer() const
Wrapper class representing virtual and physical registers.
Definition Register.h:20
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
Primary interface to the complete machine description for the target machine.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
TypeSize getRegSizeInBits(const TargetRegisterClass &RC) const
Return the size in bits of a register from class RC.
virtual Register getFrameRegister(const MachineFunction &MF) const =0
Debug information queries.
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
LLVM Value Representation.
Definition Value.h:75
Type * getType() const
All values are typed, get the type of this value.
Definition Value.h:256
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
A raw_ostream that writes to an SmallVector or SmallString.
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ SECREL
Thread Pointer Offset.
@ GOT_PREL
Thread Local Storage (General Dynamic Mode)
@ SBREL
Section Relative (Windows TLS)
@ GOTTPOFF
Global Offset Table, PC Relative.
@ TPOFF
Global Offset Table, Thread Pointer Offset.
@ MO_LO16
MO_LO16 - On a symbol operand, this represents a relocation containing lower 16 bit of the address.
@ MO_LO_0_7
MO_LO_0_7 - On a symbol operand, this represents a relocation containing bits 0 through 7 of the addr...
@ MO_LO_8_15
MO_LO_8_15 - On a symbol operand, this represents a relocation containing bits 8 through 15 of the ad...
@ MO_NONLAZY
MO_NONLAZY - This is an independent flag, on a symbol operand "FOO" it represents a symbol which,...
@ MO_HI_8_15
MO_HI_8_15 - On a symbol operand, this represents a relocation containing bits 24 through 31 of the a...
@ MO_HI16
MO_HI16 - On a symbol operand, this represents a relocation containing higher 16 bit of the address.
@ MO_DLLIMPORT
MO_DLLIMPORT - On a symbol operand, this represents that the reference to the symbol is for an import...
@ MO_HI_0_7
MO_HI_0_7 - On a symbol operand, this represents a relocation containing bits 16 through 23 of the ad...
@ MO_COFFSTUB
MO_COFFSTUB - On a symbol operand "FOO", this indicates that the reference is actually to the "....
int getSOImmVal(unsigned Arg)
getSOImmVal - Given a 32-bit immediate, if it is something that can fit into an shifter_operand immed...
int getT2SOImmVal(unsigned Arg)
getT2SOImmVal - Given a 32-bit immediate, if it is something that can fit into a Thumb-2 shifter_oper...
std::string ParseARMTriple(const Triple &TT, StringRef CPU)
const MCSpecifierExpr * createLower16(const MCExpr *Expr, MCContext &Ctx)
const MCSpecifierExpr * createUpper16(const MCExpr *Expr, MCContext &Ctx)
SymbolStorageClass
Storage class tells where and what the symbol represents.
Definition COFF.h:218
@ IMAGE_SYM_CLASS_EXTERNAL
External symbol.
Definition COFF.h:224
@ IMAGE_SYM_CLASS_STATIC
Static.
Definition COFF.h:225
@ IMAGE_SYM_DTYPE_FUNCTION
A function that returns a base type.
Definition COFF.h:276
@ SCT_COMPLEX_TYPE_SHIFT
Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT))
Definition COFF.h:280
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract_or_null(Y &&MD)
Extract a Value from Metadata, allowing null.
Definition Metadata.h:682
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:532
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
Target & getTheThumbBETarget()
@ MCDR_DataRegionEnd
.end_data_region
@ MCDR_DataRegion
.data_region
@ MCDR_DataRegionJT8
.data_region jt8
@ MCDR_DataRegionJT32
.data_region jt32
@ MCDR_DataRegionJT16
.data_region jt16
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1732
MachineInstr * getImm(const MachineOperand &MO, const MachineRegisterInfo *MRI)
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void LowerARMMachineInstrToMCInst(const MachineInstr *MI, MCInst &OutMI, ARMAsmPrinter &AP)
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
DWARFExpression::Operation Op
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1867
DenormalMode parseDenormalFPAttribute(StringRef Str)
Returns the denormal mode to use for inputs and outputs.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
Target & getTheARMLETarget()
unsigned convertAddSubFlagsOpcode(unsigned OldOpc)
Map pseudo instructions that imply an 'S' bit onto real opcodes.
@ MCSA_IndirectSymbol
.indirect_symbol (MachO)
@ MCSA_ELF_TypeFunction
.type _foo, STT_FUNC # aka @function
Target & getTheARMBETarget()
Target & getTheThumbLETarget()
Implement std::hash so that hash_code can be used in STL containers.
Definition BitVector.h:867
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39
Represent subnormal handling kind for floating point instruction inputs and outputs.
static constexpr DenormalMode getPositiveZero()
static constexpr DenormalMode getPreserveSign()
static constexpr DenormalMode getIEEE()
RegisterAsmPrinter - Helper template for registering a target specific assembly printer,...