Chromium Code Reviews| 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 |