LLVM 23.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,
523 const MachineInstr *MI) {
524 // If either end mode is unknown (EndInfo == NULL) or different than
525 // the start mode, then restore the start mode.
526 const bool WasThumb = isThumb(StartInfo);
527 if (!EndInfo || WasThumb != isThumb(*EndInfo)) {
528 auto &TS =
529 static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());
530 if (WasThumb)
531 TS.emitCode16();
532 else
533 TS.emitCode32();
534 }
535}
536
538 const Triple &TT = TM.getTargetTriple();
539 auto &TS =
540 static_cast<ARMTargetStreamer &>(*OutStreamer->getTargetStreamer());
541 // Use unified assembler syntax.
543
544 // Emit ARM Build Attributes
545 if (TT.isOSBinFormatELF())
546 emitAttributes();
547
548 // Use the triple's architecture and subarchitecture to determine
549 // if we're thumb for the purposes of the top level code16 state.
550 if (!M.getModuleInlineAsm().empty() && TT.isThumb())
551 TS.emitCode16();
552}
553
554static void
557 // L_foo$stub:
558 OutStreamer.emitLabel(StubLabel);
559 // .indirect_symbol _foo
561
562 if (MCSym.getInt())
563 // External to current translation unit.
564 OutStreamer.emitIntValue(0, 4/*size*/);
565 else
566 // Internal to current translation unit.
567 //
568 // When we place the LSDA into the TEXT section, the type info
569 // pointers need to be indirect and pc-rel. We accomplish this by
570 // using NLPs; however, sometimes the types are local to the file.
571 // We need to fill in the value for the NLP in those cases.
572 OutStreamer.emitValue(
573 MCSymbolRefExpr::create(MCSym.getPointer(), OutStreamer.getContext()),
574 4 /*size*/);
575}
576
577
579 const Triple &TT = TM.getTargetTriple();
580 if (TT.isOSBinFormatMachO()) {
581 // All darwin targets use mach-o.
582 const TargetLoweringObjectFileMachO &TLOFMacho =
584 MachineModuleInfoMachO &MMIMacho =
585 MMI->getObjFileInfo<MachineModuleInfoMachO>();
586
587 // Output non-lazy-pointers for external and common global variables.
589
590 if (!Stubs.empty()) {
591 // Switch with ".non_lazy_symbol_pointer" directive.
592 OutStreamer->switchSection(TLOFMacho.getNonLazySymbolPointerSection());
594
595 for (auto &Stub : Stubs)
596 emitNonLazySymbolPointer(*OutStreamer, Stub.first, Stub.second);
597
598 Stubs.clear();
599 OutStreamer->addBlankLine();
600 }
601
602 Stubs = MMIMacho.GetThreadLocalGVStubList();
603 if (!Stubs.empty()) {
604 // Switch with ".non_lazy_symbol_pointer" directive.
605 OutStreamer->switchSection(TLOFMacho.getThreadLocalPointerSection());
607
608 for (auto &Stub : Stubs)
609 emitNonLazySymbolPointer(*OutStreamer, Stub.first, Stub.second);
610
611 Stubs.clear();
612 OutStreamer->addBlankLine();
613 }
614
615 // Funny Darwin hack: This flag tells the linker that no global symbols
616 // contain code that falls through to other global symbols (e.g. the obvious
617 // implementation of multiple entry points). If this doesn't occur, the
618 // linker can safely perform dead code stripping. Since LLVM never
619 // generates code that does this, it is always safe to set.
620 OutStreamer->emitSubsectionsViaSymbols();
621 }
622
623 // The last attribute to be emitted is ABI_optimization_goals
624 MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
625 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
626
627 if (OptimizationGoals > 0 &&
628 (TT.isTargetAEABI() || TT.isTargetGNUAEABI() || TT.isTargetMuslAEABI()))
630 OptimizationGoals = -1;
631
633}
634
635//===----------------------------------------------------------------------===//
636// Helper routines for emitStartOfAsmFile() and emitEndOfAsmFile()
637// FIXME:
638// The following seem like one-off assembler flags, but they actually need
639// to appear in the .ARM.attributes section in ELF.
640// Instead of subclassing the MCELFStreamer, we do the work here.
641
642// Returns true if all function definitions have the same function attribute
643// value. It also returns true when the module has no functions.
646 return !any_of(M, [&](const Function &F) {
647 if (F.isDeclaration())
648 return false;
649 return F.getFnAttribute(Attr).getValueAsString() != Value;
650 });
651}
652// Returns true if all functions definitions have the same denormal mode.
653// It also returns true when the module has no functions.
656 return !any_of(M, [&](const Function &F) {
657 if (F.isDeclaration())
658 return false;
659 StringRef AttrVal = F.getFnAttribute(Attr).getValueAsString();
660 return parseDenormalFPAttribute(AttrVal) != Value;
661 });
662}
663
664// Returns true if all functions have different denormal modes.
666 auto F = M.functions().begin();
667 auto E = M.functions().end();
668 if (F == E)
669 return false;
670 DenormalMode Value = F->getDenormalModeRaw();
671 ++F;
672 return std::any_of(F, E, [&](const Function &F) {
673 return !F.isDeclaration() && F.getDenormalModeRaw() != Value;
674 });
675}
676
677void ARMAsmPrinter::emitAttributes() {
678 MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
679 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
680
682
683 ATS.switchVendor("aeabi");
684
685 // Compute ARM ELF Attributes based on the default subtarget that
686 // we'd have constructed. The existing ARM behavior isn't LTO clean
687 // anyhow.
688 // FIXME: For ifunc related functions we could iterate over and look
689 // for a feature string that doesn't match the default one.
690 const Triple &TT = TM.getTargetTriple();
691 StringRef CPU = TM.getTargetCPU();
692 StringRef FS = TM.getTargetFeatureString();
693 std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU);
694 if (!FS.empty()) {
695 if (!ArchFS.empty())
696 ArchFS = (Twine(ArchFS) + "," + FS).str();
697 else
698 ArchFS = std::string(FS);
699 }
700 const ARMBaseTargetMachine &ATM =
701 static_cast<const ARMBaseTargetMachine &>(TM);
702 const ARMSubtarget STI(TT, std::string(CPU), ArchFS, ATM,
703 ATM.isLittleEndian());
704
705 // Emit build attributes for the available hardware.
706 ATS.emitTargetAttributes(STI);
707
708 // RW data addressing.
709 if (isPositionIndependent()) {
712 } else if (STI.isRWPI()) {
713 // RWPI specific attributes.
716 }
717
718 // RO data addressing.
719 if (isPositionIndependent() || STI.isROPI()) {
722 }
723
724 // GOT use.
725 if (isPositionIndependent()) {
728 } else {
731 }
732
733 // Set FP Denormals.
734 if (checkDenormalAttributeConsistency(*MMI->getModule(), "denormal-fp-math",
738 else if (checkDenormalAttributeConsistency(*MMI->getModule(),
739 "denormal-fp-math",
743 else if (checkDenormalAttributeInconsistency(*MMI->getModule()) ||
745 *MMI->getModule(), "denormal-fp-math", DenormalMode::getIEEE()))
748 else {
749 if (!STI.hasVFP2Base()) {
750 // When the target doesn't have an FPU (by design or
751 // intention), the assumptions made on the software support
752 // mirror that of the equivalent hardware support *if it
753 // existed*. For v7 and better we indicate that denormals are
754 // flushed preserving sign, and for V6 we indicate that
755 // denormals are flushed to positive zero.
756 if (STI.hasV7Ops())
759 } else if (STI.hasVFP3Base()) {
760 // In VFPv4, VFPv4U, VFPv3, or VFPv3U, it is preserved. That is,
761 // the sign bit of the zero matches the sign bit of the input or
762 // result that is being flushed to zero.
765 }
766 // For VFPv2 implementations it is implementation defined as
767 // to whether denormals are flushed to positive zero or to
768 // whatever the sign of zero is (ARM v7AR ARM 2.7.5). Historically
769 // LLVM has chosen to flush this to positive zero (most likely for
770 // GCC compatibility), so that's the chosen value here (the
771 // absence of its emission implies zero).
772 }
773
774 // Set FP exceptions and rounding
775 if (checkFunctionsAttributeConsistency(*MMI->getModule(),
776 "no-trapping-math", "true") ||
777 TM.Options.NoTrappingFPMath)
780 else {
782
783 // If the user has permitted this code to choose the IEEE 754
784 // rounding at run-time, emit the rounding attribute.
785 if (TM.Options.HonorSignDependentRoundingFPMathOption)
787 }
788
789 // TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath is the
790 // equivalent of GCC's -ffinite-math-only flag.
791 if (TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath)
794 else
797
798 // FIXME: add more flags to ARMBuildAttributes.h
799 // 8-bytes alignment stuff.
802
803 // Hard float. Use both S and D registers and conform to AAPCS-VFP.
804 if (getTM().isAAPCS_ABI() && TM.Options.FloatABIType == FloatABI::Hard)
806
807 // FIXME: To support emitting this build attribute as GCC does, the
808 // -mfp16-format option and associated plumbing must be
809 // supported. For now the __fp16 type is exposed by default, so this
810 // attribute should be emitted with value 1.
813
814 if (const Module *SourceModule = MMI->getModule()) {
815 // ABI_PCS_wchar_t to indicate wchar_t width
816 // FIXME: There is no way to emit value 0 (wchar_t prohibited).
817 if (auto WCharWidthValue = mdconst::extract_or_null<ConstantInt>(
818 SourceModule->getModuleFlag("wchar_size"))) {
819 int WCharWidth = WCharWidthValue->getZExtValue();
820 assert((WCharWidth == 2 || WCharWidth == 4) &&
821 "wchar_t width must be 2 or 4 bytes");
823 }
824
825 // ABI_enum_size to indicate enum width
826 // FIXME: There is no way to emit value 0 (enums prohibited) or value 3
827 // (all enums contain a value needing 32 bits to encode).
828 if (auto EnumWidthValue = mdconst::extract_or_null<ConstantInt>(
829 SourceModule->getModuleFlag("min_enum_size"))) {
830 int EnumWidth = EnumWidthValue->getZExtValue();
831 assert((EnumWidth == 1 || EnumWidth == 4) &&
832 "Minimum enum width must be 1 or 4 bytes");
833 int EnumBuildAttr = EnumWidth == 1 ? 1 : 2;
835 }
836
838 SourceModule->getModuleFlag("sign-return-address"));
839 if (PACValue && PACValue->isOne()) {
840 // If "+pacbti" is used as an architecture extension,
841 // Tag_PAC_extension is emitted in
842 // ARMTargetStreamer::emitTargetAttributes().
843 if (!STI.hasPACBTI()) {
846 }
848 }
849
851 SourceModule->getModuleFlag("branch-target-enforcement"));
852 if (BTIValue && !BTIValue->isZero()) {
853 // If "+pacbti" is used as an architecture extension,
854 // Tag_BTI_extension is emitted in
855 // ARMTargetStreamer::emitTargetAttributes().
856 if (!STI.hasPACBTI()) {
859 }
861 }
862 }
863
864 // We currently do not support using R9 as the TLS pointer.
865 if (STI.isRWPI())
868 else if (STI.isR9Reserved())
871 else
874}
875
876//===----------------------------------------------------------------------===//
877
878static MCSymbol *getBFLabel(StringRef Prefix, unsigned FunctionNumber,
879 unsigned LabelId, MCContext &Ctx) {
880
881 MCSymbol *Label = Ctx.getOrCreateSymbol(Twine(Prefix)
882 + "BF" + Twine(FunctionNumber) + "_" + Twine(LabelId));
883 return Label;
884}
885
886static MCSymbol *getPICLabel(StringRef Prefix, unsigned FunctionNumber,
887 unsigned LabelId, MCContext &Ctx) {
888
889 MCSymbol *Label = Ctx.getOrCreateSymbol(Twine(Prefix)
890 + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId));
891 return Label;
892}
893
895 switch (Modifier) {
897 return ARM::S_None;
898 case ARMCP::TLSGD:
899 return ARM::S_TLSGD;
900 case ARMCP::TPOFF:
901 return ARM::S_TPOFF;
902 case ARMCP::GOTTPOFF:
903 return ARM::S_GOTTPOFF;
904 case ARMCP::SBREL:
905 return ARM::S_SBREL;
906 case ARMCP::GOT_PREL:
907 return ARM::S_GOT_PREL;
908 case ARMCP::SECREL:
909 return ARM::S_COFF_SECREL;
910 }
911 llvm_unreachable("Invalid ARMCPModifier!");
912}
913
914MCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV,
915 unsigned char TargetFlags) {
916 const Triple &TT = TM.getTargetTriple();
917 if (TT.isOSBinFormatMachO()) {
918 bool IsIndirect =
919 (TargetFlags & ARMII::MO_NONLAZY) && getTM().isGVIndirectSymbol(GV);
920
921 if (!IsIndirect)
922 return getSymbol(GV);
923
924 // FIXME: Remove this when Darwin transition to @GOT like syntax.
925 MCSymbol *MCSym = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
926 MachineModuleInfoMachO &MMIMachO =
927 MMI->getObjFileInfo<MachineModuleInfoMachO>();
929 GV->isThreadLocal() ? MMIMachO.getThreadLocalGVStubEntry(MCSym)
930 : MMIMachO.getGVStubEntry(MCSym);
931
932 if (!StubSym.getPointer())
934 !GV->hasInternalLinkage());
935 return MCSym;
936 } else if (TT.isOSBinFormatCOFF()) {
937 assert(TT.isOSWindows() && "Windows is the only supported COFF target");
938
939 bool IsIndirect =
940 (TargetFlags & (ARMII::MO_DLLIMPORT | ARMII::MO_COFFSTUB));
941 if (!IsIndirect)
942 return getSymbol(GV);
943
944 SmallString<128> Name;
945 if (TargetFlags & ARMII::MO_DLLIMPORT)
946 Name = "__imp_";
947 else if (TargetFlags & ARMII::MO_COFFSTUB)
948 Name = ".refptr.";
949 getNameWithPrefix(Name, GV);
950
951 MCSymbol *MCSym = OutContext.getOrCreateSymbol(Name);
952
953 if (TargetFlags & ARMII::MO_COFFSTUB) {
954 MachineModuleInfoCOFF &MMICOFF =
955 MMI->getObjFileInfo<MachineModuleInfoCOFF>();
957 MMICOFF.getGVStubEntry(MCSym);
958
959 if (!StubSym.getPointer())
961 }
962
963 return MCSym;
964 } else if (TT.isOSBinFormatELF()) {
965 return getSymbolPreferLocal(*GV);
966 }
967 llvm_unreachable("unexpected target");
968}
969
972 const DataLayout &DL = getDataLayout();
973 int Size = DL.getTypeAllocSize(MCPV->getType());
974
975 ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);
976
977 if (ACPV->isPromotedGlobal()) {
978 // This constant pool entry is actually a global whose storage has been
979 // promoted into the constant pool. This global may be referenced still
980 // by debug information, and due to the way AsmPrinter is set up, the debug
981 // info is immutable by the time we decide to promote globals to constant
982 // pools. Because of this, we need to ensure we emit a symbol for the global
983 // with private linkage (the default) so debug info can refer to it.
984 //
985 // However, if this global is promoted into several functions we must ensure
986 // we don't try and emit duplicate symbols!
987 auto *ACPC = cast<ARMConstantPoolConstant>(ACPV);
988 for (const auto *GV : ACPC->promotedGlobals()) {
989 if (!EmittedPromotedGlobalLabels.count(GV)) {
990 MCSymbol *GVSym = getSymbol(GV);
991 OutStreamer->emitLabel(GVSym);
992 EmittedPromotedGlobalLabels.insert(GV);
993 }
994 }
995 return emitGlobalConstant(DL, ACPC->getPromotedGlobalInit());
996 }
997
998 MCSymbol *MCSym;
999 if (ACPV->isLSDA()) {
1000 MCSym = getMBBExceptionSym(MF->front());
1001 } else if (ACPV->isBlockAddress()) {
1002 const BlockAddress *BA =
1003 cast<ARMConstantPoolConstant>(ACPV)->getBlockAddress();
1004 MCSym = GetBlockAddressSymbol(BA);
1005 } else if (ACPV->isGlobalValue()) {
1006 const GlobalValue *GV = cast<ARMConstantPoolConstant>(ACPV)->getGV();
1007
1008 // On Darwin, const-pool entries may get the "FOO$non_lazy_ptr" mangling, so
1009 // flag the global as MO_NONLAZY.
1010 unsigned char TF =
1011 TM.getTargetTriple().isOSBinFormatMachO() ? ARMII::MO_NONLAZY : 0;
1012 MCSym = GetARMGVSymbol(GV, TF);
1013 } else if (ACPV->isMachineBasicBlock()) {
1014 const MachineBasicBlock *MBB = cast<ARMConstantPoolMBB>(ACPV)->getMBB();
1015 MCSym = MBB->getSymbol();
1016 } else {
1017 assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
1018 auto Sym = cast<ARMConstantPoolSymbol>(ACPV)->getSymbol();
1019 MCSym = GetExternalSymbolSymbol(Sym);
1020 }
1021
1022 // Create an MCSymbol for the reference.
1023 const MCExpr *Expr = MCSymbolRefExpr::create(
1025
1026 if (ACPV->getPCAdjustment()) {
1027 MCSymbol *PCLabel =
1028 getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
1029 ACPV->getLabelId(), OutContext);
1030 const MCExpr *PCRelExpr = MCSymbolRefExpr::create(PCLabel, OutContext);
1031 PCRelExpr =
1032 MCBinaryExpr::createAdd(PCRelExpr,
1034 OutContext),
1035 OutContext);
1036 if (ACPV->mustAddCurrentAddress()) {
1037 // We want "(<expr> - .)", but MC doesn't have a concept of the '.'
1038 // label, so just emit a local label end reference that instead.
1039 MCSymbol *DotSym = OutContext.createTempSymbol();
1040 OutStreamer->emitLabel(DotSym);
1041 const MCExpr *DotExpr = MCSymbolRefExpr::create(DotSym, OutContext);
1042 PCRelExpr = MCBinaryExpr::createSub(PCRelExpr, DotExpr, OutContext);
1043 }
1044 Expr = MCBinaryExpr::createSub(Expr, PCRelExpr, OutContext);
1045 }
1046 OutStreamer->emitValue(Expr, Size);
1047}
1048
1050 const MachineOperand &MO1 = MI->getOperand(1);
1051 unsigned JTI = MO1.getIndex();
1052
1053 // Make sure the Thumb jump table is 4-byte aligned. This will be a nop for
1054 // ARM mode tables.
1055 emitAlignment(Align(4));
1056
1057 // Emit a label for the jump table.
1058 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);
1059 OutStreamer->emitLabel(JTISymbol);
1060
1061 // Mark the jump table as data-in-code.
1062 OutStreamer->emitDataRegion(MCDR_DataRegionJT32);
1063
1064 // Emit each entry of the table.
1065 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
1066 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
1067 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1068
1069 for (MachineBasicBlock *MBB : JTBBs) {
1070 // Construct an MCExpr for the entry. We want a value of the form:
1071 // (BasicBlockAddr - TableBeginAddr)
1072 //
1073 // For example, a table with entries jumping to basic blocks BB0 and BB1
1074 // would look like:
1075 // LJTI_0_0:
1076 // .word (LBB0 - LJTI_0_0)
1077 // .word (LBB1 - LJTI_0_0)
1078 const MCExpr *Expr = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
1079
1080 const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();
1081 if (isPositionIndependent() || STI.isROPI())
1082 Expr = MCBinaryExpr::createSub(Expr, MCSymbolRefExpr::create(JTISymbol,
1083 OutContext),
1084 OutContext);
1085 // If we're generating a table of Thumb addresses in static relocation
1086 // model, we need to add one to keep interworking correctly.
1087 else if (AFI->isThumbFunction())
1089 OutContext);
1090 OutStreamer->emitValue(Expr, 4);
1091 }
1092 // Mark the end of jump table data-in-code region.
1093 OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
1094}
1095
1097 const MachineOperand &MO1 = MI->getOperand(1);
1098 unsigned JTI = MO1.getIndex();
1099
1100 // Make sure the Thumb jump table is 4-byte aligned. This will be a nop for
1101 // ARM mode tables.
1102 emitAlignment(Align(4));
1103
1104 // Emit a label for the jump table.
1105 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);
1106 OutStreamer->emitLabel(JTISymbol);
1107
1108 // Emit each entry of the table.
1109 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
1110 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
1111 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1112
1113 for (MachineBasicBlock *MBB : JTBBs) {
1114 const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::create(MBB->getSymbol(),
1115 OutContext);
1116 // If this isn't a TBB or TBH, the entries are direct branch instructions.
1118 .addExpr(MBBSymbolExpr)
1119 .addImm(ARMCC::AL)
1120 .addReg(0));
1121 }
1122}
1123
1125 unsigned OffsetWidth) {
1126 assert((OffsetWidth == 1 || OffsetWidth == 2) && "invalid tbb/tbh width");
1127 const MachineOperand &MO1 = MI->getOperand(1);
1128 unsigned JTI = MO1.getIndex();
1129
1130 const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();
1131 if (STI.isThumb1Only())
1132 emitAlignment(Align(4));
1133
1134 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);
1135 OutStreamer->emitLabel(JTISymbol);
1136
1137 // Emit each entry of the table.
1138 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
1139 const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
1140 const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1141
1142 // Mark the jump table as data-in-code.
1143 OutStreamer->emitDataRegion(OffsetWidth == 1 ? MCDR_DataRegionJT8
1145
1146 for (auto *MBB : JTBBs) {
1147 const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::create(MBB->getSymbol(),
1148 OutContext);
1149 // Otherwise it's an offset from the dispatch instruction. Construct an
1150 // MCExpr for the entry. We want a value of the form:
1151 // (BasicBlockAddr - TBBInstAddr + 4) / 2
1152 //
1153 // For example, a TBB table with entries jumping to basic blocks BB0 and BB1
1154 // would look like:
1155 // LJTI_0_0:
1156 // .byte (LBB0 - (LCPI0_0 + 4)) / 2
1157 // .byte (LBB1 - (LCPI0_0 + 4)) / 2
1158 // where LCPI0_0 is a label defined just before the TBB instruction using
1159 // this table.
1160 MCSymbol *TBInstPC = GetCPISymbol(MI->getOperand(0).getImm());
1161 const MCExpr *Expr = MCBinaryExpr::createAdd(
1164 Expr = MCBinaryExpr::createSub(MBBSymbolExpr, Expr, OutContext);
1166 OutContext);
1167 OutStreamer->emitValue(Expr, OffsetWidth);
1168 }
1169 // Mark the end of jump table data-in-code region. 32-bit offsets use
1170 // actual branch instructions here, so we don't mark those as a data-region
1171 // at all.
1172 OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
1173
1174 // Make sure the next instruction is 2-byte aligned.
1175 emitAlignment(Align(2));
1176}
1177
1178std::tuple<const MCSymbol *, uint64_t, const MCSymbol *,
1181 const MachineInstr *BranchInstr,
1182 const MCSymbol *BranchLabel) const {
1184 const MCSymbol *BaseLabel;
1185 uint64_t BaseOffset = 0;
1186 switch (BranchInstr->getOpcode()) {
1187 case ARM::BR_JTadd:
1188 case ARM::BR_JTr:
1189 case ARM::tBR_JTr:
1190 // Word relative to the jump table address.
1192 BaseLabel = GetARMJTIPICJumpTableLabel(JTI);
1193 break;
1194 case ARM::tTBH_JT:
1195 case ARM::t2TBH_JT:
1196 // half-word shifted left, relative to *after* the branch instruction.
1198 BranchLabel = GetCPISymbol(BranchInstr->getOperand(3).getImm());
1199 BaseLabel = BranchLabel;
1200 BaseOffset = 4;
1201 break;
1202 case ARM::tTBB_JT:
1203 case ARM::t2TBB_JT:
1204 // byte shifted left, relative to *after* the branch instruction.
1206 BranchLabel = GetCPISymbol(BranchInstr->getOperand(3).getImm());
1207 BaseLabel = BranchLabel;
1208 BaseOffset = 4;
1209 break;
1210 case ARM::t2BR_JT:
1211 // Direct jump.
1212 BaseLabel = nullptr;
1214 break;
1215 default:
1216 llvm_unreachable("Unknown jump table instruction");
1217 }
1218
1219 return std::make_tuple(BaseLabel, BaseOffset, BranchLabel, EntrySize);
1220}
1221
1222void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) {
1224 "Only instruction which are involved into frame setup code are allowed");
1225
1226 MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
1227 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
1228 const MachineFunction &MF = *MI->getParent()->getParent();
1229 const TargetRegisterInfo *TargetRegInfo =
1231 const MachineRegisterInfo &MachineRegInfo = MF.getRegInfo();
1232
1233 Register FramePtr = TargetRegInfo->getFrameRegister(MF);
1234 unsigned Opc = MI->getOpcode();
1235 unsigned SrcReg, DstReg;
1236
1237 switch (Opc) {
1238 case ARM::tPUSH:
1239 // special case: tPUSH does not have src/dst regs.
1240 SrcReg = DstReg = ARM::SP;
1241 break;
1242 case ARM::tLDRpci:
1243 case ARM::t2MOVi16:
1244 case ARM::t2MOVTi16:
1245 case ARM::tMOVi8:
1246 case ARM::tADDi8:
1247 case ARM::tLSLri:
1248 // special cases:
1249 // 1) for Thumb1 code we sometimes materialize the constant via constpool
1250 // load.
1251 // 2) for Thumb1 execute only code we materialize the constant via the
1252 // following pattern:
1253 // movs r3, #:upper8_15:<const>
1254 // lsls r3, #8
1255 // adds r3, #:upper0_7:<const>
1256 // lsls r3, #8
1257 // adds r3, #:lower8_15:<const>
1258 // lsls r3, #8
1259 // adds r3, #:lower0_7:<const>
1260 // So we need to special-case MOVS, ADDS and LSLS, and keep track of
1261 // where we are in the sequence with the simplest of state machines.
1262 // 3) for Thumb2 execute only code we materialize the constant via
1263 // immediate constants in 2 separate instructions (MOVW/MOVT).
1264 SrcReg = ~0U;
1265 DstReg = MI->getOperand(0).getReg();
1266 break;
1267 case ARM::VMRS:
1268 SrcReg = ARM::FPSCR;
1269 DstReg = MI->getOperand(0).getReg();
1270 break;
1271 case ARM::VMRS_FPEXC:
1272 SrcReg = ARM::FPEXC;
1273 DstReg = MI->getOperand(0).getReg();
1274 break;
1275 default:
1276 SrcReg = MI->getOperand(1).getReg();
1277 DstReg = MI->getOperand(0).getReg();
1278 break;
1279 }
1280
1281 // Try to figure out the unwinding opcode out of src / dst regs.
1282 if (MI->mayStore()) {
1283 // Register saves.
1284 assert(DstReg == ARM::SP &&
1285 "Only stack pointer as a destination reg is supported");
1286
1288 // Skip src & dst reg, and pred ops.
1289 unsigned StartOp = 2 + 2;
1290 // Use all the operands.
1291 unsigned NumOffset = 0;
1292 // Amount of SP adjustment folded into a push, before the
1293 // registers are stored (pad at higher addresses).
1294 unsigned PadBefore = 0;
1295 // Amount of SP adjustment folded into a push, after the
1296 // registers are stored (pad at lower addresses).
1297 unsigned PadAfter = 0;
1298
1299 switch (Opc) {
1300 default:
1301 MI->print(errs());
1302 llvm_unreachable("Unsupported opcode for unwinding information");
1303 case ARM::tPUSH:
1304 // Special case here: no src & dst reg, but two extra imp ops.
1305 StartOp = 2; NumOffset = 2;
1306 [[fallthrough]];
1307 case ARM::STMDB_UPD:
1308 case ARM::t2STMDB_UPD:
1309 case ARM::VSTMDDB_UPD:
1310 assert(SrcReg == ARM::SP &&
1311 "Only stack pointer as a source reg is supported");
1312 for (unsigned i = StartOp, NumOps = MI->getNumOperands() - NumOffset;
1313 i != NumOps; ++i) {
1314 const MachineOperand &MO = MI->getOperand(i);
1315 // Actually, there should never be any impdef stuff here. Skip it
1316 // temporary to workaround PR11902.
1317 if (MO.isImplicit())
1318 continue;
1319 // Registers, pushed as a part of folding an SP update into the
1320 // push instruction are marked as undef and should not be
1321 // restored when unwinding, because the function can modify the
1322 // corresponding stack slots.
1323 if (MO.isUndef()) {
1324 assert(RegList.empty() &&
1325 "Pad registers must come before restored ones");
1326 unsigned Width =
1327 TargetRegInfo->getRegSizeInBits(MO.getReg(), MachineRegInfo) / 8;
1328 PadAfter += Width;
1329 continue;
1330 }
1331 // Check for registers that are remapped (for a Thumb1 prologue that
1332 // saves high registers).
1333 Register Reg = MO.getReg();
1334 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(Reg))
1335 Reg = RemappedReg;
1336 RegList.push_back(Reg);
1337 }
1338 break;
1339 case ARM::STR_PRE_IMM:
1340 case ARM::STR_PRE_REG:
1341 case ARM::t2STR_PRE:
1342 assert(MI->getOperand(2).getReg() == ARM::SP &&
1343 "Only stack pointer as a source reg is supported");
1344 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(SrcReg))
1345 SrcReg = RemappedReg;
1346
1347 RegList.push_back(SrcReg);
1348 break;
1349 case ARM::t2STRD_PRE:
1350 assert(MI->getOperand(3).getReg() == ARM::SP &&
1351 "Only stack pointer as a source reg is supported");
1352 SrcReg = MI->getOperand(1).getReg();
1353 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(SrcReg))
1354 SrcReg = RemappedReg;
1355 RegList.push_back(SrcReg);
1356 SrcReg = MI->getOperand(2).getReg();
1357 if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(SrcReg))
1358 SrcReg = RemappedReg;
1359 RegList.push_back(SrcReg);
1360 PadBefore = -MI->getOperand(4).getImm() - 8;
1361 break;
1362 }
1363 if (MAI->getExceptionHandlingType() == ExceptionHandling::ARM) {
1364 if (PadBefore)
1365 ATS.emitPad(PadBefore);
1366 ATS.emitRegSave(RegList, Opc == ARM::VSTMDDB_UPD);
1367 // Account for the SP adjustment, folded into the push.
1368 if (PadAfter)
1369 ATS.emitPad(PadAfter);
1370 }
1371 } else {
1372 // Changes of stack / frame pointer.
1373 if (SrcReg == ARM::SP) {
1374 int64_t Offset = 0;
1375 switch (Opc) {
1376 default:
1377 MI->print(errs());
1378 llvm_unreachable("Unsupported opcode for unwinding information");
1379 case ARM::tLDRspi:
1380 // Used to restore LR in a prologue which uses it as a temporary, has
1381 // no effect on unwind tables.
1382 return;
1383 case ARM::MOVr:
1384 case ARM::tMOVr:
1385 Offset = 0;
1386 break;
1387 case ARM::ADDri:
1388 case ARM::t2ADDri:
1389 case ARM::t2ADDri12:
1390 case ARM::t2ADDspImm:
1391 case ARM::t2ADDspImm12:
1392 Offset = -MI->getOperand(2).getImm();
1393 break;
1394 case ARM::SUBri:
1395 case ARM::t2SUBri:
1396 case ARM::t2SUBri12:
1397 case ARM::t2SUBspImm:
1398 case ARM::t2SUBspImm12:
1399 Offset = MI->getOperand(2).getImm();
1400 break;
1401 case ARM::tSUBspi:
1402 Offset = MI->getOperand(2).getImm()*4;
1403 break;
1404 case ARM::tADDspi:
1405 case ARM::tADDrSPi:
1406 Offset = -MI->getOperand(2).getImm()*4;
1407 break;
1408 case ARM::tADDhirr:
1409 Offset =
1410 -AFI->EHPrologueOffsetInRegs.lookup(MI->getOperand(2).getReg());
1411 break;
1412 }
1413
1414 if (MAI->getExceptionHandlingType() == ExceptionHandling::ARM) {
1415 if (DstReg == FramePtr && FramePtr != ARM::SP)
1416 // Set-up of the frame pointer. Positive values correspond to "add"
1417 // instruction.
1418 ATS.emitSetFP(FramePtr, ARM::SP, -Offset);
1419 else if (DstReg == ARM::SP) {
1420 // Change of SP by an offset. Positive values correspond to "sub"
1421 // instruction.
1422 ATS.emitPad(Offset);
1423 } else {
1424 // Move of SP to a register. Positive values correspond to an "add"
1425 // instruction.
1426 ATS.emitMovSP(DstReg, -Offset);
1427 }
1428 }
1429 } else if (DstReg == ARM::SP) {
1430 MI->print(errs());
1431 llvm_unreachable("Unsupported opcode for unwinding information");
1432 } else {
1433 int64_t Offset = 0;
1434 switch (Opc) {
1435 case ARM::tMOVr:
1436 // If a Thumb1 function spills r8-r11, we copy the values to low
1437 // registers before pushing them. Record the copy so we can emit the
1438 // correct ".save" later.
1439 AFI->EHPrologueRemappedRegs[DstReg] = SrcReg;
1440 break;
1441 case ARM::VMRS:
1442 case ARM::VMRS_FPEXC:
1443 // If a function spills FPSCR or FPEXC, we copy the values to low
1444 // registers before pushing them. However, we can't issue annotations
1445 // for FP status registers because ".save" requires GPR registers, and
1446 // ".vsave" requires DPR registers, so don't record the copy and simply
1447 // emit annotations for the source registers used for the store.
1448 break;
1449 case ARM::tLDRpci: {
1450 // Grab the constpool index and check, whether it corresponds to
1451 // original or cloned constpool entry.
1452 unsigned CPI = MI->getOperand(1).getIndex();
1453 const MachineConstantPool *MCP = MF.getConstantPool();
1454 if (CPI >= MCP->getConstants().size())
1455 CPI = AFI->getOriginalCPIdx(CPI);
1456 assert(CPI != -1U && "Invalid constpool index");
1457
1458 // Derive the actual offset.
1459 const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI];
1460 assert(!CPE.isMachineConstantPoolEntry() && "Invalid constpool entry");
1461 Offset = cast<ConstantInt>(CPE.Val.ConstVal)->getSExtValue();
1462 AFI->EHPrologueOffsetInRegs[DstReg] = Offset;
1463 break;
1464 }
1465 case ARM::t2MOVi16:
1466 Offset = MI->getOperand(1).getImm();
1467 AFI->EHPrologueOffsetInRegs[DstReg] = Offset;
1468 break;
1469 case ARM::t2MOVTi16:
1470 Offset = MI->getOperand(2).getImm();
1471 AFI->EHPrologueOffsetInRegs[DstReg] |= (Offset << 16);
1472 break;
1473 case ARM::tMOVi8:
1474 Offset = MI->getOperand(2).getImm();
1475 AFI->EHPrologueOffsetInRegs[DstReg] = Offset;
1476 break;
1477 case ARM::tLSLri:
1478 assert(MI->getOperand(3).getImm() == 8 &&
1479 "The shift amount is not equal to 8");
1480 assert(MI->getOperand(2).getReg() == MI->getOperand(0).getReg() &&
1481 "The source register is not equal to the destination register");
1482 AFI->EHPrologueOffsetInRegs[DstReg] <<= 8;
1483 break;
1484 case ARM::tADDi8:
1485 assert(MI->getOperand(2).getReg() == MI->getOperand(0).getReg() &&
1486 "The source register is not equal to the destination register");
1487 Offset = MI->getOperand(3).getImm();
1488 AFI->EHPrologueOffsetInRegs[DstReg] += Offset;
1489 break;
1490 case ARM::t2PAC:
1491 case ARM::t2PACBTI:
1492 AFI->EHPrologueRemappedRegs[ARM::R12] = ARM::RA_AUTH_CODE;
1493 break;
1494 default:
1495 MI->print(errs());
1496 llvm_unreachable("Unsupported opcode for unwinding information");
1497 }
1498 }
1499 }
1500}
1501
1502// Simple pseudo-instructions have their lowering (with expansion to real
1503// instructions) auto-generated.
1504#include "ARMGenMCPseudoLowering.inc"
1505
1506// Helper function to check if a register is live (used as an implicit operand)
1507// in the given call instruction.
1509 for (const MachineOperand &MO : Call.implicit_operands()) {
1510 if (MO.isReg() && MO.getReg() == Reg && MO.isUse()) {
1511 return true;
1512 }
1513 }
1514 return false;
1515}
1516
1517void ARMAsmPrinter::EmitKCFI_CHECK_ARM32(Register AddrReg, int64_t Type,
1518 const MachineInstr &Call,
1519 int64_t PrefixNops) {
1520 // Choose scratch register: r12 primary, r3 if target is r12.
1521 unsigned ScratchReg = ARM::R12;
1522 if (AddrReg == ARM::R12) {
1523 ScratchReg = ARM::R3;
1524 }
1525
1526 // Calculate ESR for ARM mode (16-bit): 0x8000 | (scratch_reg << 5) | addr_reg
1527 // Note: scratch_reg is always 0x1F since the EOR sequence clobbers it.
1528 const ARMBaseRegisterInfo *TRI = static_cast<const ARMBaseRegisterInfo *>(
1529 MF->getSubtarget().getRegisterInfo());
1530 unsigned AddrIndex = TRI->getEncodingValue(AddrReg);
1531 unsigned ESR = 0x8000 | (31 << 5) | (AddrIndex & 31);
1532
1533 // Check if r3 is live and needs to be spilled.
1534 bool NeedSpillR3 =
1535 (ScratchReg == ARM::R3) && isRegisterLiveInCall(Call, ARM::R3);
1536
1537 // If we need to spill r3, push it first.
1538 if (NeedSpillR3) {
1539 // push {r3}
1540 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::STMDB_UPD)
1541 .addReg(ARM::SP)
1542 .addReg(ARM::SP)
1543 .addImm(ARMCC::AL)
1544 .addReg(0)
1545 .addReg(ARM::R3));
1546 }
1547
1548 // Clear bit 0 of target address to handle Thumb function pointers.
1549 // In 32-bit ARM, function pointers may have the low bit set to indicate
1550 // Thumb state when ARM/Thumb interworking is enabled (ARMv4T and later).
1551 // We need to clear it to avoid an alignment fault when loading.
1552 // bic scratch, target, #1
1553 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::BICri)
1554 .addReg(ScratchReg)
1555 .addReg(AddrReg)
1556 .addImm(1)
1557 .addImm(ARMCC::AL)
1558 .addReg(0)
1559 .addReg(0));
1560
1561 // ldr scratch, [scratch, #-(PrefixNops * 4 + 4)]
1562 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12)
1563 .addReg(ScratchReg)
1564 .addReg(ScratchReg)
1565 .addImm(-(PrefixNops * 4 + 4))
1566 .addImm(ARMCC::AL)
1567 .addReg(0));
1568
1569 // Each EOR instruction XORs one byte of the type, shifted to its position.
1570 for (int i = 0; i < 4; i++) {
1571 uint8_t byte = (Type >> (i * 8)) & 0xFF;
1572 uint32_t imm = byte << (i * 8);
1573 bool isLast = (i == 3);
1574
1575 // Encode as ARM modified immediate.
1576 int SOImmVal = ARM_AM::getSOImmVal(imm);
1577 assert(SOImmVal != -1 &&
1578 "Cannot encode immediate as ARM modified immediate");
1579
1580 // eor[s] scratch, scratch, #imm (last one sets flags with CPSR)
1582 MCInstBuilder(ARM::EORri)
1583 .addReg(ScratchReg)
1584 .addReg(ScratchReg)
1585 .addImm(SOImmVal)
1586 .addImm(ARMCC::AL)
1587 .addReg(0)
1588 .addReg(isLast ? ARM::CPSR : ARM::NoRegister));
1589 }
1590
1591 // If we spilled r3, restore it immediately after the comparison.
1592 // This must happen before the branch so r3 is valid on both paths.
1593 if (NeedSpillR3) {
1594 // pop {r3}
1595 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDMIA_UPD)
1596 .addReg(ARM::SP)
1597 .addReg(ARM::SP)
1598 .addImm(ARMCC::AL)
1599 .addReg(0)
1600 .addReg(ARM::R3));
1601 }
1602
1603 // beq .Lpass (branch if types match, i.e., scratch is zero)
1604 MCSymbol *Pass = OutContext.createTempSymbol();
1606 MCInstBuilder(ARM::Bcc)
1608 .addImm(ARMCC::EQ)
1609 .addReg(ARM::CPSR));
1610
1611 // udf #ESR (trap with encoded diagnostic)
1612 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::UDF).addImm(ESR));
1613
1614 OutStreamer->emitLabel(Pass);
1615}
1616
1617void ARMAsmPrinter::EmitKCFI_CHECK_Thumb2(Register AddrReg, int64_t Type,
1618 const MachineInstr &Call,
1619 int64_t PrefixNops) {
1620 // Choose scratch register: r12 primary, r3 if target is r12.
1621 unsigned ScratchReg = ARM::R12;
1622 if (AddrReg == ARM::R12) {
1623 ScratchReg = ARM::R3;
1624 }
1625
1626 // Calculate ESR for Thumb mode (8-bit): 0x80 | addr_reg
1627 // Bit 7: KCFI trap indicator
1628 // Bits 6-5: Reserved
1629 // Bits 4-0: Address register encoding
1630 const ARMBaseRegisterInfo *TRI = static_cast<const ARMBaseRegisterInfo *>(
1631 MF->getSubtarget().getRegisterInfo());
1632 unsigned AddrIndex = TRI->getEncodingValue(AddrReg);
1633 unsigned ESR = 0x80 | (AddrIndex & 0x1F);
1634
1635 // Check if r3 is live and needs to be spilled.
1636 bool NeedSpillR3 =
1637 (ScratchReg == ARM::R3) && isRegisterLiveInCall(Call, ARM::R3);
1638
1639 // If we need to spill r3, push it first.
1640 if (NeedSpillR3) {
1641 // push {r3}
1643 *OutStreamer,
1644 MCInstBuilder(ARM::tPUSH).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));
1645 }
1646
1647 // Clear bit 0 of target address to handle Thumb function pointers.
1648 // In 32-bit ARM, function pointers may have the low bit set to indicate
1649 // Thumb state when ARM/Thumb interworking is enabled (ARMv4T and later).
1650 // We need to clear it to avoid an alignment fault when loading.
1651 // bic scratch, target, #1
1652 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2BICri)
1653 .addReg(ScratchReg)
1654 .addReg(AddrReg)
1655 .addImm(1)
1656 .addImm(ARMCC::AL)
1657 .addReg(0)
1658 .addReg(0));
1659
1660 // ldr scratch, [scratch, #-(PrefixNops * 4 + 4)]
1661 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi8)
1662 .addReg(ScratchReg)
1663 .addReg(ScratchReg)
1664 .addImm(-(PrefixNops * 4 + 4))
1665 .addImm(ARMCC::AL)
1666 .addReg(0));
1667
1668 // Each EOR instruction XORs one byte of the type, shifted to its position.
1669 for (int i = 0; i < 4; i++) {
1670 uint8_t byte = (Type >> (i * 8)) & 0xFF;
1671 uint32_t imm = byte << (i * 8);
1672 bool isLast = (i == 3);
1673
1674 // Verify the immediate can be encoded as Thumb2 modified immediate.
1675 assert(ARM_AM::getT2SOImmVal(imm) != -1 &&
1676 "Cannot encode immediate as Thumb2 modified immediate");
1677
1678 // eor[s] scratch, scratch, #imm (last one sets flags with CPSR)
1680 MCInstBuilder(ARM::t2EORri)
1681 .addReg(ScratchReg)
1682 .addReg(ScratchReg)
1683 .addImm(imm)
1684 .addImm(ARMCC::AL)
1685 .addReg(0)
1686 .addReg(isLast ? ARM::CPSR : ARM::NoRegister));
1687 }
1688
1689 // If we spilled r3, restore it immediately after the comparison.
1690 // This must happen before the branch so r3 is valid on both paths.
1691 if (NeedSpillR3) {
1692 // pop {r3}
1694 *OutStreamer,
1695 MCInstBuilder(ARM::tPOP).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));
1696 }
1697
1698 // beq .Lpass (branch if types match, i.e., scratch is zero)
1699 MCSymbol *Pass = OutContext.createTempSymbol();
1701 MCInstBuilder(ARM::t2Bcc)
1703 .addImm(ARMCC::EQ)
1704 .addReg(ARM::CPSR));
1705
1706 // udf #ESR (trap with encoded diagnostic)
1707 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tUDF).addImm(ESR));
1708
1709 OutStreamer->emitLabel(Pass);
1710}
1711
1712void ARMAsmPrinter::EmitKCFI_CHECK_Thumb1(Register AddrReg, int64_t Type,
1713 const MachineInstr &Call,
1714 int64_t PrefixNops) {
1715 // For Thumb1, use R2 unconditionally as scratch register (a low register
1716 // required for tLDRi). R3 is used for building the type hash.
1717 unsigned ScratchReg = ARM::R2;
1718 unsigned TempReg = ARM::R3;
1719
1720 // Check if r3 is live and needs to be spilled.
1721 bool NeedSpillR3 = isRegisterLiveInCall(Call, ARM::R3);
1722
1723 // Spill r3 if needed
1724 if (NeedSpillR3) {
1726 *OutStreamer,
1727 MCInstBuilder(ARM::tPUSH).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));
1728 }
1729
1730 // Check if r2 is live and needs to be spilled.
1731 bool NeedSpillR2 = isRegisterLiveInCall(Call, ARM::R2);
1732
1733 // Push R2 if it's live
1734 if (NeedSpillR2) {
1736 *OutStreamer,
1737 MCInstBuilder(ARM::tPUSH).addImm(ARMCC::AL).addReg(0).addReg(ARM::R2));
1738 }
1739
1740 // Clear bit 0 from target address
1741 // TempReg (R3) is used first as helper for BIC, then later for building type
1742 // hash.
1743
1744 // movs temp, #1
1745 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVi8)
1746 .addReg(TempReg)
1747 .addReg(ARM::CPSR)
1748 .addImm(1)
1749 .addImm(ARMCC::AL)
1750 .addReg(0));
1751
1752 // mov scratch, target
1753 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr)
1754 .addReg(ScratchReg)
1755 .addReg(AddrReg)
1756 .addImm(ARMCC::AL));
1757
1758 // bics scratch, temp (scratch = scratch & ~temp)
1759 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBIC)
1760 .addReg(ScratchReg)
1761 .addReg(ARM::CPSR)
1762 .addReg(ScratchReg)
1763 .addReg(TempReg)
1764 .addImm(ARMCC::AL)
1765 .addReg(0));
1766
1767 // Load type hash. Thumb1 doesn't support negative offsets, so subtract.
1768 int offset = PrefixNops * 4 + 4;
1769
1770 // subs scratch, #offset
1771 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tSUBi8)
1772 .addReg(ScratchReg)
1773 .addReg(ARM::CPSR)
1774 .addReg(ScratchReg)
1775 .addImm(offset)
1776 .addImm(ARMCC::AL)
1777 .addReg(0));
1778
1779 // ldr scratch, [scratch, #0]
1780 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi)
1781 .addReg(ScratchReg)
1782 .addReg(ScratchReg)
1783 .addImm(0)
1784 .addImm(ARMCC::AL)
1785 .addReg(0));
1786
1787 // Load expected type inline (instead of EOR sequence)
1788 //
1789 // This creates the 32-bit value byte-by-byte in the temp register:
1790 // movs temp, #byte3 (high byte)
1791 // lsls temp, temp, #8
1792 // adds temp, #byte2
1793 // lsls temp, temp, #8
1794 // adds temp, #byte1
1795 // lsls temp, temp, #8
1796 // adds temp, #byte0 (low byte)
1797
1798 uint8_t byte0 = (Type >> 0) & 0xFF;
1799 uint8_t byte1 = (Type >> 8) & 0xFF;
1800 uint8_t byte2 = (Type >> 16) & 0xFF;
1801 uint8_t byte3 = (Type >> 24) & 0xFF;
1802
1803 // movs temp, #byte3 (start with high byte)
1804 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVi8)
1805 .addReg(TempReg)
1806 .addReg(ARM::CPSR)
1807 .addImm(byte3)
1808 .addImm(ARMCC::AL)
1809 .addReg(0));
1810
1811 // lsls temp, temp, #8
1812 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)
1813 .addReg(TempReg)
1814 .addReg(ARM::CPSR)
1815 .addReg(TempReg)
1816 .addImm(8)
1817 .addImm(ARMCC::AL)
1818 .addReg(0));
1819
1820 // adds temp, #byte2
1821 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi8)
1822 .addReg(TempReg)
1823 .addReg(ARM::CPSR)
1824 .addReg(TempReg)
1825 .addImm(byte2)
1826 .addImm(ARMCC::AL)
1827 .addReg(0));
1828
1829 // lsls temp, temp, #8
1830 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)
1831 .addReg(TempReg)
1832 .addReg(ARM::CPSR)
1833 .addReg(TempReg)
1834 .addImm(8)
1835 .addImm(ARMCC::AL)
1836 .addReg(0));
1837
1838 // adds temp, #byte1
1839 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi8)
1840 .addReg(TempReg)
1841 .addReg(ARM::CPSR)
1842 .addReg(TempReg)
1843 .addImm(byte1)
1844 .addImm(ARMCC::AL)
1845 .addReg(0));
1846
1847 // lsls temp, temp, #8
1848 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)
1849 .addReg(TempReg)
1850 .addReg(ARM::CPSR)
1851 .addReg(TempReg)
1852 .addImm(8)
1853 .addImm(ARMCC::AL)
1854 .addReg(0));
1855
1856 // adds temp, #byte0 (low byte)
1857 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi8)
1858 .addReg(TempReg)
1859 .addReg(ARM::CPSR)
1860 .addReg(TempReg)
1861 .addImm(byte0)
1862 .addImm(ARMCC::AL)
1863 .addReg(0));
1864
1865 // cmp scratch, temp
1866 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tCMPr)
1867 .addReg(ScratchReg)
1868 .addReg(TempReg)
1869 .addImm(ARMCC::AL)
1870 .addReg(0));
1871
1872 // Restore registers if spilled (pop in reverse order of push: R2, then R3)
1873 if (NeedSpillR2) {
1874 // pop {r2}
1876 *OutStreamer,
1877 MCInstBuilder(ARM::tPOP).addImm(ARMCC::AL).addReg(0).addReg(ARM::R2));
1878 }
1879
1880 // Restore r3 if spilled
1881 if (NeedSpillR3) {
1882 // pop {r3}
1884 *OutStreamer,
1885 MCInstBuilder(ARM::tPOP).addImm(ARMCC::AL).addReg(0).addReg(ARM::R3));
1886 }
1887
1888 // beq .Lpass (branch if types match, i.e., scratch == temp)
1889 MCSymbol *Pass = OutContext.createTempSymbol();
1891 MCInstBuilder(ARM::tBcc)
1893 .addImm(ARMCC::EQ)
1894 .addReg(ARM::CPSR));
1895
1896 // bkpt #0 (trap with encoded diagnostic)
1897 EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBKPT).addImm(0));
1898
1899 OutStreamer->emitLabel(Pass);
1900}
1901
1903 Register AddrReg = MI.getOperand(0).getReg();
1904 const int64_t Type = MI.getOperand(1).getImm();
1905
1906 // Get the call instruction that follows this KCFI_CHECK.
1907 assert(std::next(MI.getIterator())->isCall() &&
1908 "KCFI_CHECK not followed by a call instruction");
1909 const MachineInstr &Call = *std::next(MI.getIterator());
1910
1911 // Adjust the offset for patchable-function-prefix.
1912 int64_t PrefixNops = 0;
1913 MI.getMF()
1914 ->getFunction()
1915 .getFnAttribute("patchable-function-prefix")
1916 .getValueAsString()
1917 .getAsInteger(10, PrefixNops);
1918
1919 // Emit the appropriate instruction sequence based on the opcode variant.
1920 switch (MI.getOpcode()) {
1921 case ARM::KCFI_CHECK_ARM:
1922 EmitKCFI_CHECK_ARM32(AddrReg, Type, Call, PrefixNops);
1923 break;
1924 case ARM::KCFI_CHECK_Thumb2:
1925 EmitKCFI_CHECK_Thumb2(AddrReg, Type, Call, PrefixNops);
1926 break;
1927 case ARM::KCFI_CHECK_Thumb1:
1928 EmitKCFI_CHECK_Thumb1(AddrReg, Type, Call, PrefixNops);
1929 break;
1930 default:
1931 llvm_unreachable("Unexpected KCFI_CHECK opcode");
1932 }
1933}
1934
1936 ARM_MC::verifyInstructionPredicates(MI->getOpcode(),
1937 getSubtargetInfo().getFeatureBits());
1938
1939 const ARMSubtarget &STI = MF->getSubtarget<ARMSubtarget>();
1940 const DataLayout &DL = getDataLayout();
1941 MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
1942 ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
1943
1944 // If we just ended a constant pool, mark it as such.
1945 if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) {
1946 OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
1947 InConstantPool = false;
1948 }
1949
1950 // Emit unwinding stuff for frame-related instructions
1951 if (TM.getTargetTriple().isTargetEHABICompatible() &&
1952 MI->getFlag(MachineInstr::FrameSetup))
1953 EmitUnwindingInstruction(MI);
1954
1955 // Do any auto-generated pseudo lowerings.
1956 if (MCInst OutInst; lowerPseudoInstExpansion(MI, OutInst)) {
1957 EmitToStreamer(*OutStreamer, OutInst);
1958 return;
1959 }
1960
1961 assert(!convertAddSubFlagsOpcode(MI->getOpcode()) &&
1962 "Pseudo flag setting opcode should be expanded early");
1963
1964 // Check for manual lowerings.
1965 unsigned Opc = MI->getOpcode();
1966 switch (Opc) {
1967 case ARM::t2MOVi32imm: llvm_unreachable("Should be lowered by thumb2it pass");
1968 case ARM::DBG_VALUE: llvm_unreachable("Should be handled by generic printing");
1969 case ARM::KCFI_CHECK_ARM:
1970 case ARM::KCFI_CHECK_Thumb2:
1971 case ARM::KCFI_CHECK_Thumb1:
1973 return;
1974 case ARM::LEApcrel:
1975 case ARM::tLEApcrel:
1976 case ARM::t2LEApcrel: {
1977 // FIXME: Need to also handle globals and externals
1978 MCSymbol *CPISymbol = GetCPISymbol(MI->getOperand(1).getIndex());
1979 EmitToStreamer(*OutStreamer, MCInstBuilder(MI->getOpcode() ==
1980 ARM::t2LEApcrel ? ARM::t2ADR
1981 : (MI->getOpcode() == ARM::tLEApcrel ? ARM::tADR
1982 : ARM::ADR))
1983 .addReg(MI->getOperand(0).getReg())
1985 // Add predicate operands.
1986 .addImm(MI->getOperand(2).getImm())
1987 .addReg(MI->getOperand(3).getReg()));
1988 return;
1989 }
1990 case ARM::LEApcrelJT:
1991 case ARM::tLEApcrelJT:
1992 case ARM::t2LEApcrelJT: {
1993 MCSymbol *JTIPICSymbol =
1994 GetARMJTIPICJumpTableLabel(MI->getOperand(1).getIndex());
1995 EmitToStreamer(*OutStreamer, MCInstBuilder(MI->getOpcode() ==
1996 ARM::t2LEApcrelJT ? ARM::t2ADR
1997 : (MI->getOpcode() == ARM::tLEApcrelJT ? ARM::tADR
1998 : ARM::ADR))
1999 .addReg(MI->getOperand(0).getReg())
2001 // Add predicate operands.
2002 .addImm(MI->getOperand(2).getImm())
2003 .addReg(MI->getOperand(3).getReg()));
2004 return;
2005 }
2006 // Darwin call instructions are just normal call instructions with different
2007 // clobber semantics (they clobber R9).
2008 case ARM::BX_CALL: {
2010 .addReg(ARM::LR)
2011 .addReg(ARM::PC)
2012 // Add predicate operands.
2013 .addImm(ARMCC::AL)
2014 .addReg(0)
2015 // Add 's' bit operand (always reg0 for this)
2016 .addReg(0));
2017
2018 assert(STI.hasV4TOps() && "Expected V4TOps for BX call");
2020 MCInstBuilder(ARM::BX).addReg(MI->getOperand(0).getReg()));
2021 return;
2022 }
2023 case ARM::tBX_CALL: {
2024 assert(!STI.hasV5TOps() && "Expected BLX to be selected for v5t+");
2025
2026 // On ARM v4t, when doing a call from thumb mode, we need to ensure
2027 // that the saved lr has its LSB set correctly (the arch doesn't
2028 // have blx).
2029 // So here we generate a bl to a small jump pad that does bx rN.
2030 // The jump pads are emitted after the function body.
2031
2032 Register TReg = MI->getOperand(0).getReg();
2033 MCSymbol *TRegSym = nullptr;
2034 for (std::pair<unsigned, MCSymbol *> &TIP : ThumbIndirectPads) {
2035 if (TIP.first == TReg) {
2036 TRegSym = TIP.second;
2037 break;
2038 }
2039 }
2040
2041 if (!TRegSym) {
2042 TRegSym = OutContext.createTempSymbol();
2043 ThumbIndirectPads.push_back(std::make_pair(TReg, TRegSym));
2044 }
2045
2046 // Create a link-saving branch to the Reg Indirect Jump Pad.
2048 // Predicate comes first here.
2049 .addImm(ARMCC::AL).addReg(0)
2050 .addExpr(MCSymbolRefExpr::create(TRegSym, OutContext)));
2051 return;
2052 }
2053 case ARM::BMOVPCRX_CALL: {
2055 .addReg(ARM::LR)
2056 .addReg(ARM::PC)
2057 // Add predicate operands.
2058 .addImm(ARMCC::AL)
2059 .addReg(0)
2060 // Add 's' bit operand (always reg0 for this)
2061 .addReg(0));
2062
2064 .addReg(ARM::PC)
2065 .addReg(MI->getOperand(0).getReg())
2066 // Add predicate operands.
2068 .addReg(0)
2069 // Add 's' bit operand (always reg0 for this)
2070 .addReg(0));
2071 return;
2072 }
2073 case ARM::BMOVPCB_CALL: {
2075 .addReg(ARM::LR)
2076 .addReg(ARM::PC)
2077 // Add predicate operands.
2078 .addImm(ARMCC::AL)
2079 .addReg(0)
2080 // Add 's' bit operand (always reg0 for this)
2081 .addReg(0));
2082
2083 const MachineOperand &Op = MI->getOperand(0);
2084 const GlobalValue *GV = Op.getGlobal();
2085 const unsigned TF = Op.getTargetFlags();
2086 MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
2087 const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext);
2089 .addExpr(GVSymExpr)
2090 // Add predicate operands.
2091 .addImm(ARMCC::AL)
2092 .addReg(0));
2093 return;
2094 }
2095 case ARM::MOVi16_ga_pcrel:
2096 case ARM::t2MOVi16_ga_pcrel: {
2097 MCInst TmpInst;
2098 TmpInst.setOpcode(Opc == ARM::MOVi16_ga_pcrel? ARM::MOVi16 : ARM::t2MOVi16);
2099 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
2100
2101 unsigned TF = MI->getOperand(1).getTargetFlags();
2102 const GlobalValue *GV = MI->getOperand(1).getGlobal();
2103 MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
2104 const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext);
2105
2106 MCSymbol *LabelSym =
2107 getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
2108 MI->getOperand(2).getImm(), OutContext);
2109 const MCExpr *LabelSymExpr= MCSymbolRefExpr::create(LabelSym, OutContext);
2110 unsigned PCAdj = (Opc == ARM::MOVi16_ga_pcrel) ? 8 : 4;
2111 const MCExpr *PCRelExpr = ARM::createLower16(
2113 GVSymExpr,
2114 MCBinaryExpr::createAdd(LabelSymExpr,
2116 OutContext),
2117 OutContext),
2118 OutContext);
2119 TmpInst.addOperand(MCOperand::createExpr(PCRelExpr));
2120
2121 // Add predicate operands.
2123 TmpInst.addOperand(MCOperand::createReg(0));
2124 // Add 's' bit operand (always reg0 for this)
2125 TmpInst.addOperand(MCOperand::createReg(0));
2126 EmitToStreamer(*OutStreamer, TmpInst);
2127 return;
2128 }
2129 case ARM::MOVTi16_ga_pcrel:
2130 case ARM::t2MOVTi16_ga_pcrel: {
2131 MCInst TmpInst;
2132 TmpInst.setOpcode(Opc == ARM::MOVTi16_ga_pcrel
2133 ? ARM::MOVTi16 : ARM::t2MOVTi16);
2134 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
2135 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(1).getReg()));
2136
2137 unsigned TF = MI->getOperand(2).getTargetFlags();
2138 const GlobalValue *GV = MI->getOperand(2).getGlobal();
2139 MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
2140 const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext);
2141
2142 MCSymbol *LabelSym =
2143 getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
2144 MI->getOperand(3).getImm(), OutContext);
2145 const MCExpr *LabelSymExpr= MCSymbolRefExpr::create(LabelSym, OutContext);
2146 unsigned PCAdj = (Opc == ARM::MOVTi16_ga_pcrel) ? 8 : 4;
2147 const MCExpr *PCRelExpr = ARM::createUpper16(
2149 GVSymExpr,
2150 MCBinaryExpr::createAdd(LabelSymExpr,
2152 OutContext),
2153 OutContext),
2154 OutContext);
2155 TmpInst.addOperand(MCOperand::createExpr(PCRelExpr));
2156 // Add predicate operands.
2158 TmpInst.addOperand(MCOperand::createReg(0));
2159 // Add 's' bit operand (always reg0 for this)
2160 TmpInst.addOperand(MCOperand::createReg(0));
2161 EmitToStreamer(*OutStreamer, TmpInst);
2162 return;
2163 }
2164 case ARM::t2BFi:
2165 case ARM::t2BFic:
2166 case ARM::t2BFLi:
2167 case ARM::t2BFr:
2168 case ARM::t2BFLr: {
2169 // This is a Branch Future instruction.
2170
2171 const MCExpr *BranchLabel = MCSymbolRefExpr::create(
2172 getBFLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
2173 MI->getOperand(0).getIndex(), OutContext),
2174 OutContext);
2175
2176 auto MCInst = MCInstBuilder(Opc).addExpr(BranchLabel);
2177 if (MI->getOperand(1).isReg()) {
2178 // For BFr/BFLr
2179 MCInst.addReg(MI->getOperand(1).getReg());
2180 } else {
2181 // For BFi/BFLi/BFic
2182 const MCExpr *BranchTarget;
2183 if (MI->getOperand(1).isMBB())
2184 BranchTarget = MCSymbolRefExpr::create(
2185 MI->getOperand(1).getMBB()->getSymbol(), OutContext);
2186 else if (MI->getOperand(1).isGlobal()) {
2187 const GlobalValue *GV = MI->getOperand(1).getGlobal();
2188 BranchTarget = MCSymbolRefExpr::create(
2189 GetARMGVSymbol(GV, MI->getOperand(1).getTargetFlags()), OutContext);
2190 } else if (MI->getOperand(1).isSymbol()) {
2191 BranchTarget = MCSymbolRefExpr::create(
2192 GetExternalSymbolSymbol(MI->getOperand(1).getSymbolName()),
2193 OutContext);
2194 } else
2195 llvm_unreachable("Unhandled operand kind in Branch Future instruction");
2196
2197 MCInst.addExpr(BranchTarget);
2198 }
2199
2200 if (Opc == ARM::t2BFic) {
2201 const MCExpr *ElseLabel = MCSymbolRefExpr::create(
2202 getBFLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
2203 MI->getOperand(2).getIndex(), OutContext),
2204 OutContext);
2205 MCInst.addExpr(ElseLabel);
2206 MCInst.addImm(MI->getOperand(3).getImm());
2207 } else {
2208 MCInst.addImm(MI->getOperand(2).getImm())
2209 .addReg(MI->getOperand(3).getReg());
2210 }
2211
2213 return;
2214 }
2215 case ARM::t2BF_LabelPseudo: {
2216 // This is a pseudo op for a label used by a branch future instruction
2217
2218 // Emit the label.
2219 OutStreamer->emitLabel(getBFLabel(DL.getPrivateGlobalPrefix(),
2221 MI->getOperand(0).getIndex(), OutContext));
2222 return;
2223 }
2224 case ARM::tPICADD: {
2225 // This is a pseudo op for a label + instruction sequence, which looks like:
2226 // LPC0:
2227 // add r0, pc
2228 // This adds the address of LPC0 to r0.
2229
2230 // Emit the label.
2231 OutStreamer->emitLabel(getPICLabel(DL.getPrivateGlobalPrefix(),
2233 MI->getOperand(2).getImm(), OutContext));
2234
2235 // Form and emit the add.
2237 .addReg(MI->getOperand(0).getReg())
2238 .addReg(MI->getOperand(0).getReg())
2239 .addReg(ARM::PC)
2240 // Add predicate operands.
2242 .addReg(0));
2243 return;
2244 }
2245 case ARM::PICADD: {
2246 // This is a pseudo op for a label + instruction sequence, which looks like:
2247 // LPC0:
2248 // add r0, pc, r0
2249 // This adds the address of LPC0 to r0.
2250
2251 // Emit the label.
2252 OutStreamer->emitLabel(getPICLabel(DL.getPrivateGlobalPrefix(),
2254 MI->getOperand(2).getImm(), OutContext));
2255
2256 // Form and emit the add.
2258 .addReg(MI->getOperand(0).getReg())
2259 .addReg(ARM::PC)
2260 .addReg(MI->getOperand(1).getReg())
2261 // Add predicate operands.
2262 .addImm(MI->getOperand(3).getImm())
2263 .addReg(MI->getOperand(4).getReg())
2264 // Add 's' bit operand (always reg0 for this)
2265 .addReg(0));
2266 return;
2267 }
2268 case ARM::PICSTR:
2269 case ARM::PICSTRB:
2270 case ARM::PICSTRH:
2271 case ARM::PICLDR:
2272 case ARM::PICLDRB:
2273 case ARM::PICLDRH:
2274 case ARM::PICLDRSB:
2275 case ARM::PICLDRSH: {
2276 // This is a pseudo op for a label + instruction sequence, which looks like:
2277 // LPC0:
2278 // OP r0, [pc, r0]
2279 // The LCP0 label is referenced by a constant pool entry in order to get
2280 // a PC-relative address at the ldr instruction.
2281
2282 // Emit the label.
2283 OutStreamer->emitLabel(getPICLabel(DL.getPrivateGlobalPrefix(),
2285 MI->getOperand(2).getImm(), OutContext));
2286
2287 // Form and emit the load
2288 unsigned Opcode;
2289 switch (MI->getOpcode()) {
2290 default:
2291 llvm_unreachable("Unexpected opcode!");
2292 case ARM::PICSTR: Opcode = ARM::STRrs; break;
2293 case ARM::PICSTRB: Opcode = ARM::STRBrs; break;
2294 case ARM::PICSTRH: Opcode = ARM::STRH; break;
2295 case ARM::PICLDR: Opcode = ARM::LDRrs; break;
2296 case ARM::PICLDRB: Opcode = ARM::LDRBrs; break;
2297 case ARM::PICLDRH: Opcode = ARM::LDRH; break;
2298 case ARM::PICLDRSB: Opcode = ARM::LDRSB; break;
2299 case ARM::PICLDRSH: Opcode = ARM::LDRSH; break;
2300 }
2302 .addReg(MI->getOperand(0).getReg())
2303 .addReg(ARM::PC)
2304 .addReg(MI->getOperand(1).getReg())
2305 .addImm(0)
2306 // Add predicate operands.
2307 .addImm(MI->getOperand(3).getImm())
2308 .addReg(MI->getOperand(4).getReg()));
2309
2310 return;
2311 }
2312 case ARM::CONSTPOOL_ENTRY: {
2313 assert(!STI.genExecuteOnly() &&
2314 "execute-only should not generate constant pools");
2315
2316 /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool
2317 /// in the function. The first operand is the ID# for this instruction, the
2318 /// second is the index into the MachineConstantPool that this is, the third
2319 /// is the size in bytes of this constant pool entry.
2320 /// The required alignment is specified on the basic block holding this MI.
2321 unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
2322 unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
2323
2324 // If this is the first entry of the pool, mark it.
2325 if (!InConstantPool) {
2326 OutStreamer->emitDataRegion(MCDR_DataRegion);
2327 InConstantPool = true;
2328 }
2329
2330 OutStreamer->emitLabel(GetCPISymbol(LabelId));
2331
2332 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
2333 if (MCPE.isMachineConstantPoolEntry())
2335 else
2337 return;
2338 }
2339 case ARM::JUMPTABLE_ADDRS:
2341 return;
2342 case ARM::JUMPTABLE_INSTS:
2344 return;
2345 case ARM::JUMPTABLE_TBB:
2346 case ARM::JUMPTABLE_TBH:
2347 emitJumpTableTBInst(MI, MI->getOpcode() == ARM::JUMPTABLE_TBB ? 1 : 2);
2348 return;
2349 case ARM::t2BR_JT: {
2351 .addReg(ARM::PC)
2352 .addReg(MI->getOperand(0).getReg())
2353 // Add predicate operands.
2355 .addReg(0));
2356 return;
2357 }
2358 case ARM::t2TBB_JT:
2359 case ARM::t2TBH_JT: {
2360 unsigned Opc = MI->getOpcode() == ARM::t2TBB_JT ? ARM::t2TBB : ARM::t2TBH;
2361 // Lower and emit the PC label, then the instruction itself.
2362 OutStreamer->emitLabel(GetCPISymbol(MI->getOperand(3).getImm()));
2364 .addReg(MI->getOperand(0).getReg())
2365 .addReg(MI->getOperand(1).getReg())
2366 // Add predicate operands.
2368 .addReg(0));
2369 return;
2370 }
2371 case ARM::tTBB_JT:
2372 case ARM::tTBH_JT: {
2373
2374 bool Is8Bit = MI->getOpcode() == ARM::tTBB_JT;
2375 Register Base = MI->getOperand(0).getReg();
2376 Register Idx = MI->getOperand(1).getReg();
2377 assert(MI->getOperand(1).isKill() && "We need the index register as scratch!");
2378
2379 // Multiply up idx if necessary.
2380 if (!Is8Bit)
2382 .addReg(Idx)
2383 .addReg(ARM::CPSR)
2384 .addReg(Idx)
2385 .addImm(1)
2386 // Add predicate operands.
2387 .addImm(ARMCC::AL)
2388 .addReg(0));
2389
2390 if (Base == ARM::PC) {
2391 // TBB [base, idx] =
2392 // ADDS idx, idx, base
2393 // LDRB idx, [idx, #4] ; or LDRH if TBH
2394 // LSLS idx, #1
2395 // ADDS pc, pc, idx
2396
2397 // When using PC as the base, it's important that there is no padding
2398 // between the last ADDS and the start of the jump table. The jump table
2399 // is 4-byte aligned, so we ensure we're 4 byte aligned here too.
2400 //
2401 // FIXME: Ideally we could vary the LDRB index based on the padding
2402 // between the sequence and jump table, however that relies on MCExprs
2403 // for load indexes which are currently not supported.
2404 OutStreamer->emitCodeAlignment(Align(4), &getSubtargetInfo());
2406 .addReg(Idx)
2407 .addReg(Idx)
2408 .addReg(Base)
2409 // Add predicate operands.
2410 .addImm(ARMCC::AL)
2411 .addReg(0));
2412
2413 unsigned Opc = Is8Bit ? ARM::tLDRBi : ARM::tLDRHi;
2415 .addReg(Idx)
2416 .addReg(Idx)
2417 .addImm(Is8Bit ? 4 : 2)
2418 // Add predicate operands.
2419 .addImm(ARMCC::AL)
2420 .addReg(0));
2421 } else {
2422 // TBB [base, idx] =
2423 // LDRB idx, [base, idx] ; or LDRH if TBH
2424 // LSLS idx, #1
2425 // ADDS pc, pc, idx
2426
2427 unsigned Opc = Is8Bit ? ARM::tLDRBr : ARM::tLDRHr;
2429 .addReg(Idx)
2430 .addReg(Base)
2431 .addReg(Idx)
2432 // Add predicate operands.
2433 .addImm(ARMCC::AL)
2434 .addReg(0));
2435 }
2436
2438 .addReg(Idx)
2439 .addReg(ARM::CPSR)
2440 .addReg(Idx)
2441 .addImm(1)
2442 // Add predicate operands.
2443 .addImm(ARMCC::AL)
2444 .addReg(0));
2445
2446 OutStreamer->emitLabel(GetCPISymbol(MI->getOperand(3).getImm()));
2448 .addReg(ARM::PC)
2449 .addReg(ARM::PC)
2450 .addReg(Idx)
2451 // Add predicate operands.
2452 .addImm(ARMCC::AL)
2453 .addReg(0));
2454 return;
2455 }
2456 case ARM::tBR_JTr:
2457 case ARM::BR_JTr: {
2458 // mov pc, target
2459 MCInst TmpInst;
2460 unsigned Opc = MI->getOpcode() == ARM::BR_JTr ?
2461 ARM::MOVr : ARM::tMOVr;
2462 TmpInst.setOpcode(Opc);
2463 TmpInst.addOperand(MCOperand::createReg(ARM::PC));
2464 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
2465 // Add predicate operands.
2467 TmpInst.addOperand(MCOperand::createReg(0));
2468 // Add 's' bit operand (always reg0 for this)
2469 if (Opc == ARM::MOVr)
2470 TmpInst.addOperand(MCOperand::createReg(0));
2471 EmitToStreamer(*OutStreamer, TmpInst);
2472 return;
2473 }
2474 case ARM::BR_JTm_i12: {
2475 // ldr pc, target
2476 MCInst TmpInst;
2477 TmpInst.setOpcode(ARM::LDRi12);
2478 TmpInst.addOperand(MCOperand::createReg(ARM::PC));
2479 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
2480 TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm()));
2481 // Add predicate operands.
2483 TmpInst.addOperand(MCOperand::createReg(0));
2484 EmitToStreamer(*OutStreamer, TmpInst);
2485 return;
2486 }
2487 case ARM::BR_JTm_rs: {
2488 // ldr pc, target
2489 MCInst TmpInst;
2490 TmpInst.setOpcode(ARM::LDRrs);
2491 TmpInst.addOperand(MCOperand::createReg(ARM::PC));
2492 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
2493 TmpInst.addOperand(MCOperand::createReg(MI->getOperand(1).getReg()));
2494 TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm()));
2495 // Add predicate operands.
2497 TmpInst.addOperand(MCOperand::createReg(0));
2498 EmitToStreamer(*OutStreamer, TmpInst);
2499 return;
2500 }
2501 case ARM::BR_JTadd: {
2502 // add pc, target, idx
2504 .addReg(ARM::PC)
2505 .addReg(MI->getOperand(0).getReg())
2506 .addReg(MI->getOperand(1).getReg())
2507 // Add predicate operands.
2509 .addReg(0)
2510 // Add 's' bit operand (always reg0 for this)
2511 .addReg(0));
2512 return;
2513 }
2514 case ARM::SPACE:
2515 OutStreamer->emitZeros(MI->getOperand(1).getImm());
2516 return;
2517 case ARM::TRAP: {
2518 // Non-Darwin binutils don't yet support the "trap" mnemonic.
2519 // FIXME: Remove this special case when they do.
2520 if (!TM.getTargetTriple().isOSBinFormatMachO()) {
2521 uint32_t Val = 0xe7ffdefeUL;
2522 OutStreamer->AddComment("trap");
2523 ATS.emitInst(Val);
2524 return;
2525 }
2526 break;
2527 }
2528 case ARM::tTRAP: {
2529 // Non-Darwin binutils don't yet support the "trap" mnemonic.
2530 // FIXME: Remove this special case when they do.
2531 if (!TM.getTargetTriple().isOSBinFormatMachO()) {
2532 uint16_t Val = 0xdefe;
2533 OutStreamer->AddComment("trap");
2534 ATS.emitInst(Val, 'n');
2535 return;
2536 }
2537 break;
2538 }
2539 case ARM::t2Int_eh_sjlj_setjmp:
2540 case ARM::t2Int_eh_sjlj_setjmp_nofp:
2541 case ARM::tInt_eh_sjlj_setjmp: {
2542 // Two incoming args: GPR:$src, GPR:$val
2543 // mov $val, pc
2544 // adds $val, #7
2545 // str $val, [$src, #4]
2546 // movs r0, #0
2547 // b LSJLJEH
2548 // movs r0, #1
2549 // LSJLJEH:
2550 Register SrcReg = MI->getOperand(0).getReg();
2551 Register ValReg = MI->getOperand(1).getReg();
2552 MCSymbol *Label = OutContext.createTempSymbol("SJLJEH");
2553 OutStreamer->AddComment("eh_setjmp begin");
2555 .addReg(ValReg)
2556 .addReg(ARM::PC)
2557 // Predicate.
2558 .addImm(ARMCC::AL)
2559 .addReg(0));
2560
2562 .addReg(ValReg)
2563 // 's' bit operand
2564 .addReg(ARM::CPSR)
2565 .addReg(ValReg)
2566 .addImm(7)
2567 // Predicate.
2568 .addImm(ARMCC::AL)
2569 .addReg(0));
2570
2572 .addReg(ValReg)
2573 .addReg(SrcReg)
2574 // The offset immediate is #4. The operand value is scaled by 4 for the
2575 // tSTR instruction.
2576 .addImm(1)
2577 // Predicate.
2578 .addImm(ARMCC::AL)
2579 .addReg(0));
2580
2582 .addReg(ARM::R0)
2583 .addReg(ARM::CPSR)
2584 .addImm(0)
2585 // Predicate.
2586 .addImm(ARMCC::AL)
2587 .addReg(0));
2588
2589 const MCExpr *SymbolExpr = MCSymbolRefExpr::create(Label, OutContext);
2591 .addExpr(SymbolExpr)
2592 .addImm(ARMCC::AL)
2593 .addReg(0));
2594
2595 OutStreamer->AddComment("eh_setjmp end");
2597 .addReg(ARM::R0)
2598 .addReg(ARM::CPSR)
2599 .addImm(1)
2600 // Predicate.
2601 .addImm(ARMCC::AL)
2602 .addReg(0));
2603
2604 OutStreamer->emitLabel(Label);
2605 return;
2606 }
2607
2608 case ARM::Int_eh_sjlj_setjmp_nofp:
2609 case ARM::Int_eh_sjlj_setjmp: {
2610 // Two incoming args: GPR:$src, GPR:$val
2611 // add $val, pc, #8
2612 // str $val, [$src, #+4]
2613 // mov r0, #0
2614 // add pc, pc, #0
2615 // mov r0, #1
2616 Register SrcReg = MI->getOperand(0).getReg();
2617 Register ValReg = MI->getOperand(1).getReg();
2618
2619 OutStreamer->AddComment("eh_setjmp begin");
2621 .addReg(ValReg)
2622 .addReg(ARM::PC)
2623 .addImm(8)
2624 // Predicate.
2625 .addImm(ARMCC::AL)
2626 .addReg(0)
2627 // 's' bit operand (always reg0 for this).
2628 .addReg(0));
2629
2631 .addReg(ValReg)
2632 .addReg(SrcReg)
2633 .addImm(4)
2634 // Predicate.
2635 .addImm(ARMCC::AL)
2636 .addReg(0));
2637
2639 .addReg(ARM::R0)
2640 .addImm(0)
2641 // Predicate.
2642 .addImm(ARMCC::AL)
2643 .addReg(0)
2644 // 's' bit operand (always reg0 for this).
2645 .addReg(0));
2646
2648 .addReg(ARM::PC)
2649 .addReg(ARM::PC)
2650 .addImm(0)
2651 // Predicate.
2652 .addImm(ARMCC::AL)
2653 .addReg(0)
2654 // 's' bit operand (always reg0 for this).
2655 .addReg(0));
2656
2657 OutStreamer->AddComment("eh_setjmp end");
2659 .addReg(ARM::R0)
2660 .addImm(1)
2661 // Predicate.
2662 .addImm(ARMCC::AL)
2663 .addReg(0)
2664 // 's' bit operand (always reg0 for this).
2665 .addReg(0));
2666 return;
2667 }
2668 case ARM::Int_eh_sjlj_longjmp: {
2669 // ldr sp, [$src, #8]
2670 // ldr $scratch, [$src, #4]
2671 // ldr r7, [$src]
2672 // bx $scratch
2673 Register SrcReg = MI->getOperand(0).getReg();
2674 Register ScratchReg = MI->getOperand(1).getReg();
2676 .addReg(ARM::SP)
2677 .addReg(SrcReg)
2678 .addImm(8)
2679 // Predicate.
2680 .addImm(ARMCC::AL)
2681 .addReg(0));
2682
2684 .addReg(ScratchReg)
2685 .addReg(SrcReg)
2686 .addImm(4)
2687 // Predicate.
2688 .addImm(ARMCC::AL)
2689 .addReg(0));
2690
2691 if (STI.isTargetDarwin() || STI.isTargetWindows()) {
2692 // These platforms always use the same frame register
2694 .addReg(STI.getFramePointerReg())
2695 .addReg(SrcReg)
2696 .addImm(0)
2697 // Predicate.
2699 .addReg(0));
2700 } else {
2701 // If the calling code might use either R7 or R11 as
2702 // frame pointer register, restore it into both.
2704 .addReg(ARM::R7)
2705 .addReg(SrcReg)
2706 .addImm(0)
2707 // Predicate.
2708 .addImm(ARMCC::AL)
2709 .addReg(0));
2711 .addReg(ARM::R11)
2712 .addReg(SrcReg)
2713 .addImm(0)
2714 // Predicate.
2715 .addImm(ARMCC::AL)
2716 .addReg(0));
2717 }
2718
2719 assert(STI.hasV4TOps());
2721 .addReg(ScratchReg)
2722 // Predicate.
2723 .addImm(ARMCC::AL)
2724 .addReg(0));
2725 return;
2726 }
2727 case ARM::tInt_eh_sjlj_longjmp: {
2728 // ldr $scratch, [$src, #8]
2729 // mov sp, $scratch
2730 // ldr $scratch, [$src, #4]
2731 // ldr r7, [$src]
2732 // bx $scratch
2733 Register SrcReg = MI->getOperand(0).getReg();
2734 Register ScratchReg = MI->getOperand(1).getReg();
2735
2737 .addReg(ScratchReg)
2738 .addReg(SrcReg)
2739 // The offset immediate is #8. The operand value is scaled by 4 for the
2740 // tLDR instruction.
2741 .addImm(2)
2742 // Predicate.
2743 .addImm(ARMCC::AL)
2744 .addReg(0));
2745
2747 .addReg(ARM::SP)
2748 .addReg(ScratchReg)
2749 // Predicate.
2750 .addImm(ARMCC::AL)
2751 .addReg(0));
2752
2754 .addReg(ScratchReg)
2755 .addReg(SrcReg)
2756 .addImm(1)
2757 // Predicate.
2758 .addImm(ARMCC::AL)
2759 .addReg(0));
2760
2761 if (STI.isTargetDarwin() || STI.isTargetWindows()) {
2762 // These platforms always use the same frame register
2764 .addReg(STI.getFramePointerReg())
2765 .addReg(SrcReg)
2766 .addImm(0)
2767 // Predicate.
2769 .addReg(0));
2770 } else {
2771 // If the calling code might use either R7 or R11 as
2772 // frame pointer register, restore it into both.
2774 .addReg(ARM::R7)
2775 .addReg(SrcReg)
2776 .addImm(0)
2777 // Predicate.
2778 .addImm(ARMCC::AL)
2779 .addReg(0));
2781 .addReg(ARM::R11)
2782 .addReg(SrcReg)
2783 .addImm(0)
2784 // Predicate.
2785 .addImm(ARMCC::AL)
2786 .addReg(0));
2787 }
2788
2790 .addReg(ScratchReg)
2791 // Predicate.
2792 .addImm(ARMCC::AL)
2793 .addReg(0));
2794 return;
2795 }
2796 case ARM::tInt_WIN_eh_sjlj_longjmp: {
2797 // ldr.w r11, [$src, #0]
2798 // ldr.w sp, [$src, #8]
2799 // ldr.w pc, [$src, #4]
2800
2801 Register SrcReg = MI->getOperand(0).getReg();
2802
2804 .addReg(ARM::R11)
2805 .addReg(SrcReg)
2806 .addImm(0)
2807 // Predicate
2808 .addImm(ARMCC::AL)
2809 .addReg(0));
2811 .addReg(ARM::SP)
2812 .addReg(SrcReg)
2813 .addImm(8)
2814 // Predicate
2815 .addImm(ARMCC::AL)
2816 .addReg(0));
2818 .addReg(ARM::PC)
2819 .addReg(SrcReg)
2820 .addImm(4)
2821 // Predicate
2822 .addImm(ARMCC::AL)
2823 .addReg(0));
2824 return;
2825 }
2826 case ARM::PATCHABLE_FUNCTION_ENTER:
2828 return;
2829 case ARM::PATCHABLE_FUNCTION_EXIT:
2831 return;
2832 case ARM::PATCHABLE_TAIL_CALL:
2834 return;
2835 case ARM::SpeculationBarrierISBDSBEndBB: {
2836 // Print DSB SYS + ISB
2837 MCInst TmpInstDSB;
2838 TmpInstDSB.setOpcode(ARM::DSB);
2839 TmpInstDSB.addOperand(MCOperand::createImm(0xf));
2840 EmitToStreamer(*OutStreamer, TmpInstDSB);
2841 MCInst TmpInstISB;
2842 TmpInstISB.setOpcode(ARM::ISB);
2843 TmpInstISB.addOperand(MCOperand::createImm(0xf));
2844 EmitToStreamer(*OutStreamer, TmpInstISB);
2845 return;
2846 }
2847 case ARM::t2SpeculationBarrierISBDSBEndBB: {
2848 // Print DSB SYS + ISB
2849 MCInst TmpInstDSB;
2850 TmpInstDSB.setOpcode(ARM::t2DSB);
2851 TmpInstDSB.addOperand(MCOperand::createImm(0xf));
2853 TmpInstDSB.addOperand(MCOperand::createReg(0));
2854 EmitToStreamer(*OutStreamer, TmpInstDSB);
2855 MCInst TmpInstISB;
2856 TmpInstISB.setOpcode(ARM::t2ISB);
2857 TmpInstISB.addOperand(MCOperand::createImm(0xf));
2859 TmpInstISB.addOperand(MCOperand::createReg(0));
2860 EmitToStreamer(*OutStreamer, TmpInstISB);
2861 return;
2862 }
2863 case ARM::SpeculationBarrierSBEndBB: {
2864 // Print SB
2865 MCInst TmpInstSB;
2866 TmpInstSB.setOpcode(ARM::SB);
2867 EmitToStreamer(*OutStreamer, TmpInstSB);
2868 return;
2869 }
2870 case ARM::t2SpeculationBarrierSBEndBB: {
2871 // Print SB
2872 MCInst TmpInstSB;
2873 TmpInstSB.setOpcode(ARM::t2SB);
2874 EmitToStreamer(*OutStreamer, TmpInstSB);
2875 return;
2876 }
2877
2878 case ARM::SEH_StackAlloc:
2879 ATS.emitARMWinCFIAllocStack(MI->getOperand(0).getImm(),
2880 MI->getOperand(1).getImm());
2881 return;
2882
2883 case ARM::SEH_SaveRegs:
2884 case ARM::SEH_SaveRegs_Ret:
2885 ATS.emitARMWinCFISaveRegMask(MI->getOperand(0).getImm(),
2886 MI->getOperand(1).getImm());
2887 return;
2888
2889 case ARM::SEH_SaveSP:
2890 ATS.emitARMWinCFISaveSP(MI->getOperand(0).getImm());
2891 return;
2892
2893 case ARM::SEH_SaveFRegs:
2894 ATS.emitARMWinCFISaveFRegs(MI->getOperand(0).getImm(),
2895 MI->getOperand(1).getImm());
2896 return;
2897
2898 case ARM::SEH_SaveLR:
2899 ATS.emitARMWinCFISaveLR(MI->getOperand(0).getImm());
2900 return;
2901
2902 case ARM::SEH_Nop:
2903 case ARM::SEH_Nop_Ret:
2904 ATS.emitARMWinCFINop(MI->getOperand(0).getImm());
2905 return;
2906
2907 case ARM::SEH_PrologEnd:
2908 ATS.emitARMWinCFIPrologEnd(/*Fragment=*/false);
2909 return;
2910
2911 case ARM::SEH_EpilogStart:
2913 return;
2914
2915 case ARM::SEH_EpilogEnd:
2917 return;
2918 }
2919
2920 MCInst TmpInst;
2921 LowerARMMachineInstrToMCInst(MI, TmpInst, *this);
2922
2923 EmitToStreamer(*OutStreamer, TmpInst);
2924}
2925
2926char ARMAsmPrinter::ID = 0;
2927
2928INITIALIZE_PASS(ARMAsmPrinter, "arm-asm-printer", "ARM Assembly Printer", false,
2929 false)
2930
2931//===----------------------------------------------------------------------===//
2932// Target Registry Stuff
2933//===----------------------------------------------------------------------===//
2934
2935// Force static initialization.
2936extern "C" LLVM_ABI LLVM_EXTERNAL_VISIBILITY void
2937LLVMInitializeARMAsmPrinter() {
2942}
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:487
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 LowerPATCHABLE_FUNCTION_EXIT(const MachineInstr &MI)
void emitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override
EmitMachineConstantPoolValue - Print a machine constantpool value to the .s file.
bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, const char *ExtraCode, raw_ostream &O) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant.
void emitXXStructor(const DataLayout &DL, const Constant *CV) override
Targets can override this to change how global constants that are part of a C++ static/global constru...
void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI)
void LowerPATCHABLE_TAIL_CALL(const MachineInstr &MI)
void emitEndOfAsmFile(Module &M) override
This virtual method can be overridden by targets that want to emit something at the end of their file...
std::tuple< const MCSymbol *, uint64_t, const MCSymbol *, codeview::JumpTableEntrySize > getCodeViewJumpTableInfo(int JTI, const MachineInstr *BranchInstr, const MCSymbol *BranchLabel) const override
Gets information required to create a CodeView debug symbol for a jump table.
void emitJumpTableInsts(const MachineInstr *MI)
const ARMBaseTargetMachine & getTM() const
void emitGlobalVariable(const GlobalVariable *GV) override
Emit the specified global variable to the .s file.
bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, const char *ExtraCode, raw_ostream &O) override
Print the specified operand of MI, an INLINEASM instruction, using the specified assembler variant as...
void emitInstruction(const MachineInstr *MI) override
Targets should implement this to emit instructions.
void PrintSymbolOperand(const MachineOperand &MO, raw_ostream &O) override
Print the MachineOperand as a symbol.
void emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, const MCSubtargetInfo *EndInfo, const MachineInstr *MI) override
Let the target do anything it needs to do after emitting inlineasm.
void LowerKCFI_CHECK(const MachineInstr &MI)
void emitGlobalAlias(const Module &M, const GlobalAlias &GA) override
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:94
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:97
MachineFunction * MF
The current machine function.
Definition AsmPrinter.h:109
virtual void SetupMachineFunction(MachineFunction &MF)
This should be called when a new MachineFunction is being processed from runOnMachineFunction.
void emitFunctionBody()
This method emits the body and trailer for a function.
virtual void emitLinkage(const GlobalValue *GV, MCSymbol *GVSym) const
This emits linkage information about GVSym based on GV, if this is supported by the target.
unsigned getFunctionNumber() const
Return a unique ID for the current function.
AsmPrinter(TargetMachine &TM, std::unique_ptr< MCStreamer > Streamer, char &ID=AsmPrinter::ID)
void printOffset(int64_t Offset, raw_ostream &OS) const
This is just convenient handler for printing offsets.
void emitGlobalConstant(const DataLayout &DL, const Constant *CV, AliasMapTy *AliasList=nullptr)
EmitGlobalConstant - Print a general LLVM constant to the .s file.
MCSymbol * getSymbolPreferLocal(const GlobalValue &GV) const
Similar to getSymbol() but preferred for references.
MCSymbol * CurrentFnSym
The symbol for the current function.
Definition AsmPrinter.h:128
MachineModuleInfo * MMI
This is a pointer to the current MachineModuleInfo.
Definition AsmPrinter.h:112
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:101
bool isPositionIndependent() const
void emitVisibility(MCSymbol *Sym, unsigned Visibility, bool IsDefinition=true) const
This emits visibility information about symbol, if this is supported by the target.
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition AsmPrinter.h:106
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:64
LLVM_ABI TypeSize getTypeAllocSize(Type *Ty) const
Returns the offset in bytes between successive objects of the specified type, including alignment pad...
bool hasFnAttribute(Attribute::AttrKind Kind) const
Return true if the function has the attribute.
Definition Function.cpp:730
LLVM_ABI const GlobalObject * getAliaseeObject() const
Definition Globals.cpp:645
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.
Definition Types.h:26
@ 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:1915
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:870
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,...