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