aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorWouter van Oortmerssen <aardappel@gmail.com>2019-02-04 18:03:11 +0000
committerWouter van Oortmerssen <aardappel@gmail.com>2019-02-04 18:03:11 +0000
commit17ad20248897d0275252abb2fe0272c03b2c1d14 (patch)
treee7a470f3584a9d39493e660dd8c4a4afa939381e /lib
parent93cc33fa0ff4da73bcec44e7fb2f403bbdbce0e4 (diff)
downloadllvm-17ad20248897d0275252abb2fe0272c03b2c1d14.tar.gz
[WebAssembly] Make segment/size/type directives optional in asm
Summary: These were "boilerplate" that repeated information already present in .functype and end_function, that needed to be repeated to Please the particular way our object writing works, and missing them would generate errors. Instead, we generate the information for these automatically so the user can concern itself with writing more canonical wasm functions that always work as expected. Reviewers: dschuff, sbc100 Subscribers: jgravelle-google, aheejin, sunfish, llvm-commits Differential Revision: https://reviews.llvm.org/D57546 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@353067 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/MC/MCParser/WasmAsmParser.cpp13
-rw-r--r--lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp36
2 files changed, 44 insertions, 5 deletions
diff --git a/lib/MC/MCParser/WasmAsmParser.cpp b/lib/MC/MCParser/WasmAsmParser.cpp
index d2099be9c8c..485be2285b0 100644
--- a/lib/MC/MCParser/WasmAsmParser.cpp
+++ b/lib/MC/MCParser/WasmAsmParser.cpp
@@ -91,8 +91,11 @@ public:
Expect(AsmToken::Comma, ",") || Expect(AsmToken::At, "@") ||
Expect(AsmToken::EndOfStatement, "eol"))
return true;
- auto WS = getContext().getWasmSection(Name, SectionKind::getText());
- getStreamer().SwitchSection(WS);
+ // This is done automatically by the assembler for text sections currently,
+ // so we don't need to emit that here. This is what it would do (and may
+ // be needed later for other section types):
+ // auto WS = getContext().getWasmSection(Name, SectionKind::getText());
+ // getStreamer().SwitchSection(WS);
return false;
}
@@ -110,8 +113,10 @@ public:
return true;
if (Expect(AsmToken::EndOfStatement, "eol"))
return true;
- // MCWasmStreamer implements this.
- getStreamer().emitELFSize(Sym, Expr);
+ // This is done automatically by the assembler for functions currently,
+ // so we don't need to emit that here. This is what it would do:
+ (void)Sym;
+ // getStreamer().emitELFSize(Sym, Expr);
return false;
}
diff --git a/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
index 48af89f24aa..a0455cb98d5 100644
--- a/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -17,10 +17,12 @@
#include "MCTargetDesc/WebAssemblyTargetStreamer.h"
#include "WebAssembly.h"
#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCExpr.h"
#include "llvm/MC/MCInst.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCSectionWasm.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCSymbol.h"
@@ -169,6 +171,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
FunctionStart,
FunctionLocals,
Instructions,
+ EndFunction,
} CurrentState = FileStart;
// For ensuring blocks are properly nested.
@@ -186,6 +189,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
// We track this to see if a .functype following a label is the same,
// as this is how we recognize the start of a function.
MCSymbol *LastLabel = nullptr;
+ MCSymbol *LastFunctionLabel = nullptr;
public:
WebAssemblyAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
@@ -445,6 +449,7 @@ public:
if (pop(BaseName, Block))
return true;
} else if (BaseName == "end_function") {
+ CurrentState = EndFunction;
if (pop(BaseName, Function) || ensureEmptyNestingStack())
return true;
}
@@ -604,6 +609,7 @@ public:
if (ensureEmptyNestingStack())
return true;
CurrentState = FunctionStart;
+ LastFunctionLabel = LastLabel;
push(Function);
}
auto Signature = make_unique<wasm::WasmSignature>();
@@ -666,8 +672,12 @@ public:
*Out.getTargetStreamer());
TOut.emitLocal(SmallVector<wasm::ValType, 0>());
}
- CurrentState = Instructions;
Out.EmitInstruction(Inst, getSTI());
+ if (CurrentState == EndFunction) {
+ onEndOfFunction();
+ } else {
+ CurrentState = Instructions;
+ }
return false;
}
case Match_MissingFeature:
@@ -693,6 +703,30 @@ public:
llvm_unreachable("Implement any new match types added!");
}
+ void doBeforeLabelEmit(MCSymbol *Symbol) override {
+ // Start a new section for the next function automatically, since our
+ // object writer expects each function to have its own section. This way
+ // The user can't forget this "convention".
+ auto SymName = Symbol->getName();
+ if (SymName.startswith(".L"))
+ return; // Local Symbol.
+ auto SecName = ".text." + SymName;
+ auto WS = getContext().getWasmSection(SecName, SectionKind::getText());
+ getStreamer().SwitchSection(WS);
+ }
+
+ void onEndOfFunction() {
+ // Automatically output a .size directive, so it becomes optional for the
+ // user.
+ auto TempSym = getContext().createLinkerPrivateTempSymbol();
+ getStreamer().EmitLabel(TempSym);
+ auto Start = MCSymbolRefExpr::create(LastLabel, getContext());
+ auto End = MCSymbolRefExpr::create(TempSym, getContext());
+ auto Expr =
+ MCBinaryExpr::create(MCBinaryExpr::Sub, End, Start, getContext());
+ getStreamer().emitELFSize(LastFunctionLabel, Expr);
+ }
+
void onEndOfFile() override { ensureEmptyNestingStack(); }
};
} // end anonymous namespace