Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WebAssembly] Support disassembler for try_table #108800

Merged
merged 1 commit into from
Sep 17, 2024
Merged

Conversation

aheejin
Copy link
Member

@aheejin aheejin commented Sep 16, 2024

This adds support for disassembler for the new try_table instruction. This adds tests for throw and throw_ref as well.

Currently tag expressions are not supported for throw or try_table instruction when instructions are parsed from the disassembler. Not sure whether there is a way to support it. (This is not a new thing for the new EH proposal; it has not been supported for the legacy EH as well.)

This adds support for disassembler for the new `try_table` instruction.
This adds tests for `throw` and `throw_ref` as well.

Currently tag expressions are not supported for `throw` or `try_table`
instruction when instructions are parsed from the disassembler. Not sure
whether there is a way to support it. (This is not a new thing for the
new EH proposal; it has not been supported for the legacy EH as well.)
@aheejin aheejin requested a review from dschuff September 16, 2024 07:34
@llvmbot llvmbot added backend:WebAssembly mc Machine (object) code labels Sep 16, 2024
@llvmbot
Copy link
Member

llvmbot commented Sep 16, 2024

@llvm/pr-subscribers-backend-webassembly

Author: Heejin Ahn (aheejin)

Changes

This adds support for disassembler for the new try_table instruction. This adds tests for throw and throw_ref as well.

Currently tag expressions are not supported for throw or try_table instruction when instructions are parsed from the disassembler. Not sure whether there is a way to support it. (This is not a new thing for the new EH proposal; it has not been supported for the legacy EH as well.)


Full diff: https://github.com/llvm/llvm-project/pull/108800.diff

3 Files Affected:

  • (modified) llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp (+18)
  • (modified) llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp (+9-4)
  • (modified) llvm/test/MC/Disassembler/WebAssembly/wasm.txt (+7)
diff --git a/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp b/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
index 3585b5f4a5c9ad..a66ee2b6ac1af7 100644
--- a/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
+++ b/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
@@ -289,6 +289,24 @@ MCDisassembler::DecodeStatus WebAssemblyDisassembler::getInstruction(
         return MCDisassembler::Fail;
       break;
     }
