[llvm] 08bba65 - [WebAssembly] Support binary generation for new EH (#109027)

via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 17 14:58:22 PDT 2024


Author: Heejin Ahn
Date: 2024-09-17T14:58:19-07:00
New Revision: 08bba6503b918c97d9d1a0cde97f4b3c64d5f2c3

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

LOG: [WebAssembly] Support binary generation for new EH (#109027)

This adds support for binary generation for the new EH proposal.

So far the only case that we emitted variable immediate operands in
binary has been `br_table`'s destinations. (Other `variable_ops` uses in
TableGen files are register operands, such as the operands of `call`, so
they don't get emitted in binary as a part of the same instruction.)

With this PR, variable immediate operands can include `try_table`'s
operands:
- The number of of catch clauses
- catch clauses sub-opcodes
  - `catch`: 0x00
  - `catch_ref`: 0x01
  - `catch_all`: 0x02
  - `catch_all_ref`: 0x03
- catch clauses' destinations

With `try_table`, we now have variable expr operands for `try_table`'s
catch clauses' tags. We treat their fixups in the same way we do for
tags in other instructions such as in `throw`.

Diff without whitespace will be easier to view.

Added: 
    

Modified: 
    llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
    llvm/test/CodeGen/WebAssembly/exception.ll
    llvm/test/MC/WebAssembly/eh-assembly.s

Removed: 
    


################################################################################
diff  --git a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
index aaca213c4afe9b..3e7487dbd8f54e 100644
--- a/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
+++ b/llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp
@@ -82,14 +82,15 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
   // For br_table instructions, encode the size of the table. In the MCInst,
   // there's an index operand (if not a stack instruction), one operand for
   // each table entry, and the default operand.
-  if (MI.getOpcode() == WebAssembly::BR_TABLE_I32_S ||
-      MI.getOpcode() == WebAssembly::BR_TABLE_I64_S)
+  unsigned Opcode = MI.getOpcode();
+  if (Opcode == WebAssembly::BR_TABLE_I32_S ||
+      Opcode == WebAssembly::BR_TABLE_I64_S)
     encodeULEB128(MI.getNumOperands() - 1, OS);
-  if (MI.getOpcode() == WebAssembly::BR_TABLE_I32 ||
-      MI.getOpcode() == WebAssembly::BR_TABLE_I64)
+  if (Opcode == WebAssembly::BR_TABLE_I32 ||
+      Opcode == WebAssembly::BR_TABLE_I64)
     encodeULEB128(MI.getNumOperands() - 2, OS);
 
-  const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
+  const MCInstrDesc &Desc = MCII.get(Opcode);
   for (unsigned I = 0, E = MI.getNumOperands(); I < E; ++I) {
     const MCOperand &MO = MI.getOperand(I);
     if (MO.isReg()) {
@@ -136,7 +137,12 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
           encodeULEB128(uint64_t(MO.getImm()), OS);
         }
       } else {
-        encodeULEB128(uint64_t(MO.getImm()), OS);
+        // Variadic immediate operands are br_table's destination operands or
+        // try_table's operands (# of catch clauses, catch sub-opcodes, or catch
+        // clause destinations)
+        assert(WebAssembly::isBrTable(Opcode) ||
+               Opcode == WebAssembly::TRY_TABLE_S);
+        encodeULEB128(uint32_t(MO.getImm()), OS);
       }
 
     } else if (MO.isSFPImm()) {
@@ -146,32 +152,38 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
       uint64_t D = MO.getDFPImm();
       support::endian::write<uint64_t>(OS, D, llvm::endianness::little);
     } else if (MO.isExpr()) {
-      const MCOperandInfo &Info = Desc.operands()[I];
       llvm::MCFixupKind FixupKind;
       size_t PaddedSize = 5;
-      switch (Info.OperandType) {
-      case WebAssembly::OPERAND_I32IMM:
-        FixupKind = MCFixupKind(WebAssembly::fixup_sleb128_i32);
-        break;
-      case WebAssembly::OPERAND_I64IMM:
-        FixupKind = MCFixupKind(WebAssembly::fixup_sleb128_i64);
-        PaddedSize = 10;
-        break;
-      case WebAssembly::OPERAND_FUNCTION32:
-      case WebAssembly::OPERAND_TABLE:
-      case WebAssembly::OPERAND_OFFSET32:
-      case WebAssembly::OPERAND_SIGNATURE:
-      case WebAssembly::OPERAND_TYPEINDEX:
-      case WebAssembly::OPERAND_GLOBAL:
-      case WebAssembly::OPERAND_TAG:
+      if (I < Desc.getNumOperands()) {
+        const MCOperandInfo &Info = Desc.operands()[I];
+        switch (Info.OperandType) {
+        case WebAssembly::OPERAND_I32IMM:
+          FixupKind = MCFixupKind(WebAssembly::fixup_sleb128_i32);
+          break;
+        case WebAssembly::OPERAND_I64IMM:
+          FixupKind = MCFixupKind(WebAssembly::fixup_sleb128_i64);
+          PaddedSize = 10;
+          break;
+        case WebAssembly::OPERAND_FUNCTION32:
+        case WebAssembly::OPERAND_TABLE:
+        case WebAssembly::OPERAND_OFFSET32:
+        case WebAssembly::OPERAND_SIGNATURE:
+        case WebAssembly::OPERAND_TYPEINDEX:
+        case WebAssembly::OPERAND_GLOBAL:
+        case WebAssembly::OPERAND_TAG:
+          FixupKind = MCFixupKind(WebAssembly::fixup_uleb128_i32);
+          break;
+        case WebAssembly::OPERAND_OFFSET64:
+          FixupKind = MCFixupKind(WebAssembly::fixup_uleb128_i64);
+          PaddedSize = 10;
+          break;
+        default:
+          llvm_unreachable("unexpected symbolic operand kind");
+        }
+      } else {
+        // Variadic expr operands are try_table's catch/catch_ref clauses' tags.
+        assert(Opcode == WebAssembly::TRY_TABLE_S);
         FixupKind = MCFixupKind(WebAssembly::fixup_uleb128_i32);
-        break;
-      case WebAssembly::OPERAND_OFFSET64:
-        FixupKind = MCFixupKind(WebAssembly::fixup_uleb128_i64);
-        PaddedSize = 10;
-        break;
-      default:
-        llvm_unreachable("unexpected symbolic operand kind");
       }
       Fixups.push_back(MCFixup::create(OS.tell() - Start, MO.getExpr(),
                                        FixupKind, MI.getLoc()));

diff  --git a/llvm/test/CodeGen/WebAssembly/exception.ll b/llvm/test/CodeGen/WebAssembly/exception.ll
index 7259761d6313b6..1ad4c84f1c0237 100644
--- a/llvm/test/CodeGen/WebAssembly/exception.ll
+++ b/llvm/test/CodeGen/WebAssembly/exception.ll
@@ -1,6 +1,7 @@
 ; RUN: llc < %s -asm-verbose=false -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -wasm-enable-exnref -verify-machineinstrs | FileCheck --implicit-check-not=ehgcr -allow-deprecated-dag-overlap %s
 ; RUN: llc < %s -asm-verbose=false -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -wasm-enable-exnref -verify-machineinstrs -O0
 ; RUN: llc < %s -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -wasm-enable-exnref
+; RUN: llc < %s -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -wasm-enable-exnref -filetype=obj
 
 target triple = "wasm32-unknown-unknown"
 

diff  --git a/llvm/test/MC/WebAssembly/eh-assembly.s b/llvm/test/MC/WebAssembly/eh-assembly.s
index a769bc447d0ba9..b4d6b324d96e3e 100644
--- a/llvm/test/MC/WebAssembly/eh-assembly.s
+++ b/llvm/test/MC/WebAssembly/eh-assembly.s
@@ -1,4 +1,6 @@
 # RUN: llvm-mc -triple=wasm32-unknown-unknown -mattr=+exception-handling --no-type-check < %s | FileCheck %s
+# Check that it converts to .o without errors, but don't check any output:
+# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -mattr=+exception-handling --no-type-check -o %t.o < %s
 
   .tagtype  __cpp_exception i32
   .tagtype  __c_longjmp i32


        


More information about the llvm-commits mailing list