From 6f2999b36a6e4834966fd5cde3aba4d296a2de97 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Thu, 18 Feb 2021 09:21:33 -0800 Subject: [PATCH] [WebAssembly] Handle multiple EH_LABELs in EH pad Usually `EH_LABEL`s are placed in - Before an `invoke` (which becomes calls in the backend) - After an `invoke` - At the start of an EH pad I don't know exactly why, but I noticed there are cases of multiple, not a single, `EH_LABEL` instructions in the beginning of an EH pad. In that case `global.set` instruction placed to restore `__stack_pointer` ended up between two `EH_LABEL` instructions before `CATCH`. It should follow after the `EH_LABEL`s and `CATCH`. This CL fixes that case. Reviewed By: dschuff Differential Revision: https://reviews.llvm.org/D96970 --- llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp | 13 ++++++++----- llvm/test/CodeGen/WebAssembly/exception.mir | 9 ++++++++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp index e07dae6..629abc0 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp @@ -212,7 +212,7 @@ bool WebAssemblyLateEHPrepare::addCatchAlls(MachineFunction &MF) { while (InsertPos != MBB.end() && InsertPos->isEHLabel()) InsertPos++; // This runs after hoistCatches(), so we assume that if there is a catch, - // that should be the non-EH label first instruction in an EH pad. + // that should be the first non-EH-label instruction in an EH pad. if (InsertPos == MBB.end() || !WebAssembly::isCatch(InsertPos->getOpcode())) { Changed = true; @@ -383,10 +383,13 @@ bool WebAssemblyLateEHPrepare::restoreStackPointer(MachineFunction &MF) { // with leaf functions, and we don't restore __stack_pointer in leaf // functions anyway. auto InsertPos = MBB.begin(); - if (InsertPos->isEHLabel()) // EH pad starts with an EH label - ++InsertPos; - if (WebAssembly::isCatch(InsertPos->getOpcode())) - ++InsertPos; + // Skip EH_LABELs in the beginning of an EH pad if present. + while (InsertPos != MBB.end() && InsertPos->isEHLabel()) + InsertPos++; + assert(InsertPos != MBB.end() && + WebAssembly::isCatch(InsertPos->getOpcode()) && + "catch/catch_all should be present in every EH pad at this point"); + ++InsertPos; // Skip the catch instruction FrameLowering->writeSPToGlobal(FrameLowering->getSPReg(MF), MF, MBB, InsertPos, MBB.begin()->getDebugLoc()); } diff --git a/llvm/test/CodeGen/WebAssembly/exception.mir b/llvm/test/CodeGen/WebAssembly/exception.mir index e0dc59f..a66e2e0 100644 --- a/llvm/test/CodeGen/WebAssembly/exception.mir +++ b/llvm/test/CodeGen/WebAssembly/exception.mir @@ -24,6 +24,8 @@ name: eh_label_test liveins: - { reg: '$arguments' } +frameInfo: + hasCalls: true body: | bb.0: ; TRY should be before EH_LABEL wrappers of throwing calls @@ -41,10 +43,15 @@ body: | bb.1 (landing-pad): ; predecessors: %bb.0 successors: %bb.2 - ; CATCH_ALL should be after an EH_LABEL at the beginning of an EH pad + ; CATCH_ALL should be after EH_LABELs in the beginning of an EH pad. + ; (Sometimes there are multiple EH_LABELs in an EH pad. This test tests + ; that.) GLOBAL_SET should follow right after that. ; CHECK: bb.1 ; CHECK: EH_LABEL + ; CHECK: EH_LABEL ; CHECK-NEXT: CATCH_ALL + ; CHECK-NEXT: GLOBAL_SET_I32 + EH_LABEL EH_LABEL CATCHRET %bb.2, %bb.1, implicit-def dead $arguments -- 2.7.4