Linearing the control flow by placing try/end_try markers can create
mismatches in unwind destinations. This patch resolves these mismatches
by wrapping those instructions with an incorrect unwind destination with
a nested try/catch/end_try and branching to the right destination
within the new catch block.
Details
Diff Detail
- Repository
- rL LLVM
- Build Status
Buildable 29361 Build 29360: arc lint + arc unit
Event Timeline
Continuing the discussion started in the email:
I think it's better not to split this pass as a separate pass. The reasons are:
- Now CFGStackify pass maintains several internal maps (ScopeTops, BeginToEnd, EndToBegin, TryToEHPad, EHPadToTry, and BeginToBottom) to keep track of start/end markers, and entries are added to these maps and queried both in CFGStackify and namely, FixUnwindMismatch pass. So these maps have to be maintained in both passes, and also, we have to either carry that information using auxiliary data structure or we have to recalculate these maps at the end of FixUnwindMatch, which is more work.
- Now CFGStackify also has several helper functions (registerScope(), registerTryScope(), and unregisterScope()) that help add and delete entries to various maps I mentioned in 1. We need these utility function in both passes.
- rewriteDepthImmediate() and fixEndsAtEndOfFunction() functions run at the end of CFGStackify. But because we change CFG in FixUnwindMatch pass as well, they should rather run at the end of FixUnwindMatch pass now. This looks a bit weird bcause FixUnwindMatch pass should only run for functions that have a personality function (or an EH pad). And also intuitively rewriting depth immediates is not a part of FixUnwindMatch but CFGStackify.
Also, if we can bear with CFGStackify file getting a bit longer, I think the two parts are kind of well divided and factorized into functions.
lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp | ||
---|---|---|
75 | This comment is pretty vague. I guess this is one block for each function, and is now shared for creating a correct signature for fallthrough returns, and to use as a target for rethrows that need to unwind to the caller, but are trapped inside an outer try/catch? | |
694 | s/Linearing/Linearizing | |
730 | s/boy/body | |
764 | remove the period after "block" | |
834 | It seems unfortunate that we have to care about whether explicit locals is turned on. Is that just because this pass runs after createWebAssemblyExplicitLocals? Does the order matter? e.g. would it be simpler to run it after CfgStackify? Or, could we just run it again if this pass changes anything? | |
869 | continue here will just skip to the next instruction, but the comment says it will skip the rest of the BB (which makes sense), should this be break instead? Or do we need to keep going to find the try/catch? | |
943 | s/don't/don't have | |
1012 | these could be else if? | |
test/CodeGen/WebAssembly/cfg-stackify-eh-mismatch.ll | ||
42 | Any weird corner cases it would be worthwhile to test for? Mixing both kinds of mismatches? A case with uwind-to-caller and block signature needed? Would multiple nesting of mismatches affect what happens? |
Addressed simple comments first.
Things I haven't addressed yet:
- Add more test cases
- Switch ExplicitLocal pass order?
lib/Target/WebAssembly/WebAssemblyCFGStackify.cpp | ||
---|---|---|
75 | Yes. Updated the comments. | |
869 | Right. It can't be break because we still need to process this part and update EHPadStack. if (MI.getOpcode() == WebAssembly::TRY) EHPadStack.pop_back(); else if (MI.getOpcode() == WebAssembly::CATCH) EHPadStack.push_back(MI.getParent()); | |
1012 | Changed to switch-case. |
Now after D59652 we don't need the separate code (and separate test commands) for when -wasm-disable-explicit-locals is set and it is not. Will fix it soon.
- Deleted all logics related to -wasm-disable-explicit-locals thanks to D59652
- Fix several bugs
- Add more tests
test/CodeGen/WebAssembly/cfg-stackify-eh-mismatch.ll | ||
---|---|---|
42 | Add some more tests.
Note that -wasm-disable-ehpad-sort is used to generate maximum # of mismatches for those mismatch tests. |
test/CodeGen/WebAssembly/cfg-stackify-eh-mismatch.ll | ||
---|---|---|
42 | Oh and please also note that I deleted this file and moved all tests to cfg-stackify-eh.ll. |
This comment is pretty vague. I guess this is one block for each function, and is now shared for creating a correct signature for fallthrough returns, and to use as a target for rethrows that need to unwind to the caller, but are trapped inside an outer try/catch?