xref: /minix3/external/bsd/llvm/dist/llvm/lib/Target/ARM/ARMAsmPrinter.cpp (revision 0a6a1f1d05b60e214de2f05a7310ddd1f0e590e7)
1f4a2713aSLionel Sambuc //===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===//
2f4a2713aSLionel Sambuc //
3f4a2713aSLionel Sambuc //                     The LLVM Compiler Infrastructure
4f4a2713aSLionel Sambuc //
5f4a2713aSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6f4a2713aSLionel Sambuc // License. See LICENSE.TXT for details.
7f4a2713aSLionel Sambuc //
8f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
9f4a2713aSLionel Sambuc //
10f4a2713aSLionel Sambuc // This file contains a printer that converts from our internal representation
11f4a2713aSLionel Sambuc // of machine-dependent LLVM code to GAS-format ARM assembly language.
12f4a2713aSLionel Sambuc //
13f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
14f4a2713aSLionel Sambuc 
15f4a2713aSLionel Sambuc #include "ARMAsmPrinter.h"
16f4a2713aSLionel Sambuc #include "ARM.h"
17f4a2713aSLionel Sambuc #include "ARMConstantPoolValue.h"
18f4a2713aSLionel Sambuc #include "ARMFPUName.h"
19f4a2713aSLionel Sambuc #include "ARMMachineFunctionInfo.h"
20f4a2713aSLionel Sambuc #include "ARMTargetMachine.h"
21f4a2713aSLionel Sambuc #include "ARMTargetObjectFile.h"
22f4a2713aSLionel Sambuc #include "InstPrinter/ARMInstPrinter.h"
23f4a2713aSLionel Sambuc #include "MCTargetDesc/ARMAddressingModes.h"
24f4a2713aSLionel Sambuc #include "MCTargetDesc/ARMMCExpr.h"
25f4a2713aSLionel Sambuc #include "llvm/ADT/SetVector.h"
26f4a2713aSLionel Sambuc #include "llvm/ADT/SmallString.h"
27f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineFunctionPass.h"
28f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineJumpTableInfo.h"
29f4a2713aSLionel Sambuc #include "llvm/CodeGen/MachineModuleInfoImpls.h"
30f4a2713aSLionel Sambuc #include "llvm/IR/Constants.h"
31f4a2713aSLionel Sambuc #include "llvm/IR/DataLayout.h"
32*0a6a1f1dSLionel Sambuc #include "llvm/IR/DebugInfo.h"
33*0a6a1f1dSLionel Sambuc #include "llvm/IR/Mangler.h"
34f4a2713aSLionel Sambuc #include "llvm/IR/Module.h"
35f4a2713aSLionel Sambuc #include "llvm/IR/Type.h"
36f4a2713aSLionel Sambuc #include "llvm/MC/MCAsmInfo.h"
37f4a2713aSLionel Sambuc #include "llvm/MC/MCAssembler.h"
38f4a2713aSLionel Sambuc #include "llvm/MC/MCContext.h"
39f4a2713aSLionel Sambuc #include "llvm/MC/MCELFStreamer.h"
40f4a2713aSLionel Sambuc #include "llvm/MC/MCInst.h"
41f4a2713aSLionel Sambuc #include "llvm/MC/MCInstBuilder.h"
42f4a2713aSLionel Sambuc #include "llvm/MC/MCObjectStreamer.h"
43f4a2713aSLionel Sambuc #include "llvm/MC/MCSectionMachO.h"
44f4a2713aSLionel Sambuc #include "llvm/MC/MCStreamer.h"
45f4a2713aSLionel Sambuc #include "llvm/MC/MCSymbol.h"
46*0a6a1f1dSLionel Sambuc #include "llvm/Support/ARMBuildAttributes.h"
47*0a6a1f1dSLionel Sambuc #include "llvm/Support/COFF.h"
48f4a2713aSLionel Sambuc #include "llvm/Support/CommandLine.h"
49f4a2713aSLionel Sambuc #include "llvm/Support/Debug.h"
50f4a2713aSLionel Sambuc #include "llvm/Support/ELF.h"
51f4a2713aSLionel Sambuc #include "llvm/Support/ErrorHandling.h"
52f4a2713aSLionel Sambuc #include "llvm/Support/TargetRegistry.h"
53f4a2713aSLionel Sambuc #include "llvm/Support/raw_ostream.h"
54f4a2713aSLionel Sambuc #include "llvm/Target/TargetMachine.h"
55f4a2713aSLionel Sambuc #include <cctype>
56f4a2713aSLionel Sambuc using namespace llvm;
57f4a2713aSLionel Sambuc 
58*0a6a1f1dSLionel Sambuc #define DEBUG_TYPE "asm-printer"
59f4a2713aSLionel Sambuc 
EmitFunctionBodyEnd()60f4a2713aSLionel Sambuc void ARMAsmPrinter::EmitFunctionBodyEnd() {
61f4a2713aSLionel Sambuc   // Make sure to terminate any constant pools that were at the end
62f4a2713aSLionel Sambuc   // of the function.
63f4a2713aSLionel Sambuc   if (!InConstantPool)
64f4a2713aSLionel Sambuc     return;
65f4a2713aSLionel Sambuc   InConstantPool = false;
66f4a2713aSLionel Sambuc   OutStreamer.EmitDataRegion(MCDR_DataRegionEnd);
67f4a2713aSLionel Sambuc }
68f4a2713aSLionel Sambuc 
EmitFunctionEntryLabel()69f4a2713aSLionel Sambuc void ARMAsmPrinter::EmitFunctionEntryLabel() {
70f4a2713aSLionel Sambuc   if (AFI->isThumbFunction()) {
71f4a2713aSLionel Sambuc     OutStreamer.EmitAssemblerFlag(MCAF_Code16);
72f4a2713aSLionel Sambuc     OutStreamer.EmitThumbFunc(CurrentFnSym);
73f4a2713aSLionel Sambuc   }
74f4a2713aSLionel Sambuc 
75f4a2713aSLionel Sambuc   OutStreamer.EmitLabel(CurrentFnSym);
76f4a2713aSLionel Sambuc }
77f4a2713aSLionel Sambuc 
EmitXXStructor(const Constant * CV)78f4a2713aSLionel Sambuc void ARMAsmPrinter::EmitXXStructor(const Constant *CV) {
79*0a6a1f1dSLionel Sambuc   uint64_t Size =
80*0a6a1f1dSLionel Sambuc       TM.getSubtargetImpl()->getDataLayout()->getTypeAllocSize(CV->getType());
81f4a2713aSLionel Sambuc   assert(Size && "C++ constructor pointer had zero size!");
82f4a2713aSLionel Sambuc 
83f4a2713aSLionel Sambuc   const GlobalValue *GV = dyn_cast<GlobalValue>(CV->stripPointerCasts());
84f4a2713aSLionel Sambuc   assert(GV && "C++ constructor pointer was not a GlobalValue!");
85f4a2713aSLionel Sambuc 
86*0a6a1f1dSLionel Sambuc   const MCExpr *E = MCSymbolRefExpr::Create(GetARMGVSymbol(GV,
87*0a6a1f1dSLionel Sambuc                                                            ARMII::MO_NO_FLAG),
88*0a6a1f1dSLionel Sambuc                                             (Subtarget->isTargetELF()
89*0a6a1f1dSLionel Sambuc                                              ? MCSymbolRefExpr::VK_ARM_TARGET1
90*0a6a1f1dSLionel Sambuc                                              : MCSymbolRefExpr::VK_None),
91f4a2713aSLionel Sambuc                                             OutContext);
92f4a2713aSLionel Sambuc 
93f4a2713aSLionel Sambuc   OutStreamer.EmitValue(E, Size);
94f4a2713aSLionel Sambuc }
95f4a2713aSLionel Sambuc 
96f4a2713aSLionel Sambuc /// runOnMachineFunction - This uses the EmitInstruction()
97f4a2713aSLionel Sambuc /// method to print assembly for each instruction.
98f4a2713aSLionel Sambuc ///
runOnMachineFunction(MachineFunction & MF)99f4a2713aSLionel Sambuc bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
100f4a2713aSLionel Sambuc   AFI = MF.getInfo<ARMFunctionInfo>();
101f4a2713aSLionel Sambuc   MCP = MF.getConstantPool();
102f4a2713aSLionel Sambuc 
103*0a6a1f1dSLionel Sambuc   SetupMachineFunction(MF);
104*0a6a1f1dSLionel Sambuc 
105*0a6a1f1dSLionel Sambuc   if (Subtarget->isTargetCOFF()) {
106*0a6a1f1dSLionel Sambuc     bool Internal = MF.getFunction()->hasInternalLinkage();
107*0a6a1f1dSLionel Sambuc     COFF::SymbolStorageClass Scl = Internal ? COFF::IMAGE_SYM_CLASS_STATIC
108*0a6a1f1dSLionel Sambuc                                             : COFF::IMAGE_SYM_CLASS_EXTERNAL;
109*0a6a1f1dSLionel Sambuc     int Type = COFF::IMAGE_SYM_DTYPE_FUNCTION << COFF::SCT_COMPLEX_TYPE_SHIFT;
110*0a6a1f1dSLionel Sambuc 
111*0a6a1f1dSLionel Sambuc     OutStreamer.BeginCOFFSymbolDef(CurrentFnSym);
112*0a6a1f1dSLionel Sambuc     OutStreamer.EmitCOFFSymbolStorageClass(Scl);
113*0a6a1f1dSLionel Sambuc     OutStreamer.EmitCOFFSymbolType(Type);
114*0a6a1f1dSLionel Sambuc     OutStreamer.EndCOFFSymbolDef();
115*0a6a1f1dSLionel Sambuc   }
116*0a6a1f1dSLionel Sambuc 
117*0a6a1f1dSLionel Sambuc   // Have common code print out the function header with linkage info etc.
118*0a6a1f1dSLionel Sambuc   EmitFunctionHeader();
119*0a6a1f1dSLionel Sambuc 
120*0a6a1f1dSLionel Sambuc   // Emit the rest of the function body.
121*0a6a1f1dSLionel Sambuc   EmitFunctionBody();
122*0a6a1f1dSLionel Sambuc 
123*0a6a1f1dSLionel Sambuc   // If we need V4T thumb mode Register Indirect Jump pads, emit them.
124*0a6a1f1dSLionel Sambuc   // These are created per function, rather than per TU, since it's
125*0a6a1f1dSLionel Sambuc   // relatively easy to exceed the thumb branch range within a TU.
126*0a6a1f1dSLionel Sambuc   if (! ThumbIndirectPads.empty()) {
127*0a6a1f1dSLionel Sambuc     OutStreamer.EmitAssemblerFlag(MCAF_Code16);
128*0a6a1f1dSLionel Sambuc     EmitAlignment(1);
129*0a6a1f1dSLionel Sambuc     for (unsigned i = 0, e = ThumbIndirectPads.size(); i < e; i++) {
130*0a6a1f1dSLionel Sambuc       OutStreamer.EmitLabel(ThumbIndirectPads[i].second);
131*0a6a1f1dSLionel Sambuc       EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tBX)
132*0a6a1f1dSLionel Sambuc         .addReg(ThumbIndirectPads[i].first)
133*0a6a1f1dSLionel Sambuc         // Add predicate operands.
134*0a6a1f1dSLionel Sambuc         .addImm(ARMCC::AL)
135*0a6a1f1dSLionel Sambuc         .addReg(0));
136*0a6a1f1dSLionel Sambuc     }
137*0a6a1f1dSLionel Sambuc     ThumbIndirectPads.clear();
138*0a6a1f1dSLionel Sambuc   }
139*0a6a1f1dSLionel Sambuc 
140*0a6a1f1dSLionel Sambuc   // We didn't modify anything.
141*0a6a1f1dSLionel Sambuc   return false;
142f4a2713aSLionel Sambuc }
143f4a2713aSLionel Sambuc 
printOperand(const MachineInstr * MI,int OpNum,raw_ostream & O,const char * Modifier)144f4a2713aSLionel Sambuc void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
145f4a2713aSLionel Sambuc                                  raw_ostream &O, const char *Modifier) {
146f4a2713aSLionel Sambuc   const MachineOperand &MO = MI->getOperand(OpNum);
147f4a2713aSLionel Sambuc   unsigned TF = MO.getTargetFlags();
148f4a2713aSLionel Sambuc 
149f4a2713aSLionel Sambuc   switch (MO.getType()) {
150f4a2713aSLionel Sambuc   default: llvm_unreachable("<unknown operand type>");
151f4a2713aSLionel Sambuc   case MachineOperand::MO_Register: {
152f4a2713aSLionel Sambuc     unsigned Reg = MO.getReg();
153f4a2713aSLionel Sambuc     assert(TargetRegisterInfo::isPhysicalRegister(Reg));
154f4a2713aSLionel Sambuc     assert(!MO.getSubReg() && "Subregs should be eliminated!");
155f4a2713aSLionel Sambuc     if(ARM::GPRPairRegClass.contains(Reg)) {
156f4a2713aSLionel Sambuc       const MachineFunction &MF = *MI->getParent()->getParent();
157*0a6a1f1dSLionel Sambuc       const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
158f4a2713aSLionel Sambuc       Reg = TRI->getSubReg(Reg, ARM::gsub_0);
159f4a2713aSLionel Sambuc     }
160f4a2713aSLionel Sambuc     O << ARMInstPrinter::getRegisterName(Reg);
161f4a2713aSLionel Sambuc     break;
162f4a2713aSLionel Sambuc   }
163f4a2713aSLionel Sambuc   case MachineOperand::MO_Immediate: {
164f4a2713aSLionel Sambuc     int64_t Imm = MO.getImm();
165f4a2713aSLionel Sambuc     O << '#';
166f4a2713aSLionel Sambuc     if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
167f4a2713aSLionel Sambuc         (TF == ARMII::MO_LO16))
168f4a2713aSLionel Sambuc       O << ":lower16:";
169f4a2713aSLionel Sambuc     else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
170f4a2713aSLionel Sambuc              (TF == ARMII::MO_HI16))
171f4a2713aSLionel Sambuc       O << ":upper16:";
172f4a2713aSLionel Sambuc     O << Imm;
173f4a2713aSLionel Sambuc     break;
174f4a2713aSLionel Sambuc   }
175f4a2713aSLionel Sambuc   case MachineOperand::MO_MachineBasicBlock:
176f4a2713aSLionel Sambuc     O << *MO.getMBB()->getSymbol();
177f4a2713aSLionel Sambuc     return;
178f4a2713aSLionel Sambuc   case MachineOperand::MO_GlobalAddress: {
179f4a2713aSLionel Sambuc     const GlobalValue *GV = MO.getGlobal();
180f4a2713aSLionel Sambuc     if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
181f4a2713aSLionel Sambuc         (TF & ARMII::MO_LO16))
182f4a2713aSLionel Sambuc       O << ":lower16:";
183f4a2713aSLionel Sambuc     else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
184f4a2713aSLionel Sambuc              (TF & ARMII::MO_HI16))
185f4a2713aSLionel Sambuc       O << ":upper16:";
186*0a6a1f1dSLionel Sambuc     O << *GetARMGVSymbol(GV, TF);
187f4a2713aSLionel Sambuc 
188f4a2713aSLionel Sambuc     printOffset(MO.getOffset(), O);
189f4a2713aSLionel Sambuc     if (TF == ARMII::MO_PLT)
190f4a2713aSLionel Sambuc       O << "(PLT)";
191f4a2713aSLionel Sambuc     break;
192f4a2713aSLionel Sambuc   }
193f4a2713aSLionel Sambuc   case MachineOperand::MO_ConstantPoolIndex:
194f4a2713aSLionel Sambuc     O << *GetCPISymbol(MO.getIndex());
195f4a2713aSLionel Sambuc     break;
196f4a2713aSLionel Sambuc   }
197f4a2713aSLionel Sambuc }
198f4a2713aSLionel Sambuc 
199f4a2713aSLionel Sambuc //===--------------------------------------------------------------------===//
200f4a2713aSLionel Sambuc 
201f4a2713aSLionel Sambuc MCSymbol *ARMAsmPrinter::
GetARMJTIPICJumpTableLabel2(unsigned uid,unsigned uid2) const202f4a2713aSLionel Sambuc GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const {
203*0a6a1f1dSLionel Sambuc   const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout();
204f4a2713aSLionel Sambuc   SmallString<60> Name;
205*0a6a1f1dSLionel Sambuc   raw_svector_ostream(Name) << DL->getPrivateGlobalPrefix() << "JTI"
206f4a2713aSLionel Sambuc     << getFunctionNumber() << '_' << uid << '_' << uid2;
207f4a2713aSLionel Sambuc   return OutContext.GetOrCreateSymbol(Name.str());
208f4a2713aSLionel Sambuc }
209f4a2713aSLionel Sambuc 
210f4a2713aSLionel Sambuc 
GetARMSJLJEHLabel() const211f4a2713aSLionel Sambuc MCSymbol *ARMAsmPrinter::GetARMSJLJEHLabel() const {
212*0a6a1f1dSLionel Sambuc   const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout();
213f4a2713aSLionel Sambuc   SmallString<60> Name;
214*0a6a1f1dSLionel Sambuc   raw_svector_ostream(Name) << DL->getPrivateGlobalPrefix() << "SJLJEH"
215f4a2713aSLionel Sambuc     << getFunctionNumber();
216f4a2713aSLionel Sambuc   return OutContext.GetOrCreateSymbol(Name.str());
217f4a2713aSLionel Sambuc }
218f4a2713aSLionel Sambuc 
PrintAsmOperand(const MachineInstr * MI,unsigned OpNum,unsigned AsmVariant,const char * ExtraCode,raw_ostream & O)219f4a2713aSLionel Sambuc bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
220f4a2713aSLionel Sambuc                                     unsigned AsmVariant, const char *ExtraCode,
221f4a2713aSLionel Sambuc                                     raw_ostream &O) {
222f4a2713aSLionel Sambuc   // Does this asm operand have a single letter operand modifier?
223f4a2713aSLionel Sambuc   if (ExtraCode && ExtraCode[0]) {
224f4a2713aSLionel Sambuc     if (ExtraCode[1] != 0) return true; // Unknown modifier.
225f4a2713aSLionel Sambuc 
226f4a2713aSLionel Sambuc     switch (ExtraCode[0]) {
227f4a2713aSLionel Sambuc     default:
228f4a2713aSLionel Sambuc       // See if this is a generic print operand
229f4a2713aSLionel Sambuc       return AsmPrinter::PrintAsmOperand(MI, OpNum, AsmVariant, ExtraCode, O);
230f4a2713aSLionel Sambuc     case 'a': // Print as a memory address.
231f4a2713aSLionel Sambuc       if (MI->getOperand(OpNum).isReg()) {
232f4a2713aSLionel Sambuc         O << "["
233f4a2713aSLionel Sambuc           << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg())
234f4a2713aSLionel Sambuc           << "]";
235f4a2713aSLionel Sambuc         return false;
236f4a2713aSLionel Sambuc       }
237f4a2713aSLionel Sambuc       // Fallthrough
238f4a2713aSLionel Sambuc     case 'c': // Don't print "#" before an immediate operand.
239f4a2713aSLionel Sambuc       if (!MI->getOperand(OpNum).isImm())
240f4a2713aSLionel Sambuc         return true;
241f4a2713aSLionel Sambuc       O << MI->getOperand(OpNum).getImm();
242f4a2713aSLionel Sambuc       return false;
243f4a2713aSLionel Sambuc     case 'P': // Print a VFP double precision register.
244f4a2713aSLionel Sambuc     case 'q': // Print a NEON quad precision register.
245f4a2713aSLionel Sambuc       printOperand(MI, OpNum, O);
246f4a2713aSLionel Sambuc       return false;
247f4a2713aSLionel Sambuc     case 'y': // Print a VFP single precision register as indexed double.
248f4a2713aSLionel Sambuc       if (MI->getOperand(OpNum).isReg()) {
249f4a2713aSLionel Sambuc         unsigned Reg = MI->getOperand(OpNum).getReg();
250*0a6a1f1dSLionel Sambuc         const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
251f4a2713aSLionel Sambuc         // Find the 'd' register that has this 's' register as a sub-register,
252f4a2713aSLionel Sambuc         // and determine the lane number.
253f4a2713aSLionel Sambuc         for (MCSuperRegIterator SR(Reg, TRI); SR.isValid(); ++SR) {
254f4a2713aSLionel Sambuc           if (!ARM::DPRRegClass.contains(*SR))
255f4a2713aSLionel Sambuc             continue;
256f4a2713aSLionel Sambuc           bool Lane0 = TRI->getSubReg(*SR, ARM::ssub_0) == Reg;
257f4a2713aSLionel Sambuc           O << ARMInstPrinter::getRegisterName(*SR) << (Lane0 ? "[0]" : "[1]");
258f4a2713aSLionel Sambuc           return false;
259f4a2713aSLionel Sambuc         }
260f4a2713aSLionel Sambuc       }
261f4a2713aSLionel Sambuc       return true;
262f4a2713aSLionel Sambuc     case 'B': // Bitwise inverse of integer or symbol without a preceding #.
263f4a2713aSLionel Sambuc       if (!MI->getOperand(OpNum).isImm())
264f4a2713aSLionel Sambuc         return true;
265f4a2713aSLionel Sambuc       O << ~(MI->getOperand(OpNum).getImm());
266f4a2713aSLionel Sambuc       return false;
267f4a2713aSLionel Sambuc     case 'L': // The low 16 bits of an immediate constant.
268f4a2713aSLionel Sambuc       if (!MI->getOperand(OpNum).isImm())
269f4a2713aSLionel Sambuc         return true;
270f4a2713aSLionel Sambuc       O << (MI->getOperand(OpNum).getImm() & 0xffff);
271f4a2713aSLionel Sambuc       return false;
272f4a2713aSLionel Sambuc     case 'M': { // A register range suitable for LDM/STM.
273f4a2713aSLionel Sambuc       if (!MI->getOperand(OpNum).isReg())
274f4a2713aSLionel Sambuc         return true;
275f4a2713aSLionel Sambuc       const MachineOperand &MO = MI->getOperand(OpNum);
276f4a2713aSLionel Sambuc       unsigned RegBegin = MO.getReg();
277f4a2713aSLionel Sambuc       // This takes advantage of the 2 operand-ness of ldm/stm and that we've
278f4a2713aSLionel Sambuc       // already got the operands in registers that are operands to the
279f4a2713aSLionel Sambuc       // inline asm statement.
280f4a2713aSLionel Sambuc       O << "{";
281f4a2713aSLionel Sambuc       if (ARM::GPRPairRegClass.contains(RegBegin)) {
282*0a6a1f1dSLionel Sambuc         const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
283f4a2713aSLionel Sambuc         unsigned Reg0 = TRI->getSubReg(RegBegin, ARM::gsub_0);
284*0a6a1f1dSLionel Sambuc         O << ARMInstPrinter::getRegisterName(Reg0) << ", ";
285f4a2713aSLionel Sambuc         RegBegin = TRI->getSubReg(RegBegin, ARM::gsub_1);
286f4a2713aSLionel Sambuc       }
287f4a2713aSLionel Sambuc       O << ARMInstPrinter::getRegisterName(RegBegin);
288f4a2713aSLionel Sambuc 
289f4a2713aSLionel Sambuc       // FIXME: The register allocator not only may not have given us the
290f4a2713aSLionel Sambuc       // registers in sequence, but may not be in ascending registers. This
291f4a2713aSLionel Sambuc       // will require changes in the register allocator that'll need to be
292f4a2713aSLionel Sambuc       // propagated down here if the operands change.
293f4a2713aSLionel Sambuc       unsigned RegOps = OpNum + 1;
294f4a2713aSLionel Sambuc       while (MI->getOperand(RegOps).isReg()) {
295f4a2713aSLionel Sambuc         O << ", "
296f4a2713aSLionel Sambuc           << ARMInstPrinter::getRegisterName(MI->getOperand(RegOps).getReg());
297f4a2713aSLionel Sambuc         RegOps++;
298f4a2713aSLionel Sambuc       }
299f4a2713aSLionel Sambuc 
300f4a2713aSLionel Sambuc       O << "}";
301f4a2713aSLionel Sambuc 
302f4a2713aSLionel Sambuc       return false;
303f4a2713aSLionel Sambuc     }
304f4a2713aSLionel Sambuc     case 'R': // The most significant register of a pair.
305f4a2713aSLionel Sambuc     case 'Q': { // The least significant register of a pair.
306f4a2713aSLionel Sambuc       if (OpNum == 0)
307f4a2713aSLionel Sambuc         return true;
308f4a2713aSLionel Sambuc       const MachineOperand &FlagsOP = MI->getOperand(OpNum - 1);
309f4a2713aSLionel Sambuc       if (!FlagsOP.isImm())
310f4a2713aSLionel Sambuc         return true;
311f4a2713aSLionel Sambuc       unsigned Flags = FlagsOP.getImm();
312f4a2713aSLionel Sambuc 
313f4a2713aSLionel Sambuc       // This operand may not be the one that actually provides the register. If
314f4a2713aSLionel Sambuc       // it's tied to a previous one then we should refer instead to that one
315f4a2713aSLionel Sambuc       // for registers and their classes.
316f4a2713aSLionel Sambuc       unsigned TiedIdx;
317f4a2713aSLionel Sambuc       if (InlineAsm::isUseOperandTiedToDef(Flags, TiedIdx)) {
318f4a2713aSLionel Sambuc         for (OpNum = InlineAsm::MIOp_FirstOperand; TiedIdx; --TiedIdx) {
319f4a2713aSLionel Sambuc           unsigned OpFlags = MI->getOperand(OpNum).getImm();
320f4a2713aSLionel Sambuc           OpNum += InlineAsm::getNumOperandRegisters(OpFlags) + 1;
321f4a2713aSLionel Sambuc         }
322f4a2713aSLionel Sambuc         Flags = MI->getOperand(OpNum).getImm();
323f4a2713aSLionel Sambuc 
324f4a2713aSLionel Sambuc         // Later code expects OpNum to be pointing at the register rather than
325f4a2713aSLionel Sambuc         // the flags.
326f4a2713aSLionel Sambuc         OpNum += 1;
327f4a2713aSLionel Sambuc       }
328f4a2713aSLionel Sambuc 
329f4a2713aSLionel Sambuc       unsigned NumVals = InlineAsm::getNumOperandRegisters(Flags);
330f4a2713aSLionel Sambuc       unsigned RC;
331f4a2713aSLionel Sambuc       InlineAsm::hasRegClassConstraint(Flags, RC);
332f4a2713aSLionel Sambuc       if (RC == ARM::GPRPairRegClassID) {
333f4a2713aSLionel Sambuc         if (NumVals != 1)
334f4a2713aSLionel Sambuc           return true;
335f4a2713aSLionel Sambuc         const MachineOperand &MO = MI->getOperand(OpNum);
336f4a2713aSLionel Sambuc         if (!MO.isReg())
337f4a2713aSLionel Sambuc           return true;
338*0a6a1f1dSLionel Sambuc         const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
339f4a2713aSLionel Sambuc         unsigned Reg = TRI->getSubReg(MO.getReg(), ExtraCode[0] == 'Q' ?
340f4a2713aSLionel Sambuc             ARM::gsub_0 : ARM::gsub_1);
341f4a2713aSLionel Sambuc         O << ARMInstPrinter::getRegisterName(Reg);
342f4a2713aSLionel Sambuc         return false;
343f4a2713aSLionel Sambuc       }
344f4a2713aSLionel Sambuc       if (NumVals != 2)
345f4a2713aSLionel Sambuc         return true;
346f4a2713aSLionel Sambuc       unsigned RegOp = ExtraCode[0] == 'Q' ? OpNum : OpNum + 1;
347f4a2713aSLionel Sambuc       if (RegOp >= MI->getNumOperands())
348f4a2713aSLionel Sambuc         return true;
349f4a2713aSLionel Sambuc       const MachineOperand &MO = MI->getOperand(RegOp);
350f4a2713aSLionel Sambuc       if (!MO.isReg())
351f4a2713aSLionel Sambuc         return true;
352f4a2713aSLionel Sambuc       unsigned Reg = MO.getReg();
353f4a2713aSLionel Sambuc       O << ARMInstPrinter::getRegisterName(Reg);
354f4a2713aSLionel Sambuc       return false;
355f4a2713aSLionel Sambuc     }
356f4a2713aSLionel Sambuc 
357f4a2713aSLionel Sambuc     case 'e': // The low doubleword register of a NEON quad register.
358f4a2713aSLionel Sambuc     case 'f': { // The high doubleword register of a NEON quad register.
359f4a2713aSLionel Sambuc       if (!MI->getOperand(OpNum).isReg())
360f4a2713aSLionel Sambuc         return true;
361f4a2713aSLionel Sambuc       unsigned Reg = MI->getOperand(OpNum).getReg();
362f4a2713aSLionel Sambuc       if (!ARM::QPRRegClass.contains(Reg))
363f4a2713aSLionel Sambuc         return true;
364*0a6a1f1dSLionel Sambuc       const TargetRegisterInfo *TRI = MF->getSubtarget().getRegisterInfo();
365f4a2713aSLionel Sambuc       unsigned SubReg = TRI->getSubReg(Reg, ExtraCode[0] == 'e' ?
366f4a2713aSLionel Sambuc                                        ARM::dsub_0 : ARM::dsub_1);
367f4a2713aSLionel Sambuc       O << ARMInstPrinter::getRegisterName(SubReg);
368f4a2713aSLionel Sambuc       return false;
369f4a2713aSLionel Sambuc     }
370f4a2713aSLionel Sambuc 
371f4a2713aSLionel Sambuc     // This modifier is not yet supported.
372f4a2713aSLionel Sambuc     case 'h': // A range of VFP/NEON registers suitable for VLD1/VST1.
373f4a2713aSLionel Sambuc       return true;
374f4a2713aSLionel Sambuc     case 'H': { // The highest-numbered register of a pair.
375f4a2713aSLionel Sambuc       const MachineOperand &MO = MI->getOperand(OpNum);
376f4a2713aSLionel Sambuc       if (!MO.isReg())
377f4a2713aSLionel Sambuc         return true;
378f4a2713aSLionel Sambuc       const MachineFunction &MF = *MI->getParent()->getParent();
379*0a6a1f1dSLionel Sambuc       const TargetRegisterInfo *TRI = MF.getSubtarget().getRegisterInfo();
380f4a2713aSLionel Sambuc       unsigned Reg = MO.getReg();
381f4a2713aSLionel Sambuc       if(!ARM::GPRPairRegClass.contains(Reg))
382f4a2713aSLionel Sambuc         return false;
383f4a2713aSLionel Sambuc       Reg = TRI->getSubReg(Reg, ARM::gsub_1);
384f4a2713aSLionel Sambuc       O << ARMInstPrinter::getRegisterName(Reg);
385f4a2713aSLionel Sambuc       return false;
386f4a2713aSLionel Sambuc     }
387f4a2713aSLionel Sambuc     }
388f4a2713aSLionel Sambuc   }
389f4a2713aSLionel Sambuc 
390f4a2713aSLionel Sambuc   printOperand(MI, OpNum, O);
391f4a2713aSLionel Sambuc   return false;
392f4a2713aSLionel Sambuc }
393f4a2713aSLionel Sambuc 
PrintAsmMemoryOperand(const MachineInstr * MI,unsigned OpNum,unsigned AsmVariant,const char * ExtraCode,raw_ostream & O)394f4a2713aSLionel Sambuc bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
395f4a2713aSLionel Sambuc                                           unsigned OpNum, unsigned AsmVariant,
396f4a2713aSLionel Sambuc                                           const char *ExtraCode,
397f4a2713aSLionel Sambuc                                           raw_ostream &O) {
398f4a2713aSLionel Sambuc   // Does this asm operand have a single letter operand modifier?
399f4a2713aSLionel Sambuc   if (ExtraCode && ExtraCode[0]) {
400f4a2713aSLionel Sambuc     if (ExtraCode[1] != 0) return true; // Unknown modifier.
401f4a2713aSLionel Sambuc 
402f4a2713aSLionel Sambuc     switch (ExtraCode[0]) {
403f4a2713aSLionel Sambuc       case 'A': // A memory operand for a VLD1/VST1 instruction.
404f4a2713aSLionel Sambuc       default: return true;  // Unknown modifier.
405f4a2713aSLionel Sambuc       case 'm': // The base register of a memory operand.
406f4a2713aSLionel Sambuc         if (!MI->getOperand(OpNum).isReg())
407f4a2713aSLionel Sambuc           return true;
408f4a2713aSLionel Sambuc         O << ARMInstPrinter::getRegisterName(MI->getOperand(OpNum).getReg());
409f4a2713aSLionel Sambuc         return false;
410f4a2713aSLionel Sambuc     }
411f4a2713aSLionel Sambuc   }
412f4a2713aSLionel Sambuc 
413f4a2713aSLionel Sambuc   const MachineOperand &MO = MI->getOperand(OpNum);
414f4a2713aSLionel Sambuc   assert(MO.isReg() && "unexpected inline asm memory operand");
415f4a2713aSLionel Sambuc   O << "[" << ARMInstPrinter::getRegisterName(MO.getReg()) << "]";
416f4a2713aSLionel Sambuc   return false;
417f4a2713aSLionel Sambuc }
418f4a2713aSLionel Sambuc 
isThumb(const MCSubtargetInfo & STI)419*0a6a1f1dSLionel Sambuc static bool isThumb(const MCSubtargetInfo& STI) {
420*0a6a1f1dSLionel Sambuc   return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
421*0a6a1f1dSLionel Sambuc }
422*0a6a1f1dSLionel Sambuc 
emitInlineAsmEnd(const MCSubtargetInfo & StartInfo,const MCSubtargetInfo * EndInfo) const423*0a6a1f1dSLionel Sambuc void ARMAsmPrinter::emitInlineAsmEnd(const MCSubtargetInfo &StartInfo,
424*0a6a1f1dSLionel Sambuc                                      const MCSubtargetInfo *EndInfo) const {
425*0a6a1f1dSLionel Sambuc   // If either end mode is unknown (EndInfo == NULL) or different than
426*0a6a1f1dSLionel Sambuc   // the start mode, then restore the start mode.
427*0a6a1f1dSLionel Sambuc   const bool WasThumb = isThumb(StartInfo);
428*0a6a1f1dSLionel Sambuc   if (!EndInfo || WasThumb != isThumb(*EndInfo)) {
429*0a6a1f1dSLionel Sambuc     OutStreamer.EmitAssemblerFlag(WasThumb ? MCAF_Code16 : MCAF_Code32);
430*0a6a1f1dSLionel Sambuc   }
431*0a6a1f1dSLionel Sambuc }
432*0a6a1f1dSLionel Sambuc 
EmitStartOfAsmFile(Module & M)433f4a2713aSLionel Sambuc void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) {
434*0a6a1f1dSLionel Sambuc   if (Subtarget->isTargetMachO()) {
435f4a2713aSLionel Sambuc     Reloc::Model RelocM = TM.getRelocationModel();
436f4a2713aSLionel Sambuc     if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) {
437f4a2713aSLionel Sambuc       // Declare all the text sections up front (before the DWARF sections
438f4a2713aSLionel Sambuc       // emitted by AsmPrinter::doInitialization) so the assembler will keep
439f4a2713aSLionel Sambuc       // them together at the beginning of the object file.  This helps
440f4a2713aSLionel Sambuc       // avoid out-of-range branches that are due a fundamental limitation of
441f4a2713aSLionel Sambuc       // the way symbol offsets are encoded with the current Darwin ARM
442f4a2713aSLionel Sambuc       // relocations.
443f4a2713aSLionel Sambuc       const TargetLoweringObjectFileMachO &TLOFMacho =
444f4a2713aSLionel Sambuc         static_cast<const TargetLoweringObjectFileMachO &>(
445f4a2713aSLionel Sambuc           getObjFileLowering());
446f4a2713aSLionel Sambuc 
447f4a2713aSLionel Sambuc       // Collect the set of sections our functions will go into.
448f4a2713aSLionel Sambuc       SetVector<const MCSection *, SmallVector<const MCSection *, 8>,
449f4a2713aSLionel Sambuc         SmallPtrSet<const MCSection *, 8> > TextSections;
450f4a2713aSLionel Sambuc       // Default text section comes first.
451f4a2713aSLionel Sambuc       TextSections.insert(TLOFMacho.getTextSection());
452f4a2713aSLionel Sambuc       // Now any user defined text sections from function attributes.
453f4a2713aSLionel Sambuc       for (Module::iterator F = M.begin(), e = M.end(); F != e; ++F)
454f4a2713aSLionel Sambuc         if (!F->isDeclaration() && !F->hasAvailableExternallyLinkage())
455*0a6a1f1dSLionel Sambuc           TextSections.insert(TLOFMacho.SectionForGlobal(F, *Mang, TM));
456f4a2713aSLionel Sambuc       // Now the coalescable sections.
457f4a2713aSLionel Sambuc       TextSections.insert(TLOFMacho.getTextCoalSection());
458f4a2713aSLionel Sambuc       TextSections.insert(TLOFMacho.getConstTextCoalSection());
459f4a2713aSLionel Sambuc 
460f4a2713aSLionel Sambuc       // Emit the sections in the .s file header to fix the order.
461f4a2713aSLionel Sambuc       for (unsigned i = 0, e = TextSections.size(); i != e; ++i)
462f4a2713aSLionel Sambuc         OutStreamer.SwitchSection(TextSections[i]);
463f4a2713aSLionel Sambuc 
464f4a2713aSLionel Sambuc       if (RelocM == Reloc::DynamicNoPIC) {
465f4a2713aSLionel Sambuc         const MCSection *sect =
466f4a2713aSLionel Sambuc           OutContext.getMachOSection("__TEXT", "__symbol_stub4",
467*0a6a1f1dSLionel Sambuc                                      MachO::S_SYMBOL_STUBS,
468f4a2713aSLionel Sambuc                                      12, SectionKind::getText());
469f4a2713aSLionel Sambuc         OutStreamer.SwitchSection(sect);
470f4a2713aSLionel Sambuc       } else {
471f4a2713aSLionel Sambuc         const MCSection *sect =
472f4a2713aSLionel Sambuc           OutContext.getMachOSection("__TEXT", "__picsymbolstub4",
473*0a6a1f1dSLionel Sambuc                                      MachO::S_SYMBOL_STUBS,
474f4a2713aSLionel Sambuc                                      16, SectionKind::getText());
475f4a2713aSLionel Sambuc         OutStreamer.SwitchSection(sect);
476f4a2713aSLionel Sambuc       }
477f4a2713aSLionel Sambuc       const MCSection *StaticInitSect =
478f4a2713aSLionel Sambuc         OutContext.getMachOSection("__TEXT", "__StaticInit",
479*0a6a1f1dSLionel Sambuc                                    MachO::S_REGULAR |
480*0a6a1f1dSLionel Sambuc                                    MachO::S_ATTR_PURE_INSTRUCTIONS,
481f4a2713aSLionel Sambuc                                    SectionKind::getText());
482f4a2713aSLionel Sambuc       OutStreamer.SwitchSection(StaticInitSect);
483f4a2713aSLionel Sambuc     }
484*0a6a1f1dSLionel Sambuc 
485*0a6a1f1dSLionel Sambuc     // Compiling with debug info should not affect the code
486*0a6a1f1dSLionel Sambuc     // generation.  Ensure the cstring section comes before the
487*0a6a1f1dSLionel Sambuc     // optional __DWARF secion. Otherwise, PC-relative loads would
488*0a6a1f1dSLionel Sambuc     // have to use different instruction sequences at "-g" in order to
489*0a6a1f1dSLionel Sambuc     // reach global data in the same object file.
490*0a6a1f1dSLionel Sambuc     OutStreamer.SwitchSection(getObjFileLowering().getCStringSection());
491f4a2713aSLionel Sambuc   }
492f4a2713aSLionel Sambuc 
493f4a2713aSLionel Sambuc   // Use unified assembler syntax.
494f4a2713aSLionel Sambuc   OutStreamer.EmitAssemblerFlag(MCAF_SyntaxUnified);
495f4a2713aSLionel Sambuc 
496f4a2713aSLionel Sambuc   // Emit ARM Build Attributes
497f4a2713aSLionel Sambuc   if (Subtarget->isTargetELF())
498f4a2713aSLionel Sambuc     emitAttributes();
499*0a6a1f1dSLionel Sambuc 
500*0a6a1f1dSLionel Sambuc   if (!M.getModuleInlineAsm().empty() && Subtarget->isThumb())
501*0a6a1f1dSLionel Sambuc     OutStreamer.EmitAssemblerFlag(MCAF_Code16);
502*0a6a1f1dSLionel Sambuc }
503*0a6a1f1dSLionel Sambuc 
504*0a6a1f1dSLionel Sambuc static void
emitNonLazySymbolPointer(MCStreamer & OutStreamer,MCSymbol * StubLabel,MachineModuleInfoImpl::StubValueTy & MCSym)505*0a6a1f1dSLionel Sambuc emitNonLazySymbolPointer(MCStreamer &OutStreamer, MCSymbol *StubLabel,
506*0a6a1f1dSLionel Sambuc                          MachineModuleInfoImpl::StubValueTy &MCSym) {
507*0a6a1f1dSLionel Sambuc   // L_foo$stub:
508*0a6a1f1dSLionel Sambuc   OutStreamer.EmitLabel(StubLabel);
509*0a6a1f1dSLionel Sambuc   //   .indirect_symbol _foo
510*0a6a1f1dSLionel Sambuc   OutStreamer.EmitSymbolAttribute(MCSym.getPointer(), MCSA_IndirectSymbol);
511*0a6a1f1dSLionel Sambuc 
512*0a6a1f1dSLionel Sambuc   if (MCSym.getInt())
513*0a6a1f1dSLionel Sambuc     // External to current translation unit.
514*0a6a1f1dSLionel Sambuc     OutStreamer.EmitIntValue(0, 4/*size*/);
515*0a6a1f1dSLionel Sambuc   else
516*0a6a1f1dSLionel Sambuc     // Internal to current translation unit.
517*0a6a1f1dSLionel Sambuc     //
518*0a6a1f1dSLionel Sambuc     // When we place the LSDA into the TEXT section, the type info
519*0a6a1f1dSLionel Sambuc     // pointers need to be indirect and pc-rel. We accomplish this by
520*0a6a1f1dSLionel Sambuc     // using NLPs; however, sometimes the types are local to the file.
521*0a6a1f1dSLionel Sambuc     // We need to fill in the value for the NLP in those cases.
522*0a6a1f1dSLionel Sambuc     OutStreamer.EmitValue(
523*0a6a1f1dSLionel Sambuc         MCSymbolRefExpr::Create(MCSym.getPointer(), OutStreamer.getContext()),
524*0a6a1f1dSLionel Sambuc         4 /*size*/);
525f4a2713aSLionel Sambuc }
526f4a2713aSLionel Sambuc 
527f4a2713aSLionel Sambuc 
EmitEndOfAsmFile(Module & M)528f4a2713aSLionel Sambuc void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
529*0a6a1f1dSLionel Sambuc   if (Subtarget->isTargetMachO()) {
530f4a2713aSLionel Sambuc     // All darwin targets use mach-o.
531f4a2713aSLionel Sambuc     const TargetLoweringObjectFileMachO &TLOFMacho =
532f4a2713aSLionel Sambuc       static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering());
533f4a2713aSLionel Sambuc     MachineModuleInfoMachO &MMIMacho =
534f4a2713aSLionel Sambuc       MMI->getObjFileInfo<MachineModuleInfoMachO>();
535f4a2713aSLionel Sambuc 
536f4a2713aSLionel Sambuc     // Output non-lazy-pointers for external and common global variables.
537f4a2713aSLionel Sambuc     MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList();
538f4a2713aSLionel Sambuc 
539f4a2713aSLionel Sambuc     if (!Stubs.empty()) {
540f4a2713aSLionel Sambuc       // Switch with ".non_lazy_symbol_pointer" directive.
541f4a2713aSLionel Sambuc       OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
542f4a2713aSLionel Sambuc       EmitAlignment(2);
543f4a2713aSLionel Sambuc 
544*0a6a1f1dSLionel Sambuc       for (auto &Stub : Stubs)
545*0a6a1f1dSLionel Sambuc         emitNonLazySymbolPointer(OutStreamer, Stub.first, Stub.second);
546f4a2713aSLionel Sambuc 
547f4a2713aSLionel Sambuc       Stubs.clear();
548f4a2713aSLionel Sambuc       OutStreamer.AddBlankLine();
549f4a2713aSLionel Sambuc     }
550f4a2713aSLionel Sambuc 
551f4a2713aSLionel Sambuc     Stubs = MMIMacho.GetHiddenGVStubList();
552f4a2713aSLionel Sambuc     if (!Stubs.empty()) {
553*0a6a1f1dSLionel Sambuc       OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
554f4a2713aSLionel Sambuc       EmitAlignment(2);
555*0a6a1f1dSLionel Sambuc 
556*0a6a1f1dSLionel Sambuc       for (auto &Stub : Stubs)
557*0a6a1f1dSLionel Sambuc         emitNonLazySymbolPointer(OutStreamer, Stub.first, Stub.second);
558f4a2713aSLionel Sambuc 
559f4a2713aSLionel Sambuc       Stubs.clear();
560f4a2713aSLionel Sambuc       OutStreamer.AddBlankLine();
561f4a2713aSLionel Sambuc     }
562f4a2713aSLionel Sambuc 
563f4a2713aSLionel Sambuc     // Funny Darwin hack: This flag tells the linker that no global symbols
564f4a2713aSLionel Sambuc     // contain code that falls through to other global symbols (e.g. the obvious
565f4a2713aSLionel Sambuc     // implementation of multiple entry points).  If this doesn't occur, the
566f4a2713aSLionel Sambuc     // linker can safely perform dead code stripping.  Since LLVM never
567f4a2713aSLionel Sambuc     // generates code that does this, it is always safe to set.
568f4a2713aSLionel Sambuc     OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
569f4a2713aSLionel Sambuc   }
570*0a6a1f1dSLionel Sambuc 
571*0a6a1f1dSLionel Sambuc   // Emit a .data.rel section containing any stubs that were created.
572*0a6a1f1dSLionel Sambuc   if (Subtarget->isTargetELF()) {
573*0a6a1f1dSLionel Sambuc     const TargetLoweringObjectFileELF &TLOFELF =
574*0a6a1f1dSLionel Sambuc       static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering());
575*0a6a1f1dSLionel Sambuc 
576*0a6a1f1dSLionel Sambuc     MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>();
577*0a6a1f1dSLionel Sambuc 
578*0a6a1f1dSLionel Sambuc     // Output stubs for external and common global variables.
579*0a6a1f1dSLionel Sambuc     MachineModuleInfoELF::SymbolListTy Stubs = MMIELF.GetGVStubList();
580*0a6a1f1dSLionel Sambuc     if (!Stubs.empty()) {
581*0a6a1f1dSLionel Sambuc       OutStreamer.SwitchSection(TLOFELF.getDataRelSection());
582*0a6a1f1dSLionel Sambuc       const DataLayout *TD = TM.getSubtargetImpl()->getDataLayout();
583*0a6a1f1dSLionel Sambuc 
584*0a6a1f1dSLionel Sambuc       for (auto &stub: Stubs) {
585*0a6a1f1dSLionel Sambuc         OutStreamer.EmitLabel(stub.first);
586*0a6a1f1dSLionel Sambuc         OutStreamer.EmitSymbolValue(stub.second.getPointer(),
587*0a6a1f1dSLionel Sambuc                                     TD->getPointerSize(0));
588*0a6a1f1dSLionel Sambuc       }
589*0a6a1f1dSLionel Sambuc       Stubs.clear();
590*0a6a1f1dSLionel Sambuc     }
591*0a6a1f1dSLionel Sambuc   }
592f4a2713aSLionel Sambuc }
593f4a2713aSLionel Sambuc 
594f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
595f4a2713aSLionel Sambuc // Helper routines for EmitStartOfAsmFile() and EmitEndOfAsmFile()
596f4a2713aSLionel Sambuc // FIXME:
597f4a2713aSLionel Sambuc // The following seem like one-off assembler flags, but they actually need
598f4a2713aSLionel Sambuc // to appear in the .ARM.attributes section in ELF.
599f4a2713aSLionel Sambuc // Instead of subclassing the MCELFStreamer, we do the work here.
600f4a2713aSLionel Sambuc 
getArchForCPU(StringRef CPU,const ARMSubtarget * Subtarget)601f4a2713aSLionel Sambuc static ARMBuildAttrs::CPUArch getArchForCPU(StringRef CPU,
602f4a2713aSLionel Sambuc                                             const ARMSubtarget *Subtarget) {
603f4a2713aSLionel Sambuc   if (CPU == "xscale")
604f4a2713aSLionel Sambuc     return ARMBuildAttrs::v5TEJ;
605f4a2713aSLionel Sambuc 
606f4a2713aSLionel Sambuc   if (Subtarget->hasV8Ops())
607f4a2713aSLionel Sambuc     return ARMBuildAttrs::v8;
608f4a2713aSLionel Sambuc   else if (Subtarget->hasV7Ops()) {
609f4a2713aSLionel Sambuc     if (Subtarget->isMClass() && Subtarget->hasThumb2DSP())
610f4a2713aSLionel Sambuc       return ARMBuildAttrs::v7E_M;
611f4a2713aSLionel Sambuc     return ARMBuildAttrs::v7;
612f4a2713aSLionel Sambuc   } else if (Subtarget->hasV6T2Ops())
613f4a2713aSLionel Sambuc     return ARMBuildAttrs::v6T2;
614f4a2713aSLionel Sambuc   else if (Subtarget->hasV6MOps())
615f4a2713aSLionel Sambuc     return ARMBuildAttrs::v6S_M;
616f4a2713aSLionel Sambuc   else if (Subtarget->hasV6Ops())
617f4a2713aSLionel Sambuc     return ARMBuildAttrs::v6;
618f4a2713aSLionel Sambuc   else if (Subtarget->hasV5TEOps())
619f4a2713aSLionel Sambuc     return ARMBuildAttrs::v5TE;
620f4a2713aSLionel Sambuc   else if (Subtarget->hasV5TOps())
621f4a2713aSLionel Sambuc     return ARMBuildAttrs::v5T;
622f4a2713aSLionel Sambuc   else if (Subtarget->hasV4TOps())
623f4a2713aSLionel Sambuc     return ARMBuildAttrs::v4T;
624f4a2713aSLionel Sambuc   else
625f4a2713aSLionel Sambuc     return ARMBuildAttrs::v4;
626f4a2713aSLionel Sambuc }
627f4a2713aSLionel Sambuc 
emitAttributes()628f4a2713aSLionel Sambuc void ARMAsmPrinter::emitAttributes() {
629*0a6a1f1dSLionel Sambuc   MCTargetStreamer &TS = *OutStreamer.getTargetStreamer();
630f4a2713aSLionel Sambuc   ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
631f4a2713aSLionel Sambuc 
632*0a6a1f1dSLionel Sambuc   ATS.emitTextAttribute(ARMBuildAttrs::conformance, "2.09");
633*0a6a1f1dSLionel Sambuc 
634f4a2713aSLionel Sambuc   ATS.switchVendor("aeabi");
635f4a2713aSLionel Sambuc 
636f4a2713aSLionel Sambuc   std::string CPUString = Subtarget->getCPUString();
637f4a2713aSLionel Sambuc 
638*0a6a1f1dSLionel Sambuc   // FIXME: remove krait check when GNU tools support krait cpu
639*0a6a1f1dSLionel Sambuc   if (CPUString != "generic" && CPUString != "krait")
640f4a2713aSLionel Sambuc     ATS.emitTextAttribute(ARMBuildAttrs::CPU_name, CPUString);
641f4a2713aSLionel Sambuc 
642f4a2713aSLionel Sambuc   ATS.emitAttribute(ARMBuildAttrs::CPU_arch,
643f4a2713aSLionel Sambuc                     getArchForCPU(CPUString, Subtarget));
644f4a2713aSLionel Sambuc 
645*0a6a1f1dSLionel Sambuc   // Tag_CPU_arch_profile must have the default value of 0 when "Architecture
646*0a6a1f1dSLionel Sambuc   // profile is not applicable (e.g. pre v7, or cross-profile code)".
647*0a6a1f1dSLionel Sambuc   if (Subtarget->hasV7Ops()) {
648f4a2713aSLionel Sambuc     if (Subtarget->isAClass()) {
649f4a2713aSLionel Sambuc       ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile,
650f4a2713aSLionel Sambuc                         ARMBuildAttrs::ApplicationProfile);
651f4a2713aSLionel Sambuc     } else if (Subtarget->isRClass()) {
652f4a2713aSLionel Sambuc       ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile,
653f4a2713aSLionel Sambuc                         ARMBuildAttrs::RealTimeProfile);
654f4a2713aSLionel Sambuc     } else if (Subtarget->isMClass()) {
655f4a2713aSLionel Sambuc       ATS.emitAttribute(ARMBuildAttrs::CPU_arch_profile,
656f4a2713aSLionel Sambuc                         ARMBuildAttrs::MicroControllerProfile);
657f4a2713aSLionel Sambuc     }
658*0a6a1f1dSLionel Sambuc   }
659f4a2713aSLionel Sambuc 
660f4a2713aSLionel Sambuc   ATS.emitAttribute(ARMBuildAttrs::ARM_ISA_use, Subtarget->hasARMOps() ?
661f4a2713aSLionel Sambuc                       ARMBuildAttrs::Allowed : ARMBuildAttrs::Not_Allowed);
662f4a2713aSLionel Sambuc   if (Subtarget->isThumb1Only()) {
663f4a2713aSLionel Sambuc     ATS.emitAttribute(ARMBuildAttrs::THUMB_ISA_use,
664f4a2713aSLionel Sambuc                       ARMBuildAttrs::Allowed);
665f4a2713aSLionel Sambuc   } else if (Subtarget->hasThumb2()) {
666f4a2713aSLionel Sambuc     ATS.emitAttribute(ARMBuildAttrs::THUMB_ISA_use,
667f4a2713aSLionel Sambuc                       ARMBuildAttrs::AllowThumb32);
668f4a2713aSLionel Sambuc   }
669f4a2713aSLionel Sambuc 
670f4a2713aSLionel Sambuc   if (Subtarget->hasNEON()) {
671f4a2713aSLionel Sambuc     /* NEON is not exactly a VFP architecture, but GAS emit one of
672f4a2713aSLionel Sambuc      * neon/neon-fp-armv8/neon-vfpv4/vfpv3/vfpv2 for .fpu parameters */
673f4a2713aSLionel Sambuc     if (Subtarget->hasFPARMv8()) {
674f4a2713aSLionel Sambuc       if (Subtarget->hasCrypto())
675f4a2713aSLionel Sambuc         ATS.emitFPU(ARM::CRYPTO_NEON_FP_ARMV8);
676f4a2713aSLionel Sambuc       else
677f4a2713aSLionel Sambuc         ATS.emitFPU(ARM::NEON_FP_ARMV8);
678f4a2713aSLionel Sambuc     }
679f4a2713aSLionel Sambuc     else if (Subtarget->hasVFP4())
680f4a2713aSLionel Sambuc       ATS.emitFPU(ARM::NEON_VFPV4);
681f4a2713aSLionel Sambuc     else
682f4a2713aSLionel Sambuc       ATS.emitFPU(ARM::NEON);
683f4a2713aSLionel Sambuc     // Emit Tag_Advanced_SIMD_arch for ARMv8 architecture
684f4a2713aSLionel Sambuc     if (Subtarget->hasV8Ops())
685f4a2713aSLionel Sambuc       ATS.emitAttribute(ARMBuildAttrs::Advanced_SIMD_arch,
686f4a2713aSLionel Sambuc                         ARMBuildAttrs::AllowNeonARMv8);
687f4a2713aSLionel Sambuc   } else {
688f4a2713aSLionel Sambuc     if (Subtarget->hasFPARMv8())
689*0a6a1f1dSLionel Sambuc       // FPv5 and FP-ARMv8 have the same instructions, so are modeled as one
690*0a6a1f1dSLionel Sambuc       // FPU, but there are two different names for it depending on the CPU.
691*0a6a1f1dSLionel Sambuc       ATS.emitFPU(Subtarget->hasD16() ? ARM::FPV5_D16 : ARM::FP_ARMV8);
692f4a2713aSLionel Sambuc     else if (Subtarget->hasVFP4())
693f4a2713aSLionel Sambuc       ATS.emitFPU(Subtarget->hasD16() ? ARM::VFPV4_D16 : ARM::VFPV4);
694f4a2713aSLionel Sambuc     else if (Subtarget->hasVFP3())
695f4a2713aSLionel Sambuc       ATS.emitFPU(Subtarget->hasD16() ? ARM::VFPV3_D16 : ARM::VFPV3);
696f4a2713aSLionel Sambuc     else if (Subtarget->hasVFP2())
697f4a2713aSLionel Sambuc       ATS.emitFPU(ARM::VFPV2);
698f4a2713aSLionel Sambuc   }
699f4a2713aSLionel Sambuc 
700*0a6a1f1dSLionel Sambuc   if (TM.getRelocationModel() == Reloc::PIC_) {
701*0a6a1f1dSLionel Sambuc     // PIC specific attributes.
702*0a6a1f1dSLionel Sambuc     ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_RW_data,
703*0a6a1f1dSLionel Sambuc                       ARMBuildAttrs::AddressRWPCRel);
704*0a6a1f1dSLionel Sambuc     ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_RO_data,
705*0a6a1f1dSLionel Sambuc                       ARMBuildAttrs::AddressROPCRel);
706*0a6a1f1dSLionel Sambuc     ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_GOT_use,
707*0a6a1f1dSLionel Sambuc                       ARMBuildAttrs::AddressGOT);
708*0a6a1f1dSLionel Sambuc   } else {
709*0a6a1f1dSLionel Sambuc     // Allow direct addressing of imported data for all other relocation models.
710*0a6a1f1dSLionel Sambuc     ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_GOT_use,
711*0a6a1f1dSLionel Sambuc                       ARMBuildAttrs::AddressDirect);
712f4a2713aSLionel Sambuc   }
713f4a2713aSLionel Sambuc 
714*0a6a1f1dSLionel Sambuc   // Signal various FP modes.
715*0a6a1f1dSLionel Sambuc   if (!TM.Options.UnsafeFPMath) {
716*0a6a1f1dSLionel Sambuc     ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal,
717*0a6a1f1dSLionel Sambuc                       ARMBuildAttrs::IEEEDenormals);
718*0a6a1f1dSLionel Sambuc     ATS.emitAttribute(ARMBuildAttrs::ABI_FP_exceptions,
719*0a6a1f1dSLionel Sambuc                       ARMBuildAttrs::Allowed);
720*0a6a1f1dSLionel Sambuc 
721*0a6a1f1dSLionel Sambuc     // If the user has permitted this code to choose the IEEE 754
722*0a6a1f1dSLionel Sambuc     // rounding at run-time, emit the rounding attribute.
723*0a6a1f1dSLionel Sambuc     if (TM.Options.HonorSignDependentRoundingFPMathOption)
724*0a6a1f1dSLionel Sambuc       ATS.emitAttribute(ARMBuildAttrs::ABI_FP_rounding,
725*0a6a1f1dSLionel Sambuc                         ARMBuildAttrs::Allowed);
726*0a6a1f1dSLionel Sambuc   } else {
727*0a6a1f1dSLionel Sambuc     if (!Subtarget->hasVFP2()) {
728*0a6a1f1dSLionel Sambuc       // When the target doesn't have an FPU (by design or
729*0a6a1f1dSLionel Sambuc       // intention), the assumptions made on the software support
730*0a6a1f1dSLionel Sambuc       // mirror that of the equivalent hardware support *if it
731*0a6a1f1dSLionel Sambuc       // existed*. For v7 and better we indicate that denormals are
732*0a6a1f1dSLionel Sambuc       // flushed preserving sign, and for V6 we indicate that
733*0a6a1f1dSLionel Sambuc       // denormals are flushed to positive zero.
734*0a6a1f1dSLionel Sambuc       if (Subtarget->hasV7Ops())
735*0a6a1f1dSLionel Sambuc         ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal,
736*0a6a1f1dSLionel Sambuc                           ARMBuildAttrs::PreserveFPSign);
737*0a6a1f1dSLionel Sambuc     } else if (Subtarget->hasVFP3()) {
738*0a6a1f1dSLionel Sambuc       // In VFPv4, VFPv4U, VFPv3, or VFPv3U, it is preserved. That is,
739*0a6a1f1dSLionel Sambuc       // the sign bit of the zero matches the sign bit of the input or
740*0a6a1f1dSLionel Sambuc       // result that is being flushed to zero.
741*0a6a1f1dSLionel Sambuc       ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal,
742*0a6a1f1dSLionel Sambuc                         ARMBuildAttrs::PreserveFPSign);
743*0a6a1f1dSLionel Sambuc     }
744*0a6a1f1dSLionel Sambuc     // For VFPv2 implementations it is implementation defined as
745*0a6a1f1dSLionel Sambuc     // to whether denormals are flushed to positive zero or to
746*0a6a1f1dSLionel Sambuc     // whatever the sign of zero is (ARM v7AR ARM 2.7.5). Historically
747*0a6a1f1dSLionel Sambuc     // LLVM has chosen to flush this to positive zero (most likely for
748*0a6a1f1dSLionel Sambuc     // GCC compatibility), so that's the chosen value here (the
749*0a6a1f1dSLionel Sambuc     // absence of its emission implies zero).
750*0a6a1f1dSLionel Sambuc   }
751*0a6a1f1dSLionel Sambuc 
752*0a6a1f1dSLionel Sambuc   // TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath is the
753*0a6a1f1dSLionel Sambuc   // equivalent of GCC's -ffinite-math-only flag.
754f4a2713aSLionel Sambuc   if (TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath)
755f4a2713aSLionel Sambuc     ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model,
756f4a2713aSLionel Sambuc                       ARMBuildAttrs::Allowed);
757f4a2713aSLionel Sambuc   else
758f4a2713aSLionel Sambuc     ATS.emitAttribute(ARMBuildAttrs::ABI_FP_number_model,
759f4a2713aSLionel Sambuc                       ARMBuildAttrs::AllowIEE754);
760f4a2713aSLionel Sambuc 
761*0a6a1f1dSLionel Sambuc   if (Subtarget->allowsUnalignedMem())
762*0a6a1f1dSLionel Sambuc     ATS.emitAttribute(ARMBuildAttrs::CPU_unaligned_access,
763*0a6a1f1dSLionel Sambuc                       ARMBuildAttrs::Allowed);
764*0a6a1f1dSLionel Sambuc   else
765*0a6a1f1dSLionel Sambuc     ATS.emitAttribute(ARMBuildAttrs::CPU_unaligned_access,
766*0a6a1f1dSLionel Sambuc                       ARMBuildAttrs::Not_Allowed);
767*0a6a1f1dSLionel Sambuc 
768*0a6a1f1dSLionel Sambuc   // FIXME: add more flags to ARMBuildAttributes.h
769f4a2713aSLionel Sambuc   // 8-bytes alignment stuff.
770*0a6a1f1dSLionel Sambuc   ATS.emitAttribute(ARMBuildAttrs::ABI_align_needed, 1);
771*0a6a1f1dSLionel Sambuc   ATS.emitAttribute(ARMBuildAttrs::ABI_align_preserved, 1);
772f4a2713aSLionel Sambuc 
773f4a2713aSLionel Sambuc   // ABI_HardFP_use attribute to indicate single precision FP.
774f4a2713aSLionel Sambuc   if (Subtarget->isFPOnlySP())
775f4a2713aSLionel Sambuc     ATS.emitAttribute(ARMBuildAttrs::ABI_HardFP_use,
776f4a2713aSLionel Sambuc                       ARMBuildAttrs::HardFPSinglePrecision);
777f4a2713aSLionel Sambuc 
778f4a2713aSLionel Sambuc   // Hard float.  Use both S and D registers and conform to AAPCS-VFP.
779f4a2713aSLionel Sambuc   if (Subtarget->isAAPCS_ABI() && TM.Options.FloatABIType == FloatABI::Hard)
780f4a2713aSLionel Sambuc     ATS.emitAttribute(ARMBuildAttrs::ABI_VFP_args, ARMBuildAttrs::HardFPAAPCS);
781f4a2713aSLionel Sambuc 
782f4a2713aSLionel Sambuc   // FIXME: Should we signal R9 usage?
783f4a2713aSLionel Sambuc 
784f4a2713aSLionel Sambuc   if (Subtarget->hasFP16())
785f4a2713aSLionel Sambuc       ATS.emitAttribute(ARMBuildAttrs::FP_HP_extension, ARMBuildAttrs::AllowHPFP);
786f4a2713aSLionel Sambuc 
787*0a6a1f1dSLionel Sambuc   // FIXME: To support emitting this build attribute as GCC does, the
788*0a6a1f1dSLionel Sambuc   // -mfp16-format option and associated plumbing must be
789*0a6a1f1dSLionel Sambuc   // supported. For now the __fp16 type is exposed by default, so this
790*0a6a1f1dSLionel Sambuc   // attribute should be emitted with value 1.
791*0a6a1f1dSLionel Sambuc   ATS.emitAttribute(ARMBuildAttrs::ABI_FP_16bit_format,
792*0a6a1f1dSLionel Sambuc                     ARMBuildAttrs::FP16FormatIEEE);
793*0a6a1f1dSLionel Sambuc 
794f4a2713aSLionel Sambuc   if (Subtarget->hasMPExtension())
795f4a2713aSLionel Sambuc       ATS.emitAttribute(ARMBuildAttrs::MPextension_use, ARMBuildAttrs::AllowMP);
796f4a2713aSLionel Sambuc 
797*0a6a1f1dSLionel Sambuc   // Hardware divide in ARM mode is part of base arch, starting from ARMv8.
798*0a6a1f1dSLionel Sambuc   // If only Thumb hwdiv is present, it must also be in base arch (ARMv7-R/M).
799*0a6a1f1dSLionel Sambuc   // It is not possible to produce DisallowDIV: if hwdiv is present in the base
800*0a6a1f1dSLionel Sambuc   // arch, supplying -hwdiv downgrades the effective arch, via ClearImpliedBits.
801*0a6a1f1dSLionel Sambuc   // AllowDIVExt is only emitted if hwdiv isn't available in the base arch;
802*0a6a1f1dSLionel Sambuc   // otherwise, the default value (AllowDIVIfExists) applies.
803*0a6a1f1dSLionel Sambuc   if (Subtarget->hasDivideInARMMode() && !Subtarget->hasV8Ops())
804*0a6a1f1dSLionel Sambuc       ATS.emitAttribute(ARMBuildAttrs::DIV_use, ARMBuildAttrs::AllowDIVExt);
805*0a6a1f1dSLionel Sambuc 
806*0a6a1f1dSLionel Sambuc   if (MMI) {
807*0a6a1f1dSLionel Sambuc     if (const Module *SourceModule = MMI->getModule()) {
808*0a6a1f1dSLionel Sambuc       // ABI_PCS_wchar_t to indicate wchar_t width
809*0a6a1f1dSLionel Sambuc       // FIXME: There is no way to emit value 0 (wchar_t prohibited).
810*0a6a1f1dSLionel Sambuc       if (auto WCharWidthValue = mdconst::extract_or_null<ConstantInt>(
811*0a6a1f1dSLionel Sambuc               SourceModule->getModuleFlag("wchar_size"))) {
812*0a6a1f1dSLionel Sambuc         int WCharWidth = WCharWidthValue->getZExtValue();
813*0a6a1f1dSLionel Sambuc         assert((WCharWidth == 2 || WCharWidth == 4) &&
814*0a6a1f1dSLionel Sambuc                "wchar_t width must be 2 or 4 bytes");
815*0a6a1f1dSLionel Sambuc         ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_wchar_t, WCharWidth);
816f4a2713aSLionel Sambuc       }
817f4a2713aSLionel Sambuc 
818*0a6a1f1dSLionel Sambuc       // ABI_enum_size to indicate enum width
819*0a6a1f1dSLionel Sambuc       // FIXME: There is no way to emit value 0 (enums prohibited) or value 3
820*0a6a1f1dSLionel Sambuc       //        (all enums contain a value needing 32 bits to encode).
821*0a6a1f1dSLionel Sambuc       if (auto EnumWidthValue = mdconst::extract_or_null<ConstantInt>(
822*0a6a1f1dSLionel Sambuc               SourceModule->getModuleFlag("min_enum_size"))) {
823*0a6a1f1dSLionel Sambuc         int EnumWidth = EnumWidthValue->getZExtValue();
824*0a6a1f1dSLionel Sambuc         assert((EnumWidth == 1 || EnumWidth == 4) &&
825*0a6a1f1dSLionel Sambuc                "Minimum enum width must be 1 or 4 bytes");
826*0a6a1f1dSLionel Sambuc         int EnumBuildAttr = EnumWidth == 1 ? 1 : 2;
827*0a6a1f1dSLionel Sambuc         ATS.emitAttribute(ARMBuildAttrs::ABI_enum_size, EnumBuildAttr);
828*0a6a1f1dSLionel Sambuc       }
829*0a6a1f1dSLionel Sambuc     }
830*0a6a1f1dSLionel Sambuc   }
831*0a6a1f1dSLionel Sambuc 
832*0a6a1f1dSLionel Sambuc   // TODO: We currently only support either reserving the register, or treating
833*0a6a1f1dSLionel Sambuc   // it as another callee-saved register, but not as SB or a TLS pointer; It
834*0a6a1f1dSLionel Sambuc   // would instead be nicer to push this from the frontend as metadata, as we do
835*0a6a1f1dSLionel Sambuc   // for the wchar and enum size tags
836*0a6a1f1dSLionel Sambuc   if (Subtarget->isR9Reserved())
837*0a6a1f1dSLionel Sambuc       ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use,
838*0a6a1f1dSLionel Sambuc                         ARMBuildAttrs::R9Reserved);
839*0a6a1f1dSLionel Sambuc   else
840*0a6a1f1dSLionel Sambuc       ATS.emitAttribute(ARMBuildAttrs::ABI_PCS_R9_use,
841*0a6a1f1dSLionel Sambuc                         ARMBuildAttrs::R9IsGPR);
842*0a6a1f1dSLionel Sambuc 
843f4a2713aSLionel Sambuc   if (Subtarget->hasTrustZone() && Subtarget->hasVirtualization())
844f4a2713aSLionel Sambuc       ATS.emitAttribute(ARMBuildAttrs::Virtualization_use,
845f4a2713aSLionel Sambuc                         ARMBuildAttrs::AllowTZVirtualization);
846f4a2713aSLionel Sambuc   else if (Subtarget->hasTrustZone())
847f4a2713aSLionel Sambuc       ATS.emitAttribute(ARMBuildAttrs::Virtualization_use,
848f4a2713aSLionel Sambuc                         ARMBuildAttrs::AllowTZ);
849f4a2713aSLionel Sambuc   else if (Subtarget->hasVirtualization())
850f4a2713aSLionel Sambuc       ATS.emitAttribute(ARMBuildAttrs::Virtualization_use,
851f4a2713aSLionel Sambuc                         ARMBuildAttrs::AllowVirtualization);
852f4a2713aSLionel Sambuc 
853f4a2713aSLionel Sambuc   ATS.finishAttributeSection();
854f4a2713aSLionel Sambuc }
855f4a2713aSLionel Sambuc 
856f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
857f4a2713aSLionel Sambuc 
getPICLabel(const char * Prefix,unsigned FunctionNumber,unsigned LabelId,MCContext & Ctx)858f4a2713aSLionel Sambuc static MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber,
859f4a2713aSLionel Sambuc                              unsigned LabelId, MCContext &Ctx) {
860f4a2713aSLionel Sambuc 
861f4a2713aSLionel Sambuc   MCSymbol *Label = Ctx.GetOrCreateSymbol(Twine(Prefix)
862f4a2713aSLionel Sambuc                        + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId));
863f4a2713aSLionel Sambuc   return Label;
864f4a2713aSLionel Sambuc }
865f4a2713aSLionel Sambuc 
866f4a2713aSLionel Sambuc static MCSymbolRefExpr::VariantKind
getModifierVariantKind(ARMCP::ARMCPModifier Modifier)867f4a2713aSLionel Sambuc getModifierVariantKind(ARMCP::ARMCPModifier Modifier) {
868f4a2713aSLionel Sambuc   switch (Modifier) {
869f4a2713aSLionel Sambuc   case ARMCP::no_modifier: return MCSymbolRefExpr::VK_None;
870*0a6a1f1dSLionel Sambuc   case ARMCP::TLSGD:       return MCSymbolRefExpr::VK_TLSGD;
871*0a6a1f1dSLionel Sambuc   case ARMCP::TPOFF:       return MCSymbolRefExpr::VK_TPOFF;
872*0a6a1f1dSLionel Sambuc   case ARMCP::GOTTPOFF:    return MCSymbolRefExpr::VK_GOTTPOFF;
873*0a6a1f1dSLionel Sambuc   case ARMCP::GOT:         return MCSymbolRefExpr::VK_GOT;
874*0a6a1f1dSLionel Sambuc   case ARMCP::GOTOFF:      return MCSymbolRefExpr::VK_GOTOFF;
875f4a2713aSLionel Sambuc   }
876f4a2713aSLionel Sambuc   llvm_unreachable("Invalid ARMCPModifier!");
877f4a2713aSLionel Sambuc }
878f4a2713aSLionel Sambuc 
GetARMGVSymbol(const GlobalValue * GV,unsigned char TargetFlags)879*0a6a1f1dSLionel Sambuc MCSymbol *ARMAsmPrinter::GetARMGVSymbol(const GlobalValue *GV,
880*0a6a1f1dSLionel Sambuc                                         unsigned char TargetFlags) {
881*0a6a1f1dSLionel Sambuc   if (Subtarget->isTargetMachO()) {
882*0a6a1f1dSLionel Sambuc     bool IsIndirect = (TargetFlags & ARMII::MO_NONLAZY) &&
883f4a2713aSLionel Sambuc       Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel());
884*0a6a1f1dSLionel Sambuc 
885*0a6a1f1dSLionel Sambuc     if (!IsIndirect)
886f4a2713aSLionel Sambuc       return getSymbol(GV);
887f4a2713aSLionel Sambuc 
888f4a2713aSLionel Sambuc     // FIXME: Remove this when Darwin transition to @GOT like syntax.
889*0a6a1f1dSLionel Sambuc     MCSymbol *MCSym = getSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
890f4a2713aSLionel Sambuc     MachineModuleInfoMachO &MMIMachO =
891f4a2713aSLionel Sambuc       MMI->getObjFileInfo<MachineModuleInfoMachO>();
892f4a2713aSLionel Sambuc     MachineModuleInfoImpl::StubValueTy &StubSym =
893*0a6a1f1dSLionel Sambuc       GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(MCSym)
894*0a6a1f1dSLionel Sambuc                                 : MMIMachO.getGVStubEntry(MCSym);
895*0a6a1f1dSLionel Sambuc     if (!StubSym.getPointer())
896*0a6a1f1dSLionel Sambuc       StubSym = MachineModuleInfoImpl::StubValueTy(getSymbol(GV),
897*0a6a1f1dSLionel Sambuc                                                    !GV->hasInternalLinkage());
898f4a2713aSLionel Sambuc     return MCSym;
899*0a6a1f1dSLionel Sambuc   } else if (Subtarget->isTargetCOFF()) {
900*0a6a1f1dSLionel Sambuc     assert(Subtarget->isTargetWindows() &&
901*0a6a1f1dSLionel Sambuc            "Windows is the only supported COFF target");
902*0a6a1f1dSLionel Sambuc 
903*0a6a1f1dSLionel Sambuc     bool IsIndirect = (TargetFlags & ARMII::MO_DLLIMPORT);
904*0a6a1f1dSLionel Sambuc     if (!IsIndirect)
905*0a6a1f1dSLionel Sambuc       return getSymbol(GV);
906*0a6a1f1dSLionel Sambuc 
907*0a6a1f1dSLionel Sambuc     SmallString<128> Name;
908*0a6a1f1dSLionel Sambuc     Name = "__imp_";
909*0a6a1f1dSLionel Sambuc     getNameWithPrefix(Name, GV);
910*0a6a1f1dSLionel Sambuc 
911*0a6a1f1dSLionel Sambuc     return OutContext.GetOrCreateSymbol(Name);
912*0a6a1f1dSLionel Sambuc   } else if (Subtarget->isTargetELF()) {
913*0a6a1f1dSLionel Sambuc     return getSymbol(GV);
914*0a6a1f1dSLionel Sambuc   }
915*0a6a1f1dSLionel Sambuc   llvm_unreachable("unexpected target");
916f4a2713aSLionel Sambuc }
917f4a2713aSLionel Sambuc 
918f4a2713aSLionel Sambuc void ARMAsmPrinter::
EmitMachineConstantPoolValue(MachineConstantPoolValue * MCPV)919f4a2713aSLionel Sambuc EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
920*0a6a1f1dSLionel Sambuc   const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout();
921*0a6a1f1dSLionel Sambuc   int Size =
922*0a6a1f1dSLionel Sambuc       TM.getSubtargetImpl()->getDataLayout()->getTypeAllocSize(MCPV->getType());
923f4a2713aSLionel Sambuc 
924f4a2713aSLionel Sambuc   ARMConstantPoolValue *ACPV = static_cast<ARMConstantPoolValue*>(MCPV);
925f4a2713aSLionel Sambuc 
926f4a2713aSLionel Sambuc   MCSymbol *MCSym;
927f4a2713aSLionel Sambuc   if (ACPV->isLSDA()) {
928f4a2713aSLionel Sambuc     SmallString<128> Str;
929f4a2713aSLionel Sambuc     raw_svector_ostream OS(Str);
930*0a6a1f1dSLionel Sambuc     OS << DL->getPrivateGlobalPrefix() << "_LSDA_" << getFunctionNumber();
931f4a2713aSLionel Sambuc     MCSym = OutContext.GetOrCreateSymbol(OS.str());
932f4a2713aSLionel Sambuc   } else if (ACPV->isBlockAddress()) {
933f4a2713aSLionel Sambuc     const BlockAddress *BA =
934f4a2713aSLionel Sambuc       cast<ARMConstantPoolConstant>(ACPV)->getBlockAddress();
935f4a2713aSLionel Sambuc     MCSym = GetBlockAddressSymbol(BA);
936f4a2713aSLionel Sambuc   } else if (ACPV->isGlobalValue()) {
937f4a2713aSLionel Sambuc     const GlobalValue *GV = cast<ARMConstantPoolConstant>(ACPV)->getGV();
938*0a6a1f1dSLionel Sambuc 
939*0a6a1f1dSLionel Sambuc     // On Darwin, const-pool entries may get the "FOO$non_lazy_ptr" mangling, so
940*0a6a1f1dSLionel Sambuc     // flag the global as MO_NONLAZY.
941*0a6a1f1dSLionel Sambuc     unsigned char TF = Subtarget->isTargetMachO() ? ARMII::MO_NONLAZY : 0;
942*0a6a1f1dSLionel Sambuc     MCSym = GetARMGVSymbol(GV, TF);
943f4a2713aSLionel Sambuc   } else if (ACPV->isMachineBasicBlock()) {
944f4a2713aSLionel Sambuc     const MachineBasicBlock *MBB = cast<ARMConstantPoolMBB>(ACPV)->getMBB();
945f4a2713aSLionel Sambuc     MCSym = MBB->getSymbol();
946f4a2713aSLionel Sambuc   } else {
947f4a2713aSLionel Sambuc     assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
948f4a2713aSLionel Sambuc     const char *Sym = cast<ARMConstantPoolSymbol>(ACPV)->getSymbol();
949f4a2713aSLionel Sambuc     MCSym = GetExternalSymbolSymbol(Sym);
950f4a2713aSLionel Sambuc   }
951f4a2713aSLionel Sambuc 
952f4a2713aSLionel Sambuc   // Create an MCSymbol for the reference.
953f4a2713aSLionel Sambuc   const MCExpr *Expr =
954f4a2713aSLionel Sambuc     MCSymbolRefExpr::Create(MCSym, getModifierVariantKind(ACPV->getModifier()),
955f4a2713aSLionel Sambuc                             OutContext);
956f4a2713aSLionel Sambuc 
957f4a2713aSLionel Sambuc   if (ACPV->getPCAdjustment()) {
958*0a6a1f1dSLionel Sambuc     MCSymbol *PCLabel = getPICLabel(DL->getPrivateGlobalPrefix(),
959f4a2713aSLionel Sambuc                                     getFunctionNumber(),
960f4a2713aSLionel Sambuc                                     ACPV->getLabelId(),
961f4a2713aSLionel Sambuc                                     OutContext);
962f4a2713aSLionel Sambuc     const MCExpr *PCRelExpr = MCSymbolRefExpr::Create(PCLabel, OutContext);
963f4a2713aSLionel Sambuc     PCRelExpr =
964f4a2713aSLionel Sambuc       MCBinaryExpr::CreateAdd(PCRelExpr,
965f4a2713aSLionel Sambuc                               MCConstantExpr::Create(ACPV->getPCAdjustment(),
966f4a2713aSLionel Sambuc                                                      OutContext),
967f4a2713aSLionel Sambuc                               OutContext);
968f4a2713aSLionel Sambuc     if (ACPV->mustAddCurrentAddress()) {
969f4a2713aSLionel Sambuc       // We want "(<expr> - .)", but MC doesn't have a concept of the '.'
970f4a2713aSLionel Sambuc       // label, so just emit a local label end reference that instead.
971f4a2713aSLionel Sambuc       MCSymbol *DotSym = OutContext.CreateTempSymbol();
972f4a2713aSLionel Sambuc       OutStreamer.EmitLabel(DotSym);
973f4a2713aSLionel Sambuc       const MCExpr *DotExpr = MCSymbolRefExpr::Create(DotSym, OutContext);
974f4a2713aSLionel Sambuc       PCRelExpr = MCBinaryExpr::CreateSub(PCRelExpr, DotExpr, OutContext);
975f4a2713aSLionel Sambuc     }
976f4a2713aSLionel Sambuc     Expr = MCBinaryExpr::CreateSub(Expr, PCRelExpr, OutContext);
977f4a2713aSLionel Sambuc   }
978f4a2713aSLionel Sambuc   OutStreamer.EmitValue(Expr, Size);
979f4a2713aSLionel Sambuc }
980f4a2713aSLionel Sambuc 
EmitJumpTable(const MachineInstr * MI)981f4a2713aSLionel Sambuc void ARMAsmPrinter::EmitJumpTable(const MachineInstr *MI) {
982f4a2713aSLionel Sambuc   unsigned Opcode = MI->getOpcode();
983f4a2713aSLionel Sambuc   int OpNum = 1;
984f4a2713aSLionel Sambuc   if (Opcode == ARM::BR_JTadd)
985f4a2713aSLionel Sambuc     OpNum = 2;
986f4a2713aSLionel Sambuc   else if (Opcode == ARM::BR_JTm)
987f4a2713aSLionel Sambuc     OpNum = 3;
988f4a2713aSLionel Sambuc 
989f4a2713aSLionel Sambuc   const MachineOperand &MO1 = MI->getOperand(OpNum);
990f4a2713aSLionel Sambuc   const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
991f4a2713aSLionel Sambuc   unsigned JTI = MO1.getIndex();
992f4a2713aSLionel Sambuc 
993f4a2713aSLionel Sambuc   // Emit a label for the jump table.
994f4a2713aSLionel Sambuc   MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
995f4a2713aSLionel Sambuc   OutStreamer.EmitLabel(JTISymbol);
996f4a2713aSLionel Sambuc 
997f4a2713aSLionel Sambuc   // Mark the jump table as data-in-code.
998f4a2713aSLionel Sambuc   OutStreamer.EmitDataRegion(MCDR_DataRegionJT32);
999f4a2713aSLionel Sambuc 
1000f4a2713aSLionel Sambuc   // Emit each entry of the table.
1001f4a2713aSLionel Sambuc   const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
1002f4a2713aSLionel Sambuc   const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
1003f4a2713aSLionel Sambuc   const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1004f4a2713aSLionel Sambuc 
1005f4a2713aSLionel Sambuc   for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
1006f4a2713aSLionel Sambuc     MachineBasicBlock *MBB = JTBBs[i];
1007f4a2713aSLionel Sambuc     // Construct an MCExpr for the entry. We want a value of the form:
1008f4a2713aSLionel Sambuc     // (BasicBlockAddr - TableBeginAddr)
1009f4a2713aSLionel Sambuc     //
1010f4a2713aSLionel Sambuc     // For example, a table with entries jumping to basic blocks BB0 and BB1
1011f4a2713aSLionel Sambuc     // would look like:
1012f4a2713aSLionel Sambuc     // LJTI_0_0:
1013f4a2713aSLionel Sambuc     //    .word (LBB0 - LJTI_0_0)
1014f4a2713aSLionel Sambuc     //    .word (LBB1 - LJTI_0_0)
1015f4a2713aSLionel Sambuc     const MCExpr *Expr = MCSymbolRefExpr::Create(MBB->getSymbol(), OutContext);
1016f4a2713aSLionel Sambuc 
1017f4a2713aSLionel Sambuc     if (TM.getRelocationModel() == Reloc::PIC_)
1018f4a2713aSLionel Sambuc       Expr = MCBinaryExpr::CreateSub(Expr, MCSymbolRefExpr::Create(JTISymbol,
1019f4a2713aSLionel Sambuc                                                                    OutContext),
1020f4a2713aSLionel Sambuc                                      OutContext);
1021f4a2713aSLionel Sambuc     // If we're generating a table of Thumb addresses in static relocation
1022f4a2713aSLionel Sambuc     // model, we need to add one to keep interworking correctly.
1023f4a2713aSLionel Sambuc     else if (AFI->isThumbFunction())
1024f4a2713aSLionel Sambuc       Expr = MCBinaryExpr::CreateAdd(Expr, MCConstantExpr::Create(1,OutContext),
1025f4a2713aSLionel Sambuc                                      OutContext);
1026f4a2713aSLionel Sambuc     OutStreamer.EmitValue(Expr, 4);
1027f4a2713aSLionel Sambuc   }
1028f4a2713aSLionel Sambuc   // Mark the end of jump table data-in-code region.
1029f4a2713aSLionel Sambuc   OutStreamer.EmitDataRegion(MCDR_DataRegionEnd);
1030f4a2713aSLionel Sambuc }
1031f4a2713aSLionel Sambuc 
EmitJump2Table(const MachineInstr * MI)1032f4a2713aSLionel Sambuc void ARMAsmPrinter::EmitJump2Table(const MachineInstr *MI) {
1033f4a2713aSLionel Sambuc   unsigned Opcode = MI->getOpcode();
1034f4a2713aSLionel Sambuc   int OpNum = (Opcode == ARM::t2BR_JT) ? 2 : 1;
1035f4a2713aSLionel Sambuc   const MachineOperand &MO1 = MI->getOperand(OpNum);
1036f4a2713aSLionel Sambuc   const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
1037f4a2713aSLionel Sambuc   unsigned JTI = MO1.getIndex();
1038f4a2713aSLionel Sambuc 
1039f4a2713aSLionel Sambuc   MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
1040f4a2713aSLionel Sambuc   OutStreamer.EmitLabel(JTISymbol);
1041f4a2713aSLionel Sambuc 
1042f4a2713aSLionel Sambuc   // Emit each entry of the table.
1043f4a2713aSLionel Sambuc   const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
1044f4a2713aSLionel Sambuc   const std::vector<MachineJumpTableEntry> &JT = MJTI->getJumpTables();
1045f4a2713aSLionel Sambuc   const std::vector<MachineBasicBlock*> &JTBBs = JT[JTI].MBBs;
1046f4a2713aSLionel Sambuc   unsigned OffsetWidth = 4;
1047f4a2713aSLionel Sambuc   if (MI->getOpcode() == ARM::t2TBB_JT) {
1048f4a2713aSLionel Sambuc     OffsetWidth = 1;
1049f4a2713aSLionel Sambuc     // Mark the jump table as data-in-code.
1050f4a2713aSLionel Sambuc     OutStreamer.EmitDataRegion(MCDR_DataRegionJT8);
1051f4a2713aSLionel Sambuc   } else if (MI->getOpcode() == ARM::t2TBH_JT) {
1052f4a2713aSLionel Sambuc     OffsetWidth = 2;
1053f4a2713aSLionel Sambuc     // Mark the jump table as data-in-code.
1054f4a2713aSLionel Sambuc     OutStreamer.EmitDataRegion(MCDR_DataRegionJT16);
1055f4a2713aSLionel Sambuc   }
1056f4a2713aSLionel Sambuc 
1057f4a2713aSLionel Sambuc   for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
1058f4a2713aSLionel Sambuc     MachineBasicBlock *MBB = JTBBs[i];
1059f4a2713aSLionel Sambuc     const MCExpr *MBBSymbolExpr = MCSymbolRefExpr::Create(MBB->getSymbol(),
1060f4a2713aSLionel Sambuc                                                           OutContext);
1061f4a2713aSLionel Sambuc     // If this isn't a TBB or TBH, the entries are direct branch instructions.
1062f4a2713aSLionel Sambuc     if (OffsetWidth == 4) {
1063*0a6a1f1dSLionel Sambuc       EmitToStreamer(OutStreamer, MCInstBuilder(ARM::t2B)
1064f4a2713aSLionel Sambuc         .addExpr(MBBSymbolExpr)
1065f4a2713aSLionel Sambuc         .addImm(ARMCC::AL)
1066f4a2713aSLionel Sambuc         .addReg(0));
1067f4a2713aSLionel Sambuc       continue;
1068f4a2713aSLionel Sambuc     }
1069f4a2713aSLionel Sambuc     // Otherwise it's an offset from the dispatch instruction. Construct an
1070f4a2713aSLionel Sambuc     // MCExpr for the entry. We want a value of the form:
1071f4a2713aSLionel Sambuc     // (BasicBlockAddr - TableBeginAddr) / 2
1072f4a2713aSLionel Sambuc     //
1073f4a2713aSLionel Sambuc     // For example, a TBB table with entries jumping to basic blocks BB0 and BB1
1074f4a2713aSLionel Sambuc     // would look like:
1075f4a2713aSLionel Sambuc     // LJTI_0_0:
1076f4a2713aSLionel Sambuc     //    .byte (LBB0 - LJTI_0_0) / 2
1077f4a2713aSLionel Sambuc     //    .byte (LBB1 - LJTI_0_0) / 2
1078f4a2713aSLionel Sambuc     const MCExpr *Expr =
1079f4a2713aSLionel Sambuc       MCBinaryExpr::CreateSub(MBBSymbolExpr,
1080f4a2713aSLionel Sambuc                               MCSymbolRefExpr::Create(JTISymbol, OutContext),
1081f4a2713aSLionel Sambuc                               OutContext);
1082f4a2713aSLionel Sambuc     Expr = MCBinaryExpr::CreateDiv(Expr, MCConstantExpr::Create(2, OutContext),
1083f4a2713aSLionel Sambuc                                    OutContext);
1084f4a2713aSLionel Sambuc     OutStreamer.EmitValue(Expr, OffsetWidth);
1085f4a2713aSLionel Sambuc   }
1086f4a2713aSLionel Sambuc   // Mark the end of jump table data-in-code region. 32-bit offsets use
1087f4a2713aSLionel Sambuc   // actual branch instructions here, so we don't mark those as a data-region
1088f4a2713aSLionel Sambuc   // at all.
1089f4a2713aSLionel Sambuc   if (OffsetWidth != 4)
1090f4a2713aSLionel Sambuc     OutStreamer.EmitDataRegion(MCDR_DataRegionEnd);
1091f4a2713aSLionel Sambuc }
1092f4a2713aSLionel Sambuc 
EmitUnwindingInstruction(const MachineInstr * MI)1093f4a2713aSLionel Sambuc void ARMAsmPrinter::EmitUnwindingInstruction(const MachineInstr *MI) {
1094f4a2713aSLionel Sambuc   assert(MI->getFlag(MachineInstr::FrameSetup) &&
1095f4a2713aSLionel Sambuc       "Only instruction which are involved into frame setup code are allowed");
1096f4a2713aSLionel Sambuc 
1097*0a6a1f1dSLionel Sambuc   MCTargetStreamer &TS = *OutStreamer.getTargetStreamer();
1098f4a2713aSLionel Sambuc   ARMTargetStreamer &ATS = static_cast<ARMTargetStreamer &>(TS);
1099f4a2713aSLionel Sambuc   const MachineFunction &MF = *MI->getParent()->getParent();
1100*0a6a1f1dSLionel Sambuc   const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();
1101f4a2713aSLionel Sambuc   const ARMFunctionInfo &AFI = *MF.getInfo<ARMFunctionInfo>();
1102f4a2713aSLionel Sambuc 
1103f4a2713aSLionel Sambuc   unsigned FramePtr = RegInfo->getFrameRegister(MF);
1104f4a2713aSLionel Sambuc   unsigned Opc = MI->getOpcode();
1105f4a2713aSLionel Sambuc   unsigned SrcReg, DstReg;
1106f4a2713aSLionel Sambuc 
1107f4a2713aSLionel Sambuc   if (Opc == ARM::tPUSH || Opc == ARM::tLDRpci) {
1108f4a2713aSLionel Sambuc     // Two special cases:
1109f4a2713aSLionel Sambuc     // 1) tPUSH does not have src/dst regs.
1110f4a2713aSLionel Sambuc     // 2) for Thumb1 code we sometimes materialize the constant via constpool
1111f4a2713aSLionel Sambuc     // load. Yes, this is pretty fragile, but for now I don't see better
1112f4a2713aSLionel Sambuc     // way... :(
1113f4a2713aSLionel Sambuc     SrcReg = DstReg = ARM::SP;
1114f4a2713aSLionel Sambuc   } else {
1115f4a2713aSLionel Sambuc     SrcReg = MI->getOperand(1).getReg();
1116f4a2713aSLionel Sambuc     DstReg = MI->getOperand(0).getReg();
1117f4a2713aSLionel Sambuc   }
1118f4a2713aSLionel Sambuc 
1119f4a2713aSLionel Sambuc   // Try to figure out the unwinding opcode out of src / dst regs.
1120f4a2713aSLionel Sambuc   if (MI->mayStore()) {
1121f4a2713aSLionel Sambuc     // Register saves.
1122f4a2713aSLionel Sambuc     assert(DstReg == ARM::SP &&
1123f4a2713aSLionel Sambuc            "Only stack pointer as a destination reg is supported");
1124f4a2713aSLionel Sambuc 
1125f4a2713aSLionel Sambuc     SmallVector<unsigned, 4> RegList;
1126f4a2713aSLionel Sambuc     // Skip src & dst reg, and pred ops.
1127f4a2713aSLionel Sambuc     unsigned StartOp = 2 + 2;
1128f4a2713aSLionel Sambuc     // Use all the operands.
1129f4a2713aSLionel Sambuc     unsigned NumOffset = 0;
1130f4a2713aSLionel Sambuc 
1131f4a2713aSLionel Sambuc     switch (Opc) {
1132f4a2713aSLionel Sambuc     default:
1133f4a2713aSLionel Sambuc       MI->dump();
1134f4a2713aSLionel Sambuc       llvm_unreachable("Unsupported opcode for unwinding information");
1135f4a2713aSLionel Sambuc     case ARM::tPUSH:
1136f4a2713aSLionel Sambuc       // Special case here: no src & dst reg, but two extra imp ops.
1137f4a2713aSLionel Sambuc       StartOp = 2; NumOffset = 2;
1138f4a2713aSLionel Sambuc     case ARM::STMDB_UPD:
1139f4a2713aSLionel Sambuc     case ARM::t2STMDB_UPD:
1140f4a2713aSLionel Sambuc     case ARM::VSTMDDB_UPD:
1141f4a2713aSLionel Sambuc       assert(SrcReg == ARM::SP &&
1142f4a2713aSLionel Sambuc              "Only stack pointer as a source reg is supported");
1143f4a2713aSLionel Sambuc       for (unsigned i = StartOp, NumOps = MI->getNumOperands() - NumOffset;
1144f4a2713aSLionel Sambuc            i != NumOps; ++i) {
1145f4a2713aSLionel Sambuc         const MachineOperand &MO = MI->getOperand(i);
1146f4a2713aSLionel Sambuc         // Actually, there should never be any impdef stuff here. Skip it
1147f4a2713aSLionel Sambuc         // temporary to workaround PR11902.
1148f4a2713aSLionel Sambuc         if (MO.isImplicit())
1149f4a2713aSLionel Sambuc           continue;
1150f4a2713aSLionel Sambuc         RegList.push_back(MO.getReg());
1151f4a2713aSLionel Sambuc       }
1152f4a2713aSLionel Sambuc       break;
1153f4a2713aSLionel Sambuc     case ARM::STR_PRE_IMM:
1154f4a2713aSLionel Sambuc     case ARM::STR_PRE_REG:
1155f4a2713aSLionel Sambuc     case ARM::t2STR_PRE:
1156f4a2713aSLionel Sambuc       assert(MI->getOperand(2).getReg() == ARM::SP &&
1157f4a2713aSLionel Sambuc              "Only stack pointer as a source reg is supported");
1158f4a2713aSLionel Sambuc       RegList.push_back(SrcReg);
1159f4a2713aSLionel Sambuc       break;
1160f4a2713aSLionel Sambuc     }
1161*0a6a1f1dSLionel Sambuc     if (MAI->getExceptionHandlingType() == ExceptionHandling::ARM)
1162f4a2713aSLionel Sambuc       ATS.emitRegSave(RegList, Opc == ARM::VSTMDDB_UPD);
1163f4a2713aSLionel Sambuc   } else {
1164f4a2713aSLionel Sambuc     // Changes of stack / frame pointer.
1165f4a2713aSLionel Sambuc     if (SrcReg == ARM::SP) {
1166f4a2713aSLionel Sambuc       int64_t Offset = 0;
1167f4a2713aSLionel Sambuc       switch (Opc) {
1168f4a2713aSLionel Sambuc       default:
1169f4a2713aSLionel Sambuc         MI->dump();
1170f4a2713aSLionel Sambuc         llvm_unreachable("Unsupported opcode for unwinding information");
1171f4a2713aSLionel Sambuc       case ARM::MOVr:
1172f4a2713aSLionel Sambuc       case ARM::tMOVr:
1173f4a2713aSLionel Sambuc         Offset = 0;
1174f4a2713aSLionel Sambuc         break;
1175f4a2713aSLionel Sambuc       case ARM::ADDri:
1176f4a2713aSLionel Sambuc         Offset = -MI->getOperand(2).getImm();
1177f4a2713aSLionel Sambuc         break;
1178f4a2713aSLionel Sambuc       case ARM::SUBri:
1179f4a2713aSLionel Sambuc       case ARM::t2SUBri:
1180f4a2713aSLionel Sambuc         Offset = MI->getOperand(2).getImm();
1181f4a2713aSLionel Sambuc         break;
1182f4a2713aSLionel Sambuc       case ARM::tSUBspi:
1183f4a2713aSLionel Sambuc         Offset = MI->getOperand(2).getImm()*4;
1184f4a2713aSLionel Sambuc         break;
1185f4a2713aSLionel Sambuc       case ARM::tADDspi:
1186f4a2713aSLionel Sambuc       case ARM::tADDrSPi:
1187f4a2713aSLionel Sambuc         Offset = -MI->getOperand(2).getImm()*4;
1188f4a2713aSLionel Sambuc         break;
1189f4a2713aSLionel Sambuc       case ARM::tLDRpci: {
1190f4a2713aSLionel Sambuc         // Grab the constpool index and check, whether it corresponds to
1191f4a2713aSLionel Sambuc         // original or cloned constpool entry.
1192f4a2713aSLionel Sambuc         unsigned CPI = MI->getOperand(1).getIndex();
1193f4a2713aSLionel Sambuc         const MachineConstantPool *MCP = MF.getConstantPool();
1194f4a2713aSLionel Sambuc         if (CPI >= MCP->getConstants().size())
1195f4a2713aSLionel Sambuc           CPI = AFI.getOriginalCPIdx(CPI);
1196f4a2713aSLionel Sambuc         assert(CPI != -1U && "Invalid constpool index");
1197f4a2713aSLionel Sambuc 
1198f4a2713aSLionel Sambuc         // Derive the actual offset.
1199f4a2713aSLionel Sambuc         const MachineConstantPoolEntry &CPE = MCP->getConstants()[CPI];
1200f4a2713aSLionel Sambuc         assert(!CPE.isMachineConstantPoolEntry() && "Invalid constpool entry");
1201f4a2713aSLionel Sambuc         // FIXME: Check for user, it should be "add" instruction!
1202f4a2713aSLionel Sambuc         Offset = -cast<ConstantInt>(CPE.Val.ConstVal)->getSExtValue();
1203f4a2713aSLionel Sambuc         break;
1204f4a2713aSLionel Sambuc       }
1205f4a2713aSLionel Sambuc       }
1206f4a2713aSLionel Sambuc 
1207*0a6a1f1dSLionel Sambuc       if (MAI->getExceptionHandlingType() == ExceptionHandling::ARM) {
1208f4a2713aSLionel Sambuc         if (DstReg == FramePtr && FramePtr != ARM::SP)
1209f4a2713aSLionel Sambuc           // Set-up of the frame pointer. Positive values correspond to "add"
1210f4a2713aSLionel Sambuc           // instruction.
1211f4a2713aSLionel Sambuc           ATS.emitSetFP(FramePtr, ARM::SP, -Offset);
1212f4a2713aSLionel Sambuc         else if (DstReg == ARM::SP) {
1213f4a2713aSLionel Sambuc           // Change of SP by an offset. Positive values correspond to "sub"
1214f4a2713aSLionel Sambuc           // instruction.
1215f4a2713aSLionel Sambuc           ATS.emitPad(Offset);
1216f4a2713aSLionel Sambuc         } else {
1217*0a6a1f1dSLionel Sambuc           // Move of SP to a register.  Positive values correspond to an "add"
1218*0a6a1f1dSLionel Sambuc           // instruction.
1219*0a6a1f1dSLionel Sambuc           ATS.emitMovSP(DstReg, -Offset);
1220*0a6a1f1dSLionel Sambuc         }
1221f4a2713aSLionel Sambuc       }
1222f4a2713aSLionel Sambuc     } else if (DstReg == ARM::SP) {
1223f4a2713aSLionel Sambuc       MI->dump();
1224f4a2713aSLionel Sambuc       llvm_unreachable("Unsupported opcode for unwinding information");
1225f4a2713aSLionel Sambuc     }
1226f4a2713aSLionel Sambuc     else {
1227f4a2713aSLionel Sambuc       MI->dump();
1228f4a2713aSLionel Sambuc       llvm_unreachable("Unsupported opcode for unwinding information");
1229f4a2713aSLionel Sambuc     }
1230f4a2713aSLionel Sambuc   }
1231f4a2713aSLionel Sambuc }
1232f4a2713aSLionel Sambuc 
1233f4a2713aSLionel Sambuc // Simple pseudo-instructions have their lowering (with expansion to real
1234f4a2713aSLionel Sambuc // instructions) auto-generated.
1235f4a2713aSLionel Sambuc #include "ARMGenMCPseudoLowering.inc"
1236f4a2713aSLionel Sambuc 
EmitInstruction(const MachineInstr * MI)1237f4a2713aSLionel Sambuc void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
1238*0a6a1f1dSLionel Sambuc   const DataLayout *DL = TM.getSubtargetImpl()->getDataLayout();
1239*0a6a1f1dSLionel Sambuc 
1240f4a2713aSLionel Sambuc   // If we just ended a constant pool, mark it as such.
1241f4a2713aSLionel Sambuc   if (InConstantPool && MI->getOpcode() != ARM::CONSTPOOL_ENTRY) {
1242f4a2713aSLionel Sambuc     OutStreamer.EmitDataRegion(MCDR_DataRegionEnd);
1243f4a2713aSLionel Sambuc     InConstantPool = false;
1244f4a2713aSLionel Sambuc   }
1245f4a2713aSLionel Sambuc 
1246f4a2713aSLionel Sambuc   // Emit unwinding stuff for frame-related instructions
1247*0a6a1f1dSLionel Sambuc   if (Subtarget->isTargetEHABICompatible() &&
1248*0a6a1f1dSLionel Sambuc        MI->getFlag(MachineInstr::FrameSetup))
1249f4a2713aSLionel Sambuc     EmitUnwindingInstruction(MI);
1250f4a2713aSLionel Sambuc 
1251f4a2713aSLionel Sambuc   // Do any auto-generated pseudo lowerings.
1252f4a2713aSLionel Sambuc   if (emitPseudoExpansionLowering(OutStreamer, MI))
1253f4a2713aSLionel Sambuc     return;
1254f4a2713aSLionel Sambuc 
1255f4a2713aSLionel Sambuc   assert(!convertAddSubFlagsOpcode(MI->getOpcode()) &&
1256f4a2713aSLionel Sambuc          "Pseudo flag setting opcode should be expanded early");
1257f4a2713aSLionel Sambuc 
1258f4a2713aSLionel Sambuc   // Check for manual lowerings.
1259f4a2713aSLionel Sambuc   unsigned Opc = MI->getOpcode();
1260f4a2713aSLionel Sambuc   switch (Opc) {
1261f4a2713aSLionel Sambuc   case ARM::t2MOVi32imm: llvm_unreachable("Should be lowered by thumb2it pass");
1262f4a2713aSLionel Sambuc   case ARM::DBG_VALUE: llvm_unreachable("Should be handled by generic printing");
1263f4a2713aSLionel Sambuc   case ARM::LEApcrel:
1264f4a2713aSLionel Sambuc   case ARM::tLEApcrel:
1265f4a2713aSLionel Sambuc   case ARM::t2LEApcrel: {
1266f4a2713aSLionel Sambuc     // FIXME: Need to also handle globals and externals
1267f4a2713aSLionel Sambuc     MCSymbol *CPISymbol = GetCPISymbol(MI->getOperand(1).getIndex());
1268*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(MI->getOpcode() ==
1269f4a2713aSLionel Sambuc                                               ARM::t2LEApcrel ? ARM::t2ADR
1270f4a2713aSLionel Sambuc                   : (MI->getOpcode() == ARM::tLEApcrel ? ARM::tADR
1271f4a2713aSLionel Sambuc                      : ARM::ADR))
1272f4a2713aSLionel Sambuc       .addReg(MI->getOperand(0).getReg())
1273f4a2713aSLionel Sambuc       .addExpr(MCSymbolRefExpr::Create(CPISymbol, OutContext))
1274f4a2713aSLionel Sambuc       // Add predicate operands.
1275f4a2713aSLionel Sambuc       .addImm(MI->getOperand(2).getImm())
1276f4a2713aSLionel Sambuc       .addReg(MI->getOperand(3).getReg()));
1277f4a2713aSLionel Sambuc     return;
1278f4a2713aSLionel Sambuc   }
1279f4a2713aSLionel Sambuc   case ARM::LEApcrelJT:
1280f4a2713aSLionel Sambuc   case ARM::tLEApcrelJT:
1281f4a2713aSLionel Sambuc   case ARM::t2LEApcrelJT: {
1282f4a2713aSLionel Sambuc     MCSymbol *JTIPICSymbol =
1283f4a2713aSLionel Sambuc       GetARMJTIPICJumpTableLabel2(MI->getOperand(1).getIndex(),
1284f4a2713aSLionel Sambuc                                   MI->getOperand(2).getImm());
1285*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(MI->getOpcode() ==
1286f4a2713aSLionel Sambuc                                               ARM::t2LEApcrelJT ? ARM::t2ADR
1287f4a2713aSLionel Sambuc                   : (MI->getOpcode() == ARM::tLEApcrelJT ? ARM::tADR
1288f4a2713aSLionel Sambuc                      : ARM::ADR))
1289f4a2713aSLionel Sambuc       .addReg(MI->getOperand(0).getReg())
1290f4a2713aSLionel Sambuc       .addExpr(MCSymbolRefExpr::Create(JTIPICSymbol, OutContext))
1291f4a2713aSLionel Sambuc       // Add predicate operands.
1292f4a2713aSLionel Sambuc       .addImm(MI->getOperand(3).getImm())
1293f4a2713aSLionel Sambuc       .addReg(MI->getOperand(4).getReg()));
1294f4a2713aSLionel Sambuc     return;
1295f4a2713aSLionel Sambuc   }
1296f4a2713aSLionel Sambuc   // Darwin call instructions are just normal call instructions with different
1297f4a2713aSLionel Sambuc   // clobber semantics (they clobber R9).
1298f4a2713aSLionel Sambuc   case ARM::BX_CALL: {
1299*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::MOVr)
1300f4a2713aSLionel Sambuc       .addReg(ARM::LR)
1301f4a2713aSLionel Sambuc       .addReg(ARM::PC)
1302f4a2713aSLionel Sambuc       // Add predicate operands.
1303f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1304f4a2713aSLionel Sambuc       .addReg(0)
1305f4a2713aSLionel Sambuc       // Add 's' bit operand (always reg0 for this)
1306f4a2713aSLionel Sambuc       .addReg(0));
1307f4a2713aSLionel Sambuc 
1308*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::BX)
1309f4a2713aSLionel Sambuc       .addReg(MI->getOperand(0).getReg()));
1310f4a2713aSLionel Sambuc     return;
1311f4a2713aSLionel Sambuc   }
1312f4a2713aSLionel Sambuc   case ARM::tBX_CALL: {
1313*0a6a1f1dSLionel Sambuc     if (Subtarget->hasV5TOps())
1314*0a6a1f1dSLionel Sambuc       llvm_unreachable("Expected BLX to be selected for v5t+");
1315f4a2713aSLionel Sambuc 
1316*0a6a1f1dSLionel Sambuc     // On ARM v4t, when doing a call from thumb mode, we need to ensure
1317*0a6a1f1dSLionel Sambuc     // that the saved lr has its LSB set correctly (the arch doesn't
1318*0a6a1f1dSLionel Sambuc     // have blx).
1319*0a6a1f1dSLionel Sambuc     // So here we generate a bl to a small jump pad that does bx rN.
1320*0a6a1f1dSLionel Sambuc     // The jump pads are emitted after the function body.
1321*0a6a1f1dSLionel Sambuc 
1322*0a6a1f1dSLionel Sambuc     unsigned TReg = MI->getOperand(0).getReg();
1323*0a6a1f1dSLionel Sambuc     MCSymbol *TRegSym = nullptr;
1324*0a6a1f1dSLionel Sambuc     for (unsigned i = 0, e = ThumbIndirectPads.size(); i < e; i++) {
1325*0a6a1f1dSLionel Sambuc       if (ThumbIndirectPads[i].first == TReg) {
1326*0a6a1f1dSLionel Sambuc         TRegSym = ThumbIndirectPads[i].second;
1327*0a6a1f1dSLionel Sambuc         break;
1328*0a6a1f1dSLionel Sambuc       }
1329*0a6a1f1dSLionel Sambuc     }
1330*0a6a1f1dSLionel Sambuc 
1331*0a6a1f1dSLionel Sambuc     if (!TRegSym) {
1332*0a6a1f1dSLionel Sambuc       TRegSym = OutContext.CreateTempSymbol();
1333*0a6a1f1dSLionel Sambuc       ThumbIndirectPads.push_back(std::make_pair(TReg, TRegSym));
1334*0a6a1f1dSLionel Sambuc     }
1335*0a6a1f1dSLionel Sambuc 
1336*0a6a1f1dSLionel Sambuc     // Create a link-saving branch to the Reg Indirect Jump Pad.
1337*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tBL)
1338*0a6a1f1dSLionel Sambuc         // Predicate comes first here.
1339*0a6a1f1dSLionel Sambuc         .addImm(ARMCC::AL).addReg(0)
1340*0a6a1f1dSLionel Sambuc         .addExpr(MCSymbolRefExpr::Create(TRegSym, OutContext)));
1341f4a2713aSLionel Sambuc     return;
1342f4a2713aSLionel Sambuc   }
1343f4a2713aSLionel Sambuc   case ARM::BMOVPCRX_CALL: {
1344*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::MOVr)
1345f4a2713aSLionel Sambuc       .addReg(ARM::LR)
1346f4a2713aSLionel Sambuc       .addReg(ARM::PC)
1347f4a2713aSLionel Sambuc       // Add predicate operands.
1348f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1349f4a2713aSLionel Sambuc       .addReg(0)
1350f4a2713aSLionel Sambuc       // Add 's' bit operand (always reg0 for this)
1351f4a2713aSLionel Sambuc       .addReg(0));
1352f4a2713aSLionel Sambuc 
1353*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::MOVr)
1354f4a2713aSLionel Sambuc       .addReg(ARM::PC)
1355f4a2713aSLionel Sambuc       .addReg(MI->getOperand(0).getReg())
1356f4a2713aSLionel Sambuc       // Add predicate operands.
1357f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1358f4a2713aSLionel Sambuc       .addReg(0)
1359f4a2713aSLionel Sambuc       // Add 's' bit operand (always reg0 for this)
1360f4a2713aSLionel Sambuc       .addReg(0));
1361f4a2713aSLionel Sambuc     return;
1362f4a2713aSLionel Sambuc   }
1363f4a2713aSLionel Sambuc   case ARM::BMOVPCB_CALL: {
1364*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::MOVr)
1365f4a2713aSLionel Sambuc       .addReg(ARM::LR)
1366f4a2713aSLionel Sambuc       .addReg(ARM::PC)
1367f4a2713aSLionel Sambuc       // Add predicate operands.
1368f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1369f4a2713aSLionel Sambuc       .addReg(0)
1370f4a2713aSLionel Sambuc       // Add 's' bit operand (always reg0 for this)
1371f4a2713aSLionel Sambuc       .addReg(0));
1372f4a2713aSLionel Sambuc 
1373*0a6a1f1dSLionel Sambuc     const MachineOperand &Op = MI->getOperand(0);
1374*0a6a1f1dSLionel Sambuc     const GlobalValue *GV = Op.getGlobal();
1375*0a6a1f1dSLionel Sambuc     const unsigned TF = Op.getTargetFlags();
1376*0a6a1f1dSLionel Sambuc     MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
1377f4a2713aSLionel Sambuc     const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext);
1378*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::Bcc)
1379f4a2713aSLionel Sambuc       .addExpr(GVSymExpr)
1380f4a2713aSLionel Sambuc       // Add predicate operands.
1381f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1382f4a2713aSLionel Sambuc       .addReg(0));
1383f4a2713aSLionel Sambuc     return;
1384f4a2713aSLionel Sambuc   }
1385f4a2713aSLionel Sambuc   case ARM::MOVi16_ga_pcrel:
1386f4a2713aSLionel Sambuc   case ARM::t2MOVi16_ga_pcrel: {
1387f4a2713aSLionel Sambuc     MCInst TmpInst;
1388f4a2713aSLionel Sambuc     TmpInst.setOpcode(Opc == ARM::MOVi16_ga_pcrel? ARM::MOVi16 : ARM::t2MOVi16);
1389f4a2713aSLionel Sambuc     TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
1390f4a2713aSLionel Sambuc 
1391f4a2713aSLionel Sambuc     unsigned TF = MI->getOperand(1).getTargetFlags();
1392f4a2713aSLionel Sambuc     const GlobalValue *GV = MI->getOperand(1).getGlobal();
1393*0a6a1f1dSLionel Sambuc     MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
1394f4a2713aSLionel Sambuc     const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext);
1395*0a6a1f1dSLionel Sambuc 
1396*0a6a1f1dSLionel Sambuc     MCSymbol *LabelSym = getPICLabel(DL->getPrivateGlobalPrefix(),
1397f4a2713aSLionel Sambuc                                      getFunctionNumber(),
1398f4a2713aSLionel Sambuc                                      MI->getOperand(2).getImm(), OutContext);
1399f4a2713aSLionel Sambuc     const MCExpr *LabelSymExpr= MCSymbolRefExpr::Create(LabelSym, OutContext);
1400f4a2713aSLionel Sambuc     unsigned PCAdj = (Opc == ARM::MOVi16_ga_pcrel) ? 8 : 4;
1401f4a2713aSLionel Sambuc     const MCExpr *PCRelExpr =
1402f4a2713aSLionel Sambuc       ARMMCExpr::CreateLower16(MCBinaryExpr::CreateSub(GVSymExpr,
1403f4a2713aSLionel Sambuc                                       MCBinaryExpr::CreateAdd(LabelSymExpr,
1404f4a2713aSLionel Sambuc                                       MCConstantExpr::Create(PCAdj, OutContext),
1405f4a2713aSLionel Sambuc                                       OutContext), OutContext), OutContext);
1406f4a2713aSLionel Sambuc       TmpInst.addOperand(MCOperand::CreateExpr(PCRelExpr));
1407f4a2713aSLionel Sambuc 
1408f4a2713aSLionel Sambuc     // Add predicate operands.
1409f4a2713aSLionel Sambuc     TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1410f4a2713aSLionel Sambuc     TmpInst.addOperand(MCOperand::CreateReg(0));
1411f4a2713aSLionel Sambuc     // Add 's' bit operand (always reg0 for this)
1412f4a2713aSLionel Sambuc     TmpInst.addOperand(MCOperand::CreateReg(0));
1413*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, TmpInst);
1414f4a2713aSLionel Sambuc     return;
1415f4a2713aSLionel Sambuc   }
1416f4a2713aSLionel Sambuc   case ARM::MOVTi16_ga_pcrel:
1417f4a2713aSLionel Sambuc   case ARM::t2MOVTi16_ga_pcrel: {
1418f4a2713aSLionel Sambuc     MCInst TmpInst;
1419f4a2713aSLionel Sambuc     TmpInst.setOpcode(Opc == ARM::MOVTi16_ga_pcrel
1420f4a2713aSLionel Sambuc                       ? ARM::MOVTi16 : ARM::t2MOVTi16);
1421f4a2713aSLionel Sambuc     TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
1422f4a2713aSLionel Sambuc     TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
1423f4a2713aSLionel Sambuc 
1424f4a2713aSLionel Sambuc     unsigned TF = MI->getOperand(2).getTargetFlags();
1425f4a2713aSLionel Sambuc     const GlobalValue *GV = MI->getOperand(2).getGlobal();
1426*0a6a1f1dSLionel Sambuc     MCSymbol *GVSym = GetARMGVSymbol(GV, TF);
1427f4a2713aSLionel Sambuc     const MCExpr *GVSymExpr = MCSymbolRefExpr::Create(GVSym, OutContext);
1428*0a6a1f1dSLionel Sambuc 
1429*0a6a1f1dSLionel Sambuc     MCSymbol *LabelSym = getPICLabel(DL->getPrivateGlobalPrefix(),
1430f4a2713aSLionel Sambuc                                      getFunctionNumber(),
1431f4a2713aSLionel Sambuc                                      MI->getOperand(3).getImm(), OutContext);
1432f4a2713aSLionel Sambuc     const MCExpr *LabelSymExpr= MCSymbolRefExpr::Create(LabelSym, OutContext);
1433f4a2713aSLionel Sambuc     unsigned PCAdj = (Opc == ARM::MOVTi16_ga_pcrel) ? 8 : 4;
1434f4a2713aSLionel Sambuc     const MCExpr *PCRelExpr =
1435f4a2713aSLionel Sambuc         ARMMCExpr::CreateUpper16(MCBinaryExpr::CreateSub(GVSymExpr,
1436f4a2713aSLionel Sambuc                                    MCBinaryExpr::CreateAdd(LabelSymExpr,
1437f4a2713aSLionel Sambuc                                       MCConstantExpr::Create(PCAdj, OutContext),
1438f4a2713aSLionel Sambuc                                           OutContext), OutContext), OutContext);
1439f4a2713aSLionel Sambuc       TmpInst.addOperand(MCOperand::CreateExpr(PCRelExpr));
1440f4a2713aSLionel Sambuc     // Add predicate operands.
1441f4a2713aSLionel Sambuc     TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1442f4a2713aSLionel Sambuc     TmpInst.addOperand(MCOperand::CreateReg(0));
1443f4a2713aSLionel Sambuc     // Add 's' bit operand (always reg0 for this)
1444f4a2713aSLionel Sambuc     TmpInst.addOperand(MCOperand::CreateReg(0));
1445*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, TmpInst);
1446f4a2713aSLionel Sambuc     return;
1447f4a2713aSLionel Sambuc   }
1448f4a2713aSLionel Sambuc   case ARM::tPICADD: {
1449f4a2713aSLionel Sambuc     // This is a pseudo op for a label + instruction sequence, which looks like:
1450f4a2713aSLionel Sambuc     // LPC0:
1451f4a2713aSLionel Sambuc     //     add r0, pc
1452f4a2713aSLionel Sambuc     // This adds the address of LPC0 to r0.
1453f4a2713aSLionel Sambuc 
1454f4a2713aSLionel Sambuc     // Emit the label.
1455*0a6a1f1dSLionel Sambuc     OutStreamer.EmitLabel(getPICLabel(DL->getPrivateGlobalPrefix(),
1456f4a2713aSLionel Sambuc                           getFunctionNumber(), MI->getOperand(2).getImm(),
1457f4a2713aSLionel Sambuc                           OutContext));
1458f4a2713aSLionel Sambuc 
1459f4a2713aSLionel Sambuc     // Form and emit the add.
1460*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tADDhirr)
1461f4a2713aSLionel Sambuc       .addReg(MI->getOperand(0).getReg())
1462f4a2713aSLionel Sambuc       .addReg(MI->getOperand(0).getReg())
1463f4a2713aSLionel Sambuc       .addReg(ARM::PC)
1464f4a2713aSLionel Sambuc       // Add predicate operands.
1465f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1466f4a2713aSLionel Sambuc       .addReg(0));
1467f4a2713aSLionel Sambuc     return;
1468f4a2713aSLionel Sambuc   }
1469f4a2713aSLionel Sambuc   case ARM::PICADD: {
1470f4a2713aSLionel Sambuc     // This is a pseudo op for a label + instruction sequence, which looks like:
1471f4a2713aSLionel Sambuc     // LPC0:
1472f4a2713aSLionel Sambuc     //     add r0, pc, r0
1473f4a2713aSLionel Sambuc     // This adds the address of LPC0 to r0.
1474f4a2713aSLionel Sambuc 
1475f4a2713aSLionel Sambuc     // Emit the label.
1476*0a6a1f1dSLionel Sambuc     OutStreamer.EmitLabel(getPICLabel(DL->getPrivateGlobalPrefix(),
1477f4a2713aSLionel Sambuc                           getFunctionNumber(), MI->getOperand(2).getImm(),
1478f4a2713aSLionel Sambuc                           OutContext));
1479f4a2713aSLionel Sambuc 
1480f4a2713aSLionel Sambuc     // Form and emit the add.
1481*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::ADDrr)
1482f4a2713aSLionel Sambuc       .addReg(MI->getOperand(0).getReg())
1483f4a2713aSLionel Sambuc       .addReg(ARM::PC)
1484f4a2713aSLionel Sambuc       .addReg(MI->getOperand(1).getReg())
1485f4a2713aSLionel Sambuc       // Add predicate operands.
1486f4a2713aSLionel Sambuc       .addImm(MI->getOperand(3).getImm())
1487f4a2713aSLionel Sambuc       .addReg(MI->getOperand(4).getReg())
1488f4a2713aSLionel Sambuc       // Add 's' bit operand (always reg0 for this)
1489f4a2713aSLionel Sambuc       .addReg(0));
1490f4a2713aSLionel Sambuc     return;
1491f4a2713aSLionel Sambuc   }
1492f4a2713aSLionel Sambuc   case ARM::PICSTR:
1493f4a2713aSLionel Sambuc   case ARM::PICSTRB:
1494f4a2713aSLionel Sambuc   case ARM::PICSTRH:
1495f4a2713aSLionel Sambuc   case ARM::PICLDR:
1496f4a2713aSLionel Sambuc   case ARM::PICLDRB:
1497f4a2713aSLionel Sambuc   case ARM::PICLDRH:
1498f4a2713aSLionel Sambuc   case ARM::PICLDRSB:
1499f4a2713aSLionel Sambuc   case ARM::PICLDRSH: {
1500f4a2713aSLionel Sambuc     // This is a pseudo op for a label + instruction sequence, which looks like:
1501f4a2713aSLionel Sambuc     // LPC0:
1502f4a2713aSLionel Sambuc     //     OP r0, [pc, r0]
1503f4a2713aSLionel Sambuc     // The LCP0 label is referenced by a constant pool entry in order to get
1504f4a2713aSLionel Sambuc     // a PC-relative address at the ldr instruction.
1505f4a2713aSLionel Sambuc 
1506f4a2713aSLionel Sambuc     // Emit the label.
1507*0a6a1f1dSLionel Sambuc     OutStreamer.EmitLabel(getPICLabel(DL->getPrivateGlobalPrefix(),
1508f4a2713aSLionel Sambuc                           getFunctionNumber(), MI->getOperand(2).getImm(),
1509f4a2713aSLionel Sambuc                           OutContext));
1510f4a2713aSLionel Sambuc 
1511f4a2713aSLionel Sambuc     // Form and emit the load
1512f4a2713aSLionel Sambuc     unsigned Opcode;
1513f4a2713aSLionel Sambuc     switch (MI->getOpcode()) {
1514f4a2713aSLionel Sambuc     default:
1515f4a2713aSLionel Sambuc       llvm_unreachable("Unexpected opcode!");
1516f4a2713aSLionel Sambuc     case ARM::PICSTR:   Opcode = ARM::STRrs; break;
1517f4a2713aSLionel Sambuc     case ARM::PICSTRB:  Opcode = ARM::STRBrs; break;
1518f4a2713aSLionel Sambuc     case ARM::PICSTRH:  Opcode = ARM::STRH; break;
1519f4a2713aSLionel Sambuc     case ARM::PICLDR:   Opcode = ARM::LDRrs; break;
1520f4a2713aSLionel Sambuc     case ARM::PICLDRB:  Opcode = ARM::LDRBrs; break;
1521f4a2713aSLionel Sambuc     case ARM::PICLDRH:  Opcode = ARM::LDRH; break;
1522f4a2713aSLionel Sambuc     case ARM::PICLDRSB: Opcode = ARM::LDRSB; break;
1523f4a2713aSLionel Sambuc     case ARM::PICLDRSH: Opcode = ARM::LDRSH; break;
1524f4a2713aSLionel Sambuc     }
1525*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(Opcode)
1526f4a2713aSLionel Sambuc       .addReg(MI->getOperand(0).getReg())
1527f4a2713aSLionel Sambuc       .addReg(ARM::PC)
1528f4a2713aSLionel Sambuc       .addReg(MI->getOperand(1).getReg())
1529f4a2713aSLionel Sambuc       .addImm(0)
1530f4a2713aSLionel Sambuc       // Add predicate operands.
1531f4a2713aSLionel Sambuc       .addImm(MI->getOperand(3).getImm())
1532f4a2713aSLionel Sambuc       .addReg(MI->getOperand(4).getReg()));
1533f4a2713aSLionel Sambuc 
1534f4a2713aSLionel Sambuc     return;
1535f4a2713aSLionel Sambuc   }
1536f4a2713aSLionel Sambuc   case ARM::CONSTPOOL_ENTRY: {
1537f4a2713aSLionel Sambuc     /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool
1538f4a2713aSLionel Sambuc     /// in the function.  The first operand is the ID# for this instruction, the
1539f4a2713aSLionel Sambuc     /// second is the index into the MachineConstantPool that this is, the third
1540f4a2713aSLionel Sambuc     /// is the size in bytes of this constant pool entry.
1541f4a2713aSLionel Sambuc     /// The required alignment is specified on the basic block holding this MI.
1542f4a2713aSLionel Sambuc     unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
1543f4a2713aSLionel Sambuc     unsigned CPIdx   = (unsigned)MI->getOperand(1).getIndex();
1544f4a2713aSLionel Sambuc 
1545f4a2713aSLionel Sambuc     // If this is the first entry of the pool, mark it.
1546f4a2713aSLionel Sambuc     if (!InConstantPool) {
1547f4a2713aSLionel Sambuc       OutStreamer.EmitDataRegion(MCDR_DataRegion);
1548f4a2713aSLionel Sambuc       InConstantPool = true;
1549f4a2713aSLionel Sambuc     }
1550f4a2713aSLionel Sambuc 
1551f4a2713aSLionel Sambuc     OutStreamer.EmitLabel(GetCPISymbol(LabelId));
1552f4a2713aSLionel Sambuc 
1553f4a2713aSLionel Sambuc     const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
1554f4a2713aSLionel Sambuc     if (MCPE.isMachineConstantPoolEntry())
1555f4a2713aSLionel Sambuc       EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
1556f4a2713aSLionel Sambuc     else
1557f4a2713aSLionel Sambuc       EmitGlobalConstant(MCPE.Val.ConstVal);
1558f4a2713aSLionel Sambuc     return;
1559f4a2713aSLionel Sambuc   }
1560f4a2713aSLionel Sambuc   case ARM::t2BR_JT: {
1561f4a2713aSLionel Sambuc     // Lower and emit the instruction itself, then the jump table following it.
1562*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tMOVr)
1563f4a2713aSLionel Sambuc       .addReg(ARM::PC)
1564f4a2713aSLionel Sambuc       .addReg(MI->getOperand(0).getReg())
1565f4a2713aSLionel Sambuc       // Add predicate operands.
1566f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1567f4a2713aSLionel Sambuc       .addReg(0));
1568f4a2713aSLionel Sambuc 
1569f4a2713aSLionel Sambuc     // Output the data for the jump table itself
1570f4a2713aSLionel Sambuc     EmitJump2Table(MI);
1571f4a2713aSLionel Sambuc     return;
1572f4a2713aSLionel Sambuc   }
1573f4a2713aSLionel Sambuc   case ARM::t2TBB_JT: {
1574f4a2713aSLionel Sambuc     // Lower and emit the instruction itself, then the jump table following it.
1575*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::t2TBB)
1576f4a2713aSLionel Sambuc       .addReg(ARM::PC)
1577f4a2713aSLionel Sambuc       .addReg(MI->getOperand(0).getReg())
1578f4a2713aSLionel Sambuc       // Add predicate operands.
1579f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1580f4a2713aSLionel Sambuc       .addReg(0));
1581f4a2713aSLionel Sambuc 
1582f4a2713aSLionel Sambuc     // Output the data for the jump table itself
1583f4a2713aSLionel Sambuc     EmitJump2Table(MI);
1584f4a2713aSLionel Sambuc     // Make sure the next instruction is 2-byte aligned.
1585f4a2713aSLionel Sambuc     EmitAlignment(1);
1586f4a2713aSLionel Sambuc     return;
1587f4a2713aSLionel Sambuc   }
1588f4a2713aSLionel Sambuc   case ARM::t2TBH_JT: {
1589f4a2713aSLionel Sambuc     // Lower and emit the instruction itself, then the jump table following it.
1590*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::t2TBH)
1591f4a2713aSLionel Sambuc       .addReg(ARM::PC)
1592f4a2713aSLionel Sambuc       .addReg(MI->getOperand(0).getReg())
1593f4a2713aSLionel Sambuc       // Add predicate operands.
1594f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1595f4a2713aSLionel Sambuc       .addReg(0));
1596f4a2713aSLionel Sambuc 
1597f4a2713aSLionel Sambuc     // Output the data for the jump table itself
1598f4a2713aSLionel Sambuc     EmitJump2Table(MI);
1599f4a2713aSLionel Sambuc     return;
1600f4a2713aSLionel Sambuc   }
1601f4a2713aSLionel Sambuc   case ARM::tBR_JTr:
1602f4a2713aSLionel Sambuc   case ARM::BR_JTr: {
1603f4a2713aSLionel Sambuc     // Lower and emit the instruction itself, then the jump table following it.
1604f4a2713aSLionel Sambuc     // mov pc, target
1605f4a2713aSLionel Sambuc     MCInst TmpInst;
1606f4a2713aSLionel Sambuc     unsigned Opc = MI->getOpcode() == ARM::BR_JTr ?
1607f4a2713aSLionel Sambuc       ARM::MOVr : ARM::tMOVr;
1608f4a2713aSLionel Sambuc     TmpInst.setOpcode(Opc);
1609f4a2713aSLionel Sambuc     TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1610f4a2713aSLionel Sambuc     TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
1611f4a2713aSLionel Sambuc     // Add predicate operands.
1612f4a2713aSLionel Sambuc     TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1613f4a2713aSLionel Sambuc     TmpInst.addOperand(MCOperand::CreateReg(0));
1614f4a2713aSLionel Sambuc     // Add 's' bit operand (always reg0 for this)
1615f4a2713aSLionel Sambuc     if (Opc == ARM::MOVr)
1616f4a2713aSLionel Sambuc       TmpInst.addOperand(MCOperand::CreateReg(0));
1617*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, TmpInst);
1618f4a2713aSLionel Sambuc 
1619f4a2713aSLionel Sambuc     // Make sure the Thumb jump table is 4-byte aligned.
1620f4a2713aSLionel Sambuc     if (Opc == ARM::tMOVr)
1621f4a2713aSLionel Sambuc       EmitAlignment(2);
1622f4a2713aSLionel Sambuc 
1623f4a2713aSLionel Sambuc     // Output the data for the jump table itself
1624f4a2713aSLionel Sambuc     EmitJumpTable(MI);
1625f4a2713aSLionel Sambuc     return;
1626f4a2713aSLionel Sambuc   }
1627f4a2713aSLionel Sambuc   case ARM::BR_JTm: {
1628f4a2713aSLionel Sambuc     // Lower and emit the instruction itself, then the jump table following it.
1629f4a2713aSLionel Sambuc     // ldr pc, target
1630f4a2713aSLionel Sambuc     MCInst TmpInst;
1631f4a2713aSLionel Sambuc     if (MI->getOperand(1).getReg() == 0) {
1632f4a2713aSLionel Sambuc       // literal offset
1633f4a2713aSLionel Sambuc       TmpInst.setOpcode(ARM::LDRi12);
1634f4a2713aSLionel Sambuc       TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1635f4a2713aSLionel Sambuc       TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
1636f4a2713aSLionel Sambuc       TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
1637f4a2713aSLionel Sambuc     } else {
1638f4a2713aSLionel Sambuc       TmpInst.setOpcode(ARM::LDRrs);
1639f4a2713aSLionel Sambuc       TmpInst.addOperand(MCOperand::CreateReg(ARM::PC));
1640f4a2713aSLionel Sambuc       TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
1641f4a2713aSLionel Sambuc       TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
1642f4a2713aSLionel Sambuc       TmpInst.addOperand(MCOperand::CreateImm(0));
1643f4a2713aSLionel Sambuc     }
1644f4a2713aSLionel Sambuc     // Add predicate operands.
1645f4a2713aSLionel Sambuc     TmpInst.addOperand(MCOperand::CreateImm(ARMCC::AL));
1646f4a2713aSLionel Sambuc     TmpInst.addOperand(MCOperand::CreateReg(0));
1647*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, TmpInst);
1648f4a2713aSLionel Sambuc 
1649f4a2713aSLionel Sambuc     // Output the data for the jump table itself
1650f4a2713aSLionel Sambuc     EmitJumpTable(MI);
1651f4a2713aSLionel Sambuc     return;
1652f4a2713aSLionel Sambuc   }
1653f4a2713aSLionel Sambuc   case ARM::BR_JTadd: {
1654f4a2713aSLionel Sambuc     // Lower and emit the instruction itself, then the jump table following it.
1655f4a2713aSLionel Sambuc     // add pc, target, idx
1656*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::ADDrr)
1657f4a2713aSLionel Sambuc       .addReg(ARM::PC)
1658f4a2713aSLionel Sambuc       .addReg(MI->getOperand(0).getReg())
1659f4a2713aSLionel Sambuc       .addReg(MI->getOperand(1).getReg())
1660f4a2713aSLionel Sambuc       // Add predicate operands.
1661f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1662f4a2713aSLionel Sambuc       .addReg(0)
1663f4a2713aSLionel Sambuc       // Add 's' bit operand (always reg0 for this)
1664f4a2713aSLionel Sambuc       .addReg(0));
1665f4a2713aSLionel Sambuc 
1666f4a2713aSLionel Sambuc     // Output the data for the jump table itself
1667f4a2713aSLionel Sambuc     EmitJumpTable(MI);
1668f4a2713aSLionel Sambuc     return;
1669f4a2713aSLionel Sambuc   }
1670*0a6a1f1dSLionel Sambuc   case ARM::SPACE:
1671*0a6a1f1dSLionel Sambuc     OutStreamer.EmitZeros(MI->getOperand(1).getImm());
1672*0a6a1f1dSLionel Sambuc     return;
1673f4a2713aSLionel Sambuc   case ARM::TRAP: {
1674f4a2713aSLionel Sambuc     // Non-Darwin binutils don't yet support the "trap" mnemonic.
1675f4a2713aSLionel Sambuc     // FIXME: Remove this special case when they do.
1676*0a6a1f1dSLionel Sambuc     if (!Subtarget->isTargetMachO()) {
1677f4a2713aSLionel Sambuc       //.long 0xe7ffdefe @ trap
1678f4a2713aSLionel Sambuc       uint32_t Val = 0xe7ffdefeUL;
1679f4a2713aSLionel Sambuc       OutStreamer.AddComment("trap");
1680f4a2713aSLionel Sambuc       OutStreamer.EmitIntValue(Val, 4);
1681f4a2713aSLionel Sambuc       return;
1682f4a2713aSLionel Sambuc     }
1683f4a2713aSLionel Sambuc     break;
1684f4a2713aSLionel Sambuc   }
1685f4a2713aSLionel Sambuc   case ARM::TRAPNaCl: {
1686f4a2713aSLionel Sambuc     //.long 0xe7fedef0 @ trap
1687f4a2713aSLionel Sambuc     uint32_t Val = 0xe7fedef0UL;
1688f4a2713aSLionel Sambuc     OutStreamer.AddComment("trap");
1689f4a2713aSLionel Sambuc     OutStreamer.EmitIntValue(Val, 4);
1690f4a2713aSLionel Sambuc     return;
1691f4a2713aSLionel Sambuc   }
1692f4a2713aSLionel Sambuc   case ARM::tTRAP: {
1693f4a2713aSLionel Sambuc     // Non-Darwin binutils don't yet support the "trap" mnemonic.
1694f4a2713aSLionel Sambuc     // FIXME: Remove this special case when they do.
1695*0a6a1f1dSLionel Sambuc     if (!Subtarget->isTargetMachO()) {
1696f4a2713aSLionel Sambuc       //.short 57086 @ trap
1697f4a2713aSLionel Sambuc       uint16_t Val = 0xdefe;
1698f4a2713aSLionel Sambuc       OutStreamer.AddComment("trap");
1699f4a2713aSLionel Sambuc       OutStreamer.EmitIntValue(Val, 2);
1700f4a2713aSLionel Sambuc       return;
1701f4a2713aSLionel Sambuc     }
1702f4a2713aSLionel Sambuc     break;
1703f4a2713aSLionel Sambuc   }
1704f4a2713aSLionel Sambuc   case ARM::t2Int_eh_sjlj_setjmp:
1705f4a2713aSLionel Sambuc   case ARM::t2Int_eh_sjlj_setjmp_nofp:
1706f4a2713aSLionel Sambuc   case ARM::tInt_eh_sjlj_setjmp: {
1707f4a2713aSLionel Sambuc     // Two incoming args: GPR:$src, GPR:$val
1708f4a2713aSLionel Sambuc     // mov $val, pc
1709f4a2713aSLionel Sambuc     // adds $val, #7
1710f4a2713aSLionel Sambuc     // str $val, [$src, #4]
1711f4a2713aSLionel Sambuc     // movs r0, #0
1712f4a2713aSLionel Sambuc     // b 1f
1713f4a2713aSLionel Sambuc     // movs r0, #1
1714f4a2713aSLionel Sambuc     // 1:
1715f4a2713aSLionel Sambuc     unsigned SrcReg = MI->getOperand(0).getReg();
1716f4a2713aSLionel Sambuc     unsigned ValReg = MI->getOperand(1).getReg();
1717f4a2713aSLionel Sambuc     MCSymbol *Label = GetARMSJLJEHLabel();
1718f4a2713aSLionel Sambuc     OutStreamer.AddComment("eh_setjmp begin");
1719*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tMOVr)
1720f4a2713aSLionel Sambuc       .addReg(ValReg)
1721f4a2713aSLionel Sambuc       .addReg(ARM::PC)
1722f4a2713aSLionel Sambuc       // Predicate.
1723f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1724f4a2713aSLionel Sambuc       .addReg(0));
1725f4a2713aSLionel Sambuc 
1726*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tADDi3)
1727f4a2713aSLionel Sambuc       .addReg(ValReg)
1728f4a2713aSLionel Sambuc       // 's' bit operand
1729f4a2713aSLionel Sambuc       .addReg(ARM::CPSR)
1730f4a2713aSLionel Sambuc       .addReg(ValReg)
1731f4a2713aSLionel Sambuc       .addImm(7)
1732f4a2713aSLionel Sambuc       // Predicate.
1733f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1734f4a2713aSLionel Sambuc       .addReg(0));
1735f4a2713aSLionel Sambuc 
1736*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tSTRi)
1737f4a2713aSLionel Sambuc       .addReg(ValReg)
1738f4a2713aSLionel Sambuc       .addReg(SrcReg)
1739f4a2713aSLionel Sambuc       // The offset immediate is #4. The operand value is scaled by 4 for the
1740f4a2713aSLionel Sambuc       // tSTR instruction.
1741f4a2713aSLionel Sambuc       .addImm(1)
1742f4a2713aSLionel Sambuc       // Predicate.
1743f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1744f4a2713aSLionel Sambuc       .addReg(0));
1745f4a2713aSLionel Sambuc 
1746*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tMOVi8)
1747f4a2713aSLionel Sambuc       .addReg(ARM::R0)
1748f4a2713aSLionel Sambuc       .addReg(ARM::CPSR)
1749f4a2713aSLionel Sambuc       .addImm(0)
1750f4a2713aSLionel Sambuc       // Predicate.
1751f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1752f4a2713aSLionel Sambuc       .addReg(0));
1753f4a2713aSLionel Sambuc 
1754f4a2713aSLionel Sambuc     const MCExpr *SymbolExpr = MCSymbolRefExpr::Create(Label, OutContext);
1755*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tB)
1756f4a2713aSLionel Sambuc       .addExpr(SymbolExpr)
1757f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1758f4a2713aSLionel Sambuc       .addReg(0));
1759f4a2713aSLionel Sambuc 
1760f4a2713aSLionel Sambuc     OutStreamer.AddComment("eh_setjmp end");
1761*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tMOVi8)
1762f4a2713aSLionel Sambuc       .addReg(ARM::R0)
1763f4a2713aSLionel Sambuc       .addReg(ARM::CPSR)
1764f4a2713aSLionel Sambuc       .addImm(1)
1765f4a2713aSLionel Sambuc       // Predicate.
1766f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1767f4a2713aSLionel Sambuc       .addReg(0));
1768f4a2713aSLionel Sambuc 
1769f4a2713aSLionel Sambuc     OutStreamer.EmitLabel(Label);
1770f4a2713aSLionel Sambuc     return;
1771f4a2713aSLionel Sambuc   }
1772f4a2713aSLionel Sambuc 
1773f4a2713aSLionel Sambuc   case ARM::Int_eh_sjlj_setjmp_nofp:
1774f4a2713aSLionel Sambuc   case ARM::Int_eh_sjlj_setjmp: {
1775f4a2713aSLionel Sambuc     // Two incoming args: GPR:$src, GPR:$val
1776f4a2713aSLionel Sambuc     // add $val, pc, #8
1777f4a2713aSLionel Sambuc     // str $val, [$src, #+4]
1778f4a2713aSLionel Sambuc     // mov r0, #0
1779f4a2713aSLionel Sambuc     // add pc, pc, #0
1780f4a2713aSLionel Sambuc     // mov r0, #1
1781f4a2713aSLionel Sambuc     unsigned SrcReg = MI->getOperand(0).getReg();
1782f4a2713aSLionel Sambuc     unsigned ValReg = MI->getOperand(1).getReg();
1783f4a2713aSLionel Sambuc 
1784f4a2713aSLionel Sambuc     OutStreamer.AddComment("eh_setjmp begin");
1785*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::ADDri)
1786f4a2713aSLionel Sambuc       .addReg(ValReg)
1787f4a2713aSLionel Sambuc       .addReg(ARM::PC)
1788f4a2713aSLionel Sambuc       .addImm(8)
1789f4a2713aSLionel Sambuc       // Predicate.
1790f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1791f4a2713aSLionel Sambuc       .addReg(0)
1792f4a2713aSLionel Sambuc       // 's' bit operand (always reg0 for this).
1793f4a2713aSLionel Sambuc       .addReg(0));
1794f4a2713aSLionel Sambuc 
1795*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::STRi12)
1796f4a2713aSLionel Sambuc       .addReg(ValReg)
1797f4a2713aSLionel Sambuc       .addReg(SrcReg)
1798f4a2713aSLionel Sambuc       .addImm(4)
1799f4a2713aSLionel Sambuc       // Predicate.
1800f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1801f4a2713aSLionel Sambuc       .addReg(0));
1802f4a2713aSLionel Sambuc 
1803*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::MOVi)
1804f4a2713aSLionel Sambuc       .addReg(ARM::R0)
1805f4a2713aSLionel Sambuc       .addImm(0)
1806f4a2713aSLionel Sambuc       // Predicate.
1807f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1808f4a2713aSLionel Sambuc       .addReg(0)
1809f4a2713aSLionel Sambuc       // 's' bit operand (always reg0 for this).
1810f4a2713aSLionel Sambuc       .addReg(0));
1811f4a2713aSLionel Sambuc 
1812*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::ADDri)
1813f4a2713aSLionel Sambuc       .addReg(ARM::PC)
1814f4a2713aSLionel Sambuc       .addReg(ARM::PC)
1815f4a2713aSLionel Sambuc       .addImm(0)
1816f4a2713aSLionel Sambuc       // Predicate.
1817f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1818f4a2713aSLionel Sambuc       .addReg(0)
1819f4a2713aSLionel Sambuc       // 's' bit operand (always reg0 for this).
1820f4a2713aSLionel Sambuc       .addReg(0));
1821f4a2713aSLionel Sambuc 
1822f4a2713aSLionel Sambuc     OutStreamer.AddComment("eh_setjmp end");
1823*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::MOVi)
1824f4a2713aSLionel Sambuc       .addReg(ARM::R0)
1825f4a2713aSLionel Sambuc       .addImm(1)
1826f4a2713aSLionel Sambuc       // Predicate.
1827f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1828f4a2713aSLionel Sambuc       .addReg(0)
1829f4a2713aSLionel Sambuc       // 's' bit operand (always reg0 for this).
1830f4a2713aSLionel Sambuc       .addReg(0));
1831f4a2713aSLionel Sambuc     return;
1832f4a2713aSLionel Sambuc   }
1833f4a2713aSLionel Sambuc   case ARM::Int_eh_sjlj_longjmp: {
1834f4a2713aSLionel Sambuc     // ldr sp, [$src, #8]
1835f4a2713aSLionel Sambuc     // ldr $scratch, [$src, #4]
1836f4a2713aSLionel Sambuc     // ldr r7, [$src]
1837f4a2713aSLionel Sambuc     // bx $scratch
1838f4a2713aSLionel Sambuc     unsigned SrcReg = MI->getOperand(0).getReg();
1839f4a2713aSLionel Sambuc     unsigned ScratchReg = MI->getOperand(1).getReg();
1840*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::LDRi12)
1841f4a2713aSLionel Sambuc       .addReg(ARM::SP)
1842f4a2713aSLionel Sambuc       .addReg(SrcReg)
1843f4a2713aSLionel Sambuc       .addImm(8)
1844f4a2713aSLionel Sambuc       // Predicate.
1845f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1846f4a2713aSLionel Sambuc       .addReg(0));
1847f4a2713aSLionel Sambuc 
1848*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::LDRi12)
1849f4a2713aSLionel Sambuc       .addReg(ScratchReg)
1850f4a2713aSLionel Sambuc       .addReg(SrcReg)
1851f4a2713aSLionel Sambuc       .addImm(4)
1852f4a2713aSLionel Sambuc       // Predicate.
1853f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1854f4a2713aSLionel Sambuc       .addReg(0));
1855f4a2713aSLionel Sambuc 
1856*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::LDRi12)
1857f4a2713aSLionel Sambuc       .addReg(ARM::R7)
1858f4a2713aSLionel Sambuc       .addReg(SrcReg)
1859f4a2713aSLionel Sambuc       .addImm(0)
1860f4a2713aSLionel Sambuc       // Predicate.
1861f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1862f4a2713aSLionel Sambuc       .addReg(0));
1863f4a2713aSLionel Sambuc 
1864*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::BX)
1865f4a2713aSLionel Sambuc       .addReg(ScratchReg)
1866f4a2713aSLionel Sambuc       // Predicate.
1867f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1868f4a2713aSLionel Sambuc       .addReg(0));
1869f4a2713aSLionel Sambuc     return;
1870f4a2713aSLionel Sambuc   }
1871f4a2713aSLionel Sambuc   case ARM::tInt_eh_sjlj_longjmp: {
1872f4a2713aSLionel Sambuc     // ldr $scratch, [$src, #8]
1873f4a2713aSLionel Sambuc     // mov sp, $scratch
1874f4a2713aSLionel Sambuc     // ldr $scratch, [$src, #4]
1875f4a2713aSLionel Sambuc     // ldr r7, [$src]
1876f4a2713aSLionel Sambuc     // bx $scratch
1877f4a2713aSLionel Sambuc     unsigned SrcReg = MI->getOperand(0).getReg();
1878f4a2713aSLionel Sambuc     unsigned ScratchReg = MI->getOperand(1).getReg();
1879*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tLDRi)
1880f4a2713aSLionel Sambuc       .addReg(ScratchReg)
1881f4a2713aSLionel Sambuc       .addReg(SrcReg)
1882f4a2713aSLionel Sambuc       // The offset immediate is #8. The operand value is scaled by 4 for the
1883f4a2713aSLionel Sambuc       // tLDR instruction.
1884f4a2713aSLionel Sambuc       .addImm(2)
1885f4a2713aSLionel Sambuc       // Predicate.
1886f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1887f4a2713aSLionel Sambuc       .addReg(0));
1888f4a2713aSLionel Sambuc 
1889*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tMOVr)
1890f4a2713aSLionel Sambuc       .addReg(ARM::SP)
1891f4a2713aSLionel Sambuc       .addReg(ScratchReg)
1892f4a2713aSLionel Sambuc       // Predicate.
1893f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1894f4a2713aSLionel Sambuc       .addReg(0));
1895f4a2713aSLionel Sambuc 
1896*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tLDRi)
1897f4a2713aSLionel Sambuc       .addReg(ScratchReg)
1898f4a2713aSLionel Sambuc       .addReg(SrcReg)
1899f4a2713aSLionel Sambuc       .addImm(1)
1900f4a2713aSLionel Sambuc       // Predicate.
1901f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1902f4a2713aSLionel Sambuc       .addReg(0));
1903f4a2713aSLionel Sambuc 
1904*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tLDRi)
1905f4a2713aSLionel Sambuc       .addReg(ARM::R7)
1906f4a2713aSLionel Sambuc       .addReg(SrcReg)
1907f4a2713aSLionel Sambuc       .addImm(0)
1908f4a2713aSLionel Sambuc       // Predicate.
1909f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1910f4a2713aSLionel Sambuc       .addReg(0));
1911f4a2713aSLionel Sambuc 
1912*0a6a1f1dSLionel Sambuc     EmitToStreamer(OutStreamer, MCInstBuilder(ARM::tBX)
1913f4a2713aSLionel Sambuc       .addReg(ScratchReg)
1914f4a2713aSLionel Sambuc       // Predicate.
1915f4a2713aSLionel Sambuc       .addImm(ARMCC::AL)
1916f4a2713aSLionel Sambuc       .addReg(0));
1917f4a2713aSLionel Sambuc     return;
1918f4a2713aSLionel Sambuc   }
1919f4a2713aSLionel Sambuc   }
1920f4a2713aSLionel Sambuc 
1921f4a2713aSLionel Sambuc   MCInst TmpInst;
1922f4a2713aSLionel Sambuc   LowerARMMachineInstrToMCInst(MI, TmpInst, *this);
1923f4a2713aSLionel Sambuc 
1924*0a6a1f1dSLionel Sambuc   EmitToStreamer(OutStreamer, TmpInst);
1925f4a2713aSLionel Sambuc }
1926f4a2713aSLionel Sambuc 
1927f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
1928f4a2713aSLionel Sambuc // Target Registry Stuff
1929f4a2713aSLionel Sambuc //===----------------------------------------------------------------------===//
1930f4a2713aSLionel Sambuc 
1931f4a2713aSLionel Sambuc // Force static initialization.
LLVMInitializeARMAsmPrinter()1932f4a2713aSLionel Sambuc extern "C" void LLVMInitializeARMAsmPrinter() {
1933*0a6a1f1dSLionel Sambuc   RegisterAsmPrinter<ARMAsmPrinter> X(TheARMLETarget);
1934*0a6a1f1dSLionel Sambuc   RegisterAsmPrinter<ARMAsmPrinter> Y(TheARMBETarget);
1935*0a6a1f1dSLionel Sambuc   RegisterAsmPrinter<ARMAsmPrinter> A(TheThumbLETarget);
1936*0a6a1f1dSLionel Sambuc   RegisterAsmPrinter<ARMAsmPrinter> B(TheThumbBETarget);
1937f4a2713aSLionel Sambuc }
1938