This is an archive of the discontinued LLVM Phabricator instance.

[WebAssembly] Enforce assembler emits to streamer in order.
ClosedPublic

Authored by aardappel on Nov 30 2018, 3:01 PM.

Details

Summary

The assembler processes directives and instructions in whatever order
they are in the file, then directly emits them to the streamer. This
could cause badly written (or generated) .s files to produce
incorrect binaries.

It now has state that tracks what it has most recently seen, to
enforce they are emitted in a given order that always produces
correct wasm binaries.

Also added a new test that compares obj2yaml output from llc (the
backend) to that going via .s and the assembler to ensure both paths
generate the same binaries.

The features this test covers could be extended.

Passes all wasm Lit tests.

Fixes: https://bugs.llvm.org/show_bug.cgi?id=39557

Diff Detail

Event Timeline

aardappel created this revision.Nov 30 2018, 3:01 PM

This took me a while to figure out what was going wrong (lack of .local in a file caused emitLocal not to be called which produced invalid wasm code sections...)

aardappel marked an inline comment as done.Nov 30 2018, 3:11 PM
aardappel added inline comments.
lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
408

This code is not super elegant, but kinda has to be this way because we have .functype which both introduces a function and ones which just declare external ones. Now if you misspel a label you'll fail to start a new function.

More ideal would be split these, and have a .functype with no name that annotates the start of a function (and the assembler enforces only comes after a label) and a different one, e.g. .funcdecl, that does have its own name and is only used for external types. Not sure if such a refactoring is worth it though, after we just re-did all the tests with .functype.

aardappel retitled this revision from [WebAssembly] Enforce assembler emits emits to streamer in order. to [WebAssembly] Enforce assembler emits to streamer in order..Nov 30 2018, 3:12 PM

Style nits

lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
144

Nit: Could you wrap comments to 80 cols? (Currently some lines end prematurely)

150

clang-format this?

161

Nit: Can we use C++11-style in-class initialization for these two variables?

400

Nit: Comment 80-col wrapping too, and maybe other parts as well

451

Is this clang-formatted?

aheejin added inline comments.Dec 3 2018, 5:57 AM
lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
149

This does not seem to be used

test/MC/WebAssembly/assembler-binary.ll
2

Do we need to check all these asm and yaml outputs in this test? Wouldn't yaml output of function symbol related parts be sufficient?

93

Trailing newline

aardappel updated this revision to Diff 176419.Dec 3 2018, 9:36 AM
aardappel marked 13 inline comments as done.

Code review fixes.

aardappel added inline comments.Dec 3 2018, 9:36 AM
lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
150

I did, it doesn't change :)

161

Sure.. I guess I was being conservative, not knowing what level of C++ I can use.

400

There's not much to wrap here, I wanted TODO to start on its own line.

408

Also note that in the past we decided that we like the assembler to be relatively "dumb", in terms of not needing to have a lot of structural knowledge about wasm. Turns out that is not possible with how streamers work, we need the assembler to enforce a certain level of structure.

test/MC/WebAssembly/assembler-binary.ll
2

Yes, but then when the yaml test breaks on e.g. the code bytes, it will be hard to track down which instruction is causing it. With the asm tests, those will break first so it will be easier to fix.

sbc100 added inline comments.Dec 3 2018, 9:39 AM
lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
155

= nullptr here?

396

This sentence doesn't make sense. typo?

408

I like the repeated name in the .functype directive because it seems to match existing assembly directives.

If we want to distinguish between types for internal vs external functions perhaps we would want a new directive such as ".extern_functype" but as you say I'm not sure its worth it.

dschuff added inline comments.Dec 3 2018, 10:10 AM
lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
161

In LLVM, we love ALL the C++! but there's still those pesky older versions of compilers, distros, etc. see https://llvm.org/docs/CodingStandards.html#languages-libraries-and-standards . See also http://lists.llvm.org/pipermail/llvm-dev/2018-October/127045.html

aardappel marked an inline comment as done.Dec 3 2018, 10:52 AM
aardappel added inline comments.
test/MC/WebAssembly/assembler-binary.ll
2

It would be awesome for obj2yaml to be able to disassemble its code section, so we could have more comprehensive binary tests that are readable.

aardappel marked 5 inline comments as done.Dec 3 2018, 11:58 AM
aardappel added inline comments.
lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
161

Yes, I use C++17 on some projects, C++0x (pre-C++11) on others, so I tend to get confused on what I can use. I'll re-read that section to remind myself :)

408

Ok, will leave it as-is unless anyone else feels strongly about it.

aardappel updated this revision to Diff 176446.Dec 3 2018, 11:59 AM
aardappel marked an inline comment as done.

Code review fixes.

sbc100 accepted this revision.Dec 3 2018, 12:17 PM
sbc100 added inline comments.
test/MC/WebAssembly/assembler-binary.ll
2

Hmm, rather than running llc twice here you could do

; RUN: llc -filetype=asm -asm-verbose=false %s -o %t.s
; RUN: FileCheck -check-prefix=ASM --input-file %t.s
; RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=asm %t.s -o - | FileCheck -check-prefix=ASM %s

Basically write the .s to a temp file and use that rather then generating and piping it twice.

I'm really not sure which is better but I thought I'd mention it as an option :)

This revision is now accepted and ready to land.Dec 3 2018, 12:17 PM
aardappel updated this revision to Diff 176453.Dec 3 2018, 12:31 PM

Optimized test runs of llc.

aardappel marked 2 inline comments as done.Dec 3 2018, 12:32 PM
aardappel added inline comments.
test/MC/WebAssembly/assembler-binary.ll
2

Good idea! Removes 3 runs of llc. Though rather than --input-file %t.s it needs -input-file %t.s %s.

This revision was automatically updated to reflect the committed changes.
aardappel marked an inline comment as done.