From a0aea0e006a0046e20c3380d1cfa83a6e6d44806 Mon Sep 17 00:00:00 2001 From: Heejin Ahn Date: Wed, 27 Feb 2019 01:35:14 +0000 Subject: [PATCH] [WebAssembly] Fix ScopeTops info in CFGStackify for EH pads Summary: When creating `ScopeTops` info for `try` ~ `catch` ~ `end_try`, we should create not only `end_try` -> `try` mapping but also `catch` -> `try` mapping as well. If this is not created, `block` and `end_block` markers later added may span across an existing `catch`, resulting in the incorrect code like: ``` try block --| (X) catch | end_block --| end_try ``` Reviewers: dschuff Subscribers: sunfish, sbc100, jgravelle-google, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D58605 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@354945 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp | 21 +++++++++--- test/CodeGen/WebAssembly/cfg-stackify-eh.ll | 39 ++++++++++++++++++++++- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp b/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp index 90017879839..35ca7b9753b 100644 --- a/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp +++ b/lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp @@ -594,11 +594,22 @@ void WebAssemblyCFGStackify::placeTryMarker(MachineBasicBlock &MBB) { TII.get(WebAssembly::END_TRY)); registerTryScope(Begin, End, &MBB); - // Track the farthest-spanning scope that ends at this point. - int Number = Cont->getNumber(); - if (!ScopeTops[Number] || - ScopeTops[Number]->getNumber() > Header->getNumber()) - ScopeTops[Number] = Header; + // Track the farthest-spanning scope that ends at this point. We create two + // mappings: (BB with 'end_try' -> BB with 'try') and (BB with 'catch' -> BB + // with 'try'). We need to create 'catch' -> 'try' mapping here too because + // markers should not span across 'catch'. For example, this should not + // happen: + // + // try + // block --| (X) + // catch | + // end_block --| + // end_try + for (int Number : {Cont->getNumber(), MBB.getNumber()}) { + if (!ScopeTops[Number] || + ScopeTops[Number]->getNumber() > Header->getNumber()) + ScopeTops[Number] = Header; + } } void WebAssemblyCFGStackify::removeUnnecessaryInstrs(MachineFunction &MF) { diff --git a/test/CodeGen/WebAssembly/cfg-stackify-eh.ll b/test/CodeGen/WebAssembly/cfg-stackify-eh.ll index 8e9933471b7..ed1996f7284 100644 --- a/test/CodeGen/WebAssembly/cfg-stackify-eh.ll +++ b/test/CodeGen/WebAssembly/cfg-stackify-eh.ll @@ -88,7 +88,44 @@ try.cont: ; preds = %entry, %catch, %cat ; } ; CHECK-LABEL: test1 -; TODO Fill in CHECK lines once we fix ScopeTops info bug in D58605 +; CHECK: try +; CHECK: call foo +; CHECK: catch +; CHECK: block +; CHECK: block +; CHECK: br_if 0, {{.*}} # 0: down to label7 +; CHECK: i32.call $drop=, __cxa_begin_catch +; CHECK: try +; CHECK: call foo +; CHECK: br 2 # 2: down to label6 +; CHECK: catch +; CHECK: try +; CHECK: block +; CHECK: br_if 0, {{.*}} # 0: down to label11 +; CHECK: i32.call $drop=, __cxa_begin_catch +; CHECK: try +; CHECK: call foo +; CHECK: br 2 # 2: down to label10 +; CHECK: catch +; CHECK: call __cxa_end_catch +; CHECK: rethrow # down to catch3 +; CHECK: end_try +; CHECK: end_block # label11: +; CHECK: call __cxa_rethrow +; CHECK: unreachable +; CHECK: catch {{.*}} # catch3: +; CHECK: call __cxa_end_catch +; CHECK: rethrow # to caller +; CHECK: end_try # label10: +; CHECK: call __cxa_end_catch +; CHECK: br 2 # 2: down to label6 +; CHECK: end_try +; CHECK: end_block # label7: +; CHECK: call __cxa_rethrow +; CHECK: unreachable +; CHECK: end_block # label6: +; CHECK: call __cxa_end_catch +; CHECK: end_try define void @test1() personality i8* bitcast (i32 (...)* @__gxx_wasm_personality_v0 to i8*) { entry: invoke void @foo() -- 2.11.0