diff options
Diffstat (limited to 'lib/MC')
-rw-r--r-- | lib/MC/MCAsmStreamer.cpp | 16 | ||||
-rw-r--r-- | lib/MC/MCAssembler.cpp | 133 | ||||
-rw-r--r-- | lib/MC/MCDwarf.cpp | 11 | ||||
-rw-r--r-- | lib/MC/MCLoggingStreamer.cpp | 12 | ||||
-rw-r--r-- | lib/MC/MCNullStreamer.cpp | 4 | ||||
-rw-r--r-- | lib/MC/MCObjectStreamer.cpp | 10 | ||||
-rw-r--r-- | lib/MC/MCParser/AsmParser.cpp | 38 | ||||
-rw-r--r-- | lib/MC/MCStreamer.cpp | 22 |
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, |