From: Heejin Ahn Date: Wed, 13 Mar 2019 00:37:31 +0000 (+0000) Subject: [WebAssembly] Place 'try' and 'catch' correctly wrt EH_LABELs X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=81f5bd5c0879249c79113f8e10fd566a23110579;p=llvm [WebAssembly] Place 'try' and 'catch' correctly wrt EH_LABELs Summary: After instruction selection phase, possibly-throwing calls, which were previously invoke, are wrapped in `EH_LABEL` instructions. For example: ``` EH_LABEL CALL_VOID @foo ... EH_LABEL ``` `EH_LABEL` is placed also in the beginning of EH pads: ``` bb.1 (landing-pad): EH_LABEL ... ``` And we'd like to maintian this relationship, so when we place a `try`, ``` TRY ... EH_LABEL CALL_VOID @foo ... EH_LABEL ``` When we place a `catch`, ``` bb.1 (landing-pad): EH_LABEL %0:except_ref = CATCH ... ... ``` Previously we didn't treat EH_LABELs specially, so `try` was placed right before a call, and `catch` was placed in the beginning of an EH pad. Reviewers: dschuff Subscribers: sbc100, jgravelle-google, sunfish, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D58914 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@355996 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp index 6002885b9e9..65cc088cd27 100644 --- a/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp +++ b/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp @@ -543,6 +543,11 @@ void WebAssemblyCFGStackify::placeTryMarker(MachineBasicBlock &MBB) { for (const auto &MI : reverse(*Header)) { if (MI.isCall()) { AfterSet.insert(&MI); + // Possibly throwing calls are usually wrapped by EH_LABEL + // instructions. We don't want to split them and the call. + if (MI.getIterator() != Header->begin() && + std::prev(MI.getIterator())->isEHLabel()) + AfterSet.insert(&*std::prev(MI.getIterator())); break; } } diff --git a/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp b/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp index 6cda1cc64dd..603b717812e 100644 --- a/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp +++ b/lib/Target/WebAssembly/WebAssemblyLateEHPrepare.cpp @@ -21,7 +21,7 @@ #include "llvm/MC/MCAsmInfo.h" using namespace llvm; -#define DEBUG_TYPE "wasm-exception-prepare" +#define DEBUG_TYPE "wasm-late-eh-prepare" namespace { class WebAssemblyLateEHPrepare final : public MachineFunctionPass { @@ -185,9 +185,12 @@ bool WebAssemblyLateEHPrepare::addCatches(MachineFunction &MF) { for (auto &MBB : MF) { if (MBB.isEHPad()) { Changed = true; + auto InsertPos = MBB.begin(); + if (InsertPos->isEHLabel()) // EH pad starts with an EH label + ++InsertPos; unsigned DstReg = MRI.createVirtualRegister(&WebAssembly::EXCEPT_REFRegClass); - BuildMI(MBB, MBB.begin(), MBB.begin()->getDebugLoc(), + BuildMI(MBB, InsertPos, MBB.begin()->getDebugLoc(), TII.get(WebAssembly::CATCH), DstReg); } } @@ -255,7 +258,11 @@ bool WebAssemblyLateEHPrepare::addExceptionExtraction(MachineFunction &MF) { for (auto *Extract : ExtractInstrs) { MachineBasicBlock *EHPad = getMatchingEHPad(Extract); assert(EHPad && "No matching EH pad for extract_exception"); - MachineInstr *Catch = &*EHPad->begin(); + auto CatchPos = EHPad->begin(); + if (CatchPos->isEHLabel()) // EH pad starts with an EH label + ++CatchPos; + MachineInstr *Catch = &*CatchPos; + if (Catch->getNextNode() != Extract) EHPad->insert(Catch->getNextNode(), Extract->removeFromParent()); @@ -359,8 +366,10 @@ bool WebAssemblyLateEHPrepare::restoreStackPointer(MachineFunction &MF) { // with leaf functions, and we don't restore __stack_pointer in leaf // functions anyway. auto InsertPos = MBB.begin(); - if (MBB.begin()->getOpcode() == WebAssembly::CATCH) - InsertPos++; + if (InsertPos->isEHLabel()) // EH pad starts with an EH label + ++InsertPos; + if (InsertPos->getOpcode() == WebAssembly::CATCH) + ++InsertPos; FrameLowering->writeSPToGlobal(WebAssembly::SP32, MF, MBB, InsertPos, MBB.begin()->getDebugLoc()); } diff --git a/test/CodeGen/WebAssembly/eh-labels.mir b/test/CodeGen/WebAssembly/eh-labels.mir new file mode 100644 index 00000000000..015276475cc --- /dev/null +++ b/test/CodeGen/WebAssembly/eh-labels.mir @@ -0,0 +1,46 @@ +# RUN: llc -mtriple=wasm32-unknown-unknown -exception-model=wasm -mattr=+exception-handling -run-pass wasm-late-eh-prepare -run-pass wasm-cfg-stackify %s -o - | FileCheck %s + +# This tests 'try' and 'catch' instructions are correctly placed with respect to +# EH_LABEL instructions. +--- | + target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" + target triple = "wasm32-unknown-unknown" + + declare i32 @__gxx_wasm_personality_v0(...) + declare void @foo() + define void @eh_label_test() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { + ret void + } +... + +--- +# CHECK-LABEL: eh_label_test +name: eh_label_test +liveins: + - { reg: '$arguments' } +body: | + bb.0: + ; TRY should be before EH_LABEL wrappers of throwing calls + ; CHECK: TRY + ; CHECK-NEXT: EH_LABEL + ; CHECK-NEXT: CALL_VOID @foo + ; CHECK-NEXT: EH_LABEL + successors: %bb.1, %bb.2 + EH_LABEL + CALL_VOID @foo, implicit-def dead $arguments, implicit $sp32, implicit $sp64 + EH_LABEL + + bb.1 (landing-pad): + ; predecessors: %bb.0 + successors: %bb.2 + ; CATCH should be after an EH_LABEL at the beginning of an EH pad + ; CHECK: EH_LABEL + ; CHECK-NEXT: CATCH + EH_LABEL + dead %0:i32 = EXTRACT_EXCEPTION_I32 implicit-def dead $arguments + CATCHRET %bb.2, %bb.0, implicit-def dead $arguments + + bb.2: + ; predecessors: %bb.0, %bb.1 + RETURN_VOID implicit-def dead $arguments +...