Changeset View
Changeset View
Standalone View
Standalone View
llvm/lib/MC/MCAssembler.cpp
Show First 20 Lines • Show All 599 Lines • ▼ Show 20 Lines | static void writeFragment(raw_ostream &OS, const MCAssembler &Asm, | ||||
case MCFragment::FT_LEB: { | case MCFragment::FT_LEB: { | ||||
const MCLEBFragment &LF = cast<MCLEBFragment>(F); | const MCLEBFragment &LF = cast<MCLEBFragment>(F); | ||||
OS << LF.getContents(); | OS << LF.getContents(); | ||||
break; | break; | ||||
} | } | ||||
case MCFragment::FT_BoundaryAlign: { | case MCFragment::FT_BoundaryAlign: { | ||||
const MCBoundaryAlignFragment &BF = cast<MCBoundaryAlignFragment>(F); | |||||
if (BF.hasEmitNops()) { | |||||
if (!Asm.getBackend().writeNopData(OS, FragmentSize)) | if (!Asm.getBackend().writeNopData(OS, FragmentSize)) | ||||
report_fatal_error("unable to write nop sequence of " + | report_fatal_error("unable to write nop sequence of " + | ||||
Twine(FragmentSize) + " bytes"); | Twine(FragmentSize) + " bytes"); | ||||
} else if (BF.hasValue()) { | |||||
for (uint64_t i = 0; i != FragmentSize; ++i) | |||||
OS << char(BF.getValue()); | |||||
LuoYuanke: Why we declare Value as int64_t in MCAlignFragment? It seems only 1 byte is needed. Or we add… | |||||
I didn't decalre Value as int64_t, I declared it as Optional<uint8_t> skan: I didn't decalre `Value` as `int64_t`, I declared it as `Optional<uint8_t>` | |||||
Not Done ReplyInline ActionsYou are right. LuoYuanke: You are right. | |||||
} | |||||
break; | break; | ||||
} | } | ||||
case MCFragment::FT_SymbolId: { | case MCFragment::FT_SymbolId: { | ||||
const MCSymbolIdFragment &SF = cast<MCSymbolIdFragment>(F); | const MCSymbolIdFragment &SF = cast<MCSymbolIdFragment>(F); | ||||
support::endian::write<uint32_t>(OS, SF.getSymbol()->getIndex(), Endian); | support::endian::write<uint32_t>(OS, SF.getSymbol()->getIndex(), Endian); | ||||
break; | break; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 362 Lines • ▼ Show 20 Lines | |||||
static bool needPadding(uint64_t StartAddr, uint64_t Size, | static bool needPadding(uint64_t StartAddr, uint64_t Size, | ||||
Align BoundaryAlignment) { | Align BoundaryAlignment) { | ||||
return mayCrossBoundary(StartAddr, Size, BoundaryAlignment) || | return mayCrossBoundary(StartAddr, Size, BoundaryAlignment) || | ||||
isAgainstBoundary(StartAddr, Size, BoundaryAlignment); | isAgainstBoundary(StartAddr, Size, BoundaryAlignment); | ||||
} | } | ||||
bool MCAssembler::relaxBoundaryAlign(MCAsmLayout &Layout, | bool MCAssembler::relaxBoundaryAlign(MCAsmLayout &Layout, | ||||
MCBoundaryAlignFragment &BF) { | MCBoundaryAlignFragment &BF) { | ||||
// The MCBoundaryAlignFragment that doesn't emit NOP should not be relaxed. | // The MCBoundaryAlignFragment that does not emit anything or not have any | ||||
if (!BF.canEmitNops()) | // fragment to be aligned should not be relaxed. | ||||
if (!BF.hasEmit() || !BF.getFragment()) | |||||
return false; | return false; | ||||
uint64_t AlignedOffset = Layout.getFragmentOffset(BF.getNextNode()); | // Compute the size of all the fragments in the range we're trying to align. | ||||
uint64_t AlignedSize = 0; | const MCFragment *TF = BF.getFragment(); | ||||
const MCFragment *F = BF.getNextNode(); | uint64_t AlignedSize = computeFragmentSize(Layout, *TF); | ||||
// If the branch is unfused, it is emitted into one fragment, otherwise it is | uint64_t AlignedOffset = Layout.getFragmentOffset(TF); | ||||
// emitted into two fragments at most, the next MCBoundaryAlignFragment(if | for (auto *F = TF->getPrevNode(); !isa<MCBoundaryAlignFragment>(F); | ||||
Is it guaranteed F->getPrevNode() will not be executed on the first Fragment? MaskRay: Is it guaranteed `F->getPrevNode()` will not be executed on the first Fragment? | |||||
// exists) also marks the end of the branch. | F = F->getPrevNode()) { | ||||
for (auto i = 0, N = BF.isFused() ? 2 : 1; | uint64_t Size = computeFragmentSize(Layout, *F); | ||||
i != N && !isa<MCBoundaryAlignFragment>(F); ++i, F = F->getNextNode()) { | AlignedSize += Size; | ||||
AlignedSize += computeFragmentSize(Layout, *F); | AlignedOffset -= Size; | ||||
Not Done ReplyInline ActionsAlignedOffset can be defined after AlignedSize is computed. MaskRay: `AlignedOffset` can be defined after AlignedSize is computed. | |||||
Sorry, I didn't get your point. skan: Sorry, I didn't get your point. | |||||
} | } | ||||
uint64_t OldSize = BF.getSize(); | |||||
AlignedOffset -= OldSize; | // Compute the size of all the MCBoundaryAlignFragments in the range | ||||
// [BF,BF.getFragment). | |||||
uint64_t FixedValue = [&]() { | |||||
Not Done ReplyInline ActionsFixedValue doesn't have to be an immediately invoked function expression. MaskRay: FixedValue doesn't have to be an immediately invoked function expression. | |||||
uint64_t N = 0; | |||||
for (const MCFragment *F = &BF; F != TF; F = F->getNextNode()) | |||||
if (auto *MBF = dyn_cast<MCBoundaryAlignFragment>(F)) | |||||
N += MBF->getSize(); | |||||
return N; | |||||
}(); | |||||
AlignedOffset -= FixedValue; | |||||
Align BoundaryAlignment = BF.getAlignment(); | Align BoundaryAlignment = BF.getAlignment(); | ||||
uint64_t NewSize = needPadding(AlignedOffset, AlignedSize, BoundaryAlignment) | uint64_t NewSize = needPadding(AlignedOffset, AlignedSize, BoundaryAlignment) | ||||
? offsetToAlignment(AlignedOffset, BoundaryAlignment) | ? offsetToAlignment(AlignedOffset, BoundaryAlignment) | ||||
: 0U; | : 0U; | ||||
if (!BF.hasEmitNops()) { | |||||
assert((*(BF.getNextNode())).hasInstructions() && | |||||
*(xxx) -> xxx-> MaskRay: `*(xxx)` -> `xxx->` | |||||
"The fragment doesn't have any instruction."); | |||||
NewSize = std::min({NewSize, | |||||
15 - computeFragmentSize(Layout, *(BF.getNextNode())), | |||||
static_cast<uint64_t>(BF.getMaxBytesToEmit())}); | |||||
assert(computeFragmentSize(Layout, *(BF.getNextNode())) <= 15 && | |||||
"The fragment's size must be no longer than 15 since it should only " | |||||
"hold one instruction."); | |||||
} | |||||
uint64_t OldSize = BF.getSize(); | |||||
if (NewSize == OldSize) | if (NewSize == OldSize) | ||||
if (NewSize == BF.getSize() MaskRay: `if (NewSize == BF.getSize()` | |||||
return false; | return false; | ||||
BF.setSize(NewSize); | BF.setSize(NewSize); | ||||
Layout.invalidateFragmentsFrom(&BF); | Layout.invalidateFragmentsFrom(&BF); | ||||
Not Done ReplyInline ActionsThis 15 limit is X86 specific. Seems weird to have it mentioned in a target independent file. Can we abstract this somehow? It can probably happen after the branch. craig.topper: This 15 limit is X86 specific. Seems weird to have it mentioned in a target independent file. | |||||
return true; | return true; | ||||
} | } | ||||
bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout, | bool MCAssembler::relaxDwarfLineAddr(MCAsmLayout &Layout, | ||||
Not Done ReplyInline ActionsSame with this 15. craig.topper: Same with this 15. | |||||
MCDwarfLineAddrFragment &DF) { | MCDwarfLineAddrFragment &DF) { | ||||
MCContext &Context = Layout.getAssembler().getContext(); | MCContext &Context = Layout.getAssembler().getContext(); | ||||
uint64_t OldSize = DF.getContents().size(); | uint64_t OldSize = DF.getContents().size(); | ||||
int64_t AddrDelta; | int64_t AddrDelta; | ||||
bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout); | bool Abs = DF.getAddrDelta().evaluateKnownAbsolute(AddrDelta, Layout); | ||||
assert(Abs && "We created a line delta with an invalid expression"); | assert(Abs && "We created a line delta with an invalid expression"); | ||||
(void)Abs; | (void)Abs; | ||||
int64_t LineDelta; | int64_t LineDelta; | ||||
▲ Show 20 Lines • Show All 176 Lines • Show Last 20 Lines |
Why we declare Value as int64_t in MCAlignFragment? It seems only 1 byte is needed. Or we add assert(BF.getValueSize() == 1)?