[llvm] 9647a6f - [WebAssembly] Added initial type checker to MC Assembler

Wouter van Oortmerssen via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 9 14:07:53 PDT 2021


Author: Wouter van Oortmerssen
Date: 2021-07-09T14:07:25-07:00
New Revision: 9647a6f719ee4b1c23eea7aef368c1dcd5317949

URL: https://github.com/llvm/llvm-project/commit/9647a6f719ee4b1c23eea7aef368c1dcd5317949
DIFF: https://github.com/llvm/llvm-project/commit/9647a6f719ee4b1c23eea7aef368c1dcd5317949.diff

LOG: [WebAssembly] Added initial type checker to MC Assembler

This to protect against non-sensical instruction sequences being assembled,
which would either cause asserts/crashes further down, or a Wasm module being output that doesn't validate.

Unlike a validator, this type checker is able to give type-errors as part of the parsing process, which makes the assembler much friendlier to be used by humans writing manual input.

Because the MC system is single pass (instructions aren't even stored in MC format, they are directly output) the type checker has to be single pass as well, which means that from now on .globaltype and .functype decls must come before their use. An extra pass is added to Codegen to collect information for this purpose, since AsmPrinter is normally single pass / streaming as well, and would otherwise generate this information on the fly.

A `-no-type-check` flag was added to llvm-mc (and any other tools that take asm input) that surpresses type errors, as a quick escape hatch for tests that were not intended to be type correct.

This is a first version of the type checker that ignores control flow, i.e. it checks that types are correct along the linear path, but not the branch path. This will still catch most errors. Branch checking could be added in the future.

Differential Revision: https://reviews.llvm.org/D104945

Added: 
    llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp
    llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h
    llvm/lib/Target/WebAssembly/WebAssemblyMCLowerPrePass.cpp

Modified: 
    lld/test/wasm/Inputs/call-ret32.s
    lld/test/wasm/Inputs/ctor-lib.s
    lld/test/wasm/Inputs/ctor-setup-call-def.s
    lld/test/wasm/Inputs/ctor-setup.s
    lld/test/wasm/Inputs/ctor-start.s
    lld/test/wasm/Inputs/hello.s
    lld/test/wasm/Inputs/import-attributes.s
    lld/test/wasm/Inputs/sig_mismatch.s
    lld/test/wasm/Inputs/undefined-globals.s
    lld/test/wasm/bsymbolic.s
    lld/test/wasm/comdat-sections.s
    lld/test/wasm/ctor_return_value.s
    lld/test/wasm/debuginfo-undefined-global.s
    lld/test/wasm/demangle.s
    lld/test/wasm/early-exit-for-bad-paths.s
    lld/test/wasm/entry-signature.s
    lld/test/wasm/export-all.s
    lld/test/wasm/export-optional.s
    lld/test/wasm/gc-imports.s
    lld/test/wasm/import-attribute-mismatch.s
    lld/test/wasm/map-file.s
    lld/test/wasm/multivalue-return-func-types.s
    lld/test/wasm/mutable-globals.s
    lld/test/wasm/name-section-mangling.s
    lld/test/wasm/relocatable-comdat.s
    lld/test/wasm/relocation-bad-tls.s
    lld/test/wasm/shared.s
    lld/test/wasm/shared64.s
    lld/test/wasm/signature-mismatch-relocatable.s
    lld/test/wasm/undefined-data.s
    lld/test/wasm/undefined-weak-call.s
    lld/test/wasm/unresolved-symbols.s
    lld/test/wasm/weak-and-strong-undef.s
    lld/test/wasm/weak-symbols.s
    lld/test/wasm/weak-undefined-pic.s
    lld/test/wasm/weak-undefined.s
    llvm/include/llvm/CodeGen/MachineModuleInfo.h
    llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h
    llvm/include/llvm/MC/MCTargetOptions.h
    llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
    llvm/lib/CodeGen/MachineModuleInfoImpls.cpp
    llvm/lib/MC/MCTargetOptions.cpp
    llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
    llvm/lib/Target/WebAssembly/AsmParser/CMakeLists.txt
    llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
    llvm/lib/Target/WebAssembly/CMakeLists.txt
    llvm/lib/Target/WebAssembly/TargetInfo/WebAssemblyTargetInfo.h
    llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp
    llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h
    llvm/lib/Target/WebAssembly/WebAssembly.h
    llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
    llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td
    llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
    llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td
    llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp
    llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.h
    llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
    llvm/test/CodeGen/WebAssembly/exception.ll
    llvm/test/CodeGen/WebAssembly/global-get.ll
    llvm/test/CodeGen/WebAssembly/i128-returned.ll
    llvm/test/CodeGen/WebAssembly/indirect-import.ll
    llvm/test/CodeGen/WebAssembly/load-store-pic.ll
    llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj-options.ll
    llvm/test/CodeGen/WebAssembly/lower-global-dtors.ll
    llvm/test/CodeGen/WebAssembly/userstack.ll
    llvm/test/MC/WebAssembly/alias-offset.s
    llvm/test/MC/WebAssembly/annotations.s
    llvm/test/MC/WebAssembly/assembler-binary.ll
    llvm/test/MC/WebAssembly/atomics-encodings.s
    llvm/test/MC/WebAssembly/bad-fixup-expr.s
    llvm/test/MC/WebAssembly/basic-assembly.s
    llvm/test/MC/WebAssembly/bulk-memory-encodings.s
    llvm/test/MC/WebAssembly/data-section-combined.s
    llvm/test/MC/WebAssembly/globals.s
    llvm/test/MC/WebAssembly/import-module.s
    llvm/test/MC/WebAssembly/null-output.s
    llvm/test/MC/WebAssembly/objdump.s
    llvm/test/MC/WebAssembly/reference-types.s
    llvm/test/MC/WebAssembly/reloc-pic.s
    llvm/test/MC/WebAssembly/reloc-pic64.s
    llvm/test/MC/WebAssembly/simd-encodings.s
    llvm/test/MC/WebAssembly/tail-call-encodings.s
    llvm/test/MC/WebAssembly/tls.s
    llvm/test/MC/WebAssembly/type-index.s
    llvm/test/MC/WebAssembly/wasm64.s
    llvm/test/MC/WebAssembly/weak-alias.s
    llvm/utils/gn/secondary/llvm/lib/Target/WebAssembly/AsmParser/BUILD.gn
    llvm/utils/gn/secondary/llvm/lib/Target/WebAssembly/BUILD.gn

Removed: 
    


################################################################################
diff  --git a/lld/test/wasm/Inputs/call-ret32.s b/lld/test/wasm/Inputs/call-ret32.s
index b0c8129059171..a49b82519a9c2 100644
--- a/lld/test/wasm/Inputs/call-ret32.s
+++ b/lld/test/wasm/Inputs/call-ret32.s
@@ -1,3 +1,5 @@
+.functype ret32 (f32) -> (i32)
+
   .globl  call_ret32
 call_ret32:
   .functype call_ret32 () -> (i32)
@@ -12,5 +14,3 @@ call_ret32:
 ret32_address:
   .int32  ret32
   .size ret32_address, 4
-
-  .functype ret32 (f32) -> (i32)

diff  --git a/lld/test/wasm/Inputs/ctor-lib.s b/lld/test/wasm/Inputs/ctor-lib.s
index 67dc0b02ee75c..bc321b26d9a2c 100644
--- a/lld/test/wasm/Inputs/ctor-lib.s
+++ b/lld/test/wasm/Inputs/ctor-lib.s
@@ -1,3 +1,5 @@
+	.functype	def () -> ()
+
 	.section	.text.lib_func,"",@
 	.globl	lib_func
 lib_func:

diff  --git a/lld/test/wasm/Inputs/ctor-setup-call-def.s b/lld/test/wasm/Inputs/ctor-setup-call-def.s
index b0d09ddceeb7f..511cedbd010e3 100644
--- a/lld/test/wasm/Inputs/ctor-setup-call-def.s
+++ b/lld/test/wasm/Inputs/ctor-setup-call-def.s
@@ -1,6 +1,8 @@
 # Like Inputs/ctor-setup.s, except it calls `def` instead of `lib_func`,
 # so it pulls in the .o file containing `ctor`.
 
+.functype       def () -> ()
+
 	.section	.text._start,"",@
 	.globl	_start
 _start:
@@ -17,5 +19,3 @@ setup:
 	.section	.init_array,"",@
 	.p2align	2
 	.int32 setup
-
-.functype       def () -> ()

diff  --git a/lld/test/wasm/Inputs/ctor-setup.s b/lld/test/wasm/Inputs/ctor-setup.s
index 814954842b5a4..01b8ad2db7314 100644
--- a/lld/test/wasm/Inputs/ctor-setup.s
+++ b/lld/test/wasm/Inputs/ctor-setup.s
@@ -1,6 +1,8 @@
 # Like Inputs/ctor-start.s, except it calls `lib_func` from a ctor
 # instead of from `_start`.
 
+.functype       lib_func () -> ()
+
 	.globl	_start
 _start:
 	.functype	_start () -> ()
@@ -16,4 +18,3 @@ setup:
 	.p2align	2
 	.int32	setup
 
-        .functype       lib_func () -> ()

diff  --git a/lld/test/wasm/Inputs/ctor-start.s b/lld/test/wasm/Inputs/ctor-start.s
index 8f85fd2b2e137..87fa3a95bdb14 100644
--- a/lld/test/wasm/Inputs/ctor-start.s
+++ b/lld/test/wasm/Inputs/ctor-start.s
@@ -1,7 +1,8 @@
+.functype	lib_func () -> ()
+
 	.globl _start
 _start:
 	.functype	_start () -> ()
 	call lib_func
 	end_function
 
-	.functype	lib_func () -> ()

diff  --git a/lld/test/wasm/Inputs/hello.s b/lld/test/wasm/Inputs/hello.s
index b245262f9eba4..664b1ccdcc090 100644
--- a/lld/test/wasm/Inputs/hello.s
+++ b/lld/test/wasm/Inputs/hello.s
@@ -2,6 +2,8 @@
 #   void puts(const char*);
 #   void hello() { puts("hello\n"); }
 
+  .functype puts (i32) -> ()
+
   .globl  hello
 hello:
   .functype hello () -> ()
@@ -14,5 +16,3 @@ hello:
 hello_str:
   .asciz  "hello\n"
   .size hello_str, 7
-
-  .functype puts (i32) -> ()

diff  --git a/lld/test/wasm/Inputs/import-attributes.s b/lld/test/wasm/Inputs/import-attributes.s
index 681b54fb78f38..031d472a2e20d 100644
--- a/lld/test/wasm/Inputs/import-attributes.s
+++ b/lld/test/wasm/Inputs/import-attributes.s
@@ -1,8 +1,9 @@
+.functype foo () -> ()
+
   .globl  call_foo
 call_foo:
   .functype call_foo () -> ()
   call  foo
   end_function
 
-  .functype foo () -> ()
   .import_module  foo, baz

diff  --git a/lld/test/wasm/Inputs/sig_mismatch.s b/lld/test/wasm/Inputs/sig_mismatch.s
index 713186b9598fd..c34ae4b1e088a 100644
--- a/lld/test/wasm/Inputs/sig_mismatch.s
+++ b/lld/test/wasm/Inputs/sig_mismatch.s
@@ -8,5 +8,6 @@ foo:
 .globl call_foo
 call_foo:
    .functype call_foo () -> (i32)
+   f32.const 0.0
    call foo
    end_function

diff  --git a/lld/test/wasm/Inputs/undefined-globals.s b/lld/test/wasm/Inputs/undefined-globals.s
index 54dc4189a7770..7cbef117eeb49 100644
--- a/lld/test/wasm/Inputs/undefined-globals.s
+++ b/lld/test/wasm/Inputs/undefined-globals.s
@@ -2,10 +2,10 @@
 .globl unused_undef_global
 .globl used_undef_global
 
+.globaltype unused_undef_global, i64, immutable
+.globaltype used_undef_global, i64, immutable
+
 use_undef_global:
   .functype use_undef_global () -> (i64)
   global.get used_undef_global
   end_function
-
-.globaltype unused_undef_global, i64, immutable
-.globaltype used_undef_global, i64, immutable

diff  --git a/lld/test/wasm/bsymbolic.s b/lld/test/wasm/bsymbolic.s
index 79c4a8700fdda..872fb1b53486b 100644
--- a/lld/test/wasm/bsymbolic.s
+++ b/lld/test/wasm/bsymbolic.s
@@ -100,6 +100,7 @@
 // SYMBOLIC-NEXT:  - Type:            EXPORT
 
 .globl foo
+
 foo:
   .functype foo () -> ()
   end_function

diff  --git a/lld/test/wasm/comdat-sections.s b/lld/test/wasm/comdat-sections.s
index fc8d2ded1980e..4fd555618b3bf 100644
--- a/lld/test/wasm/comdat-sections.s
+++ b/lld/test/wasm/comdat-sections.s
@@ -4,6 +4,7 @@
 # RUN: wasm-ld  -o %t.wasm %t.o %t1.o %t2.o
 # RUN: obj2yaml %t.wasm | FileCheck %s
 
+        .functype foo () -> ()
 
         .globl  _start
         .type  _start, at function
@@ -12,8 +13,6 @@ _start:
         call foo
         end_function
 
-        .functype foo () -> ()
-
 
 # Check that we got 1 copy of each of the .debug_foo sections from the 2 object
 # files, and that they came from the same object.

diff  --git a/lld/test/wasm/ctor_return_value.s b/lld/test/wasm/ctor_return_value.s
index d21b58eaaca13..1943306c88f90 100644
--- a/lld/test/wasm/ctor_return_value.s
+++ b/lld/test/wasm/ctor_return_value.s
@@ -2,6 +2,8 @@
 # RUN: wasm-ld %t.o -o %t.wasm
 # RUN: obj2yaml %t.wasm | FileCheck %s
 
+  .functype __wasm_call_ctors () -> ()
+
   .globl  myctor
 myctor:
   .functype myctor () -> (i32)

diff  --git a/lld/test/wasm/debuginfo-undefined-global.s b/lld/test/wasm/debuginfo-undefined-global.s
index 76794779e3c4f..3d49a970c982c 100644
--- a/lld/test/wasm/debuginfo-undefined-global.s
+++ b/lld/test/wasm/debuginfo-undefined-global.s
@@ -7,6 +7,8 @@
 # foo which is not otherwise used and will not be marked a live in the output.
 # Verify the tombstone value is written to debug_info section.
 
+.globaltype foo, i32
+
 .globl  _start
 _start:
   .functype _start () -> ()
@@ -15,7 +17,6 @@ _start:
 .section .debug_info,"",@
   .int32 foo
 
-.globaltype foo, i32
 foo:
 
 # CHECK:       - Type:            CUSTOM

diff  --git a/lld/test/wasm/demangle.s b/lld/test/wasm/demangle.s
index 7e1af46d64b89..995416eaf920a 100644
--- a/lld/test/wasm/demangle.s
+++ b/lld/test/wasm/demangle.s
@@ -8,6 +8,8 @@
 
 # CHECK-NODEMANGLE: error: {{.*}}.o: undefined symbol: _Z3fooi
 
+.functype _Z3fooi (i32) -> ()
+
   .globl  _start
 _start:
   .functype _start () -> ()
@@ -15,4 +17,3 @@ _start:
   call  _Z3fooi
   end_function
 
-.functype _Z3fooi (i32) -> ()

diff  --git a/lld/test/wasm/early-exit-for-bad-paths.s b/lld/test/wasm/early-exit-for-bad-paths.s
index 21cec318e4490..e723d6f1465a4 100644
--- a/lld/test/wasm/early-exit-for-bad-paths.s
+++ b/lld/test/wasm/early-exit-for-bad-paths.s
@@ -22,6 +22,8 @@
 # RUN: not wasm-ld %t.o -o / 2>&1 | FileCheck %s -check-prefixes=ROOT,CHECK
 # ROOT: error: cannot open output file /
 
+.functype undefined_symbol () -> ()
+
 _start:
     .functype _start () -> ()
     call undefined_symbol

diff  --git a/lld/test/wasm/entry-signature.s b/lld/test/wasm/entry-signature.s
index b6f355c131934..7f349c853b6ee 100644
--- a/lld/test/wasm/entry-signature.s
+++ b/lld/test/wasm/entry-signature.s
@@ -5,4 +5,5 @@
   .globl  _start
 _start:
   .functype _start (i64) -> (f32)
+  f32.const 0.0
   end_function

diff  --git a/lld/test/wasm/export-all.s b/lld/test/wasm/export-all.s
index 5f013813cdf17..009da9f6a3817 100644
--- a/lld/test/wasm/export-all.s
+++ b/lld/test/wasm/export-all.s
@@ -2,6 +2,8 @@
 # RUN: wasm-ld --export-all -o %t.wasm %t.o
 # RUN: obj2yaml %t.wasm | FileCheck %s
 
+.globaltype __stack_pointer, i32
+
 .globl _start
 
 _start:
@@ -15,8 +17,6 @@ foo:
   i32.const 42
   end_function
 
-.globaltype __stack_pointer, i32
-
 #      CHECK:   - Type:            EXPORT
 # CHECK-NEXT:     Exports:
 # CHECK-NEXT:       - Name:            memory

diff  --git a/lld/test/wasm/export-optional.s b/lld/test/wasm/export-optional.s
index 7e6f4debc0a97..1509715238312 100644
--- a/lld/test/wasm/export-optional.s
+++ b/lld/test/wasm/export-optional.s
@@ -8,6 +8,7 @@
   .globl  _start
 _start:
   .functype _start () -> ()
+  i32.const 0
   i32.load foo
   drop
   end_function

diff  --git a/lld/test/wasm/gc-imports.s b/lld/test/wasm/gc-imports.s
index 644e9f951a335..4e6053b5caf2c 100644
--- a/lld/test/wasm/gc-imports.s
+++ b/lld/test/wasm/gc-imports.s
@@ -7,7 +7,8 @@
 .functype use_undef_global () -> (i64)
 
 foo:
-  .functype foo () -> ()
+  .functype foo (i64) -> (i64)
+  local.get 0
   call unused_undef_function
   end_function
 
@@ -16,7 +17,9 @@ foo:
 _start:
   .functype _start () -> ()
   call used_undef_function
+  drop
   call use_undef_global
+  drop
   end_function
 
 # RUN: obj2yaml %t1.wasm | FileCheck %s

diff  --git a/lld/test/wasm/import-attribute-mismatch.s b/lld/test/wasm/import-attribute-mismatch.s
index 67aa1e39ef368..59988dc62f087 100644
--- a/lld/test/wasm/import-attribute-mismatch.s
+++ b/lld/test/wasm/import-attribute-mismatch.s
@@ -2,13 +2,14 @@
 # RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %S/Inputs/import-attributes.s -o %t2.o
 # RUN: not wasm-ld --export call_foo --allow-undefined -o %t.wasm %t1.o %t2.o 2>&1 | FileCheck %s
 
+.functype foo () -> ()
+
   .globl  _start
 _start:
   .functype _start () -> ()
   call  foo
   end_function
 
-.functype foo () -> ()
 .import_module  foo, bar
 
 # CHECK: wasm-ld: error: import module mismatch for symbol: foo

diff  --git a/lld/test/wasm/map-file.s b/lld/test/wasm/map-file.s
index 9ca2f196f331e..a1964fb6ecd1f 100644
--- a/lld/test/wasm/map-file.s
+++ b/lld/test/wasm/map-file.s
@@ -8,11 +8,10 @@
 wasm_global:
 
 bar:
-    .functype bar () -> ()
+    .functype bar () -> (i32)
     i32.const   somedata
     i32.const   somezeroes
     drop
-    drop
     end_function
 
 write_global:
@@ -43,30 +42,30 @@ somezeroes:
 
 
 #      CHECK:    Addr      Off     Size Out     In      Symbol
-# CHECK-NEXT:       -        8        a TYPE
-# CHECK-NEXT:       -       12        6 FUNCTION
-# CHECK-NEXT:       -       18        7 TABLE
-# CHECK-NEXT:       -       1f        5 MEMORY
-# CHECK-NEXT:       -       24        f GLOBAL
+# CHECK-NEXT:       -        8        e TYPE
+# CHECK-NEXT:       -       16        6 FUNCTION
+# CHECK-NEXT:       -       1c        7 TABLE
+# CHECK-NEXT:       -       23        5 MEMORY
+# CHECK-NEXT:       -       28        f GLOBAL
 # CHECK-NEXT:       0        0        0         __stack_pointer
 # CHECK-NEXT:       1        0        0         wasm_global
-# CHECK-NEXT:       -       33       15 EXPORT
-# CHECK-NEXT:       -       48       2e CODE
-# CHECK-NEXT:       -       49       11         {{.*}}{{/|\\}}map-file.s.tmp1.o:(bar)
-# CHECK-NEXT:       -       49       11                 bar
-# CHECK-NEXT:       -       5a        b         {{.*}}{{/|\\}}map-file.s.tmp1.o:(write_global)
-# CHECK-NEXT:       -       5a        b                 write_global
-# CHECK-NEXT:       -       65        f         {{.*}}{{/|\\}}map-file.s.tmp1.o:(_start)
-# CHECK-NEXT:       -       65        f                 _start
-# CHECK-NEXT:       -       76        d DATA
-# CHECK-NEXT:     400       77        4 .data
-# CHECK-NEXT:     400       7d        4         {{.*}}{{/|\\}}map-file.s.tmp1.o:(.data.somedata)
-# CHECK-NEXT:     400       7d        4                 somedata
-# CHECK-NEXT:     404       76        4 .bss
+# CHECK-NEXT:       -       37       15 EXPORT
+# CHECK-NEXT:       -       4c       2d CODE
+# CHECK-NEXT:       -       4d       10         {{.*}}{{/|\\}}map-file.s.tmp1.o:(bar)
+# CHECK-NEXT:       -       4d       10                 bar
+# CHECK-NEXT:       -       5d        b         {{.*}}{{/|\\}}map-file.s.tmp1.o:(write_global)
+# CHECK-NEXT:       -       5d        b                 write_global
+# CHECK-NEXT:       -       68        f         {{.*}}{{/|\\}}map-file.s.tmp1.o:(_start)
+# CHECK-NEXT:       -       68        f                 _start
+# CHECK-NEXT:       -       79        d DATA
+# CHECK-NEXT:     400       7a        4 .data
+# CHECK-NEXT:     400       80        4         {{.*}}{{/|\\}}map-file.s.tmp1.o:(.data.somedata)
+# CHECK-NEXT:     400       80        4                 somedata
+# CHECK-NEXT:     404       79        4 .bss
 # CHECK-NEXT:     404        0        4         {{.*}}{{/|\\}}map-file.s.tmp1.o:(.bss.somezeroes)
 # CHECK-NEXT:     404        0        4                 somezeroes
-# CHECK-NEXT:       -       83       12 CUSTOM(.debug_info)
-# CHECK-NEXT:       -       95       50 CUSTOM(name)
+# CHECK-NEXT:       -       86       12 CUSTOM(.debug_info)
+# CHECK-NEXT:       -       98       50 CUSTOM(name)
 
 # RUN: not wasm-ld %t1.o -o /dev/null -Map=/ 2>&1 \
 # RUN:  | FileCheck -check-prefix=FAIL %s

diff  --git a/lld/test/wasm/multivalue-return-func-types.s b/lld/test/wasm/multivalue-return-func-types.s
index aecfdb483397a..665702f5c5690 100644
--- a/lld/test/wasm/multivalue-return-func-types.s
+++ b/lld/test/wasm/multivalue-return-func-types.s
@@ -9,23 +9,6 @@
 .globl fn_i64_f64_i32_f32
 
 
-_start:
-  .functype _start () -> ()
-  call fn_i32
-  drop
-  call fn_i32_i32
-  drop
-  drop
-  call fn_i32_i64
-  drop
-  drop
-  call fn_i64_f64_i32_f32
-  drop
-  drop
-  drop
-  drop
-  end_function
-
 fn_i32:
   .functype fn_i32 () -> (i32)
   i32.const 1
@@ -51,6 +34,23 @@ fn_i64_f64_i32_f32:
   f32.const 1.0
   end_function
 
+_start:
+  .functype _start () -> ()
+  call fn_i32
+  drop
+  call fn_i32_i32
+  drop
+  drop
+  call fn_i32_i64
+  drop
+  drop
+  call fn_i64_f64_i32_f32
+  drop
+  drop
+  drop
+  drop
+  end_function
+
 
 # CHECK:       - Type:            TYPE
 # CHECK-NEXT:    Signatures:

diff  --git a/lld/test/wasm/mutable-globals.s b/lld/test/wasm/mutable-globals.s
index 9e8911b02bf2e..c9cd3c849e4c8 100644
--- a/lld/test/wasm/mutable-globals.s
+++ b/lld/test/wasm/mutable-globals.s
@@ -2,6 +2,8 @@
 # RUN: not wasm-ld %t.o -o %t.wasm 2>&1 | FileCheck %s
 # RUN: wasm-ld --features=mutable-globals %t.o -o %t.wasm
 
+.globaltype foo, i32
+
 .globl _start
 _start:
   .functype _start () -> ()
@@ -9,7 +11,6 @@ _start:
   global.set foo
   end_function
 
-.globaltype foo, i32
 .import_module foo, env
 .import_name foo, foo
 

diff  --git a/lld/test/wasm/name-section-mangling.s b/lld/test/wasm/name-section-mangling.s
index 8d32bfa8816d8..a24fbc747d76e 100644
--- a/lld/test/wasm/name-section-mangling.s
+++ b/lld/test/wasm/name-section-mangling.s
@@ -11,6 +11,12 @@
 .globl _Z3fooi
 .weak _Z3bari
 
+.functype _Z3bari (i32) -> ()
+
+_Z3fooi:
+  .functype _Z3fooi (i32) -> ()
+  end_function
+
 _start:
   .functype _start () -> ()
   i32.const 1
@@ -19,12 +25,6 @@ _start:
   call _Z3bari
   end_function
 
-_Z3fooi:
-  .functype _Z3fooi (i32) -> ()
-  end_function
-
-.functype _Z3bari (i32) -> ()
-
 # CHECK:        - Type:            EXPORT
 # CHECK-NEXT:     Exports:
 # CHECK-NEXT:       - Name:            memory

diff  --git a/lld/test/wasm/relocatable-comdat.s b/lld/test/wasm/relocatable-comdat.s
index e2b45d46ddcbd..ff3bfcc317503 100644
--- a/lld/test/wasm/relocatable-comdat.s
+++ b/lld/test/wasm/relocatable-comdat.s
@@ -8,7 +8,9 @@
         .type  _start, at function
 _start:
         .functype _start () -> ()
+        i32.const 0
         i32.load foo
+        drop
         end_function
 
 

diff  --git a/lld/test/wasm/relocation-bad-tls.s b/lld/test/wasm/relocation-bad-tls.s
index fad9a264173bf..99197244a6217 100644
--- a/lld/test/wasm/relocation-bad-tls.s
+++ b/lld/test/wasm/relocation-bad-tls.s
@@ -6,6 +6,8 @@ _start:
   .functype _start () -> ()
   i32.const foo at TLSREL
   i32.const bar at TLSREL
+  drop
+  drop
   end_function
 
 .section  .data,"",@

diff  --git a/lld/test/wasm/shared.s b/lld/test/wasm/shared.s
index 4799b2fba5b84..3299d844c2b3e 100644
--- a/lld/test/wasm/shared.s
+++ b/lld/test/wasm/shared.s
@@ -2,6 +2,13 @@
 # RUN: wasm-ld --experimental-pic -shared -o %t.wasm %t.o
 # RUN: obj2yaml %t.wasm | FileCheck %s
 
+.functype func_external () -> ()
+
+# Linker-synthesized globals
+.globaltype __stack_pointer, i32
+.globaltype	__table_base, i32, immutable
+.globaltype	__memory_base, i32, immutable
+
 .section .data.data,"",@
 data:
   .p2align 2
@@ -116,13 +123,6 @@ get_local_func_address:
 .int8 15
 .ascii "mutable-globals"
 
-.functype func_external () -> ()
-
-# Linker-synthesized globals
-.globaltype __stack_pointer, i32
-.globaltype	__table_base, i32, immutable
-.globaltype	__memory_base, i32, immutable
-
 # check for dylink section at start
 
 # CHECK:      Sections:

diff  --git a/lld/test/wasm/shared64.s b/lld/test/wasm/shared64.s
index 0cbe623272c90..14553c349c8a7 100644
--- a/lld/test/wasm/shared64.s
+++ b/lld/test/wasm/shared64.s
@@ -2,6 +2,13 @@
 # RUN: wasm-ld -mwasm64 --experimental-pic -shared -o %t.wasm %t.o
 # RUN: obj2yaml %t.wasm | FileCheck %s
 
+.functype func_external () -> ()
+
+# Linker-synthesized globals
+.globaltype __stack_pointer, i64
+.globaltype	__table_base, i64, immutable
+.globaltype	__memory_base, i64, immutable
+
 .section .data.data,"",@
 data:
   .p2align 2
@@ -29,8 +36,8 @@ data_addr:
 
 .section .data.data_addr_external,"",@
 data_addr_external:
-  .int32 data_external
-  .size data_addr_external, 4
+  .int64 data_external
+  .size data_addr_external, 8
 
 # .. including addends
 
@@ -72,12 +79,12 @@ foo:
   end_function
 
 get_func_address:
-  .functype get_func_address () -> (i32)
+  .functype get_func_address () -> (i64)
   global.get func_external at GOT
   end_function
 
 get_data_address:
-  .functype get_data_address () -> (i32)
+  .functype get_data_address () -> (i64)
   global.get  data_external at GOT
   end_function
 
@@ -116,19 +123,12 @@ get_local_func_address:
 .int8 15
 .ascii "mutable-globals"
 
-.functype func_external () -> ()
-
-# Linker-synthesized globals
-.globaltype __stack_pointer, i64
-.globaltype	__table_base, i64, immutable
-.globaltype	__memory_base, i64, immutable
-
 # check for dylink section at start
 
 # CHECK:      Sections:
 # CHECK-NEXT:   - Type:            CUSTOM
 # CHECK-NEXT:     Name:            dylink
-# CHECK-NEXT:     MemorySize:      24
+# CHECK-NEXT:     MemorySize:      28
 # CHECK-NEXT:     MemoryAlignment: 2
 # CHECK-NEXT:     TableSize:       2
 # CHECK-NEXT:     TableAlignment:  0
@@ -224,7 +224,7 @@ get_local_func_address:
 # CHECK-NEXT:         Body:            10020B
 # CHECK-NEXT:       - Index:           2
 # CHECK-NEXT:         Locals:          []
-# CHECK-NEXT:         Body:            230142047C2305360200230142087C230241016A3602002301420C7C230141006A360200230142107C2306360200230142147C230741046A3602000B
+# CHECK-NEXT:         Body:            230142047C2305360200230142087C230241016A3602002301420C7C230141006A360200230142107C2306370200230142187C230741046A3602000B
 
 # check the data segment initialized with __memory_base global as offset
 
@@ -235,4 +235,4 @@ get_local_func_address:
 # CHECK-NEXT:         Offset:
 # CHECK-NEXT:           Opcode:          GLOBAL_GET
 # CHECK-NEXT:           Index:           1
-# CHECK-NEXT:         Content:         '020000000000000001000000000000000000000000000000'
+# CHECK-NEXT:         Content:         '02000000000000000100000000000000000000000000000000000000'

diff  --git a/lld/test/wasm/signature-mismatch-relocatable.s b/lld/test/wasm/signature-mismatch-relocatable.s
index 7209995e01dc8..f5d99bf8ffef6 100644
--- a/lld/test/wasm/signature-mismatch-relocatable.s
+++ b/lld/test/wasm/signature-mismatch-relocatable.s
@@ -8,6 +8,8 @@
 # function was seen first and the defined function was referenced within the
 # the defining file (see %S/Inputs/sig_mismatch.s).
 
+.functype foo (i32, i64, i32) -> (i32)
+
 .globl _start
 _start:
   .functype _start () -> ()
@@ -15,10 +17,9 @@ _start:
   i64.const 2
   i32.const 3
   call foo
+  drop
   end_function
 
-.functype foo (i32, i64, i32) -> (i32)
-
 #      CHECK:  - Type:            CUSTOM
 # CHECK-NEXT:    Name:            linking
 # CHECK-NEXT:    Version:         2

diff  --git a/lld/test/wasm/undefined-data.s b/lld/test/wasm/undefined-data.s
index 05cb68a84d394..edb8917bc125e 100644
--- a/lld/test/wasm/undefined-data.s
+++ b/lld/test/wasm/undefined-data.s
@@ -6,6 +6,7 @@
 .globl  _start
 _start:
   .functype _start () -> (i32)
+  i32.const 0
   i32.load  data_external
   end_function
 

diff  --git a/lld/test/wasm/undefined-weak-call.s b/lld/test/wasm/undefined-weak-call.s
index 8f50173e9c3ec..7490104afe516 100644
--- a/lld/test/wasm/undefined-weak-call.s
+++ b/lld/test/wasm/undefined-weak-call.s
@@ -7,6 +7,11 @@
 # Check that calling an undefined weak function generates an appropriate stub
 # that will fail at runtime with "unreachable".
 
+.functype weakFunc1 () -> ()
+.functype weakFunc2 () -> ()
+.functype weakFunc3 (i32) -> ()
+.functype weakFunc4 () -> ()
+
 .globl  callWeakFuncs
 
 callWeakFuncs:
@@ -24,10 +29,6 @@ callWeakFuncs:
 .weak weakFunc2
 .weak weakFunc3
 .weak weakFunc4
-.functype weakFunc1 () -> ()
-.functype weakFunc2 () -> ()
-.functype weakFunc3 (i32) -> ()
-.functype weakFunc4 () -> ()
 
 # CHECK-GC: removing unused section {{.*}}:(weakFunc4)
 

diff  --git a/lld/test/wasm/unresolved-symbols.s b/lld/test/wasm/unresolved-symbols.s
index 56abd3c275fc6..81c94a32f3b2c 100644
--- a/lld/test/wasm/unresolved-symbols.s
+++ b/lld/test/wasm/unresolved-symbols.s
@@ -32,7 +32,7 @@
 # IGNORE-NEXT:        Body:            000B
 # IGNORE-NEXT:      - Index:           1
 # IGNORE-NEXT:        Locals:          []
-# IGNORE-NEXT:        Body:            1080808080001082808080001083808080000B
+# IGNORE-NEXT:        Body:            1080808080001082808080001083808080001A1A0B
 # IGNORE-NEXT:      - Index:           2
 # IGNORE-NEXT:        Locals:          []
 # IGNORE-NEXT:        Body:            4180808080000F0B
@@ -75,12 +75,18 @@
 # RUN: wasm-ld -r %t1.o -o %t4.wasm --unresolved-symbols=report-all
 # RUN: llvm-readobj %t4.wasm > /dev/null 2>&1
 
+.functype undef_func () -> ()
+.functype get_data_addr () -> (i32)
+.functype get_func_addr () -> (i32)
+
 .globl _start
 _start:
     .functype _start () -> ()
     call undef_func
     call get_data_addr
     call get_func_addr
+    drop
+    drop
     end_function
 
 .globl get_data_addr
@@ -96,5 +102,3 @@ get_func_addr:
     i32.const undef_func
     return
     end_function
-
-.functype undef_func () -> ()

diff  --git a/lld/test/wasm/weak-and-strong-undef.s b/lld/test/wasm/weak-and-strong-undef.s
index 51e8592e8fda2..d16ccc5cf8f54 100644
--- a/lld/test/wasm/weak-and-strong-undef.s
+++ b/lld/test/wasm/weak-and-strong-undef.s
@@ -9,10 +9,10 @@
 
 # CHECK: undefined symbol: foo
 
+.functype foo () -> ()
+
 _start:
     .globl _start
     .functype _start () -> ()
     call foo
     end_function
-
-.functype foo () -> ()

diff  --git a/lld/test/wasm/weak-symbols.s b/lld/test/wasm/weak-symbols.s
index 705b0b920d42f..165ec174aaa50 100644
--- a/lld/test/wasm/weak-symbols.s
+++ b/lld/test/wasm/weak-symbols.s
@@ -4,6 +4,8 @@
 # RUN: wasm-ld --export-dynamic -o %t.wasm %t.o %t1.o %t2.o
 # RUN: obj2yaml %t.wasm | FileCheck %s
 
+.functype weakFn () -> (i32)
+
 .globl  _start
 _start:
   .functype _start () -> ()
@@ -11,7 +13,6 @@ _start:
   drop
   end_function
 
-.functype weakFn () -> (i32)
 .size weakGlobal, 4
 
 # CHECK:      --- !WASM

diff  --git a/lld/test/wasm/weak-undefined-pic.s b/lld/test/wasm/weak-undefined-pic.s
index b0fb98583a3e8..5937380ee4e96 100644
--- a/lld/test/wasm/weak-undefined-pic.s
+++ b/lld/test/wasm/weak-undefined-pic.s
@@ -12,6 +12,8 @@
 # RUN: wasm-ld --unresolved-symbols=ignore-all %t.o -o %t2.wasm
 # RUN: obj2yaml %t2.wasm | FileCheck %s
 
+.functype foo () -> (i32)
+
 .globl get_foo_addr
 get_foo_addr:
   .functype get_foo_addr () -> (i32)
@@ -20,13 +22,13 @@ get_foo_addr:
 
 .globl _start
 _start:
-  .functype _start () -> ()
+  .functype _start () -> (i32)
   call get_foo_addr
   call foo
+  drop
   end_function
 
 .weak foo
-.functype foo () -> (i32)
 
 # Verify that we do not generate dynamic relocations for the GOT entry.
 

diff  --git a/lld/test/wasm/weak-undefined.s b/lld/test/wasm/weak-undefined.s
index 44b0bc11eb65c..a542cf9af3d9d 100644
--- a/lld/test/wasm/weak-undefined.s
+++ b/lld/test/wasm/weak-undefined.s
@@ -5,6 +5,8 @@
 # Test that undefined weak externals (global_var) and (foo) don't cause
 # link failures and resolve to zero.
 
+.functype foo () -> (i32)
+
 .globl  get_address_of_foo
 get_address_of_foo:
   .functype get_address_of_foo () -> (i32)
@@ -30,7 +32,6 @@ _start:
 
 .weak foo
 .weak global_var
-.functype foo () -> (i32)
 
 
 # CHECK:      --- !WASM

diff  --git a/llvm/include/llvm/CodeGen/MachineModuleInfo.h b/llvm/include/llvm/CodeGen/MachineModuleInfo.h
index 39939f526a6b6..860a86ee991b6 100644
--- a/llvm/include/llvm/CodeGen/MachineModuleInfo.h
+++ b/llvm/include/llvm/CodeGen/MachineModuleInfo.h
@@ -185,7 +185,7 @@ class MachineModuleInfo {
   /// Machine Function map.
   void deleteMachineFunctionFor(Function &F);
 
-  /// Keep track of various per-function pieces of information for backends
+  /// Keep track of various per-module pieces of information for backends
   /// that would like to do so.
   template<typename Ty>
   Ty &getObjFileInfo() {

diff  --git a/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h b/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h
index 746e922396130..58f7163d7b819 100644
--- a/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h
+++ b/llvm/include/llvm/CodeGen/MachineModuleInfoImpls.h
@@ -15,6 +15,7 @@
 #define LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H
 
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringSet.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
 #include <cassert>
 
@@ -101,6 +102,17 @@ class MachineModuleInfoCOFF : public MachineModuleInfoImpl {
   SymbolListTy GetGVStubList() { return getSortedStubs(GVStubs); }
 };
 
+/// MachineModuleInfoWasm - This is a MachineModuleInfoImpl implementation
+/// for Wasm targets.
+class MachineModuleInfoWasm : public MachineModuleInfoImpl {
+  virtual void anchor(); // Out of line virtual method.
+
+public:
+  MachineModuleInfoWasm(const MachineModuleInfo &) {}
+
+  StringSet<> MachineSymbolsUsed;
+};
+
 } // end namespace llvm
 
 #endif // LLVM_CODEGEN_MACHINEMODULEINFOIMPLS_H

diff  --git a/llvm/include/llvm/MC/MCTargetOptions.h b/llvm/include/llvm/MC/MCTargetOptions.h
index d29a74905ebf3..cd97cb0e29925 100644
--- a/llvm/include/llvm/MC/MCTargetOptions.h
+++ b/llvm/include/llvm/MC/MCTargetOptions.h
@@ -45,6 +45,7 @@ class MCTargetOptions {
   bool MCFatalWarnings : 1;
   bool MCNoWarn : 1;
   bool MCNoDeprecatedWarn : 1;
+  bool MCNoTypeCheck : 1;
   bool MCSaveTempLabels : 1;
   bool MCUseDwarfDirectory : 1;
   bool MCIncrementalLinkerCompatible : 1;

diff  --git a/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h b/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
index 6d3c477e4b73a..1894841989166 100644
--- a/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
+++ b/llvm/include/llvm/MC/MCTargetOptionsCommandFlags.h
@@ -40,6 +40,8 @@ bool getNoWarn();
 
 bool getNoDeprecatedWarn();
 
+bool getNoTypeCheck();
+
 std::string getABIName();
 
 /// Create this object with static storage to register mc-related command

diff  --git a/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp b/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp
index 16d24880ebe49..9c3b31935f6d6 100644
--- a/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp
+++ b/llvm/lib/CodeGen/MachineModuleInfoImpls.cpp
@@ -25,6 +25,7 @@ using namespace llvm;
 void MachineModuleInfoMachO::anchor() {}
 void MachineModuleInfoELF::anchor() {}
 void MachineModuleInfoCOFF::anchor() {}
+void MachineModuleInfoWasm::anchor() {}
 
 using PairTy = std::pair<MCSymbol *, MachineModuleInfoImpl::StubValueTy>;
 static int SortSymbolPair(const PairTy *LHS, const PairTy *RHS) {

diff  --git a/llvm/lib/MC/MCTargetOptions.cpp b/llvm/lib/MC/MCTargetOptions.cpp
index d35ef942d2db7..eb57917ee8fd5 100644
--- a/llvm/lib/MC/MCTargetOptions.cpp
+++ b/llvm/lib/MC/MCTargetOptions.cpp
@@ -13,7 +13,8 @@ using namespace llvm;
 
 MCTargetOptions::MCTargetOptions()
     : MCRelaxAll(false), MCNoExecStack(false), MCFatalWarnings(false),
-      MCNoWarn(false), MCNoDeprecatedWarn(false), MCSaveTempLabels(false),
+      MCNoWarn(false), MCNoDeprecatedWarn(false),
+      MCNoTypeCheck(false), MCSaveTempLabels(false),
       MCUseDwarfDirectory(false), MCIncrementalLinkerCompatible(false),
       ShowMCEncoding(false), ShowMCInst(false), AsmVerbose(false),
       PreserveAsmComments(true), Dwarf64(false) {}

diff  --git a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
index 38996f90006e0..762c8d43063c7 100644
--- a/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
+++ b/llvm/lib/MC/MCTargetOptionsCommandFlags.cpp
@@ -43,6 +43,7 @@ MCOPT(bool, ShowMCInst)
 MCOPT(bool, FatalWarnings)
 MCOPT(bool, NoWarn)
 MCOPT(bool, NoDeprecatedWarn)
+MCOPT(bool, NoTypeCheck)
 MCOPT(std::string, ABIName)
 
 llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() {
@@ -90,6 +91,10 @@ llvm::mc::RegisterMCTargetOptionsFlags::RegisterMCTargetOptionsFlags() {
       "no-deprecated-warn", cl::desc("Suppress all deprecated warnings"));
   MCBINDOPT(NoDeprecatedWarn);
 
+  static cl::opt<bool> NoTypeCheck(
+      "no-type-check", cl::desc("Suppress type errors (Wasm)"));
+  MCBINDOPT(NoTypeCheck);
+
   static cl::opt<std::string> ABIName(
       "target-abi", cl::Hidden,
       cl::desc("The name of the ABI to be targeted from the backend."),
@@ -110,5 +115,6 @@ MCTargetOptions llvm::mc::InitMCTargetOptionsFromFlags() {
   Options.MCFatalWarnings = getFatalWarnings();
   Options.MCNoWarn = getNoWarn();
   Options.MCNoDeprecatedWarn = getNoDeprecatedWarn();
+  Options.MCNoTypeCheck = getNoTypeCheck();
   return Options;
 }

diff  --git a/llvm/lib/Target/WebAssembly/AsmParser/CMakeLists.txt b/llvm/lib/Target/WebAssembly/AsmParser/CMakeLists.txt
index d78f1175dfcd6..717c98f15509b 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/CMakeLists.txt
+++ b/llvm/lib/Target/WebAssembly/AsmParser/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_llvm_component_library(LLVMWebAssemblyAsmParser
   WebAssemblyAsmParser.cpp
+  WebAssemblyAsmTypeCheck.cpp
 
   LINK_COMPONENTS
   MC

diff  --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
index 6e9bfccabcf34..c9f04368feec3 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -13,6 +13,7 @@
 ///
 //===----------------------------------------------------------------------===//
 
+#include "AsmParser/WebAssemblyAsmTypeCheck.h"
 #include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
 #include "MCTargetDesc/WebAssemblyTargetStreamer.h"
 #include "TargetInfo/WebAssemblyTargetInfo.h"
@@ -31,6 +32,7 @@
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/MC/MCSymbolWasm.h"
 #include "llvm/Support/Endian.h"
+#include "llvm/Support/SourceMgr.h"
 #include "llvm/Support/TargetRegistry.h"
 
 using namespace llvm;
@@ -225,17 +227,36 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
     Else,
     Undefined,
   };
-  std::vector<NestingType> NestingStack;
+  struct Nested {
+    NestingType NT;
+    wasm::WasmSignature Sig;
+  };
+  std::vector<Nested> NestingStack;
 
   MCSymbolWasm *DefaultFunctionTable = nullptr;
   MCSymbol *LastFunctionLabel = nullptr;
 
+  bool is64;
+
+  WebAssemblyAsmTypeCheck TC;
+  // Don't type check if -no-type-check was set.
+  bool SkipTypeCheck;
+
 public:
   WebAssemblyAsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
                        const MCInstrInfo &MII, const MCTargetOptions &Options)
       : MCTargetAsmParser(Options, STI, MII), Parser(Parser),
-        Lexer(Parser.getLexer()) {
+        Lexer(Parser.getLexer()),
+        is64(STI.getTargetTriple().isArch64Bit()),
+        TC(Parser, MII, is64), SkipTypeCheck(Options.MCNoTypeCheck) {
     setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
+    // Don't type check if this is inline asm, since that is a naked sequence of
+    // instructions without a function/locals decl.
+    auto &SM = Parser.getSourceManager();
+    auto BufferName =
+      SM.getBufferInfo(SM.getMainFileID()).Buffer->getBufferIdentifier();
+    if (BufferName == "<inline asm>")
+      SkipTypeCheck = true;
   }
 
   void Initialize(MCAsmParser &Parser) override {
@@ -300,15 +321,16 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
     }
   }
 
-  void push(NestingType NT) { NestingStack.push_back(NT); }
+  void push(NestingType NT) { NestingStack.push_back({NT}); }
 
   bool pop(StringRef Ins, NestingType NT1, NestingType NT2 = Undefined) {
     if (NestingStack.empty())
       return error(Twine("End of block construct with no start: ") + Ins);
     auto Top = NestingStack.back();
-    if (Top != NT1 && Top != NT2)
+    if (Top.NT != NT1 && Top.NT != NT2)
       return error(Twine("Block construct type mismatch, expected: ") +
-                   nestingString(Top).second + ", instead got: " + Ins);
+                   nestingString(Top.NT).second + ", instead got: " + Ins);
+    TC.setLastSig(Top.Sig);
     NestingStack.pop_back();
     return false;
   }
@@ -317,7 +339,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
     auto Err = !NestingStack.empty();
     while (!NestingStack.empty()) {
       error(Twine("Unmatched block construct(s) at function end: ") +
-            nestingString(NestingStack.back()).first);
+            nestingString(NestingStack.back().NT).first);
       NestingStack.pop_back();
     }
     return Err;
@@ -446,6 +468,11 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
 
   void addBlockTypeOperand(OperandVector &Operands, SMLoc NameLoc,
                            WebAssembly::BlockType BT) {
+    if (BT != WebAssembly::BlockType::Void) {
+      wasm::WasmSignature Sig({static_cast<wasm::ValType>(BT)}, {});
+      TC.setLastSig(Sig);
+      NestingStack.back().Sig = Sig;
+    }
     Operands.push_back(std::make_unique<WebAssemblyOperand>(
         WebAssemblyOperand::Integer, NameLoc, NameLoc,
         WebAssemblyOperand::IntOp{static_cast<int64_t>(BT)}));
@@ -612,6 +639,9 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
         return true;
       // Got signature as block type, don't need more
       ExpectBlockType = false;
+      TC.setLastSig(*Signature.get());
+      if (ExpectBlockType)
+        NestingStack.back().Sig = *Signature.get();
       auto &Ctx = getContext();
       // The "true" here will cause this to be a nameless symbol.
       MCSymbol *Sym = Ctx.createTempSymbol("typeindex", true);
@@ -855,6 +885,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
       auto Signature = std::make_unique<wasm::WasmSignature>();
       if (parseSignature(Signature.get()))
         return true;
+      TC.funcDecl(*Signature);
       WasmSym->setSignature(Signature.get());
       addSignature(std::move(Signature));
       WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
@@ -922,6 +953,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
       SmallVector<wasm::ValType, 4> Locals;
       if (parseRegTypeList(Locals))
         return true;
+      TC.localDecl(Locals);
       TOut.emitLocal(Locals);
       CurrentState = FunctionLocals;
       return expect(AsmToken::EndOfStatement, "EOL");
@@ -986,7 +1018,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
         if (Op0.getImm() == -1)
           Op0.setImm(Align);
       }
-      if (getSTI().getTargetTriple().isArch64Bit()) {
+      if (is64) {
         // Upgrade 32-bit loads/stores to 64-bit. These mostly 
diff er by having
         // an offset64 arg instead of offset32, but to the assembler matcher
         // they're both immediates so don't get selected for.
@@ -996,9 +1028,11 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
           Inst.setOpcode(Opc64);
         }
       }
+      if (!SkipTypeCheck && TC.typeCheck(IDLoc, Inst))
+        return true;
       Out.emitInstruction(Inst, getSTI());
       if (CurrentState == EndFunction) {
-        onEndOfFunction();
+        onEndOfFunction(IDLoc);
       } else {
         CurrentState = Instructions;
       }
@@ -1078,7 +1112,9 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
       getContext().addGenDwarfSection(WS);
   }
 
-  void onEndOfFunction() {
+  void onEndOfFunction(SMLoc ErrorLoc) {
+    TC.endOfFunction(ErrorLoc);
+
     // Automatically output a .size directive, so it becomes optional for the
     // user.
     if (!LastFunctionLabel) return;
@@ -1105,3 +1141,14 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeWebAssemblyAsmParser() {
 #define GET_SUBTARGET_FEATURE_NAME
 #define GET_MATCHER_IMPLEMENTATION
 #include "WebAssemblyGenAsmMatcher.inc"
+
+StringRef GetMnemonic(unsigned Opc) {
+  // FIXME: linear search!
+  for (auto &ME : MatchTable0) {
+    if (ME.Opcode == Opc) {
+      return ME.getMnemonic();
+    }
+  }
+  assert(false && "mnemonic not found");
+  return StringRef();
+}

diff  --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp
new file mode 100644
index 0000000000000..75099bf22c997
--- /dev/null
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.cpp
@@ -0,0 +1,262 @@
+//==- WebAssemblyAsmTypeCheck.cpp - Assembler for WebAssembly -*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file is part of the WebAssembly Assembler.
+///
+/// It contains code to translate a parsed .s file into MCInsts.
+///
+//===----------------------------------------------------------------------===//
+
+#include "AsmParser/WebAssemblyAsmTypeCheck.h"
+#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
+#include "MCTargetDesc/WebAssemblyTargetStreamer.h"
+#include "TargetInfo/WebAssemblyTargetInfo.h"
+#include "Utils/WebAssemblyTypeUtilities.h"
+#include "Utils/WebAssemblyUtilities.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"
+#include "llvm/MC/MCSymbolWasm.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/TargetRegistry.h"
+
+using namespace llvm;
+
+#define DEBUG_TYPE "wasm-asm-parser"
+
+extern StringRef GetMnemonic(unsigned Opc);
+
+namespace llvm {
+
+WebAssemblyAsmTypeCheck::WebAssemblyAsmTypeCheck(MCAsmParser &Parser,
+                                                 const MCInstrInfo &MII, bool is64)
+    : Parser(Parser), MII(MII), is64(is64) {
+}
+
+void WebAssemblyAsmTypeCheck::funcDecl(const wasm::WasmSignature &Sig) {
+  LocalTypes.assign(Sig.Params.begin(), Sig.Params.end());
+  ReturnTypes.assign(Sig.Returns.begin(), Sig.Returns.end());
+}
+
+void WebAssemblyAsmTypeCheck::localDecl(const SmallVector<wasm::ValType, 4> &Locals) {
+  LocalTypes.insert(LocalTypes.end(), Locals.begin(), Locals.end());
+}
+
+void WebAssemblyAsmTypeCheck::dumpTypeStack(Twine Msg) {
+  LLVM_DEBUG({
+    std::string s;
+    for (auto VT : Stack) {
+      s += WebAssembly::typeToString(VT);
+      s += " ";
+    }
+    dbgs() << Msg << s << '\n';
+  });
+}
+
+bool WebAssemblyAsmTypeCheck::typeError(SMLoc ErrorLoc, const Twine &Msg) {
+  // Once you get one type error in a function, it will likely trigger more
+  // which are mostly not helpful.
+  if (TypeErrorThisFunction)
+    return true;
+  TypeErrorThisFunction = true;
+  dumpTypeStack("current stack: ");
+  return Parser.Error(ErrorLoc, Msg);
+}
+
+bool WebAssemblyAsmTypeCheck::popType(SMLoc ErrorLoc,
+                                      Optional<wasm::ValType> EVT) {
+  if (Stack.empty()) {
+    return typeError(ErrorLoc,
+                      EVT.hasValue()
+                          ? StringRef("empty stack while popping ") +
+                                WebAssembly::typeToString(EVT.getValue())
+                          : StringRef(
+                                    "empty stack while popping value"));
+  }
+  auto PVT = Stack.back();
+  Stack.pop_back();
+  if (EVT.hasValue() && EVT.getValue() != PVT) {
+    return typeError(
+        ErrorLoc, StringRef("popped ") + WebAssembly::typeToString(PVT) +
+                                    ", expected " +
+                                    WebAssembly::typeToString(EVT.getValue()));
+  }
+  return false;
+}
+
+bool WebAssemblyAsmTypeCheck::getLocal(SMLoc ErrorLoc, const MCInst &Inst,
+                                       wasm::ValType &Type) {
+  auto Local = Inst.getOperand(0).getImm();
+  if (static_cast<size_t>(Local) > LocalTypes.size())
+    return typeError(ErrorLoc, StringRef("no local type specified for index ") +
+                          std::to_string(Local));
+  Type = LocalTypes[Local];
+  return false;
+}
+
+bool WebAssemblyAsmTypeCheck::checkEnd(SMLoc ErrorLoc) {
+  if (LastSig.Returns.size() > Stack.size())
+    return typeError(ErrorLoc, "end: insufficient values on the type stack");
+  for (size_t i = 0; i < LastSig.Returns.size(); i++) {
+    auto EVT = LastSig.Returns[i];
+    auto PVT = Stack[Stack.size() - LastSig.Returns.size() + i];
+    if (PVT != EVT)
+      return typeError(
+          ErrorLoc, StringRef("end got ") + WebAssembly::typeToString(PVT) +
+                        ", expected " + WebAssembly::typeToString(EVT));
+  }
+  return false;
+}
+
+bool WebAssemblyAsmTypeCheck::checkSig(SMLoc ErrorLoc,
+                                       const wasm::WasmSignature& Sig) {
+  for (auto VT : llvm::reverse(Sig.Params))
+    if (popType(ErrorLoc, VT)) return true;
+  Stack.insert(Stack.end(), Sig.Returns.begin(), Sig.Returns.end());
+  return false;
+}
+
+bool WebAssemblyAsmTypeCheck::getSymRef(SMLoc ErrorLoc, const MCInst &Inst,
+                                        const MCSymbolRefExpr *&SymRef) {
+  auto Op = Inst.getOperand(0);
+  if (!Op.isExpr())
+    return typeError(ErrorLoc, StringRef("expected expression operand"));
+  SymRef = dyn_cast<MCSymbolRefExpr>(Op.getExpr());
+  if (!SymRef)
+    return typeError(ErrorLoc, StringRef("expected symbol operand"));
+  return false;
+}
+
+bool WebAssemblyAsmTypeCheck::getGlobal(SMLoc ErrorLoc, const MCInst &Inst,
+                                        wasm::ValType &Type) {
+  const MCSymbolRefExpr *SymRef;
+  if (getSymRef(ErrorLoc, Inst, SymRef))
+    return true;
+  auto WasmSym = cast<MCSymbolWasm>(&SymRef->getSymbol());
+  switch (WasmSym->getType().getValueOr(wasm::WASM_SYMBOL_TYPE_DATA)) {
+  case wasm::WASM_SYMBOL_TYPE_GLOBAL:
+    Type = static_cast<wasm::ValType>(WasmSym->getGlobalType().Type);
+    break;
+  case wasm::WASM_SYMBOL_TYPE_FUNCTION:
+  case wasm::WASM_SYMBOL_TYPE_DATA:
+    if (SymRef->getKind() == MCSymbolRefExpr::VK_GOT) {
+      Type = is64 ? wasm::ValType::I64 : wasm::ValType::I32;
+      break;
+    }
+    // FALL-THROUGH:
+  default:
+    return typeError(ErrorLoc, StringRef("symbol ") + WasmSym->getName() +
+                                    " missing .globaltype");
+  }
+  return false;
+}
+
+void WebAssemblyAsmTypeCheck::endOfFunction(SMLoc ErrorLoc) {
+  // Check the return types.
+  for (auto RVT : llvm::reverse(ReturnTypes)) {
+    popType(ErrorLoc, RVT);
+  }
+  if (!Stack.empty()) {
+    typeError(ErrorLoc,
+              std::to_string(Stack.size()) + " superfluous return values");
+  }
+  // Reset the type checker state.
+  Clear();
+}
+
+bool WebAssemblyAsmTypeCheck::typeCheck(SMLoc ErrorLoc, const MCInst &Inst) {
+  auto Opc = Inst.getOpcode();
+  auto Name = GetMnemonic(Opc);
+  dumpTypeStack("typechecking " + Name + ": ");
+  wasm::ValType Type;
+  if (Name == "local.get") {
+    if (getLocal(ErrorLoc, Inst, Type))
+      return true;
+    Stack.push_back(Type);
+  } else if (Name == "local.set") {
+    if (getLocal(ErrorLoc, Inst, Type))
+      return true;
+    if (popType(ErrorLoc, Type))
+      return true;
+  } else if (Name == "local.tee") {
+    if (getLocal(ErrorLoc, Inst, Type))
+      return true;
+    if (popType(ErrorLoc, Type))
+      return true;
+    Stack.push_back(Type);
+  } else if (Name == "global.get") {
+    if (getGlobal(ErrorLoc, Inst, Type))
+      return true;
+    Stack.push_back(Type);
+  } else if (Name == "global.set") {
+    if (getGlobal(ErrorLoc, Inst, Type))
+      return true;
+    if (popType(ErrorLoc, Type))
+      return true;
+  } else if (Name == "drop") {
+    if (popType(ErrorLoc, {}))
+      return true;
+  } else if (Name == "end_block" || Name == "end_loop" || Name == "end_if" ||
+              Name == "else") {
+    if (checkEnd(ErrorLoc))
+      return true;
+  } else if (Name == "call_indirect" || Name == "return_call_indirect") {
+    // Function value.
+    if (popType(ErrorLoc, wasm::ValType::I32)) return true;
+    if (checkSig(ErrorLoc, LastSig)) return true;
+  } else if (Name == "call" || Name == "return_call") {
+    const MCSymbolRefExpr *SymRef;
+    if (getSymRef(ErrorLoc, Inst, SymRef))
+      return true;
+    auto WasmSym = cast<MCSymbolWasm>(&SymRef->getSymbol());
+    auto Sig = WasmSym->getSignature();
+    if (!Sig || WasmSym->getType() != wasm::WASM_SYMBOL_TYPE_FUNCTION)
+      return typeError(ErrorLoc, StringRef("symbol ") + WasmSym->getName() +
+                                      " missing .functype");
+    if (checkSig(ErrorLoc, *Sig)) return true;
+  } else if (Name == "ref.null") {
+    auto VT = static_cast<wasm::ValType>(Inst.getOperand(0).getImm());
+    Stack.push_back(VT);
+  } else {
+    // The current instruction is a stack instruction which doesn't have
+    // explicit operands that indicate push/pop types, so we get those from
+    // the register version of the same instruction.
+    auto RegOpc = WebAssembly::getRegisterOpcode(Opc);
+    assert(RegOpc != -1 && "Failed to get register version of MC instruction");
+    const auto &II = MII.get(RegOpc);
+    // First pop all the uses off the stack and check them.
+    for (unsigned I = II.getNumOperands(); I > II.getNumDefs(); I--) {
+      const auto &Op = II.OpInfo[I - 1];
+      if (Op.OperandType == MCOI::OPERAND_REGISTER) {
+        auto VT = WebAssembly::regClassToValType(Op.RegClass);
+        if (popType(ErrorLoc, VT))
+          return true;
+      }
+    }
+    // Now push all the defs onto the stack.
+    for (unsigned I = 0; I < II.getNumDefs(); I++) {
+      const auto &Op = II.OpInfo[I];
+      assert(Op.OperandType == MCOI::OPERAND_REGISTER && "Register expected");
+      auto VT = WebAssembly::regClassToValType(Op.RegClass);
+      Stack.push_back(VT);
+    }
+  }
+  return false;
+}
+
+} // end namespace llvm

diff  --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h
new file mode 100644
index 0000000000000..a5c14e19ae1cd
--- /dev/null
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmTypeCheck.h
@@ -0,0 +1,66 @@
+//==- WebAssemblyAsmTypeCheck.h - Assembler for WebAssembly -*- C++ -*-==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file is part of the WebAssembly Assembler.
+///
+/// It contains code to translate a parsed .s file into MCInsts.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_LIB_TARGET_WEBASSEMBLY_ASMPARSER_TYPECHECK_H
+#define LLVM_LIB_TARGET_WEBASSEMBLY_ASMPARSER_TYPECHECK_H
+
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCInstrInfo.h"
+#include "llvm/BinaryFormat/Wasm.h"
+#include "llvm/MC/MCSymbol.h"
+
+namespace llvm {
+
+class WebAssemblyAsmTypeCheck final {
+  MCAsmParser &Parser;
+  const MCInstrInfo &MII;
+
+  SmallVector<wasm::ValType, 8> Stack;
+  SmallVector<wasm::ValType, 16> LocalTypes;
+  SmallVector<wasm::ValType, 4> ReturnTypes;
+  wasm::WasmSignature LastSig;
+  bool TypeErrorThisFunction = false;
+  bool is64;
+
+  void Clear() {
+    Stack.clear();
+    LocalTypes.clear();
+    ReturnTypes.clear();
+    TypeErrorThisFunction = false;
+  }
+
+  void dumpTypeStack(Twine Msg);
+  bool typeError(SMLoc ErrorLoc, const Twine &Msg);
+  bool popType(SMLoc ErrorLoc, Optional<wasm::ValType> EVT);
+  bool getLocal(SMLoc ErrorLoc, const MCInst &Inst, wasm::ValType &Type);
+  bool checkEnd(SMLoc ErrorLoc);
+  bool checkSig(SMLoc ErrorLoc, const wasm::WasmSignature &Sig);
+  bool getSymRef(SMLoc ErrorLoc, const MCInst &Inst,
+                 const MCSymbolRefExpr *&SymRef);
+  bool getGlobal(SMLoc ErrorLoc, const MCInst &Inst, wasm::ValType &Type);
+
+public:
+  WebAssemblyAsmTypeCheck(MCAsmParser &Parser, const MCInstrInfo &MII, bool is64);
+
+  void funcDecl(const wasm::WasmSignature &Sig);
+  void localDecl(const SmallVector<wasm::ValType, 4> &Locals);
+  void setLastSig(const wasm::WasmSignature &Sig) { LastSig = Sig; }
+  void endOfFunction(SMLoc ErrorLoc);
+  bool typeCheck(SMLoc ErrorLoc, const MCInst &Inst);
+};
+
+} // end namespace llvm
+
+#endif LLVM_LIB_TARGET_WEBASSEMBLY_ASMPARSER_TYPECHECK_H

diff  --git a/llvm/lib/Target/WebAssembly/CMakeLists.txt b/llvm/lib/Target/WebAssembly/CMakeLists.txt
index 9704776acd33d..5ce8df82c8445 100644
--- a/llvm/lib/Target/WebAssembly/CMakeLists.txt
+++ b/llvm/lib/Target/WebAssembly/CMakeLists.txt
@@ -38,6 +38,7 @@ add_llvm_target(WebAssemblyCodeGen
   WebAssemblyLowerGlobalDtors.cpp
   WebAssemblyMachineFunctionInfo.cpp
   WebAssemblyMCInstLower.cpp
+  WebAssemblyMCLowerPrePass.cpp
   WebAssemblyNullifyDebugValueLists.cpp
   WebAssemblyOptimizeLiveIntervals.cpp
   WebAssemblyOptimizeReturned.cpp

diff  --git a/llvm/lib/Target/WebAssembly/TargetInfo/WebAssemblyTargetInfo.h b/llvm/lib/Target/WebAssembly/TargetInfo/WebAssemblyTargetInfo.h
index be7a632331c8e..741cc002f9e25 100644
--- a/llvm/lib/Target/WebAssembly/TargetInfo/WebAssemblyTargetInfo.h
+++ b/llvm/lib/Target/WebAssembly/TargetInfo/WebAssemblyTargetInfo.h
@@ -24,6 +24,7 @@ Target &getTheWebAssemblyTarget64();
 namespace WebAssembly {
 
 int getStackOpcode(unsigned short Opcode);
+int getRegisterOpcode(unsigned short Opcode);
 int getWasm64Opcode(unsigned short Opcode);
 
 } // namespace WebAssembly

diff  --git a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp
index 8923e86f69b0d..6f81431bba2d5 100644
--- a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp
+++ b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.cpp
@@ -14,6 +14,10 @@
 #include "WebAssemblyTypeUtilities.h"
 #include "llvm/ADT/StringSwitch.h"
 
+// Get register classes enum.
+#define GET_REGINFO_ENUM
+#include "WebAssemblyGenRegisterInfo.inc"
+
 using namespace llvm;
 
 Optional<wasm::ValType> WebAssembly::parseType(StringRef Type) {
@@ -149,3 +153,24 @@ wasm::ValType WebAssembly::toValType(MVT Type) {
     llvm_unreachable("unexpected type");
   }
 }
+
+wasm::ValType WebAssembly::regClassToValType(unsigned RC) {
+  switch (RC) {
+  case WebAssembly::I32RegClassID:
+    return wasm::ValType::I32;
+  case WebAssembly::I64RegClassID:
+    return wasm::ValType::I64;
+  case WebAssembly::F32RegClassID:
+    return wasm::ValType::F32;
+  case WebAssembly::F64RegClassID:
+    return wasm::ValType::F64;
+  case WebAssembly::V128RegClassID:
+    return wasm::ValType::V128;
+  case WebAssembly::FUNCREFRegClassID:
+    return wasm::ValType::FUNCREF;
+  case WebAssembly::EXTERNREFRegClassID:
+    return wasm::ValType::EXTERNREF;
+  default:
+    llvm_unreachable("unexpected type");
+  }
+}

diff  --git a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h
index 623ee5d2c0712..8d757df27b34f 100644
--- a/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h
+++ b/llvm/lib/Target/WebAssembly/Utils/WebAssemblyTypeUtilities.h
@@ -73,6 +73,9 @@ std::string signatureToString(const wasm::WasmSignature *Sig);
 // Convert a MVT into its corresponding wasm ValType.
 wasm::ValType toValType(MVT Type);
 
+// Convert a register class to a wasm ValType.
+wasm::ValType regClassToValType(unsigned RC);
+
 } // end namespace WebAssembly
 } // end namespace llvm
 

diff  --git a/llvm/lib/Target/WebAssembly/WebAssembly.h b/llvm/lib/Target/WebAssembly/WebAssembly.h
index bb928457c859e..3e9619fba3a3d 100644
--- a/llvm/lib/Target/WebAssembly/WebAssembly.h
+++ b/llvm/lib/Target/WebAssembly/WebAssembly.h
@@ -55,6 +55,7 @@ FunctionPass *createWebAssemblyLowerBrUnless();
 FunctionPass *createWebAssemblyRegNumbering();
 FunctionPass *createWebAssemblyDebugFixup();
 FunctionPass *createWebAssemblyPeephole();
+FunctionPass *createWebAssemblyMCLowerPrePass();
 
 // PassRegistry initialization declarations.
 void initializeWebAssemblyAddMissingPrototypesPass(PassRegistry &);
@@ -82,6 +83,7 @@ void initializeWebAssemblyLowerBrUnlessPass(PassRegistry &);
 void initializeWebAssemblyRegNumberingPass(PassRegistry &);
 void initializeWebAssemblyDebugFixupPass(PassRegistry &);
 void initializeWebAssemblyPeepholePass(PassRegistry &);
+void initializeWebAssemblyMCLowerPrePassPass(PassRegistry &);
 
 namespace WebAssembly {
 enum TargetIndex {

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index d70c383b5743f..56829eb45e21a 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -23,6 +23,7 @@
 #include "WebAssemblyMCInstLower.h"
 #include "WebAssemblyMachineFunctionInfo.h"
 #include "WebAssemblyRegisterInfo.h"
+#include "WebAssemblyRuntimeLibcallSignatures.h"
 #include "WebAssemblyTargetMachine.h"
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/StringExtras.h"
@@ -207,7 +208,76 @@ void WebAssemblyAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {
   }
 }
 
-void WebAssemblyAsmPrinter::emitEndOfAsmFile(Module &M) {
+MCSymbol *WebAssemblyAsmPrinter::getOrCreateWasmSymbol(StringRef Name) {
+  auto *WasmSym = cast<MCSymbolWasm>(GetExternalSymbolSymbol(Name));
+
+  // May be called multiple times, so early out.
+  if (WasmSym->getType().hasValue())
+    return WasmSym;
+
+  const WebAssemblySubtarget &Subtarget = getSubtarget();
+
+  // Except for certain known symbols, all symbols used by CodeGen are
+  // functions. It's OK to hardcode knowledge of specific symbols here; this
+  // method is precisely there for fetching the signatures of known
+  // Clang-provided symbols.
+  if (Name == "__stack_pointer" || Name == "__tls_base" ||
+      Name == "__memory_base" || Name == "__table_base" ||
+      Name == "__tls_size" || Name == "__tls_align") {
+    bool Mutable =
+        Name == "__stack_pointer" || Name == "__tls_base";
+    WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
+    WasmSym->setGlobalType(wasm::WasmGlobalType{
+        uint8_t(Subtarget.hasAddr64() ? wasm::WASM_TYPE_I64
+                                      : wasm::WASM_TYPE_I32),
+        Mutable});
+    return WasmSym;
+  }
+
+  SmallVector<wasm::ValType, 4> Returns;
+  SmallVector<wasm::ValType, 4> Params;
+  if (Name == "__cpp_exception") {
+    WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TAG);
+    // We can't confirm its signature index for now because there can be
+    // imported exceptions. Set it to be 0 for now.
+    WasmSym->setTagType(
+        {wasm::WASM_TAG_ATTRIBUTE_EXCEPTION, /* SigIndex */ 0});
+    // We may have multiple C++ compilation units to be linked together, each of
+    // which defines the exception symbol. To resolve them, we declare them as
+    // weak.
+    WasmSym->setWeak(true);
+    WasmSym->setExternal(true);
+
+    // All C++ exceptions are assumed to have a single i32 (for wasm32) or i64
+    // (for wasm64) param type and void return type. The reaon is, all C++
+    // exception values are pointers, and to share the type section with
+    // functions, exceptions are assumed to have void return type.
+    Params.push_back(Subtarget.hasAddr64() ? wasm::ValType::I64
+                                           : wasm::ValType::I32);
+  } else { // Function symbols
+    WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
+    getLibcallSignature(Subtarget, Name, Returns, Params);
+  }
+  auto Signature = std::make_unique<wasm::WasmSignature>(std::move(Returns),
+                                                         std::move(Params));
+  WasmSym->setSignature(Signature.get());
+  addSignature(std::move(Signature));
+
+  return WasmSym;
+}
+
+void WebAssemblyAsmPrinter::emitExternalDecls(const Module &M) {
+  if (signaturesEmitted)
+    return;
+  signaturesEmitted = true;
+
+  // Normally symbols for globals get discovered as the MI gets lowered,
+  // but we need to know about them ahead of time.
+  MachineModuleInfoWasm &MMIW = MMI->getObjFileInfo<MachineModuleInfoWasm>();
+  for (const auto &Name : MMIW.MachineSymbolsUsed) {
+    getOrCreateWasmSymbol(Name.getKey());
+  }
+
   for (auto &It : OutContext.getSymbols()) {
     // Emit .globaltype, .tagtype, or .tabletype declarations.
     auto Sym = cast<MCSymbolWasm>(It.getValue());
@@ -224,14 +294,10 @@ void WebAssemblyAsmPrinter::emitEndOfAsmFile(Module &M) {
   }
 
   DenseSet<MCSymbol *> InvokeSymbols;
-  bool HasAddressTakenFunction = false;
   for (const auto &F : M) {
     if (F.isIntrinsic())
       continue;
 
-    if (F.hasAddressTaken())
-      HasAddressTakenFunction = true;
-
     // Emit function type info for all undefined functions
     if (F.isDeclarationForLinker()) {
       SmallVector<MVT, 4> Results;
@@ -289,6 +355,10 @@ void WebAssemblyAsmPrinter::emitEndOfAsmFile(Module &M) {
       getTargetStreamer()->emitExportName(Sym, Name);
     }
   }
+}
+  
+void WebAssemblyAsmPrinter::emitEndOfAsmFile(Module &M) {
+  emitExternalDecls(M);
 
   // When a function's address is taken, a TABLE_INDEX relocation is emitted
   // against the function symbol at the use site.  However the relocation
@@ -296,10 +366,13 @@ void WebAssemblyAsmPrinter::emitEndOfAsmFile(Module &M) {
   // define a new kind of reloc against both the function and the table, so
   // that the linker can see that the function symbol keeps the table alive,
   // but for now manually mark the table as live.
-  if (HasAddressTakenFunction) {
-    MCSymbolWasm *FunctionTable =
-        WebAssembly::getOrCreateFunctionTableSymbol(OutContext, Subtarget);
-    OutStreamer->emitSymbolAttribute(FunctionTable, MCSA_NoDeadStrip);
+  for (const auto &F : M) {
+    if (!F.isIntrinsic() && F.hasAddressTaken()) {
+      MCSymbolWasm *FunctionTable =
+          WebAssembly::getOrCreateFunctionTableSymbol(OutContext, Subtarget);
+      OutStreamer->emitSymbolAttribute(FunctionTable, MCSA_NoDeadStrip);    
+      break;
+    }
   }
 
   for (const auto &G : M.globals()) {
@@ -452,6 +525,17 @@ void WebAssemblyAsmPrinter::emitJumpTableInfo() {
   // Nothing to do; jump tables are incorporated into the instruction stream.
 }
 
+void WebAssemblyAsmPrinter::emitLinkage(const GlobalValue *GV, MCSymbol *Sym)
+  const {
+  AsmPrinter::emitLinkage(GV, Sym);
+  // This gets called before the function label and type are emitted.
+  // We use it to emit signatures of external functions.
+  // FIXME casts!
+  const_cast<WebAssemblyAsmPrinter *>(this)
+    ->emitExternalDecls(*MMI->getModule());
+}
+
+
 void WebAssemblyAsmPrinter::emitFunctionBodyStart() {
   const Function &F = MF->getFunction();
   SmallVector<MVT, 1> ResultVTs;

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
index 99b6e1077f1d5..6b2f2000a0bd9 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.h
@@ -25,6 +25,7 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyAsmPrinter final : public AsmPrinter {
   // TODO: Do the uniquing of Signatures here instead of ObjectFileWriter?
   std::vector<std::unique_ptr<wasm::WasmSignature>> Signatures;
   std::vector<std::unique_ptr<std::string>> Names;
+  bool signaturesEmitted = false;
 
   StringRef storeName(StringRef Name) {
     std::unique_ptr<std::string> N = std::make_unique<std::string>(Name);
@@ -68,6 +69,7 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyAsmPrinter final : public AsmPrinter {
   void emitGlobalVariable(const GlobalVariable *GV) override;
   void emitJumpTableInfo() override;
   void emitConstantPool() override;
+  void emitLinkage(const GlobalValue *, MCSymbol *) const override;
   void emitFunctionBodyStart() override;
   void emitInstruction(const MachineInstr *MI) override;
   bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo,
@@ -81,6 +83,8 @@ class LLVM_LIBRARY_VISIBILITY WebAssemblyAsmPrinter final : public AsmPrinter {
   MCSymbolWasm *getMCSymbolForFunction(const Function *F, bool EnableEmEH,
                                        wasm::WasmSignature *Sig,
                                        bool &InvokeDetected);
+  MCSymbol *getOrCreateWasmSymbol(StringRef Name);
+  void emitExternalDecls(const Module &M);
 };
 
 } // end namespace llvm

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td
index 0a4289c4959ba..4dc0c9a46c387 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrFormats.td
@@ -15,7 +15,7 @@
 // We instantiate 2 of these for every actual instruction (register based
 // and stack based), see below.
 class WebAssemblyInst<bits<32> inst, string asmstr, string stack, string is64>
-  : StackRel, Wasm64Rel, Instruction {
+  : StackRel, RegisterRel, Wasm64Rel, Instruction {
   bits<32> Inst = inst; // Instruction encoding.
   string StackBased = stack;
   string BaseName = NAME;

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
index 62b34ee9da427..15748067f1235 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrInfo.td
@@ -234,6 +234,19 @@ def getStackOpcode : InstrMapping {
   let ValueCols = [["true"]];
 }
 
+//===----------------------------------------------------------------------===//
+// WebAssembly Stack to Register instruction mapping
+//===----------------------------------------------------------------------===//
+
+class RegisterRel;
+def getRegisterOpcode : InstrMapping {
+  let FilterClass = "RegisterRel";
+  let RowFields = ["BaseName"];
+  let ColFields = ["StackBased"];
+  let KeyCol = ["true"];
+  let ValueCols = [["false"]];
+}
+
 //===----------------------------------------------------------------------===//
 // WebAssembly 32 to 64-bit instruction mapping
 //===----------------------------------------------------------------------===//

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td b/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td
index 8fa80ad40995f..8d5f80be5543a 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyInstrTable.td
@@ -13,10 +13,10 @@
 
 
 multiclass TABLE<WebAssemblyRegClass rt> {
-  defm TABLE_GET_#rt : I<(outs rt:$res), (ins table32_op:$table),
+  defm TABLE_GET_#rt : I<(outs rt:$res), (ins table32_op:$table, I32:$i),
                          (outs), (ins table32_op:$table),
                          [],
-                         "table.get\t$res, $table",
+                         "table.get\t$res, $table, $i",
                          "table.get\t$table",
                          0x25>;
 

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
index 93e5f2300386e..b412a8f5fd03b 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyMCInstLower.cpp
@@ -18,7 +18,6 @@
 #include "Utils/WebAssemblyUtilities.h"
 #include "WebAssemblyAsmPrinter.h"
 #include "WebAssemblyMachineFunctionInfo.h"
-#include "WebAssemblyRuntimeLibcallSignatures.h"
 #include "llvm/CodeGen/AsmPrinter.h"
 #include "llvm/CodeGen/MachineFunction.h"
 #include "llvm/IR/Constants.h"
@@ -92,56 +91,7 @@ WebAssemblyMCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const {
 
 MCSymbol *WebAssemblyMCInstLower::GetExternalSymbolSymbol(
     const MachineOperand &MO) const {
-  const char *Name = MO.getSymbolName();
-  auto *WasmSym = cast<MCSymbolWasm>(Printer.GetExternalSymbolSymbol(Name));
-  const WebAssemblySubtarget &Subtarget = Printer.getSubtarget();
-
-  // Except for certain known symbols, all symbols used by CodeGen are
-  // functions. It's OK to hardcode knowledge of specific symbols here; this
-  // method is precisely there for fetching the signatures of known
-  // Clang-provided symbols.
-  if (strcmp(Name, "__stack_pointer") == 0 || strcmp(Name, "__tls_base") == 0 ||
-      strcmp(Name, "__memory_base") == 0 || strcmp(Name, "__table_base") == 0 ||
-      strcmp(Name, "__tls_size") == 0 || strcmp(Name, "__tls_align") == 0) {
-    bool Mutable =
-        strcmp(Name, "__stack_pointer") == 0 || strcmp(Name, "__tls_base") == 0;
-    WasmSym->setType(wasm::WASM_SYMBOL_TYPE_GLOBAL);
-    WasmSym->setGlobalType(wasm::WasmGlobalType{
-        uint8_t(Subtarget.hasAddr64() ? wasm::WASM_TYPE_I64
-                                      : wasm::WASM_TYPE_I32),
-        Mutable});
-    return WasmSym;
-  }
-
-  SmallVector<wasm::ValType, 4> Returns;
-  SmallVector<wasm::ValType, 4> Params;
-  if (strcmp(Name, "__cpp_exception") == 0) {
-    WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TAG);
-    // We can't confirm its signature index for now because there can be
-    // imported exceptions. Set it to be 0 for now.
-    WasmSym->setTagType({wasm::WASM_TAG_ATTRIBUTE_EXCEPTION, /* SigIndex */ 0});
-    // We may have multiple C++ compilation units to be linked together, each of
-    // which defines the exception symbol. To resolve them, we declare them as
-    // weak.
-    WasmSym->setWeak(true);
-    WasmSym->setExternal(true);
-
-    // All C++ exceptions are assumed to have a single i32 (for wasm32) or i64
-    // (for wasm64) param type and void return type. The reaon is, all C++
-    // exception values are pointers, and to share the type section with
-    // functions, exceptions are assumed to have void return type.
-    Params.push_back(Subtarget.hasAddr64() ? wasm::ValType::I64
-                                           : wasm::ValType::I32);
-  } else { // Function symbols
-    WasmSym->setType(wasm::WASM_SYMBOL_TYPE_FUNCTION);
-    getLibcallSignature(Subtarget, Name, Returns, Params);
-  }
-  auto Signature =
-      std::make_unique<wasm::WasmSignature>(std::move(Returns), std::move(Params));
-  WasmSym->setSignature(Signature.get());
-  Printer.addSignature(std::move(Signature));
-
-  return WasmSym;
+  return Printer.getOrCreateWasmSymbol(MO.getSymbolName());
 }
 
 MCOperand WebAssemblyMCInstLower::lowerSymbolOperand(const MachineOperand &MO,

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyMCLowerPrePass.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyMCLowerPrePass.cpp
new file mode 100644
index 0000000000000..3daffd1c23a22
--- /dev/null
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyMCLowerPrePass.cpp
@@ -0,0 +1,86 @@
+//===-- WebAssemblyMCLowerPrePass.cpp - Prepare for MC lower --------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// Some information in MC lowering / asm printing gets generated as
+/// instructions get emitted, but may be necessary at the start, such as for
+/// .globaltype declarations. This pass collects this information.
+///
+//===----------------------------------------------------------------------===//
+
+#include "MCTargetDesc/WebAssemblyMCTargetDesc.h"
+#include "Utils/WebAssemblyUtilities.h"
+#include "WebAssembly.h"
+#include "WebAssemblyMachineFunctionInfo.h"
+#include "WebAssemblySubtarget.h"
+#include "llvm/ADT/SCCIterator.h"
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineInstrBuilder.h"
+#include "llvm/CodeGen/MachineLoopInfo.h"
+#include "llvm/CodeGen/MachineModuleInfoImpls.h"
+#include "llvm/CodeGen/MachineRegisterInfo.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
+#define DEBUG_TYPE "wasm-mclower-prepass"
+
+namespace {
+class WebAssemblyMCLowerPrePass final : public MachineFunctionPass {
+  StringRef getPassName() const override {
+    return "WebAssembly MC Lower Pre Pass";
+  }
+
+  void getAnalysisUsage(AnalysisUsage &AU) const override {
+    AU.setPreservesCFG();
+    MachineFunctionPass::getAnalysisUsage(AU);
+  }
+
+  bool runOnMachineFunction(MachineFunction &MF) override;
+
+public:
+  static char ID; // Pass identification, replacement for typeid
+  WebAssemblyMCLowerPrePass() : MachineFunctionPass(ID) {}
+};
+} // end anonymous namespace
+
+char WebAssemblyMCLowerPrePass::ID = 0;
+INITIALIZE_PASS(
+    WebAssemblyMCLowerPrePass, DEBUG_TYPE,
+    "Collects information ahead of time for MC lowering",
+    false, false)
+
+FunctionPass *llvm::createWebAssemblyMCLowerPrePass() {
+  return new WebAssemblyMCLowerPrePass();
+}
+
+bool WebAssemblyMCLowerPrePass::runOnMachineFunction(MachineFunction &MF) {
+  LLVM_DEBUG(dbgs() << "********** MC Lower Pre Pass **********\n"
+                       "********** Function: "
+                    << MF.getName() << '\n');
+
+  MachineModuleInfo &MMI = MF.getMMI();
+  MachineModuleInfoWasm &MMIW = MMI.getObjFileInfo<MachineModuleInfoWasm>();
+
+  for (MachineBasicBlock &MBB : MF) {
+    for (auto &MI : MBB) {
+      // FIXME: what should all be filtered out beyond these?
+      if (MI.isDebugInstr() || MI.isInlineAsm())
+        continue;
+      for (MachineOperand &MO : MI.uses()) {
+        if (MO.isSymbol()) {
+          MMIW.MachineSymbolsUsed.insert(MO.getSymbolName());
+        }
+      }
+    }
+  }
+
+  return true;
+}

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp
index 6456026f4ba74..388c0f9110b76 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.cpp
@@ -889,14 +889,15 @@ static ManagedStatic<StaticLibcallNameMap> LibcallNameMap;
 // TODO: If the RTLIB::Libcall-taking flavor of GetSignature remains unsed
 // other than here, just roll its logic into this version.
 void llvm::getLibcallSignature(const WebAssemblySubtarget &Subtarget,
-                               const char *Name,
+                               StringRef Name,
                                SmallVectorImpl<wasm::ValType> &Rets,
                                SmallVectorImpl<wasm::ValType> &Params) {
   auto &Map = LibcallNameMap->Map;
   auto Val = Map.find(Name);
 #ifndef NDEBUG
   if (Val == Map.end()) {
-    auto message = std::string("unexpected runtime library name: ") + Name;
+    auto message = std::string("unexpected runtime library name: ") +
+                   std::string(Name);
     llvm_unreachable(message.c_str());
   }
 #endif

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.h b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.h
index 6ae8aaaba59cd..f7a94aa20bd46 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyRuntimeLibcallSignatures.h
@@ -28,7 +28,7 @@ extern void getLibcallSignature(const WebAssemblySubtarget &Subtarget,
                                 SmallVectorImpl<wasm::ValType> &Params);
 
 extern void getLibcallSignature(const WebAssemblySubtarget &Subtarget,
-                                const char *Name,
+                                StringRef Name,
                                 SmallVectorImpl<wasm::ValType> &Rets,
                                 SmallVectorImpl<wasm::ValType> &Params);
 

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
index c305da514ef39..a0c7c778767c7 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -88,6 +88,7 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeWebAssemblyTarget() {
   initializeWebAssemblyRegNumberingPass(PR);
   initializeWebAssemblyDebugFixupPass(PR);
   initializeWebAssemblyPeepholePass(PR);
+  initializeWebAssemblyMCLowerPrePassPass(PR);
 }
 
 //===----------------------------------------------------------------------===//
@@ -507,6 +508,9 @@ void WebAssemblyPassConfig::addPreEmitPass() {
   // Fix debug_values whose defs have been stackified.
   if (!WasmDisableExplicitLocals)
     addPass(createWebAssemblyDebugFixup());
+
+  // Collect information to prepare for MC lowering / asm printing.
+  addPass(createWebAssemblyMCLowerPrePass());
 }
 
 yaml::MachineFunctionInfo *

diff  --git a/llvm/test/CodeGen/WebAssembly/exception.ll b/llvm/test/CodeGen/WebAssembly/exception.ll
index 7cd5225bf5691..4fab09af195f5 100644
--- a/llvm/test/CodeGen/WebAssembly/exception.ll
+++ b/llvm/test/CodeGen/WebAssembly/exception.ll
@@ -9,6 +9,8 @@ target triple = "wasm32-unknown-unknown"
 
 @_ZTIi = external dso_local constant i8*
 
+; CHECK: .tagtype  __cpp_exception i32
+
 ; CHECK-LABEL: test_throw:
 ; CHECK:     throw __cpp_exception, $0
 ; CHECK-NOT: unreachable
@@ -372,4 +374,3 @@ attributes #0 = { nounwind }
 attributes #1 = { noreturn }
 
 ; CHECK: __cpp_exception:
-; CHECK: .tagtype  __cpp_exception i32

diff  --git a/llvm/test/CodeGen/WebAssembly/global-get.ll b/llvm/test/CodeGen/WebAssembly/global-get.ll
index a9b07657fbf57..a31b1f1c30ebd 100644
--- a/llvm/test/CodeGen/WebAssembly/global-get.ll
+++ b/llvm/test/CodeGen/WebAssembly/global-get.ll
@@ -70,10 +70,12 @@ define i32 @return_extern_i32_global() {
 ; CHECK: .globaltype f64_global, f64
 ; CHECK-LABEL: f64_global:
 
+; FIXME: are we still expecting these to be emitted?
+
 ; CHECK-NOT: .global i32_external_used
-; CHECK: .globaltype i32_external_used, i32
+; CHECK-NOT: .globaltype i32_external_used, i32
 ; CHECK-NOT: i32_external_used:
 
 ; CHECK-NOT: .global i32_external_unused
-; CHECK: .globaltype i32_external_unused, i32
+; CHECK-NOT: .globaltype i32_external_unused, i32
 ; CHECK-NOT: i32_external_unused:

diff  --git a/llvm/test/CodeGen/WebAssembly/i128-returned.ll b/llvm/test/CodeGen/WebAssembly/i128-returned.ll
index a4a136589eabc..619cb141974d7 100644
--- a/llvm/test/CodeGen/WebAssembly/i128-returned.ll
+++ b/llvm/test/CodeGen/WebAssembly/i128-returned.ll
@@ -13,7 +13,8 @@ define i128 @foo(i128) {
   ret i128 %r
 }
 
+; CHECK: .functype bar (i32, i64, i64) -> ()
+
 ; CHECK-LABEL: foo:
 ; CHECK-NEXT: .functype foo (i32, i64, i64) -> ()
 
-; CHECK: .functype bar (i32, i64, i64) -> ()

diff  --git a/llvm/test/CodeGen/WebAssembly/indirect-import.ll b/llvm/test/CodeGen/WebAssembly/indirect-import.ll
index c0f52e95c48ae..986692c2200ce 100644
--- a/llvm/test/CodeGen/WebAssembly/indirect-import.ll
+++ b/llvm/test/CodeGen/WebAssembly/indirect-import.ll
@@ -6,6 +6,14 @@ source_filename = "test/dot_s/indirect-import.c"
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32"
 
+; CHECK: .functype extern_fd (f64) -> (f32)
+; CHECK: .functype extern_vj (i64) -> ()
+; CHECK: .functype extern_v () -> ()
+; CHECK: .functype extern_ijidf  (i64, i32, f64, f32) -> (i32)
+; CHECK: .functype extern_struct (i32) -> ()
+; CHECK: .functype extern_sret (i32) -> ()
+; CHECK: .functype extern_i128ret (i32, i64) -> ()
+
 %struct.big = type { float, double, i32 }
 
 ; Function Attrs: nounwind
@@ -70,10 +78,3 @@ attributes #0 = { nounwind "disable-tail-calls"="false" "less-precise-fpmad"="fa
 attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "frame-pointer"="none" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" }
 
 
-; CHECK: .functype extern_fd (f64) -> (f32)
-; CHECK: .functype extern_vj (i64) -> ()
-; CHECK: .functype extern_v () -> ()
-; CHECK: .functype extern_ijidf  (i64, i32, f64, f32) -> (i32)
-; CHECK: .functype extern_struct (i32) -> ()
-; CHECK: .functype extern_sret (i32) -> ()
-; CHECK: .functype extern_i128ret (i32, i64) -> ()

diff  --git a/llvm/test/CodeGen/WebAssembly/load-store-pic.ll b/llvm/test/CodeGen/WebAssembly/load-store-pic.ll
index ffbc104fcc872..dd38184d7873e 100644
--- a/llvm/test/CodeGen/WebAssembly/load-store-pic.ll
+++ b/llvm/test/CodeGen/WebAssembly/load-store-pic.ll
@@ -11,6 +11,8 @@
 @external_global       = external        global i32
 @external_global_array = external        global [10 x i32]
 
+; PIC: .globaltype __memory_base, [[PTR]]
+
 declare i32 @foo();
 
 ; For hidden symbols PIC code needs to offset all loads and stores
@@ -128,5 +130,3 @@ define void @store_external_global_offset(i32 %n) {
   store i32 %n, i32* %1
   ret void
 }
-
-; PIC: .globaltype __memory_base, [[PTR]]

diff  --git a/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj-options.ll b/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj-options.ll
index a7b4b864c2b84..3403ce4590728 100644
--- a/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj-options.ll
+++ b/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj-options.ll
@@ -6,6 +6,20 @@
 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
 target triple = "wasm32-unknown-unknown"
 
+; EH: .functype  invoke_vi (i32, i32) -> ()
+; EH: .import_module  invoke_vi, env
+; EH: .import_name  invoke_vi, invoke_vi
+; EH-NOT: .functype  __invoke_void_i32
+; EH-NOT: .import_module  __invoke_void_i32
+; EH-NOT: .import_name  __invoke_void_i32
+
+; SJLJ: .functype  emscripten_longjmp (i32, i32) -> ()
+; SJLJ: .import_module  emscripten_longjmp, env
+; SJLJ: .import_name  emscripten_longjmp, emscripten_longjmp
+; SJLJ-NOT: .functype  emscripten_longjmp_jmpbuf
+; SJLJ-NOT: .import_module  emscripten_longjmp_jmpbuf
+; SJLJ-NOT: .import_name  emscripten_longjmp_jmpbuf
+
 %struct.__jmp_buf_tag = type { [6 x i32], i32, [32 x i32] }
 
 define void @exception() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) {
@@ -87,18 +101,4 @@ attributes #0 = { returns_twice }
 attributes #1 = { noreturn }
 attributes #2 = { nounwind }
 
-; EH: .functype  invoke_vi (i32, i32) -> ()
-; EH: .import_module  invoke_vi, env
-; EH: .import_name  invoke_vi, invoke_vi
-; EH-NOT: .functype  __invoke_void_i32
-; EH-NOT: .import_module  __invoke_void_i32
-; EH-NOT: .import_name  __invoke_void_i32
-
-; SJLJ: .functype  emscripten_longjmp (i32, i32) -> ()
-; SJLJ: .import_module  emscripten_longjmp, env
-; SJLJ: .import_name  emscripten_longjmp, emscripten_longjmp
-; SJLJ-NOT: .functype  emscripten_longjmp_jmpbuf
-; SJLJ-NOT: .import_module  emscripten_longjmp_jmpbuf
-; SJLJ-NOT: .import_name  emscripten_longjmp_jmpbuf
-
 ; WASM-EH-EM-EH: LLVM ERROR: -exception-model=wasm not allowed with -enable-emscripten-cxx-exceptions

diff  --git a/llvm/test/CodeGen/WebAssembly/lower-global-dtors.ll b/llvm/test/CodeGen/WebAssembly/lower-global-dtors.ll
index 38eec787db124..82321144611c0 100644
--- a/llvm/test/CodeGen/WebAssembly/lower-global-dtors.ll
+++ b/llvm/test/CodeGen/WebAssembly/lower-global-dtors.ll
@@ -51,6 +51,8 @@ declare void @after_the_null()
   { i32, void ()*, i8* } { i32 65535, void ()* @after_the_null, i8* null }
 ]
 
+; CHECK-LABEL: .functype __cxa_atexit (i32, i32, i32) -> (i32){{$}}
+
 ; CHECK-LABEL: .Lcall_dtors.0:
 ; CHECK-NEXT: .functype .Lcall_dtors.0 (i32) -> (){{$}}
 ; CHECK-NEXT: call            orig_dtor0{{$}}
@@ -186,8 +188,6 @@ declare void @after_the_null()
 
 ; CHECK-LABEL: .weak __dso_handle
 
-; CHECK-LABEL: .functype __cxa_atexit (i32, i32, i32) -> (i32){{$}}
-
 ; We shouldn't make use of a .fini_array section.
 
 ; FINI-NOT: fini_array

diff  --git a/llvm/test/CodeGen/WebAssembly/userstack.ll b/llvm/test/CodeGen/WebAssembly/userstack.ll
index 3d0e0d8c86a08..dc36c466fb3ef 100644
--- a/llvm/test/CodeGen/WebAssembly/userstack.ll
+++ b/llvm/test/CodeGen/WebAssembly/userstack.ll
@@ -4,6 +4,8 @@
 declare void @ext_func(i64* %ptr)
 declare void @ext_func_i32(i32* %ptr)
 
+; CHECK: .globaltype	__stack_pointer, i[[PTR]]{{$}}
+
 ; CHECK-LABEL: alloca32:
 ; Check that there is an extra local for the stack pointer.
 ; CHECK: .local i[[PTR]]{{$}}
@@ -344,6 +346,4 @@ define i8 @frame_offset_with_global_address() {
   ret i8 %5
 }
 
-; CHECK: .globaltype	__stack_pointer, i[[PTR]]{{$}}
-
 ; TODO: test over-aligned alloca

diff  --git a/llvm/test/MC/WebAssembly/alias-offset.s b/llvm/test/MC/WebAssembly/alias-offset.s
index d547e4bb204b7..e45b17d074f63 100644
--- a/llvm/test/MC/WebAssembly/alias-offset.s
+++ b/llvm/test/MC/WebAssembly/alias-offset.s
@@ -21,14 +21,16 @@ sym_a:
   .section    .text,"",@
 main:
   .functype   main () -> ()
+  i32.const 0
   i32.const sym_a
   i32.store sym_b
   end_function
 
 # CHECK-LABEL: <main>:
 # CHECK-EMPTY:
-# CHECK-NEXT:       3: 41 84 80 80 80 00     i32.const       4
-# CHECK-NEXT:                        00000004:  R_WASM_MEMORY_ADDR_SLEB      sym_a+0
-# CHECK-NEXT:       9: 36 02 88 80 80 80 00  i32.store       8
-# CHECK-NEXT:                        0000000b:  R_WASM_MEMORY_ADDR_LEB      sym_b+0
-# CHECK-NEXT:      10: 0b            end
+# CHECK-NEXT:       3: 41 00                 i32.const       0
+# CHECK-NEXT:       5: 41 84 80 80 80 00     i32.const       4
+# CHECK-NEXT:                        00000006:  R_WASM_MEMORY_ADDR_SLEB      sym_a+0
+# CHECK-NEXT:       b: 36 02 88 80 80 80 00  i32.store       8
+# CHECK-NEXT:                        0000000d:  R_WASM_MEMORY_ADDR_LEB      sym_b+0
+# CHECK-NEXT:      12: 0b            end

diff  --git a/llvm/test/MC/WebAssembly/annotations.s b/llvm/test/MC/WebAssembly/annotations.s
index 2d8de388b9895..18fd16f2dc687 100644
--- a/llvm/test/MC/WebAssembly/annotations.s
+++ b/llvm/test/MC/WebAssembly/annotations.s
@@ -1,4 +1,4 @@
-# RUN: llvm-mc -triple=wasm32-unknown-unknown -mattr=+exception-handling < %s | FileCheck %s
+# RUN: llvm-mc -no-type-check -triple=wasm32-unknown-unknown -mattr=+exception-handling < %s | FileCheck %s
 
 # Tests if block/loop/try/catch/end/branch/rethrow instructions are correctly
 # printed with their annotations.

diff  --git a/llvm/test/MC/WebAssembly/assembler-binary.ll b/llvm/test/MC/WebAssembly/assembler-binary.ll
index 7b64f11cd68f3..b749b19d84c9d 100644
--- a/llvm/test/MC/WebAssembly/assembler-binary.ll
+++ b/llvm/test/MC/WebAssembly/assembler-binary.ll
@@ -24,11 +24,11 @@ entry:
 ; ASM:     	.text
 ; ASM:      	.file	"assembler-binary.ll"
 ; ASM:      	.globl	foo
+; ASM:       	.functype	bar () -> ()
 ; ASM:      foo:
 ; ASM-NEXT: 	.functype	foo (i32) -> ()
 ; ASM-NEXT: 	call	bar
 ; ASM-NEXT: 	end_function
-; ASM:       	.functype	bar () -> ()
 
 
 ; CHECK:      --- !WASM

diff  --git a/llvm/test/MC/WebAssembly/atomics-encodings.s b/llvm/test/MC/WebAssembly/atomics-encodings.s
index 06ab6ca69eaf3..aa0117d623e45 100644
--- a/llvm/test/MC/WebAssembly/atomics-encodings.s
+++ b/llvm/test/MC/WebAssembly/atomics-encodings.s
@@ -1,4 +1,4 @@
-# RUN: llvm-mc -show-encoding -triple=wasm32-unknown-unknown -mattr=+atomics < %s | FileCheck %s
+# RUN: llvm-mc -no-type-check -show-encoding -triple=wasm32-unknown-unknown -mattr=+atomics < %s | FileCheck %s
 
 main:
   .functype main () -> ()

diff  --git a/llvm/test/MC/WebAssembly/bad-fixup-expr.s b/llvm/test/MC/WebAssembly/bad-fixup-expr.s
index c00f6d4462bb7..4dc9a5e1bf275 100644
--- a/llvm/test/MC/WebAssembly/bad-fixup-expr.s
+++ b/llvm/test/MC/WebAssembly/bad-fixup-expr.s
@@ -32,7 +32,7 @@ segment1:
   .text
   .section    .text.main,"",@
 main:
-  .functype   main () -> (i32)
+  .functype   main () -> (i32, i32, i32, i32, i32)
 // Expressions involving symbols within the same sections can be evaluated
 // prior to writing the object file.
 // CHECK-NOT: foo

diff  --git a/llvm/test/MC/WebAssembly/basic-assembly.s b/llvm/test/MC/WebAssembly/basic-assembly.s
index a52bc3ed03261..44640824504da 100644
--- a/llvm/test/MC/WebAssembly/basic-assembly.s
+++ b/llvm/test/MC/WebAssembly/basic-assembly.s
@@ -2,6 +2,9 @@
 # Check that it converts to .o without errors, but don't check any output:
 # RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -mattr=+reference-types,+atomics,+simd128,+nontrapping-fptoint,+exception-handling -o %t.o < %s
 
+.functype   something1 () -> ()
+.functype   something2 (i64) -> (i32, f64)
+.globaltype __stack_pointer, i32
 
 empty_func:
     .functype empty_func () -> ()
@@ -18,31 +21,37 @@ test0:
     local.get   2
     local.set   2
     # Immediates:
-    i32.const   -1
-    f64.const   0x1.999999999999ap1
     f32.const   -1.0
+    drop
     f32.const   -infinity
-    f32.const   nan
+    drop
     v128.const  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+    drop
     v128.const  0, 1, 2, 3, 4, 5, 6, 7
-    # Indirect addressing:
+    drop
     local.get   0
+    f64.const   0x1.999999999999ap1
+    # Indirect addressing:
     f64.store   1234:p2align=4
+    i32.const   -1
+    f64.const   nan
     f64.store   1234     # Natural alignment (3)
     # Loops, conditionals, binary ops, calls etc:
-    block       i32
+    block       f32
+    f32.const   2.0
     i32.const   1
     local.get   0
     i32.ge_s
     br_if       0        # 0: down to label0
 .LBB0_1:
-    loop        i32      # label1:
+    loop        void      # label1:
     call        something1
     i64.const   1234
     call        something2
     i32.const   0
     call_indirect (i32, f64) -> ()
     i32.const   1
+    i32.const   2
     i32.add
     local.tee   0
     local.get   0
@@ -51,18 +60,16 @@ test0:
 .LBB0_2:
     end_loop
     end_block            # label0:
-    local.get   4
-    local.get   5
+    drop
+    block       i32
+    block       void
+    block       void
     block       void
-    block       i64
-    block       f32
-    block       f64
     block       () -> (i32, i32)
     i32.const   1
     i32.const   2
     end_block
     drop
-    drop
     br_table {0, 1, 2}   # 2 entries, default
     end_block            # first entry jumps here.
     i32.const   1
@@ -78,14 +85,21 @@ test0:
     end_if
     else
     end_if
+    drop
+    local.get   4
+    local.get   5
     f32x4.add
+    drop
     # Test correct parsing of instructions with / and : in them:
     # TODO: enable once instruction has been added.
     #i32x4.trunc_sat_f32x4_s
+    f32.const   1.0
     i32.trunc_f32_s
     try
     i32.atomic.load 0
+    i32.const   0
     memory.atomic.notify 0
+    drop
 .LBB0_3:
     catch       __cpp_exception
     local.set   0
@@ -97,6 +111,7 @@ test0:
 .LBB0_4:
     #i32.trunc_sat_f32_s
     global.get  __stack_pointer
+    global.set  __stack_pointer
     end_function
 
     .section    .rodata..L.str,"",@
@@ -115,7 +130,6 @@ test0:
     .int32      test0
 
     .ident      "clang version 9.0.0 (trunk 364502) (llvm/trunk 364571)"
-    .globaltype __stack_pointer, i32
 
 .tabletype empty_eref_table, externref
 empty_eref_table:
@@ -125,6 +139,8 @@ empty_fref_table:
 
 
 # CHECK:           .text
+# CHECK:           .globaltype __stack_pointer, i32
+
 # CHECK-LABEL: empty_func:
 # CHECK-NEXT:      .functype	empty_func () -> ()
 # CHECK-NEXT:      end_function
@@ -135,29 +151,35 @@ empty_fref_table:
 # CHECK-NEXT:      .local      f32, f64
 # CHECK-NEXT:      local.get   2
 # CHECK-NEXT:      local.set   2
-# CHECK-NEXT:      i32.const   -1
-# CHECK-NEXT:      f64.const   0x1.999999999999ap1
 # CHECK-NEXT:      f32.const   -0x1p0
+# CHECK-NEXT:      drop
 # CHECK-NEXT:      f32.const   -infinity
-# CHECK-NEXT:      f32.const   nan
+# CHECK-NEXT:      drop
 # CHECK-NEXT:      v128.const  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+# CHECK-NEXT:      drop
 # CHECK-NEXT:      v128.const  0, 1, 2, 3, 4, 5, 6, 7
+# CHECK-NEXT:      drop
 # CHECK-NEXT:      local.get   0
+# CHECK-NEXT:      f64.const   0x1.999999999999ap1
 # CHECK-NEXT:      f64.store   1234:p2align=4
+# CHECK-NEXT:      i32.const   -1
+# CHECK-NEXT:      f64.const   nan
 # CHECK-NEXT:      f64.store   1234
-# CHECK-NEXT:      block       i32
+# CHECK-NEXT:      block       f32
+# CHECK-NEXT:      f32.const   0x1p1
 # CHECK-NEXT:      i32.const   1
 # CHECK-NEXT:      local.get   0
 # CHECK-NEXT:      i32.ge_s
 # CHECK-NEXT:      br_if       0       # 0: down to label0
 # CHECK-NEXT:  .LBB0_1:
-# CHECK-NEXT:      loop        i32     # label1:
+# CHECK-NEXT:      loop                # label1:
 # CHECK-NEXT:      call        something1
 # CHECK-NEXT:      i64.const   1234
 # CHECK-NEXT:      call        something2
 # CHECK-NEXT:      i32.const   0
 # CHECK-NEXT:      call_indirect __indirect_function_table, (i32, f64) -> ()
 # CHECK-NEXT:      i32.const   1
+# CHECK-NEXT:      i32.const   2
 # CHECK-NEXT:      i32.add
 # CHECK-NEXT:      local.tee   0
 # CHECK-NEXT:      local.get   0
@@ -166,18 +188,16 @@ empty_fref_table:
 # CHECK-NEXT:  .LBB0_2:
 # CHECK-NEXT:      end_loop
 # CHECK-NEXT:      end_block           # label0:
-# CHECK-NEXT:      local.get   4
-# CHECK-NEXT:      local.get   5
+# CHECK-NEXT:      drop
+# CHECK-NEXT:      block       i32
+# CHECK-NEXT:      block
+# CHECK-NEXT:      block
 # CHECK-NEXT:      block
-# CHECK-NEXT:      block       i64
-# CHECK-NEXT:      block       f32
-# CHECK-NEXT:      block       f64
 # CHECK-NEXT:      block       () -> (i32, i32)
 # CHECK-NEXT:      i32.const   1
 # CHECK-NEXT:      i32.const   2
 # CHECK-NEXT:      end_block
 # CHECK-NEXT:      drop
-# CHECK-NEXT:      drop
 # CHECK-NEXT:      br_table {0, 1, 2}  # 1: down to label4
 # CHECK-NEXT:                          # 2: down to label3
 # CHECK-NEXT:      end_block           # label5:
@@ -194,11 +214,18 @@ empty_fref_table:
 # CHECK-NEXT:      end_if
 # CHECK-NEXT:      else
 # CHECK-NEXT:      end_if
+# CHECK-NEXT:      drop
+# CHECK-NEXT:      local.get   4
+# CHECK-NEXT:      local.get   5
 # CHECK-NEXT:      f32x4.add
+# CHECK-NEXT:      drop
+# CHECK-NEXT:      f32.const   0x1p0
 # CHECK-NEXT:      i32.trunc_f32_s
 # CHECK-NEXT:      try
 # CHECK-NEXT:      i32.atomic.load 0
+# CHECK-NEXT:      i32.const   0
 # CHECK-NEXT:      memory.atomic.notify 0
+# CHECK-NEXT:      drop
 # CHECK-NEXT:  .LBB0_3:
 # CHECK-NEXT:      catch       __cpp_exception
 # CHECK-NEXT:      local.set   0
@@ -209,6 +236,7 @@ empty_fref_table:
 # CHECK-NEXT:      throw       0
 # CHECK-NEXT:  .LBB0_4:
 # CHECK-NEXT:      global.get  __stack_pointer
+# CHECK-NEXT:      global.set  __stack_pointer
 # CHECK-NEXT:      end_function
 
 # CHECK:           .section    .rodata..L.str,"",@
@@ -225,8 +253,6 @@ empty_fref_table:
 # CHECK-NEXT:      .p2align    2
 # CHECK-NEXT:      .int32      test0
 
-# CHECK:           .globaltype __stack_pointer, i32
-
 # CHECK:           .tabletype empty_eref_table, externref
 # CHECK-NEXT: empty_eref_table:
 

diff  --git a/llvm/test/MC/WebAssembly/bulk-memory-encodings.s b/llvm/test/MC/WebAssembly/bulk-memory-encodings.s
index 0863527c8b367..0f3a4a9f053c6 100644
--- a/llvm/test/MC/WebAssembly/bulk-memory-encodings.s
+++ b/llvm/test/MC/WebAssembly/bulk-memory-encodings.s
@@ -1,5 +1,5 @@
-# RUN: llvm-mc -show-encoding -triple=wasm32-unknown-unknown -mattr=+bulk-memory < %s | FileCheck %s
-# RUN: llvm-mc -show-encoding -triple=wasm64-unknown-unknown -mattr=+bulk-memory < %s | FileCheck %s
+# RUN: llvm-mc -show-encoding -no-type-check -triple=wasm32-unknown-unknown -mattr=+bulk-memory < %s | FileCheck %s
+# RUN: llvm-mc -show-encoding -no-type-check -triple=wasm64-unknown-unknown -mattr=+bulk-memory < %s | FileCheck %s
 
 main:
     .functype main () -> ()

diff  --git a/llvm/test/MC/WebAssembly/data-section-combined.s b/llvm/test/MC/WebAssembly/data-section-combined.s
index 255c756174cd3..1de18a4bc860d 100644
--- a/llvm/test/MC/WebAssembly/data-section-combined.s
+++ b/llvm/test/MC/WebAssembly/data-section-combined.s
@@ -3,7 +3,7 @@
 # RUN: llvm-mc -triple=wasm32-unknown-unknown < %s | FileCheck %s
 
 test0:
-    .functype   test0 () -> (i32)
+    .functype   test0 () -> (i32, i32)
     i32.const a
     i32.const b
     end_function

diff  --git a/llvm/test/MC/WebAssembly/globals.s b/llvm/test/MC/WebAssembly/globals.s
index 717d28b2945c5..b7e25cb9f0519 100644
--- a/llvm/test/MC/WebAssembly/globals.s
+++ b/llvm/test/MC/WebAssembly/globals.s
@@ -16,11 +16,14 @@ read_global:
   end_function
 
 write_global:
-  .functype write_global (i32) -> ()
+  .functype write_global (i32, i64, f32, f64) -> ()
   local.get 0
   global.set foo_global
+  local.get 1
   global.set global2
+  local.get 2
   global.set global3
+  local.get 3
   global.set global4
   end_function
 

diff  --git a/llvm/test/MC/WebAssembly/import-module.s b/llvm/test/MC/WebAssembly/import-module.s
index a59ee184eab50..5d28d5b9c0b92 100644
--- a/llvm/test/MC/WebAssembly/import-module.s
+++ b/llvm/test/MC/WebAssembly/import-module.s
@@ -1,14 +1,15 @@
 # RUN: llvm-mc -triple=wasm32 < %s | FileCheck %s -check-prefix=CHECK-ASM
 # RUN: llvm-mc -triple=wasm32 -filetype=obj -o - < %s | obj2yaml | FileCheck %s
 
+.functype foo () -> ()
+.functype plain () -> ()
+
 test:
   .functype test () -> ()
   call      foo
   call      plain
   end_function
 
-  .functype foo () -> ()
-  .functype plain () -> ()
   .import_module  foo, bar
   .import_name  foo, qux
 

diff  --git a/llvm/test/MC/WebAssembly/null-output.s b/llvm/test/MC/WebAssembly/null-output.s
index a25d095e0cbef..fb15eecffc862 100644
--- a/llvm/test/MC/WebAssembly/null-output.s
+++ b/llvm/test/MC/WebAssembly/null-output.s
@@ -5,6 +5,7 @@
     .type    main, at function
 main:
     .functype   main (i32, i32) -> (i32)
+    local.get 0
     end_function
 .Lfunc_end0:
     .size main, .Lfunc_end0-main

diff  --git a/llvm/test/MC/WebAssembly/objdump.s b/llvm/test/MC/WebAssembly/objdump.s
index 2c9f8a56acd2b..1b4fc3076400f 100644
--- a/llvm/test/MC/WebAssembly/objdump.s
+++ b/llvm/test/MC/WebAssembly/objdump.s
@@ -2,13 +2,13 @@
 # RUN: llvm-objdump --triple=wasm32-unknown-unknown -d %t.o | FileCheck %s
 
 test0:
-    .functype   test0 (i32, i64) -> (i32)
+    .functype   test0 (i32, i64) -> (f32)
     .local      f32, f64, v128, v128
     local.get   2
     end_function
 
 test1:
-    .functype   test1 (i32, i64) -> (i32)
+    .functype   test1 (i32, i64) -> (i64)
     .local      i32, i64, funcref
     local.get   3
     end_function

diff  --git a/llvm/test/MC/WebAssembly/reference-types.s b/llvm/test/MC/WebAssembly/reference-types.s
index e2154ec731268..84b4c9e2f0ca5 100644
--- a/llvm/test/MC/WebAssembly/reference-types.s
+++ b/llvm/test/MC/WebAssembly/reference-types.s
@@ -16,12 +16,14 @@ ref_null_test:
 # CHECK-NEXT: .functype ref_sig_test_funcref (funcref) -> (funcref)
 ref_sig_test_funcref:
   .functype ref_sig_test_funcref (funcref) -> (funcref)
+  local.get 0
   end_function
 
 # CHECK-LABEL: ref_sig_test_externref:
 # CHECK-NEXT: .functype ref_sig_test_externref (externref) -> (externref)
 ref_sig_test_externref:
   .functype ref_sig_test_externref (externref) -> (externref)
+  local.get 0
   end_function
 
 # CHECK-LABEL: ref_select_test:
@@ -45,9 +47,11 @@ ref_select_test:
 # CHECK: block funcref
 # CHECK: block externref
 ref_block_test:
-  .functype ref_block_test () -> ()
+  .functype ref_block_test () -> (externref, funcref)
   block funcref
   block externref
+  ref.null extern
   end_block
+  ref.null func
   end_block
   end_function

diff  --git a/llvm/test/MC/WebAssembly/reloc-pic.s b/llvm/test/MC/WebAssembly/reloc-pic.s
index 4036665ec932c..dd5d315cc2ce0 100644
--- a/llvm/test/MC/WebAssembly/reloc-pic.s
+++ b/llvm/test/MC/WebAssembly/reloc-pic.s
@@ -5,6 +5,11 @@
 # against the corrsponding function or data symbol and that the corresponding
 # data symbols are imported as a wasm globals.
 
+.functype default_func () -> (i32)
+
+.globaltype __memory_base, i32
+.globaltype __table_base, i32
+
 load_default_data:
     .functype   load_default_data () -> (i32)
     global.get  default_data at GOT
@@ -44,7 +49,6 @@ hidden_func:
 #.hidden hidden_func
 #.hidden hidden_data
 .size default_data, 4
-.functype default_func () -> (i32)
 
 # CHECK:      --- !WASM
 # CHECK-NEXT: FileHeader:
@@ -68,6 +72,16 @@ hidden_func:
 # CHECK-NEXT:         Kind:            FUNCTION
 # CHECK-NEXT:         SigIndex:        0
 # CHECK-NEXT:       - Module:          env
+# CHECK-NEXT:         Field:           __memory_base
+# CHECK-NEXT:         Kind:            GLOBAL
+# CHECK-NEXT:         GlobalType:      I32
+# CHECK-NEXT:         GlobalMutable:   true
+# CHECK-NEXT:       - Module:          env
+# CHECK-NEXT:         Field:           __table_base
+# CHECK-NEXT:         Kind:            GLOBAL
+# CHECK-NEXT:         GlobalType:      I32
+# CHECK-NEXT:         GlobalMutable:   true
+# CHECK-NEXT:       - Module:          env
 # CHECK-NEXT:         Field:           __indirect_function_table
 # CHECK-NEXT:         Kind:            TABLE
 # CHECK-NEXT:         Table:
@@ -103,13 +117,13 @@ hidden_func:
 # CHECK-NEXT:       - Type:            R_WASM_GLOBAL_INDEX_LEB
 # CHECK-NEXT:         Index:           3
 # CHECK-NEXT:         Offset:          0x10
-# CHECK-NEXT:       - Type:            R_WASM_MEMORY_ADDR_LEB
+# CHECK-NEXT:       - Type:            R_WASM_GLOBAL_INDEX_LEB
 # CHECK-NEXT:         Index:           5
 # CHECK-NEXT:         Offset:          0x1C
 # CHECK-NEXT:       - Type:            R_WASM_MEMORY_ADDR_REL_SLEB
 # CHECK-NEXT:         Index:           6
 # CHECK-NEXT:         Offset:          0x22
-# CHECK-NEXT:       - Type:            R_WASM_MEMORY_ADDR_LEB
+# CHECK-NEXT:       - Type:            R_WASM_GLOBAL_INDEX_LEB
 # CHECK-NEXT:         Index:           8
 # CHECK-NEXT:         Offset:          0x2C
 # CHECK-NEXT:       - Type:            R_WASM_TABLE_INDEX_REL_SLEB
@@ -118,16 +132,16 @@ hidden_func:
 # CHECK-NEXT:     Functions:
 # CHECK-NEXT:       - Index:           1
 # CHECK-NEXT:         Locals:          []
-# CHECK-NEXT:         Body:            2380808080002802000B
+# CHECK-NEXT:         Body:            2382808080002802000B
 # CHECK-NEXT:       - Index:           2
 # CHECK-NEXT:         Locals:          []
-# CHECK-NEXT:         Body:            2381808080002802000B
+# CHECK-NEXT:         Body:            2383808080002802000B
 # CHECK-NEXT:       - Index:           3
 # CHECK-NEXT:         Locals:          []
 # CHECK-NEXT:         Body:            2380808080004180808080006A0B
 # CHECK-NEXT:       - Index:           4
 # CHECK-NEXT:         Locals:          []
-# CHECK-NEXT:         Body:            2380808080004180808080006A0B
+# CHECK-NEXT:         Body:            2381808080004180808080006A0B
 # CHECK-NEXT:       - Index:           5
 # CHECK-NEXT:         Locals:          []
 # CHECK-NEXT:         Body:            41000B
@@ -168,9 +182,10 @@ hidden_func:
 # CHECK-NEXT:         Flags:           [ BINDING_LOCAL ]
 # CHECK-NEXT:         Function:        3
 # CHECK-NEXT:       - Index:           5
-# CHECK-NEXT:         Kind:            DATA
+# CHECK-NEXT:         Kind:            GLOBAL
 # CHECK-NEXT:         Name:            __memory_base
 # CHECK-NEXT:         Flags:           [ UNDEFINED ]
+# CHECK-NEXT:         Global:          0
 # CHECK-NEXT:       - Index:           6
 # CHECK-NEXT:         Kind:            DATA
 # CHECK-NEXT:         Name:            .L.hidden_data
@@ -183,9 +198,10 @@ hidden_func:
 # CHECK-NEXT:         Flags:           [ BINDING_LOCAL ]
 # CHECK-NEXT:         Function:        4
 # CHECK-NEXT:       - Index:           8
-# CHECK-NEXT:         Kind:            DATA
+# CHECK-NEXT:         Kind:            GLOBAL
 # CHECK-NEXT:         Name:            __table_base
 # CHECK-NEXT:         Flags:           [ UNDEFINED ]
+# CHECK-NEXT:         Global:          1
 # CHECK-NEXT:       - Index:           9
 # CHECK-NEXT:         Kind:            FUNCTION
 # CHECK-NEXT:         Name:            hidden_func

diff  --git a/llvm/test/MC/WebAssembly/reloc-pic64.s b/llvm/test/MC/WebAssembly/reloc-pic64.s
index 9a382a15a0a2f..0f2ebba2a2f33 100644
--- a/llvm/test/MC/WebAssembly/reloc-pic64.s
+++ b/llvm/test/MC/WebAssembly/reloc-pic64.s
@@ -5,6 +5,11 @@
 # against the corrsponding function or data symbol and that the corresponding
 # data symbols are imported as a wasm globals.
 
+.functype default_func () -> (i32)
+
+.globaltype __memory_base, i64
+.globaltype __table_base, i64
+
 load_default_data:
     .functype   load_default_data () -> (i32)
     global.get  default_data at GOT
@@ -44,7 +49,6 @@ hidden_func:
 #.hidden hidden_func
 #.hidden hidden_data
 .size default_data, 4
-.functype default_func () -> (i32)
 
 # CHECK:      --- !WASM
 # CHECK-NEXT: FileHeader:
@@ -73,6 +77,16 @@ hidden_func:
 # CHECK-NEXT:         Kind:            FUNCTION
 # CHECK-NEXT:         SigIndex:        0
 # CHECK-NEXT:       - Module:          env
+# CHECK-NEXT:         Field:           __memory_base
+# CHECK-NEXT:         Kind:            GLOBAL
+# CHECK-NEXT:         GlobalType:      I64
+# CHECK-NEXT:         GlobalMutable:   true
+# CHECK-NEXT:       - Module:          env
+# CHECK-NEXT:         Field:           __table_base
+# CHECK-NEXT:         Kind:            GLOBAL
+# CHECK-NEXT:         GlobalType:      I64
+# CHECK-NEXT:         GlobalMutable:   true
+# CHECK-NEXT:       - Module:          env
 # CHECK-NEXT:         Field:           __indirect_function_table
 # CHECK-NEXT:         Kind:            TABLE
 # CHECK-NEXT:         Table:
@@ -108,31 +122,31 @@ hidden_func:
 # CHECK-NEXT:       - Type:            R_WASM_GLOBAL_INDEX_LEB
 # CHECK-NEXT:         Index:           3
 # CHECK-NEXT:         Offset:          0x10
-# CHECK-NEXT:       - Type:            R_WASM_MEMORY_ADDR_LEB
+# CHECK-NEXT:       - Type:            R_WASM_GLOBAL_INDEX_LEB
 # CHECK-NEXT:         Index:           5
 # CHECK-NEXT:         Offset:          0x1C
-# CHECK-NEXT:       - Type:            R_WASM_MEMORY_ADDR_REL_SLEB
+# CHECK-NEXT:       - Type:            R_WASM_MEMORY_ADDR_REL_SLEB64
 # CHECK-NEXT:         Index:           6
 # CHECK-NEXT:         Offset:          0x22
-# CHECK-NEXT:       - Type:            R_WASM_MEMORY_ADDR_LEB
+# CHECK-NEXT:       - Type:            R_WASM_GLOBAL_INDEX_LEB
 # CHECK-NEXT:         Index:           8
 # CHECK-NEXT:         Offset:          0x31
-# CHECK-NEXT:       - Type:            R_WASM_TABLE_INDEX_REL_SLEB
+# CHECK-NEXT:       - Type:            R_WASM_TABLE_INDEX_REL_SLEB64
 # CHECK-NEXT:         Index:           9
 # CHECK-NEXT:         Offset:          0x37
 # CHECK-NEXT:     Functions:
 # CHECK-NEXT:       - Index:           1
 # CHECK-NEXT:         Locals:          []
-# CHECK-NEXT:         Body:            2380808080002802000B
+# CHECK-NEXT:         Body:            2382808080002802000B
 # CHECK-NEXT:       - Index:           2
 # CHECK-NEXT:         Locals:          []
-# CHECK-NEXT:         Body:            2381808080002802000B
+# CHECK-NEXT:         Body:            2383808080002802000B
 # CHECK-NEXT:       - Index:           3
 # CHECK-NEXT:         Locals:          []
 # CHECK-NEXT:         Body:            23808080800042808080808080808080007C0B
 # CHECK-NEXT:       - Index:           4
 # CHECK-NEXT:         Locals:          []
-# CHECK-NEXT:         Body:            23808080800042808080808080808080007C0B
+# CHECK-NEXT:         Body:            23818080800042808080808080808080007C0B
 # CHECK-NEXT:       - Index:           5
 # CHECK-NEXT:         Locals:          []
 # CHECK-NEXT:         Body:            41000B
@@ -173,9 +187,10 @@ hidden_func:
 # CHECK-NEXT:         Flags:           [ BINDING_LOCAL ]
 # CHECK-NEXT:         Function:        3
 # CHECK-NEXT:       - Index:           5
-# CHECK-NEXT:         Kind:            DATA
+# CHECK-NEXT:         Kind:            GLOBAL
 # CHECK-NEXT:         Name:            __memory_base
 # CHECK-NEXT:         Flags:           [ UNDEFINED ]
+# CHECK-NEXT:         Global:          0
 # CHECK-NEXT:       - Index:           6
 # CHECK-NEXT:         Kind:            DATA
 # CHECK-NEXT:         Name:            .L.hidden_data
@@ -188,9 +203,10 @@ hidden_func:
 # CHECK-NEXT:         Flags:           [ BINDING_LOCAL ]
 # CHECK-NEXT:         Function:        4
 # CHECK-NEXT:       - Index:           8
-# CHECK-NEXT:         Kind:            DATA
+# CHECK-NEXT:         Kind:            GLOBAL
 # CHECK-NEXT:         Name:            __table_base
 # CHECK-NEXT:         Flags:           [ UNDEFINED ]
+# CHECK-NEXT:         Global:          1
 # CHECK-NEXT:       - Index:           9
 # CHECK-NEXT:         Kind:            FUNCTION
 # CHECK-NEXT:         Name:            hidden_func

diff  --git a/llvm/test/MC/WebAssembly/simd-encodings.s b/llvm/test/MC/WebAssembly/simd-encodings.s
index 3093fb2963444..ab405406a3d11 100644
--- a/llvm/test/MC/WebAssembly/simd-encodings.s
+++ b/llvm/test/MC/WebAssembly/simd-encodings.s
@@ -1,4 +1,4 @@
-# RUN: llvm-mc -show-encoding -triple=wasm32-unknown-unknown -mattr=+simd128 < %s | FileCheck %s
+# RUN: llvm-mc -no-type-check -show-encoding -triple=wasm32-unknown-unknown -mattr=+simd128 < %s | FileCheck %s
 
 main:
     .functype main () -> ()

diff  --git a/llvm/test/MC/WebAssembly/tail-call-encodings.s b/llvm/test/MC/WebAssembly/tail-call-encodings.s
index 1b2f85b436864..c9c3c9d4fa2ac 100644
--- a/llvm/test/MC/WebAssembly/tail-call-encodings.s
+++ b/llvm/test/MC/WebAssembly/tail-call-encodings.s
@@ -15,8 +15,10 @@ foo1:
     end_function
 
 foo2:
-    .functype foo2 () -> ()
+    .functype foo2 () -> (i32)
 
+    i32.const 0
+    i32.const 0
     # REF: return_call_indirect __indirect_function_table, (i32) -> (i32) # encoding: [0x13,
     # CHECK: return_call_indirect (i32) -> (i32) # encoding: [0x13,
     # CHECK-NEXT: fixup A - offset: 1, value: .Ltypeindex0 at TYPEINDEX, kind: fixup_uleb128_i32

diff  --git a/llvm/test/MC/WebAssembly/tls.s b/llvm/test/MC/WebAssembly/tls.s
index 2df245ff9385a..0f5a5a394c398 100644
--- a/llvm/test/MC/WebAssembly/tls.s
+++ b/llvm/test/MC/WebAssembly/tls.s
@@ -2,12 +2,15 @@
 # RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -o %t.o < %s
 # RUN: obj2yaml %t.o | FileCheck %s --check-prefix=CHECK-OBJ
 
+.globaltype __tls_base, i32
+
 tls_store:
   .functype tls_store (i32) -> ()
   # CHECK: global.get __tls_base
   # CHECK-NEXT: i32.const tls1 at TLSREL
   # CHECK-NEXT: i32.add
   # CHECK-NEXT: i32.store 0
+  local.get 0
   global.get __tls_base
   i32.const tls1 at TLSREL
   i32.add
@@ -28,12 +31,12 @@ tls2:
 
 #      CHECK-OBJ:  - Type:            CODE
 # CHECK-OBJ-NEXT:    Relocations:
-# CHECK-OBJ-NEXT:      - Type:            R_WASM_MEMORY_ADDR_LEB
+# CHECK-OBJ-NEXT:      - Type:            R_WASM_GLOBAL_INDEX_LEB
 # CHECK-OBJ-NEXT:        Index:           1
-# CHECK-OBJ-NEXT:        Offset:          0x4
+# CHECK-OBJ-NEXT:        Offset:          0x6
 # CHECK-OBJ-NEXT:      - Type:            R_WASM_MEMORY_ADDR_TLS_SLEB
 # CHECK-OBJ-NEXT:        Index:           2
-# CHECK-OBJ-NEXT:        Offset:          0xA
+# CHECK-OBJ-NEXT:        Offset:          0xC
 
 #      CHECK-OBJ:  - Type:            CUSTOM
 # CHECK-OBJ-NEXT:    Name:            linking
@@ -45,9 +48,10 @@ tls2:
 # CHECK-OBJ-NEXT:        Flags:           [ BINDING_LOCAL ]
 # CHECK-OBJ-NEXT:        Function:        0
 # CHECK-OBJ-NEXT:      - Index:           1
-# CHECK-OBJ-NEXT:        Kind:            DATA
+# CHECK-OBJ-NEXT:        Kind:            GLOBAL
 # CHECK-OBJ-NEXT:        Name:            __tls_base
 # CHECK-OBJ-NEXT:        Flags:           [ UNDEFINED ]
+# CHECK-OBJ-NEXT:        Global:          0
 # CHECK-OBJ-NEXT:      - Index:           2
 # CHECK-OBJ-NEXT:        Kind:            DATA
 # CHECK-OBJ-NEXT:        Name:            tls1

diff  --git a/llvm/test/MC/WebAssembly/type-index.s b/llvm/test/MC/WebAssembly/type-index.s
index 906509e9d9af7..1c2feeda3e870 100644
--- a/llvm/test/MC/WebAssembly/type-index.s
+++ b/llvm/test/MC/WebAssembly/type-index.s
@@ -6,13 +6,15 @@
 
 test0:
     .functype   test0 (i32) -> (i32)
-    call_indirect (f64) -> (f64)
+    f64.const 1.0
+    local.get 0
+    call_indirect (f64) -> (i32)
     end_function
 
 # CHECK:	.text
 # CHECK-LABEL: test0:
 # CHECK-NEXT:	.functype	test0 (i32) -> (i32)
-# CHECK-NEXT:	call_indirect	__indirect_function_table, (f64) -> (f64)
+# CHECK:	    call_indirect	__indirect_function_table, (f64) -> (i32)
 # CHECK-NEXT:	end_function
 
 # BIN:      --- !WASM
@@ -30,7 +32,7 @@ test0:
 # BIN-NEXT:         ParamTypes:
 # BIN-NEXT:           - F64
 # BIN-NEXT:         ReturnTypes:
-# BIN-NEXT:           - F64
+# BIN-NEXT:           - I32
 # BIN-NEXT:   - Type:            IMPORT
 # BIN-NEXT:     Imports:
 # BIN-NEXT:       - Module:          env
@@ -52,14 +54,14 @@ test0:
 # BIN-NEXT:     Relocations:
 # BIN-NEXT:       - Type:            R_WASM_TYPE_INDEX_LEB
 # BIN-NEXT:         Index:           1
-# BIN-NEXT:         Offset:          0x4
+# BIN-NEXT:         Offset:          0xF
 # BIN-NEXT:       - Type:            R_WASM_TABLE_NUMBER_LEB
 # BIN-NEXT:         Index:           1
-# BIN-NEXT:         Offset:          0x9
+# BIN-NEXT:         Offset:          0x14
 # BIN-NEXT:     Functions:
 # BIN-NEXT:       - Index:           0
 # BIN-NEXT:         Locals:          []
-# BIN-NEXT:         Body:            11818080800080808080000B
+# BIN-NEXT:         Body:            44000000000000F03F200011818080800080808080000B
 # BIN-NEXT:   - Type:            CUSTOM
 # BIN-NEXT:     Name:            linking
 # BIN-NEXT:     Version:         2

diff  --git a/llvm/test/MC/WebAssembly/wasm64.s b/llvm/test/MC/WebAssembly/wasm64.s
index 402d5020caba6..c41f4f0c96009 100644
--- a/llvm/test/MC/WebAssembly/wasm64.s
+++ b/llvm/test/MC/WebAssembly/wasm64.s
@@ -3,6 +3,9 @@
 
 # Most of our other tests are for wasm32, this one adds some wasm64 specific tests.
 
+.globaltype myglob64, i64
+.globaltype __stack_pointer, i64
+
 test:
     .functype   test (i64) -> ()
     .local      i64
@@ -31,24 +34,24 @@ test:
 
     ### basic stores
 
-    f32.const   0.0
     i64.const   0         # get i64 from constant.
+    f32.const   0.0
     f32.store   0
 
-    f32.const   0.0
     local.get   0         # get i64 from local.
+    f32.const   0.0
     f32.store   0
 
-    f32.const   0.0
     i64.const   .L.str    # get i64 relocatable.
+    f32.const   0.0
     f32.store   0
 
-    f32.const   0.0
     global.get  myglob64  # get i64 from global
+    f32.const   0.0
     f32.store   0
 
-    f32.const   0.0
     i64.const   0
+    f32.const   0.0
     f32.store   .L.str    # relocatable offset!
 
     ### 64-bit SP
@@ -66,9 +69,8 @@ test:
     .int64      .L.str    # relocatable inside data.
     .size       .L.str, 24
 
-    .globaltype myglob64, i64
-    .globaltype __stack_pointer, i64
 
+# CHECK:              .globaltype     myglob64, i64
 
 # CHECK:              .functype       test (i64) -> ()
 # CHECK-NEXT:         .local          i64
@@ -95,24 +97,24 @@ test:
 # CHECK-NEXT:         drop
 
 
-# CHECK:              f32.const       0x0p0
-# CHECK-NEXT:         i64.const       0
+# CHECK:              i64.const       0
+# CHECK-NEXT:         f32.const       0x0p0
 # CHECK-NEXT:         f32.store       0
 
-# CHECK:              f32.const       0x0p0
-# CHECK-NEXT:         local.get       0
+# CHECK:              local.get       0
+# CHECK-NEXT:         f32.const       0x0p0
 # CHECK-NEXT:         f32.store       0
 
-# CHECK:              f32.const       0x0p0
-# CHECK-NEXT:         i64.const       .L.str
+# CHECK:              i64.const       .L.str
+# CHECK-NEXT:         f32.const       0x0p0
 # CHECK-NEXT:         f32.store       0
 
-# CHECK:              f32.const       0x0p0
-# CHECK-NEXT:         global.get      myglob64
+# CHECK:              global.get      myglob64
+# CHECK-NEXT:         f32.const       0x0p0
 # CHECK-NEXT:         f32.store       0
 
-# CHECK:              f32.const       0x0p0
-# CHECK-NEXT:         i64.const       0
+# CHECK:              i64.const       0
+# CHECK-NEXT:         f32.const       0x0p0
 # CHECK-NEXT:         f32.store       .L.str
 
 
@@ -127,8 +129,6 @@ test:
 # CHECK-NEXT:         .int64      .L.str
 # CHECK-NEXT:         .size       .L.str, 24
 
-# CHECK:              .globaltype     myglob64, i64
-
 
 
 # BIN:      --- !WASM
@@ -176,10 +176,10 @@ test:
 # BIN-NEXT:         Offset:          0x2F
 # BIN-NEXT:       - Type:            R_WASM_MEMORY_ADDR_SLEB64
 # BIN-NEXT:         Index:           1
-# BIN-NEXT:         Offset:          0x54
+# BIN-NEXT:         Offset:          0x4F
 # BIN-NEXT:       - Type:            R_WASM_GLOBAL_INDEX_LEB
 # BIN-NEXT:         Index:           2
-# BIN-NEXT:         Offset:          0x67
+# BIN-NEXT:         Offset:          0x62
 # BIN-NEXT:       - Type:            R_WASM_MEMORY_ADDR_LEB64
 # BIN-NEXT:         Index:           1
 # BIN-NEXT:         Offset:          0x78
@@ -191,7 +191,7 @@ test:
 # BIN-NEXT:         Locals:
 # BIN-NEXT:           - Type:            I64
 # BIN-NEXT:             Count:           1
-# BIN-NEXT:         Body:            42002A02001A20002A02001A42808080808080808080002A02001A2380808080002A02001A42002A02808080808080808080001A4300000000420038020043000000002000380200430000000042808080808080808080003802004300000000238080808000380200430000000042003802808080808080808080002381808080001A0B
+# BIN-NEXT:         Body:            42002A02001A20002A02001A42808080808080808080002A02001A2380808080002A02001A42002A02808080808080808080001A4200430000000038020020004300000000380200428080808080808080800043000000003802002380808080004300000000380200420043000000003802808080808080808080002381808080001A0B
 # BIN-NEXT:   - Type:            DATA
 # BIN-NEXT:     Relocations:
 # BIN-NEXT:       - Type:            R_WASM_MEMORY_ADDR_I64

diff  --git a/llvm/test/MC/WebAssembly/weak-alias.s b/llvm/test/MC/WebAssembly/weak-alias.s
index 7e6a9ffc36d31..2b2b4ae2b7b28 100644
--- a/llvm/test/MC/WebAssembly/weak-alias.s
+++ b/llvm/test/MC/WebAssembly/weak-alias.s
@@ -5,6 +5,8 @@
 # 'bar_alias' is weak alias of global variable 'bar'
 # Generates two exports of the same function, one of them weak
 
+.functype foo_alias () -> (i32)
+
 foo:
   .hidden foo
   .globl  foo

diff  --git a/llvm/utils/gn/secondary/llvm/lib/Target/WebAssembly/AsmParser/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Target/WebAssembly/AsmParser/BUILD.gn
index ce29b3516f48c..b9d13be8c4568 100644
--- a/llvm/utils/gn/secondary/llvm/lib/Target/WebAssembly/AsmParser/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/Target/WebAssembly/AsmParser/BUILD.gn
@@ -18,5 +18,5 @@ static_library("AsmParser") {
     "//llvm/lib/Target/WebAssembly/Utils",
   ]
   include_dirs = [ ".." ]
-  sources = [ "WebAssemblyAsmParser.cpp" ]
+  sources = [ "WebAssemblyAsmParser.cpp", "WebAssemblyAsmTypeCheck.cpp" ]
 }

diff  --git a/llvm/utils/gn/secondary/llvm/lib/Target/WebAssembly/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Target/WebAssembly/BUILD.gn
index 6f5ea41aacf05..39cfa79e15663 100644
--- a/llvm/utils/gn/secondary/llvm/lib/Target/WebAssembly/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/Target/WebAssembly/BUILD.gn
@@ -53,6 +53,7 @@ static_library("LLVMWebAssemblyCodeGen") {
     "WebAssemblyLowerEmscriptenEHSjLj.cpp",
     "WebAssemblyLowerGlobalDtors.cpp",
     "WebAssemblyMCInstLower.cpp",
+    "WebAssemblyMCLowerPrePass.cpp",
     "WebAssemblyMachineFunctionInfo.cpp",
     "WebAssemblyMemIntrinsicResults.cpp",
     "WebAssemblyNullifyDebugValueLists.cpp",


        


More information about the llvm-commits mailing list