Changeset f33eab7


Ignore:
Timestamp:
Nov 10, 2020, 2:45:16 PM (11 months ago)
Author:
m3zulfiq <m3zulfiq@…>
Branches:
arm-eh, jacob/cs343-translation, master, new-ast-unique-expr
Children:
1d379b5
Parents:
685810e (diff), b82d140 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

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

Files:
22 edited

Legend:

Unmodified
Added
Removed
  • libcfa/src/concurrency/kernel/fwd.hfa

    r685810e rf33eab7  
    6565
    6666                extern uintptr_t __cfatls_get( unsigned long int member );
    67                 // #define publicTLS_get( member ) ((typeof(__cfaabi_tls.member))__cfatls_get( __builtin_offsetof(KernelThreadData, member) ))
    68                 #define publicTLS_get( member ) (__cfaabi_tls.member)
    69                 // extern forall(otype T) T __cfatls_get( T * member, T value );
    70                 // #define publicTLS_set( member, value ) __cfatls_set( (typeof(member)*)__builtin_offsetof(KernelThreadData, member), value );
     67                #define publicTLS_get( member ) ((typeof(__cfaabi_tls.member))__cfatls_get( __builtin_offsetof(KernelThreadData, member) ))
    7168
    7269                static inline uint64_t __tls_rand() {
  • libcfa/src/concurrency/preemption.cfa

    r685810e rf33eab7  
    231231}
    232232
     233struct asm_region {
     234        void * before;
     235        void * after;
     236};
     237
     238static inline bool __cfaasm_in( void * ip, struct asm_region & region ) {
     239        return ip >= region.before && ip <= region.after;
     240}
     241
     242
    233243//----------
    234244// Get data from the TLS block
     245// struct asm_region __cfaasm_get;
    235246uintptr_t __cfatls_get( unsigned long int offset ) __attribute__((__noinline__)); //no inline to avoid problems
    236247uintptr_t __cfatls_get( unsigned long int offset ) {
     248        // __cfaasm_get.before = ({ void * value; asm("movq $__cfaasm_get_before, %[v]\n\t" : [v]"=r"(value) ); value; });
     249        // __cfaasm_get.after  = ({ void * value; asm("movq $__cfaasm_get_after , %[v]\n\t" : [v]"=r"(value) ); value; });
    237250        // create a assembler label before
    238251        // marked as clobber all to avoid movement
     
    253266                // create a assembler label before
    254267                // marked as clobber all to avoid movement
    255                 asm volatile("__cfaasm_disable_before:":::"memory");
     268                asm volatile("__cfaasm_dsable_before:":::"memory");
    256269
    257270                with( __cfaabi_tls.preemption_state ) {
     
    275288                // create a assembler label after
    276289                // marked as clobber all to avoid movement
    277                 asm volatile("__cfaasm_disable_after:":::"memory");
     290                asm volatile("__cfaasm_dsable_after:":::"memory");
    278291        }
    279292
     
    283296                // create a assembler label before
    284297                // marked as clobber all to avoid movement
    285                 asm volatile("__cfaasm_enable_before:":::"memory");
     298                asm volatile("__cfaasm_enble_before:":::"memory");
    286299
    287300                processor   * proc = __cfaabi_tls.this_processor; // Cache the processor now since interrupts can start happening after the atomic store
     
    318331                // create a assembler label after
    319332                // marked as clobber all to avoid movement
    320                 asm volatile("__cfaasm_enable_after:":::"memory");
     333                asm volatile("__cfaasm_enble_after:":::"memory");
    321334        }
    322335
     
    386399}
    387400
     401//-----------------------------------------------------------------------------
     402// Some assembly required
     403#if defined( __i386 )
     404        #ifdef __PIC__
     405                #define RELOC_PRELUDE( label ) \
     406                        "calll   .Lcfaasm_prelude_" #label "$pb\n\t" \
     407                        ".Lcfaasm_prelude_" #label "$pb:\n\t" \
     408                        "popl    %%eax\n\t" \
     409                        ".Lcfaasm_prelude_" #label "_end:\n\t" \
     410                        "addl    $_GLOBAL_OFFSET_TABLE_+(.Lcfaasm_prelude_" #label "_end-.Lcfaasm_prelude_" #label "$pb), %%eax\n\t"
     411                #define RELOC_PREFIX ""
     412                #define RELOC_SUFFIX "@GOT(%%eax)"
     413        #else
     414                #define RELOC_PREFIX "$"
     415                #define RELOC_SUFFIX ""
     416        #endif
     417        #define __cfaasm_label( label ) static struct asm_region label = \
     418                ({ \
     419                        struct asm_region region; \
     420                        asm( \
     421                                RELOC_PRELUDE( label ) \
     422                                "movl " RELOC_PREFIX "__cfaasm_" #label "_before" RELOC_SUFFIX ", %[vb]\n\t" \
     423                                "movl " RELOC_PREFIX "__cfaasm_" #label "_after"  RELOC_SUFFIX ", %[va]\n\t" \
     424                                 : [vb]"=r"(region.before), [va]"=r"(region.after) \
     425                        ); \
     426                        region; \
     427                });
     428#elif defined( __x86_64 )
     429        #ifdef __PIC__
     430                #define RELOC_PREFIX ""
     431                #define RELOC_SUFFIX "@GOTPCREL(%%rip)"
     432        #else
     433                #define RELOC_PREFIX "$"
     434                #define RELOC_SUFFIX ""
     435        #endif
     436        #define __cfaasm_label( label ) static struct asm_region label = \
     437                ({ \
     438                        struct asm_region region; \
     439                        asm( \
     440                                "movq " RELOC_PREFIX "__cfaasm_" #label "_before" RELOC_SUFFIX ", %[vb]\n\t" \
     441                                "movq " RELOC_PREFIX "__cfaasm_" #label "_after"  RELOC_SUFFIX ", %[va]\n\t" \
     442                                 : [vb]"=r"(region.before), [va]"=r"(region.after) \
     443                        ); \
     444                        region; \
     445                });
     446#elif defined( __aarch64__ )
     447        #ifdef __PIC__
     448                #define RELOC_TAG "@PLT"
     449        #else
     450                #define RELOC_TAG ""
     451        #endif
     452        #define __cfaasm_label( label ) \
     453                ({ \
     454                        struct asm_region region; \
     455                        asm( \
     456                                "mov %[vb], __cfaasm_" #label "_before@GOTPCREL(%%rip)"  "\n\t" \
     457                                "mov %[va], __cfaasm_" #label "_after@GOTPCREL(%%rip)"   "\n\t" \
     458                                 : [vb]"=r"(region.before), [va]"=r"(region.after) \
     459                        ); \
     460                        region; \
     461                });
     462#else
     463        #error unknown hardware architecture
     464#endif
     465
    388466// KERNEL ONLY
    389467// Check if a __cfactx_switch signal handler shoud defer
    390468// If true  : preemption is safe
    391469// If false : preemption is unsafe and marked as pending
    392 static inline bool preemption_ready() {
     470static inline bool preemption_ready( void * ip ) {
     471        // Get all the region for which it is not safe to preempt
     472        __cfaasm_label( get    );
     473        __cfaasm_label( check  );
     474        __cfaasm_label( dsable );
     475        __cfaasm_label( enble );
     476        __cfaasm_label( nopoll );
     477
    393478        // Check if preemption is safe
    394         bool ready = __cfaabi_tls.preemption_state.enabled && ! __cfaabi_tls.preemption_state.in_progress;
    395 
     479        bool ready = true;
     480        if( __cfaasm_in( ip, get    ) ) { ready = false; goto EXIT; };
     481        if( __cfaasm_in( ip, check  ) ) { ready = false; goto EXIT; };
     482        if( __cfaasm_in( ip, dsable ) ) { ready = false; goto EXIT; };
     483        if( __cfaasm_in( ip, enble  ) ) { ready = false; goto EXIT; };
     484        if( __cfaasm_in( ip, nopoll ) ) { ready = false; goto EXIT; };
     485        if( !__cfaabi_tls.preemption_state.enabled) { ready = false; goto EXIT; };
     486        if( __cfaabi_tls.preemption_state.in_progress ) { ready = false; goto EXIT; };
     487
     488EXIT:
    396489        // Adjust the pending flag accordingly
    397490        __cfaabi_tls.this_processor->pending_preemption = !ready;
     
    468561// Kernel Signal Handlers
    469562//=============================================================================================
    470 struct asm_region {
    471         void * before;
    472         void * after;
    473 };
    474 
    475 //-----------------------------------------------------------------------------
    476 // Some assembly required
    477 #if defined( __i386 )
    478         #define __cfaasm_label( label ) \
    479                 ({ \
    480                         struct asm_region region; \
    481                         asm( \
    482                                 "movl $__cfaasm_" #label "_before, %[vb]\n\t" \
    483                                 "movl $__cfaasm_" #label "_after , %[va]\n\t" \
    484                                  : [vb]"=r"(region.before), [vb]"=r"(region.before) \
    485                         ); \
    486                         region; \
    487                 });
    488 #elif defined( __x86_64 )
    489         #ifdef __PIC__
    490                 #define PLT "@PLT"
    491         #else
    492                 #define PLT ""
    493         #endif
    494         #define __cfaasm_label( label ) \
    495                 ({ \
    496                         struct asm_region region; \
    497                         asm( \
    498                                 "movq $__cfaasm_" #label "_before" PLT ", %[vb]\n\t" \
    499                                 "movq $__cfaasm_" #label "_after"  PLT ", %[va]\n\t" \
    500                                  : [vb]"=r"(region.before), [va]"=r"(region.after) \
    501                         ); \
    502                         region; \
    503                 });
    504 #elif defined( __aarch64__ )
    505         #error __cfaasm_label undefined for arm
    506 #else
    507         #error unknown hardware architecture
    508 #endif
    509 
    510563__cfaabi_dbg_debug_do( static thread_local void * last_interrupt = 0; )
    511564
     
    530583
    531584        // Check if it is safe to preempt here
    532         if( !preemption_ready() ) { return; }
    533 
    534         struct asm_region region;
    535         region = __cfaasm_label( get     ); if( ip >= region.before && ip <= region.after ) return;
    536         region = __cfaasm_label( check   ); if( ip >= region.before && ip <= region.after ) return;
    537         region = __cfaasm_label( disable ); if( ip >= region.before && ip <= region.after ) return;
    538         region = __cfaasm_label( enable  ); if( ip >= region.before && ip <= region.after ) return;
    539         region = __cfaasm_label( nopoll  ); if( ip >= region.before && ip <= region.after ) return;
     585        if( !preemption_ready( ip ) ) { return; }
    540586
    541587        __cfaabi_dbg_print_buffer_decl( " KERNEL: preempting core %p (%p @ %p).\n", __cfaabi_tls.this_processor, __cfaabi_tls.this_thread, (void *)(cxt->uc_mcontext.CFA_REG_IP) );
  • src/AST/Convert.cpp

    r685810e rf33eab7  
    27642764                        old->location,
    27652765                        GET_ACCEPT_1(value, Expr),
    2766                         (old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::DoConstruct
     2766                        (old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::NoConstruct
    27672767                );
    27682768        }
     
    27732773                        GET_ACCEPT_V(initializers, Init),
    27742774                        GET_ACCEPT_V(designations, Designation),
    2775                         (old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::DoConstruct
     2775                        (old->get_maybeConstructed()) ? ast::MaybeConstruct : ast::NoConstruct
    27762776                );
    27772777        }
  • src/AST/Decl.hpp

    r685810e rf33eab7  
    7979        ptr<Expr> asmName;
    8080        bool isDeleted = false;
     81        bool isTypeFixed = false;
    8182
    8283        DeclWithType( const CodeLocation& loc, const std::string& name, Storage::Classes storage,
  • src/AST/Init.hpp

    r685810e rf33eab7  
    5050
    5151/// Flag for whether to construct from initialzier
    52 enum ConstructFlag { DoConstruct, MaybeConstruct };
     52enum ConstructFlag { NoConstruct, MaybeConstruct };
    5353
    5454/// Object initializer base class
     
    7171        ptr<Expr> value;
    7272
    73         SingleInit( const CodeLocation & loc, const Expr * val, ConstructFlag mc = DoConstruct )
     73        SingleInit( const CodeLocation & loc, const Expr * val, ConstructFlag mc = NoConstruct )
    7474        : Init( loc, mc ), value( val ) {}
    7575
     
    9090
    9191        ListInit( const CodeLocation & loc, std::vector<ptr<Init>> && is,
    92                 std::vector<ptr<Designation>> && ds = {}, ConstructFlag mc = DoConstruct );
     92                std::vector<ptr<Designation>> && ds = {}, ConstructFlag mc = NoConstruct );
    9393
    9494        using iterator = std::vector<ptr<Init>>::iterator;
     
    118118        ConstructorInit(
    119119                const CodeLocation & loc, const Stmt * ctor, const Stmt * dtor, const Init * init )
    120         : Init( loc, DoConstruct ), ctor( ctor ), dtor( dtor ), init( init ) {}
     120        : Init( loc, MaybeConstruct ), ctor( ctor ), dtor( dtor ), init( init ) {}
    121121
    122122        const Init * accept( Visitor & v ) const override { return v.visit( this ); }
  • src/AST/Pass.impl.hpp

    r685810e rf33eab7  
    423423                }
    424424                catch( SemanticErrorException &e ) {
    425                         errors.append( e );
     425                        if (__pass::onError (visitor.core, *i, 0))
     426                                errors.append( e );
    426427                }
    427428
     
    683684                // Do not enter (or leave) a new scope if atFunctionTop. Remember to save the result.
    684685                auto guard1 = makeFuncGuard( [this, enterScope = !this->atFunctionTop]() {
    685                         if ( enterScope ) __pass::symtab::enter(core, 0);
     686                        if ( enterScope ) {
     687                                __pass::symtab::enter(core, 0);
     688                                __pass::scope::enter(core, 0);
     689                        }
    686690                }, [this, leaveScope = !this->atFunctionTop]() {
    687                         if ( leaveScope ) __pass::symtab::leave(core, 0);
     691                        if ( leaveScope ) {
     692                                __pass::symtab::leave(core, 0);
     693                                __pass::scope::leave(core, 0);
     694                        }
    688695                });
    689696                ValueGuard< bool > guard2( atFunctionTop );
  • src/AST/Pass.proto.hpp

    r685810e rf33eab7  
    266266        static void endTrace(core_t &, long) {}
    267267
     268        // Allows visitor to handle an error on top-level declarations, and possibly suppress the error.
     269        // If onError() returns false, the error will be ignored. By default, it returns true.
     270
     271        template< typename core_t >
     272        static bool onError (core_t &, ptr<Decl> &, long) { return true; }
     273
     274        template< typename core_t >
     275        static auto onError (core_t & core, ptr<Decl> & decl, int) -> decltype(core.onError(decl)) {
     276                return core.onError(decl);
     277        }
     278
    268279        // Another feature of the templated visitor is that it calls beginScope()/endScope() for compound statement.
    269280        // All passes which have such functions are assumed desire this behaviour
  • src/AST/Type.cpp

    r685810e rf33eab7  
    211211        for ( const Type * ty : types ) {
    212212                members.emplace_back( new ObjectDecl{
    213                         CodeLocation{}, "", ty, new ListInit( CodeLocation{}, {}, {}, MaybeConstruct ),
     213                        CodeLocation{}, "", ty, new ListInit( CodeLocation{}, {}, {}, NoConstruct ),
    214214                        Storage::Classes{}, Linkage::Cforall } );
    215215        }
  • src/CodeGen/CodeGenerator.cc

    r685810e rf33eab7  
    120120                // GCC builtins should always be printed unmangled
    121121                if ( options.pretty || decl->linkage.is_gcc_builtin ) return decl->name;
    122                 if ( decl->mangleName != "" ) {
     122                if ( LinkageSpec::isMangled(decl->linkage) && decl->mangleName != "" ) {
    123123                        // need to incorporate scope level in order to differentiate names for destructors
    124124                        return decl->get_scopedMangleName();
  • src/CodeGen/FixMain.cc

    r685810e rf33eab7  
    2626#include "SynTree/Declaration.h"   // for FunctionDecl, operator<<
    2727#include "SynTree/Type.h"          // for FunctionType
     28#include "SymTab/Mangler.h"
    2829
    2930namespace CodeGen {
     
    4748                if( main_signature ) {
    4849                        os << "static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return ";
     50                        main_signature->mangleName = SymTab::Mangler::mangle(main_signature.get());
    4951
    5052                        os << main_signature->get_scopedMangleName() << "(";
  • src/CodeGen/FixNames.cc

    r685810e rf33eab7  
    3131#include "SynTree/Type.h"          // for Type, BasicType, Type::Qualifiers
    3232#include "SynTree/Visitor.h"       // for Visitor, acceptAll
     33#include "CompilationState.h"
    3334
    3435namespace CodeGen {
     
    102103                if ( dwt->get_name() != "" ) {
    103104                        if ( LinkageSpec::isMangled( dwt->get_linkage() ) ) {
    104                                 dwt->set_mangleName( SymTab::Mangler::mangle( dwt ) );
     105                                if (!useNewAST) {
     106                                        dwt->set_mangleName( SymTab::Mangler::mangle( dwt ) );
     107                                }
    105108                                dwt->set_scopeLevel( scopeLevel );
    106109                        } // if
  • src/InitTweak/GenInit.cc

    r685810e rf33eab7  
    2626#include "AST/Node.hpp"
    2727#include "AST/Stmt.hpp"
     28#include "CompilationState.h"
    2829#include "CodeGen/OperatorTable.h"
    2930#include "Common/PassVisitor.h"        // for PassVisitor, WithGuards, WithShort...
     
    122123
    123124        void genInit( std::list< Declaration * > & translationUnit ) {
     125                HoistArrayDimension::hoistArrayDimension( translationUnit );
    124126                fixReturnStatements( translationUnit );
    125                 HoistArrayDimension::hoistArrayDimension( translationUnit );
    126                 CtorDtor::generateCtorDtor( translationUnit );
     127
     128                if (!useNewAST) {
     129                        CtorDtor::generateCtorDtor( translationUnit );
     130                }
    127131        }
    128132
     
    192196
    193197                        // need to resolve array dimensions in order to accurately determine if constexpr
    194                         ResolvExpr::findSingleExpression( arrayType->dimension, Validate::SizeType->clone(), indexer );
    195                         // array is variable-length when the dimension is not constexpr
    196                         arrayType->isVarLen = ! isConstExpr( arrayType->dimension );
     198                        if (!useNewAST) {
     199                                ResolvExpr::findSingleExpression( arrayType->dimension, Validate::SizeType->clone(), indexer );
     200                                // array is variable-length when the dimension is not constexpr
     201                                arrayType->isVarLen = ! isConstExpr( arrayType->dimension );
     202                        }
    197203                        // don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects.
    198                         if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return;
     204                        // xxx - hoisting has no side effects anyways, so don't skip since we delay resolve     
     205                        // only skip in the most trivial case, which does not require resolve
     206                        if (dynamic_cast<ConstantExpr *>(arrayType->dimension)) return;
     207                        // if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return;
    199208
    200209                        ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, Validate::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
     
    245254        }
    246255
     256        // why is this not just on FunctionDecl?
    247257        void ManagedTypes::handleDWT( DeclarationWithType * dwt ) {
    248258                // if this function is a user-defined constructor or destructor, mark down the type as "managed"
     
    274284        void ManagedTypes::beginScope() { managedTypes.beginScope(); }
    275285        void ManagedTypes::endScope() { managedTypes.endScope(); }
     286
     287        bool ManagedTypes_new::isManaged( const ast::Type * type ) const {
     288                // references are never constructed
     289                if ( dynamic_cast< const ast::ReferenceType * >( type ) ) return false;
     290                if ( auto tupleType = dynamic_cast< const ast::TupleType * > ( type ) ) {
     291                        // tuple is also managed if any of its components are managed
     292                        for (auto & component : tupleType->types) {
     293                                if (isManaged(component)) return true;
     294                        }
     295                }
     296                // need to clear and reset qualifiers when determining if a type is managed
     297                // ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() );
     298                auto tmp = shallowCopy(type);
     299                tmp->qualifiers = {};
     300                // delete tmp at return
     301                ast::ptr<ast::Type> guard = tmp;
     302                // a type is managed if it appears in the map of known managed types, or if it contains any polymorphism (is a type variable or generic type containing a type variable)
     303                return managedTypes.find( Mangle::mangle( tmp, {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) ) != managedTypes.end() || GenPoly::isPolyType( tmp );
     304        }
     305
     306        bool ManagedTypes_new::isManaged( const ast::ObjectDecl * objDecl ) const {
     307                const ast::Type * type = objDecl->type;
     308                while ( auto at = dynamic_cast< const ast::ArrayType * >( type ) ) {
     309                        // must always construct VLAs with an initializer, since this is an error in C
     310                        if ( at->isVarLen && objDecl->init ) return true;
     311                        type = at->base;
     312                }
     313                return isManaged( type );
     314        }
     315
     316        void ManagedTypes_new::handleDWT( const ast::DeclWithType * dwt ) {
     317                // if this function is a user-defined constructor or destructor, mark down the type as "managed"
     318                if ( ! dwt->linkage.is_overrideable && CodeGen::isCtorDtor( dwt->name ) ) {
     319                        auto & params = GenPoly::getFunctionType( dwt->get_type())->params;
     320                        assert( ! params.empty() );
     321                        // Type * type = InitTweak::getPointerBase( params.front() );
     322                        // assert( type );
     323                        managedTypes.insert( Mangle::mangle( params.front(), {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) );
     324                }
     325        }
     326
     327        void ManagedTypes_new::handleStruct( const ast::StructDecl * aggregateDecl ) {
     328                // don't construct members, but need to take note if there is a managed member,
     329                // because that means that this type is also managed
     330                for ( auto & member : aggregateDecl->members ) {
     331                        if ( auto field = member.as<ast::ObjectDecl>() ) {
     332                                if ( isManaged( field ) ) {
     333                                        // generic parameters should not play a role in determining whether a generic type is constructed - construct all generic types, so that
     334                                        // polymorphic constructors make generic types managed types
     335                                        ast::StructInstType inst( aggregateDecl );
     336                                        managedTypes.insert( Mangle::mangle( &inst, {Mangle::NoOverrideable | Mangle::NoGenericParams | Mangle::Type} ) );
     337                                        break;
     338                                }
     339                        }
     340                }
     341        }
     342
     343        void ManagedTypes_new::beginScope() { managedTypes.beginScope(); }
     344        void ManagedTypes_new::endScope() { managedTypes.endScope(); }
    276345
    277346        ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg ) {
     
    370439        // constructable object
    371440        InitExpander_new srcParam{ objDecl->init }, nullParam{ (const ast::Init *)nullptr };
     441        ast::ptr< ast::Expr > dstParam = new ast::VariableExpr(loc, objDecl);
    372442       
    373443        ast::ptr< ast::Stmt > ctor = SymTab::genImplicitCall(
    374                 srcParam, new ast::VariableExpr{ loc, objDecl }, loc, "?{}", objDecl );
     444                srcParam, dstParam, loc, "?{}", objDecl );
    375445        ast::ptr< ast::Stmt > dtor = SymTab::genImplicitCall(
    376                 nullParam, new ast::VariableExpr{ loc, objDecl }, loc, "^?{}", objDecl,
     446                nullParam, dstParam, loc, "^?{}", objDecl,
    377447                SymTab::LoopBackward );
    378448       
  • src/InitTweak/GenInit.h

    r685810e rf33eab7  
    5252                GenPoly::ScopedSet< std::string > managedTypes;
    5353        };
     54
     55        class ManagedTypes_new {
     56        public:
     57                bool isManaged( const ast::ObjectDecl * objDecl ) const ; // determine if object is managed
     58                bool isManaged( const ast::Type * type ) const; // determine if type is managed
     59
     60                void handleDWT( const ast::DeclWithType * dwt ); // add type to managed if ctor/dtor
     61                void handleStruct( const ast::StructDecl * aggregateDecl ); // add type to managed if child is managed
     62
     63                void beginScope();
     64                void endScope();
     65        private:
     66                GenPoly::ScopedSet< std::string > managedTypes;
     67        };
    5468} // namespace
    5569
  • src/InitTweak/InitTweak.cc

    r685810e rf33eab7  
    8787                };
    8888
     89                struct HasDesignations_new : public ast::WithShortCircuiting {
     90                        bool result = false;
     91
     92                        void previsit( const ast::Node * ) {
     93                                // short circuit if we already know there are designations
     94                                if ( result ) visit_children = false;
     95                        }
     96
     97                        void previsit( const ast::Designation * des ) {
     98                                // short circuit if we already know there are designations
     99                                if ( result ) visit_children = false;
     100                                else if ( ! des->designators.empty() ) {
     101                                        result = true;
     102                                        visit_children = false;
     103                                }
     104                        }
     105                };
     106
     107                struct InitDepthChecker_new : public ast::WithGuards {
     108                        bool result = true;
     109                        const ast::Type * type;
     110                        int curDepth = 0, maxDepth = 0;
     111                        InitDepthChecker_new( const ast::Type * type ) : type( type ) {
     112                                const ast::Type * t = type;
     113                                while ( auto at = dynamic_cast< const ast::ArrayType * >( t ) ) {
     114                                        maxDepth++;
     115                                        t = at->base;
     116                                }
     117                                maxDepth++;
     118                        }
     119                        void previsit( ListInit * ) {
     120                                curDepth++;
     121                                GuardAction( [this]() { curDepth--; } );
     122                                if ( curDepth > maxDepth ) result = false;
     123                        }
     124                };
     125
    89126                struct InitFlattener_old : public WithShortCircuiting {
    90127                        void previsit( SingleInit * singleInit ) {
     
    122159                maybeAccept( objDecl->init, checker );
    123160                return checker.pass.depthOkay;
     161        }
     162
     163        bool isDesignated( const ast::Init * init ) {
     164                ast::Pass<HasDesignations_new> finder;
     165                maybe_accept( init, finder );
     166                return finder.core.result;
     167        }
     168
     169        bool checkInitDepth( const ast::ObjectDecl * objDecl ) {
     170                ast::Pass<InitDepthChecker_new> checker( objDecl->type );
     171                maybe_accept( objDecl->init.get(), checker );
     172                return checker.core.result;
    124173        }
    125174
     
    358407                        if ( auto listInit = dynamic_cast< const ast::ListInit * >( init ) ) {
    359408                                for ( const ast::Init * init : *listInit ) {
    360                                         buildCallExpr( callExpr, index, dimension, init, out );
     409                                        buildCallExpr( shallowCopy(callExpr), index, dimension, init, out );
    361410                                }
    362411                        } else {
    363                                 buildCallExpr( callExpr, index, dimension, init, out );
     412                                buildCallExpr( shallowCopy(callExpr), index, dimension, init, out );
    364413                        }
    365414                } else {
     
    10271076        };
    10281077
     1078        struct ConstExprChecker_new : public ast::WithShortCircuiting {
     1079                // most expressions are not const expr
     1080                void previsit( const ast::Expr * ) { result = false; visit_children = false; }
     1081
     1082                void previsit( const ast::AddressExpr *addressExpr ) {
     1083                        visit_children = false;
     1084                        const ast::Expr * arg = addressExpr->arg;
     1085
     1086                        // address of a variable or member expression is constexpr
     1087                        if ( ! dynamic_cast< const ast::NameExpr * >( arg )
     1088                        && ! dynamic_cast< const ast::VariableExpr * >( arg )
     1089                        && ! dynamic_cast< const ast::MemberExpr * >( arg )
     1090                        && ! dynamic_cast< const ast::UntypedMemberExpr * >( arg ) ) result = false;
     1091                }
     1092
     1093                // these expressions may be const expr, depending on their children
     1094                void previsit( const ast::SizeofExpr * ) {}
     1095                void previsit( const ast::AlignofExpr * ) {}
     1096                void previsit( const ast::UntypedOffsetofExpr * ) {}
     1097                void previsit( const ast::OffsetofExpr * ) {}
     1098                void previsit( const ast::OffsetPackExpr * ) {}
     1099                void previsit( const ast::CommaExpr * ) {}
     1100                void previsit( const ast::LogicalExpr * ) {}
     1101                void previsit( const ast::ConditionalExpr * ) {}
     1102                void previsit( const ast::CastExpr * ) {}
     1103                void previsit( const ast::ConstantExpr * ) {}
     1104
     1105                void previsit( const ast::VariableExpr * varExpr ) {
     1106                        visit_children = false;
     1107
     1108                        if ( auto inst = varExpr->result.as<ast::EnumInstType>() ) {
     1109                                long long int value;
     1110                                if ( inst->base->valueOf( varExpr->var, value ) ) {
     1111                                        // enumerators are const expr
     1112                                        return;
     1113                                }
     1114                        }
     1115                        result = false;
     1116                }
     1117
     1118                bool result = true;
     1119        };
     1120
    10291121        bool isConstExpr( Expression * expr ) {
    10301122                if ( expr ) {
     
    10461138        }
    10471139
     1140        bool isConstExpr( const ast::Expr * expr ) {
     1141                if ( expr ) {
     1142                        ast::Pass<ConstExprChecker_new> checker;
     1143                        expr->accept( checker );
     1144                        return checker.core.result;
     1145                }
     1146                return true;
     1147        }
     1148
     1149        bool isConstExpr( const ast::Init * init ) {
     1150                if ( init ) {
     1151                        ast::Pass<ConstExprChecker_new> checker;
     1152                        init->accept( checker );
     1153                        return checker.core.result;
     1154                } // if
     1155                // for all intents and purposes, no initializer means const expr
     1156                return true;
     1157        }
     1158
    10481159        bool isConstructor( const std::string & str ) { return str == "?{}"; }
    10491160        bool isDestructor( const std::string & str ) { return str == "^?{}"; }
  • src/InitTweak/InitTweak.h

    r685810e rf33eab7  
    5959        /// True if the Initializer contains designations
    6060        bool isDesignated( Initializer * init );
     61        bool isDesignated( const ast::Init * init );
    6162
    6263        /// True if the ObjectDecl's Initializer nesting level is not deeper than the depth of its
    6364        /// type, where the depth of its type is the number of nested ArrayTypes + 1
    6465        bool checkInitDepth( ObjectDecl * objDecl );
     66        bool checkInitDepth( const ast::ObjectDecl * objDecl );
    6567
    6668        /// returns the declaration of the function called by the expr (must be ApplicationExpr or UntypedExpr)
     
    107109        bool isConstExpr( Expression * expr );
    108110        bool isConstExpr( Initializer * init );
     111
     112        bool isConstExpr( const ast::Expr * expr );
     113        bool isConstExpr( const ast::Init * init );
    109114
    110115        /// Modifies objDecl to have:
  • src/ResolvExpr/ResolveTypeof.cc

    r685810e rf33eab7  
    2929#include "SynTree/Mutator.h"     // for Mutator
    3030#include "SynTree/Type.h"        // for TypeofType, Type
     31#include "SymTab/Mangler.h"
     32#include "InitTweak/InitTweak.h" // for isConstExpr
    3133
    3234namespace SymTab {
     
    163165}
    164166
     167struct FixArrayDimension {
     168        // should not require a mutable symbol table - prevent pass template instantiation
     169        const ast::SymbolTable & _symtab;
     170        FixArrayDimension(const ast::SymbolTable & symtab): _symtab(symtab) {}
     171
     172        const ast::ArrayType * previsit (const ast::ArrayType * arrayType) {
     173                if (!arrayType->dimension) return arrayType;
     174                auto mutType = mutate(arrayType);
     175                ast::ptr<ast::Type> sizetype = ast::sizeType ? ast::sizeType : new ast::BasicType(ast::BasicType::LongUnsignedInt);
     176                mutType->dimension = findSingleExpression(arrayType->dimension, sizetype, _symtab);
     177
     178                if (InitTweak::isConstExpr(mutType->dimension)) {
     179                        mutType->isVarLen = ast::LengthFlag::FixedLen;
     180                }
     181                else {
     182                        mutType->isVarLen = ast::LengthFlag::VariableLen;
     183                }
     184                return mutType;
     185        }
     186};
     187
     188const ast::Type * fixArrayType( const ast::Type * type, const ast::SymbolTable & symtab) {
     189        ast::Pass<FixArrayDimension> visitor {symtab};
     190        return type->accept(visitor);
     191}
     192
     193const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ast::SymbolTable & symtab ) {
     194        if (!decl->isTypeFixed) {
     195                auto mutDecl = mutate(decl);
     196                auto resolvedType = resolveTypeof(decl->type, symtab);
     197                resolvedType = fixArrayType(resolvedType, symtab);
     198                mutDecl->type = resolvedType;
     199
     200                // check variable length if object is an array.
     201                // xxx - should this be part of fixObjectType?
     202
     203                /*
     204                if (auto arrayType = dynamic_cast<const ast::ArrayType *>(resolvedType)) {
     205                        auto dimExpr = findSingleExpression(arrayType->dimension, ast::sizeType, symtab);
     206                        if (auto varexpr = arrayType->dimension.as<ast::VariableExpr>()) {// hoisted previously
     207                                if (InitTweak::isConstExpr(varexpr->var.strict_as<ast::ObjectDecl>()->init)) {
     208                                        auto mutType = mutate(arrayType);
     209                                        mutType->isVarLen = ast::LengthFlag::VariableLen;
     210                                        mutDecl->type = mutType;
     211                                }
     212                        }
     213                }
     214                */
     215
     216
     217                if (!mutDecl->name.empty())
     218                        mutDecl->mangleName = Mangle::mangle(mutDecl); // do not mangle unnamed variables
     219               
     220                mutDecl->isTypeFixed = true;
     221                return mutDecl;
     222        }
     223        return decl;
     224}
     225
    165226} // namespace ResolvExpr
    166227
  • src/ResolvExpr/ResolveTypeof.h

    r685810e rf33eab7  
    2323        class Type;
    2424        class SymbolTable;
     25        class ObjectDecl;
    2526}
    2627
     
    2829        Type *resolveTypeof( Type*, const SymTab::Indexer &indexer );
    2930        const ast::Type * resolveTypeof( const ast::Type *, const ast::SymbolTable & );
     31        const ast::ObjectDecl * fixObjectType( const ast::ObjectDecl * decl , const ast::SymbolTable & symtab );
    3032} // namespace ResolvExpr
    3133
  • src/ResolvExpr/Resolver.cc

    r685810e rf33eab7  
    2626#include "RenameVars.h"                  // for RenameVars, global_renamer
    2727#include "Resolver.h"
     28#include "ResolveTypeof.h"
    2829#include "ResolvMode.h"                  // for ResolvMode
    2930#include "typeops.h"                     // for extractResultType
    3031#include "Unify.h"                       // for unify
     32#include "CompilationState.h"
    3133#include "AST/Chain.hpp"
    3234#include "AST/Decl.hpp"
     
    4547#include "SymTab/Autogen.h"              // for SizeType
    4648#include "SymTab/Indexer.h"              // for Indexer
     49#include "SymTab/Mangler.h"              // for Mangler
    4750#include "SynTree/Declaration.h"         // for ObjectDecl, TypeDecl, Declar...
    4851#include "SynTree/Expression.h"          // for Expression, CastExpr, InitExpr
     
    11791182        } // anonymous namespace
    11801183
    1181                 ast::ptr< ast::Expr > findSingleExpression(
    1182                         const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab
    1183                 ) {
    1184                         assert( untyped && type );
    1185                         ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };
    1186                         ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );
    1187                         removeExtraneousCast( newExpr, symtab );
    1188                         return newExpr;
    1189                 }
     1184        ast::ptr< ast::Expr > findSingleExpression(
     1185                const ast::Expr * untyped, const ast::Type * type, const ast::SymbolTable & symtab
     1186        ) {
     1187                assert( untyped && type );
     1188                ast::ptr< ast::Expr > castExpr = new ast::CastExpr{ untyped, type };
     1189                ast::ptr< ast::Expr > newExpr = findSingleExpression( castExpr, symtab );
     1190                removeExtraneousCast( newExpr, symtab );
     1191                return newExpr;
     1192        }
    11901193
    11911194        namespace {
     1195                bool structOrUnion( const Candidate & i ) {
     1196                        const ast::Type * t = i.expr->result->stripReferences();
     1197                        return dynamic_cast< const ast::StructInstType * >( t ) || dynamic_cast< const ast::UnionInstType * >( t );
     1198                }
    11921199                /// Predicate for "Candidate has integral type"
    11931200                bool hasIntegralType( const Candidate & i ) {
     
    12371244                ast::ptr< ast::Type > functionReturn = nullptr;
    12381245                ast::CurrentObject currentObject;
     1246                // for work previously in GenInit
     1247                static InitTweak::ManagedTypes_new managedTypes;
     1248
    12391249                bool inEnumDecl = false;
    12401250
     
    12441254                Resolver_new( const ast::SymbolTable & syms ) { symtab = syms; }
    12451255
    1246                 void previsit( const ast::FunctionDecl * );
     1256                const ast::FunctionDecl * previsit( const ast::FunctionDecl * );
    12471257                const ast::FunctionDecl * postvisit( const ast::FunctionDecl * );
    1248                 void previsit( const ast::ObjectDecl * );
     1258                const ast::ObjectDecl * previsit( const ast::ObjectDecl * );
     1259                void previsit( const ast::AggregateDecl * );
     1260                void previsit( const ast::StructDecl * );
    12491261                void previsit( const ast::EnumDecl * );
    12501262                const ast::StaticAssertDecl * previsit( const ast::StaticAssertDecl * );
     
    12671279                const ast::CatchStmt *       postvisit( const ast::CatchStmt * );
    12681280                const ast::WaitForStmt *     previsit( const ast::WaitForStmt * );
     1281                const ast::WithStmt *        previsit( const ast::WithStmt * );
    12691282
    12701283                const ast::SingleInit *      previsit( const ast::SingleInit * );
    12711284                const ast::ListInit *        previsit( const ast::ListInit * );
    12721285                const ast::ConstructorInit * previsit( const ast::ConstructorInit * );
     1286
     1287                void resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd);
     1288
     1289                void beginScope() { managedTypes.beginScope(); }
     1290                void endScope() { managedTypes.endScope(); }
     1291                bool onError(ast::ptr<ast::Decl> & decl);
    12731292        };
    12741293        // size_t Resolver_new::traceId = Stats::Heap::new_stacktrace_id("Resolver");
     1294
     1295        InitTweak::ManagedTypes_new Resolver_new::managedTypes;
    12751296
    12761297        void resolve( ast::TranslationUnit& translationUnit ) {
     
    12971318        }
    12981319
    1299         void Resolver_new::previsit( const ast::FunctionDecl * functionDecl ) {
     1320        namespace {
     1321                const ast::Attribute * handleAttribute(const CodeLocation & loc, const ast::Attribute * attr, const ast::SymbolTable & symtab) {
     1322                        std::string name = attr->normalizedName();
     1323                        if (name == "constructor" || name == "destructor") {
     1324                                if (attr->params.size() == 1) {
     1325                                        auto arg = attr->params.front();
     1326                                        auto resolved = ResolvExpr::findSingleExpression( arg, new ast::BasicType( ast::BasicType::LongLongSignedInt ), symtab );
     1327                                        auto result = eval(arg);
     1328
     1329                                        auto mutAttr = mutate(attr);
     1330                                        mutAttr->params.front() = resolved;
     1331                                        if (! result.second) {
     1332                                                SemanticWarning(loc, Warning::GccAttributes,
     1333                                                        toCString( name, " priorities must be integers from 0 to 65535 inclusive: ", arg ) );
     1334                                        }
     1335                                        else {
     1336                                                auto priority = result.first;
     1337                                                if (priority < 101) {
     1338                                                        SemanticWarning(loc, Warning::GccAttributes,
     1339                                                                toCString( name, " priorities from 0 to 100 are reserved for the implementation" ) );
     1340                                                } else if (priority < 201 && ! buildingLibrary()) {
     1341                                                        SemanticWarning(loc, Warning::GccAttributes,
     1342                                                                toCString( name, " priorities from 101 to 200 are reserved for the implementation" ) );
     1343                                                }
     1344                                        }
     1345                                        return mutAttr;
     1346                                } else if (attr->params.size() > 1) {
     1347                                        SemanticWarning(loc, Warning::GccAttributes, toCString( "too many arguments to ", name, " attribute" ) );
     1348                                } else {
     1349                                        SemanticWarning(loc, Warning::GccAttributes, toCString( "too few arguments to ", name, " attribute" ) );
     1350                                }
     1351                        }
     1352                        return attr;
     1353                }
     1354        }
     1355
     1356        const ast::FunctionDecl * Resolver_new::previsit( const ast::FunctionDecl * functionDecl ) {
    13001357                GuardValue( functionReturn );
     1358
     1359                assert (functionDecl->unique());
     1360                if (!functionDecl->has_body() && !functionDecl->withExprs.empty()) {
     1361                        SemanticError(functionDecl->location, functionDecl, "Function without body has with declarations");
     1362                }
     1363
     1364                if (!functionDecl->isTypeFixed) {
     1365                        auto mutDecl = mutate(functionDecl);
     1366                        auto mutType = mutDecl->type.get_and_mutate();
     1367
     1368                        for (auto & attr: mutDecl->attributes) {
     1369                                attr = handleAttribute(mutDecl->location, attr, symtab);
     1370                        }
     1371
     1372                        // handle assertions. (seems deep)
     1373
     1374                        symtab.enterScope();
     1375                        for (auto & typeParam : mutType->forall) {
     1376                                auto mutParam = typeParam.get_and_mutate();
     1377                                symtab.addType(mutParam);
     1378                                for (auto & asst : mutParam->assertions) {
     1379                                        asst = fixObjectType(asst.strict_as<ast::ObjectDecl>(), symtab);
     1380                                        symtab.addId(asst);
     1381                                }
     1382                                typeParam = mutParam;
     1383                        }
     1384
     1385                        // temporarily adds params to symbol table.
     1386                        // actual scoping rules for params and withexprs differ - see Pass::visit(FunctionDecl)
     1387
     1388                        std::vector<ast::ptr<ast::Type>> paramTypes;
     1389                        std::vector<ast::ptr<ast::Type>> returnTypes;
     1390
     1391                        for (auto & param : mutDecl->params) {
     1392                                param = fixObjectType(param.strict_as<ast::ObjectDecl>(), symtab);
     1393                                symtab.addId(param);
     1394                                paramTypes.emplace_back(param->get_type());
     1395                        }
     1396                        for (auto & ret : mutDecl->returns) {
     1397                                ret = fixObjectType(ret.strict_as<ast::ObjectDecl>(), symtab);
     1398                                returnTypes.emplace_back(ret->get_type());
     1399                        }
     1400                        // since function type in decl is just a view of param types, need to update that as well
     1401                        mutType->params = std::move(paramTypes);
     1402                        mutType->returns = std::move(returnTypes);
     1403
     1404                        std::list<ast::ptr<ast::Stmt>> newStmts;
     1405                        resolveWithExprs (mutDecl->withExprs, newStmts);
     1406
     1407                        if (mutDecl->stmts) {
     1408                                auto mutStmt = mutDecl->stmts.get_and_mutate();
     1409                                mutStmt->kids.splice(mutStmt->kids.begin(), std::move(newStmts));
     1410                                mutDecl->stmts = mutStmt;
     1411                        }
     1412
     1413                        symtab.leaveScope();
     1414
     1415                        mutDecl->mangleName = Mangle::mangle(mutDecl);
     1416                        mutDecl->isTypeFixed = true;
     1417                        functionDecl = mutDecl;
     1418                }
     1419                managedTypes.handleDWT(functionDecl);
     1420
    13011421                functionReturn = extractResultType( functionDecl->type );
     1422                return functionDecl;
    13021423        }
    13031424
     
    13301451        }
    13311452
    1332         void Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) {
     1453        const ast::ObjectDecl * Resolver_new::previsit( const ast::ObjectDecl * objectDecl ) {
    13331454                // To handle initialization of routine pointers [e.g. int (*fp)(int) = foo()],
    13341455                // class-variable `initContext` is changed multiple times because the LHS is analyzed
     
    13381459                // selecting the RHS.
    13391460                GuardValue( currentObject );
    1340                 currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() };
     1461
    13411462                if ( inEnumDecl && dynamic_cast< const ast::EnumInstType * >( objectDecl->get_type() ) ) {
    13421463                        // enumerator initializers should not use the enum type to initialize, since the
    13431464                        // enum type is still incomplete at this point. Use `int` instead.
     1465                        objectDecl = fixObjectType(objectDecl, symtab);
    13441466                        currentObject = ast::CurrentObject{
    13451467                                objectDecl->location, new ast::BasicType{ ast::BasicType::SignedInt } };
    13461468                }
     1469                else {
     1470                        if (!objectDecl->isTypeFixed) {
     1471                                auto newDecl = fixObjectType(objectDecl, symtab);
     1472                                auto mutDecl = mutate(newDecl);
     1473                               
     1474                                // generate CtorInit wrapper when necessary.
     1475                                // in certain cases, fixObjectType is called before reaching
     1476                                // this object in visitor pass, thus disabling CtorInit codegen.
     1477                                // this happens on aggregate members and function parameters.
     1478                                if ( InitTweak::tryConstruct( mutDecl ) && ( managedTypes.isManaged( mutDecl ) || ((! isInFunction() || mutDecl->storage.is_static ) && ! InitTweak::isConstExpr( mutDecl->init ) ) ) ) {
     1479                                        // constructed objects cannot be designated
     1480                                        if ( InitTweak::isDesignated( mutDecl->init ) ) SemanticError( mutDecl, "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n" );
     1481                                        // constructed objects should not have initializers nested too deeply
     1482                                        if ( ! InitTweak::checkInitDepth( mutDecl ) ) SemanticError( mutDecl, "Managed object's initializer is too deep " );
     1483
     1484                                        mutDecl->init = InitTweak::genCtorInit( mutDecl->location, mutDecl );
     1485                                }
     1486
     1487                                objectDecl = mutDecl;
     1488                        }
     1489                        currentObject = ast::CurrentObject{ objectDecl->location, objectDecl->get_type() };
     1490                }
     1491               
     1492                return objectDecl;
     1493        }
     1494
     1495        void Resolver_new::previsit( const ast::AggregateDecl * _aggDecl ) {
     1496                auto aggDecl = mutate(_aggDecl);
     1497                assertf(aggDecl == _aggDecl, "type declarations must be unique");
     1498
     1499                for (auto & member: aggDecl->members) {
     1500                        // nested type decls are hoisted already. no need to do anything
     1501                        if (auto obj = member.as<ast::ObjectDecl>()) {
     1502                                member = fixObjectType(obj, symtab);
     1503                        }
     1504                }
     1505        }
     1506
     1507        void Resolver_new::previsit( const ast::StructDecl * structDecl ) {
     1508                previsit(static_cast<const ast::AggregateDecl *>(structDecl));
     1509                managedTypes.handleStruct(structDecl);
    13471510        }
    13481511
     
    13511514                GuardValue( inEnumDecl );
    13521515                inEnumDecl = true;
    1353         }
     1516                // don't need to fix types for enum fields
     1517        }
     1518
    13541519
    13551520        const ast::StaticAssertDecl * Resolver_new::previsit(
     
    17801945        }
    17811946
     1947        const ast::WithStmt * Resolver_new::previsit( const ast::WithStmt * withStmt ) {
     1948                auto mutStmt = mutate(withStmt);
     1949                resolveWithExprs(mutStmt->exprs, stmtsToAddBefore);
     1950                return mutStmt;
     1951        }
     1952
     1953        void Resolver_new::resolveWithExprs(std::vector<ast::ptr<ast::Expr>> & exprs, std::list<ast::ptr<ast::Stmt>> & stmtsToAdd) {
     1954                for (auto & expr : exprs) {
     1955                        // only struct- and union-typed expressions are viable candidates
     1956                        expr = findKindExpression( expr, symtab, structOrUnion, "with expression" );
     1957
     1958                        // if with expression might be impure, create a temporary so that it is evaluated once
     1959                        if ( Tuples::maybeImpure( expr ) ) {
     1960                                static UniqueName tmpNamer( "_with_tmp_" );
     1961                                const CodeLocation loc = expr->location;
     1962                                auto tmp = new ast::ObjectDecl(loc, tmpNamer.newName(), expr->result, new ast::SingleInit(loc, expr ) );
     1963                                expr = new ast::VariableExpr( loc, tmp );
     1964                                stmtsToAdd.push_back( new ast::DeclStmt(loc, tmp ) );
     1965                                if ( InitTweak::isConstructable( tmp->type ) ) {
     1966                                        // generate ctor/dtor and resolve them
     1967                                        tmp->init = InitTweak::genCtorInit( loc, tmp );
     1968                                }
     1969                                // since tmp is freshly created, this should modify tmp in-place
     1970                                tmp->accept( *visitor );
     1971                        }
     1972                }
     1973        }
    17821974
    17831975
     
    18752067        }
    18762068
     2069        // suppress error on autogen functions and mark invalid autogen as deleted.
     2070        bool Resolver_new::onError(ast::ptr<ast::Decl> & decl) {
     2071                if (auto functionDecl = decl.as<ast::FunctionDecl>()) {
     2072                        // xxx - can intrinsic gen ever fail?
     2073                        if (functionDecl->linkage == ast::Linkage::AutoGen) {
     2074                                auto mutDecl = mutate(functionDecl);
     2075                                mutDecl->isDeleted = true;
     2076                                mutDecl->stmts = nullptr;
     2077                                decl = mutDecl;
     2078                                return false;
     2079                        }
     2080                }
     2081                return true;
     2082        }
     2083
    18772084} // namespace ResolvExpr
    18782085
  • src/ResolvExpr/SatisfyAssertions.cpp

    r685810e rf33eab7  
    247247                                auto it = inferred.find( slot );
    248248                                if ( it == inferred.end() ) {
    249                                         std::cerr << "missing assertion " << slot << std::endl;
     249                                        // std::cerr << "missing assertion " << slot << std::endl;
    250250                                        missingSlots.push_back(slot);
    251251                                        continue;
  • src/SymTab/Autogen.cc

    r685810e rf33eab7  
    3838#include "SynTree/Type.h"          // for FunctionType, Type, TypeInstType
    3939#include "SynTree/Visitor.h"       // for maybeAccept, Visitor, acceptAll
     40#include "CompilationState.h"
    4041
    4142class Attribute;
     
    346347        void FuncGenerator::resolve( FunctionDecl * dcl ) {
    347348                try {
    348                         ResolvExpr::resolveDecl( dcl, indexer );
     349                        if (!useNewAST) // attempt to delay resolver call
     350                                ResolvExpr::resolveDecl( dcl, indexer );
    349351                        if ( functionNesting == 0 ) {
    350352                                // forward declare if top-level struct, so that
  • src/SymTab/Autogen.h

    r685810e rf33eab7  
    167167                fExpr->args.emplace_back( dstParam );
    168168
    169                 const ast::Stmt * listInit = srcParam.buildListInit( fExpr );
     169                ast::ptr<ast::Stmt> listInit = srcParam.buildListInit( fExpr );
    170170
    171171                // fetch next set of arguments
  • src/SymTab/Validate.cc

    r685810e rf33eab7  
    6464#include "Common/UniqueName.h"         // for UniqueName
    6565#include "Common/utility.h"            // for operator+, cloneAll, deleteAll
     66#include "CompilationState.h"          // skip some passes in new-ast build
    6667#include "Concurrency/Keywords.h"      // for applyKeywords
    6768#include "FixFunction.h"               // for FixFunction
     
    368369                                mutateAll( translationUnit, compoundliteral );
    369370                        });
    370                         Stats::Time::TimeBlock("Resolve With Expressions", [&]() {
    371                                 ResolvExpr::resolveWithExprs( translationUnit ); // must happen before FixObjectType because user-code is resolved and may contain with variables
    372                         });
     371                        if (!useNewAST) {
     372                                Stats::Time::TimeBlock("Resolve With Expressions", [&]() {
     373                                        ResolvExpr::resolveWithExprs( translationUnit ); // must happen before FixObjectType because user-code is resolved and may contain with variables
     374                                });
     375                        }
    373376                }
    374377                {
    375378                        Stats::Heap::newPass("validate-F");
    376379                        Stats::Time::BlockGuard guard("validate-F");
    377                         Stats::Time::TimeCall("Fix Object Type",
    378                                 FixObjectType::fix, translationUnit);
     380                        if (!useNewAST) {
     381                                Stats::Time::TimeCall("Fix Object Type",
     382                                        FixObjectType::fix, translationUnit);
     383                        }
    379384                        Stats::Time::TimeCall("Array Length",
    380385                                ArrayLength::computeLength, translationUnit);
     
    383388                        Stats::Time::TimeCall("Fix Label Address",
    384389                                mutateAll<LabelAddressFixer>, translationUnit, labelAddrFixer);
    385                         Stats::Time::TimeCall("Handle Attributes",
    386                                 Validate::handleAttributes, translationUnit);
     390                        if (!useNewAST) {
     391                                Stats::Time::TimeCall("Handle Attributes",
     392                                        Validate::handleAttributes, translationUnit);
     393                        }
    387394                }
    388395        }
     
    13401347
    13411348        void ArrayLength::previsit( ArrayType * type ) {
    1342                 if ( type->dimension ) {
    1343                         // need to resolve array dimensions early so that constructor code can correctly determine
    1344                         // if a type is a VLA (and hence whether its elements need to be constructed)
    1345                         ResolvExpr::findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );
    1346 
    1347                         // must re-evaluate whether a type is a VLA, now that more information is available
    1348                         // (e.g. the dimension may have been an enumerator, which was unknown prior to this step)
    1349                         type->isVarLen = ! InitTweak::isConstExpr( type->dimension );
     1349                if (!useNewAST) {
     1350                        if ( type->dimension ) {
     1351                                // need to resolve array dimensions early so that constructor code can correctly determine
     1352                                // if a type is a VLA (and hence whether its elements need to be constructed)
     1353                                ResolvExpr::findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );
     1354
     1355                                // must re-evaluate whether a type is a VLA, now that more information is available
     1356                                // (e.g. the dimension may have been an enumerator, which was unknown prior to this step)
     1357                                type->isVarLen = ! InitTweak::isConstExpr( type->dimension );
     1358                        }
    13501359                }
    13511360        }
Note: See TracChangeset for help on using the changeset viewer.