[llvm] [WebAssembly] Support binary generation for new EH (PR #109027)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 17 11:41:44 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-mc
@llvm/pr-subscribers-backend-webassembly
Author: Heejin Ahn (aheejin)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/109027.diff
3 Files Affected:
- (modified) llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp (+41-29)
- (modified) llvm/test/CodeGen/WebAssembly/exception.ll (+1)
- (modified) llvm/test/MC/WebAssembly/eh-assembly.s (+2)
``````````diff
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
``````````
</details>
https://github.com/llvm/llvm-project/pull/109027
More information about the llvm-commits
mailing list