Skip to content

Commit

Permalink
[WebAssembly] Support binary generation for new EH (llvm#109027)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
aheejin committed Sep 17, 2024
1 parent 38333f4 commit 08bba65
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down Expand Up @@ -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()) {
Expand All @@ -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()));
Expand Down
1 change: 1 addition & 0 deletions llvm/test/CodeGen/WebAssembly/exception.ll
Original file line number Diff line number Diff line change
@@ -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"

Expand Down
2 changes: 2 additions & 0 deletions llvm/test/MC/WebAssembly/eh-assembly.s
Original file line number Diff line number Diff line change
@@ -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
Expand Down

0 comments on commit 08bba65

Please sign in to comment.