aboutsummaryrefslogtreecommitdiff
path: root/lib/MC
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MC')
-rw-r--r--lib/MC/MCAsmStreamer.cpp16
-rw-r--r--lib/MC/MCAssembler.cpp133
-rw-r--r--lib/MC/MCDwarf.cpp11
-rw-r--r--lib/MC/MCLoggingStreamer.cpp12
-rw-r--r--lib/MC/MCNullStreamer.cpp4
-rw-r--r--lib/MC/MCObjectStreamer.cpp10
-rw-r--r--lib/MC/MCParser/AsmParser.cpp38
-rw-r--r--lib/MC/MCStreamer.cpp22
8 files changed, 159 insertions, 87 deletions
diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp
index ca8dc965f2..9bb25eef95 100644
--- a/lib/MC/MCAsmStreamer.cpp
+++ b/lib/MC/MCAsmStreamer.cpp
@@ -141,7 +141,13 @@ public:
virtual void EmitBytes(StringRef Data, unsigned AddrSpace);
virtual void EmitValue(const MCExpr *Value, unsigned Size,unsigned AddrSpace);
+
virtual void EmitIntValue(uint64_t Value, unsigned Size, unsigned AddrSpace);
+
+ virtual void EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace = 0);
+
+ virtual void EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace = 0);
+
virtual void EmitGPRel32Value(const MCExpr *Value);
@@ -505,6 +511,16 @@ void MCAsmStreamer::EmitValue(const MCExpr *Value, unsigned Size,
EmitEOL();
}
+void MCAsmStreamer::EmitULEB128Value(const MCExpr *Value, unsigned AddrSpace) {
+ OS << ".uleb " << *Value;
+ EmitEOL();
+}
+
+void MCAsmStreamer::EmitSLEB128Value(const MCExpr *Value, unsigned AddrSpace) {
+ OS << ".sleb " << *Value;
+ EmitEOL();
+}
+
void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) {
assert(MAI.getGPRel32Directive() != 0);
OS << MAI.getGPRel32Directive() << *Value;
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
index 9cd0a12c12..1b464ee98f 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -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 << ">";
}
diff --git a/lib/MC/MCDwarf.cpp b/lib/MC/MCDwarf.cpp
index 17d164f2c7..d481ecf89b 100644
--- a/lib/MC/MCDwarf.cpp
+++ b/lib/MC/MCDwarf.cpp
@@ -125,7 +125,7 @@ static inline void EmitDwarfSetAddress(MCObjectStreamer *MCOS,
MCOS->EmitIntValue(dwarf::DW_LNS_extended_op, 1);
int sizeof_address = MCOS->getAssembler().getBackend().getPointerSize();
- MCOS->EmitULEB128Value(sizeof_address + 1);
+ MCOS->EmitULEB128IntValue(sizeof_address + 1);
MCOS->EmitIntValue(dwarf::DW_LNE_set_address, 1);
MCOS->EmitSymbolValue(Symbol, sizeof_address);
@@ -157,17 +157,17 @@ static inline bool EmitDwarfLineTable(MCObjectStreamer *MCOS,
if (FileNum != it->getFileNum()) {
FileNum = it->getFileNum();
MCOS->EmitIntValue(dwarf::DW_LNS_set_file, 1);
- MCOS->EmitULEB128Value(FileNum);
+ MCOS->EmitULEB128IntValue(FileNum);
}
if (Column != it->getColumn()) {
Column = it->getColumn();
MCOS->EmitIntValue(dwarf::DW_LNS_set_column, 1);
- MCOS->EmitULEB128Value(Column);
+ MCOS->EmitULEB128IntValue(Column);
}
if (Isa != it->getIsa()) {
Isa = it->getIsa();
MCOS->EmitIntValue(dwarf::DW_LNS_set_isa, 1);
- MCOS->EmitULEB128Value(Isa);
+ MCOS->EmitULEB128IntValue(Isa);
}
if ((it->getFlags() ^ Flags) & DWARF2_FLAG_IS_STMT) {
Flags = it->getFlags();
@@ -303,7 +303,8 @@ void MCDwarfFileTable::Emit(MCObjectStreamer *MCOS,
for (unsigned i = 1; i < MCDwarfFiles.size(); i++) {
MCOS->EmitBytes(MCDwarfFiles[i]->getName(), 0); // FileName
MCOS->EmitBytes(StringRef("\0", 1), 0); // the null term. of the string
- MCOS->EmitULEB128Value(MCDwarfFiles[i]->getDirIndex()); // the Directory num
+ // the Directory num
+ MCOS->EmitULEB128IntValue(MCDwarfFiles[i]->getDirIndex());
MCOS->EmitIntValue(0, 1); // last modification timestamp (always 0)
MCOS->EmitIntValue(0, 1); // filesize (always 0)
}
diff --git a/lib/MC/MCLoggingStreamer.cpp b/lib/MC/MCLoggingStreamer.cpp
index a907c11f11..cb217c780c 100644
--- a/lib/MC/MCLoggingStreamer.cpp
+++ b/lib/MC/MCLoggingStreamer.cpp
@@ -152,6 +152,18 @@ public:
return Child->EmitIntValue(Value, Size, AddrSpace);
}
+ virtual void EmitULEB128Value(const MCExpr *Value,
+ unsigned AddrSpace = 0) {
+ LogCall("EmitULEB128Value");
+ return Child->EmitULEB128Value(Value, AddrSpace);
+ }
+
+ virtual void EmitSLEB128Value(const MCExpr *Value,
+ unsigned AddrSpace = 0) {
+ LogCall("EmitSLEB128Value");
+ return Child->EmitSLEB128Value(Value, AddrSpace);
+ }
+
virtual void EmitGPRel32Value(const MCExpr *Value) {
LogCall("EmitGPRel32Value");
return Child->EmitGPRel32Value(Value);
diff --git a/lib/MC/MCNullStreamer.cpp b/lib/MC/MCNullStreamer.cpp
index 5f29b46d37..9dfb28c304 100644
--- a/lib/MC/MCNullStreamer.cpp
+++ b/lib/MC/MCNullStreamer.cpp
@@ -66,6 +66,10 @@ namespace {
virtual void EmitValue(const MCExpr *Value, unsigned Size,
unsigned AddrSpace) {}
+ virtual void EmitULEB128Value(const MCExpr *Value,
+ unsigned AddrSpace = 0) {}
+ virtual void EmitSLEB128Value(const MCExpr *Value,
+ unsigned AddrSpace = 0) {}
virtual void EmitGPRel32Value(const MCExpr *Value) {}
virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
unsigned ValueSize = 1,
diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp
index da1b7c05b1..a40c754658 100644
--- a/lib/MC/MCObjectStreamer.cpp
+++ b/lib/MC/MCObjectStreamer.cpp
@@ -75,6 +75,16 @@ const MCExpr *MCObjectStreamer::AddValueSymbols(const MCExpr *Value) {
return Value;
}
+void MCObjectStreamer::EmitULEB128Value(const MCExpr *Value,
+ unsigned AddrSpace) {
+ new MCLEBFragment(*Value, false, getCurrentSectionData());
+}
+
+void MCObjectStreamer::EmitSLEB128Value(const MCExpr *Value,
+ unsigned AddrSpace) {
+ new MCLEBFragment(*Value, true, getCurrentSectionData());
+}
+
void MCObjectStreamer::EmitWeakReference(MCSymbol *Alias,
const MCSymbol *Symbol) {
report_fatal_error("This file format doesn't support weak aliases.");
diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp
index 8aaee95eda..877bae9e1c 100644
--- a/lib/MC/MCParser/AsmParser.cpp
+++ b/lib/MC/MCParser/AsmParser.cpp
@@ -261,8 +261,6 @@ public:
bool ParseDirectiveMacro(StringRef, SMLoc DirectiveLoc);
bool ParseDirectiveEndMacro(StringRef, SMLoc DirectiveLoc);
- void ParseUleb128(uint64_t Value);
- void ParseSleb128(int64_t Value);
bool ParseDirectiveLEB128(StringRef, SMLoc);
};
@@ -2178,44 +2176,22 @@ bool GenericAsmParser::ParseDirectiveEndMacro(StringRef Directive,
"no current macro definition");
}
-void GenericAsmParser::ParseUleb128(uint64_t Value) {
- const uint64_t Mask = (1 << 7) - 1;
- do {
- unsigned Byte = Value & Mask;
- Value >>= 7;
- if (Value) // Not the last one
- Byte |= (1 << 7);
- getStreamer().EmitIntValue(Byte, 1, DEFAULT_ADDRSPACE);
- } while (Value);
-}
+bool GenericAsmParser::ParseDirectiveLEB128(StringRef DirName, SMLoc) {
+ getParser().CheckForValidSection();
-void GenericAsmParser::ParseSleb128(int64_t Value) {
- const int64_t Mask = (1 << 7) - 1;
- for(;;) {
- unsigned Byte = Value & Mask;
- Value >>= 7;
- bool Done = ((Value == 0 && (Byte & 0x40) == 0) ||
- (Value == -1 && (Byte & 0x40) != 0));
- if (!Done)
- Byte |= (1 << 7);
- getStreamer().EmitIntValue(Byte, 1, DEFAULT_ADDRSPACE);
- if (Done)
- break;
- }
-}
+ const MCExpr *Value;
-bool GenericAsmParser::ParseDirectiveLEB128(StringRef DirName, SMLoc) {
- int64_t Value;
- if (getParser().ParseAbsoluteExpression(Value))
+ if (getParser().ParseExpression(Value))
return true;
if (getLexer().isNot(AsmToken::EndOfStatement))
return TokError("unexpected token in directive");
if (DirName[1] == 's')
- ParseSleb128(Value);
+ getStreamer().EmitSLEB128Value(Value);
else
- ParseUleb128(Value);
+ getStreamer().EmitULEB128Value(Value);
+
return false;
}
diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp
index 351d9fce4c..98667f42d6 100644
--- a/lib/MC/MCStreamer.cpp
+++ b/lib/MC/MCStreamer.cpp
@@ -37,22 +37,16 @@ void MCStreamer::EmitIntValue(uint64_t Value, unsigned Size,
EmitValue(MCConstantExpr::Create(Value, getContext()), Size, AddrSpace);
}
-// EmitULEB128Value - Special case of EmitValue that emits a ULEB128 of the
-// Value as the sequence of ULEB128 encoded bytes.
-void MCStreamer::EmitULEB128Value(uint64_t Value, unsigned AddrSpace) {
- SmallString<32> Tmp;
- raw_svector_ostream OS(Tmp);
- MCObjectWriter::EncodeULEB128(Value, OS);
- EmitBytes(OS.str(), AddrSpace);
+/// EmitULEB128Value - Special case of EmitULEB128Value that avoids the
+/// client having to pass in a MCExpr for constant integers.
+void MCStreamer::EmitULEB128IntValue(uint64_t Value, unsigned AddrSpace) {
+ EmitULEB128Value(MCConstantExpr::Create(Value, getContext()), AddrSpace);
}
-// EmitSLEB128Value - Special case of EmitValue that emits a SLEB128 of the
-// Value as the sequence of ULEB128 encoded bytes.
-void MCStreamer::EmitSLEB128Value(int64_t Value, unsigned AddrSpace) {
- SmallString<32> Tmp;
- raw_svector_ostream OS(Tmp);
- MCObjectWriter::EncodeSLEB128(Value, OS);
- EmitBytes(OS.str(), AddrSpace);
+/// EmitSLEB128Value - Special case of EmitSLEB128Value that avoids the
+/// client having to pass in a MCExpr for constant integers.
+void MCStreamer::EmitSLEB128IntValue(int64_t Value, unsigned AddrSpace) {
+ EmitSLEB128Value(MCConstantExpr::Create(Value, getContext()), AddrSpace);
}
void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size,