diff options
Diffstat (limited to 'llvm/lib/MC')
-rw-r--r-- | llvm/lib/MC/MCAssembler.cpp | 45 | ||||
-rw-r--r-- | llvm/lib/MC/MCFragment.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/MC/MCObjectStreamer.cpp | 38 | ||||
-rw-r--r-- | llvm/lib/MC/WasmObjectWriter.cpp | 7 |
4 files changed, 60 insertions, 33 deletions
diff --git a/llvm/lib/MC/MCAssembler.cpp b/llvm/lib/MC/MCAssembler.cpp index a8a0177dff6..bde838a316d 100644 --- a/llvm/lib/MC/MCAssembler.cpp +++ b/llvm/lib/MC/MCAssembler.cpp @@ -295,10 +295,13 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, return cast<MCCompactEncodedInstFragment>(F).getContents().size(); case MCFragment::FT_Fill: { auto &FF = cast<MCFillFragment>(F); - int64_t Size = 0; - if (!FF.getSize().evaluateAsAbsolute(Size, Layout)) + int64_t NumValues = 0; + if (!FF.getNumValues().evaluateAsAbsolute(NumValues, Layout)) { getContext().reportError(FF.getLoc(), "expected assembly-time absolute expression"); + return 0; + } + int64_t Size = NumValues * FF.getValueSize(); if (Size < 0) { getContext().reportError(FF.getLoc(), "invalid number of bytes"); return 0; @@ -557,19 +560,35 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, case MCFragment::FT_Fill: { ++stats::EmittedFillFragments; const MCFillFragment &FF = cast<MCFillFragment>(F); - uint8_t V = FF.getValue(); + uint64_t V = FF.getValue(); + unsigned VSize = FF.getValueSize(); const unsigned MaxChunkSize = 16; char Data[MaxChunkSize]; - memcpy(Data, &V, 1); - for (unsigned I = 1; I < MaxChunkSize; ++I) - Data[I] = Data[0]; - - uint64_t Size = FragmentSize; - for (unsigned ChunkSize = MaxChunkSize; ChunkSize; ChunkSize /= 2) { - StringRef Ref(Data, ChunkSize); - for (uint64_t I = 0, E = Size / ChunkSize; I != E; ++I) - OW->writeBytes(Ref); - Size = Size % ChunkSize; + // Duplicate V into Data as byte vector to reduce number of + // writes done. As such, do endian conversion here, not in OW. + const bool isLittleEndian = Asm.getContext().getAsmInfo()->isLittleEndian(); + for (unsigned I = 0; I != VSize; ++I) { + unsigned index = isLittleEndian ? I : (VSize - I - 1); + Data[I] = uint8_t(V >> (index * 8)); + } + for (unsigned I = VSize; I < MaxChunkSize; ++I) + Data[I] = Data[I - VSize]; + + // Set to largest multiple of VSize in Data. + const unsigned NumPerChunk = MaxChunkSize / VSize; + // Set ChunkSize to largest multiple of VSize in Data + const unsigned ChunkSize = VSize * NumPerChunk; + + // Do copies by chunk. + StringRef Ref(Data, ChunkSize); + for (uint64_t I = 0, E = FragmentSize / ChunkSize; I != E; ++I) + OW->writeBytes(Ref); + + // do remainder if needed. + unsigned TrailingCount = FragmentSize % ChunkSize; + if (TrailingCount) { + StringRef RefTail(Data, TrailingCount); + OW->writeBytes(RefTail); } break; } diff --git a/llvm/lib/MC/MCFragment.cpp b/llvm/lib/MC/MCFragment.cpp index e7775ca3ab1..2d6b83e0aef 100644 --- a/llvm/lib/MC/MCFragment.cpp +++ b/llvm/lib/MC/MCFragment.cpp @@ -388,7 +388,8 @@ LLVM_DUMP_METHOD void MCFragment::dump() const { case MCFragment::FT_Fill: { const MCFillFragment *FF = cast<MCFillFragment>(this); OS << " Value:" << static_cast<unsigned>(FF->getValue()) - << " Size:" << FF->getSize(); + << " ValueSize:" << static_cast<unsigned>(FF->getValueSize()) + << " NumValues:" << FF->getNumValues(); break; } case MCFragment::FT_Relaxable: { diff --git a/llvm/lib/MC/MCObjectStreamer.cpp b/llvm/lib/MC/MCObjectStreamer.cpp index b2008b3e1bb..22b9743d80b 100644 --- a/llvm/lib/MC/MCObjectStreamer.cpp +++ b/llvm/lib/MC/MCObjectStreamer.cpp @@ -637,31 +637,37 @@ void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue, flushPendingLabels(DF, DF->getContents().size()); assert(getCurrentSectionOnly() && "need a section"); - insert(new MCFillFragment(FillValue, NumBytes, Loc)); + insert(new MCFillFragment(FillValue, 1, NumBytes, Loc)); } void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr, SMLoc Loc) { int64_t IntNumValues; - if (!NumValues.evaluateAsAbsolute(IntNumValues, getAssemblerPtr())) { - getContext().reportError(Loc, "expected absolute expression"); + // Do additional checking now if we can resolve the value. + if (NumValues.evaluateAsAbsolute(IntNumValues, getAssemblerPtr())) { + if (IntNumValues < 0) { + getContext().getSourceManager()->PrintMessage( + Loc, SourceMgr::DK_Warning, + "'.fill' directive with negative repeat count has no effect"); + return; + } + // Emit now if we can for better errors. + int64_t NonZeroSize = Size > 4 ? 4 : Size; + Expr &= ~0ULL >> (64 - NonZeroSize * 8); + for (uint64_t i = 0, e = IntNumValues; i != e; ++i) { + EmitIntValue(Expr, NonZeroSize); + if (NonZeroSize < Size) + EmitIntValue(0, Size - NonZeroSize); + } return; } - if (IntNumValues < 0) { - getContext().getSourceManager()->PrintMessage( - Loc, SourceMgr::DK_Warning, - "'.fill' directive with negative repeat count has no effect"); - return; - } + // Otherwise emit as fragment. + MCDataFragment *DF = getOrCreateDataFragment(); + flushPendingLabels(DF, DF->getContents().size()); - int64_t NonZeroSize = Size > 4 ? 4 : Size; - Expr &= ~0ULL >> (64 - NonZeroSize * 8); - for (uint64_t i = 0, e = IntNumValues; i != e; ++i) { - EmitIntValue(Expr, NonZeroSize); - if (NonZeroSize < Size) - EmitIntValue(0, Size - NonZeroSize); - } + assert(getCurrentSectionOnly() && "need a section"); + insert(new MCFillFragment(Expr, Size, NumValues, Loc)); } void MCObjectStreamer::EmitFileDirective(StringRef Filename) { diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp index 0696d6f4952..22e05c17994 100644 --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -630,10 +630,11 @@ static void addData(SmallVectorImpl<char> &DataBytes, Align->getMaxBytesToEmit()); DataBytes.resize(Size, Value); } else if (auto *Fill = dyn_cast<MCFillFragment>(&Frag)) { - int64_t Size; - if (!Fill->getSize().evaluateAsAbsolute(Size)) + int64_t NumValues; + if (!Fill->getNumValues().evaluateAsAbsolute(NumValues)) llvm_unreachable("The fill should be an assembler constant"); - DataBytes.insert(DataBytes.end(), Size, Fill->getValue()); + DataBytes.insert(DataBytes.end(), Fill->getValueSize() * NumValues, + Fill->getValue()); } else { const auto &DataFrag = cast<MCDataFragment>(Frag); const SmallVectorImpl<char> &Contents = DataFrag.getContents(); |