@@ -2506,6 +2506,93 @@ bool Compiler::fgNormalizeEHCase2()
25062506 return modified;
25072507}
25082508
2509+ // ------------------------------------------------------------------------
2510+ // fgCreateFiltersForGenericExceptions:
2511+ // For Exception types which require runtime lookup it creates a "fake" single-block
2512+ // EH filter that performs "catchArg isinst T!!" and in case of success forwards to the
2513+ // original EH handler.
2514+ //
2515+
2516+ void Compiler::fgCreateFiltersForGenericExceptions ()
2517+ {
2518+ for (unsigned ehNum = 0 ; ehNum < compHndBBtabCount; ehNum++)
2519+ {
2520+ EHblkDsc* eh = ehGetDsc (ehNum);
2521+ if (eh->ebdHandlerType == EH_HANDLER_CATCH)
2522+ {
2523+ // Resolve Exception type and check if it needs a runtime lookup
2524+ CORINFO_RESOLVED_TOKEN resolvedToken;
2525+ resolvedToken.tokenContext = impTokenLookupContextHandle;
2526+ resolvedToken.tokenScope = info.compScopeHnd ;
2527+ resolvedToken.token = eh->ebdTyp ;
2528+ resolvedToken.tokenType = CORINFO_TOKENKIND_Casting;
2529+ info.compCompHnd ->resolveToken (&resolvedToken);
2530+
2531+ CORINFO_GENERICHANDLE_RESULT embedInfo;
2532+ info.compCompHnd ->embedGenericHandle (&resolvedToken, true , &embedInfo);
2533+ if (!embedInfo.lookup .lookupKind .needsRuntimeLookup )
2534+ {
2535+ // Exception type does not need runtime lookup
2536+ continue ;
2537+ }
2538+
2539+ // Create a new bb for the fake filter
2540+ BasicBlock* filterBb = bbNewBasicBlock (BBJ_EHFILTERRET);
2541+ BasicBlock* handlerBb = eh->ebdHndBeg ;
2542+
2543+ // Now we need to spill CATCH_ARG (it should be the first thing evaluated)
2544+ GenTree* arg = new (this , GT_CATCH_ARG) GenTree (GT_CATCH_ARG, TYP_REF);
2545+ arg->gtFlags |= GTF_ORDER_SIDEEFF;
2546+ unsigned tempNum = lvaGrabTemp (false DEBUGARG (" SpillCatchArg" ));
2547+ lvaTable[tempNum].lvType = TYP_REF;
2548+ GenTree* argAsg = gtNewTempAssign (tempNum, arg);
2549+ arg = gtNewLclvNode (tempNum, TYP_REF);
2550+ fgInsertStmtAtBeg (filterBb, gtNewStmt (argAsg, handlerBb->firstStmt ()->GetDebugInfo ()));
2551+
2552+ // Create "catchArg is TException" tree
2553+ GenTree* runtimeLookup;
2554+ if (embedInfo.lookup .runtimeLookup .indirections == CORINFO_USEHELPER)
2555+ {
2556+ GenTree* ctxTree = getRuntimeContextTree (embedInfo.lookup .lookupKind .runtimeLookupKind );
2557+ runtimeLookup = impReadyToRunHelperToTree (&resolvedToken, CORINFO_HELP_READYTORUN_GENERIC_HANDLE,
2558+ TYP_I_IMPL, &embedInfo.lookup .lookupKind , ctxTree);
2559+ }
2560+ else
2561+ {
2562+ runtimeLookup = getTokenHandleTree (&resolvedToken, true );
2563+ }
2564+ GenTree* isInstOfT = gtNewHelperCallNode (CORINFO_HELP_ISINSTANCEOF_EXCEPTION, TYP_INT, runtimeLookup, arg);
2565+ GenTree* retFilt = gtNewOperNode (GT_RETFILT, TYP_INT, isInstOfT);
2566+
2567+ // Insert it right before the handler (and make it a pred of the handler)
2568+ fgInsertBBbefore (handlerBb, filterBb);
2569+ fgAddRefPred (handlerBb, filterBb);
2570+ fgNewStmtAtEnd (filterBb, retFilt, handlerBb->firstStmt ()->GetDebugInfo ());
2571+
2572+ filterBb->bbCatchTyp = BBCT_FILTER;
2573+ filterBb->bbCodeOffs = handlerBb->bbCodeOffs ;
2574+ filterBb->bbHndIndex = handlerBb->bbHndIndex ;
2575+ filterBb->bbTryIndex = handlerBb->bbTryIndex ;
2576+ filterBb->bbJumpDest = handlerBb;
2577+ filterBb->bbSetRunRarely ();
2578+ filterBb->bbFlags |= BBF_INTERNAL | BBF_DONT_REMOVE;
2579+
2580+ handlerBb->bbCatchTyp = BBCT_FILTER_HANDLER;
2581+ eh->ebdHandlerType = EH_HANDLER_FILTER;
2582+ eh->ebdFilter = filterBb;
2583+
2584+ #ifdef DEBUG
2585+ if (verbose)
2586+ {
2587+ JITDUMP (" EH%d: Adding EH filter block " FMT_BB " in front of generic handler " FMT_BB " :\n " , ehNum,
2588+ filterBb->bbNum , handlerBb->bbNum );
2589+ fgDumpBlock (filterBb);
2590+ }
2591+ #endif // DEBUG
2592+ }
2593+ }
2594+ }
2595+
25092596bool Compiler::fgNormalizeEHCase3 ()
25102597{
25112598 bool modified = false ;
0 commit comments