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/SmallString.h" 250b57cec5SDimitry Andric #include "llvm/BinaryFormat/COFF.h" 260b57cec5SDimitry Andric #include "llvm/CodeGen/MachineFunctionPass.h" 270b57cec5SDimitry Andric #include "llvm/CodeGen/MachineJumpTableInfo.h" 280b57cec5SDimitry Andric #include "llvm/CodeGen/MachineModuleInfoImpls.h" 290b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 300b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h" 310b57cec5SDimitry Andric #include "llvm/IR/Mangler.h" 320b57cec5SDimitry Andric #include "llvm/IR/Module.h" 330b57cec5SDimitry Andric #include "llvm/IR/Type.h" 340b57cec5SDimitry Andric #include "llvm/MC/MCAsmInfo.h" 350b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h" 360b57cec5SDimitry Andric #include "llvm/MC/MCContext.h" 370b57cec5SDimitry Andric #include "llvm/MC/MCELFStreamer.h" 380b57cec5SDimitry Andric #include "llvm/MC/MCInst.h" 390b57cec5SDimitry Andric #include "llvm/MC/MCInstBuilder.h" 400b57cec5SDimitry Andric #include "llvm/MC/MCObjectStreamer.h" 410b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h" 420b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h" 43349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h" 440b57cec5SDimitry Andric #include "llvm/Support/ARMBuildAttributes.h" 450b57cec5SDimitry Andric #include "llvm/Support/Debug.h" 460b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h" 470b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 480b57cec5SDimitry Andric #include "llvm/Target/TargetMachine.h" 490b57cec5SDimitry Andric using namespace llvm; 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric #define DEBUG_TYPE "asm-printer" 520b57cec5SDimitry Andric 530b57cec5SDimitry Andric ARMAsmPrinter::ARMAsmPrinter(TargetMachine &TM, 540b57cec5SDimitry Andric std::unique_ptr<MCStreamer> Streamer) 55480093f4SDimitry Andric : AsmPrinter(TM, std::move(Streamer)), Subtarget(nullptr), AFI(nullptr), 56480093f4SDimitry Andric MCP(nullptr), InConstantPool(false), OptimizationGoals(-1) {} 570b57cec5SDimitry Andric 585ffd83dbSDimitry Andric void ARMAsmPrinter::emitFunctionBodyEnd() { 590b57cec5SDimitry Andric // Make sure to terminate any constant pools that were at the end 600b57cec5SDimitry Andric // of the function. 610b57cec5SDimitry Andric if (!InConstantPool) 620b57cec5SDimitry Andric return; 630b57cec5SDimitry Andric InConstantPool = false; 645ffd83dbSDimitry Andric OutStreamer->emitDataRegion(MCDR_DataRegionEnd); 650b57cec5SDimitry Andric } 660b57cec5SDimitry Andric 675ffd83dbSDimitry Andric void ARMAsmPrinter::emitFunctionEntryLabel() { 680b57cec5SDimitry Andric if (AFI->isThumbFunction()) { 695ffd83dbSDimitry Andric OutStreamer->emitAssemblerFlag(MCAF_Code16); 705ffd83dbSDimitry Andric OutStreamer->emitThumbFunc(CurrentFnSym); 710b57cec5SDimitry Andric } else { 725ffd83dbSDimitry Andric OutStreamer->emitAssemblerFlag(MCAF_Code32); 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 755ffd83dbSDimitry Andric // Emit symbol for CMSE non-secure entry point 765ffd83dbSDimitry Andric if (AFI->isCmseNSEntryFunction()) { 775ffd83dbSDimitry Andric MCSymbol *S = 785ffd83dbSDimitry Andric OutContext.getOrCreateSymbol("__acle_se_" + CurrentFnSym->getName()); 795ffd83dbSDimitry Andric emitLinkage(&MF->getFunction(), S); 805ffd83dbSDimitry Andric OutStreamer->emitSymbolAttribute(S, MCSA_ELF_TypeFunction); 815ffd83dbSDimitry Andric OutStreamer->emitLabel(S); 825ffd83dbSDimitry Andric } 83bdd1243dSDimitry Andric AsmPrinter::emitFunctionEntryLabel(); 845ffd83dbSDimitry Andric } 855ffd83dbSDimitry Andric 865ffd83dbSDimitry Andric void ARMAsmPrinter::emitXXStructor(const DataLayout &DL, const Constant *CV) { 870b57cec5SDimitry Andric uint64_t Size = getDataLayout().getTypeAllocSize(CV->getType()); 880b57cec5SDimitry Andric assert(Size && "C++ constructor pointer had zero size!"); 890b57cec5SDimitry Andric 900b57cec5SDimitry Andric const GlobalValue *GV = dyn_cast<GlobalValue>(CV->stripPointerCasts()); 910b57cec5SDimitry Andric assert(GV && "C++ constructor pointer was not a GlobalValue!"); 920b57cec5SDimitry Andric 930b57cec5SDimitry Andric const MCExpr *E = MCSymbolRefExpr::create(GetARMGVSymbol(GV, 940b57cec5SDimitry Andric ARMII::MO_NO_FLAG), 950b57cec5SDimitry Andric (Subtarget->isTargetELF() 960b57cec5SDimitry Andric ? MCSymbolRefExpr::VK_ARM_TARGET1 970b57cec5SDimitry Andric : MCSymbolRefExpr::VK_None), 980b57cec5SDimitry Andric OutContext); 990b57cec5SDimitry Andric 1005ffd83dbSDimitry Andric OutStreamer->emitValue(E, Size); 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric 1035ffd83dbSDimitry Andric void ARMAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) { 1040b57cec5SDimitry Andric if (PromotedGlobals.count(GV)) 1050b57cec5SDimitry Andric // The global was promoted into a constant pool. It should not be emitted. 1060b57cec5SDimitry Andric return; 1075ffd83dbSDimitry Andric AsmPrinter::emitGlobalVariable(GV); 1080b57cec5SDimitry Andric } 1090b57cec5SDimitry Andric 1105ffd83dbSDimitry Andric /// runOnMachineFunction - This uses the emitInstruction() 1110b57cec5SDimitry Andric /// method to print assembly for each instruction. 1120b57cec5SDimitry Andric /// 1130b57cec5SDimitry Andric bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { 1140b57cec5SDimitry Andric AFI = MF.getInfo<ARMFunctionInfo>(); 1150b57cec5SDimitry Andric MCP = MF.getConstantPool(); 1160b57cec5SDimitry Andric Subtarget = &MF.getSubtarget<ARMSubtarget>(); 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric SetupMachineFunction(MF); 1190b57cec5SDimitry Andric const Function &F = MF.getFunction(); 1200b57cec5SDimitry Andric const TargetMachine& TM = MF.getTarget(); 1210b57cec5SDimitry Andric 1220b57cec5SDimitry Andric // Collect all globals that had their storage promoted to a constant pool. 1230b57cec5SDimitry Andric // Functions are emitted before variables, so this accumulates promoted 1240b57cec5SDimitry Andric // globals from all functions in PromotedGlobals. 125bdd1243dSDimitry Andric for (const auto *GV : AFI->getGlobalsPromotedToConstantPool()) 1260b57cec5SDimitry Andric PromotedGlobals.insert(GV); 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric // Calculate this function's optimization goal. 1290b57cec5SDimitry Andric unsigned OptimizationGoal; 1300b57cec5SDimitry Andric if (F.hasOptNone()) 1310b57cec5SDimitry Andric // For best debugging illusion, speed and small size sacrificed 1320b57cec5SDimitry Andric OptimizationGoal = 6; 1330b57cec5SDimitry Andric else if (F.hasMinSize()) 1340b57cec5SDimitry Andric // Aggressively for small size, speed and debug illusion sacrificed 1350b57cec5SDimitry Andric OptimizationGoal = 4; 1360b57cec5SDimitry Andric else if (F.hasOptSize()) 1370b57cec5SDimitry Andric // For small size, but speed and debugging illusion preserved 1380b57cec5SDimitry Andric OptimizationGoal = 3; 1395f757f3fSDimitry Andric else if (TM.getOptLevel() == CodeGenOptLevel::Aggressive) 1400b57cec5SDimitry Andric // Aggressively for speed, small size and debug illusion sacrificed 1410b57cec5SDimitry Andric OptimizationGoal = 2; 1425f757f3fSDimitry Andric else if (TM.getOptLevel() > CodeGenOptLevel::None) 1430b57cec5SDimitry Andric // For speed, but small size and good debug illusion preserved 1440b57cec5SDimitry Andric OptimizationGoal = 1; 1455f757f3fSDimitry Andric else // TM.getOptLevel() == CodeGenOptLevel::None 1460b57cec5SDimitry Andric // For good debugging, but speed and small size preserved 1470b57cec5SDimitry Andric OptimizationGoal = 5; 1480b57cec5SDimitry Andric 1490b57cec5SDimitry Andric // Combine a new optimization goal with existing ones. 1500b57cec5SDimitry Andric if (OptimizationGoals == -1) // uninitialized goals 1510b57cec5SDimitry Andric OptimizationGoals = OptimizationGoal; 1520b57cec5SDimitry Andric else if (OptimizationGoals != (int)OptimizationGoal) // conflicting goals 1530b57cec5SDimitry Andric OptimizationGoals = 0; 1540b57cec5SDimitry Andric 1550b57cec5SDimitry Andric if (Subtarget->isTargetCOFF()) { 156*52418fc2SDimitry Andric bool Local = F.hasLocalLinkage(); 157*52418fc2SDimitry Andric COFF::SymbolStorageClass Scl = 158*52418fc2SDimitry Andric Local ? COFF::IMAGE_SYM_CLASS_STATIC : COFF::IMAGE_SYM_CLASS_EXTERNAL; 1590b57cec5SDimitry Andric int Type = COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT; 1600b57cec5SDimitry Andric 16181ad6265SDimitry Andric OutStreamer->beginCOFFSymbolDef(CurrentFnSym); 16281ad6265SDimitry Andric OutStreamer->emitCOFFSymbolStorageClass(Scl); 16381ad6265SDimitry Andric OutStreamer->emitCOFFSymbolType(Type); 16481ad6265SDimitry Andric OutStreamer->endCOFFSymbolDef(); 1650b57cec5SDimitry Andric } 1660b57cec5SDimitry Andric 1670b57cec5SDimitry Andric // Emit the rest of the function body. 1685ffd83dbSDimitry Andric emitFunctionBody(); 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric // Emit the XRay table for this function. 1710b57cec5SDimitry Andric emitXRayTable(); 1720b57cec5SDimitry Andric 1730b57cec5SDimitry Andric // If we need V4T thumb mode Register Indirect Jump pads, emit them. 1740b57cec5SDimitry Andric // These are created per function, rather than per TU, since it's 1750b57cec5SDimitry Andric // relatively easy to exceed the thumb branch range within a TU. 1760b57cec5SDimitry Andric if (! ThumbIndirectPads.empty()) { 1775ffd83dbSDimitry Andric OutStreamer->emitAssemblerFlag(MCAF_Code16); 1785ffd83dbSDimitry Andric emitAlignment(Align(2)); 1790b57cec5SDimitry Andric for (std::pair<unsigned, MCSymbol *> &TIP : ThumbIndirectPads) { 1805ffd83dbSDimitry Andric OutStreamer->emitLabel(TIP.second); 1810b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBX) 1820b57cec5SDimitry Andric .addReg(TIP.first) 1830b57cec5SDimitry Andric // Add predicate operands. 1840b57cec5SDimitry Andric .addImm(ARMCC::AL) 1850b57cec5SDimitry Andric .addReg(0)); 1860b57cec5SDimitry Andric } 1870b57cec5SDimitry Andric ThumbIndirectPads.clear(); 1880b57cec5SDimitry Andric } 1890b57cec5SDimitry Andric 1900b57cec5SDimitry Andric // We didn't modify anything. 1910b57cec5SDimitry Andric return false; 1920b57cec5SDimitry Andric } 1930b57cec5SDimitry Andric 1940b57cec5SDimitry Andric void ARMAsmPrinter::PrintSymbolOperand(const MachineOperand &MO, 1950b57cec5SDimitry Andric raw_ostream &O) { 1960b57cec5SDimitry Andric assert(MO.isGlobal() && "caller should check MO.isGlobal"); 1970b57cec5SDimitry Andric unsigned TF = MO.getTargetFlags(); 1980b57cec5SDimitry Andric if (TF & ARMII::MO_LO16) 1990b57cec5SDimitry Andric O << ":lower16:"; 2000b57cec5SDimitry Andric else if (TF & ARMII::MO_HI16) 2010b57cec5SDimitry Andric O << ":upper16:"; 20206c3fb27SDimitry Andric else if (TF & ARMII::MO_LO_0_7) 20306c3fb27SDimitry Andric O << ":lower0_7:"; 20406c3fb27SDimitry Andric else if (TF & ARMII::MO_LO_8_15) 20506c3fb27SDimitry Andric O << ":lower8_15:"; 20606c3fb27SDimitry Andric else if (TF & ARMII::MO_HI_0_7) 20706c3fb27SDimitry Andric O << ":upper0_7:"; 20806c3fb27SDimitry Andric else if (TF & ARMII::MO_HI_8_15) 20906c3fb27SDimitry Andric O << ":upper8_15:"; 21006c3fb27SDimitry Andric 2110b57cec5SDimitry Andric GetARMGVSymbol(MO.getGlobal(), TF)->print(O, MAI); 2120b57cec5SDimitry Andric printOffset(MO.getOffset(), O); 2130b57cec5SDimitry Andric } 2140b57cec5SDimitry Andric 2150b57cec5SDimitry Andric void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum, 2160b57cec5SDimitry Andric raw_ostream &O) { 2170b57cec5SDimitry Andric const MachineOperand &MO = MI->getOperand(OpNum); 2180b57cec5SDimitry Andric 2190b57cec5SDimitry Andric switch (MO.getType()) { 2200b57cec5SDimitry Andric default: llvm_unreachable("<unknown operand type>"); 2210b57cec5SDimitry Andric case MachineOperand::MO_Register: { 2228bcb0991SDimitry Andric Register Reg = MO.getReg(); 223bdd1243dSDimitry Andric assert(Reg.isPhysical()); 2240b57cec5SDimitry Andric assert(!MO.getSubReg() && "Subregs should be eliminated!"); 2250b57cec5SDimitry Andric if(ARM::GPRPairRegClass.contains(Reg)) { 2260b57cec5SDimitry Andric const MachineFunction &MF = *MI->getParent()->getParent(); 2270b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 2280b57cec5SDimitry Andric Reg = TRI->getSubReg(Reg, ARM::gsub_0); 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric O << ARMInstPrinter::getRegisterName(Reg); 2310b57cec5SDimitry Andric break; 2320b57cec5SDimitry Andric } 2330b57cec5SDimitry Andric case MachineOperand::MO_Immediate: { 2340b57cec5SDimitry Andric O << '#'; 2350b57cec5SDimitry Andric unsigned TF = MO.getTargetFlags(); 2360b57cec5SDimitry Andric if (TF == ARMII::MO_LO16) 2370b57cec5SDimitry Andric O << ":lower16:"; 2380b57cec5SDimitry Andric else if (TF == ARMII::MO_HI16) 2390b57cec5SDimitry Andric O << ":upper16:"; 24006c3fb27SDimitry Andric else if (TF == ARMII::MO_LO_0_7) 24106c3fb27SDimitry Andric O << ":lower0_7:"; 24206c3fb27SDimitry Andric else if (TF == ARMII::MO_LO_8_15) 24306c3fb27SDimitry Andric O << ":lower8_15:"; 24406c3fb27SDimitry Andric else if (TF == ARMII::MO_HI_0_7) 24506c3fb27SDimitry Andric O << ":upper0_7:"; 24606c3fb27SDimitry Andric else if (TF == ARMII::MO_HI_8_15) 24706c3fb27SDimitry Andric O << ":upper8_15:"; 2480b57cec5SDimitry Andric O << MO.getImm(); 2490b57cec5SDimitry Andric break; 2500b57cec5SDimitry Andric } 2510b57cec5SDimitry Andric case MachineOperand::MO_MachineBasicBlock: 2520b57cec5SDimitry Andric MO.getMBB()->getSymbol()->print(O, MAI); 2530b57cec5SDimitry Andric return; 2540b57cec5SDimitry Andric case MachineOperand::MO_GlobalAddress: { 2550b57cec5SDimitry Andric PrintSymbolOperand(MO, O); 2560b57cec5SDimitry Andric break; 2570b57cec5SDimitry Andric } 2580b57cec5SDimitry Andric case MachineOperand::MO_ConstantPoolIndex: 2590b57cec5SDimitry Andric if (Subtarget->genExecuteOnly()) 2600b57cec5SDimitry Andric llvm_unreachable("execute-only should not generate constant pools"); 2610b57cec5SDimitry Andric GetCPISymbol(MO.getIndex())->print(O, MAI); 2620b57cec5SDimitry Andric break; 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric } 2650b57cec5SDimitry Andric 2660b57cec5SDimitry Andric MCSymbol *ARMAsmPrinter::GetCPISymbol(unsigned CPID) const { 2670b57cec5SDimitry Andric // The AsmPrinter::GetCPISymbol superclass method tries to use CPID as 2680b57cec5SDimitry Andric // indexes in MachineConstantPool, which isn't in sync with indexes used here. 2690b57cec5SDimitry Andric const DataLayout &DL = getDataLayout(); 2700b57cec5SDimitry Andric return OutContext.getOrCreateSymbol(Twine(DL.getPrivateGlobalPrefix()) + 2710b57cec5SDimitry Andric "CPI" + Twine(getFunctionNumber()) + "_" + 2720b57cec5SDimitry Andric Twine(CPID)); 2730b57cec5SDimitry Andric } 2740b57cec5SDimitry Andric 2750b57cec5SDimitry Andric //===--------------------------------------------------------------------===// 2760b57cec5SDimitry Andric 2770b57cec5SDimitry Andric MCSymbol *ARMAsmPrinter:: 2780b57cec5SDimitry Andric GetARMJTIPICJumpTableLabel(unsigned uid) const { 2790b57cec5SDimitry Andric const DataLayout &DL = getDataLayout(); 2800b57cec5SDimitry Andric SmallString<60> Name; 2810b57cec5SDimitry Andric raw_svector_ostream(Name) << DL.getPrivateGlobalPrefix() << "JTI" 2820b57cec5SDimitry Andric << getFunctionNumber() << '_' << uid; 2830b57cec5SDimitry Andric return OutContext.getOrCreateSymbol(Name); 2840b57cec5SDimitry Andric } 2850b57cec5SDimitry Andric 2860b57cec5SDimitry Andric bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, 2870b57cec5SDimitry Andric const char *ExtraCode, raw_ostream &O) { 2880b57cec5SDimitry Andric // Does this asm operand have a single letter operand modifier? 2890b57cec5SDimitry Andric if (ExtraCode && ExtraCode[0]) { 2900b57cec5SDimitry Andric if (ExtraCode[1] != 0) return true; // Unknown modifier. 2910b57cec5SDimitry Andric 2920b57cec5SDimitry Andric switch (ExtraCode[0]) { 2930b57cec5SDimitry Andric default: 2940b57cec5SDimitry Andric // See if this is a generic print operand 2950b57cec5SDimitry Andric return AsmPrinter::PrintAsmOperand(MI, OpNum, ExtraCode, O); 2960b57cec5SDimitry Andric case 'P': // Print a VFP double precision register. 2970b57cec5SDimitry Andric case 'q': // Print a NEON quad precision register. 2980b57cec5SDimitry Andric printOperand(MI, OpNum, O); 2990b57cec5SDimitry Andric return false; 3000b57cec5SDimitry Andric case 'y': // Print a VFP single precision register as indexed double. 3010b57cec5SDimitry Andric if (MI->getOperand(OpNum).isReg()) { 302e8d8bef9SDimitry Andric MCRegister Reg = MI->getOperand(OpNum).getReg().asMCReg(); 3030b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); 3040b57cec5SDimitry Andric // Find the 'd' register that has this 's' register as a sub-register, 3050b57cec5SDimitry Andric // and determine the lane number. 30606c3fb27SDimitry Andric for (MCPhysReg SR : TRI->superregs(Reg)) { 30706c3fb27SDimitry Andric if (!ARM::DPRRegClass.contains(SR)) 3080b57cec5SDimitry Andric continue; 30906c3fb27SDimitry Andric bool Lane0 = TRI->getSubReg(SR, ARM::ssub_0) == Reg; 31006c3fb27SDimitry Andric O << ARMInstPrinter::getRegisterName(SR) << (Lane0 ? "[0]" : "[1]"); 3110b57cec5SDimitry Andric return false; 3120b57cec5SDimitry Andric } 3130b57cec5SDimitry Andric } 3140b57cec5SDimitry Andric return true; 3150b57cec5SDimitry Andric case 'B': // Bitwise inverse of integer or symbol without a preceding #. 3160b57cec5SDimitry Andric if (!MI->getOperand(OpNum).isImm()) 3170b57cec5SDimitry Andric return true; 3180b57cec5SDimitry Andric O << ~(MI->getOperand(OpNum).getImm()); 3190b57cec5SDimitry Andric return false; 3200b57cec5SDimitry Andric case 'L': // The low 16 bits of an immediate constant. 3210b57cec5SDimitry Andric if (!MI->getOperand(OpNum).isImm()) 3220b57cec5SDimitry Andric return true; 3230b57cec5SDimitry Andric O << (MI->getOperand(OpNum).getImm() & 0xffff); 3240b57cec5SDimitry Andric return false; 3250b57cec5SDimitry Andric case 'M': { // A register range suitable for LDM/STM. 3260b57cec5SDimitry Andric if (!MI->getOperand(OpNum).isReg()) 3270b57cec5SDimitry Andric return true; 3280b57cec5SDimitry Andric const MachineOperand &MO = MI->getOperand(OpNum); 3298bcb0991SDimitry Andric Register RegBegin = MO.getReg(); 3300b57cec5SDimitry Andric // This takes advantage of the 2 operand-ness of ldm/stm and that we've 3310b57cec5SDimitry Andric // already got the operands in registers that are operands to the 3320b57cec5SDimitry Andric // inline asm statement. 3330b57cec5SDimitry Andric O << "{"; 3340b57cec5SDimitry Andric if (ARM::GPRPairRegClass.contains(RegBegin)) { 3350b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); 3368bcb0991SDimitry Andric Register Reg0 = TRI->getSubReg(RegBegin, ARM::gsub_0); 3370b57cec5SDimitry Andric O << ARMInstPrinter::getRegisterName(Reg0) << ", "; 3380b57cec5SDimitry Andric RegBegin = TRI->getSubReg(RegBegin, ARM::gsub_1); 3390b57cec5SDimitry Andric } 3400b57cec5SDimitry Andric O << ARMInstPrinter::getRegisterName(RegBegin); 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric // FIXME: The register allocator not only may not have given us the 3430b57cec5SDimitry Andric // registers in sequence, but may not be in ascending registers. This 3440b57cec5SDimitry Andric // will require changes in the register allocator that'll need to be 3450b57cec5SDimitry Andric // propagated down here if the operands change. 3460b57cec5SDimitry Andric unsigned RegOps = OpNum + 1; 3470b57cec5SDimitry Andric while (MI->getOperand(RegOps).isReg()) { 3480b57cec5SDimitry Andric O << ", " 3490b57cec5SDimitry Andric << ARMInstPrinter::getRegisterName(MI->getOperand(RegOps).getReg()); 3500b57cec5SDimitry Andric RegOps++; 3510b57cec5SDimitry Andric } 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric O << "}"; 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric return false; 3560b57cec5SDimitry Andric } 3570b57cec5SDimitry Andric case 'R': // The most significant register of a pair. 3580b57cec5SDimitry Andric case 'Q': { // The least significant register of a pair. 3590b57cec5SDimitry Andric if (OpNum == 0) 3600b57cec5SDimitry Andric return true; 3610b57cec5SDimitry Andric const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1); 3620b57cec5SDimitry Andric if (!FlagsOP.isImm()) 3630b57cec5SDimitry Andric return true; 3645f757f3fSDimitry Andric InlineAsm::Flag F(FlagsOP.getImm()); 3650b57cec5SDimitry Andric 3660b57cec5SDimitry Andric // This operand may not be the one that actually provides the register. If 3670b57cec5SDimitry Andric // it's tied to a previous one then we should refer instead to that one 3680b57cec5SDimitry Andric // for registers and their classes. 3690b57cec5SDimitry Andric unsigned TiedIdx; 3705f757f3fSDimitry Andric if (F.isUseOperandTiedToDef(TiedIdx)) { 3710b57cec5SDimitry Andric for (OpNum = InlineAsm::MIOp_FirstOperand; TiedIdx; --TiedIdx) { 3720b57cec5SDimitry Andric unsigned OpFlags = MI->getOperand(OpNum).getImm(); 3735f757f3fSDimitry Andric const InlineAsm::Flag F(OpFlags); 3745f757f3fSDimitry Andric OpNum += F.getNumOperandRegisters() + 1; 3750b57cec5SDimitry Andric } 3765f757f3fSDimitry Andric F = InlineAsm::Flag(MI->getOperand(OpNum).getImm()); 3770b57cec5SDimitry Andric 3780b57cec5SDimitry Andric // Later code expects OpNum to be pointing at the register rather than 3790b57cec5SDimitry Andric // the flags. 3800b57cec5SDimitry Andric OpNum += 1; 3810b57cec5SDimitry Andric } 3820b57cec5SDimitry Andric 3835f757f3fSDimitry Andric const unsigned NumVals = F.getNumOperandRegisters(); 3840b57cec5SDimitry Andric unsigned RC; 3850b57cec5SDimitry Andric bool FirstHalf; 3860b57cec5SDimitry Andric const ARMBaseTargetMachine &ATM = 3870b57cec5SDimitry Andric static_cast<const ARMBaseTargetMachine &>(TM); 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric // 'Q' should correspond to the low order register and 'R' to the high 3900b57cec5SDimitry Andric // order register. Whether this corresponds to the upper or lower half 3910b57cec5SDimitry Andric // depends on the endianess mode. 3920b57cec5SDimitry Andric if (ExtraCode[0] == 'Q') 3930b57cec5SDimitry Andric FirstHalf = ATM.isLittleEndian(); 3940b57cec5SDimitry Andric else 3950b57cec5SDimitry Andric // ExtraCode[0] == 'R'. 3960b57cec5SDimitry Andric FirstHalf = !ATM.isLittleEndian(); 3970b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); 3985f757f3fSDimitry Andric if (F.hasRegClassConstraint(RC) && 3990b57cec5SDimitry Andric ARM::GPRPairRegClass.hasSubClassEq(TRI->getRegClass(RC))) { 4000b57cec5SDimitry Andric if (NumVals != 1) 4010b57cec5SDimitry Andric return true; 4020b57cec5SDimitry Andric const MachineOperand &MO = MI->getOperand(OpNum); 4030b57cec5SDimitry Andric if (!MO.isReg()) 4040b57cec5SDimitry Andric return true; 4050b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); 4068bcb0991SDimitry Andric Register Reg = 4078bcb0991SDimitry Andric TRI->getSubReg(MO.getReg(), FirstHalf ? ARM::gsub_0 : ARM::gsub_1); 4080b57cec5SDimitry Andric O << ARMInstPrinter::getRegisterName(Reg); 4090b57cec5SDimitry Andric return false; 4100b57cec5SDimitry Andric } 4110b57cec5SDimitry Andric if (NumVals != 2) 4120b57cec5SDimitry Andric return true; 4130b57cec5SDimitry Andric unsigned RegOp = FirstHalf ? OpNum : OpNum + 1; 4140b57cec5SDimitry Andric if (RegOp >= MI->getNumOperands()) 4150b57cec5SDimitry Andric return true; 4160b57cec5SDimitry Andric const MachineOperand &MO = MI->getOperand(RegOp); 4170b57cec5SDimitry Andric if (!MO.isReg()) 4180b57cec5SDimitry Andric return true; 4198bcb0991SDimitry Andric Register Reg = MO.getReg(); 4200b57cec5SDimitry Andric O << ARMInstPrinter::getRegisterName(Reg); 4210b57cec5SDimitry Andric return false; 4220b57cec5SDimitry Andric } 4230b57cec5SDimitry Andric 4240b57cec5SDimitry Andric case 'e': // The low doubleword register of a NEON quad register. 4250b57cec5SDimitry Andric case 'f': { // The high doubleword register of a NEON quad register. 4260b57cec5SDimitry Andric if (!MI->getOperand(OpNum).isReg()) 4270b57cec5SDimitry Andric return true; 4288bcb0991SDimitry Andric Register Reg = MI->getOperand(OpNum).getReg(); 4290b57cec5SDimitry Andric if (!ARM::QPRRegClass.contains(Reg)) 4300b57cec5SDimitry Andric return true; 4310b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo(); 4328bcb0991SDimitry Andric Register SubReg = 4338bcb0991SDimitry Andric TRI->getSubReg(Reg, ExtraCode[0] == 'e' ? ARM::dsub_0 : ARM::dsub_1); 4340b57cec5SDimitry Andric O << ARMInstPrinter::getRegisterName(SubReg); 4350b57cec5SDimitry Andric return false; 4360b57cec5SDimitry Andric } 4370b57cec5SDimitry Andric 4380b57cec5SDimitry Andric // This modifier is not yet supported. 4390b57cec5SDimitry Andric case 'h': // A range of VFP/NEON registers suitable for VLD1/VST1. 4400b57cec5SDimitry Andric return true; 4410b57cec5SDimitry Andric case 'H': { // The highest-numbered register of a pair. 4420b57cec5SDimitry Andric const MachineOperand &MO = MI->getOperand(OpNum); 4430b57cec5SDimitry Andric if (!MO.isReg()) 4440b57cec5SDimitry Andric return true; 4450b57cec5SDimitry Andric const MachineFunction &MF = *MI->getParent()->getParent(); 4460b57cec5SDimitry Andric const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo(); 4478bcb0991SDimitry Andric Register Reg = MO.getReg(); 4480b57cec5SDimitry Andric if(!ARM::GPRPairRegClass.contains(Reg)) 4490b57cec5SDimitry Andric return false; 4500b57cec5SDimitry Andric Reg = TRI->getSubReg(Reg, ARM::gsub_1); 4510b57cec5SDimitry Andric O << ARMInstPrinter::getRegisterName(Reg); 4520b57cec5SDimitry Andric return false; 4530b57cec5SDimitry Andric } 4540b57cec5SDimitry Andric } 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric printOperand(MI, OpNum, O); 4580b57cec5SDimitry Andric return false; 4590b57cec5SDimitry Andric } 4600b57cec5SDimitry Andric 4610b57cec5SDimitry Andric bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, 4620b57cec5SDimitry Andric unsigned OpNum, const char *ExtraCode, 4630b57cec5SDimitry Andric raw_ostream &O) { 4640b57cec5SDimitry Andric // Does this asm operand have a single letter operand modifier? 4650b57cec5SDimitry Andric if (ExtraCode && ExtraCode[0]) { 4660b57cec5SDimitry Andric if (ExtraCode[1] != 0) return true; // Unknown modifier. 4670b57cec5SDimitry Andric 4680b57cec5SDimitry Andric switch (ExtraCode[0]) { 4690b57cec5SDimitry Andric case 'A': // A memory operand for a VLD1/VST1 instruction. 4700b57cec5SDimitry Andric default: return true; // Unknown modifier. 4710b57cec5SDimitry Andric case 'm': // The base register of a memory operand. 4720b57cec5SDimitry Andric if (!MI->getOperand(OpNum).isReg()) 4730b57cec5SDimitry Andric return true; 4740b57cec5SDimitry Andric O << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg()); 4750b57cec5SDimitry Andric return false; 4760b57cec5SDimitry Andric } 4770b57cec5SDimitry Andric } 4780b57cec5SDimitry Andric 4790b57cec5SDimitry Andric const MachineOperand &MO = MI->getOperand(OpNum); 4800b57cec5SDimitry Andric assert(MO.isReg() && "unexpected inline asm memory operand"); 4810b57cec5SDimitry Andric O << "[" << ARMInstPrinter::getRegisterName(MO.getReg()) << "]"; 4820b57cec5SDimitry Andric return false; 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric static bool isThumb(const MCSubtargetInfo& STI) { 48606c3fb27SDimitry Andric return STI.hasFeature(ARM::ModeThumb); 4870b57cec5SDimitry Andric } 4880b57cec5SDimitry Andric 4890b57cec5SDimitry Andric void ARMAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo, 4900b57cec5SDimitry Andric const MCSubtargetInfo *EndInfo) const { 4910b57cec5SDimitry Andric // If either end mode is unknown (EndInfo == NULL) or different than 4920b57cec5SDimitry Andric // the start mode, then restore the start mode. 4930b57cec5SDimitry Andric const bool WasThumb = isThumb(StartInfo); 4940b57cec5SDimitry Andric if (!EndInfo || WasThumb != isThumb(*EndInfo)) { 4955ffd83dbSDimitry Andric OutStreamer->emitAssemblerFlag(WasThumb ? MCAF_Code16 : MCAF_Code32); 4960b57cec5SDimitry Andric } 4970b57cec5SDimitry Andric } 4980b57cec5SDimitry Andric 4995ffd83dbSDimitry Andric void ARMAsmPrinter::emitStartOfAsmFile(Module &M) { 5000b57cec5SDimitry Andric const Triple &TT = TM.getTargetTriple(); 5010b57cec5SDimitry Andric // Use unified assembler syntax. 5025ffd83dbSDimitry Andric OutStreamer->emitAssemblerFlag(MCAF_SyntaxUnified); 5030b57cec5SDimitry Andric 5040b57cec5SDimitry Andric // Emit ARM Build Attributes 5050b57cec5SDimitry Andric if (TT.isOSBinFormatELF()) 5060b57cec5SDimitry Andric emitAttributes(); 5070b57cec5SDimitry Andric 5080b57cec5SDimitry Andric // Use the triple's architecture and subarchitecture to determine 5090b57cec5SDimitry Andric // if we're thumb for the purposes of the top level code16 assembler 5100b57cec5SDimitry Andric // flag. 5110b57cec5SDimitry Andric if (!M.getModuleInlineAsm().empty() && TT.isThumb()) 5125ffd83dbSDimitry Andric OutStreamer->emitAssemblerFlag(MCAF_Code16); 5130b57cec5SDimitry Andric } 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric static void 5160b57cec5SDimitry Andric emitNonLazySymbolPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel, 5170b57cec5SDimitry Andric MachineModuleInfoImpl::StubValueTy &MCSym) { 5180b57cec5SDimitry Andric // L_foo$stub: 5195ffd83dbSDimitry Andric OutStreamer.emitLabel(StubLabel); 5200b57cec5SDimitry Andric // .indirect_symbol _foo 5215ffd83dbSDimitry Andric OutStreamer.emitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol); 5220b57cec5SDimitry Andric 5230b57cec5SDimitry Andric if (MCSym.getInt()) 5240b57cec5SDimitry Andric // External to current translation unit. 5255ffd83dbSDimitry Andric OutStreamer.emitIntValue(0, 4/*size*/); 5260b57cec5SDimitry Andric else 5270b57cec5SDimitry Andric // Internal to current translation unit. 5280b57cec5SDimitry Andric // 5290b57cec5SDimitry Andric // When we place the LSDA into the TEXT section, the type info 5300b57cec5SDimitry Andric // pointers need to be indirect and pc-rel. We accomplish this by 5310b57cec5SDimitry Andric // using NLPs; however, sometimes the types are local to the file. 5320b57cec5SDimitry Andric // We need to fill in the value for the NLP in those cases. 5335ffd83dbSDimitry Andric OutStreamer.emitValue( 5340b57cec5SDimitry Andric MCSymbolRefExpr::create(MCSym.getPointer(), OutStreamer.getContext()), 5350b57cec5SDimitry Andric 4 /*size*/); 5360b57cec5SDimitry Andric } 5370b57cec5SDimitry Andric 5380b57cec5SDimitry Andric 5395ffd83dbSDimitry Andric void ARMAsmPrinter::emitEndOfAsmFile(Module &M) { 5400b57cec5SDimitry Andric const Triple &TT = TM.getTargetTriple(); 5410b57cec5SDimitry Andric if (TT.isOSBinFormatMachO()) { 5420b57cec5SDimitry Andric // All darwin targets use mach-o. 5430b57cec5SDimitry Andric const TargetLoweringObjectFileMachO &TLOFMacho = 5440b57cec5SDimitry Andric static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); 5450b57cec5SDimitry Andric MachineModuleInfoMachO &MMIMacho = 5460b57cec5SDimitry Andric MMI->getObjFileInfo<MachineModuleInfoMachO>(); 5470b57cec5SDimitry Andric 5480b57cec5SDimitry Andric // Output non-lazy-pointers for external and common global variables. 5490b57cec5SDimitry Andric MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList(); 5500b57cec5SDimitry Andric 5510b57cec5SDimitry Andric if (!Stubs.empty()) { 5520b57cec5SDimitry Andric // Switch with ".non_lazy_symbol_pointer" directive. 55381ad6265SDimitry Andric OutStreamer->switchSection(TLOFMacho.getNonLazySymbolPointerSection()); 5545ffd83dbSDimitry Andric emitAlignment(Align(4)); 5550b57cec5SDimitry Andric 5560b57cec5SDimitry Andric for (auto &Stub : Stubs) 5570b57cec5SDimitry Andric emitNonLazySymbolPointer(*OutStreamer, Stub.first, Stub.second); 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric Stubs.clear(); 56081ad6265SDimitry Andric OutStreamer->addBlankLine(); 5610b57cec5SDimitry Andric } 5620b57cec5SDimitry Andric 5630b57cec5SDimitry Andric Stubs = MMIMacho.GetThreadLocalGVStubList(); 5640b57cec5SDimitry Andric if (!Stubs.empty()) { 5650b57cec5SDimitry Andric // Switch with ".non_lazy_symbol_pointer" directive. 56681ad6265SDimitry Andric OutStreamer->switchSection(TLOFMacho.getThreadLocalPointerSection()); 5675ffd83dbSDimitry Andric emitAlignment(Align(4)); 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric for (auto &Stub : Stubs) 5700b57cec5SDimitry Andric emitNonLazySymbolPointer(*OutStreamer, Stub.first, Stub.second); 5710b57cec5SDimitry Andric 5720b57cec5SDimitry Andric Stubs.clear(); 57381ad6265SDimitry Andric OutStreamer->addBlankLine(); 5740b57cec5SDimitry Andric } 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric // Funny Darwin hack: This flag tells the linker that no global symbols 5770b57cec5SDimitry Andric // contain code that falls through to other global symbols (e.g. the obvious 5780b57cec5SDimitry Andric // implementation of multiple entry points). If this doesn't occur, the 5790b57cec5SDimitry Andric // linker can safely perform dead code stripping. Since LLVM never 5800b57cec5SDimitry Andric // generates code that does this, it is always safe to set. 5815ffd83dbSDimitry Andric OutStreamer->emitAssemblerFlag(MCAF_SubsectionsViaSymbols); 5820b57cec5SDimitry Andric } 5830b57cec5SDimitry Andric 5840b57cec5SDimitry Andric // The last attribute to be emitted is ABI_optimization_goals 5850b57cec5SDimitry Andric MCTargetStreamer &TS = *OutStreamer->getTargetStreamer(); 5860b57cec5SDimitry Andric ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS); 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric if (OptimizationGoals > 0 && 5890b57cec5SDimitry Andric (Subtarget->isTargetAEABI() || Subtarget->isTargetGNUAEABI() || 5900b57cec5SDimitry Andric Subtarget->isTargetMuslAEABI())) 5910b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_optimization_goals, OptimizationGoals); 5920b57cec5SDimitry Andric OptimizationGoals = -1; 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric ATS.finishAttributeSection(); 5950b57cec5SDimitry Andric } 5960b57cec5SDimitry Andric 5970b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 5985ffd83dbSDimitry Andric // Helper routines for emitStartOfAsmFile() and emitEndOfAsmFile() 5990b57cec5SDimitry Andric // FIXME: 6000b57cec5SDimitry Andric // The following seem like one-off assembler flags, but they actually need 6010b57cec5SDimitry Andric // to appear in the .ARM.attributes section in ELF. 6020b57cec5SDimitry Andric // Instead of subclassing the MCELFStreamer, we do the work here. 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric // Returns true if all functions have the same function attribute value. 6050b57cec5SDimitry Andric // It also returns true when the module has no functions. 6060b57cec5SDimitry Andric static bool checkFunctionsAttributeConsistency(const Module &M, StringRef Attr, 6070b57cec5SDimitry Andric StringRef Value) { 6080b57cec5SDimitry Andric return !any_of(M, [&](const Function &F) { 6090b57cec5SDimitry Andric return F.getFnAttribute(Attr).getValueAsString() != Value; 6100b57cec5SDimitry Andric }); 6110b57cec5SDimitry Andric } 6125ffd83dbSDimitry Andric // Returns true if all functions have the same denormal mode. 6135ffd83dbSDimitry Andric // It also returns true when the module has no functions. 6145ffd83dbSDimitry Andric static bool checkDenormalAttributeConsistency(const Module &M, 6155ffd83dbSDimitry Andric StringRef Attr, 6165ffd83dbSDimitry Andric DenormalMode Value) { 6175ffd83dbSDimitry Andric return !any_of(M, [&](const Function &F) { 6185ffd83dbSDimitry Andric StringRef AttrVal = F.getFnAttribute(Attr).getValueAsString(); 6195ffd83dbSDimitry Andric return parseDenormalFPAttribute(AttrVal) != Value; 6205ffd83dbSDimitry Andric }); 6215ffd83dbSDimitry Andric } 6220b57cec5SDimitry Andric 6230b57cec5SDimitry Andric void ARMAsmPrinter::emitAttributes() { 6240b57cec5SDimitry Andric MCTargetStreamer &TS = *OutStreamer->getTargetStreamer(); 6250b57cec5SDimitry Andric ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS); 6260b57cec5SDimitry Andric 6270b57cec5SDimitry Andric ATS.emitTextAttribute(ARMBuildAttrs::conformance, "2.09"); 6280b57cec5SDimitry Andric 6290b57cec5SDimitry Andric ATS.switchVendor("aeabi"); 6300b57cec5SDimitry Andric 6310b57cec5SDimitry Andric // Compute ARM ELF Attributes based on the default subtarget that 6320b57cec5SDimitry Andric // we'd have constructed. The existing ARM behavior isn't LTO clean 6330b57cec5SDimitry Andric // anyhow. 6340b57cec5SDimitry Andric // FIXME: For ifunc related functions we could iterate over and look 6350b57cec5SDimitry Andric // for a feature string that doesn't match the default one. 6360b57cec5SDimitry Andric const Triple &TT = TM.getTargetTriple(); 6370b57cec5SDimitry Andric StringRef CPU = TM.getTargetCPU(); 6380b57cec5SDimitry Andric StringRef FS = TM.getTargetFeatureString(); 6390b57cec5SDimitry Andric std::string ArchFS = ARM_MC::ParseARMTriple(TT, CPU); 6400b57cec5SDimitry Andric if (!FS.empty()) { 6410b57cec5SDimitry Andric if (!ArchFS.empty()) 6420b57cec5SDimitry Andric ArchFS = (Twine(ArchFS) + "," + FS).str(); 6430b57cec5SDimitry Andric else 6445ffd83dbSDimitry Andric ArchFS = std::string(FS); 6450b57cec5SDimitry Andric } 6460b57cec5SDimitry Andric const ARMBaseTargetMachine &ATM = 6470b57cec5SDimitry Andric static_cast<const ARMBaseTargetMachine &>(TM); 6485ffd83dbSDimitry Andric const ARMSubtarget STI(TT, std::string(CPU), ArchFS, ATM, 6495ffd83dbSDimitry Andric ATM.isLittleEndian()); 6500b57cec5SDimitry Andric 6510b57cec5SDimitry Andric // Emit build attributes for the available hardware. 6520b57cec5SDimitry Andric ATS.emitTargetAttributes(STI); 6530b57cec5SDimitry Andric 6540b57cec5SDimitry Andric // RW data addressing. 6550b57cec5SDimitry Andric if (isPositionIndependent()) { 6560b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_RW_data, 6570b57cec5SDimitry Andric ARMBuildAttrs::AddressRWPCRel); 6580b57cec5SDimitry Andric } else if (STI.isRWPI()) { 6590b57cec5SDimitry Andric // RWPI specific attributes. 6600b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_RW_data, 6610b57cec5SDimitry Andric ARMBuildAttrs::AddressRWSBRel); 6620b57cec5SDimitry Andric } 6630b57cec5SDimitry Andric 6640b57cec5SDimitry Andric // RO data addressing. 6650b57cec5SDimitry Andric if (isPositionIndependent() || STI.isROPI()) { 6660b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_RO_data, 6670b57cec5SDimitry Andric ARMBuildAttrs::AddressROPCRel); 6680b57cec5SDimitry Andric } 6690b57cec5SDimitry Andric 6700b57cec5SDimitry Andric // GOT use. 6710b57cec5SDimitry Andric if (isPositionIndependent()) { 6720b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_GOT_use, 6730b57cec5SDimitry Andric ARMBuildAttrs::AddressGOT); 6740b57cec5SDimitry Andric } else { 6750b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_GOT_use, 6760b57cec5SDimitry Andric ARMBuildAttrs::AddressDirect); 6770b57cec5SDimitry Andric } 6780b57cec5SDimitry Andric 6790b57cec5SDimitry Andric // Set FP Denormals. 6805ffd83dbSDimitry Andric if (checkDenormalAttributeConsistency(*MMI->getModule(), "denormal-fp-math", 6815ffd83dbSDimitry Andric DenormalMode::getPreserveSign())) 6820b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, 6830b57cec5SDimitry Andric ARMBuildAttrs::PreserveFPSign); 6845ffd83dbSDimitry Andric else if (checkDenormalAttributeConsistency(*MMI->getModule(), 6850b57cec5SDimitry Andric "denormal-fp-math", 6865ffd83dbSDimitry Andric DenormalMode::getPositiveZero())) 6870b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, 6880b57cec5SDimitry Andric ARMBuildAttrs::PositiveZero); 6890b57cec5SDimitry Andric else if (!TM.Options.UnsafeFPMath) 6900b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, 6910b57cec5SDimitry Andric ARMBuildAttrs::IEEEDenormals); 6920b57cec5SDimitry Andric else { 6930b57cec5SDimitry Andric if (!STI.hasVFP2Base()) { 6940b57cec5SDimitry Andric // When the target doesn't have an FPU (by design or 6950b57cec5SDimitry Andric // intention), the assumptions made on the software support 6960b57cec5SDimitry Andric // mirror that of the equivalent hardware support *if it 6970b57cec5SDimitry Andric // existed*. For v7 and better we indicate that denormals are 6980b57cec5SDimitry Andric // flushed preserving sign, and for V6 we indicate that 6990b57cec5SDimitry Andric // denormals are flushed to positive zero. 7000b57cec5SDimitry Andric if (STI.hasV7Ops()) 7010b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, 7020b57cec5SDimitry Andric ARMBuildAttrs::PreserveFPSign); 7030b57cec5SDimitry Andric } else if (STI.hasVFP3Base()) { 7040b57cec5SDimitry Andric // In VFPv4, VFPv4U, VFPv3, or VFPv3U, it is preserved. That is, 7050b57cec5SDimitry Andric // the sign bit of the zero matches the sign bit of the input or 7060b57cec5SDimitry Andric // result that is being flushed to zero. 7070b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, 7080b57cec5SDimitry Andric ARMBuildAttrs::PreserveFPSign); 7090b57cec5SDimitry Andric } 7100b57cec5SDimitry Andric // For VFPv2 implementations it is implementation defined as 7110b57cec5SDimitry Andric // to whether denormals are flushed to positive zero or to 7120b57cec5SDimitry Andric // whatever the sign of zero is (ARM v7AR ARM 2.7.5). Historically 7130b57cec5SDimitry Andric // LLVM has chosen to flush this to positive zero (most likely for 7140b57cec5SDimitry Andric // GCC compatibility), so that's the chosen value here (the 7150b57cec5SDimitry Andric // absence of its emission implies zero). 7160b57cec5SDimitry Andric } 7170b57cec5SDimitry Andric 7180b57cec5SDimitry Andric // Set FP exceptions and rounding 7190b57cec5SDimitry Andric if (checkFunctionsAttributeConsistency(*MMI->getModule(), 7200b57cec5SDimitry Andric "no-trapping-math", "true") || 7210b57cec5SDimitry Andric TM.Options.NoTrappingFPMath) 7220b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_FP_exceptions, 7230b57cec5SDimitry Andric ARMBuildAttrs::Not_Allowed); 7240b57cec5SDimitry Andric else if (!TM.Options.UnsafeFPMath) { 7250b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_FP_exceptions, ARMBuildAttrs::Allowed); 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andric // If the user has permitted this code to choose the IEEE 754 7280b57cec5SDimitry Andric // rounding at run-time, emit the rounding attribute. 7290b57cec5SDimitry Andric if (TM.Options.HonorSignDependentRoundingFPMathOption) 7300b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_FP_rounding, ARMBuildAttrs::Allowed); 7310b57cec5SDimitry Andric } 7320b57cec5SDimitry Andric 7330b57cec5SDimitry Andric // TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath is the 7340b57cec5SDimitry Andric // equivalent of GCC's -ffinite-math-only flag. 7350b57cec5SDimitry Andric if (TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath) 7360b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model, 7370b57cec5SDimitry Andric ARMBuildAttrs::Allowed); 7380b57cec5SDimitry Andric else 7390b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model, 7400b57cec5SDimitry Andric ARMBuildAttrs::AllowIEEE754); 7410b57cec5SDimitry Andric 7420b57cec5SDimitry Andric // FIXME: add more flags to ARMBuildAttributes.h 7430b57cec5SDimitry Andric // 8-bytes alignment stuff. 7440b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_align_needed, 1); 7450b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_align_preserved, 1); 7460b57cec5SDimitry Andric 7470b57cec5SDimitry Andric // Hard float. Use both S and D registers and conform to AAPCS-VFP. 7480b57cec5SDimitry Andric if (STI.isAAPCS_ABI() && TM.Options.FloatABIType == FloatABI::Hard) 7490b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_VFP_args, ARMBuildAttrs::HardFPAAPCS); 7500b57cec5SDimitry Andric 7510b57cec5SDimitry Andric // FIXME: To support emitting this build attribute as GCC does, the 7520b57cec5SDimitry Andric // -mfp16-format option and associated plumbing must be 7530b57cec5SDimitry Andric // supported. For now the __fp16 type is exposed by default, so this 7540b57cec5SDimitry Andric // attribute should be emitted with value 1. 7550b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_FP_16bit_format, 7560b57cec5SDimitry Andric ARMBuildAttrs::FP16FormatIEEE); 7570b57cec5SDimitry Andric 7580b57cec5SDimitry Andric if (const Module *SourceModule = MMI->getModule()) { 7590b57cec5SDimitry Andric // ABI_PCS_wchar_t to indicate wchar_t width 7600b57cec5SDimitry Andric // FIXME: There is no way to emit value 0 (wchar_t prohibited). 7610b57cec5SDimitry Andric if (auto WCharWidthValue = mdconst::extract_or_null<ConstantInt>( 7620b57cec5SDimitry Andric SourceModule->getModuleFlag("wchar_size"))) { 7630b57cec5SDimitry Andric int WCharWidth = WCharWidthValue->getZExtValue(); 7640b57cec5SDimitry Andric assert((WCharWidth == 2 || WCharWidth == 4) && 7650b57cec5SDimitry Andric "wchar_t width must be 2 or 4 bytes"); 7660b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_wchar_t, WCharWidth); 7670b57cec5SDimitry Andric } 7680b57cec5SDimitry Andric 7690b57cec5SDimitry Andric // ABI_enum_size to indicate enum width 7700b57cec5SDimitry Andric // FIXME: There is no way to emit value 0 (enums prohibited) or value 3 7710b57cec5SDimitry Andric // (all enums contain a value needing 32 bits to encode). 7720b57cec5SDimitry Andric if (auto EnumWidthValue = mdconst::extract_or_null<ConstantInt>( 7730b57cec5SDimitry Andric SourceModule->getModuleFlag("min_enum_size"))) { 7740b57cec5SDimitry Andric int EnumWidth = EnumWidthValue->getZExtValue(); 7750b57cec5SDimitry Andric assert((EnumWidth == 1 || EnumWidth == 4) && 7760b57cec5SDimitry Andric "Minimum enum width must be 1 or 4 bytes"); 7770b57cec5SDimitry Andric int EnumBuildAttr = EnumWidth == 1 ? 1 : 2; 7780b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_enum_size, EnumBuildAttr); 7790b57cec5SDimitry Andric } 7804824e7fdSDimitry Andric 7814824e7fdSDimitry Andric auto *PACValue = mdconst::extract_or_null<ConstantInt>( 7824824e7fdSDimitry Andric SourceModule->getModuleFlag("sign-return-address")); 78306c3fb27SDimitry Andric if (PACValue && PACValue->isOne()) { 7844824e7fdSDimitry Andric // If "+pacbti" is used as an architecture extension, 7854824e7fdSDimitry Andric // Tag_PAC_extension is emitted in 7864824e7fdSDimitry Andric // ARMTargetStreamer::emitTargetAttributes(). 7874824e7fdSDimitry Andric if (!STI.hasPACBTI()) { 7884824e7fdSDimitry Andric ATS.emitAttribute(ARMBuildAttrs::PAC_extension, 7894824e7fdSDimitry Andric ARMBuildAttrs::AllowPACInNOPSpace); 7904824e7fdSDimitry Andric } 7914824e7fdSDimitry Andric ATS.emitAttribute(ARMBuildAttrs::PACRET_use, ARMBuildAttrs::PACRETUsed); 7924824e7fdSDimitry Andric } 7934824e7fdSDimitry Andric 7944824e7fdSDimitry Andric auto *BTIValue = mdconst::extract_or_null<ConstantInt>( 7954824e7fdSDimitry Andric SourceModule->getModuleFlag("branch-target-enforcement")); 79606c3fb27SDimitry Andric if (BTIValue && BTIValue->isOne()) { 7974824e7fdSDimitry Andric // If "+pacbti" is used as an architecture extension, 7984824e7fdSDimitry Andric // Tag_BTI_extension is emitted in 7994824e7fdSDimitry Andric // ARMTargetStreamer::emitTargetAttributes(). 8004824e7fdSDimitry Andric if (!STI.hasPACBTI()) { 8014824e7fdSDimitry Andric ATS.emitAttribute(ARMBuildAttrs::BTI_extension, 8024824e7fdSDimitry Andric ARMBuildAttrs::AllowBTIInNOPSpace); 8034824e7fdSDimitry Andric } 8044824e7fdSDimitry Andric ATS.emitAttribute(ARMBuildAttrs::BTI_use, ARMBuildAttrs::BTIUsed); 8054824e7fdSDimitry Andric } 8060b57cec5SDimitry Andric } 8070b57cec5SDimitry Andric 8080b57cec5SDimitry Andric // We currently do not support using R9 as the TLS pointer. 8090b57cec5SDimitry Andric if (STI.isRWPI()) 8100b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use, 8110b57cec5SDimitry Andric ARMBuildAttrs::R9IsSB); 8120b57cec5SDimitry Andric else if (STI.isR9Reserved()) 8130b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use, 8140b57cec5SDimitry Andric ARMBuildAttrs::R9Reserved); 8150b57cec5SDimitry Andric else 8160b57cec5SDimitry Andric ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use, 8170b57cec5SDimitry Andric ARMBuildAttrs::R9IsGPR); 8180b57cec5SDimitry Andric } 8190b57cec5SDimitry Andric 8200b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 8210b57cec5SDimitry Andric 8220b57cec5SDimitry Andric static MCSymbol *getBFLabel(StringRef Prefix, unsigned FunctionNumber, 8230b57cec5SDimitry Andric unsigned LabelId, MCContext &Ctx) { 8240b57cec5SDimitry Andric 8250b57cec5SDimitry Andric MCSymbol *Label = Ctx.getOrCreateSymbol(Twine(Prefix) 8260b57cec5SDimitry Andric + "BF" + Twine(FunctionNumber) + "_" + Twine(LabelId)); 8270b57cec5SDimitry Andric return Label; 8280b57cec5SDimitry Andric } 8290b57cec5SDimitry Andric 8300b57cec5SDimitry Andric static MCSymbol *getPICLabel(StringRef Prefix, unsigned FunctionNumber, 8310b57cec5SDimitry Andric unsigned LabelId, MCContext &Ctx) { 8320b57cec5SDimitry Andric 8330b57cec5SDimitry Andric MCSymbol *Label = Ctx.getOrCreateSymbol(Twine(Prefix) 8340b57cec5SDimitry Andric + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId)); 8350b57cec5SDimitry Andric return Label; 8360b57cec5SDimitry Andric } 8370b57cec5SDimitry Andric 8380b57cec5SDimitry Andric static MCSymbolRefExpr::VariantKind 8390b57cec5SDimitry Andric getModifierVariantKind(ARMCP::ARMCPModifier Modifier) { 8400b57cec5SDimitry Andric switch (Modifier) { 8410b57cec5SDimitry Andric case ARMCP::no_modifier: 8420b57cec5SDimitry Andric return MCSymbolRefExpr::VK_None; 8430b57cec5SDimitry Andric case ARMCP::TLSGD: 8440b57cec5SDimitry Andric return MCSymbolRefExpr::VK_TLSGD; 8450b57cec5SDimitry Andric case ARMCP::TPOFF: 8460b57cec5SDimitry Andric return MCSymbolRefExpr::VK_TPOFF; 8470b57cec5SDimitry Andric case ARMCP::GOTTPOFF: 8480b57cec5SDimitry Andric return MCSymbolRefExpr::VK_GOTTPOFF; 8490b57cec5SDimitry Andric case ARMCP::SBREL: 8500b57cec5SDimitry Andric return MCSymbolRefExpr::VK_ARM_SBREL; 8510b57cec5SDimitry Andric case ARMCP::GOT_PREL: 8520b57cec5SDimitry Andric return MCSymbolRefExpr::VK_ARM_GOT_PREL; 8530b57cec5SDimitry Andric case ARMCP::SECREL: 8540b57cec5SDimitry Andric return MCSymbolRefExpr::VK_SECREL; 8550b57cec5SDimitry Andric } 8560b57cec5SDimitry Andric llvm_unreachable("Invalid ARMCPModifier!"); 8570b57cec5SDimitry Andric } 8580b57cec5SDimitry Andric 8590b57cec5SDimitry Andric MCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV, 8600b57cec5SDimitry Andric unsigned char TargetFlags) { 8610b57cec5SDimitry Andric if (Subtarget->isTargetMachO()) { 8620b57cec5SDimitry Andric bool IsIndirect = 8630b57cec5SDimitry Andric (TargetFlags & ARMII::MO_NONLAZY) && Subtarget->isGVIndirectSymbol(GV); 8640b57cec5SDimitry Andric 8650b57cec5SDimitry Andric if (!IsIndirect) 8660b57cec5SDimitry Andric return getSymbol(GV); 8670b57cec5SDimitry Andric 8680b57cec5SDimitry Andric // FIXME: Remove this when Darwin transition to @GOT like syntax. 8690b57cec5SDimitry Andric MCSymbol *MCSym = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr"); 8700b57cec5SDimitry Andric MachineModuleInfoMachO &MMIMachO = 8710b57cec5SDimitry Andric MMI->getObjFileInfo<MachineModuleInfoMachO>(); 8720b57cec5SDimitry Andric MachineModuleInfoImpl::StubValueTy &StubSym = 8730b57cec5SDimitry Andric GV->isThreadLocal() ? MMIMachO.getThreadLocalGVStubEntry(MCSym) 8740b57cec5SDimitry Andric : MMIMachO.getGVStubEntry(MCSym); 8750b57cec5SDimitry Andric 8760b57cec5SDimitry Andric if (!StubSym.getPointer()) 8770b57cec5SDimitry Andric StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(GV), 8780b57cec5SDimitry Andric !GV->hasInternalLinkage()); 8790b57cec5SDimitry Andric return MCSym; 8800b57cec5SDimitry Andric } else if (Subtarget->isTargetCOFF()) { 8810b57cec5SDimitry Andric assert(Subtarget->isTargetWindows() && 8820b57cec5SDimitry Andric "Windows is the only supported COFF target"); 8830b57cec5SDimitry Andric 8840b57cec5SDimitry Andric bool IsIndirect = 8850b57cec5SDimitry Andric (TargetFlags & (ARMII::MO_DLLIMPORT | ARMII::MO_COFFSTUB)); 8860b57cec5SDimitry Andric if (!IsIndirect) 8870b57cec5SDimitry Andric return getSymbol(GV); 8880b57cec5SDimitry Andric 8890b57cec5SDimitry Andric SmallString<128> Name; 8900b57cec5SDimitry Andric if (TargetFlags & ARMII::MO_DLLIMPORT) 8910b57cec5SDimitry Andric Name = "__imp_"; 8920b57cec5SDimitry Andric else if (TargetFlags & ARMII::MO_COFFSTUB) 8930b57cec5SDimitry Andric Name = ".refptr."; 8940b57cec5SDimitry Andric getNameWithPrefix(Name, GV); 8950b57cec5SDimitry Andric 8960b57cec5SDimitry Andric MCSymbol *MCSym = OutContext.getOrCreateSymbol(Name); 8970b57cec5SDimitry Andric 8980b57cec5SDimitry Andric if (TargetFlags & ARMII::MO_COFFSTUB) { 8990b57cec5SDimitry Andric MachineModuleInfoCOFF &MMICOFF = 9000b57cec5SDimitry Andric MMI->getObjFileInfo<MachineModuleInfoCOFF>(); 9010b57cec5SDimitry Andric MachineModuleInfoImpl::StubValueTy &StubSym = 9020b57cec5SDimitry Andric MMICOFF.getGVStubEntry(MCSym); 9030b57cec5SDimitry Andric 9040b57cec5SDimitry Andric if (!StubSym.getPointer()) 9050b57cec5SDimitry Andric StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(GV), true); 9060b57cec5SDimitry Andric } 9070b57cec5SDimitry Andric 9080b57cec5SDimitry Andric return MCSym; 9090b57cec5SDimitry Andric } else if (Subtarget->isTargetELF()) { 910bdd1243dSDimitry Andric return getSymbolPreferLocal(*GV); 9110b57cec5SDimitry Andric } 9120b57cec5SDimitry Andric llvm_unreachable("unexpected target"); 9130b57cec5SDimitry Andric } 9140b57cec5SDimitry Andric 9155ffd83dbSDimitry Andric void ARMAsmPrinter::emitMachineConstantPoolValue( 9165ffd83dbSDimitry Andric MachineConstantPoolValue *MCPV) { 9170b57cec5SDimitry Andric const DataLayout &DL = getDataLayout(); 9180b57cec5SDimitry Andric int Size = DL.getTypeAllocSize(MCPV->getType()); 9190b57cec5SDimitry Andric 9200b57cec5SDimitry Andric ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV); 9210b57cec5SDimitry Andric 9220b57cec5SDimitry Andric if (ACPV->isPromotedGlobal()) { 9230b57cec5SDimitry Andric // This constant pool entry is actually a global whose storage has been 9240b57cec5SDimitry Andric // promoted into the constant pool. This global may be referenced still 9250b57cec5SDimitry Andric // by debug information, and due to the way AsmPrinter is set up, the debug 9260b57cec5SDimitry Andric // info is immutable by the time we decide to promote globals to constant 9270b57cec5SDimitry Andric // pools. Because of this, we need to ensure we emit a symbol for the global 9280b57cec5SDimitry Andric // with private linkage (the default) so debug info can refer to it. 9290b57cec5SDimitry Andric // 9300b57cec5SDimitry Andric // However, if this global is promoted into several functions we must ensure 9310b57cec5SDimitry Andric // we don't try and emit duplicate symbols! 9320b57cec5SDimitry Andric auto *ACPC = cast<ARMConstantPoolConstant>(ACPV); 9330b57cec5SDimitry Andric for (const auto *GV : ACPC->promotedGlobals()) { 9340b57cec5SDimitry Andric if (!EmittedPromotedGlobalLabels.count(GV)) { 9350b57cec5SDimitry Andric MCSymbol *GVSym = getSymbol(GV); 9365ffd83dbSDimitry Andric OutStreamer->emitLabel(GVSym); 9370b57cec5SDimitry Andric EmittedPromotedGlobalLabels.insert(GV); 9380b57cec5SDimitry Andric } 9390b57cec5SDimitry Andric } 9405ffd83dbSDimitry Andric return emitGlobalConstant(DL, ACPC->getPromotedGlobalInit()); 9410b57cec5SDimitry Andric } 9420b57cec5SDimitry Andric 9430b57cec5SDimitry Andric MCSymbol *MCSym; 9440b57cec5SDimitry Andric if (ACPV->isLSDA()) { 945e8d8bef9SDimitry Andric MCSym = getMBBExceptionSym(MF->front()); 9460b57cec5SDimitry Andric } else if (ACPV->isBlockAddress()) { 9470b57cec5SDimitry Andric const BlockAddress *BA = 9480b57cec5SDimitry Andric cast<ARMConstantPoolConstant>(ACPV)->getBlockAddress(); 9490b57cec5SDimitry Andric MCSym = GetBlockAddressSymbol(BA); 9500b57cec5SDimitry Andric } else if (ACPV->isGlobalValue()) { 9510b57cec5SDimitry Andric const GlobalValue *GV = cast<ARMConstantPoolConstant>(ACPV)->getGV(); 9520b57cec5SDimitry Andric 9530b57cec5SDimitry Andric // On Darwin, const-pool entries may get the "FOO$non_lazy_ptr" mangling, so 9540b57cec5SDimitry Andric // flag the global as MO_NONLAZY. 9550b57cec5SDimitry Andric unsigned char TF = Subtarget->isTargetMachO() ? ARMII::MO_NONLAZY : 0; 9560b57cec5SDimitry Andric MCSym = GetARMGVSymbol(GV, TF); 9570b57cec5SDimitry Andric } else if (ACPV->isMachineBasicBlock()) { 9580b57cec5SDimitry Andric const MachineBasicBlock *MBB = cast<ARMConstantPoolMBB>(ACPV)->getMBB(); 9590b57cec5SDimitry Andric MCSym = MBB->getSymbol(); 9600b57cec5SDimitry Andric } else { 9610b57cec5SDimitry Andric assert(ACPV->isExtSymbol() && "unrecognized constant pool value"); 9620b57cec5SDimitry Andric auto Sym = cast<ARMConstantPoolSymbol>(ACPV)->getSymbol(); 9630b57cec5SDimitry Andric MCSym = GetExternalSymbolSymbol(Sym); 9640b57cec5SDimitry Andric } 9650b57cec5SDimitry Andric 9660b57cec5SDimitry Andric // Create an MCSymbol for the reference. 9670b57cec5SDimitry Andric const MCExpr *Expr = 9680b57cec5SDimitry Andric MCSymbolRefExpr::create(MCSym, getModifierVariantKind(ACPV->getModifier()), 9690b57cec5SDimitry Andric OutContext); 9700b57cec5SDimitry Andric 9710b57cec5SDimitry Andric if (ACPV->getPCAdjustment()) { 9720b57cec5SDimitry Andric MCSymbol *PCLabel = 9730b57cec5SDimitry Andric getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(), 9740b57cec5SDimitry Andric ACPV->getLabelId(), OutContext); 9750b57cec5SDimitry Andric const MCExpr *PCRelExpr = MCSymbolRefExpr::create(PCLabel, OutContext); 9760b57cec5SDimitry Andric PCRelExpr = 9770b57cec5SDimitry Andric MCBinaryExpr::createAdd(PCRelExpr, 9780b57cec5SDimitry Andric MCConstantExpr::create(ACPV->getPCAdjustment(), 9790b57cec5SDimitry Andric OutContext), 9800b57cec5SDimitry Andric OutContext); 9810b57cec5SDimitry Andric if (ACPV->mustAddCurrentAddress()) { 9820b57cec5SDimitry Andric // We want "(<expr> - .)", but MC doesn't have a concept of the '.' 9830b57cec5SDimitry Andric // label, so just emit a local label end reference that instead. 9840b57cec5SDimitry Andric MCSymbol *DotSym = OutContext.createTempSymbol(); 9855ffd83dbSDimitry Andric OutStreamer->emitLabel(DotSym); 9860b57cec5SDimitry Andric const MCExpr *DotExpr = MCSymbolRefExpr::create(DotSym, OutContext); 9870b57cec5SDimitry Andric PCRelExpr = MCBinaryExpr::createSub(PCRelExpr, DotExpr, OutContext); 9880b57cec5SDimitry Andric } 9890b57cec5SDimitry Andric Expr = MCBinaryExpr::createSub(Expr, PCRelExpr, OutContext); 9900b57cec5SDimitry Andric } 9915ffd83dbSDimitry Andric OutStreamer->emitValue(Expr, Size); 9920b57cec5SDimitry Andric } 9930b57cec5SDimitry Andric 9945ffd83dbSDimitry Andric void ARMAsmPrinter::emitJumpTableAddrs(const MachineInstr *MI) { 9950b57cec5SDimitry Andric const MachineOperand &MO1 = MI->getOperand(1); 9960b57cec5SDimitry Andric unsigned JTI = MO1.getIndex(); 9970b57cec5SDimitry Andric 9980b57cec5SDimitry Andric // Make sure the Thumb jump table is 4-byte aligned. This will be a nop for 9990b57cec5SDimitry Andric // ARM mode tables. 10005ffd83dbSDimitry Andric emitAlignment(Align(4)); 10010b57cec5SDimitry Andric 10020b57cec5SDimitry Andric // Emit a label for the jump table. 10030b57cec5SDimitry Andric MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI); 10045ffd83dbSDimitry Andric OutStreamer->emitLabel(JTISymbol); 10050b57cec5SDimitry Andric 10060b57cec5SDimitry Andric // Mark the jump table as data-in-code. 10075ffd83dbSDimitry Andric OutStreamer->emitDataRegion(MCDR_DataRegionJT32); 10080b57cec5SDimitry Andric 10090b57cec5SDimitry Andric // Emit each entry of the table. 10100b57cec5SDimitry Andric const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); 10110b57cec5SDimitry Andric const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 10120b57cec5SDimitry Andric const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; 10130b57cec5SDimitry Andric 10140b57cec5SDimitry Andric for (MachineBasicBlock *MBB : JTBBs) { 10150b57cec5SDimitry Andric // Construct an MCExpr for the entry. We want a value of the form: 10160b57cec5SDimitry Andric // (BasicBlockAddr - TableBeginAddr) 10170b57cec5SDimitry Andric // 10180b57cec5SDimitry Andric // For example, a table with entries jumping to basic blocks BB0 and BB1 10190b57cec5SDimitry Andric // would look like: 10200b57cec5SDimitry Andric // LJTI_0_0: 10210b57cec5SDimitry Andric // .word (LBB0 - LJTI_0_0) 10220b57cec5SDimitry Andric // .word (LBB1 - LJTI_0_0) 10230b57cec5SDimitry Andric const MCExpr *Expr = MCSymbolRefExpr::create(MBB->getSymbol(), OutContext); 10240b57cec5SDimitry Andric 10250b57cec5SDimitry Andric if (isPositionIndependent() || Subtarget->isROPI()) 10260b57cec5SDimitry Andric Expr = MCBinaryExpr::createSub(Expr, MCSymbolRefExpr::create(JTISymbol, 10270b57cec5SDimitry Andric OutContext), 10280b57cec5SDimitry Andric OutContext); 10290b57cec5SDimitry Andric // If we're generating a table of Thumb addresses in static relocation 10300b57cec5SDimitry Andric // model, we need to add one to keep interworking correctly. 10310b57cec5SDimitry Andric else if (AFI->isThumbFunction()) 10320b57cec5SDimitry Andric Expr = MCBinaryExpr::createAdd(Expr, MCConstantExpr::create(1,OutContext), 10330b57cec5SDimitry Andric OutContext); 10345ffd83dbSDimitry Andric OutStreamer->emitValue(Expr, 4); 10350b57cec5SDimitry Andric } 10360b57cec5SDimitry Andric // Mark the end of jump table data-in-code region. 10375ffd83dbSDimitry Andric OutStreamer->emitDataRegion(MCDR_DataRegionEnd); 10380b57cec5SDimitry Andric } 10390b57cec5SDimitry Andric 10405ffd83dbSDimitry Andric void ARMAsmPrinter::emitJumpTableInsts(const MachineInstr *MI) { 10410b57cec5SDimitry Andric const MachineOperand &MO1 = MI->getOperand(1); 10420b57cec5SDimitry Andric unsigned JTI = MO1.getIndex(); 10430b57cec5SDimitry Andric 10440b57cec5SDimitry Andric // Make sure the Thumb jump table is 4-byte aligned. This will be a nop for 10450b57cec5SDimitry Andric // ARM mode tables. 10465ffd83dbSDimitry Andric emitAlignment(Align(4)); 10470b57cec5SDimitry Andric 10480b57cec5SDimitry Andric // Emit a label for the jump table. 10490b57cec5SDimitry Andric MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI); 10505ffd83dbSDimitry Andric OutStreamer->emitLabel(JTISymbol); 10510b57cec5SDimitry Andric 10520b57cec5SDimitry Andric // Emit each entry of the table. 10530b57cec5SDimitry Andric const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); 10540b57cec5SDimitry Andric const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 10550b57cec5SDimitry Andric const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; 10560b57cec5SDimitry Andric 10570b57cec5SDimitry Andric for (MachineBasicBlock *MBB : JTBBs) { 10580b57cec5SDimitry Andric const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::create(MBB->getSymbol(), 10590b57cec5SDimitry Andric OutContext); 10600b57cec5SDimitry Andric // If this isn't a TBB or TBH, the entries are direct branch instructions. 10610b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2B) 10620b57cec5SDimitry Andric .addExpr(MBBSymbolExpr) 10630b57cec5SDimitry Andric .addImm(ARMCC::AL) 10640b57cec5SDimitry Andric .addReg(0)); 10650b57cec5SDimitry Andric } 10660b57cec5SDimitry Andric } 10670b57cec5SDimitry Andric 10685ffd83dbSDimitry Andric void ARMAsmPrinter::emitJumpTableTBInst(const MachineInstr *MI, 10690b57cec5SDimitry Andric unsigned OffsetWidth) { 10700b57cec5SDimitry Andric assert((OffsetWidth == 1 || OffsetWidth == 2) && "invalid tbb/tbh width"); 10710b57cec5SDimitry Andric const MachineOperand &MO1 = MI->getOperand(1); 10720b57cec5SDimitry Andric unsigned JTI = MO1.getIndex(); 10730b57cec5SDimitry Andric 10740b57cec5SDimitry Andric if (Subtarget->isThumb1Only()) 10755ffd83dbSDimitry Andric emitAlignment(Align(4)); 10760b57cec5SDimitry Andric 10770b57cec5SDimitry Andric MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel(JTI); 10785ffd83dbSDimitry Andric OutStreamer->emitLabel(JTISymbol); 10790b57cec5SDimitry Andric 10800b57cec5SDimitry Andric // Emit each entry of the table. 10810b57cec5SDimitry Andric const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo(); 10820b57cec5SDimitry Andric const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables(); 10830b57cec5SDimitry Andric const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs; 10840b57cec5SDimitry Andric 10850b57cec5SDimitry Andric // Mark the jump table as data-in-code. 10865ffd83dbSDimitry Andric OutStreamer->emitDataRegion(OffsetWidth == 1 ? MCDR_DataRegionJT8 10870b57cec5SDimitry Andric : MCDR_DataRegionJT16); 10880b57cec5SDimitry Andric 1089bdd1243dSDimitry Andric for (auto *MBB : JTBBs) { 10900b57cec5SDimitry Andric const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::create(MBB->getSymbol(), 10910b57cec5SDimitry Andric OutContext); 10920b57cec5SDimitry Andric // Otherwise it's an offset from the dispatch instruction. Construct an 10930b57cec5SDimitry Andric // MCExpr for the entry. We want a value of the form: 10940b57cec5SDimitry Andric // (BasicBlockAddr - TBBInstAddr + 4) / 2 10950b57cec5SDimitry Andric // 10960b57cec5SDimitry Andric // For example, a TBB table with entries jumping to basic blocks BB0 and BB1 10970b57cec5SDimitry Andric // would look like: 10980b57cec5SDimitry Andric // LJTI_0_0: 10990b57cec5SDimitry Andric // .byte (LBB0 - (LCPI0_0 + 4)) / 2 11000b57cec5SDimitry Andric // .byte (LBB1 - (LCPI0_0 + 4)) / 2 11010b57cec5SDimitry Andric // where LCPI0_0 is a label defined just before the TBB instruction using 11020b57cec5SDimitry Andric // this table. 11030b57cec5SDimitry Andric MCSymbol *TBInstPC = GetCPISymbol(MI->getOperand(0).getImm()); 11040b57cec5SDimitry Andric const MCExpr *Expr = MCBinaryExpr::createAdd( 11050b57cec5SDimitry Andric MCSymbolRefExpr::create(TBInstPC, OutContext), 11060b57cec5SDimitry Andric MCConstantExpr::create(4, OutContext), OutContext); 11070b57cec5SDimitry Andric Expr = MCBinaryExpr::createSub(MBBSymbolExpr, Expr, OutContext); 11080b57cec5SDimitry Andric Expr = MCBinaryExpr::createDiv(Expr, MCConstantExpr::create(2, OutContext), 11090b57cec5SDimitry Andric OutContext); 11105ffd83dbSDimitry Andric OutStreamer->emitValue(Expr, OffsetWidth); 11110b57cec5SDimitry Andric } 11120b57cec5SDimitry Andric // Mark the end of jump table data-in-code region. 32-bit offsets use 11130b57cec5SDimitry Andric // actual branch instructions here, so we don't mark those as a data-region 11140b57cec5SDimitry Andric // at all. 11155ffd83dbSDimitry Andric OutStreamer->emitDataRegion(MCDR_DataRegionEnd); 11160b57cec5SDimitry Andric 11170b57cec5SDimitry Andric // Make sure the next instruction is 2-byte aligned. 11185ffd83dbSDimitry Andric emitAlignment(Align(2)); 11190b57cec5SDimitry Andric } 11200b57cec5SDimitry Andric 11215f757f3fSDimitry Andric std::tuple<const MCSymbol *, uint64_t, const MCSymbol *, 11225f757f3fSDimitry Andric codeview::JumpTableEntrySize> 11235f757f3fSDimitry Andric ARMAsmPrinter::getCodeViewJumpTableInfo(int JTI, 11245f757f3fSDimitry Andric const MachineInstr *BranchInstr, 11255f757f3fSDimitry Andric const MCSymbol *BranchLabel) const { 11265f757f3fSDimitry Andric codeview::JumpTableEntrySize EntrySize; 11275f757f3fSDimitry Andric const MCSymbol *BaseLabel; 11285f757f3fSDimitry Andric uint64_t BaseOffset = 0; 11295f757f3fSDimitry Andric switch (BranchInstr->getOpcode()) { 11305f757f3fSDimitry Andric case ARM::BR_JTadd: 11315f757f3fSDimitry Andric case ARM::BR_JTr: 11325f757f3fSDimitry Andric case ARM::tBR_JTr: 11335f757f3fSDimitry Andric // Word relative to the jump table address. 11345f757f3fSDimitry Andric EntrySize = codeview::JumpTableEntrySize::UInt32; 11355f757f3fSDimitry Andric BaseLabel = GetARMJTIPICJumpTableLabel(JTI); 11365f757f3fSDimitry Andric break; 11375f757f3fSDimitry Andric case ARM::tTBH_JT: 11385f757f3fSDimitry Andric case ARM::t2TBH_JT: 11395f757f3fSDimitry Andric // half-word shifted left, relative to *after* the branch instruction. 11405f757f3fSDimitry Andric EntrySize = codeview::JumpTableEntrySize::UInt16ShiftLeft; 11415f757f3fSDimitry Andric BranchLabel = GetCPISymbol(BranchInstr->getOperand(3).getImm()); 11425f757f3fSDimitry Andric BaseLabel = BranchLabel; 11435f757f3fSDimitry Andric BaseOffset = 4; 11445f757f3fSDimitry Andric break; 11455f757f3fSDimitry Andric case ARM::tTBB_JT: 11465f757f3fSDimitry Andric case ARM::t2TBB_JT: 11475f757f3fSDimitry Andric // byte shifted left, relative to *after* the branch instruction. 11485f757f3fSDimitry Andric EntrySize = codeview::JumpTableEntrySize::UInt8ShiftLeft; 11495f757f3fSDimitry Andric BranchLabel = GetCPISymbol(BranchInstr->getOperand(3).getImm()); 11505f757f3fSDimitry Andric BaseLabel = BranchLabel; 11515f757f3fSDimitry Andric BaseOffset = 4; 11525f757f3fSDimitry Andric break; 11535f757f3fSDimitry Andric case ARM::t2BR_JT: 11545f757f3fSDimitry Andric // Direct jump. 11555f757f3fSDimitry Andric BaseLabel = nullptr; 11565f757f3fSDimitry Andric EntrySize = codeview::JumpTableEntrySize::Pointer; 11575f757f3fSDimitry Andric break; 11585f757f3fSDimitry Andric default: 11595f757f3fSDimitry Andric llvm_unreachable("Unknown jump table instruction"); 11605f757f3fSDimitry Andric } 11615f757f3fSDimitry Andric 11625f757f3fSDimitry Andric return std::make_tuple(BaseLabel, BaseOffset, BranchLabel, EntrySize); 11635f757f3fSDimitry Andric } 11645f757f3fSDimitry Andric 11650b57cec5SDimitry Andric void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) { 11660b57cec5SDimitry Andric assert(MI->getFlag(MachineInstr::FrameSetup) && 11670b57cec5SDimitry Andric "Only instruction which are involved into frame setup code are allowed"); 11680b57cec5SDimitry Andric 11690b57cec5SDimitry Andric MCTargetStreamer &TS = *OutStreamer->getTargetStreamer(); 11700b57cec5SDimitry Andric ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS); 11710b57cec5SDimitry Andric const MachineFunction &MF = *MI->getParent()->getParent(); 11720b57cec5SDimitry Andric const TargetRegisterInfo *TargetRegInfo = 11730b57cec5SDimitry Andric MF.getSubtarget().getRegisterInfo(); 11740b57cec5SDimitry Andric const MachineRegisterInfo &MachineRegInfo = MF.getRegInfo(); 11750b57cec5SDimitry Andric 11768bcb0991SDimitry Andric Register FramePtr = TargetRegInfo->getFrameRegister(MF); 11770b57cec5SDimitry Andric unsigned Opc = MI->getOpcode(); 11780b57cec5SDimitry Andric unsigned SrcReg, DstReg; 11790b57cec5SDimitry Andric 11805ffd83dbSDimitry Andric switch (Opc) { 11815ffd83dbSDimitry Andric case ARM::tPUSH: 11825ffd83dbSDimitry Andric // special case: tPUSH does not have src/dst regs. 11830b57cec5SDimitry Andric SrcReg = DstReg = ARM::SP; 11845ffd83dbSDimitry Andric break; 11855ffd83dbSDimitry Andric case ARM::tLDRpci: 11865ffd83dbSDimitry Andric case ARM::t2MOVi16: 11875ffd83dbSDimitry Andric case ARM::t2MOVTi16: 118806c3fb27SDimitry Andric case ARM::tMOVi8: 118906c3fb27SDimitry Andric case ARM::tADDi8: 119006c3fb27SDimitry Andric case ARM::tLSLri: 11915ffd83dbSDimitry Andric // special cases: 11925ffd83dbSDimitry Andric // 1) for Thumb1 code we sometimes materialize the constant via constpool 11935ffd83dbSDimitry Andric // load. 119406c3fb27SDimitry Andric // 2) for Thumb1 execute only code we materialize the constant via the 119506c3fb27SDimitry Andric // following pattern: 119606c3fb27SDimitry Andric // movs r3, #:upper8_15:<const> 119706c3fb27SDimitry Andric // lsls r3, #8 119806c3fb27SDimitry Andric // adds r3, #:upper0_7:<const> 119906c3fb27SDimitry Andric // lsls r3, #8 120006c3fb27SDimitry Andric // adds r3, #:lower8_15:<const> 120106c3fb27SDimitry Andric // lsls r3, #8 120206c3fb27SDimitry Andric // adds r3, #:lower0_7:<const> 120306c3fb27SDimitry Andric // So we need to special-case MOVS, ADDS and LSLS, and keep track of 120406c3fb27SDimitry Andric // where we are in the sequence with the simplest of state machines. 120506c3fb27SDimitry Andric // 3) for Thumb2 execute only code we materialize the constant via 12065ffd83dbSDimitry Andric // immediate constants in 2 separate instructions (MOVW/MOVT). 12075ffd83dbSDimitry Andric SrcReg = ~0U; 12085ffd83dbSDimitry Andric DstReg = MI->getOperand(0).getReg(); 12095ffd83dbSDimitry Andric break; 12105ffd83dbSDimitry Andric default: 12110b57cec5SDimitry Andric SrcReg = MI->getOperand(1).getReg(); 12120b57cec5SDimitry Andric DstReg = MI->getOperand(0).getReg(); 12135ffd83dbSDimitry Andric break; 12140b57cec5SDimitry Andric } 12150b57cec5SDimitry Andric 12160b57cec5SDimitry Andric // Try to figure out the unwinding opcode out of src / dst regs. 12170b57cec5SDimitry Andric if (MI->mayStore()) { 12180b57cec5SDimitry Andric // Register saves. 12190b57cec5SDimitry Andric assert(DstReg == ARM::SP && 12200b57cec5SDimitry Andric "Only stack pointer as a destination reg is supported"); 12210b57cec5SDimitry Andric 12220b57cec5SDimitry Andric SmallVector<unsigned, 4> RegList; 12230b57cec5SDimitry Andric // Skip src & dst reg, and pred ops. 12240b57cec5SDimitry Andric unsigned StartOp = 2 + 2; 12250b57cec5SDimitry Andric // Use all the operands. 12260b57cec5SDimitry Andric unsigned NumOffset = 0; 12270eae32dcSDimitry Andric // Amount of SP adjustment folded into a push, before the 12280eae32dcSDimitry Andric // registers are stored (pad at higher addresses). 12290eae32dcSDimitry Andric unsigned PadBefore = 0; 12300eae32dcSDimitry Andric // Amount of SP adjustment folded into a push, after the 12310eae32dcSDimitry Andric // registers are stored (pad at lower addresses). 12320eae32dcSDimitry Andric unsigned PadAfter = 0; 12330b57cec5SDimitry Andric 12340b57cec5SDimitry Andric switch (Opc) { 12350b57cec5SDimitry Andric default: 12360b57cec5SDimitry Andric MI->print(errs()); 12370b57cec5SDimitry Andric llvm_unreachable("Unsupported opcode for unwinding information"); 12380b57cec5SDimitry Andric case ARM::tPUSH: 12390b57cec5SDimitry Andric // Special case here: no src & dst reg, but two extra imp ops. 12400b57cec5SDimitry Andric StartOp = 2; NumOffset = 2; 1241bdd1243dSDimitry Andric [[fallthrough]]; 12420b57cec5SDimitry Andric case ARM::STMDB_UPD: 12430b57cec5SDimitry Andric case ARM::t2STMDB_UPD: 12440b57cec5SDimitry Andric case ARM::VSTMDDB_UPD: 12450b57cec5SDimitry Andric assert(SrcReg == ARM::SP && 12460b57cec5SDimitry Andric "Only stack pointer as a source reg is supported"); 12470b57cec5SDimitry Andric for (unsigned i = StartOp, NumOps = MI->getNumOperands() - NumOffset; 12480b57cec5SDimitry Andric i != NumOps; ++i) { 12490b57cec5SDimitry Andric const MachineOperand &MO = MI->getOperand(i); 12500b57cec5SDimitry Andric // Actually, there should never be any impdef stuff here. Skip it 12510b57cec5SDimitry Andric // temporary to workaround PR11902. 12520b57cec5SDimitry Andric if (MO.isImplicit()) 12530b57cec5SDimitry Andric continue; 12540b57cec5SDimitry Andric // Registers, pushed as a part of folding an SP update into the 12550b57cec5SDimitry Andric // push instruction are marked as undef and should not be 12560b57cec5SDimitry Andric // restored when unwinding, because the function can modify the 12570b57cec5SDimitry Andric // corresponding stack slots. 12580b57cec5SDimitry Andric if (MO.isUndef()) { 12590b57cec5SDimitry Andric assert(RegList.empty() && 12600b57cec5SDimitry Andric "Pad registers must come before restored ones"); 12610b57cec5SDimitry Andric unsigned Width = 12620b57cec5SDimitry Andric TargetRegInfo->getRegSizeInBits(MO.getReg(), MachineRegInfo) / 8; 12630eae32dcSDimitry Andric PadAfter += Width; 12640b57cec5SDimitry Andric continue; 12650b57cec5SDimitry Andric } 12660b57cec5SDimitry Andric // Check for registers that are remapped (for a Thumb1 prologue that 12670b57cec5SDimitry Andric // saves high registers). 12688bcb0991SDimitry Andric Register Reg = MO.getReg(); 12690b57cec5SDimitry Andric if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(Reg)) 12700b57cec5SDimitry Andric Reg = RemappedReg; 12710b57cec5SDimitry Andric RegList.push_back(Reg); 12720b57cec5SDimitry Andric } 12730b57cec5SDimitry Andric break; 12740b57cec5SDimitry Andric case ARM::STR_PRE_IMM: 12750b57cec5SDimitry Andric case ARM::STR_PRE_REG: 12760b57cec5SDimitry Andric case ARM::t2STR_PRE: 12770b57cec5SDimitry Andric assert(MI->getOperand(2).getReg() == ARM::SP && 12780b57cec5SDimitry Andric "Only stack pointer as a source reg is supported"); 12790eae32dcSDimitry Andric if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(SrcReg)) 12800eae32dcSDimitry Andric SrcReg = RemappedReg; 12810eae32dcSDimitry Andric 12820b57cec5SDimitry Andric RegList.push_back(SrcReg); 12830b57cec5SDimitry Andric break; 12840eae32dcSDimitry Andric case ARM::t2STRD_PRE: 12850eae32dcSDimitry Andric assert(MI->getOperand(3).getReg() == ARM::SP && 12860eae32dcSDimitry Andric "Only stack pointer as a source reg is supported"); 12870eae32dcSDimitry Andric SrcReg = MI->getOperand(1).getReg(); 12880eae32dcSDimitry Andric if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(SrcReg)) 12890eae32dcSDimitry Andric SrcReg = RemappedReg; 12900eae32dcSDimitry Andric RegList.push_back(SrcReg); 12910eae32dcSDimitry Andric SrcReg = MI->getOperand(2).getReg(); 12920eae32dcSDimitry Andric if (unsigned RemappedReg = AFI->EHPrologueRemappedRegs.lookup(SrcReg)) 12930eae32dcSDimitry Andric SrcReg = RemappedReg; 12940eae32dcSDimitry Andric RegList.push_back(SrcReg); 12950eae32dcSDimitry Andric PadBefore = -MI->getOperand(4).getImm() - 8; 12960eae32dcSDimitry Andric break; 12970b57cec5SDimitry Andric } 12980b57cec5SDimitry Andric if (MAI->getExceptionHandlingType() == ExceptionHandling::ARM) { 12990eae32dcSDimitry Andric if (PadBefore) 13000eae32dcSDimitry Andric ATS.emitPad(PadBefore); 13010b57cec5SDimitry Andric ATS.emitRegSave(RegList, Opc == ARM::VSTMDDB_UPD); 13020b57cec5SDimitry Andric // Account for the SP adjustment, folded into the push. 13030eae32dcSDimitry Andric if (PadAfter) 13040eae32dcSDimitry Andric ATS.emitPad(PadAfter); 13050b57cec5SDimitry Andric } 13060b57cec5SDimitry Andric } else { 13070b57cec5SDimitry Andric // Changes of stack / frame pointer. 13080b57cec5SDimitry Andric if (SrcReg == ARM::SP) { 13090b57cec5SDimitry Andric int64_t Offset = 0; 13100b57cec5SDimitry Andric switch (Opc) { 13110b57cec5SDimitry Andric default: 13120b57cec5SDimitry Andric MI->print(errs()); 13130b57cec5SDimitry Andric llvm_unreachable("Unsupported opcode for unwinding information"); 13140b57cec5SDimitry Andric case ARM::MOVr: 13150b57cec5SDimitry Andric case ARM::tMOVr: 13160b57cec5SDimitry Andric Offset = 0; 13170b57cec5SDimitry Andric break; 13180b57cec5SDimitry Andric case ARM::ADDri: 13190b57cec5SDimitry Andric case ARM::t2ADDri: 1320480093f4SDimitry Andric case ARM::t2ADDri12: 1321480093f4SDimitry Andric case ARM::t2ADDspImm: 1322480093f4SDimitry Andric case ARM::t2ADDspImm12: 13230b57cec5SDimitry Andric Offset = -MI->getOperand(2).getImm(); 13240b57cec5SDimitry Andric break; 13250b57cec5SDimitry Andric case ARM::SUBri: 13260b57cec5SDimitry Andric case ARM::t2SUBri: 1327480093f4SDimitry Andric case ARM::t2SUBri12: 1328480093f4SDimitry Andric case ARM::t2SUBspImm: 1329480093f4SDimitry Andric case ARM::t2SUBspImm12: 13300b57cec5SDimitry Andric Offset = MI->getOperand(2).getImm(); 13310b57cec5SDimitry Andric break; 13320b57cec5SDimitry Andric case ARM::tSUBspi: 13330b57cec5SDimitry Andric Offset = MI->getOperand(2).getImm()*4; 13340b57cec5SDimitry Andric break; 13350b57cec5SDimitry Andric case ARM::tADDspi: 13360b57cec5SDimitry Andric case ARM::tADDrSPi: 13370b57cec5SDimitry Andric Offset = -MI->getOperand(2).getImm()*4; 13380b57cec5SDimitry Andric break; 13395ffd83dbSDimitry Andric case ARM::tADDhirr: 13405ffd83dbSDimitry Andric Offset = 13415ffd83dbSDimitry Andric -AFI->EHPrologueOffsetInRegs.lookup(MI->getOperand(2).getReg()); 13420b57cec5SDimitry Andric break; 13430b57cec5SDimitry Andric } 13440b57cec5SDimitry Andric 13450b57cec5SDimitry Andric if (MAI->getExceptionHandlingType() == ExceptionHandling::ARM) { 13460b57cec5SDimitry Andric if (DstReg == FramePtr && FramePtr != ARM::SP) 13470b57cec5SDimitry Andric // Set-up of the frame pointer. Positive values correspond to "add" 13480b57cec5SDimitry Andric // instruction. 13490b57cec5SDimitry Andric ATS.emitSetFP(FramePtr, ARM::SP, -Offset); 13500b57cec5SDimitry Andric else if (DstReg == ARM::SP) { 13510b57cec5SDimitry Andric // Change of SP by an offset. Positive values correspond to "sub" 13520b57cec5SDimitry Andric // instruction. 13530b57cec5SDimitry Andric ATS.emitPad(Offset); 13540b57cec5SDimitry Andric } else { 13550b57cec5SDimitry Andric // Move of SP to a register. Positive values correspond to an "add" 13560b57cec5SDimitry Andric // instruction. 13570b57cec5SDimitry Andric ATS.emitMovSP(DstReg, -Offset); 13580b57cec5SDimitry Andric } 13590b57cec5SDimitry Andric } 13600b57cec5SDimitry Andric } else if (DstReg == ARM::SP) { 13610b57cec5SDimitry Andric MI->print(errs()); 13620b57cec5SDimitry Andric llvm_unreachable("Unsupported opcode for unwinding information"); 13635ffd83dbSDimitry Andric } else { 13645ffd83dbSDimitry Andric int64_t Offset = 0; 13655ffd83dbSDimitry Andric switch (Opc) { 13665ffd83dbSDimitry Andric case ARM::tMOVr: 13670b57cec5SDimitry Andric // If a Thumb1 function spills r8-r11, we copy the values to low 13680b57cec5SDimitry Andric // registers before pushing them. Record the copy so we can emit the 13690b57cec5SDimitry Andric // correct ".save" later. 13700b57cec5SDimitry Andric AFI->EHPrologueRemappedRegs[DstReg] = SrcReg; 13715ffd83dbSDimitry Andric break; 13725ffd83dbSDimitry Andric case ARM::tLDRpci: { 13735ffd83dbSDimitry Andric // Grab the constpool index and check, whether it corresponds to 13745ffd83dbSDimitry Andric // original or cloned constpool entry. 13755ffd83dbSDimitry Andric unsigned CPI = MI->getOperand(1).getIndex(); 13765ffd83dbSDimitry Andric const MachineConstantPool *MCP = MF.getConstantPool(); 13775ffd83dbSDimitry Andric if (CPI >= MCP->getConstants().size()) 13785ffd83dbSDimitry Andric CPI = AFI->getOriginalCPIdx(CPI); 13795ffd83dbSDimitry Andric assert(CPI != -1U && "Invalid constpool index"); 13805ffd83dbSDimitry Andric 13815ffd83dbSDimitry Andric // Derive the actual offset. 13825ffd83dbSDimitry Andric const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI]; 13835ffd83dbSDimitry Andric assert(!CPE.isMachineConstantPoolEntry() && "Invalid constpool entry"); 13845ffd83dbSDimitry Andric Offset = cast<ConstantInt>(CPE.Val.ConstVal)->getSExtValue(); 13855ffd83dbSDimitry Andric AFI->EHPrologueOffsetInRegs[DstReg] = Offset; 13865ffd83dbSDimitry Andric break; 13875ffd83dbSDimitry Andric } 13885ffd83dbSDimitry Andric case ARM::t2MOVi16: 13895ffd83dbSDimitry Andric Offset = MI->getOperand(1).getImm(); 13905ffd83dbSDimitry Andric AFI->EHPrologueOffsetInRegs[DstReg] = Offset; 13915ffd83dbSDimitry Andric break; 13925ffd83dbSDimitry Andric case ARM::t2MOVTi16: 13935ffd83dbSDimitry Andric Offset = MI->getOperand(2).getImm(); 13945ffd83dbSDimitry Andric AFI->EHPrologueOffsetInRegs[DstReg] |= (Offset << 16); 13955ffd83dbSDimitry Andric break; 139606c3fb27SDimitry Andric case ARM::tMOVi8: 139706c3fb27SDimitry Andric Offset = MI->getOperand(2).getImm(); 139806c3fb27SDimitry Andric AFI->EHPrologueOffsetInRegs[DstReg] = Offset; 139906c3fb27SDimitry Andric break; 140006c3fb27SDimitry Andric case ARM::tLSLri: 140106c3fb27SDimitry Andric assert(MI->getOperand(3).getImm() == 8 && 140206c3fb27SDimitry Andric "The shift amount is not equal to 8"); 140306c3fb27SDimitry Andric assert(MI->getOperand(2).getReg() == MI->getOperand(0).getReg() && 140406c3fb27SDimitry Andric "The source register is not equal to the destination register"); 140506c3fb27SDimitry Andric AFI->EHPrologueOffsetInRegs[DstReg] <<= 8; 140606c3fb27SDimitry Andric break; 140706c3fb27SDimitry Andric case ARM::tADDi8: 140806c3fb27SDimitry Andric assert(MI->getOperand(2).getReg() == MI->getOperand(0).getReg() && 140906c3fb27SDimitry Andric "The source register is not equal to the destination register"); 141006c3fb27SDimitry Andric Offset = MI->getOperand(3).getImm(); 141106c3fb27SDimitry Andric AFI->EHPrologueOffsetInRegs[DstReg] += Offset; 141206c3fb27SDimitry Andric break; 14130eae32dcSDimitry Andric case ARM::t2PAC: 14140eae32dcSDimitry Andric case ARM::t2PACBTI: 14150eae32dcSDimitry Andric AFI->EHPrologueRemappedRegs[ARM::R12] = ARM::RA_AUTH_CODE; 14160eae32dcSDimitry Andric break; 14175ffd83dbSDimitry Andric default: 14180b57cec5SDimitry Andric MI->print(errs()); 14190b57cec5SDimitry Andric llvm_unreachable("Unsupported opcode for unwinding information"); 14200b57cec5SDimitry Andric } 14210b57cec5SDimitry Andric } 14220b57cec5SDimitry Andric } 14235ffd83dbSDimitry Andric } 14240b57cec5SDimitry Andric 14250b57cec5SDimitry Andric // Simple pseudo-instructions have their lowering (with expansion to real 14260b57cec5SDimitry Andric // instructions) auto-generated. 14270b57cec5SDimitry Andric #include "ARMGenMCPseudoLowering.inc" 14280b57cec5SDimitry Andric 14295ffd83dbSDimitry Andric void ARMAsmPrinter::emitInstruction(const MachineInstr *MI) { 1430753f127fSDimitry Andric // TODOD FIXME: Enable feature predicate checks once all the test pass. 1431753f127fSDimitry Andric // ARM_MC::verifyInstructionPredicates(MI->getOpcode(), 1432753f127fSDimitry Andric // getSubtargetInfo().getFeatureBits()); 1433753f127fSDimitry Andric 14340b57cec5SDimitry Andric const DataLayout &DL = getDataLayout(); 14350b57cec5SDimitry Andric MCTargetStreamer &TS = *OutStreamer->getTargetStreamer(); 14360b57cec5SDimitry Andric ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS); 14370b57cec5SDimitry Andric 14380b57cec5SDimitry Andric // If we just ended a constant pool, mark it as such. 14390b57cec5SDimitry Andric if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) { 14405ffd83dbSDimitry Andric OutStreamer->emitDataRegion(MCDR_DataRegionEnd); 14410b57cec5SDimitry Andric InConstantPool = false; 14420b57cec5SDimitry Andric } 14430b57cec5SDimitry Andric 14440b57cec5SDimitry Andric // Emit unwinding stuff for frame-related instructions 14450b57cec5SDimitry Andric if (Subtarget->isTargetEHABICompatible() && 14460b57cec5SDimitry Andric MI->getFlag(MachineInstr::FrameSetup)) 14470b57cec5SDimitry Andric EmitUnwindingInstruction(MI); 14480b57cec5SDimitry Andric 14490b57cec5SDimitry Andric // Do any auto-generated pseudo lowerings. 14500b57cec5SDimitry Andric if (emitPseudoExpansionLowering(*OutStreamer, MI)) 14510b57cec5SDimitry Andric return; 14520b57cec5SDimitry Andric 14530b57cec5SDimitry Andric assert(!convertAddSubFlagsOpcode(MI->getOpcode()) && 14540b57cec5SDimitry Andric "Pseudo flag setting opcode should be expanded early"); 14550b57cec5SDimitry Andric 14560b57cec5SDimitry Andric // Check for manual lowerings. 14570b57cec5SDimitry Andric unsigned Opc = MI->getOpcode(); 14580b57cec5SDimitry Andric switch (Opc) { 14590b57cec5SDimitry Andric case ARM::t2MOVi32imm: llvm_unreachable("Should be lowered by thumb2it pass"); 14600b57cec5SDimitry Andric case ARM::DBG_VALUE: llvm_unreachable("Should be handled by generic printing"); 14610b57cec5SDimitry Andric case ARM::LEApcrel: 14620b57cec5SDimitry Andric case ARM::tLEApcrel: 14630b57cec5SDimitry Andric case ARM::t2LEApcrel: { 14640b57cec5SDimitry Andric // FIXME: Need to also handle globals and externals 14650b57cec5SDimitry Andric MCSymbol *CPISymbol = GetCPISymbol(MI->getOperand(1).getIndex()); 14660b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(MI->getOpcode() == 14670b57cec5SDimitry Andric ARM::t2LEApcrel ? ARM::t2ADR 14680b57cec5SDimitry Andric : (MI->getOpcode() == ARM::tLEApcrel ? ARM::tADR 14690b57cec5SDimitry Andric : ARM::ADR)) 14700b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 14710b57cec5SDimitry Andric .addExpr(MCSymbolRefExpr::create(CPISymbol, OutContext)) 14720b57cec5SDimitry Andric // Add predicate operands. 14730b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 14740b57cec5SDimitry Andric .addReg(MI->getOperand(3).getReg())); 14750b57cec5SDimitry Andric return; 14760b57cec5SDimitry Andric } 14770b57cec5SDimitry Andric case ARM::LEApcrelJT: 14780b57cec5SDimitry Andric case ARM::tLEApcrelJT: 14790b57cec5SDimitry Andric case ARM::t2LEApcrelJT: { 14800b57cec5SDimitry Andric MCSymbol *JTIPICSymbol = 14810b57cec5SDimitry Andric GetARMJTIPICJumpTableLabel(MI->getOperand(1).getIndex()); 14820b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(MI->getOpcode() == 14830b57cec5SDimitry Andric ARM::t2LEApcrelJT ? ARM::t2ADR 14840b57cec5SDimitry Andric : (MI->getOpcode() == ARM::tLEApcrelJT ? ARM::tADR 14850b57cec5SDimitry Andric : ARM::ADR)) 14860b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 14870b57cec5SDimitry Andric .addExpr(MCSymbolRefExpr::create(JTIPICSymbol, OutContext)) 14880b57cec5SDimitry Andric // Add predicate operands. 14890b57cec5SDimitry Andric .addImm(MI->getOperand(2).getImm()) 14900b57cec5SDimitry Andric .addReg(MI->getOperand(3).getReg())); 14910b57cec5SDimitry Andric return; 14920b57cec5SDimitry Andric } 14930b57cec5SDimitry Andric // Darwin call instructions are just normal call instructions with different 14940b57cec5SDimitry Andric // clobber semantics (they clobber R9). 14950b57cec5SDimitry Andric case ARM::BX_CALL: { 14960b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVr) 14970b57cec5SDimitry Andric .addReg(ARM::LR) 14980b57cec5SDimitry Andric .addReg(ARM::PC) 14990b57cec5SDimitry Andric // Add predicate operands. 15000b57cec5SDimitry Andric .addImm(ARMCC::AL) 15010b57cec5SDimitry Andric .addReg(0) 15020b57cec5SDimitry Andric // Add 's' bit operand (always reg0 for this) 15030b57cec5SDimitry Andric .addReg(0)); 15040b57cec5SDimitry Andric 15050b57cec5SDimitry Andric assert(Subtarget->hasV4TOps()); 15060b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::BX) 15070b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg())); 15080b57cec5SDimitry Andric return; 15090b57cec5SDimitry Andric } 15100b57cec5SDimitry Andric case ARM::tBX_CALL: { 15110b57cec5SDimitry Andric if (Subtarget->hasV5TOps()) 15120b57cec5SDimitry Andric llvm_unreachable("Expected BLX to be selected for v5t+"); 15130b57cec5SDimitry Andric 15140b57cec5SDimitry Andric // On ARM v4t, when doing a call from thumb mode, we need to ensure 15150b57cec5SDimitry Andric // that the saved lr has its LSB set correctly (the arch doesn't 15160b57cec5SDimitry Andric // have blx). 15170b57cec5SDimitry Andric // So here we generate a bl to a small jump pad that does bx rN. 15180b57cec5SDimitry Andric // The jump pads are emitted after the function body. 15190b57cec5SDimitry Andric 15208bcb0991SDimitry Andric Register TReg = MI->getOperand(0).getReg(); 15210b57cec5SDimitry Andric MCSymbol *TRegSym = nullptr; 15220b57cec5SDimitry Andric for (std::pair<unsigned, MCSymbol *> &TIP : ThumbIndirectPads) { 15230b57cec5SDimitry Andric if (TIP.first == TReg) { 15240b57cec5SDimitry Andric TRegSym = TIP.second; 15250b57cec5SDimitry Andric break; 15260b57cec5SDimitry Andric } 15270b57cec5SDimitry Andric } 15280b57cec5SDimitry Andric 15290b57cec5SDimitry Andric if (!TRegSym) { 15300b57cec5SDimitry Andric TRegSym = OutContext.createTempSymbol(); 15310b57cec5SDimitry Andric ThumbIndirectPads.push_back(std::make_pair(TReg, TRegSym)); 15320b57cec5SDimitry Andric } 15330b57cec5SDimitry Andric 15340b57cec5SDimitry Andric // Create a link-saving branch to the Reg Indirect Jump Pad. 15350b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBL) 15360b57cec5SDimitry Andric // Predicate comes first here. 15370b57cec5SDimitry Andric .addImm(ARMCC::AL).addReg(0) 15380b57cec5SDimitry Andric .addExpr(MCSymbolRefExpr::create(TRegSym, OutContext))); 15390b57cec5SDimitry Andric return; 15400b57cec5SDimitry Andric } 15410b57cec5SDimitry Andric case ARM::BMOVPCRX_CALL: { 15420b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVr) 15430b57cec5SDimitry Andric .addReg(ARM::LR) 15440b57cec5SDimitry Andric .addReg(ARM::PC) 15450b57cec5SDimitry Andric // Add predicate operands. 15460b57cec5SDimitry Andric .addImm(ARMCC::AL) 15470b57cec5SDimitry Andric .addReg(0) 15480b57cec5SDimitry Andric // Add 's' bit operand (always reg0 for this) 15490b57cec5SDimitry Andric .addReg(0)); 15500b57cec5SDimitry Andric 15510b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVr) 15520b57cec5SDimitry Andric .addReg(ARM::PC) 15530b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 15540b57cec5SDimitry Andric // Add predicate operands. 15550b57cec5SDimitry Andric .addImm(ARMCC::AL) 15560b57cec5SDimitry Andric .addReg(0) 15570b57cec5SDimitry Andric // Add 's' bit operand (always reg0 for this) 15580b57cec5SDimitry Andric .addReg(0)); 15590b57cec5SDimitry Andric return; 15600b57cec5SDimitry Andric } 15610b57cec5SDimitry Andric case ARM::BMOVPCB_CALL: { 15620b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVr) 15630b57cec5SDimitry Andric .addReg(ARM::LR) 15640b57cec5SDimitry Andric .addReg(ARM::PC) 15650b57cec5SDimitry Andric // Add predicate operands. 15660b57cec5SDimitry Andric .addImm(ARMCC::AL) 15670b57cec5SDimitry Andric .addReg(0) 15680b57cec5SDimitry Andric // Add 's' bit operand (always reg0 for this) 15690b57cec5SDimitry Andric .addReg(0)); 15700b57cec5SDimitry Andric 15710b57cec5SDimitry Andric const MachineOperand &Op = MI->getOperand(0); 15720b57cec5SDimitry Andric const GlobalValue *GV = Op.getGlobal(); 15730b57cec5SDimitry Andric const unsigned TF = Op.getTargetFlags(); 15740b57cec5SDimitry Andric MCSymbol *GVSym = GetARMGVSymbol(GV, TF); 15750b57cec5SDimitry Andric const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext); 15760b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::Bcc) 15770b57cec5SDimitry Andric .addExpr(GVSymExpr) 15780b57cec5SDimitry Andric // Add predicate operands. 15790b57cec5SDimitry Andric .addImm(ARMCC::AL) 15800b57cec5SDimitry Andric .addReg(0)); 15810b57cec5SDimitry Andric return; 15820b57cec5SDimitry Andric } 15830b57cec5SDimitry Andric case ARM::MOVi16_ga_pcrel: 15840b57cec5SDimitry Andric case ARM::t2MOVi16_ga_pcrel: { 15850b57cec5SDimitry Andric MCInst TmpInst; 15860b57cec5SDimitry Andric TmpInst.setOpcode(Opc == ARM::MOVi16_ga_pcrel? ARM::MOVi16 : ARM::t2MOVi16); 15870b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); 15880b57cec5SDimitry Andric 15890b57cec5SDimitry Andric unsigned TF = MI->getOperand(1).getTargetFlags(); 15900b57cec5SDimitry Andric const GlobalValue *GV = MI->getOperand(1).getGlobal(); 15910b57cec5SDimitry Andric MCSymbol *GVSym = GetARMGVSymbol(GV, TF); 15920b57cec5SDimitry Andric const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext); 15930b57cec5SDimitry Andric 15940b57cec5SDimitry Andric MCSymbol *LabelSym = 15950b57cec5SDimitry Andric getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(), 15960b57cec5SDimitry Andric MI->getOperand(2).getImm(), OutContext); 15970b57cec5SDimitry Andric const MCExpr *LabelSymExpr= MCSymbolRefExpr::create(LabelSym, OutContext); 15980b57cec5SDimitry Andric unsigned PCAdj = (Opc == ARM::MOVi16_ga_pcrel) ? 8 : 4; 15990b57cec5SDimitry Andric const MCExpr *PCRelExpr = 16000b57cec5SDimitry Andric ARMMCExpr::createLower16(MCBinaryExpr::createSub(GVSymExpr, 16010b57cec5SDimitry Andric MCBinaryExpr::createAdd(LabelSymExpr, 16020b57cec5SDimitry Andric MCConstantExpr::create(PCAdj, OutContext), 16030b57cec5SDimitry Andric OutContext), OutContext), OutContext); 16040b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createExpr(PCRelExpr)); 16050b57cec5SDimitry Andric 16060b57cec5SDimitry Andric // Add predicate operands. 16070b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createImm(ARMCC::AL)); 16080b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(0)); 16090b57cec5SDimitry Andric // Add 's' bit operand (always reg0 for this) 16100b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(0)); 16110b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, TmpInst); 16120b57cec5SDimitry Andric return; 16130b57cec5SDimitry Andric } 16140b57cec5SDimitry Andric case ARM::MOVTi16_ga_pcrel: 16150b57cec5SDimitry Andric case ARM::t2MOVTi16_ga_pcrel: { 16160b57cec5SDimitry Andric MCInst TmpInst; 16170b57cec5SDimitry Andric TmpInst.setOpcode(Opc == ARM::MOVTi16_ga_pcrel 16180b57cec5SDimitry Andric ? ARM::MOVTi16 : ARM::t2MOVTi16); 16190b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); 16200b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(MI->getOperand(1).getReg())); 16210b57cec5SDimitry Andric 16220b57cec5SDimitry Andric unsigned TF = MI->getOperand(2).getTargetFlags(); 16230b57cec5SDimitry Andric const GlobalValue *GV = MI->getOperand(2).getGlobal(); 16240b57cec5SDimitry Andric MCSymbol *GVSym = GetARMGVSymbol(GV, TF); 16250b57cec5SDimitry Andric const MCExpr *GVSymExpr = MCSymbolRefExpr::create(GVSym, OutContext); 16260b57cec5SDimitry Andric 16270b57cec5SDimitry Andric MCSymbol *LabelSym = 16280b57cec5SDimitry Andric getPICLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(), 16290b57cec5SDimitry Andric MI->getOperand(3).getImm(), OutContext); 16300b57cec5SDimitry Andric const MCExpr *LabelSymExpr= MCSymbolRefExpr::create(LabelSym, OutContext); 16310b57cec5SDimitry Andric unsigned PCAdj = (Opc == ARM::MOVTi16_ga_pcrel) ? 8 : 4; 16320b57cec5SDimitry Andric const MCExpr *PCRelExpr = 16330b57cec5SDimitry Andric ARMMCExpr::createUpper16(MCBinaryExpr::createSub(GVSymExpr, 16340b57cec5SDimitry Andric MCBinaryExpr::createAdd(LabelSymExpr, 16350b57cec5SDimitry Andric MCConstantExpr::create(PCAdj, OutContext), 16360b57cec5SDimitry Andric OutContext), OutContext), OutContext); 16370b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createExpr(PCRelExpr)); 16380b57cec5SDimitry Andric // Add predicate operands. 16390b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createImm(ARMCC::AL)); 16400b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(0)); 16410b57cec5SDimitry Andric // Add 's' bit operand (always reg0 for this) 16420b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(0)); 16430b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, TmpInst); 16440b57cec5SDimitry Andric return; 16450b57cec5SDimitry Andric } 16460b57cec5SDimitry Andric case ARM::t2BFi: 16470b57cec5SDimitry Andric case ARM::t2BFic: 16480b57cec5SDimitry Andric case ARM::t2BFLi: 16490b57cec5SDimitry Andric case ARM::t2BFr: 16500b57cec5SDimitry Andric case ARM::t2BFLr: { 16510b57cec5SDimitry Andric // This is a Branch Future instruction. 16520b57cec5SDimitry Andric 16530b57cec5SDimitry Andric const MCExpr *BranchLabel = MCSymbolRefExpr::create( 16540b57cec5SDimitry Andric getBFLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(), 16550b57cec5SDimitry Andric MI->getOperand(0).getIndex(), OutContext), 16560b57cec5SDimitry Andric OutContext); 16570b57cec5SDimitry Andric 16580b57cec5SDimitry Andric auto MCInst = MCInstBuilder(Opc).addExpr(BranchLabel); 16590b57cec5SDimitry Andric if (MI->getOperand(1).isReg()) { 16600b57cec5SDimitry Andric // For BFr/BFLr 16610b57cec5SDimitry Andric MCInst.addReg(MI->getOperand(1).getReg()); 16620b57cec5SDimitry Andric } else { 16630b57cec5SDimitry Andric // For BFi/BFLi/BFic 16640b57cec5SDimitry Andric const MCExpr *BranchTarget; 16650b57cec5SDimitry Andric if (MI->getOperand(1).isMBB()) 16660b57cec5SDimitry Andric BranchTarget = MCSymbolRefExpr::create( 16670b57cec5SDimitry Andric MI->getOperand(1).getMBB()->getSymbol(), OutContext); 16680b57cec5SDimitry Andric else if (MI->getOperand(1).isGlobal()) { 16690b57cec5SDimitry Andric const GlobalValue *GV = MI->getOperand(1).getGlobal(); 16700b57cec5SDimitry Andric BranchTarget = MCSymbolRefExpr::create( 16710b57cec5SDimitry Andric GetARMGVSymbol(GV, MI->getOperand(1).getTargetFlags()), OutContext); 16720b57cec5SDimitry Andric } else if (MI->getOperand(1).isSymbol()) { 16730b57cec5SDimitry Andric BranchTarget = MCSymbolRefExpr::create( 16740b57cec5SDimitry Andric GetExternalSymbolSymbol(MI->getOperand(1).getSymbolName()), 16750b57cec5SDimitry Andric OutContext); 16760b57cec5SDimitry Andric } else 16770b57cec5SDimitry Andric llvm_unreachable("Unhandled operand kind in Branch Future instruction"); 16780b57cec5SDimitry Andric 16790b57cec5SDimitry Andric MCInst.addExpr(BranchTarget); 16800b57cec5SDimitry Andric } 16810b57cec5SDimitry Andric 16820b57cec5SDimitry Andric if (Opc == ARM::t2BFic) { 16830b57cec5SDimitry Andric const MCExpr *ElseLabel = MCSymbolRefExpr::create( 16840b57cec5SDimitry Andric getBFLabel(DL.getPrivateGlobalPrefix(), getFunctionNumber(), 16850b57cec5SDimitry Andric MI->getOperand(2).getIndex(), OutContext), 16860b57cec5SDimitry Andric OutContext); 16870b57cec5SDimitry Andric MCInst.addExpr(ElseLabel); 16880b57cec5SDimitry Andric MCInst.addImm(MI->getOperand(3).getImm()); 16890b57cec5SDimitry Andric } else { 16900b57cec5SDimitry Andric MCInst.addImm(MI->getOperand(2).getImm()) 16910b57cec5SDimitry Andric .addReg(MI->getOperand(3).getReg()); 16920b57cec5SDimitry Andric } 16930b57cec5SDimitry Andric 16940b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInst); 16950b57cec5SDimitry Andric return; 16960b57cec5SDimitry Andric } 16970b57cec5SDimitry Andric case ARM::t2BF_LabelPseudo: { 16980b57cec5SDimitry Andric // This is a pseudo op for a label used by a branch future instruction 16990b57cec5SDimitry Andric 17000b57cec5SDimitry Andric // Emit the label. 17015ffd83dbSDimitry Andric OutStreamer->emitLabel(getBFLabel(DL.getPrivateGlobalPrefix(), 17020b57cec5SDimitry Andric getFunctionNumber(), 17030b57cec5SDimitry Andric MI->getOperand(0).getIndex(), OutContext)); 17040b57cec5SDimitry Andric return; 17050b57cec5SDimitry Andric } 17060b57cec5SDimitry Andric case ARM::tPICADD: { 17070b57cec5SDimitry Andric // This is a pseudo op for a label + instruction sequence, which looks like: 17080b57cec5SDimitry Andric // LPC0: 17090b57cec5SDimitry Andric // add r0, pc 17100b57cec5SDimitry Andric // This adds the address of LPC0 to r0. 17110b57cec5SDimitry Andric 17120b57cec5SDimitry Andric // Emit the label. 17135ffd83dbSDimitry Andric OutStreamer->emitLabel(getPICLabel(DL.getPrivateGlobalPrefix(), 17140b57cec5SDimitry Andric getFunctionNumber(), 17150b57cec5SDimitry Andric MI->getOperand(2).getImm(), OutContext)); 17160b57cec5SDimitry Andric 17170b57cec5SDimitry Andric // Form and emit the add. 17180b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDhirr) 17190b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 17200b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 17210b57cec5SDimitry Andric .addReg(ARM::PC) 17220b57cec5SDimitry Andric // Add predicate operands. 17230b57cec5SDimitry Andric .addImm(ARMCC::AL) 17240b57cec5SDimitry Andric .addReg(0)); 17250b57cec5SDimitry Andric return; 17260b57cec5SDimitry Andric } 17270b57cec5SDimitry Andric case ARM::PICADD: { 17280b57cec5SDimitry Andric // This is a pseudo op for a label + instruction sequence, which looks like: 17290b57cec5SDimitry Andric // LPC0: 17300b57cec5SDimitry Andric // add r0, pc, r0 17310b57cec5SDimitry Andric // This adds the address of LPC0 to r0. 17320b57cec5SDimitry Andric 17330b57cec5SDimitry Andric // Emit the label. 17345ffd83dbSDimitry Andric OutStreamer->emitLabel(getPICLabel(DL.getPrivateGlobalPrefix(), 17350b57cec5SDimitry Andric getFunctionNumber(), 17360b57cec5SDimitry Andric MI->getOperand(2).getImm(), OutContext)); 17370b57cec5SDimitry Andric 17380b57cec5SDimitry Andric // Form and emit the add. 17390b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::ADDrr) 17400b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 17410b57cec5SDimitry Andric .addReg(ARM::PC) 17420b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 17430b57cec5SDimitry Andric // Add predicate operands. 17440b57cec5SDimitry Andric .addImm(MI->getOperand(3).getImm()) 17450b57cec5SDimitry Andric .addReg(MI->getOperand(4).getReg()) 17460b57cec5SDimitry Andric // Add 's' bit operand (always reg0 for this) 17470b57cec5SDimitry Andric .addReg(0)); 17480b57cec5SDimitry Andric return; 17490b57cec5SDimitry Andric } 17500b57cec5SDimitry Andric case ARM::PICSTR: 17510b57cec5SDimitry Andric case ARM::PICSTRB: 17520b57cec5SDimitry Andric case ARM::PICSTRH: 17530b57cec5SDimitry Andric case ARM::PICLDR: 17540b57cec5SDimitry Andric case ARM::PICLDRB: 17550b57cec5SDimitry Andric case ARM::PICLDRH: 17560b57cec5SDimitry Andric case ARM::PICLDRSB: 17570b57cec5SDimitry Andric case ARM::PICLDRSH: { 17580b57cec5SDimitry Andric // This is a pseudo op for a label + instruction sequence, which looks like: 17590b57cec5SDimitry Andric // LPC0: 17600b57cec5SDimitry Andric // OP r0, [pc, r0] 17610b57cec5SDimitry Andric // The LCP0 label is referenced by a constant pool entry in order to get 17620b57cec5SDimitry Andric // a PC-relative address at the ldr instruction. 17630b57cec5SDimitry Andric 17640b57cec5SDimitry Andric // Emit the label. 17655ffd83dbSDimitry Andric OutStreamer->emitLabel(getPICLabel(DL.getPrivateGlobalPrefix(), 17660b57cec5SDimitry Andric getFunctionNumber(), 17670b57cec5SDimitry Andric MI->getOperand(2).getImm(), OutContext)); 17680b57cec5SDimitry Andric 17690b57cec5SDimitry Andric // Form and emit the load 17700b57cec5SDimitry Andric unsigned Opcode; 17710b57cec5SDimitry Andric switch (MI->getOpcode()) { 17720b57cec5SDimitry Andric default: 17730b57cec5SDimitry Andric llvm_unreachable("Unexpected opcode!"); 17740b57cec5SDimitry Andric case ARM::PICSTR: Opcode = ARM::STRrs; break; 17750b57cec5SDimitry Andric case ARM::PICSTRB: Opcode = ARM::STRBrs; break; 17760b57cec5SDimitry Andric case ARM::PICSTRH: Opcode = ARM::STRH; break; 17770b57cec5SDimitry Andric case ARM::PICLDR: Opcode = ARM::LDRrs; break; 17780b57cec5SDimitry Andric case ARM::PICLDRB: Opcode = ARM::LDRBrs; break; 17790b57cec5SDimitry Andric case ARM::PICLDRH: Opcode = ARM::LDRH; break; 17800b57cec5SDimitry Andric case ARM::PICLDRSB: Opcode = ARM::LDRSB; break; 17810b57cec5SDimitry Andric case ARM::PICLDRSH: Opcode = ARM::LDRSH; break; 17820b57cec5SDimitry Andric } 17830b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(Opcode) 17840b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 17850b57cec5SDimitry Andric .addReg(ARM::PC) 17860b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 17870b57cec5SDimitry Andric .addImm(0) 17880b57cec5SDimitry Andric // Add predicate operands. 17890b57cec5SDimitry Andric .addImm(MI->getOperand(3).getImm()) 17900b57cec5SDimitry Andric .addReg(MI->getOperand(4).getReg())); 17910b57cec5SDimitry Andric 17920b57cec5SDimitry Andric return; 17930b57cec5SDimitry Andric } 17940b57cec5SDimitry Andric case ARM::CONSTPOOL_ENTRY: { 17950b57cec5SDimitry Andric if (Subtarget->genExecuteOnly()) 17960b57cec5SDimitry Andric llvm_unreachable("execute-only should not generate constant pools"); 17970b57cec5SDimitry Andric 17980b57cec5SDimitry Andric /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool 17990b57cec5SDimitry Andric /// in the function. The first operand is the ID# for this instruction, the 18000b57cec5SDimitry Andric /// second is the index into the MachineConstantPool that this is, the third 18010b57cec5SDimitry Andric /// is the size in bytes of this constant pool entry. 18020b57cec5SDimitry Andric /// The required alignment is specified on the basic block holding this MI. 18030b57cec5SDimitry Andric unsigned LabelId = (unsigned)MI->getOperand(0).getImm(); 18040b57cec5SDimitry Andric unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex(); 18050b57cec5SDimitry Andric 18060b57cec5SDimitry Andric // If this is the first entry of the pool, mark it. 18070b57cec5SDimitry Andric if (!InConstantPool) { 18085ffd83dbSDimitry Andric OutStreamer->emitDataRegion(MCDR_DataRegion); 18090b57cec5SDimitry Andric InConstantPool = true; 18100b57cec5SDimitry Andric } 18110b57cec5SDimitry Andric 18125ffd83dbSDimitry Andric OutStreamer->emitLabel(GetCPISymbol(LabelId)); 18130b57cec5SDimitry Andric 18140b57cec5SDimitry Andric const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx]; 18150b57cec5SDimitry Andric if (MCPE.isMachineConstantPoolEntry()) 18165ffd83dbSDimitry Andric emitMachineConstantPoolValue(MCPE.Val.MachineCPVal); 18170b57cec5SDimitry Andric else 18185ffd83dbSDimitry Andric emitGlobalConstant(DL, MCPE.Val.ConstVal); 18190b57cec5SDimitry Andric return; 18200b57cec5SDimitry Andric } 18210b57cec5SDimitry Andric case ARM::JUMPTABLE_ADDRS: 18225ffd83dbSDimitry Andric emitJumpTableAddrs(MI); 18230b57cec5SDimitry Andric return; 18240b57cec5SDimitry Andric case ARM::JUMPTABLE_INSTS: 18255ffd83dbSDimitry Andric emitJumpTableInsts(MI); 18260b57cec5SDimitry Andric return; 18270b57cec5SDimitry Andric case ARM::JUMPTABLE_TBB: 18280b57cec5SDimitry Andric case ARM::JUMPTABLE_TBH: 18295ffd83dbSDimitry Andric emitJumpTableTBInst(MI, MI->getOpcode() == ARM::JUMPTABLE_TBB ? 1 : 2); 18300b57cec5SDimitry Andric return; 18310b57cec5SDimitry Andric case ARM::t2BR_JT: { 18320b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr) 18330b57cec5SDimitry Andric .addReg(ARM::PC) 18340b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 18350b57cec5SDimitry Andric // Add predicate operands. 18360b57cec5SDimitry Andric .addImm(ARMCC::AL) 18370b57cec5SDimitry Andric .addReg(0)); 18380b57cec5SDimitry Andric return; 18390b57cec5SDimitry Andric } 18400b57cec5SDimitry Andric case ARM::t2TBB_JT: 18410b57cec5SDimitry Andric case ARM::t2TBH_JT: { 18420b57cec5SDimitry Andric unsigned Opc = MI->getOpcode() == ARM::t2TBB_JT ? ARM::t2TBB : ARM::t2TBH; 18430b57cec5SDimitry Andric // Lower and emit the PC label, then the instruction itself. 18445ffd83dbSDimitry Andric OutStreamer->emitLabel(GetCPISymbol(MI->getOperand(3).getImm())); 18450b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(Opc) 18460b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 18470b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 18480b57cec5SDimitry Andric // Add predicate operands. 18490b57cec5SDimitry Andric .addImm(ARMCC::AL) 18500b57cec5SDimitry Andric .addReg(0)); 18510b57cec5SDimitry Andric return; 18520b57cec5SDimitry Andric } 18530b57cec5SDimitry Andric case ARM::tTBB_JT: 18540b57cec5SDimitry Andric case ARM::tTBH_JT: { 18550b57cec5SDimitry Andric 18560b57cec5SDimitry Andric bool Is8Bit = MI->getOpcode() == ARM::tTBB_JT; 18578bcb0991SDimitry Andric Register Base = MI->getOperand(0).getReg(); 18588bcb0991SDimitry Andric Register Idx = MI->getOperand(1).getReg(); 18590b57cec5SDimitry Andric assert(MI->getOperand(1).isKill() && "We need the index register as scratch!"); 18600b57cec5SDimitry Andric 18610b57cec5SDimitry Andric // Multiply up idx if necessary. 18620b57cec5SDimitry Andric if (!Is8Bit) 18630b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri) 18640b57cec5SDimitry Andric .addReg(Idx) 18650b57cec5SDimitry Andric .addReg(ARM::CPSR) 18660b57cec5SDimitry Andric .addReg(Idx) 18670b57cec5SDimitry Andric .addImm(1) 18680b57cec5SDimitry Andric // Add predicate operands. 18690b57cec5SDimitry Andric .addImm(ARMCC::AL) 18700b57cec5SDimitry Andric .addReg(0)); 18710b57cec5SDimitry Andric 18720b57cec5SDimitry Andric if (Base == ARM::PC) { 18730b57cec5SDimitry Andric // TBB [base, idx] = 18740b57cec5SDimitry Andric // ADDS idx, idx, base 18750b57cec5SDimitry Andric // LDRB idx, [idx, #4] ; or LDRH if TBH 18760b57cec5SDimitry Andric // LSLS idx, #1 18770b57cec5SDimitry Andric // ADDS pc, pc, idx 18780b57cec5SDimitry Andric 18790b57cec5SDimitry Andric // When using PC as the base, it's important that there is no padding 18800b57cec5SDimitry Andric // between the last ADDS and the start of the jump table. The jump table 18810b57cec5SDimitry Andric // is 4-byte aligned, so we ensure we're 4 byte aligned here too. 18820b57cec5SDimitry Andric // 18830b57cec5SDimitry Andric // FIXME: Ideally we could vary the LDRB index based on the padding 18840b57cec5SDimitry Andric // between the sequence and jump table, however that relies on MCExprs 18850b57cec5SDimitry Andric // for load indexes which are currently not supported. 1886bdd1243dSDimitry Andric OutStreamer->emitCodeAlignment(Align(4), &getSubtargetInfo()); 18870b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDhirr) 18880b57cec5SDimitry Andric .addReg(Idx) 18890b57cec5SDimitry Andric .addReg(Idx) 18900b57cec5SDimitry Andric .addReg(Base) 18910b57cec5SDimitry Andric // Add predicate operands. 18920b57cec5SDimitry Andric .addImm(ARMCC::AL) 18930b57cec5SDimitry Andric .addReg(0)); 18940b57cec5SDimitry Andric 18950b57cec5SDimitry Andric unsigned Opc = Is8Bit ? ARM::tLDRBi : ARM::tLDRHi; 18960b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(Opc) 18970b57cec5SDimitry Andric .addReg(Idx) 18980b57cec5SDimitry Andric .addReg(Idx) 18990b57cec5SDimitry Andric .addImm(Is8Bit ? 4 : 2) 19000b57cec5SDimitry Andric // Add predicate operands. 19010b57cec5SDimitry Andric .addImm(ARMCC::AL) 19020b57cec5SDimitry Andric .addReg(0)); 19030b57cec5SDimitry Andric } else { 19040b57cec5SDimitry Andric // TBB [base, idx] = 19050b57cec5SDimitry Andric // LDRB idx, [base, idx] ; or LDRH if TBH 19060b57cec5SDimitry Andric // LSLS idx, #1 19070b57cec5SDimitry Andric // ADDS pc, pc, idx 19080b57cec5SDimitry Andric 19090b57cec5SDimitry Andric unsigned Opc = Is8Bit ? ARM::tLDRBr : ARM::tLDRHr; 19100b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(Opc) 19110b57cec5SDimitry Andric .addReg(Idx) 19120b57cec5SDimitry Andric .addReg(Base) 19130b57cec5SDimitry Andric .addReg(Idx) 19140b57cec5SDimitry Andric // Add predicate operands. 19150b57cec5SDimitry Andric .addImm(ARMCC::AL) 19160b57cec5SDimitry Andric .addReg(0)); 19170b57cec5SDimitry Andric } 19180b57cec5SDimitry Andric 19190b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLSLri) 19200b57cec5SDimitry Andric .addReg(Idx) 19210b57cec5SDimitry Andric .addReg(ARM::CPSR) 19220b57cec5SDimitry Andric .addReg(Idx) 19230b57cec5SDimitry Andric .addImm(1) 19240b57cec5SDimitry Andric // Add predicate operands. 19250b57cec5SDimitry Andric .addImm(ARMCC::AL) 19260b57cec5SDimitry Andric .addReg(0)); 19270b57cec5SDimitry Andric 19285ffd83dbSDimitry Andric OutStreamer->emitLabel(GetCPISymbol(MI->getOperand(3).getImm())); 19290b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDhirr) 19300b57cec5SDimitry Andric .addReg(ARM::PC) 19310b57cec5SDimitry Andric .addReg(ARM::PC) 19320b57cec5SDimitry Andric .addReg(Idx) 19330b57cec5SDimitry Andric // Add predicate operands. 19340b57cec5SDimitry Andric .addImm(ARMCC::AL) 19350b57cec5SDimitry Andric .addReg(0)); 19360b57cec5SDimitry Andric return; 19370b57cec5SDimitry Andric } 19380b57cec5SDimitry Andric case ARM::tBR_JTr: 19390b57cec5SDimitry Andric case ARM::BR_JTr: { 19400b57cec5SDimitry Andric // mov pc, target 19410b57cec5SDimitry Andric MCInst TmpInst; 19420b57cec5SDimitry Andric unsigned Opc = MI->getOpcode() == ARM::BR_JTr ? 19430b57cec5SDimitry Andric ARM::MOVr : ARM::tMOVr; 19440b57cec5SDimitry Andric TmpInst.setOpcode(Opc); 19450b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(ARM::PC)); 19460b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); 19470b57cec5SDimitry Andric // Add predicate operands. 19480b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createImm(ARMCC::AL)); 19490b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(0)); 19500b57cec5SDimitry Andric // Add 's' bit operand (always reg0 for this) 19510b57cec5SDimitry Andric if (Opc == ARM::MOVr) 19520b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(0)); 19530b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, TmpInst); 19540b57cec5SDimitry Andric return; 19550b57cec5SDimitry Andric } 19560b57cec5SDimitry Andric case ARM::BR_JTm_i12: { 19570b57cec5SDimitry Andric // ldr pc, target 19580b57cec5SDimitry Andric MCInst TmpInst; 19590b57cec5SDimitry Andric TmpInst.setOpcode(ARM::LDRi12); 19600b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(ARM::PC)); 19610b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); 19620b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm())); 19630b57cec5SDimitry Andric // Add predicate operands. 19640b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createImm(ARMCC::AL)); 19650b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(0)); 19660b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, TmpInst); 19670b57cec5SDimitry Andric return; 19680b57cec5SDimitry Andric } 19690b57cec5SDimitry Andric case ARM::BR_JTm_rs: { 19700b57cec5SDimitry Andric // ldr pc, target 19710b57cec5SDimitry Andric MCInst TmpInst; 19720b57cec5SDimitry Andric TmpInst.setOpcode(ARM::LDRrs); 19730b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(ARM::PC)); 19740b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(MI->getOperand(0).getReg())); 19750b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(MI->getOperand(1).getReg())); 19760b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createImm(MI->getOperand(2).getImm())); 19770b57cec5SDimitry Andric // Add predicate operands. 19780b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createImm(ARMCC::AL)); 19790b57cec5SDimitry Andric TmpInst.addOperand(MCOperand::createReg(0)); 19800b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, TmpInst); 19810b57cec5SDimitry Andric return; 19820b57cec5SDimitry Andric } 19830b57cec5SDimitry Andric case ARM::BR_JTadd: { 19840b57cec5SDimitry Andric // add pc, target, idx 19850b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::ADDrr) 19860b57cec5SDimitry Andric .addReg(ARM::PC) 19870b57cec5SDimitry Andric .addReg(MI->getOperand(0).getReg()) 19880b57cec5SDimitry Andric .addReg(MI->getOperand(1).getReg()) 19890b57cec5SDimitry Andric // Add predicate operands. 19900b57cec5SDimitry Andric .addImm(ARMCC::AL) 19910b57cec5SDimitry Andric .addReg(0) 19920b57cec5SDimitry Andric // Add 's' bit operand (always reg0 for this) 19930b57cec5SDimitry Andric .addReg(0)); 19940b57cec5SDimitry Andric return; 19950b57cec5SDimitry Andric } 19960b57cec5SDimitry Andric case ARM::SPACE: 19975ffd83dbSDimitry Andric OutStreamer->emitZeros(MI->getOperand(1).getImm()); 19980b57cec5SDimitry Andric return; 19990b57cec5SDimitry Andric case ARM::TRAP: { 20000b57cec5SDimitry Andric // Non-Darwin binutils don't yet support the "trap" mnemonic. 20010b57cec5SDimitry Andric // FIXME: Remove this special case when they do. 20020b57cec5SDimitry Andric if (!Subtarget->isTargetMachO()) { 20030b57cec5SDimitry Andric uint32_t Val = 0xe7ffdefeUL; 20040b57cec5SDimitry Andric OutStreamer->AddComment("trap"); 20050b57cec5SDimitry Andric ATS.emitInst(Val); 20060b57cec5SDimitry Andric return; 20070b57cec5SDimitry Andric } 20080b57cec5SDimitry Andric break; 20090b57cec5SDimitry Andric } 20100b57cec5SDimitry Andric case ARM::TRAPNaCl: { 20110b57cec5SDimitry Andric uint32_t Val = 0xe7fedef0UL; 20120b57cec5SDimitry Andric OutStreamer->AddComment("trap"); 20130b57cec5SDimitry Andric ATS.emitInst(Val); 20140b57cec5SDimitry Andric return; 20150b57cec5SDimitry Andric } 20160b57cec5SDimitry Andric case ARM::tTRAP: { 20170b57cec5SDimitry Andric // Non-Darwin binutils don't yet support the "trap" mnemonic. 20180b57cec5SDimitry Andric // FIXME: Remove this special case when they do. 20190b57cec5SDimitry Andric if (!Subtarget->isTargetMachO()) { 20200b57cec5SDimitry Andric uint16_t Val = 0xdefe; 20210b57cec5SDimitry Andric OutStreamer->AddComment("trap"); 20220b57cec5SDimitry Andric ATS.emitInst(Val, 'n'); 20230b57cec5SDimitry Andric return; 20240b57cec5SDimitry Andric } 20250b57cec5SDimitry Andric break; 20260b57cec5SDimitry Andric } 20270b57cec5SDimitry Andric case ARM::t2Int_eh_sjlj_setjmp: 20280b57cec5SDimitry Andric case ARM::t2Int_eh_sjlj_setjmp_nofp: 20290b57cec5SDimitry Andric case ARM::tInt_eh_sjlj_setjmp: { 20300b57cec5SDimitry Andric // Two incoming args: GPR:$src, GPR:$val 20310b57cec5SDimitry Andric // mov $val, pc 20320b57cec5SDimitry Andric // adds $val, #7 20330b57cec5SDimitry Andric // str $val, [$src, #4] 20340b57cec5SDimitry Andric // movs r0, #0 20350b57cec5SDimitry Andric // b LSJLJEH 20360b57cec5SDimitry Andric // movs r0, #1 20370b57cec5SDimitry Andric // LSJLJEH: 20388bcb0991SDimitry Andric Register SrcReg = MI->getOperand(0).getReg(); 20398bcb0991SDimitry Andric Register ValReg = MI->getOperand(1).getReg(); 2040e8d8bef9SDimitry Andric MCSymbol *Label = OutContext.createTempSymbol("SJLJEH"); 20410b57cec5SDimitry Andric OutStreamer->AddComment("eh_setjmp begin"); 20420b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr) 20430b57cec5SDimitry Andric .addReg(ValReg) 20440b57cec5SDimitry Andric .addReg(ARM::PC) 20450b57cec5SDimitry Andric // Predicate. 20460b57cec5SDimitry Andric .addImm(ARMCC::AL) 20470b57cec5SDimitry Andric .addReg(0)); 20480b57cec5SDimitry Andric 20490b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tADDi3) 20500b57cec5SDimitry Andric .addReg(ValReg) 20510b57cec5SDimitry Andric // 's' bit operand 20520b57cec5SDimitry Andric .addReg(ARM::CPSR) 20530b57cec5SDimitry Andric .addReg(ValReg) 20540b57cec5SDimitry Andric .addImm(7) 20550b57cec5SDimitry Andric // Predicate. 20560b57cec5SDimitry Andric .addImm(ARMCC::AL) 20570b57cec5SDimitry Andric .addReg(0)); 20580b57cec5SDimitry Andric 20590b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tSTRi) 20600b57cec5SDimitry Andric .addReg(ValReg) 20610b57cec5SDimitry Andric .addReg(SrcReg) 20620b57cec5SDimitry Andric // The offset immediate is #4. The operand value is scaled by 4 for the 20630b57cec5SDimitry Andric // tSTR instruction. 20640b57cec5SDimitry Andric .addImm(1) 20650b57cec5SDimitry Andric // Predicate. 20660b57cec5SDimitry Andric .addImm(ARMCC::AL) 20670b57cec5SDimitry Andric .addReg(0)); 20680b57cec5SDimitry Andric 20690b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVi8) 20700b57cec5SDimitry Andric .addReg(ARM::R0) 20710b57cec5SDimitry Andric .addReg(ARM::CPSR) 20720b57cec5SDimitry Andric .addImm(0) 20730b57cec5SDimitry Andric // Predicate. 20740b57cec5SDimitry Andric .addImm(ARMCC::AL) 20750b57cec5SDimitry Andric .addReg(0)); 20760b57cec5SDimitry Andric 20770b57cec5SDimitry Andric const MCExpr *SymbolExpr = MCSymbolRefExpr::create(Label, OutContext); 20780b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tB) 20790b57cec5SDimitry Andric .addExpr(SymbolExpr) 20800b57cec5SDimitry Andric .addImm(ARMCC::AL) 20810b57cec5SDimitry Andric .addReg(0)); 20820b57cec5SDimitry Andric 20830b57cec5SDimitry Andric OutStreamer->AddComment("eh_setjmp end"); 20840b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVi8) 20850b57cec5SDimitry Andric .addReg(ARM::R0) 20860b57cec5SDimitry Andric .addReg(ARM::CPSR) 20870b57cec5SDimitry Andric .addImm(1) 20880b57cec5SDimitry Andric // Predicate. 20890b57cec5SDimitry Andric .addImm(ARMCC::AL) 20900b57cec5SDimitry Andric .addReg(0)); 20910b57cec5SDimitry Andric 20925ffd83dbSDimitry Andric OutStreamer->emitLabel(Label); 20930b57cec5SDimitry Andric return; 20940b57cec5SDimitry Andric } 20950b57cec5SDimitry Andric 20960b57cec5SDimitry Andric case ARM::Int_eh_sjlj_setjmp_nofp: 20970b57cec5SDimitry Andric case ARM::Int_eh_sjlj_setjmp: { 20980b57cec5SDimitry Andric // Two incoming args: GPR:$src, GPR:$val 20990b57cec5SDimitry Andric // add $val, pc, #8 21000b57cec5SDimitry Andric // str $val, [$src, #+4] 21010b57cec5SDimitry Andric // mov r0, #0 21020b57cec5SDimitry Andric // add pc, pc, #0 21030b57cec5SDimitry Andric // mov r0, #1 21048bcb0991SDimitry Andric Register SrcReg = MI->getOperand(0).getReg(); 21058bcb0991SDimitry Andric Register ValReg = MI->getOperand(1).getReg(); 21060b57cec5SDimitry Andric 21070b57cec5SDimitry Andric OutStreamer->AddComment("eh_setjmp begin"); 21080b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::ADDri) 21090b57cec5SDimitry Andric .addReg(ValReg) 21100b57cec5SDimitry Andric .addReg(ARM::PC) 21110b57cec5SDimitry Andric .addImm(8) 21120b57cec5SDimitry Andric // Predicate. 21130b57cec5SDimitry Andric .addImm(ARMCC::AL) 21140b57cec5SDimitry Andric .addReg(0) 21150b57cec5SDimitry Andric // 's' bit operand (always reg0 for this). 21160b57cec5SDimitry Andric .addReg(0)); 21170b57cec5SDimitry Andric 21180b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::STRi12) 21190b57cec5SDimitry Andric .addReg(ValReg) 21200b57cec5SDimitry Andric .addReg(SrcReg) 21210b57cec5SDimitry Andric .addImm(4) 21220b57cec5SDimitry Andric // Predicate. 21230b57cec5SDimitry Andric .addImm(ARMCC::AL) 21240b57cec5SDimitry Andric .addReg(0)); 21250b57cec5SDimitry Andric 21260b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVi) 21270b57cec5SDimitry Andric .addReg(ARM::R0) 21280b57cec5SDimitry Andric .addImm(0) 21290b57cec5SDimitry Andric // Predicate. 21300b57cec5SDimitry Andric .addImm(ARMCC::AL) 21310b57cec5SDimitry Andric .addReg(0) 21320b57cec5SDimitry Andric // 's' bit operand (always reg0 for this). 21330b57cec5SDimitry Andric .addReg(0)); 21340b57cec5SDimitry Andric 21350b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::ADDri) 21360b57cec5SDimitry Andric .addReg(ARM::PC) 21370b57cec5SDimitry Andric .addReg(ARM::PC) 21380b57cec5SDimitry Andric .addImm(0) 21390b57cec5SDimitry Andric // Predicate. 21400b57cec5SDimitry Andric .addImm(ARMCC::AL) 21410b57cec5SDimitry Andric .addReg(0) 21420b57cec5SDimitry Andric // 's' bit operand (always reg0 for this). 21430b57cec5SDimitry Andric .addReg(0)); 21440b57cec5SDimitry Andric 21450b57cec5SDimitry Andric OutStreamer->AddComment("eh_setjmp end"); 21460b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::MOVi) 21470b57cec5SDimitry Andric .addReg(ARM::R0) 21480b57cec5SDimitry Andric .addImm(1) 21490b57cec5SDimitry Andric // Predicate. 21500b57cec5SDimitry Andric .addImm(ARMCC::AL) 21510b57cec5SDimitry Andric .addReg(0) 21520b57cec5SDimitry Andric // 's' bit operand (always reg0 for this). 21530b57cec5SDimitry Andric .addReg(0)); 21540b57cec5SDimitry Andric return; 21550b57cec5SDimitry Andric } 21560b57cec5SDimitry Andric case ARM::Int_eh_sjlj_longjmp: { 21570b57cec5SDimitry Andric // ldr sp, [$src, #8] 21580b57cec5SDimitry Andric // ldr $scratch, [$src, #4] 21590b57cec5SDimitry Andric // ldr r7, [$src] 21600b57cec5SDimitry Andric // bx $scratch 21618bcb0991SDimitry Andric Register SrcReg = MI->getOperand(0).getReg(); 21628bcb0991SDimitry Andric Register ScratchReg = MI->getOperand(1).getReg(); 21630b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12) 21640b57cec5SDimitry Andric .addReg(ARM::SP) 21650b57cec5SDimitry Andric .addReg(SrcReg) 21660b57cec5SDimitry Andric .addImm(8) 21670b57cec5SDimitry Andric // Predicate. 21680b57cec5SDimitry Andric .addImm(ARMCC::AL) 21690b57cec5SDimitry Andric .addReg(0)); 21700b57cec5SDimitry Andric 21710b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12) 21720b57cec5SDimitry Andric .addReg(ScratchReg) 21730b57cec5SDimitry Andric .addReg(SrcReg) 21740b57cec5SDimitry Andric .addImm(4) 21750b57cec5SDimitry Andric // Predicate. 21760b57cec5SDimitry Andric .addImm(ARMCC::AL) 21770b57cec5SDimitry Andric .addReg(0)); 21780b57cec5SDimitry Andric 2179349cc55cSDimitry Andric const MachineFunction &MF = *MI->getParent()->getParent(); 2180349cc55cSDimitry Andric const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>(); 2181349cc55cSDimitry Andric 21820b57cec5SDimitry Andric if (STI.isTargetDarwin() || STI.isTargetWindows()) { 21830b57cec5SDimitry Andric // These platforms always use the same frame register 21840b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12) 2185fe6060f1SDimitry Andric .addReg(STI.getFramePointerReg()) 21860b57cec5SDimitry Andric .addReg(SrcReg) 21870b57cec5SDimitry Andric .addImm(0) 21880b57cec5SDimitry Andric // Predicate. 21890b57cec5SDimitry Andric .addImm(ARMCC::AL) 21900b57cec5SDimitry Andric .addReg(0)); 21910b57cec5SDimitry Andric } else { 21920b57cec5SDimitry Andric // If the calling code might use either R7 or R11 as 21930b57cec5SDimitry Andric // frame pointer register, restore it into both. 21940b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12) 21950b57cec5SDimitry Andric .addReg(ARM::R7) 21960b57cec5SDimitry Andric .addReg(SrcReg) 21970b57cec5SDimitry Andric .addImm(0) 21980b57cec5SDimitry Andric // Predicate. 21990b57cec5SDimitry Andric .addImm(ARMCC::AL) 22000b57cec5SDimitry Andric .addReg(0)); 22010b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::LDRi12) 22020b57cec5SDimitry Andric .addReg(ARM::R11) 22030b57cec5SDimitry Andric .addReg(SrcReg) 22040b57cec5SDimitry Andric .addImm(0) 22050b57cec5SDimitry Andric // Predicate. 22060b57cec5SDimitry Andric .addImm(ARMCC::AL) 22070b57cec5SDimitry Andric .addReg(0)); 22080b57cec5SDimitry Andric } 22090b57cec5SDimitry Andric 22100b57cec5SDimitry Andric assert(Subtarget->hasV4TOps()); 22110b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::BX) 22120b57cec5SDimitry Andric .addReg(ScratchReg) 22130b57cec5SDimitry Andric // Predicate. 22140b57cec5SDimitry Andric .addImm(ARMCC::AL) 22150b57cec5SDimitry Andric .addReg(0)); 22160b57cec5SDimitry Andric return; 22170b57cec5SDimitry Andric } 22180b57cec5SDimitry Andric case ARM::tInt_eh_sjlj_longjmp: { 22190b57cec5SDimitry Andric // ldr $scratch, [$src, #8] 22200b57cec5SDimitry Andric // mov sp, $scratch 22210b57cec5SDimitry Andric // ldr $scratch, [$src, #4] 22220b57cec5SDimitry Andric // ldr r7, [$src] 22230b57cec5SDimitry Andric // bx $scratch 22248bcb0991SDimitry Andric Register SrcReg = MI->getOperand(0).getReg(); 22258bcb0991SDimitry Andric Register ScratchReg = MI->getOperand(1).getReg(); 22260b57cec5SDimitry Andric 2227349cc55cSDimitry Andric const MachineFunction &MF = *MI->getParent()->getParent(); 2228349cc55cSDimitry Andric const ARMSubtarget &STI = MF.getSubtarget<ARMSubtarget>(); 2229349cc55cSDimitry Andric 22300b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi) 22310b57cec5SDimitry Andric .addReg(ScratchReg) 22320b57cec5SDimitry Andric .addReg(SrcReg) 22330b57cec5SDimitry Andric // The offset immediate is #8. The operand value is scaled by 4 for the 22340b57cec5SDimitry Andric // tLDR instruction. 22350b57cec5SDimitry Andric .addImm(2) 22360b57cec5SDimitry Andric // Predicate. 22370b57cec5SDimitry Andric .addImm(ARMCC::AL) 22380b57cec5SDimitry Andric .addReg(0)); 22390b57cec5SDimitry Andric 22400b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tMOVr) 22410b57cec5SDimitry Andric .addReg(ARM::SP) 22420b57cec5SDimitry Andric .addReg(ScratchReg) 22430b57cec5SDimitry Andric // Predicate. 22440b57cec5SDimitry Andric .addImm(ARMCC::AL) 22450b57cec5SDimitry Andric .addReg(0)); 22460b57cec5SDimitry Andric 22470b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi) 22480b57cec5SDimitry Andric .addReg(ScratchReg) 22490b57cec5SDimitry Andric .addReg(SrcReg) 22500b57cec5SDimitry Andric .addImm(1) 22510b57cec5SDimitry Andric // Predicate. 22520b57cec5SDimitry Andric .addImm(ARMCC::AL) 22530b57cec5SDimitry Andric .addReg(0)); 22540b57cec5SDimitry Andric 22550b57cec5SDimitry Andric if (STI.isTargetDarwin() || STI.isTargetWindows()) { 22560b57cec5SDimitry Andric // These platforms always use the same frame register 22570b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi) 2258fe6060f1SDimitry Andric .addReg(STI.getFramePointerReg()) 22590b57cec5SDimitry Andric .addReg(SrcReg) 22600b57cec5SDimitry Andric .addImm(0) 22610b57cec5SDimitry Andric // Predicate. 22620b57cec5SDimitry Andric .addImm(ARMCC::AL) 22630b57cec5SDimitry Andric .addReg(0)); 22640b57cec5SDimitry Andric } else { 22650b57cec5SDimitry Andric // If the calling code might use either R7 or R11 as 22660b57cec5SDimitry Andric // frame pointer register, restore it into both. 22670b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi) 22680b57cec5SDimitry Andric .addReg(ARM::R7) 22690b57cec5SDimitry Andric .addReg(SrcReg) 22700b57cec5SDimitry Andric .addImm(0) 22710b57cec5SDimitry Andric // Predicate. 22720b57cec5SDimitry Andric .addImm(ARMCC::AL) 22730b57cec5SDimitry Andric .addReg(0)); 22740b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tLDRi) 22750b57cec5SDimitry Andric .addReg(ARM::R11) 22760b57cec5SDimitry Andric .addReg(SrcReg) 22770b57cec5SDimitry Andric .addImm(0) 22780b57cec5SDimitry Andric // Predicate. 22790b57cec5SDimitry Andric .addImm(ARMCC::AL) 22800b57cec5SDimitry Andric .addReg(0)); 22810b57cec5SDimitry Andric } 22820b57cec5SDimitry Andric 22830b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::tBX) 22840b57cec5SDimitry Andric .addReg(ScratchReg) 22850b57cec5SDimitry Andric // Predicate. 22860b57cec5SDimitry Andric .addImm(ARMCC::AL) 22870b57cec5SDimitry Andric .addReg(0)); 22880b57cec5SDimitry Andric return; 22890b57cec5SDimitry Andric } 22900b57cec5SDimitry Andric case ARM::tInt_WIN_eh_sjlj_longjmp: { 22910b57cec5SDimitry Andric // ldr.w r11, [$src, #0] 22920b57cec5SDimitry Andric // ldr.w sp, [$src, #8] 22930b57cec5SDimitry Andric // ldr.w pc, [$src, #4] 22940b57cec5SDimitry Andric 22958bcb0991SDimitry Andric Register SrcReg = MI->getOperand(0).getReg(); 22960b57cec5SDimitry Andric 22970b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi12) 22980b57cec5SDimitry Andric .addReg(ARM::R11) 22990b57cec5SDimitry Andric .addReg(SrcReg) 23000b57cec5SDimitry Andric .addImm(0) 23010b57cec5SDimitry Andric // Predicate 23020b57cec5SDimitry Andric .addImm(ARMCC::AL) 23030b57cec5SDimitry Andric .addReg(0)); 23040b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi12) 23050b57cec5SDimitry Andric .addReg(ARM::SP) 23060b57cec5SDimitry Andric .addReg(SrcReg) 23070b57cec5SDimitry Andric .addImm(8) 23080b57cec5SDimitry Andric // Predicate 23090b57cec5SDimitry Andric .addImm(ARMCC::AL) 23100b57cec5SDimitry Andric .addReg(0)); 23110b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, MCInstBuilder(ARM::t2LDRi12) 23120b57cec5SDimitry Andric .addReg(ARM::PC) 23130b57cec5SDimitry Andric .addReg(SrcReg) 23140b57cec5SDimitry Andric .addImm(4) 23150b57cec5SDimitry Andric // Predicate 23160b57cec5SDimitry Andric .addImm(ARMCC::AL) 23170b57cec5SDimitry Andric .addReg(0)); 23180b57cec5SDimitry Andric return; 23190b57cec5SDimitry Andric } 23200b57cec5SDimitry Andric case ARM::PATCHABLE_FUNCTION_ENTER: 23210b57cec5SDimitry Andric LowerPATCHABLE_FUNCTION_ENTER(*MI); 23220b57cec5SDimitry Andric return; 23230b57cec5SDimitry Andric case ARM::PATCHABLE_FUNCTION_EXIT: 23240b57cec5SDimitry Andric LowerPATCHABLE_FUNCTION_EXIT(*MI); 23250b57cec5SDimitry Andric return; 23260b57cec5SDimitry Andric case ARM::PATCHABLE_TAIL_CALL: 23270b57cec5SDimitry Andric LowerPATCHABLE_TAIL_CALL(*MI); 23280b57cec5SDimitry Andric return; 2329e8d8bef9SDimitry Andric case ARM::SpeculationBarrierISBDSBEndBB: { 2330e8d8bef9SDimitry Andric // Print DSB SYS + ISB 2331e8d8bef9SDimitry Andric MCInst TmpInstDSB; 2332e8d8bef9SDimitry Andric TmpInstDSB.setOpcode(ARM::DSB); 2333e8d8bef9SDimitry Andric TmpInstDSB.addOperand(MCOperand::createImm(0xf)); 2334e8d8bef9SDimitry Andric EmitToStreamer(*OutStreamer, TmpInstDSB); 2335e8d8bef9SDimitry Andric MCInst TmpInstISB; 2336e8d8bef9SDimitry Andric TmpInstISB.setOpcode(ARM::ISB); 2337e8d8bef9SDimitry Andric TmpInstISB.addOperand(MCOperand::createImm(0xf)); 2338e8d8bef9SDimitry Andric EmitToStreamer(*OutStreamer, TmpInstISB); 2339e8d8bef9SDimitry Andric return; 2340e8d8bef9SDimitry Andric } 2341e8d8bef9SDimitry Andric case ARM::t2SpeculationBarrierISBDSBEndBB: { 2342e8d8bef9SDimitry Andric // Print DSB SYS + ISB 2343e8d8bef9SDimitry Andric MCInst TmpInstDSB; 2344e8d8bef9SDimitry Andric TmpInstDSB.setOpcode(ARM::t2DSB); 2345e8d8bef9SDimitry Andric TmpInstDSB.addOperand(MCOperand::createImm(0xf)); 2346e8d8bef9SDimitry Andric TmpInstDSB.addOperand(MCOperand::createImm(ARMCC::AL)); 2347e8d8bef9SDimitry Andric TmpInstDSB.addOperand(MCOperand::createReg(0)); 2348e8d8bef9SDimitry Andric EmitToStreamer(*OutStreamer, TmpInstDSB); 2349e8d8bef9SDimitry Andric MCInst TmpInstISB; 2350e8d8bef9SDimitry Andric TmpInstISB.setOpcode(ARM::t2ISB); 2351e8d8bef9SDimitry Andric TmpInstISB.addOperand(MCOperand::createImm(0xf)); 2352e8d8bef9SDimitry Andric TmpInstISB.addOperand(MCOperand::createImm(ARMCC::AL)); 2353e8d8bef9SDimitry Andric TmpInstISB.addOperand(MCOperand::createReg(0)); 2354e8d8bef9SDimitry Andric EmitToStreamer(*OutStreamer, TmpInstISB); 2355e8d8bef9SDimitry Andric return; 2356e8d8bef9SDimitry Andric } 2357e8d8bef9SDimitry Andric case ARM::SpeculationBarrierSBEndBB: { 2358e8d8bef9SDimitry Andric // Print SB 2359e8d8bef9SDimitry Andric MCInst TmpInstSB; 2360e8d8bef9SDimitry Andric TmpInstSB.setOpcode(ARM::SB); 2361e8d8bef9SDimitry Andric EmitToStreamer(*OutStreamer, TmpInstSB); 2362e8d8bef9SDimitry Andric return; 2363e8d8bef9SDimitry Andric } 2364e8d8bef9SDimitry Andric case ARM::t2SpeculationBarrierSBEndBB: { 2365e8d8bef9SDimitry Andric // Print SB 2366e8d8bef9SDimitry Andric MCInst TmpInstSB; 2367e8d8bef9SDimitry Andric TmpInstSB.setOpcode(ARM::t2SB); 2368e8d8bef9SDimitry Andric EmitToStreamer(*OutStreamer, TmpInstSB); 2369e8d8bef9SDimitry Andric return; 2370e8d8bef9SDimitry Andric } 237181ad6265SDimitry Andric 237281ad6265SDimitry Andric case ARM::SEH_StackAlloc: 237381ad6265SDimitry Andric ATS.emitARMWinCFIAllocStack(MI->getOperand(0).getImm(), 237481ad6265SDimitry Andric MI->getOperand(1).getImm()); 237581ad6265SDimitry Andric return; 237681ad6265SDimitry Andric 237781ad6265SDimitry Andric case ARM::SEH_SaveRegs: 237881ad6265SDimitry Andric case ARM::SEH_SaveRegs_Ret: 237981ad6265SDimitry Andric ATS.emitARMWinCFISaveRegMask(MI->getOperand(0).getImm(), 238081ad6265SDimitry Andric MI->getOperand(1).getImm()); 238181ad6265SDimitry Andric return; 238281ad6265SDimitry Andric 238381ad6265SDimitry Andric case ARM::SEH_SaveSP: 238481ad6265SDimitry Andric ATS.emitARMWinCFISaveSP(MI->getOperand(0).getImm()); 238581ad6265SDimitry Andric return; 238681ad6265SDimitry Andric 238781ad6265SDimitry Andric case ARM::SEH_SaveFRegs: 238881ad6265SDimitry Andric ATS.emitARMWinCFISaveFRegs(MI->getOperand(0).getImm(), 238981ad6265SDimitry Andric MI->getOperand(1).getImm()); 239081ad6265SDimitry Andric return; 239181ad6265SDimitry Andric 239281ad6265SDimitry Andric case ARM::SEH_SaveLR: 239381ad6265SDimitry Andric ATS.emitARMWinCFISaveLR(MI->getOperand(0).getImm()); 239481ad6265SDimitry Andric return; 239581ad6265SDimitry Andric 239681ad6265SDimitry Andric case ARM::SEH_Nop: 239781ad6265SDimitry Andric case ARM::SEH_Nop_Ret: 239881ad6265SDimitry Andric ATS.emitARMWinCFINop(MI->getOperand(0).getImm()); 239981ad6265SDimitry Andric return; 240081ad6265SDimitry Andric 240181ad6265SDimitry Andric case ARM::SEH_PrologEnd: 240281ad6265SDimitry Andric ATS.emitARMWinCFIPrologEnd(/*Fragment=*/false); 240381ad6265SDimitry Andric return; 240481ad6265SDimitry Andric 240581ad6265SDimitry Andric case ARM::SEH_EpilogStart: 240681ad6265SDimitry Andric ATS.emitARMWinCFIEpilogStart(ARMCC::AL); 240781ad6265SDimitry Andric return; 240881ad6265SDimitry Andric 240981ad6265SDimitry Andric case ARM::SEH_EpilogEnd: 241081ad6265SDimitry Andric ATS.emitARMWinCFIEpilogEnd(); 241181ad6265SDimitry Andric return; 24120fca6ea1SDimitry Andric 24130fca6ea1SDimitry Andric case ARM::PseudoARMInitUndefMQPR: 24140fca6ea1SDimitry Andric case ARM::PseudoARMInitUndefSPR: 24150fca6ea1SDimitry Andric case ARM::PseudoARMInitUndefDPR_VFP2: 24160fca6ea1SDimitry Andric case ARM::PseudoARMInitUndefGPR: 24170fca6ea1SDimitry Andric return; 24180b57cec5SDimitry Andric } 24190b57cec5SDimitry Andric 24200b57cec5SDimitry Andric MCInst TmpInst; 24210b57cec5SDimitry Andric LowerARMMachineInstrToMCInst(MI, TmpInst, *this); 24220b57cec5SDimitry Andric 24230b57cec5SDimitry Andric EmitToStreamer(*OutStreamer, TmpInst); 24240b57cec5SDimitry Andric } 24250b57cec5SDimitry Andric 24260b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 24270b57cec5SDimitry Andric // Target Registry Stuff 24280b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 24290b57cec5SDimitry Andric 24300b57cec5SDimitry Andric // Force static initialization. 2431480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeARMAsmPrinter() { 24320b57cec5SDimitry Andric RegisterAsmPrinter<ARMAsmPrinter> X(getTheARMLETarget()); 24330b57cec5SDimitry Andric RegisterAsmPrinter<ARMAsmPrinter> Y(getTheARMBETarget()); 24340b57cec5SDimitry Andric RegisterAsmPrinter<ARMAsmPrinter> A(getTheThumbLETarget()); 24350b57cec5SDimitry Andric RegisterAsmPrinter<ARMAsmPrinter> B(getTheThumbBETarget()); 24360b57cec5SDimitry Andric } 2437