[llvm] 388fb67 - [WebAssembly] Added .tabletype to asm and multiple table support in obj files

Sam Clegg via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 13 07:52:47 PDT 2020


Author: Paulo Matos
Date: 2020-10-13T07:52:23-07:00
New Revision: 388fb67b0dd7f41630ab6c3400c96843852319af

URL: https://github.com/llvm/llvm-project/commit/388fb67b0dd7f41630ab6c3400c96843852319af
DIFF: https://github.com/llvm/llvm-project/commit/388fb67b0dd7f41630ab6c3400c96843852319af.diff

LOG: [WebAssembly] Added .tabletype to asm and multiple table support in obj files

Adds more testing in basic-assembly.s and a new test tables.s.
Adds support to yaml reading and writing of tables as well.

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

Added: 
    llvm/test/MC/WebAssembly/tables.s

Modified: 
    lld/test/wasm/alias.s
    lld/test/wasm/call-indirect.ll
    lld/test/wasm/export-table.test
    lld/test/wasm/growable-table.test
    lld/test/wasm/import-table.test
    lld/test/wasm/local-symbols.ll
    lld/test/wasm/locals-duplicate.test
    lld/test/wasm/pie.ll
    lld/test/wasm/relocatable.ll
    lld/test/wasm/shared-memory-no-atomics.yaml
    lld/test/wasm/shared-memory.yaml
    lld/test/wasm/shared.ll
    lld/test/wasm/stack-pointer.ll
    lld/test/wasm/undefined-weak-call.ll
    lld/test/wasm/weak-alias-overide.ll
    lld/test/wasm/weak-alias.ll
    lld/test/wasm/weak-symbols.ll
    lld/test/wasm/weak-undefined.ll
    lld/wasm/SyntheticSections.cpp
    lld/wasm/WriterUtils.cpp
    llvm/include/llvm/BinaryFormat/Wasm.h
    llvm/include/llvm/MC/MCSymbolWasm.h
    llvm/include/llvm/Object/Wasm.h
    llvm/include/llvm/ObjectYAML/WasmYAML.h
    llvm/lib/BinaryFormat/Wasm.cpp
    llvm/lib/MC/WasmObjectWriter.cpp
    llvm/lib/Object/WasmObjectFile.cpp
    llvm/lib/ObjectYAML/WasmEmitter.cpp
    llvm/lib/ObjectYAML/WasmYAML.cpp
    llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
    llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
    llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp
    llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h
    llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
    llvm/test/MC/WebAssembly/assembler-binary.ll
    llvm/test/MC/WebAssembly/basic-assembly.s
    llvm/test/MC/WebAssembly/comdat.ll
    llvm/test/MC/WebAssembly/data-section.s
    llvm/test/MC/WebAssembly/global-ctor-dtor.ll
    llvm/test/MC/WebAssembly/reloc-pic.s
    llvm/test/MC/WebAssembly/type-index.s
    llvm/test/MC/WebAssembly/wasm64.s
    llvm/test/MC/WebAssembly/weak-alias.s
    llvm/test/Object/wasm-relocs-and-producers.yaml
    llvm/test/ObjectYAML/wasm/elem_section.yaml
    llvm/test/ObjectYAML/wasm/import_section.yaml
    llvm/test/ObjectYAML/wasm/table_section.yaml
    llvm/test/tools/llvm-readobj/wasm/wasm-imports.test
    llvm/tools/obj2yaml/wasm2yaml.cpp

Removed: 
    


################################################################################
diff  --git a/lld/test/wasm/alias.s b/lld/test/wasm/alias.s
index e95cef1bb6a9..1b90ed56bc7b 100644
--- a/lld/test/wasm/alias.s
+++ b/lld/test/wasm/alias.s
@@ -24,7 +24,8 @@ _start:
 # CHECK-NEXT:     FunctionTypes:   [ 0 ]
 # CHECK-NEXT:   - Type:            TABLE
 # CHECK-NEXT:     Tables:
-# CHECK-NEXT:       - ElemType:        FUNCREF
+# CHECK-NEXT:       - Index:           0
+# CHECK-NEXT:         ElemType:        FUNCREF
 # CHECK-NEXT:         Limits:
 # CHECK-NEXT:           Flags:           [ HAS_MAX ]
 # CHECK-NEXT:           Initial:         0x00000001

diff  --git a/lld/test/wasm/call-indirect.ll b/lld/test/wasm/call-indirect.ll
index 722385bdd350..fb2777ecd414 100644
--- a/lld/test/wasm/call-indirect.ll
+++ b/lld/test/wasm/call-indirect.ll
@@ -63,7 +63,8 @@ define void @call_ptr(i64 (i64)* %arg) {
 ; CHECK-NEXT:     FunctionTypes:   [ 0, 3, 1, 3, 4 ]
 ; CHECK-NEXT:   - Type:            TABLE
 ; CHECK-NEXT:     Tables:
-; CHECK-NEXT:       - ElemType:        FUNCREF
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         ElemType:        FUNCREF
 ; CHECK-NEXT:         Limits:
 ; CHECK-NEXT:           Flags:           [ HAS_MAX ]
 ; CHECK-NEXT:           Initial:         0x00000003

diff  --git a/lld/test/wasm/export-table.test b/lld/test/wasm/export-table.test
index b218392652d6..5b374fc54277 100644
--- a/lld/test/wasm/export-table.test
+++ b/lld/test/wasm/export-table.test
@@ -6,7 +6,8 @@
 
 # CHECK:        - Type:            TABLE
 # CHECK-NEXT:     Tables:
-# CHECK-NEXT:       - ElemType:        FUNCREF
+# CHECK-NEXT:       - Index:           0
+# CHECK-NEXT:         ElemType:        FUNCREF
 # CHECK-NEXT:         Limits:
 # CHECK-NEXT:           Flags:           [ HAS_MAX ]
 # CHECK-NEXT:           Initial:         0x00000001

diff  --git a/lld/test/wasm/growable-table.test b/lld/test/wasm/growable-table.test
index 00cff3fc416e..f5ebc2e346d5 100644
--- a/lld/test/wasm/growable-table.test
+++ b/lld/test/wasm/growable-table.test
@@ -6,7 +6,8 @@
 
 # CHECK:        - Type:            TABLE
 # CHECK-NEXT:     Tables:
-# CHECK-NEXT:       - ElemType:        FUNCREF
+# CHECK-NEXT:       - Index:           0
+# CHECK-NEXT:         ElemType:        FUNCREF
 # CHECK-NEXT:         Limits:
 # CHECK-NEXT:           Initial:         0x00000001
 # CHECK-NEXT:   - Type:

diff  --git a/lld/test/wasm/import-table.test b/lld/test/wasm/import-table.test
index 4d1b4c9a7832..ffc9395b485e 100644
--- a/lld/test/wasm/import-table.test
+++ b/lld/test/wasm/import-table.test
@@ -10,6 +10,7 @@
 # CHECK-NEXT:        Field:           __indirect_function_table
 # CHECK-NEXT:        Kind:            TABLE
 # CHECK-NEXT:        Table:
+# CHECK-NEXT:          Index:           0
 # CHECK-NEXT:          ElemType:        FUNCREF
 # CHECK-NEXT:          Limits:
 # CHECK-NEXT:            Initial:         0x00000001

diff  --git a/lld/test/wasm/local-symbols.ll b/lld/test/wasm/local-symbols.ll
index 03e638cdd881..d6ea9e83a0f3 100644
--- a/lld/test/wasm/local-symbols.ll
+++ b/lld/test/wasm/local-symbols.ll
@@ -37,7 +37,8 @@ entry:
 ; CHECK-NEXT:     FunctionTypes:   [ 0, 1 ]
 ; CHECK-NEXT:   - Type:            TABLE
 ; CHECK-NEXT:     Tables:
-; CHECK-NEXT:       - ElemType:        FUNCREF
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         ElemType:        FUNCREF
 ; CHECK-NEXT:         Limits:
 ; CHECK-NEXT:           Flags:           [ HAS_MAX ]
 ; CHECK-NEXT:           Initial:         0x00000001

diff  --git a/lld/test/wasm/locals-duplicate.test b/lld/test/wasm/locals-duplicate.test
index 61018f8213e3..78347ed6e47c 100644
--- a/lld/test/wasm/locals-duplicate.test
+++ b/lld/test/wasm/locals-duplicate.test
@@ -18,7 +18,8 @@
 ; CHECK-NEXT:                        0, 0 ]
 ; CHECK-NEXT:   - Type:            TABLE
 ; CHECK-NEXT:     Tables:
