From: Hans Wennborg Date: Tue, 30 Jan 2018 09:31:00 +0000 (+0000) Subject: Merging r322108, r322123 and r322131: X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=98b79f2cd78d57b8e5f5307ac889fa264cddcc36;p=llvm Merging r322108, r322123 and r322131: ------------------------------------------------------------------------ r322108 | rafael | 2018-01-09 20:29:33 +0100 (Tue, 09 Jan 2018) | 3 lines Make one of the emitFill methods non virtual. NFC. This is just preparatory work to fix PR35858. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r322123 | rafael | 2018-01-09 22:55:10 +0100 (Tue, 09 Jan 2018) | 3 lines Don't create MCFillFragment directly. Instead use higher level APIs that take care of most bookkeeping. ------------------------------------------------------------------------ ------------------------------------------------------------------------ r322131 | rafael | 2018-01-09 23:48:37 +0100 (Tue, 09 Jan 2018) | 4 lines Use a MCExpr for the size of MCFillFragment. This allows the size to be found during ralaxation. This fixes pr35858. ------------------------------------------------------------------------ git-svn-id: https://llvm.org/svn/llvm-project/llvm/branches/release_60@323735 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/MC/MCFragment.h b/include/llvm/MC/MCFragment.h index 7ebde03a758..85b55e85469 100644 --- a/include/llvm/MC/MCFragment.h +++ b/include/llvm/MC/MCFragment.h @@ -422,14 +422,21 @@ class MCFillFragment : public MCFragment { uint8_t Value; /// The number of bytes to insert. - uint64_t Size; + const MCExpr &Size; + + /// Source location of the directive that this fragment was created for. + SMLoc Loc; public: - MCFillFragment(uint8_t Value, uint64_t Size, MCSection *Sec = nullptr) - : MCFragment(FT_Fill, false, 0, Sec), Value(Value), Size(Size) {} + 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; } - uint64_t getSize() const { return Size; } + const MCExpr &getSize() const { return Size; } + + SMLoc getLoc() const { return Loc; } static bool classof(const MCFragment *F) { return F->getKind() == MCFragment::FT_Fill; diff --git a/include/llvm/MC/MCObjectStreamer.h b/include/llvm/MC/MCObjectStreamer.h index a3dbc56ebc1..43ed00b4a7a 100644 --- a/include/llvm/MC/MCObjectStreamer.h +++ b/include/llvm/MC/MCObjectStreamer.h @@ -161,7 +161,6 @@ public: bool EmitRelocDirective(const MCExpr &Offset, StringRef Name, const MCExpr *Expr, SMLoc Loc) override; using MCStreamer::emitFill; - void emitFill(uint64_t NumBytes, uint8_t FillValue) override; void emitFill(const MCExpr &NumBytes, uint64_t FillValue, SMLoc Loc = SMLoc()) override; void emitFill(const MCExpr &NumValues, int64_t Size, int64_t Expr, diff --git a/include/llvm/MC/MCStreamer.h b/include/llvm/MC/MCStreamer.h index a8205170070..28b326ae9b8 100644 --- a/include/llvm/MC/MCStreamer.h +++ b/include/llvm/MC/MCStreamer.h @@ -662,7 +662,7 @@ public: /// \brief Emit NumBytes bytes worth of the value specified by FillValue. /// This implements directives such as '.space'. - virtual void emitFill(uint64_t NumBytes, uint8_t FillValue); + void emitFill(uint64_t NumBytes, uint8_t FillValue); /// \brief Emit \p Size bytes worth of the value specified by \p FillValue. /// diff --git a/lib/MC/MCAsmStreamer.cpp b/lib/MC/MCAsmStreamer.cpp index e521b6e7c70..bddd264fe30 100644 --- a/lib/MC/MCAsmStreamer.cpp +++ b/lib/MC/MCAsmStreamer.cpp @@ -192,9 +192,6 @@ public: void EmitGPRel32Value(const MCExpr *Value) override; - - void emitFill(uint64_t NumBytes, uint8_t FillValue) override; - void emitFill(const MCExpr &NumBytes, uint64_t FillValue, SMLoc Loc = SMLoc()) override; @@ -965,17 +962,12 @@ void MCAsmStreamer::EmitGPRel32Value(const MCExpr *Value) { EmitEOL(); } -/// emitFill - Emit NumBytes bytes worth of the value specified by -/// FillValue. This implements directives such as '.space'. -void MCAsmStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) { - if (NumBytes == 0) return; - - const MCExpr *E = MCConstantExpr::create(NumBytes, getContext()); - emitFill(*E, FillValue); -} - void MCAsmStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue, SMLoc Loc) { + int64_t IntNumBytes; + if (NumBytes.evaluateAsAbsolute(IntNumBytes) && IntNumBytes == 0) + return; + if (const char *ZeroDirective = MAI->getZeroDirective()) { // FIXME: Emit location directives OS << ZeroDirective; diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp index 01d165944be..bd881b4d6e8 100644 --- a/lib/MC/MCAssembler.cpp +++ b/lib/MC/MCAssembler.cpp @@ -281,8 +281,18 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout, return cast(F).getContents().size(); case MCFragment::FT_CompactEncodedInst: return cast(F).getContents().size(); - case MCFragment::FT_Fill: - return cast(F).getSize(); + case MCFragment::FT_Fill: { + auto &FF = cast(F); + int64_t Size = 0; + if (!FF.getSize().evaluateAsAbsolute(Size, Layout)) + getContext().reportError(FF.getLoc(), + "expected assembly-time absolute expression"); + if (Size < 0) { + getContext().reportError(FF.getLoc(), "invalid number of bytes"); + return 0; + } + return Size; + } case MCFragment::FT_LEB: return cast(F).getContents().size(); @@ -540,7 +550,7 @@ static void writeFragment(const MCAssembler &Asm, const MCAsmLayout &Layout, for (unsigned I = 1; I < MaxChunkSize; ++I) Data[I] = Data[0]; - uint64_t Size = FF.getSize(); + 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) diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp index 82b75afabb3..3969143bb2c 100644 --- a/lib/MC/MCMachOStreamer.cpp +++ b/lib/MC/MCMachOStreamer.cpp @@ -411,29 +411,19 @@ void MCMachOStreamer::EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size, void MCMachOStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, uint64_t Size, unsigned ByteAlignment) { - getAssembler().registerSection(*Section); - - // The symbol may not be present, which only creates the section. - if (!Symbol) - return; - // On darwin all virtual sections have zerofill type. assert(Section->isVirtualSection() && "Section does not have zerofill type!"); - assert(Symbol->isUndefined() && "Cannot define a symbol twice!"); + PushSection(); + SwitchSection(Section); - getAssembler().registerSymbol(*Symbol); - - // Emit an align fragment if necessary. - if (ByteAlignment != 1) - new MCAlignFragment(ByteAlignment, 0, 0, ByteAlignment, Section); - - MCFragment *F = new MCFillFragment(0, Size, Section); - Symbol->setFragment(F); - - // Update the maximum alignment on the zero fill section if necessary. - if (ByteAlignment > Section->getAlignment()) - Section->setAlignment(ByteAlignment); + // The symbol may not be present, which only creates the section. + if (Symbol) { + EmitValueToAlignment(ByteAlignment, 0, 1, 0); + EmitLabel(Symbol); + EmitZeros(Size); + } + PopSection(); } // This should always be called with the thread local bss section. Like the diff --git a/lib/MC/MCObjectStreamer.cpp b/lib/MC/MCObjectStreamer.cpp index 15cc0faf540..aecb3844622 100644 --- a/lib/MC/MCObjectStreamer.cpp +++ b/lib/MC/MCObjectStreamer.cpp @@ -577,28 +577,13 @@ bool MCObjectStreamer::EmitRelocDirective(const MCExpr &Offset, StringRef Name, return false; } -void MCObjectStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) { - assert(getCurrentSectionOnly() && "need a section"); - insert(new MCFillFragment(FillValue, NumBytes)); -} - void MCObjectStreamer::emitFill(const MCExpr &NumBytes, uint64_t FillValue, SMLoc Loc) { MCDataFragment *DF = getOrCreateDataFragment(); flushPendingLabels(DF, DF->getContents().size()); - int64_t IntNumBytes; - if (!NumBytes.evaluateAsAbsolute(IntNumBytes, getAssembler())) { - getContext().reportError(Loc, "expected absolute expression"); - return; - } - - if (IntNumBytes <= 0) { - getContext().reportError(Loc, "invalid number of bytes"); - return; - } - - emitFill(IntNumBytes, FillValue); + assert(getCurrentSectionOnly() && "need a section"); + insert(new MCFillFragment(FillValue, NumBytes, Loc)); } void MCObjectStreamer::emitFill(const MCExpr &NumValues, int64_t Size, diff --git a/lib/MC/MCStreamer.cpp b/lib/MC/MCStreamer.cpp index 6e801ed8777..ed10ccbbb74 100644 --- a/lib/MC/MCStreamer.cpp +++ b/lib/MC/MCStreamer.cpp @@ -184,8 +184,7 @@ void MCStreamer::EmitGPRel32Value(const MCExpr *Value) { /// Emit NumBytes bytes worth of the value specified by FillValue. /// This implements directives such as '.space'. void MCStreamer::emitFill(uint64_t NumBytes, uint8_t FillValue) { - for (uint64_t i = 0, e = NumBytes; i != e; ++i) - EmitIntValue(FillValue, 1); + emitFill(*MCConstantExpr::create(NumBytes, getContext()), FillValue); } void MCStreamer::emitFill(uint64_t NumValues, int64_t Size, int64_t Expr) { diff --git a/lib/MC/MCWinCOFFStreamer.cpp b/lib/MC/MCWinCOFFStreamer.cpp index c2583d95c5e..8582d9adafb 100644 --- a/lib/MC/MCWinCOFFStreamer.cpp +++ b/lib/MC/MCWinCOFFStreamer.cpp @@ -257,20 +257,13 @@ void MCWinCOFFStreamer::EmitLocalCommonSymbol(MCSymbol *S, uint64_t Size, auto *Symbol = cast(S); MCSection *Section = getContext().getObjectFileInfo()->getBSSSection(); - getAssembler().registerSection(*Section); - if (Section->getAlignment() < ByteAlignment) - Section->setAlignment(ByteAlignment); - - getAssembler().registerSymbol(*Symbol); + PushSection(); + SwitchSection(Section); + EmitValueToAlignment(ByteAlignment, 0, 1, 0); + EmitLabel(Symbol); Symbol->setExternal(false); - - if (ByteAlignment != 1) - new MCAlignFragment(ByteAlignment, /*Value=*/0, /*ValueSize=*/0, - ByteAlignment, Section); - - MCFillFragment *Fragment = new MCFillFragment( - /*Value=*/0, Size, Section); - Symbol->setFragment(Fragment); + EmitZeros(Size); + PopSection(); } void MCWinCOFFStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol, diff --git a/lib/MC/WasmObjectWriter.cpp b/lib/MC/WasmObjectWriter.cpp index 0f0b645492e..66236e3abfa 100644 --- a/lib/MC/WasmObjectWriter.cpp +++ b/lib/MC/WasmObjectWriter.cpp @@ -528,7 +528,10 @@ static void addData(SmallVectorImpl &DataBytes, Align->getMaxBytesToEmit()); DataBytes.resize(Size, Value); } else if (auto *Fill = dyn_cast(&Frag)) { - DataBytes.insert(DataBytes.end(), Fill->getSize(), Fill->getValue()); + int64_t Size; + if (!Fill->getSize().evaluateAsAbsolute(Size)) + llvm_unreachable("The fill should be an assembler constant"); + DataBytes.insert(DataBytes.end(), Size, Fill->getValue()); } else { const auto &DataFrag = cast(Frag); const SmallVectorImpl &Contents = DataFrag.getContents(); diff --git a/test/MC/X86/eval-fill.s b/test/MC/X86/eval-fill.s new file mode 100644 index 00000000000..f09166ee0f1 --- /dev/null +++ b/test/MC/X86/eval-fill.s @@ -0,0 +1,17 @@ +// RUN: llvm-mc -filetype=obj %s -o - -triple x86_64-pc-linux | llvm-readobj -s | FileCheck %s + +// CHECK: Name: .text +// CHECK-NEXT: Type: SHT_PROGBITS +// CHECK-NEXT: Flags [ +// CHECK-NEXT: SHF_ALLOC +// CHECK-NEXT: SHF_EXECINSTR +// CHECK-NEXT: ] +// CHECK-NEXT: Address: +// CHECK-NEXT: Offset: +// CHECK-NEXT: Size: 4092 + + .globl foo +foo: + .space 4 +bar: + .space 4092 - (bar - foo)