OLD | NEW |
1 //===- lib/MC/MCAssembler.cpp - Assembler Backend Implementation ----------===// | 1 //===- lib/MC/MCAssembler.cpp - Assembler Backend Implementation ----------===// |
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 #include "llvm/MC/MCAssembler.h" | 10 #include "llvm/MC/MCAssembler.h" |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
212 | 212 |
213 uint64_t MCAsmLayout::getSectionFileSize(const MCSectionData *SD) const { | 213 uint64_t MCAsmLayout::getSectionFileSize(const MCSectionData *SD) const { |
214 // Virtual sections have no file size. | 214 // Virtual sections have no file size. |
215 if (SD->getSection().isVirtualSection()) | 215 if (SD->getSection().isVirtualSection()) |
216 return 0; | 216 return 0; |
217 | 217 |
218 // Otherwise, the file size is the same as the address space size. | 218 // Otherwise, the file size is the same as the address space size. |
219 return getSectionAddressSize(SD); | 219 return getSectionAddressSize(SD); |
220 } | 220 } |
221 | 221 |
222 uint64_t MCAsmLayout::computeBundlePadding(const MCFragment *F, | 222 uint64_t llvm::computeBundlePadding(const MCAssembler &Assembler, |
223 uint64_t FOffset, uint64_t FSize) { | 223 const MCFragment *F, |
| 224 uint64_t FOffset, uint64_t FSize) { |
224 uint64_t BundleSize = Assembler.getBundleAlignSize(); | 225 uint64_t BundleSize = Assembler.getBundleAlignSize(); |
225 assert(BundleSize > 0 && | 226 assert(BundleSize > 0 && |
226 "computeBundlePadding should only be called if bundling is enabled"); | 227 "computeBundlePadding should only be called if bundling is enabled"); |
227 uint64_t BundleMask = BundleSize - 1; | 228 uint64_t BundleMask = BundleSize - 1; |
228 uint64_t OffsetInBundle = FOffset & BundleMask; | 229 uint64_t OffsetInBundle = FOffset & BundleMask; |
229 uint64_t EndOfFragment = OffsetInBundle + FSize; | 230 uint64_t EndOfFragment = OffsetInBundle + FSize; |
230 | 231 |
231 // There are two kinds of bundling restrictions: | 232 // There are two kinds of bundling restrictions: |
232 // | 233 // |
233 // 1) For alignToBundleEnd(), add padding to ensure that the fragment will | 234 // 1) For alignToBundleEnd(), add padding to ensure that the fragment will |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 else | 330 else |
330 IP = MI->second; | 331 IP = MI->second; |
331 if (!ExactMatch && Subsection != 0) { | 332 if (!ExactMatch && Subsection != 0) { |
332 // The GNU as documentation claims that subsections have an alignment of 4, | 333 // The GNU as documentation claims that subsections have an alignment of 4, |
333 // although this appears not to be the case. | 334 // although this appears not to be the case. |
334 MCFragment *F = new MCDataFragment(); | 335 MCFragment *F = new MCDataFragment(); |
335 SubsectionFragmentMap.insert(MI, std::make_pair(Subsection, F)); | 336 SubsectionFragmentMap.insert(MI, std::make_pair(Subsection, F)); |
336 getFragmentList().insert(IP, F); | 337 getFragmentList().insert(IP, F); |
337 F->setParent(this); | 338 F->setParent(this); |
338 } | 339 } |
| 340 |
339 return IP; | 341 return IP; |
340 } | 342 } |
341 | 343 |
342 void MCSectionData::setBundleLockState(BundleLockStateType NewState) { | 344 void MCSectionData::setBundleLockState(BundleLockStateType NewState) { |
343 if (NewState == NotBundleLocked) { | 345 if (NewState == NotBundleLocked) { |
344 if (BundleLockNestingDepth == 0) { | 346 if (BundleLockNestingDepth == 0) { |
345 report_fatal_error("Mismatched bundle_lock/unlock directives"); | 347 report_fatal_error("Mismatched bundle_lock/unlock directives"); |
346 } | 348 } |
347 if (--BundleLockNestingDepth == 0) { | 349 if (--BundleLockNestingDepth == 0) { |
348 BundleLockState = NotBundleLocked; | 350 BundleLockState = NotBundleLocked; |
(...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
631 // ------------------------------------- | 633 // ------------------------------------- |
632 // Prev |##########| F | | 634 // Prev |##########| F | |
633 // ------------------------------------- | 635 // ------------------------------------- |
634 // ^ | 636 // ^ |
635 // | | 637 // | |
636 // F->Offset | 638 // F->Offset |
637 // | 639 // |
638 // The fragment's offset will point to after the padding, and its computed | 640 // The fragment's offset will point to after the padding, and its computed |
639 // size won't include the padding. | 641 // size won't include the padding. |
640 // | 642 // |
641 if (Assembler.isBundlingEnabled() && F->hasInstructions()) { | 643 // When the -mc-relax-all flag is used, we optimize bundling by writting the |
| 644 // bundle padding directly into fragments when the instructions are emitted |
| 645 // inside the streamer. |
| 646 // |
| 647 if (Assembler.isBundlingEnabled() && !Assembler.getRelaxAll() && |
| 648 F->hasInstructions()) { |
642 assert(isa<MCEncodedFragment>(F) && | 649 assert(isa<MCEncodedFragment>(F) && |
643 "Only MCEncodedFragment implementations have instructions"); | 650 "Only MCEncodedFragment implementations have instructions"); |
644 uint64_t FSize = Assembler.computeFragmentSize(*this, *F); | 651 uint64_t FSize = Assembler.computeFragmentSize(*this, *F); |
645 | 652 |
646 if (FSize > Assembler.getBundleAlignSize()) | 653 if (FSize > Assembler.getBundleAlignSize()) |
647 report_fatal_error("Fragment can't be larger than a bundle size"); | 654 report_fatal_error("Fragment can't be larger than a bundle size"); |
648 | 655 |
649 uint64_t RequiredBundlePadding = computeBundlePadding(F, F->Offset, FSize); | 656 uint64_t RequiredBundlePadding = computeBundlePadding(Assembler, F, |
| 657 F->Offset, FSize); |
650 if (RequiredBundlePadding > UINT8_MAX) | 658 if (RequiredBundlePadding > UINT8_MAX) |
651 report_fatal_error("Padding cannot exceed 255 bytes"); | 659 report_fatal_error("Padding cannot exceed 255 bytes"); |
652 F->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding)); | 660 F->setBundlePadding(static_cast<uint8_t>(RequiredBundlePadding)); |
653 F->Offset += RequiredBundlePadding; | 661 F->Offset += RequiredBundlePadding; |
654 } | 662 } |
655 } | 663 } |
656 | 664 |
657 /// \brief Write the contents of a fragment to the given object writer. Expects | 665 /// \brief Write the contents of a fragment to the given object writer. Expects |
658 /// a MCEncodedFragment. | 666 /// a MCEncodedFragment. |
659 static void writeFragmentContents(const MCFragment &F, MCObjectWriter *OW) { | 667 static void writeFragmentContents(const MCFragment &F, MCObjectWriter *OW) { |
660 const MCEncodedFragment &EF = cast<MCEncodedFragment>(F); | 668 const MCEncodedFragment &EF = cast<MCEncodedFragment>(F); |
661 OW->WriteBytes(EF.getContents()); | 669 OW->WriteBytes(EF.getContents()); |
662 } | 670 } |
663 | 671 |
664 /// \brief Write the fragment \p F to the output file. | 672 void MCAssembler::writeFragmentPadding(const MCFragment &F, uint64_t FSize, |
665 static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, | 673 MCObjectWriter *OW) const { |
666 const MCFragment &F) { | |
667 MCObjectWriter *OW = &Asm.getWriter(); | |
668 | |
669 // FIXME: Embed in fragments instead? | |
670 uint64_t FragmentSize = Asm.computeFragmentSize(Layout, F); | |
671 | |
672 // Should NOP padding be written out before this fragment? | 674 // Should NOP padding be written out before this fragment? |
673 unsigned BundlePadding = F.getBundlePadding(); | 675 unsigned BundlePadding = F.getBundlePadding(); |
674 if (BundlePadding > 0) { | 676 if (BundlePadding > 0) { |
675 assert(Asm.isBundlingEnabled() && | 677 assert(isBundlingEnabled() && |
676 "Writing bundle padding with disabled bundling"); | 678 "Writing bundle padding with disabled bundling"); |
677 assert(F.hasInstructions() && | 679 assert(F.hasInstructions() && |
678 "Writing bundle padding for a fragment without instructions"); | 680 "Writing bundle padding for a fragment without instructions"); |
679 | 681 |
680 unsigned TotalLength = BundlePadding + static_cast<unsigned>(FragmentSize); | 682 unsigned TotalLength = BundlePadding + static_cast<unsigned>(FSize); |
681 if (F.alignToBundleEnd() && TotalLength > Asm.getBundleAlignSize()) { | 683 if (F.alignToBundleEnd() && TotalLength > getBundleAlignSize()) { |
682 // If the padding itself crosses a bundle boundary, it must be emitted | 684 // If the padding itself crosses a bundle boundary, it must be emitted |
683 // in 2 pieces, since even nop instructions must not cross boundaries. | 685 // in 2 pieces, since even nop instructions must not cross boundaries. |
684 // v--------------v <- BundleAlignSize | 686 // v--------------v <- BundleAlignSize |
685 // v---------v <- BundlePadding | 687 // v---------v <- BundlePadding |
686 // ---------------------------- | 688 // ---------------------------- |
687 // | Prev |####|####| F | | 689 // | Prev |####|####| F | |
688 // ---------------------------- | 690 // ---------------------------- |
689 // ^-------------------^ <- TotalLength | 691 // ^-------------------^ <- TotalLength |
690 unsigned DistanceToBoundary = TotalLength - Asm.getBundleAlignSize(); | 692 unsigned DistanceToBoundary = TotalLength - getBundleAlignSize(); |
691 if (!Asm.getBackend().writeNopData(DistanceToBoundary, OW)) | 693 if (!getBackend().writeNopData(DistanceToBoundary, OW)) |
692 report_fatal_error("unable to write NOP sequence of " + | 694 report_fatal_error("unable to write NOP sequence of " + |
693 Twine(DistanceToBoundary) + " bytes"); | 695 Twine(DistanceToBoundary) + " bytes"); |
694 BundlePadding -= DistanceToBoundary; | 696 BundlePadding -= DistanceToBoundary; |
695 } | 697 } |
696 if (!Asm.getBackend().writeNopData(BundlePadding, OW)) | 698 if (!getBackend().writeNopData(BundlePadding, OW)) |
697 report_fatal_error("unable to write NOP sequence of " + | 699 report_fatal_error("unable to write NOP sequence of " + |
698 Twine(BundlePadding) + " bytes"); | 700 Twine(BundlePadding) + " bytes"); |
699 } | 701 } |
| 702 } |
| 703 |
| 704 /// \brief Write the fragment \p F to the output file. |
| 705 static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, |
| 706 const MCFragment &F) { |
| 707 MCObjectWriter *OW = &Asm.getWriter(); |
| 708 |
| 709 // FIXME: Embed in fragments instead? |
| 710 uint64_t FragmentSize = Asm.computeFragmentSize(Layout, F); |
| 711 |
| 712 Asm.writeFragmentPadding(F, FragmentSize, OW); |
700 | 713 |
701 // This variable (and its dummy usage) is to participate in the assert at | 714 // This variable (and its dummy usage) is to participate in the assert at |
702 // the end of the function. | 715 // the end of the function. |
703 uint64_t Start = OW->getStream().tell(); | 716 uint64_t Start = OW->getStream().tell(); |
704 (void) Start; | 717 (void) Start; |
705 | 718 |
706 ++stats::EmittedFragments; | 719 ++stats::EmittedFragments; |
707 | 720 |
708 switch (F.getKind()) { | 721 switch (F.getKind()) { |
709 case MCFragment::FT_Align: { | 722 case MCFragment::FT_Align: { |
(...skipping 599 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1309 void MCEncodedFragmentWithFixups::anchor() { } | 1322 void MCEncodedFragmentWithFixups::anchor() { } |
1310 void MCDataFragment::anchor() { } | 1323 void MCDataFragment::anchor() { } |
1311 void MCCompactEncodedInstFragment::anchor() { } | 1324 void MCCompactEncodedInstFragment::anchor() { } |
1312 void MCRelaxableFragment::anchor() { } | 1325 void MCRelaxableFragment::anchor() { } |
1313 void MCAlignFragment::anchor() { } | 1326 void MCAlignFragment::anchor() { } |
1314 void MCFillFragment::anchor() { } | 1327 void MCFillFragment::anchor() { } |
1315 void MCOrgFragment::anchor() { } | 1328 void MCOrgFragment::anchor() { } |
1316 void MCLEBFragment::anchor() { } | 1329 void MCLEBFragment::anchor() { } |
1317 void MCDwarfLineAddrFragment::anchor() { } | 1330 void MCDwarfLineAddrFragment::anchor() { } |
1318 void MCDwarfCallFrameFragment::anchor() { } | 1331 void MCDwarfCallFrameFragment::anchor() { } |
OLD | NEW |