OLD | NEW |
1 //===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===// | 1 //===-- ARMAsmPrinter.cpp - Print machine code to an ARM .s file ----------===// |
2 // | 2 // |
3 // The LLVM Compiler Infrastructure | 3 // The LLVM Compiler Infrastructure |
4 // | 4 // |
5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source |
6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. |
7 // | 7 // |
8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// |
9 // | 9 // |
10 // This file contains a printer that converts from our internal representation | 10 // This file contains a printer that converts from our internal representation |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 void EmitJumpTable(const MachineInstr *MI); | 100 void EmitJumpTable(const MachineInstr *MI); |
101 void EmitJump2Table(const MachineInstr *MI); | 101 void EmitJump2Table(const MachineInstr *MI); |
102 virtual void EmitInstruction(const MachineInstr *MI); | 102 virtual void EmitInstruction(const MachineInstr *MI); |
103 bool runOnMachineFunction(MachineFunction &F); | 103 bool runOnMachineFunction(MachineFunction &F); |
104 | 104 |
105 virtual void EmitConstantPool() {} // we emit constant pools customly! | 105 virtual void EmitConstantPool() {} // we emit constant pools customly! |
106 virtual void EmitFunctionEntryLabel(); | 106 virtual void EmitFunctionEntryLabel(); |
107 void EmitStartOfAsmFile(Module &M); | 107 void EmitStartOfAsmFile(Module &M); |
108 void EmitEndOfAsmFile(Module &M); | 108 void EmitEndOfAsmFile(Module &M); |
109 | 109 |
| 110 private: |
| 111 // Two helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile() |
| 112 void emitAsmAttributes(Module &M); |
| 113 void emitELFAttributes(Module &M); |
| 114 public: |
| 115 |
110 void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); | 116 void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); |
111 | 117 |
112 MachineLocation getDebugValueLocation(const MachineInstr *MI) const { | 118 MachineLocation getDebugValueLocation(const MachineInstr *MI) const { |
113 MachineLocation Location; | 119 MachineLocation Location; |
114 assert (MI->getNumOperands() == 4 && "Invalid no. of machine operands!"); | 120 assert (MI->getNumOperands() == 4 && "Invalid no. of machine operands!"); |
115 // Frame address. Currently handles register +- offset only. | 121 // Frame address. Currently handles register +- offset only. |
116 if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm()) | 122 if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm()) |
117 Location.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm()); | 123 Location.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm()); |
118 else { | 124 else { |
119 DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n"); | 125 DEBUG(dbgs() << "DBG_VALUE instruction ignored! " << *MI << "\n"); |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 SectionKind::getText()); | 421 SectionKind::getText()); |
416 OutStreamer.SwitchSection(StaticInitSect); | 422 OutStreamer.SwitchSection(StaticInitSect); |
417 } | 423 } |
418 } | 424 } |
419 | 425 |
420 // Use unified assembler syntax. | 426 // Use unified assembler syntax. |
421 OutStreamer.EmitAssemblerFlag(MCAF_SyntaxUnified); | 427 OutStreamer.EmitAssemblerFlag(MCAF_SyntaxUnified); |
422 | 428 |
423 // Emit ARM Build Attributes | 429 // Emit ARM Build Attributes |
424 if (Subtarget->isTargetELF()) { | 430 if (Subtarget->isTargetELF()) { |
425 // CPU Type | |
426 std::string CPUString = Subtarget->getCPUString(); | |
427 if (CPUString != "generic") | |
428 OutStreamer.EmitRawText("\t.cpu " + Twine(CPUString)); | |
429 | 431 |
430 // FIXME: Emit FPU type | 432 emitAsmAttributes(M); |
431 if (Subtarget->hasVFP2()) | |
432 OutStreamer.EmitRawText("\t.eabi_attribute " + | |
433 Twine(ARMBuildAttrs::VFP_arch) + ", 2"); | |
434 | |
435 // Signal various FP modes. | |
436 if (!UnsafeFPMath) { | |
437 OutStreamer.EmitRawText("\t.eabi_attribute " + | |
438 Twine(ARMBuildAttrs::ABI_FP_denormal) + ", 1"); | |
439 OutStreamer.EmitRawText("\t.eabi_attribute " + | |
440 Twine(ARMBuildAttrs::ABI_FP_exceptions) + ", 1"); | |
441 } | |
442 | |
443 if (NoInfsFPMath && NoNaNsFPMath) | |
444 OutStreamer.EmitRawText("\t.eabi_attribute " + | |
445 Twine(ARMBuildAttrs::ABI_FP_number_model)+ ", 1"); | |
446 else | |
447 OutStreamer.EmitRawText("\t.eabi_attribute " + | |
448 Twine(ARMBuildAttrs::ABI_FP_number_model)+ ", 3"); | |
449 | |
450 // 8-bytes alignment stuff. | |
451 OutStreamer.EmitRawText("\t.eabi_attribute " + | |
452 Twine(ARMBuildAttrs::ABI_align8_needed) + ", 1"); | |
453 OutStreamer.EmitRawText("\t.eabi_attribute " + | |
454 Twine(ARMBuildAttrs::ABI_align8_preserved) + ", 1"); | |
455 | |
456 // Hard float. Use both S and D registers and conform to AAPCS-VFP. | |
457 if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) { | |
458 OutStreamer.EmitRawText("\t.eabi_attribute " + | |
459 Twine(ARMBuildAttrs::ABI_HardFP_use) + ", 3"); | |
460 OutStreamer.EmitRawText("\t.eabi_attribute " + | |
461 Twine(ARMBuildAttrs::ABI_VFP_args) + ", 1"); | |
462 } | |
463 // FIXME: Should we signal R9 usage? | |
464 } | 433 } |
465 } | 434 } |
466 | 435 |
467 | 436 |
468 void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { | 437 void ARMAsmPrinter::EmitEndOfAsmFile(Module &M) { |
469 if (Subtarget->isTargetDarwin()) { | 438 if (Subtarget->isTargetDarwin()) { |
470 // All darwin targets use mach-o. | 439 // All darwin targets use mach-o. |
471 const TargetLoweringObjectFileMachO &TLOFMacho = | 440 const TargetLoweringObjectFileMachO &TLOFMacho = |
472 static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); | 441 static_cast<const TargetLoweringObjectFileMachO &>(getObjFileLowering()); |
473 MachineModuleInfoMachO &MMIMacho = | 442 MachineModuleInfoMachO &MMIMacho = |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
526 | 495 |
527 // Funny Darwin hack: This flag tells the linker that no global symbols | 496 // Funny Darwin hack: This flag tells the linker that no global symbols |
528 // contain code that falls through to other global symbols (e.g. the obvious | 497 // contain code that falls through to other global symbols (e.g. the obvious |
529 // implementation of multiple entry points). If this doesn't occur, the | 498 // implementation of multiple entry points). If this doesn't occur, the |
530 // linker can safely perform dead code stripping. Since LLVM never | 499 // linker can safely perform dead code stripping. Since LLVM never |
531 // generates code that does this, it is always safe to set. | 500 // generates code that does this, it is always safe to set. |
532 OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); | 501 OutStreamer.EmitAssemblerFlag(MCAF_SubsectionsViaSymbols); |
533 } | 502 } |
534 } | 503 } |
535 | 504 |
| 505 |
| 506 //===----------------------------------------------------------------------===// |
| 507 // Helper routines for EmitStartOfAsmFile() and EmitEndOfAsmFile() |
| 508 // FIXME: |
| 509 // The following seem like one-off assembler flags, but they actually need |
| 510 // to appear in the .ARM.attributes section in ELF. This is the reason why |
| 511 // having a common interface to emit these for both the MC/.s and |
| 512 // MC/ELF/obj emission is complicated. |
| 513 // Instead of subclassing the MCELFStreamer, we do the work here. |
| 514 |
| 515 void ARMAsmPrinter::emitAsmAttributes(Module &M) { |
| 516 if (!OutStreamer.hasRawTextSupport()) |
| 517 return; |
| 518 |
| 519 // CPU Type |
| 520 std::string CPUString = Subtarget->getCPUString(); |
| 521 if (CPUString != "generic") |
| 522 OutStreamer.EmitRawText("\t.cpu " + Twine(CPUString)); |
| 523 |
| 524 // FIXME: Emit FPU type |
| 525 if (Subtarget->hasVFP2()) |
| 526 OutStreamer.EmitRawText("\t.eabi_attribute " + |
| 527 Twine(ARMBuildAttrs::VFP_arch) + ", 2"); |
| 528 |
| 529 // Signal various FP modes. |
| 530 if (!UnsafeFPMath) { |
| 531 OutStreamer.EmitRawText("\t.eabi_attribute " + |
| 532 Twine(ARMBuildAttrs::ABI_FP_denormal) + ", 1"); |
| 533 OutStreamer.EmitRawText("\t.eabi_attribute " + |
| 534 Twine(ARMBuildAttrs::ABI_FP_exceptions) + ", 1"); |
| 535 } |
| 536 |
| 537 if (NoInfsFPMath && NoNaNsFPMath) |
| 538 OutStreamer.EmitRawText("\t.eabi_attribute " + |
| 539 Twine(ARMBuildAttrs::ABI_FP_number_model)+ ", 1"); |
| 540 else |
| 541 OutStreamer.EmitRawText("\t.eabi_attribute " + |
| 542 Twine(ARMBuildAttrs::ABI_FP_number_model)+ ", 3"); |
| 543 |
| 544 // 8-bytes alignment stuff. |
| 545 OutStreamer.EmitRawText("\t.eabi_attribute " + |
| 546 Twine(ARMBuildAttrs::ABI_align8_needed) + ", 1"); |
| 547 OutStreamer.EmitRawText("\t.eabi_attribute " + |
| 548 Twine(ARMBuildAttrs::ABI_align8_preserved) + ", 1"); |
| 549 |
| 550 // Hard float. Use both S and D registers and conform to AAPCS-VFP. |
| 551 if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) { |
| 552 OutStreamer.EmitRawText("\t.eabi_attribute " + |
| 553 Twine(ARMBuildAttrs::ABI_HardFP_use) + ", 3"); |
| 554 OutStreamer.EmitRawText("\t.eabi_attribute " + |
| 555 Twine(ARMBuildAttrs::ABI_VFP_args) + ", 1"); |
| 556 } |
| 557 // FIXME: Should we signal R9 usage? |
| 558 } |
| 559 |
| 560 void ARMAsmPrinter::emitELFAttributes(Module &M) { |
| 561 // FIXME: |
| 562 } |
| 563 |
536 //===----------------------------------------------------------------------===// | 564 //===----------------------------------------------------------------------===// |
537 | 565 |
538 static MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber, | 566 static MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber, |
539 unsigned LabelId, MCContext &Ctx) { | 567 unsigned LabelId, MCContext &Ctx) { |
540 | 568 |
541 MCSymbol *Label = Ctx.GetOrCreateSymbol(Twine(Prefix) | 569 MCSymbol *Label = Ctx.GetOrCreateSymbol(Twine(Prefix) |
542 + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId)); | 570 + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId)); |
543 return Label; | 571 return Label; |
544 } | 572 } |
545 | 573 |
(...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1228 | 1256 |
1229 // Force static initialization. | 1257 // Force static initialization. |
1230 extern "C" void LLVMInitializeARMAsmPrinter() { | 1258 extern "C" void LLVMInitializeARMAsmPrinter() { |
1231 RegisterAsmPrinter<ARMAsmPrinter> X(TheARMTarget); | 1259 RegisterAsmPrinter<ARMAsmPrinter> X(TheARMTarget); |
1232 RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget); | 1260 RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget); |
1233 | 1261 |
1234 TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter); | 1262 TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter); |
1235 TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter); | 1263 TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter); |
1236 } | 1264 } |
1237 | 1265 |
OLD | NEW |