Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/SymTab/Autogen.h

    r8913de4 re6cf857f  
    99// Author           : Rob Schluntz
    1010// Created On       : Sun May 17 21:53:34 2015
    11 // Last Modified By : Andrew Beach
    12 // Last Modified On : Fri Apr 14 15:06:00 2023
    13 // Update Count     : 17
     11// Last Modified By : Peter A. Buhr
     12// Last Modified On : Fri Dec 13 16:38:06 2019
     13// Update Count     : 16
    1414//
    1515
     
    2020#include <string>                 // for string
    2121
     22#include "AST/Decl.hpp"
     23#include "AST/Expr.hpp"
     24#include "AST/Init.hpp"
     25#include "AST/Node.hpp"
     26#include "AST/Stmt.hpp"
     27#include "AST/Type.hpp"
    2228#include "CodeGen/OperatorTable.h"
    2329#include "Common/UniqueName.h"    // for UniqueName
     
    3945        /// returns true if obj's name is the empty string and it has a bitfield width
    4046        bool isUnnamedBitfield( ObjectDecl * obj );
     47        bool isUnnamedBitfield( const ast::ObjectDecl * obj );
    4148
    4249        /// generate the type of an assignment function for paramType.
     
    4855        FunctionType * genDefaultType( Type * paramType, bool maybePolymorphic = true );
    4956
     57        ast::FunctionDecl * genDefaultFunc(const CodeLocation loc, const std::string fname, const ast::Type * paramType, bool maybePolymorphic = true);
     58
    5059        /// generate the type of a copy constructor for paramType.
    5160        /// maybePolymorphic is true if the resulting FunctionType is allowed to be polymorphic
    5261        FunctionType * genCopyType( Type * paramType, bool maybePolymorphic = true );
    5362
     63        /// Enum for loop direction
     64        enum LoopDirection { LoopBackward, LoopForward };
     65
    5466        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls.
    5567        template< typename OutputIterator >
    5668        Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast = nullptr, bool forward = true );
     69
     70        template< typename OutIter >
     71        ast::ptr< ast::Stmt > genCall(
     72                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
     73                const CodeLocation & loc, const std::string & fname, OutIter && out,
     74                const ast::Type * type, const ast::Type * addCast, LoopDirection forward = LoopForward );
    5775
    5876        /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Should only be called with non-array types.
     
    103121
    104122                *out++ = new ExprStmt( fExpr );
     123
     124                srcParam.clearArrayIndices();
     125
     126                return listInit;
     127        }
     128
     129        /// inserts into out a generated call expression to function fname with arguments dstParam and
     130        /// srcParam. Should only be called with non-array types.
     131        /// optionally returns a statement which must be inserted prior to the containing loop, if
     132        /// there is one
     133        template< typename OutIter >
     134        ast::ptr< ast::Stmt > genScalarCall(
     135                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
     136                const CodeLocation & loc, std::string fname, OutIter && out, const ast::Type * type,
     137                const ast::Type * addCast = nullptr
     138        ) {
     139                bool isReferenceCtorDtor = false;
     140                if ( dynamic_cast< const ast::ReferenceType * >( type ) && CodeGen::isCtorDtor( fname ) ) {
     141                        // reference constructors are essentially application of the rebind operator.
     142                        // apply & to both arguments, do not need a cast
     143                        fname = "?=?";
     144                        dstParam = new ast::AddressExpr{ dstParam };
     145                        addCast = nullptr;
     146                        isReferenceCtorDtor = true;
     147                }
     148
     149                // want to be able to generate assignment, ctor, and dtor generically, so fname is one of
     150                // "?=?", "?{}", or "^?{}"
     151                ast::UntypedExpr * fExpr = new ast::UntypedExpr{ loc, new ast::NameExpr{ loc, fname } };
     152
     153                if ( addCast ) {
     154                        // cast to T& with qualifiers removed, so that qualified objects can be constructed and
     155                        // destructed with the same functions as non-qualified objects. Unfortunately, lvalue
     156                        // is considered a qualifier - for AddressExpr to resolve, its argument must have an
     157                        // lvalue-qualified type, so remove all qualifiers except lvalue.
     158                        // xxx -- old code actually removed lvalue too...
     159                        ast::ptr< ast::Type > guard = addCast;  // prevent castType from mutating addCast
     160                        ast::ptr< ast::Type > castType = addCast;
     161                        ast::remove_qualifiers(
     162                                castType,
     163                                ast::CV::Const | ast::CV::Volatile | ast::CV::Restrict | ast::CV::Atomic );
     164                        dstParam = new ast::CastExpr{ dstParam, new ast::ReferenceType{ castType } };
     165                }
     166                fExpr->args.emplace_back( dstParam );
     167
     168                ast::ptr<ast::Stmt> listInit = srcParam.buildListInit( fExpr );
     169
     170                // fetch next set of arguments
     171                ++srcParam;
     172
     173                // return if adding reference fails -- will happen on default ctor and dtor
     174                if ( isReferenceCtorDtor && ! srcParam.addReference() ) return listInit;
     175
     176                std::vector< ast::ptr< ast::Expr > > args = *srcParam;
     177                splice( fExpr->args, args );
     178
     179                *out++ = new ast::ExprStmt{ loc, fExpr };
    105180
    106181                srcParam.clearArrayIndices();
     
    173248        }
    174249
     250        /// Store in out a loop which calls fname on each element of the array with srcParam and
     251        /// dstParam as arguments. If forward is true, loop goes from 0 to N-1, else N-1 to 0
     252        template< typename OutIter >
     253        void genArrayCall(
     254                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
     255                const CodeLocation & loc, const std::string & fname, OutIter && out,
     256                const ast::ArrayType * array, const ast::Type * addCast = nullptr,
     257                LoopDirection forward = LoopForward
     258        ) {
     259                static UniqueName indexName( "_index" );
     260
     261                // for a flexible array member nothing is done -- user must define own assignment
     262                if ( ! array->dimension ) return;
     263
     264                if ( addCast ) {
     265                        // peel off array layer from cast
     266                        addCast = strict_dynamic_cast< const ast::ArrayType * >( addCast )->base;
     267                }
     268
     269                ast::ptr< ast::Expr > begin, end;
     270                std::string cmp, update;
     271
     272                if ( forward ) {
     273                        // generate: for ( int i = 0; i < N; ++i )
     274                        begin = ast::ConstantExpr::from_int( loc, 0 );
     275                        end = array->dimension;
     276                        cmp = "?<?";
     277                        update = "++?";
     278                } else {
     279                        // generate: for ( int i = N-1; i >= 0; --i )
     280                        begin = ast::UntypedExpr::createCall( loc, "?-?",
     281                                { array->dimension, ast::ConstantExpr::from_int( loc, 1 ) } );
     282                        end = ast::ConstantExpr::from_int( loc, 0 );
     283                        cmp = "?>=?";
     284                        update = "--?";
     285                }
     286
     287                ast::ptr< ast::DeclWithType > index = new ast::ObjectDecl{
     288                        loc, indexName.newName(), new ast::BasicType{ ast::BasicType::SignedInt },
     289                        new ast::SingleInit{ loc, begin } };
     290                ast::ptr< ast::Expr > indexVar = new ast::VariableExpr{ loc, index };
     291
     292                ast::ptr< ast::Expr > cond = ast::UntypedExpr::createCall(
     293                        loc, cmp, { indexVar, end } );
     294
     295                ast::ptr< ast::Expr > inc = ast::UntypedExpr::createCall(
     296                        loc, update, { indexVar } );
     297
     298                ast::ptr< ast::Expr > dstIndex = ast::UntypedExpr::createCall(
     299                        loc, "?[?]", { dstParam, indexVar } );
     300
     301                // srcParam must keep track of the array indices to build the source parameter and/or
     302                // array list initializer
     303                srcParam.addArrayIndex( indexVar, array->dimension );
     304
     305                // for stmt's body, eventually containing call
     306                ast::CompoundStmt * body = new ast::CompoundStmt{ loc };
     307                ast::ptr< ast::Stmt > listInit = genCall(
     308                        srcParam, dstIndex, loc, fname, std::back_inserter( body->kids ), array->base, addCast,
     309                        forward );
     310
     311                // block containing the stmt and index variable
     312                ast::CompoundStmt * block = new ast::CompoundStmt{ loc };
     313                block->push_back( new ast::DeclStmt{ loc, index } );
     314                if ( listInit ) { block->push_back( listInit ); }
     315                block->push_back( new ast::ForStmt{ loc, {}, cond, inc, body } );
     316
     317                *out++ = block;
     318        }
     319
    175320        template< typename OutputIterator >
    176321        Statement * genCall( InitTweak::InitExpander_old & srcParam, Expression * dstParam, const std::string & fname, OutputIterator out, Type * type, Type * addCast, bool forward ) {
     
    180325                } else {
    181326                        return genScalarCall( srcParam, dstParam, fname, out, type, addCast );
     327                }
     328        }
     329
     330        template< typename OutIter >
     331        ast::ptr< ast::Stmt > genCall(
     332                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
     333                const CodeLocation & loc, const std::string & fname, OutIter && out,
     334                const ast::Type * type, const ast::Type * addCast, LoopDirection forward
     335        ) {
     336                if ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
     337                        genArrayCall(
     338                                srcParam, dstParam, loc, fname, std::forward< OutIter >(out), at, addCast,
     339                                forward );
     340                        return {};
     341                } else {
     342                        return genScalarCall(
     343                                srcParam, dstParam, loc, fname, std::forward< OutIter >( out ), type, addCast );
    182344                }
    183345        }
     
    217379        }
    218380
     381        static inline ast::ptr< ast::Stmt > genImplicitCall(
     382                InitTweak::InitExpander_new & srcParam, const ast::Expr * dstParam,
     383                const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * obj,
     384                LoopDirection forward = LoopForward
     385        ) {
     386                // unnamed bit fields are not copied as they cannot be accessed
     387                if ( isUnnamedBitfield( obj ) ) return {};
     388
     389                ast::ptr< ast::Type > addCast;
     390                if ( (fname == "?{}" || fname == "^?{}") && ( ! obj || ( obj && ! obj->bitfieldWidth ) ) ) {
     391                        assert( dstParam->result );
     392                        addCast = dstParam->result;
     393                }
     394
     395                std::vector< ast::ptr< ast::Stmt > > stmts;
     396                genCall(
     397                        srcParam, dstParam, loc, fname, back_inserter( stmts ), obj->type, addCast, forward );
     398
     399                if ( stmts.empty() ) {
     400                        return {};
     401                } else if ( stmts.size() == 1 ) {
     402                        const ast::Stmt * callStmt = stmts.front();
     403                        if ( addCast ) {
     404                                // implicitly generated ctor/dtor calls should be wrapped so that later passes are
     405                                // aware they were generated.
     406                                callStmt = new ast::ImplicitCtorDtorStmt{ callStmt->location, callStmt };
     407                        }
     408                        return callStmt;
     409                } else {
     410                        assert( false );
     411                        return {};
     412                }
     413        }
    219414} // namespace SymTab
    220415
Note: See TracChangeset for help on using the changeset viewer.