diff options
author | Wouter van Oortmerssen <aardappel@gmail.com> | 2019-03-04 17:18:04 +0000 |
---|---|---|
committer | Wouter van Oortmerssen <aardappel@gmail.com> | 2019-03-04 17:18:04 +0000 |
commit | f3feb6adb919770f7ad4888ecb3a5c15076e5bf6 (patch) | |
tree | 07d7f20e8baa412aabf78b4aaa5503b6d8007fc9 /llvm/lib | |
parent | de11105d2ece076e9d8dcfb01286643e81af8922 (diff) | |
download | bcm5719-llvm-f3feb6adb919770f7ad4888ecb3a5c15076e5bf6.tar.gz bcm5719-llvm-f3feb6adb919770f7ad4888ecb3a5c15076e5bf6.zip |
[WebAssembly] Add support for data sections in the assembler.
Summary:
This is quite minimal so far, introduce them with .section,
fill them with .int8 or .asciz, end with .size
Reviewers: dschuff, sbc100, aheejin
Subscribers: jgravelle-google, sunfish, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D58660
llvm-svn: 355321
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/MC/MCParser/WasmAsmParser.cpp | 31 | ||||
-rw-r--r-- | llvm/lib/MC/WasmObjectWriter.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp | 34 |
3 files changed, 57 insertions, 10 deletions
diff --git a/llvm/lib/MC/MCParser/WasmAsmParser.cpp b/llvm/lib/MC/MCParser/WasmAsmParser.cpp index a8a48d1cd69..197e9052566 100644 --- a/llvm/lib/MC/MCParser/WasmAsmParser.cpp +++ b/llvm/lib/MC/MCParser/WasmAsmParser.cpp @@ -130,11 +130,27 @@ public: if (expect(AsmToken::Comma, ",") || expect(AsmToken::At, "@") || expect(AsmToken::EndOfStatement, "eol")) return true; - // 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); + struct SectionType { + const char *Name; + SectionKind Kind; + }; + static SectionType SectionTypes[] = { + { ".text", SectionKind::getText() }, + { ".rodata", SectionKind::getReadOnly() }, + { ".data", SectionKind::getData() }, + // TODO: add more types. + }; + for (size_t I = 0; I < sizeof(SectionTypes) / sizeof(SectionType); I++) { + if (Name.startswith(SectionTypes[I].Name)) { + auto WS = getContext().getWasmSection(Name, SectionTypes[I].Kind); + getStreamer().SwitchSection(WS); + return false; + } + } + // Not found, just ignore this section. + // For code in a text section WebAssemblyAsmParser automatically adds + // one section per function, so they're optional to be specified with + // this directive. return false; } @@ -153,9 +169,8 @@ public: if (expect(AsmToken::EndOfStatement, "eol")) return true; // 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); + // so this is only currently needed for data sections: + getStreamer().emitELFSize(Sym, Expr); return false; } diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp index b985d4bf4d3..e82ed5898b4 100644 --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -1348,7 +1348,7 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, LLVM_DEBUG(dbgs() << " -> function index: " << Index << "\n"); } else if (WS.isData()) { - if (WS.isTemporary() && !WS.getSize()) + if (!isInSymtab(WS)) continue; if (!WS.isDefined()) { diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp index eeccc3e6449..9d5bb3f11e0 100644 --- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp +++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp @@ -172,6 +172,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser { FunctionLocals, Instructions, EndFunction, + DataSection, } CurrentState = FileStart; // For ensuring blocks are properly nested. @@ -552,6 +553,17 @@ public: return false; } + bool CheckDataSection() { + if (CurrentState != DataSection) { + auto WS = cast<MCSectionWasm>(getStreamer().getCurrentSection().first); + if (WS && WS->getKind().isText()) + return error("data directive must occur in a data segment: ", + Lexer.getTok()); + } + CurrentState = DataSection; + return false; + } + // This function processes wasm-specific directives streamed to // WebAssemblyTargetStreamer, all others go to the generic parser // (see WasmAsmParser). @@ -650,6 +662,25 @@ public: return expect(AsmToken::EndOfStatement, "EOL"); } + if (DirectiveID.getString() == ".int8") { + if (CheckDataSection()) return true; + int64_t V; + if (Parser.parseAbsoluteExpression(V)) + return error("Cannot parse int8 constant: ", Lexer.getTok()); + // TODO: error if value doesn't fit? + Out.EmitIntValue(static_cast<uint64_t>(V), 1); + return expect(AsmToken::EndOfStatement, "EOL"); + } + + if (DirectiveID.getString() == ".asciz") { + if (CheckDataSection()) return true; + std::string S; + if (Parser.parseEscapedString(S)) + return error("Cannot parse string constant: ", Lexer.getTok()); + Out.EmitBytes(StringRef(S.c_str(), S.length() + 1)); + return expect(AsmToken::EndOfStatement, "EOL"); + } + return true; // We didn't process this directive. } @@ -717,9 +748,10 @@ public: void onEndOfFunction() { // Automatically output a .size directive, so it becomes optional for the // user. + if (!LastFunctionLabel) return; auto TempSym = getContext().createLinkerPrivateTempSymbol(); getStreamer().EmitLabel(TempSym); - auto Start = MCSymbolRefExpr::create(LastLabel, getContext()); + auto Start = MCSymbolRefExpr::create(LastFunctionLabel, getContext()); auto End = MCSymbolRefExpr::create(TempSym, getContext()); auto Expr = MCBinaryExpr::create(MCBinaryExpr::Sub, End, Start, getContext()); |