xref: /freebsd/contrib/llvm-project/llvm/lib/Target/ARM/ARMAsmPrinter.cpp (revision 349cc55c9796c4596a5b9904cd3281af295f878f)
10b57cec5SDimitry Andric //===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains a printer that converts from our internal representation
100b57cec5SDimitry Andric // of machine-dependent LLVM code to GAS-format ARM assembly language.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "ARMAsmPrinter.h"
150b57cec5SDimitry Andric #include "ARM.h"
160b57cec5SDimitry Andric #include "ARMConstantPoolValue.h"
170b57cec5SDimitry Andric #include "ARMMachineFunctionInfo.h"
180b57cec5SDimitry Andric #include "ARMTargetMachine.h"
190b57cec5SDimitry Andric #include "ARMTargetObjectFile.h"
200b57cec5SDimitry Andric #include "MCTargetDesc/ARMAddressingModes.h"
210b57cec5SDimitry Andric #include "MCTargetDesc/ARMInstPrinter.h"
220b57cec5SDimitry Andric #include "MCTargetDesc/ARMMCExpr.h"
230b57cec5SDimitry Andric #include "TargetInfo/ARMTargetInfo.h"
240b57cec5SDimitry Andric #include "llvm/ADT/SetVector.h"
250b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
260b57cec5SDimitry Andric #include "llvm/BinaryFormat/COFF.h"
270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h"
280b57cec5SDimitry Andric #include "llvm/CodeGen/MachineJumpTableInfo.h"
290b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h"
300b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
310b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
320b57cec5SDimitry Andric #include "llvm/IR/Mangler.h"
330b57cec5SDimitry Andric #include "llvm/IR/Module.h"
340b57cec5SDimitry Andric #include "llvm/IR/Type.h"
350b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
360b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h"
370b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
380b57cec5SDimitry Andric #include "llvm/MC/MCELFStreamer.h"
390b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
400b57cec5SDimitry Andric #include "llvm/MC/MCInstBuilder.h"
410b57cec5SDimitry Andric #include "llvm/MC/MCObjectStreamer.h"
420b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
430b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
44*349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
450b57cec5SDimitry Andric #include "llvm/Support/ARMBuildAttributes.h"
460b57cec5SDimitry Andric #include "llvm/Support/Debug.h"
470b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
480b57cec5SDimitry Andric #include "llvm/Support/TargetParser.h"
490b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
500b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h"
510b57cec5SDimitry Andric using namespace llvm;
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric #define DEBUG_TYPE "asm-printer"
540b57cec5SDimitry Andric 
550b57cec5SDimitry Andric ARMAsmPrinter::ARMAsmPrinter(TargetMachine &TM,
560b57cec5SDimitry Andric                              std::unique_ptr<MCStreamer> Streamer)
57480093f4SDimitry Andric     : AsmPrinter(TM, std::move(Streamer)), Subtarget(nullptr), AFI(nullptr),
58480093f4SDimitry Andric       MCP(nullptr), InConstantPool(false), OptimizationGoals(-1) {}
590b57cec5SDimitry Andric 
605ffd83dbSDimitry Andric void ARMAsmPrinter::emitFunctionBodyEnd() {
610b57cec5SDimitry Andric   // Make sure to terminate any constant pools that were at the end
620b57cec5SDimitry Andric   // of the function.
630b57cec5SDimitry Andric   if (!InConstantPool)
640b57cec5SDimitry Andric     return;
650b57cec5SDimitry Andric   InConstantPool = false;
665ffd83dbSDimitry Andric   OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric 
695ffd83dbSDimitry Andric void ARMAsmPrinter::emitFunctionEntryLabel() {
700b57cec5SDimitry Andric   if (AFI->isThumbFunction()) {
715ffd83dbSDimitry Andric     OutStreamer->emitAssemblerFlag(MCAF_Code16);
725ffd83dbSDimitry Andric     OutStreamer->emitThumbFunc(CurrentFnSym);
730b57cec5SDimitry Andric   } else {
745ffd83dbSDimitry Andric     OutStreamer->emitAssemblerFlag(MCAF_Code32);
750b57cec5SDimitry Andric   }
760b57cec5SDimitry Andric 
775ffd83dbSDimitry Andric   // Emit symbol for CMSE non-secure entry point
785ffd83dbSDimitry Andric   if (AFI->isCmseNSEntryFunction()) {
795ffd83dbSDimitry Andric     MCSymbol *S =
805ffd83dbSDimitry Andric         OutContext.getOrCreateSymbol("__acle_se_" + CurrentFnSym->getName());
815ffd83dbSDimitry Andric     emitLinkage(&MF->getFunction(), S);
825ffd83dbSDimitry Andric     OutStreamer->emitSymbolAttribute(S, MCSA_ELF_TypeFunction);
835ffd83dbSDimitry Andric     OutStreamer->emitLabel(S);
845ffd83dbSDimitry Andric   }
855ffd83dbSDimitry Andric 
865ffd83dbSDimitry Andric   OutStreamer->emitLabel(CurrentFnSym);
875ffd83dbSDimitry Andric }
885ffd83dbSDimitry Andric 
895ffd83dbSDimitry Andric void ARMAsmPrinter::emitXXStructor(const DataLayout &DL, const Constant *CV) {
900b57cec5SDimitry Andric   uint64_t Size = getDataLayout().getTypeAllocSize(CV->getType());
910b57cec5SDimitry Andric   assert(Size && "C++ constructor pointer had zero size!");
920b57cec5SDimitry Andric 
930b57cec5SDimitry Andric   const GlobalValue *GV = dyn_cast<GlobalValue>(CV->stripPointerCasts());
940b57cec5SDimitry Andric   assert(GV && "C++ constructor pointer was not a GlobalValue!");
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   const MCExpr *E = MCSymbolRefExpr::create(GetARMGVSymbol(GV,
970b57cec5SDimitry Andric                                                            ARMII::MO_NO_FLAG),
980b57cec5SDimitry Andric                                             (Subtarget->isTargetELF()
990b57cec5SDimitry Andric                                              ? MCSymbolRefExpr::VK_ARM_TARGET1
1000b57cec5SDimitry Andric                                              : MCSymbolRefExpr::VK_None),
1010b57cec5SDimitry Andric                                             OutContext);
1020b57cec5SDimitry Andric 
1035ffd83dbSDimitry Andric   OutStreamer->emitValue(E, Size);
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
1065ffd83dbSDimitry Andric void ARMAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
1070b57cec5SDimitry Andric   if (PromotedGlobals.count(GV))
1080b57cec5SDimitry Andric     // The global was promoted into a constant pool. It should not be emitted.
1090b57cec5SDimitry Andric     return;
1105ffd83dbSDimitry Andric   AsmPrinter::emitGlobalVariable(GV);
1110b57cec5SDimitry Andric }
1120b57cec5SDimitry Andric 
1135ffd83dbSDimitry Andric /// runOnMachineFunction - This uses the emitInstruction()
1140b57cec5SDimitry Andric /// method to print assembly for each instruction.
1150b57cec5SDimitry Andric ///
1160b57cec5SDimitry Andric bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
1170b57cec5SDimitry Andric   AFI = MF.getInfo<ARMFunctionInfo>();
1180b57cec5SDimitry Andric   MCP = MF.getConstantPool();
1190b57cec5SDimitry Andric   Subtarget = &MF.getSubtarget<ARMSubtarget>();
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   SetupMachineFunction(MF);
1220b57cec5SDimitry Andric   const Function &F = MF.getFunction();
1230b57cec5SDimitry Andric   const TargetMachine& TM = MF.getTarget();
1240b57cec5SDimitry Andric 
1250b57cec5SDimitry Andric   // Collect all globals that had their storage promoted to a constant pool.
1260b57cec5SDimitry Andric   // Functions are emitted before variables, so this accumulates promoted
1270b57cec5SDimitry Andric   // globals from all functions in PromotedGlobals.
1280b57cec5SDimitry Andric   for (auto *GV : AFI->getGlobalsPromotedToConstantPool())
1290b57cec5SDimitry Andric     PromotedGlobals.insert(GV);
1300b57cec5SDimitry Andric 
1310b57cec5SDimitry Andric   // Calculate this function's optimization goal.
1320b57cec5SDimitry Andric   unsigned OptimizationGoal;
1330b57cec5SDimitry Andric   if (F.hasOptNone())
1340b57cec5SDimitry Andric     // For best debugging illusion, speed and small size sacrificed
1350b57cec5SDimitry Andric     OptimizationGoal = 6;
1360b57cec5SDimitry Andric   else if (F.hasMinSize())
1370b57cec5SDimitry Andric     // Aggressively for small size, speed and debug illusion sacrificed
1380b57cec5SDimitry Andric     OptimizationGoal = 4;
1390b57cec5SDimitry Andric   else if (F.hasOptSize())
1400b57cec5SDimitry Andric     // For small size, but speed and debugging illusion preserved
1410b57cec5SDimitry Andric     OptimizationGoal = 3;
1420b57cec5SDimitry Andric   else if (TM.getOptLevel() == CodeGenOpt::Aggressive)
1430b57cec5SDimitry Andric     // Aggressively for speed, small size and debug illusion sacrificed
1440b57cec5SDimitry Andric     OptimizationGoal = 2;
1450b57cec5SDimitry Andric   else if (TM.getOptLevel() > CodeGenOpt::None)
1460b57cec5SDimitry Andric     // For speed, but small size and good debug illusion preserved
1470b57cec5SDimitry Andric     OptimizationGoal = 1;
1480b57cec5SDimitry Andric   else // TM.getOptLevel() == CodeGenOpt::None
1490b57cec5SDimitry Andric     // For good debugging, but speed and small size preserved
1500b57cec5SDimitry Andric     OptimizationGoal = 5;
1510b57cec5SDimitry Andric 
1520b57cec5SDimitry Andric   // Combine a new optimization goal with existing ones.
1530b57cec5SDimitry Andric   if (OptimizationGoals == -1) // uninitialized goals
1540b57cec5SDimitry Andric     OptimizationGoals = OptimizationGoal;
1550b57cec5SDimitry Andric   else if (OptimizationGoals != (int)OptimizationGoal) // conflicting goals
1560b57cec5SDimitry Andric     OptimizationGoals = 0;
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   if (Subtarget->isTargetCOFF()) {
1590b57cec5SDimitry Andric     bool Internal = F.hasInternalLinkage();
1600b57cec5SDimitry Andric     COFF::SymbolStorageClass Scl = Internal ? COFF::IMAGE_SYM_CLASS_STATIC
1610b57cec5SDimitry Andric                                             : COFF::IMAGE_SYM_CLASS_EXTERNAL;
1620b57cec5SDimitry Andric     int Type = COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT;
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric     OutStreamer->BeginCOFFSymbolDef(CurrentFnSym);
1650b57cec5SDimitry Andric     OutStreamer->EmitCOFFSymbolStorageClass(Scl);
1660b57cec5SDimitry Andric     OutStreamer->EmitCOFFSymbolType(Type);
1670b57cec5SDimitry Andric     OutStreamer->EndCOFFSymbolDef();
1680b57cec5SDimitry Andric   }
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric   // Emit the rest of the function body.
1715ffd83dbSDimitry Andric   emitFunctionBody();
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric   // Emit the XRay table for this function.
1740b57cec5SDimitry Andric   emitXRayTable();
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   // If we need V4T thumb mode Register Indirect Jump pads, emit them.
1770b57cec5SDimitry Andric   // These are created per function, rather than per TU, since it's
1780b57cec5SDimitry Andric   // relatively easy to exceed the thumb branch range within a TU.
1790b57cec5SDimitry Andric   if (! ThumbIndirectPads.empty()) {
1805ffd83dbSDimitry Andric     OutStreamer->emitAssemblerFlag(MCAF_Code16);
1815ffd83dbSDimitry Andric     emitAlignment(Align(2));
1820b57cec5SDimitry Andric     for (std::pair<unsigned, MCSymbol *> &TIP : ThumbIndirectPads) {
1835ffd83dbSDimitry Andric       OutStreamer->emitLabel(TIP.second);
1840b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBX)
1850b57cec5SDimitry Andric         .addReg(TIP.first)
1860b57cec5SDimitry Andric         // Add predicate operands.
1870b57cec5SDimitry Andric         .addImm(ARMCC::AL)
1880b57cec5SDimitry Andric         .addReg(0));
1890b57cec5SDimitry Andric     }
1900b57cec5SDimitry Andric     ThumbIndirectPads.clear();
1910b57cec5SDimitry Andric   }
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   // We didn't modify anything.
1940b57cec5SDimitry Andric   return false;
1950b57cec5SDimitry Andric }
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric void ARMAsmPrinter::PrintSymbolOperand(const MachineOperand &MO,
1980b57cec5SDimitry Andric                                        raw_ostream &O) {
1990b57cec5SDimitry Andric   assert(MO.isGlobal() && "caller should check MO.isGlobal");
2000b57cec5SDimitry Andric   unsigned TF = MO.getTargetFlags();
2010b57cec5SDimitry Andric   if (TF & ARMII::MO_LO16)
2020b57cec5SDimitry Andric     O << ":lower16:";
2030b57cec5SDimitry Andric   else if (TF & ARMII::MO_HI16)
2040b57cec5SDimitry Andric     O << ":upper16:";
2050b57cec5SDimitry Andric   GetARMGVSymbol(MO.getGlobal(), TF)->print(O, MAI);
2060b57cec5SDimitry Andric   printOffset(MO.getOffset(), O);
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric 
2090b57cec5SDimitry Andric void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
2100b57cec5SDimitry Andric                                  raw_ostream &O) {
2110b57cec5SDimitry Andric   const MachineOperand &MO = MI->getOperand(OpNum);
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   switch (MO.getType()) {
2140b57cec5SDimitry Andric   default: llvm_unreachable("<unknown operand type>");
2150b57cec5SDimitry Andric   case MachineOperand::MO_Register: {
2168bcb0991SDimitry Andric     Register Reg = MO.getReg();
2178bcb0991SDimitry Andric     assert(Register::isPhysicalRegister(Reg));
2180b57cec5SDimitry Andric     assert(!MO.getSubReg() && "Subregs should be eliminated!");
2190b57cec5SDimitry Andric     if(ARM::GPRPairRegClass.contains(Reg)) {
2200b57cec5SDimitry Andric       const MachineFunction &MF = *MI->getParent()->getParent();
2210b57cec5SDimitry Andric       const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
2220b57cec5SDimitry Andric       Reg = TRI->getSubReg(Reg, ARM::gsub_0);
2230b57cec5SDimitry Andric     }
2240b57cec5SDimitry Andric     O << ARMInstPrinter::getRegisterName(Reg);
2250b57cec5SDimitry Andric     break;
2260b57cec5SDimitry Andric   }
2270b57cec5SDimitry Andric   case MachineOperand::MO_Immediate: {
2280b57cec5SDimitry Andric     O << '#';
2290b57cec5SDimitry Andric     unsigned TF = MO.getTargetFlags();
2300b57cec5SDimitry Andric     if (TF == ARMII::MO_LO16)
2310b57cec5SDimitry Andric       O << ":lower16:";
2320b57cec5SDimitry Andric     else if (TF == ARMII::MO_HI16)
2330b57cec5SDimitry Andric       O << ":upper16:";
2340b57cec5SDimitry Andric     O << MO.getImm();
2350b57cec5SDimitry Andric     break;
2360b57cec5SDimitry Andric   }
2370b57cec5SDimitry Andric   case MachineOperand::MO_MachineBasicBlock:
2380b57cec5SDimitry Andric     MO.getMBB()->getSymbol()->print(O, MAI);
2390b57cec5SDimitry Andric     return;
2400b57cec5SDimitry Andric   case MachineOperand::MO_GlobalAddress: {
2410b57cec5SDimitry Andric     PrintSymbolOperand(MO, O);
2420b57cec5SDimitry Andric     break;
2430b57cec5SDimitry Andric   }
2440b57cec5SDimitry Andric   case MachineOperand::MO_ConstantPoolIndex:
2450b57cec5SDimitry Andric     if (Subtarget->genExecuteOnly())
2460b57cec5SDimitry Andric       llvm_unreachable("execute-only should not generate constant pools");
2470b57cec5SDimitry Andric     GetCPISymbol(MO.getIndex())->print(O, MAI);
2480b57cec5SDimitry Andric     break;
2490b57cec5SDimitry Andric   }
2500b57cec5SDimitry Andric }
2510b57cec5SDimitry Andric 
2520b57cec5SDimitry Andric MCSymbol *ARMAsmPrinter::GetCPISymbol(unsigned CPID) const {
2530b57cec5SDimitry Andric   // The AsmPrinter::GetCPISymbol superclass method tries to use CPID as
2540b57cec5SDimitry Andric   // indexes in MachineConstantPool, which isn't in sync with indexes used here.
2550b57cec5SDimitry Andric   const DataLayout &DL = getDataLayout();
2560b57cec5SDimitry Andric   return OutContext.getOrCreateSymbol(Twine(DL.getPrivateGlobalPrefix()) +
2570b57cec5SDimitry Andric                                       "CPI" + Twine(getFunctionNumber()) + "_" +
2580b57cec5SDimitry Andric                                       Twine(CPID));
2590b57cec5SDimitry Andric }
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric //===--------------------------------------------------------------------===//
2620b57cec5SDimitry Andric 
2630b57cec5SDimitry Andric MCSymbol *ARMAsmPrinter::
2640b57cec5SDimitry Andric GetARMJTIPICJumpTableLabel(unsigned uid) const {
2650b57cec5SDimitry Andric   const DataLayout &DL = getDataLayout();
2660b57cec5SDimitry Andric   SmallString<60> Name;
2670b57cec5SDimitry Andric   raw_svector_ostream(Name) << DL.getPrivateGlobalPrefix() << "JTI"
2680b57cec5SDimitry Andric                             << getFunctionNumber() << '_' << uid;
2690b57cec5SDimitry Andric   return OutContext.getOrCreateSymbol(Name);
2700b57cec5SDimitry Andric }
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
2730b57cec5SDimitry Andric                                     const char *ExtraCode, raw_ostream &O) {
2740b57cec5SDimitry Andric   // Does this asm operand have a single letter operand modifier?
2750b57cec5SDimitry Andric   if (ExtraCode && ExtraCode[0]) {
2760b57cec5SDimitry Andric     if (ExtraCode[1] != 0) return true; // Unknown modifier.
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric     switch (ExtraCode[0]) {
2790b57cec5SDimitry Andric     default:
2800b57cec5SDimitry Andric       // See if this is a generic print operand
2810b57cec5SDimitry Andric       return AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O);
2820b57cec5SDimitry Andric     case 'P': // Print a VFP double precision register.
2830b57cec5SDimitry Andric     case 'q': // Print a NEON quad precision register.
2840b57cec5SDimitry Andric       printOperand(MI, OpNum, O);
2850b57cec5SDimitry Andric       return false;
2860b57cec5SDimitry Andric     case 'y': // Print a VFP single precision register as indexed double.
2870b57cec5SDimitry Andric       if (MI->getOperand(OpNum).isReg()) {
288e8d8bef9SDimitry Andric         MCRegister Reg = MI->getOperand(OpNum).getReg().asMCReg();
2890b57cec5SDimitry Andric         const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
2900b57cec5SDimitry Andric         // Find the 'd' register that has this 's' register as a sub-register,
2910b57cec5SDimitry Andric         // and determine the lane number.
2920b57cec5SDimitry Andric         for (MCSuperRegIterator SR(Reg, TRI); SR.isValid(); ++SR) {
2930b57cec5SDimitry Andric           if (!ARM::DPRRegClass.contains(*SR))
2940b57cec5SDimitry Andric             continue;
2950b57cec5SDimitry Andric           bool Lane0 = TRI->getSubReg(*SR, ARM::ssub_0) == Reg;
2960b57cec5SDimitry Andric           O << ARMInstPrinter::getRegisterName(*SR) << (Lane0 ? "[0]" : "[1]");
2970b57cec5SDimitry Andric           return false;
2980b57cec5SDimitry Andric         }
2990b57cec5SDimitry Andric       }
3000b57cec5SDimitry Andric       return true;
3010b57cec5SDimitry Andric     case 'B': // Bitwise inverse of integer or symbol without a preceding #.
3020b57cec5SDimitry Andric       if (!MI->getOperand(OpNum).isImm())
3030b57cec5SDimitry Andric         return true;
3040b57cec5SDimitry Andric       O << ~(MI->getOperand(OpNum).getImm());
3050b57cec5SDimitry Andric       return false;
3060b57cec5SDimitry Andric     case 'L': // The low 16 bits of an immediate constant.
3070b57cec5SDimitry Andric       if (!MI->getOperand(OpNum).isImm())
3080b57cec5SDimitry Andric         return true;
3090b57cec5SDimitry Andric       O << (MI->getOperand(OpNum).getImm() & 0xffff);
3100b57cec5SDimitry Andric       return false;
3110b57cec5SDimitry Andric     case 'M': { // A register range suitable for LDM/STM.
3120b57cec5SDimitry Andric       if (!MI->getOperand(OpNum).isReg())
3130b57cec5SDimitry Andric         return true;
3140b57cec5SDimitry Andric       const MachineOperand &MO = MI->getOperand(OpNum);
3158bcb0991SDimitry Andric       Register RegBegin = MO.getReg();
3160b57cec5SDimitry Andric       // This takes advantage of the 2 operand-ness of ldm/stm and that we've
3170b57cec5SDimitry Andric       // already got the operands in registers that are operands to the
3180b57cec5SDimitry Andric       // inline asm statement.
3190b57cec5SDimitry Andric       O << "{";
3200b57cec5SDimitry Andric       if (ARM::GPRPairRegClass.contains(RegBegin)) {
3210b57cec5SDimitry Andric         const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
3228bcb0991SDimitry Andric         Register Reg0 = TRI->getSubReg(RegBegin, ARM::gsub_0);
3230b57cec5SDimitry Andric         O << ARMInstPrinter::getRegisterName(Reg0) << ", ";
3240b57cec5SDimitry Andric         RegBegin = TRI->getSubReg(RegBegin, ARM::gsub_1);
3250b57cec5SDimitry Andric       }
3260b57cec5SDimitry Andric       O << ARMInstPrinter::getRegisterName(RegBegin);
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric       // FIXME: The register allocator not only may not have given us the
3290b57cec5SDimitry Andric       // registers in sequence, but may not be in ascending registers. This
3300b57cec5SDimitry Andric       // will require changes in the register allocator that'll need to be
3310b57cec5SDimitry Andric       // propagated down here if the operands change.
3320b57cec5SDimitry Andric       unsigned RegOps = OpNum + 1;
3330b57cec5SDimitry Andric       while (MI->getOperand(RegOps).isReg()) {
3340b57cec5SDimitry Andric         O << ", "
3350b57cec5SDimitry Andric           << ARMInstPrinter::getRegisterName(MI->getOperand(RegOps).getReg());
3360b57cec5SDimitry Andric         RegOps++;
3370b57cec5SDimitry Andric       }
3380b57cec5SDimitry Andric 
3390b57cec5SDimitry Andric       O << "}";
3400b57cec5SDimitry Andric 
3410b57cec5SDimitry Andric       return false;
3420b57cec5SDimitry Andric     }
3430b57cec5SDimitry Andric     case 'R': // The most significant register of a pair.
3440b57cec5SDimitry Andric     case 'Q': { // The least significant register of a pair.
3450b57cec5SDimitry Andric       if (OpNum == 0)
3460b57cec5SDimitry Andric         return true;
3470b57cec5SDimitry Andric       const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1);
3480b57cec5SDimitry Andric       if (!FlagsOP.isImm())
3490b57cec5SDimitry Andric         return true;
3500b57cec5SDimitry Andric       unsigned Flags = FlagsOP.getImm();
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric       // This operand may not be the one that actually provides the register. If
3530b57cec5SDimitry Andric       // it's tied to a previous one then we should refer instead to that one
3540b57cec5SDimitry Andric       // for registers and their classes.
3550b57cec5SDimitry Andric       unsigned TiedIdx;
3560b57cec5SDimitry Andric       if (InlineAsm::isUseOperandTiedToDef(Flags, TiedIdx)) {
3570b57cec5SDimitry Andric         for (OpNum = InlineAsm::MIOp_FirstOperand; TiedIdx; --TiedIdx) {
3580b57cec5SDimitry Andric           unsigned OpFlags = MI->getOperand(OpNum).getImm();
3590b57cec5SDimitry Andric           OpNum += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
3600b57cec5SDimitry Andric         }
3610b57cec5SDimitry Andric         Flags = MI->getOperand(OpNum).getImm();
3620b57cec5SDimitry Andric 
3630b57cec5SDimitry Andric         // Later code expects OpNum to be pointing at the register rather than
3640b57cec5SDimitry Andric         // the flags.
3650b57cec5SDimitry Andric         OpNum += 1;
3660b57cec5SDimitry Andric       }
3670b57cec5SDimitry Andric 
3680b57cec5SDimitry Andric       unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
3690b57cec5SDimitry Andric       unsigned RC;
3700b57cec5SDimitry Andric       bool FirstHalf;
3710b57cec5SDimitry Andric       const ARMBaseTargetMachine &ATM =
3720b57cec5SDimitry Andric         static_cast<const ARMBaseTargetMachine &>(TM);
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric       // 'Q' should correspond to the low order register and 'R' to the high
3750b57cec5SDimitry Andric       // order register.  Whether this corresponds to the upper or lower half
3760b57cec5SDimitry Andric       // depends on the endianess mode.
3770b57cec5SDimitry Andric       if (ExtraCode[0] == 'Q')
3780b57cec5SDimitry Andric         FirstHalf = ATM.isLittleEndian();
3790b57cec5SDimitry Andric       else
3800b57cec5SDimitry Andric         // ExtraCode[0] == 'R'.
3810b57cec5SDimitry Andric         FirstHalf = !ATM.isLittleEndian();
3820b57cec5SDimitry Andric       const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
3830b57cec5SDimitry Andric       if (InlineAsm::hasRegClassConstraint(Flags, RC) &&
3840b57cec5SDimitry Andric           ARM::GPRPairRegClass.hasSubClassEq(TRI->getRegClass(RC))) {
3850b57cec5SDimitry Andric         if (NumVals != 1)
3860b57cec5SDimitry Andric           return true;
3870b57cec5SDimitry Andric         const MachineOperand &MO = MI->getOperand(OpNum);
3880b57cec5SDimitry Andric         if (!MO.isReg())
3890b57cec5SDimitry Andric           return true;
3900b57cec5SDimitry Andric         const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
3918bcb0991SDimitry Andric         Register Reg =
3928bcb0991SDimitry Andric             TRI->getSubReg(MO.getReg(), FirstHalf ? ARM::gsub_0 : ARM::gsub_1);
3930b57cec5SDimitry Andric         O << ARMInstPrinter::getRegisterName(Reg);
3940b57cec5SDimitry Andric         return false;
3950b57cec5SDimitry Andric       }
3960b57cec5SDimitry Andric       if (NumVals != 2)
3970b57cec5SDimitry Andric         return true;
3980b57cec5SDimitry Andric       unsigned RegOp = FirstHalf ? OpNum : OpNum + 1;
3990b57cec5SDimitry Andric       if (RegOp >= MI->getNumOperands())
4000b57cec5SDimitry Andric         return true;
4010b57cec5SDimitry Andric       const MachineOperand &MO = MI->getOperand(RegOp);
4020b57cec5SDimitry Andric       if (!MO.isReg())
4030b57cec5SDimitry Andric         return true;
4048bcb0991SDimitry Andric       Register Reg = MO.getReg();
4050b57cec5SDimitry Andric       O << ARMInstPrinter::getRegisterName(Reg);
4060b57cec5SDimitry Andric       return false;
4070b57cec5SDimitry Andric     }
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric     case 'e': // The low doubleword register of a NEON quad register.
4100b57cec5SDimitry Andric     case 'f': { // The high doubleword register of a NEON quad register.
4110b57cec5SDimitry Andric       if (!MI->getOperand(OpNum).isReg())
4120b57cec5SDimitry Andric         return true;
4138bcb0991SDimitry Andric       Register Reg = MI->getOperand(OpNum).getReg();
4140b57cec5SDimitry Andric       if (!ARM::QPRRegClass.contains(Reg))
4150b57cec5SDimitry Andric         return true;
4160b57cec5SDimitry Andric       const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
4178bcb0991SDimitry Andric       Register SubReg =
4188bcb0991SDimitry Andric           TRI->getSubReg(Reg, ExtraCode[0] == 'e' ? ARM::dsub_0 : ARM::dsub_1);
4190b57cec5SDimitry Andric       O << ARMInstPrinter::getRegisterName(SubReg);
4200b57cec5SDimitry Andric       return false;
4210b57cec5SDimitry Andric     }
4220b57cec5SDimitry Andric 
4230b57cec5SDimitry Andric     // This modifier is not yet supported.
4240b57cec5SDimitry Andric     case 'h': // A range of VFP/NEON registers suitable for VLD1/VST1.
4250b57cec5SDimitry Andric       return true;
4260b57cec5SDimitry Andric     case 'H': { // The highest-numbered register of a pair.
4270b57cec5SDimitry Andric       const MachineOperand &MO = MI->getOperand(OpNum);
4280b57cec5SDimitry Andric       if (!MO.isReg())
4290b57cec5SDimitry Andric         return true;
4300b57cec5SDimitry Andric       const MachineFunction &MF = *MI->getParent()->getParent();
4310b57cec5SDimitry Andric       const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
4328bcb0991SDimitry Andric       Register Reg = MO.getReg();
4330b57cec5SDimitry Andric       if(!ARM::GPRPairRegClass.contains(Reg))
4340b57cec5SDimitry Andric         return false;
4350b57cec5SDimitry Andric       Reg = TRI->getSubReg(Reg, ARM::gsub_1);
4360b57cec5SDimitry Andric       O << ARMInstPrinter::getRegisterName(Reg);
4370b57cec5SDimitry Andric       return false;
4380b57cec5SDimitry Andric     }
4390b57cec5SDimitry Andric     }
4400b57cec5SDimitry Andric   }
4410b57cec5SDimitry Andric 
4420b57cec5SDimitry Andric   printOperand(MI, OpNum, O);
4430b57cec5SDimitry Andric   return false;
4440b57cec5SDimitry Andric }
4450b57cec5SDimitry Andric 
4460b57cec5SDimitry Andric bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
4470b57cec5SDimitry Andric                                           unsigned OpNum, const char *ExtraCode,
4480b57cec5SDimitry Andric                                           raw_ostream &O) {
4490b57cec5SDimitry Andric   // Does this asm operand have a single letter operand modifier?
4500b57cec5SDimitry Andric   if (ExtraCode && ExtraCode[0]) {
4510b57cec5SDimitry Andric     if (ExtraCode[1] != 0) return true; // Unknown modifier.
4520b57cec5SDimitry Andric 
4530b57cec5SDimitry Andric     switch (ExtraCode[0]) {
4540b57cec5SDimitry Andric       case 'A': // A memory operand for a VLD1/VST1 instruction.
4550b57cec5SDimitry Andric       default: return true;  // Unknown modifier.
4560b57cec5SDimitry Andric       case 'm': // The base register of a memory operand.
4570b57cec5SDimitry Andric         if (!MI->getOperand(OpNum).isReg())
4580b57cec5SDimitry Andric           return true;
4590b57cec5SDimitry Andric         O << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg());
4600b57cec5SDimitry Andric         return false;
4610b57cec5SDimitry Andric     }
4620b57cec5SDimitry Andric   }
4630b57cec5SDimitry Andric 
4640b57cec5SDimitry Andric   const MachineOperand &MO = MI->getOperand(OpNum);
4650b57cec5SDimitry Andric   assert(MO.isReg() && "unexpected inline asm memory operand");
4660b57cec5SDimitry Andric   O << "[" << ARMInstPrinter::getRegisterName(MO.getReg()) << "]";
4670b57cec5SDimitry Andric   return false;
4680b57cec5SDimitry Andric }
4690b57cec5SDimitry Andric 
4700b57cec5SDimitry Andric static bool isThumb(const MCSubtargetInfo& STI) {
4710b57cec5SDimitry Andric   return STI.getFeatureBits()[ARM::ModeThumb];
4720b57cec5SDimitry Andric }
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric void ARMAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
4750b57cec5SDimitry Andric                                      const MCSubtargetInfo *EndInfo) const {
4760b57cec5SDimitry Andric   // If either end mode is unknown (EndInfo == NULL) or different than
4770b57cec5SDimitry Andric   // the start mode, then restore the start mode.
4780b57cec5SDimitry Andric   const bool WasThumb = isThumb(StartInfo);
4790b57cec5SDimitry Andric   if (!EndInfo || WasThumb != isThumb(*EndInfo)) {
4805ffd83dbSDimitry Andric     OutStreamer->emitAssemblerFlag(WasThumb ? MCAF_Code16 : MCAF_Code32);
4810b57cec5SDimitry Andric   }
4820b57cec5SDimitry Andric }
4830b57cec5SDimitry Andric 
4845ffd83dbSDimitry Andric void ARMAsmPrinter::emitStartOfAsmFile(Module &M) {
4850b57cec5SDimitry Andric   const Triple &TT = TM.getTargetTriple();
4860b57cec5SDimitry Andric   // Use unified assembler syntax.
4875ffd83dbSDimitry Andric   OutStreamer->emitAssemblerFlag(MCAF_SyntaxUnified);
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric   // Emit ARM Build Attributes
4900b57cec5SDimitry Andric   if (TT.isOSBinFormatELF())
4910b57cec5SDimitry Andric     emitAttributes();
4920b57cec5SDimitry Andric 
4930b57cec5SDimitry Andric   // Use the triple's architecture and subarchitecture to determine
4940b57cec5SDimitry Andric   // if we're thumb for the purposes of the top level code16 assembler
4950b57cec5SDimitry Andric   // flag.
4960b57cec5SDimitry Andric   if (!M.getModuleInlineAsm().empty() && TT.isThumb())
4975ffd83dbSDimitry Andric     OutStreamer->emitAssemblerFlag(MCAF_Code16);
4980b57cec5SDimitry Andric }
4990b57cec5SDimitry Andric 
5000b57cec5SDimitry Andric static void
5010b57cec5SDimitry Andric emitNonLazySymbolPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel,
5020b57cec5SDimitry Andric                          MachineModuleInfoImpl::StubValueTy &MCSym) {
5030b57cec5SDimitry Andric   // L_foo$stub:
5045ffd83dbSDimitry Andric   OutStreamer.emitLabel(StubLabel);
5050b57cec5SDimitry Andric   //   .indirect_symbol _foo
5065ffd83dbSDimitry Andric   OutStreamer.emitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol);
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric   if (MCSym.getInt())
5090b57cec5SDimitry Andric     // External to current translation unit.
5105ffd83dbSDimitry Andric     OutStreamer.emitIntValue(0, 4/*size*/);
5110b57cec5SDimitry Andric   else
5120b57cec5SDimitry Andric     // Internal to current translation unit.
5130b57cec5SDimitry Andric     //
5140b57cec5SDimitry Andric     // When we place the LSDA into the TEXT section, the type info
5150b57cec5SDimitry Andric     // pointers need to be indirect and pc-rel. We accomplish this by
5160b57cec5SDimitry Andric     // using NLPs; however, sometimes the types are local to the file.
5170b57cec5SDimitry Andric     // We need to fill in the value for the NLP in those cases.
5185ffd83dbSDimitry Andric     OutStreamer.emitValue(
5190b57cec5SDimitry Andric         MCSymbolRefExpr::create(MCSym.getPointer(), OutStreamer.getContext()),
5200b57cec5SDimitry Andric         4 /*size*/);
5210b57cec5SDimitry Andric }
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric 
5245ffd83dbSDimitry Andric void ARMAsmPrinter::emitEndOfAsmFile(Module &M) {
5250b57cec5SDimitry Andric   const Triple &TT = TM.getTargetTriple();
5260b57cec5SDimitry Andric   if (TT.isOSBinFormatMachO()) {
5270b57cec5SDimitry Andric     // All darwin targets use mach-o.
5280b57cec5SDimitry Andric     const TargetLoweringObjectFileMachO &TLOFMacho =
5290b57cec5SDimitry Andric       static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
5300b57cec5SDimitry Andric     MachineModuleInfoMachO &MMIMacho =
5310b57cec5SDimitry Andric       MMI->getObjFileInfo<MachineModuleInfoMachO>();
5320b57cec5SDimitry Andric 
5330b57cec5SDimitry Andric     // Output non-lazy-pointers for external and common global variables.
5340b57cec5SDimitry Andric     MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList();
5350b57cec5SDimitry Andric 
5360b57cec5SDimitry Andric     if (!Stubs.empty()) {
5370b57cec5SDimitry Andric       // Switch with ".non_lazy_symbol_pointer" directive.
5380b57cec5SDimitry Andric       OutStreamer->SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
5395ffd83dbSDimitry Andric       emitAlignment(Align(4));
5400b57cec5SDimitry Andric 
5410b57cec5SDimitry Andric       for (auto &Stub : Stubs)
5420b57cec5SDimitry Andric         emitNonLazySymbolPointer(*OutStreamer, Stub.first, Stub.second);
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric       Stubs.clear();
5450b57cec5SDimitry Andric       OutStreamer->AddBlankLine();
5460b57cec5SDimitry Andric     }
5470b57cec5SDimitry Andric 
5480b57cec5SDimitry Andric     Stubs = MMIMacho.GetThreadLocalGVStubList();
5490b57cec5SDimitry Andric     if (!Stubs.empty()) {
5500b57cec5SDimitry Andric       // Switch with ".non_lazy_symbol_pointer" directive.
5510b57cec5SDimitry Andric       OutStreamer->SwitchSection(TLOFMacho.getThreadLocalPointerSection());
5525ffd83dbSDimitry Andric       emitAlignment(Align(4));
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric       for (auto &Stub : Stubs)
5550b57cec5SDimitry Andric         emitNonLazySymbolPointer(*OutStreamer, Stub.first, Stub.second);
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric       Stubs.clear();
5580b57cec5SDimitry Andric       OutStreamer->AddBlankLine();
5590b57cec5SDimitry Andric     }
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric     // Funny Darwin hack: This flag tells the linker that no global symbols
5620b57cec5SDimitry Andric     // contain code that falls through to other global symbols (e.g. the obvious
5630b57cec5SDimitry Andric     // implementation of multiple entry points).  If this doesn't occur, the
5640b57cec5SDimitry Andric     // linker can safely perform dead code stripping.  Since LLVM never
5650b57cec5SDimitry Andric     // generates code that does this, it is always safe to set.
5665ffd83dbSDimitry Andric     OutStreamer->emitAssemblerFlag(MCAF_SubsectionsViaSymbols);
5670b57cec5SDimitry Andric   }
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric   // The last attribute to be emitted is ABI_optimization_goals
5700b57cec5SDimitry Andric   MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
5710b57cec5SDimitry Andric   ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
5720b57cec5SDimitry Andric 
5730b57cec5SDimitry Andric   if (OptimizationGoals > 0 &&
5740b57cec5SDimitry Andric       (Subtarget->isTargetAEABI() || Subtarget->isTargetGNUAEABI() ||
5750b57cec5SDimitry Andric        Subtarget->isTargetMuslAEABI()))
5760b57cec5SDimitry Andric     ATS.emitAttribute(ARMBuildAttrs::ABI_optimization_goals, OptimizationGoals);
5770b57cec5SDimitry Andric   OptimizationGoals = -1;
5780b57cec5SDimitry Andric 
5790b57cec5SDimitry Andric   ATS.finishAttributeSection();
5800b57cec5SDimitry Andric }
5810b57cec5SDimitry Andric 
5820b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
5835ffd83dbSDimitry Andric // Helper routines for emitStartOfAsmFile() and emitEndOfAsmFile()
5840b57cec5SDimitry Andric // FIXME:
5850b57cec5SDimitry Andric // The following seem like one-off assembler flags, but they actually need
5860b57cec5SDimitry Andric // to appear in the .ARM.attributes section in ELF.
5870b57cec5SDimitry Andric // Instead of subclassing the MCELFStreamer, we do the work here.
5880b57cec5SDimitry Andric 
5890b57cec5SDimitry Andric  // Returns true if all functions have the same function attribute value.
5900b57cec5SDimitry Andric  // It also returns true when the module has no functions.
5910b57cec5SDimitry Andric static bool checkFunctionsAttributeConsistency(const Module &M, StringRef Attr,
5920b57cec5SDimitry Andric                                                StringRef Value) {
5930b57cec5SDimitry Andric    return !any_of(M, [&](const Function &F) {
5940b57cec5SDimitry Andric        return F.getFnAttribute(Attr).getValueAsString() != Value;
5950b57cec5SDimitry Andric    });
5960b57cec5SDimitry Andric }
5975ffd83dbSDimitry Andric // Returns true if all functions have the same denormal mode.
5985ffd83dbSDimitry Andric // It also returns true when the module has no functions.
5995ffd83dbSDimitry Andric static bool checkDenormalAttributeConsistency(const Module &M,
6005ffd83dbSDimitry Andric                                               StringRef Attr,
6015ffd83dbSDimitry Andric                                               DenormalMode Value) {
6025ffd83dbSDimitry Andric   return !any_of(M, [&](const Function &F) {
6035ffd83dbSDimitry Andric     StringRef AttrVal = F.getFnAttribute(Attr).getValueAsString();
6045ffd83dbSDimitry Andric     return parseDenormalFPAttribute(AttrVal) != Value;
6055ffd83dbSDimitry Andric   });
6065ffd83dbSDimitry Andric }
6070b57cec5SDimitry Andric 
6080b57cec5SDimitry Andric void ARMAsmPrinter::emitAttributes() {
6090b57cec5SDimitry Andric   MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
6100b57cec5SDimitry Andric   ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric   ATS.emitTextAttribute(ARMBuildAttrs::conformance, "2.09");
6130b57cec5SDimitry Andric 
6140b57cec5SDimitry Andric   ATS.switchVendor("aeabi");
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric   // Compute ARM ELF Attributes based on the default subtarget that
6170b57cec5SDimitry Andric   // we'd have constructed. The existing ARM behavior isn't LTO clean
6180b57cec5SDimitry Andric   // anyhow.
6190b57cec5SDimitry Andric   // FIXME: For ifunc related functions we could iterate over and look
6200b57cec5SDimitry Andric   // for a feature string that doesn't match the default one.
6210b57cec5SDimitry Andric   const Triple &TT = TM.getTargetTriple();
6220b57cec5SDimitry Andric   StringRef CPU = TM.getTargetCPU();
6230b57cec5SDimitry Andric   StringRef FS = TM.getTargetFeatureString();
6240b57cec5SDimitry Andric   std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU);
6250b57cec5SDimitry Andric   if (!FS.empty()) {
6260b57cec5SDimitry Andric     if (!ArchFS.empty())
6270b57cec5SDimitry Andric       ArchFS = (Twine(ArchFS) + "," + FS).str();
6280b57cec5SDimitry Andric     else
6295ffd83dbSDimitry Andric       ArchFS = std::string(FS);
6300b57cec5SDimitry Andric   }
6310b57cec5SDimitry Andric   const ARMBaseTargetMachine &ATM =
6320b57cec5SDimitry Andric       static_cast<const ARMBaseTargetMachine &>(TM);
6335ffd83dbSDimitry Andric   const ARMSubtarget STI(TT, std::string(CPU), ArchFS, ATM,
6345ffd83dbSDimitry Andric                          ATM.isLittleEndian());
6350b57cec5SDimitry Andric 
6360b57cec5SDimitry Andric   // Emit build attributes for the available hardware.
6370b57cec5SDimitry Andric   ATS.emitTargetAttributes(STI);
6380b57cec5SDimitry Andric 
6390b57cec5SDimitry Andric   // RW data addressing.
6400b57cec5SDimitry Andric   if (isPositionIndependent()) {
6410b57cec5SDimitry Andric     ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_RW_data,
6420b57cec5SDimitry Andric                       ARMBuildAttrs::AddressRWPCRel);
6430b57cec5SDimitry Andric   } else if (STI.isRWPI()) {
6440b57cec5SDimitry Andric     // RWPI specific attributes.
6450b57cec5SDimitry Andric     ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_RW_data,
6460b57cec5SDimitry Andric                       ARMBuildAttrs::AddressRWSBRel);
6470b57cec5SDimitry Andric   }
6480b57cec5SDimitry Andric 
6490b57cec5SDimitry Andric   // RO data addressing.
6500b57cec5SDimitry Andric   if (isPositionIndependent() || STI.isROPI()) {
6510b57cec5SDimitry Andric     ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_RO_data,
6520b57cec5SDimitry Andric                       ARMBuildAttrs::AddressROPCRel);
6530b57cec5SDimitry Andric   }
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric   // GOT use.
6560b57cec5SDimitry Andric   if (isPositionIndependent()) {
6570b57cec5SDimitry Andric     ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_GOT_use,
6580b57cec5SDimitry Andric                       ARMBuildAttrs::AddressGOT);
6590b57cec5SDimitry Andric   } else {
6600b57cec5SDimitry Andric     ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_GOT_use,
6610b57cec5SDimitry Andric                       ARMBuildAttrs::AddressDirect);
6620b57cec5SDimitry Andric   }
6630b57cec5SDimitry Andric 
6640b57cec5SDimitry Andric   // Set FP Denormals.
6655ffd83dbSDimitry Andric   if (checkDenormalAttributeConsistency(*MMI->getModule(), "denormal-fp-math",
6665ffd83dbSDimitry Andric                                         DenormalMode::getPreserveSign()))
6670b57cec5SDimitry Andric     ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal,
6680b57cec5SDimitry Andric                       ARMBuildAttrs::PreserveFPSign);
6695ffd83dbSDimitry Andric   else if (checkDenormalAttributeConsistency(*MMI->getModule(),
6700b57cec5SDimitry Andric                                              "denormal-fp-math",
6715ffd83dbSDimitry Andric                                              DenormalMode::getPositiveZero()))
6720b57cec5SDimitry Andric     ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal,
6730b57cec5SDimitry Andric                       ARMBuildAttrs::PositiveZero);
6740b57cec5SDimitry Andric   else if (!TM.Options.UnsafeFPMath)
6750b57cec5SDimitry Andric     ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal,
6760b57cec5SDimitry Andric                       ARMBuildAttrs::IEEEDenormals);
6770b57cec5SDimitry Andric   else {
6780b57cec5SDimitry Andric     if (!STI.hasVFP2Base()) {
6790b57cec5SDimitry Andric       // When the target doesn't have an FPU (by design or
6800b57cec5SDimitry Andric       // intention), the assumptions made on the software support
6810b57cec5SDimitry Andric       // mirror that of the equivalent hardware support *if it
6820b57cec5SDimitry Andric       // existed*. For v7 and better we indicate that denormals are
6830b57cec5SDimitry Andric       // flushed preserving sign, and for V6 we indicate that
6840b57cec5SDimitry Andric       // denormals are flushed to positive zero.
6850b57cec5SDimitry Andric       if (STI.hasV7Ops())
6860b57cec5SDimitry Andric         ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal,
6870b57cec5SDimitry Andric                           ARMBuildAttrs::PreserveFPSign);
6880b57cec5SDimitry Andric     } else if (STI.hasVFP3Base()) {
6890b57cec5SDimitry Andric       // In VFPv4, VFPv4U, VFPv3, or VFPv3U, it is preserved. That is,
6900b57cec5SDimitry Andric       // the sign bit of the zero matches the sign bit of the input or
6910b57cec5SDimitry Andric       // result that is being flushed to zero.
6920b57cec5SDimitry Andric       ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal,
6930b57cec5SDimitry Andric                         ARMBuildAttrs::PreserveFPSign);
6940b57cec5SDimitry Andric     }
6950b57cec5SDimitry Andric     // For VFPv2 implementations it is implementation defined as
6960b57cec5SDimitry Andric     // to whether denormals are flushed to positive zero or to
6970b57cec5SDimitry Andric     // whatever the sign of zero is (ARM v7AR ARM 2.7.5). Historically
6980b57cec5SDimitry Andric     // LLVM has chosen to flush this to positive zero (most likely for
6990b57cec5SDimitry Andric     // GCC compatibility), so that's the chosen value here (the
7000b57cec5SDimitry Andric     // absence of its emission implies zero).
7010b57cec5SDimitry Andric   }
7020b57cec5SDimitry Andric 
7030b57cec5SDimitry Andric   // Set FP exceptions and rounding
7040b57cec5SDimitry Andric   if (checkFunctionsAttributeConsistency(*MMI->getModule(),
7050b57cec5SDimitry Andric                                          "no-trapping-math", "true") ||
7060b57cec5SDimitry Andric       TM.Options.NoTrappingFPMath)
7070b57cec5SDimitry Andric     ATS.emitAttribute(ARMBuildAttrs::ABI_FP_exceptions,
7080b57cec5SDimitry Andric                       ARMBuildAttrs::Not_Allowed);
7090b57cec5SDimitry Andric   else if (!TM.Options.UnsafeFPMath) {
7100b57cec5SDimitry Andric     ATS.emitAttribute(ARMBuildAttrs::ABI_FP_exceptions, ARMBuildAttrs::Allowed);
7110b57cec5SDimitry Andric 
7120b57cec5SDimitry Andric     // If the user has permitted this code to choose the IEEE 754
7130b57cec5SDimitry Andric     // rounding at run-time, emit the rounding attribute.
7140b57cec5SDimitry Andric     if (TM.Options.HonorSignDependentRoundingFPMathOption)
7150b57cec5SDimitry Andric       ATS.emitAttribute(ARMBuildAttrs::ABI_FP_rounding, ARMBuildAttrs::Allowed);
7160b57cec5SDimitry Andric   }
7170b57cec5SDimitry Andric 
7180b57cec5SDimitry Andric   // TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath is the
7190b57cec5SDimitry Andric   // equivalent of GCC's -ffinite-math-only flag.
7200b57cec5SDimitry Andric   if (TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath)
7210b57cec5SDimitry Andric     ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model,
7220b57cec5SDimitry Andric                       ARMBuildAttrs::Allowed);
7230b57cec5SDimitry Andric   else
7240b57cec5SDimitry Andric     ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model,
7250b57cec5SDimitry Andric                       ARMBuildAttrs::AllowIEEE754);
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric   // FIXME: add more flags to ARMBuildAttributes.h
7280b57cec5SDimitry Andric   // 8-bytes alignment stuff.
7290b57cec5SDimitry Andric   ATS.emitAttribute(ARMBuildAttrs::ABI_align_needed, 1);
7300b57cec5SDimitry Andric   ATS.emitAttribute(ARMBuildAttrs::ABI_align_preserved, 1);
7310b57cec5SDimitry Andric 
7320b57cec5SDimitry Andric   // Hard float.  Use both S and D registers and conform to AAPCS-VFP.
7330b57cec5SDimitry Andric   if (STI.isAAPCS_ABI() && TM.Options.FloatABIType == FloatABI::Hard)
7340b57cec5SDimitry Andric     ATS.emitAttribute(ARMBuildAttrs::ABI_VFP_args, ARMBuildAttrs::HardFPAAPCS);
7350b57cec5SDimitry Andric 
7360b57cec5SDimitry Andric   // FIXME: To support emitting this build attribute as GCC does, the
7370b57cec5SDimitry Andric   // -mfp16-format option and associated plumbing must be
7380b57cec5SDimitry Andric   // supported. For now the __fp16 type is exposed by default, so this
7390b57cec5SDimitry Andric   // attribute should be emitted with value 1.
7400b57cec5SDimitry Andric   ATS.emitAttribute(ARMBuildAttrs::ABI_FP_16bit_format,
7410b57cec5SDimitry Andric                     ARMBuildAttrs::FP16FormatIEEE);
7420b57cec5SDimitry Andric 
7430b57cec5SDimitry Andric   if (MMI) {
7440b57cec5SDimitry Andric     if (const Module *SourceModule = MMI->getModule()) {
7450b57cec5SDimitry Andric       // ABI_PCS_wchar_t to indicate wchar_t width
7460b57cec5SDimitry Andric       // FIXME: There is no way to emit value 0 (wchar_t prohibited).
7470b57cec5SDimitry Andric       if (auto WCharWidthValue = mdconst::extract_or_null<ConstantInt>(
7480b57cec5SDimitry Andric               SourceModule->getModuleFlag("wchar_size"))) {
7490b57cec5SDimitry Andric         int WCharWidth = WCharWidthValue->getZExtValue();
7500b57cec5SDimitry Andric         assert((WCharWidth == 2 || WCharWidth == 4) &&
7510b57cec5SDimitry Andric                "wchar_t width must be 2 or 4 bytes");
7520b57cec5SDimitry Andric         ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_wchar_t, WCharWidth);
7530b57cec5SDimitry Andric       }
7540b57cec5SDimitry Andric 
7550b57cec5SDimitry Andric       // ABI_enum_size to indicate enum width
7560b57cec5SDimitry Andric       // FIXME: There is no way to emit value 0 (enums prohibited) or value 3
7570b57cec5SDimitry Andric       //        (all enums contain a value needing 32 bits to encode).
7580b57cec5SDimitry Andric       if (auto EnumWidthValue = mdconst::extract_or_null<ConstantInt>(
7590b57cec5SDimitry Andric               SourceModule->getModuleFlag("min_enum_size"))) {
7600b57cec5SDimitry Andric         int EnumWidth = EnumWidthValue->getZExtValue();
7610b57cec5SDimitry Andric         assert((EnumWidth == 1 || EnumWidth == 4) &&
7620b57cec5SDimitry Andric                "Minimum enum width must be 1 or 4 bytes");
7630b57cec5SDimitry Andric         int EnumBuildAttr = EnumWidth == 1 ? 1 : 2;
7640b57cec5SDimitry Andric         ATS.emitAttribute(ARMBuildAttrs::ABI_enum_size, EnumBuildAttr);
7650b57cec5SDimitry Andric       }
7660b57cec5SDimitry Andric     }
7670b57cec5SDimitry Andric   }
7680b57cec5SDimitry Andric 
7690b57cec5SDimitry Andric   // We currently do not support using R9 as the TLS pointer.
7700b57cec5SDimitry Andric   if (STI.isRWPI())
7710b57cec5SDimitry Andric     ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use,
7720b57cec5SDimitry Andric                       ARMBuildAttrs::R9IsSB);
7730b57cec5SDimitry Andric   else if (STI.isR9Reserved())
7740b57cec5SDimitry Andric     ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use,
7750b57cec5SDimitry Andric                       ARMBuildAttrs::R9Reserved);
7760b57cec5SDimitry Andric   else
7770b57cec5SDimitry Andric     ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use,
7780b57cec5SDimitry Andric                       ARMBuildAttrs::R9IsGPR);
7790b57cec5SDimitry Andric }
7800b57cec5SDimitry Andric 
7810b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
7820b57cec5SDimitry Andric 
7830b57cec5SDimitry Andric static MCSymbol *getBFLabel(StringRef Prefix, unsigned FunctionNumber,
7840b57cec5SDimitry Andric                              unsigned LabelId, MCContext &Ctx) {
7850b57cec5SDimitry Andric 
7860b57cec5SDimitry Andric   MCSymbol *Label = Ctx.getOrCreateSymbol(Twine(Prefix)
7870b57cec5SDimitry Andric                        + "BF" + Twine(FunctionNumber) + "_" + Twine(LabelId));
7880b57cec5SDimitry Andric   return Label;
7890b57cec5SDimitry Andric }
7900b57cec5SDimitry Andric 
7910b57cec5SDimitry Andric static MCSymbol *getPICLabel(StringRef Prefix, unsigned FunctionNumber,
7920b57cec5SDimitry Andric                              unsigned LabelId, MCContext &Ctx) {
7930b57cec5SDimitry Andric 
7940b57cec5SDimitry Andric   MCSymbol *Label = Ctx.getOrCreateSymbol(Twine(Prefix)
7950b57cec5SDimitry Andric                        + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId));
7960b57cec5SDimitry Andric   return Label;
7970b57cec5SDimitry Andric }
7980b57cec5SDimitry Andric 
7990b57cec5SDimitry Andric static MCSymbolRefExpr::VariantKind
8000b57cec5SDimitry Andric getModifierVariantKind(ARMCP::ARMCPModifier Modifier) {
8010b57cec5SDimitry Andric   switch (Modifier) {
8020b57cec5SDimitry Andric   case ARMCP::no_modifier:
8030b57cec5SDimitry Andric     return MCSymbolRefExpr::VK_None;
8040b57cec5SDimitry Andric   case ARMCP::TLSGD:
8050b57cec5SDimitry Andric     return MCSymbolRefExpr::VK_TLSGD;
8060b57cec5SDimitry Andric   case ARMCP::TPOFF:
8070b57cec5SDimitry Andric     return MCSymbolRefExpr::VK_TPOFF;
8080b57cec5SDimitry Andric   case ARMCP::GOTTPOFF:
8090b57cec5SDimitry Andric     return MCSymbolRefExpr::VK_GOTTPOFF;
8100b57cec5SDimitry Andric   case ARMCP::SBREL:
8110b57cec5SDimitry Andric     return MCSymbolRefExpr::VK_ARM_SBREL;
8120b57cec5SDimitry Andric   case ARMCP::GOT_PREL:
8130b57cec5SDimitry Andric     return MCSymbolRefExpr::VK_ARM_GOT_PREL;
8140b57cec5SDimitry Andric   case ARMCP::SECREL:
8150b57cec5SDimitry Andric     return MCSymbolRefExpr::VK_SECREL;
8160b57cec5SDimitry Andric   }
8170b57cec5SDimitry Andric   llvm_unreachable("Invalid ARMCPModifier!");
8180b57cec5SDimitry Andric }
8190b57cec5SDimitry Andric 
8200b57cec5SDimitry Andric MCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV,
8210b57cec5SDimitry Andric                                         unsigned char TargetFlags) {
8220b57cec5SDimitry Andric   if (Subtarget->isTargetMachO()) {
8230b57cec5SDimitry Andric     bool IsIndirect =
8240b57cec5SDimitry Andric         (TargetFlags & ARMII::MO_NONLAZY) && Subtarget->isGVIndirectSymbol(GV);
8250b57cec5SDimitry Andric 
8260b57cec5SDimitry Andric     if (!IsIndirect)
8270b57cec5SDimitry Andric       return getSymbol(GV);
8280b57cec5SDimitry Andric 
8290b57cec5SDimitry Andric     // FIXME: Remove this when Darwin transition to @GOT like syntax.
8300b57cec5SDimitry Andric     MCSymbol *MCSym = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
8310b57cec5SDimitry Andric     MachineModuleInfoMachO &MMIMachO =
8320b57cec5SDimitry Andric       MMI->getObjFileInfo<MachineModuleInfoMachO>();
8330b57cec5SDimitry Andric     MachineModuleInfoImpl::StubValueTy &StubSym =
8340b57cec5SDimitry Andric         GV->isThreadLocal() ? MMIMachO.getThreadLocalGVStubEntry(MCSym)
8350b57cec5SDimitry Andric                             : MMIMachO.getGVStubEntry(MCSym);
8360b57cec5SDimitry Andric 
8370b57cec5SDimitry Andric     if (!StubSym.getPointer())
8380b57cec5SDimitry Andric       StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(GV),
8390b57cec5SDimitry Andric                                                    !GV->hasInternalLinkage());
8400b57cec5SDimitry Andric     return MCSym;
8410b57cec5SDimitry Andric   } else if (Subtarget->isTargetCOFF()) {
8420b57cec5SDimitry Andric     assert(Subtarget->isTargetWindows() &&
8430b57cec5SDimitry Andric            "Windows is the only supported COFF target");
8440b57cec5SDimitry Andric 
8450b57cec5SDimitry Andric     bool IsIndirect =
8460b57cec5SDimitry Andric         (TargetFlags & (ARMII::MO_DLLIMPORT | ARMII::MO_COFFSTUB));
8470b57cec5SDimitry Andric     if (!IsIndirect)
8480b57cec5SDimitry Andric       return getSymbol(GV);
8490b57cec5SDimitry Andric 
8500b57cec5SDimitry Andric     SmallString<128> Name;
8510b57cec5SDimitry Andric     if (TargetFlags & ARMII::MO_DLLIMPORT)
8520b57cec5SDimitry Andric       Name = "__imp_";
8530b57cec5SDimitry Andric     else if (TargetFlags & ARMII::MO_COFFSTUB)
8540b57cec5SDimitry Andric       Name = ".refptr.";
8550b57cec5SDimitry Andric     getNameWithPrefix(Name, GV);
8560b57cec5SDimitry Andric 
8570b57cec5SDimitry Andric     MCSymbol *MCSym = OutContext.getOrCreateSymbol(Name);
8580b57cec5SDimitry Andric 
8590b57cec5SDimitry Andric     if (TargetFlags & ARMII::MO_COFFSTUB) {
8600b57cec5SDimitry Andric       MachineModuleInfoCOFF &MMICOFF =
8610b57cec5SDimitry Andric           MMI->getObjFileInfo<MachineModuleInfoCOFF>();
8620b57cec5SDimitry Andric       MachineModuleInfoImpl::StubValueTy &StubSym =
8630b57cec5SDimitry Andric           MMICOFF.getGVStubEntry(MCSym);
8640b57cec5SDimitry Andric 
8650b57cec5SDimitry Andric       if (!StubSym.getPointer())
8660b57cec5SDimitry Andric         StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(GV), true);
8670b57cec5SDimitry Andric     }
8680b57cec5SDimitry Andric 
8690b57cec5SDimitry Andric     return MCSym;
8700b57cec5SDimitry Andric   } else if (Subtarget->isTargetELF()) {
8710b57cec5SDimitry Andric     return getSymbol(GV);
8720b57cec5SDimitry Andric   }
8730b57cec5SDimitry Andric   llvm_unreachable("unexpected target");
8740b57cec5SDimitry Andric }
8750b57cec5SDimitry Andric 
8765ffd83dbSDimitry Andric void ARMAsmPrinter::emitMachineConstantPoolValue(
8775ffd83dbSDimitry Andric     MachineConstantPoolValue *MCPV) {
8780b57cec5SDimitry Andric   const DataLayout &DL = getDataLayout();
8790b57cec5SDimitry Andric   int Size = DL.getTypeAllocSize(MCPV->getType());
8800b57cec5SDimitry Andric 
8810b57cec5SDimitry Andric   ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);
8820b57cec5SDimitry Andric 
8830b57cec5SDimitry Andric   if (ACPV->isPromotedGlobal()) {
8840b57cec5SDimitry Andric     // This constant pool entry is actually a global whose storage has been
8850b57cec5SDimitry Andric     // promoted into the constant pool. This global may be referenced still
8860b57cec5SDimitry Andric     // by debug information, and due to the way AsmPrinter is set up, the debug
8870b57cec5SDimitry Andric     // info is immutable by the time we decide to promote globals to constant
8880b57cec5SDimitry Andric     // pools. Because of this, we need to ensure we emit a symbol for the global
8890b57cec5SDimitry Andric     // with private linkage (the default) so debug info can refer to it.
8900b57cec5SDimitry Andric     //
8910b57cec5SDimitry Andric     // However, if this global is promoted into several functions we must ensure
8920b57cec5SDimitry Andric     // we don't try and emit duplicate symbols!
8930b57cec5SDimitry Andric     auto *ACPC = cast<ARMConstantPoolConstant>(ACPV);
8940b57cec5SDimitry Andric     for (const auto *GV : ACPC->promotedGlobals()) {
8950b57cec5SDimitry Andric       if (!EmittedPromotedGlobalLabels.count(GV)) {
8960b57cec5SDimitry Andric         MCSymbol *GVSym = getSymbol(GV);
8975ffd83dbSDimitry Andric         OutStreamer->emitLabel(GVSym);
8980b57cec5SDimitry Andric         EmittedPromotedGlobalLabels.insert(GV);
8990b57cec5SDimitry Andric       }
9000b57cec5SDimitry Andric     }
9015ffd83dbSDimitry Andric     return emitGlobalConstant(DL, ACPC->getPromotedGlobalInit());
9020b57cec5SDimitry Andric   }
9030b57cec5SDimitry Andric 
9040b57cec5SDimitry Andric   MCSymbol *MCSym;
9050b57cec5SDimitry Andric   if (ACPV->isLSDA()) {
906e8d8bef9SDimitry Andric     MCSym = getMBBExceptionSym(MF->front());
9070b57cec5SDimitry Andric   } else if (ACPV->isBlockAddress()) {
9080b57cec5SDimitry Andric     const BlockAddress *BA =
9090b57cec5SDimitry Andric       cast<ARMConstantPoolConstant>(ACPV)->getBlockAddress();
9100b57cec5SDimitry Andric     MCSym = GetBlockAddressSymbol(BA);
9110b57cec5SDimitry Andric   } else if (ACPV->isGlobalValue()) {
9120b57cec5SDimitry Andric     const GlobalValue *GV = cast<ARMConstantPoolConstant>(ACPV)->getGV();
9130b57cec5SDimitry Andric 
9140b57cec5SDimitry Andric     // On Darwin, const-pool entries may get the "FOO$non_lazy_ptr" mangling, so
9150b57cec5SDimitry Andric     // flag the global as MO_NONLAZY.
9160b57cec5SDimitry Andric     unsigned char TF = Subtarget->isTargetMachO() ? ARMII::MO_NONLAZY : 0;
9170b57cec5SDimitry Andric     MCSym = GetARMGVSymbol(GV, TF);
9180b57cec5SDimitry Andric   } else if (ACPV->isMachineBasicBlock()) {
9190b57cec5SDimitry Andric     const MachineBasicBlock *MBB = cast<ARMConstantPoolMBB>(ACPV)->getMBB();
9200b57cec5SDimitry Andric     MCSym = MBB->getSymbol();
9210b57cec5SDimitry Andric   } else {
9220b57cec5SDimitry Andric     assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
9230b57cec5SDimitry Andric     auto Sym = cast<ARMConstantPoolSymbol>(ACPV)->getSymbol();
9240b57cec5SDimitry Andric     MCSym = GetExternalSymbolSymbol(Sym);
9250b57cec5SDimitry Andric   }
9260b57cec5SDimitry Andric 
9270b57cec5SDimitry Andric   // Create an MCSymbol for the reference.
9280b57cec5SDimitry Andric   const MCExpr *Expr =
9290b57cec5SDimitry Andric     MCSymbolRefExpr::create(MCSym, getModifierVariantKind(ACPV->getModifier()),
9300b57cec5SDimitry Andric                             OutContext);
9310b57cec5SDimitry Andric 
9320b57cec5SDimitry Andric   if (ACPV->getPCAdjustment()) {
9330b57cec5SDimitry Andric     MCSymbol *PCLabel =
9340b57cec5SDimitry Andric         getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
9350b57cec5SDimitry Andric                     ACPV->getLabelId(), OutContext);
9360b57cec5SDimitry Andric     const MCExpr *PCRelExpr = MCSymbolRefExpr::create(PCLabel, OutContext);
9370b57cec5SDimitry Andric     PCRelExpr =
9380b57cec5SDimitry Andric       MCBinaryExpr::createAdd(PCRelExpr,
9390b57cec5SDimitry Andric                               MCConstantExpr::create(ACPV->getPCAdjustment(),
9400b57cec5SDimitry Andric                                                      OutContext),
9410b57cec5SDimitry Andric                               OutContext);
9420b57cec5SDimitry Andric     if (ACPV->mustAddCurrentAddress()) {
9430b57cec5SDimitry Andric       // We want "(<expr> - .)", but MC doesn't have a concept of the '.'
9440b57cec5SDimitry Andric       // label, so just emit a local label end reference that instead.
9450b57cec5SDimitry Andric       MCSymbol *DotSym = OutContext.createTempSymbol();
9465ffd83dbSDimitry Andric       OutStreamer->emitLabel(DotSym);
9470b57cec5SDimitry Andric       const MCExpr *DotExpr = MCSymbolRefExpr::create(DotSym, OutContext);
9480b57cec5SDimitry Andric       PCRelExpr = MCBinaryExpr::createSub(PCRelExpr, DotExpr, OutContext);
9490b57cec5SDimitry Andric     }
9500b57cec5SDimitry Andric     Expr = MCBinaryExpr::createSub(Expr, PCRelExpr, OutContext);
9510b57cec5SDimitry Andric   }
9525ffd83dbSDimitry Andric   OutStreamer->emitValue(Expr, Size);
9530b57cec5SDimitry Andric }
9540b57cec5SDimitry Andric 
9555ffd83dbSDimitry Andric void ARMAsmPrinter::emitJumpTableAddrs(const MachineInstr *MI) {
9560b57cec5SDimitry Andric   const MachineOperand &MO1 = MI->getOperand(1);
9570b57cec5SDimitry Andric   unsigned JTI = MO1.getIndex();
9580b57cec5SDimitry Andric 
9590b57cec5SDimitry Andric   // Make sure the Thumb jump table is 4-byte aligned. This will be a nop for
9600b57cec5SDimitry Andric   // ARM mode tables.
9615ffd83dbSDimitry Andric   emitAlignment(Align(4));
9620b57cec5SDimitry Andric 
9630b57cec5SDimitry Andric   // Emit a label for the jump table.
9640b57cec5SDimitry Andric   MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);
9655ffd83dbSDimitry Andric   OutStreamer->emitLabel(JTISymbol);
9660b57cec5SDimitry Andric 
9670b57cec5SDimitry Andric   // Mark the jump table as data-in-code.
9685ffd83dbSDimitry Andric   OutStreamer->emitDataRegion(MCDR_DataRegionJT32);
9690b57cec5SDimitry Andric 
9700b57cec5SDimitry Andric   // Emit each entry of the table.
9710b57cec5SDimitry Andric   const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
9720b57cec5SDimitry Andric   const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
9730b57cec5SDimitry Andric   const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
9740b57cec5SDimitry Andric 
9750b57cec5SDimitry Andric   for (MachineBasicBlock *MBB : JTBBs) {
9760b57cec5SDimitry Andric     // Construct an MCExpr for the entry. We want a value of the form:
9770b57cec5SDimitry Andric     // (BasicBlockAddr - TableBeginAddr)
9780b57cec5SDimitry Andric     //
9790b57cec5SDimitry Andric     // For example, a table with entries jumping to basic blocks BB0 and BB1
9800b57cec5SDimitry Andric     // would look like:
9810b57cec5SDimitry Andric     // LJTI_0_0:
9820b57cec5SDimitry Andric     //    .word (LBB0 - LJTI_0_0)
9830b57cec5SDimitry Andric     //    .word (LBB1 - LJTI_0_0)
9840b57cec5SDimitry Andric     const MCExpr *Expr = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext);
9850b57cec5SDimitry Andric 
9860b57cec5SDimitry Andric     if (isPositionIndependent() || Subtarget->isROPI())
9870b57cec5SDimitry Andric       Expr = MCBinaryExpr::createSub(Expr, MCSymbolRefExpr::create(JTISymbol,
9880b57cec5SDimitry Andric                                                                    OutContext),
9890b57cec5SDimitry Andric                                      OutContext);
9900b57cec5SDimitry Andric     // If we're generating a table of Thumb addresses in static relocation
9910b57cec5SDimitry Andric     // model, we need to add one to keep interworking correctly.
9920b57cec5SDimitry Andric     else if (AFI->isThumbFunction())
9930b57cec5SDimitry Andric       Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(1,OutContext),
9940b57cec5SDimitry Andric                                      OutContext);
9955ffd83dbSDimitry Andric     OutStreamer->emitValue(Expr, 4);
9960b57cec5SDimitry Andric   }
9970b57cec5SDimitry Andric   // Mark the end of jump table data-in-code region.
9985ffd83dbSDimitry Andric   OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
9990b57cec5SDimitry Andric }
10000b57cec5SDimitry Andric 
10015ffd83dbSDimitry Andric void ARMAsmPrinter::emitJumpTableInsts(const MachineInstr *MI) {
10020b57cec5SDimitry Andric   const MachineOperand &MO1 = MI->getOperand(1);
10030b57cec5SDimitry Andric   unsigned JTI = MO1.getIndex();
10040b57cec5SDimitry Andric 
10050b57cec5SDimitry Andric   // Make sure the Thumb jump table is 4-byte aligned. This will be a nop for
10060b57cec5SDimitry Andric   // ARM mode tables.
10075ffd83dbSDimitry Andric   emitAlignment(Align(4));
10080b57cec5SDimitry Andric 
10090b57cec5SDimitry Andric   // Emit a label for the jump table.
10100b57cec5SDimitry Andric   MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);
10115ffd83dbSDimitry Andric   OutStreamer->emitLabel(JTISymbol);
10120b57cec5SDimitry Andric 
10130b57cec5SDimitry Andric   // Emit each entry of the table.
10140b57cec5SDimitry Andric   const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
10150b57cec5SDimitry Andric   const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
10160b57cec5SDimitry Andric   const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
10170b57cec5SDimitry Andric 
10180b57cec5SDimitry Andric   for (MachineBasicBlock *MBB : JTBBs) {
10190b57cec5SDimitry Andric     const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::create(MBB->getSymbol(),
10200b57cec5SDimitry Andric                                                           OutContext);
10210b57cec5SDimitry Andric     // If this isn't a TBB or TBH, the entries are direct branch instructions.
10220b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2B)
10230b57cec5SDimitry Andric         .addExpr(MBBSymbolExpr)
10240b57cec5SDimitry Andric         .addImm(ARMCC::AL)
10250b57cec5SDimitry Andric         .addReg(0));
10260b57cec5SDimitry Andric   }
10270b57cec5SDimitry Andric }
10280b57cec5SDimitry Andric 
10295ffd83dbSDimitry Andric void ARMAsmPrinter::emitJumpTableTBInst(const MachineInstr *MI,
10300b57cec5SDimitry Andric                                         unsigned OffsetWidth) {
10310b57cec5SDimitry Andric   assert((OffsetWidth == 1 || OffsetWidth == 2) && "invalid tbb/tbh width");
10320b57cec5SDimitry Andric   const MachineOperand &MO1 = MI->getOperand(1);
10330b57cec5SDimitry Andric   unsigned JTI = MO1.getIndex();
10340b57cec5SDimitry Andric 
10350b57cec5SDimitry Andric   if (Subtarget->isThumb1Only())
10365ffd83dbSDimitry Andric     emitAlignment(Align(4));
10370b57cec5SDimitry Andric 
10380b57cec5SDimitry Andric   MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI);
10395ffd83dbSDimitry Andric   OutStreamer->emitLabel(JTISymbol);
10400b57cec5SDimitry Andric 
10410b57cec5SDimitry Andric   // Emit each entry of the table.
10420b57cec5SDimitry Andric   const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
10430b57cec5SDimitry Andric   const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
10440b57cec5SDimitry Andric   const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
10450b57cec5SDimitry Andric 
10460b57cec5SDimitry Andric   // Mark the jump table as data-in-code.
10475ffd83dbSDimitry Andric   OutStreamer->emitDataRegion(OffsetWidth == 1 ? MCDR_DataRegionJT8
10480b57cec5SDimitry Andric                                                : MCDR_DataRegionJT16);
10490b57cec5SDimitry Andric 
10500b57cec5SDimitry Andric   for (auto MBB : JTBBs) {
10510b57cec5SDimitry Andric     const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::create(MBB->getSymbol(),
10520b57cec5SDimitry Andric                                                           OutContext);
10530b57cec5SDimitry Andric     // Otherwise it's an offset from the dispatch instruction. Construct an
10540b57cec5SDimitry Andric     // MCExpr for the entry. We want a value of the form:
10550b57cec5SDimitry Andric     // (BasicBlockAddr - TBBInstAddr + 4) / 2
10560b57cec5SDimitry Andric     //
10570b57cec5SDimitry Andric     // For example, a TBB table with entries jumping to basic blocks BB0 and BB1
10580b57cec5SDimitry Andric     // would look like:
10590b57cec5SDimitry Andric     // LJTI_0_0:
10600b57cec5SDimitry Andric     //    .byte (LBB0 - (LCPI0_0 + 4)) / 2
10610b57cec5SDimitry Andric     //    .byte (LBB1 - (LCPI0_0 + 4)) / 2
10620b57cec5SDimitry Andric     // where LCPI0_0 is a label defined just before the TBB instruction using
10630b57cec5SDimitry Andric     // this table.
10640b57cec5SDimitry Andric     MCSymbol *TBInstPC = GetCPISymbol(MI->getOperand(0).getImm());
10650b57cec5SDimitry Andric     const MCExpr *Expr = MCBinaryExpr::createAdd(
10660b57cec5SDimitry Andric         MCSymbolRefExpr::create(TBInstPC, OutContext),
10670b57cec5SDimitry Andric         MCConstantExpr::create(4, OutContext), OutContext);
10680b57cec5SDimitry Andric     Expr = MCBinaryExpr::createSub(MBBSymbolExpr, Expr, OutContext);
10690b57cec5SDimitry Andric     Expr = MCBinaryExpr::createDiv(Expr, MCConstantExpr::create(2, OutContext),
10700b57cec5SDimitry Andric                                    OutContext);
10715ffd83dbSDimitry Andric     OutStreamer->emitValue(Expr, OffsetWidth);
10720b57cec5SDimitry Andric   }
10730b57cec5SDimitry Andric   // Mark the end of jump table data-in-code region. 32-bit offsets use
10740b57cec5SDimitry Andric   // actual branch instructions here, so we don't mark those as a data-region
10750b57cec5SDimitry Andric   // at all.
10765ffd83dbSDimitry Andric   OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
10770b57cec5SDimitry Andric 
10780b57cec5SDimitry Andric   // Make sure the next instruction is 2-byte aligned.
10795ffd83dbSDimitry Andric   emitAlignment(Align(2));
10800b57cec5SDimitry Andric }
10810b57cec5SDimitry Andric 
10820b57cec5SDimitry Andric void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) {
10830b57cec5SDimitry Andric   assert(MI->getFlag(MachineInstr::FrameSetup) &&
10840b57cec5SDimitry Andric       "Only instruction which are involved into frame setup code are allowed");
10850b57cec5SDimitry Andric 
10860b57cec5SDimitry Andric   MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
10870b57cec5SDimitry Andric   ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
10880b57cec5SDimitry Andric   const MachineFunction &MF = *MI->getParent()->getParent();
10890b57cec5SDimitry Andric   const TargetRegisterInfo *TargetRegInfo =
10900b57cec5SDimitry Andric     MF.getSubtarget().getRegisterInfo();
10910b57cec5SDimitry Andric   const MachineRegisterInfo &MachineRegInfo = MF.getRegInfo();
10920b57cec5SDimitry Andric 
10938bcb0991SDimitry Andric   Register FramePtr = TargetRegInfo->getFrameRegister(MF);
10940b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
10950b57cec5SDimitry Andric   unsigned SrcReg, DstReg;
10960b57cec5SDimitry Andric 
10975ffd83dbSDimitry Andric   switch (Opc) {
10985ffd83dbSDimitry Andric   case ARM::tPUSH:
10995ffd83dbSDimitry Andric     // special case: tPUSH does not have src/dst regs.
11000b57cec5SDimitry Andric     SrcReg = DstReg = ARM::SP;
11015ffd83dbSDimitry Andric     break;
11025ffd83dbSDimitry Andric   case ARM::tLDRpci:
11035ffd83dbSDimitry Andric   case ARM::t2MOVi16:
11045ffd83dbSDimitry Andric   case ARM::t2MOVTi16:
11055ffd83dbSDimitry Andric     // special cases:
11065ffd83dbSDimitry Andric     // 1) for Thumb1 code we sometimes materialize the constant via constpool
11075ffd83dbSDimitry Andric     //    load.
11085ffd83dbSDimitry Andric     // 2) for Thumb2 execute only code we materialize the constant via
11095ffd83dbSDimitry Andric     //    immediate constants in 2 separate instructions (MOVW/MOVT).
11105ffd83dbSDimitry Andric     SrcReg = ~0U;
11115ffd83dbSDimitry Andric     DstReg = MI->getOperand(0).getReg();
11125ffd83dbSDimitry Andric     break;
11135ffd83dbSDimitry Andric   default:
11140b57cec5SDimitry Andric     SrcReg = MI->getOperand(1).getReg();
11150b57cec5SDimitry Andric     DstReg = MI->getOperand(0).getReg();
11165ffd83dbSDimitry Andric     break;
11170b57cec5SDimitry Andric   }
11180b57cec5SDimitry Andric 
11190b57cec5SDimitry Andric   // Try to figure out the unwinding opcode out of src / dst regs.
11200b57cec5SDimitry Andric   if (MI->mayStore()) {
11210b57cec5SDimitry Andric     // Register saves.
11220b57cec5SDimitry Andric     assert(DstReg == ARM::SP &&
11230b57cec5SDimitry Andric            "Only stack pointer as a destination reg is supported");
11240b57cec5SDimitry Andric 
11250b57cec5SDimitry Andric     SmallVector<unsigned, 4> RegList;
11260b57cec5SDimitry Andric     // Skip src & dst reg, and pred ops.
11270b57cec5SDimitry Andric     unsigned StartOp = 2 + 2;
11280b57cec5SDimitry Andric     // Use all the operands.
11290b57cec5SDimitry Andric     unsigned NumOffset = 0;
11300b57cec5SDimitry Andric     // Amount of SP adjustment folded into a push.
11310b57cec5SDimitry Andric     unsigned Pad = 0;
11320b57cec5SDimitry Andric 
11330b57cec5SDimitry Andric     switch (Opc) {
11340b57cec5SDimitry Andric     default:
11350b57cec5SDimitry Andric       MI->print(errs());
11360b57cec5SDimitry Andric       llvm_unreachable("Unsupported opcode for unwinding information");
11370b57cec5SDimitry Andric     case ARM::tPUSH:
11380b57cec5SDimitry Andric       // Special case here: no src & dst reg, but two extra imp ops.
11390b57cec5SDimitry Andric       StartOp = 2; NumOffset = 2;
11400b57cec5SDimitry Andric       LLVM_FALLTHROUGH;
11410b57cec5SDimitry Andric     case ARM::STMDB_UPD:
11420b57cec5SDimitry Andric     case ARM::t2STMDB_UPD:
11430b57cec5SDimitry Andric     case ARM::VSTMDDB_UPD:
11440b57cec5SDimitry Andric       assert(SrcReg == ARM::SP &&
11450b57cec5SDimitry Andric              "Only stack pointer as a source reg is supported");
11460b57cec5SDimitry Andric       for (unsigned i = StartOp, NumOps = MI->getNumOperands() - NumOffset;
11470b57cec5SDimitry Andric            i != NumOps; ++i) {
11480b57cec5SDimitry Andric         const MachineOperand &MO = MI->getOperand(i);
11490b57cec5SDimitry Andric         // Actually, there should never be any impdef stuff here. Skip it
11500b57cec5SDimitry Andric         // temporary to workaround PR11902.
11510b57cec5SDimitry Andric         if (MO.isImplicit())
11520b57cec5SDimitry Andric           continue;
11530b57cec5SDimitry Andric         // Registers, pushed as a part of folding an SP update into the
11540b57cec5SDimitry Andric         // push instruction are marked as undef and should not be
11550b57cec5SDimitry Andric         // restored when unwinding, because the function can modify the
11560b57cec5SDimitry Andric         // corresponding stack slots.
11570b57cec5SDimitry Andric         if (MO.isUndef()) {
11580b57cec5SDimitry Andric           assert(RegList.empty() &&
11590b57cec5SDimitry Andric                  "Pad registers must come before restored ones");
11600b57cec5SDimitry Andric           unsigned Width =
11610b57cec5SDimitry Andric             TargetRegInfo->getRegSizeInBits(MO.getReg(), MachineRegInfo) / 8;
11620b57cec5SDimitry Andric           Pad += Width;
11630b57cec5SDimitry Andric           continue;
11640b57cec5SDimitry Andric         }
11650b57cec5SDimitry Andric         // Check for registers that are remapped (for a Thumb1 prologue that
11660b57cec5SDimitry Andric         // saves high registers).
11678bcb0991SDimitry Andric         Register Reg = MO.getReg();
11680b57cec5SDimitry Andric         if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(Reg))
11690b57cec5SDimitry Andric           Reg = RemappedReg;
11700b57cec5SDimitry Andric         RegList.push_back(Reg);
11710b57cec5SDimitry Andric       }
11720b57cec5SDimitry Andric       break;
11730b57cec5SDimitry Andric     case ARM::STR_PRE_IMM:
11740b57cec5SDimitry Andric     case ARM::STR_PRE_REG:
11750b57cec5SDimitry Andric     case ARM::t2STR_PRE:
11760b57cec5SDimitry Andric       assert(MI->getOperand(2).getReg() == ARM::SP &&
11770b57cec5SDimitry Andric              "Only stack pointer as a source reg is supported");
11780b57cec5SDimitry Andric       RegList.push_back(SrcReg);
11790b57cec5SDimitry Andric       break;
11800b57cec5SDimitry Andric     }
11810b57cec5SDimitry Andric     if (MAI->getExceptionHandlingType() == ExceptionHandling::ARM) {
11820b57cec5SDimitry Andric       ATS.emitRegSave(RegList, Opc == ARM::VSTMDDB_UPD);
11830b57cec5SDimitry Andric       // Account for the SP adjustment, folded into the push.
11840b57cec5SDimitry Andric       if (Pad)
11850b57cec5SDimitry Andric         ATS.emitPad(Pad);
11860b57cec5SDimitry Andric     }
11870b57cec5SDimitry Andric   } else {
11880b57cec5SDimitry Andric     // Changes of stack / frame pointer.
11890b57cec5SDimitry Andric     if (SrcReg == ARM::SP) {
11900b57cec5SDimitry Andric       int64_t Offset = 0;
11910b57cec5SDimitry Andric       switch (Opc) {
11920b57cec5SDimitry Andric       default:
11930b57cec5SDimitry Andric         MI->print(errs());
11940b57cec5SDimitry Andric         llvm_unreachable("Unsupported opcode for unwinding information");
11950b57cec5SDimitry Andric       case ARM::MOVr:
11960b57cec5SDimitry Andric       case ARM::tMOVr:
11970b57cec5SDimitry Andric         Offset = 0;
11980b57cec5SDimitry Andric         break;
11990b57cec5SDimitry Andric       case ARM::ADDri:
12000b57cec5SDimitry Andric       case ARM::t2ADDri:
1201480093f4SDimitry Andric       case ARM::t2ADDri12:
1202480093f4SDimitry Andric       case ARM::t2ADDspImm:
1203480093f4SDimitry Andric       case ARM::t2ADDspImm12:
12040b57cec5SDimitry Andric         Offset = -MI->getOperand(2).getImm();
12050b57cec5SDimitry Andric         break;
12060b57cec5SDimitry Andric       case ARM::SUBri:
12070b57cec5SDimitry Andric       case ARM::t2SUBri:
1208480093f4SDimitry Andric       case ARM::t2SUBri12:
1209480093f4SDimitry Andric       case ARM::t2SUBspImm:
1210480093f4SDimitry Andric       case ARM::t2SUBspImm12:
12110b57cec5SDimitry Andric         Offset = MI->getOperand(2).getImm();
12120b57cec5SDimitry Andric         break;
12130b57cec5SDimitry Andric       case ARM::tSUBspi:
12140b57cec5SDimitry Andric         Offset = MI->getOperand(2).getImm()*4;
12150b57cec5SDimitry Andric         break;
12160b57cec5SDimitry Andric       case ARM::tADDspi:
12170b57cec5SDimitry Andric       case ARM::tADDrSPi:
12180b57cec5SDimitry Andric         Offset = -MI->getOperand(2).getImm()*4;
12190b57cec5SDimitry Andric         break;
12205ffd83dbSDimitry Andric       case ARM::tADDhirr:
12215ffd83dbSDimitry Andric         Offset =
12225ffd83dbSDimitry Andric             -AFI->EHPrologueOffsetInRegs.lookup(MI->getOperand(2).getReg());
12230b57cec5SDimitry Andric         break;
12240b57cec5SDimitry Andric       }
12250b57cec5SDimitry Andric 
12260b57cec5SDimitry Andric       if (MAI->getExceptionHandlingType() == ExceptionHandling::ARM) {
12270b57cec5SDimitry Andric         if (DstReg == FramePtr && FramePtr != ARM::SP)
12280b57cec5SDimitry Andric           // Set-up of the frame pointer. Positive values correspond to "add"
12290b57cec5SDimitry Andric           // instruction.
12300b57cec5SDimitry Andric           ATS.emitSetFP(FramePtr, ARM::SP, -Offset);
12310b57cec5SDimitry Andric         else if (DstReg == ARM::SP) {
12320b57cec5SDimitry Andric           // Change of SP by an offset. Positive values correspond to "sub"
12330b57cec5SDimitry Andric           // instruction.
12340b57cec5SDimitry Andric           ATS.emitPad(Offset);
12350b57cec5SDimitry Andric         } else {
12360b57cec5SDimitry Andric           // Move of SP to a register.  Positive values correspond to an "add"
12370b57cec5SDimitry Andric           // instruction.
12380b57cec5SDimitry Andric           ATS.emitMovSP(DstReg, -Offset);
12390b57cec5SDimitry Andric         }
12400b57cec5SDimitry Andric       }
12410b57cec5SDimitry Andric     } else if (DstReg == ARM::SP) {
12420b57cec5SDimitry Andric       MI->print(errs());
12430b57cec5SDimitry Andric       llvm_unreachable("Unsupported opcode for unwinding information");
12445ffd83dbSDimitry Andric     } else {
12455ffd83dbSDimitry Andric       int64_t Offset = 0;
12465ffd83dbSDimitry Andric       switch (Opc) {
12475ffd83dbSDimitry Andric       case ARM::tMOVr:
12480b57cec5SDimitry Andric         // If a Thumb1 function spills r8-r11, we copy the values to low
12490b57cec5SDimitry Andric         // registers before pushing them. Record the copy so we can emit the
12500b57cec5SDimitry Andric         // correct ".save" later.
12510b57cec5SDimitry Andric         AFI->EHPrologueRemappedRegs[DstReg] = SrcReg;
12525ffd83dbSDimitry Andric         break;
12535ffd83dbSDimitry Andric       case ARM::tLDRpci: {
12545ffd83dbSDimitry Andric         // Grab the constpool index and check, whether it corresponds to
12555ffd83dbSDimitry Andric         // original or cloned constpool entry.
12565ffd83dbSDimitry Andric         unsigned CPI = MI->getOperand(1).getIndex();
12575ffd83dbSDimitry Andric         const MachineConstantPool *MCP = MF.getConstantPool();
12585ffd83dbSDimitry Andric         if (CPI >= MCP->getConstants().size())
12595ffd83dbSDimitry Andric           CPI = AFI->getOriginalCPIdx(CPI);
12605ffd83dbSDimitry Andric         assert(CPI != -1U && "Invalid constpool index");
12615ffd83dbSDimitry Andric 
12625ffd83dbSDimitry Andric         // Derive the actual offset.
12635ffd83dbSDimitry Andric         const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI];
12645ffd83dbSDimitry Andric         assert(!CPE.isMachineConstantPoolEntry() && "Invalid constpool entry");
12655ffd83dbSDimitry Andric         Offset = cast<ConstantInt>(CPE.Val.ConstVal)->getSExtValue();
12665ffd83dbSDimitry Andric         AFI->EHPrologueOffsetInRegs[DstReg] = Offset;
12675ffd83dbSDimitry Andric         break;
12685ffd83dbSDimitry Andric       }
12695ffd83dbSDimitry Andric       case ARM::t2MOVi16:
12705ffd83dbSDimitry Andric         Offset = MI->getOperand(1).getImm();
12715ffd83dbSDimitry Andric         AFI->EHPrologueOffsetInRegs[DstReg] = Offset;
12725ffd83dbSDimitry Andric         break;
12735ffd83dbSDimitry Andric       case ARM::t2MOVTi16:
12745ffd83dbSDimitry Andric         Offset = MI->getOperand(2).getImm();
12755ffd83dbSDimitry Andric         AFI->EHPrologueOffsetInRegs[DstReg] |= (Offset << 16);
12765ffd83dbSDimitry Andric         break;
12775ffd83dbSDimitry Andric       default:
12780b57cec5SDimitry Andric         MI->print(errs());
12790b57cec5SDimitry Andric         llvm_unreachable("Unsupported opcode for unwinding information");
12800b57cec5SDimitry Andric       }
12810b57cec5SDimitry Andric     }
12820b57cec5SDimitry Andric   }
12835ffd83dbSDimitry Andric }
12840b57cec5SDimitry Andric 
12850b57cec5SDimitry Andric // Simple pseudo-instructions have their lowering (with expansion to real
12860b57cec5SDimitry Andric // instructions) auto-generated.
12870b57cec5SDimitry Andric #include "ARMGenMCPseudoLowering.inc"
12880b57cec5SDimitry Andric 
12895ffd83dbSDimitry Andric void ARMAsmPrinter::emitInstruction(const MachineInstr *MI) {
12900b57cec5SDimitry Andric   const DataLayout &DL = getDataLayout();
12910b57cec5SDimitry Andric   MCTargetStreamer &TS = *OutStreamer->getTargetStreamer();
12920b57cec5SDimitry Andric   ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
12930b57cec5SDimitry Andric 
12940b57cec5SDimitry Andric   // If we just ended a constant pool, mark it as such.
12950b57cec5SDimitry Andric   if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) {
12965ffd83dbSDimitry Andric     OutStreamer->emitDataRegion(MCDR_DataRegionEnd);
12970b57cec5SDimitry Andric     InConstantPool = false;
12980b57cec5SDimitry Andric   }
12990b57cec5SDimitry Andric 
13000b57cec5SDimitry Andric   // Emit unwinding stuff for frame-related instructions
13010b57cec5SDimitry Andric   if (Subtarget->isTargetEHABICompatible() &&
13020b57cec5SDimitry Andric        MI->getFlag(MachineInstr::FrameSetup))
13030b57cec5SDimitry Andric     EmitUnwindingInstruction(MI);
13040b57cec5SDimitry Andric 
13050b57cec5SDimitry Andric   // Do any auto-generated pseudo lowerings.
13060b57cec5SDimitry Andric   if (emitPseudoExpansionLowering(*OutStreamer, MI))
13070b57cec5SDimitry Andric     return;
13080b57cec5SDimitry Andric 
13090b57cec5SDimitry Andric   assert(!convertAddSubFlagsOpcode(MI->getOpcode()) &&
13100b57cec5SDimitry Andric          "Pseudo flag setting opcode should be expanded early");
13110b57cec5SDimitry Andric 
13120b57cec5SDimitry Andric   // Check for manual lowerings.
13130b57cec5SDimitry Andric   unsigned Opc = MI->getOpcode();
13140b57cec5SDimitry Andric   switch (Opc) {
13150b57cec5SDimitry Andric   case ARM::t2MOVi32imm: llvm_unreachable("Should be lowered by thumb2it pass");
13160b57cec5SDimitry Andric   case ARM::DBG_VALUE: llvm_unreachable("Should be handled by generic printing");
13170b57cec5SDimitry Andric   case ARM::LEApcrel:
13180b57cec5SDimitry Andric   case ARM::tLEApcrel:
13190b57cec5SDimitry Andric   case ARM::t2LEApcrel: {
13200b57cec5SDimitry Andric     // FIXME: Need to also handle globals and externals
13210b57cec5SDimitry Andric     MCSymbol *CPISymbol = GetCPISymbol(MI->getOperand(1).getIndex());
13220b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(MI->getOpcode() ==
13230b57cec5SDimitry Andric                                                ARM::t2LEApcrel ? ARM::t2ADR
13240b57cec5SDimitry Andric                   : (MI->getOpcode() == ARM::tLEApcrel ? ARM::tADR
13250b57cec5SDimitry Andric                      : ARM::ADR))
13260b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
13270b57cec5SDimitry Andric       .addExpr(MCSymbolRefExpr::create(CPISymbol, OutContext))
13280b57cec5SDimitry Andric       // Add predicate operands.
13290b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
13300b57cec5SDimitry Andric       .addReg(MI->getOperand(3).getReg()));
13310b57cec5SDimitry Andric     return;
13320b57cec5SDimitry Andric   }
13330b57cec5SDimitry Andric   case ARM::LEApcrelJT:
13340b57cec5SDimitry Andric   case ARM::tLEApcrelJT:
13350b57cec5SDimitry Andric   case ARM::t2LEApcrelJT: {
13360b57cec5SDimitry Andric     MCSymbol *JTIPICSymbol =
13370b57cec5SDimitry Andric       GetARMJTIPICJumpTableLabel(MI->getOperand(1).getIndex());
13380b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(MI->getOpcode() ==
13390b57cec5SDimitry Andric                                                ARM::t2LEApcrelJT ? ARM::t2ADR
13400b57cec5SDimitry Andric                   : (MI->getOpcode() == ARM::tLEApcrelJT ? ARM::tADR
13410b57cec5SDimitry Andric                      : ARM::ADR))
13420b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
13430b57cec5SDimitry Andric       .addExpr(MCSymbolRefExpr::create(JTIPICSymbol, OutContext))
13440b57cec5SDimitry Andric       // Add predicate operands.
13450b57cec5SDimitry Andric       .addImm(MI->getOperand(2).getImm())
13460b57cec5SDimitry Andric       .addReg(MI->getOperand(3).getReg()));
13470b57cec5SDimitry Andric     return;
13480b57cec5SDimitry Andric   }
13490b57cec5SDimitry Andric   // Darwin call instructions are just normal call instructions with different
13500b57cec5SDimitry Andric   // clobber semantics (they clobber R9).
13510b57cec5SDimitry Andric   case ARM::BX_CALL: {
13520b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVr)
13530b57cec5SDimitry Andric       .addReg(ARM::LR)
13540b57cec5SDimitry Andric       .addReg(ARM::PC)
13550b57cec5SDimitry Andric       // Add predicate operands.
13560b57cec5SDimitry Andric       .addImm(ARMCC::AL)
13570b57cec5SDimitry Andric       .addReg(0)
13580b57cec5SDimitry Andric       // Add 's' bit operand (always reg0 for this)
13590b57cec5SDimitry Andric       .addReg(0));
13600b57cec5SDimitry Andric 
13610b57cec5SDimitry Andric     assert(Subtarget->hasV4TOps());
13620b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::BX)
13630b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg()));
13640b57cec5SDimitry Andric     return;
13650b57cec5SDimitry Andric   }
13660b57cec5SDimitry Andric   case ARM::tBX_CALL: {
13670b57cec5SDimitry Andric     if (Subtarget->hasV5TOps())
13680b57cec5SDimitry Andric       llvm_unreachable("Expected BLX to be selected for v5t+");
13690b57cec5SDimitry Andric 
13700b57cec5SDimitry Andric     // On ARM v4t, when doing a call from thumb mode, we need to ensure
13710b57cec5SDimitry Andric     // that the saved lr has its LSB set correctly (the arch doesn't
13720b57cec5SDimitry Andric     // have blx).
13730b57cec5SDimitry Andric     // So here we generate a bl to a small jump pad that does bx rN.
13740b57cec5SDimitry Andric     // The jump pads are emitted after the function body.
13750b57cec5SDimitry Andric 
13768bcb0991SDimitry Andric     Register TReg = MI->getOperand(0).getReg();
13770b57cec5SDimitry Andric     MCSymbol *TRegSym = nullptr;
13780b57cec5SDimitry Andric     for (std::pair<unsigned, MCSymbol *> &TIP : ThumbIndirectPads) {
13790b57cec5SDimitry Andric       if (TIP.first == TReg) {
13800b57cec5SDimitry Andric         TRegSym = TIP.second;
13810b57cec5SDimitry Andric         break;
13820b57cec5SDimitry Andric       }
13830b57cec5SDimitry Andric     }
13840b57cec5SDimitry Andric 
13850b57cec5SDimitry Andric     if (!TRegSym) {
13860b57cec5SDimitry Andric       TRegSym = OutContext.createTempSymbol();
13870b57cec5SDimitry Andric       ThumbIndirectPads.push_back(std::make_pair(TReg, TRegSym));
13880b57cec5SDimitry Andric     }
13890b57cec5SDimitry Andric 
13900b57cec5SDimitry Andric     // Create a link-saving branch to the Reg Indirect Jump Pad.
13910b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBL)
13920b57cec5SDimitry Andric         // Predicate comes first here.
13930b57cec5SDimitry Andric         .addImm(ARMCC::AL).addReg(0)
13940b57cec5SDimitry Andric         .addExpr(MCSymbolRefExpr::create(TRegSym, OutContext)));
13950b57cec5SDimitry Andric     return;
13960b57cec5SDimitry Andric   }
13970b57cec5SDimitry Andric   case ARM::BMOVPCRX_CALL: {
13980b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVr)
13990b57cec5SDimitry Andric       .addReg(ARM::LR)
14000b57cec5SDimitry Andric       .addReg(ARM::PC)
14010b57cec5SDimitry Andric       // Add predicate operands.
14020b57cec5SDimitry Andric       .addImm(ARMCC::AL)
14030b57cec5SDimitry Andric       .addReg(0)
14040b57cec5SDimitry Andric       // Add 's' bit operand (always reg0 for this)
14050b57cec5SDimitry Andric       .addReg(0));
14060b57cec5SDimitry Andric 
14070b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVr)
14080b57cec5SDimitry Andric       .addReg(ARM::PC)
14090b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
14100b57cec5SDimitry Andric       // Add predicate operands.
14110b57cec5SDimitry Andric       .addImm(ARMCC::AL)
14120b57cec5SDimitry Andric       .addReg(0)
14130b57cec5SDimitry Andric       // Add 's' bit operand (always reg0 for this)
14140b57cec5SDimitry Andric       .addReg(0));
14150b57cec5SDimitry Andric     return;
14160b57cec5SDimitry Andric   }
14170b57cec5SDimitry Andric   case ARM::BMOVPCB_CALL: {
14180b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVr)
14190b57cec5SDimitry Andric       .addReg(ARM::LR)
14200b57cec5SDimitry Andric       .addReg(ARM::PC)
14210b57cec5SDimitry Andric       // Add predicate operands.
14220b57cec5SDimitry Andric       .addImm(ARMCC::AL)
14230b57cec5SDimitry Andric       .addReg(0)
14240b57cec5SDimitry Andric       // Add 's' bit operand (always reg0 for this)
14250b57cec5SDimitry Andric       .addReg(0));
14260b57cec5SDimitry Andric 
14270b57cec5SDimitry Andric     const MachineOperand &Op = MI->getOperand(0);
14280b57cec5SDimitry Andric     const GlobalValue *GV = Op.getGlobal();
14290b57cec5SDimitry Andric     const unsigned TF = Op.getTargetFlags();
14300b57cec5SDimitry Andric     MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
14310b57cec5SDimitry Andric     const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext);
14320b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::Bcc)
14330b57cec5SDimitry Andric       .addExpr(GVSymExpr)
14340b57cec5SDimitry Andric       // Add predicate operands.
14350b57cec5SDimitry Andric       .addImm(ARMCC::AL)
14360b57cec5SDimitry Andric       .addReg(0));
14370b57cec5SDimitry Andric     return;
14380b57cec5SDimitry Andric   }
14390b57cec5SDimitry Andric   case ARM::MOVi16_ga_pcrel:
14400b57cec5SDimitry Andric   case ARM::t2MOVi16_ga_pcrel: {
14410b57cec5SDimitry Andric     MCInst TmpInst;
14420b57cec5SDimitry Andric     TmpInst.setOpcode(Opc == ARM::MOVi16_ga_pcrel? ARM::MOVi16 : ARM::t2MOVi16);
14430b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
14440b57cec5SDimitry Andric 
14450b57cec5SDimitry Andric     unsigned TF = MI->getOperand(1).getTargetFlags();
14460b57cec5SDimitry Andric     const GlobalValue *GV = MI->getOperand(1).getGlobal();
14470b57cec5SDimitry Andric     MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
14480b57cec5SDimitry Andric     const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext);
14490b57cec5SDimitry Andric 
14500b57cec5SDimitry Andric     MCSymbol *LabelSym =
14510b57cec5SDimitry Andric         getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
14520b57cec5SDimitry Andric                     MI->getOperand(2).getImm(), OutContext);
14530b57cec5SDimitry Andric     const MCExpr *LabelSymExpr= MCSymbolRefExpr::create(LabelSym, OutContext);
14540b57cec5SDimitry Andric     unsigned PCAdj = (Opc == ARM::MOVi16_ga_pcrel) ? 8 : 4;
14550b57cec5SDimitry Andric     const MCExpr *PCRelExpr =
14560b57cec5SDimitry Andric       ARMMCExpr::createLower16(MCBinaryExpr::createSub(GVSymExpr,
14570b57cec5SDimitry Andric                                       MCBinaryExpr::createAdd(LabelSymExpr,
14580b57cec5SDimitry Andric                                       MCConstantExpr::create(PCAdj, OutContext),
14590b57cec5SDimitry Andric                                       OutContext), OutContext), OutContext);
14600b57cec5SDimitry Andric       TmpInst.addOperand(MCOperand::createExpr(PCRelExpr));
14610b57cec5SDimitry Andric 
14620b57cec5SDimitry Andric     // Add predicate operands.
14630b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(ARMCC::AL));
14640b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createReg(0));
14650b57cec5SDimitry Andric     // Add 's' bit operand (always reg0 for this)
14660b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createReg(0));
14670b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, TmpInst);
14680b57cec5SDimitry Andric     return;
14690b57cec5SDimitry Andric   }
14700b57cec5SDimitry Andric   case ARM::MOVTi16_ga_pcrel:
14710b57cec5SDimitry Andric   case ARM::t2MOVTi16_ga_pcrel: {
14720b57cec5SDimitry Andric     MCInst TmpInst;
14730b57cec5SDimitry Andric     TmpInst.setOpcode(Opc == ARM::MOVTi16_ga_pcrel
14740b57cec5SDimitry Andric                       ? ARM::MOVTi16 : ARM::t2MOVTi16);
14750b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
14760b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createReg(MI->getOperand(1).getReg()));
14770b57cec5SDimitry Andric 
14780b57cec5SDimitry Andric     unsigned TF = MI->getOperand(2).getTargetFlags();
14790b57cec5SDimitry Andric     const GlobalValue *GV = MI->getOperand(2).getGlobal();
14800b57cec5SDimitry Andric     MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
14810b57cec5SDimitry Andric     const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext);
14820b57cec5SDimitry Andric 
14830b57cec5SDimitry Andric     MCSymbol *LabelSym =
14840b57cec5SDimitry Andric         getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
14850b57cec5SDimitry Andric                     MI->getOperand(3).getImm(), OutContext);
14860b57cec5SDimitry Andric     const MCExpr *LabelSymExpr= MCSymbolRefExpr::create(LabelSym, OutContext);
14870b57cec5SDimitry Andric     unsigned PCAdj = (Opc == ARM::MOVTi16_ga_pcrel) ? 8 : 4;
14880b57cec5SDimitry Andric     const MCExpr *PCRelExpr =
14890b57cec5SDimitry Andric         ARMMCExpr::createUpper16(MCBinaryExpr::createSub(GVSymExpr,
14900b57cec5SDimitry Andric                                    MCBinaryExpr::createAdd(LabelSymExpr,
14910b57cec5SDimitry Andric                                       MCConstantExpr::create(PCAdj, OutContext),
14920b57cec5SDimitry Andric                                           OutContext), OutContext), OutContext);
14930b57cec5SDimitry Andric       TmpInst.addOperand(MCOperand::createExpr(PCRelExpr));
14940b57cec5SDimitry Andric     // Add predicate operands.
14950b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(ARMCC::AL));
14960b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createReg(0));
14970b57cec5SDimitry Andric     // Add 's' bit operand (always reg0 for this)
14980b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createReg(0));
14990b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, TmpInst);
15000b57cec5SDimitry Andric     return;
15010b57cec5SDimitry Andric   }
15020b57cec5SDimitry Andric   case ARM::t2BFi:
15030b57cec5SDimitry Andric   case ARM::t2BFic:
15040b57cec5SDimitry Andric   case ARM::t2BFLi:
15050b57cec5SDimitry Andric   case ARM::t2BFr:
15060b57cec5SDimitry Andric   case ARM::t2BFLr: {
15070b57cec5SDimitry Andric     // This is a Branch Future instruction.
15080b57cec5SDimitry Andric 
15090b57cec5SDimitry Andric     const MCExpr *BranchLabel = MCSymbolRefExpr::create(
15100b57cec5SDimitry Andric         getBFLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
15110b57cec5SDimitry Andric                    MI->getOperand(0).getIndex(), OutContext),
15120b57cec5SDimitry Andric         OutContext);
15130b57cec5SDimitry Andric 
15140b57cec5SDimitry Andric     auto MCInst = MCInstBuilder(Opc).addExpr(BranchLabel);
15150b57cec5SDimitry Andric     if (MI->getOperand(1).isReg()) {
15160b57cec5SDimitry Andric       // For BFr/BFLr
15170b57cec5SDimitry Andric       MCInst.addReg(MI->getOperand(1).getReg());
15180b57cec5SDimitry Andric     } else {
15190b57cec5SDimitry Andric       // For BFi/BFLi/BFic
15200b57cec5SDimitry Andric       const MCExpr *BranchTarget;
15210b57cec5SDimitry Andric       if (MI->getOperand(1).isMBB())
15220b57cec5SDimitry Andric         BranchTarget = MCSymbolRefExpr::create(
15230b57cec5SDimitry Andric             MI->getOperand(1).getMBB()->getSymbol(), OutContext);
15240b57cec5SDimitry Andric       else if (MI->getOperand(1).isGlobal()) {
15250b57cec5SDimitry Andric         const GlobalValue *GV = MI->getOperand(1).getGlobal();
15260b57cec5SDimitry Andric         BranchTarget = MCSymbolRefExpr::create(
15270b57cec5SDimitry Andric             GetARMGVSymbol(GV, MI->getOperand(1).getTargetFlags()), OutContext);
15280b57cec5SDimitry Andric       } else if (MI->getOperand(1).isSymbol()) {
15290b57cec5SDimitry Andric         BranchTarget = MCSymbolRefExpr::create(
15300b57cec5SDimitry Andric             GetExternalSymbolSymbol(MI->getOperand(1).getSymbolName()),
15310b57cec5SDimitry Andric             OutContext);
15320b57cec5SDimitry Andric       } else
15330b57cec5SDimitry Andric         llvm_unreachable("Unhandled operand kind in Branch Future instruction");
15340b57cec5SDimitry Andric 
15350b57cec5SDimitry Andric       MCInst.addExpr(BranchTarget);
15360b57cec5SDimitry Andric     }
15370b57cec5SDimitry Andric 
15380b57cec5SDimitry Andric       if (Opc == ARM::t2BFic) {
15390b57cec5SDimitry Andric         const MCExpr *ElseLabel = MCSymbolRefExpr::create(
15400b57cec5SDimitry Andric             getBFLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(),
15410b57cec5SDimitry Andric                        MI->getOperand(2).getIndex(), OutContext),
15420b57cec5SDimitry Andric             OutContext);
15430b57cec5SDimitry Andric         MCInst.addExpr(ElseLabel);
15440b57cec5SDimitry Andric         MCInst.addImm(MI->getOperand(3).getImm());
15450b57cec5SDimitry Andric       } else {
15460b57cec5SDimitry Andric         MCInst.addImm(MI->getOperand(2).getImm())
15470b57cec5SDimitry Andric             .addReg(MI->getOperand(3).getReg());
15480b57cec5SDimitry Andric       }
15490b57cec5SDimitry Andric 
15500b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInst);
15510b57cec5SDimitry Andric     return;
15520b57cec5SDimitry Andric   }
15530b57cec5SDimitry Andric   case ARM::t2BF_LabelPseudo: {
15540b57cec5SDimitry Andric     // This is a pseudo op for a label used by a branch future instruction
15550b57cec5SDimitry Andric 
15560b57cec5SDimitry Andric     // Emit the label.
15575ffd83dbSDimitry Andric     OutStreamer->emitLabel(getBFLabel(DL.getPrivateGlobalPrefix(),
15580b57cec5SDimitry Andric                                        getFunctionNumber(),
15590b57cec5SDimitry Andric                                        MI->getOperand(0).getIndex(), OutContext));
15600b57cec5SDimitry Andric     return;
15610b57cec5SDimitry Andric   }
15620b57cec5SDimitry Andric   case ARM::tPICADD: {
15630b57cec5SDimitry Andric     // This is a pseudo op for a label + instruction sequence, which looks like:
15640b57cec5SDimitry Andric     // LPC0:
15650b57cec5SDimitry Andric     //     add r0, pc
15660b57cec5SDimitry Andric     // This adds the address of LPC0 to r0.
15670b57cec5SDimitry Andric 
15680b57cec5SDimitry Andric     // Emit the label.
15695ffd83dbSDimitry Andric     OutStreamer->emitLabel(getPICLabel(DL.getPrivateGlobalPrefix(),
15700b57cec5SDimitry Andric                                        getFunctionNumber(),
15710b57cec5SDimitry Andric                                        MI->getOperand(2).getImm(), OutContext));
15720b57cec5SDimitry Andric 
15730b57cec5SDimitry Andric     // Form and emit the add.
15740b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDhirr)
15750b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
15760b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
15770b57cec5SDimitry Andric       .addReg(ARM::PC)
15780b57cec5SDimitry Andric       // Add predicate operands.
15790b57cec5SDimitry Andric       .addImm(ARMCC::AL)
15800b57cec5SDimitry Andric       .addReg(0));
15810b57cec5SDimitry Andric     return;
15820b57cec5SDimitry Andric   }
15830b57cec5SDimitry Andric   case ARM::PICADD: {
15840b57cec5SDimitry Andric     // This is a pseudo op for a label + instruction sequence, which looks like:
15850b57cec5SDimitry Andric     // LPC0:
15860b57cec5SDimitry Andric     //     add r0, pc, r0
15870b57cec5SDimitry Andric     // This adds the address of LPC0 to r0.
15880b57cec5SDimitry Andric 
15890b57cec5SDimitry Andric     // Emit the label.
15905ffd83dbSDimitry Andric     OutStreamer->emitLabel(getPICLabel(DL.getPrivateGlobalPrefix(),
15910b57cec5SDimitry Andric                                        getFunctionNumber(),
15920b57cec5SDimitry Andric                                        MI->getOperand(2).getImm(), OutContext));
15930b57cec5SDimitry Andric 
15940b57cec5SDimitry Andric     // Form and emit the add.
15950b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::ADDrr)
15960b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
15970b57cec5SDimitry Andric       .addReg(ARM::PC)
15980b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
15990b57cec5SDimitry Andric       // Add predicate operands.
16000b57cec5SDimitry Andric       .addImm(MI->getOperand(3).getImm())
16010b57cec5SDimitry Andric       .addReg(MI->getOperand(4).getReg())
16020b57cec5SDimitry Andric       // Add 's' bit operand (always reg0 for this)
16030b57cec5SDimitry Andric       .addReg(0));
16040b57cec5SDimitry Andric     return;
16050b57cec5SDimitry Andric   }
16060b57cec5SDimitry Andric   case ARM::PICSTR:
16070b57cec5SDimitry Andric   case ARM::PICSTRB:
16080b57cec5SDimitry Andric   case ARM::PICSTRH:
16090b57cec5SDimitry Andric   case ARM::PICLDR:
16100b57cec5SDimitry Andric   case ARM::PICLDRB:
16110b57cec5SDimitry Andric   case ARM::PICLDRH:
16120b57cec5SDimitry Andric   case ARM::PICLDRSB:
16130b57cec5SDimitry Andric   case ARM::PICLDRSH: {
16140b57cec5SDimitry Andric     // This is a pseudo op for a label + instruction sequence, which looks like:
16150b57cec5SDimitry Andric     // LPC0:
16160b57cec5SDimitry Andric     //     OP r0, [pc, r0]
16170b57cec5SDimitry Andric     // The LCP0 label is referenced by a constant pool entry in order to get
16180b57cec5SDimitry Andric     // a PC-relative address at the ldr instruction.
16190b57cec5SDimitry Andric 
16200b57cec5SDimitry Andric     // Emit the label.
16215ffd83dbSDimitry Andric     OutStreamer->emitLabel(getPICLabel(DL.getPrivateGlobalPrefix(),
16220b57cec5SDimitry Andric                                        getFunctionNumber(),
16230b57cec5SDimitry Andric                                        MI->getOperand(2).getImm(), OutContext));
16240b57cec5SDimitry Andric 
16250b57cec5SDimitry Andric     // Form and emit the load
16260b57cec5SDimitry Andric     unsigned Opcode;
16270b57cec5SDimitry Andric     switch (MI->getOpcode()) {
16280b57cec5SDimitry Andric     default:
16290b57cec5SDimitry Andric       llvm_unreachable("Unexpected opcode!");
16300b57cec5SDimitry Andric     case ARM::PICSTR:   Opcode = ARM::STRrs; break;
16310b57cec5SDimitry Andric     case ARM::PICSTRB:  Opcode = ARM::STRBrs; break;
16320b57cec5SDimitry Andric     case ARM::PICSTRH:  Opcode = ARM::STRH; break;
16330b57cec5SDimitry Andric     case ARM::PICLDR:   Opcode = ARM::LDRrs; break;
16340b57cec5SDimitry Andric     case ARM::PICLDRB:  Opcode = ARM::LDRBrs; break;
16350b57cec5SDimitry Andric     case ARM::PICLDRH:  Opcode = ARM::LDRH; break;
16360b57cec5SDimitry Andric     case ARM::PICLDRSB: Opcode = ARM::LDRSB; break;
16370b57cec5SDimitry Andric     case ARM::PICLDRSH: Opcode = ARM::LDRSH; break;
16380b57cec5SDimitry Andric     }
16390b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(Opcode)
16400b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
16410b57cec5SDimitry Andric       .addReg(ARM::PC)
16420b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
16430b57cec5SDimitry Andric       .addImm(0)
16440b57cec5SDimitry Andric       // Add predicate operands.
16450b57cec5SDimitry Andric       .addImm(MI->getOperand(3).getImm())
16460b57cec5SDimitry Andric       .addReg(MI->getOperand(4).getReg()));
16470b57cec5SDimitry Andric 
16480b57cec5SDimitry Andric     return;
16490b57cec5SDimitry Andric   }
16500b57cec5SDimitry Andric   case ARM::CONSTPOOL_ENTRY: {
16510b57cec5SDimitry Andric     if (Subtarget->genExecuteOnly())
16520b57cec5SDimitry Andric       llvm_unreachable("execute-only should not generate constant pools");
16530b57cec5SDimitry Andric 
16540b57cec5SDimitry Andric     /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool
16550b57cec5SDimitry Andric     /// in the function.  The first operand is the ID# for this instruction, the
16560b57cec5SDimitry Andric     /// second is the index into the MachineConstantPool that this is, the third
16570b57cec5SDimitry Andric     /// is the size in bytes of this constant pool entry.
16580b57cec5SDimitry Andric     /// The required alignment is specified on the basic block holding this MI.
16590b57cec5SDimitry Andric     unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
16600b57cec5SDimitry Andric     unsigned CPIdx   = (unsigned)MI->getOperand(1).getIndex();
16610b57cec5SDimitry Andric 
16620b57cec5SDimitry Andric     // If this is the first entry of the pool, mark it.
16630b57cec5SDimitry Andric     if (!InConstantPool) {
16645ffd83dbSDimitry Andric       OutStreamer->emitDataRegion(MCDR_DataRegion);
16650b57cec5SDimitry Andric       InConstantPool = true;
16660b57cec5SDimitry Andric     }
16670b57cec5SDimitry Andric 
16685ffd83dbSDimitry Andric     OutStreamer->emitLabel(GetCPISymbol(LabelId));
16690b57cec5SDimitry Andric 
16700b57cec5SDimitry Andric     const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
16710b57cec5SDimitry Andric     if (MCPE.isMachineConstantPoolEntry())
16725ffd83dbSDimitry Andric       emitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
16730b57cec5SDimitry Andric     else
16745ffd83dbSDimitry Andric       emitGlobalConstant(DL, MCPE.Val.ConstVal);
16750b57cec5SDimitry Andric     return;
16760b57cec5SDimitry Andric   }
16770b57cec5SDimitry Andric   case ARM::JUMPTABLE_ADDRS:
16785ffd83dbSDimitry Andric     emitJumpTableAddrs(MI);
16790b57cec5SDimitry Andric     return;
16800b57cec5SDimitry Andric   case ARM::JUMPTABLE_INSTS:
16815ffd83dbSDimitry Andric     emitJumpTableInsts(MI);
16820b57cec5SDimitry Andric     return;
16830b57cec5SDimitry Andric   case ARM::JUMPTABLE_TBB:
16840b57cec5SDimitry Andric   case ARM::JUMPTABLE_TBH:
16855ffd83dbSDimitry Andric     emitJumpTableTBInst(MI, MI->getOpcode() == ARM::JUMPTABLE_TBB ? 1 : 2);
16860b57cec5SDimitry Andric     return;
16870b57cec5SDimitry Andric   case ARM::t2BR_JT: {
16880b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr)
16890b57cec5SDimitry Andric       .addReg(ARM::PC)
16900b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
16910b57cec5SDimitry Andric       // Add predicate operands.
16920b57cec5SDimitry Andric       .addImm(ARMCC::AL)
16930b57cec5SDimitry Andric       .addReg(0));
16940b57cec5SDimitry Andric     return;
16950b57cec5SDimitry Andric   }
16960b57cec5SDimitry Andric   case ARM::t2TBB_JT:
16970b57cec5SDimitry Andric   case ARM::t2TBH_JT: {
16980b57cec5SDimitry Andric     unsigned Opc = MI->getOpcode() == ARM::t2TBB_JT ? ARM::t2TBB : ARM::t2TBH;
16990b57cec5SDimitry Andric     // Lower and emit the PC label, then the instruction itself.
17005ffd83dbSDimitry Andric     OutStreamer->emitLabel(GetCPISymbol(MI->getOperand(3).getImm()));
17010b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(Opc)
17020b57cec5SDimitry Andric                                      .addReg(MI->getOperand(0).getReg())
17030b57cec5SDimitry Andric                                      .addReg(MI->getOperand(1).getReg())
17040b57cec5SDimitry Andric                                      // Add predicate operands.
17050b57cec5SDimitry Andric                                      .addImm(ARMCC::AL)
17060b57cec5SDimitry Andric                                      .addReg(0));
17070b57cec5SDimitry Andric     return;
17080b57cec5SDimitry Andric   }
17090b57cec5SDimitry Andric   case ARM::tTBB_JT:
17100b57cec5SDimitry Andric   case ARM::tTBH_JT: {
17110b57cec5SDimitry Andric 
17120b57cec5SDimitry Andric     bool Is8Bit = MI->getOpcode() == ARM::tTBB_JT;
17138bcb0991SDimitry Andric     Register Base = MI->getOperand(0).getReg();
17148bcb0991SDimitry Andric     Register Idx = MI->getOperand(1).getReg();
17150b57cec5SDimitry Andric     assert(MI->getOperand(1).isKill() && "We need the index register as scratch!");
17160b57cec5SDimitry Andric 
17170b57cec5SDimitry Andric     // Multiply up idx if necessary.
17180b57cec5SDimitry Andric     if (!Is8Bit)
17190b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)
17200b57cec5SDimitry Andric                                        .addReg(Idx)
17210b57cec5SDimitry Andric                                        .addReg(ARM::CPSR)
17220b57cec5SDimitry Andric                                        .addReg(Idx)
17230b57cec5SDimitry Andric                                        .addImm(1)
17240b57cec5SDimitry Andric                                        // Add predicate operands.
17250b57cec5SDimitry Andric                                        .addImm(ARMCC::AL)
17260b57cec5SDimitry Andric                                        .addReg(0));
17270b57cec5SDimitry Andric 
17280b57cec5SDimitry Andric     if (Base == ARM::PC) {
17290b57cec5SDimitry Andric       // TBB [base, idx] =
17300b57cec5SDimitry Andric       //    ADDS idx, idx, base
17310b57cec5SDimitry Andric       //    LDRB idx, [idx, #4] ; or LDRH if TBH
17320b57cec5SDimitry Andric       //    LSLS idx, #1
17330b57cec5SDimitry Andric       //    ADDS pc, pc, idx
17340b57cec5SDimitry Andric 
17350b57cec5SDimitry Andric       // When using PC as the base, it's important that there is no padding
17360b57cec5SDimitry Andric       // between the last ADDS and the start of the jump table. The jump table
17370b57cec5SDimitry Andric       // is 4-byte aligned, so we ensure we're 4 byte aligned here too.
17380b57cec5SDimitry Andric       //
17390b57cec5SDimitry Andric       // FIXME: Ideally we could vary the LDRB index based on the padding
17400b57cec5SDimitry Andric       // between the sequence and jump table, however that relies on MCExprs
17410b57cec5SDimitry Andric       // for load indexes which are currently not supported.
1742*349cc55cSDimitry Andric       OutStreamer->emitCodeAlignment(4, &getSubtargetInfo());
17430b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDhirr)
17440b57cec5SDimitry Andric                                        .addReg(Idx)
17450b57cec5SDimitry Andric                                        .addReg(Idx)
17460b57cec5SDimitry Andric                                        .addReg(Base)
17470b57cec5SDimitry Andric                                        // Add predicate operands.
17480b57cec5SDimitry Andric                                        .addImm(ARMCC::AL)
17490b57cec5SDimitry Andric                                        .addReg(0));
17500b57cec5SDimitry Andric 
17510b57cec5SDimitry Andric       unsigned Opc = Is8Bit ? ARM::tLDRBi : ARM::tLDRHi;
17520b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(Opc)
17530b57cec5SDimitry Andric                                        .addReg(Idx)
17540b57cec5SDimitry Andric                                        .addReg(Idx)
17550b57cec5SDimitry Andric                                        .addImm(Is8Bit ? 4 : 2)
17560b57cec5SDimitry Andric                                        // Add predicate operands.
17570b57cec5SDimitry Andric                                        .addImm(ARMCC::AL)
17580b57cec5SDimitry Andric                                        .addReg(0));
17590b57cec5SDimitry Andric     } else {
17600b57cec5SDimitry Andric       // TBB [base, idx] =
17610b57cec5SDimitry Andric       //    LDRB idx, [base, idx] ; or LDRH if TBH
17620b57cec5SDimitry Andric       //    LSLS idx, #1
17630b57cec5SDimitry Andric       //    ADDS pc, pc, idx
17640b57cec5SDimitry Andric 
17650b57cec5SDimitry Andric       unsigned Opc = Is8Bit ? ARM::tLDRBr : ARM::tLDRHr;
17660b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(Opc)
17670b57cec5SDimitry Andric                                        .addReg(Idx)
17680b57cec5SDimitry Andric                                        .addReg(Base)
17690b57cec5SDimitry Andric                                        .addReg(Idx)
17700b57cec5SDimitry Andric                                        // Add predicate operands.
17710b57cec5SDimitry Andric                                        .addImm(ARMCC::AL)
17720b57cec5SDimitry Andric                                        .addReg(0));
17730b57cec5SDimitry Andric     }
17740b57cec5SDimitry Andric 
17750b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri)
17760b57cec5SDimitry Andric                                      .addReg(Idx)
17770b57cec5SDimitry Andric                                      .addReg(ARM::CPSR)
17780b57cec5SDimitry Andric                                      .addReg(Idx)
17790b57cec5SDimitry Andric                                      .addImm(1)
17800b57cec5SDimitry Andric                                      // Add predicate operands.
17810b57cec5SDimitry Andric                                      .addImm(ARMCC::AL)
17820b57cec5SDimitry Andric                                      .addReg(0));
17830b57cec5SDimitry Andric 
17845ffd83dbSDimitry Andric     OutStreamer->emitLabel(GetCPISymbol(MI->getOperand(3).getImm()));
17850b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDhirr)
17860b57cec5SDimitry Andric                                      .addReg(ARM::PC)
17870b57cec5SDimitry Andric                                      .addReg(ARM::PC)
17880b57cec5SDimitry Andric                                      .addReg(Idx)
17890b57cec5SDimitry Andric                                      // Add predicate operands.
17900b57cec5SDimitry Andric                                      .addImm(ARMCC::AL)
17910b57cec5SDimitry Andric                                      .addReg(0));
17920b57cec5SDimitry Andric     return;
17930b57cec5SDimitry Andric   }
17940b57cec5SDimitry Andric   case ARM::tBR_JTr:
17950b57cec5SDimitry Andric   case ARM::BR_JTr: {
17960b57cec5SDimitry Andric     // mov pc, target
17970b57cec5SDimitry Andric     MCInst TmpInst;
17980b57cec5SDimitry Andric     unsigned Opc = MI->getOpcode() == ARM::BR_JTr ?
17990b57cec5SDimitry Andric       ARM::MOVr : ARM::tMOVr;
18000b57cec5SDimitry Andric     TmpInst.setOpcode(Opc);
18010b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createReg(ARM::PC));
18020b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
18030b57cec5SDimitry Andric     // Add predicate operands.
18040b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(ARMCC::AL));
18050b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createReg(0));
18060b57cec5SDimitry Andric     // Add 's' bit operand (always reg0 for this)
18070b57cec5SDimitry Andric     if (Opc == ARM::MOVr)
18080b57cec5SDimitry Andric       TmpInst.addOperand(MCOperand::createReg(0));
18090b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, TmpInst);
18100b57cec5SDimitry Andric     return;
18110b57cec5SDimitry Andric   }
18120b57cec5SDimitry Andric   case ARM::BR_JTm_i12: {
18130b57cec5SDimitry Andric     // ldr pc, target
18140b57cec5SDimitry Andric     MCInst TmpInst;
18150b57cec5SDimitry Andric     TmpInst.setOpcode(ARM::LDRi12);
18160b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createReg(ARM::PC));
18170b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
18180b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm()));
18190b57cec5SDimitry Andric     // Add predicate operands.
18200b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(ARMCC::AL));
18210b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createReg(0));
18220b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, TmpInst);
18230b57cec5SDimitry Andric     return;
18240b57cec5SDimitry Andric   }
18250b57cec5SDimitry Andric   case ARM::BR_JTm_rs: {
18260b57cec5SDimitry Andric     // ldr pc, target
18270b57cec5SDimitry Andric     MCInst TmpInst;
18280b57cec5SDimitry Andric     TmpInst.setOpcode(ARM::LDRrs);
18290b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createReg(ARM::PC));
18300b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg()));
18310b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createReg(MI->getOperand(1).getReg()));
18320b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm()));
18330b57cec5SDimitry Andric     // Add predicate operands.
18340b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createImm(ARMCC::AL));
18350b57cec5SDimitry Andric     TmpInst.addOperand(MCOperand::createReg(0));
18360b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, TmpInst);
18370b57cec5SDimitry Andric     return;
18380b57cec5SDimitry Andric   }
18390b57cec5SDimitry Andric   case ARM::BR_JTadd: {
18400b57cec5SDimitry Andric     // add pc, target, idx
18410b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::ADDrr)
18420b57cec5SDimitry Andric       .addReg(ARM::PC)
18430b57cec5SDimitry Andric       .addReg(MI->getOperand(0).getReg())
18440b57cec5SDimitry Andric       .addReg(MI->getOperand(1).getReg())
18450b57cec5SDimitry Andric       // Add predicate operands.
18460b57cec5SDimitry Andric       .addImm(ARMCC::AL)
18470b57cec5SDimitry Andric       .addReg(0)
18480b57cec5SDimitry Andric       // Add 's' bit operand (always reg0 for this)
18490b57cec5SDimitry Andric       .addReg(0));
18500b57cec5SDimitry Andric     return;
18510b57cec5SDimitry Andric   }
18520b57cec5SDimitry Andric   case ARM::SPACE:
18535ffd83dbSDimitry Andric     OutStreamer->emitZeros(MI->getOperand(1).getImm());
18540b57cec5SDimitry Andric     return;
18550b57cec5SDimitry Andric   case ARM::TRAP: {
18560b57cec5SDimitry Andric     // Non-Darwin binutils don't yet support the "trap" mnemonic.
18570b57cec5SDimitry Andric     // FIXME: Remove this special case when they do.
18580b57cec5SDimitry Andric     if (!Subtarget->isTargetMachO()) {
18590b57cec5SDimitry Andric       uint32_t Val = 0xe7ffdefeUL;
18600b57cec5SDimitry Andric       OutStreamer->AddComment("trap");
18610b57cec5SDimitry Andric       ATS.emitInst(Val);
18620b57cec5SDimitry Andric       return;
18630b57cec5SDimitry Andric     }
18640b57cec5SDimitry Andric     break;
18650b57cec5SDimitry Andric   }
18660b57cec5SDimitry Andric   case ARM::TRAPNaCl: {
18670b57cec5SDimitry Andric     uint32_t Val = 0xe7fedef0UL;
18680b57cec5SDimitry Andric     OutStreamer->AddComment("trap");
18690b57cec5SDimitry Andric     ATS.emitInst(Val);
18700b57cec5SDimitry Andric     return;
18710b57cec5SDimitry Andric   }
18720b57cec5SDimitry Andric   case ARM::tTRAP: {
18730b57cec5SDimitry Andric     // Non-Darwin binutils don't yet support the "trap" mnemonic.
18740b57cec5SDimitry Andric     // FIXME: Remove this special case when they do.
18750b57cec5SDimitry Andric     if (!Subtarget->isTargetMachO()) {
18760b57cec5SDimitry Andric       uint16_t Val = 0xdefe;
18770b57cec5SDimitry Andric       OutStreamer->AddComment("trap");
18780b57cec5SDimitry Andric       ATS.emitInst(Val, 'n');
18790b57cec5SDimitry Andric       return;
18800b57cec5SDimitry Andric     }
18810b57cec5SDimitry Andric     break;
18820b57cec5SDimitry Andric   }
18830b57cec5SDimitry Andric   case ARM::t2Int_eh_sjlj_setjmp:
18840b57cec5SDimitry Andric   case ARM::t2Int_eh_sjlj_setjmp_nofp:
18850b57cec5SDimitry Andric   case ARM::tInt_eh_sjlj_setjmp: {
18860b57cec5SDimitry Andric     // Two incoming args: GPR:$src, GPR:$val
18870b57cec5SDimitry Andric     // mov $val, pc
18880b57cec5SDimitry Andric     // adds $val, #7
18890b57cec5SDimitry Andric     // str $val, [$src, #4]
18900b57cec5SDimitry Andric     // movs r0, #0
18910b57cec5SDimitry Andric     // b LSJLJEH
18920b57cec5SDimitry Andric     // movs r0, #1
18930b57cec5SDimitry Andric     // LSJLJEH:
18948bcb0991SDimitry Andric     Register SrcReg = MI->getOperand(0).getReg();
18958bcb0991SDimitry Andric     Register ValReg = MI->getOperand(1).getReg();
1896e8d8bef9SDimitry Andric     MCSymbol *Label = OutContext.createTempSymbol("SJLJEH");
18970b57cec5SDimitry Andric     OutStreamer->AddComment("eh_setjmp begin");
18980b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr)
18990b57cec5SDimitry Andric       .addReg(ValReg)
19000b57cec5SDimitry Andric       .addReg(ARM::PC)
19010b57cec5SDimitry Andric       // Predicate.
19020b57cec5SDimitry Andric       .addImm(ARMCC::AL)
19030b57cec5SDimitry Andric       .addReg(0));
19040b57cec5SDimitry Andric 
19050b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi3)
19060b57cec5SDimitry Andric       .addReg(ValReg)
19070b57cec5SDimitry Andric       // 's' bit operand
19080b57cec5SDimitry Andric       .addReg(ARM::CPSR)
19090b57cec5SDimitry Andric       .addReg(ValReg)
19100b57cec5SDimitry Andric       .addImm(7)
19110b57cec5SDimitry Andric       // Predicate.
19120b57cec5SDimitry Andric       .addImm(ARMCC::AL)
19130b57cec5SDimitry Andric       .addReg(0));
19140b57cec5SDimitry Andric 
19150b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tSTRi)
19160b57cec5SDimitry Andric       .addReg(ValReg)
19170b57cec5SDimitry Andric       .addReg(SrcReg)
19180b57cec5SDimitry Andric       // The offset immediate is #4. The operand value is scaled by 4 for the
19190b57cec5SDimitry Andric       // tSTR instruction.
19200b57cec5SDimitry Andric       .addImm(1)
19210b57cec5SDimitry Andric       // Predicate.
19220b57cec5SDimitry Andric       .addImm(ARMCC::AL)
19230b57cec5SDimitry Andric       .addReg(0));
19240b57cec5SDimitry Andric 
19250b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVi8)
19260b57cec5SDimitry Andric       .addReg(ARM::R0)
19270b57cec5SDimitry Andric       .addReg(ARM::CPSR)
19280b57cec5SDimitry Andric       .addImm(0)
19290b57cec5SDimitry Andric       // Predicate.
19300b57cec5SDimitry Andric       .addImm(ARMCC::AL)
19310b57cec5SDimitry Andric       .addReg(0));
19320b57cec5SDimitry Andric 
19330b57cec5SDimitry Andric     const MCExpr *SymbolExpr = MCSymbolRefExpr::create(Label, OutContext);
19340b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tB)
19350b57cec5SDimitry Andric       .addExpr(SymbolExpr)
19360b57cec5SDimitry Andric       .addImm(ARMCC::AL)
19370b57cec5SDimitry Andric       .addReg(0));
19380b57cec5SDimitry Andric 
19390b57cec5SDimitry Andric     OutStreamer->AddComment("eh_setjmp end");
19400b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVi8)
19410b57cec5SDimitry Andric       .addReg(ARM::R0)
19420b57cec5SDimitry Andric       .addReg(ARM::CPSR)
19430b57cec5SDimitry Andric       .addImm(1)
19440b57cec5SDimitry Andric       // Predicate.
19450b57cec5SDimitry Andric       .addImm(ARMCC::AL)
19460b57cec5SDimitry Andric       .addReg(0));
19470b57cec5SDimitry Andric 
19485ffd83dbSDimitry Andric     OutStreamer->emitLabel(Label);
19490b57cec5SDimitry Andric     return;
19500b57cec5SDimitry Andric   }
19510b57cec5SDimitry Andric 
19520b57cec5SDimitry Andric   case ARM::Int_eh_sjlj_setjmp_nofp:
19530b57cec5SDimitry Andric   case ARM::Int_eh_sjlj_setjmp: {
19540b57cec5SDimitry Andric     // Two incoming args: GPR:$src, GPR:$val
19550b57cec5SDimitry Andric     // add $val, pc, #8
19560b57cec5SDimitry Andric     // str $val, [$src, #+4]
19570b57cec5SDimitry Andric     // mov r0, #0
19580b57cec5SDimitry Andric     // add pc, pc, #0
19590b57cec5SDimitry Andric     // mov r0, #1
19608bcb0991SDimitry Andric     Register SrcReg = MI->getOperand(0).getReg();
19618bcb0991SDimitry Andric     Register ValReg = MI->getOperand(1).getReg();
19620b57cec5SDimitry Andric 
19630b57cec5SDimitry Andric     OutStreamer->AddComment("eh_setjmp begin");
19640b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::ADDri)
19650b57cec5SDimitry Andric       .addReg(ValReg)
19660b57cec5SDimitry Andric       .addReg(ARM::PC)
19670b57cec5SDimitry Andric       .addImm(8)
19680b57cec5SDimitry Andric       // Predicate.
19690b57cec5SDimitry Andric       .addImm(ARMCC::AL)
19700b57cec5SDimitry Andric       .addReg(0)
19710b57cec5SDimitry Andric       // 's' bit operand (always reg0 for this).
19720b57cec5SDimitry Andric       .addReg(0));
19730b57cec5SDimitry Andric 
19740b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::STRi12)
19750b57cec5SDimitry Andric       .addReg(ValReg)
19760b57cec5SDimitry Andric       .addReg(SrcReg)
19770b57cec5SDimitry Andric       .addImm(4)
19780b57cec5SDimitry Andric       // Predicate.
19790b57cec5SDimitry Andric       .addImm(ARMCC::AL)
19800b57cec5SDimitry Andric       .addReg(0));
19810b57cec5SDimitry Andric 
19820b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVi)
19830b57cec5SDimitry Andric       .addReg(ARM::R0)
19840b57cec5SDimitry Andric       .addImm(0)
19850b57cec5SDimitry Andric       // Predicate.
19860b57cec5SDimitry Andric       .addImm(ARMCC::AL)
19870b57cec5SDimitry Andric       .addReg(0)
19880b57cec5SDimitry Andric       // 's' bit operand (always reg0 for this).
19890b57cec5SDimitry Andric       .addReg(0));
19900b57cec5SDimitry Andric 
19910b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::ADDri)
19920b57cec5SDimitry Andric       .addReg(ARM::PC)
19930b57cec5SDimitry Andric       .addReg(ARM::PC)
19940b57cec5SDimitry Andric       .addImm(0)
19950b57cec5SDimitry Andric       // Predicate.
19960b57cec5SDimitry Andric       .addImm(ARMCC::AL)
19970b57cec5SDimitry Andric       .addReg(0)
19980b57cec5SDimitry Andric       // 's' bit operand (always reg0 for this).
19990b57cec5SDimitry Andric       .addReg(0));
20000b57cec5SDimitry Andric 
20010b57cec5SDimitry Andric     OutStreamer->AddComment("eh_setjmp end");
20020b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVi)
20030b57cec5SDimitry Andric       .addReg(ARM::R0)
20040b57cec5SDimitry Andric       .addImm(1)
20050b57cec5SDimitry Andric       // Predicate.
20060b57cec5SDimitry Andric       .addImm(ARMCC::AL)
20070b57cec5SDimitry Andric       .addReg(0)
20080b57cec5SDimitry Andric       // 's' bit operand (always reg0 for this).
20090b57cec5SDimitry Andric       .addReg(0));
20100b57cec5SDimitry Andric     return;
20110b57cec5SDimitry Andric   }
20120b57cec5SDimitry Andric   case ARM::Int_eh_sjlj_longjmp: {
20130b57cec5SDimitry Andric     // ldr sp, [$src, #8]
20140b57cec5SDimitry Andric     // ldr $scratch, [$src, #4]
20150b57cec5SDimitry Andric     // ldr r7, [$src]
20160b57cec5SDimitry Andric     // bx $scratch
20178bcb0991SDimitry Andric     Register SrcReg = MI->getOperand(0).getReg();
20188bcb0991SDimitry Andric     Register ScratchReg = MI->getOperand(1).getReg();
20190b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12)
20200b57cec5SDimitry Andric       .addReg(ARM::SP)
20210b57cec5SDimitry Andric       .addReg(SrcReg)
20220b57cec5SDimitry Andric       .addImm(8)
20230b57cec5SDimitry Andric       // Predicate.
20240b57cec5SDimitry Andric       .addImm(ARMCC::AL)
20250b57cec5SDimitry Andric       .addReg(0));
20260b57cec5SDimitry Andric 
20270b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12)
20280b57cec5SDimitry Andric       .addReg(ScratchReg)
20290b57cec5SDimitry Andric       .addReg(SrcReg)
20300b57cec5SDimitry Andric       .addImm(4)
20310b57cec5SDimitry Andric       // Predicate.
20320b57cec5SDimitry Andric       .addImm(ARMCC::AL)
20330b57cec5SDimitry Andric       .addReg(0));
20340b57cec5SDimitry Andric 
2035*349cc55cSDimitry Andric     const MachineFunction &MF = *MI->getParent()->getParent();
2036*349cc55cSDimitry Andric     const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>();
2037*349cc55cSDimitry Andric 
20380b57cec5SDimitry Andric     if (STI.isTargetDarwin() || STI.isTargetWindows()) {
20390b57cec5SDimitry Andric       // These platforms always use the same frame register
20400b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12)
2041fe6060f1SDimitry Andric                                        .addReg(STI.getFramePointerReg())
20420b57cec5SDimitry Andric                                        .addReg(SrcReg)
20430b57cec5SDimitry Andric                                        .addImm(0)
20440b57cec5SDimitry Andric                                        // Predicate.
20450b57cec5SDimitry Andric                                        .addImm(ARMCC::AL)
20460b57cec5SDimitry Andric                                        .addReg(0));
20470b57cec5SDimitry Andric     } else {
20480b57cec5SDimitry Andric       // If the calling code might use either R7 or R11 as
20490b57cec5SDimitry Andric       // frame pointer register, restore it into both.
20500b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12)
20510b57cec5SDimitry Andric         .addReg(ARM::R7)
20520b57cec5SDimitry Andric         .addReg(SrcReg)
20530b57cec5SDimitry Andric         .addImm(0)
20540b57cec5SDimitry Andric         // Predicate.
20550b57cec5SDimitry Andric         .addImm(ARMCC::AL)
20560b57cec5SDimitry Andric         .addReg(0));
20570b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12)
20580b57cec5SDimitry Andric         .addReg(ARM::R11)
20590b57cec5SDimitry Andric         .addReg(SrcReg)
20600b57cec5SDimitry Andric         .addImm(0)
20610b57cec5SDimitry Andric         // Predicate.
20620b57cec5SDimitry Andric         .addImm(ARMCC::AL)
20630b57cec5SDimitry Andric         .addReg(0));
20640b57cec5SDimitry Andric     }
20650b57cec5SDimitry Andric 
20660b57cec5SDimitry Andric     assert(Subtarget->hasV4TOps());
20670b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::BX)
20680b57cec5SDimitry Andric       .addReg(ScratchReg)
20690b57cec5SDimitry Andric       // Predicate.
20700b57cec5SDimitry Andric       .addImm(ARMCC::AL)
20710b57cec5SDimitry Andric       .addReg(0));
20720b57cec5SDimitry Andric     return;
20730b57cec5SDimitry Andric   }
20740b57cec5SDimitry Andric   case ARM::tInt_eh_sjlj_longjmp: {
20750b57cec5SDimitry Andric     // ldr $scratch, [$src, #8]
20760b57cec5SDimitry Andric     // mov sp, $scratch
20770b57cec5SDimitry Andric     // ldr $scratch, [$src, #4]
20780b57cec5SDimitry Andric     // ldr r7, [$src]
20790b57cec5SDimitry Andric     // bx $scratch
20808bcb0991SDimitry Andric     Register SrcReg = MI->getOperand(0).getReg();
20818bcb0991SDimitry Andric     Register ScratchReg = MI->getOperand(1).getReg();
20820b57cec5SDimitry Andric 
2083*349cc55cSDimitry Andric     const MachineFunction &MF = *MI->getParent()->getParent();
2084*349cc55cSDimitry Andric     const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>();
2085*349cc55cSDimitry Andric 
20860b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi)
20870b57cec5SDimitry Andric       .addReg(ScratchReg)
20880b57cec5SDimitry Andric       .addReg(SrcReg)
20890b57cec5SDimitry Andric       // The offset immediate is #8. The operand value is scaled by 4 for the
20900b57cec5SDimitry Andric       // tLDR instruction.
20910b57cec5SDimitry Andric       .addImm(2)
20920b57cec5SDimitry Andric       // Predicate.
20930b57cec5SDimitry Andric       .addImm(ARMCC::AL)
20940b57cec5SDimitry Andric       .addReg(0));
20950b57cec5SDimitry Andric 
20960b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr)
20970b57cec5SDimitry Andric       .addReg(ARM::SP)
20980b57cec5SDimitry Andric       .addReg(ScratchReg)
20990b57cec5SDimitry Andric       // Predicate.
21000b57cec5SDimitry Andric       .addImm(ARMCC::AL)
21010b57cec5SDimitry Andric       .addReg(0));
21020b57cec5SDimitry Andric 
21030b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi)
21040b57cec5SDimitry Andric       .addReg(ScratchReg)
21050b57cec5SDimitry Andric       .addReg(SrcReg)
21060b57cec5SDimitry Andric       .addImm(1)
21070b57cec5SDimitry Andric       // Predicate.
21080b57cec5SDimitry Andric       .addImm(ARMCC::AL)
21090b57cec5SDimitry Andric       .addReg(0));
21100b57cec5SDimitry Andric 
21110b57cec5SDimitry Andric     if (STI.isTargetDarwin() || STI.isTargetWindows()) {
21120b57cec5SDimitry Andric       // These platforms always use the same frame register
21130b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi)
2114fe6060f1SDimitry Andric                                        .addReg(STI.getFramePointerReg())
21150b57cec5SDimitry Andric                                        .addReg(SrcReg)
21160b57cec5SDimitry Andric                                        .addImm(0)
21170b57cec5SDimitry Andric                                        // Predicate.
21180b57cec5SDimitry Andric                                        .addImm(ARMCC::AL)
21190b57cec5SDimitry Andric                                        .addReg(0));
21200b57cec5SDimitry Andric     } else {
21210b57cec5SDimitry Andric       // If the calling code might use either R7 or R11 as
21220b57cec5SDimitry Andric       // frame pointer register, restore it into both.
21230b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi)
21240b57cec5SDimitry Andric         .addReg(ARM::R7)
21250b57cec5SDimitry Andric         .addReg(SrcReg)
21260b57cec5SDimitry Andric         .addImm(0)
21270b57cec5SDimitry Andric         // Predicate.
21280b57cec5SDimitry Andric         .addImm(ARMCC::AL)
21290b57cec5SDimitry Andric         .addReg(0));
21300b57cec5SDimitry Andric       EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi)
21310b57cec5SDimitry Andric         .addReg(ARM::R11)
21320b57cec5SDimitry Andric         .addReg(SrcReg)
21330b57cec5SDimitry Andric         .addImm(0)
21340b57cec5SDimitry Andric         // Predicate.
21350b57cec5SDimitry Andric         .addImm(ARMCC::AL)
21360b57cec5SDimitry Andric         .addReg(0));
21370b57cec5SDimitry Andric     }
21380b57cec5SDimitry Andric 
21390b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBX)
21400b57cec5SDimitry Andric       .addReg(ScratchReg)
21410b57cec5SDimitry Andric       // Predicate.
21420b57cec5SDimitry Andric       .addImm(ARMCC::AL)
21430b57cec5SDimitry Andric       .addReg(0));
21440b57cec5SDimitry Andric     return;
21450b57cec5SDimitry Andric   }
21460b57cec5SDimitry Andric   case ARM::tInt_WIN_eh_sjlj_longjmp: {
21470b57cec5SDimitry Andric     // ldr.w r11, [$src, #0]
21480b57cec5SDimitry Andric     // ldr.w  sp, [$src, #8]
21490b57cec5SDimitry Andric     // ldr.w  pc, [$src, #4]
21500b57cec5SDimitry Andric 
21518bcb0991SDimitry Andric     Register SrcReg = MI->getOperand(0).getReg();
21520b57cec5SDimitry Andric 
21530b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi12)
21540b57cec5SDimitry Andric                                      .addReg(ARM::R11)
21550b57cec5SDimitry Andric                                      .addReg(SrcReg)
21560b57cec5SDimitry Andric                                      .addImm(0)
21570b57cec5SDimitry Andric                                      // Predicate
21580b57cec5SDimitry Andric                                      .addImm(ARMCC::AL)
21590b57cec5SDimitry Andric                                      .addReg(0));
21600b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi12)
21610b57cec5SDimitry Andric                                      .addReg(ARM::SP)
21620b57cec5SDimitry Andric                                      .addReg(SrcReg)
21630b57cec5SDimitry Andric                                      .addImm(8)
21640b57cec5SDimitry Andric                                      // Predicate
21650b57cec5SDimitry Andric                                      .addImm(ARMCC::AL)
21660b57cec5SDimitry Andric                                      .addReg(0));
21670b57cec5SDimitry Andric     EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi12)
21680b57cec5SDimitry Andric                                      .addReg(ARM::PC)
21690b57cec5SDimitry Andric                                      .addReg(SrcReg)
21700b57cec5SDimitry Andric                                      .addImm(4)
21710b57cec5SDimitry Andric                                      // Predicate
21720b57cec5SDimitry Andric                                      .addImm(ARMCC::AL)
21730b57cec5SDimitry Andric                                      .addReg(0));
21740b57cec5SDimitry Andric     return;
21750b57cec5SDimitry Andric   }
21760b57cec5SDimitry Andric   case ARM::PATCHABLE_FUNCTION_ENTER:
21770b57cec5SDimitry Andric     LowerPATCHABLE_FUNCTION_ENTER(*MI);
21780b57cec5SDimitry Andric     return;
21790b57cec5SDimitry Andric   case ARM::PATCHABLE_FUNCTION_EXIT:
21800b57cec5SDimitry Andric     LowerPATCHABLE_FUNCTION_EXIT(*MI);
21810b57cec5SDimitry Andric     return;
21820b57cec5SDimitry Andric   case ARM::PATCHABLE_TAIL_CALL:
21830b57cec5SDimitry Andric     LowerPATCHABLE_TAIL_CALL(*MI);
21840b57cec5SDimitry Andric     return;
2185e8d8bef9SDimitry Andric   case ARM::SpeculationBarrierISBDSBEndBB: {
2186e8d8bef9SDimitry Andric     // Print DSB SYS + ISB
2187e8d8bef9SDimitry Andric     MCInst TmpInstDSB;
2188e8d8bef9SDimitry Andric     TmpInstDSB.setOpcode(ARM::DSB);
2189e8d8bef9SDimitry Andric     TmpInstDSB.addOperand(MCOperand::createImm(0xf));
2190e8d8bef9SDimitry Andric     EmitToStreamer(*OutStreamer, TmpInstDSB);
2191e8d8bef9SDimitry Andric     MCInst TmpInstISB;
2192e8d8bef9SDimitry Andric     TmpInstISB.setOpcode(ARM::ISB);
2193e8d8bef9SDimitry Andric     TmpInstISB.addOperand(MCOperand::createImm(0xf));
2194e8d8bef9SDimitry Andric     EmitToStreamer(*OutStreamer, TmpInstISB);
2195e8d8bef9SDimitry Andric     return;
2196e8d8bef9SDimitry Andric   }
2197e8d8bef9SDimitry Andric   case ARM::t2SpeculationBarrierISBDSBEndBB: {
2198e8d8bef9SDimitry Andric     // Print DSB SYS + ISB
2199e8d8bef9SDimitry Andric     MCInst TmpInstDSB;
2200e8d8bef9SDimitry Andric     TmpInstDSB.setOpcode(ARM::t2DSB);
2201e8d8bef9SDimitry Andric     TmpInstDSB.addOperand(MCOperand::createImm(0xf));
2202e8d8bef9SDimitry Andric     TmpInstDSB.addOperand(MCOperand::createImm(ARMCC::AL));
2203e8d8bef9SDimitry Andric     TmpInstDSB.addOperand(MCOperand::createReg(0));
2204e8d8bef9SDimitry Andric     EmitToStreamer(*OutStreamer, TmpInstDSB);
2205e8d8bef9SDimitry Andric     MCInst TmpInstISB;
2206e8d8bef9SDimitry Andric     TmpInstISB.setOpcode(ARM::t2ISB);
2207e8d8bef9SDimitry Andric     TmpInstISB.addOperand(MCOperand::createImm(0xf));
2208e8d8bef9SDimitry Andric     TmpInstISB.addOperand(MCOperand::createImm(ARMCC::AL));
2209e8d8bef9SDimitry Andric     TmpInstISB.addOperand(MCOperand::createReg(0));
2210e8d8bef9SDimitry Andric     EmitToStreamer(*OutStreamer, TmpInstISB);
2211e8d8bef9SDimitry Andric     return;
2212e8d8bef9SDimitry Andric   }
2213e8d8bef9SDimitry Andric   case ARM::SpeculationBarrierSBEndBB: {
2214e8d8bef9SDimitry Andric     // Print SB
2215e8d8bef9SDimitry Andric     MCInst TmpInstSB;
2216e8d8bef9SDimitry Andric     TmpInstSB.setOpcode(ARM::SB);
2217e8d8bef9SDimitry Andric     EmitToStreamer(*OutStreamer, TmpInstSB);
2218e8d8bef9SDimitry Andric     return;
2219e8d8bef9SDimitry Andric   }
2220e8d8bef9SDimitry Andric   case ARM::t2SpeculationBarrierSBEndBB: {
2221e8d8bef9SDimitry Andric     // Print SB
2222e8d8bef9SDimitry Andric     MCInst TmpInstSB;
2223e8d8bef9SDimitry Andric     TmpInstSB.setOpcode(ARM::t2SB);
2224e8d8bef9SDimitry Andric     EmitToStreamer(*OutStreamer, TmpInstSB);
2225e8d8bef9SDimitry Andric     return;
2226e8d8bef9SDimitry Andric   }
22270b57cec5SDimitry Andric   }
22280b57cec5SDimitry Andric 
22290b57cec5SDimitry Andric   MCInst TmpInst;
22300b57cec5SDimitry Andric   LowerARMMachineInstrToMCInst(MI, TmpInst, *this);
22310b57cec5SDimitry Andric 
22320b57cec5SDimitry Andric   EmitToStreamer(*OutStreamer, TmpInst);
22330b57cec5SDimitry Andric }
22340b57cec5SDimitry Andric 
22350b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
22360b57cec5SDimitry Andric // Target Registry Stuff
22370b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
22380b57cec5SDimitry Andric 
22390b57cec5SDimitry Andric // Force static initialization.
2240480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARMAsmPrinter() {
22410b57cec5SDimitry Andric   RegisterAsmPrinter<ARMAsmPrinter> X(getTheARMLETarget());
22420b57cec5SDimitry Andric   RegisterAsmPrinter<ARMAsmPrinter> Y(getTheARMBETarget());
22430b57cec5SDimitry Andric   RegisterAsmPrinter<ARMAsmPrinter> A(getTheThumbLETarget());
22440b57cec5SDimitry Andric   RegisterAsmPrinter<ARMAsmPrinter> B(getTheThumbBETarget());
22450b57cec5SDimitry Andric }
2246