-; CHECK-NEXT:       - ElemType:        FUNCREF
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         ElemType:        FUNCREF
 ; CHECK-NEXT:         Limits:
 ; CHECK-NEXT:           Flags:           [ HAS_MAX ]
 ; CHECK-NEXT:           Initial:         0x00000007
@@ -229,7 +230,8 @@
 ; RELOC-NEXT:                        0, 0 ]
 ; RELOC-NEXT:   - Type:            TABLE
 ; RELOC-NEXT:     Tables:
-; RELOC-NEXT:       - ElemType:        FUNCREF
+; RELOC-NEXT:       - Index:           0
+; RELOC-NEXT:         ElemType:        FUNCREF
 ; RELOC-NEXT:         Limits:
 ; RELOC-NEXT:           Flags:           [ HAS_MAX ]
 ; RELOC-NEXT:           Initial:         0x00000007

diff  --git a/lld/test/wasm/pie.ll b/lld/test/wasm/pie.ll
index a203d31798c9..13d30ffe51c3 100644
--- a/lld/test/wasm/pie.ll
+++ b/lld/test/wasm/pie.ll
@@ -36,6 +36,7 @@ define void @_start() {
 ; CHECK-NEXT:         Field:           __indirect_function_table
 ; CHECK-NEXT:         Kind:            TABLE
 ; CHECK-NEXT:         Table:
+; CHECK-NEXT:           Index:           0
 ; CHECK-NEXT:           ElemType:        FUNCREF
 ; CHECK-NEXT:           Limits:
 ; CHECK-NEXT:             Initial:         0x00000001

diff  --git a/lld/test/wasm/relocatable.ll b/lld/test/wasm/relocatable.ll
index 1bf039108614..a1932e59a081 100644
--- a/lld/test/wasm/relocatable.ll
+++ b/lld/test/wasm/relocatable.ll
@@ -67,7 +67,8 @@ entry:
 ; CHECK-NEXT:     FunctionTypes:   [ 2, 1, 1 ]
 ; CHECK-NEXT:   - Type:            TABLE
 ; CHECK-NEXT:     Tables:
-; CHECK-NEXT:       - ElemType:        FUNCREF
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         ElemType:        FUNCREF
 ; CHECK-NEXT:         Limits:
 ; CHECK-NEXT:           Flags:           [ HAS_MAX ]
 ; CHECK-NEXT:           Initial:         0x00000004

diff  --git a/lld/test/wasm/shared-memory-no-atomics.yaml b/lld/test/wasm/shared-memory-no-atomics.yaml
index 7e01a89c4557..31d0edef1534 100644
--- a/lld/test/wasm/shared-memory-no-atomics.yaml
+++ b/lld/test/wasm/shared-memory-no-atomics.yaml
@@ -19,6 +19,7 @@ Sections:
         Field:           __indirect_function_table
         Kind:            TABLE
         Table:
+          Index:           0
           ElemType:        FUNCREF
           Limits:
             Initial:         0x00000000

diff  --git a/lld/test/wasm/shared-memory.yaml b/lld/test/wasm/shared-memory.yaml
index 1c238a52357d..7d3be4c95ed5 100644
--- a/lld/test/wasm/shared-memory.yaml
+++ b/lld/test/wasm/shared-memory.yaml
@@ -27,6 +27,7 @@ Sections:
         Field:           __indirect_function_table
         Kind:            TABLE
         Table:
+          Index:           0
           ElemType:        FUNCREF
           Limits:
             Initial:         0x00000000

diff  --git a/lld/test/wasm/shared.ll b/lld/test/wasm/shared.ll
index 59c1855bed56..95edd6515162 100644
--- a/lld/test/wasm/shared.ll
+++ b/lld/test/wasm/shared.ll
@@ -72,6 +72,7 @@ declare void @func_external()
 ; CHECK-NEXT:         Field:           __indirect_function_table
 ; CHECK-NEXT:         Kind:            TABLE
 ; CHECK-NEXT:         Table:
+; CHECK-NEXT:           Index:           0
 ; CHECK-NEXT:           ElemType:        FUNCREF
 ; CHECK-NEXT:           Limits:
 ; CHECK-NEXT:             Initial:         0x00000002

diff  --git a/lld/test/wasm/stack-pointer.ll b/lld/test/wasm/stack-pointer.ll
index 4be1bf9503d7..889d89e5ab41 100644
--- a/lld/test/wasm/stack-pointer.ll
+++ b/lld/test/wasm/stack-pointer.ll
@@ -32,7 +32,8 @@ entry:
 ; CHECK-NEXT:     FunctionTypes:   [ 0 ]
 ; CHECK-NEXT:   - Type:            TABLE
 ; CHECK-NEXT:     Tables:
-; CHECK-NEXT:       - ElemType:        FUNCREF
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         ElemType:        FUNCREF
 ; CHECK-NEXT:         Limits:
 ; CHECK-NEXT:           Flags:           [ HAS_MAX ]
 ; CHECK-NEXT:           Initial:         0x00000001

diff  --git a/lld/test/wasm/undefined-weak-call.ll b/lld/test/wasm/undefined-weak-call.ll
index bcb740209a95..a1491549ae7e 100644
--- a/lld/test/wasm/undefined-weak-call.ll
+++ b/lld/test/wasm/undefined-weak-call.ll
@@ -46,7 +46,8 @@ define i32 @callWeakFuncs() {
 ; CHECK-NEXT:     FunctionTypes:   [ 0, 0, 1, 2 ]
 ; CHECK-NEXT:   - Type:            TABLE
 ; CHECK-NEXT:     Tables:
-; CHECK-NEXT:       - ElemType:        FUNCREF
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         ElemType:        FUNCREF
 ; CHECK-NEXT:         Limits:
 ; CHECK-NEXT:           Flags:           [ HAS_MAX ]
 ; CHECK-NEXT:           Initial:         0x00000001

diff  --git a/lld/test/wasm/weak-alias-overide.ll b/lld/test/wasm/weak-alias-overide.ll
index c65d73a94405..391fb82c8ebc 100644
--- a/lld/test/wasm/weak-alias-overide.ll
+++ b/lld/test/wasm/weak-alias-overide.ll
@@ -36,7 +36,8 @@ entry:
 ; CHECK-NEXT:     FunctionTypes:   [ 0, 1, 0, 0, 0, 0, 0 ]
 ; CHECK-NEXT:   - Type:            TABLE
 ; CHECK-NEXT:     Tables:
-; CHECK-NEXT:       - ElemType:        FUNCREF
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         ElemType:        FUNCREF
 ; CHECK-NEXT:         Limits:
 ; CHECK-NEXT:           Flags:           [ HAS_MAX ]
 ; CHECK-NEXT:           Initial:         0x00000003

diff  --git a/lld/test/wasm/weak-alias.ll b/lld/test/wasm/weak-alias.ll
index 7c38fa185990..4ea72b110625 100644
--- a/lld/test/wasm/weak-alias.ll
+++ b/lld/test/wasm/weak-alias.ll
@@ -33,7 +33,8 @@ entry:
 ; CHECK-NEXT:     FunctionTypes:   [ 0, 1, 1, 1, 1, 1 ]
 ; CHECK-NEXT:   - Type:            TABLE
 ; CHECK-NEXT:     Tables:
-; CHECK-NEXT:       - ElemType:        FUNCREF
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         ElemType:        FUNCREF
 ; CHECK-NEXT:         Limits:
 ; CHECK-NEXT:           Flags:           [ HAS_MAX ]
 ; CHECK-NEXT:           Initial:         0x00000002
@@ -149,7 +150,8 @@ entry:
 ; RELOC-NEXT:     FunctionTypes:   [ 0, 1, 1, 1, 1, 1 ]
 ; RELOC-NEXT:   - Type:            TABLE
 ; RELOC-NEXT:     Tables:
-; RELOC-NEXT:       - ElemType:        FUNCREF
+; RELOC-NEXT:       - Index:           0
+; RELOC-NEXT:         ElemType:        FUNCREF
 ; RELOC-NEXT:         Limits:
 ; RELOC-NEXT:           Flags:           [ HAS_MAX ]
 ; RELOC-NEXT:           Initial:         0x00000002

diff  --git a/lld/test/wasm/weak-symbols.ll b/lld/test/wasm/weak-symbols.ll
index 43e9014ff322..58f15c591dd1 100644
--- a/lld/test/wasm/weak-symbols.ll
+++ b/lld/test/wasm/weak-symbols.ll
@@ -33,7 +33,8 @@ entry:
 ; CHECK-NEXT:     FunctionTypes:   [ 0, 1, 1, 1 ]
 ; CHECK-NEXT:   - Type:            TABLE
 ; CHECK-NEXT:     Tables:
-; CHECK-NEXT:       - ElemType:        FUNCREF
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         ElemType:        FUNCREF
 ; CHECK-NEXT:         Limits:
 ; CHECK-NEXT:           Flags:           [ HAS_MAX ]
 ; CHECK-NEXT:           Initial:         0x00000002

diff  --git a/lld/test/wasm/weak-undefined.ll b/lld/test/wasm/weak-undefined.ll
index 8023eb7d368b..769c531e0c61 100644
--- a/lld/test/wasm/weak-undefined.ll
+++ b/lld/test/wasm/weak-undefined.ll
@@ -44,7 +44,8 @@ entry:
 ; CHECK-NEXT:     FunctionTypes:   [ 0, 0, 1 ]
 ; CHECK-NEXT:   - Type:            TABLE
 ; CHECK-NEXT:     Tables:
-; CHECK-NEXT:       - ElemType:        FUNCREF
+; CHECK-NEXT:       - Index:           0
+; CHECK-NEXT:         ElemType:        FUNCREF
 ; CHECK-NEXT:         Limits:
 ; CHECK-NEXT:           Flags:           [ HAS_MAX ]
 ; CHECK-NEXT:           Initial:         0x00000001

diff  --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp
index ca4394e17212..3c702b71e34a 100644
--- a/lld/wasm/SyntheticSections.cpp
+++ b/lld/wasm/SyntheticSections.cpp
@@ -223,7 +223,7 @@ void TableSection::writeBody() {
     limits = {0, tableSize, 0};
   else
     limits = {WASM_LIMITS_FLAG_HAS_MAX, tableSize, tableSize};
-  writeTableType(os, WasmTable{WASM_TYPE_FUNCREF, limits});
+  writeTableType(os, WasmTable{0, WASM_TYPE_FUNCREF, limits});
 }
 
 void MemorySection::writeBody() {

diff  --git a/lld/wasm/WriterUtils.cpp b/lld/wasm/WriterUtils.cpp
index 9206d2fa68e9..cd221855a12b 100644
--- a/lld/wasm/WriterUtils.cpp
+++ b/lld/wasm/WriterUtils.cpp
@@ -32,6 +32,8 @@ std::string toString(ValType type) {
     return "v128";
   case ValType::EXNREF:
     return "exnref";
+  case ValType::FUNCREF:
+    return "funcref";
   case ValType::EXTERNREF:
     return "externref";
   }

diff  --git a/llvm/include/llvm/BinaryFormat/Wasm.h b/llvm/include/llvm/BinaryFormat/Wasm.h
index 1aca692e30a7..dd05bb02cea7 100644
--- a/llvm/include/llvm/BinaryFormat/Wasm.h
+++ b/llvm/include/llvm/BinaryFormat/Wasm.h
@@ -41,7 +41,7 @@ struct WasmDylinkInfo {
   uint32_t MemoryAlignment;  // P2 alignment of memory
   uint32_t TableSize;  // Table size in elements
   uint32_t TableAlignment;  // P2 alignment of table
-  std::vector<StringRef> Needed; // Shared library depenedencies
+  std::vector<StringRef> Needed; // Shared library dependencies
 };
 
 struct WasmProducerInfo {
@@ -68,6 +68,7 @@ struct WasmLimits {
 };
 
 struct WasmTable {
+  uint32_t Index;
   uint8_t ElemType;
   WasmLimits Limits;
 };
@@ -325,6 +326,7 @@ enum WasmSymbolType : unsigned {
   WASM_SYMBOL_TYPE_GLOBAL = 0x2,
   WASM_SYMBOL_TYPE_SECTION = 0x3,
   WASM_SYMBOL_TYPE_EVENT = 0x4,
+  WASM_SYMBOL_TYPE_TABLE = 0x5,
 };
 
 // Kinds of event attributes.
@@ -361,6 +363,7 @@ enum class ValType {
   F64 = WASM_TYPE_F64,
   V128 = WASM_TYPE_V128,
   EXNREF = WASM_TYPE_EXNREF,
+  FUNCREF = WASM_TYPE_FUNCREF,
   EXTERNREF = WASM_TYPE_EXTERNREF,
 };
 

diff  --git a/llvm/include/llvm/MC/MCSymbolWasm.h b/llvm/include/llvm/MC/MCSymbolWasm.h
index ffd8a7aad312..52ff9f933f92 100644
--- a/llvm/include/llvm/MC/MCSymbolWasm.h
+++ b/llvm/include/llvm/MC/MCSymbolWasm.h
@@ -25,6 +25,7 @@ class MCSymbolWasm : public MCSymbol {
   Optional<StringRef> ExportName;
   wasm::WasmSignature *Signature = nullptr;
   Optional<wasm::WasmGlobalType> GlobalType;
+  Optional<wasm::ValType> TableType;
   Optional<wasm::WasmEventType> EventType;
 
   /// An expression describing how to calculate the size of a symbol. If a
@@ -42,6 +43,7 @@ class MCSymbolWasm : public MCSymbol {
   bool isFunction() const { return Type == wasm::WASM_SYMBOL_TYPE_FUNCTION; }
   bool isData() const { return Type == wasm::WASM_SYMBOL_TYPE_DATA; }
   bool isGlobal() const { return Type == wasm::WASM_SYMBOL_TYPE_GLOBAL; }
+  bool isTable() const { return Type == wasm::WASM_SYMBOL_TYPE_TABLE; }
   bool isSection() const { return Type == wasm::WASM_SYMBOL_TYPE_SECTION; }
   bool isEvent() const { return Type == wasm::WASM_SYMBOL_TYPE_EVENT; }
   wasm::WasmSymbolType getType() const { return Type; }
@@ -109,6 +111,12 @@ class MCSymbolWasm : public MCSymbol {
   }
   void setGlobalType(wasm::WasmGlobalType GT) { GlobalType = GT; }
 
+  const wasm::ValType &getTableType() const {
+    assert(TableType.hasValue());
+    return TableType.getValue();
+  }
+  void setTableType(wasm::ValType TT) { TableType = TT; }
+
   const wasm::WasmEventType &getEventType() const {
     assert(EventType.hasValue());
     return EventType.getValue();

diff  --git a/llvm/include/llvm/Object/Wasm.h b/llvm/include/llvm/Object/Wasm.h
index 05a04af347fc..37e5a9ad6f70 100644
--- a/llvm/include/llvm/Object/Wasm.h
+++ b/llvm/include/llvm/Object/Wasm.h
@@ -35,14 +35,15 @@ namespace object {
 class WasmSymbol {
 public:
   WasmSymbol(const wasm::WasmSymbolInfo &Info,
-             const wasm::WasmGlobalType *GlobalType,
+             const wasm::WasmGlobalType *GlobalType, const uint8_t TableType,
              const wasm::WasmEventType *EventType,
              const wasm::WasmSignature *Signature)
-      : Info(Info), GlobalType(GlobalType), EventType(EventType),
-        Signature(Signature) {}
+      : Info(Info), GlobalType(GlobalType), TableType(TableType),
+        EventType(EventType), Signature(Signature) {}
 
   const wasm::WasmSymbolInfo &Info;
   const wasm::WasmGlobalType *GlobalType;
+  const uint8_t TableType;
   const wasm::WasmEventType *EventType;
   const wasm::WasmSignature *Signature;
 
@@ -149,6 +150,7 @@ class WasmObjectFile : public ObjectFile {
   ArrayRef<wasm::WasmFunctionName> debugNames() const { return DebugNames; }
   uint32_t startFunction() const { return StartFunction; }
   uint32_t getNumImportedGlobals() const { return NumImportedGlobals; }
+  uint32_t getNumImportedTables() const { return NumImportedTables; }
   uint32_t getNumImportedFunctions() const { return NumImportedFunctions; }
   uint32_t getNumImportedEvents() const { return NumImportedEvents; }
   uint32_t getNumSections() const { return Sections.size(); }
@@ -214,7 +216,9 @@ class WasmObjectFile : public ObjectFile {
   bool isValidFunctionIndex(uint32_t Index) const;
   bool isDefinedFunctionIndex(uint32_t Index) const;
   bool isValidGlobalIndex(uint32_t Index) const;
+  bool isValidTableIndex(uint32_t Index) const;
   bool isDefinedGlobalIndex(uint32_t Index) const;
+  bool isDefinedTableIndex(uint32_t Index) const;
   bool isValidEventIndex(uint32_t Index) const;
   bool isDefinedEventIndex(uint32_t Index) const;
   bool isValidFunctionSymbol(uint32_t Index) const;
@@ -285,6 +289,7 @@ class WasmObjectFile : public ObjectFile {
   bool HasMemory64 = false;
   wasm::WasmLinkingData LinkingData;
   uint32_t NumImportedGlobals = 0;
+  uint32_t NumImportedTables = 0;
   uint32_t NumImportedFunctions = 0;
   uint32_t NumImportedEvents = 0;
   uint32_t CodeSection = 0;

diff  --git a/llvm/include/llvm/ObjectYAML/WasmYAML.h b/llvm/include/llvm/ObjectYAML/WasmYAML.h
index bffb314e2d3b..c2f4d4af8231 100644
--- a/llvm/include/llvm/ObjectYAML/WasmYAML.h
+++ b/llvm/include/llvm/ObjectYAML/WasmYAML.h
@@ -53,6 +53,7 @@ struct Limits {
 struct Table {
   TableType ElemType;
   Limits TableLimits;
+  uint32_t Index;
 };
 
 struct Export {

diff  --git a/llvm/lib/BinaryFormat/Wasm.cpp b/llvm/lib/BinaryFormat/Wasm.cpp
index 88608168783b..19dce2bae47d 100644
--- a/llvm/lib/BinaryFormat/Wasm.cpp
+++ b/llvm/lib/BinaryFormat/Wasm.cpp
@@ -14,6 +14,8 @@ std::string llvm::wasm::toString(wasm::WasmSymbolType Type) {
     return "WASM_SYMBOL_TYPE_FUNCTION";
   case wasm::WASM_SYMBOL_TYPE_GLOBAL:
     return "WASM_SYMBOL_TYPE_GLOBAL";
+  case wasm::WASM_SYMBOL_TYPE_TABLE:
+    return "WASM_SYMBOL_TYPE_TABLE";
   case wasm::WASM_SYMBOL_TYPE_DATA:
     return "WASM_SYMBOL_TYPE_DATA";
   case wasm::WASM_SYMBOL_TYPE_SECTION:

diff  --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index a0e65aa6108a..4e673f2a49ea 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -194,8 +194,8 @@ class WasmObjectWriter : public MCObjectWriter {
   // Maps function symbols to the table element index space. Used
   // for TABLE_INDEX relocation types (i.e. address taken functions).
   DenseMap<const MCSymbolWasm *, uint32_t> TableIndices;
-  // Maps function/global symbols to the function/global/event/section index
-  // space.
+  // Maps function/global/table symbols to the
+  // function/global/table/event/section index space.
   DenseMap<const MCSymbolWasm *, uint32_t> WasmIndices;
   DenseMap<const MCSymbolWasm *, uint32_t> GOTIndices;
   // Maps data symbols to the Wasm segment and offset/size with the segment.
@@ -218,6 +218,9 @@ class WasmObjectWriter : public MCObjectWriter {
   SmallVector<WasmDataSegment, 4> DataSegments;
   unsigned NumFunctionImports = 0;
   unsigned NumGlobalImports = 0;
+  // NumTableImports is initialized to 1 to account for the hardcoded import of
+  // __indirect_function_table
+  unsigned NumTableImports = 1;
   unsigned NumEventImports = 0;
   uint32_t SectionCount = 0;
 
@@ -267,6 +270,7 @@ class WasmObjectWriter : public MCObjectWriter {
     SectionFunctions.clear();
     NumFunctionImports = 0;
     NumGlobalImports = 0;
+    NumTableImports = 1;
     MCObjectWriter::reset();
   }
 
@@ -316,6 +320,7 @@ class WasmObjectWriter : public MCObjectWriter {
   uint32_t writeDataSection(const MCAsmLayout &Layout);
   void writeEventSection(ArrayRef<wasm::WasmEventType> Events);
   void writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals);
+  void writeTableSection(ArrayRef<wasm::WasmTable> Tables);
   void writeRelocSection(uint32_t SectionIndex, StringRef Name,
                          std::vector<WasmRelocationEntry> &Relocations);
   void writeLinkingMetaDataSection(
@@ -827,6 +832,24 @@ void WasmObjectWriter::writeGlobalSection(ArrayRef<wasm::WasmGlobal> Globals) {
   endSection(Section);
 }
 
+void WasmObjectWriter::writeTableSection(ArrayRef<wasm::WasmTable> Tables) {
+  if (Tables.empty())
+    return;
+
+  SectionBookkeeping Section;
+  startSection(Section, wasm::WASM_SEC_TABLE);
+
+  encodeULEB128(Tables.size(), W->OS);
+  for (const wasm::WasmTable &Table : Tables) {
+    encodeULEB128(Table.ElemType, W->OS);
+    encodeULEB128(Table.Limits.Flags, W->OS);
+    encodeULEB128(Table.Limits.Initial, W->OS);
+    if (Table.Limits.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX)
+      encodeULEB128(Table.Limits.Maximum, W->OS);
+  }
+  endSection(Section);
+}
+
 void WasmObjectWriter::writeExportSection(ArrayRef<wasm::WasmExport> Exports) {
   if (Exports.empty())
     return;
@@ -1003,6 +1026,7 @@ void WasmObjectWriter::writeLinkingMetaDataSection(
       case wasm::WASM_SYMBOL_TYPE_FUNCTION:
       case wasm::WASM_SYMBOL_TYPE_GLOBAL:
       case wasm::WASM_SYMBOL_TYPE_EVENT:
+      case wasm::WASM_SYMBOL_TYPE_TABLE:
         encodeULEB128(Sym.ElementIndex, W->OS);
         if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
             (Sym.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0)
@@ -1292,6 +1316,7 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
   SmallVector<wasm::WasmExport, 4> Exports;
   SmallVector<wasm::WasmEventType, 1> Events;
   SmallVector<wasm::WasmGlobal, 1> Globals;
+  SmallVector<wasm::WasmTable, 1> Tables;
   SmallVector<wasm::WasmSymbolInfo, 4> SymbolInfos;
   SmallVector<std::pair<uint16_t, uint32_t>, 2> InitFuncs;
   std::map<StringRef, std::vector<WasmComdatEntry>> Comdats;
@@ -1494,6 +1519,20 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
         LLVM_DEBUG(dbgs() << "  -> global index: "
                           << WasmIndices.find(&WS)->second << "\n");
       }
+    } else if (WS.isTable()) {
+      if (WS.isDefined()) {
+        assert(WasmIndices.count(&WS) == 0);
+        wasm::WasmTable Table;
+        Table.ElemType = static_cast<uint8_t>(WS.getTableType());
+        Table.Index = NumTableImports + Tables.size();
+        // FIXME: Work on custom limits is ongoing
+        Table.Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0};
+
+        WasmIndices[&WS] = Table.Index;
+        Tables.push_back(Table);
+      }
+      LLVM_DEBUG(dbgs() << " -> table index: " << WasmIndices.find(&WS)->second
+                        << "\n");
     } else if (WS.isEvent()) {
       // C++ exception symbol (__cpp_exception)
       unsigned Index;
@@ -1715,10 +1754,10 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
     writeTypeSection(Signatures);
     writeImportSection(Imports, DataSize, TableElems.size());
     writeFunctionSection(Functions);
-    // Skip the "table" section; we import the table instead.
     // Skip the "memory" section; we import the memory instead.
     writeEventSection(Events);
     writeGlobalSection(Globals);
+    writeTableSection(Tables);
     writeExportSection(Exports);
     writeElemSection(TableElems);
     writeDataCountSection();

diff  --git a/llvm/lib/Object/WasmObjectFile.cpp b/llvm/lib/Object/WasmObjectFile.cpp
index 23418a358fa4..107a9efc9b33 100644
--- a/llvm/lib/Object/WasmObjectFile.cpp
+++ b/llvm/lib/Object/WasmObjectFile.cpp
@@ -218,6 +218,7 @@ static wasm::WasmTable readTable(WasmObjectFile::ReadContext &Ctx) {
   wasm::WasmTable Table;
   Table.ElemType = readUint8(Ctx);
   Table.Limits = readLimits(Ctx);
+  // The caller needs to set Table.Index field for Table
   return Table;
 }
 
@@ -499,6 +500,7 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
     wasm::WasmSymbolInfo Info;
     const wasm::WasmSignature *Signature = nullptr;
     const wasm::WasmGlobalType *GlobalType = nullptr;
+    uint8_t TableType = 0;
     const wasm::WasmEventType *EventType = nullptr;
 
     Info.Kind = readUint8(Ctx);
@@ -567,6 +569,27 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
       }
       break;
 
+    case wasm::WASM_SYMBOL_TYPE_TABLE:
+      Info.ElementIndex = readVaruint32(Ctx);
+      if (!isValidTableIndex(Info.ElementIndex) ||
+          IsDefined != isDefinedTableIndex(Info.ElementIndex))
+        return make_error<GenericBinaryError>("invalid table symbol index",
+                                              object_error::parse_failed);
+      if (!IsDefined && (Info.Flags & wasm::WASM_SYMBOL_BINDING_MASK) ==
+                            wasm::WASM_SYMBOL_BINDING_WEAK)
+        return make_error<GenericBinaryError>("undefined weak table symbol",
+                                              object_error::parse_failed);
+      if (IsDefined) {
+        Info.Name = readString(Ctx);
+        unsigned TableIndex = Info.ElementIndex - NumImportedTables;
+        wasm::WasmTable &Table = Tables[TableIndex];
+        TableType = Table.ElemType;
+      } else {
+        return make_error<GenericBinaryError>("undefined table symbol",
+                                              object_error::parse_failed);
+      }
+      break;
+
     case wasm::WASM_SYMBOL_TYPE_DATA:
       Info.Name = readString(Ctx);
       if (IsDefined) {
@@ -644,8 +667,8 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) {
                                                 Twine(Info.Name),
                                             object_error::parse_failed);
     LinkingData.SymbolTable.emplace_back(Info);
-    Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, EventType,
-                         Signature);
+    Symbols.emplace_back(LinkingData.SymbolTable.back(), GlobalType, TableType,
+                         EventType, Signature);
     LLVM_DEBUG(dbgs() << "Adding symbol: " << Symbols.back() << "\n");
   }
 
@@ -963,12 +986,17 @@ Error WasmObjectFile::parseImportSection(ReadContext &Ctx) {
       if (Im.Memory.Flags & wasm::WASM_LIMITS_FLAG_IS_64)
         HasMemory64 = true;
       break;
-    case wasm::WASM_EXTERNAL_TABLE:
+    case wasm::WASM_EXTERNAL_TABLE: {
       Im.Table = readTable(Ctx);
-      if (Im.Table.ElemType != wasm::WASM_TYPE_FUNCREF)
+      Im.Table.Index = NumImportedTables + Tables.size();
+      NumImportedTables++;
+      auto ElemType = Im.Table.ElemType;
+      if (ElemType != wasm::WASM_TYPE_FUNCREF &&
+          ElemType != wasm::WASM_TYPE_EXTERNREF)
         return make_error<GenericBinaryError>("Invalid table element type",
                                               object_error::parse_failed);
       break;
+    }
     case wasm::WASM_EXTERNAL_EVENT:
       NumImportedEvents++;
       Im.Event.Attribute = readVarint32(Ctx);
@@ -1008,8 +1036,12 @@ Error WasmObjectFile::parseTableSection(ReadContext &Ctx) {
   uint32_t Count = readVaruint32(Ctx);
   Tables.reserve(Count);
   while (Count--) {
-    Tables.push_back(readTable(Ctx));
-    if (Tables.back().ElemType != wasm::WASM_TYPE_FUNCREF) {
+    wasm::WasmTable T = readTable(Ctx);
+    T.Index = NumImportedTables + Tables.size();
+    Tables.push_back(T);
+    auto ElemType = Tables.back().ElemType;
+    if (ElemType != wasm::WASM_TYPE_FUNCREF &&
+        ElemType != wasm::WASM_TYPE_EXTERNREF) {
       return make_error<GenericBinaryError>("Invalid table element type",
                                             object_error::parse_failed);
     }
@@ -1125,10 +1157,18 @@ bool WasmObjectFile::isValidGlobalIndex(uint32_t Index) const {
   return Index < NumImportedGlobals + Globals.size();
 }
 
+bool WasmObjectFile::isValidTableIndex(uint32_t Index) const {
+  return Index < NumImportedTables + Tables.size();
+}
+
 bool WasmObjectFile::isDefinedGlobalIndex(uint32_t Index) const {
   return Index >= NumImportedGlobals && isValidGlobalIndex(Index);
 }
 
+bool WasmObjectFile::isDefinedTableIndex(uint32_t Index) const {
+  return Index >= NumImportedTables && isValidTableIndex(Index);
+}
+
 bool WasmObjectFile::isValidEventIndex(uint32_t Index) const {
   return Index < NumImportedEvents + Events.size();
 }

diff  --git a/llvm/lib/ObjectYAML/WasmEmitter.cpp b/llvm/lib/ObjectYAML/WasmEmitter.cpp
index cbb062d87ae6..81e24bfdaf84 100644
--- a/llvm/lib/ObjectYAML/WasmEmitter.cpp
+++ b/llvm/lib/ObjectYAML/WasmEmitter.cpp
@@ -60,6 +60,7 @@ class WasmWriter {
   WasmYAML::Object &Obj;
   uint32_t NumImportedFunctions = 0;
   uint32_t NumImportedGlobals = 0;
+  uint32_t NumImportedTables = 0;
   uint32_t NumImportedEvents = 0;
 
   bool HasError = false;
@@ -187,6 +188,7 @@ void WasmWriter::writeSectionContent(raw_ostream &OS,
       switch (Info.Kind) {
       case wasm::WASM_SYMBOL_TYPE_FUNCTION:
       case wasm::WASM_SYMBOL_TYPE_GLOBAL:
+      case wasm::WASM_SYMBOL_TYPE_TABLE:
       case wasm::WASM_SYMBOL_TYPE_EVENT:
         encodeULEB128(Info.ElementIndex, SubSection.getStream());
         if ((Info.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 ||
@@ -360,7 +362,7 @@ void WasmWriter::writeSectionContent(raw_ostream &OS,
     case wasm::WASM_EXTERNAL_EVENT:
       writeUint32(OS, Import.EventImport.Attribute);
       writeUint32(OS, Import.EventImport.SigIndex);
-      NumImportedGlobals++;
+      NumImportedEvents++;
       break;
     case wasm::WASM_EXTERNAL_MEMORY:
       writeLimits(Import.Memory, OS);
@@ -368,6 +370,7 @@ void WasmWriter::writeSectionContent(raw_ostream &OS,
     case wasm::WASM_EXTERNAL_TABLE:
       writeUint8(OS, Import.TableImport.ElemType);
       writeLimits(Import.TableImport.TableLimits, OS);
+      NumImportedTables++;
       break;
     default:
       reportError("unknown import type: " +Twine(Import.Kind));
@@ -401,7 +404,13 @@ void WasmWriter::writeSectionContent(raw_ostream &OS,
 void WasmWriter::writeSectionContent(raw_ostream &OS,
                                      WasmYAML::TableSection &Section) {
   encodeULEB128(Section.Tables.size(), OS);
+  uint32_t ExpectedIndex = NumImportedTables;
   for (auto &Table : Section.Tables) {
+    if (Table.Index != ExpectedIndex) {
+      reportError("unexpected table index: " + Twine(Table.Index));
+      return;
+    }
+    ++ExpectedIndex;
     writeUint8(OS, Table.ElemType);
     writeLimits(Table.TableLimits, OS);
   }

diff  --git a/llvm/lib/ObjectYAML/WasmYAML.cpp b/llvm/lib/ObjectYAML/WasmYAML.cpp
index d1aa1181a344..f99ff69812aa 100644
--- a/llvm/lib/ObjectYAML/WasmYAML.cpp
+++ b/llvm/lib/ObjectYAML/WasmYAML.cpp
@@ -300,6 +300,7 @@ void MappingTraits<WasmYAML::Signature>::mapping(
 }
 
 void MappingTraits<WasmYAML::Table>::mapping(IO &IO, WasmYAML::Table &Table) {
+  IO.mapRequired("Index", Table.Index);
   IO.mapRequired("ElemType", Table.ElemType);
   IO.mapRequired("Limits", Table.TableLimits);
 }
@@ -496,6 +497,8 @@ void MappingTraits<WasmYAML::SymbolInfo>::mapping(IO &IO,
     IO.mapRequired("Function", Info.ElementIndex);
   } else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_GLOBAL) {
     IO.mapRequired("Global", Info.ElementIndex);
+  } else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_TABLE) {
+    IO.mapRequired("Table", Info.ElementIndex);
   } else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_EVENT) {
     IO.mapRequired("Event", Info.ElementIndex);
   } else if (Info.Kind == wasm::WASM_SYMBOL_TYPE_DATA) {
@@ -551,6 +554,7 @@ void ScalarEnumerationTraits<WasmYAML::SymbolKind>::enumeration(
   ECase(FUNCTION);
   ECase(DATA);
   ECase(GLOBAL);
+  ECase(TABLE);
   ECase(SECTION);
   ECase(EVENT);
 #undef ECase
@@ -599,6 +603,7 @@ void ScalarEnumerationTraits<WasmYAML::TableType>::enumeration(
     IO &IO, WasmYAML::TableType &Type) {
 #define ECase(X) IO.enumCase(Type, #X, wasm::WASM_TYPE_##X);
   ECase(FUNCREF);
+  ECase(EXTERNREF);
 #undef ECase
 }
 

diff  --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
index 0e6c95d5dd3b..14908a630a0d 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -324,6 +324,8 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
       return wasm::ValType::V128;
     if (Type == "exnref")
       return wasm::ValType::EXNREF;
+    if (Type == "funcref")
+      return wasm::ValType::FUNCREF;
     if (Type == "externref")
       return wasm::ValType::EXTERNREF;
     return Optional<wasm::ValType>();
@@ -712,6 +714,29 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
       return expect(AsmToken::EndOfStatement, "EOL");
     }
 
+    if (DirectiveID.getString() == ".tabletype") {
+      auto SymName = expectIdent();
+      if (SymName.empty())
+        return true;
+      if (expect(AsmToken::Comma, ","))
+        return true;
+      auto TypeTok = Lexer.getTok();
+      auto TypeName = expectIdent();
+      if (TypeName.empty())
+        return true;
+      auto Type = parseType(TypeName);
+      if (!Type)
+        return error("Unknown type in .tabletype directive: ", TypeTok);
+
+      // Now that we have the name and table type, we can actually create the
+      // symbol
+      auto WasmSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol(SymName));
+      WasmSym->setType(wasm::WASM_SYMBOL_TYPE_TABLE);
+      WasmSym->setTableType(Type.getValue());
+      TOut.emitTableType(WasmSym);
+      return expect(AsmToken::EndOfStatement, "EOL");
+    }
+
     if (DirectiveID.getString() == ".functype") {
       // This code has to send things to the streamer similar to
       // WebAssemblyAsmPrinter::EmitFunctionBodyStart.

diff  --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
index f60b5fcd14ec..86c894eb2076 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
@@ -318,6 +318,8 @@ const char *WebAssembly::anyTypeToString(unsigned Ty) {
     return "v128";
   case wasm::WASM_TYPE_FUNCREF:
     return "funcref";
+  case wasm::WASM_TYPE_EXTERNREF:
+    return "externref";
   case wasm::WASM_TYPE_FUNC:
     return "func";
   case wasm::WASM_TYPE_EXNREF:

diff  --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp
index d2b2de0dca1f..652d7a00a63c 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp
@@ -77,6 +77,13 @@ void WebAssemblyTargetAsmStreamer::emitGlobalType(const MCSymbolWasm *Sym) {
   OS << '\n';
 }
 
+void WebAssemblyTargetAsmStreamer::emitTableType(const MCSymbolWasm *Sym) {
+  assert(Sym->isTable());
+  OS << "\t.tabletype\t" << Sym->getName() << ", "
+     << WebAssembly::typeToString(Sym->getTableType());
+  OS << '\n';
+}
+
 void WebAssemblyTargetAsmStreamer::emitEventType(const MCSymbolWasm *Sym) {
   assert(Sym->isEvent());
   OS << "\t.eventtype\t" << Sym->getName() << " ";

diff  --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h
index d6fba05c9986..75c9fb4e289d 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h
@@ -39,6 +39,8 @@ class WebAssemblyTargetStreamer : public MCTargetStreamer {
   virtual void emitIndIdx(const MCExpr *Value) = 0;
   /// .globaltype
   virtual void emitGlobalType(const MCSymbolWasm *Sym) = 0;
+  /// .tabletype
+  virtual void emitTableType(const MCSymbolWasm *Sym) = 0;
   /// .eventtype
   virtual void emitEventType(const MCSymbolWasm *Sym) = 0;
   /// .import_module
@@ -67,6 +69,7 @@ class WebAssemblyTargetAsmStreamer final : public WebAssemblyTargetStreamer {
   void emitFunctionType(const MCSymbolWasm *Sym) override;
   void emitIndIdx(const MCExpr *Value) override;
   void emitGlobalType(const MCSymbolWasm *Sym) override;
+  void emitTableType(const MCSymbolWasm *Sym) override;
   void emitEventType(const MCSymbolWasm *Sym) override;
   void emitImportModule(const MCSymbolWasm *Sym, StringRef ImportModule) override;
   void emitImportName(const MCSymbolWasm *Sym, StringRef ImportName) override;
@@ -83,6 +86,7 @@ class WebAssemblyTargetWasmStreamer final : public WebAssemblyTargetStreamer {
   void emitFunctionType(const MCSymbolWasm *Sym) override {}
   void emitIndIdx(const MCExpr *Value) override;
   void emitGlobalType(const MCSymbolWasm *Sym) override {}
+  void emitTableType(const MCSymbolWasm *Sym) override {}
   void emitEventType(const MCSymbolWasm *Sym) override {}
   void emitImportModule(const MCSymbolWasm *Sym,
                         StringRef ImportModule) override {}
@@ -103,6 +107,7 @@ class WebAssemblyTargetNullStreamer final : public WebAssemblyTargetStreamer {
   void emitFunctionType(const MCSymbolWasm *) override {}
   void emitIndIdx(const MCExpr *) override {}
   void emitGlobalType(const MCSymbolWasm *) override {}
+  void emitTableType(const MCSymbolWasm *) override {}
   void emitEventType(const MCSymbolWasm *) override {}
   void emitImportModule(const MCSymbolWasm *, StringRef) override {}
   void emitImportName(const MCSymbolWasm *, StringRef) override {}

diff  --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index ad0bbd110077..b233bc2bdc19 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -121,6 +121,8 @@ static char getInvokeSig(wasm::ValType VT) {
     return 'V';
   case wasm::ValType::EXNREF:
     return 'E';
+  case wasm::ValType::FUNCREF:
+    return 'F';
   case wasm::ValType::EXTERNREF:
     return 'X';
   }

diff  --git a/llvm/test/MC/WebAssembly/assembler-binary.ll b/llvm/test/MC/WebAssembly/assembler-binary.ll
index 35fa4111117b..ed7b5f2cc875 100644
--- a/llvm/test/MC/WebAssembly/assembler-binary.ll
+++ b/llvm/test/MC/WebAssembly/assembler-binary.ll
@@ -55,6 +55,7 @@ entry:
 ; CHECK-NEXT:         Field:           __indirect_function_table
 ; CHECK-NEXT:         Kind:            TABLE
 ; CHECK-NEXT:         Table:
+; CHECK-NEXT:           Index:           0
 ; CHECK-NEXT:           ElemType:        FUNCREF
 ; CHECK-NEXT:           Limits:
 ; CHECK-NEXT:             Initial:         0x00000000

diff  --git a/llvm/test/MC/WebAssembly/basic-assembly.s b/llvm/test/MC/WebAssembly/basic-assembly.s
index 151d261ef4cf..73c7182cf3ca 100644
--- a/llvm/test/MC/WebAssembly/basic-assembly.s
+++ b/llvm/test/MC/WebAssembly/basic-assembly.s
@@ -121,6 +121,13 @@ test0:
     .ident      "clang version 9.0.0 (trunk 364502) (llvm/trunk 364571)"
     .globaltype __stack_pointer, i32
 
+.tabletype empty_eref_table, externref
+empty_eref_table:       
+
+.tabletype empty_fref_table, funcref
+empty_fref_table:       
+
+        
 # CHECK:           .text
 # CHECK-LABEL: empty_func:
 # CHECK-NEXT:      .functype	empty_func () -> ()
@@ -228,3 +235,9 @@ test0:
 # CHECK-NEXT:      .int32      test0
 
 # CHECK:           .globaltype __stack_pointer, i32
+
+# CHECK:           .tabletype empty_eref_table, externref
+# CHECK-NEXT: empty_eref_table:
+        
+# CHECK:           .tabletype empty_fref_table, funcref
+# CHECK-NEXT: empty_fref_table:

diff  --git a/llvm/test/MC/WebAssembly/comdat.ll b/llvm/test/MC/WebAssembly/comdat.ll
index e50f5bf1cc96..fd87b5ce797a 100644
--- a/llvm/test/MC/WebAssembly/comdat.ll
+++ b/llvm/test/MC/WebAssembly/comdat.ll
@@ -42,6 +42,7 @@ define linkonce_odr i32 @sharedFn() #1 comdat($sharedComdat) {
 ; CHECK-NEXT:         Field:           __indirect_function_table
 ; CHECK-NEXT:         Kind:            TABLE
 ; CHECK-NEXT:         Table:
+; CHECK-NEXT:           Index:           0
 ; CHECK-NEXT:           ElemType:        FUNCREF
 ; CHECK-NEXT:           Limits:
 ; CHECK-NEXT:             Initial:         0x00000000

diff  --git a/llvm/test/MC/WebAssembly/data-section.s b/llvm/test/MC/WebAssembly/data-section.s
index 52e60f6d4a7d..e2dab163bea0 100644
--- a/llvm/test/MC/WebAssembly/data-section.s
+++ b/llvm/test/MC/WebAssembly/data-section.s
@@ -49,6 +49,7 @@ test0:
 # BIN-NEXT:         Field:           __indirect_function_table
 # BIN-NEXT:         Kind:            TABLE
 # BIN-NEXT:         Table:
+# BIN-NEXT:           Index:           0
 # BIN-NEXT:           ElemType:        FUNCREF
 # BIN-NEXT:           Limits:
 # BIN-NEXT:             Initial:         0x00000000

diff  --git a/llvm/test/MC/WebAssembly/global-ctor-dtor.ll b/llvm/test/MC/WebAssembly/global-ctor-dtor.ll
index f506794467c2..750a1d8768a5 100644
--- a/llvm/test/MC/WebAssembly/global-ctor-dtor.ll
+++ b/llvm/test/MC/WebAssembly/global-ctor-dtor.ll
@@ -30,6 +30,7 @@ declare void @func3()
 ; CHECK-NEXT:         Field:           __indirect_function_table
 ; CHECK-NEXT:         Kind:            TABLE
 ; CHECK-NEXT:         Table:
+; CHECK-NEXT:           Index:           0
 ; CHECK-NEXT:           ElemType:        FUNCREF
 ; CHECK-NEXT:           Limits:
 ; CHECK-NEXT:             Initial:         0x00000002

diff  --git a/llvm/test/MC/WebAssembly/reloc-pic.s b/llvm/test/MC/WebAssembly/reloc-pic.s
index 4732b7ee7314..e19ba0a681cd 100644
--- a/llvm/test/MC/WebAssembly/reloc-pic.s
+++ b/llvm/test/MC/WebAssembly/reloc-pic.s
@@ -66,6 +66,7 @@ hidden_func:
 # CHECK-NEXT:         Field:           __indirect_function_table
 # CHECK-NEXT:         Kind:            TABLE
 # CHECK-NEXT:         Table:
+# CHECK-NEXT:           Index:           0
 # CHECK-NEXT:           ElemType:        FUNCREF
 # CHECK-NEXT:           Limits:
 # CHECK-NEXT:             Initial:         0x00000001

diff  --git a/llvm/test/MC/WebAssembly/tables.s b/llvm/test/MC/WebAssembly/tables.s
new file mode 100644
index 000000000000..1c6837d6f69a
--- /dev/null
+++ b/llvm/test/MC/WebAssembly/tables.s
@@ -0,0 +1,42 @@
+# RUN: llvm-mc -triple=wasm32-unknown-unknown < %s | FileCheck %s
+# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj < %s | obj2yaml | FileCheck -check-prefix=BIN %s
+
+# Test creating several empty tables
+
+.tabletype foo, externref        
+foo:
+
+bar:
+.tabletype bar, funcref
+
+# CHECK: .tabletype foo, externref
+# CHECK: foo:
+
+#      CHECK: bar:
+# CHECK-NEXT: .tabletype bar, funcref
+
+#      BIN:  - Type:            TABLE
+# BIN-NEXT:    Tables:
+# BIN-NEXT:      - Index:           1
+# BIN-NEXT:        ElemType:        EXTERNREF
+# BIN-NEXT:        Limits:
+# BIN-NEXT:          Initial:         0x00000000
+# BIN-NEXT:      - Index:           2
+# BIN-NEXT:        ElemType:        FUNCREF
+# BIN-NEXT:        Limits:
+# BIN-NEXT:          Initial:         0x00000000
+
+#      BIN:  - Type:            CUSTOM
+# BIN-NEXT:    Name:            linking
+# BIN-NEXT:    Version:         2
+# BIN-NEXT:    SymbolTable:
+# BIN-NEXT:      - Index:           0
+# BIN-NEXT:        Kind:            TABLE
+# BIN-NEXT:        Name:            foo
+# BIN-NEXT:        Flags:           [ BINDING_LOCAL ]
+# BIN-NEXT:        Table:           1
+# BIN-NEXT:      - Index:           1
+# BIN-NEXT:        Kind:            TABLE
+# BIN-NEXT:        Name:            bar
+# BIN-NEXT:        Flags:           [ BINDING_LOCAL ]
+# BIN-NEXT:        Table:           2

diff  --git a/llvm/test/MC/WebAssembly/type-index.s b/llvm/test/MC/WebAssembly/type-index.s
index 9c77434589f5..04e124bc180a 100644
--- a/llvm/test/MC/WebAssembly/type-index.s
+++ b/llvm/test/MC/WebAssembly/type-index.s
@@ -42,6 +42,7 @@ test0:
 # BIN-NEXT:         Field:           __indirect_function_table
 # BIN-NEXT:         Kind:            TABLE
 # BIN-NEXT:         Table:
+# BIN-NEXT:           Index:           0
 # BIN-NEXT:           ElemType:        FUNCREF
 # BIN-NEXT:           Limits:
 # BIN-NEXT:             Initial:         0x00000000

diff  --git a/llvm/test/MC/WebAssembly/wasm64.s b/llvm/test/MC/WebAssembly/wasm64.s
index b89718816a9f..487ca2b76e89 100644
--- a/llvm/test/MC/WebAssembly/wasm64.s
+++ b/llvm/test/MC/WebAssembly/wasm64.s
@@ -153,6 +153,7 @@ test:
 # BIN-NEXT:         Field:           __indirect_function_table
 # BIN-NEXT:         Kind:            TABLE
 # BIN-NEXT:         Table:
+# BIN-NEXT:           Index:           0
 # BIN-NEXT:           ElemType:        FUNCREF
 # BIN-NEXT:           Limits:
 # BIN-NEXT:             Initial:         0x00000000

diff  --git a/llvm/test/MC/WebAssembly/weak-alias.s b/llvm/test/MC/WebAssembly/weak-alias.s
index 89be4dae0a63..e16116201bf0 100644
--- a/llvm/test/MC/WebAssembly/weak-alias.s
+++ b/llvm/test/MC/WebAssembly/weak-alias.s
@@ -92,6 +92,7 @@ alias_address:
 # CHECK-NEXT:         Field:           __indirect_function_table
 # CHECK-NEXT:         Kind:            TABLE
 # CHECK-NEXT:         Table:
+# CHECK-NEXT:           Index:           0
 # CHECK-NEXT:           ElemType:        FUNCREF
 # CHECK-NEXT:           Limits:
 # CHECK-NEXT:             Initial:         0x00000001

diff  --git a/llvm/test/Object/wasm-relocs-and-producers.yaml b/llvm/test/Object/wasm-relocs-and-producers.yaml
index 2bdc12e4619d..9bbb0a1d084d 100644
--- a/llvm/test/Object/wasm-relocs-and-producers.yaml
+++ b/llvm/test/Object/wasm-relocs-and-producers.yaml
@@ -29,6 +29,7 @@ Sections:
         Field:           __indirect_function_table
         Kind:            TABLE
         Table:
+          Index:           0
           ElemType:        FUNCREF
           Limits:
             Initial:         0x00000000

diff  --git a/llvm/test/ObjectYAML/wasm/elem_section.yaml b/llvm/test/ObjectYAML/wasm/elem_section.yaml
index 73989dda878c..f3f81ba01754 100644
--- a/llvm/test/ObjectYAML/wasm/elem_section.yaml
+++ b/llvm/test/ObjectYAML/wasm/elem_section.yaml
@@ -5,7 +5,8 @@ FileHeader:
 Sections:
   - Type:            TABLE
     Tables:         
-      - ElemType:          FUNCREF
+      - Index:             0
+        ElemType:          FUNCREF
         Limits:
           Flags:           [ HAS_MAX ]
           Initial:         0x00000010

diff  --git a/llvm/test/ObjectYAML/wasm/import_section.yaml b/llvm/test/ObjectYAML/wasm/import_section.yaml
index 2df2f3928ecb..58dae6da5f33 100644
--- a/llvm/test/ObjectYAML/wasm/import_section.yaml
+++ b/llvm/test/ObjectYAML/wasm/import_section.yaml
@@ -32,6 +32,7 @@ Sections:
         Field:           imported_table
         Kind:            TABLE
         Table:
+          Index:         0
           ElemType:      FUNCREF
           Limits:
             Flags:           [ HAS_MAX ]

diff  --git a/llvm/test/ObjectYAML/wasm/table_section.yaml b/llvm/test/ObjectYAML/wasm/table_section.yaml
index 90e73fdd40bc..3ce425bbbea3 100644
--- a/llvm/test/ObjectYAML/wasm/table_section.yaml
+++ b/llvm/test/ObjectYAML/wasm/table_section.yaml
@@ -5,7 +5,8 @@ FileHeader:
 Sections:
   - Type:            TABLE
     Tables:         
-      - ElemType:        FUNCREF
+      - Index:           0
+        ElemType:        FUNCREF
         Limits:
           Flags:           [ HAS_MAX ]
           Initial:         0x00000010
@@ -17,7 +18,8 @@ Sections:
 # CHECK: Sections:
 # CHECK:  - Type:            TABLE
 # CHECK:    Tables:         
-# CHECK:      - ElemType:        FUNCREF
+# CHECK:      - Index:           0
+# CHECK:        ElemType:        FUNCREF
 # CHECK:        Limits:
 # CHECK:          Flags:           [ HAS_MAX ]
 # CHECK:          Initial:         0x00000010

diff  --git a/llvm/test/tools/llvm-readobj/wasm/wasm-imports.test b/llvm/test/tools/llvm-readobj/wasm/wasm-imports.test
index 35639d11ee97..dd93c14fbebe 100644
--- a/llvm/test/tools/llvm-readobj/wasm/wasm-imports.test
+++ b/llvm/test/tools/llvm-readobj/wasm/wasm-imports.test
@@ -26,6 +26,7 @@ Sections:
         Field:           __indirect_function_table
         Kind:            TABLE
         Table:           
+          Index:           0
           ElemType:        FUNCREF
           Limits:          
             Initial:         0x00000000

diff  --git a/llvm/tools/obj2yaml/wasm2yaml.cpp b/llvm/tools/obj2yaml/wasm2yaml.cpp
index 689c231b0dd7..3a40829b34aa 100644
--- a/llvm/tools/obj2yaml/wasm2yaml.cpp
+++ b/llvm/tools/obj2yaml/wasm2yaml.cpp
@@ -37,6 +37,7 @@ static WasmYAML::Table makeTable(const wasm::WasmTable &Table) {
   T.TableLimits.Flags = Table.Limits.Flags;
   T.TableLimits.Initial = Table.Limits.Initial;
   T.TableLimits.Maximum = Table.Limits.Maximum;
+  T.Index = Table.Index;
   return T;
 }
 
@@ -116,6 +117,7 @@ WasmDumper::dumpCustomSection(const WasmSection &WasmSec) {
         break;
       case wasm::WASM_SYMBOL_TYPE_FUNCTION:
       case wasm::WASM_SYMBOL_TYPE_GLOBAL:
+      case wasm::WASM_SYMBOL_TYPE_TABLE:
       case wasm::WASM_SYMBOL_TYPE_EVENT:
         Info.ElementIndex = Symbol.ElementIndex;
         break;


        


More information about the llvm-commits mailing list