[llvm] c9801db - [WebAssembly][MC] Record limit constraints for table sizes

Andy Wingo via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 24 01:47:41 PDT 2021


Author: Andy Wingo
Date: 2021-03-24T09:44:22+01:00
New Revision: c9801db2eb4b273ccf4b793784911b4465366f68

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

LOG: [WebAssembly][MC] Record limit constraints for table sizes

This commit adds a full WasmTableType to MCSymbolWasm, differing from
the current situation (just an ElemType) in that it additionally records
a WasmLimits.

We add support for specifying the limits in .S files also, via the
following syntax variations:

  .tabletype SYM, ELEMTYPE
  .tabletype SYM, ELEMTYPE, MINSIZE
  .tabletype SYM, ELEMTYPE, MINSIZE, MAXSIZE

Depends on D99186.

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

Added: 
    

Modified: 
    llvm/include/llvm/MC/MCSymbolWasm.h
    llvm/lib/MC/WasmObjectWriter.cpp
    llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
    llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp
    llvm/test/MC/WebAssembly/tables.s

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/MC/MCSymbolWasm.h b/llvm/include/llvm/MC/MCSymbolWasm.h
index 49d57919f6f3..14b3a5d8e941 100644
--- a/llvm/include/llvm/MC/MCSymbolWasm.h
+++ b/llvm/include/llvm/MC/MCSymbolWasm.h
@@ -26,7 +26,7 @@ class MCSymbolWasm : public MCSymbol {
   Optional<StringRef> ExportName;
   wasm::WasmSignature *Signature = nullptr;
   Optional<wasm::WasmGlobalType> GlobalType;
-  Optional<wasm::ValType> TableType;
+  Optional<wasm::WasmTableType> TableType;
   Optional<wasm::WasmEventType> EventType;
 
   /// An expression describing how to calculate the size of a symbol. If a
@@ -108,7 +108,7 @@ class MCSymbolWasm : public MCSymbol {
 
   bool isFunctionTable() const {
     return isTable() && hasTableType() &&
-           getTableType() == wasm::ValType::FUNCREF;
+           getTableType().ElemType == wasm::WASM_TYPE_FUNCREF;
   }
   void setFunctionTable() {
     setType(wasm::WASM_SYMBOL_TYPE_TABLE);
@@ -131,11 +131,17 @@ class MCSymbolWasm : public MCSymbol {
   void setGlobalType(wasm::WasmGlobalType GT) { GlobalType = GT; }
 
   bool hasTableType() const { return TableType.hasValue(); }
-  wasm::ValType getTableType() const {
+  const wasm::WasmTableType &getTableType() const {
     assert(hasTableType());
     return TableType.getValue();
   }
-  void setTableType(wasm::ValType TT) { TableType = TT; }
+  void setTableType(wasm::WasmTableType TT) { TableType = TT; }
+  void setTableType(wasm::ValType VT) {
+    // Declare a table with element type VT and no limits (min size 0, no max
+    // size).
+    wasm::WasmLimits Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0};
+    setTableType({uint8_t(VT), Limits});
+  }
 
   const wasm::WasmEventType &getEventType() const {
     assert(EventType.hasValue());

diff  --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp
index 2a679ca687d4..0eda8b5a3234 100644
--- a/llvm/lib/MC/WasmObjectWriter.cpp
+++ b/llvm/lib/MC/WasmObjectWriter.cpp
@@ -1338,12 +1338,7 @@ void WasmObjectWriter::prepareImports(
         Import.Module = WS.getImportModule();
         Import.Field = WS.getImportName();
         Import.Kind = wasm::WASM_EXTERNAL_TABLE;
-        wasm::ValType ElemType = WS.getTableType();
-        Import.Table.ElemType = uint8_t(ElemType);
-        // FIXME: Extend table type to include limits? For now we don't specify
-        // a min or max which does not place any restrictions on the size of the
-        // imported table.
-        Import.Table.Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0};
+        Import.Table = WS.getTableType();
         Imports.push_back(Import);
         assert(WasmIndices.count(&WS) == 0);
         WasmIndices[&WS] = NumTableImports++;
@@ -1626,9 +1621,7 @@ uint64_t WasmObjectWriter::writeOneObject(MCAssembler &Asm,
         if (WS.isDefined()) {
           wasm::WasmTable Table;
           Table.Index = NumTableImports + Tables.size();
-          Table.Type.ElemType = static_cast<uint8_t>(WS.getTableType());
-          // FIXME: Work on custom limits is ongoing
-          Table.Type.Limits = {wasm::WASM_LIMITS_FLAG_NONE, 0, 0};
+          Table.Type = WS.getTableType();
           assert(WasmIndices.count(&WS) == 0);
           WasmIndices[&WS] = Table.Index;
           Tables.push_back(Table);

diff  --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
index c17067351154..d57c7ec17187 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -169,6 +169,11 @@ struct WebAssemblyOperand : public MCParsedAsmOperand {
   }
 };
 
+// Perhaps this should go somewhere common.
+static wasm::WasmLimits DefaultLimits() {
+  return {wasm::WASM_LIMITS_FLAG_NONE, 0, 0};
+}
+
 static MCSymbolWasm *GetOrCreateFunctionTableSymbol(MCContext &Ctx,
                                                     const StringRef &Name) {
   MCSymbolWasm *Sym = cast_or_null<MCSymbolWasm>(Ctx.lookupSymbol(Name));
@@ -487,6 +492,28 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
         WebAssemblyOperand::IntOp{static_cast<int64_t>(BT)}));
   }
 
+  bool parseLimits(wasm::WasmLimits *Limits) {
+    auto Tok = Lexer.getTok();
+    if (!Tok.is(AsmToken::Integer))
+      return error("Expected integer constant, instead got: ", Tok);
+    int64_t Val = Tok.getIntVal();
+    assert(Val >= 0);
+    Limits->Minimum = Val;
+    Parser.Lex();
+
+    if (isNext(AsmToken::Comma)) {
+      Limits->Flags |= wasm::WASM_LIMITS_FLAG_HAS_MAX;
+      auto Tok = Lexer.getTok();
+      if (!Tok.is(AsmToken::Integer))
+        return error("Expected integer constant, instead got: ", Tok);
+      int64_t Val = Tok.getIntVal();
+      assert(Val >= 0);
+      Limits->Maximum = Val;
+      Parser.Lex();
+    }
+    return false;
+  }
+
   bool parseFunctionTableOperand(std::unique_ptr<WebAssemblyOperand> *Op) {
     if (STI->checkFeatures("+reference-types")) {
       // If the reference-types feature is enabled, there is an explicit table
@@ -819,24 +846,31 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
     }
 
     if (DirectiveID.getString() == ".tabletype") {
+      // .tabletype SYM, ELEMTYPE[, MINSIZE[, MAXSIZE]]
       auto SymName = expectIdent();
       if (SymName.empty())
         return true;
       if (expect(AsmToken::Comma, ","))
         return true;
-      auto TypeTok = Lexer.getTok();
-      auto TypeName = expectIdent();
-      if (TypeName.empty())
+
+      auto ElemTypeTok = Lexer.getTok();
+      auto ElemTypeName = expectIdent();
+      if (ElemTypeName.empty())
+        return true;
+      Optional<wasm::ValType> ElemType = parseType(ElemTypeName);
+      if (!ElemType)
+        return error("Unknown type in .tabletype directive: ", ElemTypeTok);
+
+      wasm::WasmLimits Limits = DefaultLimits();
+      if (isNext(AsmToken::Comma) && parseLimits(&Limits))
         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());
+      wasm::WasmTableType Type = {uint8_t(ElemType.getValue()), Limits};
+      WasmSym->setTableType(Type);
       TOut.emitTableType(WasmSym);
       return expect(AsmToken::EndOfStatement, "EOL");
     }

diff  --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp
index 652d7a00a63c..3dd961efca42 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp
@@ -79,8 +79,15 @@ void WebAssemblyTargetAsmStreamer::emitGlobalType(const MCSymbolWasm *Sym) {
 
 void WebAssemblyTargetAsmStreamer::emitTableType(const MCSymbolWasm *Sym) {
   assert(Sym->isTable());
+  const wasm::WasmTableType &Type = Sym->getTableType();
   OS << "\t.tabletype\t" << Sym->getName() << ", "
-     << WebAssembly::typeToString(Sym->getTableType());
+     << WebAssembly::typeToString(static_cast<wasm::ValType>(Type.ElemType));
+  bool HasMaximum = Type.Limits.Flags & wasm::WASM_LIMITS_FLAG_HAS_MAX;
+  if (Type.Limits.Minimum != 0 || HasMaximum) {
+    OS << ", " << Type.Limits.Minimum;
+    if (HasMaximum)
+      OS << ", " << Type.Limits.Maximum;
+  }
   OS << '\n';
 }
 

diff  --git a/llvm/test/MC/WebAssembly/tables.s b/llvm/test/MC/WebAssembly/tables.s
index b1bf1a988646..a682a738445b 100644
--- a/llvm/test/MC/WebAssembly/tables.s
+++ b/llvm/test/MC/WebAssembly/tables.s
@@ -16,9 +16,9 @@ bar:
     .tabletype bar, funcref
 
 table1:
-    .tabletype table1, funcref
+    .tabletype table1, funcref, 42
 table2:
-    .tabletype table2, funcref
+    .tabletype table2, funcref, 42, 100
 
 # Table instructions
 
@@ -132,11 +132,13 @@ table_fill:
 # BIN-NEXT:      - Index:           2
 # BIN-NEXT:        ElemType:        FUNCREF
 # BIN-NEXT:        Limits:
-# BIN-NEXT:          Minimum:         0x0
+# BIN-NEXT:          Minimum:         0x2A
 # BIN-NEXT:      - Index:           3
 # BIN-NEXT:        ElemType:        FUNCREF
 # BIN-NEXT:        Limits:
-# BIN-NEXT:          Minimum:         0x0
+# BIN-NEXT:          Flags:           [ HAS_MAX ]
+# BIN-NEXT:          Minimum:         0x2A
+# BIN-NEXT:          Maximum:         0x64
 
 #      BIN:  - Type:            CODE
 # BIN-NEXT:    Relocations:


        


More information about the llvm-commits mailing list