[llvm] [WebAssembly] Support assembly parsing for new EH (PR #108668)

Heejin Ahn via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 16 20:12:16 PDT 2024


https://github.com/aheejin updated https://github.com/llvm/llvm-project/pull/108668

>From 04640a300dd5ef5587f593ff82feebc0d5c0fa4e Mon Sep 17 00:00:00 2001
From: Heejin Ahn <aheejin at gmail.com>
Date: Tue, 10 Sep 2024 04:22:35 +0000
Subject: [PATCH 01/10] [WebAssembly] Support assembly parsing for new EH

This adds assembly parsing support for the new EH (exnref) proposal.

`try_table` parsing is a little tricky because catch clause lists use
`()` and the multivalue block return types also use `()`. This handles
all combinations below:
- No return type (void) + no catch list
- No return type (void) + catch list
- Single return type + no catch list
- Single return type + catch list
- Multivalue return type + no catch list
- Multivalue return type + catch list

This does not include AsmTypeCheck support yet. That's the reason why
this adds a new test file and use `--no-type-check` in the command line.
After the type checker is added as a follow-up, I plan to merge this
file with the existing
https://github.com/llvm/llvm-project/blob/main/llvm/test/MC/WebAssembly/eh-assembly.s.
(Turning on `-mattr=+exception-handling` adds support for all
legacy and new EH instructions in the assembly. `-wasm-enable-exnref`
in `llc` only controls which instructions to generate and it doesn't
affect `llvm-mc` and assembly parsing.)
---
 .../AsmParser/WebAssemblyAsmParser.cpp        | 147 ++++++++++++++++--
 llvm/test/MC/WebAssembly/eh-assembly-new.s    | 146 +++++++++++++++++
 2 files changed, 283 insertions(+), 10 deletions(-)
 create mode 100644 llvm/test/MC/WebAssembly/eh-assembly-new.s

diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
index 5299e6ea06f0bd..03ea5b09c4fd4a 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -69,12 +69,23 @@ struct WebAssemblyOperand : public MCParsedAsmOperand {
     std::vector<unsigned> List;
   };
 
+  struct CaLOpElem {
+    int64_t Opcode;
+    const MCExpr *Tag;
+    int64_t Dest;
+  };
+
+  struct CaLOp {
+    std::vector<CaLOpElem> List;
+  };
+
   union {
     struct TokOp Tok;
     struct IntOp Int;
     struct FltOp Flt;
     struct SymOp Sym;
     struct BrLOp BrL;
+    struct CaLOp CaL;
   };
 
   WebAssemblyOperand(SMLoc Start, SMLoc End, TokOp T)
@@ -85,12 +96,16 @@ struct WebAssemblyOperand : public MCParsedAsmOperand {
       : Kind(Float), StartLoc(Start), EndLoc(End), Flt(F) {}
   WebAssemblyOperand(SMLoc Start, SMLoc End, SymOp S)
       : Kind(Symbol), StartLoc(Start), EndLoc(End), Sym(S) {}
-  WebAssemblyOperand(SMLoc Start, SMLoc End)
-      : Kind(BrList), StartLoc(Start), EndLoc(End), BrL() {}
+  WebAssemblyOperand(SMLoc Start, SMLoc End, BrLOp B)
+      : Kind(BrList), StartLoc(Start), EndLoc(End), BrL(B) {}
+  WebAssemblyOperand(SMLoc Start, SMLoc End, CaLOp C)
+      : Kind(CatchList), StartLoc(Start), EndLoc(End), CaL(C) {}
 
   ~WebAssemblyOperand() {
     if (isBrList())
       BrL.~BrLOp();
+    if (isCatchList())
+      CaL.~CaLOp();
   }
 
   bool isToken() const override { return Kind == Token; }
@@ -153,7 +168,15 @@ struct WebAssemblyOperand : public MCParsedAsmOperand {
   }
 
   void addCatchListOperands(MCInst &Inst, unsigned N) const {
-    // TODO
+    assert(N == 1 && isCatchList() && "Invalid CatchList!");
+    Inst.addOperand(MCOperand::createImm(CaL.List.size()));
+    for (auto Ca : CaL.List) {
+      Inst.addOperand(MCOperand::createImm(Ca.Opcode));
+      if (Ca.Opcode == wasm::WASM_OPCODE_CATCH ||
+          Ca.Opcode == wasm::WASM_OPCODE_CATCH_REF)
+        Inst.addOperand(MCOperand::createExpr(Ca.Tag));
+      Inst.addOperand(MCOperand::createImm(Ca.Dest));
+    }
   }
 
   void print(raw_ostream &OS) const override {
@@ -174,7 +197,7 @@ struct WebAssemblyOperand : public MCParsedAsmOperand {
       OS << "BrList:" << BrL.List.size();
       break;
     case CatchList:
-      // TODO
+      OS << "CaList:" << CaL.List.size();
       break;
     }
   }
@@ -228,6 +251,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
     Loop,
     Try,
     CatchAll,
+    TryTable,
     If,
     Else,
     Undefined,
@@ -304,6 +328,8 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
       return {"try", "end_try/delegate"};
     case CatchAll:
       return {"catch_all", "end_try"};
+    case TryTable:
+      return {"try_table", "end_try_table"};
     case If:
       return {"if", "end_if"};
     case Else:
@@ -571,6 +597,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
     // proper nesting.
     bool ExpectBlockType = false;
     bool ExpectFuncType = false;
+    bool ExpectCatchList = false;
     std::unique_ptr<WebAssemblyOperand> FunctionTable;
     if (Name == "block") {
       push(Block);
@@ -593,12 +620,19 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
     } else if (Name == "catch_all") {
       if (popAndPushWithSameSignature(Name, Try, CatchAll))
         return true;
+    } else if (Name == "try_table") {
+      push(TryTable);
+      ExpectBlockType = true;
+      ExpectCatchList = true;
     } else if (Name == "end_if") {
       if (pop(Name, If, Else))
         return true;
     } else if (Name == "end_try") {
       if (pop(Name, Try, CatchAll))
         return true;
+    } else if (Name == "end_try_table") {
+      if (pop(Name, TryTable))
+        return true;
     } else if (Name == "delegate") {
       if (pop(Name, Try))
         return true;
@@ -622,7 +656,18 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
       ExpectFuncType = true;
     }
 
-    if (ExpectFuncType || (ExpectBlockType && Lexer.is(AsmToken::LParen))) {
+    // Returns true if the next tokens are a catch clause
+    auto PeekCatchList = [&]() {
+      if (Lexer.isNot(AsmToken::LParen))
+        return false;
+      AsmToken NextTok = Lexer.peekTok();
+      return NextTok.getKind() == AsmToken::Identifier &&
+             NextTok.getIdentifier().starts_with("catch");
+    };
+
+    // Parse a multivalue block type
+    if (ExpectFuncType ||
+        (Lexer.is(AsmToken::LParen) && ExpectBlockType && !PeekCatchList())) {
       // This has a special TYPEINDEX operand which in text we
       // represent as a signature, such that we can re-build this signature,
       // attach it to an anonymous symbol, which is what WasmObjectWriter
@@ -648,6 +693,23 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
           Loc.getLoc(), Loc.getEndLoc(), WebAssemblyOperand::SymOp{Expr}));
     }
 
+    // If we are expecting a catch clause list, try to parse it here.
+    //
+    // If there is a multivalue block return type before this catch list, it
+    // should have been parsed above. If there is no return type before
+    // encountering this catch list, this means the type is void.
+    // The case when there is a single block return value and then a catch list
+    // will be handled below in the 'while' loop.
+    if (ExpectCatchList && PeekCatchList()) {
+      if (ExpectBlockType) {
+        ExpectBlockType = false;
+        addBlockTypeOperand(Operands, NameLoc, WebAssembly::BlockType::Void);
+      }
+      if (parseCatchList(Operands))
+        return true;
+      ExpectCatchList = false;
+    }
+
     while (Lexer.isNot(AsmToken::EndOfStatement)) {
       auto &Tok = Lexer.getTok();
       switch (Tok.getKind()) {
@@ -661,7 +723,15 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
           if (BT == WebAssembly::BlockType::Invalid)
             return error("Unknown block type: ", Id);
           addBlockTypeOperand(Operands, NameLoc, BT);
+          ExpectBlockType = false;
           Parser.Lex();
+          // Now that we've parsed a single block return type, if we are
+          // expecting a catch clause list, try to parse it.
+          if (ExpectCatchList && PeekCatchList()) {
+            if (parseCatchList(Operands))
+              return true;
+            ExpectCatchList = false;
+          }
         } else {
           // Assume this identifier is a label.
           const MCExpr *Val;
@@ -703,8 +773,8 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
       }
       case AsmToken::LCurly: {
         Parser.Lex();
-        auto Op =
-            std::make_unique<WebAssemblyOperand>(Tok.getLoc(), Tok.getEndLoc());
+        auto Op = std::make_unique<WebAssemblyOperand>(
+            Tok.getLoc(), Tok.getEndLoc(), WebAssemblyOperand::BrLOp{});
         if (!Lexer.is(AsmToken::RCurly))
           for (;;) {
             Op->BrL.List.push_back(Lexer.getTok().getIntVal());
@@ -724,10 +794,18 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
           return true;
       }
     }
-    if (ExpectBlockType && Operands.size() == 1) {
-      // Support blocks with no operands as default to void.
+
+    // If we are still expecting to parse a block type or a catch list at this
+    // point, we set them to the default/empty state.
+
+    // Support blocks with no operands as default to void.
+    if (ExpectBlockType)
       addBlockTypeOperand(Operands, NameLoc, WebAssembly::BlockType::Void);
-    }
+    // If no catch list has been parsed, add an empty catch list operand.
+    if (ExpectCatchList)
+      Operands.push_back(std::make_unique<WebAssemblyOperand>(
+          NameLoc, NameLoc, WebAssemblyOperand::CaLOp{}));
+
     if (FunctionTable)
       Operands.push_back(std::move(FunctionTable));
     Parser.Lex();
@@ -752,6 +830,55 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
     return false;
   }
 
+  bool parseCatchList(OperandVector &Operands) {
+    auto Op = std::make_unique<WebAssemblyOperand>(
+        Lexer.getTok().getLoc(), SMLoc(), WebAssemblyOperand::CaLOp{});
+    SMLoc EndLoc;
+
+    while (Lexer.is(AsmToken::LParen)) {
+      if (expect(AsmToken::LParen, "("))
+        return true;
+
+      auto CatchStr = expectIdent();
+      if (CatchStr.empty())
+        return true;
+      int64_t CatchOpcode =
+          StringSwitch<int64_t>(CatchStr)
+              .Case("catch", wasm::WASM_OPCODE_CATCH)
+              .Case("catch_ref", wasm::WASM_OPCODE_CATCH_REF)
+              .Case("catch_all", wasm::WASM_OPCODE_CATCH_ALL)
+              .Case("catch_all_ref", wasm::WASM_OPCODE_CATCH_ALL_REF)
+              .Default(-1);
+      if (CatchOpcode == -1)
+        return error(
+            "Expected catch/catch_ref/catch_all/catch_all_ref, instead got: " +
+            CatchStr);
+
+      const MCExpr *Tag = nullptr;
+      if (CatchOpcode == wasm::WASM_OPCODE_CATCH ||
+          CatchOpcode == wasm::WASM_OPCODE_CATCH_REF) {
+        if (Parser.parseExpression(Tag))
+          return error("Cannot parse symbol: ", Lexer.getTok());
+      }
+
+      auto &DestTok = Lexer.getTok();
+      if (DestTok.isNot(AsmToken::Integer))
+        return error("Expected integer constant, instead got: ", DestTok);
+      int64_t Dest = DestTok.getIntVal();
+      Parser.Lex();
+
+      EndLoc = Lexer.getTok().getEndLoc();
+      if (expect(AsmToken::RParen, ")"))
+        return true;
+
+      Op->CaL.List.push_back({CatchOpcode, Tag, Dest});
+    }
+
+    Op->EndLoc = EndLoc;
+    Operands.push_back(std::move(Op));
+    return false;
+  }
+
   bool CheckDataSection() {
     if (CurrentState != DataSection) {
       auto WS = cast<MCSectionWasm>(getStreamer().getCurrentSectionOnly());
diff --git a/llvm/test/MC/WebAssembly/eh-assembly-new.s b/llvm/test/MC/WebAssembly/eh-assembly-new.s
new file mode 100644
index 00000000000000..8069b666d73e53
--- /dev/null
+++ b/llvm/test/MC/WebAssembly/eh-assembly-new.s
@@ -0,0 +1,146 @@
+# RUN: llvm-mc -triple=wasm32-unknown-unknown -mattr=+exception-handling --no-type-check < %s | FileCheck %s
+
+  .tagtype  __cpp_exception i32
+  .tagtype  __c_longjmp i32
+  .functype  eh_test () -> ()
+  .functype  foo () -> ()
+
+eh_test:
+  # try_table with all four kinds of catch clauses
+  block exnref
+    block
+      block () -> (i32, exnref)
+        block i32
+          try_table (catch __cpp_exception 0) (catch_ref __c_longjmp 1) (catch_all 2) (catch_all_ref 3)
+            i32.const 0
+            throw     __cpp_exception
+          end_try_table
+        end_block
+        drop
+      end_block
+      drop
+      drop
+    end_block
+  end_block
+  drop
+
+  # You can use the same kind of catch clause more than once
+  block
+    block exnref
+      block
+        try_table (catch_all 0) (catch_all_ref 1) (catch_all 2)
+          call  foo
+        end_try_table
+      end_block
+    end_block
+    drop
+  end_block
+
+  # Two catch clauses targeting the same block
+  block
+    try_table (catch_all 0) (catch_all 0)
+    end_try_table
+  end_block
+
+  # try_table with a return type
+  block
+    try_table f32 (catch_all 0)
+      f32.const 0.0
+    end_try_table
+    drop
+  end_block
+
+  # try_table with a multivalue type return
+  block
+    try_table () -> (i32, f32) (catch_all 0)
+      i32.const 0
+      f32.const 0.0
+    end_try_table
+    drop
+    drop
+  end_block
+
+  # catch-less try_tables
+  try_table
+    call  foo
+  end_try_table
+
+  try_table i32
+    i32.const 0
+  end_try_table
+  drop
+
+  try_table () -> (i32, f32)
+    i32.const 0
+    f32.const 0.0
+  end_try_table
+  drop
+  drop
+
+  end_function
+
+# CHECK-LABEL: eh_test:
+# CHECK-NEXT:    block           exnref
+# CHECK-NEXT:    block
+# CHECK-NEXT:    block           () -> (i32, exnref)
+# CHECK-NEXT:    block           i32
+# CHECK-NEXT:    try_table        (catch __cpp_exception 0) (catch_ref __c_longjmp 1) (catch_all 2) (catch_all_ref 3)
+# CHECK:         i32.const       0
+# CHECK-NEXT:    throw           __cpp_exception
+# CHECK-NEXT:    end_try_table
+# CHECK-NEXT:    end_block
+# CHECK-NEXT:    drop
+# CHECK-NEXT:    end_block
+# CHECK-NEXT:    drop
+# CHECK-NEXT:    drop
+# CHECK-NEXT:    end_block
+# CHECK-NEXT:    end_block
+# CHECK-NEXT:    drop
+
+# CHECK:         block
+# CHECK-NEXT:    block           exnref
+# CHECK-NEXT:    block
+# CHECK-NEXT:    try_table        (catch_all 0) (catch_all_ref 1) (catch_all 2)
+# CHECK:         call    foo
+# CHECK-NEXT:    end_try_table
+# CHECK-NEXT:    end_block
+# CHECK-NEXT:    end_block
+# CHECK-NEXT:    drop
+# CHECK-NEXT:    end_block
+
+# CHECK:         block
+# CHECK-NEXT:    try_table        (catch_all 0) (catch_all 0)
+# CHECK:         end_try_table
+# CHECK-NEXT:    end_block
+
+# CHECK:         block
+# CHECK-NEXT:    try_table       f32 (catch_all 0)
+# CHECK:         f32.const       0x0p0
+# CHECK-NEXT:    end_try_table
+# CHECK-NEXT:    drop
+# CHECK-NEXT:    end_block
+
+# CHECK:         block
+# CHECK-NEXT:    try_table       () -> (i32, f32) (catch_all 0)
+# CHECK:         i32.const       0
+# CHECK-NEXT:    f32.const       0x0p0
+# CHECK-NEXT:    end_try_table
+# CHECK-NEXT:    drop
+# CHECK-NEXT:    drop
+# CHECK-NEXT:    end_block
+
+# CHECK:         try_table
+# CHECK-NEXT:    call    foo
+# CHECK-NEXT:    end_try_table
+
+# CHECK:         try_table       i32
+# CHECK-NEXT:    i32.const       0
+# CHECK-NEXT:    end_try_table
+# CHECK-NEXT:    drop
+
+# CHECK:         try_table       () -> (i32, f32)
+# CHECK-NEXT:    i32.const       0
+# CHECK-NEXT:    f32.const       0x0p0
+# CHECK-NEXT:    end_try_table
+# CHECK-NEXT:    drop
+# CHECK-NEXT:    drop

>From cbcf191ed3f34a61211f1a1563966dc4bd695f3a Mon Sep 17 00:00:00 2001
From: Heejin Ahn <aheejin at gmail.com>
Date: Sat, 14 Sep 2024 02:09:11 +0000
Subject: [PATCH 02/10] Add throw_ref to tests

---
 llvm/test/MC/WebAssembly/eh-assembly-new.s | 7 ++++---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/llvm/test/MC/WebAssembly/eh-assembly-new.s b/llvm/test/MC/WebAssembly/eh-assembly-new.s
index 8069b666d73e53..c13ee8ecb30d91 100644
--- a/llvm/test/MC/WebAssembly/eh-assembly-new.s
+++ b/llvm/test/MC/WebAssembly/eh-assembly-new.s
@@ -19,9 +19,10 @@ eh_test:
         drop
       end_block
       drop
-      drop
+      throw_ref
     end_block
   end_block
+  throw_ref
   drop
 
   # You can use the same kind of catch clause more than once
@@ -92,10 +93,10 @@ eh_test:
 # CHECK-NEXT:    drop
 # CHECK-NEXT:    end_block
 # CHECK-NEXT:    drop
-# CHECK-NEXT:    drop
+# CHECK-NEXT:    throw_ref
 # CHECK-NEXT:    end_block
 # CHECK-NEXT:    end_block
-# CHECK-NEXT:    drop
+# CHECK-NEXT:    throw_ref
 
 # CHECK:         block
 # CHECK-NEXT:    block           exnref

>From dc379e7c2f6f6bb96c245375ed390404e399291e Mon Sep 17 00:00:00 2001
From: Heejin Ahn <aheejin at gmail.com>
Date: Sun, 15 Sep 2024 07:09:15 +0000
Subject: [PATCH 03/10] test fix

---
 llvm/test/MC/WebAssembly/eh-assembly-new.s | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/llvm/test/MC/WebAssembly/eh-assembly-new.s b/llvm/test/MC/WebAssembly/eh-assembly-new.s
index c13ee8ecb30d91..4ecb8c3b0dd875 100644
--- a/llvm/test/MC/WebAssembly/eh-assembly-new.s
+++ b/llvm/test/MC/WebAssembly/eh-assembly-new.s
@@ -15,14 +15,15 @@ eh_test:
             i32.const 0
             throw     __cpp_exception
           end_try_table
+          return
         end_block
         drop
+        return
       end_block
-      drop
       throw_ref
+      drop
     end_block
   end_block
-  throw_ref
   drop
 
   # You can use the same kind of catch clause more than once
@@ -33,6 +34,7 @@ eh_test:
           call  foo
         end_try_table
       end_block
+      return
     end_block
     drop
   end_block
@@ -89,14 +91,16 @@ eh_test:
 # CHECK:         i32.const       0
 # CHECK-NEXT:    throw           __cpp_exception
 # CHECK-NEXT:    end_try_table
+# CHECK-NEXT:    return
 # CHECK-NEXT:    end_block
 # CHECK-NEXT:    drop
+# CHECK-NEXT:    return
 # CHECK-NEXT:    end_block
-# CHECK-NEXT:    drop
 # CHECK-NEXT:    throw_ref
+# CHECK-NEXT:    drop
 # CHECK-NEXT:    end_block
 # CHECK-NEXT:    end_block
-# CHECK-NEXT:    throw_ref
+# CHECK-NEXT:    drop
 
 # CHECK:         block
 # CHECK-NEXT:    block           exnref
@@ -105,6 +109,7 @@ eh_test:
 # CHECK:         call    foo
 # CHECK-NEXT:    end_try_table
 # CHECK-NEXT:    end_block
+# CHECK-NEXT:    return
 # CHECK-NEXT:    end_block
 # CHECK-NEXT:    drop
 # CHECK-NEXT:    end_block

>From 558f3a5380d5e4b6a4d661d7717a9347e5f28b02 Mon Sep 17 00:00:00 2001
From: Heejin Ahn <aheejin at gmail.com>
Date: Sun, 15 Sep 2024 09:34:43 +0000
Subject: [PATCH 04/10] functype location

---
 llvm/test/MC/WebAssembly/eh-assembly-new.s | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/test/MC/WebAssembly/eh-assembly-new.s b/llvm/test/MC/WebAssembly/eh-assembly-new.s
index 4ecb8c3b0dd875..0bae4a3512235f 100644
--- a/llvm/test/MC/WebAssembly/eh-assembly-new.s
+++ b/llvm/test/MC/WebAssembly/eh-assembly-new.s
@@ -2,10 +2,11 @@
 
   .tagtype  __cpp_exception i32
   .tagtype  __c_longjmp i32
-  .functype  eh_test () -> ()
   .functype  foo () -> ()
 
 eh_test:
+  .functype  eh_test () -> ()
+
   # try_table with all four kinds of catch clauses
   block exnref
     block

>From 9a0aaeab8a0eeea594874b2291bdd2b490480b41 Mon Sep 17 00:00:00 2001
From: Heejin Ahn <aheejin at gmail.com>
Date: Sun, 15 Sep 2024 09:44:33 +0000
Subject: [PATCH 05/10] fix

---
 llvm/test/MC/WebAssembly/eh-assembly-new.s | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/test/MC/WebAssembly/eh-assembly-new.s b/llvm/test/MC/WebAssembly/eh-assembly-new.s
index 0bae4a3512235f..d5298f1a6b763d 100644
--- a/llvm/test/MC/WebAssembly/eh-assembly-new.s
+++ b/llvm/test/MC/WebAssembly/eh-assembly-new.s
@@ -84,7 +84,7 @@ eh_test:
   end_function
 
 # CHECK-LABEL: eh_test:
-# CHECK-NEXT:    block           exnref
+# CHECK:         block           exnref
 # CHECK-NEXT:    block
 # CHECK-NEXT:    block           () -> (i32, exnref)
 # CHECK-NEXT:    block           i32

>From 9b2f371a6f6281d3c7ad0994842a48ae6d8b834b Mon Sep 17 00:00:00 2001
From: Heejin Ahn <aheejin at gmail.com>
Date: Sun, 15 Sep 2024 09:46:08 +0000
Subject: [PATCH 06/10] fix

---
 llvm/test/MC/WebAssembly/eh-assembly-new.s | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/llvm/test/MC/WebAssembly/eh-assembly-new.s b/llvm/test/MC/WebAssembly/eh-assembly-new.s
index d5298f1a6b763d..a769bc447d0ba9 100644
--- a/llvm/test/MC/WebAssembly/eh-assembly-new.s
+++ b/llvm/test/MC/WebAssembly/eh-assembly-new.s
@@ -24,6 +24,7 @@ eh_test:
       throw_ref
       drop
     end_block
+    return
   end_block
   drop
 
@@ -100,6 +101,7 @@ eh_test:
 # CHECK-NEXT:    throw_ref
 # CHECK-NEXT:    drop
 # CHECK-NEXT:    end_block
+# CHECK-NEXT:    return
 # CHECK-NEXT:    end_block
 # CHECK-NEXT:    drop
 

>From d578e2c254bced2e4ac946ddbeb6ef1fe1561f5a Mon Sep 17 00:00:00 2001
From: Heejin Ahn <aheejin at gmail.com>
Date: Mon, 16 Sep 2024 18:38:05 +0000
Subject: [PATCH 07/10] eh-assembly-new.s -> eh-assembly.s

---
 llvm/test/MC/WebAssembly/{eh-assembly-new.s => eh-assembly.s} | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename llvm/test/MC/WebAssembly/{eh-assembly-new.s => eh-assembly.s} (100%)

diff --git a/llvm/test/MC/WebAssembly/eh-assembly-new.s b/llvm/test/MC/WebAssembly/eh-assembly.s
similarity index 100%
rename from llvm/test/MC/WebAssembly/eh-assembly-new.s
rename to llvm/test/MC/WebAssembly/eh-assembly.s

>From 17f3e92f7baed2d36c861a6ee7787e2f2fc178fc Mon Sep 17 00:00:00 2001
From: Heejin Ahn <aheejin at gmail.com>
Date: Tue, 17 Sep 2024 02:58:59 +0000
Subject: [PATCH 08/10] Fix CalOpElem type

---
 .../WebAssembly/AsmParser/WebAssemblyAsmParser.cpp | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
index 03ea5b09c4fd4a..4fef5fa0ef2208 100644
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -70,9 +70,9 @@ struct WebAssemblyOperand : public MCParsedAsmOperand {
   };
 
   struct CaLOpElem {
-    int64_t Opcode;
+    uint8_t Opcode;
     const MCExpr *Tag;
-    int64_t Dest;
+    unsigned Dest;
   };
 
   struct CaLOp {
@@ -842,14 +842,14 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
       auto CatchStr = expectIdent();
       if (CatchStr.empty())
         return true;
-      int64_t CatchOpcode =
-          StringSwitch<int64_t>(CatchStr)
+      uint8_t CatchOpcode =
+          StringSwitch<uint8_t>(CatchStr)
               .Case("catch", wasm::WASM_OPCODE_CATCH)
               .Case("catch_ref", wasm::WASM_OPCODE_CATCH_REF)
               .Case("catch_all", wasm::WASM_OPCODE_CATCH_ALL)
               .Case("catch_all_ref", wasm::WASM_OPCODE_CATCH_ALL_REF)
-              .Default(-1);
-      if (CatchOpcode == -1)
+              .Default(0xff);
+      if (CatchOpcode == 0xff)
         return error(
             "Expected catch/catch_ref/catch_all/catch_all_ref, instead got: " +
             CatchStr);
@@ -864,7 +864,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
       auto &DestTok = Lexer.getTok();
       if (DestTok.isNot(AsmToken::Integer))
         return error("Expected integer constant, instead got: ", DestTok);
-      int64_t Dest = DestTok.getIntVal();
+      unsigned Dest = DestTok.getIntVal();
       Parser.Lex();
 
       EndLoc = Lexer.getTok().getEndLoc();

>From 29f7e2f2febeb73702b6aff4e26dde031b722690 Mon Sep 17 00:00:00 2001
From: Heejin Ahn <aheejin at gmail.com>
Date: Tue, 17 Sep 2024 03:03:08 +0000
Subject: [PATCH 09/10] drive-by vix

---
 .../Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp  | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
index 903dbcd21ea967..37dc19c02c6e48 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
@@ -378,7 +378,7 @@ void WebAssemblyInstPrinter::printCatchList(const MCInst *MI, unsigned OpNo,
     const MCSymbolRefExpr *TagExpr = nullptr;
     const MCSymbolWasm *TagSym = nullptr;
     assert(Op.isExpr());
-    TagExpr = dyn_cast<MCSymbolRefExpr>(Op.getExpr());
+    TagExpr = cast<MCSymbolRefExpr>(Op.getExpr());
     TagSym = cast<MCSymbolWasm>(&TagExpr->getSymbol());
     O << TagSym->getName() << " ";
   };

>From a5cec4ba0453a8f681ca1aad367dac4b8e591070 Mon Sep 17 00:00:00 2001
From: Heejin Ahn <aheejin at gmail.com>
Date: Tue, 17 Sep 2024 03:03:21 +0000
Subject: [PATCH 10/10] Error test cases

---
 .../MC/WebAssembly/basic-assembly-errors.s    | 32 +++++++++++++++++--
 1 file changed, 29 insertions(+), 3 deletions(-)

diff --git a/llvm/test/MC/WebAssembly/basic-assembly-errors.s b/llvm/test/MC/WebAssembly/basic-assembly-errors.s
index aab3b5b1a9028e..6699b66d04a150 100644
--- a/llvm/test/MC/WebAssembly/basic-assembly-errors.s
+++ b/llvm/test/MC/WebAssembly/basic-assembly-errors.s
@@ -26,11 +26,37 @@ test0:
     catch_all
 # CHECK: error: Block construct type mismatch, expected: end_try, instead got: catch_all
     end
-# CHECK: Block construct type mismatch, expected: end_try, instead got: end_function
+
+# CHECK: error: Expected integer constant, instead got: )
+    try_table (catch __cpp_exception)
+    end_try_table
+
+    block
+# CHECK: error: invalid operand for instruction
+    try_table (catch_all 0) i32
+    i32.const 0
+    end_try_table
+    drop
+    end_block
+
+    block
+# CHECK: error: Expected identifier, got: )
+    try_table (catch_all 0) () -> (i32, i32)
+    i32.const 0
+    i32.const 0
+    end_try_table
+    drop
+    drop
+    end_block
+
+# CHECK: error: unknown type: not_catch
+    try_table (not_catch 0)
+
+# CHECK: Block construct type mismatch, expected: end_try_table, instead got: end_function
+    end_function
+# CHECK: error: Unmatched block construct(s) at function end: try_table
 # CHECK: error: Unmatched block construct(s) at function end: catch_all
 # CHECK: error: Unmatched block construct(s) at function end: loop
 # CHECK: error: Unmatched block construct(s) at function end: try
 # CHECK: error: Unmatched block construct(s) at function end: block
 # CHECK: error: Unmatched block construct(s) at function end: function
-    end_function
-



More information about the llvm-commits mailing list