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