Skip to content

Commit 5afdd64

Browse files
committed
[WebAssembly] Update InstPrinter and AsmParser for new EH instructions
This updates InstPrinter and AsmParser for `delegate` and `catch_all` instructions. Both will reject programs with multiple `catch_all`s per a single `try`. And InstPrinter uses `EHInstStack` to figure out whether to print catch label comments: It does not print catch label comments for second `catch` or `catch_all` in a `try`. Reviewed By: aardappel Differential Revision: https://reviews.llvm.org/D94051
1 parent 4af7357 commit 5afdd64

File tree

5 files changed

+53
-8
lines changed

5 files changed

+53
-8
lines changed

llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
216216
Block,
217217
Loop,
218218
Try,
219+
CatchAll,
219220
If,
220221
Else,
221222
Undefined,
@@ -273,7 +274,9 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
273274
case Loop:
274275
return {"loop", "end_loop"};
275276
case Try:
276-
return {"try", "end_try"};
277+
return {"try", "end_try/delegate"};
278+
case CatchAll:
279+
return {"catch_all", "end_try"};
277280
case If:
278281
return {"if", "end_if"};
279282
case Else:
@@ -533,10 +536,17 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
533536
if (pop(Name, Try))
534537
return true;
535538
push(Try);
539+
} else if (Name == "catch_all") {
540+
if (pop(Name, Try))
541+
return true;
542+
push(CatchAll);
536543
} else if (Name == "end_if") {
537544
if (pop(Name, If, Else))
538545
return true;
539546
} else if (Name == "end_try") {
547+
if (pop(Name, Try, CatchAll))
548+
return true;
549+
} else if (Name == "delegate") {
540550
if (pop(Name, Try))
541551
return true;
542552
} else if (Name == "end_loop") {

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

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, uint64_t Address,
108108
ControlFlowStack.push_back(std::make_pair(ControlFlowCounter, false));
109109
EHPadStack.push_back(ControlFlowCounter);
110110
DelegateStack.push_back(ControlFlowCounter++);
111+
EHInstStack.push_back(TRY);
111112
return;
112113

113114
case WebAssembly::END_LOOP:
@@ -133,23 +134,39 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, uint64_t Address,
133134

134135
case WebAssembly::END_TRY:
135136
case WebAssembly::END_TRY_S:
136-
if (ControlFlowStack.empty()) {
137+
if (ControlFlowStack.empty() || EHInstStack.empty()) {
137138
printAnnotation(OS, "End marker mismatch!");
138139
} else {
139140
printAnnotation(
140141
OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':');
142+
EHInstStack.pop_back();
141143
}
142144
return;
143145

144146
case WebAssembly::CATCH:
145147
case WebAssembly::CATCH_S:
146148
case WebAssembly::CATCH_ALL:
147149
case WebAssembly::CATCH_ALL_S:
148-
if (EHPadStack.empty() || DelegateStack.empty()) {
150+
// There can be multiple catch instructions for one try instruction, so
151+
// we print a label only for the first 'catch' label.
152+
if (EHInstStack.empty()) {
149153
printAnnotation(OS, "try-catch mismatch!");
150-
} else {
151-
printAnnotation(OS, "catch" + utostr(EHPadStack.pop_back_val()) + ':');
152-
DelegateStack.pop_back();
154+
} else if (EHInstStack.back() == CATCH_ALL) {
155+
printAnnotation(OS, "catch/catch_all cannot occur after catch_all");
156+
} else if (EHInstStack.back() == TRY) {
157+
if (EHPadStack.empty() || DelegateStack.empty()) {
158+
printAnnotation(OS, "try-catch mismatch!");
159+
} else {
160+
printAnnotation(OS,
161+
"catch" + utostr(EHPadStack.pop_back_val()) + ':');
162+
DelegateStack.pop_back();
163+
}
164+
EHInstStack.pop_back();
165+
if (Opc == WebAssembly::CATCH || Opc == WebAssembly::CATCH_S) {
166+
EHInstStack.push_back(CATCH);
167+
} else {
168+
EHInstStack.push_back(CATCH_ALL);
169+
}
153170
}
154171
return;
155172

@@ -167,7 +184,7 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, uint64_t Address,
167184
case WebAssembly::DELEGATE:
168185
case WebAssembly::DELEGATE_S:
169186
if (ControlFlowStack.empty() || EHPadStack.empty() ||
170-
DelegateStack.empty()) {
187+
DelegateStack.empty() || EHInstStack.empty()) {
171188
printAnnotation(OS, "try-delegate mismatch!");
172189
} else {
173190
// 'delegate' is
@@ -181,6 +198,7 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, uint64_t Address,
181198
": ";
182199
EHPadStack.pop_back();
183200
DelegateStack.pop_back();
201+
EHInstStack.pop_back();
184202
uint64_t Depth = MI->getOperand(0).getImm();
185203
if (Depth >= DelegateStack.size()) {
186204
Label += "to caller";

llvm/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyInstPrinter.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ class WebAssemblyInstPrinter final : public MCInstPrinter {
3333
// separate stack for 'delegate'.
3434
SmallVector<uint64_t, 4> DelegateStack;
3535

36+
enum EHInstKind { TRY, CATCH, CATCH_ALL };
37+
SmallVector<EHInstKind, 4> EHInstStack;
38+
3639
public:
3740
WebAssemblyInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
3841
const MCRegisterInfo &MRI);

llvm/test/MC/WebAssembly/annotations.s

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@ test_annotation:
2121
try
2222
rethrow 0
2323
catch __cpp_exception
24+
catch_all
2425
block
2526
try
2627
br 0
28+
try
29+
delegate 1
2730
catch_all
2831
end_try
2932
end_block
@@ -46,9 +49,12 @@ test_annotation:
4649
# CHECK-NEXT: try
4750
# CHECK-NEXT: rethrow 0 # down to catch3
4851
# CHECK-NEXT: catch __cpp_exception # catch3:
52+
# CHECK-NEXT: catch_all{{$}}
4953
# CHECK-NEXT: block
5054
# CHECK-NEXT: try
5155
# CHECK-NEXT: br 0 # 0: down to label5
56+
# CHECK-NEXT: try
57+
# CHECK-NEXT: delegate 1 # label/catch6: down to catch4
5258
# CHECK-NEXT: catch_all # catch5:
5359
# CHECK-NEXT: end_try # label5:
5460
# CHECK-NEXT: end_block # label4:

llvm/test/MC/WebAssembly/basic-assembly-errors.s

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,16 @@ test0:
1818
# CHECK: Block construct type mismatch, expected: end_block, instead got: end_if
1919
end_if
2020
try
21+
# CHECK: Block construct type mismatch, expected: end_try/delegate, instead got: end_block
22+
end_block
2123
loop
22-
# CHECK: Block construct type mismatch, expected: end_loop, instead got: end_function
24+
try
25+
catch_all
26+
catch_all
27+
# CHECK: error: Block construct type mismatch, expected: end_try, instead got: catch_all
28+
end
29+
# CHECK: Block construct type mismatch, expected: end_try, instead got: end_function
30+
# CHECK: error: Unmatched block construct(s) at function end: catch_all
2331
# CHECK: error: Unmatched block construct(s) at function end: loop
2432
# CHECK: error: Unmatched block construct(s) at function end: try
2533
# CHECK: error: Unmatched block construct(s) at function end: block

0 commit comments

Comments
 (0)