source: src/ControlStruct/ExceptTranslate.cc @ cbce272

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since cbce272 was cbce272, checked in by Andrew Beach <ajbeach@…>, 7 years ago

Structure based exception handling.

  • Property mode set to 100644
File size: 20.6 KB
RevLine 
[ba912706]1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// ExceptVisitor.cc --
8//
9// Author           : Andrew Beach
10// Created On       : Wed Jun 14 16:49:00 2017
11// Last Modified By : Andrew Beach
[cbce272]12// Last Modified On : Tus Aug  8 16:54:00 2017
[948b0c8]13// Update Count     : 7
[ba912706]14//
15
16#include "ExceptTranslate.h"
17#include "Common/PassVisitor.h"
[288eede]18#include "SynTree/Statement.h"
19#include "SynTree/Declaration.h"
20#include "SynTree/Expression.h"
21#include "SynTree/Type.h"
22#include "SynTree/Attribute.h"
[86d5ba7c]23#include "SynTree/VarExprReplacer.h"
[ba912706]24
[307a732]25namespace ControlStruct {
[ba912706]26
[948b0c8]27        // Buricratic Helpers (Not having to do with the paritular operation.)
28
29        typedef std::list<CatchStmt*> CatchList;
30
31        void split( CatchList& allHandlers, CatchList& terHandlers,
32                                CatchList& resHandlers ) {
33                while ( !allHandlers.empty() ) {
34                        CatchStmt * stmt = allHandlers.front();
35                        allHandlers.pop_front();
36                        if (CatchStmt::Terminate == stmt->get_kind()) {
37                                terHandlers.push_back(stmt);
38                        } else {
39                                resHandlers.push_back(stmt);
40                        }
41                }
42        }
43
44        void appendDeclStmt( CompoundStmt * block, Declaration * item ) {
45                block->push_back(new DeclStmt(noLabels, item));
46        }
47
48        Expression * nameOf( DeclarationWithType * decl ) {
49                return new VariableExpr( decl );
50        }
51
52        class ExceptionMutatorCore : public WithGuards {
53                enum Context { NoHandler, TerHandler, ResHandler };
54
55                // Also need to handle goto, break & continue.
56                // They need to be cut off in a ResHandler, until we enter another
57                // loop, switch or the goto stays within the function.
58
59                Context cur_context;
60
61                // The current (innermost) termination handler exception declaration.
62                ObjectDecl * handler_except_decl;
63
64                // The built in types used in translation.
65                StructDecl * except_decl;
66                StructDecl * node_decl;
67                StructDecl * hook_decl;
68
69                // The many helper functions for code/syntree generation.
70                Statement * create_given_throw(
71                        const char * throwFunc, ThrowStmt * throwStmt );
72                Statement * create_terminate_throw( ThrowStmt * throwStmt );
73                Statement * create_terminate_rethrow( ThrowStmt * throwStmt );
74                Statement * create_resume_throw( ThrowStmt * throwStmt );
75                Statement * create_resume_rethrow( ThrowStmt * throwStmt );
76                CompoundStmt * take_try_block( TryStmt * tryStmt );
77                FunctionDecl * create_try_wrapper( CompoundStmt * body );
78                FunctionDecl * create_terminate_catch( CatchList &handlers );
79                CompoundStmt * create_single_matcher(
80                        DeclarationWithType * except_obj, CatchStmt * modded_handler );
81                FunctionDecl * create_terminate_match( CatchList &handlers );
82                CompoundStmt * create_terminate_caller( FunctionDecl * try_wrapper,
83                        FunctionDecl * terminate_catch, FunctionDecl * terminate_match );
84                FunctionDecl * create_resume_handler( CatchList &handlers );
85                CompoundStmt * create_resume_wrapper(
86                        Statement * wraps, FunctionDecl * resume_handler );
87                FunctionDecl * create_finally_wrapper( TryStmt * tryStmt );
88                ObjectDecl * create_finally_hook( FunctionDecl * finally_wrapper );
89
90                // Types used in translation, make sure to use clone.
91                // void (*function)();
92                FunctionType try_func_t;
93                // void (*function)(int, exception);
94                FunctionType catch_func_t;
95                // int (*function)(exception);
96                FunctionType match_func_t;
97                // bool (*function)(exception);
98                FunctionType handle_func_t;
99                // void (*function)(__attribute__((unused)) void *);
100                FunctionType finally_func_t;
101
102                StructInstType * create_except_type() {
103                        assert( except_decl );
104                        return new StructInstType( noQualifiers, except_decl );
105                }
106                void init_func_types();
107
108        public:
109                ExceptionMutatorCore() :
110                        cur_context( NoHandler ),
111                        handler_except_decl( nullptr ),
112                        except_decl( nullptr ), node_decl( nullptr ), hook_decl( nullptr ),
113                        try_func_t( noQualifiers, false ),
114                        catch_func_t( noQualifiers, false ),
115                        match_func_t( noQualifiers, false ),
116                        handle_func_t( noQualifiers, false ),
117                        finally_func_t( noQualifiers, false )
[cbce272]118                {}
[948b0c8]119
120                void premutate( CatchStmt *catchStmt );
121                void premutate( StructDecl *structDecl );
122                Statement * postmutate( ThrowStmt *throwStmt );
123                Statement * postmutate( TryStmt *tryStmt );
124        };
125
126        void ExceptionMutatorCore::init_func_types() {
[cbce272]127                assert( except_decl );
128
[ba912706]129                ObjectDecl index_obj(
[288eede]130                        "__handler_index",
[ba912706]131                        Type::StorageClasses(),
132                        LinkageSpec::Cforall,
133                        /*bitfieldWidth*/ NULL,
[ac10576]134                        new BasicType( noQualifiers, BasicType::SignedInt ),
[ba912706]135                        /*init*/ NULL
[307a732]136                        );
[ba912706]137                ObjectDecl exception_obj(
[288eede]138                        "__exception_inst",
[ba912706]139                        Type::StorageClasses(),
140                        LinkageSpec::Cforall,
141                        /*bitfieldWidth*/ NULL,
[307a732]142                        new PointerType(
[ac10576]143                                noQualifiers,
[cbce272]144                                new StructInstType( noQualifiers, except_decl )
[307a732]145                                ),
[ba912706]146                        /*init*/ NULL
[307a732]147                        );
[ba912706]148                ObjectDecl bool_obj(
[288eede]149                        "__ret_bool",
[ba912706]150                        Type::StorageClasses(),
151                        LinkageSpec::Cforall,
152                        /*bitfieldWidth*/ NULL,
[948b0c8]153                        new BasicType( noQualifiers, BasicType::Bool ),
[ba912706]154                        /*init*/ NULL
[307a732]155                        );
156                ObjectDecl voidptr_obj(
157                        "__hook",
158                        Type::StorageClasses(),
159                        LinkageSpec::Cforall,
160                        NULL,
161                        new PointerType(
[ac10576]162                                noQualifiers,
[307a732]163                                new VoidType(
[ac10576]164                                        noQualifiers
[307a732]165                                        ),
[948b0c8]166                                std::list<Attribute *>{ new Attribute( "unused" ) }
[307a732]167                                ),
168                        NULL
169                        );
[ba912706]170
[307a732]171                catch_func_t.get_parameters().push_back( index_obj.clone() );
172                catch_func_t.get_parameters().push_back( exception_obj.clone() );
173                match_func_t.get_returnVals().push_back( index_obj.clone() );
174                match_func_t.get_parameters().push_back( exception_obj.clone() );
175                handle_func_t.get_returnVals().push_back( bool_obj.clone() );
176                handle_func_t.get_parameters().push_back( exception_obj.clone() );
177                finally_func_t.get_parameters().push_back( voidptr_obj.clone() );
[ba912706]178        }
179
180        // ThrowStmt Mutation Helpers
181
[948b0c8]182        Statement * ExceptionMutatorCore::create_given_throw(
[307a732]183                        const char * throwFunc, ThrowStmt * throwStmt ) {
[cbce272]184                // `throwFunc`( `throwStmt->get_name` );
[307a732]185                UntypedExpr * call = new UntypedExpr( new NameExpr( throwFunc ) );
[cbce272]186                call->get_args().push_back( throwStmt->get_expr() );
[ba912706]187                throwStmt->set_expr( nullptr );
188                delete throwStmt;
[cbce272]189                return new ExprStmt( noLabels, call );
[ba912706]190        }
[307a732]191
[948b0c8]192        Statement * ExceptionMutatorCore::create_terminate_throw(
193                        ThrowStmt *throwStmt ) {
[cbce272]194                // __throw_terminate( `throwStmt->get_name()` ); }
[38ac6ec]195                return create_given_throw( "__cfaehm__throw_terminate", throwStmt );
[307a732]196        }
[86d5ba7c]197
[948b0c8]198        Statement * ExceptionMutatorCore::create_terminate_rethrow(
199                        ThrowStmt *throwStmt ) {
[86d5ba7c]200                // { `handler_except_decl` = NULL; __rethrow_terminate(); }
[288eede]201                assert( nullptr == throwStmt->get_expr() );
[86d5ba7c]202                assert( handler_except_decl );
203
204                CompoundStmt * result = new CompoundStmt( throwStmt->get_labels() );
205                result->push_back( new ExprStmt( noLabels, UntypedExpr::createAssign(
206                        nameOf( handler_except_decl ),
207                        new ConstantExpr( Constant::null(
208                                new PointerType(
209                                        noQualifiers,
210                                        handler_except_decl->get_type()->clone()
211                                        )
212                                ) )
213                        ) ) );
214                result->push_back( new ExprStmt(
215                        noLabels,
[38ac6ec]216                        new UntypedExpr( new NameExpr( "__cfaehm__rethrow_terminate" ) )
[86d5ba7c]217                        ) );
[ba912706]218                delete throwStmt;
219                return result;
220        }
[86d5ba7c]221
[948b0c8]222        Statement * ExceptionMutatorCore::create_resume_throw(
223                        ThrowStmt *throwStmt ) {
[cbce272]224                // __throw_resume( `throwStmt->get_name` );
[38ac6ec]225                return create_given_throw( "__cfaehm__throw_resume", throwStmt );
[ba912706]226        }
[86d5ba7c]227
[948b0c8]228        Statement * ExceptionMutatorCore::create_resume_rethrow(
229                        ThrowStmt *throwStmt ) {
[ba912706]230                // return false;
231                Statement * result = new ReturnStmt(
232                        throwStmt->get_labels(),
[288eede]233                        new ConstantExpr( Constant::from_bool( false ) )
[ba912706]234                        );
235                delete throwStmt;
236                return result;
237        }
238
239        // TryStmt Mutation Helpers
240
[948b0c8]241        CompoundStmt * ExceptionMutatorCore::take_try_block( TryStmt *tryStmt ) {
[ba912706]242                CompoundStmt * block = tryStmt->get_block();
243                tryStmt->set_block( nullptr );
244                return block;
245        }
[948b0c8]246
247        FunctionDecl * ExceptionMutatorCore::create_try_wrapper(
248                        CompoundStmt *body ) {
[ba912706]249
[288eede]250                return new FunctionDecl( "try", Type::StorageClasses(),
[307a732]251                        LinkageSpec::Cforall, try_func_t.clone(), body );
[ba912706]252        }
253
[948b0c8]254        FunctionDecl * ExceptionMutatorCore::create_terminate_catch(
255                        CatchList &handlers ) {
[ba912706]256                std::list<CaseStmt *> handler_wrappers;
257
[288eede]258                FunctionType *func_type = catch_func_t.clone();
259                DeclarationWithType * index_obj = func_type->get_parameters().front();
[86d5ba7c]260                DeclarationWithType * except_obj = func_type->get_parameters().back();
[288eede]261
[ba912706]262                // Index 1..{number of handlers}
263                int index = 0;
264                CatchList::iterator it = handlers.begin();
265                for ( ; it != handlers.end() ; ++it ) {
266                        ++index;
267                        CatchStmt * handler = *it;
268
[288eede]269                        // case `index`:
270                        // {
[cbce272]271                        //     `handler.decl` = { (virtual `decl.type`)`except` };
272                        //     `handler.body`;
[288eede]273                        // }
274                        // return;
[86d5ba7c]275                        CompoundStmt * block = new CompoundStmt( noLabels );
276
[03eedd5]277                        // Just copy the exception value. (Post Validation)
[86d5ba7c]278                        ObjectDecl * handler_decl =
[03eedd5]279                                static_cast<ObjectDecl *>( handler->get_decl() );
[86d5ba7c]280                        ObjectDecl * local_except = handler_decl->clone();
[03eedd5]281                        local_except->set_init(
[86d5ba7c]282                                new ListInit({ new SingleInit(
283                                        new VirtualCastExpr( nameOf( except_obj ),
284                                                local_except->get_type()
285                                                )
[03eedd5]286                                        ) })
287                                );
[86d5ba7c]288                        block->push_back( new DeclStmt( noLabels, local_except ) );
289
290                        // Add the cleanup attribute.
291                        local_except->get_attributes().push_back( new Attribute(
292                                "cleanup",
293                                { new NameExpr( "__cfaehm__cleanup_terminate" ) }
294                                ) );
295
296                        // Update variables in the body to point to this local copy.
297                        {
298                                VarExprReplacer::DeclMap mapping;
299                                mapping[ handler_decl ] = local_except;
300                                VarExprReplacer mapper( mapping );
301                                handler->get_body()->accept( mapper );
302                        }
303
304                        block->push_back( handler->get_body() );
[288eede]305                        handler->set_body( nullptr );
306
[86d5ba7c]307                        std::list<Statement *> caseBody
308                                        { block, new ReturnStmt( noLabels, nullptr ) };
[288eede]309                        handler_wrappers.push_back( new CaseStmt(
[ba912706]310                                noLabels,
311                                new ConstantExpr( Constant::from_int( index ) ),
[288eede]312                                caseBody
313                                ) );
[ba912706]314                }
315                // TODO: Some sort of meaningful error on default perhaps?
316
[288eede]317                std::list<Statement*> stmt_handlers;
318                while ( !handler_wrappers.empty() ) {
319                        stmt_handlers.push_back( handler_wrappers.front() );
320                        handler_wrappers.pop_front();
321                }
322
[ba912706]323                SwitchStmt * handler_lookup = new SwitchStmt(
324                        noLabels,
[288eede]325                        nameOf( index_obj ),
326                        stmt_handlers
[ba912706]327                        );
328                CompoundStmt * body = new CompoundStmt( noLabels );
329                body->push_back( handler_lookup );
330
331                return new FunctionDecl("catch", Type::StorageClasses(),
[288eede]332                        LinkageSpec::Cforall, func_type, body);
[ba912706]333        }
334
335        // Create a single check from a moddified handler.
[288eede]336        // except_obj is referenced, modded_handler will be freed.
[948b0c8]337        CompoundStmt * ExceptionMutatorCore::create_single_matcher(
[288eede]338                        DeclarationWithType * except_obj, CatchStmt * modded_handler ) {
[86d5ba7c]339                // {
340                //     `modded_handler.decl`
[cbce272]341                //     if ( `decl.name = (virtual `decl.type`)`except`
[86d5ba7c]342                //             [&& `modded_handler.cond`] ) {
343                //         `modded_handler.body`
344                //     }
345                // }
346
[cbce272]347                CompoundStmt * block = new CompoundStmt( noLabels );
348
349                // Local Declaration
350                ObjectDecl * local_except =
351                        dynamic_cast<ObjectDecl *>( modded_handler->get_decl() );
352                assert( local_except );
353                block->push_back( new DeclStmt( noLabels, local_except ) );
354
[86d5ba7c]355                // Check for type match.
356                Expression * cond = UntypedExpr::createAssign( nameOf( local_except ),
357                        new VirtualCastExpr( nameOf( except_obj ),
358                                local_except->get_type()->clone() ) );
[ba912706]359
[86d5ba7c]360                // Add the check on the conditional if it is provided.
[ba912706]361                if ( modded_handler->get_cond() ) {
[288eede]362                        cond = new LogicalExpr( cond, modded_handler->get_cond() );
[ba912706]363                }
[86d5ba7c]364                // Construct the match condition.
[ba912706]365                block->push_back( new IfStmt( noLabels,
[288eede]366                        cond, modded_handler->get_body(), nullptr ) );
[ba912706]367
368                modded_handler->set_decl( nullptr );
369                modded_handler->set_cond( nullptr );
370                modded_handler->set_body( nullptr );
371                delete modded_handler;
372                return block;
373        }
374
[948b0c8]375        FunctionDecl * ExceptionMutatorCore::create_terminate_match(
376                        CatchList &handlers ) {
[86d5ba7c]377                // int match(exception * except) {
378                //     HANDLER WRAPPERS { return `index`; }
379                // }
380
[ba912706]381                CompoundStmt * body = new CompoundStmt( noLabels );
382
[288eede]383                FunctionType * func_type = match_func_t.clone();
384                DeclarationWithType * except_obj = func_type->get_parameters().back();
385
[ba912706]386                // Index 1..{number of handlers}
387                int index = 0;
388                CatchList::iterator it;
389                for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
390                        ++index;
391                        CatchStmt * handler = *it;
392
[288eede]393                        // Body should have been taken by create_terminate_catch.
394                        assert( nullptr == handler->get_body() );
395
396                        // Create new body.
[ba912706]397                        handler->set_body( new ReturnStmt( noLabels,
398                                new ConstantExpr( Constant::from_int( index ) ) ) );
399
[288eede]400                        // Create the handler.
401                        body->push_back( create_single_matcher( except_obj, handler ) );
402                        *it = nullptr;
[ba912706]403                }
404
[307a732]405                body->push_back( new ReturnStmt( noLabels, new ConstantExpr(
406                        Constant::from_int( 0 ) ) ) );
407
[ba912706]408                return new FunctionDecl("match", Type::StorageClasses(),
[288eede]409                        LinkageSpec::Cforall, func_type, body);
[ba912706]410        }
411
[948b0c8]412        CompoundStmt * ExceptionMutatorCore::create_terminate_caller(
[ba912706]413                        FunctionDecl * try_wrapper,
414                        FunctionDecl * terminate_catch,
[948b0c8]415                        FunctionDecl * terminate_match ) {
[86d5ba7c]416                // { __cfaehm__try_terminate(`try`, `catch`, `match`); }
[ba912706]417
[288eede]418                UntypedExpr * caller = new UntypedExpr( new NameExpr(
419                        "__cfaehm__try_terminate" ) );
420                std::list<Expression *>& args = caller->get_args();
[ba912706]421                args.push_back( nameOf( try_wrapper ) );
422                args.push_back( nameOf( terminate_catch ) );
423                args.push_back( nameOf( terminate_match ) );
424
[288eede]425                CompoundStmt * callStmt = new CompoundStmt( noLabels );
426                callStmt->push_back( new ExprStmt( noLabels, caller ) );
427                return callStmt;
[ba912706]428        }
429
[948b0c8]430        FunctionDecl * ExceptionMutatorCore::create_resume_handler(
431                        CatchList &handlers ) {
[86d5ba7c]432                // bool handle(exception * except) {
433                //     HANDLER WRAPPERS { `hander->body`; return true; }
434                // }
[288eede]435                CompoundStmt * body = new CompoundStmt( noLabels );
436
437                FunctionType * func_type = match_func_t.clone();
438                DeclarationWithType * except_obj = func_type->get_parameters().back();
[ba912706]439
440                CatchList::iterator it;
441                for ( it = handlers.begin() ; it != handlers.end() ; ++it ) {
442                        CatchStmt * handler = *it;
443
444                        // Modifiy body.
445                        CompoundStmt * handling_code =
446                                dynamic_cast<CompoundStmt*>( handler->get_body() );
447                        if ( ! handling_code ) {
448                                handling_code = new CompoundStmt( noLabels );
449                                handling_code->push_back( handler->get_body() );
450                        }
[288eede]451                        handling_code->push_back( new ReturnStmt( noLabels,
[ad0be81]452                                new ConstantExpr( Constant::from_bool( true ) ) ) );
[ba912706]453                        handler->set_body( handling_code );
454
455                        // Create the handler.
[288eede]456                        body->push_back( create_single_matcher( except_obj, handler ) );
457                        *it = nullptr;
[ba912706]458                }
459
[ad0be81]460                body->push_back( new ReturnStmt( noLabels, new ConstantExpr(
461                        Constant::from_bool( false ) ) ) );
462
[ba912706]463                return new FunctionDecl("handle", Type::StorageClasses(),
[288eede]464                        LinkageSpec::Cforall, func_type, body);
[ba912706]465        }
466
[948b0c8]467        CompoundStmt * ExceptionMutatorCore::create_resume_wrapper(
[ba912706]468                        Statement * wraps,
469                        FunctionDecl * resume_handler ) {
470                CompoundStmt * body = new CompoundStmt( noLabels );
471
[288eede]472                // struct __try_resume_node __resume_node
473                //      __attribute__((cleanup( __cfaehm__try_resume_cleanup )));
474                // ** unwinding of the stack here could cause problems **
475                // ** however I don't think that can happen currently **
476                // __cfaehm__try_resume_setup( &__resume_node, resume_handler );
[ba912706]477
478                std::list< Attribute * > attributes;
479                {
480                        std::list< Expression * > attr_params;
[288eede]481                        attr_params.push_back( new NameExpr(
482                                "__cfaehm__try_resume_cleanup" ) );
483                        attributes.push_back( new Attribute( "cleanup", attr_params ) );
[ba912706]484                }
485
[288eede]486                ObjectDecl * obj = new ObjectDecl(
487                        "__resume_node",
[ba912706]488                        Type::StorageClasses(),
489                        LinkageSpec::Cforall,
490                        nullptr,
[288eede]491                        new StructInstType(
492                                Type::Qualifiers(),
493                                node_decl
494                                ),
495                        nullptr,
[ba912706]496                        attributes
[288eede]497                        );
498                appendDeclStmt( body, obj );
499
500                UntypedExpr *setup = new UntypedExpr( new NameExpr(
501                        "__cfaehm__try_resume_setup" ) );
[307a732]502                setup->get_args().push_back( new AddressExpr( nameOf( obj ) ) );
[288eede]503                setup->get_args().push_back( nameOf( resume_handler ) );
504
505                body->push_back( new ExprStmt( noLabels, setup ) );
506
[ba912706]507                body->push_back( wraps );
508                return body;
509        }
510
[948b0c8]511        FunctionDecl * ExceptionMutatorCore::create_finally_wrapper(
512                        TryStmt * tryStmt ) {
[86d5ba7c]513                // void finally() { <finally code> }
[288eede]514                FinallyStmt * finally = tryStmt->get_finally();
515                CompoundStmt * body = finally->get_block();
516                finally->set_block( nullptr );
517                delete finally;
[ba912706]518                tryStmt->set_finally( nullptr );
519
520                return new FunctionDecl("finally", Type::StorageClasses(),
[307a732]521                        LinkageSpec::Cforall, finally_func_t.clone(), body);
[ba912706]522        }
523
[948b0c8]524        ObjectDecl * ExceptionMutatorCore::create_finally_hook(
525                        FunctionDecl * finally_wrapper ) {
[288eede]526                // struct __cfaehm__cleanup_hook __finally_hook
527                //      __attribute__((cleanup( finally_wrapper )));
[ba912706]528
529                // Make Cleanup Attribute.
530                std::list< Attribute * > attributes;
531                {
532                        std::list< Expression * > attr_params;
533                        attr_params.push_back( nameOf( finally_wrapper ) );
[288eede]534                        attributes.push_back( new Attribute( "cleanup", attr_params ) );
[ba912706]535                }
536
[288eede]537                return new ObjectDecl(
538                        "__finally_hook",
[ba912706]539                        Type::StorageClasses(),
540                        LinkageSpec::Cforall,
541                        nullptr,
[288eede]542                        new StructInstType(
[ac10576]543                                noQualifiers,
[288eede]544                                hook_decl
545                                ),
[ba912706]546                        nullptr,
547                        attributes
548                        );
549        }
550
[948b0c8]551        // Visiting/Mutating Functions
[86d5ba7c]552        void ExceptionMutatorCore::premutate( CatchStmt *catchStmt ) {
[03eedd5]553                // Validate the Statement's form.
554                ObjectDecl * decl =
555                        dynamic_cast<ObjectDecl *>( catchStmt->get_decl() );
556                if ( decl && true /* check decl->get_type() */ ) {
557                        // Pass.
558                } else if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
559                        throw SemanticError("catch must have exception type");
560                } else {
561                        throw SemanticError("catchResume must have exception type");
562                }
563
564                // Track the handler context.
[86d5ba7c]565                GuardValue( cur_context );
566                if ( CatchStmt::Terminate == catchStmt->get_kind() ) {
567                        cur_context = TerHandler;
568
569                        GuardValue( handler_except_decl );
[03eedd5]570                        handler_except_decl = decl;
[86d5ba7c]571                } else {
572                        cur_context = ResHandler;
573                }
574        }
575
576        void ExceptionMutatorCore::premutate( StructDecl *structDecl ) {
577                if ( !structDecl->has_body() ) {
578                        // Skip children?
579                        return;
[cbce272]580                } else if ( structDecl->get_name() == "__cfaehm__base_exception_t" ) {
581                        assert( nullptr == except_decl );
582                        except_decl = structDecl;
583                        init_func_types();
[86d5ba7c]584                } else if ( structDecl->get_name() == "__cfaehm__try_resume_node" ) {
585                        assert( nullptr == node_decl );
586                        node_decl = structDecl;
587                } else if ( structDecl->get_name() == "__cfaehm__cleanup_hook" ) {
588                        assert( nullptr == hook_decl );
589                        hook_decl = structDecl;
590                }
591                // Later we might get the exception type as well.
592        }
593
[ba912706]594        Statement * ExceptionMutatorCore::postmutate( ThrowStmt *throwStmt ) {
[cbce272]595                assert( except_decl );
596
[ba912706]597                // Ignoring throwStmt->get_target() for now.
598                if ( ThrowStmt::Terminate == throwStmt->get_kind() ) {
599                        if ( throwStmt->get_expr() ) {
600                                return create_terminate_throw( throwStmt );
[288eede]601                        } else if ( TerHandler == cur_context ) {
[948b0c8]602                                return create_terminate_rethrow( throwStmt );
[ba912706]603                        } else {
604                                assertf(false, "Invalid throw in %s at %i\n",
[288eede]605                                        throwStmt->location.filename.c_str(),
[ba912706]606                                        throwStmt->location.linenumber);
607                                return nullptr;
608                        }
609                } else {
610                        if ( throwStmt->get_expr() ) {
611                                return create_resume_throw( throwStmt );
[288eede]612                        } else if ( ResHandler == cur_context ) {
[ba912706]613                                return create_resume_rethrow( throwStmt );
614                        } else {
615                                assertf(false, "Invalid throwResume in %s at %i\n",
[288eede]616                                        throwStmt->location.filename.c_str(),
[ba912706]617                                        throwStmt->location.linenumber);
618                                return nullptr;
619                        }
620                }
621        }
622
623        Statement * ExceptionMutatorCore::postmutate( TryStmt *tryStmt ) {
[cbce272]624                assert( except_decl );
[288eede]625                assert( node_decl );
626                assert( hook_decl );
627
[ba912706]628                // Generate a prefix for the function names?
629
[288eede]630                CompoundStmt * block = new CompoundStmt( noLabels );
631                CompoundStmt * inner = take_try_block( tryStmt );
[ba912706]632
633                if ( tryStmt->get_finally() ) {
634                        // Define the helper function.
635                        FunctionDecl * finally_block =
636                                create_finally_wrapper( tryStmt );
637                        appendDeclStmt( block, finally_block );
638                        // Create and add the finally cleanup hook.
[948b0c8]639                        appendDeclStmt( block, create_finally_hook( finally_block ) );
[ba912706]640                }
641
[288eede]642                CatchList termination_handlers;
643                CatchList resumption_handlers;
644                split( tryStmt->get_catchers(),
[1abc5ab]645                           termination_handlers, resumption_handlers );
[ba912706]646
[288eede]647                if ( resumption_handlers.size() ) {
[ba912706]648                        // Define the helper function.
649                        FunctionDecl * resume_handler =
650                                create_resume_handler( resumption_handlers );
651                        appendDeclStmt( block, resume_handler );
652                        // Prepare hooks
[948b0c8]653                        inner = create_resume_wrapper( inner, resume_handler );
[ba912706]654                }
655
656                if ( termination_handlers.size() ) {
657                        // Define the three helper functions.
658                        FunctionDecl * try_wrapper = create_try_wrapper( inner );
659                        appendDeclStmt( block, try_wrapper );
660                        FunctionDecl * terminate_catch =
661                                create_terminate_catch( termination_handlers );
662                        appendDeclStmt( block, terminate_catch );
663                        FunctionDecl * terminate_match =
664                                create_terminate_match( termination_handlers );
665                        appendDeclStmt( block, terminate_match );
666                        // Build the call to the try wrapper.
667                        inner = create_terminate_caller(
668                                try_wrapper, terminate_catch, terminate_match );
669                }
670
671                // Embed the try block.
672                block->push_back( inner );
673
674                return block;
675        }
676
[1abc5ab]677        void translateEHM( std::list< Declaration *> & translationUnit ) {
[ba912706]678                PassVisitor<ExceptionMutatorCore> translator;
[6fca7ea]679                mutateAll( translationUnit, translator );
[ba912706]680        }
681}
Note: See TracBrowser for help on using the repository browser.