llvm.org GIT mirror llvm / f447a5f
sink the arm implementations of ASmPrinter and MCInstLower out of the AsmPrinter directory into libarm. Now the ARM InstPrinters depend jsut on the MC stuff, not on vmcore or codegen. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@108783 91177308-0d34-0410-b5e6-96231b3b80d8 Chris Lattner 10 years ago
6 changed file(s) with 1656 addition(s) and 1656 deletion(s). Raw diff Collapse all Expand all
0 //===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains a printer that converts from our internal representation
10 // of machine-dependent LLVM code to GAS-format ARM assembly language.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "asm-printer"
15 #include "ARM.h"
16 #include "ARMBuildAttrs.h"
17 #include "ARMAddressingModes.h"
18 #include "ARMConstantPoolValue.h"
19 #include "AsmPrinter/ARMInstPrinter.h"
20 #include "ARMMachineFunctionInfo.h"
21 #include "ARMMCInstLower.h"
22 #include "ARMTargetMachine.h"
23 #include "llvm/Analysis/DebugInfo.h"
24 #include "llvm/Constants.h"
25 #include "llvm/Module.h"
26 #include "llvm/Type.h"
27 #include "llvm/Assembly/Writer.h"
28 #include "llvm/CodeGen/AsmPrinter.h"
29 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
30 #include "llvm/CodeGen/MachineFunctionPass.h"
31 #include "llvm/CodeGen/MachineJumpTableInfo.h"
32 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
33 #include "llvm/MC/MCAsmInfo.h"
34 #include "llvm/MC/MCContext.h"
35 #include "llvm/MC/MCExpr.h"
36 #include "llvm/MC/MCInst.h"
37 #include "llvm/MC/MCSectionMachO.h"
38 #include "llvm/MC/MCStreamer.h"
39 #include "llvm/MC/MCSymbol.h"
40 #include "llvm/Target/Mangler.h"
41 #include "llvm/Target/TargetData.h"
42 #include "llvm/Target/TargetMachine.h"
43 #include "llvm/Target/TargetOptions.h"
44 #include "llvm/Target/TargetRegistry.h"
45 #include "llvm/ADT/SmallPtrSet.h"
46 #include "llvm/ADT/SmallString.h"
47 #include "llvm/ADT/StringExtras.h"
48 #include "llvm/Support/CommandLine.h"
49 #include "llvm/Support/ErrorHandling.h"
50 #include "llvm/Support/raw_ostream.h"
51 #include
52 using namespace llvm;
53
54 static cl::opt
55 EnableMCInst("enable-arm-mcinst-printer", cl::Hidden,
56 cl::desc("enable experimental asmprinter gunk in the arm backend"));
57
58 namespace {
59 class ARMAsmPrinter : public AsmPrinter {
60
61 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
62 /// make the right decision when printing asm code for different targets.
63 const ARMSubtarget *Subtarget;
64
65 /// AFI - Keep a pointer to ARMFunctionInfo for the current
66 /// MachineFunction.
67 ARMFunctionInfo *AFI;
68
69 /// MCP - Keep a pointer to constantpool entries of the current
70 /// MachineFunction.
71 const MachineConstantPool *MCP;
72
73 public:
74 explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
75 : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL) {
76 Subtarget = &TM.getSubtarget();
77 }
78
79 virtual const char *getPassName() const {
80 return "ARM Assembly Printer";
81 }
82
83 void printInstructionThroughMCStreamer(const MachineInstr *MI);
84
85
86 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
87 const char *Modifier = 0);
88 void printSOImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
89 void printSOImm2PartOperand(const MachineInstr *MI, int OpNum,
90 raw_ostream &O);
91 void printSORegOperand(const MachineInstr *MI, int OpNum,
92 raw_ostream &O);
93 void printAddrMode2Operand(const MachineInstr *MI, int OpNum,
94 raw_ostream &O);
95 void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNum,
96 raw_ostream &O);
97 void printAddrMode3Operand(const MachineInstr *MI, int OpNum,
98 raw_ostream &O);
99 void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNum,
100 raw_ostream &O);
101 void printAddrMode4Operand(const MachineInstr *MI, int OpNum,raw_ostream &O,
102 const char *Modifier = 0);
103 void printAddrMode5Operand(const MachineInstr *MI, int OpNum,raw_ostream &O,
104 const char *Modifier = 0);
105 void printAddrMode6Operand(const MachineInstr *MI, int OpNum,
106 raw_ostream &O);
107 void printAddrMode6OffsetOperand(const MachineInstr *MI, int OpNum,
108 raw_ostream &O);
109 void printAddrModePCOperand(const MachineInstr *MI, int OpNum,
110 raw_ostream &O,
111 const char *Modifier = 0);
112 void printBitfieldInvMaskImmOperand (const MachineInstr *MI, int OpNum,
113 raw_ostream &O);
114
115 void printThumbS4ImmOperand(const MachineInstr *MI, int OpNum,
116 raw_ostream &O);
117 void printThumbITMask(const MachineInstr *MI, int OpNum, raw_ostream &O);
118 void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNum,
119 raw_ostream &O);
120 void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNum,
121 raw_ostream &O,
122 unsigned Scale);
123 void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNum,
124 raw_ostream &O);
125 void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNum,
126 raw_ostream &O);
127 void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNum,
128 raw_ostream &O);
129 void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNum,
130 raw_ostream &O);
131
132 void printT2SOOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
133 void printT2AddrModeImm12Operand(const MachineInstr *MI, int OpNum,
134 raw_ostream &O);
135 void printT2AddrModeImm8Operand(const MachineInstr *MI, int OpNum,
136 raw_ostream &O);
137 void printT2AddrModeImm8s4Operand(const MachineInstr *MI, int OpNum,
138 raw_ostream &O);
139 void printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, int OpNum,
140 raw_ostream &O);
141 void printT2AddrModeImm8s4OffsetOperand(const MachineInstr *MI, int OpNum,
142 raw_ostream &O) {}
143 void printT2AddrModeSoRegOperand(const MachineInstr *MI, int OpNum,
144 raw_ostream &O);
145
146 void printCPSOptionOperand(const MachineInstr *MI, int OpNum,
147 raw_ostream &O) {}
148 void printMSRMaskOperand(const MachineInstr *MI, int OpNum,
149 raw_ostream &O) {}
150 void printNegZeroOperand(const MachineInstr *MI, int OpNum,
151 raw_ostream &O) {}
152 void printPredicateOperand(const MachineInstr *MI, int OpNum,
153 raw_ostream &O);
154 void printMandatoryPredicateOperand(const MachineInstr *MI, int OpNum,
155 raw_ostream &O);
156 void printSBitModifierOperand(const MachineInstr *MI, int OpNum,
157 raw_ostream &O);
158 void printPCLabel(const MachineInstr *MI, int OpNum,
159 raw_ostream &O);
160 void printRegisterList(const MachineInstr *MI, int OpNum,
161 raw_ostream &O);
162 void printCPInstOperand(const MachineInstr *MI, int OpNum,
163 raw_ostream &O,
164 const char *Modifier);
165 void printJTBlockOperand(const MachineInstr *MI, int OpNum,
166 raw_ostream &O);
167 void printJT2BlockOperand(const MachineInstr *MI, int OpNum,
168 raw_ostream &O);
169 void printTBAddrMode(const MachineInstr *MI, int OpNum,
170 raw_ostream &O);
171 void printNoHashImmediate(const MachineInstr *MI, int OpNum,
172 raw_ostream &O);
173 void printVFPf32ImmOperand(const MachineInstr *MI, int OpNum,
174 raw_ostream &O);
175 void printVFPf64ImmOperand(const MachineInstr *MI, int OpNum,
176 raw_ostream &O);
177 void printNEONModImmOperand(const MachineInstr *MI, int OpNum,
178 raw_ostream &O);
179
180 virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
181 unsigned AsmVariant, const char *ExtraCode,
182 raw_ostream &O);
183 virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
184 unsigned AsmVariant,
185 const char *ExtraCode, raw_ostream &O);
186
187 void printInstruction(const MachineInstr *MI, raw_ostream &O); // autogen
188 static const char *getRegisterName(unsigned RegNo);
189
190 virtual void EmitInstruction(const MachineInstr *MI);
191 bool runOnMachineFunction(MachineFunction &F);
192
193 virtual void EmitConstantPool() {} // we emit constant pools customly!
194 virtual void EmitFunctionEntryLabel();
195 void EmitStartOfAsmFile(Module &M);
196 void EmitEndOfAsmFile(Module &M);
197
198 MCSymbol *GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
199 const MachineBasicBlock *MBB) const;
200 MCSymbol *GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const;
201
202 /// EmitMachineConstantPoolValue - Print a machine constantpool value to
203 /// the .s file.
204 virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
205 SmallString<128> Str;
206 raw_svector_ostream OS(Str);
207 EmitMachineConstantPoolValue(MCPV, OS);
208 OutStreamer.EmitRawText(OS.str());
209 }
210
211 void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV,
212 raw_ostream &O) {
213 switch (TM.getTargetData()->getTypeAllocSize(MCPV->getType())) {
214 case 1: O << MAI->getData8bitsDirective(0); break;
215 case 2: O << MAI->getData16bitsDirective(0); break;
216 case 4: O << MAI->getData32bitsDirective(0); break;
217 default: assert(0 && "Unknown CPV size");
218 }
219
220 ARMConstantPoolValue *ACPV = static_cast(MCPV);
221
222 if (ACPV->isLSDA()) {
223 O << MAI->getPrivateGlobalPrefix() << "_LSDA_" << getFunctionNumber();
224 } else if (ACPV->isBlockAddress()) {
225 O << *GetBlockAddressSymbol(ACPV->getBlockAddress());
226 } else if (ACPV->isGlobalValue()) {
227 const GlobalValue *GV = ACPV->getGV();
228 bool isIndirect = Subtarget->isTargetDarwin() &&
229 Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel());
230 if (!isIndirect)
231 O << *Mang->getSymbol(GV);
232 else {
233 // FIXME: Remove this when Darwin transition to @GOT like syntax.
234 MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
235 O << *Sym;
236
237 MachineModuleInfoMachO &MMIMachO =
238 MMI->getObjFileInfo();
239 MachineModuleInfoImpl::StubValueTy &StubSym =
240 GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(Sym) :
241 MMIMachO.getGVStubEntry(Sym);
242 if (StubSym.getPointer() == 0)
243 StubSym = MachineModuleInfoImpl::
244 StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage());
245 }
246 } else {
247 assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
248 O << *GetExternalSymbolSymbol(ACPV->getSymbol());
249 }
250
251 if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
252 if (ACPV->getPCAdjustment() != 0) {
253 O << "-(" << MAI->getPrivateGlobalPrefix() << "PC"
254 << getFunctionNumber() << "_" << ACPV->getLabelId()
255 << "+" << (unsigned)ACPV->getPCAdjustment();
256 if (ACPV->mustAddCurrentAddress())
257 O << "-.";
258 O << ')';
259 }
260 }
261 };
262 } // end of anonymous namespace
263
264 #include "ARMGenAsmWriter.inc"
265
266 void ARMAsmPrinter::EmitFunctionEntryLabel() {
267 if (AFI->isThumbFunction()) {
268 OutStreamer.EmitRawText(StringRef("\t.code\t16"));
269 if (!Subtarget->isTargetDarwin())
270 OutStreamer.EmitRawText(StringRef("\t.thumb_func"));
271 else {
272 // This needs to emit to a temporary string to get properly quoted
273 // MCSymbols when they have spaces in them.
274 SmallString<128> Tmp;
275 raw_svector_ostream OS(Tmp);
276 OS << "\t.thumb_func\t" << *CurrentFnSym;
277 OutStreamer.EmitRawText(OS.str());
278 }
279 }
280
281 OutStreamer.EmitLabel(CurrentFnSym);
282 }
283
284 /// runOnMachineFunction - This uses the printInstruction()
285 /// method to print assembly for each instruction.
286 ///
287 bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
288 AFI = MF.getInfo();
289 MCP = MF.getConstantPool();
290
291 return AsmPrinter::runOnMachineFunction(MF);
292 }
293
294 void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
295 raw_ostream &O, const char *Modifier) {
296 const MachineOperand &MO = MI->getOperand(OpNum);
297 unsigned TF = MO.getTargetFlags();
298
299 switch (MO.getType()) {
300 default:
301 assert(0 && "");
302 case MachineOperand::MO_Register: {
303 unsigned Reg = MO.getReg();
304 assert(TargetRegisterInfo::isPhysicalRegister(Reg));
305 if (Modifier && strcmp(Modifier, "dregpair") == 0) {
306 unsigned DRegLo = TM.getRegisterInfo()->getSubReg(Reg, ARM::dsub_0);
307 unsigned DRegHi = TM.getRegisterInfo()->getSubReg(Reg, ARM::dsub_1);
308 O << '{'
309 << getRegisterName(DRegLo) << ", " << getRegisterName(DRegHi)
310 << '}';
311 } else if (Modifier && strcmp(Modifier, "lane") == 0) {
312 unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg);
313 unsigned DReg =
314 TM.getRegisterInfo()->getMatchingSuperReg(Reg,
315 RegNum & 1 ? ARM::ssub_1 : ARM::ssub_0, &ARM::DPR_VFP2RegClass);
316 O << getRegisterName(DReg) << '[' << (RegNum & 1) << ']';
317 } else {
318 assert(!MO.getSubReg() && "Subregs should be eliminated!");
319 O << getRegisterName(Reg);
320 }
321 break;
322 }
323 case MachineOperand::MO_Immediate: {
324 int64_t Imm = MO.getImm();
325 O << '#';
326 if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
327 (TF & ARMII::MO_LO16))
328 O << ":lower16:";
329 else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
330 (TF & ARMII::MO_HI16))
331 O << ":upper16:";
332 O << Imm;
333 break;
334 }
335 case MachineOperand::MO_MachineBasicBlock:
336 O << *MO.getMBB()->getSymbol();
337 return;
338 case MachineOperand::MO_GlobalAddress: {
339 bool isCallOp = Modifier && !strcmp(Modifier, "call");
340 const GlobalValue *GV = MO.getGlobal();
341
342 if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
343 (TF & ARMII::MO_LO16))
344 O << ":lower16:";
345 else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
346 (TF & ARMII::MO_HI16))
347 O << ":upper16:";
348 O << *Mang->getSymbol(GV);
349
350 printOffset(MO.getOffset(), O);
351
352 if (isCallOp && Subtarget->isTargetELF() &&
353 TM.getRelocationModel() == Reloc::PIC_)
354 O << "(PLT)";
355 break;
356 }
357 case MachineOperand::MO_ExternalSymbol: {
358 bool isCallOp = Modifier && !strcmp(Modifier, "call");
359 O << *GetExternalSymbolSymbol(MO.getSymbolName());
360
361 if (isCallOp && Subtarget->isTargetELF() &&
362 TM.getRelocationModel() == Reloc::PIC_)
363 O << "(PLT)";
364 break;
365 }
366 case MachineOperand::MO_ConstantPoolIndex:
367 O << *GetCPISymbol(MO.getIndex());
368 break;
369 case MachineOperand::MO_JumpTableIndex:
370 O << *GetJTISymbol(MO.getIndex());
371 break;
372 }
373 }
374
375 static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm,
376 const MCAsmInfo *MAI) {
377 // Break it up into two parts that make up a shifter immediate.
378 V = ARM_AM::getSOImmVal(V);
379 assert(V != -1 && "Not a valid so_imm value!");
380
381 unsigned Imm = ARM_AM::getSOImmValImm(V);
382 unsigned Rot = ARM_AM::getSOImmValRot(V);
383
384 // Print low-level immediate formation info, per
385 // A5.1.3: "Data-processing operands - Immediate".
386 if (Rot) {
387 O << "#" << Imm << ", " << Rot;
388 // Pretty printed version.
389 if (VerboseAsm) {
390 O << "\t" << MAI->getCommentString() << ' ';
391 O << (int)ARM_AM::rotr32(Imm, Rot);
392 }
393 } else {
394 O << "#" << Imm;
395 }
396 }
397
398 /// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
399 /// immediate in bits 0-7.
400 void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum,
401 raw_ostream &O) {
402 const MachineOperand &MO = MI->getOperand(OpNum);
403 assert(MO.isImm() && "Not a valid so_imm value!");
404 printSOImm(O, MO.getImm(), isVerbose(), MAI);
405 }
406
407 /// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov'
408 /// followed by an 'orr' to materialize.
409 void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum,
410 raw_ostream &O) {
411 const MachineOperand &MO = MI->getOperand(OpNum);
412 assert(MO.isImm() && "Not a valid so_imm value!");
413 unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO.getImm());
414 unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO.getImm());
415 printSOImm(O, V1, isVerbose(), MAI);
416 O << "\n\torr";
417 printPredicateOperand(MI, 2, O);
418 O << "\t";
419 printOperand(MI, 0, O);
420 O << ", ";
421 printOperand(MI, 0, O);
422 O << ", ";
423 printSOImm(O, V2, isVerbose(), MAI);
424 }
425
426 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
427 // "Addressing Mode 1 - Data-processing operands" forms. This includes:
428 // REG 0 0 - e.g. R5
429 // REG REG 0,SH_OPC - e.g. R5, ROR R3
430 // REG 0 IMM,SH_OPC - e.g. R5, LSL #3
431 void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op,
432 raw_ostream &O) {
433 const MachineOperand &MO1 = MI->getOperand(Op);
434 const MachineOperand &MO2 = MI->getOperand(Op+1);
435 const MachineOperand &MO3 = MI->getOperand(Op+2);
436
437 O << getRegisterName(MO1.getReg());
438
439 // Print the shift opc.
440 O << ", "
441 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()))
442 << " ";
443
444 if (MO2.getReg()) {
445 O << getRegisterName(MO2.getReg());
446 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
447 } else {
448 O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
449 }
450 }
451
452 void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op,
453 raw_ostream &O) {
454 const MachineOperand &MO1 = MI->getOperand(Op);
455 const MachineOperand &MO2 = MI->getOperand(Op+1);
456 const MachineOperand &MO3 = MI->getOperand(Op+2);
457
458 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
459 printOperand(MI, Op, O);
460 return;
461 }
462
463 O << "[" << getRegisterName(MO1.getReg());
464
465 if (!MO2.getReg()) {
466 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
467 O << ", #"
468 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
469 << ARM_AM::getAM2Offset(MO3.getImm());
470 O << "]";
471 return;
472 }
473
474 O << ", "
475 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
476 << getRegisterName(MO2.getReg());
477
478 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
479 O << ", "
480 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
481 << " #" << ShImm;
482 O << "]";
483 }
484
485 void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op,
486 raw_ostream &O) {
487 const MachineOperand &MO1 = MI->getOperand(Op);
488 const MachineOperand &MO2 = MI->getOperand(Op+1);
489
490 if (!MO1.getReg()) {
491 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
492 O << "#"
493 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
494 << ImmOffs;
495 return;
496 }
497
498 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
499 << getRegisterName(MO1.getReg());
500
501 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
502 O << ", "
503 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
504 << " #" << ShImm;
505 }
506
507 void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op,
508 raw_ostream &O) {
509 const MachineOperand &MO1 = MI->getOperand(Op);
510 const MachineOperand &MO2 = MI->getOperand(Op+1);
511 const MachineOperand &MO3 = MI->getOperand(Op+2);
512
513 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
514 O << "[" << getRegisterName(MO1.getReg());
515
516 if (MO2.getReg()) {
517 O << ", "
518 << (char)ARM_AM::getAM3Op(MO3.getImm())
519 << getRegisterName(MO2.getReg())
520 << "]";
521 return;
522 }
523
524 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
525 O << ", #"
526 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
527 << ImmOffs;
528 O << "]";
529 }
530
531 void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op,
532 raw_ostream &O){
533 const MachineOperand &MO1 = MI->getOperand(Op);
534 const MachineOperand &MO2 = MI->getOperand(Op+1);
535
536 if (MO1.getReg()) {
537 O << (char)ARM_AM::getAM3Op(MO2.getImm())
538 << getRegisterName(MO1.getReg());
539 return;
540 }
541
542 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
543 O << "#"
544 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
545 << ImmOffs;
546 }
547
548 void ARMAsmPrinter::printAddrMode4Operand(const MachineInstr *MI, int Op,
549 raw_ostream &O,
550 const char *Modifier) {
551 const MachineOperand &MO2 = MI->getOperand(Op+1);
552 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
553 if (Modifier && strcmp(Modifier, "submode") == 0) {
554 O << ARM_AM::getAMSubModeStr(Mode);
555 } else if (Modifier && strcmp(Modifier, "wide") == 0) {
556 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
557 if (Mode == ARM_AM::ia)
558 O << ".w";
559 } else {
560 printOperand(MI, Op, O);
561 }
562 }
563
564 void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op,
565 raw_ostream &O,
566 const char *Modifier) {
567 const MachineOperand &MO1 = MI->getOperand(Op);
568 const MachineOperand &MO2 = MI->getOperand(Op+1);
569
570 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
571 printOperand(MI, Op, O);
572 return;
573 }
574
575 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
576
577 if (Modifier && strcmp(Modifier, "submode") == 0) {
578 ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm());
579 O << ARM_AM::getAMSubModeStr(Mode);
580 return;
581 } else if (Modifier && strcmp(Modifier, "base") == 0) {
582 // Used for FSTM{D|S} and LSTM{D|S} operations.
583 O << getRegisterName(MO1.getReg());
584 return;
585 }
586
587 O << "[" << getRegisterName(MO1.getReg());
588
589 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
590 O << ", #"
591 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
592 << ImmOffs*4;
593 }
594 O << "]";
595 }
596
597 void ARMAsmPrinter::printAddrMode6Operand(const MachineInstr *MI, int Op,
598 raw_ostream &O) {
599 const MachineOperand &MO1 = MI->getOperand(Op);
600 const MachineOperand &MO2 = MI->getOperand(Op+1);
601
602 O << "[" << getRegisterName(MO1.getReg());
603 if (MO2.getImm()) {
604 // FIXME: Both darwin as and GNU as violate ARM docs here.
605 O << ", :" << (MO2.getImm() << 3);
606 }
607 O << "]";
608 }
609
610 void ARMAsmPrinter::printAddrMode6OffsetOperand(const MachineInstr *MI, int Op,
611 raw_ostream &O){
612 const MachineOperand &MO = MI->getOperand(Op);
613 if (MO.getReg() == 0)
614 O << "!";
615 else
616 O << ", " << getRegisterName(MO.getReg());
617 }
618
619 void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op,
620 raw_ostream &O,
621 const char *Modifier) {
622 if (Modifier && strcmp(Modifier, "label") == 0) {
623 printPCLabel(MI, Op+1, O);
624 return;
625 }
626
627 const MachineOperand &MO1 = MI->getOperand(Op);
628 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
629 O << "[pc, " << getRegisterName(MO1.getReg()) << "]";
630 }
631
632 void
633 ARMAsmPrinter::printBitfieldInvMaskImmOperand(const MachineInstr *MI, int Op,
634 raw_ostream &O) {
635 const MachineOperand &MO = MI->getOperand(Op);
636 uint32_t v = ~MO.getImm();
637 int32_t lsb = CountTrailingZeros_32(v);
638 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
639 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
640 O << "#" << lsb << ", #" << width;
641 }
642
643 //===--------------------------------------------------------------------===//
644
645 void ARMAsmPrinter::printThumbS4ImmOperand(const MachineInstr *MI, int Op,
646 raw_ostream &O) {
647 O << "#" << MI->getOperand(Op).getImm() * 4;
648 }
649
650 void
651 ARMAsmPrinter::printThumbITMask(const MachineInstr *MI, int Op,
652 raw_ostream &O) {
653 // (3 - the number of trailing zeros) is the number of then / else.
654 unsigned Mask = MI->getOperand(Op).getImm();
655 unsigned CondBit0 = Mask >> 4 & 1;
656 unsigned NumTZ = CountTrailingZeros_32(Mask);
657 assert(NumTZ <= 3 && "Invalid IT mask!");
658 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
659 bool T = ((Mask >> Pos) & 1) == CondBit0;
660 if (T)
661 O << 't';
662 else
663 O << 'e';
664 }
665 }
666
667 void
668 ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op,
669 raw_ostream &O) {
670 const MachineOperand &MO1 = MI->getOperand(Op);
671 const MachineOperand &MO2 = MI->getOperand(Op+1);
672 O << "[" << getRegisterName(MO1.getReg());
673 O << ", " << getRegisterName(MO2.getReg()) << "]";
674 }
675
676 void
677 ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op,
678 raw_ostream &O,
679 unsigned Scale) {
680 const MachineOperand &MO1 = MI->getOperand(Op);
681 const MachineOperand &MO2 = MI->getOperand(Op+1);
682 const MachineOperand &MO3 = MI->getOperand(Op+2);
683
684 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
685 printOperand(MI, Op, O);
686 return;
687 }
688
689 O << "[" << getRegisterName(MO1.getReg());
690 if (MO3.getReg())
691 O << ", " << getRegisterName(MO3.getReg());
692 else if (unsigned ImmOffs = MO2.getImm())
693 O << ", #" << ImmOffs * Scale;
694 O << "]";
695 }
696
697 void
698 ARMAsmPrinter::printThumbAddrModeS1Operand(const MachineInstr *MI, int Op,
699 raw_ostream &O) {
700 printThumbAddrModeRI5Operand(MI, Op, O, 1);
701 }
702 void
703 ARMAsmPrinter::printThumbAddrModeS2Operand(const MachineInstr *MI, int Op,
704 raw_ostream &O) {
705 printThumbAddrModeRI5Operand(MI, Op, O, 2);
706 }
707 void
708 ARMAsmPrinter::printThumbAddrModeS4Operand(const MachineInstr *MI, int Op,
709 raw_ostream &O) {
710 printThumbAddrModeRI5Operand(MI, Op, O, 4);
711 }
712
713 void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op,
714 raw_ostream &O) {
715 const MachineOperand &MO1 = MI->getOperand(Op);
716 const MachineOperand &MO2 = MI->getOperand(Op+1);
717 O << "[" << getRegisterName(MO1.getReg());
718 if (unsigned ImmOffs = MO2.getImm())
719 O << ", #" << ImmOffs*4;
720 O << "]";
721 }
722
723 //===--------------------------------------------------------------------===//
724
725 // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
726 // register with shift forms.
727 // REG 0 0 - e.g. R5
728 // REG IMM, SH_OPC - e.g. R5, LSL #3
729 void ARMAsmPrinter::printT2SOOperand(const MachineInstr *MI, int OpNum,
730 raw_ostream &O) {
731 const MachineOperand &MO1 = MI->getOperand(OpNum);
732 const MachineOperand &MO2 = MI->getOperand(OpNum+1);
733
734 unsigned Reg = MO1.getReg();
735 assert(TargetRegisterInfo::isPhysicalRegister(Reg));
736 O << getRegisterName(Reg);
737
738 // Print the shift opc.
739 O << ", "
740 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()))
741 << " ";
742
743 assert(MO2.isImm() && "Not a valid t2_so_reg value!");
744 O << "#" << ARM_AM::getSORegOffset(MO2.getImm());
745 }
746
747 void ARMAsmPrinter::printT2AddrModeImm12Operand(const MachineInstr *MI,
748 int OpNum,
749 raw_ostream &O) {
750 const MachineOperand &MO1 = MI->getOperand(OpNum);
751 const MachineOperand &MO2 = MI->getOperand(OpNum+1);
752
753 O << "[" << getRegisterName(MO1.getReg());
754
755 unsigned OffImm = MO2.getImm();
756 if (OffImm) // Don't print +0.
757 O << ", #" << OffImm;
758 O << "]";
759 }
760
761 void ARMAsmPrinter::printT2AddrModeImm8Operand(const MachineInstr *MI,
762 int OpNum,
763 raw_ostream &O) {
764 const MachineOperand &MO1 = MI->getOperand(OpNum);
765 const MachineOperand &MO2 = MI->getOperand(OpNum+1);
766
767 O << "[" << getRegisterName(MO1.getReg());
768
769 int32_t OffImm = (int32_t)MO2.getImm();
770 // Don't print +0.
771 if (OffImm < 0)
772 O << ", #-" << -OffImm;
773 else if (OffImm > 0)
774 O << ", #" << OffImm;
775 O << "]";
776 }
777
778 void ARMAsmPrinter::printT2AddrModeImm8s4Operand(const MachineInstr *MI,
779 int OpNum,
780 raw_ostream &O) {
781 const MachineOperand &MO1 = MI->getOperand(OpNum);
782 const MachineOperand &MO2 = MI->getOperand(OpNum+1);
783
784 O << "[" << getRegisterName(MO1.getReg());
785
786 int32_t OffImm = (int32_t)MO2.getImm() / 4;
787 // Don't print +0.
788 if (OffImm < 0)
789 O << ", #-" << -OffImm * 4;
790 else if (OffImm > 0)
791 O << ", #" << OffImm * 4;
792 O << "]";
793 }
794
795 void ARMAsmPrinter::printT2AddrModeImm8OffsetOperand(const MachineInstr *MI,
796 int OpNum,
797 raw_ostream &O) {
798 const MachineOperand &MO1 = MI->getOperand(OpNum);
799 int32_t OffImm = (int32_t)MO1.getImm();
800 // Don't print +0.
801 if (OffImm < 0)
802 O << "#-" << -OffImm;
803 else if (OffImm > 0)
804 O << "#" << OffImm;
805 }
806
807 void ARMAsmPrinter::printT2AddrModeSoRegOperand(const MachineInstr *MI,
808 int OpNum,
809 raw_ostream &O) {
810 const MachineOperand &MO1 = MI->getOperand(OpNum);
811 const MachineOperand &MO2 = MI->getOperand(OpNum+1);
812 const MachineOperand &MO3 = MI->getOperand(OpNum+2);
813
814 O << "[" << getRegisterName(MO1.getReg());
815
816 assert(MO2.getReg() && "Invalid so_reg load / store address!");
817 O << ", " << getRegisterName(MO2.getReg());
818
819 unsigned ShAmt = MO3.getImm();
820 if (ShAmt) {
821 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
822 O << ", lsl #" << ShAmt;
823 }
824 O << "]";
825 }
826
827
828 //===--------------------------------------------------------------------===//
829
830 void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int OpNum,
831 raw_ostream &O) {
832 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
833 if (CC != ARMCC::AL)
834 O << ARMCondCodeToString(CC);
835 }
836
837 void ARMAsmPrinter::printMandatoryPredicateOperand(const MachineInstr *MI,
838 int OpNum,
839 raw_ostream &O) {
840 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
841 O << ARMCondCodeToString(CC);
842 }
843
844 void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int OpNum,
845 raw_ostream &O){
846 unsigned Reg = MI->getOperand(OpNum).getReg();
847 if (Reg) {
848 assert(Reg == ARM::CPSR && "Expect ARM CPSR register!");
849 O << 's';
850 }
851 }
852
853 void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int OpNum,
854 raw_ostream &O) {
855 int Id = (int)MI->getOperand(OpNum).getImm();
856 O << MAI->getPrivateGlobalPrefix()
857 << "PC" << getFunctionNumber() << "_" << Id;
858 }
859
860 void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int OpNum,
861 raw_ostream &O) {
862 O << "{";
863 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
864 if (MI->getOperand(i).isImplicit())
865 continue;
866 if ((int)i != OpNum) O << ", ";
867 printOperand(MI, i, O);
868 }
869 O << "}";
870 }
871
872 void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNum,
873 raw_ostream &O, const char *Modifier) {
874 assert(Modifier && "This operand only works with a modifier!");
875 // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the
876 // data itself.
877 if (!strcmp(Modifier, "label")) {
878 unsigned ID = MI->getOperand(OpNum).getImm();
879 OutStreamer.EmitLabel(GetCPISymbol(ID));
880 } else {
881 assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
882 unsigned CPI = MI->getOperand(OpNum).getIndex();
883
884 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPI];
885
886 if (MCPE.isMachineConstantPoolEntry()) {
887 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
888 } else {
889 EmitGlobalConstant(MCPE.Val.ConstVal);
890 }
891 }
892 }
893
894 MCSymbol *ARMAsmPrinter::
895 GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
896 const MachineBasicBlock *MBB) const {
897 SmallString<60> Name;
898 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
899 << getFunctionNumber() << '_' << uid << '_' << uid2
900 << "_set_" << MBB->getNumber();
901 return OutContext.GetOrCreateSymbol(Name.str());
902 }
903
904 MCSymbol *ARMAsmPrinter::
905 GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const {
906 SmallString<60> Name;
907 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI"
908 << getFunctionNumber() << '_' << uid << '_' << uid2;
909 return OutContext.GetOrCreateSymbol(Name.str());
910 }
911
912 void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum,
913 raw_ostream &O) {
914 assert(!Subtarget->isThumb2() && "Thumb2 should use double-jump jumptables!");
915
916 const MachineOperand &MO1 = MI->getOperand(OpNum);
917 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
918
919 unsigned JTI = MO1.getIndex();
920 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
921 // Can't use EmitLabel until instprinter happens, label comes out in the wrong
922 // order.
923 O << *JTISymbol << ":\n";
924
925 const char *JTEntryDirective = MAI->getData32bitsDirective();
926
927 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
928 const std::vector &JT = MJTI->getJumpTables();
929 const std::vector &JTBBs = JT[JTI].MBBs;
930 bool UseSet= MAI->hasSetDirective() && TM.getRelocationModel() == Reloc::PIC_;
931 SmallPtrSet JTSets;
932 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
933 MachineBasicBlock *MBB = JTBBs[i];
934 bool isNew = JTSets.insert(MBB);
935
936 if (UseSet && isNew) {
937 O << "\t.set\t"
938 << *GetARMSetPICJumpTableLabel2(JTI, MO2.getImm(), MBB) << ','
939 << *MBB->getSymbol() << '-' << *JTISymbol << '\n';
940 }
941
942 O << JTEntryDirective << ' ';
943 if (UseSet)
944 O << *GetARMSetPICJumpTableLabel2(JTI, MO2.getImm(), MBB);
945 else if (TM.getRelocationModel() == Reloc::PIC_)
946 O << *MBB->getSymbol() << '-' << *JTISymbol;
947 else
948 O << *MBB->getSymbol();
949
950 if (i != e-1)
951 O << '\n';
952 }
953 }
954
955 void ARMAsmPrinter::printJT2BlockOperand(const MachineInstr *MI, int OpNum,
956 raw_ostream &O) {
957 const MachineOperand &MO1 = MI->getOperand(OpNum);
958 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
959 unsigned JTI = MO1.getIndex();
960
961 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
962
963 // Can't use EmitLabel until instprinter happens, label comes out in the wrong
964 // order.
965 O << *JTISymbol << ":\n";
966
967 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
968 const std::vector &JT = MJTI->getJumpTables();
969 const std::vector &JTBBs = JT[JTI].MBBs;
970 bool ByteOffset = false, HalfWordOffset = false;
971 if (MI->getOpcode() == ARM::t2TBB)
972 ByteOffset = true;
973 else if (MI->getOpcode() == ARM::t2TBH)
974 HalfWordOffset = true;
975
976 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
977 MachineBasicBlock *MBB = JTBBs[i];
978 if (ByteOffset)
979 O << MAI->getData8bitsDirective();
980 else if (HalfWordOffset)
981 O << MAI->getData16bitsDirective();
982
983 if (ByteOffset || HalfWordOffset)
984 O << '(' << *MBB->getSymbol() << "-" << *JTISymbol << ")/2";
985 else
986 O << "\tb.w " << *MBB->getSymbol();
987
988 if (i != e-1)
989 O << '\n';
990 }
991 }
992
993 void ARMAsmPrinter::printTBAddrMode(const MachineInstr *MI, int OpNum,
994 raw_ostream &O) {
995 O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg());
996 if (MI->getOpcode() == ARM::t2TBH)
997 O << ", lsl #1";
998 O << ']';
999 }
1000
1001 void ARMAsmPrinter::printNoHashImmediate(const MachineInstr *MI, int OpNum,
1002 raw_ostream &O) {
1003 O << MI->getOperand(OpNum).getImm();
1004 }
1005
1006 void ARMAsmPrinter::printVFPf32ImmOperand(const MachineInstr *MI, int OpNum,
1007 raw_ostream &O) {
1008 const ConstantFP *FP = MI->getOperand(OpNum).getFPImm();
1009 O << '#' << FP->getValueAPF().convertToFloat();
1010 if (isVerbose()) {
1011 O << "\t\t" << MAI->getCommentString() << ' ';
1012 WriteAsOperand(O, FP, /*PrintType=*/false);
1013 }
1014 }
1015
1016 void ARMAsmPrinter::printVFPf64ImmOperand(const MachineInstr *MI, int OpNum,
1017 raw_ostream &O) {
1018 const ConstantFP *FP = MI->getOperand(OpNum).getFPImm();
1019 O << '#' << FP->getValueAPF().convertToDouble();
1020 if (isVerbose()) {
1021 O << "\t\t" << MAI->getCommentString() << ' ';
1022 WriteAsOperand(O, FP, /*PrintType=*/false);
1023 }
1024 }
1025
1026 void ARMAsmPrinter::printNEONModImmOperand(const MachineInstr *MI, int OpNum,
1027 raw_ostream &O) {
1028 unsigned EncodedImm = MI->getOperand(OpNum).getImm();
1029 unsigned EltBits;
1030 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
1031 O << "#0x" << utohexstr(Val);
1032 }
1033
1034 bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
1035 unsigned AsmVariant, const char *ExtraCode,
1036 raw_ostream &O) {
1037 // Does this asm operand have a single letter operand modifier?
1038 if (ExtraCode && ExtraCode[0]) {
1039 if (ExtraCode[1] != 0) return true; // Unknown modifier.
1040
1041 switch (ExtraCode[0]) {
1042 default: return true; // Unknown modifier.
1043 case 'a': // Print as a memory address.
1044 if (MI->getOperand(OpNum).isReg()) {
1045 O << "[" << getRegisterName(MI->getOperand(OpNum).getReg()) << "]";
1046 return false;
1047 }
1048 // Fallthrough
1049 case 'c': // Don't print "#" before an immediate operand.
1050 if (!MI->getOperand(OpNum).isImm())
1051 return true;
1052 printNoHashImmediate(MI, OpNum, O);
1053 return false;
1054 case 'P': // Print a VFP double precision register.
1055 case 'q': // Print a NEON quad precision register.
1056 printOperand(MI, OpNum, O);
1057 return false;
1058 case 'Q':
1059 case 'R':
1060 case 'H':
1061 report_fatal_error("llvm does not support 'Q', 'R', and 'H' modifiers!");
1062 return true;
1063 }
1064 }
1065
1066 printOperand(MI, OpNum, O);
1067 return false;
1068 }
1069
1070 bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
1071 unsigned OpNum, unsigned AsmVariant,
1072 const char *ExtraCode,
1073 raw_ostream &O) {
1074 if (ExtraCode && ExtraCode[0])
1075 return true; // Unknown modifier.
1076
1077 const MachineOperand &MO = MI->getOperand(OpNum);
1078 assert(MO.isReg() && "unexpected inline asm memory operand");
1079 O << "[" << getRegisterName(MO.getReg()) << "]";
1080 return false;
1081 }
1082
1083 void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
1084 if (EnableMCInst) {
1085 printInstructionThroughMCStreamer(MI);
1086 return;
1087 }
1088
1089 if (MI->getOpcode() == ARM::CONSTPOOL_ENTRY)
1090 EmitAlignment(2);
1091
1092 SmallString<128> Str;
1093 raw_svector_ostream OS(Str);
1094 if (MI->getOpcode() == ARM::DBG_VALUE) {
1095 unsigned NOps = MI->getNumOperands();
1096 assert(NOps==4);
1097 OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
1098 // cast away const; DIetc do not take const operands for some reason.
1099 DIVariable V(const_cast(MI->getOperand(NOps-1).getMetadata()));
1100 OS << V.getName();
1101 OS << " <- ";
1102 // Frame address. Currently handles register +- offset only.
1103 assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm());
1104 OS << '['; printOperand(MI, 0, OS); OS << '+'; printOperand(MI, 1, OS);
1105 OS << ']';
1106 OS << "+";
1107 printOperand(MI, NOps-2, OS);
1108 OutStreamer.EmitRawText(OS.str());
1109 return;
1110 }
1111
1112 printInstruction(MI, OS);
1113 OutStreamer.EmitRawText(OS.str());
1114
1115 // Make sure the instruction that follows TBB is 2-byte aligned.
1116 // FIXME: Constant island pass should insert an "ALIGN" instruction instead.
1117 if (MI->getOpcode() == ARM::t2TBB)
1118 EmitAlignment(1);
1119 }
1120
1121 void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) {
1122 if (Subtarget->isTargetDarwin()) {
1123 Reloc::Model RelocM = TM.getRelocationModel();
1124 if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) {
1125 // Declare all the text sections up front (before the DWARF sections
1126 // emitted by AsmPrinter::doInitialization) so the assembler will keep
1127 // them together at the beginning of the object file. This helps
1128 // avoid out-of-range branches that are due a fundamental limitation of
1129 // the way symbol offsets are encoded with the current Darwin ARM
1130 // relocations.
1131 const TargetLoweringObjectFileMachO &TLOFMacho =
1132 static_cast(
1133 getObjFileLowering());
1134 OutStreamer.SwitchSection(TLOFMacho.getTextSection());
1135 OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection());
1136 OutStreamer.SwitchSection(TLOFMacho.getConstTextCoalSection());
1137 if (RelocM == Reloc::DynamicNoPIC) {
1138 const MCSection *sect =
1139 OutContext.getMachOSection("__TEXT", "__symbol_stub4",
1140 MCSectionMachO::S_SYMBOL_STUBS,
1141 12, SectionKind::getText());
1142 OutStreamer.SwitchSection(sect);
1143 } else {
1144 const MCSection *sect =
1145 OutContext.getMachOSection("__TEXT", "__picsymbolstub4",
1146 MCSectionMachO::S_SYMBOL_STUBS,
1147 16, SectionKind::getText());
1148 OutStreamer.SwitchSection(sect);
1149 }
1150 }
1151 }
1152
1153 // Use unified assembler syntax.
1154 OutStreamer.EmitRawText(StringRef("\t.syntax unified"));
1155
1156 // Emit ARM Build Attributes
1157 if (Subtarget->isTargetELF()) {
1158 // CPU Type
1159 std::string CPUString = Subtarget->getCPUString();
1160 if (CPUString != "generic")
1161 OutStreamer.EmitRawText("\t.cpu " + Twine(CPUString));
1162
1163 // FIXME: Emit FPU type
1164 if (Subtarget->hasVFP2())
1165 OutStreamer.EmitRawText("\t.eabi_attribute " +
1166 Twine(ARMBuildAttrs::VFP_arch) + ", 2");
1167
1168 // Signal various FP modes.
1169 if (!UnsafeFPMath) {
1170 OutStreamer.EmitRawText("\t.eabi_attribute " +
1171 Twine(ARMBuildAttrs::ABI_FP_denormal) + ", 1");
1172 OutStreamer.EmitRawText("\t.eabi_attribute " +
1173 Twine(ARMBuildAttrs::ABI_FP_exceptions) + ", 1");
1174 }
1175
1176 if (NoInfsFPMath && NoNaNsFPMath)
1177 OutStreamer.EmitRawText("\t.eabi_attribute " +
1178 Twine(ARMBuildAttrs::ABI_FP_number_model)+ ", 1");
1179 else
1180 OutStreamer.EmitRawText("\t.eabi_attribute " +
1181 Twine(ARMBuildAttrs::ABI_FP_number_model)+ ", 3");
1182
1183 // 8-bytes alignment stuff.
1184 OutStreamer.EmitRawText("\t.eabi_attribute " +
1185 Twine(ARMBuildAttrs::ABI_align8_needed) + ", 1");
1186 OutStreamer.EmitRawText("\t.eabi_attribute " +
1187 Twine(ARMBuildAttrs::ABI_align8_preserved) + ", 1");
1188
1189 // Hard float. Use both S and D registers and conform to AAPCS-VFP.
1190 if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) {
1191 OutStreamer.EmitRawText("\t.eabi_attribute " +
1192 Twine(ARMBuildAttrs::ABI_HardFP_use) + ", 3");
1193 OutStreamer.EmitRawText("\t.eabi_attribute " +
1194 Twine(ARMBuildAttrs::ABI_VFP_args) + ", 1");
1195 }
1196 // FIXME: Should we signal R9 usage?
1197 }
1198 }
1199
1200
1201 void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
1202 if (Subtarget->isTargetDarwin()) {
1203 // All darwin targets use mach-o.
1204 const TargetLoweringObjectFileMachO &TLOFMacho =
1205 static_cast(getObjFileLowering());
1206 MachineModuleInfoMachO &MMIMacho =
1207 MMI->getObjFileInfo();
1208
1209 // Output non-lazy-pointers for external and common global variables.
1210 MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList();
1211
1212 if (!Stubs.empty()) {
1213 // Switch with ".non_lazy_symbol_pointer" directive.
1214 OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
1215 EmitAlignment(2);
1216 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
1217 // L_foo$stub:
1218 OutStreamer.EmitLabel(Stubs[i].first);
1219 // .indirect_symbol _foo
1220 MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second;
1221 OutStreamer.EmitSymbolAttribute(MCSym.getPointer(),MCSA_IndirectSymbol);
1222
1223 if (MCSym.getInt())
1224 // External to current translation unit.
1225 OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
1226 else
1227 // Internal to current translation unit.
1228 //
1229 // When we place the LSDA into the TEXT section, the type info pointers
1230 // need to be indirect and pc-rel. We accomplish this by using NLPs.
1231 // However, sometimes the types are local to the file. So we need to
1232 // fill in the value for the NLP in those cases.
1233 OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(),
1234 OutContext),
1235 4/*size*/, 0/*addrspace*/);
1236 }
1237
1238 Stubs.clear();
1239 OutStreamer.AddBlankLine();
1240 }
1241
1242 Stubs = MMIMacho.GetHiddenGVStubList();
1243 if (!Stubs.empty()) {
1244 OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
1245 EmitAlignment(2);
1246 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
1247 // L_foo$stub:
1248 OutStreamer.EmitLabel(Stubs[i].first);
1249 // .long _foo
1250 OutStreamer.EmitValue(MCSymbolRefExpr::
1251 Create(Stubs[i].second.getPointer(),
1252 OutContext),
1253 4/*size*/, 0/*addrspace*/);
1254 }
1255
1256 Stubs.clear();
1257 OutStreamer.AddBlankLine();
1258 }
1259
1260 // Funny Darwin hack: This flag tells the linker that no global symbols
1261 // contain code that falls through to other global symbols (e.g. the obvious
1262 // implementation of multiple entry points). If this doesn't occur, the
1263 // linker can safely perform dead code stripping. Since LLVM never
1264 // generates code that does this, it is always safe to set.
1265 OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
1266 }
1267 }
1268
1269 //===----------------------------------------------------------------------===//
1270
1271 void ARMAsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) {
1272 ARMMCInstLower MCInstLowering(OutContext, *Mang, *this);
1273 switch (MI->getOpcode()) {
1274 case ARM::t2MOVi32imm:
1275 assert(0 && "Should be lowered by thumb2it pass");
1276 default: break;
1277 case ARM::PICADD: { // FIXME: Remove asm string from td file.
1278 // This is a pseudo op for a label + instruction sequence, which looks like:
1279 // LPC0:
1280 // add r0, pc, r0
1281 // This adds the address of LPC0 to r0.
1282
1283 // Emit the label.
1284 // FIXME: MOVE TO SHARED PLACE.
1285 unsigned Id = (unsigned)MI->getOperand(2).getImm();
1286 const char *Prefix = MAI->getPrivateGlobalPrefix();
1287 MCSymbol *Label =OutContext.GetOrCreateSymbol(Twine(Prefix)
1288 + "PC" + Twine(getFunctionNumber()) + "_" + Twine(Id));
1289 OutStreamer.EmitLabel(Label);
1290
1291
1292 // Form and emit tha dd.
1293 MCInst AddInst;
1294 AddInst.setOpcode(ARM::ADDrr);
1295 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
1296 AddInst.addOperand(MCOperand::CreateReg(ARM::PC));
1297 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
1298 OutStreamer.EmitInstruction(AddInst);
1299 return;
1300 }
1301 case ARM::CONSTPOOL_ENTRY: { // FIXME: Remove asm string from td file.
1302 /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool
1303 /// in the function. The first operand is the ID# for this instruction, the
1304 /// second is the index into the MachineConstantPool that this is, the third
1305 /// is the size in bytes of this constant pool entry.
1306 unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
1307 unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
1308
1309 EmitAlignment(2);
1310 OutStreamer.EmitLabel(GetCPISymbol(LabelId));
1311
1312 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
1313 if (MCPE.isMachineConstantPoolEntry())
1314 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
1315 else
1316 EmitGlobalConstant(MCPE.Val.ConstVal);
1317
1318 return;
1319 }
1320 case ARM::MOVi2pieces: { // FIXME: Remove asmstring from td file.
1321 // This is a hack that lowers as a two instruction sequence.
1322 unsigned DstReg = MI->getOperand(0).getReg();
1323 unsigned ImmVal = (unsigned)MI->getOperand(1).getImm();
1324
1325 unsigned SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(ImmVal);
1326 unsigned SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(ImmVal);
1327
1328 {
1329 MCInst TmpInst;
1330 TmpInst.setOpcode(ARM::MOVi);
1331 TmpInst.addOperand(MCOperand::CreateReg(DstReg));
1332 TmpInst.addOperand(MCOperand::CreateImm(SOImmValV1));
1333
1334 // Predicate.
1335 TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
1336 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg()));
1337
1338 TmpInst.addOperand(MCOperand::CreateReg(0)); // cc_out
1339 OutStreamer.EmitInstruction(TmpInst);
1340 }
1341
1342 {
1343 MCInst TmpInst;
1344 TmpInst.setOpcode(ARM::ORRri);
1345 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // dstreg
1346 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // inreg
1347 TmpInst.addOperand(MCOperand::CreateImm(SOImmValV2)); // so_imm
1348 // Predicate.
1349 TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
1350 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg()));
1351
1352 TmpInst.addOperand(MCOperand::CreateReg(0)); // cc_out
1353 OutStreamer.EmitInstruction(TmpInst);
1354 }
1355 return;
1356 }
1357 case ARM::MOVi32imm: { // FIXME: Remove asmstring from td file.
1358 // This is a hack that lowers as a two instruction sequence.
1359 unsigned DstReg = MI->getOperand(0).getReg();
1360 const MachineOperand &MO = MI->getOperand(1);
1361 MCOperand V1, V2;
1362 if (MO.isImm()) {
1363 unsigned ImmVal = (unsigned)MI->getOperand(1).getImm();
1364 V1 = MCOperand::CreateImm(ImmVal & 65535);
1365 V2 = MCOperand::CreateImm(ImmVal >> 16);
1366 } else if (MO.isGlobal()) {
1367 MCSymbol *Symbol = MCInstLowering.GetGlobalAddressSymbol(MO);
1368 const MCSymbolRefExpr *SymRef1 =
1369 MCSymbolRefExpr::Create(Symbol,
1370 MCSymbolRefExpr::VK_ARM_LO16, OutContext);
1371 const MCSymbolRefExpr *SymRef2 =
1372 MCSymbolRefExpr::Create(Symbol,
1373 MCSymbolRefExpr::VK_ARM_HI16, OutContext);
1374 V1 = MCOperand::CreateExpr(SymRef1);
1375 V2 = MCOperand::CreateExpr(SymRef2);
1376 } else {
1377 MI->dump();
1378 llvm_unreachable("cannot handle this operand");
1379 }
1380
1381 {
1382 MCInst TmpInst;
1383 TmpInst.setOpcode(ARM::MOVi16);
1384 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // dstreg
1385 TmpInst.addOperand(V1); // lower16(imm)
1386
1387 // Predicate.
1388 TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
1389 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg()));
1390
1391 OutStreamer.EmitInstruction(TmpInst);
1392 }
1393
1394 {
1395 MCInst TmpInst;
1396 TmpInst.setOpcode(ARM::MOVTi16);
1397 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // dstreg
1398 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // srcreg
1399 TmpInst.addOperand(V2); // upper16(imm)
1400
1401 // Predicate.
1402 TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
1403 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg()));
1404
1405 OutStreamer.EmitInstruction(TmpInst);
1406 }
1407
1408 return;
1409 }
1410 }
1411
1412 MCInst TmpInst;
1413 MCInstLowering.Lower(MI, TmpInst);
1414 OutStreamer.EmitInstruction(TmpInst);
1415 }
1416
1417 //===----------------------------------------------------------------------===//
1418 // Target Registry Stuff
1419 //===----------------------------------------------------------------------===//
1420
1421 static MCInstPrinter *createARMMCInstPrinter(const Target &T,
1422 unsigned SyntaxVariant,
1423 const MCAsmInfo &MAI) {
1424 if (SyntaxVariant == 0)
1425 return new ARMInstPrinter(MAI, false);
1426 return 0;
1427 }
1428
1429 // Force static initialization.
1430 extern "C" void LLVMInitializeARMAsmPrinter() {
1431 RegisterAsmPrinter X(TheARMTarget);
1432 RegisterAsmPrinter Y(TheThumbTarget);
1433
1434 TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter);
1435 TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter);
1436 }
1437
0 //===-- ARMMCInstLower.cpp - Convert ARM MachineInstr to an MCInst --------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains code to lower ARM MachineInstrs to their corresponding
10 // MCInst records.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "ARMMCInstLower.h"
15 //#include "llvm/CodeGen/MachineModuleInfoImpls.h"
16 #include "llvm/CodeGen/AsmPrinter.h"
17 #include "llvm/CodeGen/MachineBasicBlock.h"
18 #include "llvm/MC/MCAsmInfo.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCExpr.h"
21 #include "llvm/MC/MCInst.h"
22 //#include "llvm/MC/MCStreamer.h"
23 #include "llvm/Target/Mangler.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include "llvm/ADT/SmallString.h"
26 using namespace llvm;
27
28
29 #if 0
30 const ARMSubtarget &ARMMCInstLower::getSubtarget() const {
31 return AsmPrinter.getSubtarget();
32 }
33
34 MachineModuleInfoMachO &ARMMCInstLower::getMachOMMI() const {
35 assert(getSubtarget().isTargetDarwin() &&"Can only get MachO info on darwin");
36 return AsmPrinter.MMI->getObjFileInfo();
37 }
38 #endif
39
40 MCSymbol *ARMMCInstLower::
41 GetGlobalAddressSymbol(const MachineOperand &MO) const {
42 // FIXME: HANDLE PLT references how??
43 switch (MO.getTargetFlags()) {
44 default: assert(0 && "Unknown target flag on GV operand");
45 case 0: break;
46 }
47
48 return Printer.Mang->getSymbol(MO.getGlobal());
49 }
50
51 MCSymbol *ARMMCInstLower::
52 GetExternalSymbolSymbol(const MachineOperand &MO) const {
53 // FIXME: HANDLE PLT references how??
54 switch (MO.getTargetFlags()) {
55 default: assert(0 && "Unknown target flag on GV operand");
56 case 0: break;
57 }
58
59 return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
60 }
61
62
63
64 MCSymbol *ARMMCInstLower::
65 GetJumpTableSymbol(const MachineOperand &MO) const {
66 SmallString<256> Name;
67 raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "JTI"
68 << Printer.getFunctionNumber() << '_' << MO.getIndex();
69
70 #if 0
71 switch (MO.getTargetFlags()) {
72 default: llvm_unreachable("Unknown target flag on GV operand");
73 }
74 #endif
75
76 // Create a symbol for the name.
77 return Ctx.GetOrCreateSymbol(Name.str());
78 }
79
80 MCSymbol *ARMMCInstLower::
81 GetConstantPoolIndexSymbol(const MachineOperand &MO) const {
82 SmallString<256> Name;
83 raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "CPI"
84 << Printer.getFunctionNumber() << '_' << MO.getIndex();
85
86 #if 0
87 switch (MO.getTargetFlags()) {
88 default: llvm_unreachable("Unknown target flag on GV operand");
89 }
90 #endif
91
92 // Create a symbol for the name.
93 return Ctx.GetOrCreateSymbol(Name.str());
94 }
95
96 MCOperand ARMMCInstLower::
97 LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const {
98 // FIXME: We would like an efficient form for this, so we don't have to do a
99 // lot of extra uniquing.
100 const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx);
101
102 #if 0
103 switch (MO.getTargetFlags()) {
104 default: llvm_unreachable("Unknown target flag on GV operand");
105 }
106 #endif
107
108 if (!MO.isJTI() && MO.getOffset())
109 Expr = MCBinaryExpr::CreateAdd(Expr,
110 MCConstantExpr::Create(MO.getOffset(), Ctx),
111 Ctx);
112 return MCOperand::CreateExpr(Expr);
113 }
114
115
116 void ARMMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
117 OutMI.setOpcode(MI->getOpcode());
118
119 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
120 const MachineOperand &MO = MI->getOperand(i);
121
122 MCOperand MCOp;
123 switch (MO.getType()) {
124 default:
125 MI->dump();
126 assert(0 && "unknown operand type");
127 case MachineOperand::MO_Register:
128 // Ignore all implicit register operands.
129 if (MO.isImplicit()) continue;
130 assert(!MO.getSubReg() && "Subregs should be eliminated!");
131 MCOp = MCOperand::CreateReg(MO.getReg());
132 break;
133 case MachineOperand::MO_Immediate:
134 MCOp = MCOperand::CreateImm(MO.getImm());
135 break;
136 case MachineOperand::MO_MachineBasicBlock:
137 MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
138 MO.getMBB()->getSymbol(), Ctx));
139 break;
140 case MachineOperand::MO_GlobalAddress:
141 MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
142 break;
143 case MachineOperand::MO_ExternalSymbol:
144 MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
145 break;
146 case MachineOperand::MO_JumpTableIndex:
147 MCOp = LowerSymbolOperand(MO, GetJumpTableSymbol(MO));
148 break;
149 case MachineOperand::MO_ConstantPoolIndex:
150 MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO));
151 break;
152 case MachineOperand::MO_BlockAddress:
153 MCOp = LowerSymbolOperand(MO, Printer.GetBlockAddressSymbol(
154 MO.getBlockAddress()));
155 break;
156 }
157
158 OutMI.addOperand(MCOp);
159 }
160
161 }
0 //===-- ARMMCInstLower.h - Lower MachineInstr to MCInst -------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef ARM_MCINSTLOWER_H
10 #define ARM_MCINSTLOWER_H
11
12 #include "llvm/Support/Compiler.h"
13
14 namespace llvm {
15 class AsmPrinter;
16 class MCAsmInfo;
17 class MCContext;
18 class MCInst;
19 class MCOperand;
20 class MCSymbol;
21 class MachineInstr;
22 class MachineModuleInfoMachO;
23 class MachineOperand;
24 class Mangler;
25 //class ARMSubtarget;
26
27 /// ARMMCInstLower - This class is used to lower an MachineInstr into an MCInst.
28 class LLVM_LIBRARY_VISIBILITY ARMMCInstLower {
29 MCContext &Ctx;
30 Mangler &Mang;
31 AsmPrinter &Printer;
32
33 //const ARMSubtarget &getSubtarget() const;
34 public:
35 ARMMCInstLower(MCContext &ctx, Mangler &mang, AsmPrinter &printer)
36 : Ctx(ctx), Mang(mang), Printer(printer) {}
37
38 void Lower(const MachineInstr *MI, MCInst &OutMI) const;
39
40 //MCSymbol *GetPICBaseSymbol() const;
41 MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const;
42 MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const;
43 MCSymbol *GetJumpTableSymbol(const MachineOperand &MO) const;
44 MCSymbol *GetConstantPoolIndexSymbol(const MachineOperand &MO) const;
45 MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const;
46
47 /*
48 private:
49 MachineModuleInfoMachO &getMachOMMI() const;
50 */
51 };
52
53 }
54
55 #endif
+0
-1438
lib/Target/ARM/AsmPrinter/ARMAsmPrinter.cpp less more
None //===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains a printer that converts from our internal representation
10 // of machine-dependent LLVM code to GAS-format ARM assembly language.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "asm-printer"
15 #include "ARM.h"
16 #include "ARMBuildAttrs.h"
17 #include "ARMAddressingModes.h"
18 #include "ARMConstantPoolValue.h"
19 #include "ARMInstPrinter.h"
20 #include "ARMMachineFunctionInfo.h"
21 #include "ARMMCInstLower.h"
22 #include "ARMTargetMachine.h"
23 #include "llvm/Analysis/DebugInfo.h"
24 #include "llvm/Constants.h"
25 #include "llvm/Module.h"
26 #include "llvm/Type.h"
27 #include "llvm/Assembly/Writer.h"
28 #include "llvm/CodeGen/AsmPrinter.h"
29 #include "llvm/CodeGen/MachineModuleInfoImpls.h"
30 #include "llvm/CodeGen/MachineFunctionPass.h"
31 #include "llvm/CodeGen/MachineJumpTableInfo.h"
32 #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h"
33 #include "llvm/MC/MCAsmInfo.h"
34 #include "llvm/MC/MCContext.h"
35 #include "llvm/MC/MCExpr.h"
36 #include "llvm/MC/MCInst.h"
37 #include "llvm/MC/MCSectionMachO.h"
38 #include "llvm/MC/MCStreamer.h"
39 #include "llvm/MC/MCSymbol.h"
40 #include "llvm/Target/Mangler.h"
41 #include "llvm/Target/TargetData.h"
42 #include "llvm/Target/TargetMachine.h"
43 #include "llvm/Target/TargetOptions.h"
44 #include "llvm/Target/TargetRegistry.h"
45 #include "llvm/ADT/SmallPtrSet.h"
46 #include "llvm/ADT/SmallString.h"
47 #include "llvm/ADT/StringExtras.h"
48 #include "llvm/Support/CommandLine.h"
49 #include "llvm/Support/ErrorHandling.h"
50 #include "llvm/Support/raw_ostream.h"
51 #include
52 using namespace llvm;
53
54 static cl::opt
55 EnableMCInst("enable-arm-mcinst-printer", cl::Hidden,
56 cl::desc("enable experimental asmprinter gunk in the arm backend"));
57
58 namespace {
59 class ARMAsmPrinter : public AsmPrinter {
60
61 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
62 /// make the right decision when printing asm code for different targets.
63 const ARMSubtarget *Subtarget;
64
65 /// AFI - Keep a pointer to ARMFunctionInfo for the current
66 /// MachineFunction.
67 ARMFunctionInfo *AFI;
68
69 /// MCP - Keep a pointer to constantpool entries of the current
70 /// MachineFunction.
71 const MachineConstantPool *MCP;
72
73 public:
74 explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer)
75 : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL) {
76 Subtarget = &TM.getSubtarget();
77 }
78
79 virtual const char *getPassName() const {
80 return "ARM Assembly Printer";
81 }
82
83 void printInstructionThroughMCStreamer(const MachineInstr *MI);
84
85
86 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O,
87 const char *Modifier = 0);
88 void printSOImmOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
89 void printSOImm2PartOperand(const MachineInstr *MI, int OpNum,
90 raw_ostream &O);
91 void printSORegOperand(const MachineInstr *MI, int OpNum,
92 raw_ostream &O);
93 void printAddrMode2Operand(const MachineInstr *MI, int OpNum,
94 raw_ostream &O);
95 void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNum,
96 raw_ostream &O);
97 void printAddrMode3Operand(const MachineInstr *MI, int OpNum,
98 raw_ostream &O);
99 void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNum,
100 raw_ostream &O);
101 void printAddrMode4Operand(const MachineInstr *MI, int OpNum,raw_ostream &O,
102 const char *Modifier = 0);
103 void printAddrMode5Operand(const MachineInstr *MI, int OpNum,raw_ostream &O,
104 const char *Modifier = 0);
105 void printAddrMode6Operand(const MachineInstr *MI, int OpNum,
106 raw_ostream &O);
107 void printAddrMode6OffsetOperand(const MachineInstr *MI, int OpNum,
108 raw_ostream &O);
109 void printAddrModePCOperand(const MachineInstr *MI, int OpNum,
110 raw_ostream &O,
111 const char *Modifier = 0);
112 void printBitfieldInvMaskImmOperand (const MachineInstr *MI, int OpNum,
113 raw_ostream &O);
114
115 void printThumbS4ImmOperand(const MachineInstr *MI, int OpNum,
116 raw_ostream &O);
117 void printThumbITMask(const MachineInstr *MI, int OpNum, raw_ostream &O);
118 void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNum,
119 raw_ostream &O);
120 void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNum,
121 raw_ostream &O,
122 unsigned Scale);
123 void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNum,
124 raw_ostream &O);
125 void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNum,
126 raw_ostream &O);
127 void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNum,
128 raw_ostream &O);
129 void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNum,
130 raw_ostream &O);
131
132 void printT2SOOperand(const MachineInstr *MI, int OpNum, raw_ostream &O);
133 void printT2AddrModeImm12Operand(const MachineInstr *MI, int OpNum,
134 raw_ostream &O);
135 void printT2AddrModeImm8Operand(const MachineInstr *MI, int OpNum,
136 raw_ostream &O);
137 void printT2AddrModeImm8s4Operand(const MachineInstr *MI, int OpNum,
138 raw_ostream &O);
139 void printT2AddrModeImm8OffsetOperand(const MachineInstr *MI, int OpNum,
140 raw_ostream &O);
141 void printT2AddrModeImm8s4OffsetOperand(const MachineInstr *MI, int OpNum,
142 raw_ostream &O) {}
143 void printT2AddrModeSoRegOperand(const MachineInstr *MI, int OpNum,
144 raw_ostream &O);
145
146 void printCPSOptionOperand(const MachineInstr *MI, int OpNum,
147 raw_ostream &O) {}
148 void printMSRMaskOperand(const MachineInstr *MI, int OpNum,
149 raw_ostream &O) {}
150 void printNegZeroOperand(const MachineInstr *MI, int OpNum,
151 raw_ostream &O) {}
152 void printPredicateOperand(const MachineInstr *MI, int OpNum,
153 raw_ostream &O);
154 void printMandatoryPredicateOperand(const MachineInstr *MI, int OpNum,
155 raw_ostream &O);
156 void printSBitModifierOperand(const MachineInstr *MI, int OpNum,
157 raw_ostream &O);
158 void printPCLabel(const MachineInstr *MI, int OpNum,
159 raw_ostream &O);
160 void printRegisterList(const MachineInstr *MI, int OpNum,
161 raw_ostream &O);
162 void printCPInstOperand(const MachineInstr *MI, int OpNum,
163 raw_ostream &O,
164 const char *Modifier);
165 void printJTBlockOperand(const MachineInstr *MI, int OpNum,
166 raw_ostream &O);
167 void printJT2BlockOperand(const MachineInstr *MI, int OpNum,
168 raw_ostream &O);
169 void printTBAddrMode(const MachineInstr *MI, int OpNum,
170 raw_ostream &O);
171 void printNoHashImmediate(const MachineInstr *MI, int OpNum,
172 raw_ostream &O);
173 void printVFPf32ImmOperand(const MachineInstr *MI, int OpNum,
174 raw_ostream &O);
175 void printVFPf64ImmOperand(const MachineInstr *MI, int OpNum,
176 raw_ostream &O);
177 void printNEONModImmOperand(const MachineInstr *MI, int OpNum,
178 raw_ostream &O);
179
180 virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
181 unsigned AsmVariant, const char *ExtraCode,
182 raw_ostream &O);
183 virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum,
184 unsigned AsmVariant,
185 const char *ExtraCode, raw_ostream &O);
186
187 void printInstruction(const MachineInstr *MI, raw_ostream &O); // autogen
188 static const char *getRegisterName(unsigned RegNo);
189
190 virtual void EmitInstruction(const MachineInstr *MI);
191 bool runOnMachineFunction(MachineFunction &F);
192
193 virtual void EmitConstantPool() {} // we emit constant pools customly!
194 virtual void EmitFunctionEntryLabel();
195 void EmitStartOfAsmFile(Module &M);
196 void EmitEndOfAsmFile(Module &M);
197
198 MCSymbol *GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
199 const MachineBasicBlock *MBB) const;
200 MCSymbol *GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const;
201
202 /// EmitMachineConstantPoolValue - Print a machine constantpool value to
203 /// the .s file.
204 virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
205 SmallString<128> Str;
206 raw_svector_ostream OS(Str);
207 EmitMachineConstantPoolValue(MCPV, OS);
208 OutStreamer.EmitRawText(OS.str());
209 }
210
211 void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV,
212 raw_ostream &O) {
213 switch (TM.getTargetData()->getTypeAllocSize(MCPV->getType())) {
214 case 1: O << MAI->getData8bitsDirective(0); break;
215 case 2: O << MAI->getData16bitsDirective(0); break;
216 case 4: O << MAI->getData32bitsDirective(0); break;
217 default: assert(0 && "Unknown CPV size");
218 }
219
220 ARMConstantPoolValue *ACPV = static_cast(MCPV);
221
222 if (ACPV->isLSDA()) {
223 O << MAI->getPrivateGlobalPrefix() << "_LSDA_" << getFunctionNumber();
224 } else if (ACPV->isBlockAddress()) {
225 O << *GetBlockAddressSymbol(ACPV->getBlockAddress());
226 } else if (ACPV->isGlobalValue()) {
227 const GlobalValue *GV = ACPV->getGV();
228 bool isIndirect = Subtarget->isTargetDarwin() &&
229 Subtarget->GVIsIndirectSymbol(GV, TM.getRelocationModel());
230 if (!isIndirect)
231 O << *Mang->getSymbol(GV);
232 else {
233 // FIXME: Remove this when Darwin transition to @GOT like syntax.
234 MCSymbol *Sym = GetSymbolWithGlobalValueBase(GV, "$non_lazy_ptr");
235 O << *Sym;
236
237 MachineModuleInfoMachO &MMIMachO =
238 MMI->getObjFileInfo();
239 MachineModuleInfoImpl::StubValueTy &StubSym =
240 GV->hasHiddenVisibility() ? MMIMachO.getHiddenGVStubEntry(Sym) :
241 MMIMachO.getGVStubEntry(Sym);
242 if (StubSym.getPointer() == 0)
243 StubSym = MachineModuleInfoImpl::
244 StubValueTy(Mang->getSymbol(GV), !GV->hasInternalLinkage());
245 }
246 } else {
247 assert(ACPV->isExtSymbol() && "unrecognized constant pool value");
248 O << *GetExternalSymbolSymbol(ACPV->getSymbol());
249 }
250
251 if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
252 if (ACPV->getPCAdjustment() != 0) {
253 O << "-(" << MAI->getPrivateGlobalPrefix() << "PC"
254 << getFunctionNumber() << "_" << ACPV->getLabelId()
255 << "+" << (unsigned)ACPV->getPCAdjustment();
256 if (ACPV->mustAddCurrentAddress())
257 O << "-.";
258 O << ')';
259 }
260 }
261 };
262 } // end of anonymous namespace
263
264 #include "ARMGenAsmWriter.inc"
265
266 void ARMAsmPrinter::EmitFunctionEntryLabel() {
267 if (AFI->isThumbFunction()) {
268 OutStreamer.EmitRawText(StringRef("\t.code\t16"));
269 if (!Subtarget->isTargetDarwin())
270 OutStreamer.EmitRawText(StringRef("\t.thumb_func"));
271 else {
272 // This needs to emit to a temporary string to get properly quoted
273 // MCSymbols when they have spaces in them.
274 SmallString<128> Tmp;
275 raw_svector_ostream OS(Tmp);
276 OS << "\t.thumb_func\t" << *CurrentFnSym;
277 OutStreamer.EmitRawText(OS.str());
278 }
279 }
280
281 OutStreamer.EmitLabel(CurrentFnSym);
282 }
283
284 /// runOnMachineFunction - This uses the printInstruction()
285 /// method to print assembly for each instruction.
286 ///
287 bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
288 AFI = MF.getInfo();
289 MCP = MF.getConstantPool();
290
291 return AsmPrinter::runOnMachineFunction(MF);
292 }
293
294 void ARMAsmPrinter::printOperand(const MachineInstr *MI, int OpNum,
295 raw_ostream &O, const char *Modifier) {
296 const MachineOperand &MO = MI->getOperand(OpNum);
297 unsigned TF = MO.getTargetFlags();
298
299 switch (MO.getType()) {
300 default:
301 assert(0 && "");
302 case MachineOperand::MO_Register: {
303 unsigned Reg = MO.getReg();
304 assert(TargetRegisterInfo::isPhysicalRegister(Reg));
305 if (Modifier && strcmp(Modifier, "dregpair") == 0) {
306 unsigned DRegLo = TM.getRegisterInfo()->getSubReg(Reg, ARM::dsub_0);
307 unsigned DRegHi = TM.getRegisterInfo()->getSubReg(Reg, ARM::dsub_1);
308 O << '{'
309 << getRegisterName(DRegLo) << ", " << getRegisterName(DRegHi)
310 << '}';
311 } else if (Modifier && strcmp(Modifier, "lane") == 0) {
312 unsigned RegNum = ARMRegisterInfo::getRegisterNumbering(Reg);
313 unsigned DReg =
314 TM.getRegisterInfo()->getMatchingSuperReg(Reg,
315 RegNum & 1 ? ARM::ssub_1 : ARM::ssub_0, &ARM::DPR_VFP2RegClass);
316 O << getRegisterName(DReg) << '[' << (RegNum & 1) << ']';
317 } else {
318 assert(!MO.getSubReg() && "Subregs should be eliminated!");
319 O << getRegisterName(Reg);
320 }
321 break;
322 }
323 case MachineOperand::MO_Immediate: {
324 int64_t Imm = MO.getImm();
325 O << '#';
326 if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
327 (TF & ARMII::MO_LO16))
328 O << ":lower16:";
329 else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
330 (TF & ARMII::MO_HI16))
331 O << ":upper16:";
332 O << Imm;
333 break;
334 }
335 case MachineOperand::MO_MachineBasicBlock:
336 O << *MO.getMBB()->getSymbol();
337 return;
338 case MachineOperand::MO_GlobalAddress: {
339 bool isCallOp = Modifier && !strcmp(Modifier, "call");
340 const GlobalValue *GV = MO.getGlobal();
341
342 if ((Modifier && strcmp(Modifier, "lo16") == 0) ||
343 (TF & ARMII::MO_LO16))
344 O << ":lower16:";
345 else if ((Modifier && strcmp(Modifier, "hi16") == 0) ||
346 (TF & ARMII::MO_HI16))
347 O << ":upper16:";
348 O << *Mang->getSymbol(GV);
349
350 printOffset(MO.getOffset(), O);
351
352 if (isCallOp && Subtarget->isTargetELF() &&
353 TM.getRelocationModel() == Reloc::PIC_)
354 O << "(PLT)";
355 break;
356 }
357 case MachineOperand::MO_ExternalSymbol: {
358 bool isCallOp = Modifier && !strcmp(Modifier, "call");
359 O << *GetExternalSymbolSymbol(MO.getSymbolName());
360
361 if (isCallOp && Subtarget->isTargetELF() &&
362 TM.getRelocationModel() == Reloc::PIC_)
363 O << "(PLT)";
364 break;
365 }
366 case MachineOperand::MO_ConstantPoolIndex:
367 O << *GetCPISymbol(MO.getIndex());
368 break;
369 case MachineOperand::MO_JumpTableIndex:
370 O << *GetJTISymbol(MO.getIndex());
371 break;
372 }
373 }
374
375 static void printSOImm(raw_ostream &O, int64_t V, bool VerboseAsm,
376 const MCAsmInfo *MAI) {
377 // Break it up into two parts that make up a shifter immediate.
378 V = ARM_AM::getSOImmVal(V);
379 assert(V != -1 && "Not a valid so_imm value!");
380
381 unsigned Imm = ARM_AM::getSOImmValImm(V);
382 unsigned Rot = ARM_AM::getSOImmValRot(V);
383
384 // Print low-level immediate formation info, per
385 // A5.1.3: "Data-processing operands - Immediate".
386 if (Rot) {
387 O << "#" << Imm << ", " << Rot;
388 // Pretty printed version.
389 if (VerboseAsm) {
390 O << "\t" << MAI->getCommentString() << ' ';
391 O << (int)ARM_AM::rotr32(Imm, Rot);
392 }
393 } else {
394 O << "#" << Imm;
395 }
396 }
397
398 /// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
399 /// immediate in bits 0-7.
400 void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum,
401 raw_ostream &O) {
402 const MachineOperand &MO = MI->getOperand(OpNum);
403 assert(MO.isImm() && "Not a valid so_imm value!");
404 printSOImm(O, MO.getImm(), isVerbose(), MAI);
405 }
406
407 /// printSOImm2PartOperand - SOImm is broken into two pieces using a 'mov'
408 /// followed by an 'orr' to materialize.
409 void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum,
410 raw_ostream &O) {
411 const MachineOperand &MO = MI->getOperand(OpNum);
412 assert(MO.isImm() && "Not a valid so_imm value!");
413 unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO.getImm());
414 unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO.getImm());
415 printSOImm(O, V1, isVerbose(), MAI);
416 O << "\n\torr";
417 printPredicateOperand(MI, 2, O);
418 O << "\t";
419 printOperand(MI, 0, O);
420 O << ", ";
421 printOperand(MI, 0, O);
422 O << ", ";
423 printSOImm(O, V2, isVerbose(), MAI);
424 }
425
426 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
427 // "Addressing Mode 1 - Data-processing operands" forms. This includes:
428 // REG 0 0 - e.g. R5
429 // REG REG 0,SH_OPC - e.g. R5, ROR R3
430 // REG 0 IMM,SH_OPC - e.g. R5, LSL #3
431 void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op,
432 raw_ostream &O) {
433 const MachineOperand &MO1 = MI->getOperand(Op);
434 const MachineOperand &MO2 = MI->getOperand(Op+1);
435 const MachineOperand &MO3 = MI->getOperand(Op+2);
436
437 O << getRegisterName(MO1.getReg());
438
439 // Print the shift opc.
440 O << ", "
441 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()))
442 << " ";
443
444 if (MO2.getReg()) {
445 O << getRegisterName(MO2.getReg());
446 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
447 } else {
448 O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
449 }
450 }
451
452 void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op,
453 raw_ostream &O) {
454 const MachineOperand &MO1 = MI->getOperand(Op);
455 const MachineOperand &MO2 = MI->getOperand(Op+1);
456 const MachineOperand &MO3 = MI->getOperand(Op+2);
457
458 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
459 printOperand(MI, Op, O);
460 return;
461 }
462
463 O << "[" << getRegisterName(MO1.getReg());
464
465 if (!MO2.getReg()) {
466 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
467 O << ", #"
468 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
469 << ARM_AM::getAM2Offset(MO3.getImm());
470 O << "]";
471 return;
472 }
473
474 O << ", "
475 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO3.getImm()))
476 << getRegisterName(MO2.getReg());
477
478 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
479 O << ", "
480 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
481 << " #" << ShImm;
482 O << "]";
483 }
484
485 void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op,
486 raw_ostream &O) {
487 const MachineOperand &MO1 = MI->getOperand(Op);
488 const MachineOperand &MO2 = MI->getOperand(Op+1);
489
490 if (!MO1.getReg()) {
491 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
492 O << "#"
493 << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
494 << ImmOffs;
495 return;
496 }
497
498 O << ARM_AM::getAddrOpcStr(ARM_AM::getAM2Op(MO2.getImm()))
499 << getRegisterName(MO1.getReg());
500
501 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
502 O << ", "
503 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
504 << " #" << ShImm;
505 }
506
507 void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op,
508 raw_ostream &O) {
509 const MachineOperand &MO1 = MI->getOperand(Op);
510 const MachineOperand &MO2 = MI->getOperand(Op+1);
511 const MachineOperand &MO3 = MI->getOperand(Op+2);
512
513 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
514 O << "[" << getRegisterName(MO1.getReg());
515
516 if (MO2.getReg()) {
517 O << ", "
518 << (char)ARM_AM::getAM3Op(MO3.getImm())
519 << getRegisterName(MO2.getReg())
520 << "]";
521 return;
522 }
523
524 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
525 O << ", #"
526 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO3.getImm()))
527 << ImmOffs;
528 O << "]";
529 }
530
531 void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op,
532 raw_ostream &O){
533 const MachineOperand &MO1 = MI->getOperand(Op);
534 const MachineOperand &MO2 = MI->getOperand(Op+1);
535
536 if (MO1.getReg()) {
537 O << (char)ARM_AM::getAM3Op(MO2.getImm())
538 << getRegisterName(MO1.getReg());
539 return;
540 }
541
542 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
543 O << "#"
544 << ARM_AM::getAddrOpcStr(ARM_AM::getAM3Op(MO2.getImm()))
545 << ImmOffs;
546 }
547
548 void ARMAsmPrinter::printAddrMode4Operand(const MachineInstr *MI, int Op,
549 raw_ostream &O,
550 const char *Modifier) {
551 const MachineOperand &MO2 = MI->getOperand(Op+1);
552 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
553 if (Modifier && strcmp(Modifier, "submode") == 0) {
554 O << ARM_AM::getAMSubModeStr(Mode);
555 } else if (Modifier && strcmp(Modifier, "wide") == 0) {
556 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
557 if (Mode == ARM_AM::ia)
558 O << ".w";
559 } else {
560 printOperand(MI, Op, O);
561 }
562 }
563
564 void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op,
565 raw_ostream &O,
566 const char *Modifier) {
567 const MachineOperand &MO1 = MI->getOperand(Op);
568 const MachineOperand &MO2 = MI->getOperand(Op+1);
569
570 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
571 printOperand(MI, Op, O);
572 return;
573 }
574
575 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
576
577 if (Modifier && strcmp(Modifier, "submode") == 0) {
578 ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm());
579 O << ARM_AM::getAMSubModeStr(Mode);
580 return;
581 } else if (Modifier && strcmp(Modifier, "base") == 0) {
582 // Used for FSTM{D|S} and LSTM{D|S} operations.
583 O << getRegisterName(MO1.getReg());
584 return;
585 }
586
587 O << "[" << getRegisterName(MO1.getReg());
588
589 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
590 O << ", #"
591 << ARM_AM::getAddrOpcStr(ARM_AM::getAM5Op(MO2.getImm()))
592 << ImmOffs*4;
593 }
594 O << "]";
595 }
596
597 void ARMAsmPrinter::printAddrMode6Operand(const MachineInstr *MI, int Op,
598 raw_ostream &O) {
599 const MachineOperand &MO1 = MI->getOperand(Op);
600 const MachineOperand &MO2 = MI->getOperand(Op+1);
601
602 O << "[" << getRegisterName(MO1.getReg());
603 if (MO2.getImm()) {
604 // FIXME: Both darwin as and GNU as violate ARM docs here.
605 O << ", :" << (MO2.getImm() << 3);
606 }
607 O << "]";
608 }
609
610 void ARMAsmPrinter::printAddrMode6OffsetOperand(const MachineInstr *MI, int Op,
611 raw_ostream &O){
612 const MachineOperand &MO = MI->getOperand(Op);
613 if (MO.getReg() == 0)
614 O << "!";
615 else
616 O << ", " << getRegisterName(MO.getReg());
617 }
618
619 void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op,
620 raw_ostream &O,
621 const char *Modifier) {
622 if (Modifier && strcmp(Modifier, "label") == 0) {
623 printPCLabel(MI, Op+1, O);
624 return;
625 }
626
627 const MachineOperand &MO1 = MI->getOperand(Op);
628 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
629 O << "[pc, " << getRegisterName(MO1.getReg()) << "]";
630 }
631
632 void
633 ARMAsmPrinter::printBitfieldInvMaskImmOperand(const MachineInstr *MI, int Op,
634 raw_ostream &O) {
635 const MachineOperand &MO = MI->getOperand(Op);
636 uint32_t v = ~MO.getImm();
637 int32_t lsb = CountTrailingZeros_32(v);
638 int32_t width = (32 - CountLeadingZeros_32 (v)) - lsb;
639 assert(MO.isImm() && "Not a valid bf_inv_mask_imm value!");
640 O << "#" << lsb << ", #" << width;
641 }
642
643 //===--------------------------------------------------------------------===//
644
645 void ARMAsmPrinter::printThumbS4ImmOperand(const MachineInstr *MI, int Op,
646 raw_ostream &O) {
647 O << "#" << MI->getOperand(Op).getImm() * 4;
648 }
649
650 void
651 ARMAsmPrinter::printThumbITMask(const MachineInstr *MI, int Op,
652 raw_ostream &O) {
653 // (3 - the number of trailing zeros) is the number of then / else.
654 unsigned Mask = MI->getOperand(Op).getImm();
655 unsigned CondBit0 = Mask >> 4 & 1;
656 unsigned NumTZ = CountTrailingZeros_32(Mask);
657 assert(NumTZ <= 3 && "Invalid IT mask!");
658 for (unsigned Pos = 3, e = NumTZ; Pos > e; --Pos) {
659 bool T = ((Mask >> Pos) & 1) == CondBit0;
660 if (T)
661 O << 't';
662 else
663 O << 'e';
664 }
665 }
666
667 void
668 ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op,
669 raw_ostream &O) {
670 const MachineOperand &MO1 = MI->getOperand(Op);
671 const MachineOperand &MO2 = MI->getOperand(Op+1);
672 O << "[" << getRegisterName(MO1.getReg());
673 O << ", " << getRegisterName(MO2.getReg()) << "]";
674 }
675
676 void
677 ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op,
678 raw_ostream &O,
679 unsigned Scale) {
680 const MachineOperand &MO1 = MI->getOperand(Op);
681 const MachineOperand &MO2 = MI->getOperand(Op+1);
682 const MachineOperand &MO3 = MI->getOperand(Op+2);
683
684 if (!MO1.isReg()) { // FIXME: This is for CP entries, but isn't right.
685 printOperand(MI, Op, O);
686 return;
687 }
688
689 O << "[" << getRegisterName(MO1.getReg());
690 if (MO3.getReg())
691 O << ", " << getRegisterName(MO3.getReg());
692 else if (unsigned ImmOffs = MO2.getImm())
693 O << ", #" << ImmOffs * Scale;
694 O << "]";
695 }
696
697 void
698 ARMAsmPrinter::printThumbAddrModeS1Operand(const MachineInstr *MI, int Op,
699 raw_ostream &O) {
700 printThumbAddrModeRI5Operand(MI, Op, O, 1);
701 }
702 void
703 ARMAsmPrinter::printThumbAddrModeS2Operand(const MachineInstr *MI, int Op,
704 raw_ostream &O) {
705 printThumbAddrModeRI5Operand(MI, Op, O, 2);
706 }
707 void
708 ARMAsmPrinter::printThumbAddrModeS4Operand(const MachineInstr *MI, int Op,
709 raw_ostream &O) {
710 printThumbAddrModeRI5Operand(MI, Op, O, 4);
711 }
712
713 void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op,
714 raw_ostream &O) {
715 const MachineOperand &MO1 = MI->getOperand(Op);
716 const MachineOperand &MO2 = MI->getOperand(Op+1);
717 O << "[" << getRegisterName(MO1.getReg());
718 if (unsigned ImmOffs = MO2.getImm())
719 O << ", #" << ImmOffs*4;
720 O << "]";
721 }
722
723 //===--------------------------------------------------------------------===//
724
725 // Constant shifts t2_so_reg is a 2-operand unit corresponding to the Thumb2
726 // register with shift forms.
727 // REG 0 0 - e.g. R5
728 // REG IMM, SH_OPC - e.g. R5, LSL #3
729 void ARMAsmPrinter::printT2SOOperand(const MachineInstr *MI, int OpNum,
730 raw_ostream &O) {
731 const MachineOperand &MO1 = MI->getOperand(OpNum);
732 const MachineOperand &MO2 = MI->getOperand(OpNum+1);
733
734 unsigned Reg = MO1.getReg();
735 assert(TargetRegisterInfo::isPhysicalRegister(Reg));
736 O << getRegisterName(Reg);
737
738 // Print the shift opc.
739 O << ", "
740 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO2.getImm()))
741 << " ";
742
743 assert(MO2.isImm() && "Not a valid t2_so_reg value!");
744 O << "#" << ARM_AM::getSORegOffset(MO2.getImm());
745 }
746
747 void ARMAsmPrinter::printT2AddrModeImm12Operand(const MachineInstr *MI,
748 int OpNum,
749 raw_ostream &O) {
750 const MachineOperand &MO1 = MI->getOperand(OpNum);
751 const MachineOperand &MO2 = MI->getOperand(OpNum+1);
752
753 O << "[" << getRegisterName(MO1.getReg());
754
755 unsigned OffImm = MO2.getImm();
756 if (OffImm) // Don't print +0.
757 O << ", #" << OffImm;
758 O << "]";
759 }
760
761 void ARMAsmPrinter::printT2AddrModeImm8Operand(const MachineInstr *MI,
762 int OpNum,
763 raw_ostream &O) {
764 const MachineOperand &MO1 = MI->getOperand(OpNum);
765 const MachineOperand &MO2 = MI->getOperand(OpNum+1);
766
767 O << "[" << getRegisterName(MO1.getReg());
768
769 int32_t OffImm = (int32_t)MO2.getImm();
770 // Don't print +0.
771 if (OffImm < 0)
772 O << ", #-" << -OffImm;
773 else if (OffImm > 0)
774 O << ", #" << OffImm;
775 O << "]";
776 }
777
778 void ARMAsmPrinter::printT2AddrModeImm8s4Operand(const MachineInstr *MI,
779 int OpNum,
780 raw_ostream &O) {
781 const MachineOperand &MO1 = MI->getOperand(OpNum);
782 const MachineOperand &MO2 = MI->getOperand(OpNum+1);
783
784 O << "[" << getRegisterName(MO1.getReg());
785
786 int32_t OffImm = (int32_t)MO2.getImm() / 4;
787 // Don't print +0.
788 if (OffImm < 0)
789 O << ", #-" << -OffImm * 4;
790 else if (OffImm > 0)
791 O << ", #" << OffImm * 4;
792 O << "]";
793 }
794
795 void ARMAsmPrinter::printT2AddrModeImm8OffsetOperand(const MachineInstr *MI,
796 int OpNum,
797 raw_ostream &O) {
798 const MachineOperand &MO1 = MI->getOperand(OpNum);
799 int32_t OffImm = (int32_t)MO1.getImm();
800 // Don't print +0.
801 if (OffImm < 0)
802 O << "#-" << -OffImm;
803 else if (OffImm > 0)
804 O << "#" << OffImm;
805 }
806
807 void ARMAsmPrinter::printT2AddrModeSoRegOperand(const MachineInstr *MI,
808 int OpNum,
809 raw_ostream &O) {
810 const MachineOperand &MO1 = MI->getOperand(OpNum);
811 const MachineOperand &MO2 = MI->getOperand(OpNum+1);
812 const MachineOperand &MO3 = MI->getOperand(OpNum+2);
813
814 O << "[" << getRegisterName(MO1.getReg());
815
816 assert(MO2.getReg() && "Invalid so_reg load / store address!");
817 O << ", " << getRegisterName(MO2.getReg());
818
819 unsigned ShAmt = MO3.getImm();
820 if (ShAmt) {
821 assert(ShAmt <= 3 && "Not a valid Thumb2 addressing mode!");
822 O << ", lsl #" << ShAmt;
823 }
824 O << "]";
825 }
826
827
828 //===--------------------------------------------------------------------===//
829
830 void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int OpNum,
831 raw_ostream &O) {
832 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
833 if (CC != ARMCC::AL)
834 O << ARMCondCodeToString(CC);
835 }
836
837 void ARMAsmPrinter::printMandatoryPredicateOperand(const MachineInstr *MI,
838 int OpNum,
839 raw_ostream &O) {
840 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(OpNum).getImm();
841 O << ARMCondCodeToString(CC);
842 }
843
844 void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int OpNum,
845 raw_ostream &O){
846 unsigned Reg = MI->getOperand(OpNum).getReg();
847 if (Reg) {
848 assert(Reg == ARM::CPSR && "Expect ARM CPSR register!");
849 O << 's';
850 }
851 }
852
853 void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int OpNum,
854 raw_ostream &O) {
855 int Id = (int)MI->getOperand(OpNum).getImm();
856 O << MAI->getPrivateGlobalPrefix()
857 << "PC" << getFunctionNumber() << "_" << Id;
858 }
859
860 void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int OpNum,
861 raw_ostream &O) {
862 O << "{";
863 for (unsigned i = OpNum, e = MI->getNumOperands(); i != e; ++i) {
864 if (MI->getOperand(i).isImplicit())
865 continue;
866 if ((int)i != OpNum) O << ", ";
867 printOperand(MI, i, O);
868 }
869 O << "}";
870 }
871
872 void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNum,
873 raw_ostream &O, const char *Modifier) {
874 assert(Modifier && "This operand only works with a modifier!");
875 // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the
876 // data itself.
877 if (!strcmp(Modifier, "label")) {
878 unsigned ID = MI->getOperand(OpNum).getImm();
879 OutStreamer.EmitLabel(GetCPISymbol(ID));
880 } else {
881 assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
882 unsigned CPI = MI->getOperand(OpNum).getIndex();
883
884 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPI];
885
886 if (MCPE.isMachineConstantPoolEntry()) {
887 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
888 } else {
889 EmitGlobalConstant(MCPE.Val.ConstVal);
890 }
891 }
892 }
893
894 MCSymbol *ARMAsmPrinter::
895 GetARMSetPICJumpTableLabel2(unsigned uid, unsigned uid2,
896 const MachineBasicBlock *MBB) const {
897 SmallString<60> Name;
898 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix()
899 << getFunctionNumber() << '_' << uid << '_' << uid2
900 << "_set_" << MBB->getNumber();
901 return OutContext.GetOrCreateSymbol(Name.str());
902 }
903
904 MCSymbol *ARMAsmPrinter::
905 GetARMJTIPICJumpTableLabel2(unsigned uid, unsigned uid2) const {
906 SmallString<60> Name;
907 raw_svector_ostream(Name) << MAI->getPrivateGlobalPrefix() << "JTI"
908 << getFunctionNumber() << '_' << uid << '_' << uid2;
909 return OutContext.GetOrCreateSymbol(Name.str());
910 }
911
912 void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNum,
913 raw_ostream &O) {
914 assert(!Subtarget->isThumb2() && "Thumb2 should use double-jump jumptables!");
915
916 const MachineOperand &MO1 = MI->getOperand(OpNum);
917 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
918
919 unsigned JTI = MO1.getIndex();
920 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
921 // Can't use EmitLabel until instprinter happens, label comes out in the wrong
922 // order.
923 O << *JTISymbol << ":\n";
924
925 const char *JTEntryDirective = MAI->getData32bitsDirective();
926
927 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
928 const std::vector &JT = MJTI->getJumpTables();
929 const std::vector &JTBBs = JT[JTI].MBBs;
930 bool UseSet= MAI->hasSetDirective() && TM.getRelocationModel() == Reloc::PIC_;
931 SmallPtrSet JTSets;
932 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
933 MachineBasicBlock *MBB = JTBBs[i];
934 bool isNew = JTSets.insert(MBB);
935
936 if (UseSet && isNew) {
937 O << "\t.set\t"
938 << *GetARMSetPICJumpTableLabel2(JTI, MO2.getImm(), MBB) << ','
939 << *MBB->getSymbol() << '-' << *JTISymbol << '\n';
940 }
941
942 O << JTEntryDirective << ' ';
943 if (UseSet)
944 O << *GetARMSetPICJumpTableLabel2(JTI, MO2.getImm(), MBB);
945 else if (TM.getRelocationModel() == Reloc::PIC_)
946 O << *MBB->getSymbol() << '-' << *JTISymbol;
947 else
948 O << *MBB->getSymbol();
949
950 if (i != e-1)
951 O << '\n';
952 }
953 }
954
955 void ARMAsmPrinter::printJT2BlockOperand(const MachineInstr *MI, int OpNum,
956 raw_ostream &O) {
957 const MachineOperand &MO1 = MI->getOperand(OpNum);
958 const MachineOperand &MO2 = MI->getOperand(OpNum+1); // Unique Id
959 unsigned JTI = MO1.getIndex();
960
961 MCSymbol *JTISymbol = GetARMJTIPICJumpTableLabel2(JTI, MO2.getImm());
962
963 // Can't use EmitLabel until instprinter happens, label comes out in the wrong
964 // order.
965 O << *JTISymbol << ":\n";
966
967 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
968 const std::vector &JT = MJTI->getJumpTables();
969 const std::vector &JTBBs = JT[JTI].MBBs;
970 bool ByteOffset = false, HalfWordOffset = false;
971 if (MI->getOpcode() == ARM::t2TBB)
972 ByteOffset = true;
973 else if (MI->getOpcode() == ARM::t2TBH)
974 HalfWordOffset = true;
975
976 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
977 MachineBasicBlock *MBB = JTBBs[i];
978 if (ByteOffset)
979 O << MAI->getData8bitsDirective();
980 else if (HalfWordOffset)
981 O << MAI->getData16bitsDirective();
982
983 if (ByteOffset || HalfWordOffset)
984 O << '(' << *MBB->getSymbol() << "-" << *JTISymbol << ")/2";
985 else
986 O << "\tb.w " << *MBB->getSymbol();
987
988 if (i != e-1)
989 O << '\n';
990 }
991 }
992
993 void ARMAsmPrinter::printTBAddrMode(const MachineInstr *MI, int OpNum,
994 raw_ostream &O) {
995 O << "[pc, " << getRegisterName(MI->getOperand(OpNum).getReg());
996 if (MI->getOpcode() == ARM::t2TBH)
997 O << ", lsl #1";
998 O << ']';
999 }
1000
1001 void ARMAsmPrinter::printNoHashImmediate(const MachineInstr *MI, int OpNum,
1002 raw_ostream &O) {
1003 O << MI->getOperand(OpNum).getImm();
1004 }
1005
1006 void ARMAsmPrinter::printVFPf32ImmOperand(const MachineInstr *MI, int OpNum,
1007 raw_ostream &O) {
1008 const ConstantFP *FP = MI->getOperand(OpNum).getFPImm();
1009 O << '#' << FP->getValueAPF().convertToFloat();
1010 if (isVerbose()) {
1011 O << "\t\t" << MAI->getCommentString() << ' ';
1012 WriteAsOperand(O, FP, /*PrintType=*/false);
1013 }
1014 }
1015
1016 void ARMAsmPrinter::printVFPf64ImmOperand(const MachineInstr *MI, int OpNum,
1017 raw_ostream &O) {
1018 const ConstantFP *FP = MI->getOperand(OpNum).getFPImm();
1019 O << '#' << FP->getValueAPF().convertToDouble();
1020 if (isVerbose()) {
1021 O << "\t\t" << MAI->getCommentString() << ' ';
1022 WriteAsOperand(O, FP, /*PrintType=*/false);
1023 }
1024 }
1025
1026 void ARMAsmPrinter::printNEONModImmOperand(const MachineInstr *MI, int OpNum,
1027 raw_ostream &O) {
1028 unsigned EncodedImm = MI->getOperand(OpNum).getImm();
1029 unsigned EltBits;
1030 uint64_t Val = ARM_AM::decodeNEONModImm(EncodedImm, EltBits);
1031 O << "#0x" << utohexstr(Val);
1032 }
1033
1034 bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNum,
1035 unsigned AsmVariant, const char *ExtraCode,
1036 raw_ostream &O) {
1037 // Does this asm operand have a single letter operand modifier?
1038 if (ExtraCode && ExtraCode[0]) {
1039 if (ExtraCode[1] != 0) return true; // Unknown modifier.
1040
1041 switch (ExtraCode[0]) {
1042 default: return true; // Unknown modifier.
1043 case 'a': // Print as a memory address.
1044 if (MI->getOperand(OpNum).isReg()) {
1045 O << "[" << getRegisterName(MI->getOperand(OpNum).getReg()) << "]";
1046 return false;
1047 }
1048 // Fallthrough
1049 case 'c': // Don't print "#" before an immediate operand.
1050 if (!MI->getOperand(OpNum).isImm())
1051 return true;
1052 printNoHashImmediate(MI, OpNum, O);
1053 return false;
1054 case 'P': // Print a VFP double precision register.
1055 case 'q': // Print a NEON quad precision register.
1056 printOperand(MI, OpNum, O);
1057 return false;
1058 case 'Q':
1059 case 'R':
1060 case 'H':
1061 report_fatal_error("llvm does not support 'Q', 'R', and 'H' modifiers!");
1062 return true;
1063 }
1064 }
1065
1066 printOperand(MI, OpNum, O);
1067 return false;
1068 }
1069
1070 bool ARMAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI,
1071 unsigned OpNum, unsigned AsmVariant,
1072 const char *ExtraCode,
1073 raw_ostream &O) {
1074 if (ExtraCode && ExtraCode[0])
1075 return true; // Unknown modifier.
1076
1077 const MachineOperand &MO = MI->getOperand(OpNum);
1078 assert(MO.isReg() && "unexpected inline asm memory operand");
1079 O << "[" << getRegisterName(MO.getReg()) << "]";
1080 return false;
1081 }
1082
1083 void ARMAsmPrinter::EmitInstruction(const MachineInstr *MI) {
1084 if (EnableMCInst) {
1085 printInstructionThroughMCStreamer(MI);
1086 return;
1087 }
1088
1089 if (MI->getOpcode() == ARM::CONSTPOOL_ENTRY)
1090 EmitAlignment(2);
1091
1092 SmallString<128> Str;
1093 raw_svector_ostream OS(Str);
1094 if (MI->getOpcode() == ARM::DBG_VALUE) {
1095 unsigned NOps = MI->getNumOperands();
1096 assert(NOps==4);
1097 OS << '\t' << MAI->getCommentString() << "DEBUG_VALUE: ";
1098 // cast away const; DIetc do not take const operands for some reason.
1099 DIVariable V(const_cast(MI->getOperand(NOps-1).getMetadata()));
1100 OS << V.getName();
1101 OS << " <- ";
1102 // Frame address. Currently handles register +- offset only.
1103 assert(MI->getOperand(0).isReg() && MI->getOperand(1).isImm());
1104 OS << '['; printOperand(MI, 0, OS); OS << '+'; printOperand(MI, 1, OS);
1105 OS << ']';
1106 OS << "+";
1107 printOperand(MI, NOps-2, OS);
1108 OutStreamer.EmitRawText(OS.str());
1109 return;
1110 }
1111
1112 printInstruction(MI, OS);
1113 OutStreamer.EmitRawText(OS.str());
1114
1115 // Make sure the instruction that follows TBB is 2-byte aligned.
1116 // FIXME: Constant island pass should insert an "ALIGN" instruction instead.
1117 if (MI->getOpcode() == ARM::t2TBB)
1118 EmitAlignment(1);
1119 }
1120
1121 void ARMAsmPrinter::EmitStartOfAsmFile(Module &M) {
1122 if (Subtarget->isTargetDarwin()) {
1123 Reloc::Model RelocM = TM.getRelocationModel();
1124 if (RelocM == Reloc::PIC_ || RelocM == Reloc::DynamicNoPIC) {
1125 // Declare all the text sections up front (before the DWARF sections
1126 // emitted by AsmPrinter::doInitialization) so the assembler will keep
1127 // them together at the beginning of the object file. This helps
1128 // avoid out-of-range branches that are due a fundamental limitation of
1129 // the way symbol offsets are encoded with the current Darwin ARM
1130 // relocations.
1131 const TargetLoweringObjectFileMachO &TLOFMacho =
1132 static_cast(
1133 getObjFileLowering());
1134 OutStreamer.SwitchSection(TLOFMacho.getTextSection());
1135 OutStreamer.SwitchSection(TLOFMacho.getTextCoalSection());
1136 OutStreamer.SwitchSection(TLOFMacho.getConstTextCoalSection());
1137 if (RelocM == Reloc::DynamicNoPIC) {
1138 const MCSection *sect =
1139 OutContext.getMachOSection("__TEXT", "__symbol_stub4",
1140 MCSectionMachO::S_SYMBOL_STUBS,
1141 12, SectionKind::getText());
1142 OutStreamer.SwitchSection(sect);
1143 } else {
1144 const MCSection *sect =
1145 OutContext.getMachOSection("__TEXT", "__picsymbolstub4",
1146 MCSectionMachO::S_SYMBOL_STUBS,
1147 16, SectionKind::getText());
1148 OutStreamer.SwitchSection(sect);
1149 }
1150 }
1151 }
1152
1153 // Use unified assembler syntax.
1154 OutStreamer.EmitRawText(StringRef("\t.syntax unified"));
1155
1156 // Emit ARM Build Attributes
1157 if (Subtarget->isTargetELF()) {
1158 // CPU Type
1159 std::string CPUString = Subtarget->getCPUString();
1160 if (CPUString != "generic")
1161 OutStreamer.EmitRawText("\t.cpu " + Twine(CPUString));
1162
1163 // FIXME: Emit FPU type
1164 if (Subtarget->hasVFP2())
1165 OutStreamer.EmitRawText("\t.eabi_attribute " +
1166 Twine(ARMBuildAttrs::VFP_arch) + ", 2");
1167
1168 // Signal various FP modes.
1169 if (!UnsafeFPMath) {
1170 OutStreamer.EmitRawText("\t.eabi_attribute " +
1171 Twine(ARMBuildAttrs::ABI_FP_denormal) + ", 1");
1172 OutStreamer.EmitRawText("\t.eabi_attribute " +
1173 Twine(ARMBuildAttrs::ABI_FP_exceptions) + ", 1");
1174 }
1175
1176 if (NoInfsFPMath && NoNaNsFPMath)
1177 OutStreamer.EmitRawText("\t.eabi_attribute " +
1178 Twine(ARMBuildAttrs::ABI_FP_number_model)+ ", 1");
1179 else
1180 OutStreamer.EmitRawText("\t.eabi_attribute " +
1181 Twine(ARMBuildAttrs::ABI_FP_number_model)+ ", 3");
1182
1183 // 8-bytes alignment stuff.
1184 OutStreamer.EmitRawText("\t.eabi_attribute " +
1185 Twine(ARMBuildAttrs::ABI_align8_needed) + ", 1");
1186 OutStreamer.EmitRawText("\t.eabi_attribute " +
1187 Twine(ARMBuildAttrs::ABI_align8_preserved) + ", 1");
1188
1189 // Hard float. Use both S and D registers and conform to AAPCS-VFP.
1190 if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) {
1191 OutStreamer.EmitRawText("\t.eabi_attribute " +
1192 Twine(ARMBuildAttrs::ABI_HardFP_use) + ", 3");
1193 OutStreamer.EmitRawText("\t.eabi_attribute " +
1194 Twine(ARMBuildAttrs::ABI_VFP_args) + ", 1");
1195 }
1196 // FIXME: Should we signal R9 usage?
1197 }
1198 }
1199
1200
1201 void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) {
1202 if (Subtarget->isTargetDarwin()) {
1203 // All darwin targets use mach-o.
1204 const TargetLoweringObjectFileMachO &TLOFMacho =
1205 static_cast(getObjFileLowering());
1206 MachineModuleInfoMachO &MMIMacho =
1207 MMI->getObjFileInfo();
1208
1209 // Output non-lazy-pointers for external and common global variables.
1210 MachineModuleInfoMachO::SymbolListTy Stubs = MMIMacho.GetGVStubList();
1211
1212 if (!Stubs.empty()) {
1213 // Switch with ".non_lazy_symbol_pointer" directive.
1214 OutStreamer.SwitchSection(TLOFMacho.getNonLazySymbolPointerSection());
1215 EmitAlignment(2);
1216 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
1217 // L_foo$stub:
1218 OutStreamer.EmitLabel(Stubs[i].first);
1219 // .indirect_symbol _foo
1220 MachineModuleInfoImpl::StubValueTy &MCSym = Stubs[i].second;
1221 OutStreamer.EmitSymbolAttribute(MCSym.getPointer(),MCSA_IndirectSymbol);
1222
1223 if (MCSym.getInt())
1224 // External to current translation unit.
1225 OutStreamer.EmitIntValue(0, 4/*size*/, 0/*addrspace*/);
1226 else
1227 // Internal to current translation unit.
1228 //
1229 // When we place the LSDA into the TEXT section, the type info pointers
1230 // need to be indirect and pc-rel. We accomplish this by using NLPs.
1231 // However, sometimes the types are local to the file. So we need to
1232 // fill in the value for the NLP in those cases.
1233 OutStreamer.EmitValue(MCSymbolRefExpr::Create(MCSym.getPointer(),
1234 OutContext),
1235 4/*size*/, 0/*addrspace*/);
1236 }
1237
1238 Stubs.clear();
1239 OutStreamer.AddBlankLine();
1240 }
1241
1242 Stubs = MMIMacho.GetHiddenGVStubList();
1243 if (!Stubs.empty()) {
1244 OutStreamer.SwitchSection(getObjFileLowering().getDataSection());
1245 EmitAlignment(2);
1246 for (unsigned i = 0, e = Stubs.size(); i != e; ++i) {
1247 // L_foo$stub:
1248 OutStreamer.EmitLabel(Stubs[i].first);
1249 // .long _foo
1250 OutStreamer.EmitValue(MCSymbolRefExpr::
1251 Create(Stubs[i].second.getPointer(),
1252 OutContext),
1253 4/*size*/, 0/*addrspace*/);
1254 }
1255
1256 Stubs.clear();
1257 OutStreamer.AddBlankLine();
1258 }
1259
1260 // Funny Darwin hack: This flag tells the linker that no global symbols
1261 // contain code that falls through to other global symbols (e.g. the obvious
1262 // implementation of multiple entry points). If this doesn't occur, the
1263 // linker can safely perform dead code stripping. Since LLVM never
1264 // generates code that does this, it is always safe to set.
1265 OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols);
1266 }
1267 }
1268
1269 //===----------------------------------------------------------------------===//
1270
1271 void ARMAsmPrinter::printInstructionThroughMCStreamer(const MachineInstr *MI) {
1272 ARMMCInstLower MCInstLowering(OutContext, *Mang, *this);
1273 switch (MI->getOpcode()) {
1274 case ARM::t2MOVi32imm:
1275 assert(0 && "Should be lowered by thumb2it pass");
1276 default: break;
1277 case ARM::PICADD: { // FIXME: Remove asm string from td file.
1278 // This is a pseudo op for a label + instruction sequence, which looks like:
1279 // LPC0:
1280 // add r0, pc, r0
1281 // This adds the address of LPC0 to r0.
1282
1283 // Emit the label.
1284 // FIXME: MOVE TO SHARED PLACE.
1285 unsigned Id = (unsigned)MI->getOperand(2).getImm();
1286 const char *Prefix = MAI->getPrivateGlobalPrefix();
1287 MCSymbol *Label =OutContext.GetOrCreateSymbol(Twine(Prefix)
1288 + "PC" + Twine(getFunctionNumber()) + "_" + Twine(Id));
1289 OutStreamer.EmitLabel(Label);
1290
1291
1292 // Form and emit tha dd.
1293 MCInst AddInst;
1294 AddInst.setOpcode(ARM::ADDrr);
1295 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(0).getReg()));
1296 AddInst.addOperand(MCOperand::CreateReg(ARM::PC));
1297 AddInst.addOperand(MCOperand::CreateReg(MI->getOperand(1).getReg()));
1298 OutStreamer.EmitInstruction(AddInst);
1299 return;
1300 }
1301 case ARM::CONSTPOOL_ENTRY: { // FIXME: Remove asm string from td file.
1302 /// CONSTPOOL_ENTRY - This instruction represents a floating constant pool
1303 /// in the function. The first operand is the ID# for this instruction, the
1304 /// second is the index into the MachineConstantPool that this is, the third
1305 /// is the size in bytes of this constant pool entry.
1306 unsigned LabelId = (unsigned)MI->getOperand(0).getImm();
1307 unsigned CPIdx = (unsigned)MI->getOperand(1).getIndex();
1308
1309 EmitAlignment(2);
1310 OutStreamer.EmitLabel(GetCPISymbol(LabelId));
1311
1312 const MachineConstantPoolEntry &MCPE = MCP->getConstants()[CPIdx];
1313 if (MCPE.isMachineConstantPoolEntry())
1314 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
1315 else
1316 EmitGlobalConstant(MCPE.Val.ConstVal);
1317
1318 return;
1319 }
1320 case ARM::MOVi2pieces: { // FIXME: Remove asmstring from td file.
1321 // This is a hack that lowers as a two instruction sequence.
1322 unsigned DstReg = MI->getOperand(0).getReg();
1323 unsigned ImmVal = (unsigned)MI->getOperand(1).getImm();
1324
1325 unsigned SOImmValV1 = ARM_AM::getSOImmTwoPartFirst(ImmVal);
1326 unsigned SOImmValV2 = ARM_AM::getSOImmTwoPartSecond(ImmVal);
1327
1328 {
1329 MCInst TmpInst;
1330 TmpInst.setOpcode(ARM::MOVi);
1331 TmpInst.addOperand(MCOperand::CreateReg(DstReg));
1332 TmpInst.addOperand(MCOperand::CreateImm(SOImmValV1));
1333
1334 // Predicate.
1335 TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
1336 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg()));
1337
1338 TmpInst.addOperand(MCOperand::CreateReg(0)); // cc_out
1339 OutStreamer.EmitInstruction(TmpInst);
1340 }
1341
1342 {
1343 MCInst TmpInst;
1344 TmpInst.setOpcode(ARM::ORRri);
1345 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // dstreg
1346 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // inreg
1347 TmpInst.addOperand(MCOperand::CreateImm(SOImmValV2)); // so_imm
1348 // Predicate.
1349 TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
1350 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg()));
1351
1352 TmpInst.addOperand(MCOperand::CreateReg(0)); // cc_out
1353 OutStreamer.EmitInstruction(TmpInst);
1354 }
1355 return;
1356 }
1357 case ARM::MOVi32imm: { // FIXME: Remove asmstring from td file.
1358 // This is a hack that lowers as a two instruction sequence.
1359 unsigned DstReg = MI->getOperand(0).getReg();
1360 const MachineOperand &MO = MI->getOperand(1);
1361 MCOperand V1, V2;
1362 if (MO.isImm()) {
1363 unsigned ImmVal = (unsigned)MI->getOperand(1).getImm();
1364 V1 = MCOperand::CreateImm(ImmVal & 65535);
1365 V2 = MCOperand::CreateImm(ImmVal >> 16);
1366 } else if (MO.isGlobal()) {
1367 MCSymbol *Symbol = MCInstLowering.GetGlobalAddressSymbol(MO);
1368 const MCSymbolRefExpr *SymRef1 =
1369 MCSymbolRefExpr::Create(Symbol,
1370 MCSymbolRefExpr::VK_ARM_LO16, OutContext);
1371 const MCSymbolRefExpr *SymRef2 =
1372 MCSymbolRefExpr::Create(Symbol,
1373 MCSymbolRefExpr::VK_ARM_HI16, OutContext);
1374 V1 = MCOperand::CreateExpr(SymRef1);
1375 V2 = MCOperand::CreateExpr(SymRef2);
1376 } else {
1377 MI->dump();
1378 llvm_unreachable("cannot handle this operand");
1379 }
1380
1381 {
1382 MCInst TmpInst;
1383 TmpInst.setOpcode(ARM::MOVi16);
1384 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // dstreg
1385 TmpInst.addOperand(V1); // lower16(imm)
1386
1387 // Predicate.
1388 TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
1389 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg()));
1390
1391 OutStreamer.EmitInstruction(TmpInst);
1392 }
1393
1394 {
1395 MCInst TmpInst;
1396 TmpInst.setOpcode(ARM::MOVTi16);
1397 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // dstreg
1398 TmpInst.addOperand(MCOperand::CreateReg(DstReg)); // srcreg
1399 TmpInst.addOperand(V2); // upper16(imm)
1400
1401 // Predicate.
1402 TmpInst.addOperand(MCOperand::CreateImm(MI->getOperand(2).getImm()));
1403 TmpInst.addOperand(MCOperand::CreateReg(MI->getOperand(3).getReg()));
1404
1405 OutStreamer.EmitInstruction(TmpInst);
1406 }
1407
1408 return;
1409 }
1410 }
1411
1412 MCInst TmpInst;
1413 MCInstLowering.Lower(MI, TmpInst);
1414 OutStreamer.EmitInstruction(TmpInst);
1415 }
1416
1417 //===----------------------------------------------------------------------===//
1418 // Target Registry Stuff
1419 //===----------------------------------------------------------------------===//
1420
1421 static MCInstPrinter *createARMMCInstPrinter(const Target &T,
1422 unsigned SyntaxVariant,
1423 const MCAsmInfo &MAI) {
1424 if (SyntaxVariant == 0)
1425 return new ARMInstPrinter(MAI, false);
1426 return 0;
1427 }
1428
1429 // Force static initialization.
1430 extern "C" void LLVMInitializeARMAsmPrinter() {
1431 RegisterAsmPrinter X(TheARMTarget);
1432 RegisterAsmPrinter Y(TheThumbTarget);
1433
1434 TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter);
1435 TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter);
1436 }
1437
+0
-162
lib/Target/ARM/AsmPrinter/ARMMCInstLower.cpp less more
None //===-- ARMMCInstLower.cpp - Convert ARM MachineInstr to an MCInst --------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains code to lower ARM MachineInstrs to their corresponding
10 // MCInst records.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "ARMMCInstLower.h"
15 //#include "llvm/CodeGen/MachineModuleInfoImpls.h"
16 #include "llvm/CodeGen/AsmPrinter.h"
17 #include "llvm/CodeGen/MachineBasicBlock.h"
18 #include "llvm/MC/MCAsmInfo.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCExpr.h"
21 #include "llvm/MC/MCInst.h"
22 //#include "llvm/MC/MCStreamer.h"
23 #include "llvm/Target/Mangler.h"
24 #include "llvm/Support/raw_ostream.h"
25 #include "llvm/ADT/SmallString.h"
26 using namespace llvm;
27
28
29 #if 0
30 const ARMSubtarget &ARMMCInstLower::getSubtarget() const {
31 return AsmPrinter.getSubtarget();
32 }
33
34 MachineModuleInfoMachO &ARMMCInstLower::getMachOMMI() const {
35 assert(getSubtarget().isTargetDarwin() &&"Can only get MachO info on darwin");
36 return AsmPrinter.MMI->getObjFileInfo();
37 }
38 #endif
39
40 MCSymbol *ARMMCInstLower::
41 GetGlobalAddressSymbol(const MachineOperand &MO) const {
42 // FIXME: HANDLE PLT references how??
43 switch (MO.getTargetFlags()) {
44 default: assert(0 && "Unknown target flag on GV operand");
45 case 0: break;
46 }
47
48 return Printer.Mang->getSymbol(MO.getGlobal());
49 }
50
51 MCSymbol *ARMMCInstLower::
52 GetExternalSymbolSymbol(const MachineOperand &MO) const {
53 // FIXME: HANDLE PLT references how??
54 switch (MO.getTargetFlags()) {
55 default: assert(0 && "Unknown target flag on GV operand");
56 case 0: break;
57 }
58
59 return Printer.GetExternalSymbolSymbol(MO.getSymbolName());
60 }
61
62
63
64 MCSymbol *ARMMCInstLower::
65 GetJumpTableSymbol(const MachineOperand &MO) const {
66 SmallString<256> Name;
67 raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "JTI"
68 << Printer.getFunctionNumber() << '_' << MO.getIndex();
69
70 #if 0
71 switch (MO.getTargetFlags()) {
72 default: llvm_unreachable("Unknown target flag on GV operand");
73 }
74 #endif
75
76 // Create a symbol for the name.
77 return Ctx.GetOrCreateSymbol(Name.str());
78 }
79
80 MCSymbol *ARMMCInstLower::
81 GetConstantPoolIndexSymbol(const MachineOperand &MO) const {
82 SmallString<256> Name;
83 raw_svector_ostream(Name) << Printer.MAI->getPrivateGlobalPrefix() << "CPI"
84 << Printer.getFunctionNumber() << '_' << MO.getIndex();
85
86 #if 0
87 switch (MO.getTargetFlags()) {
88 default: llvm_unreachable("Unknown target flag on GV operand");
89 }
90 #endif
91
92 // Create a symbol for the name.
93 return Ctx.GetOrCreateSymbol(Name.str());
94 }
95
96 MCOperand ARMMCInstLower::
97 LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const {
98 // FIXME: We would like an efficient form for this, so we don't have to do a
99 // lot of extra uniquing.
100 const MCExpr *Expr = MCSymbolRefExpr::Create(Sym, Ctx);
101
102 #if 0
103 switch (MO.getTargetFlags()) {
104 default: llvm_unreachable("Unknown target flag on GV operand");
105 }
106 #endif
107
108 if (!MO.isJTI() && MO.getOffset())
109 Expr = MCBinaryExpr::CreateAdd(Expr,
110 MCConstantExpr::Create(MO.getOffset(), Ctx),
111 Ctx);
112 return MCOperand::CreateExpr(Expr);
113 }
114
115
116 void ARMMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const {
117 OutMI.setOpcode(MI->getOpcode());
118
119 for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
120 const MachineOperand &MO = MI->getOperand(i);
121
122 MCOperand MCOp;
123 switch (MO.getType()) {
124 default:
125 MI->dump();
126 assert(0 && "unknown operand type");
127 case MachineOperand::MO_Register:
128 // Ignore all implicit register operands.
129 if (MO.isImplicit()) continue;
130 assert(!MO.getSubReg() && "Subregs should be eliminated!");
131 MCOp = MCOperand::CreateReg(MO.getReg());
132 break;
133 case MachineOperand::MO_Immediate:
134 MCOp = MCOperand::CreateImm(MO.getImm());
135 break;
136 case MachineOperand::MO_MachineBasicBlock:
137 MCOp = MCOperand::CreateExpr(MCSymbolRefExpr::Create(
138 MO.getMBB()->getSymbol(), Ctx));
139 break;
140 case MachineOperand::MO_GlobalAddress:
141 MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO));
142 break;
143 case MachineOperand::MO_ExternalSymbol:
144 MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO));
145 break;
146 case MachineOperand::MO_JumpTableIndex:
147 MCOp = LowerSymbolOperand(MO, GetJumpTableSymbol(MO));
148 break;
149 case MachineOperand::MO_ConstantPoolIndex:
150 MCOp = LowerSymbolOperand(MO, GetConstantPoolIndexSymbol(MO));
151 break;
152 case MachineOperand::MO_BlockAddress:
153 MCOp = LowerSymbolOperand(MO, Printer.GetBlockAddressSymbol(
154 MO.getBlockAddress()));
155 break;
156 }
157
158 OutMI.addOperand(MCOp);
159 }
160
161 }
+0
-56
lib/Target/ARM/AsmPrinter/ARMMCInstLower.h less more
None //===-- ARMMCInstLower.h - Lower MachineInstr to MCInst -------------------===//
1 //
2 // The LLVM Compiler Infrastructure
3 //
4 // This file is distributed under the University of Illinois Open Source
5 // License. See LICENSE.TXT for details.
6 //
7 //===----------------------------------------------------------------------===//
8
9 #ifndef ARM_MCINSTLOWER_H
10 #define ARM_MCINSTLOWER_H
11
12 #include "llvm/Support/Compiler.h"
13
14 namespace llvm {
15 class AsmPrinter;
16 class MCAsmInfo;
17 class MCContext;
18 class MCInst;
19 class MCOperand;
20 class MCSymbol;
21 class MachineInstr;
22 class MachineModuleInfoMachO;
23 class MachineOperand;
24 class Mangler;
25 //class ARMSubtarget;
26
27 /// ARMMCInstLower - This class is used to lower an MachineInstr into an MCInst.
28 class LLVM_LIBRARY_VISIBILITY ARMMCInstLower {
29 MCContext &Ctx;
30 Mangler &Mang;
31 AsmPrinter &Printer;
32
33 //const ARMSubtarget &getSubtarget() const;
34 public:
35 ARMMCInstLower(MCContext &ctx, Mangler &mang, AsmPrinter &printer)
36 : Ctx(ctx), Mang(mang), Printer(printer) {}
37
38 void Lower(const MachineInstr *MI, MCInst &OutMI) const;
39
40 //MCSymbol *GetPICBaseSymbol() const;
41 MCSymbol *GetGlobalAddressSymbol(const MachineOperand &MO) const;
42 MCSymbol *GetExternalSymbolSymbol(const MachineOperand &MO) const;
43 MCSymbol *GetJumpTableSymbol(const MachineOperand &MO) const;
44 MCSymbol *GetConstantPoolIndexSymbol(const MachineOperand &MO) const;
45 MCOperand LowerSymbolOperand(const MachineOperand &MO, MCSymbol *Sym) const;
46
47 /*
48 private:
49 MachineModuleInfoMachO &getMachOMMI() const;
50 */
51 };
52
53 }
54
55 #endif