[llvm] r351460 - [WebAssembly] Fixed objdump not parsing function headers.
Wouter van Oortmerssen via llvm-commits
llvm-commits at lists.llvm.org
Thu Jan 17 10:14:10 PST 2019
Author: aardappel
Date: Thu Jan 17 10:14:09 2019
New Revision: 351460
URL: http://llvm.org/viewvc/llvm-project?rev=351460&view=rev
Log:
[WebAssembly] Fixed objdump not parsing function headers.
Summary:
objdump was interpreting the function header containing the locals
declaration as instructions. To parse these without injecting target
specific code in objdump, MCDisassembler::onSymbolStart was added to
be implemented by the WebAssembly implemention.
WasmObjectFile now returns a code offset for the "address" of a symbol,
rather than the index. This is also more in-line with what other
targets do.
Also ensured that the AsmParser correctly puts each function
in its own segment to enable this test case.
Reviewers: sbc100, dschuff
Subscribers: jgravelle-google, aheejin, sunfish, rupprecht, llvm-commits
Differential Revision: https://reviews.llvm.org/D56684
Added:
llvm/trunk/test/MC/WebAssembly/objdump.s
Modified:
llvm/trunk/include/llvm/MC/MCDisassembler/MCDisassembler.h
llvm/trunk/include/llvm/Object/Wasm.h
llvm/trunk/lib/MC/MCDisassembler/MCDisassembler.cpp
llvm/trunk/lib/MC/MCParser/WasmAsmParser.cpp
llvm/trunk/lib/Object/WasmObjectFile.cpp
llvm/trunk/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
llvm/trunk/lib/Target/WebAssembly/Disassembler/LLVMBuild.txt
llvm/trunk/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
llvm/trunk/test/MC/WebAssembly/weak-alias.ll
llvm/trunk/test/tools/llvm-objdump/WebAssembly/symbol-table.test
llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp
Modified: llvm/trunk/include/llvm/MC/MCDisassembler/MCDisassembler.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/MC/MCDisassembler/MCDisassembler.h?rev=351460&r1=351459&r2=351460&view=diff
==============================================================================
--- llvm/trunk/include/llvm/MC/MCDisassembler/MCDisassembler.h (original)
+++ llvm/trunk/include/llvm/MC/MCDisassembler/MCDisassembler.h Thu Jan 17 10:14:09 2019
@@ -17,6 +17,7 @@
namespace llvm {
template <typename T> class ArrayRef;
+class StringRef;
class MCContext;
class MCInst;
class MCSubtargetInfo;
@@ -80,6 +81,23 @@ public:
raw_ostream &VStream,
raw_ostream &CStream) const = 0;
+ /// May parse any prelude that precedes instructions after the start of a
+ /// symbol. Needed for some targets, e.g. WebAssembly.
+ ///
+ /// \param Name - The name of the symbol.
+ /// \param Size - The number of bytes consumed.
+ /// \param Address - The address, in the memory space of region, of the first
+ /// byte of the symbol.
+ /// \param Bytes - A reference to the actual bytes at the symbol location.
+ /// \param VStream - The stream to print warnings and diagnostic messages on.
+ /// \param CStream - The stream to print comments and annotations on.
+ /// \return - MCDisassembler::Success if the bytes are valid,
+ /// MCDisassembler::Fail if the bytes were invalid.
+ virtual DecodeStatus onSymbolStart(StringRef Name, uint64_t &Size,
+ ArrayRef<uint8_t> Bytes, uint64_t Address,
+ raw_ostream &VStream,
+ raw_ostream &CStream) const;
+
private:
MCContext &Ctx;
Modified: llvm/trunk/include/llvm/Object/Wasm.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Object/Wasm.h?rev=351460&r1=351459&r2=351460&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Object/Wasm.h (original)
+++ llvm/trunk/include/llvm/Object/Wasm.h Thu Jan 17 10:14:09 2019
@@ -222,6 +222,7 @@ private:
bool isValidDataSymbol(uint32_t Index) const;
bool isValidSectionSymbol(uint32_t Index) const;
wasm::WasmFunction &getDefinedFunction(uint32_t Index);
+ const wasm::WasmFunction &getDefinedFunction(uint32_t Index) const;
wasm::WasmGlobal &getDefinedGlobal(uint32_t Index);
wasm::WasmEvent &getDefinedEvent(uint32_t Index);
Modified: llvm/trunk/lib/MC/MCDisassembler/MCDisassembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCDisassembler/MCDisassembler.cpp?rev=351460&r1=351459&r2=351460&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCDisassembler/MCDisassembler.cpp (original)
+++ llvm/trunk/lib/MC/MCDisassembler/MCDisassembler.cpp Thu Jan 17 10:14:09 2019
@@ -8,6 +8,8 @@
//===----------------------------------------------------------------------===//
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/StringRef.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -15,6 +17,13 @@ using namespace llvm;
MCDisassembler::~MCDisassembler() = default;
+MCDisassembler::DecodeStatus MCDisassembler::onSymbolStart(
+ StringRef Name, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address,
+ raw_ostream &VStream, raw_ostream &CStream) const {
+ Size = 0;
+ return MCDisassembler::Success;
+}
+
bool MCDisassembler::tryAddingSymbolicOperand(MCInst &Inst, int64_t Value,
uint64_t Address, bool IsBranch,
uint64_t Offset,
Modified: llvm/trunk/lib/MC/MCParser/WasmAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/MC/MCParser/WasmAsmParser.cpp?rev=351460&r1=351459&r2=351460&view=diff
==============================================================================
--- llvm/trunk/lib/MC/MCParser/WasmAsmParser.cpp (original)
+++ llvm/trunk/lib/MC/MCParser/WasmAsmParser.cpp Thu Jan 17 10:14:09 2019
@@ -22,6 +22,7 @@
#include "llvm/MC/MCParser/MCAsmLexer.h"
#include "llvm/MC/MCParser/MCAsmParser.h"
#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/MC/MCSectionWasm.h"
#include "llvm/MC/MCStreamer.h"
#include "llvm/MC/MCSymbol.h"
#include "llvm/MC/MCSymbolWasm.h"
@@ -83,8 +84,16 @@ public:
}
bool parseSectionDirective(StringRef, SMLoc) {
- // FIXME: .section currently no-op.
- while (Lexer->isNot(AsmToken::EndOfStatement)) Parser->Lex();
+ StringRef Name;
+ if (Parser->parseIdentifier(Name))
+ return TokError("expected identifier in directive");
+ // FIXME: currently requiring this very fixed format.
+ if (Expect(AsmToken::Comma, ",") || Expect(AsmToken::String, "string") ||
+ Expect(AsmToken::Comma, ",") || Expect(AsmToken::At, "@") ||
+ Expect(AsmToken::EndOfStatement, "eol"))
+ return true;
+ auto WS = getContext().getWasmSection(Name, SectionKind::getText());
+ getStreamer().SwitchSection(WS);
return false;
}
@@ -95,15 +104,13 @@ public:
if (Parser->parseIdentifier(Name))
return TokError("expected identifier in directive");
auto Sym = getContext().getOrCreateSymbol(Name);
- if (Lexer->isNot(AsmToken::Comma))
- return TokError("unexpected token in directive");
- Lex();
+ if (Expect(AsmToken::Comma, ","))
+ return true;
const MCExpr *Expr;
if (Parser->parseExpression(Expr))
return true;
- if (Lexer->isNot(AsmToken::EndOfStatement))
- return TokError("unexpected token in directive");
- Lex();
+ if (Expect(AsmToken::EndOfStatement, "eol"))
+ return true;
// MCWasmStreamer implements this.
getStreamer().emitELFSize(Sym, Expr);
return false;
Modified: llvm/trunk/lib/Object/WasmObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/WasmObjectFile.cpp?rev=351460&r1=351459&r2=351460&view=diff
==============================================================================
--- llvm/trunk/lib/Object/WasmObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/WasmObjectFile.cpp Thu Jan 17 10:14:09 2019
@@ -1055,6 +1055,12 @@ wasm::WasmFunction &WasmObjectFile::getD
return Functions[Index - NumImportedFunctions];
}
+const wasm::WasmFunction &
+WasmObjectFile::getDefinedFunction(uint32_t Index) const {
+ assert(isDefinedFunctionIndex(Index));
+ return Functions[Index - NumImportedFunctions];
+}
+
wasm::WasmGlobal &WasmObjectFile::getDefinedGlobal(uint32_t Index) {
assert(isDefinedGlobalIndex(Index));
return Globals[Index - NumImportedGlobals];
@@ -1221,7 +1227,12 @@ Expected<StringRef> WasmObjectFile::getS
}
Expected<uint64_t> WasmObjectFile::getSymbolAddress(DataRefImpl Symb) const {
- return getSymbolValue(Symb);
+ auto &Sym = getWasmSymbol(Symb);
+ if (Sym.Info.Kind == wasm::WASM_SYMBOL_TYPE_FUNCTION &&
+ isDefinedFunctionIndex(Sym.Info.ElementIndex))
+ return getDefinedFunction(Sym.Info.ElementIndex).CodeSectionOffset;
+ else
+ return getSymbolValue(Symb);
}
uint64_t WasmObjectFile::getWasmSymbolValue(const WasmSymbol &Sym) const {
Modified: llvm/trunk/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp?rev=351460&r1=351459&r2=351460&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp Thu Jan 17 10:14:09 2019
@@ -298,6 +298,8 @@ public:
Type == "i32x4" || Type == "i64x2" || Type == "f32x4" ||
Type == "f64x2")
return wasm::ValType::V128;
+ if (Type == "except_ref")
+ return wasm::ValType::EXCEPT_REF;
return Optional<wasm::ValType>();
}
@@ -317,7 +319,7 @@ public:
while (Lexer.is(AsmToken::Identifier)) {
auto Type = parseType(Lexer.getTok().getString());
if (!Type)
- return true;
+ return error("unknown type: ", Lexer.getTok());
Types.push_back(Type.getValue());
Parser.Lex();
if (!isNext(AsmToken::Comma))
@@ -561,6 +563,7 @@ public:
auto &Out = getStreamer();
auto &TOut =
reinterpret_cast<WebAssemblyTargetStreamer &>(*Out.getTargetStreamer());
+ auto &Ctx = Out.getContext();
// TODO: any time we return an error, at least one token must have been
// consumed, otherwise this will not signal an error to the caller.
@@ -578,8 +581,7 @@ public:
if (!Type)
return error("Unknown type in .globaltype directive: ", TypeTok);
// Now set this symbol with the correct type.
- auto WasmSym = cast<MCSymbolWasm>(
- TOut.getStreamer().getContext().getOrCreateSymbol(SymName));
+ auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
WasmSym->setGlobalType(
wasm::WasmGlobalType{uint8_t(Type.getValue()), true});
@@ -597,8 +599,7 @@ public:
auto SymName = expectIdent();
if (SymName.empty())
return true;
- auto WasmSym = cast<MCSymbolWasm>(
- TOut.getStreamer().getContext().getOrCreateSymbol(SymName));
+ auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
if (CurrentState == Label && WasmSym == LastLabel) {
// This .functype indicates a start of a function.
if (ensureEmptyNestingStack())
@@ -621,8 +622,7 @@ public:
auto SymName = expectIdent();
if (SymName.empty())
return true;
- auto WasmSym = cast<MCSymbolWasm>(
- TOut.getStreamer().getContext().getOrCreateSymbol(SymName));
+ auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
auto Signature = make_unique<wasm::WasmSignature>();
if (parseRegTypeList(Signature->Params))
return true;
Modified: llvm/trunk/lib/Target/WebAssembly/Disassembler/LLVMBuild.txt
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/Disassembler/LLVMBuild.txt?rev=351460&r1=351459&r2=351460&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/Disassembler/LLVMBuild.txt (original)
+++ llvm/trunk/lib/Target/WebAssembly/Disassembler/LLVMBuild.txt Thu Jan 17 10:14:09 2019
@@ -19,5 +19,5 @@
type = Library
name = WebAssemblyDisassembler
parent = WebAssembly
-required_libraries = MCDisassembler WebAssemblyInfo Support
+required_libraries = MCDisassembler WebAssemblyInfo WebAssemblyAsmPrinter Support
add_to_library_groups = WebAssembly
Modified: llvm/trunk/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp?rev=351460&r1=351459&r2=351460&view=diff
==============================================================================
--- llvm/trunk/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp (original)
+++ llvm/trunk/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp Thu Jan 17 10:14:09 2019
@@ -15,6 +15,7 @@
///
//===----------------------------------------------------------------------===//
+#include "InstPrinter/WebAssemblyInstPrinter.h"
#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
@@ -45,6 +46,10 @@ class WebAssemblyDisassembler final : pu
ArrayRef<uint8_t> Bytes, uint64_t Address,
raw_ostream &VStream,
raw_ostream &CStream) const override;
+ DecodeStatus onSymbolStart(StringRef Name, uint64_t &Size,
+ ArrayRef<uint8_t> Bytes, uint64_t Address,
+ raw_ostream &VStream,
+ raw_ostream &CStream) const override;
public:
WebAssemblyDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
@@ -77,7 +82,7 @@ static int nextByte(ArrayRef<uint8_t> By
}
static bool nextLEB(int64_t &Val, ArrayRef<uint8_t> Bytes, uint64_t &Size,
- bool Signed = false) {
+ bool Signed) {
unsigned N = 0;
const char *Error = nullptr;
Val = Signed ? decodeSLEB128(Bytes.data() + Size, &N,
@@ -116,6 +121,41 @@ bool parseImmediate(MCInst &MI, uint64_t
return true;
}
+MCDisassembler::DecodeStatus WebAssemblyDisassembler::onSymbolStart(
+ StringRef Name, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t Address,
+ raw_ostream &VStream, raw_ostream &CStream) const {
+ Size = 0;
+ if (Address == 0) {
+ // Start of a code section: we're parsing only the function count.
+ int64_t FunctionCount;
+ if (!nextLEB(FunctionCount, Bytes, Size, false))
+ return MCDisassembler::Fail;
+ outs() << " # " << FunctionCount << " functions in section.";
+ } else {
+ // Parse the start of a single function.
+ int64_t BodySize, LocalEntryCount;
+ if (!nextLEB(BodySize, Bytes, Size, false) ||
+ !nextLEB(LocalEntryCount, Bytes, Size, false))
+ return MCDisassembler::Fail;
+ if (LocalEntryCount) {
+ outs() << " .local ";
+ for (int64_t I = 0; I < LocalEntryCount; I++) {
+ int64_t Count, Type;
+ if (!nextLEB(Count, Bytes, Size, false) ||
+ !nextLEB(Type, Bytes, Size, false))
+ return MCDisassembler::Fail;
+ for (int64_t J = 0; J < Count; J++) {
+ if (I || J)
+ outs() << ", ";
+ outs() << WebAssembly::anyTypeToString(Type);
+ }
+ }
+ }
+ }
+ outs() << "\n";
+ return MCDisassembler::Success;
+}
+
MCDisassembler::DecodeStatus WebAssemblyDisassembler::getInstruction(
MCInst &MI, uint64_t &Size, ArrayRef<uint8_t> Bytes, uint64_t /*Address*/,
raw_ostream & /*OS*/, raw_ostream &CS) const {
@@ -138,7 +178,7 @@ MCDisassembler::DecodeStatus WebAssembly
if (!WasmInst)
return MCDisassembler::Fail;
int64_t PrefixedOpc;
- if (!nextLEB(PrefixedOpc, Bytes, Size))
+ if (!nextLEB(PrefixedOpc, Bytes, Size, false))
return MCDisassembler::Fail;
if (PrefixedOpc < 0 || PrefixedOpc >= WebAssemblyInstructionTableSize)
return MCDisassembler::Fail;
Added: llvm/trunk/test/MC/WebAssembly/objdump.s
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/WebAssembly/objdump.s?rev=351460&view=auto
==============================================================================
--- llvm/trunk/test/MC/WebAssembly/objdump.s (added)
+++ llvm/trunk/test/MC/WebAssembly/objdump.s Thu Jan 17 10:14:09 2019
@@ -0,0 +1,34 @@
+# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -o %t.o -mattr=+simd128,+nontrapping-fptoint,+exception-handling < %s
+# RUN: llvm-objdump -triple=wasm32-unknown-unknown -disassemble %t.o | FileCheck %s
+
+ .section .text.main1,"",@
+ .type test0, at function
+test0:
+ .functype test0 (i32, i64) -> (i32)
+ .local f32, f64, v128, v128
+ local.get 2
+ end_function
+.Lfunc_end0:
+ .size test0, .Lfunc_end0-test0
+
+ .section .text.main2,"",@
+ .type test1, at function
+test1:
+ .functype test1 (i32, i64) -> (i32)
+ .local i32, i64, except_ref
+ local.get 3
+ end_function
+.Lfunc_end1:
+ .size test1, .Lfunc_end1-test1
+
+
+# CHECK-LABEL: CODE:
+# CHECK: # 2 functions in section.
+# CHECK-LABEL: test0:
+# CHECK-NEXT: .local f32, f64, v128, v128
+# CHECK-NEXT: 9: 20 02 local.get 2
+# CHECK-NEXT: b: 0b end_block
+# CHECK-LABEL: test1:
+# CHECK-NEXT: .local i32, i64, except_ref
+# CHECK-NEXT: 14: 20 03 local.get 3
+# CHECK-NEXT: 16: 0b end_block
Modified: llvm/trunk/test/MC/WebAssembly/weak-alias.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/MC/WebAssembly/weak-alias.ll?rev=351460&r1=351459&r2=351460&view=diff
==============================================================================
--- llvm/trunk/test/MC/WebAssembly/weak-alias.ll (original)
+++ llvm/trunk/test/MC/WebAssembly/weak-alias.ll Thu Jan 17 10:14:09 2019
@@ -210,13 +210,13 @@ entry:
; CHECK-NEXT: ...
; CHECK-SYMS: SYMBOL TABLE:
-; CHECK-SYMS-NEXT: 00000000 g F CODE .hidden foo
-; CHECK-SYMS-NEXT: 00000001 g F CODE .hidden call_direct
-; CHECK-SYMS-NEXT: 00000002 g F CODE .hidden call_alias
-; CHECK-SYMS-NEXT: 00000000 gw F CODE .hidden foo_alias
-; CHECK-SYMS-NEXT: 00000003 g F CODE .hidden call_direct_ptr
+; CHECK-SYMS-NEXT: 00000001 g F CODE .hidden foo
+; CHECK-SYMS-NEXT: 00000006 g F CODE .hidden call_direct
+; CHECK-SYMS-NEXT: 0000000f g F CODE .hidden call_alias
+; CHECK-SYMS-NEXT: 00000001 gw F CODE .hidden foo_alias
+; CHECK-SYMS-NEXT: 00000018 g F CODE .hidden call_direct_ptr
; CHECK-SYMS-NEXT: 00000008 g O DATA direct_address
-; CHECK-SYMS-NEXT: 00000004 g F CODE .hidden call_alias_ptr
+; CHECK-SYMS-NEXT: 0000002b g F CODE .hidden call_alias_ptr
; CHECK-SYMS-NEXT: 00000010 g O DATA alias_address
; CHECK-SYMS-NEXT: 00000000 g O DATA bar
; CHECK-SYMS-NEXT: 00000000 gw O DATA .hidden bar_alias
Modified: llvm/trunk/test/tools/llvm-objdump/WebAssembly/symbol-table.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objdump/WebAssembly/symbol-table.test?rev=351460&r1=351459&r2=351460&view=diff
==============================================================================
--- llvm/trunk/test/tools/llvm-objdump/WebAssembly/symbol-table.test (original)
+++ llvm/trunk/test/tools/llvm-objdump/WebAssembly/symbol-table.test Thu Jan 17 10:14:09 2019
@@ -1,9 +1,9 @@
RUN: llvm-objdump -t %p/../Inputs/trivial.obj.wasm | FileCheck %s
CHECK: SYMBOL TABLE:
-CHECK-NEXT: 00000002 g F CODE main
+CHECK-NEXT: 00000001 g F CODE main
CHECK-NEXT: 00000000 l O DATA .L.str
CHECK-NEXT: 00000000 g F *UND* puts
-CHECK-NEXT: 00000003 l F CODE .LSomeOtherFunction_bitcast
+CHECK-NEXT: 00000019 l F CODE .LSomeOtherFunction_bitcast
CHECK-NEXT: 00000000 g F *UND* SomeOtherFunction
CHECK-NEXT: 00000010 g O DATA var
Modified: llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp?rev=351460&r1=351459&r2=351460&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp (original)
+++ llvm/trunk/tools/llvm-objdump/llvm-objdump.cpp Thu Jan 17 10:14:09 2019
@@ -1605,6 +1605,12 @@ static void disassembleObject(const Obje
raw_ostream &DebugOut = nulls();
#endif
+ // Some targets (like WebAssembly) have a special prelude at the start
+ // of each symbol.
+ DisAsm->onSymbolStart(SymbolName, Size, Bytes.slice(Start, End - Start),
+ SectionAddr + Start, DebugOut, CommentStream);
+ Start += Size;
+
for (Index = Start; Index < End; Index += Size) {
MCInst Inst;
More information about the llvm-commits
mailing list