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
ARMAsmPrinter(TargetMachine & TM,std::unique_ptr<MCStreamer> Streamer)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
emitFunctionBodyEnd()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
emitFunctionEntryLabel()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
emitXXStructor(const DataLayout & DL,const Constant * CV)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
emitGlobalVariable(const GlobalVariable * GV)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 ///
runOnMachineFunction(MachineFunction & MF)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
PrintSymbolOperand(const MachineOperand & MO,raw_ostream & O)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
printOperand(const MachineInstr * MI,int OpNum,raw_ostream & O)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
GetCPISymbol(unsigned CPID) const2660b57cec5SDimitry 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::
GetARMJTIPICJumpTableLabel(unsigned uid) const2780b57cec5SDimitry 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
PrintAsmOperand(const MachineInstr * MI,unsigned OpNum,const char * ExtraCode,raw_ostream & O)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
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNum,const char * ExtraCode,raw_ostream & O)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
isThumb(const MCSubtargetInfo & STI)4850b57cec5SDimitry Andric static bool isThumb(const MCSubtargetInfo& STI) {
48606c3fb27SDimitry Andric return STI.hasFeature(ARM::ModeThumb);
4870b57cec5SDimitry Andric }
4880b57cec5SDimitry Andric
emitInlineAsmEnd(const MCSubtargetInfo & StartInfo,const MCSubtargetInfo * EndInfo) const4890b57cec5SDimitry 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
emitStartOfAsmFile(Module & M)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
emitNonLazySymbolPointer(MCStreamer & OutStreamer,MCSymbol * StubLabel,MachineModuleInfoImpl::StubValueTy & MCSym)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
emitEndOfAsmFile(Module & M)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.
checkFunctionsAttributeConsistency(const Module & M,StringRef Attr,StringRef Value)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.
checkDenormalAttributeConsistency(const Module & M,StringRef Attr,DenormalMode Value)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
emitAttributes()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
getBFLabel(StringRef Prefix,unsigned FunctionNumber,unsigned LabelId,MCContext & Ctx)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
getPICLabel(StringRef Prefix,unsigned FunctionNumber,unsigned LabelId,MCContext & Ctx)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
getModifierVariantKind(ARMCP::ARMCPModifier Modifier)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
GetARMGVSymbol(const GlobalValue * GV,unsigned char TargetFlags)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
emitMachineConstantPoolValue(MachineConstantPoolValue * MCPV)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
emitJumpTableAddrs(const MachineInstr * MI)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
emitJumpTableInsts(const MachineInstr * MI)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
emitJumpTableTBInst(const MachineInstr * MI,unsigned OffsetWidth)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>
getCodeViewJumpTableInfo(int JTI,const MachineInstr * BranchInstr,const MCSymbol * BranchLabel) const11235f757f3fSDimitry 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
EmitUnwindingInstruction(const MachineInstr * MI)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
emitInstruction(const MachineInstr * MI)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.
LLVMInitializeARMAsmPrinter()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