mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-21 18:24:23 +00:00
Add support for expressions in .sleb/.uleb directives.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@118023 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -318,6 +318,9 @@ uint64_t MCAssembler::ComputeFragmentSize(MCAsmLayout &Layout,
|
||||
case MCFragment::FT_Inst:
|
||||
return cast<MCInstFragment>(F).getInstSize();
|
||||
|
||||
case MCFragment::FT_LEB:
|
||||
return cast<MCLEBFragment>(F).getSize();
|
||||
|
||||
case MCFragment::FT_Align: {
|
||||
const MCAlignFragment &AF = cast<MCAlignFragment>(F);
|
||||
|
||||
@ -514,6 +517,23 @@ static void WriteFragmentData(const MCAssembler &Asm, const MCAsmLayout &Layout,
|
||||
llvm_unreachable("unexpected inst fragment after lowering");
|
||||
break;
|
||||
|
||||
case MCFragment::FT_LEB: {
|
||||
MCLEBFragment &LF = cast<MCLEBFragment>(F);
|
||||
|
||||
// FIXME: It is probably better if we don't call EvaluateAsAbsolute in
|
||||
// here.
|
||||
int64_t Value;
|
||||
LF.getValue().EvaluateAsAbsolute(Value, &Layout);
|
||||
SmallString<32> Tmp;
|
||||
raw_svector_ostream OSE(Tmp);
|
||||
if (LF.isSigned())
|
||||
MCObjectWriter::EncodeSLEB128(Value, OSE);
|
||||
else
|
||||
MCObjectWriter::EncodeULEB128(Value, OSE);
|
||||
OW->WriteBytes(OSE.str());
|
||||
break;
|
||||
}
|
||||
|
||||
case MCFragment::FT_Org: {
|
||||
MCOrgFragment &OF = cast<MCOrgFragment>(F);
|
||||
|
||||
@ -781,6 +801,63 @@ bool MCAssembler::FragmentNeedsRelaxation(const MCObjectWriter &Writer,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MCAssembler::RelaxInstruction(const MCObjectWriter &Writer,
|
||||
MCAsmLayout &Layout,
|
||||
MCInstFragment &IF) {
|
||||
if (!FragmentNeedsRelaxation(Writer, &IF, Layout))
|
||||
return false;
|
||||
|
||||
++stats::RelaxedInstructions;
|
||||
|
||||
// FIXME-PERF: We could immediately lower out instructions if we can tell
|
||||
// they are fully resolved, to avoid retesting on later passes.
|
||||
|
||||
// Relax the fragment.
|
||||
|
||||
MCInst Relaxed;
|
||||
getBackend().RelaxInstruction(IF.getInst(), Relaxed);
|
||||
|
||||
// Encode the new instruction.
|
||||
//
|
||||
// FIXME-PERF: If it matters, we could let the target do this. It can
|
||||
// probably do so more efficiently in many cases.
|
||||
SmallVector<MCFixup, 4> Fixups;
|
||||
SmallString<256> Code;
|
||||
raw_svector_ostream VecOS(Code);
|
||||
getEmitter().EncodeInstruction(Relaxed, VecOS, Fixups);
|
||||
VecOS.flush();
|
||||
|
||||
// Update the instruction fragment.
|
||||
int SlideAmount = Code.size() - IF.getInstSize();
|
||||
IF.setInst(Relaxed);
|
||||
IF.getCode() = Code;
|
||||
IF.getFixups().clear();
|
||||
// FIXME: Eliminate copy.
|
||||
for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
|
||||
IF.getFixups().push_back(Fixups[i]);
|
||||
|
||||
// Update the layout, and remember that we relaxed.
|
||||
Layout.UpdateForSlide(&IF, SlideAmount);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MCAssembler::RelaxLEB(const MCObjectWriter &Writer,
|
||||
MCAsmLayout &Layout,
|
||||
MCLEBFragment &LF) {
|
||||
int64_t Value;
|
||||
LF.getValue().EvaluateAsAbsolute(Value, &Layout);
|
||||
SmallString<32> Tmp;
|
||||
raw_svector_ostream OSE(Tmp);
|
||||
if (LF.isSigned())
|
||||
MCObjectWriter::EncodeSLEB128(Value, OSE);
|
||||
else
|
||||
MCObjectWriter::EncodeULEB128(Value, OSE);
|
||||
uint64_t OldSize = LF.getSize();
|
||||
LF.setSize(OSE.GetNumBytesInBuffer());
|
||||
return OldSize != LF.getSize();
|
||||
}
|
||||
|
||||
|
||||
bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer,
|
||||
MCAsmLayout &Layout) {
|
||||
++stats::RelaxationSteps;
|
||||
@ -795,43 +872,18 @@ bool MCAssembler::LayoutOnce(const MCObjectWriter &Writer,
|
||||
|
||||
for (MCSectionData::iterator it2 = SD.begin(),
|
||||
ie2 = SD.end(); it2 != ie2; ++it2) {
|
||||
// Check if this is an instruction fragment that needs relaxation.
|
||||
MCInstFragment *IF = dyn_cast<MCInstFragment>(it2);
|
||||
if (!IF || !FragmentNeedsRelaxation(Writer, IF, Layout))
|
||||
continue;
|
||||
|
||||
++stats::RelaxedInstructions;
|
||||
|
||||
// FIXME-PERF: We could immediately lower out instructions if we can tell
|
||||
// they are fully resolved, to avoid retesting on later passes.
|
||||
|
||||
// Relax the fragment.
|
||||
|
||||
MCInst Relaxed;
|
||||
getBackend().RelaxInstruction(IF->getInst(), Relaxed);
|
||||
|
||||
// Encode the new instruction.
|
||||
//
|
||||
// FIXME-PERF: If it matters, we could let the target do this. It can
|
||||
// probably do so more efficiently in many cases.
|
||||
SmallVector<MCFixup, 4> Fixups;
|
||||
SmallString<256> Code;
|
||||
raw_svector_ostream VecOS(Code);
|
||||
getEmitter().EncodeInstruction(Relaxed, VecOS, Fixups);
|
||||
VecOS.flush();
|
||||
|
||||
// Update the instruction fragment.
|
||||
int SlideAmount = Code.size() - IF->getInstSize();
|
||||
IF->setInst(Relaxed);
|
||||
IF->getCode() = Code;
|
||||
IF->getFixups().clear();
|
||||
// FIXME: Eliminate copy.
|
||||
for (unsigned i = 0, e = Fixups.size(); i != e; ++i)
|
||||
IF->getFixups().push_back(Fixups[i]);
|
||||
|
||||
// Update the layout, and remember that we relaxed.
|
||||
Layout.UpdateForSlide(IF, SlideAmount);
|
||||
WasRelaxed = true;
|
||||
// Check if this is an fragment that needs relaxation.
|
||||
switch(it2->getKind()) {
|
||||
default:
|
||||
break;
|
||||
case MCFragment::FT_Inst:
|
||||
WasRelaxed |= RelaxInstruction(Writer, Layout,
|
||||
*cast<MCInstFragment>(it2));
|
||||
break;
|
||||
case MCFragment::FT_LEB:
|
||||
WasRelaxed |= RelaxLEB(Writer, Layout, *cast<MCLEBFragment>(it2));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -903,6 +955,7 @@ void MCFragment::dump() {
|
||||
case MCFragment::FT_Inst: OS << "MCInstFragment"; break;
|
||||
case MCFragment::FT_Org: OS << "MCOrgFragment"; break;
|
||||
case MCFragment::FT_Dwarf: OS << "MCDwarfFragment"; break;
|
||||
case MCFragment::FT_LEB: OS << "MCLEBFragment"; break;
|
||||
}
|
||||
|
||||
OS << "<MCFragment " << (void*) this << " LayoutOrder:" << LayoutOrder
|
||||
@ -970,6 +1023,12 @@ void MCFragment::dump() {
|
||||
<< " LineDelta:" << OF->getLineDelta();
|
||||
break;
|
||||
}
|
||||
case MCFragment::FT_LEB: {
|
||||
const MCLEBFragment *LF = cast<MCLEBFragment>(this);
|
||||
OS << "\n ";
|
||||
OS << " Value:" << LF->getValue() << " Signed:" << LF->isSigned();
|
||||
break;
|
||||
}
|
||||
}
|
||||
OS << ">";
|
||||
}
|
||||
|
Reference in New Issue
Block a user