forked from OSchip/llvm-project
[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
This commit is contained in:
parent
4af73572c7
commit
5afdd64a53
|
@ -216,6 +216,7 @@ class WebAssemblyAsmParser final : public MCTargetAsmParser {
|
||||||
Block,
|
Block,
|
||||||
Loop,
|
Loop,
|
||||||
Try,
|
Try,
|
||||||
|
CatchAll,
|
||||||
If,
|
If,
|
||||||
Else,
|
Else,
|
||||||
Undefined,
|
Undefined,
|
||||||
|
@ -273,7 +274,9 @@ public:
|
||||||
case Loop:
|
case Loop:
|
||||||
return {"loop", "end_loop"};
|
return {"loop", "end_loop"};
|
||||||
case Try:
|
case Try:
|
||||||
return {"try", "end_try"};
|
return {"try", "end_try/delegate"};
|
||||||
|
case CatchAll:
|
||||||
|
return {"catch_all", "end_try"};
|
||||||
case If:
|
case If:
|
||||||
return {"if", "end_if"};
|
return {"if", "end_if"};
|
||||||
case Else:
|
case Else:
|
||||||
|
@ -533,10 +536,17 @@ public:
|
||||||
if (pop(Name, Try))
|
if (pop(Name, Try))
|
||||||
return true;
|
return true;
|
||||||
push(Try);
|
push(Try);
|
||||||
|
} else if (Name == "catch_all") {
|
||||||
|
if (pop(Name, Try))
|
||||||
|
return true;
|
||||||
|
push(CatchAll);
|
||||||
} else if (Name == "end_if") {
|
} else if (Name == "end_if") {
|
||||||
if (pop(Name, If, Else))
|
if (pop(Name, If, Else))
|
||||||
return true;
|
return true;
|
||||||
} else if (Name == "end_try") {
|
} else if (Name == "end_try") {
|
||||||
|
if (pop(Name, Try, CatchAll))
|
||||||
|
return true;
|
||||||
|
} else if (Name == "delegate") {
|
||||||
if (pop(Name, Try))
|
if (pop(Name, Try))
|
||||||
return true;
|
return true;
|
||||||
} else if (Name == "end_loop") {
|
} else if (Name == "end_loop") {
|
||||||
|
|
|
@ -108,6 +108,7 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, uint64_t Address,
|
||||||
ControlFlowStack.push_back(std::make_pair(ControlFlowCounter, false));
|
ControlFlowStack.push_back(std::make_pair(ControlFlowCounter, false));
|
||||||
EHPadStack.push_back(ControlFlowCounter);
|
EHPadStack.push_back(ControlFlowCounter);
|
||||||
DelegateStack.push_back(ControlFlowCounter++);
|
DelegateStack.push_back(ControlFlowCounter++);
|
||||||
|
EHInstStack.push_back(TRY);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case WebAssembly::END_LOOP:
|
case WebAssembly::END_LOOP:
|
||||||
|
@ -133,11 +134,12 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, uint64_t Address,
|
||||||
|
|
||||||
case WebAssembly::END_TRY:
|
case WebAssembly::END_TRY:
|
||||||
case WebAssembly::END_TRY_S:
|
case WebAssembly::END_TRY_S:
|
||||||
if (ControlFlowStack.empty()) {
|
if (ControlFlowStack.empty() || EHInstStack.empty()) {
|
||||||
printAnnotation(OS, "End marker mismatch!");
|
printAnnotation(OS, "End marker mismatch!");
|
||||||
} else {
|
} else {
|
||||||
printAnnotation(
|
printAnnotation(
|
||||||
OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':');
|
OS, "label" + utostr(ControlFlowStack.pop_back_val().first) + ':');
|
||||||
|
EHInstStack.pop_back();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -145,12 +147,27 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, uint64_t Address,
|
||||||
case WebAssembly::CATCH_S:
|
case WebAssembly::CATCH_S:
|
||||||
case WebAssembly::CATCH_ALL:
|
case WebAssembly::CATCH_ALL:
|
||||||
case WebAssembly::CATCH_ALL_S:
|
case WebAssembly::CATCH_ALL_S:
|
||||||
|
// There can be multiple catch instructions for one try instruction, so
|
||||||
|
// we print a label only for the first 'catch' label.
|
||||||
|
if (EHInstStack.empty()) {
|
||||||
|
printAnnotation(OS, "try-catch mismatch!");
|
||||||
|
} else if (EHInstStack.back() == CATCH_ALL) {
|
||||||
|
printAnnotation(OS, "catch/catch_all cannot occur after catch_all");
|
||||||
|
} else if (EHInstStack.back() == TRY) {
|
||||||
if (EHPadStack.empty() || DelegateStack.empty()) {
|
if (EHPadStack.empty() || DelegateStack.empty()) {
|
||||||
printAnnotation(OS, "try-catch mismatch!");
|
printAnnotation(OS, "try-catch mismatch!");
|
||||||
} else {
|
} else {
|
||||||
printAnnotation(OS, "catch" + utostr(EHPadStack.pop_back_val()) + ':');
|
printAnnotation(OS,
|
||||||
|
"catch" + utostr(EHPadStack.pop_back_val()) + ':');
|
||||||
DelegateStack.pop_back();
|
DelegateStack.pop_back();
|
||||||
}
|
}
|
||||||
|
EHInstStack.pop_back();
|
||||||
|
if (Opc == WebAssembly::CATCH || Opc == WebAssembly::CATCH_S) {
|
||||||
|
EHInstStack.push_back(CATCH);
|
||||||
|
} else {
|
||||||
|
EHInstStack.push_back(CATCH_ALL);
|
||||||
|
}
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case WebAssembly::RETHROW:
|
case WebAssembly::RETHROW:
|
||||||
|
@ -167,7 +184,7 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, uint64_t Address,
|
||||||
case WebAssembly::DELEGATE:
|
case WebAssembly::DELEGATE:
|
||||||
case WebAssembly::DELEGATE_S:
|
case WebAssembly::DELEGATE_S:
|
||||||
if (ControlFlowStack.empty() || EHPadStack.empty() ||
|
if (ControlFlowStack.empty() || EHPadStack.empty() ||
|
||||||
DelegateStack.empty()) {
|
DelegateStack.empty() || EHInstStack.empty()) {
|
||||||
printAnnotation(OS, "try-delegate mismatch!");
|
printAnnotation(OS, "try-delegate mismatch!");
|
||||||
} else {
|
} else {
|
||||||
// 'delegate' is
|
// 'delegate' is
|
||||||
|
@ -181,6 +198,7 @@ void WebAssemblyInstPrinter::printInst(const MCInst *MI, uint64_t Address,
|
||||||
": ";
|
": ";
|
||||||
EHPadStack.pop_back();
|
EHPadStack.pop_back();
|
||||||
DelegateStack.pop_back();
|
DelegateStack.pop_back();
|
||||||
|
EHInstStack.pop_back();
|
||||||
uint64_t Depth = MI->getOperand(0).getImm();
|
uint64_t Depth = MI->getOperand(0).getImm();
|
||||||
if (Depth >= DelegateStack.size()) {
|
if (Depth >= DelegateStack.size()) {
|
||||||
Label += "to caller";
|
Label += "to caller";
|
||||||
|
|
|
@ -33,6 +33,9 @@ class WebAssemblyInstPrinter final : public MCInstPrinter {
|
||||||
// separate stack for 'delegate'.
|
// separate stack for 'delegate'.
|
||||||
SmallVector<uint64_t, 4> DelegateStack;
|
SmallVector<uint64_t, 4> DelegateStack;
|
||||||
|
|
||||||
|
enum EHInstKind { TRY, CATCH, CATCH_ALL };
|
||||||
|
SmallVector<EHInstKind, 4> EHInstStack;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WebAssemblyInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
|
WebAssemblyInstPrinter(const MCAsmInfo &MAI, const MCInstrInfo &MII,
|
||||||
const MCRegisterInfo &MRI);
|
const MCRegisterInfo &MRI);
|
||||||
|
|
|
@ -21,9 +21,12 @@ test_annotation:
|
||||||
try
|
try
|
||||||
rethrow 0
|
rethrow 0
|
||||||
catch __cpp_exception
|
catch __cpp_exception
|
||||||
|
catch_all
|
||||||
block
|
block
|
||||||
try
|
try
|
||||||
br 0
|
br 0
|
||||||
|
try
|
||||||
|
delegate 1
|
||||||
catch_all
|
catch_all
|
||||||
end_try
|
end_try
|
||||||
end_block
|
end_block
|
||||||
|
@ -46,9 +49,12 @@ test_annotation:
|
||||||
# CHECK-NEXT: try
|
# CHECK-NEXT: try
|
||||||
# CHECK-NEXT: rethrow 0 # down to catch3
|
# CHECK-NEXT: rethrow 0 # down to catch3
|
||||||
# CHECK-NEXT: catch __cpp_exception # catch3:
|
# CHECK-NEXT: catch __cpp_exception # catch3:
|
||||||
|
# CHECK-NEXT: catch_all{{$}}
|
||||||
# CHECK-NEXT: block
|
# CHECK-NEXT: block
|
||||||
# CHECK-NEXT: try
|
# CHECK-NEXT: try
|
||||||
# CHECK-NEXT: br 0 # 0: down to label5
|
# CHECK-NEXT: br 0 # 0: down to label5
|
||||||
|
# CHECK-NEXT: try
|
||||||
|
# CHECK-NEXT: delegate 1 # label/catch6: down to catch4
|
||||||
# CHECK-NEXT: catch_all # catch5:
|
# CHECK-NEXT: catch_all # catch5:
|
||||||
# CHECK-NEXT: end_try # label5:
|
# CHECK-NEXT: end_try # label5:
|
||||||
# CHECK-NEXT: end_block # label4:
|
# CHECK-NEXT: end_block # label4:
|
||||||
|
|
|
@ -18,8 +18,16 @@ test0:
|
||||||
# CHECK: Block construct type mismatch, expected: end_block, instead got: end_if
|
# CHECK: Block construct type mismatch, expected: end_block, instead got: end_if
|
||||||
end_if
|
end_if
|
||||||
try
|
try
|
||||||
|
# CHECK: Block construct type mismatch, expected: end_try/delegate, instead got: end_block
|
||||||
|
end_block
|
||||||
loop
|
loop
|
||||||
# CHECK: Block construct type mismatch, expected: end_loop, instead got: end_function
|
try
|
||||||
|
catch_all
|
||||||
|
catch_all
|
||||||
|
# CHECK: error: Block construct type mismatch, expected: end_try, instead got: catch_all
|
||||||
|
end
|
||||||
|
# CHECK: Block construct type mismatch, expected: end_try, instead got: end_function
|
||||||
|
# CHECK: error: Unmatched block construct(s) at function end: catch_all
|
||||||
# CHECK: error: Unmatched block construct(s) at function end: loop
|
# CHECK: error: Unmatched block construct(s) at function end: loop
|
||||||
# CHECK: error: Unmatched block construct(s) at function end: try
|
# CHECK: error: Unmatched block construct(s) at function end: try
|
||||||
# CHECK: error: Unmatched block construct(s) at function end: block
|
# CHECK: error: Unmatched block construct(s) at function end: block
|
||||||
|
|
Loading…
Reference in New Issue