+    case WebAssembly::OPERAND_CATCH_LIST: {
+      if (!parseLEBImmediate(MI, Size, Bytes, false))
+        return MCDisassembler::Fail;
+      int64_t NumCatches = MI.getOperand(MI.getNumOperands() - 1).getImm();
+      for (int64_t I = 0; I < NumCatches; I++) {
+        if (!parseImmediate<uint8_t>(MI, Size, Bytes))
+          return MCDisassembler::Fail;
+        int64_t CatchOpcode = MI.getOperand(MI.getNumOperands() - 1).getImm();
+        if (CatchOpcode == wasm::WASM_OPCODE_CATCH ||
+            CatchOpcode == wasm::WASM_OPCODE_CATCH_REF) {
+          if (!parseLEBImmediate(MI, Size, Bytes, false)) // tag index
+            return MCDisassembler::Fail;
+        }
+        if (!parseLEBImmediate(MI, Size, Bytes, false)) // destination
+          return MCDisassembler::Fail;
+      }
+      break;
+    }
     case MCOI::OPERAND_REGISTER:
       // The tablegen header currently does not have any register operands since
       // we use only the stack (_S) instructions.
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
index 903dbcd21ea967..7255195fbaab31 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
@@ -377,10 +377,15 @@ void WebAssemblyInstPrinter::printCatchList(const MCInst *MI, unsigned OpNo,
   auto PrintTagOp = [&](const MCOperand &Op) {
     const MCSymbolRefExpr *TagExpr = nullptr;
     const MCSymbolWasm *TagSym = nullptr;
-    assert(Op.isExpr());
-    TagExpr = dyn_cast<MCSymbolRefExpr>(Op.getExpr());
-    TagSym = cast<MCSymbolWasm>(&TagExpr->getSymbol());
-    O << TagSym->getName() << " ";
+    if (Op.isExpr()) {
+      TagExpr = dyn_cast<MCSymbolRefExpr>(Op.getExpr());
+      TagSym = cast<MCSymbolWasm>(&TagExpr->getSymbol());
+      O << TagSym->getName() << " ";
+    } else {
+      // When instructions are parsed from the disassembler, we have an
+      // immediate tag index and not a tag expr
+      O << Op.getImm() << " ";
+    }
   };
 
   for (unsigned I = 0; I < NumCatches; I++) {
diff --git a/llvm/test/MC/Disassembler/WebAssembly/wasm.txt b/llvm/test/MC/Disassembler/WebAssembly/wasm.txt
index 0cbf584d9688e1..f6a3527fc5ed12 100644
--- a/llvm/test/MC/Disassembler/WebAssembly/wasm.txt
+++ b/llvm/test/MC/Disassembler/WebAssembly/wasm.txt
@@ -53,3 +53,10 @@
 # This can mean end_block/end_loop/end_if/end_function/end_try..
 # CHECK: end
 0x0B
+
+# CHECK:  try_table        (catch 0 0) (catch_ref 0 1) (catch_all 2) (catch_all_ref 3)
+0x1F 0x40 0x04 0x00 0x00 0x00 0x01 0x00 0x01 0x02 0x02 0x03 0x03
+# CHECK: throw 0
+0x08 0x00
+# CHECK: throw_ref
+0x0a

@llvmbot
Copy link
Member

llvmbot commented Sep 16, 2024

@llvm/pr-subscribers-mc

Author: Heejin Ahn (aheejin)

Changes

This adds support for disassembler for the new try_table instruction. This adds tests for throw and throw_ref as well.

Currently tag expressions are not supported for throw or try_table instruction when instructions are parsed from the disassembler. Not sure whether there is a way to support it. (This is not a new thing for the new EH proposal; it has not been supported for the legacy EH as well.)


Full diff: https://github.com/llvm/llvm-project/pull/108800.diff

3 Files Affected:

  • (modified) llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp (+18)
  • (modified) llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp (+9-4)
  • (modified) llvm/test/MC/Disassembler/WebAssembly/wasm.txt (+7)
diff --git a/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp b/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
index 3585b5f4a5c9ad..a66ee2b6ac1af7 100644
--- a/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
+++ b/llvm/lib/Target/WebAssembly/Disassembler/WebAssemblyDisassembler.cpp
@@ -289,6 +289,24 @@ MCDisassembler::DecodeStatus WebAssemblyDisassembler::getInstruction(
         return MCDisassembler::Fail;
       break;
     }
+    case WebAssembly::OPERAND_CATCH_LIST: {
+      if (!parseLEBImmediate(MI, Size, Bytes, false))
+        return MCDisassembler::Fail;
+      int64_t NumCatches = MI.getOperand(MI.getNumOperands() - 1).getImm();
+      for (int64_t I = 0; I < NumCatches; I++) {
+        if (!parseImmediate<uint8_t>(MI, Size, Bytes))
+          return MCDisassembler::Fail;
+        int64_t CatchOpcode = MI.getOperand(MI.getNumOperands() - 1).getImm();
+        if (CatchOpcode == wasm::WASM_OPCODE_CATCH ||
+            CatchOpcode == wasm::WASM_OPCODE_CATCH_REF) {
+          if (!parseLEBImmediate(MI, Size, Bytes, false)) // tag index
+            return MCDisassembler::Fail;
+        }
+        if (!parseLEBImmediate(MI, Size, Bytes, false)) // destination
+          return MCDisassembler::Fail;
+      }
+      break;
+    }
     case MCOI::OPERAND_REGISTER:
       // The tablegen header currently does not have any register operands since
       // we use only the stack (_S) instructions.
diff --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
index 903dbcd21ea967..7255195fbaab31 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.cpp
@@ -377,10 +377,15 @@ void WebAssemblyInstPrinter::printCatchList(const MCInst *MI, unsigned OpNo,
   auto PrintTagOp = [&](const MCOperand &Op) {
     const MCSymbolRefExpr *TagExpr = nullptr;
     const MCSymbolWasm *TagSym = nullptr;
-    assert(Op.isExpr());
-    TagExpr = dyn_cast<MCSymbolRefExpr>(Op.getExpr());
-    TagSym = cast<MCSymbolWasm>(&TagExpr->getSymbol());
-    O << TagSym->getName() << " ";
+    if (Op.isExpr()) {
+      TagExpr = dyn_cast<MCSymbolRefExpr>(Op.getExpr());
+      TagSym = cast<MCSymbolWasm>(&TagExpr->getSymbol());
+      O << TagSym->getName() << " ";
+    } else {
+      // When instructions are parsed from the disassembler, we have an
+      // immediate tag index and not a tag expr
+      O << Op.getImm() << " ";
+    }
   };
 
   for (unsigned I = 0; I < NumCatches; I++) {
diff --git a/llvm/test/MC/Disassembler/WebAssembly/wasm.txt b/llvm/test/MC/Disassembler/WebAssembly/wasm.txt
index 0cbf584d9688e1..f6a3527fc5ed12 100644
--- a/llvm/test/MC/Disassembler/WebAssembly/wasm.txt
+++ b/llvm/test/MC/Disassembler/WebAssembly/wasm.txt
@@ -53,3 +53,10 @@
 # This can mean end_block/end_loop/end_if/end_function/end_try..
 # CHECK: end
 0x0B
+
+# CHECK:  try_table        (catch 0 0) (catch_ref 0 1) (catch_all 2) (catch_all_ref 3)
+0x1F 0x40 0x04 0x00 0x00 0x00 0x01 0x00 0x01 0x02 0x02 0x03 0x03
+# CHECK: throw 0
+0x08 0x00
+# CHECK: throw_ref
+0x0a

case WebAssembly::OPERAND_CATCH_LIST: {
if (!parseLEBImmediate(MI, Size, Bytes, false))
return MCDisassembler::Fail;
int64_t NumCatches = MI.getOperand(MI.getNumOperands() - 1).getImm();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where do these operands actually get added to the MI?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In those parse*** functions. For example:

static bool parseLEBImmediate(MCInst &MI, uint64_t &Size,
ArrayRef<uint8_t> Bytes, bool Signed) {
int64_t Val;
if (!nextLEB(Val, Bytes, Size, Signed))
return false;
MI.addOperand(MCOperand::createImm(Val));
return true;
}

Yeah it was a little confusing to me too so I had to look into those functions...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see, the number of catches is the last operand currently, because we haven't parsed the rest yet.

case WebAssembly::OPERAND_CATCH_LIST: {
if (!parseLEBImmediate(MI, Size, Bytes, false))
return MCDisassembler::Fail;
int64_t NumCatches = MI.getOperand(MI.getNumOperands() - 1).getImm();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see, the number of catches is the last operand currently, because we haven't parsed the rest yet.

@aheejin aheejin merged commit 97ae505 into llvm:main Sep 17, 2024
11 checks passed
@aheejin aheejin deleted the eh_disas branch September 17, 2024 03:08
tmsri pushed a commit to tmsri/llvm-project that referenced this pull request Sep 19, 2024
This adds support for disassembler for the new `try_table` instruction.
This adds tests for `throw` and `throw_ref` as well.

Currently tag expressions are not supported for `throw` or `try_table`
instruction when instructions are parsed from the disassembler. Not sure
whether there is a way to support it. (This is not a new thing for the
new EH proposal; it has not been supported for the legacy EH as well.)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:WebAssembly mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants