summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2018-01-30 09:31:00 +0000
committerHans Wennborg <hans@hanshq.net>2018-01-30 09:31:00 +0000
commit98b79f2cd78d57b8e5f5307ac889fa264cddcc36 (patch)
tree7636da279d64d7a07d0580e24e617f06ca3ad6fd
parentf1286127b73c0d81ced8595af62e78ed703ced8b (diff)
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
-rw-r--r--include/llvm/MC/MCFragment.h15
-rw-r--r--include/llvm/MC/MCObjectStreamer.h1
-rw-r--r--include/llvm/MC/MCStreamer.h2
-rw-r--r--lib/MC/MCAsmStreamer.cpp16
-rw-r--r--lib/MC/MCAssembler.cpp16
-rw-r--r--lib/MC/MCMachOStreamer.cpp28
-rw-r--r--lib/MC/MCObjectStreamer.cpp19
-rw-r--r--lib/MC/MCStreamer.cpp3
-rw-r--r--lib/MC/MCWinCOFFStreamer.cpp19
-rw-r--r--lib/MC/WasmObjectWriter.cpp5
-rw-r--r--test/MC/X86/eval-fill.s17
11 files changed, 68 insertions, 73 deletions
diff --git a/include/llvm/MC/MCFragment.h b/include/llvm/MC/MCFragment.h
index 7ebde03a758c..85b55e85469a 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 a3dbc56ebc10..43ed00b4a7a7 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 a82051700708..28b326ae9b87 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 e521b6e7c704..bddd264fe30b 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 01d165944bec..bd881b4d6e85 100644
--- a/lib/MC/MCAssembler.cpp
+++ b/lib/MC/MCAssembler.cpp
@@ -281,8 +281,18 @@ uint64_t MCAssembler::computeFragmentSize(const MCAsmLayout &Layout,
return cast<MCRelaxableFragment>(F).getContents().size();
case MCFragment::FT_CompactEncodedInst:
return cast<MCCompactEncodedInstFragment>(F).getContents().size();
- case MCFragment::FT_Fill:
- return cast<MCFillFragment>(F).getSize();
+ case MCFragment::FT_Fill: {
+ auto &FF = cast<MCFillFragment>(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<MCLEBFragment>(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 82b75afabb3c..3969143bb2c7 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 15cc0faf5407..aecb3844622b 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 6e801ed8777c..ed10ccbbb742 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 c2583d95c5ed..8582d9adafb8 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<MCSymbolCOFF>(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 0f0b645492ee..66236e3abfab 100644
--- a/lib/MC/WasmObjectWriter.cpp
+++ b/lib/MC/WasmObjectWriter.cpp
@@ -528,7 +528,10 @@ static void addData(SmallVectorImpl<char> &DataBytes,
Align->getMaxBytesToEmit());
DataBytes.resize(Size, Value);
} else if (auto *Fill = dyn_cast<MCFillFragment>(&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<MCDataFragment>(Frag);
const SmallVectorImpl<char> &Contents = DataFrag.getContents();
diff --git a/test/MC/X86/eval-fill.s b/test/MC/X86/eval-fill.s
new file mode 100644
index 000000000000..f09166ee0f12
--- /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)