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