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 #define DEBUG_TYPE "assembler" | 10 #define DEBUG_TYPE "assembler" |
(...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
486 | 486 |
487 case MCFragment::FT_Dwarf: | 487 case MCFragment::FT_Dwarf: |
488 return cast<MCDwarfLineAddrFragment>(F).getContents().size(); | 488 return cast<MCDwarfLineAddrFragment>(F).getContents().size(); |
489 case MCFragment::FT_DwarfFrame: | 489 case MCFragment::FT_DwarfFrame: |
490 return cast<MCDwarfCallFrameFragment>(F).getContents().size(); | 490 return cast<MCDwarfCallFrameFragment>(F).getContents().size(); |
491 } | 491 } |
492 | 492 |
493 llvm_unreachable("invalid fragment kind"); | 493 llvm_unreachable("invalid fragment kind"); |
494 } | 494 } |
495 | 495 |
496 void MCAsmLayout::LayoutFragment(MCFragment *F) { | |
497 MCFragment *Prev = F->getPrevNode(); | |
498 | |
499 // We should never try to recompute something which is up-to-date. | |
500 assert(!isFragmentUpToDate(F) && "Attempt to recompute up-to-date fragment!"); | |
501 // We should never try to compute the fragment layout if it's predecessor | |
502 // isn't up-to-date. | |
503 assert((!Prev || isFragmentUpToDate(Prev)) && | |
504 "Attempt to compute fragment before it's predecessor!"); | |
505 | |
506 ++stats::FragmentLayouts; | |
507 | |
508 // Compute fragment offset and size. | |
509 uint64_t Offset = 0; | |
510 if (Prev) | |
511 Offset += Prev->Offset + getAssembler().computeFragmentSize(*this, *Prev); | |
512 // @LOCALMOD-BEGIN | |
513 F->BundlePadding = getAssembler().ComputeBundlePadding(*this, F, Offset); | |
514 Offset += F->BundlePadding; | |
515 // @LOCALMOD-END | |
516 F->Offset = Offset; | |
517 LastValidFragment[F->getParent()] = F; | |
518 } | |
519 | |
520 // @LOCALMOD-BEGIN | 496 // @LOCALMOD-BEGIN |
497 namespace { | |
521 // Returns number of bytes of padding needed to align to bundle start. | 498 // Returns number of bytes of padding needed to align to bundle start. |
522 static uint64_t AddressToBundlePadding(uint64_t Address, uint64_t BundleMask) { | 499 uint64_t AddressToBundlePadding(uint64_t Address, uint64_t BundleMask) { |
eliben
2012/12/05 00:01:34
Why was static removed?
sehr
2012/12/05 00:11:05
Added back, per the coding conventions.
| |
523 return (~Address + 1) & BundleMask; | 500 return (~Address + 1) & BundleMask; |
524 } | 501 } |
525 | 502 |
526 uint64_t MCAssembler::getBundleSize() const { | 503 uint64_t ComputeNaClAlignMask(uint64_t NaClAlignSize) { |
eliben
2012/12/05 00:01:34
static?
eliben
2012/12/05 00:01:34
why the change s/bundle/nacl/ here? Would we not w
sehr
2012/12/05 00:11:05
Done.
sehr
2012/12/05 00:11:05
Reverted, per your suggestion.
| |
527 return getBackend().getBundleSize(); | 504 uint64_t NaClAlignMask = NaClAlignSize - 1; |
505 assert(NaClAlignSize != 0); | |
506 assert((NaClAlignSize & NaClAlignMask) == 0 && | |
507 "Bundle size must be a power of 2!"); | |
508 return NaClAlignMask; | |
528 } | 509 } |
529 | 510 |
530 uint64_t MCAssembler::getBundleMask() const { | 511 unsigned ComputeGroupSize(MCFragment *F) { |
531 uint64_t BundleSize = getBundleSize(); | |
532 uint64_t BundleMask = BundleSize - 1; | |
533 assert(BundleSize != 0); | |
534 assert((BundleSize & BundleMask) == 0 && | |
535 "Bundle size must be a power of 2!"); | |
536 return BundleMask; | |
537 } | |
538 | |
539 static unsigned ComputeGroupSize(MCFragment *F) { | |
540 if (!F->isBundleGroupStart()) { | 512 if (!F->isBundleGroupStart()) { |
541 return 0; | 513 return 0; |
542 } | 514 } |
543 | 515 |
544 unsigned GroupSize = 0; | 516 unsigned GroupSize = 0; |
545 MCFragment *Cur = F; | 517 MCFragment *Cur = F; |
546 while (Cur) { | 518 while (Cur) { |
547 switch (Cur->getKind()) { | 519 switch (Cur->getKind()) { |
548 default: llvm_unreachable("Unexpected fragment type in bundle!"); | 520 default: llvm_unreachable("Unexpected fragment type in bundle!"); |
549 case MCFragment::FT_Align: | 521 case MCFragment::FT_Align: |
(...skipping 13 matching lines...) Expand all Loading... | |
563 GroupSize += cast<MCTinyFragment>(Cur)->getContents().size(); | 535 GroupSize += cast<MCTinyFragment>(Cur)->getContents().size(); |
564 break; | 536 break; |
565 } | 537 } |
566 if (Cur->isBundleGroupEnd()) | 538 if (Cur->isBundleGroupEnd()) |
567 break; | 539 break; |
568 Cur = Cur->getNextNode(); | 540 Cur = Cur->getNextNode(); |
569 } | 541 } |
570 return GroupSize; | 542 return GroupSize; |
571 } | 543 } |
572 | 544 |
573 uint8_t MCAssembler::ComputeBundlePadding(const MCAsmLayout &Layout, | 545 uint8_t ComputeBundlePadding(const MCAssembler &Asm, |
574 MCFragment *F, | 546 const MCAsmLayout &Layout, |
575 uint64_t FragmentOffset) const { | 547 MCFragment *F, |
548 uint64_t FragmentOffset) { | |
576 if (!F->getParent()->isBundlingEnabled()) | 549 if (!F->getParent()->isBundlingEnabled()) |
577 return 0; | 550 return 0; |
578 | 551 |
579 uint64_t BundleSize = getBundleSize(); | 552 uint64_t BundleSize = Asm.getBackend().getBundleSize(); |
580 uint64_t BundleMask = getBundleMask(); | 553 uint64_t BundleMask = ComputeNaClAlignMask(BundleSize); |
581 unsigned GroupSize = ComputeGroupSize(F); | 554 unsigned GroupSize = ComputeGroupSize(F); |
582 | 555 |
583 if (GroupSize > BundleSize) { | 556 if (GroupSize > BundleSize) { |
584 // EmitFill creates large groups consisting of repeated single bytes. | 557 // EmitFill creates large groups consisting of repeated single bytes. |
585 // These should be safe at any alignment, and in any case we cannot | 558 // These should be safe at any alignment, and in any case we cannot |
586 // fix them up here. | 559 // fix them up here. |
587 return 0; | 560 return 0; |
588 } | 561 } |
589 | 562 |
590 uint64_t Padding = 0; | 563 uint64_t Padding = 0; |
591 uint64_t OffsetInBundle = FragmentOffset & BundleMask; | 564 uint64_t OffsetInBundle = FragmentOffset & BundleMask; |
592 | 565 |
593 if (OffsetInBundle + GroupSize > BundleSize || | 566 if (OffsetInBundle + GroupSize > BundleSize || |
594 F->getBundleAlign() == MCFragment::BundleAlignStart) { | 567 F->getBundleAlign() == MCFragment::BundleAlignStart) { |
595 // If this group would cross the bundle boundary, or this group must be | 568 // If this group would cross the bundle boundary, or this group must be |
596 // aligned to the start of a bundle, then pad up to start of the next bundle | 569 // aligned to the start of a bundle, then pad up to start of the next bundle |
597 Padding += AddressToBundlePadding(OffsetInBundle, BundleMask); | 570 Padding += AddressToBundlePadding(OffsetInBundle, BundleMask); |
598 OffsetInBundle = 0; | 571 OffsetInBundle = 0; |
599 } | 572 } |
600 if (F->getBundleAlign() == MCFragment::BundleAlignEnd) { | 573 if (F->getBundleAlign() == MCFragment::BundleAlignEnd) { |
601 // Push to the end of the bundle | 574 // Push to the end of the bundle |
602 Padding += AddressToBundlePadding(OffsetInBundle + GroupSize, BundleMask); | 575 Padding += AddressToBundlePadding(OffsetInBundle + GroupSize, BundleMask); |
603 } | 576 } |
604 return Padding; | 577 return Padding; |
605 } | 578 } |
606 // @LOCALMOD-END | |
607 | 579 |
608 | |
609 | |
610 | |
611 // @LOCALMOD-BEGIN | |
612 // Write out BundlePadding bytes in NOPs, being careful not to cross a bundle | 580 // Write out BundlePadding bytes in NOPs, being careful not to cross a bundle |
613 // boundary. | 581 // boundary. |
614 static void WriteBundlePadding(const MCAssembler &Asm, | 582 void WriteBundlePadding(const MCAssembler &Asm, |
615 const MCAsmLayout &Layout, | 583 const MCAsmLayout &Layout, |
616 uint64_t Offset, uint64_t TotalPadding, | 584 uint64_t Offset, uint64_t TotalPadding, |
617 MCObjectWriter *OW) { | 585 MCObjectWriter *OW) { |
618 uint64_t BundleSize = Asm.getBundleSize(); | 586 uint64_t BundleSize = Asm.getBackend().getBundleSize(); |
619 uint64_t BundleMask = Asm.getBundleMask(); | 587 uint64_t BundleMask = ComputeNaClAlignMask(BundleSize); |
620 uint64_t PaddingLeft = TotalPadding; | 588 uint64_t PaddingLeft = TotalPadding; |
621 uint64_t StartPos = Offset; | 589 uint64_t StartPos = Offset; |
622 | 590 |
623 bool FirstWrite = true; | 591 bool FirstWrite = true; |
624 while (PaddingLeft > 0) { | 592 while (PaddingLeft > 0) { |
625 uint64_t NopsToWrite = | 593 uint64_t NopsToWrite = |
626 FirstWrite ? AddressToBundlePadding(StartPos, BundleMask) : | 594 FirstWrite ? AddressToBundlePadding(StartPos, BundleMask) : |
627 BundleSize; | 595 BundleSize; |
628 if (NopsToWrite > PaddingLeft) | 596 if (NopsToWrite > PaddingLeft) |
629 NopsToWrite = PaddingLeft; | 597 NopsToWrite = PaddingLeft; |
630 if (!Asm.getBackend().writeNopData(NopsToWrite, OW)) | 598 if (!Asm.getBackend().writeNopData(NopsToWrite, OW)) |
631 report_fatal_error("unable to write nop sequence of " + | 599 report_fatal_error("unable to write nop sequence of " + |
632 Twine(NopsToWrite) + " bytes"); | 600 Twine(NopsToWrite) + " bytes"); |
633 PaddingLeft -= NopsToWrite; | 601 PaddingLeft -= NopsToWrite; |
634 FirstWrite = false; | 602 FirstWrite = false; |
635 } | 603 } |
636 } | 604 } |
605 | |
606 } // namespace | |
637 // @LOCALMOD-END | 607 // @LOCALMOD-END |
638 | 608 |
609 void MCAsmLayout::LayoutFragment(MCFragment *F) { | |
610 MCFragment *Prev = F->getPrevNode(); | |
611 | |
612 // We should never try to recompute something which is up-to-date. | |
613 assert(!isFragmentUpToDate(F) && "Attempt to recompute up-to-date fragment!"); | |
614 // We should never try to compute the fragment layout if it's predecessor | |
615 // isn't up-to-date. | |
616 assert((!Prev || isFragmentUpToDate(Prev)) && | |
617 "Attempt to compute fragment before it's predecessor!"); | |
618 | |
619 ++stats::FragmentLayouts; | |
620 | |
621 // Compute fragment offset and size. | |
622 uint64_t Offset = 0; | |
623 if (Prev) | |
624 Offset += Prev->Offset + getAssembler().computeFragmentSize(*this, *Prev); | |
625 // @LOCALMOD-BEGIN | |
626 F->BundlePadding = ComputeBundlePadding(getAssembler(), *this, F, Offset); | |
627 Offset += F->BundlePadding; | |
628 // @LOCALMOD-END | |
629 F->Offset = Offset; | |
630 LastValidFragment[F->getParent()] = F; | |
631 } | |
632 | |
633 | |
639 /// WriteFragmentData - Write the \p F data to the output file. | 634 /// WriteFragmentData - Write the \p F data to the output file. |
640 static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout, | 635 static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout, |
641 const MCFragment &F) { | 636 const MCFragment &F) { |
642 MCObjectWriter *OW = &Asm.getWriter(); | 637 MCObjectWriter *OW = &Asm.getWriter(); |
643 // @LOCALMOD-BEGIN | 638 // @LOCALMOD-BEGIN |
644 if (F.getParent()->isBundlingEnabled()) { | 639 if (F.getParent()->isBundlingEnabled()) { |
645 uint64_t BundlePadding = Layout.getFragmentPadding(&F); | 640 uint64_t BundlePadding = Layout.getFragmentPadding(&F); |
646 uint64_t PaddingOffset = Layout.getFragmentOffset(&F) - BundlePadding; | 641 uint64_t PaddingOffset = Layout.getFragmentOffset(&F) - BundlePadding; |
647 WriteBundlePadding(Asm, Layout, PaddingOffset, BundlePadding, OW); | 642 WriteBundlePadding(Asm, Layout, PaddingOffset, BundlePadding, OW); |
648 } | 643 } |
(...skipping 21 matching lines...) Expand all Loading... | |
670 Twine(AF.getValueSize()) + | 665 Twine(AF.getValueSize()) + |
671 "' is not a divisor of padding size '" + | 666 "' is not a divisor of padding size '" + |
672 Twine(FragmentSize) + "'"); | 667 Twine(FragmentSize) + "'"); |
673 | 668 |
674 // See if we are aligning with nops, and if so do that first to try to fill | 669 // See if we are aligning with nops, and if so do that first to try to fill |
675 // the Count bytes. Then if that did not fill any bytes or there are any | 670 // the Count bytes. Then if that did not fill any bytes or there are any |
676 // bytes left to fill use the Value and ValueSize to fill the rest. | 671 // bytes left to fill use the Value and ValueSize to fill the rest. |
677 // If we are aligning with nops, ask that target to emit the right data. | 672 // If we are aligning with nops, ask that target to emit the right data. |
678 if (AF.hasEmitNops()) { | 673 if (AF.hasEmitNops()) { |
679 // @LOCALMOD-BEGIN | 674 // @LOCALMOD-BEGIN |
680 if (Asm.getBundleSize()) { | 675 if (Asm.getBackend().getBundleSize()) { |
681 WriteBundlePadding(Asm, Layout, | 676 WriteBundlePadding(Asm, Layout, |
682 Layout.getFragmentOffset(&F), | 677 Layout.getFragmentOffset(&F), |
683 FragmentSize, | 678 FragmentSize, |
684 OW); | 679 OW); |
685 break; | 680 break; |
686 } | 681 } |
687 // @LOCALMOD-END | 682 // @LOCALMOD-END |
688 | 683 |
689 if (!Asm.getBackend().writeNopData(Count, OW)) | 684 if (!Asm.getBackend().writeNopData(Count, OW)) |
690 report_fatal_error("unable to write nop sequence of " + | 685 report_fatal_error("unable to write nop sequence of " + |
(...skipping 594 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1285 | 1280 |
1286 // anchors for MC*Fragment vtables | 1281 // anchors for MC*Fragment vtables |
1287 void MCDataFragment::anchor() { } | 1282 void MCDataFragment::anchor() { } |
1288 void MCInstFragment::anchor() { } | 1283 void MCInstFragment::anchor() { } |
1289 void MCAlignFragment::anchor() { } | 1284 void MCAlignFragment::anchor() { } |
1290 void MCFillFragment::anchor() { } | 1285 void MCFillFragment::anchor() { } |
1291 void MCOrgFragment::anchor() { } | 1286 void MCOrgFragment::anchor() { } |
1292 void MCLEBFragment::anchor() { } | 1287 void MCLEBFragment::anchor() { } |
1293 void MCDwarfLineAddrFragment::anchor() { } | 1288 void MCDwarfLineAddrFragment::anchor() { } |
1294 void MCDwarfCallFrameFragment::anchor() { } | 1289 void MCDwarfCallFrameFragment::anchor() { } |
OLD | NEW |