Index: llvm/include/llvm/MC/MCFragment.h =================================================================== --- llvm/include/llvm/MC/MCFragment.h +++ llvm/include/llvm/MC/MCFragment.h @@ -419,22 +419,23 @@ class MCFillFragment : public MCFragment { /// Value to use for filling bytes. - uint8_t Value; - + uint64_t Value; + uint8_t ValueSize; /// The number of bytes to insert. - const MCExpr &Size; + const MCExpr &NumValues; /// Source location of the directive that this fragment was created for. SMLoc Loc; public: - MCFillFragment(uint8_t Value, const MCExpr &Size, SMLoc Loc, - MCSection *Sec = nullptr) - : MCFragment(FT_Fill, false, 0, Sec), Value(Value), Size(Size), Loc(Loc) { - } - - uint8_t getValue() const { return Value; } - const MCExpr &getSize() const { return Size; } + MCFillFragment(uint64_t Value, uint8_t VSize, const MCExpr &NumValues, + SMLoc Loc, MCSection *Sec = nullptr) + : MCFragment(FT_Fill, false, 0, Sec), Value(Value), ValueSize(VSize), + NumValues(NumValues), Loc(Loc) {} + + uint64_t getValue() const { return Value; } + uint8_t getValueSize() const { return ValueSize; } + const MCExpr &getNumValues() const { return NumValues; } SMLoc getLoc() const { return Loc; } Index: llvm/lib/MC/MCAssembler.cpp =================================================================== --- llvm/lib/MC/MCAssembler.cpp +++ llvm/lib/MC/MCAssembler.cpp @@ -291,10 +291,13 @@ return cast(F).getContents().size(); case MCFragment::FT_Fill: { auto &FF = cast(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; @@ -553,19 +556,33 @@ case MCFragment::FT_Fill: { ++stats::EmittedFillFragments; const MCFillFragment &FF = cast(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; + 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. + unsigned NumPerChunk = MaxChunkSize / VSize; + 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; } Index: llvm/lib/MC/MCFragment.cpp =================================================================== --- llvm/lib/MC/MCFragment.cpp +++ llvm/lib/MC/MCFragment.cpp @@ -388,7 +388,8 @@ case MCFragment::FT_Fill: { const MCFillFragment *FF = cast(this); OS << " Value:" << static_cast(FF->getValue()) - << " Size:" << FF->getSize(); + << " ValueSize:" << static_cast(FF->getValueSize()) + << " NumValues:" << FF->getNumValues(); break; } case MCFragment::FT_Relaxable: { Index: llvm/lib/MC/MCObjectStreamer.cpp =================================================================== --- llvm/lib/MC/MCObjectStreamer.cpp +++ llvm/lib/MC/MCObjectStreamer.cpp @@ -637,31 +637,38 @@ 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) { Index: llvm/lib/MC/WasmObjectWriter.cpp =================================================================== --- llvm/lib/MC/WasmObjectWriter.cpp +++ llvm/lib/MC/WasmObjectWriter.cpp @@ -640,10 +640,11 @@ Align->getMaxBytesToEmit()); DataBytes.resize(Size, Value); } else if (auto *Fill = dyn_cast(&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(Frag); const SmallVectorImpl &Contents = DataFrag.getContents(); Index: llvm/test/MC/AsmParser/assembler-expressions.s =================================================================== --- llvm/test/MC/AsmParser/assembler-expressions.s +++ llvm/test/MC/AsmParser/assembler-expressions.s @@ -28,7 +28,8 @@ # nop is a fixed size instruction so this should pass. # OBJTEXT: Contents of section .text -# OBJTEXT-NEXT: 0000 9090ff34 25 +# OBJTEXT-NEXT: 0000 9090ff34 25000000 00909090 78563412 +# OBJTEXT-NEXT: 0010 78563412 90 .text @@ -41,7 +42,23 @@ ret .endif push gs - + nop + nop + nop # No additional errors. # # ASM-ERR-NOT: {{[0-9]+}}:{{[0-9]+}}: error: + + + +text2: + .long 0x12345678 +text3: + .fill (text3-text2)/4, 4, 0x12345678 + nop + + + + + + Index: llvm/test/MC/AsmParser/directive_fill.s =================================================================== --- llvm/test/MC/AsmParser/directive_fill.s +++ llvm/test/MC/AsmParser/directive_fill.s @@ -1,7 +1,7 @@ # RUN: llvm-mc -triple i386-unknown-unknown %s 2> %t.err | FileCheck %s # RUN: FileCheck --check-prefix=CHECK-WARNINGS %s < %t.err -# RUN: llvm-mc -triple i386-unknown-unknown -filetype=obj -o %t.o %s 2> %t.err2 -# RUN: FileCheck --check-prefix=OBJ-WARNINGS %s < %t.err2 +# RUN: not llvm-mc -triple i386-unknown-unknown -filetype=obj -o %t.o %s 2> %t.err2 +# RUN: FileCheck --check-prefix=OBJ-ERRS %s < %t.err2 # CHECK: TEST0: # CHECK: .fill 1, 1, 0xa @@ -47,7 +47,7 @@ # CHECK: TEST8 # CHECK: .fill -1, 8, 0x1 -# OBJ-WARNINGS: '.fill' directive with negative repeat count has no effect +# OBJ-ERRS: '.fill' directive with negative repeat count has no effect TEST8: .fill -1, 8, 1 @@ -66,7 +66,14 @@ .fill TEST11 - TEST10 # CHECK: TEST12 -# CHECK: .fill TEST11-TEST12, 3, 0x12345678 -# OBJ-WARNINGS: '.fill' directive with negative repeat count has no effect +# CHECK: .fill TEST11-TEST12, 4, 0x12345678 +# OBJ-ERRS: '.fill' directive with negative repeat count has no effect TEST12: - .fill TEST11 - TEST12, 3, 0x12345678 + .fill TEST11 - TEST12, 4, 0x12345678 + +# CHECK: TEST13 +# CHECK: .fill (TEST11-TEST12)+i, 4, 0x12345678 +# OBJ-ERRS: [[@LINE+2]]:8: error: expected assembly-time absolute expression +TEST13: + .fill TEST11 - TEST12+i, 4, 0x12345678 + Index: llvm/test/MC/AsmParser/directive_fill_2.s =================================================================== --- /dev/null +++ llvm/test/MC/AsmParser/directive_fill_2.s @@ -0,0 +1,32 @@ +# RUN: llvm-mc -filetype=obj -defsym=I=6 -triple i686-unknown-unknown %s | llvm-objdump -triple i686-unknown-unknown -s - | FileCheck --check-prefix="CHECK" %s +# RUN: not llvm-mc -filetype=obj -defsym=I=4 -triple i686-unknown-unknown %s -o /dev/null 2>&1 | FileCheck --check-prefix="CHECK-ERR" %s + + + +# CHECK: Contents of section .text +# CHECK-NEXT: 0000 e9810000 00cc9090 90909090 90909090 + +# Make sure we emit in correct endianness. + +# CHECK: Contents of section .data +# CHECK-NEXT: 0000 78563412 78563412 78563412 + +.text +foo: +jmp bar2 +# CHECK-ERR: [[@LINE+1]]:7: error: invalid number of bytes +.fill ((I+foo) - .), 1, 0xcc +bar: + .space 128, 0x90 +bar2: +.byte 0xff + +# This fill length is not known at assembler time. + +.if (I==6) + +.data +.long 0x12345678 +.fill ((foo+8)-bar), 4, 0x12345678 + +.endif