| 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 |