Skip to content

Commit ac4b884

Browse files
aheejintmsri
authored andcommitted
[WebAssembly] Support binary generation for new EH (llvm#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.
1 parent 1388887 commit ac4b884

File tree

3 files changed

+44
-29
lines changed

3 files changed

+44
-29
lines changed

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyMCCodeEmitter.cpp

Lines changed: 41 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,15 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
8282
// For br_table instructions, encode the size of the table. In the MCInst,
8383
// there's an index operand (if not a stack instruction), one operand for
8484
// each table entry, and the default operand.
85-
if (MI.getOpcode() == WebAssembly::BR_TABLE_I32_S ||
86-
MI.getOpcode() == WebAssembly::BR_TABLE_I64_S)
85+
unsigned Opcode = MI.getOpcode();
86+
if (Opcode == WebAssembly::BR_TABLE_I32_S ||
87+
Opcode == WebAssembly::BR_TABLE_I64_S)
8788
encodeULEB128(MI.getNumOperands() - 1, OS);
88-
if (MI.getOpcode() == WebAssembly::BR_TABLE_I32 ||
89-
MI.getOpcode() == WebAssembly::BR_TABLE_I64)
89+
if (Opcode == WebAssembly::BR_TABLE_I32 ||
90+
Opcode == WebAssembly::BR_TABLE_I64)
9091
encodeULEB128(MI.getNumOperands() - 2, OS);
9192

92-
const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
93+
const MCInstrDesc &Desc = MCII.get(Opcode);
9394
for (unsigned I = 0, E = MI.getNumOperands(); I < E; ++I) {
9495
const MCOperand &MO = MI.getOperand(I);
9596
if (MO.isReg()) {
@@ -136,7 +137,12 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
136137
encodeULEB128(uint64_t(MO.getImm()), OS);
137138
}
138139
} else {
139-
encodeULEB128(uint64_t(MO.getImm()), OS);
140+
// Variadic immediate operands are br_table's destination operands or
141+
// try_table's operands (# of catch clauses, catch sub-opcodes, or catch
142+
// clause destinations)
143+
assert(WebAssembly::isBrTable(Opcode) ||
144+
Opcode == WebAssembly::TRY_TABLE_S);
145+
encodeULEB128(uint32_t(MO.getImm()), OS);
140146
}
141147

142148
} else if (MO.isSFPImm()) {
@@ -146,32 +152,38 @@ void WebAssemblyMCCodeEmitter::encodeInstruction(
146152
uint64_t D = MO.getDFPImm();
147153
support::endian::write<uint64_t>(OS, D, llvm::endianness::little);
148154
} else if (MO.isExpr()) {
149-
const MCOperandInfo &Info = Desc.operands()[I];
150155
llvm::MCFixupKind FixupKind;
151156
size_t PaddedSize = 5;
152-
switch (Info.OperandType) {
153-
case WebAssembly::OPERAND_I32IMM:
154-
FixupKind = MCFixupKind(WebAssembly::fixup_sleb128_i32);
155-
break;
156-
case WebAssembly::OPERAND_I64IMM:
157-
FixupKind = MCFixupKind(WebAssembly::fixup_sleb128_i64);
158-
PaddedSize = 10;
159-
break;
160-
case WebAssembly::OPERAND_FUNCTION32:
161-
case WebAssembly::OPERAND_TABLE:
162-
case WebAssembly::OPERAND_OFFSET32:
163-
case WebAssembly::OPERAND_SIGNATURE:
164-
case WebAssembly::OPERAND_TYPEINDEX:
165-
case WebAssembly::OPERAND_GLOBAL:
166-
case WebAssembly::OPERAND_TAG:
157+
if (I < Desc.getNumOperands()) {
158+
const MCOperandInfo &Info = Desc.operands()[I];
159+
switch (Info.OperandType) {
160+
case WebAssembly::OPERAND_I32IMM:
161+
FixupKind = MCFixupKind(WebAssembly::fixup_sleb128_i32);
162+
break;
163+
case WebAssembly::OPERAND_I64IMM:
164+
FixupKind = MCFixupKind(WebAssembly::fixup_sleb128_i64);
165+
PaddedSize = 10;
166+
break;
167+
case WebAssembly::OPERAND_FUNCTION32:
168+
case WebAssembly::OPERAND_TABLE:
169+
case WebAssembly::OPERAND_OFFSET32:
170+
case WebAssembly::OPERAND_SIGNATURE:
171+
case WebAssembly::OPERAND_TYPEINDEX:
172+
case WebAssembly::OPERAND_GLOBAL:
173+
case WebAssembly::OPERAND_TAG:
174+
FixupKind = MCFixupKind(WebAssembly::fixup_uleb128_i32);
175+
break;
176+
case WebAssembly::OPERAND_OFFSET64:
177+
FixupKind = MCFixupKind(WebAssembly::fixup_uleb128_i64);
178+
PaddedSize = 10;
179+
break;
180+
default:
181+
llvm_unreachable("unexpected symbolic operand kind");
182+
}
183+
} else {
184+
// Variadic expr operands are try_table's catch/catch_ref clauses' tags.
185+
assert(Opcode == WebAssembly::TRY_TABLE_S);
167186
FixupKind = MCFixupKind(WebAssembly::fixup_uleb128_i32);
168-
break;
169-
case WebAssembly::OPERAND_OFFSET64:
170-
FixupKind = MCFixupKind(WebAssembly::fixup_uleb128_i64);
171-
PaddedSize = 10;
172-
break;
173-
default:
174-
llvm_unreachable("unexpected symbolic operand kind");
175187
}
176188
Fixups.push_back(MCFixup::create(OS.tell() - Start, MO.getExpr(),
177189
FixupKind, MI.getLoc()));

llvm/test/CodeGen/WebAssembly/exception.ll

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
; 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
22
; RUN: llc < %s -asm-verbose=false -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -wasm-enable-exnref -verify-machineinstrs -O0
33
; RUN: llc < %s -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -wasm-enable-exnref
4+
; RUN: llc < %s -wasm-enable-eh -exception-model=wasm -mattr=+exception-handling -wasm-enable-exnref -filetype=obj
45

56
target triple = "wasm32-unknown-unknown"
67

llvm/test/MC/WebAssembly/eh-assembly.s

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# RUN: llvm-mc -triple=wasm32-unknown-unknown -mattr=+exception-handling --no-type-check < %s | FileCheck %s
2+
# Check that it converts to .o without errors, but don't check any output:
3+
# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -mattr=+exception-handling --no-type-check -o %t.o < %s
24

35
.tagtype __cpp_exception i32
46
.tagtype __c_longjmp i32

0 commit comments

Comments
 (0)