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