mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-02-04 07:32:13 +00:00
Add the align_to_end option to .bundle_lock in the MC implementation of aligned
bundling. The document describing this feature and the implementation has also been updated: https://sites.google.com/a/chromium.org/dev/nativeclient/pnacl/aligned-bundling-support-in-llvm git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@171797 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
d3ae2866d1
commit
6c1d4972cf
@ -100,9 +100,12 @@ public:
|
||||
void setLayoutOrder(unsigned Value) { LayoutOrder = Value; }
|
||||
|
||||
/// \brief Does this fragment have instructions emitted into it? By default
|
||||
/// this is false, but specific fragment types may set it to true.
|
||||
/// this is false, but specific fragment types may set it to true.
|
||||
virtual bool hasInstructions() const { return false; }
|
||||
|
||||
/// \brief Should this fragment be placed at the end of an aligned bundle?
|
||||
virtual bool alignToBundleEnd() const { return false; }
|
||||
|
||||
/// \brief Get the padding size that must be inserted before this fragment.
|
||||
/// Used for bundling. By default, no padding is inserted.
|
||||
/// Note that padding size is restricted to 8 bits. This is an optimization
|
||||
@ -165,6 +168,9 @@ class MCDataFragment : public MCEncodedFragment {
|
||||
/// \brief Does this fragment contain encoded instructions anywhere in it?
|
||||
bool HasInstructions;
|
||||
|
||||
/// \brief Should this fragment be aligned to the end of a bundle?
|
||||
bool AlignToBundleEnd;
|
||||
|
||||
SmallVector<char, 32> Contents;
|
||||
|
||||
/// Fixups - The list of fixups in this fragment.
|
||||
@ -172,7 +178,7 @@ class MCDataFragment : public MCEncodedFragment {
|
||||
public:
|
||||
MCDataFragment(MCSectionData *SD = 0)
|
||||
: MCEncodedFragment(FT_Data, SD),
|
||||
HasInstructions(false)
|
||||
HasInstructions(false), AlignToBundleEnd(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -190,6 +196,9 @@ public:
|
||||
virtual bool hasInstructions() const { return HasInstructions; }
|
||||
virtual void setHasInstructions(bool V) { HasInstructions = V; }
|
||||
|
||||
virtual bool alignToBundleEnd() const { return AlignToBundleEnd; }
|
||||
virtual void setAlignToBundleEnd(bool V) { AlignToBundleEnd = V; }
|
||||
|
||||
fixup_iterator fixup_begin() { return Fixups.begin(); }
|
||||
const_fixup_iterator fixup_begin() const { return Fixups.begin(); }
|
||||
|
||||
@ -476,6 +485,12 @@ public:
|
||||
typedef FragmentListType::const_reverse_iterator const_reverse_iterator;
|
||||
typedef FragmentListType::reverse_iterator reverse_iterator;
|
||||
|
||||
/// \brief Express the state of bundle locked groups while emitting code.
|
||||
enum BundleLockStateType {
|
||||
NotBundleLocked,
|
||||
BundleLocked,
|
||||
BundleLockedAlignToEnd
|
||||
};
|
||||
private:
|
||||
FragmentListType Fragments;
|
||||
const MCSection *Section;
|
||||
@ -489,8 +504,8 @@ private:
|
||||
/// Alignment - The maximum alignment seen in this section.
|
||||
unsigned Alignment;
|
||||
|
||||
/// \brief We're currently inside a bundle-locked group.
|
||||
bool BundleLocked;
|
||||
/// \brief Keeping track of bundle-locked state.
|
||||
BundleLockStateType BundleLockState;
|
||||
|
||||
/// \brief We've seen a bundle_lock directive but not its first instruction
|
||||
/// yet.
|
||||
@ -549,11 +564,15 @@ public:
|
||||
bool empty() const { return Fragments.empty(); }
|
||||
|
||||
bool isBundleLocked() const {
|
||||
return BundleLocked;
|
||||
return BundleLockState != NotBundleLocked;
|
||||
}
|
||||
|
||||
void setBundleLocked(bool IsLocked) {
|
||||
BundleLocked = IsLocked;
|
||||
BundleLockStateType getBundleLockState() const {
|
||||
return BundleLockState;
|
||||
}
|
||||
|
||||
void setBundleLockState(BundleLockStateType NewState) {
|
||||
BundleLockState = NewState;
|
||||
}
|
||||
|
||||
bool isBundleGroupBeforeFirstInst() const {
|
||||
|
@ -85,7 +85,7 @@ private:
|
||||
virtual void EmitInstToData(const MCInst &Inst);
|
||||
|
||||
virtual void EmitBundleAlignMode(unsigned AlignPow2);
|
||||
virtual void EmitBundleLock();
|
||||
virtual void EmitBundleLock(bool AlignToEnd);
|
||||
virtual void EmitBundleUnlock();
|
||||
|
||||
void fixSymbolsInTLSFixups(const MCExpr *expr);
|
||||
|
@ -84,7 +84,7 @@ public:
|
||||
virtual void EmitInstToFragment(const MCInst &Inst);
|
||||
|
||||
virtual void EmitBundleAlignMode(unsigned AlignPow2);
|
||||
virtual void EmitBundleLock();
|
||||
virtual void EmitBundleLock(bool AlignToEnd);
|
||||
virtual void EmitBundleUnlock();
|
||||
virtual void EmitBytes(StringRef Data, unsigned AddrSpace);
|
||||
virtual void EmitValueToAlignment(unsigned ByteAlignment,
|
||||
|
@ -562,7 +562,10 @@ namespace llvm {
|
||||
virtual void EmitBundleAlignMode(unsigned AlignPow2) = 0;
|
||||
|
||||
/// \brief The following instructions are a bundle-locked group.
|
||||
virtual void EmitBundleLock() = 0;
|
||||
///
|
||||
/// \param AlignToEnd - If true, the bundle-locked group will be aligned to
|
||||
/// the end of a bundle.
|
||||
virtual void EmitBundleLock(bool AlignToEnd) = 0;
|
||||
|
||||
/// \brief Ends a bundle-locked group.
|
||||
virtual void EmitBundleUnlock() = 0;
|
||||
|
@ -260,7 +260,7 @@ public:
|
||||
virtual void EmitInstruction(const MCInst &Inst);
|
||||
|
||||
virtual void EmitBundleAlignMode(unsigned AlignPow2);
|
||||
virtual void EmitBundleLock();
|
||||
virtual void EmitBundleLock(bool AlignToEnd);
|
||||
virtual void EmitBundleUnlock();
|
||||
|
||||
/// EmitRawText - If this file is backed by an assembly streamer, this dumps
|
||||
@ -1370,8 +1370,10 @@ void MCAsmStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
|
||||
EmitEOL();
|
||||
}
|
||||
|
||||
void MCAsmStreamer::EmitBundleLock() {
|
||||
void MCAsmStreamer::EmitBundleLock(bool AlignToEnd) {
|
||||
OS << "\t.bundle_lock";
|
||||
if (AlignToEnd)
|
||||
OS << " align_to_end";
|
||||
EmitEOL();
|
||||
}
|
||||
|
||||
|
@ -167,10 +167,34 @@ uint64_t MCAsmLayout::computeBundlePadding(const MCFragment *F,
|
||||
"computeBundlePadding should only be called if bundling is enabled");
|
||||
uint64_t BundleMask = BundleSize - 1;
|
||||
uint64_t OffsetInBundle = FOffset & BundleMask;
|
||||
uint64_t EndOfFragment = OffsetInBundle + FSize;
|
||||
|
||||
// If the fragment would cross a bundle boundary, add enough padding until
|
||||
// the end of the current bundle.
|
||||
if (OffsetInBundle + FSize > BundleSize)
|
||||
// There are two kinds of bundling restrictions:
|
||||
//
|
||||
// 1) For alignToBundleEnd(), add padding to ensure that the fragment will
|
||||
// *end* on a bundle boundary.
|
||||
// 2) Otherwise, check if the fragment would cross a bundle boundary. If it
|
||||
// would, add padding until the end of the bundle so that the fragment
|
||||
// will start in a new one.
|
||||
if (F->alignToBundleEnd()) {
|
||||
// Three possibilities here:
|
||||
//
|
||||
// A) The fragment just happens to end at a bundle boundary, so we're good.
|
||||
// B) The fragment ends before the current bundle boundary: pad it just
|
||||
// enough to reach the boundary.
|
||||
// C) The fragment ends after the current bundle boundary: pad it until it
|
||||
// reaches the end of the next bundle boundary.
|
||||
//
|
||||
// Note: this code could be made shorter with some modulo trickery, but it's
|
||||
// intentionally kept in its more explicit form for simplicity.
|
||||
if (EndOfFragment == BundleSize)
|
||||
return 0;
|
||||
else if (EndOfFragment < BundleSize)
|
||||
return BundleSize - EndOfFragment;
|
||||
else { // EndOfFragment > BundleSize
|
||||
return 2 * BundleSize - EndOfFragment;
|
||||
}
|
||||
} else if (EndOfFragment > BundleSize)
|
||||
return BundleSize - OffsetInBundle;
|
||||
else
|
||||
return 0;
|
||||
@ -204,7 +228,7 @@ MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
|
||||
: Section(&_Section),
|
||||
Ordinal(~UINT32_C(0)),
|
||||
Alignment(1),
|
||||
BundleLocked(false), BundleGroupBeforeFirstInst(false),
|
||||
BundleLockState(NotBundleLocked), BundleGroupBeforeFirstInst(false),
|
||||
HasInstructions(false)
|
||||
{
|
||||
if (A)
|
||||
|
@ -379,8 +379,14 @@ void MCELFStreamer::EmitInstToData(const MCInst &Inst) {
|
||||
MCSectionData *SD = getCurrentSectionData();
|
||||
if (SD->isBundleLocked() && !SD->isBundleGroupBeforeFirstInst())
|
||||
DF = getOrCreateDataFragment();
|
||||
else
|
||||
else {
|
||||
DF = new MCDataFragment(SD);
|
||||
if (SD->getBundleLockState() == MCSectionData::BundleLockedAlignToEnd) {
|
||||
// If this is a new fragment created for a bundle-locked group, and the
|
||||
// group was marked as "align_to_end", set a flag in the fragment.
|
||||
DF->setAlignToBundleEnd(true);
|
||||
}
|
||||
}
|
||||
|
||||
// We're now emitting an instruction in a bundle group, so this flag has
|
||||
// to be turned off.
|
||||
@ -407,7 +413,7 @@ void MCELFStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
|
||||
report_fatal_error(".bundle_align_mode should be only set once per file");
|
||||
}
|
||||
|
||||
void MCELFStreamer::EmitBundleLock() {
|
||||
void MCELFStreamer::EmitBundleLock(bool AlignToEnd) {
|
||||
MCSectionData *SD = getCurrentSectionData();
|
||||
|
||||
// Sanity checks
|
||||
@ -417,7 +423,8 @@ void MCELFStreamer::EmitBundleLock() {
|
||||
else if (SD->isBundleLocked())
|
||||
report_fatal_error("Nesting of .bundle_lock is forbidden");
|
||||
|
||||
SD->setBundleLocked(true);
|
||||
SD->setBundleLockState(AlignToEnd ? MCSectionData::BundleLockedAlignToEnd :
|
||||
MCSectionData::BundleLocked);
|
||||
SD->setBundleGroupBeforeFirstInst(true);
|
||||
}
|
||||
|
||||
@ -432,7 +439,7 @@ void MCELFStreamer::EmitBundleUnlock() {
|
||||
else if (SD->isBundleGroupBeforeFirstInst())
|
||||
report_fatal_error("Empty bundle-locked group is forbidden");
|
||||
|
||||
SD->setBundleLocked(false);
|
||||
SD->setBundleLockState(MCSectionData::NotBundleLocked);
|
||||
}
|
||||
|
||||
void MCELFStreamer::FinishImpl() {
|
||||
|
@ -96,7 +96,7 @@ namespace {
|
||||
virtual void EmitInstruction(const MCInst &Inst) {}
|
||||
|
||||
virtual void EmitBundleAlignMode(unsigned AlignPow2) {}
|
||||
virtual void EmitBundleLock() {}
|
||||
virtual void EmitBundleLock(bool AlignToEnd) {}
|
||||
virtual void EmitBundleUnlock() {}
|
||||
|
||||
virtual void FinishImpl() {}
|
||||
|
@ -233,7 +233,7 @@ void MCObjectStreamer::EmitBundleAlignMode(unsigned AlignPow2) {
|
||||
llvm_unreachable(BundlingNotImplementedMsg);
|
||||
}
|
||||
|
||||
void MCObjectStreamer::EmitBundleLock() {
|
||||
void MCObjectStreamer::EmitBundleLock(bool AlignToEnd) {
|
||||
llvm_unreachable(BundlingNotImplementedMsg);
|
||||
}
|
||||
|
||||
|
@ -2473,15 +2473,31 @@ bool AsmParser::ParseDirectiveBundleAlignMode() {
|
||||
}
|
||||
|
||||
/// ParseDirectiveBundleLock
|
||||
/// ::= {.bundle_lock}
|
||||
/// ::= {.bundle_lock} [align_to_end]
|
||||
bool AsmParser::ParseDirectiveBundleLock() {
|
||||
CheckForValidSection();
|
||||
bool AlignToEnd = false;
|
||||
|
||||
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
||||
StringRef Option;
|
||||
SMLoc Loc = getTok().getLoc();
|
||||
const char *kInvalidOptionError =
|
||||
"invalid option for '.bundle_lock' directive";
|
||||
|
||||
if (ParseIdentifier(Option))
|
||||
return Error(Loc, kInvalidOptionError);
|
||||
|
||||
if (Option != "align_to_end")
|
||||
return Error(Loc, kInvalidOptionError);
|
||||
else if (getLexer().isNot(AsmToken::EndOfStatement))
|
||||
return Error(Loc,
|
||||
"unexpected token after '.bundle_lock' directive option");
|
||||
AlignToEnd = true;
|
||||
}
|
||||
|
||||
if (getLexer().isNot(AsmToken::EndOfStatement))
|
||||
return TokError("unexpected token in '.bundle_lock' directive");
|
||||
Lex();
|
||||
|
||||
getStreamer().EmitBundleLock();
|
||||
getStreamer().EmitBundleLock(AlignToEnd);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
# RUN: | llvm-objdump -no-show-raw-insn -triple armv7 -disassemble - | FileCheck %s
|
||||
|
||||
# On ARM each instruction is 4 bytes long so padding for individual
|
||||
# instructions should not be inserted. However, for bundle=locked groups
|
||||
# instructions should not be inserted. However, for bundle-locked groups
|
||||
# it can be.
|
||||
|
||||
.syntax unified
|
||||
|
@ -14,5 +14,9 @@ foo:
|
||||
jle .L_ELSE
|
||||
.bundle_unlock
|
||||
# CHECK: .bundle_unlock
|
||||
.bundle_lock align_to_end
|
||||
# CHECK: .bundle_lock align_to_end
|
||||
add %rbx, %rdx
|
||||
.bundle_unlock
|
||||
|
||||
|
||||
|
@ -766,7 +766,7 @@ namespace {
|
||||
}
|
||||
|
||||
virtual void EmitBundleAlignMode(unsigned AlignPow2) {}
|
||||
virtual void EmitBundleLock() {}
|
||||
virtual void EmitBundleLock(bool AlignToEnd) {}
|
||||
virtual void EmitBundleUnlock() {}
|
||||
|
||||
// Noop calls.
|
||||
|
Loading…
x
Reference in New Issue
Block a user