Changeset ae357ec


Ignore:
Timestamp:
Mar 8, 2016, 10:25:06 PM (6 years ago)
Author:
Peter A. Buhr <pabuhr@…>
Branches:
aaron-thesis, arm-eh, cleanup-dtors, ctor, deferred_resn, demangler, gc_noraii, jacob/cs343-translation, jenkins-sandbox, master, memory, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, resolv-new, string, with_gc
Children:
5447e09
Parents:
b63e376 (diff), bed4c63e (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 plg2:software/cfa/cfa-cc

Location:
src
Files:
8 deleted
13 edited

Legend:

Unmodified
Added
Removed
  • src/CodeGen/CodeGenerator.cc

    rb63e376 rae357ec  
    2121#include "Parser/ParseNode.h"
    2222
    23 #include "SynTree/Type.h"
     23#include "SynTree/Declaration.h"
    2424#include "SynTree/Expression.h"
    2525#include "SynTree/Initializer.h"
    2626#include "SynTree/Statement.h"
     27#include "SynTree/Type.h"
    2728
    2829#include "Common/utility.h"
  • src/CodeGen/CodeGenerator.h

    rb63e376 rae357ec  
    1919#include <list>
    2020
     21#include "SynTree/Declaration.h"
    2122#include "SynTree/SynTree.h"
    2223#include "SynTree/Visitor.h"
     24
    2325#include "SymTab/Indexer.h"
    2426
  • src/CodeGen/GenType.cc

    rb63e376 rae357ec  
    1919#include "GenType.h"
    2020#include "CodeGenerator.h"
     21
     22#include "SynTree/Declaration.h"
     23#include "SynTree/Expression.h"
     24#include "SynTree/Type.h"
    2125#include "SynTree/Visitor.h"
    22 #include "SynTree/Type.h"
    23 #include "SynTree/Expression.h"
    2426
    2527namespace CodeGen {
  • src/GenPoly/Box.cc

    rb63e376 rae357ec  
    1414//
    1515
     16#include <algorithm>
     17#include <iterator>
     18#include <list>
     19#include <map>
    1620#include <set>
    1721#include <stack>
    1822#include <string>
    19 #include <iterator>
    20 #include <algorithm>
     23#include <utility>
     24#include <vector>
    2125#include <cassert>
    2226
    2327#include "Box.h"
    24 #include "InstantiateGeneric.h"
     28#include "DeclMutator.h"
    2529#include "PolyMutator.h"
    2630#include "FindFunction.h"
     31#include "ScopedMap.h"
    2732#include "ScrubTyVars.h"
    2833
     
    3035
    3136#include "SynTree/Constant.h"
    32 #include "SynTree/Type.h"
     37#include "SynTree/Declaration.h"
    3338#include "SynTree/Expression.h"
    3439#include "SynTree/Initializer.h"
     40#include "SynTree/Mutator.h"
    3541#include "SynTree/Statement.h"
    36 #include "SynTree/Mutator.h"
     42#include "SynTree/Type.h"
     43#include "SynTree/TypeSubstitution.h"
    3744
    3845#include "ResolvExpr/TypeEnvironment.h"
     
    4047#include "ResolvExpr/typeops.h"
    4148
     49#include "SymTab/Indexer.h"
    4250#include "SymTab/Mangler.h"
    4351
     
    5462                FunctionType *makeAdapterType( FunctionType *adaptee, const TyVarMap &tyVars );
    5563
     64                /// Key for a unique concrete type; generic base type paired with type parameter list
     65                struct ConcreteType {
     66                        ConcreteType() : base(NULL), params() {}
     67
     68                        ConcreteType(AggregateDecl *_base, const std::list< Type* >& _params) : base(_base), params() { cloneAll(_params, params); }
     69
     70                        ConcreteType(const ConcreteType& that) : base(that.base), params() { cloneAll(that.params, params); }
     71
     72                        /// Extracts types from a list of TypeExpr*
     73                        ConcreteType(AggregateDecl *_base, const std::list< TypeExpr* >& _params) : base(_base), params() {
     74                                for ( std::list< TypeExpr* >::const_iterator param = _params.begin(); param != _params.end(); ++param ) {
     75                                        params.push_back( (*param)->get_type()->clone() );
     76                                }
     77                        }
     78
     79                        ConcreteType& operator= (const ConcreteType& that) {
     80                                deleteAll( params );
     81                                params.clear();
     82
     83                                base = that.base;
     84                                cloneAll( that.params, params );
     85
     86                                return *this;
     87                        }
     88
     89                        ~ConcreteType() { deleteAll( params ); }
     90
     91                        bool operator== (const ConcreteType& that) const {
     92                                if ( base != that.base ) return false;
     93
     94                                SymTab::Indexer dummy;
     95                                if ( params.size() != that.params.size() ) return false;
     96                                for ( std::list< Type* >::const_iterator it = params.begin(), jt = that.params.begin(); it != params.end(); ++it, ++jt ) {
     97                                        if ( ! ResolvExpr::typesCompatible( *it, *jt, dummy ) ) return false;
     98                                }
     99                                return true;
     100                        }
     101
     102                        AggregateDecl *base;        ///< Base generic type
     103                        std::list< Type* > params;  ///< Instantiation parameters
     104                };
     105
     106                /// Maps a concrete type to the some value, accounting for scope
     107                template< typename Value >
     108                class InstantiationMap {
     109                        /// Information about a specific instantiation of a generic type
     110                        struct Instantiation {
     111                                ConcreteType key;  ///< Instantiation parameters for this type
     112                                Value *value;      ///< Value for this instantiation
     113
     114                                Instantiation() : key(), value(0) {}
     115                                Instantiation(const ConcreteType &_key, Value *_value) : key(_key), value(_value) {}
     116                        };
     117                        /// Map of generic types to instantiations of them
     118                        typedef std::map< AggregateDecl*, std::vector< Instantiation > > Scope;
     119
     120                        std::vector< Scope > scopes;  ///< list of scopes, from outermost to innermost
     121
     122                public:
     123                        /// Starts a new scope
     124                        void beginScope() {
     125                                Scope scope;
     126                                scopes.push_back(scope);
     127                        }
     128
     129                        /// Ends a scope
     130                        void endScope() {
     131                                scopes.pop_back();
     132                        }
     133
     134                        /// Default constructor initializes with one scope
     135                        InstantiationMap() { beginScope(); }
     136
     137//              private:
     138                        /// Gets the value for the concrete instantiation of this type, assuming it has already been instantiated in the current scope.
     139                        /// Returns NULL on none such.
     140                        Value *lookup( AggregateDecl *generic, const std::list< TypeExpr* >& params ) {
     141                                ConcreteType key(generic, params);
     142                                // scan scopes from innermost out
     143                                for ( typename std::vector< Scope >::const_reverse_iterator scope = scopes.rbegin(); scope != scopes.rend(); ++scope ) {
     144                                        // skip scope if no instantiations of this generic type
     145                                        typename Scope::const_iterator insts = scope->find( generic );
     146                                        if ( insts == scope->end() ) continue;
     147                                        // look through instantiations for matches to concrete type
     148                                        for ( typename std::vector< Instantiation >::const_iterator inst = insts->second.begin(); inst != insts->second.end(); ++inst ) {
     149                                                if ( inst->key == key ) return inst->value;
     150                                        }
     151                                }
     152                                // no matching instantiation found
     153                                return 0;
     154                        }
     155                public:
     156//                      StructDecl* lookup( StructInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (StructDecl*)lookup( inst->get_baseStruct(), typeSubs ); }
     157//                      UnionDecl* lookup( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (UnionDecl*)lookup( inst->get_baseUnion(), typeSubs ); }
     158
     159//              private:
     160                        /// Adds a value for a concrete type to the current scope
     161                        void insert( AggregateDecl *generic, const std::list< TypeExpr* > &params, Value *value ) {
     162                                ConcreteType key(generic, params);
     163                                scopes.back()[generic].push_back( Instantiation( key, value ) );
     164                        }
     165//              public:
     166//                      void insert( StructInstType *inst, const std::list< TypeExpr* > &typeSubs, StructDecl *decl ) { insert( inst->get_baseStruct(), typeSubs, decl ); }
     167//                      void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { insert( inst->get_baseUnion(), typeSubs, decl ); }
     168                };
     169
     170                /// Adds layout-generation functions to polymorphic types
     171                class LayoutFunctionBuilder : public DeclMutator {
     172                        unsigned int functionNesting;  // current level of nested functions
     173                public:
     174                        LayoutFunctionBuilder() : functionNesting( 0 ) {}
     175
     176                        virtual DeclarationWithType *mutate( FunctionDecl *functionDecl );
     177                        virtual Declaration *mutate( StructDecl *structDecl );
     178                        virtual Declaration *mutate( UnionDecl *unionDecl );
     179                };
     180               
    56181                /// Replaces polymorphic return types with out-parameters, replaces calls to polymorphic functions with adapter calls as needed, and adds appropriate type variables to the function call
    57182                class Pass1 : public PolyMutator {
     
    100225                        ObjectDecl *makeTemporary( Type *type );
    101226
    102                         typedef std::map< std::string, DeclarationWithType *> AdapterMap;
    103227                        std::map< std::string, DeclarationWithType *> assignOps;
    104228                        ResolvExpr::TypeMap< DeclarationWithType > scopedAssignOps;
    105                         std::stack< AdapterMap > adapters;
     229                        ScopedMap< std::string, DeclarationWithType* > adapters;
    106230                        DeclarationWithType *retval;
    107231                        bool useRetval;
     
    124248
    125249                        std::map< UniqueId, std::string > adapterName;
     250                };
     251
     252                /// Mutator pass that replaces concrete instantiations of generic types with actual struct declarations, scoped appropriately
     253                class GenericInstantiator : public DeclMutator {
     254                        /// Map of (generic type, parameter list) pairs to concrete type instantiations
     255                        InstantiationMap< AggregateDecl > instantiations;
     256                        /// Namer for concrete types
     257                        UniqueName typeNamer;
     258
     259                public:
     260                        GenericInstantiator() : DeclMutator(), instantiations(), typeNamer("_conc_") {}
     261
     262                        virtual Type* mutate( StructInstType *inst );
     263                        virtual Type* mutate( UnionInstType *inst );
     264
     265        //              virtual Expression* mutate( MemberExpr *memberExpr );
     266
     267                        virtual void doBeginScope();
     268                        virtual void doEndScope();
     269                private:
     270                        /// Wrap instantiation lookup for structs
     271                        StructDecl* lookup( StructInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (StructDecl*)instantiations.lookup( inst->get_baseStruct(), typeSubs ); }
     272                        /// Wrap instantiation lookup for unions
     273                        UnionDecl* lookup( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs ) { return (UnionDecl*)instantiations.lookup( inst->get_baseUnion(), typeSubs ); }
     274                        /// Wrap instantiation insertion for structs
     275                        void insert( StructInstType *inst, const std::list< TypeExpr* > &typeSubs, StructDecl *decl ) { instantiations.insert( inst->get_baseStruct(), typeSubs, decl ); }
     276                        /// Wrap instantiation insertion for unions
     277                        void insert( UnionInstType *inst, const std::list< TypeExpr* > &typeSubs, UnionDecl *decl ) { instantiations.insert( inst->get_baseUnion(), typeSubs, decl ); }
    126278                };
    127279
     
    159311        } // anonymous namespace
    160312
    161         void printAllNotBuiltin( const std::list< Declaration *>& translationUnit, std::ostream &os ) {
    162                 for ( std::list< Declaration *>::const_iterator i = translationUnit.begin(); i != translationUnit.end(); ++i ) {
    163                         if ( ! LinkageSpec::isBuiltin( (*i)->get_linkage() ) ) {
    164                                 (*i)->print( os );
    165                                 os << std::endl;
    166                         } // if
    167                 } // for
    168         }
    169 
    170313        /// version of mutateAll with special handling for translation unit so you can check the end of the prelude when debugging
    171314        template< typename MutatorType >
     
    195338
    196339        void box( std::list< Declaration *>& translationUnit ) {
     340                LayoutFunctionBuilder layoutBuilder;
    197341                Pass1 pass1;
    198342                Pass2 pass2;
     343                GenericInstantiator instantiator;
    199344                MemberExprFixer memberFixer;
    200345                Pass3 pass3;
     346               
     347                layoutBuilder.mutateDeclarationList( translationUnit );
    201348                mutateTranslationUnit/*All*/( translationUnit, pass1 );
    202349                mutateTranslationUnit/*All*/( translationUnit, pass2 );
    203                 instantiateGeneric( translationUnit );
     350//              instantiateGeneric( translationUnit );
     351                instantiator.mutateDeclarationList( translationUnit );
    204352                mutateTranslationUnit/*All*/( translationUnit, memberFixer );
    205353                mutateTranslationUnit/*All*/( translationUnit, pass3 );
    206354        }
    207355
     356        ////////////////////////////////// LayoutFunctionBuilder ////////////////////////////////////////////
     357
     358        DeclarationWithType *LayoutFunctionBuilder::mutate( FunctionDecl *functionDecl ) {
     359                functionDecl->set_functionType( maybeMutate( functionDecl->get_functionType(), *this ) );
     360                mutateAll( functionDecl->get_oldDecls(), *this );
     361                ++functionNesting;
     362                functionDecl->set_statements( maybeMutate( functionDecl->get_statements(), *this ) );
     363                --functionNesting;
     364                return functionDecl;
     365        }
     366       
     367        /// Get a list of type declarations that will affect a layout function
     368        std::list< TypeDecl* > takeOtypeOnly( std::list< TypeDecl* > &decls ) {
     369                std::list< TypeDecl * > otypeDecls;
     370
     371                for ( std::list< TypeDecl* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) {
     372                        if ( (*decl)->get_kind() == TypeDecl::Any ) {
     373                                otypeDecls.push_back( *decl );
     374                        }
     375                }
     376               
     377                return otypeDecls;
     378        }
     379
     380        /// Adds parameters for otype layout to a function type
     381        void addOtypeParams( FunctionType *layoutFnType, std::list< TypeDecl* > &otypeParams ) {
     382                BasicType sizeAlignType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     383               
     384                for ( std::list< TypeDecl* >::const_iterator param = otypeParams.begin(); param != otypeParams.end(); ++param ) {
     385                        TypeInstType paramType( Type::Qualifiers(), (*param)->get_name(), *param );
     386                        layoutFnType->get_parameters().push_back( new ObjectDecl( sizeofName( &paramType ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
     387                        layoutFnType->get_parameters().push_back( new ObjectDecl( alignofName( &paramType ), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignType.clone(), 0 ) );
     388                }
     389        }
     390
     391        /// Builds a layout function declaration
     392        FunctionDecl *buildLayoutFunctionDecl( const std::string &typeName, unsigned int functionNesting, FunctionType *layoutFnType ) {
     393                // Routines at global scope marked "static" to prevent multiple definitions is separate translation units
     394                // because each unit generates copies of the default routines for each aggregate.
     395                FunctionDecl *layoutDecl = new FunctionDecl(
     396                        "__layoutof_" + typeName, functionNesting > 0 ? DeclarationNode::NoStorageClass : DeclarationNode::Static, LinkageSpec::AutoGen, layoutFnType, new CompoundStmt( noLabels ), true, false );
     397                layoutDecl->fixUniqueId();
     398                return layoutDecl;
     399        }
     400
     401        /// Makes a unary operation
     402        Expression *makeOp( const std::string &name, Expression *arg ) {
     403                UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );
     404                expr->get_args().push_back( arg );
     405                return expr;
     406        }
     407
     408        /// Makes a binary operation
     409        Expression *makeOp( const std::string &name, Expression *lhs, Expression *rhs ) {
     410                UntypedExpr *expr = new UntypedExpr( new NameExpr( name ) );
     411                expr->get_args().push_back( lhs );
     412                expr->get_args().push_back( rhs );
     413                return expr;
     414        }
     415
     416        /// Returns the dereference of a local pointer variable
     417        Expression *derefVar( ObjectDecl *var ) {
     418                return makeOp( "*?", new VariableExpr( var ) );
     419        }
     420
     421        /// makes an if-statement with a single-expression if-block and no then block
     422        Statement *makeCond( Expression *cond, Expression *ifPart ) {
     423                return new IfStmt( noLabels, cond, new ExprStmt( noLabels, ifPart ), 0 );
     424        }
     425
     426        /// makes a statement that assigns rhs to lhs if lhs < rhs
     427        Statement *makeAssignMax( Expression *lhs, Expression *rhs ) {
     428                return makeCond( makeOp( "?<?", lhs, rhs ), makeOp( "?=?", lhs->clone(), rhs->clone() ) );
     429        }
     430
     431        /// makes a statement that aligns lhs to rhs (rhs should be an integer power of two)
     432        Statement *makeAlignTo( Expression *lhs, Expression *rhs ) {
     433                // check that the lhs is zeroed out to the level of rhs
     434                Expression *ifCond = makeOp( "?&?", lhs, makeOp( "?-?", rhs, new ConstantExpr( Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), "1" ) ) ) );
     435                // if not aligned, increment to alignment
     436                Expression *ifExpr = makeOp( "?+=?", lhs->clone(), makeOp( "?-?", rhs->clone(), ifCond->clone() ) );
     437                return makeCond( ifCond, ifExpr );
     438        }
     439       
     440        /// adds an expression to a compound statement
     441        void addExpr( CompoundStmt *stmts, Expression *expr ) {
     442                stmts->get_kids().push_back( new ExprStmt( noLabels, expr ) );
     443        }
     444
     445        /// adds a statement to a compound statement
     446        void addStmt( CompoundStmt *stmts, Statement *stmt ) {
     447                stmts->get_kids().push_back( stmt );
     448        }
     449       
     450        Declaration *LayoutFunctionBuilder::mutate( StructDecl *structDecl ) {
     451                // do not generate layout function for "empty" tag structs
     452                if ( structDecl->get_members().empty() ) return structDecl;
     453
     454                // get parameters that can change layout, exiting early if none
     455                std::list< TypeDecl* > otypeParams = takeOtypeOnly( structDecl->get_parameters() );
     456                if ( otypeParams.empty() ) return structDecl;
     457
     458                // build layout function signature
     459                FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );
     460                BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     461                PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
     462               
     463                ObjectDecl *sizeParam = new ObjectDecl( "__sizeof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
     464                layoutFnType->get_parameters().push_back( sizeParam );
     465                ObjectDecl *alignParam = new ObjectDecl( "__alignof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
     466                layoutFnType->get_parameters().push_back( alignParam );
     467                ObjectDecl *offsetParam = new ObjectDecl( "__offsetof_" + structDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
     468                layoutFnType->get_parameters().push_back( offsetParam );
     469                addOtypeParams( layoutFnType, otypeParams );
     470
     471                // build function decl
     472                FunctionDecl *layoutDecl = buildLayoutFunctionDecl( structDecl->get_name(), functionNesting, layoutFnType );
     473
     474                // calculate struct layout in function body
     475
     476                // initialize size and alignment to 0 and 1 (will have at least one member to re-edit size
     477                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "0" ) ) ) );
     478                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
     479                unsigned long n_members = 0;
     480                bool firstMember = true;
     481                for ( std::list< Declaration* >::const_iterator member = structDecl->get_members().begin(); member != structDecl->get_members().end(); ++member ) {
     482                        DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );
     483                        assert( dwt );
     484                        Type *memberType = dwt->get_type();
     485
     486                        if ( firstMember ) {
     487                                firstMember = false;
     488                        } else {
     489                                // make sure all members after the first (automatically aligned at 0) are properly padded for alignment
     490                                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), new AlignofExpr( memberType->clone() ) ) );
     491                        }
     492                       
     493                        // place current size in the current offset index
     494                        addExpr( layoutDecl->get_statements(), makeOp( "?=?", makeOp( "?[?]", new VariableExpr( offsetParam ), new ConstantExpr( Constant::from( n_members ) ) ),
     495                                                                              derefVar( sizeParam ) ) );
     496                        ++n_members;
     497
     498                        // add member size to current size
     499                        addExpr( layoutDecl->get_statements(), makeOp( "?+=?", derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );
     500                       
     501                        // take max of member alignment and global alignment
     502                        addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );
     503                }
     504                // make sure the type is end-padded to a multiple of its alignment
     505                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
     506
     507                addDeclarationAfter( layoutDecl );
     508                return structDecl;
     509        }
     510       
     511        Declaration *LayoutFunctionBuilder::mutate( UnionDecl *unionDecl ) {
     512                // do not generate layout function for "empty" tag unions
     513                if ( unionDecl->get_members().empty() ) return unionDecl;
     514               
     515                // get parameters that can change layout, exiting early if none
     516                std::list< TypeDecl* > otypeParams = takeOtypeOnly( unionDecl->get_parameters() );
     517                if ( otypeParams.empty() ) return unionDecl;
     518
     519                // build layout function signature
     520                FunctionType *layoutFnType = new FunctionType( Type::Qualifiers(), false );
     521                BasicType *sizeAlignType = new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt );
     522                PointerType *sizeAlignOutType = new PointerType( Type::Qualifiers(), sizeAlignType );
     523               
     524                ObjectDecl *sizeParam = new ObjectDecl( "__sizeof_" + unionDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType, 0 );
     525                layoutFnType->get_parameters().push_back( sizeParam );
     526                ObjectDecl *alignParam = new ObjectDecl( "__alignof_" + unionDecl->get_name(), DeclarationNode::NoStorageClass, LinkageSpec::Cforall, 0, sizeAlignOutType->clone(), 0 );
     527                layoutFnType->get_parameters().push_back( alignParam );
     528                addOtypeParams( layoutFnType, otypeParams );
     529
     530                // build function decl
     531                FunctionDecl *layoutDecl = buildLayoutFunctionDecl( unionDecl->get_name(), functionNesting, layoutFnType );
     532
     533                // calculate union layout in function body
     534                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( sizeParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
     535                addExpr( layoutDecl->get_statements(), makeOp( "?=?", derefVar( alignParam ), new ConstantExpr( Constant( sizeAlignType->clone(), "1" ) ) ) );
     536                for ( std::list< Declaration* >::const_iterator member = unionDecl->get_members().begin(); member != unionDecl->get_members().end(); ++member ) {
     537                        DeclarationWithType *dwt = dynamic_cast< DeclarationWithType * >( *member );
     538                        assert( dwt );
     539                        Type *memberType = dwt->get_type();
     540                       
     541                        // take max member size and global size
     542                        addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( sizeParam ), new SizeofExpr( memberType->clone() ) ) );
     543                       
     544                        // take max of member alignment and global alignment
     545                        addStmt( layoutDecl->get_statements(), makeAssignMax( derefVar( alignParam ), new AlignofExpr( memberType->clone() ) ) );
     546                }
     547                // make sure the type is end-padded to a multiple of its alignment
     548                addStmt( layoutDecl->get_statements(), makeAlignTo( derefVar( sizeParam ), derefVar( alignParam ) ) );
     549
     550                addDeclarationAfter( layoutDecl );
     551                return unionDecl;
     552        }
     553       
    208554        ////////////////////////////////////////// Pass1 ////////////////////////////////////////////////////
    209555
     
    245591                }
    246592
    247                 Pass1::Pass1() : useRetval( false ), tempNamer( "_temp" ) {
    248                         adapters.push(AdapterMap());
    249                 }
     593                Pass1::Pass1() : useRetval( false ), tempNamer( "_temp" ) {}
    250594
    251595                /// Returns T if the given declaration is (*?=?)(T *, T) for some TypeInstType T (return not checked, but maybe should be), NULL otherwise
     
    350694                                } // for
    351695
    352                                 AdapterMap & adapters = Pass1::adapters.top();
    353696                                for ( std::list< FunctionType *>::iterator funType = functions.begin(); funType != functions.end(); ++funType ) {
    354697                                        std::string mangleName = mangleAdapterName( *funType, scopeTyVars );
     
    7721115                                        mangleName += makePolyMonoSuffix( originalFunction, exprTyVars );
    7731116
    774                                         AdapterMap & adapters = Pass1::adapters.top();
    775                                         AdapterMap::iterator adapter = adapters.find( mangleName );
     1117                                        typedef ScopedMap< std::string, DeclarationWithType* >::iterator AdapterIter;
     1118                                        AdapterIter adapter = adapters.find( mangleName );
    7761119                                        if ( adapter == adapters.end() ) {
    7771120                                                // adapter has not been created yet in the current scope, so define it
    7781121                                                FunctionDecl *newAdapter = makeAdapter( *funType, realFunction, mangleName, exprTyVars );
    779                                                 adapter = adapters.insert( adapters.begin(), std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
     1122                                                std::pair< AdapterIter, bool > answer = adapters.insert( std::pair< std::string, DeclarationWithType *>( mangleName, newAdapter ) );
     1123                                                adapter = answer.first;
    7801124                                                stmtsToAdd.push_back( new DeclStmt( noLabels, newAdapter ) );
    7811125                                        } // if
     
    11561500
    11571501                void Pass1::doBeginScope() {
    1158                         // push a copy of the current map
    1159                         adapters.push(adapters.top());
     1502                        adapters.beginScope();
    11601503                        scopedAssignOps.beginScope();
    11611504                }
    11621505
    11631506                void Pass1::doEndScope() {
    1164                         adapters.pop();
     1507                        adapters.endScope();
    11651508                        scopedAssignOps.endScope();
    11661509                }
     
    13091652                }
    13101653
     1654//////////////////////////////////////// GenericInstantiator //////////////////////////////////////////////////
     1655
     1656                /// Makes substitutions of params into baseParams; returns true if all parameters substituted for a concrete type
     1657                bool makeSubstitutions( const std::list< TypeDecl* >& baseParams, const std::list< Expression* >& params, std::list< TypeExpr* >& out ) {
     1658                        bool allConcrete = true;  // will finish the substitution list even if they're not all concrete
     1659
     1660                        // substitute concrete types for given parameters, and incomplete types for placeholders
     1661                        std::list< TypeDecl* >::const_iterator baseParam = baseParams.begin();
     1662                        std::list< Expression* >::const_iterator param = params.begin();
     1663                        for ( ; baseParam != baseParams.end() && param != params.end(); ++baseParam, ++param ) {
     1664        //                      switch ( (*baseParam)->get_kind() ) {
     1665        //                      case TypeDecl::Any: {   // any type is a valid substitution here; complete types can be used to instantiate generics
     1666                                        TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
     1667                                        assert(paramType && "Aggregate parameters should be type expressions");
     1668                                        out.push_back( paramType->clone() );
     1669                                        // check that the substituted type isn't a type variable itself
     1670                                        if ( dynamic_cast< TypeInstType* >( paramType->get_type() ) ) {
     1671                                                allConcrete = false;
     1672                                        }
     1673        //                              break;
     1674        //                      }
     1675        //                      case TypeDecl::Dtype:  // dtype can be consistently replaced with void [only pointers, which become void*]
     1676        //                              out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
     1677        //                              break;
     1678        //                      case TypeDecl::Ftype:  // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype]
     1679        //                              out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );
     1680        //                              break;
     1681        //                      }
     1682                        }
     1683
     1684                        // if any parameters left over, not done
     1685                        if ( baseParam != baseParams.end() ) return false;
     1686        //              // if not enough parameters given, substitute remaining incomplete types for placeholders
     1687        //              for ( ; baseParam != baseParams.end(); ++baseParam ) {
     1688        //                      switch ( (*baseParam)->get_kind() ) {
     1689        //                      case TypeDecl::Any:    // no more substitutions here, fail early
     1690        //                              return false;
     1691        //                      case TypeDecl::Dtype:  // dtype can be consistently replaced with void [only pointers, which become void*]
     1692        //                              out.push_back( new TypeExpr( new VoidType( Type::Qualifiers() ) ) );
     1693        //                              break;
     1694        //                      case TypeDecl::Ftype:  // pointer-to-ftype can be consistently replaced with void (*)(void) [similar to dtype]
     1695        //                              out.push_back( new TypeExpr( new FunctionType( Type::Qualifiers(), false ) ) );
     1696        //                              break;
     1697        //                      }
     1698        //              }
     1699
     1700                        return allConcrete;
     1701                }
     1702
     1703                /// Substitutes types of members of in according to baseParams => typeSubs, appending the result to out
     1704                void substituteMembers( const std::list< Declaration* >& in, const std::list< TypeDecl* >& baseParams, const std::list< TypeExpr* >& typeSubs,
     1705                                                                std::list< Declaration* >& out ) {
     1706                        // substitute types into new members
     1707                        TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
     1708                        for ( std::list< Declaration* >::const_iterator member = in.begin(); member != in.end(); ++member ) {
     1709                                Declaration *newMember = (*member)->clone();
     1710                                subs.apply(newMember);
     1711                                out.push_back( newMember );
     1712                        }
     1713                }
     1714
     1715                Type* GenericInstantiator::mutate( StructInstType *inst ) {
     1716                        // mutate subtypes
     1717                        Type *mutated = Mutator::mutate( inst );
     1718                        inst = dynamic_cast< StructInstType* >( mutated );
     1719                        if ( ! inst ) return mutated;
     1720
     1721                        // exit early if no need for further mutation
     1722                        if ( inst->get_parameters().empty() ) return inst;
     1723                        assert( inst->get_baseParameters() && "Base struct has parameters" );
     1724
     1725                        // check if type can be concretely instantiated; put substitutions into typeSubs
     1726                        std::list< TypeExpr* > typeSubs;
     1727                        if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) {
     1728                                deleteAll( typeSubs );
     1729                                return inst;
     1730                        }
     1731
     1732                        // make concrete instantiation of generic type
     1733                        StructDecl *concDecl = lookup( inst, typeSubs );
     1734                        if ( ! concDecl ) {
     1735                                // set concDecl to new type, insert type declaration into statements to add
     1736                                concDecl = new StructDecl( typeNamer.newName( inst->get_name() ) );
     1737                                substituteMembers( inst->get_baseStruct()->get_members(), *inst->get_baseParameters(), typeSubs,        concDecl->get_members() );
     1738                                DeclMutator::addDeclaration( concDecl );
     1739                                insert( inst, typeSubs, concDecl );
     1740                        }
     1741                        StructInstType *newInst = new StructInstType( inst->get_qualifiers(), concDecl->get_name() );
     1742                        newInst->set_baseStruct( concDecl );
     1743
     1744                        deleteAll( typeSubs );
     1745                        delete inst;
     1746                        return newInst;
     1747                }
     1748
     1749                Type* GenericInstantiator::mutate( UnionInstType *inst ) {
     1750                        // mutate subtypes
     1751                        Type *mutated = Mutator::mutate( inst );
     1752                        inst = dynamic_cast< UnionInstType* >( mutated );
     1753                        if ( ! inst ) return mutated;
     1754
     1755                        // exit early if no need for further mutation
     1756                        if ( inst->get_parameters().empty() ) return inst;
     1757                        assert( inst->get_baseParameters() && "Base union has parameters" );
     1758
     1759                        // check if type can be concretely instantiated; put substitutions into typeSubs
     1760                        std::list< TypeExpr* > typeSubs;
     1761                        if ( ! makeSubstitutions( *inst->get_baseParameters(), inst->get_parameters(), typeSubs ) ) {
     1762                                deleteAll( typeSubs );
     1763                                return inst;
     1764                        }
     1765
     1766                        // make concrete instantiation of generic type
     1767                        UnionDecl *concDecl = lookup( inst, typeSubs );
     1768                        if ( ! concDecl ) {
     1769                                // set concDecl to new type, insert type declaration into statements to add
     1770                                concDecl = new UnionDecl( typeNamer.newName( inst->get_name() ) );
     1771                                substituteMembers( inst->get_baseUnion()->get_members(), *inst->get_baseParameters(), typeSubs, concDecl->get_members() );
     1772                                DeclMutator::addDeclaration( concDecl );
     1773                                insert( inst, typeSubs, concDecl );
     1774                        }
     1775                        UnionInstType *newInst = new UnionInstType( inst->get_qualifiers(), concDecl->get_name() );
     1776                        newInst->set_baseUnion( concDecl );
     1777
     1778                        deleteAll( typeSubs );
     1779                        delete inst;
     1780                        return newInst;
     1781                }
     1782
     1783        //      /// Gets the base struct or union declaration for a member expression; NULL if not applicable
     1784        //      AggregateDecl* getMemberBaseDecl( MemberExpr *memberExpr ) {
     1785        //              // get variable for member aggregate
     1786        //              VariableExpr *varExpr = dynamic_cast< VariableExpr* >( memberExpr->get_aggregate() );
     1787        //              if ( ! varExpr ) return NULL;
     1788        //
     1789        //              // get object for variable
     1790        //              ObjectDecl *objectDecl = dynamic_cast< ObjectDecl* >( varExpr->get_var() );
     1791        //              if ( ! objectDecl ) return NULL;
     1792        //
     1793        //              // get base declaration from object type
     1794        //              Type *objectType = objectDecl->get_type();
     1795        //              StructInstType *structType = dynamic_cast< StructInstType* >( objectType );
     1796        //              if ( structType ) return structType->get_baseStruct();
     1797        //              UnionInstType *unionType = dynamic_cast< UnionInstType* >( objectType );
     1798        //              if ( unionType ) return unionType->get_baseUnion();
     1799        //
     1800        //              return NULL;
     1801        //      }
     1802        //
     1803        //      /// Finds the declaration with the given name, returning decls.end() if none such
     1804        //      std::list< Declaration* >::const_iterator findDeclNamed( const std::list< Declaration* > &decls, const std::string &name ) {
     1805        //              for( std::list< Declaration* >::const_iterator decl = decls.begin(); decl != decls.end(); ++decl ) {
     1806        //                      if ( (*decl)->get_name() == name ) return decl;
     1807        //              }
     1808        //              return decls.end();
     1809        //      }
     1810        //
     1811        //      Expression* Instantiate::mutate( MemberExpr *memberExpr ) {
     1812        //              // mutate, exiting early if no longer MemberExpr
     1813        //              Expression *expr = Mutator::mutate( memberExpr );
     1814        //              memberExpr = dynamic_cast< MemberExpr* >( expr );
     1815        //              if ( ! memberExpr ) return expr;
     1816        //
     1817        //              // get declaration of member and base declaration of member, exiting early if not found
     1818        //              AggregateDecl *memberBase = getMemberBaseDecl( memberExpr );
     1819        //              if ( ! memberBase ) return memberExpr;
     1820        //              DeclarationWithType *memberDecl = memberExpr->get_member();
     1821        //              std::list< Declaration* >::const_iterator baseIt = findDeclNamed( memberBase->get_members(), memberDecl->get_name() );
     1822        //              if ( baseIt == memberBase->get_members().end() ) return memberExpr;
     1823        //              DeclarationWithType *baseDecl = dynamic_cast< DeclarationWithType* >( *baseIt );
     1824        //              if ( ! baseDecl ) return memberExpr;
     1825        //
     1826        //              // check if stated type of the member is not the type of the member's declaration; if so, need a cast
     1827        //              // this *SHOULD* be safe, I don't think anything but the void-replacements I put in for dtypes would make it past the typechecker
     1828        //              SymTab::Indexer dummy;
     1829        //              if ( ResolvExpr::typesCompatible( memberDecl->get_type(), baseDecl->get_type(), dummy ) ) return memberExpr;
     1830        //              else return new CastExpr( memberExpr, memberDecl->get_type() );
     1831        //      }
     1832
     1833                void GenericInstantiator::doBeginScope() {
     1834                        DeclMutator::doBeginScope();
     1835                        instantiations.beginScope();
     1836                }
     1837
     1838                void GenericInstantiator::doEndScope() {
     1839                        DeclMutator::doEndScope();
     1840                        instantiations.endScope();
     1841                }
     1842
    13111843////////////////////////////////////////// MemberExprFixer ////////////////////////////////////////////////////
    13121844
  • src/GenPoly/DeclMutator.cc

    rb63e376 rae357ec  
    2424        }
    2525
    26         DeclMutator::DeclMutator() : Mutator(), declsToAdd(1) {}
     26        DeclMutator::DeclMutator() : Mutator(), declsToAdd(1), declsToAddAfter(1) {}
    2727
    2828        DeclMutator::~DeclMutator() {}
    2929       
    3030        void DeclMutator::mutateDeclarationList( std::list< Declaration* > &decls ) {
    31                 for ( std::list< Declaration* >::iterator decl = decls.begin(); decl != decls.end(); ++decl ) {
     31                for ( std::list< Declaration* >::iterator decl = decls.begin(); ; ++decl ) {
     32                        // splice in new declarations after previous decl
     33                        decls.splice( decl, declsToAddAfter.back() );
     34
     35                        if ( decl == decls.end() ) break;
     36                       
    3237                        // run mutator on declaration
    3338                        *decl = maybeMutate( *decl, *this );
     
    3944
    4045        void DeclMutator::doBeginScope() {
    41                 // add new decl list for inside of scope
     46                // add new decl lists for inside of scope
    4247                declsToAdd.resize( declsToAdd.size()+1 );
     48                declsToAddAfter.resize( declsToAddAfter.size()+1 );
    4349        }
    4450
     
    4955                newBack->splice( newBack->end(), *back );
    5056                declsToAdd.pop_back();
     57               
     58                back = declsToAddAfter.rbegin();
     59                newBack = back + 1;
     60                newBack->splice( newBack->end(), *back );
     61                declsToAddAfter.pop_back();
    5162        }
    5263
     
    6172                stmt = maybeMutate( stmt, *this );
    6273                // return if no declarations to add
    63                 if ( declsToAdd.back().empty() ) return stmt;
     74                if ( declsToAdd.back().empty() && declsToAddAfter.back().empty() ) {
     75                        doEndScope();
     76                        return stmt;
     77                }
    6478
    6579                // otherwise add declarations to new compound statement
     
    7185                declsToAdd.back().clear();
    7286
     87                // add mutated statement
     88                compound->get_kids().push_back( stmt );
     89
     90                // add declarations after to new compound statement
     91                for ( std::list< Declaration* >::iterator decl = declsToAddAfter.back().begin(); decl != declsToAddAfter.back().end(); ++decl ) {
     92                        DeclStmt *declStmt = new DeclStmt( noLabels, *decl );
     93                        compound->get_kids().push_back( declStmt );
     94                }
     95                declsToAddAfter.back().clear();
     96
    7397                doEndScope();
    74 
    75                 // add mutated statement and return
    76                 compound->get_kids().push_back( stmt );
    7798                return compound;
    7899        }
     
    80101        void DeclMutator::mutateStatementList( std::list< Statement* > &stmts ) {
    81102                doBeginScope();
     103
    82104               
    83                 for ( std::list< Statement* >::iterator stmt = stmts.begin(); stmt != stmts.end(); ++stmt ) {
     105                for ( std::list< Statement* >::iterator stmt = stmts.begin(); ; ++stmt ) {
     106                        // add any new declarations after the previous statement
     107                        for ( std::list< Declaration* >::iterator decl = declsToAddAfter.back().begin(); decl != declsToAddAfter.back().end(); ++decl ) {
     108                                DeclStmt *declStmt = new DeclStmt( noLabels, *decl );
     109                                stmts.insert( stmt, declStmt );
     110                        }
     111                        declsToAddAfter.back().clear();
     112
     113                        if ( stmt == stmts.end() ) break;
     114                       
    84115                        // run mutator on statement
    85116                        *stmt = maybeMutate( *stmt, *this );
     
    92123                        declsToAdd.back().clear();
    93124                }
    94 
     125               
    95126                doEndScope();
    96127        }
     
    98129        void DeclMutator::addDeclaration( Declaration *decl ) {
    99130                declsToAdd.back().push_back( decl );
     131        }
     132
     133        void DeclMutator::addDeclarationAfter( Declaration *decl ) {
     134                declsToAddAfter.back().push_back( decl );
    100135        }
    101136
  • src/GenPoly/DeclMutator.h

    rb63e376 rae357ec  
    5555                /// Add a declaration to the list to be added before the current position
    5656                void addDeclaration( Declaration* decl );
     57                /// Add a declaration to the list to be added after the current position
     58                void addDeclarationAfter( Declaration* decl );
    5759        private:
    5860                /// A stack of declarations to add before the current declaration or statement
    5961                std::vector< std::list< Declaration* > > declsToAdd;
     62                /// A stack of declarations to add after the current declaration or statement
     63                std::vector< std::list< Declaration* > > declsToAddAfter;
    6064        };
    6165} // namespace
  • src/GenPoly/module.mk

    rb63e376 rae357ec  
    2323       GenPoly/CopyParams.cc \
    2424       GenPoly/FindFunction.cc \
    25        GenPoly/InstantiateGeneric.cc \
    2625       GenPoly/DeclMutator.cc
  • src/Makefile.in

    rb63e376 rae357ec  
    122122        GenPoly/driver_cfa_cpp-CopyParams.$(OBJEXT) \
    123123        GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT) \
    124         GenPoly/driver_cfa_cpp-InstantiateGeneric.$(OBJEXT) \
    125124        GenPoly/driver_cfa_cpp-DeclMutator.$(OBJEXT) \
    126125        InitTweak/driver_cfa_cpp-RemoveInit.$(OBJEXT) \
     
    154153        ResolvExpr/driver_cfa_cpp-Occurs.$(OBJEXT) \
    155154        ResolvExpr/driver_cfa_cpp-TypeEnvironment.$(OBJEXT) \
    156         SymTab/driver_cfa_cpp-IdTable.$(OBJEXT) \
    157155        SymTab/driver_cfa_cpp-Indexer.$(OBJEXT) \
    158156        SymTab/driver_cfa_cpp-Mangler.$(OBJEXT) \
     
    347345        GenPoly/ScrubTyVars.cc GenPoly/Lvalue.cc GenPoly/Specialize.cc \
    348346        GenPoly/CopyParams.cc GenPoly/FindFunction.cc \
    349         GenPoly/InstantiateGeneric.cc GenPoly/DeclMutator.cc \
    350         InitTweak/RemoveInit.cc Parser/parser.yy Parser/lex.ll \
    351         Parser/TypedefTable.cc Parser/ParseNode.cc \
    352         Parser/DeclarationNode.cc Parser/ExpressionNode.cc \
    353         Parser/StatementNode.cc Parser/InitializerNode.cc \
    354         Parser/TypeData.cc Parser/LinkageSpec.cc \
    355         Parser/parseutility.cc Parser/Parser.cc \
     347        GenPoly/DeclMutator.cc InitTweak/RemoveInit.cc \
     348        Parser/parser.yy Parser/lex.ll Parser/TypedefTable.cc \
     349        Parser/ParseNode.cc Parser/DeclarationNode.cc \
     350        Parser/ExpressionNode.cc Parser/StatementNode.cc \
     351        Parser/InitializerNode.cc Parser/TypeData.cc \
     352        Parser/LinkageSpec.cc Parser/parseutility.cc Parser/Parser.cc \
    356353        ResolvExpr/AlternativeFinder.cc ResolvExpr/Alternative.cc \
    357354        ResolvExpr/Unify.cc ResolvExpr/PtrsAssignable.cc \
     
    362359        ResolvExpr/RenameVars.cc ResolvExpr/FindOpenVars.cc \
    363360        ResolvExpr/PolyCost.cc ResolvExpr/Occurs.cc \
    364         ResolvExpr/TypeEnvironment.cc SymTab/IdTable.cc \
    365         SymTab/Indexer.cc SymTab/Mangler.cc SymTab/Validate.cc \
    366         SymTab/FixFunction.cc SymTab/ImplementationType.cc \
    367         SymTab/TypeEquality.cc SynTree/Type.cc SynTree/VoidType.cc \
    368         SynTree/BasicType.cc SynTree/PointerType.cc \
    369         SynTree/ArrayType.cc SynTree/FunctionType.cc \
    370         SynTree/ReferenceToType.cc SynTree/TupleType.cc \
    371         SynTree/TypeofType.cc SynTree/AttrType.cc \
     361        ResolvExpr/TypeEnvironment.cc SymTab/Indexer.cc \
     362        SymTab/Mangler.cc SymTab/Validate.cc SymTab/FixFunction.cc \
     363        SymTab/ImplementationType.cc SymTab/TypeEquality.cc \
     364        SynTree/Type.cc SynTree/VoidType.cc SynTree/BasicType.cc \
     365        SynTree/PointerType.cc SynTree/ArrayType.cc \
     366        SynTree/FunctionType.cc SynTree/ReferenceToType.cc \
     367        SynTree/TupleType.cc SynTree/TypeofType.cc SynTree/AttrType.cc \
    372368        SynTree/VarArgsType.cc SynTree/Constant.cc \
    373369        SynTree/Expression.cc SynTree/TupleExpr.cc \
     
    556552        GenPoly/$(DEPDIR)/$(am__dirstamp)
    557553GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT):  \
    558         GenPoly/$(am__dirstamp) GenPoly/$(DEPDIR)/$(am__dirstamp)
    559 GenPoly/driver_cfa_cpp-InstantiateGeneric.$(OBJEXT):  \
    560554        GenPoly/$(am__dirstamp) GenPoly/$(DEPDIR)/$(am__dirstamp)
    561555GenPoly/driver_cfa_cpp-DeclMutator.$(OBJEXT): GenPoly/$(am__dirstamp) \
     
    664658        @$(MKDIR_P) SymTab/$(DEPDIR)
    665659        @: > SymTab/$(DEPDIR)/$(am__dirstamp)
    666 SymTab/driver_cfa_cpp-IdTable.$(OBJEXT): SymTab/$(am__dirstamp) \
    667         SymTab/$(DEPDIR)/$(am__dirstamp)
    668660SymTab/driver_cfa_cpp-Indexer.$(OBJEXT): SymTab/$(am__dirstamp) \
    669661        SymTab/$(DEPDIR)/$(am__dirstamp)
     
    796788        -rm -f GenPoly/driver_cfa_cpp-FindFunction.$(OBJEXT)
    797789        -rm -f GenPoly/driver_cfa_cpp-GenPoly.$(OBJEXT)
    798         -rm -f GenPoly/driver_cfa_cpp-InstantiateGeneric.$(OBJEXT)
    799790        -rm -f GenPoly/driver_cfa_cpp-Lvalue.$(OBJEXT)
    800791        -rm -f GenPoly/driver_cfa_cpp-PolyMutator.$(OBJEXT)
     
    832823        -rm -f ResolvExpr/driver_cfa_cpp-Unify.$(OBJEXT)
    833824        -rm -f SymTab/driver_cfa_cpp-FixFunction.$(OBJEXT)
    834         -rm -f SymTab/driver_cfa_cpp-IdTable.$(OBJEXT)
    835825        -rm -f SymTab/driver_cfa_cpp-ImplementationType.$(OBJEXT)
    836826        -rm -f SymTab/driver_cfa_cpp-Indexer.$(OBJEXT)
     
    903893@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-FindFunction.Po@am__quote@
    904894@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-GenPoly.Po@am__quote@
    905 @AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Po@am__quote@
    906895@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-Lvalue.Po@am__quote@
    907896@AMDEP_TRUE@@am__include@ @am__quote@GenPoly/$(DEPDIR)/driver_cfa_cpp-PolyMutator.Po@am__quote@
     
    939928@AMDEP_TRUE@@am__include@ @am__quote@ResolvExpr/$(DEPDIR)/driver_cfa_cpp-Unify.Po@am__quote@
    940929@AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-FixFunction.Po@am__quote@
    941 @AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-IdTable.Po@am__quote@
    942930@AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-ImplementationType.Po@am__quote@
    943931@AMDEP_TRUE@@am__include@ @am__quote@SymTab/$(DEPDIR)/driver_cfa_cpp-Indexer.Po@am__quote@
     
    13641352@am__fastdepCXX_FALSE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-FindFunction.obj `if test -f 'GenPoly/FindFunction.cc'; then $(CYGPATH_W) 'GenPoly/FindFunction.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/FindFunction.cc'; fi`
    13651353
    1366 GenPoly/driver_cfa_cpp-InstantiateGeneric.o: GenPoly/InstantiateGeneric.cc
    1367 @am__fastdepCXX_TRUE@   $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-InstantiateGeneric.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Tpo -c -o GenPoly/driver_cfa_cpp-InstantiateGeneric.o `test -f 'GenPoly/InstantiateGeneric.cc' || echo '$(srcdir)/'`GenPoly/InstantiateGeneric.cc
    1368 @am__fastdepCXX_TRUE@   $(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Po
    1369 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      source='GenPoly/InstantiateGeneric.cc' object='GenPoly/driver_cfa_cpp-InstantiateGeneric.o' libtool=no @AMDEPBACKSLASH@
    1370 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1371 @am__fastdepCXX_FALSE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-InstantiateGeneric.o `test -f 'GenPoly/InstantiateGeneric.cc' || echo '$(srcdir)/'`GenPoly/InstantiateGeneric.cc
    1372 
    1373 GenPoly/driver_cfa_cpp-InstantiateGeneric.obj: GenPoly/InstantiateGeneric.cc
    1374 @am__fastdepCXX_TRUE@   $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-InstantiateGeneric.obj -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Tpo -c -o GenPoly/driver_cfa_cpp-InstantiateGeneric.obj `if test -f 'GenPoly/InstantiateGeneric.cc'; then $(CYGPATH_W) 'GenPoly/InstantiateGeneric.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/InstantiateGeneric.cc'; fi`
    1375 @am__fastdepCXX_TRUE@   $(am__mv) GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Tpo GenPoly/$(DEPDIR)/driver_cfa_cpp-InstantiateGeneric.Po
    1376 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      source='GenPoly/InstantiateGeneric.cc' object='GenPoly/driver_cfa_cpp-InstantiateGeneric.obj' libtool=no @AMDEPBACKSLASH@
    1377 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1378 @am__fastdepCXX_FALSE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o GenPoly/driver_cfa_cpp-InstantiateGeneric.obj `if test -f 'GenPoly/InstantiateGeneric.cc'; then $(CYGPATH_W) 'GenPoly/InstantiateGeneric.cc'; else $(CYGPATH_W) '$(srcdir)/GenPoly/InstantiateGeneric.cc'; fi`
    1379 
    13801354GenPoly/driver_cfa_cpp-DeclMutator.o: GenPoly/DeclMutator.cc
    13811355@am__fastdepCXX_TRUE@   $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT GenPoly/driver_cfa_cpp-DeclMutator.o -MD -MP -MF GenPoly/$(DEPDIR)/driver_cfa_cpp-DeclMutator.Tpo -c -o GenPoly/driver_cfa_cpp-DeclMutator.o `test -f 'GenPoly/DeclMutator.cc' || echo '$(srcdir)/'`GenPoly/DeclMutator.cc
     
    18111785@AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    18121786@am__fastdepCXX_FALSE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o ResolvExpr/driver_cfa_cpp-TypeEnvironment.obj `if test -f 'ResolvExpr/TypeEnvironment.cc'; then $(CYGPATH_W) 'ResolvExpr/TypeEnvironment.cc'; else $(CYGPATH_W) '$(srcdir)/ResolvExpr/TypeEnvironment.cc'; fi`
    1813 
    1814 SymTab/driver_cfa_cpp-IdTable.o: SymTab/IdTable.cc
    1815 @am__fastdepCXX_TRUE@   $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-IdTable.o -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-IdTable.Tpo -c -o SymTab/driver_cfa_cpp-IdTable.o `test -f 'SymTab/IdTable.cc' || echo '$(srcdir)/'`SymTab/IdTable.cc
    1816 @am__fastdepCXX_TRUE@   $(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-IdTable.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-IdTable.Po
    1817 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      source='SymTab/IdTable.cc' object='SymTab/driver_cfa_cpp-IdTable.o' libtool=no @AMDEPBACKSLASH@
    1818 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1819 @am__fastdepCXX_FALSE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-IdTable.o `test -f 'SymTab/IdTable.cc' || echo '$(srcdir)/'`SymTab/IdTable.cc
    1820 
    1821 SymTab/driver_cfa_cpp-IdTable.obj: SymTab/IdTable.cc
    1822 @am__fastdepCXX_TRUE@   $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -MT SymTab/driver_cfa_cpp-IdTable.obj -MD -MP -MF SymTab/$(DEPDIR)/driver_cfa_cpp-IdTable.Tpo -c -o SymTab/driver_cfa_cpp-IdTable.obj `if test -f 'SymTab/IdTable.cc'; then $(CYGPATH_W) 'SymTab/IdTable.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/IdTable.cc'; fi`
    1823 @am__fastdepCXX_TRUE@   $(am__mv) SymTab/$(DEPDIR)/driver_cfa_cpp-IdTable.Tpo SymTab/$(DEPDIR)/driver_cfa_cpp-IdTable.Po
    1824 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      source='SymTab/IdTable.cc' object='SymTab/driver_cfa_cpp-IdTable.obj' libtool=no @AMDEPBACKSLASH@
    1825 @AMDEP_TRUE@@am__fastdepCXX_FALSE@      DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@
    1826 @am__fastdepCXX_FALSE@  $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(driver_cfa_cpp_CXXFLAGS) $(CXXFLAGS) -c -o SymTab/driver_cfa_cpp-IdTable.obj `if test -f 'SymTab/IdTable.cc'; then $(CYGPATH_W) 'SymTab/IdTable.cc'; else $(CYGPATH_W) '$(srcdir)/SymTab/IdTable.cc'; fi`
    18271787
    18281788SymTab/driver_cfa_cpp-Indexer.o: SymTab/Indexer.cc
  • src/SymTab/Indexer.cc

    rb63e376 rae357ec  
    1414//
    1515
     16#include "Indexer.h"
     17
     18#include <string>
     19#include <typeinfo>
     20#include <unordered_map>
     21#include <utility>
     22
     23#include "Mangler.h"
     24
     25#include "Common/utility.h"
     26
     27#include "ResolvExpr/typeops.h"
     28
    1629#include "SynTree/Declaration.h"
    1730#include "SynTree/Type.h"
     
    1932#include "SynTree/Initializer.h"
    2033#include "SynTree/Statement.h"
    21 #include "Indexer.h"
    22 #include <typeinfo>
    23 #include "Common/utility.h"
    2434
    2535#define debugPrint(x) if ( doDebug ) { std::cout << x; }
     
    3343        }
    3444
    35         Indexer::Indexer( bool useDebug ) : doDebug( useDebug ) {}
    36 
    37         Indexer::~Indexer() {}
     45        typedef std::unordered_map< std::string, DeclarationWithType* > MangleTable;
     46        typedef std::unordered_map< std::string, MangleTable > IdTable;
     47        typedef std::unordered_map< std::string, NamedTypeDecl* > TypeTable;
     48        typedef std::unordered_map< std::string, StructDecl* > StructTable;
     49        typedef std::unordered_map< std::string, EnumDecl* > EnumTable;
     50        typedef std::unordered_map< std::string, UnionDecl* > UnionTable;
     51        typedef std::unordered_map< std::string, TraitDecl* > TraitTable;
     52
     53        void dump( const IdTable &table, std::ostream &os ) {
     54                for ( IdTable::const_iterator id = table.begin(); id != table.end(); ++id ) {
     55                        for ( MangleTable::const_iterator mangle = id->second.begin(); mangle != id->second.end(); ++mangle ) {
     56                                os << mangle->second << std::endl;
     57                        }
     58                }
     59        }
     60       
     61        template< typename Decl >
     62        void dump( const std::unordered_map< std::string, Decl* > &table, std::ostream &os ) {
     63                for ( typename std::unordered_map< std::string, Decl* >::const_iterator it = table.begin(); it != table.end(); ++it ) {
     64                        os << it->second << std::endl;
     65                } // for
     66        }
     67       
     68        struct Indexer::Impl {
     69                Impl( unsigned long _scope ) : refCount(1), scope( _scope ), size( 0 ), base(),
     70                                idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable() {}
     71                Impl( unsigned long _scope, Indexer &&_base ) : refCount(1), scope( _scope ), size( 0 ), base( _base ),
     72                                idTable(), typeTable(), structTable(), enumTable(), unionTable(), traitTable() {}
     73                unsigned long refCount;   ///< Number of references to these tables
     74                unsigned long scope;      ///< Scope these tables are associated with
     75                unsigned long size;       ///< Number of elements stored in this table
     76                const Indexer base;       ///< Base indexer this extends
     77               
     78                IdTable idTable;          ///< Identifier namespace
     79                TypeTable typeTable;      ///< Type namespace
     80                StructTable structTable;  ///< Struct namespace
     81                EnumTable enumTable;      ///< Enum namespace
     82                UnionTable unionTable;    ///< Union namespace
     83                TraitTable traitTable;    ///< Trait namespace
     84        };
     85
     86        Indexer::Impl *Indexer::newRef( Indexer::Impl *toClone ) {
     87                if ( ! toClone ) return 0;
     88
     89                // shorten the search chain by skipping empty links
     90                Indexer::Impl *ret = toClone->size == 0 ? toClone->base.tables : toClone;
     91                if ( ret ) { ++ret->refCount; }
     92
     93                return ret;
     94        }
     95
     96        void Indexer::deleteRef( Indexer::Impl *toFree ) {
     97                if ( ! toFree ) return;
     98
     99                if ( --toFree->refCount == 0 ) delete toFree;
     100        }
     101
     102        void Indexer::makeWritable() {
     103                if ( ! tables ) {
     104                        // create indexer if not yet set
     105                        tables = new Indexer::Impl( scope );
     106                } else if ( tables->refCount > 1 || tables->scope != scope ) {
     107                        // make this indexer the base of a fresh indexer at the current scope
     108                        tables = new Indexer::Impl( scope, std::move( *this ) );
     109                }
     110        }
     111
     112        Indexer::Indexer( bool _doDebug ) : tables( 0 ), scope( 0 ), doDebug( _doDebug ) {}
     113
     114        Indexer::Indexer( const Indexer &that ) : tables( newRef( that.tables ) ), scope( that.scope ), doDebug( that.doDebug ) {}
     115
     116        Indexer::Indexer( Indexer &&that ) : tables( that.tables ), scope( that.scope ), doDebug( that.doDebug ) {
     117                that.tables = 0;
     118        }
     119
     120        Indexer::~Indexer() {
     121                deleteRef( tables );
     122        }
     123
     124        Indexer& Indexer::operator= ( const Indexer &that ) {
     125                deleteRef( tables );
     126
     127                tables = newRef( that.tables );
     128                scope = that.scope;
     129                doDebug = that.doDebug;
     130
     131                return *this;
     132        }
     133
     134        Indexer& Indexer::operator= ( Indexer &&that ) {
     135                deleteRef( tables );
     136
     137                tables = that.tables;
     138                scope = that.scope;
     139                doDebug = that.doDebug;
     140
     141                that.tables = 0;
     142
     143                return *this;
     144        }
    38145
    39146        void Indexer::visit( ObjectDecl *objectDecl ) {
     
    45152                if ( objectDecl->get_name() != "" ) {
    46153                        debugPrint( "Adding object " << objectDecl->get_name() << std::endl );
    47                         idTable.addDecl( objectDecl );
     154                        addId( objectDecl );
    48155                } // if
    49156        }
     
    52159                if ( functionDecl->get_name() == "" ) return;
    53160                debugPrint( "Adding function " << functionDecl->get_name() << std::endl );
    54                 idTable.addDecl( functionDecl );
     161                addId( functionDecl );
    55162                enterScope();
    56163                maybeAccept( functionDecl->get_functionType(), *this );
     
    90197                leaveScope();
    91198                debugPrint( "Adding type " << typeDecl->get_name() << std::endl );
    92                 typeTable.add( typeDecl );
     199                addType( typeDecl );
    93200                acceptAll( typeDecl->get_assertions(), *this );
    94201        }
     
    100207                leaveScope();
    101208                debugPrint( "Adding typedef " << typeDecl->get_name() << std::endl );
    102                 typeTable.add( typeDecl );
     209                addType( typeDecl );
    103210        }
    104211
     
    108215                cloneAll( aggregateDecl->get_parameters(), fwdDecl.get_parameters() );
    109216                debugPrint( "Adding fwd decl for struct " << fwdDecl.get_name() << std::endl );
    110                 structTable.add( &fwdDecl );
     217                addStruct( &fwdDecl );
    111218 
    112219                enterScope();
     
    117224                debugPrint( "Adding struct " << aggregateDecl->get_name() << std::endl );
    118225                // this addition replaces the forward declaration
    119                 structTable.add( aggregateDecl );
     226                addStruct( aggregateDecl );
    120227        }
    121228
     
    125232                cloneAll( aggregateDecl->get_parameters(), fwdDecl.get_parameters() );
    126233                debugPrint( "Adding fwd decl for union " << fwdDecl.get_name() << std::endl );
    127                 unionTable.add( &fwdDecl );
     234                addUnion( &fwdDecl );
    128235 
    129236                enterScope();
     
    133240 
    134241                debugPrint( "Adding union " << aggregateDecl->get_name() << std::endl );
    135                 unionTable.add( aggregateDecl );
     242                addUnion( aggregateDecl );
    136243        }
    137244
    138245        void Indexer::visit( EnumDecl *aggregateDecl ) {
    139246                debugPrint( "Adding enum " << aggregateDecl->get_name() << std::endl );
    140                 enumTable.add( aggregateDecl );
     247                addEnum( aggregateDecl );
    141248                // unlike structs, contexts, and unions, enums inject their members into the global scope
    142249                acceptAll( aggregateDecl->get_members(), *this );
     
    150257 
    151258                debugPrint( "Adding context " << aggregateDecl->get_name() << std::endl );
    152                 contextTable.add( aggregateDecl );
     259                addTrait( aggregateDecl );
    153260        }
    154261
     
    299406
    300407        void Indexer::visit( StructInstType *structInst ) {
    301                 if ( ! structTable.lookup( structInst->get_name() ) ) {
     408                if ( ! lookupStruct( structInst->get_name() ) ) {
    302409                        debugPrint( "Adding struct " << structInst->get_name() << " from implicit forward declaration" << std::endl );
    303                         structTable.add( structInst->get_name() );
     410                        addStruct( structInst->get_name() );
    304411                }
    305412                enterScope();
     
    309416
    310417        void Indexer::visit( UnionInstType *unionInst ) {
    311                 if ( ! unionTable.lookup( unionInst->get_name() ) ) {
     418                if ( ! lookupUnion( unionInst->get_name() ) ) {
    312419                        debugPrint( "Adding union " << unionInst->get_name() << " from implicit forward declaration" << std::endl );
    313                         unionTable.add( unionInst->get_name() );
     420                        addUnion( unionInst->get_name() );
    314421                }
    315422                enterScope();
     
    325432        }
    326433
    327 
    328         void Indexer::lookupId( const std::string &id, std::list< DeclarationWithType* > &list ) const {
    329                 idTable.lookupId( id, list );
    330         }
    331 
    332         DeclarationWithType* Indexer::lookupId( const std::string &id) const {
    333                 return idTable.lookupId(id);
     434       
     435
     436        void Indexer::lookupId( const std::string &id, std::list< DeclarationWithType* > &out ) const {
     437                if ( ! tables ) return;
     438
     439                IdTable::const_iterator decls = tables->idTable.find( id );
     440                if ( decls != tables->idTable.end() ) {
     441                        const MangleTable &mangleTable = decls->second;
     442                        for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) {
     443                                out.push_back( decl->second );
     444                        }
     445                }
     446               
     447                // get declarations from base indexers
     448                tables->base.lookupId( id, out );
    334449        }
    335450
    336451        NamedTypeDecl *Indexer::lookupType( const std::string &id ) const {
    337                 return typeTable.lookup( id );
     452                if ( ! tables ) return 0;
     453
     454                TypeTable::const_iterator ret = tables->typeTable.find( id );
     455                return ret != tables->typeTable.end() ? ret->second : tables->base.lookupType( id );
    338456        }
    339457
    340458        StructDecl *Indexer::lookupStruct( const std::string &id ) const {
    341                 return structTable.lookup( id );
     459                if ( ! tables ) return 0;
     460
     461                StructTable::const_iterator ret = tables->structTable.find( id );
     462                return ret != tables->structTable.end() ? ret->second : tables->base.lookupStruct( id );
    342463        }
    343464
    344465        EnumDecl *Indexer::lookupEnum( const std::string &id ) const {
    345                 return enumTable.lookup( id );
     466                if ( ! tables ) return 0;
     467
     468                EnumTable::const_iterator ret = tables->enumTable.find( id );
     469                return ret != tables->enumTable.end() ? ret->second : tables->base.lookupEnum( id );
    346470        }
    347471
    348472        UnionDecl *Indexer::lookupUnion( const std::string &id ) const {
    349                 return unionTable.lookup( id );
    350         }
    351 
    352         TraitDecl  * Indexer::lookupTrait( const std::string &id ) const {
    353                 return contextTable.lookup( id );
     473                if ( ! tables ) return 0;
     474
     475                UnionTable::const_iterator ret = tables->unionTable.find( id );
     476                return ret != tables->unionTable.end() ? ret->second : tables->base.lookupUnion( id );
     477        }
     478
     479        TraitDecl *Indexer::lookupTrait( const std::string &id ) const {
     480                if ( ! tables ) return 0;
     481
     482                TraitTable::const_iterator ret = tables->traitTable.find( id );
     483                return ret != tables->traitTable.end() ? ret->second : tables->base.lookupTrait( id );
     484        }
     485
     486        DeclarationWithType *Indexer::lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const {
     487                if ( ! tables ) return 0;
     488                if ( tables->scope < scope ) return 0;
     489
     490                IdTable::const_iterator decls = tables->idTable.find( id );
     491                if ( decls != tables->idTable.end() ) {
     492                        const MangleTable &mangleTable = decls->second;
     493                        MangleTable::const_iterator decl = mangleTable.find( mangleName );
     494                        if ( decl != mangleTable.end() ) return decl->second;
     495                }
     496
     497                return tables->base.lookupIdAtScope( id, mangleName, scope );
     498        }
     499
     500        bool Indexer::hasCDeclWithName( const std::string &id ) const {
     501                if ( ! tables ) return false;
     502
     503                IdTable::const_iterator decls = tables->idTable.find( id );
     504                if ( decls != tables->idTable.end() ) {
     505                        const MangleTable &mangleTable = decls->second;
     506                        for ( MangleTable::const_iterator decl = mangleTable.begin(); decl != mangleTable.end(); ++decl ) {
     507                                if ( decl->second->get_linkage() == LinkageSpec::C ) return true;
     508                        }
     509                }
     510
     511                return tables->base.hasCDeclWithName( id );
     512        }
     513       
     514        NamedTypeDecl *Indexer::lookupTypeAtScope( const std::string &id, unsigned long scope ) const {
     515                if ( ! tables ) return 0;
     516                if ( tables->scope < scope ) return 0;
     517
     518                TypeTable::const_iterator ret = tables->typeTable.find( id );
     519                return ret != tables->typeTable.end() ? ret->second : tables->base.lookupTypeAtScope( id, scope );
     520        }
     521       
     522        StructDecl *Indexer::lookupStructAtScope( const std::string &id, unsigned long scope ) const {
     523                if ( ! tables ) return 0;
     524                if ( tables->scope < scope ) return 0;
     525
     526                StructTable::const_iterator ret = tables->structTable.find( id );
     527                return ret != tables->structTable.end() ? ret->second : tables->base.lookupStructAtScope( id, scope );
     528        }
     529       
     530        EnumDecl *Indexer::lookupEnumAtScope( const std::string &id, unsigned long scope ) const {
     531                if ( ! tables ) return 0;
     532                if ( tables->scope < scope ) return 0;
     533
     534                EnumTable::const_iterator ret = tables->enumTable.find( id );
     535                return ret != tables->enumTable.end() ? ret->second : tables->base.lookupEnumAtScope( id, scope );
     536        }
     537       
     538        UnionDecl *Indexer::lookupUnionAtScope( const std::string &id, unsigned long scope ) const {
     539                if ( ! tables ) return 0;
     540                if ( tables->scope < scope ) return 0;
     541
     542                UnionTable::const_iterator ret = tables->unionTable.find( id );
     543                return ret != tables->unionTable.end() ? ret->second : tables->base.lookupUnionAtScope( id, scope );
     544        }
     545       
     546        TraitDecl *Indexer::lookupTraitAtScope( const std::string &id, unsigned long scope ) const {
     547                if ( ! tables ) return 0;
     548                if ( tables->scope < scope ) return 0;
     549
     550                TraitTable::const_iterator ret = tables->traitTable.find( id );
     551                return ret != tables->traitTable.end() ? ret->second : tables->base.lookupTraitAtScope( id, scope );
     552        }
     553
     554        bool addedIdConflicts( DeclarationWithType *existing, DeclarationWithType *added ) {
     555                // if we're giving the same name mangling to things of different types then there is something wrong
     556                assert( (dynamic_cast<ObjectDecl*>( added ) && dynamic_cast<ObjectDecl*>( existing ) )
     557                        || (dynamic_cast<FunctionDecl*>( added ) && dynamic_cast<FunctionDecl*>( existing ) ) );
     558
     559                if ( LinkageSpec::isOverridable( existing->get_linkage() ) ) {
     560                        // new definition shadows the autogenerated one, even at the same scope
     561                        return false;
     562                } else if ( added->get_linkage() != LinkageSpec::C || ResolvExpr::typesCompatible( added->get_type(), existing->get_type(), Indexer() ) ) {
     563                        // typesCompatible doesn't really do the right thing here. When checking compatibility of function types,
     564                        // we should ignore outermost pointer qualifiers, except _Atomic?
     565                        FunctionDecl *newentry = dynamic_cast< FunctionDecl* >( added );
     566                        FunctionDecl *oldentry = dynamic_cast< FunctionDecl* >( existing );
     567                        if ( newentry && oldentry ) {
     568                                if ( newentry->get_statements() && oldentry->get_statements() ) {
     569                                        throw SemanticError( "duplicate function definition for ", added );
     570                                } // if
     571                        } else {
     572                                // two objects with the same mangled name defined in the same scope.
     573                                // both objects must be marked extern or both must be intrinsic for this to be okay
     574                                // xxx - perhaps it's actually if either is intrinsic then this is okay?
     575                                //       might also need to be same storage class?
     576                                ObjectDecl *newobj = dynamic_cast< ObjectDecl* >( added );
     577                                ObjectDecl *oldobj = dynamic_cast< ObjectDecl* >( existing );
     578                                if ( newobj->get_storageClass() != DeclarationNode::Extern && oldobj->get_storageClass() != DeclarationNode::Extern ) {
     579                                        throw SemanticError( "duplicate object definition for ", added );
     580                                } // if
     581                        } // if
     582                } else {
     583                        throw SemanticError( "duplicate definition for ", added );
     584                } // if
     585
     586                return true;
     587        }
     588       
     589        void Indexer::addId( DeclarationWithType *decl ) {
     590                makeWritable();
     591
     592                const std::string &name = decl->get_name();
     593                std::string mangleName;
     594                if ( decl->get_linkage() == LinkageSpec::C ) {
     595                        mangleName = name;
     596                } else if ( LinkageSpec::isOverridable( decl->get_linkage() ) ) {
     597                        // mangle the name without including the appropriate suffix, so overridable routines are placed into the
     598                        // same "bucket" as their user defined versions.
     599                        mangleName = Mangler::mangle( decl, false );
     600                } else {
     601                        mangleName = Mangler::mangle( decl );
     602                } // if
     603
     604                DeclarationWithType *existing = lookupIdAtScope( name, mangleName, scope );
     605                if ( ! existing || ! addedIdConflicts( existing, decl ) ) {
     606                        // this ensures that no two declarations with the same unmangled name both have C linkage
     607                        if ( decl->get_linkage() == LinkageSpec::C && hasCDeclWithName( name ) ) {
     608                                throw SemanticError( "invalid overload of C function ", decl );
     609                        }
     610                       
     611                        tables->idTable[ name ][ mangleName ] = decl;
     612                        ++tables->size;
     613                }
     614        }
     615
     616        bool addedTypeConflicts( NamedTypeDecl *existing, NamedTypeDecl *added ) {
     617                if ( existing->get_base() == 0 ) {
     618                        return false;
     619                } else if ( added->get_base() == 0 ) {
     620                        return true;
     621                } else {
     622                        throw SemanticError( "redeclaration of ", added );
     623                }
     624        }
     625       
     626        void Indexer::addType( NamedTypeDecl *decl ) {
     627                makeWritable();
     628
     629                const std::string &id = decl->get_name();
     630                TypeTable::iterator existing = tables->typeTable.find( id );
     631                if ( existing == tables->typeTable.end() ) {
     632                        NamedTypeDecl *parent = tables->base.lookupTypeAtScope( id, scope );
     633                        if ( ! parent || ! addedTypeConflicts( parent, decl ) ) {
     634                                tables->typeTable.insert( existing, std::make_pair( id, decl ) );
     635                                ++tables->size;
     636                        }
     637                } else {
     638                        if ( ! addedTypeConflicts( existing->second, decl ) ) {
     639                                existing->second = decl;
     640                        }
     641                }
     642        }
     643
     644        bool addedDeclConflicts( AggregateDecl *existing, AggregateDecl *added ) {
     645                if ( existing->get_members().empty() ) {
     646                        return false;
     647                } else if ( ! added->get_members().empty() ) {
     648                        throw SemanticError( "redeclaration of ", added );
     649                } // if
     650                return true;
     651        }
     652
     653        void Indexer::addStruct( const std::string &id ) {
     654                addStruct( new StructDecl( id ) );
     655        }
     656       
     657        void Indexer::addStruct( StructDecl *decl ) {
     658                makeWritable();
     659
     660                const std::string &id = decl->get_name();
     661                StructTable::iterator existing = tables->structTable.find( id );
     662                if ( existing == tables->structTable.end() ) {
     663                        StructDecl *parent = tables->base.lookupStructAtScope( id, scope );
     664                        if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
     665                                tables->structTable.insert( existing, std::make_pair( id, decl ) );
     666                                ++tables->size;
     667                        }
     668                } else {
     669                        if ( ! addedDeclConflicts( existing->second, decl ) ) {
     670                                existing->second = decl;
     671                        }
     672                }
     673        }
     674       
     675        void Indexer::addEnum( EnumDecl *decl ) {
     676                makeWritable();
     677
     678                const std::string &id = decl->get_name();
     679                EnumTable::iterator existing = tables->enumTable.find( id );
     680                if ( existing == tables->enumTable.end() ) {
     681                        EnumDecl *parent = tables->base.lookupEnumAtScope( id, scope );
     682                        if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
     683                                tables->enumTable.insert( existing, std::make_pair( id, decl ) );
     684                                ++tables->size;
     685                        }
     686                } else {
     687                        if ( ! addedDeclConflicts( existing->second, decl ) ) {
     688                                existing->second = decl;
     689                        }
     690                }
     691        }
     692
     693        void Indexer::addUnion( const std::string &id ) {
     694                addUnion( new UnionDecl( id ) );
     695        }
     696       
     697        void Indexer::addUnion( UnionDecl *decl ) {
     698                makeWritable();
     699
     700                const std::string &id = decl->get_name();
     701                UnionTable::iterator existing = tables->unionTable.find( id );
     702                if ( existing == tables->unionTable.end() ) {
     703                        UnionDecl *parent = tables->base.lookupUnionAtScope( id, scope );
     704                        if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
     705                                tables->unionTable.insert( existing, std::make_pair( id, decl ) );
     706                                ++tables->size;
     707                        }
     708                } else {
     709                        if ( ! addedDeclConflicts( existing->second, decl ) ) {
     710                                existing->second = decl;
     711                        }
     712                }
     713        }
     714       
     715        void Indexer::addTrait( TraitDecl *decl ) {
     716                makeWritable();
     717
     718                const std::string &id = decl->get_name();
     719                TraitTable::iterator existing = tables->traitTable.find( id );
     720                if ( existing == tables->traitTable.end() ) {
     721                        TraitDecl *parent = tables->base.lookupTraitAtScope( id, scope );
     722                        if ( ! parent || ! addedDeclConflicts( parent, decl ) ) {
     723                                tables->traitTable.insert( existing, std::make_pair( id, decl ) );
     724                                ++tables->size;
     725                        }
     726                } else {
     727                        if ( ! addedDeclConflicts( existing->second, decl ) ) {
     728                                existing->second = decl;
     729                        }
     730                }
    354731        }
    355732
    356733        void Indexer::enterScope() {
     734                ++scope;
     735               
    357736                if ( doDebug ) {
    358                         std::cout << "--- Entering scope" << std::endl;
    359                 }
    360                 idTable.enterScope();
    361                 typeTable.enterScope();
    362                 structTable.enterScope();
    363                 enumTable.enterScope();
    364                 unionTable.enterScope();
    365                 contextTable.enterScope();
     737                        std::cout << "--- Entering scope " << scope << std::endl;
     738                }
    366739        }
    367740
    368741        void Indexer::leaveScope() {
    369742                using std::cout;
    370                 using std::endl;
    371  
    372                 if ( doDebug ) {
    373                         cout << "--- Leaving scope containing" << endl;
    374                         idTable.dump( cout );
    375                         typeTable.dump( cout );
    376                         structTable.dump( cout );
    377                         enumTable.dump( cout );
    378                         unionTable.dump( cout );
    379                         contextTable.dump( cout );
    380                 }
    381                 idTable.leaveScope();
    382                 typeTable.leaveScope();
    383                 structTable.leaveScope();
    384                 enumTable.leaveScope();
    385                 unionTable.leaveScope();
    386                 contextTable.leaveScope();
     743
     744                assert( scope > 0 && "cannot leave initial scope" );
     745                --scope;
     746
     747                while ( tables && tables->scope > scope ) {
     748                        if ( doDebug ) {
     749                                cout << "--- Leaving scope " << tables->scope << " containing" << std::endl;
     750                                dump( tables->idTable, cout );
     751                                dump( tables->typeTable, cout );
     752                                dump( tables->structTable, cout );
     753                                dump( tables->enumTable, cout );
     754                                dump( tables->unionTable, cout );
     755                                dump( tables->traitTable, cout );
     756                        }
     757
     758                        // swap tables for base table until we find one at an appropriate scope
     759                        Indexer::Impl *base = newRef( tables->base.tables );
     760                        deleteRef( tables );
     761                        tables = base;
     762                }
    387763        }
    388764
    389765        void Indexer::print( std::ostream &os, int indent ) const {
    390766            using std::cerr;
    391             using std::endl;
    392 
    393             cerr << "===idTable===" << endl;
    394             idTable.dump( os );
    395             cerr << "===typeTable===" << endl;
    396             typeTable.dump( os );
    397             cerr << "===structTable===" << endl;
    398             structTable.dump( os );
    399             cerr << "===enumTable===" << endl;
    400             enumTable.dump( os );
    401             cerr << "===unionTable===" << endl;
    402             unionTable.dump( os );
    403             cerr << "===contextTable===" << endl;
    404             contextTable.dump( os );
    405 #if 0
    406                 idTable.dump( os );
    407                 typeTable.dump( os );
    408                 structTable.dump( os );
    409                 enumTable.dump( os );
    410                 unionTable.dump( os );
    411                 contextTable.dump( os );
    412 #endif
     767
     768            cerr << "===idTable===" << std::endl;
     769            if ( tables ) dump( tables->idTable, os );
     770            cerr << "===typeTable===" << std::endl;
     771            if ( tables ) dump( tables->typeTable, os );
     772            cerr << "===structTable===" << std::endl;
     773            if ( tables ) dump( tables->structTable, os );
     774            cerr << "===enumTable===" << std::endl;
     775            if ( tables ) dump( tables->enumTable, os );
     776            cerr << "===unionTable===" << std::endl;
     777            if ( tables ) dump( tables->unionTable, os );
     778            cerr << "===contextTable===" << std::endl;
     779            if ( tables ) dump( tables->traitTable, os );
    413780        }
    414781} // namespace SymTab
  • src/SymTab/Indexer.h

    rb63e376 rae357ec  
    2121
    2222#include "SynTree/Visitor.h"
    23 #include "IdTable.h"
    24 #include "AggregateTable.h"
    25 #include "TypeTable.h"
    2623
    2724namespace SymTab {
     
    2926          public:
    3027                Indexer( bool useDebug = false );
     28
     29                Indexer( const Indexer &that );
     30                Indexer( Indexer &&that );
    3131                virtual ~Indexer();
     32                Indexer& operator= ( const Indexer &that );
     33                Indexer& operator= ( Indexer &&that );
    3234
    3335                //using Visitor::visit;
     
    7880                void leaveScope();
    7981
    80                 void lookupId( const std::string &id, std::list< DeclarationWithType* >& ) const;
    81                 DeclarationWithType* lookupId( const std::string &id) const;
     82                /// Gets all declarations with the given ID
     83                void lookupId( const std::string &id, std::list< DeclarationWithType* > &out ) const;
     84                /// Gets the top-most type declaration with the given ID
    8285                NamedTypeDecl *lookupType( const std::string &id ) const;
     86                /// Gets the top-most struct declaration with the given ID
    8387                StructDecl *lookupStruct( const std::string &id ) const;
     88                /// Gets the top-most enum declaration with the given ID
    8489                EnumDecl *lookupEnum( const std::string &id ) const;
     90                /// Gets the top-most union declaration with the given ID
    8591                UnionDecl *lookupUnion( const std::string &id ) const;
     92                /// Gets the top-most trait declaration with the given ID
    8693                TraitDecl *lookupTrait( const std::string &id ) const;
    8794 
    8895                void print( std::ostream &os, int indent = 0 ) const;
    8996          private:
    90                 IdTable idTable;
    91                 TypeTable typeTable;
    92                 StructTable structTable;
    93                 EnumTable enumTable;
    94                 UnionTable unionTable;
    95                 TraitTable contextTable;
    96  
    97                 bool doDebug;                                   // display debugging trace
     97                /// looks up a specific mangled ID at the given scope
     98                DeclarationWithType *lookupIdAtScope( const std::string &id, const std::string &mangleName, unsigned long scope ) const;
     99                /// returns true if there exists a declaration with C linkage and the given name
     100                bool hasCDeclWithName( const std::string &id ) const;
     101                // equivalents to lookup functions that only look at tables at scope `scope` (which should be >= tables->scope)
     102                NamedTypeDecl *lookupTypeAtScope( const std::string &id, unsigned long scope ) const;
     103                StructDecl *lookupStructAtScope( const std::string &id, unsigned long scope ) const;
     104                EnumDecl *lookupEnumAtScope( const std::string &id, unsigned long scope ) const;
     105                UnionDecl *lookupUnionAtScope( const std::string &id, unsigned long scope ) const;
     106                TraitDecl *lookupTraitAtScope( const std::string &id, unsigned long scope ) const;
     107               
     108                void addId( DeclarationWithType *decl );
     109                void addType( NamedTypeDecl *decl );
     110                void addStruct( const std::string &id );
     111                void addStruct( StructDecl *decl );
     112                void addEnum( EnumDecl *decl );
     113                void addUnion( const std::string &id );
     114                void addUnion( UnionDecl *decl );
     115                void addTrait( TraitDecl *decl );
     116               
     117                struct Impl;
     118                Impl *tables;         ///< Copy-on-write instance of table data structure
     119                unsigned long scope;  ///< Scope index of this pointer
     120                bool doDebug;         ///< Display debugging trace?
     121
     122                /// Takes a new ref to a table (returns null if null)
     123                static Impl *newRef( Impl *toClone );
     124                /// Clears a ref to a table (does nothing if null)
     125                static void deleteRef( Impl *toFree );
     126
     127                /// Ensures that tables variable is writable (i.e. allocated, uniquely owned by this Indexer, and at the current scope)
     128                void makeWritable();
    98129        };
    99130} // namespace SymTab
  • src/SymTab/module.mk

    rb63e376 rae357ec  
    1515###############################################################################
    1616
    17 SRC += SymTab/IdTable.cc \
    18        SymTab/Indexer.cc \
     17SRC += SymTab/Indexer.cc \
    1918       SymTab/Mangler.cc \
    2019       SymTab/Validate.cc \
  • src/SynTree/Constant.cc

    rb63e376 rae357ec  
    1616#include <iostream>
    1717#include <list>
     18#include <string>
    1819
    1920#include "Constant.h"
     
    2829
    2930Constant::~Constant() { delete type; }
     31
     32Constant Constant::from( int i ) {
     33        return Constant( new BasicType( Type::Qualifiers(), BasicType::SignedInt ), std::to_string( i ) );
     34}
     35
     36Constant Constant::from( unsigned long i ) {
     37        return Constant( new BasicType( Type::Qualifiers(), BasicType::LongUnsignedInt ), std::to_string( i ) );
     38}
     39
     40Constant Constant::from( double d ) {
     41        return Constant( new BasicType( Type::Qualifiers(), BasicType::Double ), std::to_string( d ) );
     42}
    3043
    3144Constant *Constant::clone() const { assert( false ); return 0; }
  • src/SynTree/Constant.h

    rb63e376 rae357ec  
    3232        void set_value( std::string newValue ) { value = newValue; }
    3333
     34        /// generates an integer constant of the given int
     35        static Constant from( int i );
     36        /// generates an integer constant of the given unsigned long int
     37        static Constant from( unsigned long i );
     38        /// generates a floating point constant of the given double
     39        static Constant from( double d );
     40
    3441        virtual Constant *clone() const;
    3542        virtual void accept( Visitor &v ) { v.visit( this ); }
Note: See TracChangeset for help on using the changeset viewer.