llvm.org GIT mirror llvm / 0bd8971
Move ARM to pluggable asmprinter git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@54889 91177308-0d34-0410-b5e6-96231b3b80d8 Anton Korobeynikov 12 years ago
6 changed file(s) with 1091 addition(s) and 1040 deletion(s). Raw diff Collapse all Expand all
+0
-1030
lib/Target/ARM/ARMAsmPrinter.cpp less more
None //===-- ARMAsmPrinter.cpp - ARM LLVM assembly writer ----------------------===//
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 "ARMTargetMachine.h"
17 #include "ARMAddressingModes.h"
18 #include "ARMConstantPoolValue.h"
19 #include "ARMMachineFunctionInfo.h"
20 #include "llvm/Constants.h"
21 #include "llvm/Module.h"
22 #include "llvm/CodeGen/AsmPrinter.h"
23 #include "llvm/CodeGen/DwarfWriter.h"
24 #include "llvm/CodeGen/MachineModuleInfo.h"
25 #include "llvm/CodeGen/MachineFunctionPass.h"
26 #include "llvm/CodeGen/MachineJumpTableInfo.h"
27 #include "llvm/Target/TargetAsmInfo.h"
28 #include "llvm/Target/TargetData.h"
29 #include "llvm/Target/TargetMachine.h"
30 #include "llvm/Target/TargetOptions.h"
31 #include "llvm/ADT/SmallPtrSet.h"
32 #include "llvm/ADT/Statistic.h"
33 #include "llvm/ADT/StringExtras.h"
34 #include "llvm/Support/Compiler.h"
35 #include "llvm/Support/Mangler.h"
36 #include "llvm/Support/MathExtras.h"
37 #include
38 using namespace llvm;
39
40 STATISTIC(EmittedInsts, "Number of machine instrs printed");
41
42 namespace {
43 struct VISIBILITY_HIDDEN ARMAsmPrinter : public AsmPrinter {
44 ARMAsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
45 : AsmPrinter(O, TM, T), DW(O, this, T), MMI(NULL), AFI(NULL),
46 InCPMode(false) {
47 Subtarget = &TM.getSubtarget();
48 }
49
50 DwarfWriter DW;
51 MachineModuleInfo *MMI;
52
53 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
54 /// make the right decision when printing asm code for different targets.
55 const ARMSubtarget *Subtarget;
56
57 /// AFI - Keep a pointer to ARMFunctionInfo for the current
58 /// MachineFunction
59 ARMFunctionInfo *AFI;
60
61 /// We name each basic block in a Function with a unique number, so
62 /// that we can consistently refer to them later. This is cleared
63 /// at the beginning of each call to runOnMachineFunction().
64 ///
65 typedef std::map ValueMapTy;
66 ValueMapTy NumberForBB;
67
68 /// GVNonLazyPtrs - Keeps the set of GlobalValues that require
69 /// non-lazy-pointers for indirect access.
70 std::set GVNonLazyPtrs;
71
72 /// FnStubs - Keeps the set of external function GlobalAddresses that the
73 /// asm printer should generate stubs for.
74 std::set FnStubs;
75
76 /// PCRelGVs - Keeps the set of GlobalValues used in pc relative
77 /// constantpool.
78 SmallPtrSet PCRelGVs;
79
80 /// True if asm printer is printing a series of CONSTPOOL_ENTRY.
81 bool InCPMode;
82
83 virtual const char *getPassName() const {
84 return "ARM Assembly Printer";
85 }
86
87 void printOperand(const MachineInstr *MI, int opNum,
88 const char *Modifier = 0);
89 void printSOImmOperand(const MachineInstr *MI, int opNum);
90 void printSOImm2PartOperand(const MachineInstr *MI, int opNum);
91 void printSORegOperand(const MachineInstr *MI, int opNum);
92 void printAddrMode2Operand(const MachineInstr *MI, int OpNo);
93 void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNo);
94 void printAddrMode3Operand(const MachineInstr *MI, int OpNo);
95 void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNo);
96 void printAddrMode4Operand(const MachineInstr *MI, int OpNo,
97 const char *Modifier = 0);
98 void printAddrMode5Operand(const MachineInstr *MI, int OpNo,
99 const char *Modifier = 0);
100 void printAddrModePCOperand(const MachineInstr *MI, int OpNo,
101 const char *Modifier = 0);
102 void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNo);
103 void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNo,
104 unsigned Scale);
105 void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNo);
106 void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNo);
107 void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNo);
108 void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNo);
109 void printPredicateOperand(const MachineInstr *MI, int opNum);
110 void printSBitModifierOperand(const MachineInstr *MI, int opNum);
111 void printPCLabel(const MachineInstr *MI, int opNum);
112 void printRegisterList(const MachineInstr *MI, int opNum);
113 void printCPInstOperand(const MachineInstr *MI, int opNum,
114 const char *Modifier);
115 void printJTBlockOperand(const MachineInstr *MI, int opNum);
116
117 virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
118 unsigned AsmVariant, const char *ExtraCode);
119
120 void printModuleLevelGV(const GlobalVariable* GVar);
121 bool printInstruction(const MachineInstr *MI); // autogenerated.
122 void printMachineInstruction(const MachineInstr *MI);
123 bool runOnMachineFunction(MachineFunction &F);
124 bool doInitialization(Module &M);
125 bool doFinalization(Module &M);
126
127 /// getSectionForFunction - Return the section that we should emit the
128 /// specified function body into.
129 virtual std::string getSectionForFunction(const Function &F) const;
130
131 /// EmitMachineConstantPoolValue - Print a machine constantpool value to
132 /// the .s file.
133 virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
134 printDataDirective(MCPV->getType());
135
136 ARMConstantPoolValue *ACPV = static_cast(MCPV);
137 GlobalValue *GV = ACPV->getGV();
138 std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix();
139 if (!GV)
140 Name += ACPV->getSymbol();
141 if (ACPV->isNonLazyPointer()) {
142 GVNonLazyPtrs.insert(Name);
143 printSuffixedName(Name, "$non_lazy_ptr");
144 } else if (ACPV->isStub()) {
145 FnStubs.insert(Name);
146 printSuffixedName(Name, "$stub");
147 } else
148 O << Name;
149 if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
150 if (ACPV->getPCAdjustment() != 0) {
151 O << "-(" << TAI->getPrivateGlobalPrefix() << "PC"
152 << utostr(ACPV->getLabelId())
153 << "+" << (unsigned)ACPV->getPCAdjustment();
154 if (ACPV->mustAddCurrentAddress())
155 O << "-.";
156 O << ")";
157 }
158 O << "\n";
159
160 // If the constant pool value is a extern weak symbol, remember to emit
161 // the weak reference.
162 if (GV && GV->hasExternalWeakLinkage())
163 ExtWeakSymbols.insert(GV);
164 }
165
166 void getAnalysisUsage(AnalysisUsage &AU) const {
167 AsmPrinter::getAnalysisUsage(AU);
168 AU.setPreservesAll();
169 AU.addRequired();
170 }
171 };
172 } // end of anonymous namespace
173
174 #include "ARMGenAsmWriter.inc"
175
176 /// createARMCodePrinterPass - Returns a pass that prints the ARM
177 /// assembly code for a MachineFunction to the given output stream,
178 /// using the given target machine description. This should work
179 /// regardless of whether the function is in SSA form.
180 ///
181 FunctionPass *llvm::createARMCodePrinterPass(std::ostream &o,
182 ARMTargetMachine &tm) {
183 return new ARMAsmPrinter(o, tm, tm.getTargetAsmInfo());
184 }
185
186 // Substitute old hook with new one temporary
187 std::string ARMAsmPrinter::getSectionForFunction(const Function &F) const {
188 return TAI->SectionForGlobal(&F);
189 }
190
191 /// runOnMachineFunction - This uses the printInstruction()
192 /// method to print assembly for each instruction.
193 ///
194 bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
195 AFI = MF.getInfo();
196
197 SetupMachineFunction(MF);
198 O << "\n";
199
200 // NOTE: we don't print out constant pools here, they are handled as
201 // instructions.
202
203 O << "\n";
204 // Print out labels for the function.
205 const Function *F = MF.getFunction();
206 switch (F->getLinkage()) {
207 default: assert(0 && "Unknown linkage type!");
208 case Function::InternalLinkage:
209 SwitchToTextSection("\t.text", F);
210 break;
211 case Function::ExternalLinkage:
212 SwitchToTextSection("\t.text", F);
213 O << "\t.globl\t" << CurrentFnName << "\n";
214 break;
215 case Function::WeakLinkage:
216 case Function::LinkOnceLinkage:
217 if (Subtarget->isTargetDarwin()) {
218 SwitchToTextSection(
219 ".section __TEXT,__textcoal_nt,coalesced,pure_instructions", F);
220 O << "\t.globl\t" << CurrentFnName << "\n";
221 O << "\t.weak_definition\t" << CurrentFnName << "\n";
222 } else {
223 O << TAI->getWeakRefDirective() << CurrentFnName << "\n";
224 }
225 break;
226 }
227
228 printVisibility(CurrentFnName, F->getVisibility());
229
230 if (AFI->isThumbFunction()) {
231 EmitAlignment(1, F, AFI->getAlign());
232 O << "\t.code\t16\n";
233 O << "\t.thumb_func";
234 if (Subtarget->isTargetDarwin())
235 O << "\t" << CurrentFnName;
236 O << "\n";
237 InCPMode = false;
238 } else
239 EmitAlignment(2, F);
240
241 O << CurrentFnName << ":\n";
242 // Emit pre-function debug information.
243 DW.BeginFunction(&MF);
244
245 if (Subtarget->isTargetDarwin()) {
246 // If the function is empty, then we need to emit *something*. Otherwise,
247 // the function's label might be associated with something that it wasn't
248 // meant to be associated with. We emit a noop in this situation.
249 MachineFunction::iterator I = MF.begin();
250
251 if (++I == MF.end() && MF.front().empty())
252 O << "\tnop\n";
253 }
254
255 // Print out code for the function.
256 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
257 I != E; ++I) {
258 // Print a label for the basic block.
259 if (I != MF.begin()) {
260 printBasicBlockLabel(I, true, true);
261 O << '\n';
262 }
263 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
264 II != E; ++II) {
265 // Print the assembly for the instruction.
266 printMachineInstruction(II);
267 }
268 }
269
270 if (TAI->hasDotTypeDotSizeDirective())
271 O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n";
272
273 // Emit post-function debug information.
274 DW.EndFunction();
275
276 return false;
277 }
278
279 void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
280 const char *Modifier) {
281 const MachineOperand &MO = MI->getOperand(opNum);
282 switch (MO.getType()) {
283 case MachineOperand::MO_Register:
284 if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
285 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
286 else
287 assert(0 && "not implemented");
288 break;
289 case MachineOperand::MO_Immediate: {
290 if (!Modifier || strcmp(Modifier, "no_hash") != 0)
291 O << "#";
292
293 O << (int)MO.getImm();
294 break;
295 }
296 case MachineOperand::MO_MachineBasicBlock:
297 printBasicBlockLabel(MO.getMBB());
298 return;
299 case MachineOperand::MO_GlobalAddress: {
300 bool isCallOp = Modifier && !strcmp(Modifier, "call");
301 GlobalValue *GV = MO.getGlobal();
302 std::string Name = Mang->getValueName(GV);
303 bool isExt = (GV->isDeclaration() || GV->hasWeakLinkage() ||
304 GV->hasLinkOnceLinkage());
305 if (isExt && isCallOp && Subtarget->isTargetDarwin() &&
306 TM.getRelocationModel() != Reloc::Static) {
307 printSuffixedName(Name, "$stub");
308 FnStubs.insert(Name);
309 } else
310 O << Name;
311
312 if (MO.getOffset() > 0)
313 O << '+' << MO.getOffset();
314 else if (MO.getOffset() < 0)
315 O << MO.getOffset();
316
317 if (isCallOp && Subtarget->isTargetELF() &&
318 TM.getRelocationModel() == Reloc::PIC_)
319 O << "(PLT)";
320 if (GV->hasExternalWeakLinkage())
321 ExtWeakSymbols.insert(GV);
322 break;
323 }
324 case MachineOperand::MO_ExternalSymbol: {
325 bool isCallOp = Modifier && !strcmp(Modifier, "call");
326 std::string Name(TAI->getGlobalPrefix());
327 Name += MO.getSymbolName();
328 if (isCallOp && Subtarget->isTargetDarwin() &&
329 TM.getRelocationModel() != Reloc::Static) {
330 printSuffixedName(Name, "$stub");
331 FnStubs.insert(Name);
332 } else
333 O << Name;
334 if (isCallOp && Subtarget->isTargetELF() &&
335 TM.getRelocationModel() == Reloc::PIC_)
336 O << "(PLT)";
337 break;
338 }
339 case MachineOperand::MO_ConstantPoolIndex:
340 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
341 << '_' << MO.getIndex();
342 break;
343 case MachineOperand::MO_JumpTableIndex:
344 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
345 << '_' << MO.getIndex();
346 break;
347 default:
348 O << ""; abort (); break;
349 }
350 }
351
352 static void printSOImm(std::ostream &O, int64_t V, const TargetAsmInfo *TAI) {
353 assert(V < (1 << 12) && "Not a valid so_imm value!");
354 unsigned Imm = ARM_AM::getSOImmValImm(V);
355 unsigned Rot = ARM_AM::getSOImmValRot(V);
356
357 // Print low-level immediate formation info, per
358 // A5.1.3: "Data-processing operands - Immediate".
359 if (Rot) {
360 O << "#" << Imm << ", " << Rot;
361 // Pretty printed version.
362 O << ' ' << TAI->getCommentString() << ' ' << (int)ARM_AM::rotr32(Imm, Rot);
363 } else {
364 O << "#" << Imm;
365 }
366 }
367
368 /// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
369 /// immediate in bits 0-7.
370 void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) {
371 const MachineOperand &MO = MI->getOperand(OpNum);
372 assert(MO.isImmediate() && "Not a valid so_imm value!");
373 printSOImm(O, MO.getImm(), TAI);
374 }
375
376 /// printSOImm2PartOperand - SOImm is broken into two pieces using a mov
377 /// followed by a or to materialize.
378 void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) {
379 const MachineOperand &MO = MI->getOperand(OpNum);
380 assert(MO.isImmediate() && "Not a valid so_imm value!");
381 unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO.getImm());
382 unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO.getImm());
383 printSOImm(O, ARM_AM::getSOImmVal(V1), TAI);
384 O << "\n\torr";
385 printPredicateOperand(MI, 2);
386 O << " ";
387 printOperand(MI, 0);
388 O << ", ";
389 printOperand(MI, 0);
390 O << ", ";
391 printSOImm(O, ARM_AM::getSOImmVal(V2), TAI);
392 }
393
394 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
395 // "Addressing Mode 1 - Data-processing operands" forms. This includes:
396 // REG 0 0 - e.g. R5
397 // REG REG 0,SH_OPC - e.g. R5, ROR R3
398 // REG 0 IMM,SH_OPC - e.g. R5, LSL #3
399 void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) {
400 const MachineOperand &MO1 = MI->getOperand(Op);
401 const MachineOperand &MO2 = MI->getOperand(Op+1);
402 const MachineOperand &MO3 = MI->getOperand(Op+2);
403
404 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
405 O << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
406
407 // Print the shift opc.
408 O << ", "
409 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()))
410 << " ";
411
412 if (MO2.getReg()) {
413 assert(TargetRegisterInfo::isPhysicalRegister(MO2.getReg()));
414 O << TM.getRegisterInfo()->get(MO2.getReg()).AsmName;
415 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
416 } else {
417 O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
418 }
419 }
420
421 void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) {
422 const MachineOperand &MO1 = MI->getOperand(Op);
423 const MachineOperand &MO2 = MI->getOperand(Op+1);
424 const MachineOperand &MO3 = MI->getOperand(Op+2);
425
426 if (!MO1.isRegister()) { // FIXME: This is for CP entries, but isn't right.
427 printOperand(MI, Op);
428 return;
429 }
430
431 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
432
433 if (!MO2.getReg()) {
434 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
435 O << ", #"
436 << (char)ARM_AM::getAM2Op(MO3.getImm())
437 << ARM_AM::getAM2Offset(MO3.getImm());
438 O << "]";
439 return;
440 }
441
442 O << ", "
443 << (char)ARM_AM::getAM2Op(MO3.getImm())
444 << TM.getRegisterInfo()->get(MO2.getReg()).AsmName;
445
446 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
447 O << ", "
448 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
449 << " #" << ShImm;
450 O << "]";
451 }
452
453 void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op){
454 const MachineOperand &MO1 = MI->getOperand(Op);
455 const MachineOperand &MO2 = MI->getOperand(Op+1);
456
457 if (!MO1.getReg()) {
458 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
459 assert(ImmOffs && "Malformed indexed load / store!");
460 O << "#"
461 << (char)ARM_AM::getAM2Op(MO2.getImm())
462 << ImmOffs;
463 return;
464 }
465
466 O << (char)ARM_AM::getAM2Op(MO2.getImm())
467 << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
468
469 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
470 O << ", "
471 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
472 << " #" << ShImm;
473 }
474
475 void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op) {
476 const MachineOperand &MO1 = MI->getOperand(Op);
477 const MachineOperand &MO2 = MI->getOperand(Op+1);
478 const MachineOperand &MO3 = MI->getOperand(Op+2);
479
480 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
481 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
482
483 if (MO2.getReg()) {
484 O << ", "
485 << (char)ARM_AM::getAM3Op(MO3.getImm())
486 << TM.getRegisterInfo()->get(MO2.getReg()).AsmName
487 << "]";
488 return;
489 }
490
491 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
492 O << ", #"
493 << (char)ARM_AM::getAM3Op(MO3.getImm())
494 << ImmOffs;
495 O << "]";
496 }
497
498 void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op){
499 const MachineOperand &MO1 = MI->getOperand(Op);
500 const MachineOperand &MO2 = MI->getOperand(Op+1);
501
502 if (MO1.getReg()) {
503 O << (char)ARM_AM::getAM3Op(MO2.getImm())
504 << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
505 return;
506 }
507
508 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
509 assert(ImmOffs && "Malformed indexed load / store!");
510 O << "#"
511 << (char)ARM_AM::getAM3Op(MO2.getImm())
512 << ImmOffs;
513 }
514
515 void ARMAsmPrinter::printAddrMode4Operand(const MachineInstr *MI, int Op,
516 const char *Modifier) {
517 const MachineOperand &MO1 = MI->getOperand(Op);
518 const MachineOperand &MO2 = MI->getOperand(Op+1);
519 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
520 if (Modifier && strcmp(Modifier, "submode") == 0) {
521 if (MO1.getReg() == ARM::SP) {
522 bool isLDM = (MI->getOpcode() == ARM::LDM ||
523 MI->getOpcode() == ARM::LDM_RET);
524 O << ARM_AM::getAMSubModeAltStr(Mode, isLDM);
525 } else
526 O << ARM_AM::getAMSubModeStr(Mode);
527 } else {
528 printOperand(MI, Op);
529 if (ARM_AM::getAM4WBFlag(MO2.getImm()))
530 O << "!";
531 }
532 }
533
534 void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op,
535 const char *Modifier) {
536 const MachineOperand &MO1 = MI->getOperand(Op);
537 const MachineOperand &MO2 = MI->getOperand(Op+1);
538
539 if (!MO1.isRegister()) { // FIXME: This is for CP entries, but isn't right.
540 printOperand(MI, Op);
541 return;
542 }
543
544 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
545
546 if (Modifier && strcmp(Modifier, "submode") == 0) {
547 ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm());
548 if (MO1.getReg() == ARM::SP) {
549 bool isFLDM = (MI->getOpcode() == ARM::FLDMD ||
550 MI->getOpcode() == ARM::FLDMS);
551 O << ARM_AM::getAMSubModeAltStr(Mode, isFLDM);
552 } else
553 O << ARM_AM::getAMSubModeStr(Mode);
554 return;
555 } else if (Modifier && strcmp(Modifier, "base") == 0) {
556 // Used for FSTM{D|S} and LSTM{D|S} operations.
557 O << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
558 if (ARM_AM::getAM5WBFlag(MO2.getImm()))
559 O << "!";
560 return;
561 }
562
563 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
564
565 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
566 O << ", #"
567 << (char)ARM_AM::getAM5Op(MO2.getImm())
568 << ImmOffs*4;
569 }
570 O << "]";
571 }
572
573 void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op,
574 const char *Modifier) {
575 if (Modifier && strcmp(Modifier, "label") == 0) {
576 printPCLabel(MI, Op+1);
577 return;
578 }
579
580 const MachineOperand &MO1 = MI->getOperand(Op);
581 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
582 O << "[pc, +" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName << "]";
583 }
584
585 void
586 ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op) {
587 const MachineOperand &MO1 = MI->getOperand(Op);
588 const MachineOperand &MO2 = MI->getOperand(Op+1);
589 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
590 O << ", " << TM.getRegisterInfo()->get(MO2.getReg()).AsmName << "]";
591 }
592
593 void
594 ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op,
595 unsigned Scale) {
596 const MachineOperand &MO1 = MI->getOperand(Op);
597 const MachineOperand &MO2 = MI->getOperand(Op+1);
598 const MachineOperand &MO3 = MI->getOperand(Op+2);
599
600 if (!MO1.isRegister()) { // FIXME: This is for CP entries, but isn't right.
601 printOperand(MI, Op);
602 return;
603 }
604
605 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
606 if (MO3.getReg())
607 O << ", " << TM.getRegisterInfo()->get(MO3.getReg()).AsmName;
608 else if (unsigned ImmOffs = MO2.getImm()) {
609 O << ", #" << ImmOffs;
610 if (Scale > 1)
611 O << " * " << Scale;
612 }
613 O << "]";
614 }
615
616 void
617 ARMAsmPrinter::printThumbAddrModeS1Operand(const MachineInstr *MI, int Op) {
618 printThumbAddrModeRI5Operand(MI, Op, 1);
619 }
620 void
621 ARMAsmPrinter::printThumbAddrModeS2Operand(const MachineInstr *MI, int Op) {
622 printThumbAddrModeRI5Operand(MI, Op, 2);
623 }
624 void
625 ARMAsmPrinter::printThumbAddrModeS4Operand(const MachineInstr *MI, int Op) {
626 printThumbAddrModeRI5Operand(MI, Op, 4);
627 }
628
629 void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) {
630 const MachineOperand &MO1 = MI->getOperand(Op);
631 const MachineOperand &MO2 = MI->getOperand(Op+1);
632 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
633 if (unsigned ImmOffs = MO2.getImm())
634 O << ", #" << ImmOffs << " * 4";
635 O << "]";
636 }
637
638 void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int opNum) {
639 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(opNum).getImm();
640 if (CC != ARMCC::AL)
641 O << ARMCondCodeToString(CC);
642 }
643
644 void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int opNum){
645 unsigned Reg = MI->getOperand(opNum).getReg();
646 if (Reg) {
647 assert(Reg == ARM::CPSR && "Expect ARM CPSR register!");
648 O << 's';
649 }
650 }
651
652 void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int opNum) {
653 int Id = (int)MI->getOperand(opNum).getImm();
654 O << TAI->getPrivateGlobalPrefix() << "PC" << Id;
655 }
656
657 void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int opNum) {
658 O << "{";
659 for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) {
660 printOperand(MI, i);
661 if (i != e-1) O << ", ";
662 }
663 O << "}";
664 }
665
666 void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNo,
667 const char *Modifier) {
668 assert(Modifier && "This operand only works with a modifier!");
669 // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the
670 // data itself.
671 if (!strcmp(Modifier, "label")) {
672 unsigned ID = MI->getOperand(OpNo).getImm();
673 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
674 << '_' << ID << ":\n";
675 } else {
676 assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
677 unsigned CPI = MI->getOperand(OpNo).getIndex();
678
679 const MachineConstantPoolEntry &MCPE = // Chasing pointers is fun?
680 MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI];
681
682 if (MCPE.isMachineConstantPoolEntry()) {
683 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
684 ARMConstantPoolValue *ACPV =
685 static_cast(MCPE.Val.MachineCPVal);
686 if (ACPV->getPCAdjustment() != 0) {
687 const GlobalValue *GV = ACPV->getGV();
688 PCRelGVs.insert(GV);
689 }
690 } else {
691 EmitGlobalConstant(MCPE.Val.ConstVal);
692 // remember to emit the weak reference
693 if (const GlobalValue *GV = dyn_cast(MCPE.Val.ConstVal))
694 if (GV->hasExternalWeakLinkage())
695 ExtWeakSymbols.insert(GV);
696 }
697 }
698 }
699
700 void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNo) {
701 const MachineOperand &MO1 = MI->getOperand(OpNo);
702 const MachineOperand &MO2 = MI->getOperand(OpNo+1); // Unique Id
703 unsigned JTI = MO1.getIndex();
704 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
705 << '_' << JTI << '_' << MO2.getImm() << ":\n";
706
707 const char *JTEntryDirective = TAI->getJumpTableDirective();
708 if (!JTEntryDirective)
709 JTEntryDirective = TAI->getData32bitsDirective();
710
711 const MachineFunction *MF = MI->getParent()->getParent();
712 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
713 const std::vector &JT = MJTI->getJumpTables();
714 const std::vector &JTBBs = JT[JTI].MBBs;
715 bool UseSet= TAI->getSetDirective() && TM.getRelocationModel() == Reloc::PIC_;
716 std::set JTSets;
717 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
718 MachineBasicBlock *MBB = JTBBs[i];
719 if (UseSet && JTSets.insert(MBB).second)
720 printPICJumpTableSetLabel(JTI, MO2.getImm(), MBB);
721
722 O << JTEntryDirective << ' ';
723 if (UseSet)
724 O << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
725 << '_' << JTI << '_' << MO2.getImm()
726 << "_set_" << MBB->getNumber();
727 else if (TM.getRelocationModel() == Reloc::PIC_) {
728 printBasicBlockLabel(MBB, false, false, false);
729 // If the arch uses custom Jump Table directives, don't calc relative to JT
730 if (!TAI->getJumpTableDirective())
731 O << '-' << TAI->getPrivateGlobalPrefix() << "JTI"
732 << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm();
733 } else
734 printBasicBlockLabel(MBB, false, false, false);
735 if (i != e-1)
736 O << '\n';
737 }
738 }
739
740
741 bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
742 unsigned AsmVariant, const char *ExtraCode){
743 // Does this asm operand have a single letter operand modifier?
744 if (ExtraCode && ExtraCode[0]) {
745 if (ExtraCode[1] != 0) return true; // Unknown modifier.
746
747 switch (ExtraCode[0]) {
748 default: return true; // Unknown modifier.
749 case 'c': // Don't print "$" before a global var name or constant.
750 case 'P': // Print a VFP double precision register.
751 printOperand(MI, OpNo);
752 return false;
753 case 'Q':
754 if (TM.getTargetData()->isLittleEndian())
755 break;
756 // Fallthrough
757 case 'R':
758 if (TM.getTargetData()->isBigEndian())
759 break;
760 // Fallthrough
761 case 'H': // Write second word of DI / DF reference.
762 // Verify that this operand has two consecutive registers.
763 if (!MI->getOperand(OpNo).isRegister() ||
764 OpNo+1 == MI->getNumOperands() ||
765 !MI->getOperand(OpNo+1).isRegister())
766 return true;
767 ++OpNo; // Return the high-part.
768 }
769 }
770
771 printOperand(MI, OpNo);
772 return false;
773 }
774
775 void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
776 ++EmittedInsts;
777
778 int Opc = MI->getOpcode();
779 switch (Opc) {
780 case ARM::CONSTPOOL_ENTRY:
781 if (!InCPMode && AFI->isThumbFunction()) {
782 EmitAlignment(2);
783 InCPMode = true;
784 }
785 break;
786 default: {
787 if (InCPMode && AFI->isThumbFunction())
788 InCPMode = false;
789 switch (Opc) {
790 case ARM::PICADD:
791 case ARM::PICLD:
792 case ARM::PICLDZH:
793 case ARM::PICLDZB:
794 case ARM::PICLDH:
795 case ARM::PICLDB:
796 case ARM::PICLDSH:
797 case ARM::PICLDSB:
798 case ARM::PICSTR:
799 case ARM::PICSTRH:
800 case ARM::PICSTRB:
801 case ARM::tPICADD:
802 break;
803 default:
804 break;
805 }
806 }}
807
808 // Call the autogenerated instruction printer routines.
809 printInstruction(MI);
810 }
811
812 bool ARMAsmPrinter::doInitialization(Module &M) {
813 // Emit initial debug information.
814 DW.BeginModule(&M);
815
816 bool Result = AsmPrinter::doInitialization(M);
817
818 // AsmPrinter::doInitialization should have done this analysis.
819 MMI = getAnalysisToUpdate();
820 assert(MMI);
821 DW.SetModuleInfo(MMI);
822
823 // Darwin wants symbols to be quoted if they have complex names.
824 if (Subtarget->isTargetDarwin())
825 Mang->setUseQuotes(true);
826
827 return Result;
828 }
829
830 /// PrintUnmangledNameSafely - Print out the printable characters in the name.
831 /// Don't print things like \n or \0.
832 static void PrintUnmangledNameSafely(const Value *V, std::ostream &OS) {
833 for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
834 Name != E; ++Name)
835 if (isprint(*Name))
836 OS << *Name;
837 }
838
839 void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
840 const TargetData *TD = TM.getTargetData();
841
842 if (!GVar->hasInitializer()) // External global require no code
843 return;
844
845 // Check to see if this is a special global used by LLVM, if so, emit it.
846
847 if (EmitSpecialLLVMGlobal(GVar)) {
848 if (Subtarget->isTargetDarwin() &&
849 TM.getRelocationModel() == Reloc::Static) {
850 if (GVar->getName() == "llvm.global_ctors")
851 O << ".reference .constructors_used\n";
852 else if (GVar->getName() == "llvm.global_dtors")
853 O << ".reference .destructors_used\n";
854 }
855 return;
856 }
857
858 std::string SectionName = TAI->SectionForGlobal(GVar);
859 std::string name = Mang->getValueName(GVar);
860 Constant *C = GVar->getInitializer();
861 const Type *Type = C->getType();
862 unsigned Size = TD->getABITypeSize(Type);
863 unsigned Align = TD->getPreferredAlignmentLog(GVar);
864
865 printVisibility(name, GVar->getVisibility());
866
867 if (Subtarget->isTargetELF())
868 O << "\t.type " << name << ",%object\n";
869
870 SwitchToDataSection(SectionName.c_str());
871
872 if (C->isNullValue() && !GVar->hasSection() && !GVar->isThreadLocal()) {
873 // FIXME: This seems to be pretty darwin-specific
874
875 if (GVar->hasExternalLinkage()) {
876 if (const char *Directive = TAI->getZeroFillDirective()) {
877 O << "\t.globl\t" << name << "\n";
878 O << Directive << "__DATA, __common, " << name << ", "
879 << Size << ", " << Align << "\n";
880 return;
881 }
882 }
883
884 if (GVar->hasInternalLinkage() || GVar->isWeakForLinker()) {
885 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
886
887 if (TAI->getLCOMMDirective() != NULL) {
888 if (PCRelGVs.count(GVar) || GVar->hasInternalLinkage()) {
889 O << TAI->getLCOMMDirective() << name << "," << Size;
890 if (Subtarget->isTargetDarwin())
891 O << "," << Align;
892 } else
893 O << TAI->getCOMMDirective() << name << "," << Size;
894 } else {
895 if (GVar->hasInternalLinkage())
896 O << "\t.local\t" << name << "\n";
897 O << TAI->getCOMMDirective() << name << "," << Size;
898 if (TAI->getCOMMDirectiveTakesAlignment())
899 O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
900 }
901 O << "\t\t" << TAI->getCommentString() << " ";
902 PrintUnmangledNameSafely(GVar, O);
903 O << "\n";
904 return;
905 }
906 }
907
908 switch (GVar->getLinkage()) {
909 case GlobalValue::LinkOnceLinkage:
910 case GlobalValue::WeakLinkage:
911 if (Subtarget->isTargetDarwin()) {
912 O << "\t.globl " << name << "\n"
913 << "\t.weak_definition " << name << "\n";
914 } else {
915 O << "\t.weak " << name << "\n";
916 }
917 break;
918 case GlobalValue::AppendingLinkage:
919 // FIXME: appending linkage variables should go into a section of
920 // their name or something. For now, just emit them as external.
921 case GlobalValue::ExternalLinkage:
922 O << "\t.globl " << name << "\n";
923 // FALL THROUGH
924 case GlobalValue::InternalLinkage:
925 break;
926 default:
927 assert(0 && "Unknown linkage type!");
928 break;
929 }
930
931 EmitAlignment(Align, GVar);
932 O << name << ":\t\t\t\t" << TAI->getCommentString() << " ";
933 PrintUnmangledNameSafely(GVar, O);
934 O << "\n";
935 if (TAI->hasDotTypeDotSizeDirective())
936 O << "\t.size " << name << ", " << Size << "\n";
937
938 // If the initializer is a extern weak symbol, remember to emit the weak
939 // reference!
940 if (const GlobalValue *GV = dyn_cast(C))
941 if (GV->hasExternalWeakLinkage())
942 ExtWeakSymbols.insert(GV);
943
944 EmitGlobalConstant(C);
945 O << '\n';
946 }
947
948
949 bool ARMAsmPrinter::doFinalization(Module &M) {
950 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
951 I != E; ++I)
952 printModuleLevelGV(I);
953
954 if (Subtarget->isTargetDarwin()) {
955 SwitchToDataSection("");
956
957 // Output stubs for dynamically-linked functions
958 unsigned j = 1;
959 for (std::set::iterator i = FnStubs.begin(), e = FnStubs.end();
960 i != e; ++i, ++j) {
961 if (TM.getRelocationModel() == Reloc::PIC_)
962 SwitchToTextSection(".section __TEXT,__picsymbolstub4,symbol_stubs,"
963 "none,16", 0);
964 else
965 SwitchToTextSection(".section __TEXT,__symbol_stub4,symbol_stubs,"
966 "none,12", 0);
967
968 EmitAlignment(2);
969 O << "\t.code\t32\n";
970
971 std::string p = *i;
972 printSuffixedName(p, "$stub");
973 O << ":\n";
974 O << "\t.indirect_symbol " << *i << "\n";
975 O << "\tldr ip, ";
976 printSuffixedName(p, "$slp");
977 O << "\n";
978 if (TM.getRelocationModel() == Reloc::PIC_) {
979 printSuffixedName(p, "$scv");
980 O << ":\n";
981 O << "\tadd ip, pc, ip\n";
982 }
983 O << "\tldr pc, [ip, #0]\n";
984 printSuffixedName(p, "$slp");
985 O << ":\n";
986 O << "\t.long\t";
987 printSuffixedName(p, "$lazy_ptr");
988 if (TM.getRelocationModel() == Reloc::PIC_) {
989 O << "-(";
990 printSuffixedName(p, "$scv");
991 O << "+8)\n";
992 } else
993 O << "\n";
994 SwitchToDataSection(".lazy_symbol_pointer", 0);
995 printSuffixedName(p, "$lazy_ptr");
996 O << ":\n";
997 O << "\t.indirect_symbol " << *i << "\n";
998 O << "\t.long\tdyld_stub_binding_helper\n";
999 }
1000 O << "\n";
1001
1002 // Output non-lazy-pointers for external and common global variables.
1003 if (!GVNonLazyPtrs.empty())
1004 SwitchToDataSection(".non_lazy_symbol_pointer", 0);
1005 for (std::set::iterator i = GVNonLazyPtrs.begin(),
1006 e = GVNonLazyPtrs.end(); i != e; ++i) {
1007 std::string p = *i;
1008 printSuffixedName(p, "$non_lazy_ptr");
1009 O << ":\n";
1010 O << "\t.indirect_symbol " << *i << "\n";
1011 O << "\t.long\t0\n";
1012 }
1013
1014 // Emit initial debug information.
1015 DW.EndModule();
1016
1017 // Funny Darwin hack: This flag tells the linker that no global symbols
1018 // contain code that falls through to other global symbols (e.g. the obvious
1019 // implementation of multiple entry points). If this doesn't occur, the
1020 // linker can safely perform dead code stripping. Since LLVM never
1021 // generates code that does this, it is always safe to set.
1022 O << "\t.subsections_via_symbols\n";
1023 } else {
1024 // Emit final debug information for ELF.
1025 DW.EndModule();
1026 }
1027
1028 return AsmPrinter::doFinalization(M);
1029 }
2929 // Register the target.
3030 static RegisterTarget X("arm", " ARM");
3131 static RegisterTarget Y("thumb", " Thumb");
32
33 // No assembler printer by default
34 ARMTargetMachine::AsmPrinterCtorFn ARMTargetMachine::AsmPrinterCtor = 0;
3235
3336 /// ThumbTargetMachine - Create an Thumb architecture model.
3437 ///
141144 bool ARMTargetMachine::addAssemblyEmitter(PassManagerBase &PM, bool Fast,
142145 std::ostream &Out) {
143146 // Output assembly language.
144 PM.add(createARMCodePrinterPass(Out, *this));
147 assert(AsmPrinterCtor && "AsmPrinter was not linked in");
148 if (AsmPrinterCtor)
149 PM.add(AsmPrinterCtor(Out, *this));
150
145151 return false;
146152 }
147153
153159
154160 // Machine code emitter pass for ARM.
155161 PM.add(createARMCodeEmitterPass(*this, MCE));
156 if (DumpAsm)
157 PM.add(createARMCodePrinterPass(*cerr.stream(), *this));
162 if (DumpAsm) {
163 assert(AsmPrinterCtor && "AsmPrinter was not linked in");
164 if (AsmPrinterCtor)
165 PM.add(AsmPrinterCtor(*cerr.stream(), *this));
166 }
167
158168 return false;
159169 }
160170
162172 bool DumpAsm, MachineCodeEmitter &MCE) {
163173 // Machine code emitter pass for ARM.
164174 PM.add(createARMCodeEmitterPass(*this, MCE));
165 if (DumpAsm)
166 PM.add(createARMCodePrinterPass(*cerr.stream(), *this));
175 if (DumpAsm) {
176 assert(AsmPrinterCtor && "AsmPrinter was not linked in");
177 if (AsmPrinterCtor)
178 PM.add(AsmPrinterCtor(*cerr.stream(), *this));
179 }
180
167181 return false;
168182 }
3434 ARMJITInfo JITInfo;
3535 ARMTargetLowering TLInfo;
3636
37 protected:
38 // To avoid having target depend on the asmprinter stuff libraries, asmprinter
39 // set this functions to ctor pointer at startup time if they are linked in.
40 typedef FunctionPass *(*AsmPrinterCtorFn)(std::ostream &o,
41 ARMTargetMachine &tm);
42 static AsmPrinterCtorFn AsmPrinterCtor;
43
3744 public:
3845 ARMTargetMachine(const Module &M, const std::string &FS, bool isThumb = false);
3946
4552 }
4653 virtual const TargetData *getTargetData() const { return &DataLayout; }
4754 virtual const ARMSubtarget *getSubtargetImpl() const { return &Subtarget; }
48 virtual ARMTargetLowering *getTargetLowering() const {
49 return const_cast(&TLInfo);
55 virtual ARMTargetLowering *getTargetLowering() const {
56 return const_cast(&TLInfo);
5057 }
58
59 static void registerAsmPrinter(AsmPrinterCtorFn F) {
60 AsmPrinterCtor = F;
61 }
62
5163 static unsigned getModuleMatchQuality(const Module &M);
5264 static unsigned getJITMatchQuality();
5365
5466 virtual const TargetAsmInfo *createTargetAsmInfo() const;
55
67
5668 // Pass Pipeline Configuration
5769 virtual bool addInstSelector(PassManagerBase &PM, bool Fast);
5870 virtual bool addPreEmitPass(PassManagerBase &PM, bool Fast);
59 virtual bool addAssemblyEmitter(PassManagerBase &PM, bool Fast,
71 virtual bool addAssemblyEmitter(PassManagerBase &PM, bool Fast,
6072 std::ostream &Out);
6173 virtual bool addCodeEmitter(PassManagerBase &PM, bool Fast,
6274 bool DumpAsm, MachineCodeEmitter &MCE);
0 //===-- ARMAsmPrinter.cpp - ARM LLVM assembly writer ----------------------===//
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 "ARMTargetMachine.h"
17 #include "ARMAddressingModes.h"
18 #include "ARMConstantPoolValue.h"
19 #include "ARMMachineFunctionInfo.h"
20 #include "llvm/Constants.h"
21 #include "llvm/Module.h"
22 #include "llvm/CodeGen/AsmPrinter.h"
23 #include "llvm/CodeGen/DwarfWriter.h"
24 #include "llvm/CodeGen/MachineModuleInfo.h"
25 #include "llvm/CodeGen/MachineFunctionPass.h"
26 #include "llvm/CodeGen/MachineJumpTableInfo.h"
27 #include "llvm/Target/TargetAsmInfo.h"
28 #include "llvm/Target/TargetData.h"
29 #include "llvm/Target/TargetMachine.h"
30 #include "llvm/Target/TargetOptions.h"
31 #include "llvm/ADT/SmallPtrSet.h"
32 #include "llvm/ADT/Statistic.h"
33 #include "llvm/ADT/StringExtras.h"
34 #include "llvm/Support/Compiler.h"
35 #include "llvm/Support/Mangler.h"
36 #include "llvm/Support/MathExtras.h"
37 #include
38 using namespace llvm;
39
40 STATISTIC(EmittedInsts, "Number of machine instrs printed");
41
42 namespace {
43 struct VISIBILITY_HIDDEN ARMAsmPrinter : public AsmPrinter {
44 ARMAsmPrinter(std::ostream &O, TargetMachine &TM, const TargetAsmInfo *T)
45 : AsmPrinter(O, TM, T), DW(O, this, T), MMI(NULL), AFI(NULL),
46 InCPMode(false) {
47 Subtarget = &TM.getSubtarget();
48 }
49
50 DwarfWriter DW;
51 MachineModuleInfo *MMI;
52
53 /// Subtarget - Keep a pointer to the ARMSubtarget around so that we can
54 /// make the right decision when printing asm code for different targets.
55 const ARMSubtarget *Subtarget;
56
57 /// AFI - Keep a pointer to ARMFunctionInfo for the current
58 /// MachineFunction
59 ARMFunctionInfo *AFI;
60
61 /// We name each basic block in a Function with a unique number, so
62 /// that we can consistently refer to them later. This is cleared
63 /// at the beginning of each call to runOnMachineFunction().
64 ///
65 typedef std::map ValueMapTy;
66 ValueMapTy NumberForBB;
67
68 /// GVNonLazyPtrs - Keeps the set of GlobalValues that require
69 /// non-lazy-pointers for indirect access.
70 std::set GVNonLazyPtrs;
71
72 /// FnStubs - Keeps the set of external function GlobalAddresses that the
73 /// asm printer should generate stubs for.
74 std::set FnStubs;
75
76 /// PCRelGVs - Keeps the set of GlobalValues used in pc relative
77 /// constantpool.
78 SmallPtrSet PCRelGVs;
79
80 /// True if asm printer is printing a series of CONSTPOOL_ENTRY.
81 bool InCPMode;
82
83 virtual const char *getPassName() const {
84 return "ARM Assembly Printer";
85 }
86
87 void printOperand(const MachineInstr *MI, int opNum,
88 const char *Modifier = 0);
89 void printSOImmOperand(const MachineInstr *MI, int opNum);
90 void printSOImm2PartOperand(const MachineInstr *MI, int opNum);
91 void printSORegOperand(const MachineInstr *MI, int opNum);
92 void printAddrMode2Operand(const MachineInstr *MI, int OpNo);
93 void printAddrMode2OffsetOperand(const MachineInstr *MI, int OpNo);
94 void printAddrMode3Operand(const MachineInstr *MI, int OpNo);
95 void printAddrMode3OffsetOperand(const MachineInstr *MI, int OpNo);
96 void printAddrMode4Operand(const MachineInstr *MI, int OpNo,
97 const char *Modifier = 0);
98 void printAddrMode5Operand(const MachineInstr *MI, int OpNo,
99 const char *Modifier = 0);
100 void printAddrModePCOperand(const MachineInstr *MI, int OpNo,
101 const char *Modifier = 0);
102 void printThumbAddrModeRROperand(const MachineInstr *MI, int OpNo);
103 void printThumbAddrModeRI5Operand(const MachineInstr *MI, int OpNo,
104 unsigned Scale);
105 void printThumbAddrModeS1Operand(const MachineInstr *MI, int OpNo);
106 void printThumbAddrModeS2Operand(const MachineInstr *MI, int OpNo);
107 void printThumbAddrModeS4Operand(const MachineInstr *MI, int OpNo);
108 void printThumbAddrModeSPOperand(const MachineInstr *MI, int OpNo);
109 void printPredicateOperand(const MachineInstr *MI, int opNum);
110 void printSBitModifierOperand(const MachineInstr *MI, int opNum);
111 void printPCLabel(const MachineInstr *MI, int opNum);
112 void printRegisterList(const MachineInstr *MI, int opNum);
113 void printCPInstOperand(const MachineInstr *MI, int opNum,
114 const char *Modifier);
115 void printJTBlockOperand(const MachineInstr *MI, int opNum);
116
117 virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
118 unsigned AsmVariant, const char *ExtraCode);
119
120 void printModuleLevelGV(const GlobalVariable* GVar);
121 bool printInstruction(const MachineInstr *MI); // autogenerated.
122 void printMachineInstruction(const MachineInstr *MI);
123 bool runOnMachineFunction(MachineFunction &F);
124 bool doInitialization(Module &M);
125 bool doFinalization(Module &M);
126
127 /// getSectionForFunction - Return the section that we should emit the
128 /// specified function body into.
129 virtual std::string getSectionForFunction(const Function &F) const;
130
131 /// EmitMachineConstantPoolValue - Print a machine constantpool value to
132 /// the .s file.
133 virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) {
134 printDataDirective(MCPV->getType());
135
136 ARMConstantPoolValue *ACPV = static_cast(MCPV);
137 GlobalValue *GV = ACPV->getGV();
138 std::string Name = GV ? Mang->getValueName(GV) : TAI->getGlobalPrefix();
139 if (!GV)
140 Name += ACPV->getSymbol();
141 if (ACPV->isNonLazyPointer()) {
142 GVNonLazyPtrs.insert(Name);
143 printSuffixedName(Name, "$non_lazy_ptr");
144 } else if (ACPV->isStub()) {
145 FnStubs.insert(Name);
146 printSuffixedName(Name, "$stub");
147 } else
148 O << Name;
149 if (ACPV->hasModifier()) O << "(" << ACPV->getModifier() << ")";
150 if (ACPV->getPCAdjustment() != 0) {
151 O << "-(" << TAI->getPrivateGlobalPrefix() << "PC"
152 << utostr(ACPV->getLabelId())
153 << "+" << (unsigned)ACPV->getPCAdjustment();
154 if (ACPV->mustAddCurrentAddress())
155 O << "-.";
156 O << ")";
157 }
158 O << "\n";
159
160 // If the constant pool value is a extern weak symbol, remember to emit
161 // the weak reference.
162 if (GV && GV->hasExternalWeakLinkage())
163 ExtWeakSymbols.insert(GV);
164 }
165
166 void getAnalysisUsage(AnalysisUsage &AU) const {
167 AsmPrinter::getAnalysisUsage(AU);
168 AU.setPreservesAll();
169 AU.addRequired();
170 }
171 };
172 } // end of anonymous namespace
173
174 #include "ARMGenAsmWriter.inc"
175
176 // Substitute old hook with new one temporary
177 std::string ARMAsmPrinter::getSectionForFunction(const Function &F) const {
178 return TAI->SectionForGlobal(&F);
179 }
180
181 /// runOnMachineFunction - This uses the printInstruction()
182 /// method to print assembly for each instruction.
183 ///
184 bool ARMAsmPrinter::runOnMachineFunction(MachineFunction &MF) {
185 AFI = MF.getInfo();
186
187 SetupMachineFunction(MF);
188 O << "\n";
189
190 // NOTE: we don't print out constant pools here, they are handled as
191 // instructions.
192
193 O << "\n";
194 // Print out labels for the function.
195 const Function *F = MF.getFunction();
196 switch (F->getLinkage()) {
197 default: assert(0 && "Unknown linkage type!");
198 case Function::InternalLinkage:
199 SwitchToTextSection("\t.text", F);
200 break;
201 case Function::ExternalLinkage:
202 SwitchToTextSection("\t.text", F);
203 O << "\t.globl\t" << CurrentFnName << "\n";
204 break;
205 case Function::WeakLinkage:
206 case Function::LinkOnceLinkage:
207 if (Subtarget->isTargetDarwin()) {
208 SwitchToTextSection(
209 ".section __TEXT,__textcoal_nt,coalesced,pure_instructions", F);
210 O << "\t.globl\t" << CurrentFnName << "\n";
211 O << "\t.weak_definition\t" << CurrentFnName << "\n";
212 } else {
213 O << TAI->getWeakRefDirective() << CurrentFnName << "\n";
214 }
215 break;
216 }
217
218 printVisibility(CurrentFnName, F->getVisibility());
219
220 if (AFI->isThumbFunction()) {
221 EmitAlignment(1, F, AFI->getAlign());
222 O << "\t.code\t16\n";
223 O << "\t.thumb_func";
224 if (Subtarget->isTargetDarwin())
225 O << "\t" << CurrentFnName;
226 O << "\n";
227 InCPMode = false;
228 } else
229 EmitAlignment(2, F);
230
231 O << CurrentFnName << ":\n";
232 // Emit pre-function debug information.
233 DW.BeginFunction(&MF);
234
235 if (Subtarget->isTargetDarwin()) {
236 // If the function is empty, then we need to emit *something*. Otherwise,
237 // the function's label might be associated with something that it wasn't
238 // meant to be associated with. We emit a noop in this situation.
239 MachineFunction::iterator I = MF.begin();
240
241 if (++I == MF.end() && MF.front().empty())
242 O << "\tnop\n";
243 }
244
245 // Print out code for the function.
246 for (MachineFunction::const_iterator I = MF.begin(), E = MF.end();
247 I != E; ++I) {
248 // Print a label for the basic block.
249 if (I != MF.begin()) {
250 printBasicBlockLabel(I, true, true);
251 O << '\n';
252 }
253 for (MachineBasicBlock::const_iterator II = I->begin(), E = I->end();
254 II != E; ++II) {
255 // Print the assembly for the instruction.
256 printMachineInstruction(II);
257 }
258 }
259
260 if (TAI->hasDotTypeDotSizeDirective())
261 O << "\t.size " << CurrentFnName << ", .-" << CurrentFnName << "\n";
262
263 // Emit post-function debug information.
264 DW.EndFunction();
265
266 return false;
267 }
268
269 void ARMAsmPrinter::printOperand(const MachineInstr *MI, int opNum,
270 const char *Modifier) {
271 const MachineOperand &MO = MI->getOperand(opNum);
272 switch (MO.getType()) {
273 case MachineOperand::MO_Register:
274 if (TargetRegisterInfo::isPhysicalRegister(MO.getReg()))
275 O << TM.getRegisterInfo()->get(MO.getReg()).AsmName;
276 else
277 assert(0 && "not implemented");
278 break;
279 case MachineOperand::MO_Immediate: {
280 if (!Modifier || strcmp(Modifier, "no_hash") != 0)
281 O << "#";
282
283 O << (int)MO.getImm();
284 break;
285 }
286 case MachineOperand::MO_MachineBasicBlock:
287 printBasicBlockLabel(MO.getMBB());
288 return;
289 case MachineOperand::MO_GlobalAddress: {
290 bool isCallOp = Modifier && !strcmp(Modifier, "call");
291 GlobalValue *GV = MO.getGlobal();
292 std::string Name = Mang->getValueName(GV);
293 bool isExt = (GV->isDeclaration() || GV->hasWeakLinkage() ||
294 GV->hasLinkOnceLinkage());
295 if (isExt && isCallOp && Subtarget->isTargetDarwin() &&
296 TM.getRelocationModel() != Reloc::Static) {
297 printSuffixedName(Name, "$stub");
298 FnStubs.insert(Name);
299 } else
300 O << Name;
301
302 if (MO.getOffset() > 0)
303 O << '+' << MO.getOffset();
304 else if (MO.getOffset() < 0)
305 O << MO.getOffset();
306
307 if (isCallOp && Subtarget->isTargetELF() &&
308 TM.getRelocationModel() == Reloc::PIC_)
309 O << "(PLT)";
310 if (GV->hasExternalWeakLinkage())
311 ExtWeakSymbols.insert(GV);
312 break;
313 }
314 case MachineOperand::MO_ExternalSymbol: {
315 bool isCallOp = Modifier && !strcmp(Modifier, "call");
316 std::string Name(TAI->getGlobalPrefix());
317 Name += MO.getSymbolName();
318 if (isCallOp && Subtarget->isTargetDarwin() &&
319 TM.getRelocationModel() != Reloc::Static) {
320 printSuffixedName(Name, "$stub");
321 FnStubs.insert(Name);
322 } else
323 O << Name;
324 if (isCallOp && Subtarget->isTargetELF() &&
325 TM.getRelocationModel() == Reloc::PIC_)
326 O << "(PLT)";
327 break;
328 }
329 case MachineOperand::MO_ConstantPoolIndex:
330 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
331 << '_' << MO.getIndex();
332 break;
333 case MachineOperand::MO_JumpTableIndex:
334 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
335 << '_' << MO.getIndex();
336 break;
337 default:
338 O << ""; abort (); break;
339 }
340 }
341
342 static void printSOImm(std::ostream &O, int64_t V, const TargetAsmInfo *TAI) {
343 assert(V < (1 << 12) && "Not a valid so_imm value!");
344 unsigned Imm = ARM_AM::getSOImmValImm(V);
345 unsigned Rot = ARM_AM::getSOImmValRot(V);
346
347 // Print low-level immediate formation info, per
348 // A5.1.3: "Data-processing operands - Immediate".
349 if (Rot) {
350 O << "#" << Imm << ", " << Rot;
351 // Pretty printed version.
352 O << ' ' << TAI->getCommentString() << ' ' << (int)ARM_AM::rotr32(Imm, Rot);
353 } else {
354 O << "#" << Imm;
355 }
356 }
357
358 /// printSOImmOperand - SOImm is 4-bit rotate amount in bits 8-11 with 8-bit
359 /// immediate in bits 0-7.
360 void ARMAsmPrinter::printSOImmOperand(const MachineInstr *MI, int OpNum) {
361 const MachineOperand &MO = MI->getOperand(OpNum);
362 assert(MO.isImmediate() && "Not a valid so_imm value!");
363 printSOImm(O, MO.getImm(), TAI);
364 }
365
366 /// printSOImm2PartOperand - SOImm is broken into two pieces using a mov
367 /// followed by a or to materialize.
368 void ARMAsmPrinter::printSOImm2PartOperand(const MachineInstr *MI, int OpNum) {
369 const MachineOperand &MO = MI->getOperand(OpNum);
370 assert(MO.isImmediate() && "Not a valid so_imm value!");
371 unsigned V1 = ARM_AM::getSOImmTwoPartFirst(MO.getImm());
372 unsigned V2 = ARM_AM::getSOImmTwoPartSecond(MO.getImm());
373 printSOImm(O, ARM_AM::getSOImmVal(V1), TAI);
374 O << "\n\torr";
375 printPredicateOperand(MI, 2);
376 O << " ";
377 printOperand(MI, 0);
378 O << ", ";
379 printOperand(MI, 0);
380 O << ", ";
381 printSOImm(O, ARM_AM::getSOImmVal(V2), TAI);
382 }
383
384 // so_reg is a 4-operand unit corresponding to register forms of the A5.1
385 // "Addressing Mode 1 - Data-processing operands" forms. This includes:
386 // REG 0 0 - e.g. R5
387 // REG REG 0,SH_OPC - e.g. R5, ROR R3
388 // REG 0 IMM,SH_OPC - e.g. R5, LSL #3
389 void ARMAsmPrinter::printSORegOperand(const MachineInstr *MI, int Op) {
390 const MachineOperand &MO1 = MI->getOperand(Op);
391 const MachineOperand &MO2 = MI->getOperand(Op+1);
392 const MachineOperand &MO3 = MI->getOperand(Op+2);
393
394 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
395 O << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
396
397 // Print the shift opc.
398 O << ", "
399 << ARM_AM::getShiftOpcStr(ARM_AM::getSORegShOp(MO3.getImm()))
400 << " ";
401
402 if (MO2.getReg()) {
403 assert(TargetRegisterInfo::isPhysicalRegister(MO2.getReg()));
404 O << TM.getRegisterInfo()->get(MO2.getReg()).AsmName;
405 assert(ARM_AM::getSORegOffset(MO3.getImm()) == 0);
406 } else {
407 O << "#" << ARM_AM::getSORegOffset(MO3.getImm());
408 }
409 }
410
411 void ARMAsmPrinter::printAddrMode2Operand(const MachineInstr *MI, int Op) {
412 const MachineOperand &MO1 = MI->getOperand(Op);
413 const MachineOperand &MO2 = MI->getOperand(Op+1);
414 const MachineOperand &MO3 = MI->getOperand(Op+2);
415
416 if (!MO1.isRegister()) { // FIXME: This is for CP entries, but isn't right.
417 printOperand(MI, Op);
418 return;
419 }
420
421 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
422
423 if (!MO2.getReg()) {
424 if (ARM_AM::getAM2Offset(MO3.getImm())) // Don't print +0.
425 O << ", #"
426 << (char)ARM_AM::getAM2Op(MO3.getImm())
427 << ARM_AM::getAM2Offset(MO3.getImm());
428 O << "]";
429 return;
430 }
431
432 O << ", "
433 << (char)ARM_AM::getAM2Op(MO3.getImm())
434 << TM.getRegisterInfo()->get(MO2.getReg()).AsmName;
435
436 if (unsigned ShImm = ARM_AM::getAM2Offset(MO3.getImm()))
437 O << ", "
438 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO3.getImm()))
439 << " #" << ShImm;
440 O << "]";
441 }
442
443 void ARMAsmPrinter::printAddrMode2OffsetOperand(const MachineInstr *MI, int Op){
444 const MachineOperand &MO1 = MI->getOperand(Op);
445 const MachineOperand &MO2 = MI->getOperand(Op+1);
446
447 if (!MO1.getReg()) {
448 unsigned ImmOffs = ARM_AM::getAM2Offset(MO2.getImm());
449 assert(ImmOffs && "Malformed indexed load / store!");
450 O << "#"
451 << (char)ARM_AM::getAM2Op(MO2.getImm())
452 << ImmOffs;
453 return;
454 }
455
456 O << (char)ARM_AM::getAM2Op(MO2.getImm())
457 << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
458
459 if (unsigned ShImm = ARM_AM::getAM2Offset(MO2.getImm()))
460 O << ", "
461 << ARM_AM::getShiftOpcStr(ARM_AM::getAM2ShiftOpc(MO2.getImm()))
462 << " #" << ShImm;
463 }
464
465 void ARMAsmPrinter::printAddrMode3Operand(const MachineInstr *MI, int Op) {
466 const MachineOperand &MO1 = MI->getOperand(Op);
467 const MachineOperand &MO2 = MI->getOperand(Op+1);
468 const MachineOperand &MO3 = MI->getOperand(Op+2);
469
470 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
471 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
472
473 if (MO2.getReg()) {
474 O << ", "
475 << (char)ARM_AM::getAM3Op(MO3.getImm())
476 << TM.getRegisterInfo()->get(MO2.getReg()).AsmName
477 << "]";
478 return;
479 }
480
481 if (unsigned ImmOffs = ARM_AM::getAM3Offset(MO3.getImm()))
482 O << ", #"
483 << (char)ARM_AM::getAM3Op(MO3.getImm())
484 << ImmOffs;
485 O << "]";
486 }
487
488 void ARMAsmPrinter::printAddrMode3OffsetOperand(const MachineInstr *MI, int Op){
489 const MachineOperand &MO1 = MI->getOperand(Op);
490 const MachineOperand &MO2 = MI->getOperand(Op+1);
491
492 if (MO1.getReg()) {
493 O << (char)ARM_AM::getAM3Op(MO2.getImm())
494 << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
495 return;
496 }
497
498 unsigned ImmOffs = ARM_AM::getAM3Offset(MO2.getImm());
499 assert(ImmOffs && "Malformed indexed load / store!");
500 O << "#"
501 << (char)ARM_AM::getAM3Op(MO2.getImm())
502 << ImmOffs;
503 }
504
505 void ARMAsmPrinter::printAddrMode4Operand(const MachineInstr *MI, int Op,
506 const char *Modifier) {
507 const MachineOperand &MO1 = MI->getOperand(Op);
508 const MachineOperand &MO2 = MI->getOperand(Op+1);
509 ARM_AM::AMSubMode Mode = ARM_AM::getAM4SubMode(MO2.getImm());
510 if (Modifier && strcmp(Modifier, "submode") == 0) {
511 if (MO1.getReg() == ARM::SP) {
512 bool isLDM = (MI->getOpcode() == ARM::LDM ||
513 MI->getOpcode() == ARM::LDM_RET);
514 O << ARM_AM::getAMSubModeAltStr(Mode, isLDM);
515 } else
516 O << ARM_AM::getAMSubModeStr(Mode);
517 } else {
518 printOperand(MI, Op);
519 if (ARM_AM::getAM4WBFlag(MO2.getImm()))
520 O << "!";
521 }
522 }
523
524 void ARMAsmPrinter::printAddrMode5Operand(const MachineInstr *MI, int Op,
525 const char *Modifier) {
526 const MachineOperand &MO1 = MI->getOperand(Op);
527 const MachineOperand &MO2 = MI->getOperand(Op+1);
528
529 if (!MO1.isRegister()) { // FIXME: This is for CP entries, but isn't right.
530 printOperand(MI, Op);
531 return;
532 }
533
534 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
535
536 if (Modifier && strcmp(Modifier, "submode") == 0) {
537 ARM_AM::AMSubMode Mode = ARM_AM::getAM5SubMode(MO2.getImm());
538 if (MO1.getReg() == ARM::SP) {
539 bool isFLDM = (MI->getOpcode() == ARM::FLDMD ||
540 MI->getOpcode() == ARM::FLDMS);
541 O << ARM_AM::getAMSubModeAltStr(Mode, isFLDM);
542 } else
543 O << ARM_AM::getAMSubModeStr(Mode);
544 return;
545 } else if (Modifier && strcmp(Modifier, "base") == 0) {
546 // Used for FSTM{D|S} and LSTM{D|S} operations.
547 O << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
548 if (ARM_AM::getAM5WBFlag(MO2.getImm()))
549 O << "!";
550 return;
551 }
552
553 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
554
555 if (unsigned ImmOffs = ARM_AM::getAM5Offset(MO2.getImm())) {
556 O << ", #"
557 << (char)ARM_AM::getAM5Op(MO2.getImm())
558 << ImmOffs*4;
559 }
560 O << "]";
561 }
562
563 void ARMAsmPrinter::printAddrModePCOperand(const MachineInstr *MI, int Op,
564 const char *Modifier) {
565 if (Modifier && strcmp(Modifier, "label") == 0) {
566 printPCLabel(MI, Op+1);
567 return;
568 }
569
570 const MachineOperand &MO1 = MI->getOperand(Op);
571 assert(TargetRegisterInfo::isPhysicalRegister(MO1.getReg()));
572 O << "[pc, +" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName << "]";
573 }
574
575 void
576 ARMAsmPrinter::printThumbAddrModeRROperand(const MachineInstr *MI, int Op) {
577 const MachineOperand &MO1 = MI->getOperand(Op);
578 const MachineOperand &MO2 = MI->getOperand(Op+1);
579 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
580 O << ", " << TM.getRegisterInfo()->get(MO2.getReg()).AsmName << "]";
581 }
582
583 void
584 ARMAsmPrinter::printThumbAddrModeRI5Operand(const MachineInstr *MI, int Op,
585 unsigned Scale) {
586 const MachineOperand &MO1 = MI->getOperand(Op);
587 const MachineOperand &MO2 = MI->getOperand(Op+1);
588 const MachineOperand &MO3 = MI->getOperand(Op+2);
589
590 if (!MO1.isRegister()) { // FIXME: This is for CP entries, but isn't right.
591 printOperand(MI, Op);
592 return;
593 }
594
595 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
596 if (MO3.getReg())
597 O << ", " << TM.getRegisterInfo()->get(MO3.getReg()).AsmName;
598 else if (unsigned ImmOffs = MO2.getImm()) {
599 O << ", #" << ImmOffs;
600 if (Scale > 1)
601 O << " * " << Scale;
602 }
603 O << "]";
604 }
605
606 void
607 ARMAsmPrinter::printThumbAddrModeS1Operand(const MachineInstr *MI, int Op) {
608 printThumbAddrModeRI5Operand(MI, Op, 1);
609 }
610 void
611 ARMAsmPrinter::printThumbAddrModeS2Operand(const MachineInstr *MI, int Op) {
612 printThumbAddrModeRI5Operand(MI, Op, 2);
613 }
614 void
615 ARMAsmPrinter::printThumbAddrModeS4Operand(const MachineInstr *MI, int Op) {
616 printThumbAddrModeRI5Operand(MI, Op, 4);
617 }
618
619 void ARMAsmPrinter::printThumbAddrModeSPOperand(const MachineInstr *MI,int Op) {
620 const MachineOperand &MO1 = MI->getOperand(Op);
621 const MachineOperand &MO2 = MI->getOperand(Op+1);
622 O << "[" << TM.getRegisterInfo()->get(MO1.getReg()).AsmName;
623 if (unsigned ImmOffs = MO2.getImm())
624 O << ", #" << ImmOffs << " * 4";
625 O << "]";
626 }
627
628 void ARMAsmPrinter::printPredicateOperand(const MachineInstr *MI, int opNum) {
629 ARMCC::CondCodes CC = (ARMCC::CondCodes)MI->getOperand(opNum).getImm();
630 if (CC != ARMCC::AL)
631 O << ARMCondCodeToString(CC);
632 }
633
634 void ARMAsmPrinter::printSBitModifierOperand(const MachineInstr *MI, int opNum){
635 unsigned Reg = MI->getOperand(opNum).getReg();
636 if (Reg) {
637 assert(Reg == ARM::CPSR && "Expect ARM CPSR register!");
638 O << 's';
639 }
640 }
641
642 void ARMAsmPrinter::printPCLabel(const MachineInstr *MI, int opNum) {
643 int Id = (int)MI->getOperand(opNum).getImm();
644 O << TAI->getPrivateGlobalPrefix() << "PC" << Id;
645 }
646
647 void ARMAsmPrinter::printRegisterList(const MachineInstr *MI, int opNum) {
648 O << "{";
649 for (unsigned i = opNum, e = MI->getNumOperands(); i != e; ++i) {
650 printOperand(MI, i);
651 if (i != e-1) O << ", ";
652 }
653 O << "}";
654 }
655
656 void ARMAsmPrinter::printCPInstOperand(const MachineInstr *MI, int OpNo,
657 const char *Modifier) {
658 assert(Modifier && "This operand only works with a modifier!");
659 // There are two aspects to a CONSTANTPOOL_ENTRY operand, the label and the
660 // data itself.
661 if (!strcmp(Modifier, "label")) {
662 unsigned ID = MI->getOperand(OpNo).getImm();
663 O << TAI->getPrivateGlobalPrefix() << "CPI" << getFunctionNumber()
664 << '_' << ID << ":\n";
665 } else {
666 assert(!strcmp(Modifier, "cpentry") && "Unknown modifier for CPE");
667 unsigned CPI = MI->getOperand(OpNo).getIndex();
668
669 const MachineConstantPoolEntry &MCPE = // Chasing pointers is fun?
670 MI->getParent()->getParent()->getConstantPool()->getConstants()[CPI];
671
672 if (MCPE.isMachineConstantPoolEntry()) {
673 EmitMachineConstantPoolValue(MCPE.Val.MachineCPVal);
674 ARMConstantPoolValue *ACPV =
675 static_cast(MCPE.Val.MachineCPVal);
676 if (ACPV->getPCAdjustment() != 0) {
677 const GlobalValue *GV = ACPV->getGV();
678 PCRelGVs.insert(GV);
679 }
680 } else {
681 EmitGlobalConstant(MCPE.Val.ConstVal);
682 // remember to emit the weak reference
683 if (const GlobalValue *GV = dyn_cast(MCPE.Val.ConstVal))
684 if (GV->hasExternalWeakLinkage())
685 ExtWeakSymbols.insert(GV);
686 }
687 }
688 }
689
690 void ARMAsmPrinter::printJTBlockOperand(const MachineInstr *MI, int OpNo) {
691 const MachineOperand &MO1 = MI->getOperand(OpNo);
692 const MachineOperand &MO2 = MI->getOperand(OpNo+1); // Unique Id
693 unsigned JTI = MO1.getIndex();
694 O << TAI->getPrivateGlobalPrefix() << "JTI" << getFunctionNumber()
695 << '_' << JTI << '_' << MO2.getImm() << ":\n";
696
697 const char *JTEntryDirective = TAI->getJumpTableDirective();
698 if (!JTEntryDirective)
699 JTEntryDirective = TAI->getData32bitsDirective();
700
701 const MachineFunction *MF = MI->getParent()->getParent();
702 const MachineJumpTableInfo *MJTI = MF->getJumpTableInfo();
703 const std::vector &JT = MJTI->getJumpTables();
704 const std::vector &JTBBs = JT[JTI].MBBs;
705 bool UseSet= TAI->getSetDirective() && TM.getRelocationModel() == Reloc::PIC_;
706 std::set JTSets;
707 for (unsigned i = 0, e = JTBBs.size(); i != e; ++i) {
708 MachineBasicBlock *MBB = JTBBs[i];
709 if (UseSet && JTSets.insert(MBB).second)
710 printPICJumpTableSetLabel(JTI, MO2.getImm(), MBB);
711
712 O << JTEntryDirective << ' ';
713 if (UseSet)
714 O << TAI->getPrivateGlobalPrefix() << getFunctionNumber()
715 << '_' << JTI << '_' << MO2.getImm()
716 << "_set_" << MBB->getNumber();
717 else if (TM.getRelocationModel() == Reloc::PIC_) {
718 printBasicBlockLabel(MBB, false, false, false);
719 // If the arch uses custom Jump Table directives, don't calc relative to JT
720 if (!TAI->getJumpTableDirective())
721 O << '-' << TAI->getPrivateGlobalPrefix() << "JTI"
722 << getFunctionNumber() << '_' << JTI << '_' << MO2.getImm();
723 } else
724 printBasicBlockLabel(MBB, false, false, false);
725 if (i != e-1)
726 O << '\n';
727 }
728 }
729
730
731 bool ARMAsmPrinter::PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
732 unsigned AsmVariant, const char *ExtraCode){
733 // Does this asm operand have a single letter operand modifier?
734 if (ExtraCode && ExtraCode[0]) {
735 if (ExtraCode[1] != 0) return true; // Unknown modifier.
736
737 switch (ExtraCode[0]) {
738 default: return true; // Unknown modifier.
739 case 'c': // Don't print "$" before a global var name or constant.
740 case 'P': // Print a VFP double precision register.
741 printOperand(MI, OpNo);
742 return false;
743 case 'Q':
744 if (TM.getTargetData()->isLittleEndian())
745 break;
746 // Fallthrough
747 case 'R':
748 if (TM.getTargetData()->isBigEndian())
749 break;
750 // Fallthrough
751 case 'H': // Write second word of DI / DF reference.
752 // Verify that this operand has two consecutive registers.
753 if (!MI->getOperand(OpNo).isRegister() ||
754 OpNo+1 == MI->getNumOperands() ||
755 !MI->getOperand(OpNo+1).isRegister())
756 return true;
757 ++OpNo; // Return the high-part.
758 }
759 }
760
761 printOperand(MI, OpNo);
762 return false;
763 }
764
765 void ARMAsmPrinter::printMachineInstruction(const MachineInstr *MI) {
766 ++EmittedInsts;
767
768 int Opc = MI->getOpcode();
769 switch (Opc) {
770 case ARM::CONSTPOOL_ENTRY:
771 if (!InCPMode && AFI->isThumbFunction()) {
772 EmitAlignment(2);
773 InCPMode = true;
774 }
775 break;
776 default: {
777 if (InCPMode && AFI->isThumbFunction())
778 InCPMode = false;
779 switch (Opc) {
780 case ARM::PICADD:
781 case ARM::PICLD:
782 case ARM::PICLDZH:
783 case ARM::PICLDZB:
784 case ARM::PICLDH:
785 case ARM::PICLDB:
786 case ARM::PICLDSH:
787 case ARM::PICLDSB:
788 case ARM::PICSTR:
789 case ARM::PICSTRH:
790 case ARM::PICSTRB:
791 case ARM::tPICADD:
792 break;
793 default:
794 break;
795 }
796 }}
797
798 // Call the autogenerated instruction printer routines.
799 printInstruction(MI);
800 }
801
802 bool ARMAsmPrinter::doInitialization(Module &M) {
803 // Emit initial debug information.
804 DW.BeginModule(&M);
805
806 bool Result = AsmPrinter::doInitialization(M);
807
808 // AsmPrinter::doInitialization should have done this analysis.
809 MMI = getAnalysisToUpdate();
810 assert(MMI);
811 DW.SetModuleInfo(MMI);
812
813 // Darwin wants symbols to be quoted if they have complex names.
814 if (Subtarget->isTargetDarwin())
815 Mang->setUseQuotes(true);
816
817 return Result;
818 }
819
820 /// PrintUnmangledNameSafely - Print out the printable characters in the name.
821 /// Don't print things like \n or \0.
822 static void PrintUnmangledNameSafely(const Value *V, std::ostream &OS) {
823 for (const char *Name = V->getNameStart(), *E = Name+V->getNameLen();
824 Name != E; ++Name)
825 if (isprint(*Name))
826 OS << *Name;
827 }
828
829 void ARMAsmPrinter::printModuleLevelGV(const GlobalVariable* GVar) {
830 const TargetData *TD = TM.getTargetData();
831
832 if (!GVar->hasInitializer()) // External global require no code
833 return;
834
835 // Check to see if this is a special global used by LLVM, if so, emit it.
836
837 if (EmitSpecialLLVMGlobal(GVar)) {
838 if (Subtarget->isTargetDarwin() &&
839 TM.getRelocationModel() == Reloc::Static) {
840 if (GVar->getName() == "llvm.global_ctors")
841 O << ".reference .constructors_used\n";
842 else if (GVar->getName() == "llvm.global_dtors")
843 O << ".reference .destructors_used\n";
844 }
845 return;
846 }
847
848 std::string SectionName = TAI->SectionForGlobal(GVar);
849 std::string name = Mang->getValueName(GVar);
850 Constant *C = GVar->getInitializer();
851 const Type *Type = C->getType();
852 unsigned Size = TD->getABITypeSize(Type);
853 unsigned Align = TD->getPreferredAlignmentLog(GVar);
854
855 printVisibility(name, GVar->getVisibility());
856
857 if (Subtarget->isTargetELF())
858 O << "\t.type " << name << ",%object\n";
859
860 SwitchToDataSection(SectionName.c_str());
861
862 if (C->isNullValue() && !GVar->hasSection() && !GVar->isThreadLocal()) {
863 // FIXME: This seems to be pretty darwin-specific
864
865 if (GVar->hasExternalLinkage()) {
866 if (const char *Directive = TAI->getZeroFillDirective()) {
867 O << "\t.globl\t" << name << "\n";
868 O << Directive << "__DATA, __common, " << name << ", "
869 << Size << ", " << Align << "\n";
870 return;
871 }
872 }
873
874 if (GVar->hasInternalLinkage() || GVar->isWeakForLinker()) {
875 if (Size == 0) Size = 1; // .comm Foo, 0 is undefined, avoid it.
876
877 if (TAI->getLCOMMDirective() != NULL) {
878 if (PCRelGVs.count(GVar) || GVar->hasInternalLinkage()) {
879 O << TAI->getLCOMMDirective() << name << "," << Size;
880 if (Subtarget->isTargetDarwin())
881 O << "," << Align;
882 } else
883 O << TAI->getCOMMDirective() << name << "," << Size;
884 } else {
885 if (GVar->hasInternalLinkage())
886 O << "\t.local\t" << name << "\n";
887 O << TAI->getCOMMDirective() << name << "," << Size;
888 if (TAI->getCOMMDirectiveTakesAlignment())
889 O << "," << (TAI->getAlignmentIsInBytes() ? (1 << Align) : Align);
890 }
891 O << "\t\t" << TAI->getCommentString() << " ";
892 PrintUnmangledNameSafely(GVar, O);
893 O << "\n";
894 return;
895 }
896 }
897
898 switch (GVar->getLinkage()) {
899 case GlobalValue::LinkOnceLinkage:
900 case GlobalValue::WeakLinkage:
901 if (Subtarget->isTargetDarwin()) {
902 O << "\t.globl " << name << "\n"
903 << "\t.weak_definition " << name << "\n";
904 } else {
905 O << "\t.weak " << name << "\n";
906 }
907 break;
908 case GlobalValue::AppendingLinkage:
909 // FIXME: appending linkage variables should go into a section of
910 // their name or something. For now, just emit them as external.
911 case GlobalValue::ExternalLinkage:
912 O << "\t.globl " << name << "\n";
913 // FALL THROUGH
914 case GlobalValue::InternalLinkage:
915 break;
916 default:
917 assert(0 && "Unknown linkage type!");
918 break;
919 }
920
921 EmitAlignment(Align, GVar);
922 O << name << ":\t\t\t\t" << TAI->getCommentString() << " ";
923 PrintUnmangledNameSafely(GVar, O);
924 O << "\n";
925 if (TAI->hasDotTypeDotSizeDirective())
926 O << "\t.size " << name << ", " << Size << "\n";
927
928 // If the initializer is a extern weak symbol, remember to emit the weak
929 // reference!
930 if (const GlobalValue *GV = dyn_cast(C))
931 if (GV->hasExternalWeakLinkage())
932 ExtWeakSymbols.insert(GV);
933
934 EmitGlobalConstant(C);
935 O << '\n';
936 }
937
938
939 bool ARMAsmPrinter::doFinalization(Module &M) {
940 for (Module::const_global_iterator I = M.global_begin(), E = M.global_end();
941 I != E; ++I)
942 printModuleLevelGV(I);
943
944 if (Subtarget->isTargetDarwin()) {
945 SwitchToDataSection("");
946
947 // Output stubs for dynamically-linked functions
948 unsigned j = 1;
949 for (std::set::iterator i = FnStubs.begin(), e = FnStubs.end();
950 i != e; ++i, ++j) {
951 if (TM.getRelocationModel() == Reloc::PIC_)
952 SwitchToTextSection(".section __TEXT,__picsymbolstub4,symbol_stubs,"
953 "none,16", 0);
954 else
955 SwitchToTextSection(".section __TEXT,__symbol_stub4,symbol_stubs,"
956 "none,12", 0);
957
958 EmitAlignment(2);
959 O << "\t.code\t32\n";
960
961 std::string p = *i;
962 printSuffixedName(p, "$stub");
963 O << ":\n";
964 O << "\t.indirect_symbol " << *i << "\n";
965 O << "\tldr ip, ";
966 printSuffixedName(p, "$slp");
967 O << "\n";
968 if (TM.getRelocationModel() == Reloc::PIC_) {
969 printSuffixedName(p, "$scv");
970 O << ":\n";
971 O << "\tadd ip, pc, ip\n";
972 }
973 O << "\tldr pc, [ip, #0]\n";
974 printSuffixedName(p, "$slp");
975 O << ":\n";
976 O << "\t.long\t";
977 printSuffixedName(p, "$lazy_ptr");
978 if (TM.getRelocationModel() == Reloc::PIC_) {
979 O << "-(";
980 printSuffixedName(p, "$scv");
981 O << "+8)\n";
982 } else
983 O << "\n";
984 SwitchToDataSection(".lazy_symbol_pointer", 0);
985 printSuffixedName(p, "$lazy_ptr");
986 O << ":\n";
987 O << "\t.indirect_symbol " << *i << "\n";
988 O << "\t.long\tdyld_stub_binding_helper\n";
989 }
990 O << "\n";
991
992 // Output non-lazy-pointers for external and common global variables.
993 if (!GVNonLazyPtrs.empty())
994 SwitchToDataSection(".non_lazy_symbol_pointer", 0);
995 for (std::set::iterator i = GVNonLazyPtrs.begin(),
996 e = GVNonLazyPtrs.end(); i != e; ++i) {
997 std::string p = *i;
998 printSuffixedName(p, "$non_lazy_ptr");
999 O << ":\n";
1000 O << "\t.indirect_symbol " << *i << "\n";
1001 O << "\t.long\t0\n";
1002 }
1003
1004 // Emit initial debug information.
1005 DW.EndModule();
1006
1007 // Funny Darwin hack: This flag tells the linker that no global symbols
1008 // contain code that falls through to other global symbols (e.g. the obvious
1009 // implementation of multiple entry points). If this doesn't occur, the
1010 // linker can safely perform dead code stripping. Since LLVM never
1011 // generates code that does this, it is always safe to set.
1012 O << "\t.subsections_via_symbols\n";
1013 } else {
1014 // Emit final debug information for ELF.
1015 DW.EndModule();
1016 }
1017
1018 return AsmPrinter::doFinalization(M);
1019 }
1020
1021 /// createARMCodePrinterPass - Returns a pass that prints the ARM
1022 /// assembly code for a MachineFunction to the given output stream,
1023 /// using the given target machine description. This should work
1024 /// regardless of whether the function is in SSA form.
1025 ///
1026 FunctionPass *llvm::createARMCodePrinterPass(std::ostream &o,
1027 ARMTargetMachine &tm) {
1028 return new ARMAsmPrinter(o, tm, tm.getTargetAsmInfo());
1029 }
1030
1031 namespace {
1032 static struct Register {
1033 Register() {
1034 ARMTargetMachine::registerAsmPrinter(createARMCodePrinterPass);
1035 }
1036 } Registrator;
1037 }
0 ##===- lib/Target/X86/Makefile -----------------------------*- Makefile -*-===##
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 LEVEL = ../../../..
9 LIBRARYNAME = LLVMARMAsmPrinter
10
11 # Hack: we need to include 'main' x86 target directory to grab private headers
12 CPPFLAGS = -I$(PROJ_OBJ_DIR)/.. -I$(PROJ_SRC_DIR)/..
13
14 include $(LEVEL)/Makefile.common
77 ##===----------------------------------------------------------------------===##
88
99 LEVEL = ../../..
10 LIBRARYNAME = LLVMARM
10 LIBRARYNAME = LLVMARMCodeGen
1111 TARGET = ARM
1212
1313 # Make sure that tblgen is run, first thing.
1616 ARMGenInstrInfo.inc ARMGenAsmWriter.inc \
1717 ARMGenDAGISel.inc ARMGenSubtarget.inc
1818
19 DIRS = AsmPrinter
20
1921 include $(LEVEL)/Makefile.common