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 20 matching lines...) Expand all Loading... |
31 #include "llvm/CodeGen/MachineModuleInfoImpls.h" | 31 #include "llvm/CodeGen/MachineModuleInfoImpls.h" |
32 #include "llvm/CodeGen/MachineFunctionPass.h" | 32 #include "llvm/CodeGen/MachineFunctionPass.h" |
33 #include "llvm/CodeGen/MachineJumpTableInfo.h" | 33 #include "llvm/CodeGen/MachineJumpTableInfo.h" |
34 #include "llvm/MC/MCAsmInfo.h" | 34 #include "llvm/MC/MCAsmInfo.h" |
35 #include "llvm/MC/MCContext.h" | 35 #include "llvm/MC/MCContext.h" |
36 #include "llvm/MC/MCExpr.h" | 36 #include "llvm/MC/MCExpr.h" |
37 #include "llvm/MC/MCInst.h" | 37 #include "llvm/MC/MCInst.h" |
38 #include "llvm/MC/MCSectionMachO.h" | 38 #include "llvm/MC/MCSectionMachO.h" |
39 #include "llvm/MC/MCStreamer.h" | 39 #include "llvm/MC/MCStreamer.h" |
40 #include "llvm/MC/MCSymbol.h" | 40 #include "llvm/MC/MCSymbol.h" |
| 41 #include "llvm/MC/MCAssembler.h" |
41 #include "llvm/Target/Mangler.h" | 42 #include "llvm/Target/Mangler.h" |
42 #include "llvm/Target/TargetData.h" | 43 #include "llvm/Target/TargetData.h" |
43 #include "llvm/Target/TargetMachine.h" | 44 #include "llvm/Target/TargetMachine.h" |
44 #include "llvm/Target/TargetOptions.h" | 45 #include "llvm/Target/TargetOptions.h" |
45 #include "llvm/Target/TargetRegistry.h" | 46 #include "llvm/Target/TargetRegistry.h" |
46 #include "llvm/ADT/SmallPtrSet.h" | 47 #include "llvm/ADT/SmallPtrSet.h" |
47 #include "llvm/ADT/SmallString.h" | 48 #include "llvm/ADT/SmallString.h" |
48 #include "llvm/ADT/StringExtras.h" | 49 #include "llvm/ADT/StringExtras.h" |
49 #include "llvm/Support/CommandLine.h" | 50 #include "llvm/Support/CommandLine.h" |
50 #include "llvm/Support/Debug.h" | 51 #include "llvm/Support/Debug.h" |
| 52 #include "llvm/Support/ELF.h" |
51 #include "llvm/Support/ErrorHandling.h" | 53 #include "llvm/Support/ErrorHandling.h" |
52 #include "llvm/Support/raw_ostream.h" | 54 #include "llvm/Support/raw_ostream.h" |
53 #include <cctype> | 55 #include <cctype> |
54 using namespace llvm; | 56 using namespace llvm; |
55 | 57 |
56 namespace llvm { | 58 namespace llvm { |
57 namespace ARM { | 59 namespace ARM { |
58 enum DW_ISA { | 60 enum DW_ISA { |
59 DW_ISA_ARM_thumb = 1, | 61 DW_ISA_ARM_thumb = 1, |
60 DW_ISA_ARM_arm = 2 | 62 DW_ISA_ARM_arm = 2 |
(...skipping 11 matching lines...) Expand all Loading... |
72 /// AFI - Keep a pointer to ARMFunctionInfo for the current | 74 /// AFI - Keep a pointer to ARMFunctionInfo for the current |
73 /// MachineFunction. | 75 /// MachineFunction. |
74 ARMFunctionInfo *AFI; | 76 ARMFunctionInfo *AFI; |
75 | 77 |
76 /// MCP - Keep a pointer to constantpool entries of the current | 78 /// MCP - Keep a pointer to constantpool entries of the current |
77 /// MachineFunction. | 79 /// MachineFunction. |
78 const MachineConstantPool *MCP; | 80 const MachineConstantPool *MCP; |
79 | 81 |
80 public: | 82 public: |
81 explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) | 83 explicit ARMAsmPrinter(TargetMachine &TM, MCStreamer &Streamer) |
82 : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL) { | 84 : AsmPrinter(TM, Streamer), AFI(NULL), MCP(NULL), |
| 85 headFragment(NULL), currFileFragment(NULL), |
| 86 currSectionFragment(NULL), currSymbolFragment(NULL) { |
83 Subtarget = &TM.getSubtarget<ARMSubtarget>(); | 87 Subtarget = &TM.getSubtarget<ARMSubtarget>(); |
84 } | 88 } |
85 | 89 |
86 virtual const char *getPassName() const { | 90 virtual const char *getPassName() const { |
87 return "ARM Assembly Printer"; | 91 return "ARM Assembly Printer"; |
88 } | 92 } |
89 | 93 |
90 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, | 94 void printOperand(const MachineInstr *MI, int OpNum, raw_ostream &O, |
91 const char *Modifier = 0); | 95 const char *Modifier = 0); |
92 | 96 |
93 virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, | 97 virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNum, |
94 unsigned AsmVariant, const char *ExtraCode, | 98 unsigned AsmVariant, const char *ExtraCode, |
95 raw_ostream &O); | 99 raw_ostream &O); |
96 virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, | 100 virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNum, |
97 unsigned AsmVariant, | 101 unsigned AsmVariant, |
98 const char *ExtraCode, raw_ostream &O); | 102 const char *ExtraCode, raw_ostream &O); |
99 | 103 |
100 void EmitJumpTable(const MachineInstr *MI); | 104 void EmitJumpTable(const MachineInstr *MI); |
101 void EmitJump2Table(const MachineInstr *MI); | 105 void EmitJump2Table(const MachineInstr *MI); |
102 virtual void EmitInstruction(const MachineInstr *MI); | 106 virtual void EmitInstruction(const MachineInstr *MI); |
103 bool runOnMachineFunction(MachineFunction &F); | 107 bool runOnMachineFunction(MachineFunction &F); |
104 | 108 |
105 virtual void EmitConstantPool() {} // we emit constant pools customly! | 109 virtual void EmitConstantPool() {} // we emit constant pools customly! |
106 virtual void EmitFunctionEntryLabel(); | 110 virtual void EmitFunctionEntryLabel(); |
107 void EmitStartOfAsmFile(Module &M); | 111 void EmitStartOfAsmFile(Module &M); |
108 void EmitEndOfAsmFile(Module &M); | 112 void EmitEndOfAsmFile(Module &M); |
109 | 113 |
110 private: | 114 private: |
| 115 |
111 // Helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile() | 116 // Helpers for EmitStartOfAsmFile() and EmitEndOfAsmFile() |
| 117 // Helper for ELF .s/.o only |
112 void emitAttributes(); | 118 void emitAttributes(); |
113 void emitTextAttribute(ARMBuildAttrs::SpecialAttr attr, StringRef v); | 119 void emitTextAttribute(ARMBuildAttrs::SpecialAttr attr, StringRef v); |
114 void emitAttribute(ARMBuildAttrs::AttrType attr, int v); | 120 void emitAttribute(ARMBuildAttrs::AttrType attr, int v); |
115 | 121 |
116 // Helper for ELF .o only | |
117 void emitARMAttributeSection(); | 122 void emitARMAttributeSection(); |
118 | 123 |
| 124 // Slots for keeping state for above member funcs. |
| 125 MCDataFragment *headFragment; |
| 126 |
| 127 // Fixme: do we ever need more than one of each? |
| 128 MCDataFragment *currFileFragment, |
| 129 *currSectionFragment, *currSymbolFragment; |
| 130 |
| 131 // Section-global offset counters |
| 132 int currOffset; |
| 133 int attrDataStartOffset; |
| 134 |
| 135 // Helper routine for the emit*() functions above |
| 136 MCDataFragment *addAttrSubsec(MCSectionData *AttrSecData, |
| 137 ARMBuildAttrs::AttrType attr, |
| 138 int SecOrSym=0); |
| 139 |
| 140 int fixupAttrSizes(); |
| 141 int fixupAttrSize(MCDataFragment *F, int secLenOffset, int lenAdjust); |
119 public: | 142 public: |
120 void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); | 143 void PrintDebugValueComment(const MachineInstr *MI, raw_ostream &OS); |
121 | 144 |
122 MachineLocation getDebugValueLocation(const MachineInstr *MI) const { | 145 MachineLocation getDebugValueLocation(const MachineInstr *MI) const { |
123 MachineLocation Location; | 146 MachineLocation Location; |
124 assert (MI->getNumOperands() == 4 && "Invalid no. of machine operands!"); | 147 assert (MI->getNumOperands() == 4 && "Invalid no. of machine operands!"); |
125 // Frame address. Currently handles register +- offset only. | 148 // Frame address. Currently handles register +- offset only. |
126 if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm()) | 149 if (MI->getOperand(0).isReg() && MI->getOperand(1).isImm()) |
127 Location.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm()); | 150 Location.set(MI->getOperand(0).getReg(), MI->getOperand(1).getImm()); |
128 else { | 151 else { |
(...skipping 394 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
523 // 8-bytes alignment stuff. | 546 // 8-bytes alignment stuff. |
524 emitAttribute(ARMBuildAttrs::ABI_align8_needed, 1); | 547 emitAttribute(ARMBuildAttrs::ABI_align8_needed, 1); |
525 emitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1); | 548 emitAttribute(ARMBuildAttrs::ABI_align8_preserved, 1); |
526 | 549 |
527 // Hard float. Use both S and D registers and conform to AAPCS-VFP. | 550 // Hard float. Use both S and D registers and conform to AAPCS-VFP. |
528 if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) { | 551 if (Subtarget->isAAPCS_ABI() && FloatABIType == FloatABI::Hard) { |
529 emitAttribute(ARMBuildAttrs::ABI_HardFP_use, 3); | 552 emitAttribute(ARMBuildAttrs::ABI_HardFP_use, 3); |
530 emitAttribute(ARMBuildAttrs::ABI_VFP_args, 1); | 553 emitAttribute(ARMBuildAttrs::ABI_VFP_args, 1); |
531 } | 554 } |
532 // FIXME: Should we signal R9 usage? | 555 // FIXME: Should we signal R9 usage? |
| 556 |
| 557 // FIXME: This is just a freebie set by GNU/ARM as for ELF/.o only. |
| 558 // LLVM never emitted this explicitly for .s |
| 559 if (!OutStreamer.hasRawTextSupport()) { |
| 560 emitAttribute(ARMBuildAttrs::DIV_use, 1); |
| 561 } |
| 562 |
| 563 (void) fixupAttrSizes(); |
533 } | 564 } |
534 | 565 |
535 void ARMAsmPrinter::emitARMAttributeSection() { | 566 void ARMAsmPrinter::emitARMAttributeSection() { |
536 // <format-version> | 567 // <format-version> |
537 // [ <section-length> "vendor-name" | 568 // [ <section-length> "vendor-name" |
538 // [ <file-tag> <size> <attribute>* | 569 // [ <file-tag> <size> <attribute>* |
539 // | <section-tag> <size> <section-number>* 0 <attribute>* | 570 // | <section-tag> <size> <section-number>* 0 <attribute>* |
540 // | <symbol-tag> <size> <symbol-number>* 0 <attribute>* | 571 // | <symbol-tag> <size> <symbol-number>* 0 <attribute>* |
541 // ]+ | 572 // ]+ |
542 // ]* | 573 // ]* |
543 | 574 |
544 if (OutStreamer.hasRawTextSupport()) | 575 if (OutStreamer.hasRawTextSupport()) |
545 return; | 576 return; |
546 | 577 |
547 const ARMElfTargetObjectFile &TLOFELF = | 578 const ARMElfTargetObjectFile &TLOFELF = |
548 static_cast<const ARMElfTargetObjectFile &> | 579 static_cast<const ARMElfTargetObjectFile &> |
549 (getObjFileLowering()); | 580 (getObjFileLowering()); |
550 | 581 |
551 OutStreamer.SwitchSection(TLOFELF.getAttributesSection()); | 582 OutStreamer.SwitchSection(TLOFELF.getAttributesSection()); |
552 // Fixme: Still more to do here. | 583 |
| 584 MCObjectStreamer *ELFStreamer = static_cast<MCObjectStreamer*>(&OutStreamer); |
| 585 MCAssembler *Asm = &ELFStreamer->getAssembler(); |
| 586 |
| 587 bool newSec = false; |
| 588 MCSectionData *AttrSecData = |
| 589 &(Asm->getOrCreateSectionData(*TLOFELF.getAttributesSection(), &newSec)); |
| 590 |
| 591 headFragment = new MCDataFragment(AttrSecData); |
| 592 SmallString<32> *FC = &headFragment->getContents(); |
| 593 |
| 594 (*FC) += ((char)ARMBuildAttrs::Format_Version); |
| 595 |
| 596 FC->append(sizeof(ELF::Elf32_Word), 0); |
| 597 |
| 598 FC->append(ARMBuildAttrs::Vendor_Name, |
| 599 ARMBuildAttrs::Vendor_Name_End); |
| 600 |
| 601 currFileFragment = |
| 602 addAttrSubsec(AttrSecData, ARMBuildAttrs::File); |
553 } | 603 } |
554 | 604 |
555 void ARMAsmPrinter::emitAttribute(ARMBuildAttrs::AttrType attr, int v) { | 605 void ARMAsmPrinter::emitAttribute(ARMBuildAttrs::AttrType attr, int v) { |
556 if (OutStreamer.hasRawTextSupport()) { | 606 if (OutStreamer.hasRawTextSupport()) { |
557 OutStreamer.EmitRawText("\t.eabi_attribute " + | 607 OutStreamer.EmitRawText("\t.eabi_attribute " + |
558 Twine(attr) + ", " + Twine(v)); | 608 Twine(attr) + ", " + Twine(v)); |
559 | 609 |
560 } else { | 610 } else { |
561 assert(0 && "ELF .ARM.attributes unimplemented"); | 611 switch (attr) { |
| 612 // These all go into the File subsection |
| 613 case ARMBuildAttrs::VFP_arch: |
| 614 case ARMBuildAttrs::ABI_FP_denormal: |
| 615 case ARMBuildAttrs::ABI_FP_exceptions: |
| 616 case ARMBuildAttrs::ABI_FP_number_model: |
| 617 case ARMBuildAttrs::ABI_align8_needed: |
| 618 case ARMBuildAttrs::ABI_align8_preserved: |
| 619 case ARMBuildAttrs::ABI_HardFP_use: |
| 620 case ARMBuildAttrs::ABI_VFP_args: |
| 621 case ARMBuildAttrs::DIV_use: { |
| 622 assert(currFileFragment && "No File subsection found"); |
| 623 SmallString<32> *FC = &currFileFragment->getContents(); |
| 624 (*FC) += static_cast<char>(attr); |
| 625 (*FC) += static_cast<char>(0xFF & v); |
| 626 }; break; |
| 627 default: assert(0 && "Unsupported ARMBuildAttrs::AttrType"); break; |
| 628 } |
562 } | 629 } |
563 } | 630 } |
564 | 631 |
565 void ARMAsmPrinter::emitTextAttribute(ARMBuildAttrs::SpecialAttr attr, | 632 void ARMAsmPrinter::emitTextAttribute(ARMBuildAttrs::SpecialAttr attr, |
566 StringRef val) { | 633 StringRef val) { |
567 switch (attr) { | 634 switch (attr) { |
568 default: assert(0 && "Unimplemented ARMBuildAttrs::SpecialAttr"); break; | 635 default: assert(0 && "Unimplemented ARMBuildAttrs::SpecialAttr"); break; |
569 case ARMBuildAttrs::SEL_CPU: | 636 case ARMBuildAttrs::SEL_CPU: |
570 if (OutStreamer.hasRawTextSupport()) { | 637 if (OutStreamer.hasRawTextSupport()) { |
571 if (val != "generic") { | 638 if (val != "generic") { |
572 OutStreamer.EmitRawText("\t.cpu " + val); | 639 OutStreamer.EmitRawText("\t.cpu " + val); |
573 } | 640 } |
574 } else { | 641 } else { |
575 // FIXME: ELF | 642 // .o |
| 643 if (val == "generic") { |
| 644 assert(currFileFragment && "No File subsection found"); |
| 645 SmallString<32> *FC = &currFileFragment->getContents(); |
| 646 (*FC) += static_cast<char>(ARMBuildAttrs::CPU_arch); |
| 647 (*FC) += static_cast<char>(ARMBuildAttrs::v4T); |
| 648 |
| 649 (*FC) += static_cast<char>(ARMBuildAttrs::ARM_ISA_use); |
| 650 (*FC) += static_cast<char>(1); |
| 651 |
| 652 (*FC) += static_cast<char>(ARMBuildAttrs::THUMB_ISA_use); |
| 653 (*FC) += static_cast<char>(1); |
| 654 } else { |
| 655 assert(0 && "unsupported .cpu attribute for ELF/.o"); |
| 656 } |
576 } | 657 } |
577 } | 658 } |
578 } | 659 } |
579 | 660 |
| 661 MCDataFragment *ARMAsmPrinter::addAttrSubsec(MCSectionData *AttrSecData, |
| 662 ARMBuildAttrs::AttrType attr, |
| 663 int SecOrSym) { |
| 664 MCDataFragment *rtn = new MCDataFragment(AttrSecData); |
| 665 SmallString<32> *FC = &rtn->getContents(); |
| 666 |
| 667 (*FC) += static_cast<char>(ARMBuildAttrs::File); |
| 668 FC->append(sizeof(ELF::Elf32_Word), 0); |
| 669 |
| 670 switch (attr) { |
| 671 case ARMBuildAttrs::File: break; |
| 672 case ARMBuildAttrs::Section: |
| 673 case ARMBuildAttrs::Symbol: { |
| 674 (*FC) += (0xFF & SecOrSym); |
| 675 (*FC) += (0xFF & (SecOrSym >> 8)); |
| 676 (*FC) += (0xFF & (SecOrSym >> 16)); |
| 677 (*FC) += (0xFF & (SecOrSym >> 24)); |
| 678 |
| 679 (*FC) += 0; |
| 680 } break; |
| 681 default: assert(0 && "Unknown .ARM.attributes subsection"); break; |
| 682 } |
| 683 |
| 684 return rtn; |
| 685 } |
| 686 |
| 687 int ARMAsmPrinter::fixupAttrSizes() { |
| 688 int SFileAttr = fixupAttrSize(currFileFragment, 1, 0); |
| 689 int SSecAttr = fixupAttrSize(currSectionFragment, 1, 0); |
| 690 int SSymAttr = fixupAttrSize(currSymbolFragment, 1, 0); |
| 691 int Shead = fixupAttrSize(headFragment, 1, |
| 692 (SFileAttr + SSecAttr + SSymAttr - 1)); |
| 693 return Shead; |
| 694 } |
| 695 |
| 696 int ARMAsmPrinter::fixupAttrSize(MCDataFragment *F, |
| 697 int secLenOffset, int lenAdjust) { |
| 698 if (F) { |
| 699 SmallString<32> *FC = &F->getContents(); |
| 700 |
| 701 int S = (int)(FC->size() + lenAdjust); |
| 702 (*FC)[secLenOffset+0] = 0xFF & S; |
| 703 (*FC)[secLenOffset+1] = 0xFF & (S>>8); |
| 704 (*FC)[secLenOffset+2] = 0xFF & (S>>16); |
| 705 (*FC)[secLenOffset+3] = 0xFF & (S>>24); |
| 706 return S + lenAdjust; |
| 707 } |
| 708 return 0; |
| 709 } |
| 710 |
580 //===----------------------------------------------------------------------===// | 711 //===----------------------------------------------------------------------===// |
581 | 712 |
582 static MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber, | 713 static MCSymbol *getPICLabel(const char *Prefix, unsigned FunctionNumber, |
583 unsigned LabelId, MCContext &Ctx) { | 714 unsigned LabelId, MCContext &Ctx) { |
584 | 715 |
585 MCSymbol *Label = Ctx.GetOrCreateSymbol(Twine(Prefix) | 716 MCSymbol *Label = Ctx.GetOrCreateSymbol(Twine(Prefix) |
586 + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId)); | 717 + "PC" + Twine(FunctionNumber) + "_" + Twine(LabelId)); |
587 return Label; | 718 return Label; |
588 } | 719 } |
589 | 720 |
(...skipping 682 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1272 | 1403 |
1273 // Force static initialization. | 1404 // Force static initialization. |
1274 extern "C" void LLVMInitializeARMAsmPrinter() { | 1405 extern "C" void LLVMInitializeARMAsmPrinter() { |
1275 RegisterAsmPrinter<ARMAsmPrinter> X(TheARMTarget); | 1406 RegisterAsmPrinter<ARMAsmPrinter> X(TheARMTarget); |
1276 RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget); | 1407 RegisterAsmPrinter<ARMAsmPrinter> Y(TheThumbTarget); |
1277 | 1408 |
1278 TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter); | 1409 TargetRegistry::RegisterMCInstPrinter(TheARMTarget, createARMMCInstPrinter); |
1279 TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter); | 1410 TargetRegistry::RegisterMCInstPrinter(TheThumbTarget, createARMMCInstPrinter); |
1280 } | 1411 } |
1281 | 1412 |
OLD | NEW |