Ignore:
Timestamp:
Jun 24, 2019, 10:30:47 AM (6 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
84917e2
Parents:
3c6e417 (diff), 9e0a360 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' of plg.uwaterloo.ca:software/cfa/cfa-cc

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/InitTweak/InitTweak.cc

    r3c6e417 r54dd994  
    2222
    2323#include "AST/Expr.hpp"
     24#include "AST/Init.hpp"
     25#include "AST/Node.hpp"
     26#include "AST/Pass.hpp"
    2427#include "AST/Stmt.hpp"
    2528#include "AST/Type.hpp"
     
    8487                };
    8588
    86                 struct InitFlattener : public WithShortCircuiting {
     89                struct InitFlattener_old : public WithShortCircuiting {
    8790                        void previsit( SingleInit * singleInit ) {
    8891                                visit_children = false;
     
    9295                };
    9396
    94         }
     97                struct InitFlattener_new : public ast::WithShortCircuiting {
     98                        std::vector< ast::ptr< ast::Expr > > argList;
     99
     100                        void previsit( const ast::SingleInit * singleInit ) {
     101                                visit_children = false;
     102                                argList.emplace_back( singleInit->value );
     103                        }
     104                };
     105
     106        } // anonymous namespace
    95107
    96108        std::list< Expression * > makeInitList( Initializer * init ) {
    97                 PassVisitor<InitFlattener> flattener;
     109                PassVisitor<InitFlattener_old> flattener;
    98110                maybeAccept( init, flattener );
    99111                return flattener.pass.argList;
     
    112124        }
    113125
    114         class InitExpander::ExpanderImpl {
     126std::vector< ast::ptr< ast::Expr > > makeInitList( const ast::Init * init ) {
     127        ast::Pass< InitFlattener_new > flattener;
     128        maybe_accept( init, flattener );
     129        return std::move( flattener.pass.argList );
     130}
     131
     132        class InitExpander_old::ExpanderImpl {
    115133        public:
    116134                virtual ~ExpanderImpl() = default;
     
    119137        };
    120138
    121         class InitImpl : public InitExpander::ExpanderImpl {
     139        class InitImpl_old : public InitExpander_old::ExpanderImpl {
    122140        public:
    123                 InitImpl( Initializer * init ) : init( init ) {}
    124                 virtual ~InitImpl() = default;
     141                InitImpl_old( Initializer * init ) : init( init ) {}
     142                virtual ~InitImpl_old() = default;
    125143
    126144                virtual std::list< Expression * > next( __attribute((unused)) std::list< Expression * > & indices ) {
     
    136154        };
    137155
    138         class ExprImpl : public InitExpander::ExpanderImpl {
     156        class ExprImpl_old : public InitExpander_old::ExpanderImpl {
    139157        public:
    140                 ExprImpl( Expression * expr ) : arg( expr ) {}
    141                 virtual ~ExprImpl() { delete arg; }
     158                ExprImpl_old( Expression * expr ) : arg( expr ) {}
     159                virtual ~ExprImpl_old() { delete arg; }
    142160
    143161                virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
     
    163181        };
    164182
    165         InitExpander::InitExpander( Initializer * init ) : expander( new InitImpl( init ) ) {}
    166 
    167         InitExpander::InitExpander( Expression * expr ) : expander( new ExprImpl( expr ) ) {}
    168 
    169         std::list< Expression * > InitExpander::operator*() {
     183        InitExpander_old::InitExpander_old( Initializer * init ) : expander( new InitImpl_old( init ) ) {}
     184
     185        InitExpander_old::InitExpander_old( Expression * expr ) : expander( new ExprImpl_old( expr ) ) {}
     186
     187        std::list< Expression * > InitExpander_old::operator*() {
    170188                return cur;
    171189        }
    172190
    173         InitExpander & InitExpander::operator++() {
     191        InitExpander_old & InitExpander_old::operator++() {
    174192                cur = expander->next( indices );
    175193                return *this;
     
    177195
    178196        // use array indices list to build switch statement
    179         void InitExpander::addArrayIndex( Expression * index, Expression * dimension ) {
     197        void InitExpander_old::addArrayIndex( Expression * index, Expression * dimension ) {
    180198                indices.push_back( index );
    181199                indices.push_back( dimension );
    182200        }
    183201
    184         void InitExpander::clearArrayIndices() {
     202        void InitExpander_old::clearArrayIndices() {
    185203                deleteAll( indices );
    186204                indices.clear();
    187205        }
    188206
    189         bool InitExpander::addReference() {
     207        bool InitExpander_old::addReference() {
    190208                bool added = false;
    191209                for ( Expression *& expr : cur ) {
     
    218236
    219237                template< typename OutIterator >
    220                 void build( UntypedExpr * callExpr, InitExpander::IndexList::iterator idx, InitExpander::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) {
     238                void build( UntypedExpr * callExpr, InitExpander_old::IndexList::iterator idx, InitExpander_old::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) {
    221239                        if ( idx == idxEnd ) return;
    222240                        Expression * index = *idx++;
     
    275293        // remaining elements.
    276294        // To accomplish this, generate switch statement, consuming all of expander's elements
    277         Statement * InitImpl::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
     295        Statement * InitImpl_old::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
    278296                if ( ! init ) return nullptr;
    279297                CompoundStmt * block = new CompoundStmt();
     
    288306        }
    289307
    290         Statement * ExprImpl::buildListInit( UntypedExpr *, std::list< Expression * > & ) {
     308        Statement * ExprImpl_old::buildListInit( UntypedExpr *, std::list< Expression * > & ) {
    291309                return nullptr;
    292310        }
    293311
    294         Statement * InitExpander::buildListInit( UntypedExpr * dst ) {
     312        Statement * InitExpander_old::buildListInit( UntypedExpr * dst ) {
    295313                return expander->buildListInit( dst, indices );
    296314        }
     315
     316class InitExpander_new::ExpanderImpl {
     317public:
     318        virtual ~ExpanderImpl() = default;
     319        virtual std::vector< ast::ptr< ast::Expr > > next( IndexList & indices ) = 0;
     320        virtual ast::ptr< ast::Stmt > buildListInit(
     321                ast::UntypedExpr * callExpr, IndexList & indices ) = 0;
     322};
     323
     324namespace {
     325        template< typename Out >
     326        void buildCallExpr(
     327                ast::UntypedExpr * callExpr, const ast::Expr * index, const ast::Expr * dimension,
     328                const ast::Init * init, Out & out
     329        ) {
     330                const CodeLocation & loc = init->location;
     331
     332                auto cond = new ast::UntypedExpr{
     333                        loc, new ast::NameExpr{ loc, "?<?" }, { index, dimension } };
     334               
     335                std::vector< ast::ptr< ast::Expr > > args = makeInitList( init );
     336                splice( callExpr->args, args );
     337
     338                out.emplace_back( new ast::IfStmt{ loc, cond, new ast::ExprStmt{ loc, callExpr } } );
     339
     340                out.emplace_back( new ast::ExprStmt{
     341                        loc, new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, "++?" }, { index } } } );
     342        }
     343
     344        template< typename Out >
     345        void build(
     346                ast::UntypedExpr * callExpr, const InitExpander_new::IndexList & indices,
     347                const ast::Init * init, Out & out
     348        ) {
     349                if ( indices.empty() ) return;
     350
     351                unsigned idx = 0;
     352
     353                const ast::Expr * index = indices[idx++];
     354                assert( idx != indices.size() );
     355                const ast::Expr * dimension = indices[idx++];
     356
     357                if ( idx == indices.size() ) {
     358                        if ( auto listInit = dynamic_cast< const ast::ListInit * >( init ) ) {
     359                                for ( const ast::Init * init : *listInit ) {
     360                                        buildCallExpr( callExpr, index, dimension, init, out );
     361                                }
     362                        } else {
     363                                buildCallExpr( callExpr, index, dimension, init, out );
     364                        }
     365                } else {
     366                        const CodeLocation & loc = init->location;
     367
     368                        unsigned long cond = 0;
     369                        auto listInit = dynamic_cast< const ast::ListInit * >( init );
     370                        if ( ! listInit ) { SemanticError( loc, "unbalanced list initializers" ); }
     371
     372                        static UniqueName targetLabel( "L__autogen__" );
     373                        ast::Label switchLabel{
     374                                loc, targetLabel.newName(), { new ast::Attribute{ "unused" } } };
     375                       
     376                        std::vector< ast::ptr< ast::Stmt > > branches;
     377                        for ( const ast::Init * init : *listInit ) {
     378                                auto condition = ast::ConstantExpr::from_ulong( loc, cond );
     379                                ++cond;
     380
     381                                std::vector< ast::ptr< ast::Stmt > > stmts;
     382                                build( callExpr, indices, init, stmts );
     383                                stmts.emplace_back(
     384                                        new ast::BranchStmt{ loc, ast::BranchStmt::Break, switchLabel } );
     385                                branches.emplace_back( new ast::CaseStmt{ loc, condition, std::move( stmts ) } );
     386                        }
     387                        out.emplace_back( new ast::SwitchStmt{ loc, index, std::move( branches ) } );
     388                        out.emplace_back( new ast::NullStmt{ loc, { switchLabel } } );
     389                }
     390        }
     391
     392        class InitImpl_new final : public InitExpander_new::ExpanderImpl {
     393                ast::ptr< ast::Init > init;
     394        public:
     395                InitImpl_new( const ast::Init * i ) : init( i ) {}
     396
     397                std::vector< ast::ptr< ast::Expr > > next( InitExpander_new::IndexList & ) override {
     398                        return makeInitList( init );
     399                }
     400               
     401                ast::ptr< ast::Stmt > buildListInit(
     402                        ast::UntypedExpr * callExpr, InitExpander_new::IndexList & indices
     403                ) override {
     404                        // If array came with an initializer list, initialize each element. We may have more
     405                        // initializers than elements of the array; need to check at each index that we have
     406                        // not exceeded size. We may have fewer initializers than elements in the array; need
     407                        // to default-construct remaining elements. To accomplish this, generate switch
     408                        // statement consuming all of expander's elements
     409
     410                        if ( ! init ) return {};
     411
     412                        std::list< ast::ptr< ast::Stmt > > stmts;
     413                        build( callExpr, indices, init, stmts );
     414                        if ( stmts.empty() ) {
     415                                return {};
     416                        } else {
     417                                auto block = new ast::CompoundStmt{ init->location, std::move( stmts ) };
     418                                init = nullptr;  // consumed in creating the list init
     419                                return block;
     420                        }
     421                }
     422        };
     423
     424        class ExprImpl_new final : public InitExpander_new::ExpanderImpl {
     425                ast::ptr< ast::Expr > arg;
     426        public:
     427                ExprImpl_new( const ast::Expr * a ) : arg( a ) {}
     428
     429                std::vector< ast::ptr< ast::Expr > > next(
     430                        InitExpander_new::IndexList & indices
     431                ) override {
     432                        if ( ! arg ) return {};
     433
     434                        const CodeLocation & loc = arg->location;
     435                        const ast::Expr * expr = arg;
     436                        for ( auto it = indices.rbegin(); it != indices.rend(); ++it ) {
     437                                // go through indices and layer on subscript exprs ?[?]
     438                                ++it;
     439                                expr = new ast::UntypedExpr{
     440                                        loc, new ast::NameExpr{ loc, "?[?]" }, { expr, *it } };
     441                        }
     442                        return { expr };
     443                }
     444               
     445                ast::ptr< ast::Stmt > buildListInit(
     446                        ast::UntypedExpr *, InitExpander_new::IndexList &
     447                ) override {
     448                        return {};
     449                }
     450        };
     451} // anonymous namespace
     452
     453InitExpander_new::InitExpander_new( const ast::Init * init )
     454: expander( new InitImpl_new{ init } ), crnt(), indices() {}
     455
     456InitExpander_new::InitExpander_new( const ast::Expr * expr )
     457: expander( new ExprImpl_new{ expr } ), crnt(), indices() {}
     458
     459std::vector< ast::ptr< ast::Expr > > InitExpander_new::operator* () { return crnt; }
     460
     461InitExpander_new & InitExpander_new::operator++ () {
     462        crnt = expander->next( indices );
     463        return *this;
     464}
     465
     466/// builds statement which has the same semantics as a C-style list initializer (for array
     467/// initializers) using callExpr as the base expression to perform initialization
     468ast::ptr< ast::Stmt > InitExpander_new::buildListInit( ast::UntypedExpr * callExpr ) {
     469        return expander->buildListInit( callExpr, indices );
     470}
     471
     472void InitExpander_new::addArrayIndex( const ast::Expr * index, const ast::Expr * dimension ) {
     473        indices.emplace_back( index );
     474        indices.emplace_back( dimension );
     475}
     476
     477void InitExpander_new::clearArrayIndices() { indices.clear(); }
     478
     479bool InitExpander_new::addReference() {
     480        for ( ast::ptr< ast::Expr > & expr : crnt ) {
     481                expr = new ast::AddressExpr{ expr };
     482        }
     483        return ! crnt.empty();
     484}
    297485
    298486        Type * getTypeofThis( FunctionType * ftype ) {
Note: See TracChangeset for help on using the changeset viewer.