Changeset c6b4432


Ignore:
Timestamp:
Nov 8, 2023, 2:01:11 PM (23 months ago)
Author:
Andrew Beach <ajbeach@…>
Branches:
master
Children:
3e4bf0d, f5ec35a
Parents:
790d835
Message:

Remove BaseSyntaxNode and clean-up.

Location:
src
Files:
113 deleted
77 edited

Legend:

Unmodified
Added
Removed
  • src/AST/module.mk

    r790d835 rc6b4432  
    2020        AST/Bitfield.hpp \
    2121        AST/Chain.hpp \
    22         AST/Convert.cpp \
    23         AST/Convert.hpp \
    2422        AST/Copy.cpp \
    2523        AST/Copy.hpp \
  • src/BasicTypes-gen.cc

    r790d835 rc6b4432  
    272272        size_t start, end;
    273273
    274 
    275         #define TypeH TOP_SRCDIR "src/SynTree/Type.h"
    276         resetInput( file, TypeH, buffer, code, str );
    277 
    278         if ( (start = str.find( STARTMK )) == string::npos ) Abort( "start", TypeH );
    279         start += sizeof( STARTMK );                                                     // includes newline
    280         code << str.substr( 0, start );
    281 
    282         code << "\t" << BYMK << endl;
    283         code << "\tenum Kind {" << endl;
    284         for ( int r = 0; r < NUMBER_OF_BASIC_TYPES; r += 1 ) {
    285                 code << "\t\t" << graph[r].name << "," << endl;
    286         } // for
    287         code << "\t\tNUMBER_OF_BASIC_TYPES" << endl;
    288         code << "\t} kind;" << endl;
    289         code << "\t";                                                                           // indentation for end marker
    290 
    291         if ( (start = str.find( ENDMK, start + 1 )) == string::npos ) Abort( "end", TypeH );
    292         code << str.substr( start );
    293 
    294         output( file, TypeH, code );
    295         // cout << code.str();
    296 
    297 
    298         #define TypeC TOP_SRCDIR "src/SynTree/Type.cc"
    299         resetInput( file, TypeC, buffer, code, str );
    300 
    301         if ( (start = str.find( STARTMK )) == string::npos ) Abort( "start", TypeC );
    302         start += sizeof( STARTMK );                                                     // includes newline
    303         code << str.substr( 0, start );
    304 
    305         code << BYMK << endl;
    306         code << "const char * BasicType::typeNames[] = {" << endl;
    307         for ( int r = 0; r < NUMBER_OF_BASIC_TYPES; r += 1 ) {
    308                 code << "\t\"" << graph[r].type << "\"," << endl;
    309         } // for
    310         code << "};" << endl;
    311 
    312         if ( (start = str.find( ENDMK, start + 1 )) == string::npos ) Abort( "end", TypeC );
    313         code << str.substr( start );
    314 
    315         output( file, TypeC, code );
    316         // cout << code.str();
    317 
    318 
    319         // TEMPORARY DURING CHANGE OVER
    320274        #define TypeH_AST TOP_SRCDIR "src/AST/Type.hpp"
    321275        resetInput( file, TypeH_AST, buffer, code, str );
  • src/CodeGen/FixMain.cc

    r790d835 rc6b4432  
    2525#include "AST/Type.hpp"
    2626#include "AST/Vector.hpp"
    27 #include "Common/PassVisitor.h"
    2827#include "Common/SemanticError.h"  // for SemanticError
    2928#include "CodeGen/GenType.h"       // for GenType
    30 #include "SynTree/Declaration.h"   // for FunctionDecl, operator<<
    31 #include "SynTree/Type.h"          // for FunctionType
    3229#include "SymTab/Mangler.h"
    3330
     
    3532
    3633namespace {
    37 
    38 struct FindMainCore {
    39         FunctionDecl * main_signature = nullptr;
    40 
    41         void previsit( FunctionDecl * decl ) {
    42                 if ( FixMain::isMain( decl ) ) {
    43                         if ( main_signature ) {
    44                                 SemanticError( decl, "Multiple definition of main routine\n" );
    45                         }
    46                         main_signature = decl;
    47                 }
    48         }
    49 };
    5034
    5135struct FindMainCore_new {
     
    6549        return genType( types[at], "", Options( false, false, false, false ) );
    6650}
    67 
    68 }
    69 
    70         template<typename container>
    71         std::string genTypeAt(const container& p, size_t idx) {
    72                 return genType((*std::next(p.begin(), idx))->get_type(), "");
    73         }
    74 
    75         void FixMain::fix( std::list< Declaration * > & translationUnit,
    76                         std::ostream &os, const char* bootloader_filename ) {
    77                 PassVisitor< FindMainCore > main_finder;
    78                 acceptAll( translationUnit, main_finder );
    79                 FunctionDecl * main_signature = main_finder.pass.main_signature;
    80 
    81                 if( main_signature ) {
    82                         os << "static inline int invoke_main(int argc, char* argv[], char* envp[]) { (void)argc; (void)argv; (void)envp; return ";
    83                         main_signature->mangleName = SymTab::Mangler::mangle(main_signature);
    84 
    85                         os << main_signature->get_scopedMangleName() << "(";
    86                         const auto& params = main_signature->get_functionType()->get_parameters();
    87                         switch(params.size()) {
    88                                 case 3: os << "(" << genTypeAt(params, 0) << ")argc, (" << genTypeAt(params, 1) << ")argv, (" << genTypeAt(params, 2) << ")envp"; break;
    89                                 case 2: os << "(" << genTypeAt(params, 0) << ")argc, (" << genTypeAt(params, 1) << ")argv"; break;
    90                                 case 0: break;
    91                                 default : assert(false);
    92                         }
    93                         os << "); }\n";
    94 
    95                         std::ifstream bootloader(bootloader_filename, std::ios::in);
    96                         assertf( bootloader.is_open(), "cannot open bootloader.c\n" );
    97                         os << bootloader.rdbuf();
    98                 }
    99         }
    100 
    101 namespace {
    10251
    10352ast::ObjectDecl * makeIntObj(){
     
    159108} // namespace
    160109
    161 bool FixMain::isMain( FunctionDecl * decl ) {
    162         if ( std::string("main") != decl->name ) {
    163                 return false;
    164         }
    165         return is_main( SymTab::Mangler::mangle( decl, true, true ) );
    166 }
    167 
    168110bool FixMain::isMain( const ast::FunctionDecl * decl ) {
    169111        if ( std::string("main") != decl->name ) {
  • src/CodeGen/FixMain.h

    r790d835 rc6b4432  
    2121
    2222#include "AST/LinkageSpec.hpp"
    23 #include "SynTree/LinkageSpec.h"
    2423
    25 class Declaration;
    26 class FunctionDecl;
    2724namespace ast {
    2825        class FunctionDecl;
     
    3431class FixMain {
    3532public :
    36         static inline LinkageSpec::Spec mainLinkage() {
    37                 return replace_main ? LinkageSpec::Cforall : LinkageSpec::C;
    38         }
    3933        static inline ast::Linkage::Spec getMainLinkage() {
    4034                return replace_main ? ast::Linkage::Cforall : ast::Linkage::C;
     
    4539        }
    4640
    47         static bool isMain(FunctionDecl* decl);
    4841        static bool isMain(const ast::FunctionDecl * decl);
    4942
    50         static void fix( std::list< Declaration * > & decls,
    51                         std::ostream &os, const char* bootloader_filename );
    5243        static void fix( ast::TranslationUnit & translationUnit,
    5344                        std::ostream &os, const char * bootloader_filename );
  • src/CodeGen/FixNames.cc

    r790d835 rc6b4432  
    2222#include "AST/Expr.hpp"
    2323#include "AST/Pass.hpp"
    24 #include "Common/PassVisitor.h"
    2524#include "Common/SemanticError.h"  // for SemanticError
    2625#include "FixMain.h"               // for FixMain
    2726#include "SymTab/Mangler.h"        // for Mangler
    28 #include "SynTree/LinkageSpec.h"   // for Cforall, isMangled
    29 #include "SynTree/Constant.h"      // for Constant
    30 #include "SynTree/Declaration.h"   // for FunctionDecl, ObjectDecl, Declarat...
    31 #include "SynTree/Expression.h"    // for ConstantExpr
    32 #include "SynTree/Label.h"         // for Label, noLabels
    33 #include "SynTree/Statement.h"     // for ReturnStmt, CompoundStmt
    34 #include "SynTree/Type.h"          // for Type, BasicType, Type::Qualifiers
    35 #include "SynTree/Visitor.h"       // for Visitor, acceptAll
    3627#include "CompilationState.h"
    3728
    3829namespace CodeGen {
    39         class FixNames : public WithGuards {
    40           public:
    41                 void postvisit( ObjectDecl *objectDecl );
    42                 void postvisit( FunctionDecl *functionDecl );
    43 
    44                 void previsit( CompoundStmt *compoundStmt );
    45           private:
    46                 int scopeLevel = 1;
    47 
    48                 void fixDWT( DeclarationWithType *dwt );
    49         };
    50 
    51         void fixNames( std::list< Declaration* > & translationUnit ) {
    52                 PassVisitor<FixNames> fixer;
    53                 acceptAll( translationUnit, fixer );
    54         }
    55 
    56         void FixNames::fixDWT( DeclarationWithType * dwt ) {
    57                 if ( dwt->get_name() != "" ) {
    58                         if ( LinkageSpec::isMangled( dwt->get_linkage() ) ) {
    59                                 if (!useNewAST) {
    60                                         dwt->set_mangleName( SymTab::Mangler::mangle( dwt ) );
    61                                 }
    62                                 dwt->set_scopeLevel( scopeLevel );
    63                         } // if
    64                 } // if
    65         }
    66 
    67         void FixNames::postvisit( ObjectDecl * objectDecl ) {
    68                 fixDWT( objectDecl );
    69         }
    70 
    71         void FixNames::postvisit( FunctionDecl * functionDecl ) {
    72                 fixDWT( functionDecl );
    73 
    74                 if ( FixMain::isMain( functionDecl ) ) {
    75                         int nargs = functionDecl->get_functionType()->get_parameters().size();
    76                         if( !(nargs == 0 || nargs == 2 || nargs == 3) ) {
    77                                 SemanticError(functionDecl, "Main expected to have 0, 2 or 3 arguments\n");
    78                         }
    79                         functionDecl->get_statements()->get_kids().push_back( new ReturnStmt( new ConstantExpr( Constant::from_int( 0 ) ) ) );
    80                 }
    81         }
    82 
    83         void FixNames::previsit( CompoundStmt * ) {
    84                 scopeLevel++;
    85                 GuardAction( [this](){ scopeLevel--; } );
    86         }
    87 
    8830/// Does work with the main function and scopeLevels.
    8931class FixNames_new final {
  • src/CodeGen/GenType.cc

    r790d835 rc6b4432  
    2121#include "AST/Print.hpp"          // for print
    2222#include "AST/Vector.hpp"         // for vector
    23 #include "CodeGenerator.h"        // for CodeGenerator
    2423#include "CodeGeneratorNew.hpp"   // for CodeGenerator_new
    2524#include "Common/UniqueName.h"    // for UniqueName
    26 #include "SynTree/Declaration.h"  // for DeclarationWithType
    27 #include "SynTree/Expression.h"   // for Expression
    28 #include "SynTree/Type.h"         // for PointerType, Type, FunctionType
    29 #include "SynTree/Visitor.h"      // for Visitor
    3025
    3126namespace CodeGen {
    32         struct GenType : public WithVisitorRef<GenType>, public WithShortCircuiting {
    33                 std::string typeString;
    34                 GenType( const std::string &typeString, const Options &options );
    35 
    36                 void previsit( BaseSyntaxNode * );
    37                 void postvisit( BaseSyntaxNode * );
    38 
    39                 void postvisit( FunctionType * funcType );
    40                 void postvisit( VoidType * voidType );
    41                 void postvisit( BasicType * basicType );
    42                 void postvisit( PointerType * pointerType );
    43                 void postvisit( ArrayType * arrayType );
    44                 void postvisit( ReferenceType * refType );
    45                 void postvisit( StructInstType * structInst );
    46                 void postvisit( UnionInstType * unionInst );
    47                 void postvisit( EnumInstType * enumInst );
    48                 void postvisit( TypeInstType * typeInst );
    49                 void postvisit( TupleType  * tupleType );
    50                 void postvisit( VarArgsType * varArgsType );
    51                 void postvisit( ZeroType * zeroType );
    52                 void postvisit( OneType * oneType );
    53                 void postvisit( GlobalScopeType * globalType );
    54                 void postvisit( TraitInstType * inst );
    55                 void postvisit( TypeofType * typeof );
    56                 void postvisit( VTableType * vtable );
    57                 void postvisit( QualifiedType * qualType );
    58 
    59           private:
    60                 void handleQualifiers( Type *type );
    61                 std::string handleGeneric( ReferenceToType * refType );
    62                 void genArray( const Type::Qualifiers &qualifiers, Type *base, Expression *dimension, bool isVarLen, bool isStatic );
    63 
    64                 Options options;
    65         };
    66 
    67         std::string genType( Type *type, const std::string &baseString, const Options &options ) {
    68                 PassVisitor<GenType> gt( baseString, options );
    69                 std::ostringstream os;
    70 
    71                 if ( ! type->get_attributes().empty() ) {
    72                         PassVisitor<CodeGenerator> cg( os, options );
    73                         cg.pass.genAttributes( type->get_attributes() );
    74                 } // if
    75 
    76                 type->accept( gt );
    77                 return os.str() + gt.pass.typeString;
    78         }
    79 
    80         std::string genType( Type *type, const std::string &baseString, bool pretty, bool genC , bool lineMarks ) {
    81                 return genType( type, baseString, Options(pretty, genC, lineMarks, false ) );
    82         }
    83 
    84         std::string genPrettyType( Type * type, const std::string & baseString ) {
    85                 return genType( type, baseString, true, false );
    86         }
    87 
    88         GenType::GenType( const std::string &typeString, const Options &options ) : typeString( typeString ), options( options ) {}
    89 
    90         // *** BaseSyntaxNode
    91         void GenType::previsit( BaseSyntaxNode * ) {
    92                 // turn off automatic recursion for all nodes, to allow each visitor to
    93                 // precisely control the order in which its children are visited.
    94                 visit_children = false;
    95         }
    96 
    97         void GenType::postvisit( BaseSyntaxNode * node ) {
    98                 std::stringstream ss;
    99                 node->print( ss );
    100                 assertf( false, "Unhandled node reached in GenType: %s", ss.str().c_str() );
    101         }
    102 
    103         void GenType::postvisit( VoidType * voidType ) {
    104                 typeString = "void " + typeString;
    105                 handleQualifiers( voidType );
    106         }
    107 
    108         void GenType::postvisit( BasicType * basicType ) {
    109                 BasicType::Kind kind = basicType->kind;
    110                 assert( 0 <= kind && kind < BasicType::NUMBER_OF_BASIC_TYPES );
    111                 typeString = std::string( BasicType::typeNames[kind] ) + " " + typeString;
    112                 handleQualifiers( basicType );
    113         }
    114 
    115         void GenType::genArray( const Type::Qualifiers & qualifiers, Type * base, Expression *dimension, bool isVarLen, bool isStatic ) {
    116                 std::ostringstream os;
    117                 if ( typeString != "" ) {
    118                         if ( typeString[ 0 ] == '*' ) {
    119                                 os << "(" << typeString << ")";
    120                         } else {
    121                                 os << typeString;
    122                         } // if
    123                 } // if
    124                 os << "[";
    125 
    126                 if ( isStatic ) {
    127                         os << "static ";
    128                 } // if
    129                 if ( qualifiers.is_const ) {
    130                         os << "const ";
    131                 } // if
    132                 if ( qualifiers.is_volatile ) {
    133                         os << "volatile ";
    134                 } // if
    135                 if ( qualifiers.is_restrict ) {
    136                         os << "__restrict ";
    137                 } // if
    138                 if ( qualifiers.is_atomic ) {
    139                         os << "_Atomic ";
    140                 } // if
    141                 if ( dimension != 0 ) {
    142                         PassVisitor<CodeGenerator> cg( os, options );
    143                         dimension->accept( cg );
    144                 } else if ( isVarLen ) {
    145                         // no dimension expression on a VLA means it came in with the * token
    146                         os << "*";
    147                 } // if
    148                 os << "]";
    149 
    150                 typeString = os.str();
    151 
    152                 base->accept( *visitor );
    153         }
    154 
    155         void GenType::postvisit( PointerType * pointerType ) {
    156                 assert( pointerType->base != 0);
    157                 if ( pointerType->get_isStatic() || pointerType->get_isVarLen() || pointerType->dimension ) {
    158                         genArray( pointerType->get_qualifiers(), pointerType->base, pointerType->dimension, pointerType->get_isVarLen(), pointerType->get_isStatic() );
    159                 } else {
    160                         handleQualifiers( pointerType );
    161                         if ( typeString[ 0 ] == '?' ) {
    162                                 typeString = "* " + typeString;
    163                         } else {
    164                                 typeString = "*" + typeString;
    165                         } // if
    166                         pointerType->base->accept( *visitor );
    167                 } // if
    168         }
    169 
    170         void GenType::postvisit( ArrayType * arrayType ) {
    171                 genArray( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->get_isVarLen(), arrayType->get_isStatic() );
    172         }
    173 
    174         void GenType::postvisit( ReferenceType * refType ) {
    175                 assert( 0 != refType->base );
    176                 assertf( ! options.genC, "Reference types should not reach code generation." );
    177                 handleQualifiers( refType );
    178                 typeString = "&" + typeString;
    179                 refType->base->accept( *visitor );
    180         }
    181 
    182         void GenType::postvisit( FunctionType * funcType ) {
    183                 std::ostringstream os;
    184 
    185                 if ( typeString != "" ) {
    186                         if ( typeString[ 0 ] == '*' ) {
    187                                 os << "(" << typeString << ")";
    188                         } else {
    189                                 os << typeString;
    190                         } // if
    191                 } // if
    192 
    193                 /************* parameters ***************/
    194 
    195                 const std::list<DeclarationWithType *> &pars = funcType->parameters;
    196 
    197                 if ( pars.empty() ) {
    198                         if ( funcType->get_isVarArgs() ) {
    199                                 os << "()";
    200                         } else {
    201                                 os << "(void)";
    202                         } // if
    203                 } else {
    204                         PassVisitor<CodeGenerator> cg( os, options );
    205                         os << "(" ;
    206 
    207                         cg.pass.genCommaList( pars.begin(), pars.end() );
    208 
    209                         if ( funcType->get_isVarArgs() ) {
    210                                 os << ", ...";
    211                         } // if
    212                         os << ")";
    213                 } // if
    214 
    215                 typeString = os.str();
    216 
    217                 if ( funcType->returnVals.size() == 0 ) {
    218                         typeString = "void " + typeString;
    219                 } else {
    220                         funcType->returnVals.front()->get_type()->accept( *visitor );
    221                 } // if
    222 
    223                 // add forall
    224                 if( ! funcType->forall.empty() && ! options.genC ) {
    225                         // assertf( ! genC, "Aggregate type parameters should not reach code generation." );
    226                         std::ostringstream os;
    227                         PassVisitor<CodeGenerator> cg( os, options );
    228                         os << "forall(";
    229                         cg.pass.genCommaList( funcType->forall.begin(), funcType->forall.end() );
    230                         os << ")" << std::endl;
    231                         typeString = os.str() + typeString;
    232                 }
    233         }
    234 
    235         std::string GenType::handleGeneric( ReferenceToType * refType ) {
    236                 if ( ! refType->parameters.empty() ) {
    237                         std::ostringstream os;
    238                         PassVisitor<CodeGenerator> cg( os, options );
    239                         os << "(";
    240                         cg.pass.genCommaList( refType->parameters.begin(), refType->parameters.end() );
    241                         os << ") ";
    242                         return os.str();
    243                 }
    244                 return "";
    245         }
    246 
    247         void GenType::postvisit( StructInstType * structInst )  {
    248                 typeString = structInst->name + handleGeneric( structInst ) + " " + typeString;
    249                 if ( options.genC ) typeString = "struct " + typeString;
    250                 handleQualifiers( structInst );
    251         }
    252 
    253         void GenType::postvisit( UnionInstType * unionInst ) {
    254                 typeString = unionInst->name + handleGeneric( unionInst ) + " " + typeString;
    255                 if ( options.genC ) typeString = "union " + typeString;
    256                 handleQualifiers( unionInst );
    257         }
    258 
    259         void GenType::postvisit( EnumInstType * enumInst ) {
    260                 if ( enumInst->baseEnum && enumInst->baseEnum->base ) {
    261                         typeString = genType(enumInst->baseEnum->base, typeString, options);
    262                 } else {
    263                         typeString = enumInst->name + " " + typeString;
    264                         if ( options.genC ) {
    265                                 typeString = "enum " + typeString;
    266                         }
    267                 }
    268                 handleQualifiers( enumInst );
    269         }
    270 
    271         void GenType::postvisit( TypeInstType * typeInst ) {
    272                 assertf( ! options.genC, "Type instance types should not reach code generation." );
    273                 typeString = typeInst->name + " " + typeString;
    274                 handleQualifiers( typeInst );
    275         }
    276 
    277         void GenType::postvisit( TupleType * tupleType ) {
    278                 assertf( ! options.genC, "Tuple types should not reach code generation." );
    279                 unsigned int i = 0;
    280                 std::ostringstream os;
    281                 os << "[";
    282                 for ( Type * t : *tupleType ) {
    283                         i++;
    284                         os << genType( t, "", options ) << (i == tupleType->size() ? "" : ", ");
    285                 }
    286                 os << "] ";
    287                 typeString = os.str() + typeString;
    288         }
    289 
    290         void GenType::postvisit( VarArgsType * varArgsType ) {
    291                 typeString = "__builtin_va_list " + typeString;
    292                 handleQualifiers( varArgsType );
    293         }
    294 
    295         void GenType::postvisit( ZeroType * zeroType ) {
    296                 // ideally these wouldn't hit codegen at all, but should be safe to make them ints
    297                 typeString = (options.pretty ? "zero_t " : "long int ") + typeString;
    298                 handleQualifiers( zeroType );
    299         }
    300 
    301         void GenType::postvisit( OneType * oneType ) {
    302                 // ideally these wouldn't hit codegen at all, but should be safe to make them ints
    303                 typeString = (options.pretty ? "one_t " : "long int ") + typeString;
    304                 handleQualifiers( oneType );
    305         }
    306 
    307         void GenType::postvisit( GlobalScopeType * globalType ) {
    308                 assertf( ! options.genC, "Global scope type should not reach code generation." );
    309                 handleQualifiers( globalType );
    310         }
    311 
    312         void GenType::postvisit( TraitInstType * inst ) {
    313                 assertf( ! options.genC, "Trait types should not reach code generation." );
    314                 typeString = inst->name + " " + typeString;
    315                 handleQualifiers( inst );
    316         }
    317 
    318         void GenType::postvisit( TypeofType * typeof ) {
    319                 std::ostringstream os;
    320                 PassVisitor<CodeGenerator> cg( os, options );
    321                 os << "typeof(";
    322                 typeof->expr->accept( cg );
    323                 os << ") " << typeString;
    324                 typeString = os.str();
    325                 handleQualifiers( typeof );
    326         }
    327 
    328         void GenType::postvisit( VTableType * vtable ) {
    329                 assertf( ! options.genC, "Virtual table types should not reach code generation." );
    330                 std::ostringstream os;
    331                 os << "vtable(" << genType( vtable->base, "", options ) << ") " << typeString;
    332                 typeString = os.str();
    333                 handleQualifiers( vtable );
    334         }
    335 
    336         void GenType::postvisit( QualifiedType * qualType ) {
    337                 assertf( ! options.genC, "Qualified types should not reach code generation." );
    338                 std::ostringstream os;
    339                 os << genType( qualType->parent, "", options ) << "." << genType( qualType->child, "", options ) << typeString;
    340                 typeString = os.str();
    341                 handleQualifiers( qualType );
    342         }
    343 
    344         void GenType::handleQualifiers( Type * type ) {
    345                 if ( type->get_const() ) {
    346                         typeString = "const " + typeString;
    347                 } // if
    348                 if ( type->get_volatile() ) {
    349                         typeString = "volatile " + typeString;
    350                 } // if
    351                 if ( type->get_restrict() ) {
    352                         typeString = "__restrict " + typeString;
    353                 } // if
    354                 if ( type->get_atomic() ) {
    355                         typeString = "_Atomic " + typeString;
    356                 } // if
    357         }
    35827
    35928namespace {
  • src/CodeGen/Generate.cc

    r790d835 rc6b4432  
    2020
    2121#include "CodeGeneratorNew.hpp"      // for CodeGenerator_new, doSemicolon, ...
    22 #include "CodeGenerator.h"           // for CodeGenerator, doSemicolon, oper...
    2322#include "GenType.h"                 // for genPrettyType
    24 #include "Common/PassVisitor.h"      // for PassVisitor
    25 #include "SynTree/LinkageSpec.h"     // for isBuiltin, isGeneratable
    26 #include "SynTree/BaseSyntaxNode.h"  // for BaseSyntaxNode
    27 #include "SynTree/Declaration.h"     // for Declaration
    28 #include "SynTree/Type.h"            // for Type
    2923
    3024using namespace std;
    3125
    3226namespace CodeGen {
    33         namespace {
    34                 /// Removes misc. nodes that should not exist in CodeGen
    35                 struct TreeCleaner {
    36                         void premutate( CompoundStmt * stmt );
    37                         Statement * postmutate( ImplicitCtorDtorStmt * stmt );
    38 
    39                         static bool shouldClean( Declaration * );
    40                 };
    41 
    42                 void cleanTree( std::list< Declaration * > & translationUnit ) {
    43                         PassVisitor<TreeCleaner> cleaner;
    44                         filter( translationUnit, [](Declaration * decl) { return TreeCleaner::shouldClean(decl); }, false );
    45                         mutateAll( translationUnit, cleaner );
    46                 } // cleanTree
    47         } // namespace
    48 
    49         void generate( std::list< Declaration* > translationUnit, std::ostream &os, bool doIntrinsics, bool pretty, bool generateC, bool lineMarks, bool printExprTypes ) {
    50                 cleanTree( translationUnit );
    51 
    52                 PassVisitor<CodeGenerator> cgv( os, pretty, generateC, lineMarks, printExprTypes );
    53                 for ( auto & dcl : translationUnit ) {
    54                         if ( LinkageSpec::isGeneratable( dcl->get_linkage() ) && (doIntrinsics || ! LinkageSpec::isBuiltin( dcl->get_linkage() ) ) ) {
    55                                 cgv.pass.updateLocation( dcl );
    56                                 dcl->accept(cgv);
    57                                 if ( doSemicolon( dcl ) ) {
    58                                         os << ";";
    59                                 } // if
    60                                 os << cgv.pass.endl;
    61                         } // if
    62                 } // for
    63         }
    64 
    65         void generate( BaseSyntaxNode * node, std::ostream & os ) {
    66                 if ( Type * type = dynamic_cast< Type * >( node ) ) {
    67                         os << genPrettyType( type, "" );
    68                 } else {
    69                         PassVisitor<CodeGenerator> cgv( os, true, false, false, false );
    70                         node->accept( cgv );
    71                 }
    72                 os << std::endl;
    73         }
    74 
    75         namespace {
    76                 void TreeCleaner::premutate( CompoundStmt * cstmt ) {
    77                         filter( cstmt->kids, [](Statement * stmt) {
    78                                 if ( DeclStmt * declStmt = dynamic_cast< DeclStmt * >( stmt ) ) {
    79                                         return shouldClean( declStmt->decl );
    80                                 }
    81                                 return false;
    82                         }, false );
    83                 }
    84 
    85                 Statement * TreeCleaner::postmutate( ImplicitCtorDtorStmt * stmt ) {
    86                         Statement * callStmt = nullptr;
    87                         std::swap( stmt->callStmt, callStmt );
    88                         delete stmt;
    89                         return callStmt;
    90                 }
    91 
    92                 bool TreeCleaner::shouldClean( Declaration * decl ) {
    93                         return dynamic_cast< TraitDecl * >( decl );
    94                 }
    95         } // namespace
    9627
    9728namespace {
  • src/CodeGen/Generate.h

    r790d835 rc6b4432  
    2727
    2828namespace CodeGen {
    29         /// Generates code. doIntrinsics determines if intrinsic functions are printed, pretty formats output nicely (e.g., uses unmangled names, etc.), generateC is true when the output must consist only of C code (allows some assertions, etc.)
    30         void generate( std::list< Declaration* > translationUnit, std::ostream &os, bool doIntrinsics, bool pretty, bool generateC = false , bool lineMarks = false, bool printTypeExpr = false );
    31 
    32         /// Generate code for a single node -- helpful for debugging in gdb
    33         void generate( BaseSyntaxNode * node, std::ostream & os );
    3429
    3530/// Generates all code in transUnit and writing it to the os.
  • src/CodeGen/LinkOnce.cc

    r790d835 rc6b4432  
    2222#include "AST/Expr.hpp"
    2323#include "AST/Pass.hpp"
    24 #include "Common/PassVisitor.h"       // for PassVisitor, WithShortCircuiting
    2524
    2625namespace CodeGen {
    2726
    2827namespace {
    29 
    30 bool is_cfa_linkonce_old( Attribute const * attr ) {
    31         return std::string("cfa_linkonce") == attr->name;
    32 }
    33 
    34 bool is_section_attribute_old( Attribute const * attr ) {
    35         return std::string("section") == attr->name;
    36 }
    37 
    38 class LinkOnceVisitorCore : public WithShortCircuiting {
    39 public:
    40         void previsit( Declaration * ) {
    41                 visit_children = false;
    42         }
    43 
    44         void previsit( DeclarationWithType * decl ) {
    45                 std::list< Attribute * > & attributes = decl->attributes;
    46                 // See if we can find the element:
    47                 auto found = std::find_if(attributes.begin(), attributes.end(), is_cfa_linkonce_old );
    48                 if ( attributes.end() != found ) {
    49                         // Remove any other sections:
    50                         attributes.remove_if( is_section_attribute_old );
    51                         // Iterator to the cfa_linkonce attribute should still be valid.
    52                         Attribute * attribute = *found;
    53                         assert( attribute->parameters.empty() );
    54                         assert( !decl->mangleName.empty() );
    55                         // Overwrite the attribute in place.
    56                         const std::string section_name = ".gnu.linkonce." + decl->mangleName;
    57                         attribute->name = "section";
    58                         attribute->parameters.push_back(
    59                                 new ConstantExpr( Constant::from_string( section_name ) )
    60                         );
    61 
    62                         // Unconditionnaly add "visibility(default)" to anything with gnu.linkonce
    63                         // visibility is a mess otherwise
    64                         attributes.push_back(new Attribute("visibility", {new ConstantExpr( Constant::from_string( "default" ) )}));
    65 
    66                 }
    67                 visit_children = false;
    68         }
    69 };
    7028
    7129bool is_cfa_linkonce( ast::Attribute const * attr ) {
     
    12280} // namespace
    12381
    124 void translateLinkOnce( std::list< Declaration *> & translationUnit ) {
    125         PassVisitor<LinkOnceVisitorCore> translator;
    126         acceptAll( translationUnit, translator );
    127 }
    128 
    12982void translateLinkOnce( ast::TranslationUnit & translationUnit ) {
    13083        ast::Pass<LinkOnceCore>::run( translationUnit );
  • src/CodeGen/LinkOnce.h

    r790d835 rc6b4432  
    2020// for now its almost the only attribute we handle.
    2121
    22 #include <list>  // for list
    2322
    24 class Declaration;
    2523namespace ast {
    2624        class TranslationUnit;
     
    2927namespace CodeGen {
    3028
    31 void translateLinkOnce( std::list< Declaration *> & translationUnit );
    3229void translateLinkOnce( ast::TranslationUnit & translationUnit );
    3330/* Convert the cfa_linkonce attribute on top level declaration into
  • src/CodeGen/module.mk

    r790d835 rc6b4432  
    1616
    1717SRC_CODEGEN = \
    18         CodeGen/CodeGenerator.cc \
    19         CodeGen/CodeGenerator.h \
    2018        CodeGen/CodeGeneratorNew.cpp \
    2119        CodeGen/CodeGeneratorNew.hpp \
  • src/Common/Eval.cc

    r790d835 rc6b4432  
    1919
    2020#include "AST/Inspect.hpp"
    21 #include "Common/PassVisitor.h"
    2221#include "CodeGen/OperatorTable.h"                                              // access: OperatorInfo
    2322#include "AST/Pass.hpp"
    2423#include "InitTweak/InitTweak.h"
    25 #include "SynTree/Expression.h"
    26 
    27 //-------------------------------------------------------------
    28 // Old AST
    29 struct EvalOld : public WithShortCircuiting {
    30         long long int value = 0;                                                        // compose the result of the constant expression
    31         bool valid = true;                                                                      // true => constant expression and value is the result
    32                                                                                                                 // false => not constant expression, e.g., ++i
    33         bool cfavalid = true;                                                           // true => constant expression and value computable
    34                                                                                                                 // false => constant expression but value not computable, e.g., sizeof(int)
    35 
    36         void previsit( const BaseSyntaxNode * ) { visit_children = false; }
    37         void postvisit( const BaseSyntaxNode * ) { valid = false; }
    38 
    39         void postvisit( const SizeofExpr * ) {
    40         }
    41 
    42         void postvisit( const ConstantExpr * expr ) {
    43                 value = expr->intValue();
    44         }
    45 
    46         void postvisit( const CastExpr * expr ) {
    47                 auto arg = eval(expr->arg);
    48                 valid = arg.second;
    49                 value = arg.first;
    50                 // TODO: perform type conversion on value if valid
    51         }
    52 
    53         void postvisit( const VariableExpr * const expr ) {
    54                 if ( EnumInstType * inst = dynamic_cast<EnumInstType *>(expr->result) ) {
    55                         if ( EnumDecl * decl = inst->baseEnum ) {
    56                                 if ( decl->valueOf( expr->var, value ) ) { // value filled by valueOf
    57                                         return;
    58                                 }
    59                         }
    60                 }
    61                 valid = false;
    62         }
    63 
    64         void postvisit( const ApplicationExpr * expr ) {
    65                 DeclarationWithType * function = InitTweak::getFunction(const_cast<ApplicationExpr *>(expr));
    66                 if ( ! function || function->linkage != LinkageSpec::Intrinsic ) { valid = false; return; }
    67                 const std::string & fname = function->name;
    68                 assertf( expr->args.size() == 1 || expr->args.size() == 2, "Intrinsic function with %zd arguments: %s", expr->args.size(), fname.c_str() );
    69                 std::pair<long long int, bool> arg1, arg2;
    70                 arg1 = eval(expr->args.front());
    71                 valid = valid && arg1.second;
    72                 if ( ! valid ) return;
    73                 if ( expr->args.size() == 2 ) {
    74                         arg2 = eval(expr->args.back());
    75                         valid = valid && arg2.second;
    76                         if ( ! valid ) return;
    77                 }
    78                 if (fname == "?+?") {
    79                         value = arg1.first + arg2.first;
    80                 } else if (fname == "?-?") {
    81                         value = arg1.first - arg2.first;
    82                 } else if (fname == "?*?") {
    83                         value = arg1.first * arg2.first;
    84                 } else if (fname == "?/?") {
    85                         value = arg1.first / arg2.first;
    86                 } else if (fname == "?%?") {
    87                         value = arg1.first % arg2.first;
    88                 } else {
    89                         valid = false;
    90                 }
    91                 // TODO: implement other intrinsic functions
    92         }
    93 };
    94 
    95 //-------------------------------------------------------------
    96 // New AST
     24
    9725struct EvalNew : public ast::WithShortCircuiting {
    9826        Evaluation result = { 0, true, true };
     
    270198};
    271199
    272 std::pair<long long int, bool> eval( const Expression * expr ) {
    273         PassVisitor<EvalOld> ev;
    274         if ( expr ) {
    275                 expr->accept( ev );
    276                 return std::make_pair( ev.pass.value, ev.pass.valid );
    277         } else {
    278                 return std::make_pair( 0, false );
    279         }
    280 }
    281 
    282200Evaluation eval( const ast::Expr * expr ) {
    283201        if ( expr ) {
  • src/Common/Eval.h

    r790d835 rc6b4432  
    3030
    3131/// Evaluates expr as a long long int.
    32 /// If second is false, expr could not be evaluated.
    33 std::pair<long long int, bool> eval(const Expression * expr);
    3432Evaluation eval(const ast::Expr * expr);
    3533
  • src/Common/Examine.cc

    r790d835 rc6b4432  
    1919#include "CodeGen/OperatorTable.h"
    2020#include "InitTweak/InitTweak.h"
    21 
    22 DeclarationWithType * isMainFor( FunctionDecl * func, AggregateDecl::Aggregate kind ) {
    23         if (func->name != "main") return nullptr;
    24         if (func->type->parameters.size() != 1) return nullptr;
    25 
    26         auto param = func->type->parameters.front();
    27 
    28         auto type = dynamic_cast<ReferenceType * >(param->get_type());
    29         if (!type) return nullptr;
    30 
    31         auto obj = dynamic_cast<StructInstType *>(type->base);
    32         if (!obj) return nullptr;
    33 
    34         if (kind != obj->baseStruct->kind) return nullptr;
    35 
    36         return param;
    37 }
    3821
    3922namespace {
     
    6952
    7053namespace {
    71         Type * getDestructorParam( FunctionDecl * func ) {
    72                 if ( !CodeGen::isDestructor( func->name ) ) return nullptr;
    73 
    74                 auto params = func->type->parameters;
    75                 if ( 1 != params.size() ) return nullptr;
    76 
    77                 auto ref = dynamic_cast<ReferenceType *>( params.front()->get_type() );
    78                 if ( ref ) {
    79                         return ref->base;
    80                 }
    81                 return nullptr;
    82         }
    8354
    8455const ast::Type * getDestructorParam( const ast::FunctionDecl * func ) {
     
    8859}
    8960
    90 }
    91 
    92 bool isDestructorFor( FunctionDecl * func, StructDecl * type_decl ) {
    93         if ( Type * type = getDestructorParam( func ) ) {
    94                 auto stype = dynamic_cast<StructInstType *>( type );
    95                 return stype && stype->baseStruct == type_decl;
    96         }
    97         return false;
    9861}
    9962
  • src/Common/Examine.h

    r790d835 rc6b4432  
    1515
    1616#include "AST/Decl.hpp"
    17 #include "SynTree/Declaration.h"
    1817
    1918/// Check if this is a main function for a type of an aggregate kind.
    20 DeclarationWithType * isMainFor( FunctionDecl * func, AggregateDecl::Aggregate kind );
    2119const ast::DeclWithType * isMainFor(
    2220        const ast::FunctionDecl * func, ast::AggregateDecl::Aggregate kind );
     
    2422
    2523/// Check if this function is a destructor for the given structure.
    26 bool isDestructorFor( FunctionDecl * func, StructDecl * type_decl );
    2724bool isDestructorFor(
    2825        const ast::FunctionDecl * func, const ast::StructDecl * type );
  • src/Common/module.mk

    r790d835 rc6b4432  
    3131        Common/Indenter.cc \
    3232        Common/Iterate.hpp \
    33         Common/PassVisitor.cc \
    34         Common/PassVisitor.h \
    35         Common/PassVisitor.impl.h \
    36         Common/PassVisitor.proto.h \
    3733        Common/PersistentMap.h \
    3834        Common/ResolvProtoDump.hpp \
  • src/Concurrency/module.mk

    r790d835 rc6b4432  
    2121        Concurrency/Corun.hpp \
    2222        Concurrency/KeywordsNew.cpp \
    23         Concurrency/Keywords.cc \
    2423        Concurrency/Keywords.h \
    2524        Concurrency/WaitforNew.cpp \
    26         Concurrency/Waitfor.cc \
    2725        Concurrency/Waitfor.h \
    2826        Concurrency/Waituntil.cpp \
  • src/ControlStruct/module.mk

    r790d835 rc6b4432  
    1616
    1717SRC += \
    18         ControlStruct/ExceptDecl.cc \
    1918        ControlStruct/ExceptDeclNew.cpp \
    2019        ControlStruct/ExceptDecl.h \
    2120        ControlStruct/ExceptTranslateNew.cpp \
    22         ControlStruct/ExceptTranslate.cc \
    2321        ControlStruct/ExceptTranslate.h \
    2422        ControlStruct/FixLabels.cpp \
    2523        ControlStruct/FixLabels.hpp \
    26         ControlStruct/ForExprMutator.cc \
    27         ControlStruct/ForExprMutator.h \
    2824        ControlStruct/HoistControlDecls.cpp \
    2925        ControlStruct/HoistControlDecls.hpp \
    30         ControlStruct/LabelFixer.cc \
    31         ControlStruct/LabelFixer.h \
    32         ControlStruct/LabelGenerator.cc \
    33         ControlStruct/LabelGenerator.h \
    3426        ControlStruct/LabelGeneratorNew.cpp \
    3527        ControlStruct/LabelGeneratorNew.hpp \
    36         ControlStruct/MLEMutator.cc \
    37         ControlStruct/MLEMutator.h \
    3828        ControlStruct/MultiLevelExit.cpp \
    39         ControlStruct/MultiLevelExit.hpp \
    40         ControlStruct/Mutate.cc \
    41         ControlStruct/Mutate.h
     29        ControlStruct/MultiLevelExit.hpp
    4230
  • src/GenPoly/FindFunction.cc

    r790d835 rc6b4432  
    2020#include "AST/Pass.hpp"                 // for Pass
    2121#include "AST/Type.hpp"
    22 #include "Common/PassVisitor.h"         // for PassVisitor
    2322#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::iterator
    2423#include "GenPoly/GenPoly.h"            // for TyVarMap
    2524#include "ScrubTyVars.h"                // for ScrubTyVars
    26 #include "SynTree/Declaration.h"        // for DeclarationWithType, TypeDecl
    27 #include "SynTree/Mutator.h"            // for Mutator, mutateAll
    28 #include "SynTree/Type.h"               // for FunctionType, Type, Type::For...
    2925
    3026namespace GenPoly {
    31         class FindFunction : public WithGuards, public WithVisitorRef<FindFunction>, public WithShortCircuiting {
    32           public:
    33                 FindFunction( std::list< FunctionType const* > &functions, const TyVarMap &tyVars, bool replaceMode, FindFunctionPredicate predicate );
    34 
    35                 void premutate( FunctionType * functionType );
    36                 Type * postmutate( FunctionType * functionType );
    37                 void premutate( PointerType * pointerType );
    38           private:
    39                 void handleForall( const Type::ForallList &forall );
    40 
    41                 std::list< FunctionType const * > & functions;
    42                 TyVarMap tyVars;
    43                 bool replaceMode;
    44                 FindFunctionPredicate predicate;
    45         };
    46 
    47         void findFunction( Type *type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate ) {
    48                 PassVisitor<FindFunction> finder( functions, tyVars, false, predicate );
    49                 type->acceptMutator( finder );
    50         }
    51 
    52         void findAndReplaceFunction( Type *&type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate ) {
    53                 PassVisitor<FindFunction> finder( functions, tyVars, true, predicate );
    54                 type = type->acceptMutator( finder );
    55         }
    56 
    57         FindFunction::FindFunction( std::list< FunctionType const * > &functions, const TyVarMap &tyVars, bool replaceMode, FindFunctionPredicate predicate )
    58                 : functions( functions ), tyVars( tyVars ), replaceMode( replaceMode ), predicate( predicate ) {
    59         }
    60 
    61         void FindFunction::handleForall( const Type::ForallList &forall ) {
    62                 for ( const Declaration * td : forall ) {
    63                         TyVarMap::iterator var = tyVars.find( td->name );
    64                         if ( var != tyVars.end() ) {
    65                                 tyVars.erase( var->first );
    66                         } // if
    67                 } // for
    68         }
    69 
    70         void FindFunction::premutate( FunctionType * functionType ) {
    71                 visit_children = false;
    72                 GuardScope( tyVars );
    73                 handleForall( functionType->get_forall() );
    74                 mutateAll( functionType->get_returnVals(), *visitor );
    75         }
    76 
    77         Type * FindFunction::postmutate( FunctionType * functionType ) {
    78                 Type *ret = functionType;
    79                 if ( predicate( functionType, tyVars ) ) {
    80                         functions.push_back( functionType );
    81                         if ( replaceMode ) {
    82                                 // replace type parameters in function type with void*
    83                                 ret = ScrubTyVars::scrub( functionType->clone(), tyVars );
    84                         } // if
    85                 } // if
    86                 return ret;
    87         }
    88 
    89         void FindFunction::premutate( PointerType * pointerType ) {
    90                 GuardScope( tyVars );
    91                 handleForall( pointerType->get_forall() );
    92         }
    9327
    9428namespace {
     
    15488void FindFunctionCore::previsit( ast::PointerType const * /*type*/ ) {
    15589        GuardScope( typeVars );
    156         //handleForall( type->forall );
    15790}
    15891
     
    16497        ast::Pass<FindFunctionCore> pass( functions, typeVars, predicate, false );
    16598        type->accept( pass );
    166         //(void)type;
    167         //(void)functions;
    168         //(void)typeVars;
    169         //(void)predicate;
    17099}
    171100
     
    175104        ast::Pass<FindFunctionCore> pass( functions, typeVars, predicate, true );
    176105        return type->accept( pass );
    177         //(void)functions;
    178         //(void)typeVars;
    179         //(void)predicate;
    180         //return type;
    181106}
    182107
  • src/GenPoly/FindFunction.h

    r790d835 rc6b4432  
    1616#pragma once
    1717
    18 #include <list>       // for list
    19 
    2018#include "GenPoly.h"  // for TyVarMap
    2119
    22 class FunctionType;
    23 class Type;
    24 
    2520namespace GenPoly {
    26         typedef bool (*FindFunctionPredicate)( FunctionType*, const TyVarMap& );
    27 
    28         /// recursively walk `type`, placing all functions that match `predicate` under `tyVars` into `functions`
    29         void findFunction( Type *type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate );
    30         /// like `findFunction`, but also replaces the function type with void ()(void)
    31         void findAndReplaceFunction( Type *&type, std::list< FunctionType const * > &functions, const TyVarMap &tyVars, FindFunctionPredicate predicate );
    3221
    3322typedef bool (*FindFunctionPred)( const ast::FunctionType *, const TypeVarMap & );
  • src/GenPoly/GenPoly.cc

    r790d835 rc6b4432  
    2929#include "GenPoly/ErasableScopedMap.h"  // for ErasableScopedMap<>::const_it...
    3030#include "ResolvExpr/typeops.h"         // for flatten
    31 #include "SynTree/Constant.h"           // for Constant
    32 #include "SynTree/Expression.h"         // for Expression, TypeExpr, Constan...
    33 #include "SynTree/Type.h"               // for Type, StructInstType, UnionIn...
    34 #include "SynTree/TypeSubstitution.h"   // for TypeSubstitution
    3531
    3632using namespace std;
     
    3935        namespace {
    4036                /// Checks a parameter list for polymorphic parameters; will substitute according to env if present
    41                 bool hasPolyParams( std::list< Expression* >& params, const TypeSubstitution *env ) {
    42                         for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
    43                                 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
    44                                 assertf(paramType, "Aggregate parameters should be type expressions");
    45                                 if ( isPolyType( paramType->get_type(), env ) ) return true;
    46                         }
    47                         return false;
    48                 }
    49 
    5037                bool hasPolyParams( const std::vector<ast::ptr<ast::Expr>> & params, const ast::TypeSubstitution * env ) {
    5138                        for ( auto &param : params ) {
     
    5845
    5946                /// Checks a parameter list for polymorphic parameters from tyVars; will substitute according to env if present
    60                 bool hasPolyParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {
    61                         for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
    62                                 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
    63                                 assertf(paramType, "Aggregate parameters should be type expressions");
    64                                 if ( isPolyType( paramType->get_type(), tyVars, env ) ) return true;
    65                         }
    66                         return false;
    67                 }
    68 
    6947                bool hasPolyParams( const std::vector<ast::ptr<ast::Expr>> & params, const TypeVarMap & typeVars, const ast::TypeSubstitution * env ) {
    7048                        for ( auto & param : params ) {
     
    7755
    7856                /// Checks a parameter list for dynamic-layout parameters from tyVars; will substitute according to env if present
    79                 bool hasDynParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {
    80                         for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
    81                                 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
    82                                 assertf(paramType, "Aggregate parameters should be type expressions");
    83                                 if ( isDynType( paramType->get_type(), tyVars, env ) ) return true;
    84                         }
    85                         return false;
    86                 }
    87 
    8857                bool hasDynParams(
    8958                                const std::vector<ast::ptr<ast::Expr>> & params,
     
    9968                        return false;
    10069                }
    101 
    102                 /// Checks a parameter list for inclusion of polymorphic parameters; will substitute according to env if present
    103                 bool includesPolyParams( std::list< Expression* >& params, const TypeSubstitution *env ) {
    104                         for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
    105                                 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
    106                                 assertf(paramType, "Aggregate parameters should be type expressions");
    107                                 if ( includesPolyType( paramType->get_type(), env ) ) return true;
    108                         }
    109                         return false;
    110                 }
    111 
    112                 /// Checks a parameter list for inclusion of polymorphic parameters from tyVars; will substitute according to env if present
    113                 bool includesPolyParams( std::list< Expression* >& params, const TyVarMap &tyVars, const TypeSubstitution *env ) {
    114                         for ( std::list< Expression* >::iterator param = params.begin(); param != params.end(); ++param ) {
    115                                 TypeExpr *paramType = dynamic_cast< TypeExpr* >( *param );
    116                                 assertf(paramType, "Aggregate parameters should be type expressions");
    117                                 if ( includesPolyType( paramType->get_type(), tyVars, env ) ) return true;
    118                         }
    119                         return false;
    120                 }
    121         }
    122 
    123         Type* replaceTypeInst( Type* type, const TypeSubstitution* env ) {
    124                 if ( ! env ) return type;
    125                 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType* >( type ) ) {
    126                         Type *newType = env->lookup( typeInst->get_name() );
    127                         if ( newType ) return newType;
    128                 }
    129                 return type;
    130         }
    131 
    132         const Type* replaceTypeInst( const Type* type, const TypeSubstitution* env ) {
    133                 if ( ! env ) return type;
    134                 if ( auto typeInst = dynamic_cast< const TypeInstType* >( type ) ) {
    135                         Type *newType = env->lookup( typeInst->get_name() );
    136                         if ( newType ) return newType;
    137                 }
    138                 return type;
    13970        }
    14071
     
    14677                }
    14778                return type;
    148         }
    149 
    150         Type *isPolyType( Type *type, const TypeSubstitution *env ) {
    151                 type = replaceTypeInst( type, env );
    152 
    153                 if ( dynamic_cast< TypeInstType * >( type ) ) {
    154                         return type;
    155                 } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
    156                         return isPolyType( arrayType->base, env );
    157                 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
    158                         if ( hasPolyParams( structType->get_parameters(), env ) ) return type;
    159                 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
    160                         if ( hasPolyParams( unionType->get_parameters(), env ) ) return type;
    161                 }
    162                 return 0;
    16379        }
    16480
     
    17894        }
    17995
    180         Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
    181                 type = replaceTypeInst( type, env );
    182 
    183                 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
    184                         if ( tyVars.contains( typeInst->get_name() ) ) {
    185                                 return type;
    186                         }
    187                 } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
    188                         return isPolyType( arrayType->base, tyVars, env );
    189                 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
    190                         if ( hasPolyParams( structType->get_parameters(), tyVars, env ) ) return type;
    191                 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
    192                         if ( hasPolyParams( unionType->get_parameters(), tyVars, env ) ) return type;
    193                 }
    194                 return 0;
    195         }
    196 
    19796const ast::Type * isPolyType( const ast::Type * type,
    19897                const TypeVarMap & typeVars, const ast::TypeSubstitution * subst ) {
     
    211110}
    212111
    213         ReferenceToType *isDynType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
    214                 type = replaceTypeInst( type, env );
    215 
    216                 if ( TypeInstType *typeInst = dynamic_cast< TypeInstType * >( type ) ) {
    217                         auto var = tyVars.find( typeInst->get_name() );
    218                         if ( var != tyVars.end() && var->second.isComplete ) {
    219                                 return typeInst;
    220                         }
    221                 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
    222                         if ( hasDynParams( structType->get_parameters(), tyVars, env ) ) return structType;
    223                 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
    224                         if ( hasDynParams( unionType->get_parameters(), tyVars, env ) ) return unionType;
    225                 }
    226                 return 0;
    227         }
    228 
    229112const ast::BaseInstType * isDynType(
    230113                const ast::Type * type, const TypeVarMap & typeVars,
     
    249132}
    250133
    251         ReferenceToType *isDynRet( FunctionType *function, const TyVarMap &forallTypes ) {
    252                 if ( function->get_returnVals().empty() ) return 0;
    253 
    254                 return (ReferenceToType*)isDynType( function->get_returnVals().front()->get_type(), forallTypes );
    255         }
    256 
    257134const ast::BaseInstType *isDynRet(
    258135                const ast::FunctionType * type, const TypeVarMap & typeVars ) {
     
    262139}
    263140
    264         ReferenceToType *isDynRet( FunctionType *function ) {
    265                 if ( function->get_returnVals().empty() ) return 0;
    266 
    267                 TyVarMap forallTypes( TypeDecl::Data{} );
    268                 makeTyVarMap( function, forallTypes );
    269                 return (ReferenceToType*)isDynType( function->get_returnVals().front()->get_type(), forallTypes );
    270         }
    271 
    272141const ast::BaseInstType *isDynRet( const ast::FunctionType * func ) {
    273142        if ( func->returns.empty() ) return nullptr;
     
    278147}
    279148
    280         bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVars ) {
    281 //              if ( ! adaptee->get_returnVals().empty() && isPolyType( adaptee->get_returnVals().front()->get_type(), tyVars ) ) {
    282 //                      return true;
    283 //              } // if
    284                 if ( isDynRet( adaptee, tyVars ) ) return true;
    285 
    286                 for ( std::list< DeclarationWithType* >::const_iterator innerArg = adaptee->get_parameters().begin(); innerArg != adaptee->get_parameters().end(); ++innerArg ) {
    287 //                      if ( isPolyType( (*innerArg)->get_type(), tyVars ) ) {
    288                         if ( isDynType( (*innerArg)->get_type(), tyVars ) ) {
    289                                 return true;
    290                         } // if
    291                 } // for
    292                 return false;
    293         }
    294 
    295149bool needsAdapter(
    296150                ast::FunctionType const * adaptee, const TypeVarMap & typeVars ) {
     
    304158        return false;
    305159}
    306 
    307         Type *isPolyPtr( Type *type, const TypeSubstitution *env ) {
    308                 type = replaceTypeInst( type, env );
    309 
    310                 if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
    311                         return isPolyType( ptr->get_base(), env );
    312                 }
    313                 return 0;
    314         }
    315 
    316         Type *isPolyPtr( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
    317                 type = replaceTypeInst( type, env );
    318 
    319                 if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
    320                         return isPolyType( ptr->get_base(), tyVars, env );
    321                 }
    322                 return 0;
    323         }
    324160
    325161const ast::Type * isPolyPtr(
     
    333169        return nullptr;
    334170}
    335 
    336         Type * hasPolyBase( Type *type, int *levels, const TypeSubstitution *env ) {
    337                 int dummy;
    338                 if ( ! levels ) { levels = &dummy; }
    339                 *levels = 0;
    340 
    341                 while ( true ) {
    342                         type = replaceTypeInst( type, env );
    343 
    344                         if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
    345                                 type = ptr->get_base();
    346                                 ++(*levels);
    347                         } else break;
    348                 }
    349 
    350                 return isPolyType( type, env );
    351         }
    352 
    353         Type * hasPolyBase( Type *type, const TyVarMap &tyVars, int *levels, const TypeSubstitution *env ) {
    354                 int dummy;
    355                 if ( ! levels ) { levels = &dummy; }
    356                 *levels = 0;
    357 
    358                 while ( true ) {
    359                         type = replaceTypeInst( type, env );
    360 
    361                         if ( PointerType *ptr = dynamic_cast< PointerType *>( type ) ) {
    362                                 type = ptr->get_base();
    363                                 ++(*levels);
    364                         } else break;
    365                 }
    366 
    367                 return isPolyType( type, tyVars, env );
    368         }
    369171
    370172ast::Type const * hasPolyBase(
     
    388190}
    389191
    390         bool includesPolyType( Type *type, const TypeSubstitution *env ) {
    391                 type = replaceTypeInst( type, env );
    392 
    393                 if ( dynamic_cast< TypeInstType * >( type ) ) {
    394                         return true;
    395                 } else if ( PointerType *pointerType = dynamic_cast< PointerType* >( type ) ) {
    396                         if ( includesPolyType( pointerType->get_base(), env ) ) return true;
    397                 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
    398                         if ( includesPolyParams( structType->get_parameters(), env ) ) return true;
    399                 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
    400                         if ( includesPolyParams( unionType->get_parameters(), env ) ) return true;
    401                 }
    402                 return false;
    403         }
    404 
    405         bool includesPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env ) {
    406                 type = replaceTypeInst( type, env );
    407 
    408                 if ( TypeInstType *typeInstType = dynamic_cast< TypeInstType * >( type ) ) {
    409                         if ( tyVars.contains( typeInstType->get_name() ) ) {
    410                                 return true;
    411                         }
    412                 } else if ( PointerType *pointerType = dynamic_cast< PointerType* >( type ) ) {
    413                         if ( includesPolyType( pointerType->get_base(), tyVars, env ) ) return true;
    414                 } else if ( StructInstType *structType = dynamic_cast< StructInstType* >( type ) ) {
    415                         if ( includesPolyParams( structType->get_parameters(), tyVars, env ) ) return true;
    416                 } else if ( UnionInstType *unionType = dynamic_cast< UnionInstType* >( type ) ) {
    417                         if ( includesPolyParams( unionType->get_parameters(), tyVars, env ) ) return true;
    418                 }
    419                 return false;
    420         }
    421 
    422         FunctionType * getFunctionType( Type *ty ) {
    423                 PointerType *ptrType;
    424                 if ( ( ptrType = dynamic_cast< PointerType* >( ty ) ) ) {
    425                         return dynamic_cast< FunctionType* >( ptrType->get_base() ); // pointer if FunctionType, NULL otherwise
    426                 } else {
    427                         return dynamic_cast< FunctionType* >( ty ); // pointer if FunctionType, NULL otherwise
    428                 }
    429         }
    430 
    431192        const ast::FunctionType * getFunctionType( const ast::Type * ty ) {
    432193                if ( auto pty = dynamic_cast< const ast::PointerType * >( ty ) ) {
     
    437198        }
    438199
    439         VariableExpr * getBaseVar( Expression *expr, int *levels ) {
    440                 int dummy;
    441                 if ( ! levels ) { levels = &dummy; }
    442                 *levels = 0;
    443 
    444                 while ( true ) {
    445                         if ( VariableExpr *varExpr = dynamic_cast< VariableExpr* >( expr ) ) {
    446                                 return varExpr;
    447                         } else if ( MemberExpr *memberExpr = dynamic_cast< MemberExpr* >( expr ) ) {
    448                                 expr = memberExpr->get_aggregate();
    449                         } else if ( AddressExpr *addressExpr = dynamic_cast< AddressExpr* >( expr ) ) {
    450                                 expr = addressExpr->get_arg();
    451                         } else if ( UntypedExpr *untypedExpr = dynamic_cast< UntypedExpr* >( expr ) ) {
    452                                 // look for compiler-inserted dereference operator
    453                                 NameExpr *fn = dynamic_cast< NameExpr* >( untypedExpr->get_function() );
    454                                 if ( ! fn || fn->get_name() != std::string("*?") ) return 0;
    455                                 expr = *untypedExpr->begin_args();
    456                         } else if ( CommaExpr *commaExpr = dynamic_cast< CommaExpr* >( expr ) ) {
    457                                 // copy constructors insert comma exprs, look at second argument which contains the variable
    458                                 expr = commaExpr->get_arg2();
    459                                 continue;
    460                         } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( expr ) ) {
    461                                 int lvl1;
    462                                 int lvl2;
    463                                 VariableExpr * var1 = getBaseVar( condExpr->get_arg2(), &lvl1 );
    464                                 VariableExpr * var2 = getBaseVar( condExpr->get_arg3(), &lvl2 );
    465                                 if ( lvl1 == lvl2 && var1 && var2 && var1->get_var() == var2->get_var() ) {
    466                                         *levels = lvl1;
    467                                         return var1;
    468                                 }
    469                                 break;
    470                         } else break;
    471 
    472                         ++(*levels);
    473                 }
    474 
    475                 return 0;
    476         }
    477 
    478200        namespace {
    479201                /// Checks if is a pointer to D
     
    488210                inline D const * as( B const * p ) {
    489211                        return reinterpret_cast<D const *>( p );
    490                 }
    491 
    492                 /// Flattens a declaration list
    493                 template<typename Output>
    494                 void flattenList( list< DeclarationWithType* > src, Output out ) {
    495                         for ( DeclarationWithType* decl : src ) {
    496                                 ResolvExpr::flatten( decl->get_type(), out );
    497                         }
    498                 }
    499 
    500                 /// Flattens a list of types
    501                 template<typename Output>
    502                 void flattenList( list< Type* > src, Output out ) {
    503                         for ( Type* ty : src ) {
    504                                 ResolvExpr::flatten( ty, out );
    505                         }
    506212                }
    507213
     
    515221                }
    516222
    517                 /// Checks if two lists of parameters are equal up to polymorphic substitution.
    518                 bool paramListsPolyCompatible( const list< Expression* >& aparams, const list< Expression* >& bparams ) {
    519                         if ( aparams.size() != bparams.size() ) return false;
    520 
    521                         for ( list< Expression* >::const_iterator at = aparams.begin(), bt = bparams.begin();
    522                                         at != aparams.end(); ++at, ++bt ) {
    523                                 TypeExpr *aparam = dynamic_cast< TypeExpr* >(*at);
    524                                 assertf(aparam, "Aggregate parameters should be type expressions");
    525                                 TypeExpr *bparam = dynamic_cast< TypeExpr* >(*bt);
    526                                 assertf(bparam, "Aggregate parameters should be type expressions");
    527 
    528                                 // xxx - might need to let VoidType be a wildcard here too; could have some voids
    529                                 // stuffed in for dtype-statics.
    530                                 // if ( is<VoidType>( aparam->get_type() ) || is<VoidType>( bparam->get_type() ) ) continue;
    531                                 if ( ! typesPolyCompatible( aparam->get_type(), bparam->get_type() ) ) return false;
    532                         }
    533 
    534                         return true;
    535                 }
    536 
    537223                bool paramListsPolyCompatible(
    538224                                std::vector<ast::ptr<ast::Expr>> const & lparams,
     
    559245                        return true;
    560246                }
    561         }
    562 
    563         bool typesPolyCompatible( Type *a, Type *b ) {
    564                 type_index aid{ typeid(*a) };
    565                 // polymorphic types always match
    566                 if ( aid == type_index{typeid(TypeInstType)} ) return true;
    567 
    568                 type_index bid{ typeid(*b) };
    569                 // polymorphic types always match
    570                 if ( bid == type_index{typeid(TypeInstType)} ) return true;
    571 
    572                 // can't match otherwise if different types
    573                 if ( aid != bid ) return false;
    574 
    575                 // recurse through type structure (conditions borrowed from Unify.cc)
    576                 if ( aid == type_index{typeid(BasicType)} ) {
    577                         return as<BasicType>(a)->get_kind() == as<BasicType>(b)->get_kind();
    578                 } else if ( aid == type_index{typeid(PointerType)} ) {
    579                         PointerType *ap = as<PointerType>(a), *bp = as<PointerType>(b);
    580 
    581                         // void pointers should match any other pointer type
    582                         return is<VoidType>( ap->get_base() ) || is<VoidType>( bp->get_base() )
    583                                 || typesPolyCompatible( ap->get_base(), bp->get_base() );
    584                 } else if ( aid == type_index{typeid(ReferenceType)} ) {
    585                         ReferenceType *ap = as<ReferenceType>(a), *bp = as<ReferenceType>(b);
    586                         return is<VoidType>( ap->get_base() ) || is<VoidType>( bp->get_base() )
    587                                 || typesPolyCompatible( ap->get_base(), bp->get_base() );
    588                 } else if ( aid == type_index{typeid(ArrayType)} ) {
    589                         ArrayType *aa = as<ArrayType>(a), *ba = as<ArrayType>(b);
    590 
    591                         if ( aa->get_isVarLen() ) {
    592                                 if ( ! ba->get_isVarLen() ) return false;
    593                         } else {
    594                                 if ( ba->get_isVarLen() ) return false;
    595 
    596                                 ConstantExpr *ad = dynamic_cast<ConstantExpr*>( aa->get_dimension() );
    597                                 ConstantExpr *bd = dynamic_cast<ConstantExpr*>( ba->get_dimension() );
    598                                 if ( ad && bd
    599                                                 && ad->get_constant()->get_value() != bd->get_constant()->get_value() )
    600                                         return false;
    601                         }
    602 
    603                         return typesPolyCompatible( aa->get_base(), ba->get_base() );
    604                 } else if ( aid == type_index{typeid(FunctionType)} ) {
    605                         FunctionType *af = as<FunctionType>(a), *bf = as<FunctionType>(b);
    606 
    607                         vector<Type*> aparams, bparams;
    608                         flattenList( af->get_parameters(), back_inserter( aparams ) );
    609                         flattenList( bf->get_parameters(), back_inserter( bparams ) );
    610                         if ( aparams.size() != bparams.size() ) return false;
    611 
    612                         vector<Type*> areturns, breturns;
    613                         flattenList( af->get_returnVals(), back_inserter( areturns ) );
    614                         flattenList( bf->get_returnVals(), back_inserter( breturns ) );
    615                         if ( areturns.size() != breturns.size() ) return false;
    616 
    617                         for ( unsigned i = 0; i < aparams.size(); ++i ) {
    618                                 if ( ! typesPolyCompatible( aparams[i], bparams[i] ) ) return false;
    619                         }
    620                         for ( unsigned i = 0; i < areturns.size(); ++i ) {
    621                                 if ( ! typesPolyCompatible( areturns[i], breturns[i] ) ) return false;
    622                         }
    623                         return true;
    624                 } else if ( aid == type_index{typeid(StructInstType)} ) {
    625                         StructInstType *aa = as<StructInstType>(a), *ba = as<StructInstType>(b);
    626 
    627                         if ( aa->get_name() != ba->get_name() ) return false;
    628                         return paramListsPolyCompatible( aa->get_parameters(), ba->get_parameters() );
    629                 } else if ( aid == type_index{typeid(UnionInstType)} ) {
    630                         UnionInstType *aa = as<UnionInstType>(a), *ba = as<UnionInstType>(b);
    631 
    632                         if ( aa->get_name() != ba->get_name() ) return false;
    633                         return paramListsPolyCompatible( aa->get_parameters(), ba->get_parameters() );
    634                 } else if ( aid == type_index{typeid(EnumInstType)} ) {
    635                         return as<EnumInstType>(a)->get_name() == as<EnumInstType>(b)->get_name();
    636                 } else if ( aid == type_index{typeid(TraitInstType)} ) {
    637                         return as<TraitInstType>(a)->get_name() == as<TraitInstType>(b)->get_name();
    638                 } else if ( aid == type_index{typeid(TupleType)} ) {
    639                         TupleType *at = as<TupleType>(a), *bt = as<TupleType>(b);
    640 
    641                         vector<Type*> atypes, btypes;
    642                         flattenList( at->get_types(), back_inserter( atypes ) );
    643                         flattenList( bt->get_types(), back_inserter( btypes ) );
    644                         if ( atypes.size() != btypes.size() ) return false;
    645 
    646                         for ( unsigned i = 0; i < atypes.size(); ++i ) {
    647                                 if ( ! typesPolyCompatible( atypes[i], btypes[i] ) ) return false;
    648                         }
    649                         return true;
    650                 } else return true; // VoidType, VarArgsType, ZeroType & OneType just need the same type
    651247        }
    652248
     
    763359}
    764360
    765         bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env ) {
    766                 // is parameter is not polymorphic, don't need to box
    767                 if ( ! isPolyType( param, exprTyVars ) ) return false;
    768                 Type * newType = arg->clone();
    769                 if ( env ) env->apply( newType );
    770                 std::unique_ptr<Type> manager( newType );
    771                 // if the argument's type is polymorphic, we don't need to box again!
    772                 return ! isPolyType( newType );
    773         }
    774 
    775361bool needsBoxing( const ast::Type * param, const ast::Type * arg,
    776362                const TypeVarMap & typeVars, const ast::TypeSubstitution * subst ) {
     
    786372        return !isPolyType( newType );
    787373}
    788 
    789         bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env ) {
    790                 FunctionType * function = getFunctionType( appExpr->function->result );
    791                 assertf( function, "ApplicationExpr has non-function type: %s", toString( appExpr->function->result ).c_str() );
    792                 TyVarMap exprTyVars( TypeDecl::Data{} );
    793                 makeTyVarMap( function, exprTyVars );
    794                 return needsBoxing( param, arg, exprTyVars, env );
    795         }
    796374
    797375bool needsBoxing(
     
    806384}
    807385
    808         void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap ) {
    809                 tyVarMap.insert( tyVar->name, TypeDecl::Data{ tyVar } );
    810         }
    811 
    812386void addToTypeVarMap( const ast::TypeDecl * decl, TypeVarMap & typeVars ) {
    813387        typeVars.insert( ast::TypeEnvKey( decl, 0, 0 ), ast::TypeData( decl ) );
     
    817391        typeVars.insert( ast::TypeEnvKey( *type ), ast::TypeData( type->base ) );
    818392}
    819 
    820         void makeTyVarMap( Type *type, TyVarMap &tyVarMap ) {
    821                 for ( Type::ForallList::const_iterator tyVar = type->get_forall().begin(); tyVar != type->get_forall().end(); ++tyVar ) {
    822                         assert( *tyVar );
    823                         addToTyVarMap( *tyVar, tyVarMap );
    824                 }
    825                 if ( PointerType *pointer = dynamic_cast< PointerType* >( type ) ) {
    826                         makeTyVarMap( pointer->get_base(), tyVarMap );
    827                 }
    828         }
    829393
    830394void makeTypeVarMap( const ast::Type * type, TypeVarMap & typeVars ) {
     
    846410}
    847411
    848         void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap ) {
    849                 for ( TyVarMap::const_iterator i = tyVarMap.begin(); i != tyVarMap.end(); ++i ) {
    850                         os << i->first << " (" << i->second << ") ";
    851                 } // for
    852                 os << std::endl;
    853         }
    854 
    855412} // namespace GenPoly
    856413
  • src/GenPoly/GenPoly.h

    r790d835 rc6b4432  
    2323#include "AST/Fwd.hpp"            // for ApplicationExpr, BaseInstType, Func...
    2424#include "SymTab/Mangler.h"       // for Mangler
    25 #include "SynTree/Declaration.h"  // for TypeDecl::Data, AggregateDecl, Type...
    26 #include "SynTree/SynTree.h"      // for Visitor Nodes
    2725
    2826namespace ast {
     
    3230namespace GenPoly {
    3331
    34         typedef ErasableScopedMap< std::string, TypeDecl::Data > TyVarMap;
    3532        struct TypeVarMap : public ErasableScopedMap<ast::TypeEnvKey, ast::TypeData> {
    3633                TypeVarMap() : ErasableScopedMap( ast::TypeData() ) {}
     
    3835
    3936        /// Replaces a TypeInstType by its referrent in the environment, if applicable
    40         Type* replaceTypeInst( Type* type, const TypeSubstitution* env );
    41         const Type* replaceTypeInst( const Type* type, const TypeSubstitution* env );
    4237        const ast::Type * replaceTypeInst( const ast::Type *, const ast::TypeSubstitution * );
    4338
    4439        /// returns polymorphic type if is polymorphic type, NULL otherwise; will look up substitution in env if provided
    45         Type *isPolyType( Type *type, const TypeSubstitution *env = 0 );
    4640        const ast::Type * isPolyType(const ast::Type * type, const ast::TypeSubstitution * env = nullptr);
    4741
    4842        /// returns polymorphic type if is polymorphic type in tyVars, NULL otherwise; will look up substitution in env if provided
    49         Type *isPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
    5043        const ast::Type * isPolyType( const ast::Type * type, const TypeVarMap & typeVars, const ast::TypeSubstitution * subst = nullptr );
    5144
    5245        /// returns dynamic-layout type if is dynamic-layout type in tyVars, NULL otherwise; will look up substitution in env if provided
    53         ReferenceToType *isDynType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
    5446        const ast::BaseInstType *isDynType( const ast::Type * type, const TypeVarMap & typeVars, const ast::TypeSubstitution * subst = 0 );
    5547
    5648        /// true iff function has dynamic-layout return type under the given type variable map
    57         ReferenceToType *isDynRet( FunctionType *function, const TyVarMap &tyVars );
    5849        const ast::BaseInstType *isDynRet( const ast::FunctionType * type, const TypeVarMap & typeVars );
    5950
    6051        /// true iff function has dynamic-layout return type under the type variable map generated from its forall-parameters
    61         ReferenceToType *isDynRet( FunctionType *function );
    6252        const ast::BaseInstType *isDynRet( const ast::FunctionType * func );
    6353
    6454        /// A function needs an adapter if it returns a dynamic-layout value or if any of its parameters have dynamic-layout type
    65         bool needsAdapter( FunctionType *adaptee, const TyVarMap &tyVarr );
    6655        bool needsAdapter( ast::FunctionType const * adaptee, const TypeVarMap & typeVars );
    6756
    68         /// returns polymorphic type if is pointer to polymorphic type, NULL otherwise; will look up substitution in env if provided
    69         Type *isPolyPtr( Type *type, const TypeSubstitution *env = 0 );
    70 
    7157        /// returns polymorphic type if is pointer to polymorphic type in tyVars, NULL otherwise; will look up substitution in env if provided
    72         Type *isPolyPtr( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
    7358        const ast::Type * isPolyPtr( const ast::Type * type, const TypeVarMap & typeVars, const ast::TypeSubstitution * env = 0 );
    74 
    75         /// if the base type (after dereferencing N >= 0 pointers) is a polymorphic type, returns the base type, NULL otherwise;
    76         /// N will be stored in levels, if provided, will look up substitution in env if provided
    77         Type *hasPolyBase( Type *type, int *levels = 0, const TypeSubstitution *env = 0 );
    7859
    7960        /// if the base type (after dereferencing N >= 0 pointers) is a polymorphic type in tyVars, returns the base type, NULL otherwise;
    8061        /// N will be stored in levels, if provided, will look up substitution in env if provided
    81         Type *hasPolyBase( Type *type, const TyVarMap &tyVars, int *levels = 0, const TypeSubstitution *env = 0 );
    8262        const ast::Type * hasPolyBase( const ast::Type * type, const TypeVarMap & typeVars, int * levels = 0, const ast::TypeSubstitution * env = 0 );
    8363
    84         /// true iff this type or some base of this type after dereferencing pointers is either polymorphic or a generic type with at least one
    85         /// polymorphic parameter; will look up substitution in env if provided.
    86         bool includesPolyType( Type *type, const TypeSubstitution *env = 0 );
    87 
    88         /// true iff this type or some base of this type after dereferencing pointers is either polymorphic in tyVars, or a generic type with
    89         /// at least one polymorphic parameter in tyVars; will look up substitution in env if provided.
    90         bool includesPolyType( Type *type, const TyVarMap &tyVars, const TypeSubstitution *env = 0 );
    91 
    9264        /// Returns a pointer to the base FunctionType if ty is the type of a function (or pointer to one), NULL otherwise
    93         FunctionType *getFunctionType( Type *ty );
    9465        const ast::FunctionType * getFunctionType( const ast::Type * ty );
    9566
    96         /// If expr (after dereferencing N >= 0 pointers) is a variable expression, returns the variable expression, NULL otherwise;
    97         /// N will be stored in levels, if provided
    98         VariableExpr *getBaseVar( Expression *expr, int *levels = 0 );
    99 
    10067        /// true iff types are structurally identical, where TypeInstType's match any type.
    101         bool typesPolyCompatible( Type *aty, Type *bty );
    10268        bool typesPolyCompatible( ast::Type const * lhs, ast::Type const * rhs );
    10369
    10470        /// true if arg requires boxing given exprTyVars
    105         bool needsBoxing( Type * param, Type * arg, const TyVarMap &exprTyVars, const TypeSubstitution * env );
    10671        bool needsBoxing( const ast::Type * param, const ast::Type * arg, const TypeVarMap & typeVars, const ast::TypeSubstitution * subst );
    10772
    10873        /// true if arg requires boxing in the call to appExpr
    109         bool needsBoxing( Type * param, Type * arg, ApplicationExpr * appExpr, const TypeSubstitution * env );
    11074        bool needsBoxing( const ast::Type * param, const ast::Type * arg, const ast::ApplicationExpr * expr, const ast::TypeSubstitution * subst );
    11175
    11276        /// Adds the type variable `tyVar` to `tyVarMap`
    113         void addToTyVarMap( TypeDecl * tyVar, TyVarMap &tyVarMap );
    11477        void addToTypeVarMap( const ast::TypeDecl * type, TypeVarMap & typeVars );
    11578        void addToTypeVarMap( const ast::TypeInstType * type, TypeVarMap & typeVars );
    11679
    11780        /// Adds the declarations in the forall list of type (and its pointed-to type if it's a pointer type) to `tyVarMap`
    118         void makeTyVarMap( Type *type, TyVarMap &tyVarMap );
    11981        void makeTypeVarMap( const ast::Type * type, TypeVarMap & typeVars );
    12082        void makeTypeVarMap( const ast::FunctionDecl * decl, TypeVarMap & typeVars );
    121 
    122         /// Prints type variable map
    123         void printTyVarMap( std::ostream &os, const TyVarMap &tyVarMap );
    124 
    125         /// Gets the mangled name of this type; alias for SymTab::Mangler::mangleType().
    126         inline std::string mangleType( const Type *ty ) { return SymTab::Mangler::mangleType( ty ); }
    12783
    12884        /// Gets the name of the sizeof parameter for the type, given its mangled name
     
    13692
    13793        /// Gets the name of the layout function for a given aggregate type, given its declaration
    138         inline std::string layoutofName( AggregateDecl *decl ) { return std::string( "_layoutof_" ) + decl->get_name(); }
    13994        inline std::string layoutofName( ast::AggregateDecl const * decl ) {
    14095                return std::string( "_layoutof_" ) + decl->name;
  • src/GenPoly/ScrubTyVars.cc

    r790d835 rc6b4432  
    2121#include "ScrubTyVars.h"
    2222#include "SymTab/Mangler.h"             // for mangleType
    23 #include "SynTree/Declaration.h"        // for TypeDecl, TypeDecl::Data, Typ...
    24 #include "SynTree/Expression.h"         // for Expression (ptr only), NameExpr
    25 #include "SynTree/Mutator.h"            // for Mutator
    26 #include "SynTree/Type.h"               // for PointerType, TypeInstType, Type
    2723
    2824namespace GenPoly {
    29         Type * ScrubTyVars::postmutate( TypeInstType * typeInst ) {
    30                 if ( ! tyVars ) {
    31                         if ( typeInst->get_isFtype() ) {
    32                                 delete typeInst;
    33                                 return new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
    34                         } else {
    35                                 PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) );
    36                                 delete typeInst;
    37                                 return ret;
    38                         }
    39                 }
    40 
    41                 TyVarMap::const_iterator tyVar = tyVars->find( typeInst->name );
    42                 if ( tyVar != tyVars->end() ) {
    43                         switch ( tyVar->second.kind ) {
    44                           case TypeDecl::Dtype:
    45                           case TypeDecl::Ttype:
    46                                 {
    47                                         PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( typeInst->get_qualifiers() ) );
    48                                         delete typeInst;
    49                                         return ret;
    50                                 }
    51                           case TypeDecl::Ftype:
    52                                 delete typeInst;
    53                                 return new PointerType( Type::Qualifiers(), new FunctionType( Type::Qualifiers(), true ) );
    54                           default:
    55                                 assertf(false, "Unhandled tyvar kind: %d", tyVar->second.kind);
    56                         } // switch
    57                 } // if
    58                 return typeInst;
    59         }
    60 
    61         Type * ScrubTyVars::mutateAggregateType( Type * ty ) {
    62                 if ( shouldScrub( ty ) ) {
    63                         PointerType * ret = new PointerType( Type::Qualifiers(), new VoidType( ty->get_qualifiers() ) );
    64                         delete ty;
    65                         return ret;
    66                 }
    67                 return ty;
    68         }
    69 
    70         Type * ScrubTyVars::postmutate( StructInstType * structInst ) {
    71                 return mutateAggregateType( structInst );
    72         }
    73 
    74         Type * ScrubTyVars::postmutate( UnionInstType * unionInst ) {
    75                 return mutateAggregateType( unionInst );
    76         }
    77 
    78         void ScrubTyVars::primeBaseScrub( Type * type ) {
    79                 // need to determine whether type needs to be scrubbed to determine whether
    80                 // automatic recursion is necessary
    81                 if ( Type * t = shouldScrub( type ) ) {
    82                         visit_children = false;
    83                         GuardValue( dynType );
    84                         dynType = t;
    85                 }
    86         }
    87 
    88         Expression * ScrubTyVars::postmutate( SizeofExpr * szeof ) {
    89                 // sizeof( T ) => _sizeof_T parameter, which is the size of T
    90                 if ( dynType ) {
    91                         Expression *expr = new NameExpr( sizeofName( mangleType( dynType ) ) );
    92                         return expr;
    93                 } // if
    94                 return szeof;
    95         }
    96 
    97         Expression * ScrubTyVars::postmutate( AlignofExpr * algnof ) {
    98                 // alignof( T ) => _alignof_T parameter, which is the alignment of T
    99                 if ( dynType ) {
    100                         Expression *expr = new NameExpr( alignofName( mangleType( dynType ) ) );
    101                         return expr;
    102                 } // if
    103                 return algnof;
    104         }
    105 
    106         Type * ScrubTyVars::postmutate( PointerType * pointer ) {
    107                 if ( dynType ) {
    108                         Type * ret = dynType->acceptMutator( *visitor );
    109                         ret->get_qualifiers() |= pointer->get_qualifiers();
    110                         pointer->base = nullptr;
    111                         delete pointer;
    112                         return ret;
    113                 }
    114                 return pointer;
    115         }
    11625
    11726namespace {
  • src/GenPoly/ScrubTyVars.h

    r790d835 rc6b4432  
    1919
    2020#include "AST/Fwd.hpp"        // for Node
    21 #include "Common/PassVisitor.h"
    2221#include "GenPoly.h"          // for TyVarMap, isPolyType, isDynType
    23 #include "SynTree/Mutator.h"  // for Mutator
    24 #include "SynTree/Type.h"     // for Type (ptr only), PointerType (ptr only)
    25 
    26 class AlignofExpr;
    27 class Expression;
    28 class SizeofExpr;
    2922
    3023namespace GenPoly {
    31         struct ScrubTyVars : public WithVisitorRef<ScrubTyVars>, public WithShortCircuiting, public WithGuards {
    32                 /// Whether to scrub all type variables from the provided map, dynamic type variables from the provided map, or all type variables
    33                 enum ScrubMode { FromMap, DynamicFromMap, All };
    34 
    35                 ScrubTyVars() : tyVars(nullptr), mode( All ) {}
    36 
    37                 ScrubTyVars( const TyVarMap &tyVars, ScrubMode mode = FromMap ): tyVars( &tyVars ), mode( mode ) {}
    38 
    39         public:
    40                 /// For all polymorphic types with type variables in `tyVars`, replaces generic types, dtypes, and ftypes with the appropriate void type,
    41                 /// and sizeof/alignof expressions with the proper variable
    42                 template< typename SynTreeClass >
    43                 static SynTreeClass *scrub( SynTreeClass *target, const TyVarMap &tyVars );
    44 
    45                 /// For all dynamic-layout types with type variables in `tyVars`, replaces generic types, dtypes, and ftypes with the appropriate void type,
    46                 /// and sizeof/alignof expressions with the proper variable
    47                 template< typename SynTreeClass >
    48                 static SynTreeClass *scrubDynamic( SynTreeClass *target, const TyVarMap &tyVars );
    49 
    50                 /// For all polymorphic types, replaces generic types, dtypes, and ftypes with the appropriate void type,
    51                 /// and sizeof/alignof expressions with the proper variable
    52                 template< typename SynTreeClass >
    53                 static SynTreeClass *scrubAll( SynTreeClass *target );
    54 
    55                 /// determine if children should be visited based on whether base type should be scrubbed.
    56                 void primeBaseScrub( Type * );
    57 
    58                 void premutate( TypeInstType * ) { visit_children = false; }
    59                 void premutate( StructInstType * ) { visit_children = false; }
    60                 void premutate( UnionInstType * ) { visit_children = false; }
    61                 void premutate( SizeofExpr * szeof ) { primeBaseScrub( szeof->type ); }
    62                 void premutate( AlignofExpr * algnof ) { primeBaseScrub( algnof->type ); }
    63                 void premutate( PointerType * pointer ) { primeBaseScrub( pointer->base ); }
    64 
    65                 Type * postmutate( TypeInstType * typeInst );
    66                 Type * postmutate( StructInstType * structInst );
    67                 Type * postmutate( UnionInstType * unionInst );
    68                 Expression * postmutate( SizeofExpr * szeof );
    69                 Expression * postmutate( AlignofExpr * algnof );
    70                 Type * postmutate( PointerType * pointer );
    71 
    72           private:
    73                 /// Returns the type if it should be scrubbed, NULL otherwise.
    74                 Type* shouldScrub( Type *ty ) {
    75                         switch ( mode ) {
    76                         case FromMap: return isPolyType( ty, *tyVars );
    77                         case DynamicFromMap: return isDynType( ty, *tyVars );
    78                         case All: return isPolyType( ty );
    79                         }
    80                         assert(false); return nullptr; // unreachable
    81                         // return dynamicOnly ? isDynType( ty, tyVars ) : isPolyType( ty, tyVars );
    82                 }
    83 
    84                 /// Mutates (possibly generic) aggregate types appropriately
    85                 Type* mutateAggregateType( Type *ty );
    86 
    87                 const TyVarMap *tyVars;  ///< Type variables to scrub
    88                 ScrubMode mode;          ///< which type variables to scrub? [FromMap]
    89 
    90                 Type * dynType = nullptr; ///< result of shouldScrub
    91         };
    92 
    93         template< typename SynTreeClass >
    94         SynTreeClass * ScrubTyVars::scrub( SynTreeClass *target, const TyVarMap &tyVars ) {
    95                 PassVisitor<ScrubTyVars> scrubber( tyVars );
    96                 return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) );
    97         }
    98 
    99         template< typename SynTreeClass >
    100         SynTreeClass * ScrubTyVars::scrubDynamic( SynTreeClass *target, const TyVarMap &tyVars ) {
    101                 PassVisitor<ScrubTyVars> scrubber( tyVars, ScrubTyVars::DynamicFromMap );
    102                 return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) );
    103         }
    104 
    105         template< typename SynTreeClass >
    106         SynTreeClass * ScrubTyVars::scrubAll( SynTreeClass *target ) {
    107                 PassVisitor<ScrubTyVars> scrubber;
    108                 return static_cast< SynTreeClass * >( target->acceptMutator( scrubber ) );
    109         }
    11024
    11125// ScrubMode and scrubTypeVarsBase are internal.
  • src/GenPoly/SpecializeNew.cpp

    r790d835 rc6b4432  
    2323#include "GenPoly/GenPoly.h"             // for getFunctionType
    2424#include "ResolvExpr/FindOpenVars.h"     // for findOpenVars
    25 #include "ResolvExpr/TypeEnvironment.h"  // for FirstOpen, FirstClosed
    2625
    2726namespace GenPoly {
  • src/GenPoly/module.mk

    r790d835 rc6b4432  
    2323SRC += $(SRC_GENPOLY) \
    2424        GenPoly/BoxNew.cpp \
    25         GenPoly/Box.cc \
    2625        GenPoly/Box.h \
    2726        GenPoly/ErasableScopedMap.h \
     
    2928        GenPoly/FindFunction.h \
    3029        GenPoly/InstantiateGenericNew.cpp \
    31         GenPoly/InstantiateGeneric.cc \
    3230        GenPoly/InstantiateGeneric.h \
    3331        GenPoly/LvalueNew.cpp \
    34         GenPoly/Lvalue.cc \
    3532        GenPoly/ScopedSet.h \
    3633        GenPoly/ScrubTyVars.cc \
    3734        GenPoly/ScrubTyVars.h \
    38         GenPoly/Specialize.cc \
    3935        GenPoly/SpecializeNew.cpp \
    4036        GenPoly/Specialize.h
  • src/InitTweak/FixGlobalInit.cc

    r790d835 rc6b4432  
    2020#include <algorithm>               // for replace_if
    2121
    22 #include "Common/PassVisitor.h"
    23 #include "Common/UniqueName.h"     // for UniqueName
    24 #include "InitTweak.h"             // for isIntrinsicSingleArgCallStmt
    25 #include "SynTree/LinkageSpec.h"   // for C
    26 #include "SynTree/Attribute.h"     // for Attribute
    27 #include "SynTree/Constant.h"      // for Constant
    28 #include "SynTree/Declaration.h"   // for FunctionDecl, ObjectDecl, Declaration
    29 #include "SynTree/Expression.h"    // for ConstantExpr, Expression (ptr only)
    30 #include "SynTree/Initializer.h"   // for ConstructorInit, Initializer
    31 #include "SynTree/Label.h"         // for Label
    32 #include "SynTree/Statement.h"     // for CompoundStmt, Statement (ptr only)
    33 #include "SynTree/Type.h"          // for Type, Type::StorageClasses, Functi...
    34 #include "SynTree/Visitor.h"       // for acceptAll, Visitor
    35 
    3622#include "AST/Expr.hpp"
    3723#include "AST/Node.hpp"
    3824#include "AST/Pass.hpp"
     25#include "Common/UniqueName.h"     // for UniqueName
     26#include "InitTweak.h"             // for isIntrinsicSingleArgCallStmt
    3927
    4028namespace InitTweak {
    41         class GlobalFixer : public WithShortCircuiting {
    42           public:
    43                 GlobalFixer( bool inLibrary );
    44 
    45                 void previsit( ObjectDecl *objDecl );
    46                 void previsit( FunctionDecl *functionDecl );
    47                 void previsit( StructDecl *aggregateDecl );
    48                 void previsit( UnionDecl *aggregateDecl );
    49                 void previsit( EnumDecl *aggregateDecl );
    50                 void previsit( TraitDecl *aggregateDecl );
    51                 void previsit( TypeDecl *typeDecl );
    52 
    53                 UniqueName tempNamer;
    54                 FunctionDecl * initFunction;
    55                 FunctionDecl * destroyFunction;
    56         };
    57 
    5829        class GlobalFixer_new : public ast::WithShortCircuiting {
    5930        public:
     
    6940                std::list< ast::ptr<ast::Stmt> > destroyStmts;
    7041        };
    71 
    72         void fixGlobalInit( std::list< Declaration * > & translationUnit, bool inLibrary ) {
    73                 PassVisitor<GlobalFixer> visitor( inLibrary );
    74                 acceptAll( translationUnit, visitor );
    75                 GlobalFixer & fixer = visitor.pass;
    76                 // don't need to include function if it's empty
    77                 if ( fixer.initFunction->get_statements()->get_kids().empty() ) {
    78                         delete fixer.initFunction;
    79                 } else {
    80                         translationUnit.push_back( fixer.initFunction );
    81                 } // if
    82 
    83                 if ( fixer.destroyFunction->get_statements()->get_kids().empty() ) {
    84                         delete fixer.destroyFunction;
    85                 } else {
    86                         translationUnit.push_back( fixer.destroyFunction );
    87                 } // if
    88         }
    89 
    90         GlobalFixer::GlobalFixer( bool inLibrary ) : tempNamer( "_global_init" ) {
    91                 std::list< Expression * > ctorParameters;
    92                 std::list< Expression * > dtorParameters;
    93                 if ( inLibrary ) {
    94                         // Constructor/destructor attributes take a single parameter which
    95                         // is the priority, with lower numbers meaning higher priority.
    96                         // Functions specified with priority are guaranteed to run before
    97                         // functions without a priority. To ensure that constructors and destructors
    98                         // for library code are run before constructors and destructors for user code,
    99                         // specify a priority when building the library. Priorities 0-100 are reserved by gcc.
    100                         // Priorities 101-200 are reserved by cfa, so use priority 200 for CFA library globals,
    101                         // allowing room for overriding with a higher priority.
    102                         ctorParameters.push_back( new ConstantExpr( Constant::from_int( 200 ) ) );
    103                         dtorParameters.push_back( new ConstantExpr( Constant::from_int( 200 ) ) );
    104                 }
    105                 initFunction = new FunctionDecl( "__global_init__", Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
    106                 initFunction->get_attributes().push_back( new Attribute( "constructor", ctorParameters ) );
    107                 destroyFunction = new FunctionDecl( "__global_destroy__", Type::StorageClasses( Type::Static ), LinkageSpec::C, new FunctionType( Type::Qualifiers(), false ), new CompoundStmt() );
    108                 destroyFunction->get_attributes().push_back( new Attribute( "destructor", dtorParameters ) );
    109         }
    11042
    11143        void fixGlobalInit(ast::TranslationUnit & translationUnit, bool inLibrary) {
     
    14173        }
    14274
    143         void GlobalFixer::previsit( ObjectDecl *objDecl ) {
    144                 std::list< Statement * > & initStatements = initFunction->get_statements()->get_kids();
    145                 std::list< Statement * > & destroyStatements = destroyFunction->get_statements()->get_kids();
    146 
    147                 // C allows you to initialize objects with constant expressions
    148                 // xxx - this is an optimization. Need to first resolve constructors before we decide
    149                 // to keep C-style initializer.
    150                 // if ( isConstExpr( objDecl->get_init() ) ) return;
    151 
    152                 if ( ConstructorInit * ctorInit = dynamic_cast< ConstructorInit * >( objDecl->get_init() ) ) {
    153                         // a decision should have been made by the resolver, so ctor and init are not both non-NULL
    154                         assert( ! ctorInit->ctor || ! ctorInit->init );
    155 
    156                         Statement * dtor = ctorInit->dtor;
    157                         if ( dtor && ! isIntrinsicSingleArgCallStmt( dtor ) ) {
    158                                 // don't need to call intrinsic dtor, because it does nothing, but
    159                                 // non-intrinsic dtors must be called
    160                                 destroyStatements.push_front( dtor );
    161                                 ctorInit->dtor = nullptr;
    162                         } // if
    163                         if ( Statement * ctor = ctorInit->ctor ) {
    164                                 addDataSectionAttribute( objDecl );
    165                                 initStatements.push_back( ctor );
    166                                 objDecl->init = nullptr;
    167                                 ctorInit->ctor = nullptr;
    168                         } else if ( Initializer * init = ctorInit->init ) {
    169                                 objDecl->init = init;
    170                                 ctorInit->init = nullptr;
    171                         } else {
    172                                 // no constructor and no initializer, which is okay
    173                                 objDecl->init = nullptr;
    174                         } // if
    175                         delete ctorInit;
    176                 } // if
    177         }
    178 
    17975        void GlobalFixer_new::previsit(const ast::ObjectDecl * objDecl) {
    18076                auto mutDecl = mutate(objDecl);
     
    207103        }
    208104
    209         // only modify global variables
    210         void GlobalFixer::previsit( FunctionDecl * ) { visit_children = false; }
    211         void GlobalFixer::previsit( StructDecl * ) { visit_children = false; }
    212         void GlobalFixer::previsit( UnionDecl * ) { visit_children = false; }
    213         void GlobalFixer::previsit( EnumDecl * ) { visit_children = false; }
    214         void GlobalFixer::previsit( TraitDecl * ) { visit_children = false; }
    215         void GlobalFixer::previsit( TypeDecl * ) { visit_children = false; }
    216 
    217105} // namespace InitTweak
    218106
  • src/InitTweak/FixInitNew.cpp

    r790d835 rc6b4432  
    178178/// (currently by FixInit)
    179179struct InsertDtors final : public ObjDeclCollector, public ast::WithStmtsToAdd<> {
    180         typedef std::list< ObjectDecl * > OrderedDecls;
    181         typedef std::list< OrderedDecls > OrderedDeclsStack;
    182 
    183180        InsertDtors( ast::Pass<LabelFinder> & finder ) : finder( finder ), labelVars( finder.core.vars ) {}
    184181
     
    194191        ast::Pass<LabelFinder> & finder;
    195192        LabelFinder::LabelMap & labelVars;
    196         OrderedDeclsStack reverseDeclOrder;
    197193};
    198194
  • src/InitTweak/GenInit.cc

    r790d835 rc6b4432  
    2929#include "CompilationState.h"
    3030#include "CodeGen/OperatorTable.h"
    31 #include "Common/PassVisitor.h"        // for PassVisitor, WithGuards, WithShort...
    3231#include "Common/SemanticError.h"      // for SemanticError
    3332#include "Common/ToString.hpp"         // for toCString
     
    3837#include "InitTweak.h"                 // for isConstExpr, InitExpander, checkIn...
    3938#include "ResolvExpr/Resolver.h"
    40 #include "SymTab/Autogen.h"            // for genImplicitCall
    4139#include "SymTab/GenImplicitCall.hpp"  // for genImplicitCall
    4240#include "SymTab/Mangler.h"            // for Mangler
    43 #include "SynTree/LinkageSpec.h"       // for isOverridable, C
    44 #include "SynTree/Declaration.h"       // for ObjectDecl, DeclarationWithType
    45 #include "SynTree/Expression.h"        // for VariableExpr, UntypedExpr, Address...
    46 #include "SynTree/Initializer.h"       // for ConstructorInit, SingleInit, Initi...
    47 #include "SynTree/Label.h"             // for Label
    48 #include "SynTree/Mutator.h"           // for mutateAll
    49 #include "SynTree/Statement.h"         // for CompoundStmt, ImplicitCtorDtorStmt
    50 #include "SynTree/Type.h"              // for Type, ArrayType, Type::Qualifiers
    51 #include "SynTree/Visitor.h"           // for acceptAll, maybeAccept
    5241#include "Tuples/Tuples.h"             // for maybeImpure
    5342#include "Validate/FindSpecialDecls.h" // for SizeType
    5443
    5544namespace InitTweak {
    56         namespace {
    57                 const std::list<Label> noLabels;
    58                 const std::list<Expression *> noDesignators;
    59         }
    60 
    61         struct ReturnFixer : public WithStmtsToAdd, public WithGuards {
    62                 /// consistently allocates a temporary variable for the return value
    63                 /// of a function so that anything which the resolver decides can be constructed
    64                 /// into the return type of a function can be returned.
    65                 static void makeReturnTemp( std::list< Declaration * > &translationUnit );
    66 
    67                 void premutate( FunctionDecl *functionDecl );
    68                 void premutate( ReturnStmt * returnStmt );
    69 
    70           protected:
    71                 FunctionType * ftype = nullptr;
    72                 std::string funcName;
    73         };
    74 
    75         struct CtorDtor : public WithGuards, public WithShortCircuiting, public WithVisitorRef<CtorDtor>  {
    76                 /// create constructor and destructor statements for object declarations.
    77                 /// the actual call statements will be added in after the resolver has run
    78                 /// so that the initializer expression is only removed if a constructor is found
    79                 /// and the same destructor call is inserted in all of the appropriate locations.
    80                 static void generateCtorDtor( std::list< Declaration * > &translationUnit );
    81 
    82                 void previsit( ObjectDecl * );
    83                 void previsit( FunctionDecl *functionDecl );
    84 
    85                 // should not traverse into any of these declarations to find objects
    86                 // that need to be constructed or destructed
    87                 void previsit( StructDecl *aggregateDecl );
    88                 void previsit( AggregateDecl * ) { visit_children = false; }
    89                 void previsit( NamedTypeDecl * ) { visit_children = false; }
    90                 void previsit( FunctionType * ) { visit_children = false; }
    91 
    92                 void previsit( CompoundStmt * compoundStmt );
    93 
    94           private:
    95                 // set of mangled type names for which a constructor or destructor exists in the current scope.
    96                 // these types require a ConstructorInit node to be generated, anything else is a POD type and thus
    97                 // should not have a ConstructorInit generated.
    98 
    99                 ManagedTypes managedTypes;
    100                 bool inFunction = false;
    101         };
    102 
    103         struct HoistArrayDimension final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards, public WithIndexer {
    104                 /// hoist dimension from array types in object declaration so that it uses a single
    105                 /// const variable of type size_t, so that side effecting array dimensions are only
    106                 /// computed once.
    107                 static void hoistArrayDimension( std::list< Declaration * > & translationUnit );
    108 
    109                 void premutate( ObjectDecl * objectDecl );
    110                 DeclarationWithType * postmutate( ObjectDecl * objectDecl );
    111                 void premutate( FunctionDecl *functionDecl );
    112                 // should not traverse into any of these declarations to find objects
    113                 // that need to be constructed or destructed
    114                 void premutate( AggregateDecl * ) { visit_children = false; }
    115                 void premutate( NamedTypeDecl * ) { visit_children = false; }
    116                 void premutate( FunctionType * ) { visit_children = false; }
    117 
    118                 // need this so that enumerators are added to the indexer, due to premutate(AggregateDecl *)
    119                 void premutate( EnumDecl * ) {}
    120 
    121                 void hoist( Type * type );
    122 
    123                 Type::StorageClasses storageClasses;
    124                 bool inFunction = false;
    125         };
    126 
    127         struct HoistArrayDimension_NoResolve final : public WithDeclsToAdd, public WithShortCircuiting, public WithGuards {
    128                 /// hoist dimension from array types in object declaration so that it uses a single
    129                 /// const variable of type size_t, so that side effecting array dimensions are only
    130                 /// computed once.
    131                 static void hoistArrayDimension( std::list< Declaration * > & translationUnit );
    132 
    133                 void premutate( ObjectDecl * objectDecl );
    134                 DeclarationWithType * postmutate( ObjectDecl * objectDecl );
    135                 void premutate( FunctionDecl *functionDecl );
    136                 // should not traverse into any of these declarations to find objects
    137                 // that need to be constructed or destructed
    138                 void premutate( AggregateDecl * ) { visit_children = false; }
    139                 void premutate( NamedTypeDecl * ) { visit_children = false; }
    140                 void premutate( FunctionType * ) { visit_children = false; }
    141 
    142                 void hoist( Type * type );
    143 
    144                 Type::StorageClasses storageClasses;
    145                 bool inFunction = false;
    146         };
    147 
    148         void genInit( std::list< Declaration * > & translationUnit ) {
    149                 if (!useNewAST) {
    150                         HoistArrayDimension::hoistArrayDimension( translationUnit );
    151                 }
    152                 else {
    153                         HoistArrayDimension_NoResolve::hoistArrayDimension( translationUnit );
    154                 }
    155                 fixReturnStatements( translationUnit );
    156 
    157                 if (!useNewAST) {
    158                         CtorDtor::generateCtorDtor( translationUnit );
    159                 }
    160         }
    161 
    162         void fixReturnStatements( std::list< Declaration * > & translationUnit ) {
    163                 PassVisitor<ReturnFixer> fixer;
    164                 mutateAll( translationUnit, fixer );
    165         }
    166 
    167         void ReturnFixer::premutate( ReturnStmt *returnStmt ) {
    168                 std::list< DeclarationWithType * > & returnVals = ftype->get_returnVals();
    169                 assert( returnVals.size() == 0 || returnVals.size() == 1 );
    170                 // hands off if the function returns a reference - we don't want to allocate a temporary if a variable's address
    171                 // is being returned
    172                 if ( returnStmt->expr && returnVals.size() == 1 && isConstructable( returnVals.front()->get_type() ) ) {
    173                         // explicitly construct the return value using the return expression and the retVal object
    174                         assertf( returnVals.front()->name != "", "Function %s has unnamed return value\n", funcName.c_str() );
    175 
    176                         ObjectDecl * retVal = strict_dynamic_cast< ObjectDecl * >( returnVals.front() );
    177                         if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( returnStmt->expr ) ) {
    178                                 // return statement has already been mutated - don't need to do it again
    179                                 if ( varExpr->var == retVal ) return;
    180                         }
    181                         Statement * stmt = genCtorDtor( "?{}", retVal, returnStmt->expr );
    182                         assertf( stmt, "ReturnFixer: genCtorDtor returned nullptr: %s / %s", toString( retVal ).c_str(), toString( returnStmt->expr ).c_str() );
    183                         stmtsToAddBefore.push_back( stmt );
    184 
    185                         // return the retVal object
    186                         returnStmt->expr = new VariableExpr( returnVals.front() );
    187                 } // if
    188         }
    189 
    190         void ReturnFixer::premutate( FunctionDecl *functionDecl ) {
    191                 GuardValue( ftype );
    192                 GuardValue( funcName );
    193 
    194                 ftype = functionDecl->type;
    195                 funcName = functionDecl->name;
    196         }
    197 
    198         // precompute array dimension expression, because constructor generation may duplicate it,
    199         // which would be incorrect if it is a side-effecting computation.
    200         void HoistArrayDimension::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
    201                 PassVisitor<HoistArrayDimension> hoister;
    202                 mutateAll( translationUnit, hoister );
    203         }
    204 
    205         void HoistArrayDimension::premutate( ObjectDecl * objectDecl ) {
    206                 GuardValue( storageClasses );
    207                 storageClasses = objectDecl->get_storageClasses();
    208         }
    209 
    210         DeclarationWithType * HoistArrayDimension::postmutate( ObjectDecl * objectDecl ) {
    211                 hoist( objectDecl->get_type() );
    212                 return objectDecl;
    213         }
    214 
    215         void HoistArrayDimension::hoist( Type * type ) {
    216                 // if in function, generate const size_t var
    217                 static UniqueName dimensionName( "_array_dim" );
    218 
    219                 // C doesn't allow variable sized arrays at global scope or for static variables, so don't hoist dimension.
    220                 if ( ! inFunction ) return;
    221                 if ( storageClasses.is_static ) return;
    222 
    223                 if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
    224                         if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist?
    225 
    226                         // need to resolve array dimensions in order to accurately determine if constexpr
    227                         ResolvExpr::findSingleExpression( arrayType->dimension, Validate::SizeType->clone(), indexer );
    228                         // array is variable-length when the dimension is not constexpr
    229                         arrayType->isVarLen = ! isConstExpr( arrayType->dimension );
    230                         // don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects.
    231                         // xxx - hoisting has no side effects anyways, so don't skip since we delay resolve
    232                         // still try to detect constant expressions
    233                         if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return;
    234 
    235                         ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, Validate::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
    236                         arrayDimension->get_type()->set_const( true );
    237 
    238                         arrayType->set_dimension( new VariableExpr( arrayDimension ) );
    239                         declsToAddBefore.push_back( arrayDimension );
    240 
    241                         hoist( arrayType->get_base() );
    242                         return;
    243                 }
    244         }
    245 
    246         void HoistArrayDimension::premutate( FunctionDecl * ) {
    247                 GuardValue( inFunction );
    248                 inFunction = true;
    249         }
    250 
    251         // precompute array dimension expression, because constructor generation may duplicate it,
    252         // which would be incorrect if it is a side-effecting computation.
    253         void HoistArrayDimension_NoResolve::hoistArrayDimension( std::list< Declaration * > & translationUnit ) {
    254                 PassVisitor<HoistArrayDimension_NoResolve> hoister;
    255                 mutateAll( translationUnit, hoister );
    256         }
    257 
    258         void HoistArrayDimension_NoResolve::premutate( ObjectDecl * objectDecl ) {
    259                 GuardValue( storageClasses );
    260                 storageClasses = objectDecl->get_storageClasses();
    261         }
    262 
    263         DeclarationWithType * HoistArrayDimension_NoResolve::postmutate( ObjectDecl * objectDecl ) {
    264                 hoist( objectDecl->get_type() );
    265                 return objectDecl;
    266         }
    267 
    268         void HoistArrayDimension_NoResolve::hoist( Type * type ) {
    269                 // if in function, generate const size_t var
    270                 static UniqueName dimensionName( "_array_dim" );
    271 
    272                 // C doesn't allow variable sized arrays at global scope or for static variables, so don't hoist dimension.
    273                 if ( ! inFunction ) return;
    274                 if ( storageClasses.is_static ) return;
    275 
    276                 if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
    277                         if ( ! arrayType->get_dimension() ) return; // xxx - recursive call to hoist?
    278                         // don't need to hoist dimension if it's definitely pure - only need to if there's potential for side effects.
    279                         // xxx - hoisting has no side effects anyways, so don't skip since we delay resolve
    280                         // still try to detect constant expressions
    281                         if ( ! Tuples::maybeImpure( arrayType->dimension ) ) return;
    282 
    283                         ObjectDecl * arrayDimension = new ObjectDecl( dimensionName.newName(), storageClasses, LinkageSpec::C, 0, Validate::SizeType->clone(), new SingleInit( arrayType->get_dimension() ) );
    284                         arrayDimension->get_type()->set_const( true );
    285 
    286                         arrayType->set_dimension( new VariableExpr( arrayDimension ) );
    287                         declsToAddBefore.push_back( arrayDimension );
    288 
    289                         hoist( arrayType->get_base() );
    290                         return;
    291                 }
    292         }
    293 
    294         void HoistArrayDimension_NoResolve::premutate( FunctionDecl * ) {
    295                 GuardValue( inFunction );
    296                 inFunction = true;
    297         }
    29845
    29946namespace {
     
    526273        }
    527274
    528         void CtorDtor::generateCtorDtor( std::list< Declaration * > & translationUnit ) {
    529                 PassVisitor<CtorDtor> ctordtor;
    530                 acceptAll( translationUnit, ctordtor );
    531         }
    532 
    533         bool ManagedTypes::isManaged( Type * type ) const {
    534                 // references are never constructed
    535                 if ( dynamic_cast< ReferenceType * >( type ) ) return false;
    536                 // need to clear and reset qualifiers when determining if a type is managed
    537                 ValueGuard< Type::Qualifiers > qualifiers( type->get_qualifiers() );
    538                 type->get_qualifiers() = Type::Qualifiers();
    539                 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( type ) ) {
    540                         // tuple is also managed if any of its components are managed
    541                         if ( std::any_of( tupleType->types.begin(), tupleType->types.end(), [&](Type * type) { return isManaged( type ); }) ) {
    542                                 return true;
    543                         }
    544                 }
    545                 // 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)
    546                 return managedTypes.find( SymTab::Mangler::mangleConcrete( type ) ) != managedTypes.end() || GenPoly::isPolyType( type );
    547         }
    548 
    549         bool ManagedTypes::isManaged( ObjectDecl * objDecl ) const {
    550                 Type * type = objDecl->get_type();
    551                 while ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    552                         // must always construct VLAs with an initializer, since this is an error in C
    553                         if ( at->isVarLen && objDecl->init ) return true;
    554                         type = at->get_base();
    555                 }
    556                 return isManaged( type );
    557         }
    558 
    559         // why is this not just on FunctionDecl?
    560         void ManagedTypes::handleDWT( DeclarationWithType * dwt ) {
    561                 // if this function is a user-defined constructor or destructor, mark down the type as "managed"
    562                 if ( ! LinkageSpec::isOverridable( dwt->get_linkage() ) && CodeGen::isCtorDtor( dwt->get_name() ) ) {
    563                         std::list< DeclarationWithType * > & params = GenPoly::getFunctionType( dwt->get_type() )->get_parameters();
    564                         assert( ! params.empty() );
    565                         Type * type = InitTweak::getPointerBase( params.front()->get_type() );
    566                         assert( type );
    567                         managedTypes.insert( SymTab::Mangler::mangleConcrete( type ) );
    568                 }
    569         }
    570 
    571         void ManagedTypes::handleStruct( StructDecl * aggregateDecl ) {
    572                 // don't construct members, but need to take note if there is a managed member,
    573                 // because that means that this type is also managed
    574                 for ( Declaration * member : aggregateDecl->get_members() ) {
    575                         if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( member ) ) {
    576                                 if ( isManaged( field ) ) {
    577                                         // generic parameters should not play a role in determining whether a generic type is constructed - construct all generic types, so that
    578                                         // polymorphic constructors make generic types managed types
    579                                         StructInstType inst( Type::Qualifiers(), aggregateDecl );
    580                                         managedTypes.insert( SymTab::Mangler::mangleConcrete( &inst ) );
    581                                         break;
    582                                 }
    583                         }
    584                 }
    585         }
    586 
    587         void ManagedTypes::beginScope() { managedTypes.beginScope(); }
    588         void ManagedTypes::endScope() { managedTypes.endScope(); }
    589 
    590275        bool ManagedTypes_new::isManaged( const ast::Type * type ) const {
    591276                // references are never constructed
     
    647332        void ManagedTypes_new::endScope() { managedTypes.endScope(); }
    648333
    649         ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg ) {
    650                 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
    651                 assertf( objDecl, "genCtorDtor passed null objDecl" );
    652                 std::list< Statement * > stmts;
    653                 InitExpander_old srcParam( maybeClone( arg ) );
    654                 SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), fname, back_inserter( stmts ), objDecl );
    655                 assert( stmts.size() <= 1 );
    656                 return stmts.size() == 1 ? strict_dynamic_cast< ImplicitCtorDtorStmt * >( stmts.front() ) : nullptr;
    657 
    658         }
    659 
    660334        ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg) {
    661335                assertf(objDecl, "genCtorDtor passed null objDecl");
    662336                InitExpander_new srcParam(arg);
    663337                return SymTab::genImplicitCall(srcParam, new ast::VariableExpr(loc, objDecl), loc, fname, objDecl);
    664         }
    665 
    666         ConstructorInit * genCtorInit( ObjectDecl * objDecl ) {
    667                 // call into genImplicitCall from Autogen.h to generate calls to ctor/dtor
    668                 // for each constructable object
    669                 std::list< Statement * > ctor;
    670                 std::list< Statement * > dtor;
    671 
    672                 InitExpander_old srcParam( objDecl->get_init() );
    673                 InitExpander_old nullParam( (Initializer *)NULL );
    674                 SymTab::genImplicitCall( srcParam, new VariableExpr( objDecl ), "?{}", back_inserter( ctor ), objDecl );
    675                 SymTab::genImplicitCall( nullParam, new VariableExpr( objDecl ), "^?{}", front_inserter( dtor ), objDecl, false );
    676 
    677                 // Currently genImplicitCall produces a single Statement - a CompoundStmt
    678                 // which  wraps everything that needs to happen. As such, it's technically
    679                 // possible to use a Statement ** in the above calls, but this is inherently
    680                 // unsafe, so instead we take the slightly less efficient route, but will be
    681                 // immediately informed if somehow the above assumption is broken. In this case,
    682                 // we could always wrap the list of statements at this point with a CompoundStmt,
    683                 // but it seems reasonable at the moment for this to be done by genImplicitCall
    684                 // itself. It is possible that genImplicitCall produces no statements (e.g. if
    685                 // an array type does not have a dimension). In this case, it's fine to ignore
    686                 // the object for the purposes of construction.
    687                 assert( ctor.size() == dtor.size() && ctor.size() <= 1 );
    688                 if ( ctor.size() == 1 ) {
    689                         // need to remember init expression, in case no ctors exist
    690                         // if ctor does exist, want to use ctor expression instead of init
    691                         // push this decision to the resolver
    692                         assert( dynamic_cast< ImplicitCtorDtorStmt * > ( ctor.front() ) && dynamic_cast< ImplicitCtorDtorStmt * > ( dtor.front() ) );
    693                         return new ConstructorInit( ctor.front(), dtor.front(), objDecl->get_init() );
    694                 }
    695                 return nullptr;
    696         }
    697 
    698         void CtorDtor::previsit( ObjectDecl * objDecl ) {
    699                 managedTypes.handleDWT( objDecl );
    700                 // hands off if @=, extern, builtin, etc.
    701                 // even if unmanaged, try to construct global or static if initializer is not constexpr, since this is not legal C
    702                 if ( tryConstruct( objDecl ) && ( managedTypes.isManaged( objDecl ) || ((! inFunction || objDecl->get_storageClasses().is_static ) && ! isConstExpr( objDecl->get_init() ) ) ) ) {
    703                         // constructed objects cannot be designated
    704                         if ( isDesignated( objDecl->get_init() ) ) SemanticError( objDecl, "Cannot include designations in the initializer for a managed Object. If this is really what you want, then initialize with @=.\n" );
    705                         // constructed objects should not have initializers nested too deeply
    706                         if ( ! checkInitDepth( objDecl ) ) SemanticError( objDecl, "Managed object's initializer is too deep " );
    707 
    708                         objDecl->set_init( genCtorInit( objDecl ) );
    709                 }
    710         }
    711 
    712         void CtorDtor::previsit( FunctionDecl *functionDecl ) {
    713                 visit_children = false;  // do not try and construct parameters or forall parameters
    714                 GuardValue( inFunction );
    715                 inFunction = true;
    716 
    717                 managedTypes.handleDWT( functionDecl );
    718 
    719                 GuardScope( managedTypes );
    720                 // go through assertions and recursively add seen ctor/dtors
    721                 for ( auto & tyDecl : functionDecl->get_functionType()->get_forall() ) {
    722                         for ( DeclarationWithType *& assertion : tyDecl->get_assertions() ) {
    723                                 managedTypes.handleDWT( assertion );
    724                         }
    725                 }
    726 
    727                 maybeAccept( functionDecl->get_statements(), *visitor );
    728         }
    729 
    730         void CtorDtor::previsit( StructDecl *aggregateDecl ) {
    731                 visit_children = false; // do not try to construct and destruct aggregate members
    732 
    733                 managedTypes.handleStruct( aggregateDecl );
    734         }
    735 
    736         void CtorDtor::previsit( CompoundStmt * ) {
    737                 GuardScope( managedTypes );
    738338        }
    739339
  • src/InitTweak/GenInit.h

    r790d835 rc6b4432  
    2222#include "Common/CodeLocation.h"
    2323#include "GenPoly/ScopedSet.h" // for ScopedSet
    24 #include "SynTree/SynTree.h"   // for Visitor Nodes
    2524
    2625namespace InitTweak {
    2726        /// Adds return value temporaries and wraps Initializers in ConstructorInit nodes
    28         void genInit( std::list< Declaration * > & translationUnit );
    2927        void genInit( ast::TranslationUnit & translationUnit );
    3028
    3129        /// Converts return statements into copy constructor calls on the hidden return variable.
    3230        /// This pass must happen before auto-gen.
    33         void fixReturnStatements( std::list< Declaration * > & translationUnit );
    3431        void fixReturnStatements( ast::TranslationUnit & translationUnit );
    3532
    3633        /// generates a single ctor/dtor statement using objDecl as the 'this' parameter and arg as the optional argument
    37         ImplicitCtorDtorStmt * genCtorDtor( const std::string & fname, ObjectDecl * objDecl, Expression * arg = nullptr );
    3834        ast::ptr<ast::Stmt> genCtorDtor (const CodeLocation & loc, const std::string & fname, const ast::ObjectDecl * objDecl, const ast::Expr * arg = nullptr);
    3935
    4036        /// creates an appropriate ConstructorInit node which contains a constructor, destructor, and C-initializer
    41         ConstructorInit * genCtorInit( ObjectDecl * objDecl );
    4237        ast::ConstructorInit * genCtorInit( const CodeLocation & loc, const ast::ObjectDecl * objDecl );
    43 
    44         class ManagedTypes {
    45         public:
    46                 bool isManaged( ObjectDecl * objDecl ) const ; // determine if object is managed
    47                 bool isManaged( Type * type ) const; // determine if type is managed
    48 
    49                 void handleDWT( DeclarationWithType * dwt ); // add type to managed if ctor/dtor
    50                 void handleStruct( StructDecl * aggregateDecl ); // add type to managed if child is managed
    51 
    52                 void beginScope();
    53                 void endScope();
    54         private:
    55                 GenPoly::ScopedSet< std::string > managedTypes;
    56         };
    5738
    5839        class ManagedTypes_new {
  • src/InitTweak/InitTweak.cc

    r790d835 rc6b4432  
    2929#include "AST/Type.hpp"
    3030#include "CodeGen/OperatorTable.h" // for isConstructor, isDestructor, isCto...
    31 #include "Common/PassVisitor.h"
    3231#include "Common/SemanticError.h"  // for SemanticError
    3332#include "Common/UniqueName.h"     // for UniqueName
     
    3635#include "InitTweak.h"
    3736#include "ResolvExpr/Unify.h"      // for typesCompatibleIgnoreQualifiers
    38 #include "SymTab/Autogen.h"
    39 #include "SymTab/Indexer.h"        // for Indexer
    40 #include "SynTree/LinkageSpec.h"   // for Spec, isBuiltin, Intrinsic
    41 #include "SynTree/Attribute.h"     // for Attribute
    42 #include "SynTree/Constant.h"      // for Constant
    43 #include "SynTree/Declaration.h"   // for ObjectDecl, DeclarationWithType
    44 #include "SynTree/Expression.h"    // for Expression, UntypedExpr, Applicati...
    45 #include "SynTree/Initializer.h"   // for Initializer, ListInit, Designation
    46 #include "SynTree/Label.h"         // for Label
    47 #include "SynTree/Statement.h"     // for CompoundStmt, ExprStmt, BranchStmt
    48 #include "SynTree/Type.h"          // for FunctionType, ArrayType, PointerType
    49 #include "SynTree/Visitor.h"       // for Visitor, maybeAccept
    5037#include "Tuples/Tuples.h"         // for Tuples::isTtype
    5138
    5239namespace InitTweak {
    5340        namespace {
    54                 struct HasDesignations : public WithShortCircuiting {
    55                         bool hasDesignations = false;
    56 
    57                         void previsit( BaseSyntaxNode * ) {
    58                                 // short circuit if we already know there are designations
    59                                 if ( hasDesignations ) visit_children = false;
    60                         }
    61 
    62                         void previsit( Designation * des ) {
    63                                 // short circuit if we already know there are designations
    64                                 if ( hasDesignations ) visit_children = false;
    65                                 else if ( ! des->get_designators().empty() ) {
    66                                         hasDesignations = true;
    67                                         visit_children = false;
    68                                 }
    69                         }
    70                 };
    71 
    72                 struct InitDepthChecker : public WithGuards {
    73                         bool depthOkay = true;
    74                         Type * type;
    75                         int curDepth = 0, maxDepth = 0;
    76                         InitDepthChecker( Type * type ) : type( type ) {
    77                                 Type * t = type;
    78                                 while ( ArrayType * at = dynamic_cast< ArrayType * >( t ) ) {
    79                                         maxDepth++;
    80                                         t = at->get_base();
    81                                 }
    82                                 maxDepth++;
    83                         }
    84                         void previsit( ListInit * ) {
    85                                 curDepth++;
    86                                 GuardAction( [this]() { curDepth--; } );
    87                                 if ( curDepth > maxDepth ) depthOkay = false;
    88                         }
    89                 };
    90 
    9141                struct HasDesignations_new : public ast::WithShortCircuiting {
    9242                        bool result = false;
     
    12878                };
    12979
    130                 struct InitFlattener_old : public WithShortCircuiting {
    131                         void previsit( SingleInit * singleInit ) {
    132                                 visit_children = false;
    133                                 argList.push_back( singleInit->value->clone() );
    134                         }
    135                         std::list< Expression * > argList;
    136                 };
    137 
    13880                struct InitFlattener_new : public ast::WithShortCircuiting {
    13981                        std::vector< ast::ptr< ast::Expr > > argList;
     
    14688
    14789        } // anonymous namespace
    148 
    149         std::list< Expression * > makeInitList( Initializer * init ) {
    150                 PassVisitor<InitFlattener_old> flattener;
    151                 maybeAccept( init, flattener );
    152                 return flattener.pass.argList;
    153         }
    154 
    155         bool isDesignated( Initializer * init ) {
    156                 PassVisitor<HasDesignations> finder;
    157                 maybeAccept( init, finder );
    158                 return finder.pass.hasDesignations;
    159         }
    160 
    161         bool checkInitDepth( ObjectDecl * objDecl ) {
    162                 PassVisitor<InitDepthChecker> checker( objDecl->type );
    163                 maybeAccept( objDecl->init, checker );
    164                 return checker.pass.depthOkay;
    165         }
    16690
    16791        bool isDesignated( const ast::Init * init ) {
     
    182106        return std::move( flattener.core.argList );
    183107}
    184 
    185         class InitExpander_old::ExpanderImpl {
    186         public:
    187                 virtual ~ExpanderImpl() = default;
    188                 virtual std::list< Expression * > next( std::list< Expression * > & indices ) = 0;
    189                 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ) = 0;
    190         };
    191 
    192         class InitImpl_old : public InitExpander_old::ExpanderImpl {
    193         public:
    194                 InitImpl_old( Initializer * init ) : init( init ) {}
    195                 virtual ~InitImpl_old() = default;
    196 
    197                 virtual std::list< Expression * > next( __attribute((unused)) std::list< Expression * > & indices ) {
    198                         // this is wrong, but just a placeholder for now
    199                         // if ( ! flattened ) flatten( indices );
    200                         // return ! inits.empty() ? makeInitList( inits.front() ) : std::list< Expression * >();
    201                         return makeInitList( init );
    202                 }
    203 
    204                 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );
    205         private:
    206                 Initializer * init;
    207         };
    208 
    209         class ExprImpl_old : public InitExpander_old::ExpanderImpl {
    210         public:
    211                 ExprImpl_old( Expression * expr ) : arg( expr ) {}
    212                 virtual ~ExprImpl_old() { delete arg; }
    213 
    214                 virtual std::list< Expression * > next( std::list< Expression * > & indices ) {
    215                         std::list< Expression * > ret;
    216                         Expression * expr = maybeClone( arg );
    217                         if ( expr ) {
    218                                 for ( std::list< Expression * >::reverse_iterator it = indices.rbegin(); it != indices.rend(); ++it ) {
    219                                         // go through indices and layer on subscript exprs ?[?]
    220                                         ++it;
    221                                         UntypedExpr * subscriptExpr = new UntypedExpr( new NameExpr( "?[?]") );
    222                                         subscriptExpr->get_args().push_back( expr );
    223                                         subscriptExpr->get_args().push_back( (*it)->clone() );
    224                                         expr = subscriptExpr;
    225                                 }
    226                                 ret.push_back( expr );
    227                         }
    228                         return ret;
    229                 }
    230 
    231                 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices );
    232         private:
    233                 Expression * arg;
    234         };
    235 
    236         InitExpander_old::InitExpander_old( Initializer * init ) : expander( new InitImpl_old( init ) ) {}
    237 
    238         InitExpander_old::InitExpander_old( Expression * expr ) : expander( new ExprImpl_old( expr ) ) {}
    239 
    240         std::list< Expression * > InitExpander_old::operator*() {
    241                 return cur;
    242         }
    243 
    244         InitExpander_old & InitExpander_old::operator++() {
    245                 cur = expander->next( indices );
    246                 return *this;
    247         }
    248 
    249         // use array indices list to build switch statement
    250         void InitExpander_old::addArrayIndex( Expression * index, Expression * dimension ) {
    251                 indices.push_back( index );
    252                 indices.push_back( dimension );
    253         }
    254 
    255         void InitExpander_old::clearArrayIndices() {
    256                 deleteAll( indices );
    257                 indices.clear();
    258         }
    259 
    260         bool InitExpander_old::addReference() {
    261                 bool added = false;
    262                 for ( Expression *& expr : cur ) {
    263                         expr = new AddressExpr( expr );
    264                         added = true;
    265                 }
    266                 return added;
    267         }
    268 
    269         namespace {
    270                 /// given index i, dimension d, initializer init, and callExpr f, generates
    271                 ///   if (i < d) f(..., init)
    272                 ///   ++i;
    273                 /// so that only elements within the range of the array are constructed
    274                 template< typename OutIterator >
    275                 void buildCallExpr( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) {
    276                         UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") );
    277                         cond->get_args().push_back( index->clone() );
    278                         cond->get_args().push_back( dimension->clone() );
    279 
    280                         std::list< Expression * > args = makeInitList( init );
    281                         callExpr->get_args().splice( callExpr->get_args().end(), args );
    282 
    283                         *out++ = new IfStmt( cond, new ExprStmt( callExpr ), nullptr );
    284 
    285                         UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) );
    286                         increment->get_args().push_back( index->clone() );
    287                         *out++ = new ExprStmt( increment );
    288                 }
    289 
    290                 template< typename OutIterator >
    291                 void build( UntypedExpr * callExpr, InitExpander_old::IndexList::iterator idx, InitExpander_old::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) {
    292                         if ( idx == idxEnd ) return;
    293                         Expression * index = *idx++;
    294                         assert( idx != idxEnd );
    295                         Expression * dimension = *idx++;
    296 
    297                         // xxx - may want to eventually issue a warning here if we can detect
    298                         // that the number of elements exceeds to dimension of the array
    299                         if ( idx == idxEnd ) {
    300                                 if ( ListInit * listInit = dynamic_cast< ListInit * >( init ) ) {
    301                                         for ( Initializer * init : *listInit ) {
    302                                                 buildCallExpr( callExpr->clone(), index, dimension, init, out );
    303                                         }
    304                                 } else {
    305                                         buildCallExpr( callExpr->clone(), index, dimension, init, out );
    306                                 }
    307                         } else {
    308                                 std::list< Statement * > branches;
    309 
    310                                 unsigned long cond = 0;
    311                                 ListInit * listInit = dynamic_cast< ListInit * >( init );
    312                                 if ( ! listInit ) {
    313                                         // xxx - this shouldn't be an error, but need a way to
    314                                         // terminate without creating output, so should catch this error
    315                                         SemanticError( init->location, "unbalanced list initializers" );
    316                                 }
    317 
    318                                 static UniqueName targetLabel( "L__autogen__" );
    319                                 Label switchLabel( targetLabel.newName(), 0, std::list< Attribute * >{ new Attribute("unused") } );
    320                                 for ( Initializer * init : *listInit ) {
    321                                         Expression * condition;
    322                                         // check for designations
    323                                         // if ( init-> ) {
    324                                                 condition = new ConstantExpr( Constant::from_ulong( cond ) );
    325                                                 ++cond;
    326                                         // } else {
    327                                         //      condition = // ... take designation
    328                                         //      cond = // ... take designation+1
    329                                         // }
    330                                         std::list< Statement * > stmts;
    331                                         build( callExpr, idx, idxEnd, init, back_inserter( stmts ) );
    332                                         stmts.push_back( new BranchStmt( switchLabel, BranchStmt::Break ) );
    333                                         CaseStmt * caseStmt = new CaseStmt( condition, stmts );
    334                                         branches.push_back( caseStmt );
    335                                 }
    336                                 *out++ = new SwitchStmt( index->clone(), branches );
    337                                 *out++ = new NullStmt( { switchLabel } );
    338                         }
    339                 }
    340         }
    341 
    342         // if array came with an initializer list: initialize each element
    343         // may have more initializers than elements in the array - need to check at each index that
    344         // we haven't exceeded size.
    345         // may have fewer initializers than elements in the array - need to default construct
    346         // remaining elements.
    347         // To accomplish this, generate switch statement, consuming all of expander's elements
    348         Statement * InitImpl_old::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) {
    349                 if ( ! init ) return nullptr;
    350                 CompoundStmt * block = new CompoundStmt();
    351                 build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) );
    352                 if ( block->get_kids().empty() ) {
    353                         delete block;
    354                         return nullptr;
    355                 } else {
    356                         init = nullptr; // init was consumed in creating the list init
    357                         return block;
    358                 }
    359         }
    360 
    361         Statement * ExprImpl_old::buildListInit( UntypedExpr *, std::list< Expression * > & ) {
    362                 return nullptr;
    363         }
    364 
    365         Statement * InitExpander_old::buildListInit( UntypedExpr * dst ) {
    366                 return expander->buildListInit( dst, indices );
    367         }
    368108
    369109class InitExpander_new::ExpanderImpl {
     
    537277}
    538278
    539         Type * getTypeofThis( FunctionType * ftype ) {
    540                 assertf( ftype, "getTypeofThis: nullptr ftype" );
    541                 ObjectDecl * thisParam = getParamThis( ftype );
    542                 ReferenceType * refType = strict_dynamic_cast< ReferenceType * >( thisParam->type );
    543                 return refType->base;
    544         }
    545 
    546279        const ast::Type * getTypeofThis( const ast::FunctionType * ftype ) {
    547280                assertf( ftype, "getTypeofThis: nullptr ftype" );
     
    554287        }
    555288
    556         ObjectDecl * getParamThis( FunctionType * ftype ) {
    557                 assertf( ftype, "getParamThis: nullptr ftype" );
    558                 auto & params = ftype->parameters;
    559                 assertf( ! params.empty(), "getParamThis: ftype with 0 parameters: %s", toString( ftype ).c_str() );
    560                 return strict_dynamic_cast< ObjectDecl * >( params.front() );
    561         }
    562 
    563289        const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func) {
    564290                assertf( func, "getParamThis: nullptr ftype" );
     
    566292                assertf( ! params.empty(), "getParamThis: ftype with 0 parameters: %s", toString( func ).c_str());
    567293                return params.front().strict_as<ast::ObjectDecl>();
    568         }
    569 
    570         bool tryConstruct( DeclarationWithType * dwt ) {
    571                 ObjectDecl * objDecl = dynamic_cast< ObjectDecl * >( dwt );
    572                 if ( ! objDecl ) return false;
    573                 return (objDecl->get_init() == nullptr ||
    574                                 ( objDecl->get_init() != nullptr && objDecl->get_init()->get_maybeConstructed() ))
    575                         && ! objDecl->get_storageClasses().is_extern
    576                         && isConstructable( objDecl->type );
    577         }
    578 
    579         bool isConstructable( Type * type ) {
    580                 return ! dynamic_cast< VarArgsType * >( type ) && ! dynamic_cast< ReferenceType * >( type ) && ! dynamic_cast< FunctionType * >( type ) && ! Tuples::isTtype( type );
    581294        }
    582295
     
    595308        }
    596309
    597         struct CallFinder_old {
    598                 CallFinder_old( const std::list< std::string > & names ) : names( names ) {}
    599 
    600                 void postvisit( ApplicationExpr * appExpr ) {
    601                         handleCallExpr( appExpr );
    602                 }
    603 
    604                 void postvisit( UntypedExpr * untypedExpr ) {
    605                         handleCallExpr( untypedExpr );
    606                 }
    607 
    608                 std::list< Expression * > * matches;
    609         private:
    610                 const std::list< std::string > names;
    611 
    612                 template< typename CallExpr >
    613                 void handleCallExpr( CallExpr * expr ) {
    614                         std::string fname = getFunctionName( expr );
    615                         if ( std::find( names.begin(), names.end(), fname ) != names.end() ) {
    616                                 matches->push_back( expr );
    617                         }
    618                 }
    619         };
    620 
    621310        struct CallFinder_new final {
    622311                std::vector< const ast::Expr * > matches;
     
    636325        };
    637326
    638         void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) {
    639                 static PassVisitor<CallFinder_old> finder( std::list< std::string >{ "?{}", "^?{}" } );
    640                 finder.pass.matches = &matches;
    641                 maybeAccept( stmt, finder );
    642         }
    643 
    644327        std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt ) {
    645328                ast::Pass< CallFinder_new > finder{ std::vector< std::string >{ "?{}", "^?{}" } };
     
    648331        }
    649332
    650         Expression * getCtorDtorCall( Statement * stmt ) {
    651                 std::list< Expression * > matches;
    652                 collectCtorDtorCalls( stmt, matches );
    653                 assertf( matches.size() <= 1, "%zd constructor/destructors found in %s", matches.size(), toString( stmt ).c_str() );
    654                 return matches.size() == 1 ? matches.front() : nullptr;
    655         }
    656 
    657333        namespace {
    658                 DeclarationWithType * getCalledFunction( Expression * expr );
    659 
    660                 template<typename CallExpr>
    661                 DeclarationWithType * handleDerefCalledFunction( CallExpr * expr ) {
    662                         // (*f)(x) => should get "f"
    663                         std::string name = getFunctionName( expr );
    664                         assertf( name == "*?", "Unexpected untyped expression: %s", name.c_str() );
    665                         assertf( ! expr->get_args().empty(), "Cannot get called function from dereference with no arguments" );
    666                         return getCalledFunction( expr->get_args().front() );
    667                 }
    668 
    669                 DeclarationWithType * getCalledFunction( Expression * expr ) {
    670                         assert( expr );
    671                         if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
    672                                 return varExpr->var;
    673                         } else if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( expr ) ) {
    674                                 return memberExpr->member;
    675                         } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    676                                 return getCalledFunction( castExpr->arg );
    677                         } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( expr ) ) {
    678                                 return handleDerefCalledFunction( untypedExpr );
    679                         } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
    680                                 return handleDerefCalledFunction( appExpr );
    681                         } else if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( expr ) ) {
    682                                 return getCalledFunction( addrExpr->arg );
    683                         } else if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( expr ) ) {
    684                                 return getCalledFunction( commaExpr->arg2 );
    685                         }
    686                         return nullptr;
    687                 }
    688 
    689                 DeclarationWithType * getFunctionCore( const Expression * expr ) {
    690                         if ( const auto * appExpr = dynamic_cast< const ApplicationExpr * >( expr ) ) {
    691                                 return getCalledFunction( appExpr->function );
    692                         } else if ( const auto * untyped = dynamic_cast< const UntypedExpr * >( expr ) ) {
    693                                 return getCalledFunction( untyped->function );
    694                         }
    695                         assertf( false, "getFunction with unknown expression: %s", toString( expr ).c_str() );
    696                 }
    697         }
    698 
    699         DeclarationWithType * getFunction( Expression * expr ) {
    700                 return getFunctionCore( expr );
    701         }
    702 
    703         const DeclarationWithType * getFunction( const Expression * expr ) {
    704                 return getFunctionCore( expr );
    705         }
    706 
    707         ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) {
    708                 ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr );
    709                 if ( ! appExpr ) return nullptr;
    710                 DeclarationWithType * function = getCalledFunction( appExpr->get_function() );
    711                 assertf( function, "getCalledFunction returned nullptr: %s", toString( appExpr->get_function() ).c_str() );
    712                 // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor
    713                 // will call all member dtors, and some members may have a user defined dtor.
    714                 return function->get_linkage() == LinkageSpec::Intrinsic ? appExpr : nullptr;
    715         }
    716 
    717         namespace {
    718                 template <typename Predicate>
    719                 bool allofCtorDtor( Statement * stmt, const Predicate & pred ) {
    720                         std::list< Expression * > callExprs;
    721                         collectCtorDtorCalls( stmt, callExprs );
    722                         return std::all_of( callExprs.begin(), callExprs.end(), pred);
    723                 }
    724 
    725334                template <typename Predicate>
    726335                bool allofCtorDtor( const ast::Stmt * stmt, const Predicate & pred ) {
     
    728337                        return std::all_of( callExprs.begin(), callExprs.end(), pred );
    729338                }
    730         }
    731 
    732         bool isIntrinsicSingleArgCallStmt( Statement * stmt ) {
    733                 return allofCtorDtor( stmt, []( Expression * callExpr ){
    734                         if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) {
    735                                 FunctionType *funcType = GenPoly::getFunctionType( appExpr->function->result );
    736                                 assert( funcType );
    737                                 return funcType->get_parameters().size() == 1;
    738                         }
    739                         return false;
    740                 });
    741339        }
    742340
     
    751349                        return false;
    752350                });
    753         }
    754 
    755         bool isIntrinsicCallStmt( Statement * stmt ) {
    756                 return allofCtorDtor( stmt, []( Expression * callExpr ) {
    757                         return isIntrinsicCallExpr( callExpr );
    758                 });
    759         }
    760 
    761         namespace {
    762                 template<typename CallExpr>
    763                 Expression *& callArg( CallExpr * callExpr, unsigned int pos ) {
    764                         if ( pos >= callExpr->get_args().size() ) assertf( false, "getCallArg for argument that doesn't exist: (%u); %s.", pos, toString( callExpr ).c_str() );
    765                         for ( Expression *& arg : callExpr->get_args() ) {
    766                                 if ( pos == 0 ) return arg;
    767                                 pos--;
    768                         }
    769                         assert( false );
    770                 }
    771         }
    772 
    773         Expression *& getCallArg( Expression * callExpr, unsigned int pos ) {
    774                 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( callExpr ) ) {
    775                         return callArg( appExpr, pos );
    776                 } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( callExpr ) ) {
    777                         return callArg( untypedExpr, pos );
    778                 } else if ( TupleAssignExpr * tupleExpr = dynamic_cast< TupleAssignExpr * > ( callExpr ) ) {
    779                         std::list< Statement * > & stmts = tupleExpr->get_stmtExpr()->get_statements()->get_kids();
    780                         assertf( ! stmts.empty(), "TupleAssignExpr somehow has no statements." );
    781                         ExprStmt * stmt = strict_dynamic_cast< ExprStmt * >( stmts.back() );
    782                         TupleExpr * tuple = strict_dynamic_cast< TupleExpr * >( stmt->get_expr() );
    783                         assertf( ! tuple->get_exprs().empty(), "TupleAssignExpr somehow has empty tuple expr." );
    784                         return getCallArg( tuple->get_exprs().front(), pos );
    785                 } else if ( ImplicitCopyCtorExpr * copyCtor = dynamic_cast< ImplicitCopyCtorExpr * >( callExpr ) ) {
    786                         return getCallArg( copyCtor->callExpr, pos );
    787                 } else {
    788                         assertf( false, "Unexpected expression type passed to getCallArg: %s", toString( callExpr ).c_str() );
    789                 }
    790         }
    791 
    792         namespace {
    793                 std::string funcName( Expression * func );
    794 
    795                 template<typename CallExpr>
    796                 std::string handleDerefName( CallExpr * expr ) {
    797                         // (*f)(x) => should get name "f"
    798                         std::string name = getFunctionName( expr );
    799                         assertf( name == "*?", "Unexpected untyped expression: %s", name.c_str() );
    800                         assertf( ! expr->get_args().empty(), "Cannot get function name from dereference with no arguments" );
    801                         return funcName( expr->get_args().front() );
    802                 }
    803 
    804                 std::string funcName( Expression * func ) {
    805                         if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( func ) ) {
    806                                 return nameExpr->get_name();
    807                         } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( func ) ) {
    808                                 return varExpr->get_var()->get_name();
    809                         } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( func ) ) {
    810                                 return funcName( castExpr->get_arg() );
    811                         } else if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( func ) ) {
    812                                 return memberExpr->get_member()->get_name();
    813                         } else if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * > ( func ) ) {
    814                                 return funcName( memberExpr->get_member() );
    815                         } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( func ) ) {
    816                                 return handleDerefName( untypedExpr );
    817                         } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( func ) ) {
    818                                 return handleDerefName( appExpr );
    819                         } else if ( ConstructorExpr * ctorExpr = dynamic_cast< ConstructorExpr * >( func ) ) {
    820                                 return funcName( getCallArg( ctorExpr->get_callExpr(), 0 ) );
    821                         } else {
    822                                 assertf( false, "Unexpected expression type being called as a function in call expression: %s", toString( func ).c_str() );
    823                         }
    824                 }
    825         }
    826 
    827         std::string getFunctionName( Expression * expr ) {
    828                 // there's some unforunate overlap here with getCalledFunction. Ideally this would be able to use getCalledFunction and
    829                 // return the name of the DeclarationWithType, but this needs to work for NameExpr and UntypedMemberExpr, where getCalledFunction
    830                 // can't possibly do anything reasonable.
    831                 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr ) ) {
    832                         return funcName( appExpr->get_function() );
    833                 } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * > ( expr ) ) {
    834                         return funcName( untypedExpr->get_function() );
    835                 } else {
    836                         std::cerr << expr << std::endl;
    837                         assertf( false, "Unexpected expression type passed to getFunctionName" );
    838                 }
    839         }
    840 
    841         Type * getPointerBase( Type * type ) {
    842                 if ( PointerType * ptrType = dynamic_cast< PointerType * >( type ) ) {
    843                         return ptrType->get_base();
    844                 } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) {
    845                         return arrayType->get_base();
    846                 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( type ) ) {
    847                         return refType->get_base();
    848                 } else {
    849                         return nullptr;
    850                 }
    851         }
    852 
    853         Type * isPointerType( Type * type ) {
    854                 return getPointerBase( type ) ? type : nullptr;
    855         }
    856 
    857         ApplicationExpr * createBitwiseAssignment( Expression * dst, Expression * src ) {
    858                 static FunctionDecl * assign = nullptr;
    859                 if ( ! assign ) {
    860                         // temporary? Generate a fake assignment operator to represent bitwise assignments.
    861                         // This operator could easily exist as a real function, but it's tricky because nothing should resolve to this function.
    862                         TypeDecl * td = new TypeDecl( "T", noStorageClasses, nullptr, TypeDecl::Dtype, true );
    863                         assign = new FunctionDecl( "?=?", noStorageClasses, LinkageSpec::Intrinsic, SymTab::genAssignType( new TypeInstType( noQualifiers, td->name, td ) ), nullptr );
    864                 }
    865                 if ( dynamic_cast< ReferenceType * >( dst->result ) ) {
    866                         for (int depth = dst->result->referenceDepth(); depth > 0; depth--) {
    867                                 dst = new AddressExpr( dst );
    868                         }
    869                 } else {
    870                         dst = new CastExpr( dst, new ReferenceType( noQualifiers, dst->result->clone() ) );
    871                 }
    872                 if ( dynamic_cast< ReferenceType * >( src->result ) ) {
    873                         for (int depth = src->result->referenceDepth(); depth > 0; depth--) {
    874                                 src = new AddressExpr( src );
    875                         }
    876                 }
    877                 return new ApplicationExpr( VariableExpr::functionPointer( assign ), { dst, src } );
    878351        }
    879352
     
    907380                return app;
    908381        }
    909 
    910         struct ConstExprChecker : public WithShortCircuiting {
    911                 // most expressions are not const expr
    912                 void previsit( Expression * ) { isConstExpr = false; visit_children = false; }
    913 
    914                 void previsit( AddressExpr *addressExpr ) {
    915                         visit_children = false;
    916 
    917                         // address of a variable or member expression is constexpr
    918                         Expression * arg = addressExpr->get_arg();
    919                         if ( ! dynamic_cast< NameExpr * >( arg) && ! dynamic_cast< VariableExpr * >( arg ) && ! dynamic_cast< MemberExpr * >( arg ) && ! dynamic_cast< UntypedMemberExpr * >( arg ) ) isConstExpr = false;
    920                 }
    921 
    922                 // these expressions may be const expr, depending on their children
    923                 void previsit( SizeofExpr * ) {}
    924                 void previsit( AlignofExpr * ) {}
    925                 void previsit( UntypedOffsetofExpr * ) {}
    926                 void previsit( OffsetofExpr * ) {}
    927                 void previsit( OffsetPackExpr * ) {}
    928                 void previsit( CommaExpr * ) {}
    929                 void previsit( LogicalExpr * ) {}
    930                 void previsit( ConditionalExpr * ) {}
    931                 void previsit( CastExpr * ) {}
    932                 void previsit( ConstantExpr * ) {}
    933 
    934                 void previsit( VariableExpr * varExpr ) {
    935                         visit_children = false;
    936 
    937                         if ( EnumInstType * inst = dynamic_cast< EnumInstType * >( varExpr->result ) ) {
    938                                 long long int value;
    939                                 if ( inst->baseEnum->valueOf( varExpr->var, value ) ) {
    940                                         // enumerators are const expr
    941                                         return;
    942                                 }
    943                         }
    944                         isConstExpr = false;
    945                 }
    946 
    947                 bool isConstExpr = true;
    948         };
    949382
    950383        struct ConstExprChecker_new : public ast::WithShortCircuiting {
     
    991424        };
    992425
    993         bool isConstExpr( Expression * expr ) {
    994                 if ( expr ) {
    995                         PassVisitor<ConstExprChecker> checker;
    996                         expr->accept( checker );
    997                         return checker.pass.isConstExpr;
    998                 }
    999                 return true;
    1000         }
    1001 
    1002         bool isConstExpr( Initializer * init ) {
    1003                 if ( init ) {
    1004                         PassVisitor<ConstExprChecker> checker;
    1005                         init->accept( checker );
    1006                         return checker.pass.isConstExpr;
    1007                 } // if
    1008                 // for all intents and purposes, no initializer means const expr
    1009                 return true;
    1010         }
    1011 
    1012426        bool isConstExpr( const ast::Expr * expr ) {
    1013427                if ( expr ) {
     
    1029443        }
    1030444
    1031         const FunctionDecl * isCopyFunction( const Declaration * decl, const std::string & fname ) {
    1032                 const FunctionDecl * function = dynamic_cast< const FunctionDecl * >( decl );
    1033                 if ( ! function ) return nullptr;
    1034                 if ( function->name != fname ) return nullptr;
    1035                 FunctionType * ftype = function->type;
    1036                 if ( ftype->parameters.size() != 2 ) return nullptr;
    1037 
    1038                 Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() );
    1039                 Type * t2 = ftype->parameters.back()->get_type();
    1040                 assert( t1 );
    1041 
    1042                 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, SymTab::Indexer() ) ) {
    1043                         return function;
    1044                 } else {
    1045                         return nullptr;
    1046                 }
    1047         }
    1048 
    1049445bool isAssignment( const ast::FunctionDecl * decl ) {
    1050446        return CodeGen::isAssignment( decl->name ) && isCopyFunction( decl );
     
    1073469        return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2 );
    1074470}
    1075 
    1076 
    1077         const FunctionDecl * isAssignment( const Declaration * decl ) {
    1078                 return isCopyFunction( decl, "?=?" );
    1079         }
    1080         const FunctionDecl * isDestructor( const Declaration * decl ) {
    1081                 if ( CodeGen::isDestructor( decl->name ) ) {
    1082                         return dynamic_cast< const FunctionDecl * >( decl );
    1083                 }
    1084                 return nullptr;
    1085         }
    1086         const FunctionDecl * isDefaultConstructor( const Declaration * decl ) {
    1087                 if ( CodeGen::isConstructor( decl->name ) ) {
    1088                         if ( const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl ) ) {
    1089                                 if ( func->type->parameters.size() == 1 ) {
    1090                                         return func;
    1091                                 }
    1092                         }
    1093                 }
    1094                 return nullptr;
    1095         }
    1096         const FunctionDecl * isCopyConstructor( const Declaration * decl ) {
    1097                 return isCopyFunction( decl, "?{}" );
    1098         }
    1099471
    1100472        #if defined( __x86_64 ) || defined( __i386 ) // assembler comment to prevent assembler warning message
     
    1105477        static const char * const data_section =  ".data" ASM_COMMENT;
    1106478        static const char * const tlsd_section = ".tdata" ASM_COMMENT;
    1107         void addDataSectionAttribute( ObjectDecl * objDecl ) {
    1108                 const bool is_tls = objDecl->get_storageClasses().is_threadlocal_any();
    1109                 const char * section = is_tls ? tlsd_section : data_section;
    1110                 objDecl->attributes.push_back(new Attribute("section", {
    1111                         new ConstantExpr( Constant::from_string( section ) )
    1112                 }));
    1113         }
    1114479
    1115480        void addDataSectionAttribute( ast::ObjectDecl * objDecl ) {
  • src/InitTweak/InitTweak.h

    r790d835 rc6b4432  
    2222
    2323#include "AST/Fwd.hpp"        // for AST nodes
    24 #include "SynTree/SynTree.h"  // for Visitor Nodes
    2524
    2625// helper functions for initialization
    2726namespace InitTweak {
    28         const FunctionDecl * isAssignment( const Declaration * decl );
    29         const FunctionDecl * isDestructor( const Declaration * decl );
    30         const FunctionDecl * isDefaultConstructor( const Declaration * decl );
    31         const FunctionDecl * isCopyConstructor( const Declaration * decl );
    32         const FunctionDecl * isCopyFunction( const Declaration * decl, const std::string & fname );
    3327        bool isAssignment( const ast::FunctionDecl * decl );
    3428        bool isDestructor( const ast::FunctionDecl * decl );
     
    3832
    3933        /// returns the base type of the first parameter to a constructor/destructor/assignment function
    40         Type * getTypeofThis( FunctionType * ftype );
    4134        const ast::Type * getTypeofThis( const ast::FunctionType * ftype );
    4235
    4336        /// returns the first parameter of a constructor/destructor/assignment function
    44         ObjectDecl * getParamThis( FunctionType * ftype );
    4537        const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func);
    4638
    4739        /// generate a bitwise assignment operation.
    48         ApplicationExpr * createBitwiseAssignment( Expression * dst, Expression * src );
    49 
    5040        ast::Expr * createBitwiseAssignment( const ast::Expr * dst, const ast::Expr * src);
    5141
    5242        /// transform Initializer into an argument list that can be passed to a call expression
    53         std::list< Expression * > makeInitList( Initializer * init );
    5443        std::vector< ast::ptr< ast::Expr > > makeInitList( const ast::Init * init );
    5544
    5645        /// True if the resolver should try to construct dwt
    57         bool tryConstruct( DeclarationWithType * dwt );
    5846        bool tryConstruct( const ast::DeclWithType * dwt );
    5947
    6048        /// True if the type can have a user-defined constructor
    61         bool isConstructable( Type * t );
    6249        bool isConstructable( const ast::Type * t );
    6350
    6451        /// True if the Initializer contains designations
    65         bool isDesignated( Initializer * init );
    6652        bool isDesignated( const ast::Init * init );
    6753
    6854        /// True if the ObjectDecl's Initializer nesting level is not deeper than the depth of its
    6955        /// type, where the depth of its type is the number of nested ArrayTypes + 1
    70         bool checkInitDepth( ObjectDecl * objDecl );
    7156        bool checkInitDepth( const ast::ObjectDecl * objDecl );
    72 
    73         /// returns the declaration of the function called by the expr (must be ApplicationExpr or UntypedExpr)
    74         DeclarationWithType * getFunction( Expression * expr );
    75         const DeclarationWithType * getFunction( const Expression * expr );
    76 
    77         /// Non-Null if expr is a call expression whose target function is intrinsic
    78         ApplicationExpr * isIntrinsicCallExpr( Expression * expr );
    7957
    8058        /// True if stmt is a call statement where the function called is intrinsic and takes one parameter.
    8159        /// Intended to be used for default ctor/dtor calls, but might have use elsewhere.
    8260        /// Currently has assertions that make it less than fully general.
    83         bool isIntrinsicSingleArgCallStmt( Statement * stmt );
    8461        bool isIntrinsicSingleArgCallStmt( const ast::Stmt * stmt );
    8562
    86         /// True if stmt is a call statement where the function called is intrinsic.
    87         bool isIntrinsicCallStmt( Statement * stmt );
    88 
    8963        /// get all Ctor/Dtor call expressions from a Statement
    90         void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches );
    9164        std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt );
    9265
    93         /// get the Ctor/Dtor call expression from a Statement that looks like a generated ctor/dtor call
    94         Expression * getCtorDtorCall( Statement * stmt );
    95 
    96         /// returns the name of the function being called
    97         std::string getFunctionName( Expression * expr );
    98 
    99         /// returns the argument to a call expression in position N indexed from 0
    100         Expression *& getCallArg( Expression * callExpr, unsigned int pos );
    101 
    102         /// returns the base type of a PointerType or ArrayType, else returns NULL
    103         Type * getPointerBase( Type * );
    104 
    105         /// returns the argument if it is a PointerType or ArrayType, else returns NULL
    106         Type * isPointerType( Type * );
    107 
    10866        /// returns true if expr is trivially a compile-time constant
    109         bool isConstExpr( Expression * expr );
    110         bool isConstExpr( Initializer * init );
    111 
    11267        bool isConstExpr( const ast::Expr * expr );
    11368        bool isConstExpr( const ast::Init * init );
     
    12277        ///    .section .data#,"a"
    12378        /// to avoid assembler warning "ignoring changed section attributes for .data"
    124         void addDataSectionAttribute( ObjectDecl * objDecl );
    125 
    12679        void addDataSectionAttribute( ast::ObjectDecl * objDecl );
    127 
    128         class InitExpander_old {
    129         public:
    130                 // expand by stepping through init to get each list of arguments
    131                 InitExpander_old( Initializer * init );
    132 
    133                 // always expand to expr
    134                 InitExpander_old( Expression * expr );
    135 
    136                 // iterator-like interface
    137                 std::list< Expression * > operator*();
    138                 InitExpander_old & operator++();
    139 
    140                 // builds statement which has the same semantics as a C-style list initializer
    141                 // (for array initializers) using callExpr as the base expression to perform initialization
    142                 Statement * buildListInit( UntypedExpr * callExpr );
    143                 void addArrayIndex( Expression * index, Expression * dimension );
    144                 void clearArrayIndices();
    145                 bool addReference();
    146 
    147                 class ExpanderImpl;
    148 
    149                 typedef std::list< Expression * > IndexList;
    150         private:
    151                 std::shared_ptr< ExpanderImpl > expander;
    152                 std::list< Expression * > cur;
    153 
    154                 // invariant: list of size 2N (elements come in pairs [index, dimension])
    155                 IndexList indices;
    156         };
    15780
    15881        class InitExpander_new {
  • src/InitTweak/module.mk

    r790d835 rc6b4432  
    2424        InitTweak/FixGlobalInit.cc \
    2525        InitTweak/FixGlobalInit.h \
    26         InitTweak/FixInit.cc \
    2726        InitTweak/FixInit.h \
    2827        InitTweak/FixInitNew.cpp
  • src/MakeLibCfa.h

    r790d835 rc6b4432  
    2424
    2525namespace LibCfa {
    26         void makeLibCfa( std::list< Declaration* > &prelude );
    2726        void makeLibCfa( ast::TranslationUnit & translationUnit );
    2827} // namespace LibCfa
  • src/Makefile.am

    r790d835 rc6b4432  
    2222      CompilationState.cc \
    2323      CompilationState.h \
    24       MakeLibCfa.cc \
    2524          MakeLibCfaNew.cpp \
    2625        MakeLibCfa.h
     
    4241include AST/module.mk
    4342include CodeGen/module.mk
    44 include CodeTools/module.mk
    4543include Concurrency/module.mk
    4644include Common/module.mk
     
    5149include ResolvExpr/module.mk
    5250include SymTab/module.mk
    53 include SynTree/module.mk
    5451include Tuples/module.mk
    5552include Validate/module.mk
    5653include Virtual/module.mk
    5754
    58 $(addprefix $(srcdir)/, ResolvExpr/ConversionCost.cc ResolvExpr/CommonType.cc SymTab/ManglerCommon.cc) : $(srcdir)/SynTree/Type.h
     55$(addprefix $(srcdir)/, ResolvExpr/ConversionCost.cc ResolvExpr/CommonType.cc SymTab/ManglerCommon.cc) : $(srcdir)/AST/Type.hpp
    5956
    6057$(srcdir)/AST/Type.hpp : BasicTypes-gen.cc
  • src/Parser/RunParser.cpp

    r790d835 rc6b4432  
    1616#include "RunParser.hpp"
    1717
    18 #include "AST/Convert.hpp"                  // for convert
    1918#include "AST/TranslationUnit.hpp"          // for TranslationUnit
    20 #include "CodeTools/TrackLoc.h"             // for fillLocations
    2119#include "Common/CodeLocationTools.hpp"     // for forceFillCodeLocations
    2220#include "Parser/DeclarationNode.h"         // for DeclarationNode, buildList
  • src/Parser/parser.yy

    r790d835 rc6b4432  
    5757#include "Common/SemanticError.h"                                               // error_str
    5858#include "Common/utility.h"                                                             // for maybeMoveBuild, maybeBuild, CodeLo...
    59 
    60 #include "SynTree/Attribute.h"                                                  // for Attribute
    6159
    6260// lex uses __null in a boolean context, it's fine.
  • src/ResolvExpr/AdjustExprType.cc

    r790d835 rc6b4432  
    1919#include "AST/Type.hpp"
    2020#include "AST/TypeEnvironment.hpp"
    21 #include "Common/PassVisitor.h"
    22 #include "SymTab/Indexer.h"       // for Indexer
    23 #include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Kind::Ftype
    24 #include "SynTree/Mutator.h"      // for Mutator
    25 #include "SynTree/Type.h"         // for PointerType, TypeInstType, Type
    26 #include "TypeEnvironment.h"      // for EqvClass, TypeEnvironment
    2721
    2822namespace ResolvExpr {
    29 
    30 namespace {
    31         class AdjustExprType_old final : public WithShortCircuiting {
    32                 public:
    33                 AdjustExprType_old( const TypeEnvironment & env, const SymTab::Indexer & indexer );
    34                 void premutate( VoidType * ) { visit_children = false; }
    35                 void premutate( BasicType * ) { visit_children = false; }
    36                 void premutate( PointerType * ) { visit_children = false; }
    37                 void premutate( ArrayType * ) { visit_children = false; }
    38                 void premutate( FunctionType * ) { visit_children = false; }
    39                 void premutate( StructInstType * ) { visit_children = false; }
    40                 void premutate( UnionInstType * ) { visit_children = false; }
    41                 void premutate( EnumInstType * ) { visit_children = false; }
    42                 void premutate( TraitInstType * ) { visit_children = false; }
    43                 void premutate( TypeInstType * ) { visit_children = false; }
    44                 void premutate( TupleType * ) { visit_children = false; }
    45                 void premutate( VarArgsType * ) { visit_children = false; }
    46                 void premutate( ZeroType * ) { visit_children = false; }
    47                 void premutate( OneType * ) { visit_children = false; }
    48 
    49                 Type * postmutate( ArrayType * arrayType );
    50                 Type * postmutate( FunctionType * functionType );
    51                 Type * postmutate( TypeInstType * aggregateUseType );
    52 
    53                 private:
    54                 const TypeEnvironment & env;
    55                 const SymTab::Indexer & indexer;
    56         };
    57 
    58         AdjustExprType_old::AdjustExprType_old( const TypeEnvironment &env, const SymTab::Indexer &indexer )
    59                 : env( env ), indexer( indexer ) {
    60         }
    61 
    62         Type * AdjustExprType_old::postmutate( ArrayType * arrayType ) {
    63                 PointerType * pointerType = new PointerType{ arrayType->get_qualifiers(), arrayType->base };
    64                 arrayType->base = nullptr;
    65                 delete arrayType;
    66                 return pointerType;
    67         }
    68 
    69         Type * AdjustExprType_old::postmutate( FunctionType * functionType ) {
    70                 return new PointerType{ Type::Qualifiers(), functionType };
    71         }
    72 
    73         Type * AdjustExprType_old::postmutate( TypeInstType * typeInst ) {
    74                 if ( const EqvClass * eqvClass = env.lookup( typeInst->get_name() ) ) {
    75                         if ( eqvClass->data.kind == TypeDecl::Ftype ) {
    76                                 return new PointerType{ Type::Qualifiers(), typeInst };
    77                         }
    78                 } else if ( const NamedTypeDecl * ntDecl = indexer.lookupType( typeInst->get_name() ) ) {
    79                         if ( const TypeDecl * tyDecl = dynamic_cast< const TypeDecl * >( ntDecl ) ) {
    80                                 if ( tyDecl->get_kind() == TypeDecl::Ftype ) {
    81                                         return new PointerType{ Type::Qualifiers(), typeInst };
    82                                 } // if
    83                         } // if
    84                 } // if
    85                 return typeInst;
    86         }
    87 } // anonymous namespace
    88 
    89 void adjustExprType( Type *&type, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    90         PassVisitor<AdjustExprType_old> adjuster( env, indexer );
    91         Type * newType = type->acceptMutator( adjuster );
    92         type = newType;
    93 }
    94 
    95 void adjustExprType( Type *& type ) {
    96         TypeEnvironment env;
    97         SymTab::Indexer indexer;
    98         adjustExprType( type, env, indexer );
    99 }
    10023
    10124namespace {
  • src/ResolvExpr/CastCost.cc

    r790d835 rc6b4432  
    2626#include "ResolvExpr/ConversionCost.h"   // for conversionCost
    2727#include "ResolvExpr/PtrsCastable.hpp"   // for ptrsCastable
    28 #include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment, EqvClass
    2928#include "ResolvExpr/typeops.h"          // for ptrsCastable
    3029#include "ResolvExpr/Unify.h"            // for typesCompatibleIgnoreQualifiers
    31 #include "SymTab/Indexer.h"              // for Indexer
    32 #include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl
    33 #include "SynTree/Type.h"                // for PointerType, Type, TypeInstType
    3430
    3531#if 0
     
    4036
    4137namespace ResolvExpr {
    42         struct CastCost_old : public ConversionCost {
    43           public:
    44                 CastCost_old( const Type * dest, bool srcIsLvalue,
    45                         const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
    46 
    47                 using ConversionCost::previsit;
    48                 using ConversionCost::postvisit;
    49                 void postvisit( const BasicType * basicType );
    50                 void postvisit( const PointerType * pointerType );
    51         };
    52 
    53         Cost castCost( const Type * src, const Type * dest, bool srcIsLvalue,
    54                         const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    55                 if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType * >( dest ) ) {
    56                         if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->name ) ) {
    57                                 if ( eqvClass->type ) {
    58                                         return castCost( src, eqvClass->type, srcIsLvalue, indexer, env );
    59                                 } else {
    60                                         return Cost::infinity;
    61                                 }
    62                         } else if ( const NamedTypeDecl * namedType = indexer.lookupType( destAsTypeInst->name ) ) {
    63                                 // all typedefs should be gone by this point
    64                                 const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( namedType );
    65                                 if ( type->base ) {
    66                                         return castCost( src, type->base, srcIsLvalue, indexer, env ) + Cost::safe;
    67                                 } // if
    68                         } // if
    69                 } // if
    70 
    71                 PRINT(
    72                         std::cerr << "castCost ::: src is ";
    73                         src->print( std::cerr );
    74                         std::cerr << std::endl << "dest is ";
    75                         dest->print( std::cerr );
    76                         std::cerr << std::endl << "env is" << std::endl;
    77                         env.print( std::cerr, 8 );
    78                 )
    79 
    80                 if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
    81                         PRINT( std::cerr << "compatible!" << std::endl; )
    82                         return Cost::zero;
    83                 } else if ( dynamic_cast< const VoidType * >( dest ) ) {
    84                         return Cost::safe;
    85                 } else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) {
    86                         PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
    87                         return convertToReferenceCost( src, refType, srcIsLvalue, indexer, env, [](const Type * t1, const Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
    88                                 return ptrsCastable( t1, t2, env, indexer );
    89                         });
    90                 } else {
    91                         PassVisitor<CastCost_old> converter(
    92                                 dest, srcIsLvalue, indexer, env,
    93                                 (Cost (*)( const Type *, const Type *, bool, const SymTab::Indexer &, const TypeEnvironment & ))
    94                                         castCost );
    95                         src->accept( converter );
    96                         if ( converter.pass.get_cost() == Cost::infinity ) {
    97                                 return Cost::infinity;
    98                         } else {
    99                                 // xxx - why are we adding cost 0 here?
    100                                 return converter.pass.get_cost() + Cost::zero;
    101                         } // if
    102                 } // if
    103         }
    104 
    105         CastCost_old::CastCost_old( const Type * dest, bool srcIsLvalue,
    106                         const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
    107                 : ConversionCost( dest, srcIsLvalue, indexer, env, costFunc ) {
    108         }
    109 
    110         void CastCost_old::postvisit( const BasicType * basicType ) {
    111                 const PointerType * destAsPointer = dynamic_cast< const PointerType * >( dest );
    112                 if ( destAsPointer && basicType->isInteger() ) {
    113                         // necessary for, e.g. unsigned long => void *
    114                         cost = Cost::unsafe;
    115                 } else {
    116                         cost = conversionCost( basicType, dest, srcIsLvalue, indexer, env );
    117                 } // if
    118         }
    119 
    120         void CastCost_old::postvisit( const PointerType * pointerType ) {
    121                 if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) {
    122                         if ( pointerType->tq <= destAsPtr->tq && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
    123                                 cost = Cost::safe;
    124                         } else {
    125                                 TypeEnvironment newEnv( env );
    126                                 newEnv.add( pointerType->forall );
    127                                 newEnv.add( pointerType->base->forall );
    128                                 int castResult = ptrsCastable( pointerType->base, destAsPtr->base, newEnv, indexer );
    129                                 if ( castResult > 0 ) {
    130                                         cost = Cost::safe;
    131                                 } else if ( castResult < 0 ) {
    132                                         cost = Cost::infinity;
    133                                 } // if
    134                         } // if
    135                 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
    136                         if ( destAsBasic->isInteger() ) {
    137                                 // necessary for, e.g. void * => unsigned long
    138                                 cost = Cost::unsafe;
    139                         } // if
    140                 }
    141         }
    14238
    14339namespace {
     
    20096} // anonymous namespace
    20197
    202 
    203 
    20498Cost castCost(
    20599        const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
  • src/ResolvExpr/CommonType.cc

    r790d835 rc6b4432  
    2323#include "AST/Pass.hpp"
    2424#include "AST/Type.hpp"
    25 #include "Common/PassVisitor.h"
    26 #include "ResolvExpr/TypeEnvironment.h"  // for OpenVarSet, AssertionSet
    27 #include "SymTab/Indexer.h"              // for Indexer
    28 #include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl (ptr...
    29 #include "SynTree/Type.h"                // for BasicType, BasicType::Kind::...
    30 #include "SynTree/Visitor.h"             // for Visitor
    3125#include "Unify.h"                       // for unifyExact, WidenMode
    3226#include "typeops.h"                     // for isFtype
     
    4135
    4236namespace ResolvExpr {
    43         struct CommonType_old : public WithShortCircuiting {
    44                 CommonType_old( Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars );
    45                 Type * get_result() const { return result; }
    46 
    47                 void previsit( BaseSyntaxNode * ) { visit_children = false; }
    48 
    49                 void postvisit( VoidType * voidType );
    50                 void postvisit( BasicType * basicType );
    51                 void postvisit( PointerType * pointerType );
    52                 void postvisit( ArrayType * arrayType );
    53                 void postvisit( ReferenceType * refType );
    54                 void postvisit( FunctionType * functionType );
    55                 void postvisit( StructInstType * aggregateUseType );
    56                 void postvisit( UnionInstType * aggregateUseType );
    57                 void postvisit( EnumInstType * aggregateUseType );
    58                 void postvisit( TraitInstType * aggregateUseType );
    59                 void postvisit( TypeInstType * aggregateUseType );
    60                 void postvisit( TupleType * tupleType );
    61                 void postvisit( VarArgsType * varArgsType );
    62                 void postvisit( ZeroType * zeroType );
    63                 void postvisit( OneType * oneType );
    64 
    65           private:
    66                 template< typename Pointer > void getCommonWithVoidPointer( Pointer * voidPointer, Pointer * otherPointer );
    67                 template< typename RefType > void handleRefType( RefType * inst, Type * other );
    68 
    69                 Type * result;
    70                 Type * type2;                           // inherited
    71                 bool widenFirst, widenSecond;
    72                 const SymTab::Indexer &indexer;
    73                 TypeEnvironment &env;
    74                 const OpenVarSet &openVars;
    75         };
    76 
    77         Type * handleReference( Type * t1, Type * t2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment & env, const OpenVarSet &openVars ) {
    78                 Type * common = nullptr;
    79                 AssertionSet have, need;
    80                 OpenVarSet newOpen( openVars );
    81                 // need unify to bind type variables
    82                 if ( unify( t1, t2, env, have, need, newOpen, indexer, common ) ) {
    83                         PRINT(
    84                                 std::cerr << "unify success: " << widenFirst << " " << widenSecond << std::endl;
    85                         )
    86                         if ( (widenFirst || t2->tq <= t1->tq) && (widenSecond || t1->tq <= t2->tq) ) {
    87                                 PRINT(
    88                                         std::cerr << "widen okay" << std::endl;
    89                                 )
    90                                 common->tq |= t1->tq;
    91                                 common->tq |= t2->tq;
    92                                 return common;
    93                         }
    94                 }
    95                 PRINT(
    96                         std::cerr << "exact unify failed: " << t1 << " " << t2 << std::endl;
    97                 )
    98                 return nullptr;
    99         }
    100 
    101         Type * commonType( Type * type1, Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars ) {
    102                 PassVisitor<CommonType_old> visitor( type2, widenFirst, widenSecond, indexer, env, openVars );
    103 
    104                 int depth1 = type1->referenceDepth();
    105                 int depth2 = type2->referenceDepth();
    106                 if ( depth1 > 0 || depth2 > 0 ) {
    107                         int diff = depth1-depth2;
    108                         // TODO: should it be possible for commonType to generate complicated conversions? I would argue no, only conversions that involve types of the same reference level or a difference of 1 should be allowed.
    109                         // if ( diff > 1 || diff < -1 ) return nullptr;
    110 
    111                         // special case where one type has a reference depth of 1 larger than the other
    112                         if ( diff > 0 || diff < 0 ) {
    113                                 PRINT(
    114                                         std::cerr << "reference depth diff: " << diff << std::endl;
    115                                 )
    116                                 Type * result = nullptr;
    117                                 ReferenceType * ref1 = dynamic_cast< ReferenceType * >( type1 );
    118                                 ReferenceType * ref2 = dynamic_cast< ReferenceType * >( type2 );
    119                                 if ( diff > 0 ) {
    120                                         // deeper on the left
    121                                         assert( ref1 );
    122                                         result = handleReference( ref1->base, type2, widenFirst, widenSecond, indexer, env, openVars );
    123                                 } else {
    124                                         // deeper on the right
    125                                         assert( ref2 );
    126                                         result = handleReference( type1, ref2->base, widenFirst, widenSecond, indexer, env, openVars );
    127                                 }
    128                                 if ( result && ref1 ) {
    129                                         // formal is reference, so result should be reference
    130                                         PRINT(
    131                                                 std::cerr << "formal is reference; result should be reference" << std::endl;
    132                                         )
    133                                         result = new ReferenceType( ref1->tq, result );
    134                                 }
    135                                 PRINT(
    136                                         std::cerr << "common type of reference [" << type1 << "] and [" << type2 << "] is [" << result << "]" << std::endl;
    137                                 )
    138                                 return result;
    139                         }
    140                         // otherwise, both are reference types of the same depth and this is handled by the CommonType visitor.
    141                 }
    142 
    143                 type1->accept( visitor );
    144                 Type * result = visitor.pass.get_result();
    145                 if ( ! result ) {
    146                         // this appears to be handling for opaque type declarations
    147                         if ( widenSecond ) {
    148                                 if ( const TypeInstType * inst = dynamic_cast< const TypeInstType * >( type2 ) ) {
    149                                         if ( const NamedTypeDecl * nt = indexer.lookupType( inst->get_name() ) ) {
    150                                                 const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( nt );
    151                                                 if ( type->get_base() ) {
    152                                                         Type::Qualifiers tq1 = type1->tq, tq2 = type2->tq;
    153                                                         AssertionSet have, need;
    154                                                         OpenVarSet newOpen( openVars );
    155                                                         type1->tq = Type::Qualifiers();
    156                                                         type->get_base()->tq = tq1;
    157                                                         if ( unifyExact( type1, type->get_base(), env, have, need, newOpen, indexer ) ) {
    158                                                                 result = type1->clone();
    159                                                                 result->tq = tq1 | tq2;
    160                                                         } // if
    161                                                         type1->tq = tq1;
    162                                                         type->get_base()->tq = Type::Qualifiers();
    163                                                 } // if
    164                                         } // if
    165                                 } // if
    166                         } // if
    167                 } // if
    168 #ifdef DEBUG
    169                 std::cerr << "============= commonType" << std::endl << "type1 is ";
    170                 type1->print( std::cerr );
    171                 std::cerr << " type2 is ";
    172                 type2->print( std::cerr );
    173                 if ( result ) {
    174                         std::cerr << " common type is ";
    175                         result->print( std::cerr );
    176                 } else {
    177                         std::cerr << " no common type";
    178                 } // if
    179                 std::cerr << std::endl;
    180 #endif
    181                 return result;
    182         }
    18337
    18438        // GENERATED START, DO NOT EDIT
     
    488342                "Each basic type kind should have a corresponding row in the combined type matrix"
    489343        );
    490 
    491         CommonType_old::CommonType_old( Type * type2, bool widenFirst, bool widenSecond, const SymTab::Indexer &indexer, TypeEnvironment &env, const OpenVarSet &openVars )
    492                 : result( 0 ), type2( type2 ), widenFirst( widenFirst ), widenSecond( widenSecond ), indexer( indexer ), env( env ), openVars( openVars ) {
    493         }
    494 
    495         void CommonType_old::postvisit( VoidType * ) {}
    496 
    497         void CommonType_old::postvisit( BasicType * basicType ) {
    498                 if ( BasicType * otherBasic = dynamic_cast< BasicType * >( type2 ) ) {
    499                         BasicType::Kind newType = (BasicType::Kind)(int)commonTypes[ (ast::BasicType::Kind)(int)basicType->get_kind() ][ (ast::BasicType::Kind)(int)otherBasic->get_kind() ];
    500                         if ( ( ( newType == basicType->get_kind() && basicType->tq >= otherBasic->tq ) || widenFirst ) && ( ( newType == otherBasic->get_kind() && basicType->tq <= otherBasic->tq ) || widenSecond ) ) {
    501                                 result = new BasicType( basicType->tq | otherBasic->tq, newType );
    502                         } // if
    503                 } else if (  dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType * >( type2 ) ) {
    504                         // use signed int in lieu of the enum/zero/one type
    505                         BasicType::Kind newType = (BasicType::Kind)(int)commonTypes[ (ast::BasicType::Kind)(int)basicType->get_kind() ][ ast::BasicType::SignedInt ];
    506                         if ( ( ( newType == basicType->get_kind() && basicType->tq >= type2->tq ) || widenFirst ) && ( ( newType != basicType->get_kind() && basicType->tq <= type2->tq ) || widenSecond ) ) {
    507                                 result = new BasicType( basicType->tq | type2->tq, newType );
    508                         } // if
    509                 } else if ( const EnumInstType * enumInst = dynamic_cast< const EnumInstType * > ( type2 ) ) {
    510                         const EnumDecl* enumDecl = enumInst->baseEnum;
    511                         if ( const Type* baseType = enumDecl->base ) {
    512                                 result = baseType->clone();
    513                         } else {
    514                                 BasicType::Kind newType = (BasicType::Kind)(int)commonTypes[ (ast::BasicType::Kind)(int)basicType->get_kind() ][ ast::BasicType::SignedInt ];
    515                                 if ( ( ( newType == basicType->get_kind() && basicType->tq >= type2->tq ) || widenFirst ) && ( ( newType != basicType->get_kind() && basicType->tq <= type2->tq ) || widenSecond ) ) {
    516                                         result = new BasicType( basicType->tq | type2->tq, newType );
    517                                 } // if
    518                         }
    519                 }
    520         }
    521 
    522         template< typename Pointer >
    523         void CommonType_old::getCommonWithVoidPointer( Pointer * voidPointer, Pointer * otherPointer ) {
    524                 if ( TypeInstType * var = dynamic_cast< TypeInstType * >( otherPointer->get_base() ) ) {
    525                         OpenVarSet::const_iterator entry = openVars.find( var->get_name() );
    526                         if ( entry != openVars.end() ) {
    527                                 AssertionSet need, have;
    528                                 WidenMode widen( widenFirst, widenSecond );
    529                                 if ( entry != openVars.end() && ! env.bindVar(var, voidPointer->get_base(), entry->second, need, have, openVars, widen, indexer ) ) return;
    530                         }
    531                 }
    532                 result = voidPointer->clone();
    533                 result->tq |= otherPointer->tq;
    534         }
    535 
    536         void CommonType_old::postvisit( PointerType * pointerType ) {
    537                 if ( PointerType * otherPointer = dynamic_cast< PointerType * >( type2 ) ) {
    538                         // std::cerr << "commonType: two pointers: " << pointerType << " / " << otherPointer << std::endl;
    539                         if ( widenFirst && dynamic_cast< VoidType * >( otherPointer->get_base() ) && ! isFtype(pointerType->get_base()) ) {
    540                                 getCommonWithVoidPointer( otherPointer, pointerType );
    541                         } else if ( widenSecond && dynamic_cast< VoidType * >( pointerType->get_base() ) && ! isFtype(otherPointer->get_base()) ) {
    542                                 getCommonWithVoidPointer( pointerType, otherPointer );
    543                         } else if ( ( pointerType->get_base()->tq >= otherPointer->get_base()->tq || widenFirst )
    544                                            && ( pointerType->get_base()->tq <= otherPointer->get_base()->tq || widenSecond ) ) {
    545                                 // std::cerr << "middle case" << std::endl;
    546                                 Type::Qualifiers tq1 = pointerType->get_base()->tq, tq2 = otherPointer->get_base()->tq;
    547                                 pointerType->get_base()->tq = Type::Qualifiers();
    548                                 otherPointer->get_base()->tq = Type::Qualifiers();
    549                                 AssertionSet have, need;
    550                                 OpenVarSet newOpen( openVars );
    551                                 if ( unifyExact( pointerType->get_base(), otherPointer->get_base(), env, have, need, newOpen, indexer ) ) {
    552                                         // std::cerr << "unifyExact success" << std::endl;
    553                                         if ( tq1 < tq2 ) {
    554                                                 result = pointerType->clone();
    555                                         } else {
    556                                                 result = otherPointer->clone();
    557                                         } // if
    558                                         strict_dynamic_cast<PointerType *>(result)->base->tq = tq1 | tq2;
    559                                 } else {
    560                                         /// std::cerr << "place for ptr-to-type" << std::endl;
    561                                 } // if
    562                                 pointerType->get_base()->tq = tq1;
    563                                 otherPointer->get_base()->tq = tq2;
    564                         } // if
    565                 } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {
    566                         result = pointerType->clone();
    567                         result->tq |= type2->tq;
    568                 } // if
    569         }
    570 
    571         void CommonType_old::postvisit( ArrayType * ) {}
    572 
    573         void CommonType_old::postvisit( ReferenceType * refType ) {
    574                 if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( type2 ) ) {
    575                         // std::cerr << "commonType: both references: " << refType << " / " << otherRef << std::endl;
    576                         // std::cerr << ( refType->get_base()->tq >= otherRef->get_base()->tq || widenFirst ) << (refType->get_base()->tq <= otherRef->get_base()->tq || widenSecond) << std::endl;
    577                         if ( widenFirst && dynamic_cast< VoidType * >( otherRef->get_base() ) && ! isFtype(refType->get_base()) ) {
    578                                 getCommonWithVoidPointer( otherRef, refType );
    579                         } else if ( widenSecond && dynamic_cast< VoidType * >( refType->get_base() ) && ! isFtype(otherRef->get_base()) ) {
    580                                 getCommonWithVoidPointer( refType, otherRef );
    581                         } else if ( ( refType->get_base()->tq >= otherRef->get_base()->tq || widenFirst )
    582                                            && ( refType->get_base()->tq <= otherRef->get_base()->tq || widenSecond ) ) {
    583                                 // std::cerr << "middle case" << std::endl;
    584                                 Type::Qualifiers tq1 = refType->get_base()->tq, tq2 = otherRef->get_base()->tq;
    585                                 refType->get_base()->tq = Type::Qualifiers();
    586                                 otherRef->get_base()->tq = Type::Qualifiers();
    587                                 AssertionSet have, need;
    588                                 OpenVarSet newOpen( openVars );
    589                                 if ( unifyExact( refType->get_base(), otherRef->get_base(), env, have, need, newOpen, indexer ) ) {
    590                                         if ( tq1 < tq2 ) {
    591                                                 result = refType->clone();
    592                                         } else {
    593                                                 result = otherRef->clone();
    594                                         } // if
    595                                         strict_dynamic_cast<ReferenceType *>(result)->base->tq = tq1 | tq2;
    596                                 } else {
    597                                         /// std::cerr << "place for ptr-to-type" << std::endl;
    598                                 } // if
    599                                 refType->get_base()->tq = tq1;
    600                                 otherRef->get_base()->tq = tq2;
    601                         } // if
    602                 } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {
    603                         result = refType->clone();
    604                         result->tq |= type2->tq;
    605                 } // if
    606         }
    607 
    608         void CommonType_old::postvisit( FunctionType * ) {}
    609         void CommonType_old::postvisit( StructInstType * ) {}
    610         void CommonType_old::postvisit( UnionInstType * ) {}
    611 
    612         void CommonType_old::postvisit( EnumInstType * enumInstType ) {
    613                 if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< ZeroType * >( type2 ) || dynamic_cast< OneType * >( type2 ) ) {
    614                         // reuse BasicType, EnumInstType code by swapping type2 with enumInstType
    615                         result = commonType( type2, enumInstType, widenSecond, widenFirst, indexer, env, openVars );
    616                 } // if
    617         }
    618 
    619         void CommonType_old::postvisit( TraitInstType * ) {
    620         }
    621 
    622         void CommonType_old::postvisit( TypeInstType * inst ) {
    623                 if ( widenFirst ) {
    624                         const NamedTypeDecl * nt = indexer.lookupType( inst->get_name() );
    625                         if ( nt ) {
    626                                 const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( nt );
    627                                 if ( type->get_base() ) {
    628                                         Type::Qualifiers tq1 = inst->tq, tq2 = type2->tq;
    629                                         AssertionSet have, need;
    630                                         OpenVarSet newOpen( openVars );
    631                                         type2->tq = Type::Qualifiers();
    632                                         type->get_base()->tq = tq1;
    633                                         if ( unifyExact( type->get_base(), type2, env, have, need, newOpen, indexer ) ) {
    634                                                 result = type2->clone();
    635                                                 result->tq = tq1 | tq2;
    636                                         } // if
    637                                         type2->tq = tq2;
    638                                         type->get_base()->tq = Type::Qualifiers();
    639                                 } // if
    640                         } // if
    641                 } // if
    642         }
    643 
    644         void CommonType_old::postvisit( TupleType * ) {}
    645         void CommonType_old::postvisit( VarArgsType * ) {}
    646 
    647         void CommonType_old::postvisit( ZeroType * zeroType ) {
    648                 if ( widenFirst ) {
    649                         if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< PointerType * >( type2 ) || dynamic_cast< EnumInstType * >( type2 ) ) {
    650                                 if ( widenSecond || zeroType->tq <= type2->tq ) {
    651                                         result = type2->clone();
    652                                         result->tq |= zeroType->tq;
    653                                 }
    654                         } else if ( widenSecond && dynamic_cast< OneType * >( type2 ) ) {
    655                                 result = new BasicType( zeroType->tq, BasicType::SignedInt );
    656                                 result->tq |= type2->tq;
    657                         }
    658                 }
    659         }
    660 
    661         void CommonType_old::postvisit( OneType * oneType ) {
    662                 if ( widenFirst ) {
    663                         if ( dynamic_cast< BasicType * >( type2 ) || dynamic_cast< EnumInstType * >( type2 ) ) {
    664                                 if ( widenSecond || oneType->tq <= type2->tq ) {
    665                                         result = type2->clone();
    666                                         result->tq |= oneType->tq;
    667                                 }
    668                         } else if ( widenSecond && dynamic_cast< ZeroType * >( type2 ) ) {
    669                                 result = new BasicType( oneType->tq, BasicType::SignedInt );
    670                                 result->tq |= type2->tq;
    671                         }
    672                 }
    673         }
    674344
    675345        class CommonType_new final : public ast::WithShortCircuiting {
  • src/ResolvExpr/CommonType.hpp

    r790d835 rc6b4432  
    1818#include "AST/Fwd.hpp"
    1919#include "AST/TypeEnvironment.hpp"  // for AssertionSet, OpenVarSet
    20 #include "TypeEnvironment.h"        // for AssertionSet, OpenVarSet
    2120#include "WidenMode.h"              // for WidenMode
    22 
    23 class Type;
    24 namespace SymTab {
    25         class Indexer;
    26 }
    2721
    2822namespace ResolvExpr {
    2923
    30 Type * commonType(
    31         Type * type1, Type * type2, bool widenFirst, bool widenSecond,
    32         const SymTab::Indexer & indexer, TypeEnvironment & env,
    33         const OpenVarSet & openVars );
    3424ast::ptr< ast::Type > commonType(
    3525        const ast::ptr< ast::Type > & type1, const ast::ptr< ast::Type > & type2,
  • src/ResolvExpr/ConversionCost.cc

    r790d835 rc6b4432  
    2121
    2222#include "ResolvExpr/Cost.h"             // for Cost
    23 #include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    2423#include "ResolvExpr/Unify.h"            // for typesCompatibleIgnoreQualifiers
    2524#include "ResolvExpr/PtrsAssignable.hpp" // for ptrsAssignable
    26 #include "SymTab/Indexer.h"              // for Indexer
    27 #include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl
    28 #include "SynTree/Type.h"                // for Type, BasicType, TypeInstType
    29 
    3025
    3126namespace ResolvExpr {
    32 #if 0
    33         const Cost Cost::zero =      Cost{  0,  0,  0,  0,  0,  0,  0 };
    34         const Cost Cost::infinity =  Cost{ -1, -1, -1, -1, -1,  1, -1 };
    35         const Cost Cost::unsafe =    Cost{  1,  0,  0,  0,  0,  0,  0 };
    36         const Cost Cost::poly =      Cost{  0,  1,  0,  0,  0,  0,  0 };
    37         const Cost Cost::safe =      Cost{  0,  0,  1,  0,  0,  0,  0 };
    38         const Cost Cost::sign =      Cost{  0,  0,  0,  1,  0,  0,  0 };
    39         const Cost Cost::var =       Cost{  0,  0,  0,  0,  1,  0,  0 };
    40         const Cost Cost::spec =      Cost{  0,  0,  0,  0,  0, -1,  0 };
    41         const Cost Cost::reference = Cost{  0,  0,  0,  0,  0,  0,  1 };
    42 #endif
    4327
    4428#if 0
     
    4731#define PRINT(x)
    4832#endif
    49 
    50         Cost conversionCost( const Type * src, const Type * dest, bool srcIsLvalue,
    51                         const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    52                 if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType * >( dest ) ) {
    53                         PRINT( std::cerr << "type inst " << destAsTypeInst->name; )
    54                         if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->name ) ) {
    55                                 if ( eqvClass->type ) {
    56                                         return conversionCost( src, eqvClass->type, srcIsLvalue, indexer, env );
    57                                 } else {
    58                                         return Cost::infinity;
    59                                 }
    60                         } else if ( const NamedTypeDecl * namedType = indexer.lookupType( destAsTypeInst->name ) ) {
    61                                 PRINT( std::cerr << " found" << std::endl; )
    62                                 const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
    63                                 // all typedefs should be gone by this point
    64                                 assert( type );
    65                                 if ( type->base ) {
    66                                         return conversionCost( src, type->base, srcIsLvalue, indexer, env )
    67                                                 + Cost::safe;
    68                                 } // if
    69                         } // if
    70                         PRINT( std::cerr << " not found" << std::endl; )
    71                 } // if
    72                 PRINT(
    73                         std::cerr << "src is ";
    74                         src->print( std::cerr );
    75                         std::cerr << std::endl << "dest is ";
    76                         dest->print( std::cerr );
    77                         std::cerr << std::endl << "env is" << std::endl;
    78                         env.print( std::cerr, 8 );
    79                 )
    80                 if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
    81                         PRINT( std::cerr << "compatible!" << std::endl; )
    82                         return Cost::zero;
    83                 } else if ( dynamic_cast< const VoidType * >( dest ) ) {
    84                         return Cost::safe;
    85                 } else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) {
    86                         PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
    87                         return convertToReferenceCost( src, refType, srcIsLvalue, indexer, env, [](const Type * const t1, const Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){
    88                                 return ptrsAssignable( t1, t2, env );
    89                         });
    90                 } else {
    91                         PassVisitor<ConversionCost> converter(
    92                                 dest, srcIsLvalue, indexer, env,
    93                                 (Cost (*)(const Type *, const Type *, bool, const SymTab::Indexer&, const TypeEnvironment&))
    94                                         conversionCost );
    95                         src->accept( converter );
    96                         if ( converter.pass.get_cost() == Cost::infinity ) {
    97                                 return Cost::infinity;
    98                         } else {
    99                                 return converter.pass.get_cost() + Cost::zero;
    100                         } // if
    101                 } // if
    102         }
    103 
    104         static Cost convertToReferenceCost( const Type * src, const Type * dest, bool srcIsLvalue,
    105                         int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
    106                 PRINT( std::cerr << "convert to reference cost... diff " << diff << " " << src << " / " << dest << std::endl; )
    107                 if ( diff > 0 ) {
    108                         // TODO: document this
    109                         Cost cost = convertToReferenceCost(
    110                                 strict_dynamic_cast< const ReferenceType * >( src )->base, dest, srcIsLvalue,
    111                                 diff-1, indexer, env, func );
    112                         cost.incReference();
    113                         return cost;
    114                 } else if ( diff < -1 ) {
    115                         // TODO: document this
    116                         Cost cost = convertToReferenceCost(
    117                                 src, strict_dynamic_cast< const ReferenceType * >( dest )->base, srcIsLvalue,
    118                                 diff+1, indexer, env, func );
    119                         cost.incReference();
    120                         return cost;
    121                 } else if ( diff == 0 ) {
    122                         const ReferenceType * srcAsRef = dynamic_cast< const ReferenceType * >( src );
    123                         const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest );
    124                         if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
    125                                 PRINT( std::cerr << "converting between references" << std::endl; )
    126                                 Type::Qualifiers tq1 = srcAsRef->base->tq;
    127                                 Type::Qualifiers tq2 = destAsRef->base->tq;
    128                                 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->base, destAsRef->base, indexer, env ) ) {
    129                                         PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
    130                                         if ( tq1 == tq2 ) {
    131                                                 // types are the same
    132                                                 return Cost::zero;
    133                                         } else {
    134                                                 // types are the same, except otherPointer has more qualifiers
    135                                                 return Cost::safe;
    136                                         }
    137                                 } else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
    138                                         int assignResult = func( srcAsRef->base, destAsRef->base, indexer, env );
    139                                         PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; )
    140                                         if ( assignResult > 0 ) {
    141                                                 return Cost::safe;
    142                                         } else if ( assignResult < 0 ) {
    143                                                 return Cost::unsafe;
    144                                         } // if
    145                                 } // if
    146                         } else {
    147                                 PRINT( std::cerr << "reference to rvalue conversion" << std::endl; )
    148                                 PassVisitor<ConversionCost> converter(
    149                                         dest, srcIsLvalue, indexer, env,
    150                                         (Cost (*)(const Type *, const Type *, bool, const SymTab::Indexer&, const TypeEnvironment&))
    151                                                 conversionCost );
    152                                 src->accept( converter );
    153                                 return converter.pass.get_cost();
    154                         } // if
    155                 } else {
    156                         const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest );
    157                         assert( diff == -1 && destAsRef );
    158                         PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; )
    159                         if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) {
    160                                 PRINT( std::cerr << "converting compatible base type" << std::endl; )
    161                                 if ( srcIsLvalue ) {
    162                                         PRINT(
    163                                                 std::cerr << "lvalue to reference conversion" << std::endl;
    164                                                 std::cerr << src << " => " << destAsRef << std::endl;
    165                                         )
    166                                         // lvalue-to-reference conversion:  cv lvalue T => cv T &
    167                                         if ( src->tq == destAsRef->base->tq ) {
    168                                                 return Cost::reference; // cost needs to be non-zero to add cast
    169                                         } if ( src->tq < destAsRef->base->tq ) {
    170                                                 return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
    171                                         } else {
    172                                                 return Cost::unsafe;
    173                                         } // if
    174                                 } else if ( destAsRef->base->get_const() ) {
    175                                         PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; )
    176                                         // rvalue-to-const-reference conversion: T => const T &
    177                                         return Cost::safe;
    178                                 } else {
    179                                         PRINT( std::cerr << "rvalue to non-const reference conversion" << std::endl; )
    180                                         // rvalue-to-reference conversion: T => T &
    181                                         return Cost::unsafe;
    182                                 } // if
    183                         } // if
    184                         PRINT( std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl; )
    185                 }
    186                 return Cost::infinity;
    187         }
    188 
    189         Cost convertToReferenceCost( const Type * src, const ReferenceType * dest, bool srcIsLvalue,
    190                         const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
    191                 int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
    192                 Cost cost = convertToReferenceCost( src, dest, srcIsLvalue, sdepth-ddepth, indexer, env, func );
    193                 PRINT( std::cerr << "convertToReferenceCost result: " << cost << std::endl; )
    194                 return cost;
    195         }
    196 
    197         ConversionCost::ConversionCost( const Type * dest, bool srcIsLvalue, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
    198                 : dest( dest ), srcIsLvalue( srcIsLvalue ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) {
    199         }
    20033
    20134        // GENERATED START, DO NOT EDIT
     
    319152        );
    320153
    321         void ConversionCost::postvisit( const VoidType * ) {
    322                 cost = Cost::infinity;
    323         }
    324 
    325         // refactor for code resue
    326         void ConversionCost::conversionCostFromBasicToBasic(const BasicType * src, const BasicType * dest) {
    327                 int tableResult = costMatrix[ src->kind ][ dest->kind ];
    328                 if ( tableResult == -1 ) {
    329                         cost = Cost::unsafe;
    330                 } else {
    331                         cost = Cost::zero;
    332                         cost.incSafe( tableResult );
    333                         cost.incSign( signMatrix[ src->kind ][ dest->kind ] );
    334                 } // if
    335         } // ConversionCost::conversionCostFromBasicToBasic
    336 
    337         void ConversionCost::postvisit(const BasicType * basicType) {
    338                 if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
    339                         conversionCostFromBasicToBasic(basicType, destAsBasic);
    340                 } else if ( const EnumInstType * enumInst = dynamic_cast< const EnumInstType * >( dest ) ) {
    341                         const EnumDecl * base_enum = enumInst->baseEnum;
    342                         if ( const Type * base = base_enum->base ) {
    343                                 if ( const BasicType * enumBaseAstBasic = dynamic_cast< const BasicType *> (base) ) {
    344                                         conversionCostFromBasicToBasic(basicType, enumBaseAstBasic);
    345                                 } else {
    346                                         cost = Cost::infinity;
    347                                 } // if
    348                         } else {
    349                                 cost = Cost::unsafe;
    350                         } // if
    351                 } // if
    352                 // no cases for zero_t/one_t because it should not be possible to convert int, etc. to zero_t/one_t.
    353         }
    354 
    355         void ConversionCost::postvisit( const PointerType * pointerType ) {
    356                 if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) {
    357                         PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; )
    358                         Type::Qualifiers tq1 = pointerType->base->tq;
    359                         Type::Qualifiers tq2 = destAsPtr->base->tq;
    360                         if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
    361                                 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
    362                                 if ( tq1 == tq2 ) {
    363                                         // types are the same
    364                                         cost = Cost::zero;
    365                                 } else {
    366                                         // types are the same, except otherPointer has more qualifiers
    367                                         cost = Cost::safe;
    368                                 } // if
    369                         } else {
    370                                 int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env );
    371                                 PRINT( std::cerr << " :: " << assignResult << std::endl; )
    372                                 if ( assignResult > 0 && tq1 <= tq2 ) {
    373                                         // xxx - want the case where qualifiers are added to be more expensive than the case where qualifiers are the same. Is 1 safe vs. 2 safe correct?
    374                                         if ( tq1 == tq2 ) {
    375                                                 cost = Cost::safe;
    376                                         } else if ( tq1 < tq2 ) {
    377                                                 cost = Cost::safe+Cost::safe;
    378                                         }
    379                                 } else if ( assignResult < 0 ) {
    380                                         cost = Cost::unsafe;
    381                                 } // if
    382                                 // assignResult == 0 means Cost::Infinity
    383                         } // if
    384                         // case case for zero_t because it should not be possible to convert pointers to zero_t.
    385                 } // if
    386         }
    387 
    388         void ConversionCost::postvisit( const ArrayType * ) {}
    389 
    390         void ConversionCost::postvisit( const ReferenceType * refType ) {
    391                 // Note: dest can never be a reference, since it would have been caught in an earlier check
    392                 assert( ! dynamic_cast< const ReferenceType * >( dest ) );
    393                 // convert reference to rvalue: cv T1 & => T2
    394                 // recursively compute conversion cost from T1 to T2.
    395                 // cv can be safely dropped because of 'implicit dereference' behavior.
    396                 cost = costFunc( refType->base, dest, srcIsLvalue, indexer, env );
    397                 if ( refType->base->tq == dest->tq ) {
    398                         cost.incReference();  // prefer exact qualifiers
    399                 } else if ( refType->base->tq < dest->tq ) {
    400                         cost.incSafe(); // then gaining qualifiers
    401                 } else {
    402                         cost.incUnsafe(); // lose qualifiers as last resort
    403                 }
    404                 PRINT( std::cerr << refType << " ==> " << dest << " " << cost << std::endl; )
    405         }
    406 
    407         void ConversionCost::postvisit( const FunctionType * ) {}
    408 
    409         void ConversionCost::postvisit( const EnumInstType * enumInst) {
    410                 const EnumDecl * enumDecl = enumInst -> baseEnum;
    411                 if ( const Type * enumType = enumDecl -> base ) { // if it is a typed enum
    412                         cost = costFunc( enumType, dest, srcIsLvalue, indexer, env );
    413                 } else {
    414                         static Type::Qualifiers q;
    415                         static BasicType integer( q, BasicType::SignedInt );
    416                         cost = costFunc( &integer, dest, srcIsLvalue, indexer, env );  // safe if dest >= int
    417                 } // if
    418                 if ( cost < Cost::unsafe ) {
    419                                 cost.incSafe();
    420                 } // if
    421         }
    422 
    423         void ConversionCost::postvisit( const TraitInstType * ) {}
    424 
    425         void ConversionCost::postvisit( const TypeInstType * inst ) {
    426                 if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
    427                         cost = costFunc( eqvClass->type, dest, srcIsLvalue, indexer, env );
    428                 } else if ( const TypeInstType * destAsInst = dynamic_cast< const TypeInstType * >( dest ) ) {
    429                         if ( inst->name == destAsInst->name ) {
    430                                 cost = Cost::zero;
    431                         }
    432                 } else if ( const NamedTypeDecl * namedType = indexer.lookupType( inst->name ) ) {
    433                         const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
    434                         // all typedefs should be gone by this point
    435                         assert( type );
    436                         if ( type->base ) {
    437                                 cost = costFunc( type->base, dest, srcIsLvalue, indexer, env ) + Cost::safe;
    438                         } // if
    439                 } // if
    440         }
    441 
    442         void ConversionCost::postvisit( const TupleType * tupleType ) {
    443                 Cost c = Cost::zero;
    444                 if ( const TupleType * destAsTuple = dynamic_cast< const TupleType * >( dest ) ) {
    445                         std::list< Type * >::const_iterator srcIt = tupleType->types.begin();
    446                         std::list< Type * >::const_iterator destIt = destAsTuple->types.begin();
    447                         while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) {
    448                                 Cost newCost = costFunc( * srcIt++, * destIt++, srcIsLvalue, indexer, env );
    449                                 if ( newCost == Cost::infinity ) {
    450                                         return;
    451                                 } // if
    452                                 c += newCost;
    453                         } // while
    454                         if ( destIt != destAsTuple->types.end() ) {
    455                                 cost = Cost::infinity;
    456                         } else {
    457                                 cost = c;
    458                         } // if
    459                 } // if
    460         }
    461 
    462         void ConversionCost::postvisit( const VarArgsType * ) {
    463                 if ( dynamic_cast< const VarArgsType * >( dest ) ) {
    464                         cost = Cost::zero;
    465                 }
    466         }
    467 
    468         void ConversionCost::postvisit( const ZeroType * ) {
    469                 if ( dynamic_cast< const ZeroType * >( dest ) ) {
    470                         cost = Cost::zero;
    471                 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
    472                         // copied from visit(BasicType *) for signed int, but +1 for safe conversions
    473                         int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
    474                         if ( tableResult == -1 ) {
    475                                 cost = Cost::unsafe;
    476                         } else {
    477                                 cost = Cost::zero;
    478                                 cost.incSafe( tableResult + 1 );
    479                                 cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
    480                         } // if
    481                 } else if ( dynamic_cast< const PointerType * >( dest ) ) {
    482                         cost = Cost::zero;
    483                         cost.incSafe( maxIntCost + 2 ); // +1 for zero_t -> int, +1 for disambiguation
    484                 } // if
    485         }
    486 
    487         void ConversionCost::postvisit( const OneType * ) {
    488                 if ( dynamic_cast< const OneType * >( dest ) ) {
    489                         cost = Cost::zero;
    490                 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
    491                         // copied from visit(BasicType *) for signed int, but +1 for safe conversions
    492                         int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
    493                         if ( tableResult == -1 ) {
    494                                 cost = Cost::unsafe;
    495                         } else {
    496                                 cost = Cost::zero;
    497                                 cost.incSafe( tableResult + 1 );
    498                                 cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
    499                         } // if
    500                 } // if
    501         }
    502 
    503154namespace {
    504155        # warning For overload resolution between the two versions.
  • src/ResolvExpr/ConversionCost.h

    r790d835 rc6b4432  
    2222#include "AST/Fwd.hpp"
    2323#include "AST/Pass.hpp"       // for WithShortCircuiting
    24 #include "Common/PassVisitor.h"
    25 #include "SynTree/Visitor.h"  // for Visitor
    26 #include "SynTree/SynTree.h"  // for Visitor Nodes
    2724
    2825namespace SymTab {
     
    3229namespace ResolvExpr {
    3330        class TypeEnvironment;
    34 
    35         Cost conversionCost(
    36                 const Type * src, const Type * dest, bool srcIsLvalue,
    37                 const SymTab::Indexer & indexer, const TypeEnvironment & env );
    38 
    39         typedef std::function<Cost(const Type *, const Type *, bool,
    40                 const SymTab::Indexer &, const TypeEnvironment &)> CostFunction;
    41 
    42         struct ConversionCost : public WithShortCircuiting {
    43           public:
    44                 ConversionCost( const Type * dest, bool srcIsLvalue,
    45                         const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction );
    46 
    47                 Cost get_cost() const { return cost; }
    48 
    49                 void previsit( const BaseSyntaxNode * ) { visit_children = false; }
    50 
    51                 void postvisit( const VoidType * voidType );
    52                 void postvisit( const BasicType * basicType );
    53                 void postvisit( const PointerType * pointerType );
    54                 void postvisit( const ArrayType * arrayType );
    55                 void postvisit( const ReferenceType * refType );
    56                 void postvisit( const FunctionType * functionType );
    57                 void postvisit( const EnumInstType * aggregateUseType );
    58                 void postvisit( const TraitInstType * aggregateUseType );
    59                 void postvisit( const TypeInstType * aggregateUseType );
    60                 void postvisit( const TupleType * tupleType );
    61                 void postvisit( const VarArgsType * varArgsType );
    62                 void postvisit( const ZeroType * zeroType );
    63                 void postvisit( const OneType * oneType );
    64           protected:
    65                 const Type * dest;
    66                 bool srcIsLvalue;
    67                 const SymTab::Indexer &indexer;
    68                 Cost cost;
    69                 const TypeEnvironment &env;
    70                 CostFunction costFunc;
    71           private:
    72                 // refactor for code resue
    73                 void conversionCostFromBasicToBasic( const BasicType * src, const BasicType* dest );
    74         };
    75 
    76         typedef std::function<int(const Type *, const Type *, const SymTab::Indexer &, const TypeEnvironment &)> PtrsFunction;
    77         Cost convertToReferenceCost( const Type * src, const ReferenceType * dest, bool srcIsLvalue,
    78                 const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func );
    7931
    8032// Some function pointer types, differ in return type.
  • src/ResolvExpr/CurrentObject.cc

    r790d835 rc6b4432  
    3333#include "Common/utility.h"            // for toString
    3434#include "CurrentObject.h"
    35 #include "SynTree/Constant.h"          // for Constant
    36 #include "SynTree/Declaration.h"       // for ObjectDecl, Declaration, Struc...
    37 #include "SynTree/Expression.h"        // for InitAlternative, VariableExpr
    38 #include "SynTree/Initializer.h"       // for Designation, operator<<
    39 #include "SynTree/Type.h"              // for Type, StructInstType, UnionIns...
    40 #include "SynTree/TypeSubstitution.h"  // for TypeSubstitution
    4135
    4236#if 0
     
    4539#define PRINT(x)
    4640#endif
    47 
    48 namespace ResolvExpr {
    49         template< typename AggrInst >
    50         TypeSubstitution makeGenericSubstitution( AggrInst * inst ) {
    51                 assert( inst );
    52                 assert( inst->get_baseParameters() );
    53                 std::list< TypeDecl * > baseParams = *inst->get_baseParameters();
    54                 std::list< Expression * > typeSubs = inst->get_parameters();
    55                 TypeSubstitution subs( baseParams.begin(), baseParams.end(), typeSubs.begin() );
    56                 return subs;
    57         }
    58 
    59         TypeSubstitution makeGenericSubstitution( Type * type ) {
    60                 if ( StructInstType * inst = dynamic_cast< StructInstType * >( type ) ) {
    61                         return makeGenericSubstitution( inst );
    62                 } else if ( UnionInstType * inst = dynamic_cast< UnionInstType * >( type ) ) {
    63                         return makeGenericSubstitution( inst );
    64                 } else {
    65                         return TypeSubstitution();
    66                 }
    67         }
    68 
    69         class MemberIterator {
    70         public:
    71                 virtual ~MemberIterator() {}
    72 
    73                 /// walks the current object using the given designators as a guide
    74                 virtual void setPosition( std::list< Expression * > & designators ) = 0;
    75 
    76                 /// retrieve the list of possible Type/Designation pairs for the current position in the currect object
    77                 virtual std::list<InitAlternative> operator*() const = 0;
    78 
    79                 /// true if the iterator is not currently at the end
    80                 virtual operator bool() const = 0;
    81 
    82                 /// moves the iterator by one member in the current object
    83                 virtual MemberIterator & bigStep() = 0;
    84 
    85                 /// moves the iterator by one member in the current subobject
    86                 virtual MemberIterator & smallStep() = 0;
    87 
    88                 /// the type of the current object
    89                 virtual Type * getType() = 0;
    90 
    91                 /// the type of the current subobject
    92                 virtual Type * getNext() = 0;
    93 
    94                 /// printing for debug
    95                 virtual void print( std::ostream & out, Indenter indent ) const = 0;
    96 
    97                 /// helper for operator*; aggregates must add designator to each init alternative, but
    98                 /// adding designators in operator* creates duplicates.
    99                 virtual std::list<InitAlternative> first() const = 0; // should be protected
    100         };
    101 
    102         std::ostream & operator<<(std::ostream & out, const MemberIterator & it) {
    103                 Indenter indenter;
    104                 it.print( out, indenter );
    105                 return out;
    106         }
    107 
    108         /// create a new MemberIterator that traverses a type correctly
    109         MemberIterator * createMemberIterator( Type * type );
    110 
    111         /// iterates "other" types, e.g. basic types, pointer types, etc. which do not change at list initializer entry
    112         class SimpleIterator : public MemberIterator {
    113         public:
    114                 SimpleIterator( Type * type ) : type( type ) {}
    115 
    116                 virtual void setPosition( std::list< Expression * > & designators ) {
    117                         assertf( designators.empty(), "simple iterator given non-empty designator..." ); // xxx - might be semantic error
    118                 }
    119 
    120                 virtual std::list<InitAlternative> operator*() const { return first(); }
    121                 virtual operator bool() const { return type; }
    122 
    123                 // big step is the same as small step
    124                 virtual MemberIterator & bigStep() { return smallStep(); }
    125                 virtual MemberIterator & smallStep() {
    126                         type = nullptr;  // type is nullified on increment since SimpleIterators do not have members
    127                         return *this;
    128                 }
    129 
    130                 virtual void print( std::ostream & out, __attribute__((unused)) Indenter indent ) const {
    131                         out << "SimpleIterator(" << type << ")";
    132                 }
    133 
    134                 virtual Type * getType() { return type; }
    135                 virtual Type * getNext() { return type; }
    136 
    137         protected:
    138                 virtual std::list<InitAlternative> first() const {
    139                         if ( type ) return std::list<InitAlternative>{ { type->clone(), new Designation( {} ) } };
    140                         else return std::list<InitAlternative>{};
    141                 }
    142         private:
    143                 Type * type = nullptr;
    144         };
    145 
    146         class ArrayIterator : public MemberIterator {
    147         public:
    148                 ArrayIterator( ArrayType * at ) : array( at ) {
    149                         PRINT( std::cerr << "Creating array iterator: " << at << std::endl; )
    150                         base = at->base;
    151                         memberIter = createMemberIterator( base );
    152                         if ( at->isVarLen ) SemanticError( at, "VLA initialization does not support @=: " );
    153                         setSize( at->dimension );
    154                 }
    155 
    156                 ~ArrayIterator() {
    157                         delete memberIter;
    158                 }
    159 
    160         private:
    161                 void setSize( Expression * expr ) {
    162                         auto res = eval( expr );
    163                         if (res.second) {
    164                                 size = res.first;
    165                         } else {
    166                                 SemanticError( expr->location, toString("Array designator must be a constant expression: ", expr) );
    167                         }
    168                 }
    169 
    170         public:
    171                 void setPosition( Expression * expr ) {
    172                         // need to permit integer-constant-expressions, including: integer constants, enumeration constants, character constants, sizeof expressions, _Alignof expressions, cast expressions
    173                         auto arg = eval( expr );
    174                         index = arg.first;
    175                         return;
    176 
    177                         // if ( ConstantExpr * constExpr = dynamic_cast< ConstantExpr * >( expr ) ) {
    178                         //      try {
    179                         //              index = constExpr->intValue();
    180                         //      } catch( SemanticErrorException & ) {
    181                         //              SemanticError( expr, "Constant expression of non-integral type in array designator: " );
    182                         //      }
    183                         // } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    184                         //      setPosition( castExpr->get_arg() );
    185                         // } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) {
    186                         //      EnumInstType * inst = dynamic_cast<EnumInstType *>( varExpr->get_result() );
    187                         //      assertf( inst, "ArrayIterator given variable that isn't an enum constant : %s", toString( expr ).c_str() );
    188                         //      long long int value;
    189                         //      if ( inst->baseEnum->valueOf( varExpr->var, value ) ) {
    190                         //              index = value;
    191                         //      }
    192                         // } else if ( dynamic_cast< SizeofExpr * >( expr ) || dynamic_cast< AlignofExpr * >( expr ) ) {
    193                         //      index = 0; // xxx - get actual sizeof/alignof value?
    194                         // } else {
    195                         //      assertf( false, "4 bad designator given to ArrayIterator: %s", toString( expr ).c_str() );
    196                         // }
    197                 }
    198 
    199                 virtual void setPosition( std::list< Expression * > & designators ) {
    200                         if ( ! designators.empty() ) {
    201                                 setPosition( designators.front() );
    202                                 designators.pop_front();
    203                                 memberIter->setPosition( designators );
    204                         }
    205                 }
    206 
    207                 virtual std::list<InitAlternative> operator*() const {
    208                         return first();
    209                 }
    210 
    211                 virtual operator bool() const { return index < size; }
    212 
    213                 virtual MemberIterator & bigStep() {
    214                         PRINT( std::cerr << "bigStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
    215                         ++index;
    216                         delete memberIter;
    217                         if ( index < size ) memberIter = createMemberIterator( base );
    218                         else memberIter = nullptr;
    219                         return *this;
    220                 }
    221 
    222                 virtual MemberIterator & smallStep() {
    223                         PRINT( std::cerr << "smallStep in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
    224                         if ( memberIter ) {
    225                                 PRINT( std::cerr << "has member iter: " << *memberIter << std::endl; )
    226                                 memberIter->smallStep();
    227                                 if ( *memberIter ) {
    228                                         PRINT( std::cerr << "has valid member iter" << std::endl; )
    229                                         return *this;
    230                                 }
    231                         }
    232                         return bigStep();
    233                 }
    234 
    235                 virtual Type * getType() { return array; }
    236                 virtual Type * getNext() { return base; }
    237 
    238                 virtual std::list<InitAlternative> first() const {
    239                         PRINT( std::cerr << "first in ArrayIterator (" << index << "/" << size << ")" << std::endl; )
    240                         if ( memberIter && *memberIter ) {
    241                                 std::list<InitAlternative> ret = memberIter->first();
    242                                 for ( InitAlternative & alt : ret ) {
    243                                         alt.designation->get_designators().push_front( new ConstantExpr( Constant::from_ulong( index ) ) );
    244                                 }
    245                                 return ret;
    246                         }
    247                         return std::list<InitAlternative>();
    248                 }
    249 
    250                 virtual void print( std::ostream & out, Indenter indent ) const {
    251                         out << "ArrayIterator(Array of " << base << ")";
    252                         if ( memberIter ) {
    253                                 Indenter childIndent = indent+1;
    254                                 out << std::endl << childIndent;
    255                                 memberIter->print( out, childIndent );
    256                         }
    257                 }
    258 
    259         private:
    260                 ArrayType * array = nullptr;
    261                 Type * base = nullptr;
    262                 size_t index = 0;
    263                 size_t size = 0;
    264                 MemberIterator * memberIter = nullptr;
    265         };
    266 
    267         class AggregateIterator : public MemberIterator {
    268         public:
    269                 typedef std::list<Declaration *> MemberList;
    270                 typedef MemberList::const_iterator iterator;
    271                 std::string kind = ""; // for debug
    272                 std::string name;
    273                 Type * inst = nullptr;
    274                 const MemberList & members;
    275                 iterator curMember;
    276                 bool atbegin = true; // false at first {small,big}Step -- this aggr type is only added to the possibilities at the beginning
    277                 Type * curType = nullptr;
    278                 MemberIterator * memberIter = nullptr;
    279                 mutable TypeSubstitution sub;
    280 
    281                 AggregateIterator( const std::string & kind, const std::string & name, Type * inst, const MemberList & members ) : kind( kind ), name( name ), inst( inst ), members( members ), curMember( members.begin() ), sub( makeGenericSubstitution( inst ) ) {
    282                         PRINT( std::cerr << "Creating " << kind << "(" << name << ")"; )
    283                         init();
    284                 }
    285 
    286                 virtual ~AggregateIterator() {
    287                         delete memberIter;
    288                 }
    289 
    290                 bool init() {
    291                         PRINT( std::cerr << "--init()--" << members.size() << std::endl; )
    292                         if ( curMember != members.end() ) {
    293                                 if ( ObjectDecl * field = dynamic_cast< ObjectDecl * >( *curMember ) ) {
    294                                         PRINT( std::cerr << "incremented to field: " << field << std::endl; )
    295                                         curType = field->get_type();
    296                                         memberIter = createMemberIterator( curType );
    297                                         return true;
    298                                 }
    299                         }
    300                         return false;
    301                 }
    302 
    303                 virtual std::list<InitAlternative> operator*() const {
    304                         if (memberIter && *memberIter) {
    305                                 std::list<InitAlternative> ret = memberIter->first();
    306                                 PRINT( std::cerr << "sub: " << sub << std::endl; )
    307                                 for ( InitAlternative & alt : ret ) {
    308                                         PRINT( std::cerr << "iterating and adding designators" << std::endl; )
    309                                         alt.designation->get_designators().push_front( new VariableExpr( strict_dynamic_cast< ObjectDecl * >( *curMember ) ) );
    310                                         // need to substitute for generic types, so that casts are to concrete types
    311                                         PRINT( std::cerr << "  type is: " << alt.type; )
    312                                         sub.apply( alt.type ); // also apply to designation??
    313                                         PRINT( std::cerr << " ==> " << alt.type << std::endl; )
    314                                 }
    315                                 return ret;
    316                         }
    317                         return std::list<InitAlternative>();
    318                 }
    319 
    320                 virtual void setPosition( std::list< Expression * > & designators ) {
    321                         if ( ! designators.empty() ) {
    322                                 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( designators.front() ) ) {
    323                                         for ( curMember = members.begin(); curMember != members.end(); ++curMember ) {
    324                                                 if ( *curMember == varExpr->get_var() ) {
    325                                                         designators.pop_front();
    326                                                         delete memberIter;
    327                                                         memberIter = createMemberIterator( varExpr->get_result() );
    328                                                         curType = varExpr->get_result();
    329                                                         atbegin = curMember == members.begin() && designators.empty(); // xxx - is this the right condition for atbegin??
    330                                                         memberIter->setPosition( designators );
    331                                                         return;
    332                                                 } // if
    333                                         } // for
    334                                         assertf( false, "could not find member in %s: %s", kind.c_str(), toString( varExpr ).c_str() );
    335                                 } else {
    336                                         assertf( false, "3 bad designator given to %s: %s", kind.c_str(), toString( designators.front() ).c_str() );
    337                                 } // if
    338                         } // if
    339                 }
    340 
    341                 virtual MemberIterator & smallStep() {
    342                         PRINT( std::cerr << "smallStep in " << kind << std::endl; )
    343                         atbegin = false;
    344                         if ( memberIter ) {
    345                                 PRINT( std::cerr << "has member iter, incrementing..." << std::endl; )
    346                                 memberIter->smallStep();
    347                                 if ( *memberIter ) {
    348                                         PRINT( std::cerr << "success!" << std::endl; )
    349                                         return *this;
    350                                 }
    351                         }
    352                         return bigStep();
    353                 }
    354 
    355                 virtual Type * getType() { return inst; }
    356                 virtual Type * getNext() {
    357                         if ( memberIter && *memberIter ) return memberIter->getType(); // xxx - ??? recursive call???
    358                         return nullptr;
    359                 }
    360 
    361                 virtual std::list<InitAlternative> first() const {
    362                         std::list<InitAlternative> ret;
    363                         PRINT( std::cerr << "first " << kind << std::endl; )
    364                         if ( memberIter && *memberIter ) { // might not need *memberIter??
    365                                 PRINT( std::cerr << "adding children" << std::endl; )
    366                                 ret = memberIter->first();
    367                                 for ( InitAlternative & alt : ret ) {
    368                                         PRINT( std::cerr << "iterating and adding designators" << std::endl; )
    369                                         alt.designation->get_designators().push_front( new VariableExpr( strict_dynamic_cast< ObjectDecl * >( *curMember ) ) );
    370                                 }
    371                         }
    372                         if ( atbegin ) {
    373                                 // xxx - what about case of empty struct??
    374                                 // only add self if at the very beginning of the structure
    375                                 PRINT( std::cerr << "adding self" << std::endl; )
    376                                 ret.push_front( { inst->clone(), new Designation( {} ) } );
    377                         }
    378                         return ret;
    379                 }
    380 
    381                 virtual void print( std::ostream & out, Indenter indent ) const {
    382                         out << kind << "(" << name << ")";
    383                         if ( memberIter ) {
    384                                 Indenter childIndent = indent+1;
    385                                 out << std::endl << childIndent;
    386                                 memberIter->print( out, childIndent );
    387                         }
    388                 }
    389         };
    390 
    391         class UnionIterator : public AggregateIterator {
    392         public:
    393                 UnionIterator( UnionInstType * inst ) : AggregateIterator( "UnionIterator", inst->get_name(), inst, inst->get_baseUnion()->get_members() ) {}
    394 
    395                 virtual operator bool() const { return (memberIter && *memberIter); }
    396                 virtual MemberIterator & bigStep() {
    397                         // unions only initialize one member
    398                         PRINT( std::cerr << "bigStep in " << kind << std::endl; )
    399                         atbegin = false;
    400                         delete memberIter;
    401                         memberIter = nullptr;
    402                         curType = nullptr;
    403                         curMember = members.end();
    404                         return *this;
    405                 }
    406         };
    407 
    408         class StructIterator : public AggregateIterator {
    409         public:
    410                 StructIterator( StructInstType * inst ) : AggregateIterator( "StructIterator", inst->get_name(), inst, inst->get_baseStruct()->get_members() ) {}
    411 
    412                 virtual operator bool() const { return curMember != members.end() || (memberIter && *memberIter); }
    413 
    414                 virtual MemberIterator & bigStep() {
    415                         PRINT( std::cerr << "bigStep in " << kind << std::endl; )
    416                         atbegin = false;
    417                         delete memberIter;
    418                         memberIter = nullptr;
    419                         curType = nullptr;
    420                         for ( ; curMember != members.end(); ) {
    421                                 ++curMember;
    422                                 if ( init() ) {
    423                                         return *this;
    424                                 }
    425                         }
    426                         return *this;
    427                 }
    428         };
    429 
    430         class TupleIterator : public AggregateIterator {
    431         public:
    432                 TupleIterator( TupleType * inst ) : AggregateIterator( "TupleIterator", toString("Tuple", inst->size()), inst, inst->get_members() ) {}
    433 
    434                 virtual operator bool() const { return curMember != members.end() || (memberIter && *memberIter); }
    435 
    436                 virtual MemberIterator & bigStep() {
    437                         PRINT( std::cerr << "bigStep in " << kind << std::endl; )
    438                         atbegin = false;
    439                         delete memberIter;
    440                         memberIter = nullptr;
    441                         curType = nullptr;
    442                         for ( ; curMember != members.end(); ) {
    443                                 ++curMember;
    444                                 if ( init() ) {
    445                                         return *this;
    446                                 }
    447                         }
    448                         return *this;
    449                 }
    450         };
    451 
    452         MemberIterator * createMemberIterator( Type * type ) {
    453                 if ( ReferenceToType * aggr = dynamic_cast< ReferenceToType * >( type ) ) {
    454                         if ( StructInstType * sit = dynamic_cast< StructInstType * >( aggr ) ) {
    455                                 return new StructIterator( sit );
    456                         } else if ( UnionInstType * uit = dynamic_cast< UnionInstType * >( aggr ) ) {
    457                                 return new UnionIterator( uit );
    458                         } else {
    459                                 assertf( dynamic_cast< EnumInstType * >( type ) || dynamic_cast< TypeInstType * >( type ), "Encountered unhandled ReferenceToType in createMemberIterator: %s", toString( type ).c_str() );
    460                                 return new SimpleIterator( type );
    461                         }
    462                 } else if ( ArrayType * at = dynamic_cast< ArrayType * >( type ) ) {
    463                         return new ArrayIterator( at );
    464                 } else if ( TupleType * tt = dynamic_cast< TupleType * >( type ) ) {
    465                         return new TupleIterator( tt );
    466                 } else {
    467                         return new SimpleIterator( type );
    468                 }
    469         }
    470 
    471         CurrentObject::CurrentObject() {}
    472         CurrentObject::CurrentObject( Type * type ) {
    473                 objStack.push( new SimpleIterator( type ) );
    474         }
    475 
    476 
    477         void CurrentObject::setNext( Designation * designation ) {
    478                 assertf( ! objStack.empty(), "obj stack empty in setNext" );
    479                 PRINT( std::cerr << "____setNext" << designation << std::endl; )
    480                 objStack.top()->setPosition( designation->get_designators() );
    481         }
    482 
    483         Designation * CurrentObject::findNext( Designation * designation ) {
    484                 typedef std::list< Expression * > DesignatorChain;
    485                 PRINT( std::cerr << "___findNext" << std::endl; )
    486                 // find all the d's
    487                 std::list<DesignatorChain> desigAlts{ { } }, newDesigAlts;
    488                 std::list<Type *> curTypes { (objStack.top())->getType() }, newTypes;
    489                 for ( Expression * expr : designation->get_designators() ) {
    490                         PRINT( std::cerr << "____untyped: " << expr << std::endl; )
    491                         std::list<DesignatorChain>::iterator dit = desigAlts.begin();
    492                         if ( NameExpr * nexpr = dynamic_cast<NameExpr *>(expr) ) {
    493                                 for ( Type * t : curTypes ) {
    494                                         assert( dit != desigAlts.end() );
    495                                         DesignatorChain & d = *dit;
    496                                         PRINT( std::cerr << "____actual: " << t << std::endl; )
    497                                         ReferenceToType * refType = dynamic_cast<ReferenceToType *>(t);
    498                                         std::list<Declaration *> members;
    499                                         if ( refType ) {
    500                                                 refType->lookup( nexpr->get_name(), members ); // concatenate identical field name
    501                                                 // xxx - need to also include anonymous members in this somehow...
    502                                                 for ( Declaration * mem: members ) {
    503                                                         if ( ObjectDecl * field = dynamic_cast<ObjectDecl *>(mem) ) {
    504                                                                 PRINT( std::cerr << "____alt: " << field->get_type() << std::endl; )
    505                                                                 DesignatorChain newD = d;
    506                                                                 newD.push_back( new VariableExpr( field ) );
    507                                                                 newDesigAlts.push_back( newD );
    508                                                                 newTypes.push_back( field->get_type() );
    509                                                         } // if
    510                                                 } // for
    511                                         } // if
    512                                         ++dit;
    513                                 } // for
    514                         } else {
    515                                 for ( Type * t : curTypes ) {
    516                                         assert( dit != desigAlts.end() );
    517                                         DesignatorChain & d = *dit;
    518                                         if ( ArrayType * at = dynamic_cast< ArrayType * > ( t ) ) {
    519                                                 PRINT( std::cerr << "____alt: " << at->get_base() << std::endl; )
    520                                                 d.push_back( expr );
    521                                                 newDesigAlts.push_back( d );
    522                                                 newTypes.push_back( at->get_base() );
    523                                         }
    524                                         ++dit;
    525                                 } // for
    526                         } // if
    527                         desigAlts = newDesigAlts;
    528                         newDesigAlts.clear();
    529                         curTypes = newTypes;
    530                         newTypes.clear();
    531                         assertf( desigAlts.size() == curTypes.size(), "Designator alternatives (%zu) and current types (%zu) out of sync", desigAlts.size(), curTypes.size() );
    532                 } // for
    533                 if ( desigAlts.size() > 1 ) {
    534                         SemanticError( designation, toString("Too many alternatives (", desigAlts.size(), ") for designation: ") );
    535                 } else if ( desigAlts.size() == 0 ) {
    536                         SemanticError( designation, "No reasonable alternatives for designation: " );
    537                 }
    538                 DesignatorChain & d = desigAlts.back();
    539                 PRINT( for ( Expression * expr : d ) {
    540                         std::cerr << "____desig: " << expr << std::endl;
    541                 } ) // for
    542                 assertf( ! curTypes.empty(), "empty designator chosen");
    543 
    544                 // set new designators
    545                 assertf( ! objStack.empty(), "empty object stack when setting designation" );
    546                 Designation * actualDesignation = new Designation( d );
    547                 objStack.top()->setPosition( d ); // destroys d
    548                 return actualDesignation;
    549         }
    550 
    551         void CurrentObject::increment() {
    552                 PRINT( std::cerr << "____increment" << std::endl; )
    553                 if ( ! objStack.empty() ) {
    554                         PRINT( std::cerr << *objStack.top() << std::endl; )
    555                         objStack.top()->smallStep();
    556                 }
    557         }
    558 
    559         void CurrentObject::enterListInit() {
    560                 PRINT( std::cerr << "____entering list init" << std::endl; )
    561                 assertf( ! objStack.empty(), "empty obj stack entering list init" );
    562                 Type * type = objStack.top()->getNext();
    563                 if ( type ) {
    564                         objStack.push( createMemberIterator( type ) );
    565                 } else {
    566                         assertf( false, "not sure about this case..." );
    567                 }
    568         }
    569 
    570         void CurrentObject::exitListInit() {
    571                 PRINT( std::cerr << "____exiting list init" << std::endl; )
    572                 assertf( ! objStack.empty(), "objstack empty" );
    573                 delete objStack.top();
    574                 objStack.pop();
    575                 if ( ! objStack.empty() ) {
    576                         PRINT( std::cerr << *objStack.top() << std::endl; )
    577                         objStack.top()->bigStep();
    578                 }
    579         }
    580 
    581         std::list< InitAlternative > CurrentObject::getOptions() {
    582                 PRINT( std::cerr << "____getting current options" << std::endl; )
    583                 assertf( ! objStack.empty(), "objstack empty in getOptions" );
    584                 return **objStack.top();
    585         }
    586 
    587         Type * CurrentObject::getCurrentType() {
    588                 PRINT( std::cerr << "____getting current type" << std::endl; )
    589                 assertf( ! objStack.empty(), "objstack empty in getCurrentType" );
    590                 return objStack.top()->getNext();
    591         }
    592 } // namespace ResolvExpr
    59341
    59442namespace ast {
  • src/ResolvExpr/FindOpenVars.cc

    r790d835 rc6b4432  
    1616#include "FindOpenVars.h"
    1717
    18 #include <list>                   // for _List_const_iterator, list<>::const...
    19 #include <map>                    // for map<>::mapped_type
    20 
    2118#include "AST/Pass.hpp"
    2219#include "AST/Type.hpp"
    2320#include "AST/TypeEnvironment.hpp"
    24 #include "Common/PassVisitor.h"
    25 #include "SynTree/Declaration.h"  // for TypeDecl, DeclarationWithType (ptr ...
    26 #include "SynTree/Type.h"         // for Type, Type::ForallList, ArrayType
    2721
    2822#include <iostream>
    2923
    3024namespace ResolvExpr {
    31         struct FindOpenVars_old : public WithGuards {
    32                 FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
    33 
    34                 void previsit( const PointerType * pointerType );
    35                 void previsit( const ArrayType * arrayType );
    36                 void previsit( const FunctionType * functionType );
    37                 void previsit( const TupleType * tupleType );
    38 
    39                 void common_action( const Type *type );
    40 
    41                 OpenVarSet &openVars, &closedVars;
    42                 AssertionSet &needAssertions, &haveAssertions;
    43                 bool nextIsOpen;
    44         };
    45 
    46         void findOpenVars( const Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen ) {
    47                 PassVisitor<FindOpenVars_old> finder( openVars, closedVars, needAssertions, haveAssertions, firstIsOpen );
    48                 type->accept( finder );
    49         }
    50 
    51         FindOpenVars_old::FindOpenVars_old( OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen )
    52                 : openVars( openVars ), closedVars( closedVars ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), nextIsOpen( firstIsOpen ) {
    53         }
    54 
    55         void FindOpenVars_old::common_action( const Type * type ) {
    56                 if ( nextIsOpen ) {
    57                         for ( Type::ForallList::const_iterator i = type->forall.begin(); i != type->forall.end(); ++i ) {
    58                                 openVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) };
    59                                 for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
    60                                         needAssertions[ *assert ].isUsed = false;
    61                                 }
    62 ///       cloneAll( (*i)->get_assertions(), needAssertions );
    63 ///       needAssertions.insert( needAssertions.end(), (*i)->get_assertions().begin(), (*i)->get_assertions().end() );
    64                         }
    65                 } else {
    66                         for ( Type::ForallList::const_iterator i = type->forall.begin(); i != type->forall.end(); ++i ) {
    67                                 closedVars[ (*i)->get_name() ] = TypeDecl::Data{ (*i) };
    68                                 for ( std::list< DeclarationWithType* >::const_iterator assert = (*i)->get_assertions().begin(); assert != (*i)->get_assertions().end(); ++assert ) {
    69                                         haveAssertions[ *assert ].isUsed = false;
    70                                 }
    71 ///       cloneAll( (*i)->get_assertions(), haveAssertions );
    72 ///       haveAssertions.insert( haveAssertions.end(), (*i)->get_assertions().begin(), (*i)->get_assertions().end() );
    73                         } // for
    74                 } // if
    75 ///   std::cerr << "type is ";
    76 ///   type->print( std::cerr );
    77 ///   std::cerr << std::endl << "need is" << std::endl;
    78 ///   printAssertionSet( needAssertions, std::cerr );
    79 ///   std::cerr << std::endl << "have is" << std::endl;
    80 ///   printAssertionSet( haveAssertions, std::cerr );
    81         }
    82 
    83         void FindOpenVars_old::previsit(const PointerType * pointerType) {
    84                 common_action( pointerType );
    85         }
    86 
    87         void FindOpenVars_old::previsit(const ArrayType * arrayType) {
    88                 common_action( arrayType );
    89         }
    90 
    91         void FindOpenVars_old::previsit(const FunctionType * functionType) {
    92                 common_action( functionType );
    93                 nextIsOpen = ! nextIsOpen;
    94                 GuardAction( [this](){ nextIsOpen = ! nextIsOpen; } );
    95         }
    96 
    97         void FindOpenVars_old::previsit(const TupleType * tupleType) {
    98                 common_action( tupleType );
    99         }
    10025
    10126        namespace {
  • src/ResolvExpr/FindOpenVars.h

    r790d835 rc6b4432  
    1717
    1818#include "AST/TypeEnvironment.hpp"  // for AssertionSet, OpenVarSet
    19 #include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
    2019
    21 class Type;
    2220namespace ast {
    2321        class Type;
     
    2523
    2624namespace ResolvExpr {
    27         // Updates open and closed variables and their associated assertions
    28         void findOpenVars( const Type *type, OpenVarSet &openVars, OpenVarSet &closedVars, AssertionSet &needAssertions, AssertionSet &haveAssertions, bool firstIsOpen );
    29 
    3025        enum FirstMode { FirstClosed, FirstOpen };
    3126
  • src/ResolvExpr/PolyCost.cc

    r790d835 rc6b4432  
    1818#include "AST/Type.hpp"
    1919#include "AST/TypeEnvironment.hpp"
    20 #include "Common/PassVisitor.h"
    21 #include "SymTab/Indexer.h"   // for Indexer
    22 #include "SynTree/Type.h"     // for TypeInstType, Type
    23 #include "TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    2420
    2521namespace ResolvExpr {
    26         struct PolyCost {
    27                 PolyCost( const TypeEnvironment &env, const SymTab::Indexer &indexer );
    28 
    29                 void previsit( TypeInstType * aggregateUseType );
    30                 int result;
    31                 const TypeEnvironment &tenv;
    32                 const SymTab::Indexer &indexer;
    33         };
    34 
    35         int polyCost( Type *type, const TypeEnvironment & env, const SymTab::Indexer &indexer ) {
    36                 PassVisitor<PolyCost> coster( env, indexer );
    37                 type->accept( coster );
    38                 return (coster.pass.result > 0) ? 1 : 0;
    39         }
    40 
    41         PolyCost::PolyCost( const TypeEnvironment & env, const SymTab::Indexer & indexer ) : result( 0 ), tenv( env ), indexer( indexer ) {
    42         }
    43 
    44         void PolyCost::previsit(TypeInstType * typeInst) {
    45                 if ( const EqvClass *eqvClass = tenv.lookup( typeInst->name ) ) {
    46                         if ( eqvClass->type ) {
    47                                 if ( TypeInstType * otherTypeInst = dynamic_cast< TypeInstType* >( eqvClass->type ) ) {
    48                                         if ( indexer.lookupType( otherTypeInst->name ) ) {
    49                                                 // bound to opaque type
    50                                                 result += 1;
    51                                         } // if
    52                                 } else {
    53                                         // bound to concrete type
    54                                         result += 1;
    55                                 } // if
    56                         } // if
    57                 } // if
    58         }
    5922
    6023// TODO: When the old PolyCost is torn out get rid of the _new suffix.
  • src/ResolvExpr/PtrsAssignable.cc

    r790d835 rc6b4432  
    1919#include "AST/Type.hpp"
    2020#include "AST/TypeEnvironment.hpp"
    21 #include "Common/PassVisitor.h"
    22 #include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    23 #include "SynTree/Type.h"                // for TypeInstType, Type, BasicType
    24 #include "SynTree/Visitor.h"             // for Visitor
    25 
    2621
    2722namespace ResolvExpr {
    28         struct PtrsAssignable : public WithShortCircuiting {
    29                 PtrsAssignable( const Type * dest, const TypeEnvironment &env );
    30 
    31                 int get_result() const { return result; }
    32 
    33                 void previsit( const Type * ) { visit_children = false; }
    34 
    35                 void postvisit( const VoidType * voidType );
    36                 void postvisit( const BasicType * basicType );
    37                 void postvisit( const PointerType * pointerType );
    38                 void postvisit( const ArrayType * arrayType );
    39                 void postvisit( const FunctionType * functionType );
    40                 void postvisit( const StructInstType * inst );
    41                 void postvisit( const UnionInstType * inst );
    42                 void postvisit( const EnumInstType * inst );
    43                 void postvisit( const TraitInstType * inst );
    44                 void postvisit( const TypeInstType * inst );
    45                 void postvisit( const TupleType * tupleType );
    46                 void postvisit( const VarArgsType * varArgsType );
    47                 void postvisit( const ZeroType * zeroType );
    48                 void postvisit( const OneType * oneType );
    49           private:
    50                 const Type * dest;
    51                 int result;
    52                 const TypeEnvironment &env;
    53         };
    54 
    55         int ptrsAssignable( const Type *src, const Type * dest, const TypeEnvironment &env ) {
    56                 // std::cerr << "assignable: " << src << " | " << dest << std::endl;
    57                 if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType* >( dest ) ) {
    58                         if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
    59                                 return ptrsAssignable( src, eqvClass->type, env );
    60                         } // if
    61                 } // if
    62                 if ( dynamic_cast< const VoidType* >( dest ) ) {
    63                         // void * = T * for any T is unsafe
    64                         // xxx - this should be safe, but that currently breaks the build
    65                         return -1;
    66                 } else {
    67                         PassVisitor<PtrsAssignable> ptrs( dest, env );
    68                         src->accept( ptrs );
    69                         return ptrs.pass.get_result();
    70                 } // if
    71         }
    72 
    73         PtrsAssignable::PtrsAssignable( const Type * dest, const TypeEnvironment &env ) : dest( dest ), result( 0 ), env( env ) {}
    74 
    75         void PtrsAssignable::postvisit( const VoidType * ) {
    76                 // T * = void * is disallowed - this is a change from C, where any
    77                 // void * can be assigned or passed to a non-void pointer without a cast.
    78         }
    79 
    80         void PtrsAssignable::postvisit( const BasicType * ) {}
    81         void PtrsAssignable::postvisit( const PointerType * ) {}
    82         void PtrsAssignable::postvisit( const ArrayType * ) {}
    83         void PtrsAssignable::postvisit( const FunctionType * ) {}
    84 
    85         void PtrsAssignable::postvisit( const StructInstType * ) {}
    86         void PtrsAssignable::postvisit( const UnionInstType * ) {}
    87 
    88         void PtrsAssignable::postvisit( const EnumInstType * ) {
    89                 if ( dynamic_cast< const BasicType* >( dest ) ) {
    90                         // int * = E *, etc. is safe. This isn't technically correct, as each
    91                         // enum has one basic type that it is compatible with, an that type can
    92                         // differ from enum to enum. Without replicating GCC's internal logic,
    93                         // there is no way to know which type this particular enum is compatible
    94                         // with, so punt on this for now.
    95                         result = 1;
    96                 }
    97         }
    98 
    99         void PtrsAssignable::postvisit(  const TraitInstType * ) {}
    100         void PtrsAssignable::postvisit( const TypeInstType * inst ) {
    101                 if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
    102                         if ( eqvClass->type ) {
    103                                 // T * = S * for any S depends on the type bound to T
    104                                 result = ptrsAssignable( eqvClass->type, dest, env );
    105                         }
    106                 } // if
    107         }
    108 
    109         void PtrsAssignable::postvisit( const TupleType * ) {}
    110         void PtrsAssignable::postvisit( const VarArgsType * ) {}
    111         void PtrsAssignable::postvisit( const ZeroType * ) {}
    112         void PtrsAssignable::postvisit( const OneType * ) {}
    11323
    11424// TODO: Get rid of the `_new` suffix when the old version is removed.
  • src/ResolvExpr/PtrsCastable.cc

    r790d835 rc6b4432  
    2020#include "AST/Type.hpp"
    2121#include "AST/TypeEnvironment.hpp"
    22 #include "Common/PassVisitor.h"
    2322#include "ResolvExpr/PtrsAssignable.hpp" // for ptrsAssignable
    24 #include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
    25 #include "SymTab/Indexer.h"              // for Indexer
    26 #include "SynTree/Declaration.h"         // for TypeDecl, TypeDecl::Kind::Ftype
    27 #include "SynTree/Type.h"                // for TypeInstType, Type, BasicType
    28 #include "SynTree/Visitor.h"             // for Visitor
    2923
    3024namespace ResolvExpr {
    31         struct PtrsCastable_old : public WithShortCircuiting  {
    32           public:
    33                 PtrsCastable_old( const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer );
    34 
    35                 int get_result() const { return result; }
    36 
    37                 void previsit( const Type * ) { visit_children = false; }
    38 
    39                 void postvisit( const VoidType * voidType );
    40                 void postvisit( const BasicType * basicType );
    41                 void postvisit( const PointerType * pointerType );
    42                 void postvisit( const ArrayType * arrayType );
    43                 void postvisit( const FunctionType * functionType );
    44                 void postvisit( const StructInstType * inst );
    45                 void postvisit( const UnionInstType * inst );
    46                 void postvisit( const EnumInstType * inst );
    47                 void postvisit( const TraitInstType * inst );
    48                 void postvisit( const TypeInstType * inst );
    49                 void postvisit( const TupleType * tupleType );
    50                 void postvisit( const VarArgsType * varArgsType );
    51                 void postvisit( const ZeroType * zeroType );
    52                 void postvisit( const OneType * oneType );
    53           private:
    54                 const Type * dest;
    55                 int result;
    56                 const TypeEnvironment &env;
    57                 const SymTab::Indexer &indexer;
    58         };
    59 
    60         namespace {
    61                 int objectCast( const Type * src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    62                         if ( dynamic_cast< const FunctionType* >( src ) ) {
    63                                 return -1;
    64                         } else if ( const TypeInstType * typeInst = dynamic_cast< const TypeInstType* >( src ) ) {
    65                                 if ( const NamedTypeDecl * ntDecl = indexer.lookupType( typeInst->name ) ) {
    66                                         if ( const TypeDecl * tyDecl = dynamic_cast< const TypeDecl* >( ntDecl ) ) {
    67                                                 if ( tyDecl->kind == TypeDecl::Ftype ) {
    68                                                         return -1;
    69                                                 } // if
    70                                         } //if
    71                                 } else if ( const EqvClass * eqvClass = env.lookup( typeInst->get_name() ) ) {
    72                                         if ( eqvClass->data.kind == TypeDecl::Ftype ) {
    73                                                 return -1;
    74                                         } // if
    75                                 } // if
    76                         } //if
    77                         return 1;
    78                 }
    79                 int functionCast( const Type * src, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    80                         return -1 * objectCast( src, env, indexer );  // reverse the sense of objectCast
    81                 }
    82         }
    83 
    84         int ptrsCastable( const Type * src, const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer ) {
    85                 if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType* >( dest ) ) {
    86                         if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
    87                                 // xxx - should this be ptrsCastable?
    88                                 return ptrsAssignable( src, eqvClass->type, env );
    89                         } // if
    90                 } // if
    91                 if ( dynamic_cast< const VoidType* >( dest ) ) {
    92                         return objectCast( src, env, indexer );
    93                 } else {
    94                         PassVisitor<PtrsCastable_old> ptrs( dest, env, indexer );
    95                         src->accept( ptrs );
    96                         return ptrs.pass.get_result();
    97                 } // if
    98         }
    99 
    100         PtrsCastable_old::PtrsCastable_old( const Type * dest, const TypeEnvironment &env, const SymTab::Indexer &indexer )
    101                 : dest( dest ), result( 0 ), env( env ), indexer( indexer )     {
    102         }
    103 
    104         void PtrsCastable_old::postvisit( const VoidType * ) {
    105                 result = objectCast( dest, env, indexer );
    106         }
    107 
    108         void PtrsCastable_old::postvisit( const BasicType * ) {
    109                 result = objectCast( dest, env, indexer );
    110         }
    111 
    112         void PtrsCastable_old::postvisit( const PointerType * ) {
    113                 result = objectCast( dest, env, indexer );
    114         }
    115 
    116         void PtrsCastable_old::postvisit( const ArrayType * ) {
    117                 result = objectCast( dest, env, indexer );
    118         }
    119 
    120         void PtrsCastable_old::postvisit( const FunctionType * ) {
    121                 // result = -1;
    122                 result = functionCast( dest, env, indexer );
    123         }
    124 
    125         void PtrsCastable_old::postvisit( const StructInstType * ) {
    126                 result = objectCast( dest, env, indexer );
    127         }
    128 
    129         void PtrsCastable_old::postvisit( const UnionInstType * ) {
    130                 result = objectCast( dest, env, indexer );
    131         }
    132 
    133         void PtrsCastable_old::postvisit( const EnumInstType * ) {
    134                 if ( dynamic_cast< const EnumInstType * >( dest ) ) {
    135                         result = 1;
    136                 } else if ( const BasicType * bt = dynamic_cast< const BasicType * >( dest ) ) {
    137                         if ( bt->kind == BasicType::SignedInt ) {
    138                                 result = 0;
    139                         } else {
    140                                 result = 1;
    141                         }
    142                 } else {
    143                         result = objectCast( dest, env, indexer );
    144                 }
    145         }
    146 
    147         void PtrsCastable_old::postvisit( const TraitInstType * ) {}
    148 
    149         void PtrsCastable_old::postvisit( const TypeInstType *inst ) {
    150                 //result = objectCast( inst, env, indexer ) > 0 && objectCast( dest, env, indexer ) > 0 ? 1 : -1;
    151                 result = objectCast( inst, env, indexer ) == objectCast( dest, env, indexer ) ? 1 : -1;
    152         }
    153 
    154         void PtrsCastable_old::postvisit( const TupleType * ) {
    155                 result = objectCast( dest, env, indexer );
    156         }
    157 
    158         void PtrsCastable_old::postvisit( const VarArgsType * ) {
    159                 result = objectCast( dest, env, indexer );
    160         }
    161 
    162         void PtrsCastable_old::postvisit( const ZeroType * ) {
    163                 result = objectCast( dest, env, indexer );
    164         }
    165 
    166         void PtrsCastable_old::postvisit( const OneType * ) {
    167                 result = objectCast( dest, env, indexer );
    168         }
    16925
    17026namespace {
  • src/ResolvExpr/RenameVars.cc

    r790d835 rc6b4432  
    2121#include "AST/Pass.hpp"
    2222#include "AST/Type.hpp"
    23 #include "Common/PassVisitor.h"
    2423#include "Common/ScopedMap.h"
    2524#include "Common/SemanticError.h"  // for SemanticError
    2625#include "RenameVars.h"
    27 #include "SynTree/Declaration.h"   // for DeclarationWithType, TypeDecl, Dec...
    28 #include "SynTree/Expression.h"    // for Expression
    29 #include "SynTree/Type.h"          // for Type, TypeInstType, TraitInstType
    30 #include "SynTree/Visitor.h"       // for acceptAll, maybeAccept
    3126
    3227#include "AST/Copy.hpp"
     
    4944                }
    5045
    51                 void rename( TypeInstType * type ) {
    52                         auto it = nameMap.find( type->name );
    53                         if ( it != nameMap.end() ) {
    54                                 type->name = it->second;
    55                         }
    56                 }
    57 
    5846                void nextUsage() {
    5947                        ++next_usage_id;
    60                 }
    61 
    62                 void openLevel( Type * type ) {
    63                         if ( ! type->forall.empty() ) {
    64                                 nameMap.beginScope();
    65                                 // renames all "forall" type names to `_${level}_${name}'
    66                                 for ( auto td : type->forall ) {
    67                                         std::ostringstream output;
    68                                         output << "_" << resetCount << "_" << level << "_" << td->name;
    69                                         std::string newname( output.str() );
    70                                         nameMap[ td->get_name() ] = newname;
    71                                         td->name = newname;
    72                                         // ditto for assertion names, the next level in
    73                                         level++;
    74                                 }
    75                         }
    76                 }
    77 
    78                 void closeLevel( Type * type ) {
    79                         if ( !type->forall.empty() ) {
    80                                 nameMap.endScope();
    81                         }
    8248                }
    8349
     
    135101        RenamingData renaming;
    136102
    137         struct RenameVars_old {
    138                 void previsit( TypeInstType * instType ) {
    139                         renaming.openLevel( (Type*)instType );
    140                         renaming.rename( instType );
    141                 }
    142                 void previsit( Type * type ) {
    143                         renaming.openLevel( type );
    144                 }
    145                 void postvisit( Type * type ) {
    146                         renaming.closeLevel( type );
    147                 }
    148         };
    149 
    150103        struct RenameVars_new : public ast::PureVisitor /*: public ast::WithForallSubstitutor*/ {
    151104                RenameMode mode;
     
    178131} // namespace
    179132
    180 void renameTyVars( Type * t ) {
    181         PassVisitor<RenameVars_old> renamer;
    182         t->accept( renamer );
    183 }
    184 
    185133const ast::Type * renameTyVars( const ast::Type * t, RenameMode mode, bool reset ) {
    186134        ast::Pass<RenameVars_new> renamer;
  • src/ResolvExpr/RenameVars.h

    r790d835 rc6b4432  
    1616#pragma once
    1717
    18 #include <list>               // for list
    19 #include <map>                // for map
    20 #include <string>             // for string
    21 
    22 #include "SynTree/SynTree.h"  // for Visitor Nodes
    23 #include "SynTree/Visitor.h"  // for Visitor
    24 
    2518namespace ast {
    2619        class Type;
     
    2821
    2922namespace ResolvExpr {
    30         /// Provides a consistent renaming of forall type names in a hierarchy by prefixing them with a unique "level" ID
    31         void renameTyVars( Type * );
    32 
    3323        enum RenameMode {
    3424                GEN_USAGE, // for type in VariableExpr
  • src/ResolvExpr/ResolveTypeof.cc

    r790d835 rc6b4432  
    2424#include "AST/Type.hpp"
    2525#include "AST/TypeEnvironment.hpp"
    26 #include "Common/PassVisitor.h"   // for PassVisitor
    2726#include "Common/utility.h"       // for copy
    2827#include "InitTweak/InitTweak.h"  // for isConstExpr
     
    3029#include "Resolver.h"  // for resolveInVoidContext
    3130#include "SymTab/Mangler.h"
    32 #include "SynTree/Expression.h"  // for Expression
    33 #include "SynTree/Mutator.h"     // for Mutator
    34 #include "SynTree/Type.h"        // for TypeofType, Type
    35 
    36 namespace SymTab {
    37 class Indexer;
    38 }  // namespace SymTab
    3931
    4032namespace ResolvExpr {
    41 namespace {
    42 #if 0
    43                 void
    44                 printAlts( const AltList &list, std::ostream &os, int indent = 0 )
    45                 {
    46                         for ( AltList::const_iterator i = list.begin(); i != list.end(); ++i ) {
    47                                 i->print( os, indent );
    48                                 os << std::endl;
    49                         }
    50                 }
    51 #endif
    52         }
    53 
    54 class ResolveTypeof_old : public WithShortCircuiting {
    55    public:
    56                 ResolveTypeof_old( const SymTab::Indexer &indexer ) : indexer( indexer ) {}
    57                 void premutate( TypeofType *typeofType );
    58                 Type * postmutate( TypeofType *typeofType );
    59 
    60    private:
    61     const SymTab::Indexer &indexer;
    62 };
    63 
    64         Type * resolveTypeof( Type *type, const SymTab::Indexer &indexer ) {
    65                 PassVisitor<ResolveTypeof_old> mutator( indexer );
    66                 return type->acceptMutator( mutator );
    67         }
    68 
    69         void ResolveTypeof_old::premutate( TypeofType * ) {
    70                 visit_children = false;
    71         }
    72 
    73     Type * ResolveTypeof_old::postmutate( TypeofType *typeofType ) {
    74 #if 0
    75                 std::cerr << "resolving typeof: ";
    76                 typeofType->print( std::cerr );
    77                 std::cerr << std::endl;
    78 #endif
    79     // pass on null expression
    80                 if ( ! typeofType->expr ) return typeofType;
    81 
    82     bool isBasetypeof = typeofType->is_basetypeof;
    83     auto oldQuals = typeofType->get_qualifiers().val;
    84 
    85     Type* newType;
    86                 if ( TypeExpr* tyExpr = dynamic_cast<TypeExpr*>(typeofType->expr) ) {
    87         // typeof wrapping type
    88         newType = tyExpr->type;
    89         tyExpr->type = nullptr;
    90         delete tyExpr;
    91     } else {
    92         // typeof wrapping expression
    93                         Expression * newExpr = resolveInVoidContext( typeofType->expr, indexer );
    94                         assert( newExpr->result && ! newExpr->result->isVoid() );
    95         newType = newExpr->result;
    96         newExpr->result = nullptr;
    97         delete typeofType;
    98         delete newExpr;
    99     }
    100 
    101     // clear qualifiers for base, combine with typeoftype quals in any case
    102     if ( isBasetypeof ) {
    103                         // replace basetypeof(<enum>) by int
    104                         if ( dynamic_cast<EnumInstType*>(newType) ) {
    105                                 Type* newerType =
    106                                         new BasicType{ newType->get_qualifiers(), BasicType::SignedInt,
    107                                         newType->attributes };
    108                                 delete newType;
    109                                 newType = newerType;
    110                         }
    111                         newType->get_qualifiers().val
    112                                 = ( newType->get_qualifiers().val & ~Type::Qualifiers::Mask ) | oldQuals;
    113                 } else {
    114         newType->get_qualifiers().val |= oldQuals;
    115     }
    116 
    117     return newType;
    118 }
    11933
    12034namespace {
  • src/ResolvExpr/Resolver.cc

    r790d835 rc6b4432  
    1919#include <vector>                        // for vector
    2020
    21 #include "Alternative.h"                 // for Alternative, AltList
    22 #include "AlternativeFinder.h"           // for AlternativeFinder, resolveIn...
    2321#include "Candidate.hpp"
    2422#include "CandidateFinder.hpp"
     
    4038#include "Common/Eval.h"                 // for eval
    4139#include "Common/Iterate.hpp"            // for group_iterate
    42 #include "Common/PassVisitor.h"          // for PassVisitor
    4340#include "Common/SemanticError.h"        // for SemanticError
    4441#include "Common/Stats/ResolveTime.h"    // for ResolveTime::start(), ResolveTime::stop()
    4542#include "Common/ToString.hpp"           // for toCString
     43#include "Common/UniqueName.h"           // for UniqueName
    4644#include "InitTweak/GenInit.h"
    4745#include "InitTweak/InitTweak.h"         // for isIntrinsicSingleArgCallStmt
    48 #include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
    49 #include "SymTab/Autogen.h"              // for SizeType
    50 #include "SymTab/Indexer.h"              // for Indexer
    5146#include "SymTab/Mangler.h"              // for Mangler
    52 #include "SynTree/Declaration.h"         // for ObjectDecl, TypeDecl, Declar...
    53 #include "SynTree/Expression.h"          // for Expression, CastExpr, InitExpr
    54 #include "SynTree/Initializer.h"         // for ConstructorInit, SingleInit
    55 #include "SynTree/Statement.h"           // for ForStmt, Statement, BranchStmt
    56 #include "SynTree/Type.h"                // for Type, BasicType, PointerType
    57 #include "SynTree/TypeSubstitution.h"    // for TypeSubstitution
    58 #include "SynTree/Visitor.h"             // for acceptAll, maybeAccept
    5947#include "Tuples/Tuples.h"
    6048#include "Validate/FindSpecialDecls.h"   // for SizeType
     
    6351
    6452namespace ResolvExpr {
    65         struct Resolver_old final : public WithIndexer, public WithGuards, public WithVisitorRef<Resolver_old>, public WithShortCircuiting, public WithStmtsToAdd {
    66                 Resolver_old() {}
    67                 Resolver_old( const SymTab::Indexer & other ) {
    68                         indexer = other;
    69                 }
    70 
    71                 void previsit( FunctionDecl * functionDecl );
    72                 void postvisit( FunctionDecl * functionDecl );
    73                 void previsit( ObjectDecl * objectDecll );
    74                 void previsit( EnumDecl * enumDecl );
    75                 void previsit( StaticAssertDecl * assertDecl );
    76 
    77                 void previsit( ArrayType * at );
    78                 void previsit( PointerType * at );
    79 
    80                 void previsit( ExprStmt * exprStmt );
    81                 void previsit( AsmExpr * asmExpr );
    82                 void previsit( AsmStmt * asmStmt );
    83                 void previsit( IfStmt * ifStmt );
    84                 void previsit( WhileDoStmt * whileDoStmt );
    85                 void previsit( ForStmt * forStmt );
    86                 void previsit( SwitchStmt * switchStmt );
    87                 void previsit( CaseStmt * caseStmt );
    88                 void previsit( BranchStmt * branchStmt );
    89                 void previsit( ReturnStmt * returnStmt );
    90                 void previsit( ThrowStmt * throwStmt );
    91                 void previsit( CatchStmt * catchStmt );
    92                 void postvisit( CatchStmt * catchStmt );
    93                 void previsit( WaitForStmt * stmt );
    94 
    95                 void previsit( SingleInit * singleInit );
    96                 void previsit( ListInit * listInit );
    97                 void previsit( ConstructorInit * ctorInit );
    98           private:
    99                 typedef std::list< Initializer * >::iterator InitIterator;
    100 
    101                 template< typename PtrType >
    102                 void handlePtrType( PtrType * type );
    103 
    104                 void fallbackInit( ConstructorInit * ctorInit );
    105 
    106                 Type * functionReturn = nullptr;
    107                 CurrentObject currentObject = nullptr;
    108                 bool inEnumDecl = false;
    109         };
    110 
    111         struct ResolveWithExprs : public WithIndexer, public WithGuards, public WithVisitorRef<ResolveWithExprs>, public WithShortCircuiting, public WithStmtsToAdd {
    112                 void previsit( FunctionDecl * );
    113                 void previsit( WithStmt * );
    114 
    115                 void resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts );
    116         };
    117 
    118         void resolve( std::list< Declaration * > translationUnit ) {
    119                 PassVisitor<Resolver_old> resolver;
    120                 acceptAll( translationUnit, resolver );
    121         }
    122 
    123         void resolveDecl( Declaration * decl, const SymTab::Indexer & indexer ) {
    124                 PassVisitor<Resolver_old> resolver( indexer );
    125                 maybeAccept( decl, resolver );
    126         }
    127 
    128         namespace {
    129                 struct DeleteFinder_old : public WithShortCircuiting    {
    130                         DeletedExpr * delExpr = nullptr;
    131                         void previsit( DeletedExpr * expr ) {
    132                                 if ( delExpr ) visit_children = false;
    133                                 else delExpr = expr;
    134                         }
    135 
    136                         void previsit( Expression * ) {
    137                                 if ( delExpr ) visit_children = false;
    138                         }
    139                 };
    140         }
    141 
    142         DeletedExpr * findDeletedExpr( Expression * expr ) {
    143                 PassVisitor<DeleteFinder_old> finder;
    144                 expr->accept( finder );
    145                 return finder.pass.delExpr;
    146         }
    147 
    148         namespace {
    149                 struct StripCasts_old {
    150                         Expression * postmutate( CastExpr * castExpr ) {
    151                                 if ( castExpr->isGenerated && ResolvExpr::typesCompatible( castExpr->arg->result, castExpr->result, SymTab::Indexer() ) ) {
    152                                         // generated cast is to the same type as its argument, so it's unnecessary -- remove it
    153                                         Expression * expr = castExpr->arg;
    154                                         castExpr->arg = nullptr;
    155                                         std::swap( expr->env, castExpr->env );
    156                                         return expr;
    157                                 }
    158                                 return castExpr;
    159                         }
    160 
    161                         static void strip( Expression *& expr ) {
    162                                 PassVisitor<StripCasts_old> stripper;
    163                                 expr = expr->acceptMutator( stripper );
    164                         }
    165                 };
    166 
    167                 void finishExpr( Expression *& expr, const TypeEnvironment & env, TypeSubstitution * oldenv = nullptr ) {
    168                         expr->env = oldenv ? oldenv->clone() : new TypeSubstitution;
    169                         env.makeSubstitution( *expr->env );
    170                         StripCasts_old::strip( expr ); // remove unnecessary casts that may be buried in an expression
    171                 }
    172 
    173                 void removeExtraneousCast( Expression *& expr, const SymTab::Indexer & indexer ) {
    174                         if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    175                                 if ( typesCompatible( castExpr->arg->result, castExpr->result, indexer ) ) {
    176                                         // cast is to the same type as its argument, so it's unnecessary -- remove it
    177                                         expr = castExpr->arg;
    178                                         castExpr->arg = nullptr;
    179                                         std::swap( expr->env, castExpr->env );
    180                                         delete castExpr;
    181                                 }
    182                         }
    183                 }
    184         } // namespace
    185 
    186         namespace {
    187                 void findUnfinishedKindExpression(Expression * untyped, Alternative & alt, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{} ) {
    188                         assertf( untyped, "expected a non-null expression." );
    189 
    190                         // xxx - this isn't thread-safe, but should work until we parallelize the resolver
    191                         static unsigned recursion_level = 0;
    192 
    193                         ++recursion_level;
    194                         TypeEnvironment env;
    195                         AlternativeFinder finder( indexer, env );
    196                         finder.find( untyped, recursion_level == 1 ? mode.atTopLevel() : mode );
    197                         --recursion_level;
    198 
    199                         #if 0
    200                         if ( finder.get_alternatives().size() != 1 ) {
    201                                 std::cerr << "untyped expr is ";
    202                                 untyped->print( std::cerr );
    203                                 std::cerr << std::endl << "alternatives are:";
    204                                 for ( const Alternative & alt : finder.get_alternatives() ) {
    205                                         alt.print( std::cerr );
    206                                 } // for
    207                         } // if
    208                         #endif
    209 
    210                         // produce filtered list of alternatives
    211                         AltList candidates;
    212                         for ( Alternative & alt : finder.get_alternatives() ) {
    213                                 if ( pred( alt ) ) {
    214                                         candidates.push_back( std::move( alt ) );
    215                                 }
    216                         }
    217 
    218                         // produce invalid error if no candidates
    219                         if ( candidates.empty() ) {
    220                                 SemanticError( untyped, toString( "No reasonable alternatives for ", kindStr, (kindStr != "" ? " " : ""), "expression: ") );
    221                         }
    222 
    223                         // search for cheapest candidate
    224                         AltList winners;
    225                         bool seen_undeleted = false;
    226                         for ( unsigned i = 0; i < candidates.size(); ++i ) {
    227                                 int c = winners.empty() ? -1 : candidates[i].cost.compare( winners.front().cost );
    228 
    229                                 if ( c > 0 ) continue; // skip more expensive than winner
    230 
    231                                 if ( c < 0 ) {
    232                                         // reset on new cheapest
    233                                         seen_undeleted = ! findDeletedExpr( candidates[i].expr );
    234                                         winners.clear();
    235                                 } else /* if ( c == 0 ) */ {
    236                                         if ( findDeletedExpr( candidates[i].expr ) ) {
    237                                                 // skip deleted expression if already seen one equivalent-cost not
    238                                                 if ( seen_undeleted ) continue;
    239                                         } else if ( ! seen_undeleted ) {
    240                                                 // replace list of equivalent-cost deleted expressions with one non-deleted
    241                                                 winners.clear();
    242                                                 seen_undeleted = true;
    243                                         }
    244                                 }
    245 
    246                                 winners.emplace_back( std::move( candidates[i] ) );
    247                         }
    248 
    249                         // promote alternative.cvtCost to .cost
    250                         // xxx - I don't know why this is done, but I'm keeping the behaviour from findMinCost
    251                         for ( Alternative& winner : winners ) {
    252                                 winner.cost = winner.cvtCost;
    253                         }
    254 
    255                         // produce ambiguous errors, if applicable
    256                         if ( winners.size() != 1 ) {
    257                                 std::ostringstream stream;
    258                                 stream << "Cannot choose between " << winners.size() << " alternatives for " << kindStr << (kindStr != "" ? " " : "") << "expression\n";
    259                                 untyped->print( stream );
    260                                 stream << " Alternatives are:\n";
    261                                 printAlts( winners, stream, 1 );
    262                                 SemanticError( untyped->location, stream.str() );
    263                         }
    264 
    265                         // single selected choice
    266                         Alternative& choice = winners.front();
    267 
    268                         // fail on only expression deleted
    269                         if ( ! seen_undeleted ) {
    270                                 SemanticError( untyped->location, choice.expr, "Unique best alternative includes deleted identifier in " );
    271                         }
    272 
    273                         // xxx - check for ambiguous expressions
    274 
    275                         // output selected choice
    276                         alt = std::move( choice );
    277                 }
    278 
    279                 /// resolve `untyped` to the expression whose alternative satisfies `pred` with the lowest cost; kindStr is used for providing better error messages
    280                 void findKindExpression(Expression *& untyped, const SymTab::Indexer & indexer, const std::string & kindStr, std::function<bool(const Alternative &)> pred, ResolvMode mode = ResolvMode{}) {
    281                         if ( ! untyped ) return;
    282                         Alternative choice;
    283                         findUnfinishedKindExpression( untyped, choice, indexer, kindStr, pred, mode );
    284                         finishExpr( choice.expr, choice.env, untyped->env );
    285                         delete untyped;
    286                         untyped = choice.expr;
    287                         choice.expr = nullptr;
    288                 }
    289 
    290                 bool standardAlternativeFilter( const Alternative & ) {
    291                         // currently don't need to filter, under normal circumstances.
    292                         // in the future, this may be useful for removing deleted expressions
    293                         return true;
    294                 }
    295         } // namespace
    296 
    297         // used in resolveTypeof
    298         Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer ) {
    299                 TypeEnvironment env;
    300                 return resolveInVoidContext( expr, indexer, env );
    301         }
    302 
    303         Expression * resolveInVoidContext( Expression * expr, const SymTab::Indexer & indexer, TypeEnvironment & env ) {
    304                 // it's a property of the language that a cast expression has either 1 or 0 interpretations; if it has 0
    305                 // interpretations, an exception has already been thrown.
    306                 assertf( expr, "expected a non-null expression." );
    307 
    308                 CastExpr * untyped = new CastExpr( expr ); // cast to void
    309                 untyped->location = expr->location;
    310 
    311                 // set up and resolve expression cast to void
    312                 Alternative choice;
    313                 findUnfinishedKindExpression( untyped, choice, indexer, "", standardAlternativeFilter, ResolvMode::withAdjustment() );
    314                 CastExpr * castExpr = strict_dynamic_cast< CastExpr * >( choice.expr );
    315                 assert( castExpr );
    316                 env = std::move( choice.env );
    317 
    318                 // clean up resolved expression
    319                 Expression * ret = castExpr->arg;
    320                 castExpr->arg = nullptr;
    321 
    322                 // unlink the arg so that it isn't deleted twice at the end of the program
    323                 untyped->arg = nullptr;
    324                 return ret;
    325         }
    326 
    327         void findVoidExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
    328                 resetTyVarRenaming();
    329                 TypeEnvironment env;
    330                 Expression * newExpr = resolveInVoidContext( untyped, indexer, env );
    331                 finishExpr( newExpr, env, untyped->env );
    332                 delete untyped;
    333                 untyped = newExpr;
    334         }
    335 
    336         void findSingleExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
    337                 findKindExpression( untyped, indexer, "", standardAlternativeFilter );
    338         }
    339 
    340         void findSingleExpression( Expression *& untyped, Type * type, const SymTab::Indexer & indexer ) {
    341                 assert( untyped && type );
    342                 // transfer location to generated cast for error purposes
    343                 CodeLocation location = untyped->location;
    344                 untyped = new CastExpr( untyped, type );
    345                 untyped->location = location;
    346                 findSingleExpression( untyped, indexer );
    347                 removeExtraneousCast( untyped, indexer );
    348         }
    349 
    350         namespace {
    351                 bool isIntegralType( const Alternative & alt ) {
    352                         Type * type = alt.expr->result;
    353                         if ( dynamic_cast< EnumInstType * >( type ) ) {
    354                                 return true;
    355                         } else if ( BasicType * bt = dynamic_cast< BasicType * >( type ) ) {
    356                                 return bt->isInteger();
    357                         } else if ( dynamic_cast< ZeroType* >( type ) != nullptr || dynamic_cast< OneType* >( type ) != nullptr ) {
    358                                 return true;
    359                         } else {
    360                                 return false;
    361                         } // if
    362                 }
    363 
    364                 void findIntegralExpression( Expression *& untyped, const SymTab::Indexer & indexer ) {
    365                         findKindExpression( untyped, indexer, "condition", isIntegralType );
    366                 }
    367         }
    368 
    369 
    370         bool isStructOrUnion( const Alternative & alt ) {
    371                 Type * t = alt.expr->result->stripReferences();
    372                 return dynamic_cast< StructInstType * >( t ) || dynamic_cast< UnionInstType * >( t );
    373         }
    374 
    375         void resolveWithExprs( std::list< Declaration * > & translationUnit ) {
    376                 PassVisitor<ResolveWithExprs> resolver;
    377                 acceptAll( translationUnit, resolver );
    378         }
    379 
    380         void ResolveWithExprs::resolveWithExprs( std::list< Expression * > & withExprs, std::list< Statement * > & newStmts ) {
    381                 for ( Expression *& expr : withExprs )  {
    382                         // only struct- and union-typed expressions are viable candidates
    383                         findKindExpression( expr, indexer, "with statement", isStructOrUnion );
    384 
    385                         // if with expression might be impure, create a temporary so that it is evaluated once
    386                         if ( Tuples::maybeImpure( expr ) ) {
    387                                 static UniqueName tmpNamer( "_with_tmp_" );
    388                                 ObjectDecl * tmp = ObjectDecl::newObject( tmpNamer.newName(), expr->result->clone(), new SingleInit( expr ) );
    389                                 expr = new VariableExpr( tmp );
    390                                 newStmts.push_back( new DeclStmt( tmp ) );
    391                                 if ( InitTweak::isConstructable( tmp->type ) ) {
    392                                         // generate ctor/dtor and resolve them
    393                                         tmp->init = InitTweak::genCtorInit( tmp );
    394                                         tmp->accept( *visitor );
    395                                 }
    396                         }
    397                 }
    398         }
    399 
    400         void ResolveWithExprs::previsit( WithStmt * withStmt ) {
    401                 resolveWithExprs( withStmt->exprs, stmtsToAddBefore );
    402         }
    403 
    404         void ResolveWithExprs::previsit( FunctionDecl * functionDecl ) {
    405                 {
    406                         // resolve with-exprs with parameters in scope and add any newly generated declarations to the
    407                         // front of the function body.
    408                         auto guard = makeFuncGuard( [this]() { indexer.enterScope(); }, [this](){ indexer.leaveScope(); } );
    409                         indexer.addFunctionType( functionDecl->type );
    410                         std::list< Statement * > newStmts;
    411                         resolveWithExprs( functionDecl->withExprs, newStmts );
    412                         if ( functionDecl->statements ) {
    413                                 functionDecl->statements->kids.splice( functionDecl->statements->kids.begin(), newStmts );
    414                         } else {
    415                                 assertf( functionDecl->withExprs.empty() && newStmts.empty(), "Function %s without a body has with-clause and/or generated with declarations.", functionDecl->name.c_str() );
    416                         }
    417                 }
    418         }
    419 
    420         void Resolver_old::previsit( ObjectDecl * objectDecl ) {
    421                 // To handle initialization of routine pointers, e.g., int (*fp)(int) = foo(), means that
    422                 // class-variable initContext is changed multiple time because the LHS is analysed twice.
    423                 // The second analysis changes initContext because of a function type can contain object
    424                 // declarations in the return and parameter types. So each value of initContext is
    425                 // retained, so the type on the first analysis is preserved and used for selecting the RHS.
    426                 GuardValue( currentObject );
    427                 currentObject = CurrentObject( objectDecl->get_type() );
    428                 if ( inEnumDecl && dynamic_cast< EnumInstType * >( objectDecl->get_type() ) ) {
    429                         // enumerator initializers should not use the enum type to initialize, since
    430                         // the enum type is still incomplete at this point. Use signed int instead.
    431                         // TODO: BasicType::SignedInt may not longer be true
    432                         currentObject = CurrentObject( new BasicType( Type::Qualifiers(), BasicType::SignedInt ) );
    433                 }
    434         }
    435 
    436         template< typename PtrType >
    437         void Resolver_old::handlePtrType( PtrType * type ) {
    438                 if ( type->get_dimension() ) {
    439                         findSingleExpression( type->dimension, Validate::SizeType->clone(), indexer );
    440                 }
    441         }
    442 
    443         void Resolver_old::previsit( ArrayType * at ) {
    444                 handlePtrType( at );
    445         }
    446 
    447         void Resolver_old::previsit( PointerType * pt ) {
    448                 handlePtrType( pt );
    449         }
    450 
    451         void Resolver_old::previsit( FunctionDecl * functionDecl ) {
    452 #if 0
    453                 std::cerr << "resolver visiting functiondecl ";
    454                 functionDecl->print( std::cerr );
    455                 std::cerr << std::endl;
    456 #endif
    457                 GuardValue( functionReturn );
    458                 functionReturn = ResolvExpr::extractResultType( functionDecl->type );
    459         }
    460 
    461         void Resolver_old::postvisit( FunctionDecl * functionDecl ) {
    462                 // default value expressions have an environment which shouldn't be there and trips up
    463                 // later passes.
    464                 // xxx - it might be necessary to somehow keep the information from this environment, but I
    465                 // can't currently see how it's useful.
    466                 for ( Declaration * d : functionDecl->type->parameters ) {
    467                         if ( ObjectDecl * obj = dynamic_cast< ObjectDecl * >( d ) ) {
    468                                 if ( SingleInit * init = dynamic_cast< SingleInit * >( obj->init ) ) {
    469                                         delete init->value->env;
    470                                         init->value->env = nullptr;
    471                                 }
    472                         }
    473                 }
    474         }
    475 
    476         void Resolver_old::previsit( EnumDecl * ) {
    477                 // in case we decide to allow nested enums
    478                 GuardValue( inEnumDecl );
    479                 inEnumDecl = true;
    480         }
    481 
    482         void Resolver_old::previsit( StaticAssertDecl * assertDecl ) {
    483                 findIntegralExpression( assertDecl->condition, indexer );
    484         }
    485 
    486         void Resolver_old::previsit( ExprStmt * exprStmt ) {
    487                 visit_children = false;
    488                 assertf( exprStmt->expr, "ExprStmt has null Expression in resolver" );
    489                 findVoidExpression( exprStmt->expr, indexer );
    490         }
    491 
    492         void Resolver_old::previsit( AsmExpr * asmExpr ) {
    493                 visit_children = false;
    494                 findVoidExpression( asmExpr->operand, indexer );
    495         }
    496 
    497         void Resolver_old::previsit( AsmStmt * asmStmt ) {
    498                 visit_children = false;
    499                 acceptAll( asmStmt->get_input(), *visitor );
    500                 acceptAll( asmStmt->get_output(), *visitor );
    501         }
    502 
    503         void Resolver_old::previsit( IfStmt * ifStmt ) {
    504                 findIntegralExpression( ifStmt->condition, indexer );
    505         }
    506 
    507         void Resolver_old::previsit( WhileDoStmt * whileDoStmt ) {
    508                 findIntegralExpression( whileDoStmt->condition, indexer );
    509         }
    510 
    511         void Resolver_old::previsit( ForStmt * forStmt ) {
    512                 if ( forStmt->condition ) {
    513                         findIntegralExpression( forStmt->condition, indexer );
    514                 } // if
    515 
    516                 if ( forStmt->increment ) {
    517                         findVoidExpression( forStmt->increment, indexer );
    518                 } // if
    519         }
    520 
    521         void Resolver_old::previsit( SwitchStmt * switchStmt ) {
    522                 GuardValue( currentObject );
    523                 findIntegralExpression( switchStmt->condition, indexer );
    524 
    525                 currentObject = CurrentObject( switchStmt->condition->result );
    526         }
    527 
    528         void Resolver_old::previsit( CaseStmt * caseStmt ) {
    529                 if ( caseStmt->condition ) {
    530                         std::list< InitAlternative > initAlts = currentObject.getOptions();
    531                         assertf( initAlts.size() == 1, "SwitchStmt did not correctly resolve an integral expression." );
    532                         // must remove cast from case statement because RangeExpr cannot be cast.
    533                         Expression * newExpr = new CastExpr( caseStmt->condition, initAlts.front().type->clone() );
    534                         findSingleExpression( newExpr, indexer );
    535                         // case condition cannot have a cast in C, so it must be removed, regardless of whether it performs a conversion.
    536                         // Ideally we would perform the conversion internally here.
    537                         if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( newExpr ) ) {
    538                                 newExpr = castExpr->arg;
    539                                 castExpr->arg = nullptr;
    540                                 std::swap( newExpr->env, castExpr->env );
    541                                 delete castExpr;
    542                         }
    543                         caseStmt->condition = newExpr;
    544                 }
    545         }
    546 
    547         void Resolver_old::previsit( BranchStmt * branchStmt ) {
    548                 visit_children = false;
    549                 // must resolve the argument for a computed goto
    550                 if ( branchStmt->get_type() == BranchStmt::Goto ) { // check for computed goto statement
    551                         if ( branchStmt->computedTarget ) {
    552                                 // computed goto argument is void *
    553                                 findSingleExpression( branchStmt->computedTarget, new PointerType( Type::Qualifiers(), new VoidType( Type::Qualifiers() ) ), indexer );
    554                         } // if
    555                 } // if
    556         }
    557 
    558         void Resolver_old::previsit( ReturnStmt * returnStmt ) {
    559                 visit_children = false;
    560                 if ( returnStmt->expr ) {
    561                         findSingleExpression( returnStmt->expr, functionReturn->clone(), indexer );
    562                 } // if
    563         }
    564 
    565         void Resolver_old::previsit( ThrowStmt * throwStmt ) {
    566                 visit_children = false;
    567                 // TODO: Replace *exception type with &exception type.
    568                 if ( throwStmt->get_expr() ) {
    569                         const StructDecl * exception_decl = indexer.lookupStruct( "__cfaehm_base_exception_t" );
    570                         assert( exception_decl );
    571                         Type * exceptType = new PointerType( noQualifiers, new StructInstType( noQualifiers, const_cast<StructDecl *>(exception_decl) ) );
    572                         findSingleExpression( throwStmt->expr, exceptType, indexer );
    573                 }
    574         }
    575 
    576         void Resolver_old::previsit( CatchStmt * catchStmt ) {
    577                 // Until we are very sure this invarent (ifs that move between passes have then)
    578                 // holds, check it. This allows a check for when to decode the mangling.
    579                 if ( IfStmt * ifStmt = dynamic_cast<IfStmt *>( catchStmt->body ) ) {
    580                         assert( ifStmt->then );
    581                 }
    582                 // Encode the catchStmt so the condition can see the declaration.
    583                 if ( catchStmt->cond ) {
    584                         IfStmt * ifStmt = new IfStmt( catchStmt->cond, nullptr, catchStmt->body );
    585                         catchStmt->cond = nullptr;
    586                         catchStmt->body = ifStmt;
    587                 }
    588         }
    589 
    590         void Resolver_old::postvisit( CatchStmt * catchStmt ) {
    591                 // Decode the catchStmt so everything is stored properly.
    592                 IfStmt * ifStmt = dynamic_cast<IfStmt *>( catchStmt->body );
    593                 if ( nullptr != ifStmt && nullptr == ifStmt->then ) {
    594                         assert( ifStmt->condition );
    595                         assert( ifStmt->else_ );
    596                         catchStmt->cond = ifStmt->condition;
    597                         catchStmt->body = ifStmt->else_;
    598                         ifStmt->condition = nullptr;
    599                         ifStmt->else_ = nullptr;
    600                         delete ifStmt;
    601                 }
    602         }
    603 
    60453        template< typename iterator_t >
    60554        inline bool advance_to_mutex( iterator_t & it, const iterator_t & end ) {
     
    61059                return it != end;
    61160        }
    612 
    613         void Resolver_old::previsit( WaitForStmt * stmt ) {
    614                 visit_children = false;
    615 
    616                 // Resolve all clauses first
    617                 for( auto& clause : stmt->clauses ) {
    618 
    619                         TypeEnvironment env;
    620                         AlternativeFinder funcFinder( indexer, env );
    621 
    622                         // Find all alternatives for a function in canonical form
    623                         funcFinder.findWithAdjustment( clause.target.function );
    624 
    625                         if ( funcFinder.get_alternatives().empty() ) {
    626                                 stringstream ss;
    627                                 ss << "Use of undeclared indentifier '";
    628                                 ss << strict_dynamic_cast<NameExpr*>( clause.target.function )->name;
    629                                 ss << "' in call to waitfor";
    630                                 SemanticError( stmt->location, ss.str() );
    631                         }
    632 
    633                         if(clause.target.arguments.empty()) {
    634                                 SemanticError( stmt->location, "Waitfor clause must have at least one mutex parameter");
    635                         }
    636 
    637                         // Find all alternatives for all arguments in canonical form
    638                         std::vector< AlternativeFinder > argAlternatives;
    639                         funcFinder.findSubExprs( clause.target.arguments.begin(), clause.target.arguments.end(), back_inserter( argAlternatives ) );
    640 
    641                         // List all combinations of arguments
    642                         std::vector< AltList > possibilities;
    643                         combos( argAlternatives.begin(), argAlternatives.end(), back_inserter( possibilities ) );
    644 
    645                         AltList                func_candidates;
    646                         std::vector< AltList > args_candidates;
    647 
    648                         // For every possible function :
    649                         //      try matching the arguments to the parameters
    650                         //      not the other way around because we have more arguments than parameters
    651                         SemanticErrorException errors;
    652                         for ( Alternative & func : funcFinder.get_alternatives() ) {
    653                                 try {
    654                                         PointerType * pointer = dynamic_cast< PointerType* >( func.expr->get_result()->stripReferences() );
    655                                         if( !pointer ) {
    656                                                 SemanticError( func.expr->get_result(), "candidate not viable: not a pointer type\n" );
    657                                         }
    658 
    659                                         FunctionType * function = dynamic_cast< FunctionType* >( pointer->get_base() );
    660                                         if( !function ) {
    661                                                 SemanticError( pointer->get_base(), "candidate not viable: not a function type\n" );
    662                                         }
    663 
    664 
    665                                         {
    666                                                 auto param     = function->parameters.begin();
    667                                                 auto param_end = function->parameters.end();
    668 
    669                                                 if( !advance_to_mutex( param, param_end ) ) {
    670                                                         SemanticError(function, "candidate function not viable: no mutex parameters\n");
    671                                                 }
    672                                         }
    673 
    674                                         Alternative newFunc( func );
    675                                         // Strip reference from function
    676                                         referenceToRvalueConversion( newFunc.expr, newFunc.cost );
    677 
    678                                         // For all the set of arguments we have try to match it with the parameter of the current function alternative
    679                                         for ( auto & argsList : possibilities ) {
    680 
    681                                                 try {
    682                                                         // Declare data structures need for resolution
    683                                                         OpenVarSet openVars;
    684                                                         AssertionSet resultNeed, resultHave;
    685                                                         TypeEnvironment resultEnv( func.env );
    686                                                         makeUnifiableVars( function, openVars, resultNeed );
    687                                                         // add all type variables as open variables now so that those not used in the parameter
    688                                                         // list are still considered open.
    689                                                         resultEnv.add( function->forall );
    690 
    691                                                         // Load type variables from arguemnts into one shared space
    692                                                         simpleCombineEnvironments( argsList.begin(), argsList.end(), resultEnv );
    693 
    694                                                         // Make sure we don't widen any existing bindings
    695                                                         resultEnv.forbidWidening();
    696 
    697                                                         // Find any unbound type variables
    698                                                         resultEnv.extractOpenVars( openVars );
    699 
    700                                                         auto param     = function->parameters.begin();
    701                                                         auto param_end = function->parameters.end();
    702 
    703                                                         int n_mutex_param = 0;
    704 
    705                                                         // For every arguments of its set, check if it matches one of the parameter
    706                                                         // The order is important
    707                                                         for( auto & arg : argsList ) {
    708 
    709                                                                 // Ignore non-mutex arguments
    710                                                                 if( !advance_to_mutex( param, param_end ) ) {
    711                                                                         // We ran out of parameters but still have arguments
    712                                                                         // this function doesn't match
    713                                                                         SemanticError( function, toString("candidate function not viable: too many mutex arguments, expected ", n_mutex_param, "\n" ));
    714                                                                 }
    715 
    716                                                                 n_mutex_param++;
    717 
    718                                                                 // Check if the argument matches the parameter type in the current scope
    719                                                                 if( ! unify( arg.expr->get_result(), (*param)->get_type(), resultEnv, resultNeed, resultHave, openVars, this->indexer ) ) {
    720                                                                         // Type doesn't match
    721                                                                         stringstream ss;
    722                                                                         ss << "candidate function not viable: no known convertion from '";
    723                                                                         (*param)->get_type()->print( ss );
    724                                                                         ss << "' to '";
    725                                                                         arg.expr->get_result()->print( ss );
    726                                                                         ss << "' with env '";
    727                                                                         resultEnv.print(ss);
    728                                                                         ss << "'\n";
    729                                                                         SemanticError( function, ss.str() );
    730                                                                 }
    731 
    732                                                                 param++;
    733                                                         }
    734 
    735                                                         // All arguments match !
    736 
    737                                                         // Check if parameters are missing
    738                                                         if( advance_to_mutex( param, param_end ) ) {
    739                                                                 do {
    740                                                                         n_mutex_param++;
    741                                                                         param++;
    742                                                                 } while( advance_to_mutex( param, param_end ) );
    743 
    744                                                                 // We ran out of arguments but still have parameters left
    745                                                                 // this function doesn't match
    746                                                                 SemanticError( function, toString("candidate function not viable: too few mutex arguments, expected ", n_mutex_param, "\n" ));
    747                                                         }
    748 
    749                                                         // All parameters match !
    750 
    751                                                         // Finish the expressions to tie in the proper environments
    752                                                         finishExpr( newFunc.expr, resultEnv );
    753                                                         for( Alternative & alt : argsList ) {
    754                                                                 finishExpr( alt.expr, resultEnv );
    755                                                         }
    756 
    757                                                         // This is a match store it and save it for later
    758                                                         func_candidates.push_back( newFunc );
    759                                                         args_candidates.push_back( argsList );
    760 
    761                                                 }
    762                                                 catch( SemanticErrorException & e ) {
    763                                                         errors.append( e );
    764                                                 }
    765                                         }
    766                                 }
    767                                 catch( SemanticErrorException & e ) {
    768                                         errors.append( e );
    769                                 }
    770                         }
    771 
    772                         // Make sure we got the right number of arguments
    773                         if( func_candidates.empty() )    { SemanticErrorException top( stmt->location, "No alternatives for function in call to waitfor"  ); top.append( errors ); throw top; }
    774                         if( args_candidates.empty() )    { SemanticErrorException top( stmt->location, "No alternatives for arguments in call to waitfor" ); top.append( errors ); throw top; }
    775                         if( func_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous function in call to waitfor"            ); top.append( errors ); throw top; }
    776                         if( args_candidates.size() > 1 ) { SemanticErrorException top( stmt->location, "Ambiguous arguments in call to waitfor"           ); top.append( errors ); throw top; }
    777                         // TODO: need to use findDeletedExpr to ensure no deleted identifiers are used.
    778 
    779                         // Swap the results from the alternative with the unresolved values.
    780                         // Alternatives will handle deletion on destruction
    781                         std::swap( clause.target.function, func_candidates.front().expr );
    782                         for( auto arg_pair : group_iterate( clause.target.arguments, args_candidates.front() ) ) {
    783                                 std::swap ( std::get<0>( arg_pair), std::get<1>( arg_pair).expr );
    784                         }
    785 
    786                         // Resolve the conditions as if it were an IfStmt
    787                         // Resolve the statments normally
    788                         findSingleExpression( clause.condition, this->indexer );
    789                         clause.statement->accept( *visitor );
    790                 }
    791 
    792 
    793                 if( stmt->timeout.statement ) {
    794                         // Resolve the timeout as an size_t for now
    795                         // Resolve the conditions as if it were an IfStmt
    796                         // Resolve the statments normally
    797                         findSingleExpression( stmt->timeout.time, new BasicType( noQualifiers, BasicType::LongLongUnsignedInt ), this->indexer );
    798                         findSingleExpression( stmt->timeout.condition, this->indexer );
    799                         stmt->timeout.statement->accept( *visitor );
    800                 }
    801 
    802                 if( stmt->orelse.statement ) {
    803                         // Resolve the conditions as if it were an IfStmt
    804                         // Resolve the statments normally
    805                         findSingleExpression( stmt->orelse.condition, this->indexer );
    806                         stmt->orelse.statement->accept( *visitor );
    807                 }
    808         }
    809 
    810         bool isCharType( Type * t ) {
    811                 if ( BasicType * bt = dynamic_cast< BasicType * >( t ) ) {
    812                         return bt->get_kind() == BasicType::Char || bt->get_kind() == BasicType::SignedChar ||
    813                                 bt->get_kind() == BasicType::UnsignedChar;
    814                 }
    815                 return false;
    816         }
    817 
    818         void Resolver_old::previsit( SingleInit * singleInit ) {
    819                 visit_children = false;
    820                 // resolve initialization using the possibilities as determined by the currentObject cursor
    821                 Expression * newExpr = new UntypedInitExpr( singleInit->value, currentObject.getOptions() );
    822                 findSingleExpression( newExpr, indexer );
    823                 InitExpr * initExpr = strict_dynamic_cast< InitExpr * >( newExpr );
    824 
    825                 // move cursor to the object that is actually initialized
    826                 currentObject.setNext( initExpr->get_designation() );
    827 
    828                 // discard InitExpr wrapper and retain relevant pieces
    829                 newExpr = initExpr->expr;
    830                 initExpr->expr = nullptr;
    831                 std::swap( initExpr->env, newExpr->env );
    832                 // InitExpr may have inferParams in the case where the expression specializes a function
    833                 // pointer, and newExpr may already have inferParams of its own, so a simple swap is not
    834                 // sufficient.
    835                 newExpr->spliceInferParams( initExpr );
    836                 delete initExpr;
    837 
    838                 // get the actual object's type (may not exactly match what comes back from the resolver
    839                 // due to conversions)
    840                 Type * initContext = currentObject.getCurrentType();
    841 
    842                 removeExtraneousCast( newExpr, indexer );
    843 
    844                 // check if actual object's type is char[]
    845                 if ( ArrayType * at = dynamic_cast< ArrayType * >( initContext ) ) {
    846                         if ( isCharType( at->get_base() ) ) {
    847                                 // check if the resolved type is char *
    848                                 if ( PointerType * pt = dynamic_cast< PointerType *>( newExpr->get_result() ) ) {
    849                                         if ( isCharType( pt->get_base() ) ) {
    850                                                 if ( CastExpr * ce = dynamic_cast< CastExpr * >( newExpr ) ) {
    851                                                         // strip cast if we're initializing a char[] with a char *,
    852                                                         // e.g.  char x[] = "hello";
    853                                                         newExpr = ce->get_arg();
    854                                                         ce->set_arg( nullptr );
    855                                                         std::swap( ce->env, newExpr->env );
    856                                                         delete ce;
    857                                                 }
    858                                         }
    859                                 }
    860                         }
    861                 }
    862 
    863                 // set initializer expr to resolved express
    864                 singleInit->value = newExpr;
    865 
    866                 // move cursor to next object in preparation for next initializer
    867                 currentObject.increment();
    868         }
    869 
    870         void Resolver_old::previsit( ListInit * listInit ) {
    871                 visit_children = false;
    872                 // move cursor into brace-enclosed initializer-list
    873                 currentObject.enterListInit();
    874                 // xxx - fix this so that the list isn't copied, iterator should be used to change current
    875                 // element
    876                 std::list<Designation *> newDesignations;
    877                 for ( auto p : group_iterate(listInit->get_designations(), listInit->get_initializers()) ) {
    878                         // iterate designations and initializers in pairs, moving the cursor to the current
    879                         // designated object and resolving the initializer against that object.
    880                         Designation * des = std::get<0>(p);
    881                         Initializer * init = std::get<1>(p);
    882                         newDesignations.push_back( currentObject.findNext( des ) );
    883                         init->accept( *visitor );
    884                 }
    885                 // set the set of 'resolved' designations and leave the brace-enclosed initializer-list
    886                 listInit->get_designations() = newDesignations; // xxx - memory management
    887                 currentObject.exitListInit();
    888 
    889                 // xxx - this part has not be folded into CurrentObject yet
    890                 // } else if ( TypeInstType * tt = dynamic_cast< TypeInstType * >( initContext ) ) {
    891                 //      Type * base = tt->get_baseType()->get_base();
    892                 //      if ( base ) {
    893                 //              // know the implementation type, so try using that as the initContext
    894                 //              ObjectDecl tmpObj( "", Type::StorageClasses(), LinkageSpec::Cforall, nullptr, base->clone(), nullptr );
    895                 //              currentObject = &tmpObj;
    896                 //              visit( listInit );
    897                 //      } else {
    898                 //              // missing implementation type -- might be an unknown type variable, so try proceeding with the current init context
    899                 //              Parent::visit( listInit );
    900                 //      }
    901                 // } else {
    902         }
    903 
    904         // ConstructorInit - fall back on C-style initializer
    905         void Resolver_old::fallbackInit( ConstructorInit * ctorInit ) {
    906                 // could not find valid constructor, or found an intrinsic constructor
    907                 // fall back on C-style initializer
    908                 delete ctorInit->get_ctor();
    909                 ctorInit->set_ctor( nullptr );
    910                 delete ctorInit->get_dtor();
    911                 ctorInit->set_dtor( nullptr );
    912                 maybeAccept( ctorInit->get_init(), *visitor );
    913         }
    914 
    915         // needs to be callable from outside the resolver, so this is a standalone function
    916         void resolveCtorInit( ConstructorInit * ctorInit, const SymTab::Indexer & indexer ) {
    917                 assert( ctorInit );
    918                 PassVisitor<Resolver_old> resolver( indexer );
    919                 ctorInit->accept( resolver );
    920         }
    921 
    922         void resolveStmtExpr( StmtExpr * stmtExpr, const SymTab::Indexer & indexer ) {
    923                 assert( stmtExpr );
    924                 PassVisitor<Resolver_old> resolver( indexer );
    925                 stmtExpr->accept( resolver );
    926                 stmtExpr->computeResult();
    927                 // xxx - aggregate the environments from all statements? Possibly in AlternativeFinder instead?
    928         }
    929 
    930         void Resolver_old::previsit( ConstructorInit * ctorInit ) {
    931                 visit_children = false;
    932                 // xxx - fallback init has been removed => remove fallbackInit function and remove complexity from FixInit and remove C-init from ConstructorInit
    933                 maybeAccept( ctorInit->ctor, *visitor );
    934                 maybeAccept( ctorInit->dtor, *visitor );
    935 
    936                 // found a constructor - can get rid of C-style initializer
    937                 delete ctorInit->init;
    938                 ctorInit->init = nullptr;
    939 
    940                 // intrinsic single parameter constructors and destructors do nothing. Since this was
    941                 // implicitly generated, there's no way for it to have side effects, so get rid of it
    942                 // to clean up generated code.
    943                 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->ctor ) ) {
    944                         delete ctorInit->ctor;
    945                         ctorInit->ctor = nullptr;
    946                 }
    947 
    948                 if ( InitTweak::isIntrinsicSingleArgCallStmt( ctorInit->dtor ) ) {
    949                         delete ctorInit->dtor;
    950                         ctorInit->dtor = nullptr;
    951                 }
    952 
    953                 // xxx - todo -- what about arrays?
    954                 // if ( dtor == nullptr && InitTweak::isIntrinsicCallStmt( ctorInit->get_ctor() ) ) {
    955                 //      // can reduce the constructor down to a SingleInit using the
    956                 //      // second argument from the ctor call, since
    957                 //      delete ctorInit->get_ctor();
    958                 //      ctorInit->set_ctor( nullptr );
    959 
    960                 //      Expression * arg =
    961                 //      ctorInit->set_init( new SingleInit( arg ) );
    962                 // }
    963         }
    964 
    965         ///////////////////////////////////////////////////////////////////////////
    966         //
    967         // *** NEW RESOLVER ***
    968         //
    969         ///////////////////////////////////////////////////////////////////////////
    97061
    97162        namespace {
  • src/ResolvExpr/SatisfyAssertions.cpp

    r790d835 rc6b4432  
    4646#include "SymTab/Mangler.h"
    4747
    48 
    49 
    5048namespace ResolvExpr {
    5149
  • src/ResolvExpr/SpecCost.cc

    r790d835 rc6b4432  
    2121#include "AST/Pass.hpp"
    2222#include "AST/Type.hpp"
    23 #include "Common/PassVisitor.h"
    24 #include "SynTree/Declaration.h"
    25 #include "SynTree/Expression.h"
    26 #include "SynTree/Type.h"
    2723
    2824namespace ResolvExpr {
    29 
    30         /// Counts specializations in a type
    31         class CountSpecs : public WithShortCircuiting, public WithVisitorRef<CountSpecs> {
    32                 int count = -1;  ///< specialization count (-1 for none)
    33 
    34         public:
    35                 int get_count() const { return count >= 0 ? count : 0; }
    36 
    37                 // mark specialization of base type
    38                 void postvisit(PointerType*) { if ( count >= 0 ) ++count; }
    39 
    40                 // mark specialization of base type
    41                 void postvisit(ArrayType*) { if ( count >= 0 ) ++count; }
    42 
    43                 // mark specialization of base type
    44                 void postvisit(ReferenceType*) { if ( count >= 0 ) ++count; }
    45 
    46                 void postvisit(StructInstType*) { if ( count >= 0 ) ++count; }
    47                 void postvisit(UnionInstType*) { if ( count >= 0 ) ++count; }
    48 
    49         private:
    50                 // takes minimum non-negative count over parameter/return list
    51                 void takeminover( int& mincount, std::list<DeclarationWithType*>& dwts ) {
    52                         for ( DeclarationWithType* dwt : dwts ) {
    53                                 count = -1;
    54                                 maybeAccept( dwt->get_type(), *visitor );
    55                                 if ( count != -1 && count < mincount ) mincount = count;
    56                         }
    57                 }
    58 
    59         public:
    60                 // take minimal specialization value over ->returnVals and ->parameters
    61                 void previsit(FunctionType* fty) {
    62                         int mincount = std::numeric_limits<int>::max();
    63                         takeminover( mincount, fty->parameters );
    64                         takeminover( mincount, fty->returnVals );
    65                         // add another level to mincount if set
    66                         count = mincount < std::numeric_limits<int>::max() ? mincount + 1 : -1;
    67                         // already visited children
    68                         visit_children = false;
    69                 }
    70 
    71         private:
    72                 // returns minimum non-negative count + 1 over type parameters (-1 if none such)
    73                 int minover( std::list<Expression*>& parms ) {
    74                         int mincount = std::numeric_limits<int>::max();
    75                         for ( Expression* parm : parms ) {
    76                                 count = -1;
    77                                 maybeAccept( parm->result, *visitor );
    78                                 if ( count != -1 && count < mincount ) mincount = count;
    79                         }
    80                         return mincount < std::numeric_limits<int>::max() ? mincount + 1 : -1;
    81                 }
    82 
    83         public:
    84                 // look for polymorphic parameters
    85                 void previsit(StructInstType* sty) {
    86                         count = minover( sty->parameters );
    87                 }
    88 
    89                 // look for polymorphic parameters
    90                 void previsit(UnionInstType* uty) {
    91                         count = minover( uty->parameters );
    92                 }
    93 
    94                 // note polymorphic type (which may be specialized)
    95                 // xxx - maybe account for open/closed type variables
    96                 void postvisit(TypeInstType*) { count = 0; }
    97 
    98                 // take minimal specialization over elements
    99                 // xxx - maybe don't increment, tuple flattening doesn't necessarily specialize
    100                 void previsit(TupleType* tty) {
    101                         int mincount = std::numeric_limits<int>::max();
    102                         for ( Type* ty : tty->types ) {
    103                                 count = -1;
    104                                 maybeAccept( ty, *visitor );
    105                                 if ( count != -1 && count < mincount ) mincount = count;
    106                         }
    107                         count = mincount < std::numeric_limits<int>::max() ? mincount + 1 : -1;
    108                         visit_children = false;
    109                 }
    110         };
    111 
    112         /// Returns the (negated) specialization cost for a given type
    113         int specCost( Type* ty ) {
    114                 PassVisitor<CountSpecs> counter;
    115                 maybeAccept( ty, *counter.pass.visitor );
    116                 return counter.pass.get_count();
    117         }
    11825
    11926namespace {
  • src/ResolvExpr/Unify.cc

    r790d835 rc6b4432  
    3333#include "AST/TypeEnvironment.hpp"
    3434#include "Common/Eval.h"            // for eval
    35 #include "Common/PassVisitor.h"     // for PassVisitor
    3635#include "CommonType.hpp"           // for commonType
    3736#include "FindOpenVars.h"           // for findOpenVars
    3837#include "SpecCost.hpp"             // for SpecCost
    39 #include "SynTree/LinkageSpec.h"    // for C
    40 #include "SynTree/Constant.h"       // for Constant
    41 #include "SynTree/Declaration.h"    // for TypeDecl, TypeDecl::Data, Declarati...
    42 #include "SynTree/Expression.h"     // for TypeExpr, Expression, ConstantExpr
    43 #include "SynTree/Mutator.h"        // for Mutator
    44 #include "SynTree/Type.h"           // for Type, TypeInstType, FunctionType
    45 #include "SynTree/Visitor.h"        // for Visitor
    4638#include "Tuples/Tuples.h"          // for isTtype
    47 #include "TypeEnvironment.h"        // for EqvClass, AssertionSet, OpenVarSet
    4839#include "typeops.h"                // for flatten, occurs
    4940
     
    5243}
    5344
    54 namespace SymTab {
    55         class Indexer;
    56 }  // namespace SymTab
    57 
    5845// #define DEBUG
    5946
    6047namespace ResolvExpr {
    61 
    62 // Template Helpers:
    63 template< typename Iterator1, typename Iterator2 >
    64 bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, std::list< Type* > &commonTypes ) {
    65         for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
    66                 Type *commonType = 0;
    67                 if ( ! unify( *list1Begin, *list2Begin, env, needAssertions, haveAssertions, openVars, indexer, commonType ) ) {
    68                         return false;
    69                 } // if
    70                 commonTypes.push_back( commonType );
    71         } // for
    72         return ( list1Begin == list1End && list2Begin == list2End );
    73 }
    74 
    75 template< typename Iterator1, typename Iterator2 >
    76 bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    77         std::list< Type* > commonTypes;
    78         if ( unifyList( list1Begin, list1End, list2Begin, list2End, env, needAssertions, haveAssertions,  openVars, indexer, commonTypes ) ) {
    79                 deleteAll( commonTypes );
    80                 return true;
    81         } else {
    82                 return false;
    83         } // if
    84 }
    85 
    86         struct Unify_old : public WithShortCircuiting {
    87                 Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
    88 
    89                 bool get_result() const { return result; }
    90 
    91                 void previsit( BaseSyntaxNode * ) { visit_children = false; }
    92 
    93                 void postvisit( VoidType * voidType );
    94                 void postvisit( BasicType * basicType );
    95                 void postvisit( PointerType * pointerType );
    96                 void postvisit( ArrayType * arrayType );
    97                 void postvisit( ReferenceType * refType );
    98                 void postvisit( FunctionType * functionType );
    99                 void postvisit( StructInstType * aggregateUseType );
    100                 void postvisit( UnionInstType * aggregateUseType );
    101                 void postvisit( EnumInstType * aggregateUseType );
    102                 void postvisit( TraitInstType * aggregateUseType );
    103                 void postvisit( TypeInstType * aggregateUseType );
    104                 void postvisit( TupleType * tupleType );
    105                 void postvisit( VarArgsType * varArgsType );
    106                 void postvisit( ZeroType * zeroType );
    107                 void postvisit( OneType * oneType );
    108 
    109           private:
    110                 template< typename RefType > void handleRefType( RefType *inst, Type *other );
    111                 template< typename RefType > void handleGenericRefType( RefType *inst, Type *other );
    112 
    113                 bool result;
    114                 Type *type2;                            // inherited
    115                 TypeEnvironment &env;
    116                 AssertionSet &needAssertions;
    117                 AssertionSet &haveAssertions;
    118                 const OpenVarSet &openVars;
    119                 WidenMode widen;
    120                 const SymTab::Indexer &indexer;
    121         };
    122 
    123         /// Attempts an inexact unification of type1 and type2.
    124         /// Returns false if no such unification; if the types can be unified, sets common (unless they unify exactly and have identical type qualifiers)
    125         bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common );
    126         bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer );
    127 
    128         bool unifyExact(
    129                 const ast::Type * type1, const ast::Type * type2, ast::TypeEnvironment & env,
    130                 ast::AssertionSet & need, ast::AssertionSet & have, const ast::OpenVarSet & open,
    131                 WidenMode widen );
    132 
    133         bool typesCompatible( const Type * first, const Type * second, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
    134                 TypeEnvironment newEnv;
    135                 OpenVarSet openVars, closedVars; // added closedVars
    136                 AssertionSet needAssertions, haveAssertions;
    137                 Type * newFirst = first->clone(), * newSecond = second->clone();
    138                 env.apply( newFirst );
    139                 env.apply( newSecond );
    140 
    141                 // do we need to do this? Seems like we do, types should be able to be compatible if they
    142                 // have free variables that can unify
    143                 findOpenVars( newFirst, openVars, closedVars, needAssertions, haveAssertions, false );
    144                 findOpenVars( newSecond, openVars, closedVars, needAssertions, haveAssertions, true );
    145 
    146                 bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    147                 delete newFirst;
    148                 delete newSecond;
    149                 return result;
    150         }
    15148
    15249        bool typesCompatible(
     
    16562
    16663                return unifyExact(newFirst, newSecond, newEnv, need, have, open, noWiden() );
    167         }
    168 
    169         bool typesCompatibleIgnoreQualifiers( const Type * first, const Type * second, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    170                 TypeEnvironment newEnv;
    171                 OpenVarSet openVars;
    172                 AssertionSet needAssertions, haveAssertions;
    173                 Type *newFirst = first->clone(), *newSecond = second->clone();
    174                 env.apply( newFirst );
    175                 env.apply( newSecond );
    176                 newFirst->get_qualifiers() = Type::Qualifiers();
    177                 newSecond->get_qualifiers() = Type::Qualifiers();
    178 
    179                 bool result = unifyExact( newFirst, newSecond, newEnv, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    180                 delete newFirst;
    181                 delete newSecond;
    182                 return result;
    18364        }
    18465
     
    21899                        subSecond,
    219100                        newEnv, need, have, open, noWiden() );
    220         }
    221 
    222         bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    223                 OpenVarSet closedVars;
    224                 findOpenVars( type1, openVars, closedVars, needAssertions, haveAssertions, false );
    225                 findOpenVars( type2, openVars, closedVars, needAssertions, haveAssertions, true );
    226                 Type *commonType = 0;
    227                 if ( unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType ) ) {
    228                         if ( commonType ) {
    229                                 delete commonType;
    230                         } // if
    231                         return true;
    232                 } else {
    233                         return false;
    234                 } // if
    235         }
    236 
    237         bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType ) {
    238                 OpenVarSet closedVars;
    239                 findOpenVars( type1, openVars, closedVars, needAssertions, haveAssertions, false );
    240                 findOpenVars( type2, openVars, closedVars, needAssertions, haveAssertions, true );
    241                 return unifyInexact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( true, true ), indexer, commonType );
    242         }
    243 
    244         bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer ) {
    245 #ifdef DEBUG
    246                 TypeEnvironment debugEnv( env );
    247 #endif
    248                 if ( type1->get_qualifiers() != type2->get_qualifiers() ) {
    249                         return false;
    250                 }
    251 
    252                 bool result;
    253                 TypeInstType *var1 = dynamic_cast< TypeInstType* >( type1 );
    254                 TypeInstType *var2 = dynamic_cast< TypeInstType* >( type2 );
    255                 OpenVarSet::const_iterator entry1, entry2;
    256                 if ( var1 ) {
    257                         entry1 = openVars.find( var1->get_name() );
    258                 } // if
    259                 if ( var2 ) {
    260                         entry2 = openVars.find( var2->get_name() );
    261                 } // if
    262                 bool isopen1 = var1 && ( entry1 != openVars.end() );
    263                 bool isopen2 = var2 && ( entry2 != openVars.end() );
    264 
    265                 if ( isopen1 && isopen2 ) {
    266                         if ( entry1->second.kind != entry2->second.kind ) {
    267                                 result = false;
    268                         } else {
    269                                 result = env.bindVarToVar(
    270                                         var1, var2, TypeDecl::Data{ entry1->second, entry2->second }, needAssertions,
    271                                         haveAssertions, openVars, widen, indexer );
    272                         }
    273                 } else if ( isopen1 ) {
    274                         result = env.bindVar( var1, type2, entry1->second, needAssertions, haveAssertions, openVars, widen, indexer );
    275                 } else if ( isopen2 ) { // TODO: swap widen values in call, since type positions are flipped?
    276                         result = env.bindVar( var2, type1, entry2->second, needAssertions, haveAssertions, openVars, widen, indexer );
    277                 } else {
    278                         PassVisitor<Unify_old> comparator( type2, env, needAssertions, haveAssertions, openVars, widen, indexer );
    279                         type1->accept( comparator );
    280                         result = comparator.pass.get_result();
    281                 } // if
    282 #ifdef DEBUG
    283                 std::cerr << "============ unifyExact" << std::endl;
    284                 std::cerr << "type1 is ";
    285                 type1->print( std::cerr );
    286                 std::cerr << std::endl << "type2 is ";
    287                 type2->print( std::cerr );
    288                 std::cerr << std::endl << "openVars are ";
    289                 printOpenVarSet( openVars, std::cerr, 8 );
    290                 std::cerr << std::endl << "input env is " << std::endl;
    291                 debugEnv.print( std::cerr, 8 );
    292                 std::cerr << std::endl << "result env is " << std::endl;
    293                 env.print( std::cerr, 8 );
    294                 std::cerr << "result is " << result << std::endl;
    295 #endif
    296                 return result;
    297         }
    298 
    299         bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    300                 return unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    301         }
    302 
    303         bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common ) {
    304                 Type::Qualifiers tq1 = type1->get_qualifiers(), tq2 = type2->get_qualifiers();
    305                 type1->get_qualifiers() = Type::Qualifiers();
    306                 type2->get_qualifiers() = Type::Qualifiers();
    307                 bool result;
    308 #ifdef DEBUG
    309                 std::cerr << "unifyInexact type 1 is ";
    310                 type1->print( std::cerr );
    311                 std::cerr << " type 2 is ";
    312                 type2->print( std::cerr );
    313                 std::cerr << std::endl;
    314 #endif
    315                 if ( ! unifyExact( type1, type2, env, needAssertions, haveAssertions, openVars, widen, indexer ) ) {
    316 #ifdef DEBUG
    317                         std::cerr << "unifyInexact: no exact unification found" << std::endl;
    318 #endif
    319                         if ( ( common = commonType( type1, type2, widen.first, widen.second, indexer, env, openVars ) ) ) {
    320                                 common->tq = tq1.unify( tq2 );
    321 #ifdef DEBUG
    322                                 std::cerr << "unifyInexact: common type is ";
    323                                 common->print( std::cerr );
    324                                 std::cerr << std::endl;
    325 #endif
    326                                 result = true;
    327                         } else {
    328 #ifdef DEBUG
    329                                 std::cerr << "unifyInexact: no common type found" << std::endl;
    330 #endif
    331                                 result = false;
    332                         } // if
    333                 } else {
    334                         if ( tq1 != tq2 ) {
    335                                 if ( ( tq1 > tq2 || widen.first ) && ( tq2 > tq1 || widen.second ) ) {
    336                                         common = type1->clone();
    337                                         common->tq = tq1.unify( tq2 );
    338                                         result = true;
    339                                 } else {
    340                                         result = false;
    341                                 } // if
    342                         } else {
    343                                 common = type1->clone();
    344                                 common->tq = tq1.unify( tq2 );
    345                                 result = true;
    346                         } // if
    347                 } // if
    348                 type1->get_qualifiers() = tq1;
    349                 type2->get_qualifiers() = tq2;
    350                 return result;
    351         }
    352 
    353         Unify_old::Unify_old( Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer )
    354                 : result( false ), type2( type2 ), env( env ), needAssertions( needAssertions ), haveAssertions( haveAssertions ), openVars( openVars ), widen( widen ), indexer( indexer ) {
    355         }
    356 
    357         void Unify_old::postvisit( __attribute__((unused)) VoidType *voidType) {
    358                 result = dynamic_cast< VoidType* >( type2 );
    359         }
    360 
    361         void Unify_old::postvisit(BasicType *basicType) {
    362                 if ( BasicType *otherBasic = dynamic_cast< BasicType* >( type2 ) ) {
    363                         result = basicType->get_kind() == otherBasic->get_kind();
    364                 } // if
    365         }
    366 
    367         void markAssertionSet( AssertionSet &assertions, DeclarationWithType *assert ) {
    368                 AssertionSet::iterator i = assertions.find( assert );
    369                 if ( i != assertions.end() ) {
    370                         i->second.isUsed = true;
    371                 } // if
    372         }
    373 
    374         void markAssertions( AssertionSet &assertion1, AssertionSet &assertion2, Type *type ) {
    375                 for ( std::list< TypeDecl* >::const_iterator tyvar = type->get_forall().begin(); tyvar != type->get_forall().end(); ++tyvar ) {
    376                         for ( std::list< DeclarationWithType* >::const_iterator assert = (*tyvar)->get_assertions().begin(); assert != (*tyvar)->get_assertions().end(); ++assert ) {
    377                                 markAssertionSet( assertion1, *assert );
    378                                 markAssertionSet( assertion2, *assert );
    379                         } // for
    380                 } // for
    381         }
    382 
    383         void Unify_old::postvisit(PointerType *pointerType) {
    384                 if ( PointerType *otherPointer = dynamic_cast< PointerType* >( type2 ) ) {
    385                         result = unifyExact( pointerType->get_base(), otherPointer->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    386                         markAssertions( haveAssertions, needAssertions, pointerType );
    387                         markAssertions( haveAssertions, needAssertions, otherPointer );
    388                 } // if
    389         }
    390 
    391         void Unify_old::postvisit(ReferenceType *refType) {
    392                 if ( ReferenceType *otherRef = dynamic_cast< ReferenceType* >( type2 ) ) {
    393                         result = unifyExact( refType->get_base(), otherRef->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    394                         markAssertions( haveAssertions, needAssertions, refType );
    395                         markAssertions( haveAssertions, needAssertions, otherRef );
    396                 } // if
    397         }
    398 
    399         void Unify_old::postvisit(ArrayType *arrayType) {
    400                 ArrayType *otherArray = dynamic_cast< ArrayType* >( type2 );
    401                 // to unify, array types must both be VLA or both not VLA
    402                 // and must both have a dimension expression or not have a dimension
    403                 if ( otherArray && arrayType->get_isVarLen() == otherArray->get_isVarLen() ) {
    404 
    405                         if ( ! arrayType->get_isVarLen() && ! otherArray->get_isVarLen() &&
    406                                 arrayType->get_dimension() != 0 && otherArray->get_dimension() != 0 ) {
    407                                 ConstantExpr * ce1 = dynamic_cast< ConstantExpr * >( arrayType->get_dimension() );
    408                                 ConstantExpr * ce2 = dynamic_cast< ConstantExpr * >( otherArray->get_dimension() );
    409                                 // see C11 Reference Manual 6.7.6.2.6
    410                                 // two array types with size specifiers that are integer constant expressions are
    411                                 // compatible if both size specifiers have the same constant value
    412                                 if ( ce1 && ce2 ) {
    413                                         Constant * c1 = ce1->get_constant();
    414                                         Constant * c2 = ce2->get_constant();
    415 
    416                                         if ( c1->get_value() != c2->get_value() ) {
    417                                                 // does not unify if the dimension is different
    418                                                 return;
    419                                         }
    420                                 }
    421                         }
    422 
    423                         result = unifyExact( arrayType->get_base(), otherArray->get_base(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    424                 } // if
    425         }
    426 
    427         template< typename Iterator, typename Func >
    428         std::unique_ptr<Type> combineTypes( Iterator begin, Iterator end, Func & toType ) {
    429                 std::list< Type * > types;
    430                 for ( ; begin != end; ++begin ) {
    431                         // it's guaranteed that a ttype variable will be bound to a flat tuple, so ensure that this results in a flat tuple
    432                         flatten( toType( *begin ), back_inserter( types ) );
    433                 }
    434                 return std::unique_ptr<Type>( new TupleType( Type::Qualifiers(), types ) );
    435         }
    436 
    437         template< typename Iterator1, typename Iterator2 >
    438         bool unifyTypeList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    439                 auto get_type = [](DeclarationWithType * dwt){ return dwt->get_type(); };
    440                 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
    441                         Type * t1 = (*list1Begin)->get_type();
    442                         Type * t2 = (*list2Begin)->get_type();
    443                         bool isTtype1 = Tuples::isTtype( t1 );
    444                         bool isTtype2 = Tuples::isTtype( t2 );
    445                         // xxx - assumes ttype must be last parameter
    446                         // xxx - there may be a nice way to refactor this, but be careful because the argument positioning might matter in some cases.
    447                         if ( isTtype1 && ! isTtype2 ) {
    448                                 // combine all of the things in list2, then unify
    449                                 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    450                         } else if ( isTtype2 && ! isTtype1 ) {
    451                                 // combine all of the things in list1, then unify
    452                                 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    453                         } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) {
    454                                 return false;
    455                         } // if
    456                 } // for
    457                 // may get to the end of one argument list before the end of the other. This is only okay when the other is a ttype
    458                 if ( list1Begin != list1End ) {
    459                         // try unifying empty tuple type with ttype
    460                         Type * t1 = (*list1Begin)->get_type();
    461                         if ( Tuples::isTtype( t1 ) ) {
    462                                 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    463                         } else return false;
    464                 } else if ( list2Begin != list2End ) {
    465                         // try unifying empty tuple type with ttype
    466                         Type * t2 = (*list2Begin)->get_type();
    467                         if ( Tuples::isTtype( t2 ) ) {
    468                                 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    469                         } else return false;
    470                 } else {
    471                         return true;
    472                 } // if
    473         }
    474 
    475         /// Finds ttypes and replaces them with their expansion, if known.
    476         /// This needs to be done so that satisfying ttype assertions is easier.
    477         /// If this isn't done then argument lists can have wildly different
    478         /// size and structure, when they should be compatible.
    479         struct TtypeExpander_old : public WithShortCircuiting {
    480                 TypeEnvironment & tenv;
    481                 TtypeExpander_old( TypeEnvironment & tenv ) : tenv( tenv ) {}
    482                 void premutate( TypeInstType * ) { visit_children = false; }
    483                 Type * postmutate( TypeInstType * typeInst ) {
    484                         if ( const EqvClass *eqvClass = tenv.lookup( typeInst->get_name() ) ) {
    485                                 // expand ttype parameter into its actual type
    486                                 if ( eqvClass->data.kind == TypeDecl::Ttype && eqvClass->type ) {
    487                                         delete typeInst;
    488                                         return eqvClass->type->clone();
    489                                 }
    490                         }
    491                         return typeInst;
    492                 }
    493         };
    494 
    495         /// flattens a list of declarations, so that each tuple type has a single declaration.
    496         /// makes use of TtypeExpander to ensure ttypes are flat as well.
    497         void flattenList( std::list< DeclarationWithType * > src, std::list< DeclarationWithType * > & dst, TypeEnvironment & env ) {
    498                 dst.clear();
    499                 for ( DeclarationWithType * dcl : src ) {
    500                         PassVisitor<TtypeExpander_old> expander( env );
    501                         dcl->acceptMutator( expander );
    502                         std::list< Type * > types;
    503                         flatten( dcl->get_type(), back_inserter( types ) );
    504                         for ( Type * t : types ) {
    505                                 // outermost const, volatile, _Atomic qualifiers in parameters should not play a role in the unification of function types, since they do not determine whether a function is callable.
    506                                 // Note: MUST consider at least mutex qualifier, since functions can be overloaded on outermost mutex and a mutex function has different requirements than a non-mutex function.
    507                                 t->get_qualifiers() -= Type::Qualifiers(Type::Const | Type::Volatile | Type::Atomic);
    508 
    509                                 dst.push_back( new ObjectDecl( "", Type::StorageClasses(), LinkageSpec::C, nullptr, t, nullptr ) );
    510                         }
    511                         delete dcl;
    512                 }
    513         }
    514 
    515         void Unify_old::postvisit(FunctionType *functionType) {
    516                 FunctionType *otherFunction = dynamic_cast< FunctionType* >( type2 );
    517                 if ( otherFunction && functionType->get_isVarArgs() == otherFunction->get_isVarArgs() ) {
    518                         // flatten the parameter lists for both functions so that tuple structure
    519                         // doesn't affect unification. Must be a clone so that the types don't change.
    520                         std::unique_ptr<FunctionType> flatFunc( functionType->clone() );
    521                         std::unique_ptr<FunctionType> flatOther( otherFunction->clone() );
    522                         flattenList( flatFunc->get_parameters(), flatFunc->get_parameters(), env );
    523                         flattenList( flatOther->get_parameters(), flatOther->get_parameters(), env );
    524 
    525                         // sizes don't have to match if ttypes are involved; need to be more precise wrt where the ttype is to prevent errors
    526                         if (
    527                                         (flatFunc->parameters.size() == flatOther->parameters.size() &&
    528                                                 flatFunc->returnVals.size() == flatOther->returnVals.size())
    529                                         || flatFunc->isTtype()
    530                                         || flatOther->isTtype()
    531                         ) {
    532                                 if ( unifyTypeList( flatFunc->parameters.begin(), flatFunc->parameters.end(), flatOther->parameters.begin(), flatOther->parameters.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    533                                         if ( unifyTypeList( flatFunc->returnVals.begin(), flatFunc->returnVals.end(), flatOther->returnVals.begin(), flatOther->returnVals.end(), env, needAssertions, haveAssertions, openVars, indexer ) ) {
    534 
    535                                                 // the original types must be used in mark assertions, since pointer comparisons are used
    536                                                 markAssertions( haveAssertions, needAssertions, functionType );
    537                                                 markAssertions( haveAssertions, needAssertions, otherFunction );
    538 
    539                                                 result = true;
    540                                         } // if
    541                                 } // if
    542                         } // if
    543                 } // if
    544         }
    545 
    546         template< typename RefType >
    547         void Unify_old::handleRefType( RefType *inst, Type *other ) {
    548                 // check that other type is compatible and named the same
    549                 RefType *otherStruct = dynamic_cast< RefType* >( other );
    550                 result = otherStruct && inst->name == otherStruct->name;
    551         }
    552 
    553         template< typename RefType >
    554         void Unify_old::handleGenericRefType( RefType *inst, Type *other ) {
    555                 // Check that other type is compatible and named the same
    556                 handleRefType( inst, other );
    557                 if ( ! result ) return;
    558                 // Check that parameters of types unify, if any
    559                 std::list< Expression* > params = inst->parameters;
    560                 std::list< Expression* > otherParams = ((RefType*)other)->parameters;
    561 
    562                 std::list< Expression* >::const_iterator it = params.begin(), jt = otherParams.begin();
    563                 for ( ; it != params.end() && jt != otherParams.end(); ++it, ++jt ) {
    564                         TypeExpr *param = dynamic_cast< TypeExpr* >(*it);
    565                         assertf(param, "Aggregate parameters should be type expressions");
    566                         TypeExpr *otherParam = dynamic_cast< TypeExpr* >(*jt);
    567                         assertf(otherParam, "Aggregate parameters should be type expressions");
    568 
    569                         Type* paramTy = param->get_type();
    570                         Type* otherParamTy = otherParam->get_type();
    571 
    572                         bool tupleParam = Tuples::isTtype( paramTy );
    573                         bool otherTupleParam = Tuples::isTtype( otherParamTy );
    574 
    575                         if ( tupleParam && otherTupleParam ) {
    576                                 ++it; ++jt;  // skip ttype parameters for break
    577                         } else if ( tupleParam ) {
    578                                 // bundle other parameters into tuple to match
    579                                 std::list< Type * > binderTypes;
    580 
    581                                 do {
    582                                         binderTypes.push_back( otherParam->get_type()->clone() );
    583                                         ++jt;
    584 
    585                                         if ( jt == otherParams.end() ) break;
    586 
    587                                         otherParam = dynamic_cast< TypeExpr* >(*jt);
    588                                         assertf(otherParam, "Aggregate parameters should be type expressions");
    589                                 } while (true);
    590 
    591                                 otherParamTy = new TupleType{ paramTy->get_qualifiers(), binderTypes };
    592                                 ++it;  // skip ttype parameter for break
    593                         } else if ( otherTupleParam ) {
    594                                 // bundle parameters into tuple to match other
    595                                 std::list< Type * > binderTypes;
    596 
    597                                 do {
    598                                         binderTypes.push_back( param->get_type()->clone() );
    599                                         ++it;
    600 
    601                                         if ( it == params.end() ) break;
    602 
    603                                         param = dynamic_cast< TypeExpr* >(*it);
    604                                         assertf(param, "Aggregate parameters should be type expressions");
    605                                 } while (true);
    606 
    607                                 paramTy = new TupleType{ otherParamTy->get_qualifiers(), binderTypes };
    608                                 ++jt;  // skip ttype parameter for break
    609                         }
    610 
    611                         if ( ! unifyExact( paramTy, otherParamTy, env, needAssertions, haveAssertions, openVars, WidenMode(false, false), indexer ) ) {
    612                                 result = false;
    613                                 return;
    614                         }
    615 
    616                         // ttype parameter should be last
    617                         if ( tupleParam || otherTupleParam ) break;
    618                 }
    619                 result = ( it == params.end() && jt == otherParams.end() );
    620         }
    621 
    622         void Unify_old::postvisit(StructInstType *structInst) {
    623                 handleGenericRefType( structInst, type2 );
    624         }
    625 
    626         void Unify_old::postvisit(UnionInstType *unionInst) {
    627                 handleGenericRefType( unionInst, type2 );
    628         }
    629 
    630         void Unify_old::postvisit(EnumInstType *enumInst) {
    631                 handleRefType( enumInst, type2 );
    632         }
    633 
    634         void Unify_old::postvisit(TraitInstType *contextInst) {
    635                 handleRefType( contextInst, type2 );
    636         }
    637 
    638         void Unify_old::postvisit(TypeInstType *typeInst) {
    639                 assert( openVars.find( typeInst->get_name() ) == openVars.end() );
    640                 TypeInstType *otherInst = dynamic_cast< TypeInstType* >( type2 );
    641                 if ( otherInst && typeInst->get_name() == otherInst->get_name() ) {
    642                         result = true;
    643 ///   } else {
    644 ///     NamedTypeDecl *nt = indexer.lookupType( typeInst->get_name() );
    645 ///     if ( nt ) {
    646 ///       TypeDecl *type = dynamic_cast< TypeDecl* >( nt );
    647 ///       assert( type );
    648 ///       if ( type->get_base() ) {
    649 ///         result = unifyExact( type->get_base(), typeInst, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    650 ///       }
    651 ///     }
    652                 } // if
    653         }
    654 
    655         template< typename Iterator1, typename Iterator2 >
    656         bool unifyList( Iterator1 list1Begin, Iterator1 list1End, Iterator2 list2Begin, Iterator2 list2End, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, const SymTab::Indexer &indexer ) {
    657                 auto get_type = [](Type * t) { return t; };
    658                 for ( ; list1Begin != list1End && list2Begin != list2End; ++list1Begin, ++list2Begin ) {
    659                         Type * t1 = *list1Begin;
    660                         Type * t2 = *list2Begin;
    661                         bool isTtype1 = Tuples::isTtype( t1 );
    662                         bool isTtype2 = Tuples::isTtype( t2 );
    663                         // xxx - assumes ttype must be last parameter
    664                         // xxx - there may be a nice way to refactor this, but be careful because the argument positioning might matter in some cases.
    665                         if ( isTtype1 && ! isTtype2 ) {
    666                                 // combine all of the things in list2, then unify
    667                                 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    668                         } else if ( isTtype2 && ! isTtype1 ) {
    669                                 // combine all of the things in list1, then unify
    670                                 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    671                         } else if ( ! unifyExact( t1, t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer ) ) {
    672                                 return false;
    673                         } // if
    674 
    675                 } // for
    676                 if ( list1Begin != list1End ) {
    677                         // try unifying empty tuple type with ttype
    678                         Type * t1 = *list1Begin;
    679                         if ( Tuples::isTtype( t1 ) ) {
    680                                 return unifyExact( t1, combineTypes( list2Begin, list2End, get_type ).get(), env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    681                         } else return false;
    682                 } else if ( list2Begin != list2End ) {
    683                         // try unifying empty tuple type with ttype
    684                         Type * t2 = *list2Begin;
    685                         if ( Tuples::isTtype( t2 ) ) {
    686                                 return unifyExact( combineTypes( list1Begin, list1End, get_type ).get(), t2, env, needAssertions, haveAssertions, openVars, WidenMode( false, false ), indexer );
    687                         } else return false;
    688                 } else {
    689                         return true;
    690                 } // if
    691         }
    692 
    693         void Unify_old::postvisit(TupleType *tupleType) {
    694                 if ( TupleType *otherTuple = dynamic_cast< TupleType* >( type2 ) ) {
    695                         std::unique_ptr<TupleType> flat1( tupleType->clone() );
    696                         std::unique_ptr<TupleType> flat2( otherTuple->clone() );
    697                         std::list<Type *> types1, types2;
    698 
    699                         PassVisitor<TtypeExpander_old> expander( env );
    700                         flat1->acceptMutator( expander );
    701                         flat2->acceptMutator( expander );
    702 
    703                         flatten( flat1.get(), back_inserter( types1 ) );
    704                         flatten( flat2.get(), back_inserter( types2 ) );
    705 
    706                         result = unifyList( types1.begin(), types1.end(), types2.begin(), types2.end(), env, needAssertions, haveAssertions, openVars, indexer );
    707                 } // if
    708         }
    709 
    710         void Unify_old::postvisit( __attribute__((unused)) VarArgsType *varArgsType ) {
    711                 result = dynamic_cast< VarArgsType* >( type2 );
    712         }
    713 
    714         void Unify_old::postvisit( __attribute__((unused)) ZeroType *zeroType ) {
    715                 result = dynamic_cast< ZeroType* >( type2 );
    716         }
    717 
    718         void Unify_old::postvisit( __attribute__((unused)) OneType *oneType ) {
    719                 result = dynamic_cast< OneType* >( type2 );
    720         }
    721 
    722         Type * extractResultType( FunctionType * function ) {
    723                 if ( function->get_returnVals().size() == 0 ) {
    724                         return new VoidType( Type::Qualifiers() );
    725                 } else if ( function->get_returnVals().size() == 1 ) {
    726                         return function->get_returnVals().front()->get_type()->clone();
    727                 } else {
    728                         std::list< Type * > types;
    729                         for ( DeclarationWithType * decl : function->get_returnVals() ) {
    730                                 types.push_back( decl->get_type()->clone() );
    731                         } // for
    732                         return new TupleType( Type::Qualifiers(), types );
    733                 }
    734101        }
    735102
  • src/ResolvExpr/Unify.h

    r790d835 rc6b4432  
    2020#include "AST/Node.hpp"             // for ptr
    2121#include "AST/TypeEnvironment.hpp"  // for TypeEnvironment, AssertionSet, OpenVarSet
    22 #include "Common/utility.h"       // for deleteAll
    23 #include "SynTree/Declaration.h"  // for TypeDecl, TypeDecl::Data
    24 #include "TypeEnvironment.h"      // for AssertionSet, OpenVarSet
    2522#include "WidenMode.h"              // for WidenMode
    26 
    27 class Type;
    28 class TypeInstType;
    29 namespace SymTab {
    30         class Indexer;
    31 }
    3223
    3324namespace ast {
     
    3728
    3829namespace ResolvExpr {
    39 
    40 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    41 bool unify( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer, Type *&commonType );
    42 bool unifyExact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, OpenVarSet &openVars, const SymTab::Indexer &indexer );
    43 bool unifyInexact( Type *type1, Type *type2, TypeEnvironment &env, AssertionSet &needAssertions, AssertionSet &haveAssertions, const OpenVarSet &openVars, WidenMode widen, const SymTab::Indexer &indexer, Type *&common );
    44 
    45 bool typesCompatible( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
    46 bool typesCompatibleIgnoreQualifiers( const Type *, const Type *, const SymTab::Indexer & indexer, const TypeEnvironment & env );
    47 
    48 inline bool typesCompatible( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
    49         TypeEnvironment env;
    50         return typesCompatible( t1, t2, indexer, env );
    51 }
    52 
    53 inline bool typesCompatibleIgnoreQualifiers( const Type * t1, const Type * t2, const SymTab::Indexer & indexer ) {
    54         TypeEnvironment env;
    55         return typesCompatibleIgnoreQualifiers( t1, t2, indexer, env );
    56 }
    5730
    5831bool unify(
     
    8558        const ast::TypeEnvironment & env = {} );
    8659
    87 /// Creates the type represented by the list of returnVals in a FunctionType.
    88 /// The caller owns the return value.
    89 Type * extractResultType( FunctionType * functionType );
    9060/// Creates or extracts the type represented by returns in a `FunctionType`.
    9161ast::ptr<ast::Type> extractResultType( const ast::FunctionType * func );
  • src/ResolvExpr/module.mk

    r790d835 rc6b4432  
    1818      ResolvExpr/AdjustExprType.cc \
    1919      ResolvExpr/AdjustExprType.hpp \
    20       ResolvExpr/Alternative.cc \
    21       ResolvExpr/AlternativeFinder.cc \
    22       ResolvExpr/AlternativeFinder.h \
    23       ResolvExpr/Alternative.h \
    2420      ResolvExpr/Candidate.cpp \
    2521      ResolvExpr/CandidateFinder.cpp \
     
    3531      ResolvExpr/CurrentObject.cc \
    3632      ResolvExpr/CurrentObject.h \
    37       ResolvExpr/ExplodedActual.cc \
    38       ResolvExpr/ExplodedActual.h \
    3933      ResolvExpr/ExplodedArg.cpp \
    4034      ResolvExpr/ExplodedArg.hpp \
    4135      ResolvExpr/FindOpenVars.cc \
    4236      ResolvExpr/FindOpenVars.h \
    43       ResolvExpr/Occurs.cc \
    4437      ResolvExpr/PolyCost.cc \
    4538      ResolvExpr/PolyCost.hpp \
     
    5043      ResolvExpr/RenameVars.cc \
    5144      ResolvExpr/RenameVars.h \
    52       ResolvExpr/ResolveAssertions.cc \
    53       ResolvExpr/ResolveAssertions.h \
    5445      ResolvExpr/Resolver.cc \
    5546      ResolvExpr/Resolver.h \
     
    6152      ResolvExpr/SpecCost.cc \
    6253      ResolvExpr/SpecCost.hpp \
    63       ResolvExpr/TypeEnvironment.cc \
    64       ResolvExpr/TypeEnvironment.h \
    6554      ResolvExpr/typeops.h \
    6655      ResolvExpr/Unify.cc \
     
    6958
    7059SRC += $(SRC_RESOLVEXPR) \
    71         ResolvExpr/AlternativePrinter.cc \
    72         ResolvExpr/AlternativePrinter.h \
    7360        ResolvExpr/CandidatePrinter.cpp \
    7461        ResolvExpr/CandidatePrinter.hpp \
  • src/ResolvExpr/typeops.h

    r790d835 rc6b4432  
    1919
    2020#include "AST/Type.hpp"
    21 #include "SynTree/Type.h"
    2221
    2322namespace SymTab {
     
    5251                        std::copy( i.begin(), i.end(), inserter );
    5352                        *out++ = result;
    54                 }
    55         }
    56 
    57         // in Occurs.cc
    58         bool occurs( const Type * type, const std::string & varName, const TypeEnvironment & env );
    59         // new AST version in TypeEnvironment.cpp (only place it was used in old AST)
    60 
    61         template<typename Iter>
    62         bool occursIn( Type* ty, Iter begin, Iter end, const TypeEnvironment & env ) {
    63                 while ( begin != end ) {
    64                         if ( occurs( ty, *begin, env ) ) return true;
    65                         ++begin;
    66                 }
    67                 return false;
    68         }
    69 
    70         /// flatten tuple type into list of types
    71         template< typename OutputIterator >
    72         void flatten( Type * type, OutputIterator out ) {
    73                 if ( TupleType * tupleType = dynamic_cast< TupleType * >( type ) ) {
    74                         for ( Type * t : tupleType->get_types() ) {
    75                                 flatten( t, out );
    76                         }
    77                 } else {
    78                         *out++ = type->clone();
    7953                }
    8054        }
     
    12094                return tupleFromTypes( tys.begin(), tys.end() );
    12195        }
    122 
    123         // in TypeEnvironment.cc
    124         bool isFtype( const Type * type );
    12596} // namespace ResolvExpr
    12697
  • src/SymTab/Demangle.cc

    r790d835 rc6b4432  
    2121#include "CodeGen/GenType.h"
    2222#include "CodeGen/OperatorTable.h"
    23 #include "Common/PassVisitor.h"
    2423#include "Common/utility.h"                                                             // isPrefix
    2524#include "Mangler.h"
    26 #include "SynTree/Type.h"
    27 #include "SynTree/Declaration.h"
    2825
    2926#define DEBUG
     
    3330#define PRINT(x) {}
    3431#endif
    35 
    36 namespace SymTab {
    37         namespace Mangler {
    38                 namespace {
    39                         struct StringView {
    40                         private:
    41                                 std::string str;
    42                                 size_t idx = 0;
    43                                 // typedef Type * (StringView::*parser)(Type::Qualifiers);
    44                                 typedef std::function<Type * (Type::Qualifiers)> parser;
    45                                 std::vector<std::pair<std::string, parser>> parsers;
    46                         public:
    47                                 StringView(const std::string & str);
    48 
    49                                 bool done() const { return idx >= str.size(); }
    50                                 char cur() const { assert(! done()); return str[idx]; }
    51 
    52                                 bool expect(char ch) { return str[idx++] == ch; }
    53                                 void next(size_t inc = 1) { idx += inc; }
    54 
    55                                 /// determines if `pref` is a prefix of `str`
    56                                 bool isPrefix(const std::string & pref);
    57                                 bool extractNumber(size_t & out);
    58                                 bool extractName(std::string & out);
    59                                 bool stripMangleName(std::string & name);
    60 
    61                                 Type * parseFunction(Type::Qualifiers tq);
    62                                 Type * parseTuple(Type::Qualifiers tq);
    63                                 Type * parseVoid(Type::Qualifiers tq);
    64                                 Type * parsePointer(Type::Qualifiers tq);
    65                                 Type * parseArray(Type::Qualifiers tq);
    66                                 Type * parseStruct(Type::Qualifiers tq);
    67                                 Type * parseUnion(Type::Qualifiers tq);
    68                                 Type * parseEnum(Type::Qualifiers tq);
    69                                 Type * parseType(Type::Qualifiers tq);
    70 
    71                                 Type * parseType();
    72                                 bool parse(std::string & name, Type *& type);
    73                         };
    74 
    75                         StringView::StringView(const std::string & str) : str(str) {
    76                                 // basic types
    77                                 for (size_t k = 0; k < BasicType::NUMBER_OF_BASIC_TYPES; ++k) {
    78                                         parsers.emplace_back(Encoding::basicTypes[k], [k](Type::Qualifiers tq) {
    79                                                 PRINT( std::cerr << "basic type: " << k << std::endl; )
    80                                                 return new BasicType(tq, (BasicType::Kind)k);
    81                                         });
    82                                 }
    83                                 // type variable types
    84                                 for (size_t k = 0; k < TypeDecl::NUMBER_OF_KINDS; ++k) {
    85                                         static const std::string typeVariableNames[] = { "DT", "DST", "OT", "FT", "TT", "ALT", };
    86                                         static_assert(
    87                                                 sizeof(typeVariableNames)/sizeof(typeVariableNames[0]) == TypeDecl::NUMBER_OF_KINDS,
    88                                                 "Each type variable kind should have a demangle name prefix"
    89                                         );
    90                                         parsers.emplace_back(Encoding::typeVariables[k], [k, this](Type::Qualifiers tq) -> TypeInstType * {
    91                                                 PRINT( std::cerr << "type variable type: " << k << std::endl; )
    92                                                 size_t N;
    93                                                 if (! extractNumber(N)) return nullptr;
    94                                                 return new TypeInstType(tq, toString(typeVariableNames[k], N), (TypeDecl::Kind)k != TypeDecl::Ftype);
    95                                         });
    96                                 }
    97                                 // everything else
    98                                 parsers.emplace_back(Encoding::void_t, [this](Type::Qualifiers tq) { return parseVoid(tq); });
    99                                 parsers.emplace_back(Encoding::function, [this](Type::Qualifiers tq) { return parseFunction(tq); });
    100                                 parsers.emplace_back(Encoding::pointer, [this](Type::Qualifiers tq) { return parsePointer(tq); });
    101                                 parsers.emplace_back(Encoding::array, [this](Type::Qualifiers tq) { return parseArray(tq); });
    102                                 parsers.emplace_back(Encoding::tuple, [this](Type::Qualifiers tq) { return parseTuple(tq); });
    103                                 parsers.emplace_back(Encoding::struct_t, [this](Type::Qualifiers tq) { return parseStruct(tq); });
    104                                 parsers.emplace_back(Encoding::union_t, [this](Type::Qualifiers tq) { return parseUnion(tq); });
    105                                 parsers.emplace_back(Encoding::enum_t, [this](Type::Qualifiers tq) { return parseEnum(tq); });
    106                                 parsers.emplace_back(Encoding::type, [this](Type::Qualifiers tq) { return parseType(tq); });
    107                                 parsers.emplace_back(Encoding::zero, [](Type::Qualifiers tq) { return new ZeroType(tq); });
    108                                 parsers.emplace_back(Encoding::one, [](Type::Qualifiers tq) { return new OneType(tq); });
    109                         }
    110 
    111                         bool StringView::extractNumber(size_t & out) {
    112                                 std::stringstream numss;
    113                                 if (idx >= str.size()) return false;
    114                                 while (isdigit(str[idx])) {
    115                                         numss << str[idx];
    116                                         ++idx;
    117                                         if (idx == str.size()) break;
    118                                 }
    119                                 if (! (numss >> out)) return false;
    120                                 PRINT( std::cerr << "extractNumber success: " << out << std::endl; )
    121                                 return true;
    122                         }
    123 
    124                         bool StringView::extractName(std::string & out) {
    125                                 size_t len;
    126                                 if (! extractNumber(len)) return false;
    127                                 if (idx+len > str.size()) return false;
    128                                 out = str.substr(idx, len);
    129                                 idx += len;
    130                                 PRINT( std::cerr << "extractName success: " << out << std::endl; )
    131                                 return true;
    132                         }
    133 
    134                         bool StringView::isPrefix(const std::string & pref) {
    135                                 // if ( pref.size() > str.size()-idx ) return false;
    136                                 // auto its = std::mismatch( pref.begin(), pref.end(), std::next(str.begin(), idx) );
    137                                 // if (its.first == pref.end()) {
    138                                 //      idx += pref.size();
    139                                 //      return true;
    140                                 // }
    141 
    142                                 // This update is untested because there are no tests for this code.
    143                                 if ( ::isPrefix( str, pref, idx ) ) {
    144                                         idx += pref.size();
    145                                         return true;
    146                                 }
    147                                 return false;
    148                         }
    149 
    150                         // strips __NAME__cfa__TYPE_N, where N is [0-9]+: returns str is a match is found, returns empty string otherwise
    151                         bool StringView::stripMangleName(std::string & name) {
    152                                 PRINT( std::cerr << "====== " << str.size() << " " << str << std::endl; )
    153                                 if (str.size() < 2+Encoding::manglePrefix.size()) return false; // +2 for at least _1 suffix
    154                                 if ( ! isPrefix(Encoding::manglePrefix) || ! isdigit(str.back() ) ) return false;
    155 
    156                                 // get name
    157                                 if (! extractName(name)) return false;
    158 
    159                                 // find bounds for type
    160                                 PRINT( std::cerr << idx << " " << str.size() << std::endl; )
    161                                 PRINT( std::cerr << "[");
    162                                 while (isdigit(str.back())) {
    163                                         PRINT(std::cerr << ".");
    164                                         str.pop_back();
    165                                         if (str.size() <= idx) return false;
    166                                 }
    167                                 PRINT( std::cerr << "]" << std::endl );
    168                                 if (str.back() != '_') return false;
    169                                 str.pop_back();
    170                                 PRINT( std::cerr << str.size() << " " << name << " " << str.substr(idx) << std::endl; )
    171                                 return str.size() > idx;
    172                         }
    173 
    174                         Type * StringView::parseFunction(Type::Qualifiers tq) {
    175                                 PRINT( std::cerr << "function..." << std::endl; )
    176                                 if (done()) return nullptr;
    177                                 FunctionType * ftype = new FunctionType( tq, false );
    178                                 std::unique_ptr<Type> manager(ftype);
    179                                 Type * retVal = parseType();
    180                                 if (! retVal) return nullptr;
    181                                 PRINT( std::cerr << "with return type: " << retVal << std::endl; )
    182                                 ftype->returnVals.push_back(ObjectDecl::newObject("", retVal, nullptr));
    183                                 if (done() || ! expect('_')) return nullptr;
    184                                 while (! done()) {
    185                                         PRINT( std::cerr << "got ch: " << cur() << std::endl; )
    186                                         if (cur() == '_') return manager.release();
    187                                         Type * param = parseType();
    188                                         if (! param) return nullptr;
    189                                         PRINT( std::cerr << "with parameter : " << param << std::endl; )
    190                                         ftype->parameters.push_back(ObjectDecl::newObject("", param, nullptr));
    191                                 }
    192                                 return nullptr;
    193                         }
    194 
    195                         Type * StringView::parseTuple(Type::Qualifiers tq) {
    196                                 PRINT( std::cerr << "tuple..." << std::endl; )
    197                                 std::list< Type * > types;
    198                                 size_t ncomponents;
    199                                 if (! extractNumber(ncomponents)) return nullptr;
    200                                 for (size_t i = 0; i < ncomponents; ++i) {
    201                                         // TODO: delete all on return
    202                                         if (done()) return nullptr;
    203                                         PRINT( std::cerr << "got ch: " << cur() << std::endl; )
    204                                         Type * t = parseType();
    205                                         if (! t) return nullptr;
    206                                         PRINT( std::cerr << "with type : " << t << std::endl; )
    207                                         types.push_back(t);
    208                                 }
    209                                 return new TupleType( tq, types );
    210                         }
    211 
    212                         Type * StringView::parseVoid(Type::Qualifiers tq) {
    213                                 return new VoidType( tq );
    214                         }
    215 
    216                         Type * StringView::parsePointer(Type::Qualifiers tq) {
    217                                 PRINT( std::cerr << "pointer..." << std::endl; )
    218                                 Type * t = parseType();
    219                                 if (! t) return nullptr;
    220                                 return new PointerType( tq, t );
    221                         }
    222 
    223                         Type * StringView::parseArray(Type::Qualifiers tq) {
    224                                 PRINT( std::cerr << "array..." << std::endl; )
    225                                 size_t length;
    226                                 if (! extractNumber(length)) return nullptr;
    227                                 Type * t = parseType();
    228                                 if (! t) return nullptr;
    229                                 return new ArrayType( tq, t, new ConstantExpr( Constant::from_ulong(length) ), false, false );
    230                         }
    231 
    232                         Type * StringView::parseStruct(Type::Qualifiers tq) {
    233                                 PRINT( std::cerr << "struct..." << std::endl; )
    234                                 std::string name;
    235                                 if (! extractName(name)) return nullptr;
    236                                 return new StructInstType(tq, name);
    237                         }
    238 
    239                         Type * StringView::parseUnion(Type::Qualifiers tq) {
    240                                 PRINT( std::cerr << "union..." << std::endl; )
    241                                 std::string name;
    242                                 if (! extractName(name)) return nullptr;
    243                                 return new UnionInstType(tq, name);
    244                         }
    245 
    246                         Type * StringView::parseEnum(Type::Qualifiers tq) {
    247                                 PRINT( std::cerr << "enum..." << std::endl; )
    248                                 std::string name;
    249                                 if (! extractName(name)) return nullptr;
    250                                 return new EnumInstType(tq, name);
    251                         }
    252 
    253                         Type * StringView::parseType(Type::Qualifiers tq) {
    254                                 PRINT( std::cerr << "type..." << std::endl; )
    255                                 std::string name;
    256                                 if (! extractName(name)) return nullptr;
    257                                 PRINT( std::cerr << "typename..." << name << std::endl; )
    258                                 return new TypeInstType(tq, name, false);
    259                         }
    260 
    261                         Type * StringView::parseType() {
    262                                 if (done()) return nullptr;
    263 
    264                                 std::list<TypeDecl *> forall;
    265                                 if (isPrefix(Encoding::forall)) {
    266                                         PRINT( std::cerr << "polymorphic with..." << std::endl; )
    267                                         size_t dcount, fcount, vcount, acount;
    268                                         if (! extractNumber(dcount)) return nullptr;
    269                                         PRINT( std::cerr << dcount << " dtypes" << std::endl; )
    270                                         if (! expect('_')) return nullptr;
    271                                         if (! extractNumber(fcount)) return nullptr;
    272                                         PRINT( std::cerr << fcount << " ftypes" << std::endl; )
    273                                         if (! expect('_')) return nullptr;
    274                                         if (! extractNumber(vcount)) return nullptr;
    275                                         PRINT( std::cerr << vcount << " ttypes" << std::endl; )
    276                                         if (! expect('_')) return nullptr;
    277                                         if (! extractNumber(acount)) return nullptr;
    278                                         PRINT( std::cerr << acount << " assertions" << std::endl; )
    279                                         if (! expect('_')) return nullptr;
    280                                         for (size_t i = 0; i < acount; ++i) {
    281                                                 // TODO: need to recursively parse assertions, but for now just return nullptr so that
    282                                                 // demangler does not crash if there are assertions
    283                                                 return nullptr;
    284                                         }
    285                                         if (! expect('_')) return nullptr;
    286                                 }
    287 
    288                                 // qualifiers
    289                                 Type::Qualifiers tq;
    290                                 while (true) {
    291                                         auto qual = std::find_if(Encoding::qualifiers.begin(), Encoding::qualifiers.end(), [this](decltype(Encoding::qualifiers)::value_type val) {
    292                                                 return isPrefix(val.second);
    293                                         });
    294                                         if (qual == Encoding::qualifiers.end()) break;
    295                                         tq |= qual->first;
    296                                 }
    297 
    298                                 // find the correct type parser and use it
    299                                 auto iter = std::find_if(parsers.begin(), parsers.end(), [this](std::pair<std::string, parser> & p) {
    300                                         return isPrefix(p.first);
    301                                 });
    302                                 assertf(iter != parsers.end(), "Unhandled type letter: %c at index: %zd", cur(), idx);
    303                                 Type * ret = iter->second(tq);
    304                                 if (! ret) return nullptr;
    305                                 ret->forall = std::move(forall);
    306                                 return ret;
    307                         }
    308 
    309                         bool StringView::parse(std::string & name, Type *& type) {
    310                                 if (! stripMangleName(name)) return false;
    311                                 PRINT( std::cerr << "stripped name: " << name << std::endl; )
    312                                 Type * t = parseType();
    313                                 if (! t) return false;
    314                                 type = t;
    315                                 return true;
    316                         }
    317 
    318                         std::string demangle(const std::string & mangleName) {
    319                                 SymTab::Mangler::StringView view(mangleName);
    320                                 std::string name;
    321                                 Type * type = nullptr;
    322                                 if (! view.parse(name, type)) return mangleName;
    323                                 auto info = CodeGen::operatorLookupByOutput(name);
    324                                 if (info) name = info->inputName;
    325                                 std::unique_ptr<Type> manager(type);
    326                                 return CodeGen::genType(type, name);
    327                         }
    328                 } // namespace
    329         } // namespace Mangler
    330 } // namespace SymTab
    33132
    33233namespace Mangle {
     
    550251        if (done()) return nullptr;
    551252
    552         std::list<TypeDecl *> forall;
    553253        if (isPrefix(Encoding::forall)) {
    554254                PRINT( std::cerr << "polymorphic with..." << std::endl; )
  • src/SymTab/FixFunction.cc

    r790d835 rc6b4432  
    2222#include "AST/Type.hpp"
    2323#include "Common/utility.h"       // for copy
    24 #include "SynTree/Declaration.h"  // for FunctionDecl, ObjectDecl, Declarati...
    25 #include "SynTree/Expression.h"   // for Expression
    26 #include "SynTree/Type.h"         // for ArrayType, PointerType, Type, Basic...
    2724
    2825namespace SymTab {
    29         class FixFunction_old : public WithShortCircuiting {
    30                 typedef Mutator Parent;
    31           public:
    32                 FixFunction_old() : isVoid( false ) {}
    33 
    34                 void premutate(FunctionDecl *functionDecl);
    35                 DeclarationWithType* postmutate(FunctionDecl *functionDecl);
    36 
    37                 Type * postmutate(ArrayType * arrayType);
    38 
    39                 void premutate(ArrayType * arrayType);
    40                 void premutate(VoidType * voidType);
    41                 void premutate(BasicType * basicType);
    42                 void premutate(PointerType * pointerType);
    43                 void premutate(StructInstType * aggregateUseType);
    44                 void premutate(UnionInstType * aggregateUseType);
    45                 void premutate(EnumInstType * aggregateUseType);
    46                 void premutate(TraitInstType * aggregateUseType);
    47                 void premutate(TypeInstType * aggregateUseType);
    48                 void premutate(TupleType * tupleType);
    49                 void premutate(VarArgsType * varArgsType);
    50                 void premutate(ZeroType * zeroType);
    51                 void premutate(OneType * oneType);
    52 
    53                 bool isVoid;
    54         };
    55 
    56         DeclarationWithType * FixFunction_old::postmutate(FunctionDecl *functionDecl) {
    57                 // can't delete function type because it may contain assertions, so transfer ownership to new object
    58                 ObjectDecl *pointer = new ObjectDecl( functionDecl->name, functionDecl->get_storageClasses(), functionDecl->linkage, nullptr, new PointerType( Type::Qualifiers(), functionDecl->type ), nullptr, functionDecl->attributes );
    59                 pointer->location = functionDecl->location;
    60                 functionDecl->attributes.clear();
    61                 functionDecl->type = nullptr;
    62                 delete functionDecl;
    63                 return pointer;
    64         }
    65 
    66         // xxx - this passes on void[], e.g.
    67         //   void foo(void [10]);
    68         // does not cause an error
    69 
    70         Type * FixFunction_old::postmutate(ArrayType *arrayType) {
    71                 // need to recursively mutate the base type in order for multi-dimensional arrays to work.
    72                 PointerType *pointerType = new PointerType( arrayType->get_qualifiers(), arrayType->base, arrayType->dimension, arrayType->isVarLen, arrayType->isStatic );
    73                 pointerType->location = arrayType->location;
    74                 arrayType->base = nullptr;
    75                 arrayType->dimension = nullptr;
    76                 delete arrayType;
    77                 return pointerType;
    78         }
    79 
    80         void FixFunction_old::premutate(VoidType *) {
    81                 isVoid = true;
    82         }
    83 
    84         void FixFunction_old::premutate(FunctionDecl *) { visit_children = false; }
    85         void FixFunction_old::premutate(ArrayType *) { visit_children = false; }
    86         void FixFunction_old::premutate(BasicType *) { visit_children = false; }
    87         void FixFunction_old::premutate(PointerType *) { visit_children = false; }
    88         void FixFunction_old::premutate(StructInstType *) { visit_children = false; }
    89         void FixFunction_old::premutate(UnionInstType *) { visit_children = false; }
    90         void FixFunction_old::premutate(EnumInstType *) { visit_children = false; }
    91         void FixFunction_old::premutate(TraitInstType *) { visit_children = false; }
    92         void FixFunction_old::premutate(TypeInstType *) { visit_children = false; }
    93         void FixFunction_old::premutate(TupleType *) { visit_children = false; }
    94         void FixFunction_old::premutate(VarArgsType *) { visit_children = false; }
    95         void FixFunction_old::premutate(ZeroType *) { visit_children = false; }
    96         void FixFunction_old::premutate(OneType *) { visit_children = false; }
    97 
    98         bool fixFunction( DeclarationWithType *& dwt ) {
    99                 PassVisitor<FixFunction_old> fixer;
    100                 dwt = dwt->acceptMutator( fixer );
    101                 return fixer.pass.isVoid;
    102         }
    10326
    10427namespace {
  • src/SymTab/FixFunction.h

    r790d835 rc6b4432  
    1616#pragma once
    1717
    18 #include "Common/PassVisitor.h" // for PassVisitor
    19 #include "SynTree/SynTree.h"    // for Types
    20 
    2118namespace ast {
    2219        class DeclWithType;
     
    2522
    2623namespace SymTab {
    27         /// Replaces function and array types by equivalent pointer types. Returns true if type is
    28         /// void
    29         bool fixFunction( DeclarationWithType *& );
    30 
    3124        /// Returns declaration with function and array types replaced by equivalent pointer types.
    3225        /// Sets isVoid to true if type is void
  • src/SymTab/Mangler.cc

    r790d835 rc6b4432  
    2424#include "AST/Pass.hpp"
    2525#include "CodeGen/OperatorTable.h"       // for OperatorInfo, operatorLookup
    26 #include "Common/PassVisitor.h"
    2726#include "Common/ToString.hpp"           // for toCString
    2827#include "Common/SemanticError.h"        // for SemanticError
    29 #include "ResolvExpr/TypeEnvironment.h"  // for TypeEnvironment
    30 #include "SynTree/LinkageSpec.h"         // for Spec, isOverridable, AutoGen, Int...
    31 #include "SynTree/Declaration.h"         // for TypeDecl, DeclarationWithType
    32 #include "SynTree/Expression.h"          // for TypeExpr, Expression, operator<<
    33 #include "SynTree/Type.h"                // for Type, ReferenceToType, Type::Fora...
    34 
    35 namespace SymTab {
    36         namespace Mangler {
    37                 namespace {
    38                         /// Mangles names to a unique C identifier
    39                         struct Mangler_old : public WithShortCircuiting, public WithVisitorRef<Mangler_old>, public WithGuards {
    40                                 Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams );
    41                                 Mangler_old( const Mangler_old & ) = delete;
    42 
    43                                 void previsit( const BaseSyntaxNode * ) { visit_children = false; }
    44 
    45                                 void postvisit( const ObjectDecl * declaration );
    46                                 void postvisit( const FunctionDecl * declaration );
    47                                 void postvisit( const TypeDecl * declaration );
    48 
    49                                 void postvisit( const VoidType * voidType );
    50                                 void postvisit( const BasicType * basicType );
    51                                 void postvisit( const PointerType * pointerType );
    52                                 void postvisit( const ArrayType * arrayType );
    53                                 void postvisit( const ReferenceType * refType );
    54                                 void postvisit( const FunctionType * functionType );
    55                                 void postvisit( const StructInstType * aggregateUseType );
    56                                 void postvisit( const UnionInstType * aggregateUseType );
    57                                 void postvisit( const EnumInstType * aggregateUseType );
    58                                 void postvisit( const TypeInstType * aggregateUseType );
    59                                 void postvisit( const TraitInstType * inst );
    60                                 void postvisit( const TupleType * tupleType );
    61                                 void postvisit( const VarArgsType * varArgsType );
    62                                 void postvisit( const ZeroType * zeroType );
    63                                 void postvisit( const OneType * oneType );
    64                                 void postvisit( const QualifiedType * qualType );
    65 
    66                                 std::string get_mangleName() { return mangleName; }
    67                           private:
    68                                 std::string mangleName;         ///< Mangled name being constructed
    69                                 typedef std::map< std::string, std::pair< int, int > > VarMapType;
    70                                 VarMapType varNums;             ///< Map of type variables to indices
    71                                 int nextVarNum;                 ///< Next type variable index
    72                                 bool isTopLevel;                ///< Is the Mangler at the top level
    73                                 bool mangleOverridable;         ///< Specially mangle overridable built-in methods
    74                                 bool typeMode;                  ///< Produce a unique mangled name for a type
    75                                 bool mangleGenericParams;       ///< Include generic parameters in name mangling if true
    76                                 bool inFunctionType = false;    ///< Include type qualifiers if false.
    77                                 bool inQualifiedType = false;   ///< Add start/end delimiters around qualified type
    78 
    79                           public:
    80                                 Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
    81                                         int nextVarNum, const VarMapType& varNums );
    82 
    83                           private:
    84                                 void mangleDecl( const DeclarationWithType * declaration );
    85                                 void mangleRef( const ReferenceToType * refType, std::string prefix );
    86 
    87                                 void printQualifiers( const Type *type );
    88                         }; // Mangler_old
    89                 } // namespace
    90 
    91                 std::string mangle( const BaseSyntaxNode * decl, bool mangleOverridable, bool typeMode, bool mangleGenericParams ) {
    92                         PassVisitor<Mangler_old> mangler( mangleOverridable, typeMode, mangleGenericParams );
    93                         maybeAccept( decl, mangler );
    94                         return mangler.pass.get_mangleName();
    95                 }
    96 
    97                 std::string mangleType( const Type * ty ) {
    98                         PassVisitor<Mangler_old> mangler( false, true, true );
    99                         maybeAccept( ty, mangler );
    100                         return mangler.pass.get_mangleName();
    101                 }
    102 
    103                 std::string mangleConcrete( const Type * ty ) {
    104                         PassVisitor<Mangler_old> mangler( false, false, false );
    105                         maybeAccept( ty, mangler );
    106                         return mangler.pass.get_mangleName();
    107                 }
    108 
    109                 namespace {
    110                         Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams )
    111                                 : nextVarNum( 0 ), isTopLevel( true ),
    112                                 mangleOverridable( mangleOverridable ), typeMode( typeMode ),
    113                                 mangleGenericParams( mangleGenericParams ) {}
    114 
    115                         Mangler_old::Mangler_old( bool mangleOverridable, bool typeMode, bool mangleGenericParams,
    116                                 int nextVarNum, const VarMapType& varNums )
    117                                 : varNums( varNums ), nextVarNum( nextVarNum ), isTopLevel( false ),
    118                                 mangleOverridable( mangleOverridable ), typeMode( typeMode ),
    119                                 mangleGenericParams( mangleGenericParams ) {}
    120 
    121                         void Mangler_old::mangleDecl( const DeclarationWithType * declaration ) {
    122                                 bool wasTopLevel = isTopLevel;
    123                                 if ( isTopLevel ) {
    124                                         varNums.clear();
    125                                         nextVarNum = 0;
    126                                         isTopLevel = false;
    127                                 } // if
    128                                 mangleName += Encoding::manglePrefix;
    129                                 const CodeGen::OperatorInfo * opInfo = CodeGen::operatorLookup( declaration->get_name() );
    130                                 if ( opInfo ) {
    131                                         mangleName += std::to_string( opInfo->outputName.size() ) + opInfo->outputName;
    132                                 } else {
    133                                         mangleName += std::to_string( declaration->name.size() ) + declaration->name;
    134                                 } // if
    135                                 maybeAccept( declaration->get_type(), *visitor );
    136                                 if ( mangleOverridable && LinkageSpec::isOverridable( declaration->get_linkage() ) ) {
    137                                         // want to be able to override autogenerated and intrinsic routines,
    138                                         // so they need a different name mangling
    139                                         if ( declaration->get_linkage() == LinkageSpec::AutoGen ) {
    140                                                 mangleName += Encoding::autogen;
    141                                         } else if ( declaration->get_linkage() == LinkageSpec::Intrinsic ) {
    142                                                 mangleName += Encoding::intrinsic;
    143                                         } else {
    144                                                 // if we add another kind of overridable function, this has to change
    145                                                 assert( false && "unknown overrideable linkage" );
    146                                         } // if
    147                                 }
    148                                 isTopLevel = wasTopLevel;
    149                         }
    150 
    151                         void Mangler_old::postvisit( const ObjectDecl * declaration ) {
    152                                 mangleDecl( declaration );
    153                         }
    154 
    155                         void Mangler_old::postvisit( const FunctionDecl * declaration ) {
    156                                 mangleDecl( declaration );
    157                         }
    158 
    159                         void Mangler_old::postvisit( const VoidType * voidType ) {
    160                                 printQualifiers( voidType );
    161                                 mangleName += Encoding::void_t;
    162                         }
    163 
    164                         void Mangler_old::postvisit( const BasicType * basicType ) {
    165                                 printQualifiers( basicType );
    166                                 assertf( basicType->kind < BasicType::NUMBER_OF_BASIC_TYPES, "Unhandled basic type: %d", basicType->kind );
    167                                 mangleName += Encoding::basicTypes[ basicType->kind ];
    168                         }
    169 
    170                         void Mangler_old::postvisit( const PointerType * pointerType ) {
    171                                 printQualifiers( pointerType );
    172                                 // mangle void (*f)() and void f() to the same name to prevent overloading on functions and function pointers
    173                                 if ( ! dynamic_cast<FunctionType *>( pointerType->base ) ) mangleName += Encoding::pointer;
    174                                 maybeAccept( pointerType->base, *visitor );
    175                         }
    176 
    177                         void Mangler_old::postvisit( const ArrayType * arrayType ) {
    178                                 // TODO: encode dimension
    179                                 printQualifiers( arrayType );
    180                                 mangleName += Encoding::array + "0";
    181                                 maybeAccept( arrayType->base, *visitor );
    182                         }
    183 
    184                         void Mangler_old::postvisit( const ReferenceType * refType ) {
    185                                 // don't print prefix (e.g. 'R') for reference types so that references and non-references do not overload.
    186                                 // Further, do not print the qualifiers for a reference type (but do run printQualifers because of TypeDecls, etc.),
    187                                 // by pretending every reference type is a function parameter.
    188                                 GuardValue( inFunctionType );
    189                                 inFunctionType = true;
    190                                 printQualifiers( refType );
    191                                 maybeAccept( refType->base, *visitor );
    192                         }
    193 
    194                         namespace {
    195                                 inline std::list< Type* > getTypes( const std::list< DeclarationWithType* > decls ) {
    196                                         std::list< Type* > ret;
    197                                         std::transform( decls.begin(), decls.end(), std::back_inserter( ret ),
    198                                                                         std::mem_fun( &DeclarationWithType::get_type ) );
    199                                         return ret;
    200                                 }
    201                         }
    202 
    203                         void Mangler_old::postvisit( const FunctionType * functionType ) {
    204                                 printQualifiers( functionType );
    205                                 mangleName += Encoding::function;
    206                                 // turn on inFunctionType so that printQualifiers does not print most qualifiers for function parameters,
    207                                 // since qualifiers on outermost parameter type do not differentiate function types, e.g.,
    208                                 // void (*)(const int) and void (*)(int) are the same type, but void (*)(const int *) and void (*)(int *) are different
    209                                 GuardValue( inFunctionType );
    210                                 inFunctionType = true;
    211                                 std::list< Type* > returnTypes = getTypes( functionType->returnVals );
    212                                 if (returnTypes.empty()) mangleName += Encoding::void_t;
    213                                 else acceptAll( returnTypes, *visitor );
    214                                 mangleName += "_";
    215                                 std::list< Type* > paramTypes = getTypes( functionType->parameters );
    216                                 acceptAll( paramTypes, *visitor );
    217                                 mangleName += "_";
    218                         }
    219 
    220                         void Mangler_old::mangleRef( const ReferenceToType * refType, std::string prefix ) {
    221                                 printQualifiers( refType );
    222 
    223                                 mangleName += prefix + std::to_string( refType->name.length() ) + refType->name;
    224 
    225                                 if ( mangleGenericParams ) {
    226                                         const std::list< Expression* > & params = refType->parameters;
    227                                         if ( ! params.empty() ) {
    228                                                 mangleName += "_";
    229                                                 for ( const Expression * param : params ) {
    230                                                         const TypeExpr * paramType = dynamic_cast< const TypeExpr * >( param );
    231                                                         assertf(paramType, "Aggregate parameters should be type expressions: %s", toCString(param));
    232                                                         maybeAccept( paramType->type, *visitor );
    233                                                 }
    234                                                 mangleName += "_";
    235                                         }
    236                                 }
    237                         }
    238 
    239                         void Mangler_old::postvisit( const StructInstType * aggregateUseType ) {
    240                                 mangleRef( aggregateUseType, Encoding::struct_t );
    241                         }
    242 
    243                         void Mangler_old::postvisit( const UnionInstType * aggregateUseType ) {
    244                                 mangleRef( aggregateUseType, Encoding::union_t );
    245                         }
    246 
    247                         void Mangler_old::postvisit( const EnumInstType * aggregateUseType ) {
    248                                 mangleRef( aggregateUseType, Encoding::enum_t );
    249                         }
    250 
    251                         void Mangler_old::postvisit( const TypeInstType * typeInst ) {
    252                                 VarMapType::iterator varNum = varNums.find( typeInst->get_name() );
    253                                 if ( varNum == varNums.end() ) {
    254                                         mangleRef( typeInst, Encoding::type );
    255                                 } else {
    256                                         printQualifiers( typeInst );
    257                                         // Note: Can't use name here, since type variable names do not actually disambiguate a function, e.g.
    258                                         //   forall(dtype T) void f(T);
    259                                         //   forall(dtype S) void f(S);
    260                                         // are equivalent and should mangle the same way. This is accomplished by numbering the type variables when they
    261                                         // are first found and prefixing with the appropriate encoding for the type class.
    262                                         assertf( varNum->second.second < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", varNum->second.second );
    263                                         mangleName += Encoding::typeVariables[varNum->second.second] + std::to_string( varNum->second.first );
    264                                 } // if
    265                         }
    266 
    267                         void Mangler_old::postvisit( const TraitInstType * inst ) {
    268                                 printQualifiers( inst );
    269                                 mangleName += std::to_string( inst->name.size() ) + inst->name;
    270                         }
    271 
    272                         void Mangler_old::postvisit( const TupleType * tupleType ) {
    273                                 printQualifiers( tupleType );
    274                                 mangleName += Encoding::tuple + std::to_string( tupleType->types.size() );
    275                                 acceptAll( tupleType->types, *visitor );
    276                         }
    277 
    278                         void Mangler_old::postvisit( const VarArgsType * varArgsType ) {
    279                                 printQualifiers( varArgsType );
    280                                 static const std::string vargs = "__builtin_va_list";
    281                                 mangleName += Encoding::type + std::to_string( vargs.size() ) + vargs;
    282                         }
    283 
    284                         void Mangler_old::postvisit( const ZeroType * ) {
    285                                 mangleName += Encoding::zero;
    286                         }
    287 
    288                         void Mangler_old::postvisit( const OneType * ) {
    289                                 mangleName += Encoding::one;
    290                         }
    291 
    292                         void Mangler_old::postvisit( const QualifiedType * qualType ) {
    293                                 bool inqual = inQualifiedType;
    294                                 if (! inqual ) {
    295                                         // N marks the start of a qualified type
    296                                         inQualifiedType = true;
    297                                         mangleName += Encoding::qualifiedTypeStart;
    298                                 }
    299                                 maybeAccept( qualType->parent, *visitor );
    300                                 maybeAccept( qualType->child, *visitor );
    301                                 if ( ! inqual ) {
    302                                         // E marks the end of a qualified type
    303                                         inQualifiedType = false;
    304                                         mangleName += Encoding::qualifiedTypeEnd;
    305                                 }
    306                         }
    307 
    308                         void Mangler_old::postvisit( const TypeDecl * decl ) {
    309                                 // TODO: is there any case where mangling a TypeDecl makes sense? If so, this code needs to be
    310                                 // fixed to ensure that two TypeDecls mangle to the same name when they are the same type and vice versa.
    311                                 // Note: The current scheme may already work correctly for this case, I have not thought about this deeply
    312                                 // and the case has not yet come up in practice. Alternatively, if not then this code can be removed
    313                                 // aside from the assert false.
    314                                 assertf( false, "Mangler_old should not visit typedecl: %s", toCString(decl));
    315                                 assertf( decl->kind < TypeDecl::NUMBER_OF_KINDS, "Unhandled type variable kind: %d", decl->kind );
    316                                 mangleName += Encoding::typeVariables[ decl->kind ] + std::to_string( decl->name.length() ) + decl->name;
    317                         }
    318 
    319                         __attribute__((unused)) void printVarMap( const std::map< std::string, std::pair< int, int > > &varMap, std::ostream &os ) {
    320                                 for ( std::map< std::string, std::pair< int, int > >::const_iterator i = varMap.begin(); i != varMap.end(); ++i ) {
    321                                         os << i->first << "(" << i->second.first << "/" << i->second.second << ")" << std::endl;
    322                                 } // for
    323                         }
    324 
    325                         void Mangler_old::printQualifiers( const Type * type ) {
    326                                 // skip if not including qualifiers
    327                                 if ( typeMode ) return;
    328                                 if ( ! type->forall.empty() ) {
    329                                         std::list< std::string > assertionNames;
    330                                         int dcount = 0, fcount = 0, vcount = 0, acount = 0;
    331                                         mangleName += Encoding::forall;
    332                                         for ( const TypeDecl * i : type->forall ) {
    333                                                 switch ( i->kind ) {
    334                                                   case TypeDecl::Dtype:
    335                                                         dcount++;
    336                                                         break;
    337                                                   case TypeDecl::Ftype:
    338                                                         fcount++;
    339                                                         break;
    340                                                   case TypeDecl::Ttype:
    341                                                         vcount++;
    342                                                         break;
    343                                                   default:
    344                                                         assertf( false, "unimplemented kind for type variable %s", SymTab::Mangler::Encoding::typeVariables[i->kind].c_str() );
    345                                                 } // switch
    346                                                 varNums[ i->name ] = std::make_pair( nextVarNum, (int)i->kind );
    347                                                 for ( const DeclarationWithType * assert : i->assertions ) {
    348                                                         PassVisitor<Mangler_old> sub_mangler(
    349                                                                 mangleOverridable, typeMode, mangleGenericParams, nextVarNum, varNums );
    350                                                         assert->accept( sub_mangler );
    351                                                         assertionNames.push_back( sub_mangler.pass.get_mangleName() );
    352                                                         acount++;
    353                                                 } // for
    354                                         } // for
    355                                         mangleName += std::to_string( dcount ) + "_" + std::to_string( fcount ) + "_" + std::to_string( vcount ) + "_" + std::to_string( acount ) + "_";
    356                                         for(const auto & a : assertionNames) mangleName += a;
    357 //                                      std::copy( assertionNames.begin(), assertionNames.end(), std::ostream_iterator< std::string >( mangleName, "" ) );
    358                                         mangleName += "_";
    359                                 } // if
    360                                 if ( ! inFunctionType ) {
    361                                         // these qualifiers do not distinguish the outermost type of a function parameter
    362                                         if ( type->get_const() ) {
    363                                                 mangleName += Encoding::qualifiers.at(Type::Const);
    364                                         } // if
    365                                         if ( type->get_volatile() ) {
    366                                                 mangleName += Encoding::qualifiers.at(Type::Volatile);
    367                                         } // if
    368                                         // Removed due to restrict not affecting function compatibility in GCC
    369                                         // if ( type->get_isRestrict() ) {
    370                                         //      mangleName += "E";
    371                                         // } // if
    372                                         if ( type->get_atomic() ) {
    373                                                 mangleName += Encoding::qualifiers.at(Type::Atomic);
    374                                         } // if
    375                                 }
    376                                 if ( type->get_mutex() ) {
    377                                         mangleName += Encoding::qualifiers.at(Type::Mutex);
    378                                 } // if
    379                                 if ( inFunctionType ) {
    380                                         // turn off inFunctionType so that types can be differentiated for nested qualifiers
    381                                         GuardValue( inFunctionType );
    382                                         inFunctionType = false;
    383                                 }
    384                         }
    385                 } // namespace
    386         } // namespace Mangler
    387 } // namespace SymTab
    38828
    38929namespace Mangle {
  • src/SymTab/Mangler.h

    r790d835 rc6b4432  
    2222
    2323#include "AST/Bitfield.hpp"
    24 #include "SynTree/SynTree.h"  // for Types
    25 #include "SynTree/Visitor.h"  // for Visitor, maybeAccept
    2624
    2725// https://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling
     
    3533        class Node;
    3634}
    37 namespace ResolvExpr {
    38         class TypeEnvironment;
    39 }
    4035
    4136namespace SymTab {
    4237        namespace Mangler {
    43                 /// Mangle syntax tree object; primary interface to clients
    44                 std::string mangle( const BaseSyntaxNode * decl, bool mangleOverridable = true, bool typeMode = false, bool mangleGenericParams = true );
    45 
    46                 /// Mangle a type name; secondary interface
    47                 std::string mangleType( const Type * ty );
    48                 /// Mangle ignoring generic type parameters
    49                 std::string mangleConcrete( const Type * ty );
    50 
    5138                namespace Encoding {
    5239                        extern const std::string manglePrefix;
  • src/SymTab/module.mk

    r790d835 rc6b4432  
    1616
    1717SRC_SYMTAB = \
    18         SymTab/Autogen.cc \
    19         SymTab/Autogen.h \
    2018        SymTab/FixFunction.cc \
    2119        SymTab/FixFunction.h \
    2220        SymTab/GenImplicitCall.cpp \
    2321        SymTab/GenImplicitCall.hpp \
    24         SymTab/Indexer.cc \
    25         SymTab/Indexer.h \
    2622        SymTab/Mangler.cc \
    2723        SymTab/ManglerCommon.cc \
    28         SymTab/Mangler.h \
    29         SymTab/ValidateType.cc \
    30         SymTab/ValidateType.h
     24        SymTab/Mangler.h
    3125
    32 SRC += $(SRC_SYMTAB) \
    33         SymTab/Validate.cc \
    34         SymTab/Validate.h
     26SRC += $(SRC_SYMTAB)
    3527
    3628SRCDEMANGLE += $(SRC_SYMTAB) \
  • src/Tuples/Explode.cc

    r790d835 rc6b4432  
    1515
    1616#include "Explode.h"
    17 #include <list>                  // for list
    1817
    1918#include "AST/Pass.hpp"          // for Pass
    20 #include "SynTree/Mutator.h"     // for Mutator
    21 #include "Common/PassVisitor.h"  // for PassVisitor
    2219
    2320namespace Tuples {
    24         namespace {
    25                 // remove one level of reference from a reference type -- may be useful elsewhere.
    26                 Type * getReferenceBase( Type * t ) {
    27                         if ( ReferenceType * refType = dynamic_cast<ReferenceType *>( t ) ) {
    28                                 return refType->get_base();
    29                         } else {
    30                                 // for the moment, I want to know immediately if a non-reference type is ever passed in here.
    31                                 assertf( false, "getReferenceBase for non-ref: %s", toString( refType ).c_str() );
    32                                 return nullptr;
    33                         }
    34                 }
    35 
    36                 struct CastExploder {
    37                         bool castAdded = false;
    38                         bool foundUniqueExpr = false;
    39                         Expression * applyCast( Expression * expr, bool first = true ) {
    40                                 if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ){
    41                                         foundUniqueExpr = true;
    42                                         std::list< Expression * > exprs;
    43                                         for ( Expression *& expr : tupleExpr->get_exprs() ) {
    44                                                 // move cast into tuple exprs
    45                                                 exprs.push_back( applyCast( expr, false ) );
    46                                         }
    47                                         // want the top-level expression to be cast to reference type, but not nested
    48                                         // tuple expressions
    49                                         if ( first ) {
    50                                                 castAdded = true;
    51                                                 Expression * tupleExpr = new TupleExpr( exprs );
    52                                                 return new CastExpr( tupleExpr, new ReferenceType( Type::Qualifiers(), tupleExpr->result->clone() ) );
    53                                         } else {
    54                                                 return new TupleExpr( exprs );
    55                                         }
    56                                 }
    57                                 if ( dynamic_cast<ReferenceType*>( expr->result ) ) {
    58                                         // don't need to cast reference type to another reference type
    59                                         return expr->clone();
    60                                 } else {
    61                                         // anything else should be cast to reference as normal
    62                                         castAdded = true;
    63                                         return new CastExpr( expr->clone(), new ReferenceType( Type::Qualifiers(), expr->result->clone() ) );
    64                                 }
    65                         }
    66 
    67                         Expression * postmutate( UniqueExpr * uniqueExpr ) {
    68                                 // move cast into unique expr so that the unique expr has type T& rather than
    69                                 // type T. In particular, this transformation helps with generating the
    70                                 // correct code for reference-cast member tuple expressions, since the result
    71                                 // should now be a tuple of references rather than a reference to a tuple.
    72                                 // Still, this code is a bit awkward, and could use some improvement.
    73                                 UniqueExpr * newUniqueExpr = new UniqueExpr( applyCast( uniqueExpr->get_expr() ), uniqueExpr->get_id() );
    74                                 delete uniqueExpr;
    75                                 if ( castAdded ) {
    76                                         // if a cast was added by applyCast, then unique expr now has one more layer of reference
    77                                         // than it had coming into this function. To ensure types still match correctly, need to cast
    78                                         //  to reference base so that outer expressions are still correct.
    79                                         castAdded = false;
    80                                         Type * toType = getReferenceBase( newUniqueExpr->result );
    81                                         return new CastExpr( newUniqueExpr, toType->clone() );
    82                                 }
    83                                 return newUniqueExpr;
    84                         }
    85 
    86 
    87                         Expression * postmutate( TupleIndexExpr * tupleExpr ) {
    88                                 // tuple index expr needs to be rebuilt to ensure that the type of the
    89                                 // field is consistent with the type of the tuple expr, since the field
    90                                 // may have changed from type T to T&.
    91                                 Expression * expr = tupleExpr->get_tuple();
    92                                 tupleExpr->set_tuple( nullptr );
    93                                 TupleIndexExpr * ret = new TupleIndexExpr( expr, tupleExpr->get_index() );
    94                                 delete tupleExpr;
    95                                 return ret;
    96                         }
    97                 };
    98         } // namespace
    99 
    100         Expression * distributeReference( Expression * expr ) {
    101                 PassVisitor<CastExploder> exploder;
    102                 expr = expr->acceptMutator( exploder );
    103                 if ( ! exploder.pass.foundUniqueExpr ) {
    104                         // if a UniqueExpr was found, then the cast has already been added inside the UniqueExpr as appropriate
    105                         expr = new CastExpr( expr, new ReferenceType( Type::Qualifiers(), expr->result->clone() ) );
    106                 }
    107                 return expr;
    108         }
    10921
    11022namespace {
  • src/Tuples/Explode.h

    r790d835 rc6b4432  
    2020
    2121#include "AST/Expr.hpp"
    22 #include "ResolvExpr/Alternative.h"     // for Alternative, AltList
    2322#include "ResolvExpr/Candidate.hpp"     // for Candidate, CandidateList
    24 #include "ResolvExpr/ExplodedActual.h"  // for ExplodedActual
    2523#include "ResolvExpr/ExplodedArg.hpp"   // for ExplodedArg
    26 #include "SynTree/Expression.h"         // for Expression, UniqueExpr, AddressExpr
    27 #include "SynTree/Type.h"               // for TupleType, Type
    2824#include "Tuples.h"                     // for maybeImpure
    2925
     
    3228}
    3329
    34 namespace SymTab {
    35 class Indexer;
    36 }  // namespace SymTab
    37 
    3830namespace Tuples {
    39         Expression * distributeReference( Expression * );
    40 
    41         static inline CastExpr * isReferenceCast( Expression * expr ) {
    42                 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    43                         if ( dynamic_cast< ReferenceType * >( castExpr->result ) ) {
    44                                 return castExpr;
    45                         }
    46                 }
    47                 return nullptr;
    48         }
    49 
    50         /// Append alternative to an OutputIterator of Alternatives
    51         template<typename OutputIterator>
    52         void append( OutputIterator out, Expression* expr, const ResolvExpr::TypeEnvironment& env,
    53                         const ResolvExpr::OpenVarSet& openVars, const ResolvExpr::AssertionList& need,
    54                         const ResolvExpr::Cost& cost, const ResolvExpr::Cost& cvtCost ) {
    55                 *out++ = ResolvExpr::Alternative{ expr, env, openVars, need, cost, cvtCost };
    56         }
    57 
    58         /// Append alternative to an ExplodedActual
    59         static inline void append( ResolvExpr::ExplodedActual& ea, Expression* expr,
    60                         const ResolvExpr::TypeEnvironment&, const ResolvExpr::OpenVarSet&,
    61                         const ResolvExpr::AssertionList&, const ResolvExpr::Cost&, const ResolvExpr::Cost& ) {
    62                 ea.exprs.emplace_back( expr );
    63                 /// xxx -- merge environment, openVars, need, cost?
    64         }
    65 
    66         /// helper function used by explode
    67         template< typename Output >
    68         void explodeUnique( Expression * expr, const ResolvExpr::Alternative & alt,
    69                         const SymTab::Indexer & indexer, Output&& out, bool isTupleAssign ) {
    70                 if ( isTupleAssign ) {
    71                         // tuple assignment needs CastExprs to be recursively exploded to easily get at all of the components
    72                         if ( CastExpr * castExpr = isReferenceCast( expr ) ) {
    73                                 ResolvExpr::AltList alts;
    74                                 explodeUnique(
    75                                         castExpr->get_arg(), alt, indexer, back_inserter( alts ), isTupleAssign );
    76                                 for ( ResolvExpr::Alternative & alt : alts ) {
    77                                         // distribute reference cast over all components
    78                                         append( std::forward<Output>(out), distributeReference( alt.release_expr() ),
    79                                                 alt.env, alt.openVars, alt.need, alt.cost, alt.cvtCost );
    80                                 }
    81                                 // in tuple assignment, still need to handle the other cases, but only if not already handled here (don't want to output too many alternatives)
    82                                 return;
    83                         }
    84                 }
    85                 Type * res = expr->get_result()->stripReferences();
    86                 if ( TupleType * tupleType = dynamic_cast< TupleType * > ( res ) ) {
    87                         if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * >( expr ) ) {
    88                                 // can open tuple expr and dump its exploded components
    89                                 for ( Expression * expr : tupleExpr->get_exprs() ) {
    90                                         explodeUnique( expr, alt, indexer, std::forward<Output>(out), isTupleAssign );
    91                                 }
    92                         } else {
    93                                 // tuple type, but not tuple expr - recursively index into its components.
    94                                 // if expr type is reference, convert to value type
    95                                 Expression * arg = expr->clone();
    96                                 if ( Tuples::maybeImpureIgnoreUnique( arg ) ) {
    97                                         // expressions which may contain side effects require a single unique instance of the expression.
    98                                         arg = new UniqueExpr( arg );
    99                                 }
    100                                 // cast reference to value type to facilitate further explosion
    101                                 if ( dynamic_cast<ReferenceType *>( arg->get_result() ) ) {
    102                                         arg = new CastExpr( arg, tupleType->clone() );
    103                                 }
    104                                 for ( unsigned int i = 0; i < tupleType->size(); i++ ) {
    105                                         TupleIndexExpr * idx = new TupleIndexExpr( arg->clone(), i );
    106                                         explodeUnique( idx, alt, indexer, std::forward<Output>(out), isTupleAssign );
    107                                         delete idx;
    108                                 }
    109                                 delete arg;
    110                         }
    111                 } else {
    112                         // atomic (non-tuple) type - output a clone of the expression in a new alternative
    113                         append( std::forward<Output>(out), expr->clone(), alt.env, alt.openVars, alt.need,
    114                                 alt.cost, alt.cvtCost );
    115                 }
    116         }
    117 
    118         /// expands a tuple-valued alternative into multiple alternatives, each with a non-tuple-type
    119         template< typename Output >
    120         void explode( const ResolvExpr::Alternative &alt, const SymTab::Indexer & indexer,
    121                         Output&& out, bool isTupleAssign = false ) {
    122                 explodeUnique( alt.expr, alt, indexer, std::forward<Output>(out), isTupleAssign );
    123         }
    124 
    125         // explode list of alternatives
    126         template< typename AltIterator, typename Output >
    127         void explode( AltIterator altBegin, AltIterator altEnd, const SymTab::Indexer & indexer,
    128                         Output&& out, bool isTupleAssign = false ) {
    129                 for ( ; altBegin != altEnd; ++altBegin ) {
    130                         explode( *altBegin, indexer, std::forward<Output>(out), isTupleAssign );
    131                 }
    132         }
    133 
    134         template< typename Output >
    135         void explode( const ResolvExpr::AltList & alts, const SymTab::Indexer & indexer, Output&& out,
    136                         bool isTupleAssign = false ) {
    137                 explode( alts.begin(), alts.end(), indexer, std::forward<Output>(out), isTupleAssign );
    138         }
    13931
    14032const ast::Expr * distributeReference( const ast::Expr * );
  • src/Tuples/TupleAssignment.cc

    r790d835 rc6b4432  
    2828#include "AST/TypeEnvironment.hpp"
    2929#include "CodeGen/OperatorTable.h"
    30 #include "Common/PassVisitor.h"
    3130#include "Common/UniqueName.h"             // for UniqueName
    3231#include "Common/utility.h"                // for splice, zipWith
     
    3433#include "InitTweak/GenInit.h"             // for genCtorInit
    3534#include "InitTweak/InitTweak.h"           // for getPointerBase, isAssignment
    36 #include "ResolvExpr/Alternative.h"        // for AltList, Alternative
    37 #include "ResolvExpr/AlternativeFinder.h"  // for AlternativeFinder, simpleC...
    3835#include "ResolvExpr/Cost.h"               // for Cost
    3936#include "ResolvExpr/Resolver.h"           // for resolveCtorInit
    40 #include "ResolvExpr/TypeEnvironment.h"    // for TypeEnvironment
    4137#include "ResolvExpr/typeops.h"            // for combos
    42 #include "SynTree/LinkageSpec.h"           // for Cforall
    43 #include "SynTree/Declaration.h"           // for ObjectDecl
    44 #include "SynTree/Expression.h"            // for Expression, CastExpr, Name...
    45 #include "SynTree/Initializer.h"           // for ConstructorInit, SingleInit
    46 #include "SynTree/Statement.h"             // for ExprStmt
    47 #include "SynTree/Type.h"                  // for Type, Type::Qualifiers
    48 #include "SynTree/TypeSubstitution.h"      // for TypeSubstitution
    49 #include "SynTree/Visitor.h"               // for Visitor
    5038
    5139#if 0
     
    5644
    5745namespace Tuples {
    58         class TupleAssignSpotter_old {
    59           public:
    60                 // dispatcher for Tuple (multiple and mass) assignment operations
    61                 TupleAssignSpotter_old( ResolvExpr::AlternativeFinder & );
    62                 void spot( UntypedExpr * expr, std::vector<ResolvExpr::AlternativeFinder> &args );
    63 
    64           private:
    65                 void match();
    66 
    67                 struct Matcher {
    68                   public:
    69                         Matcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs,
    70                                 const ResolvExpr::AltList& rhs );
    71                         virtual ~Matcher() {}
    72 
    73                         virtual void match( std::list< Expression * > &out ) = 0;
    74                         ObjectDecl * newObject( UniqueName & namer, Expression * expr );
    75 
    76                         void combineState( const ResolvExpr::Alternative& alt ) {
    77                                 compositeEnv.simpleCombine( alt.env );
    78                                 ResolvExpr::mergeOpenVars( openVars, alt.openVars );
    79                                 cloneAll( alt.need, need );
    80                         }
    81 
    82                         void combineState( const ResolvExpr::AltList& alts ) {
    83                                 for ( const ResolvExpr::Alternative& alt : alts ) { combineState( alt ); }
    84                         }
    85 
    86                         ResolvExpr::AltList lhs, rhs;
    87                         TupleAssignSpotter_old &spotter;
    88                         ResolvExpr::Cost baseCost;
    89                         std::list< ObjectDecl * > tmpDecls;
    90                         ResolvExpr::TypeEnvironment compositeEnv;
    91                         ResolvExpr::OpenVarSet openVars;
    92                         ResolvExpr::AssertionSet need;
    93                 };
    94 
    95                 struct MassAssignMatcher : public Matcher {
    96                   public:
    97                         MassAssignMatcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs,
    98                                 const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {}
    99                         virtual void match( std::list< Expression * > &out );
    100                 };
    101 
    102                 struct MultipleAssignMatcher : public Matcher {
    103                   public:
    104                         MultipleAssignMatcher( TupleAssignSpotter_old &spotter, const ResolvExpr::AltList& lhs,
    105                                 const ResolvExpr::AltList& rhs ) : Matcher(spotter, lhs, rhs) {}
    106                         virtual void match( std::list< Expression * > &out );
    107                 };
    108 
    109                 ResolvExpr::AlternativeFinder &currentFinder;
    110                 std::string fname;
    111                 std::unique_ptr< Matcher > matcher;
    112         };
    113 
    114         /// true if expr is an expression of tuple type
    115         bool isTuple( Expression *expr ) {
    116                 if ( ! expr ) return false;
    117                 assert( expr->result );
    118                 return dynamic_cast< TupleType * >( expr->get_result()->stripReferences() );
    119         }
    120 
    121         template< typename AltIter >
    122         bool isMultAssign( AltIter begin, AltIter end ) {
    123                 // multiple assignment if more than one alternative in the range or if
    124                 // the alternative is a tuple
    125                 if ( begin == end ) return false;
    126                 if ( isTuple( begin->expr ) ) return true;
    127                 return ++begin != end;
    128         }
    129 
    130         bool refToTuple( Expression *expr ) {
    131                 assert( expr->get_result() );
    132                 // also check for function returning tuple of reference types
    133                 if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) {
    134                         return refToTuple( castExpr->get_arg() );
    135                 } else {
    136                         return isTuple( expr );
    137                 }
    138                 return false;
    139         }
    140 
    141         void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * expr,
    142                                 std::vector<ResolvExpr::AlternativeFinder> &args ) {
    143                 TupleAssignSpotter_old spotter( currentFinder );
    144                 spotter.spot( expr, args );
    145         }
    146 
    147         TupleAssignSpotter_old::TupleAssignSpotter_old( ResolvExpr::AlternativeFinder &f )
    148                 : currentFinder(f) {}
    149 
    150         void TupleAssignSpotter_old::spot( UntypedExpr * expr,
    151                         std::vector<ResolvExpr::AlternativeFinder> &args ) {
    152                 if (  NameExpr *op = dynamic_cast< NameExpr * >(expr->get_function()) ) {
    153                         if ( CodeGen::isCtorDtorAssign( op->get_name() ) ) {
    154                                 fname = op->get_name();
    155 
    156                                 // AlternativeFinder will naturally handle this case case, if it's legal
    157                                 if ( args.size() == 0 ) return;
    158 
    159                                 // if an assignment only takes 1 argument, that's odd, but maybe someone wrote
    160                                 // the function, in which case AlternativeFinder will handle it normally
    161                                 if ( args.size() == 1 && CodeGen::isAssignment( fname ) ) return;
    162 
    163                                 // look over all possible left-hand-sides
    164                                 for ( ResolvExpr::Alternative& lhsAlt : args[0] ) {
    165                                         // skip non-tuple LHS
    166                                         if ( ! refToTuple(lhsAlt.expr) ) continue;
    167 
    168                                         // explode is aware of casts - ensure every LHS expression is sent into explode
    169                                         // with a reference cast
    170                                         // xxx - this seems to change the alternatives before the normal
    171                                         //  AlternativeFinder flow; maybe this is desired?
    172                                         if ( ! dynamic_cast<CastExpr*>( lhsAlt.expr ) ) {
    173                                                 lhsAlt.expr = new CastExpr( lhsAlt.expr,
    174                                                                 new ReferenceType( Type::Qualifiers(),
    175                                                                         lhsAlt.expr->result->clone() ) );
    176                                         }
    177 
    178                                         // explode the LHS so that each field of a tuple-valued-expr is assigned
    179                                         ResolvExpr::AltList lhs;
    180                                         explode( lhsAlt, currentFinder.get_indexer(), back_inserter(lhs), true );
    181                                         for ( ResolvExpr::Alternative& alt : lhs ) {
    182                                                 // each LHS value must be a reference - some come in with a cast expression,
    183                                                 // if not just cast to reference here
    184                                                 if ( ! dynamic_cast<ReferenceType*>( alt.expr->get_result() ) ) {
    185                                                         alt.expr = new CastExpr( alt.expr,
    186                                                                 new ReferenceType( Type::Qualifiers(),
    187                                                                         alt.expr->get_result()->clone() ) );
    188                                                 }
    189                                         }
    190 
    191                                         if ( args.size() == 1 ) {
    192                                                 // mass default-initialization/destruction
    193                                                 ResolvExpr::AltList rhs{};
    194                                                 matcher.reset( new MassAssignMatcher( *this, lhs, rhs ) );
    195                                                 match();
    196                                         } else if ( args.size() > 2 ) {
    197                                                 // expand all possible RHS possibilities
    198                                                 // TODO build iterative version of this instead of using combos
    199                                                 std::vector< ResolvExpr::AltList > rhsAlts;
    200                                                 combos( std::next(args.begin(), 1), args.end(),
    201                                                         std::back_inserter( rhsAlts ) );
    202                                                 for ( const ResolvExpr::AltList& rhsAlt : rhsAlts ) {
    203                                                         // multiple assignment
    204                                                         ResolvExpr::AltList rhs;
    205                                                         explode( rhsAlt, currentFinder.get_indexer(),
    206                                                                 std::back_inserter(rhs), true );
    207                                                         matcher.reset( new MultipleAssignMatcher( *this, lhs, rhs ) );
    208                                                         match();
    209                                                 }
    210                                         } else {
    211                                                 for ( const ResolvExpr::Alternative& rhsAlt : args[1] ) {
    212                                                         ResolvExpr::AltList rhs;
    213                                                         if ( isTuple(rhsAlt.expr) ) {
    214                                                                 // multiple assignment
    215                                                                 explode( rhsAlt, currentFinder.get_indexer(),
    216                                                                         std::back_inserter(rhs), true );
    217                                                                 matcher.reset( new MultipleAssignMatcher( *this, lhs, rhs ) );
    218                                                         } else {
    219                                                                 // mass assignment
    220                                                                 rhs.push_back( rhsAlt );
    221                                                                 matcher.reset( new MassAssignMatcher( *this, lhs, rhs ) );
    222                                                         }
    223                                                         match();
    224                                                 }
    225                                         }
    226                                 }
    227                         }
    228                 }
    229         }
    230 
    231         void TupleAssignSpotter_old::match() {
    232                 assert ( matcher != 0 );
    233 
    234                 std::list< Expression * > new_assigns;
    235                 matcher->match( new_assigns );
    236 
    237                 if ( ! matcher->lhs.empty() || ! matcher->rhs.empty() ) {
    238                         // if both lhs and rhs are empty then this is the empty tuple case, wherein it's okay for new_assigns to be empty.
    239                         // if not the empty tuple case, return early so that no new alternatives are generated.
    240                         if ( new_assigns.empty() ) return;
    241                 }
    242                 ResolvExpr::AltList current;
    243                 // now resolve new assignments
    244                 for ( std::list< Expression * >::iterator i = new_assigns.begin();
    245                                 i != new_assigns.end(); ++i ) {
    246                         PRINT(
    247                                 std::cerr << "== resolving tuple assign ==" << std::endl;
    248                                 std::cerr << *i << std::endl;
    249                         )
    250 
    251                         ResolvExpr::AlternativeFinder finder{ currentFinder.get_indexer(),
    252                                 matcher->compositeEnv };
    253 
    254                         try {
    255                                 finder.findWithAdjustment(*i);
    256                         } catch (...) {
    257                                 return; // no match should not mean failure, it just means this particular tuple assignment isn't valid
    258                         }
    259                         // prune expressions that don't coincide with
    260                         ResolvExpr::AltList alts = finder.get_alternatives();
    261                         assert( alts.size() == 1 );
    262                         assert( alts.front().expr != 0 );
    263                         current.push_back( alts.front() );
    264                 }
    265 
    266                 // extract expressions from the assignment alternatives to produce a list of assignments
    267                 // that together form a single alternative
    268                 std::list< Expression *> solved_assigns;
    269                 for ( ResolvExpr::Alternative & alt : current ) {
    270                         solved_assigns.push_back( alt.expr->clone() );
    271                         matcher->combineState( alt );
    272                 }
    273 
    274                 // xxx -- was push_front
    275                 currentFinder.get_alternatives().push_back( ResolvExpr::Alternative{
    276                         new TupleAssignExpr{ solved_assigns, matcher->tmpDecls }, matcher->compositeEnv,
    277                         matcher->openVars,
    278                         ResolvExpr::AssertionList( matcher->need.begin(), matcher->need.end() ),
    279                         ResolvExpr::sumCost( current ) + matcher->baseCost } );
    280         }
    281 
    282         TupleAssignSpotter_old::Matcher::Matcher( TupleAssignSpotter_old &spotter,
    283                 const ResolvExpr::AltList &lhs, const ResolvExpr::AltList &rhs )
    284         : lhs(lhs), rhs(rhs), spotter(spotter),
    285           baseCost( ResolvExpr::sumCost( lhs ) + ResolvExpr::sumCost( rhs ) ) {
    286                 combineState( lhs );
    287                 combineState( rhs );
    288         }
    289 
    290         UntypedExpr * createFunc( const std::string &fname, ObjectDecl *left, ObjectDecl *right ) {
    291                 assert( left );
    292                 std::list< Expression * > args;
    293                 args.push_back( new VariableExpr( left ) );
    294                 // args.push_back( new AddressExpr( new VariableExpr( left ) ) );
    295                 if ( right ) args.push_back( new VariableExpr( right ) );
    296                 if ( left->type->referenceDepth() > 1 && CodeGen::isConstructor( fname ) ) {
    297                         args.front() = new AddressExpr( args.front() );
    298                         if ( right ) args.back() = new AddressExpr( args.back() );
    299                         return new UntypedExpr( new NameExpr( "?=?" ), args );
    300                 } else {
    301                         return new UntypedExpr( new NameExpr( fname ), args );
    302                 }
    303         }
    304 
    305         // removes environments from subexpressions within statement exprs, which could throw off later passes like those in Box which rely on PolyMutator, and adds the bindings to the compositeEnv
    306         // xxx - maybe this should happen in alternative finder for every StmtExpr?
    307         struct EnvRemover {
    308                 void previsit( ExprStmt * stmt ) {
    309                         assert( compositeEnv );
    310                         if ( stmt->expr->env ) {
    311                                 compositeEnv->add( *stmt->expr->env );
    312                                 delete stmt->expr->env;
    313                                 stmt->expr->env = nullptr;
    314                         }
    315                 }
    316 
    317                 ResolvExpr::TypeEnvironment * compositeEnv = nullptr;
    318         };
    319 
    320         ObjectDecl * TupleAssignSpotter_old::Matcher::newObject( UniqueName & namer, Expression * expr ) {
    321                 assert( expr->result && ! expr->get_result()->isVoid() );
    322                 ObjectDecl * ret = new ObjectDecl( namer.newName(), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, expr->result->clone(), new SingleInit( expr->clone() ) );
    323                 // if expression type is a reference, don't need to construct anything, a simple initializer is sufficient.
    324                 if ( ! dynamic_cast< ReferenceType * >( expr->result ) ) {
    325                         ConstructorInit * ctorInit = InitTweak::genCtorInit( ret );
    326                         ret->init = ctorInit;
    327                         ResolvExpr::resolveCtorInit( ctorInit, spotter.currentFinder.get_indexer() ); // resolve ctor/dtors for the new object
    328                         PassVisitor<EnvRemover> rm; // remove environments from subexpressions of StmtExprs
    329                         rm.pass.compositeEnv = &compositeEnv;
    330                         ctorInit->accept( rm );
    331                 }
    332                 PRINT( std::cerr << "new object: " << ret << std::endl; )
    333                 return ret;
    334         }
    335 
    336         void TupleAssignSpotter_old::MassAssignMatcher::match( std::list< Expression * > &out ) {
    337                 static UniqueName lhsNamer( "__massassign_L" );
    338                 static UniqueName rhsNamer( "__massassign_R" );
    339                 // empty tuple case falls into this matcher, hence the second part of the assert
    340                 assert( (! lhs.empty() && rhs.size() <= 1) || (lhs.empty() && rhs.empty()) );
    341 
    342                 // xxx - may need to split this up into multiple declarations, because potential conversion to references
    343                 //  probably should not reference local variable - see MultipleAssignMatcher::match
    344                 ObjectDecl * rtmp = rhs.size() == 1 ? newObject( rhsNamer, rhs.front().expr ) : nullptr;
    345                 for ( ResolvExpr::Alternative & lhsAlt : lhs ) {
    346                         // create a temporary object for each value in the lhs and create a call involving the rhs
    347                         ObjectDecl * ltmp = newObject( lhsNamer, lhsAlt.expr );
    348                         out.push_back( createFunc( spotter.fname, ltmp, rtmp ) );
    349                         tmpDecls.push_back( ltmp );
    350                 }
    351                 if ( rtmp ) tmpDecls.push_back( rtmp );
    352         }
    353 
    354         void TupleAssignSpotter_old::MultipleAssignMatcher::match( std::list< Expression * > &out ) {
    355                 static UniqueName lhsNamer( "__multassign_L" );
    356                 static UniqueName rhsNamer( "__multassign_R" );
    357 
    358                 if ( lhs.size() == rhs.size() ) {
    359                         // produce a new temporary object for each value in the lhs and rhs and pairwise create the calls
    360                         std::list< ObjectDecl * > ltmp;
    361                         std::list< ObjectDecl * > rtmp;
    362                         for ( auto p : group_iterate( lhs, rhs ) ) {
    363                                 ResolvExpr::Alternative & lhsAlt = std::get<0>(p);
    364                                 ResolvExpr::Alternative & rhsAlt = std::get<1>(p);
    365                                 // convert RHS to LHS type minus one reference -- important for the case where LHS is && and RHS is lvalue, etc.
    366                                 ReferenceType * lhsType = strict_dynamic_cast<ReferenceType *>( lhsAlt.expr->result );
    367                                 rhsAlt.expr = new CastExpr( rhsAlt.expr, lhsType->base->clone() );
    368                                 ObjectDecl * lobj = newObject( lhsNamer, lhsAlt.expr );
    369                                 ObjectDecl * robj = newObject( rhsNamer, rhsAlt.expr );
    370                                 out.push_back( createFunc(spotter.fname, lobj, robj) );
    371                                 ltmp.push_back( lobj );
    372                                 rtmp.push_back( robj );
    373 
    374                                 // resolve the cast expression so that rhsAlt return type is bound by the cast type as needed, and transfer the resulting environment
    375                                 ResolvExpr::AlternativeFinder finder{ spotter.currentFinder.get_indexer(), compositeEnv };
    376                                 finder.findWithAdjustment( rhsAlt.expr );
    377                                 assert( finder.get_alternatives().size() == 1 );
    378                                 compositeEnv = std::move( finder.get_alternatives().front().env );
    379                         }
    380                         tmpDecls.splice( tmpDecls.end(), ltmp );
    381                         tmpDecls.splice( tmpDecls.end(), rtmp );
    382                 }
    383         }
    38446
    38547namespace {
  • src/Tuples/TupleExpansion.cc

    r790d835 rc6b4432  
    2323#include "AST/Node.hpp"
    2424#include "AST/Type.hpp"
    25 #include "Common/PassVisitor.h"   // for PassVisitor, WithDeclsToAdd, WithGu...
    2625#include "Common/ScopedMap.h"     // for ScopedMap
    2726#include "Common/utility.h"       // for CodeLocation
    2827#include "InitTweak/InitTweak.h"  // for getFunction
    29 #include "SynTree/LinkageSpec.h"  // for Spec, C, Intrinsic
    30 #include "SynTree/Constant.h"     // for Constant
    31 #include "SynTree/Declaration.h"  // for StructDecl, DeclarationWithType
    32 #include "SynTree/Expression.h"   // for UntypedMemberExpr, Expression, Uniq...
    33 #include "SynTree/Label.h"        // for operator==, Label
    34 #include "SynTree/Mutator.h"      // for Mutator
    35 #include "SynTree/Type.h"         // for Type, Type::Qualifiers, TupleType
    36 #include "SynTree/Visitor.h"      // for Visitor
    3728#include "Tuples.h"
    3829
    39 class CompoundStmt;
    40 class TypeSubstitution;
     30namespace Tuples {
    4131
    42 namespace Tuples {
    43         namespace {
    44                 struct MemberTupleExpander final : public WithShortCircuiting, public WithVisitorRef<MemberTupleExpander> {
    45                         void premutate( UntypedMemberExpr * ) { visit_children = false; }
    46                         Expression * postmutate( UntypedMemberExpr * memberExpr );
    47                 };
    48 
    49                 struct UniqueExprExpander final : public WithDeclsToAdd {
    50                         Expression * postmutate( UniqueExpr * unqExpr );
    51 
    52                         std::map< int, Expression * > decls; // not vector, because order added may not be increasing order
    53 
    54                         ~UniqueExprExpander() {
    55                                 for ( std::pair<const int, Expression *> & p : decls ) {
    56                                         delete p.second;
    57                                 }
    58                         }
    59                 };
    60 
    61                 struct TupleAssignExpander {
    62                         Expression * postmutate( TupleAssignExpr * tupleExpr );
    63                 };
    64 
    65                 struct TupleTypeReplacer : public WithDeclsToAdd, public WithGuards, public WithConstTypeSubstitution {
    66                         Type * postmutate( TupleType * tupleType );
    67 
    68                         void premutate( CompoundStmt * ) {
    69                                 GuardScope( typeMap );
    70                         }
    71                   private:
    72                         ScopedMap< int, StructDecl * > typeMap;
    73                 };
    74 
    75                 struct TupleIndexExpander {
    76                         Expression * postmutate( TupleIndexExpr * tupleExpr );
    77                 };
    78 
    79                 struct TupleExprExpander final {
    80                         Expression * postmutate( TupleExpr * tupleExpr );
    81                 };
    82         }
    83 
    84         void expandMemberTuples( std::list< Declaration * > & translationUnit ) {
    85                 PassVisitor<MemberTupleExpander> expander;
    86                 mutateAll( translationUnit, expander );
    87         }
    88 
    89         void expandUniqueExpr( std::list< Declaration * > & translationUnit ) {
    90                 PassVisitor<UniqueExprExpander> unqExpander;
    91                 mutateAll( translationUnit, unqExpander );
    92         }
    93 
    94         void expandTuples( std::list< Declaration * > & translationUnit ) {
    95                 PassVisitor<TupleAssignExpander> assnExpander;
    96                 mutateAll( translationUnit, assnExpander );
    97 
    98                 PassVisitor<TupleTypeReplacer> replacer;
    99                 mutateAll( translationUnit, replacer );
    100 
    101                 PassVisitor<TupleIndexExpander> idxExpander;
    102                 mutateAll( translationUnit, idxExpander );
    103 
    104                 PassVisitor<TupleExprExpander> exprExpander;
    105                 mutateAll( translationUnit, exprExpander );
    106         }
    107 
    108         namespace {
    109                 /// given a expression representing the member and an expression representing the aggregate,
    110                 /// reconstructs a flattened UntypedMemberExpr with the right precedence
    111                 Expression * reconstructMemberExpr( Expression * member, Expression * aggr, CodeLocation & loc ) {
    112                         if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * >( member ) ) {
    113                                 // construct a new UntypedMemberExpr with the correct structure , and recursively
    114                                 // expand that member expression.
    115                                 PassVisitor<MemberTupleExpander> expander;
    116                                 UntypedMemberExpr * inner = new UntypedMemberExpr( memberExpr->aggregate, aggr->clone() );
    117                                 UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->member, inner );
    118                                 inner->location = newMemberExpr->location = loc;
    119                                 memberExpr->member = nullptr;
    120                                 memberExpr->aggregate = nullptr;
    121                                 delete memberExpr;
    122                                 return newMemberExpr->acceptMutator( expander );
    123                         } else {
    124                                 // not a member expression, so there is nothing to do but attach and return
    125                                 UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( member, aggr->clone() );
    126                                 newMemberExpr->location = loc;
    127                                 return newMemberExpr;
    128                         }
    129                 }
    130         }
    131 
    132         Expression * MemberTupleExpander::postmutate( UntypedMemberExpr * memberExpr ) {
    133                 if ( UntypedTupleExpr * tupleExpr = dynamic_cast< UntypedTupleExpr * > ( memberExpr->member ) ) {
    134                         Expression * aggr = memberExpr->aggregate->clone()->acceptMutator( *visitor );
    135                         // aggregate expressions which might be impure must be wrapped in unique expressions
    136                         if ( Tuples::maybeImpureIgnoreUnique( memberExpr->aggregate ) ) aggr = new UniqueExpr( aggr );
    137                         for ( Expression *& expr : tupleExpr->exprs ) {
    138                                 expr = reconstructMemberExpr( expr, aggr, memberExpr->location );
    139                                 expr->location = memberExpr->location;
    140                         }
    141                         delete aggr;
    142                         tupleExpr->location = memberExpr->location;
    143                         return tupleExpr;
    144                 } else {
    145                         // there may be a tuple expr buried in the aggregate
    146                         // xxx - this is a memory leak
    147                         UntypedMemberExpr * newMemberExpr = new UntypedMemberExpr( memberExpr->member->clone(), memberExpr->aggregate->acceptMutator( *visitor ) );
    148                         newMemberExpr->location = memberExpr->location;
    149                         return newMemberExpr;
    150                 }
    151         }
    152 
    153         Expression * UniqueExprExpander::postmutate( UniqueExpr * unqExpr ) {
    154                 const int id = unqExpr->get_id();
    155 
    156                 // on first time visiting a unique expr with a particular ID, generate the expression that replaces all UniqueExprs with that ID,
    157                 // and lookup on subsequent hits. This ensures that all unique exprs with the same ID reference the same variable.
    158                 if ( ! decls.count( id ) ) {
    159                         Expression * assignUnq;
    160                         Expression * var = unqExpr->get_var();
    161                         if ( unqExpr->get_object() ) {
    162                                 // an object was generated to represent this unique expression -- it should be added to the list of declarations now
    163                                 declsToAddBefore.push_back( unqExpr->get_object() );
    164                                 unqExpr->set_object( nullptr );
    165                                 // steal the expr from the unqExpr
    166                                 assignUnq = UntypedExpr::createAssign( unqExpr->get_var()->clone(), unqExpr->get_expr() );
    167                                 unqExpr->set_expr( nullptr );
    168                         } else {
    169                                 // steal the already generated assignment to var from the unqExpr - this has been generated by FixInit
    170                                 Expression * expr = unqExpr->get_expr();
    171                                 CommaExpr * commaExpr = strict_dynamic_cast< CommaExpr * >( expr );
    172                                 assignUnq = commaExpr->get_arg1();
    173                                 commaExpr->set_arg1( nullptr );
    174                         }
    175                         ObjectDecl * finished = new ObjectDecl( toString( "_unq", id, "_finished_" ), Type::StorageClasses(), LinkageSpec::Cforall, nullptr, new BasicType( Type::Qualifiers(), BasicType::Bool ),
    176                                                                                                         new SingleInit( new ConstantExpr( Constant::from_int( 0 ) ) ) );
    177                         declsToAddBefore.push_back( finished );
    178                         // (finished ? _unq_expr_N : (_unq_expr_N = <unqExpr->get_expr()>, finished = 1, _unq_expr_N))
    179                         // This pattern ensures that each unique expression is evaluated once, regardless of evaluation order of the generated C code.
    180                         Expression * assignFinished = UntypedExpr::createAssign( new VariableExpr(finished), new ConstantExpr( Constant::from_int( 1 ) ) );
    181                         ConditionalExpr * condExpr = new ConditionalExpr( new VariableExpr( finished ), var->clone(),
    182                                 new CommaExpr( new CommaExpr( assignUnq, assignFinished ), var->clone() ) );
    183                         condExpr->set_result( var->get_result()->clone() );
    184                         condExpr->set_env( maybeClone( unqExpr->get_env() ) );
    185                         decls[id] = condExpr;
    186                 }
    187                 delete unqExpr;
    188                 return decls[id]->clone();
    189         }
    190 
    191         Expression * TupleAssignExpander::postmutate( TupleAssignExpr * assnExpr ) {
    192                 StmtExpr * ret = assnExpr->get_stmtExpr();
    193                 assnExpr->set_stmtExpr( nullptr );
    194                 // move env to StmtExpr
    195                 ret->set_env( assnExpr->get_env() );
    196                 assnExpr->set_env( nullptr );
    197                 delete assnExpr;
    198                 return ret;
    199         }
    200 
    201         Type * TupleTypeReplacer::postmutate( TupleType * tupleType ) {
    202                 unsigned tupleSize = tupleType->size();
    203                 if ( ! typeMap.count( tupleSize ) ) {
    204                         // generate struct type to replace tuple type based on the number of components in the tuple
    205                         StructDecl * decl = new StructDecl( toString( "_tuple", tupleSize, "_" ) );
    206                         decl->location = tupleType->location;
    207                         decl->set_body( true );
    208                         for ( size_t i = 0; i < tupleSize; ++i ) {
    209                                 TypeDecl * tyParam = new TypeDecl( toString( "tuple_param_", tupleSize, "_", i ), Type::StorageClasses(), nullptr, TypeDecl::Dtype, true );
    210                                 decl->get_members().push_back( new ObjectDecl( toString("field_", i ), Type::StorageClasses(), LinkageSpec::C, nullptr, new TypeInstType( Type::Qualifiers(), tyParam->get_name(), tyParam ), nullptr ) );
    211                                 decl->get_parameters().push_back( tyParam );
    212                         }
    213                         if ( tupleSize == 0 ) {
    214                                 // empty structs are not standard C. Add a dummy field to empty tuples to silence warnings when a compound literal Tuple0 is created.
    215                                 decl->get_members().push_back( new ObjectDecl( "dummy", Type::StorageClasses(), LinkageSpec::C, nullptr, new BasicType( Type::Qualifiers(), BasicType::SignedInt ), nullptr ) );
    216                         }
    217                         typeMap[tupleSize] = decl;
    218                         declsToAddBefore.push_back( decl );
    219                 }
    220                 Type::Qualifiers qualifiers = tupleType->get_qualifiers();
    221 
    222                 StructDecl * decl = typeMap[tupleSize];
    223                 StructInstType * newType = new StructInstType( qualifiers, decl );
    224                 for ( auto p : group_iterate( tupleType->get_types(), decl->get_parameters() ) ) {
    225                         Type * t = std::get<0>(p);
    226                         newType->get_parameters().push_back( new TypeExpr( t->clone() ) );
    227                 }
    228                 delete tupleType;
    229                 return newType;
    230         }
    231 
    232         Expression * TupleIndexExpander::postmutate( TupleIndexExpr * tupleExpr ) {
    233                 Expression * tuple = tupleExpr->tuple;
    234                 assert( tuple );
    235                 tupleExpr->tuple = nullptr;
    236                 unsigned int idx = tupleExpr->index;
    237                 TypeSubstitution * env = tupleExpr->env;
    238                 tupleExpr->env = nullptr;
    239                 delete tupleExpr;
    240 
    241                 if ( TupleExpr * tupleExpr = dynamic_cast< TupleExpr * > ( tuple ) ) {
    242                         if ( ! maybeImpureIgnoreUnique( tupleExpr ) ) {
    243                                 // optimization: definitely pure tuple expr => can reduce to the only relevant component.
    244                                 assert( tupleExpr->exprs.size() > idx );
    245                                 Expression *& expr = *std::next(tupleExpr->exprs.begin(), idx);
    246                                 Expression * ret = expr;
    247                                 ret->env = env;
    248                                 expr = nullptr; // remove from list so it can safely be deleted
    249                                 delete tupleExpr;
    250                                 return ret;
    251                         }
    252                 }
    253 
    254                 StructInstType * type = strict_dynamic_cast< StructInstType * >( tuple->result );
    255                 StructDecl * structDecl = type->baseStruct;
    256                 assert( structDecl->members.size() > idx );
    257                 Declaration * member = *std::next(structDecl->members.begin(), idx);
    258                 MemberExpr * memExpr = new MemberExpr( strict_dynamic_cast< DeclarationWithType * >( member ), tuple );
    259                 memExpr->env = env;
    260                 return memExpr;
    261         }
    262 
    263         Expression * replaceTupleExpr( Type * result, const std::list< Expression * > & exprs, TypeSubstitution * env ) {
    264                 if ( result->isVoid() ) {
    265                         // void result - don't need to produce a value for cascading - just output a chain of comma exprs
    266                         assert( ! exprs.empty() );
    267                         std::list< Expression * >::const_iterator iter = exprs.begin();
    268                         Expression * expr = new CastExpr( *iter++ );
    269                         for ( ; iter != exprs.end(); ++iter ) {
    270                                 expr = new CommaExpr( expr, new CastExpr( *iter ) );
    271                         }
    272                         expr->set_env( env );
    273                         return expr;
    274                 } else {
    275                         // typed tuple expression - produce a compound literal which performs each of the expressions
    276                         // as a distinct part of its initializer - the produced compound literal may be used as part of
    277                         // another expression
    278                         std::list< Initializer * > inits;
    279                         for ( Expression * expr : exprs ) {
    280                                 inits.push_back( new SingleInit( expr ) );
    281                         }
    282                         Expression * expr = new CompoundLiteralExpr( result, new ListInit( inits ) );
    283                         expr->set_env( env );
    284                         return expr;
    285                 }
    286         }
    287 
    288         Expression * TupleExprExpander::postmutate( TupleExpr * tupleExpr ) {
    289                 Type * result = tupleExpr->get_result();
    290                 std::list< Expression * > exprs = tupleExpr->get_exprs();
    291                 assert( result );
    292                 TypeSubstitution * env = tupleExpr->get_env();
    293 
    294                 // remove data from shell and delete it
    295                 tupleExpr->set_result( nullptr );
    296                 tupleExpr->get_exprs().clear();
    297                 tupleExpr->set_env( nullptr );
    298                 delete tupleExpr;
    299 
    300                 return replaceTupleExpr( result, exprs, env );
    301         }
    302 
    303         Type * makeTupleType( const std::list< Expression * > & exprs ) {
    304                 // produce the TupleType which aggregates the types of the exprs
    305                 std::list< Type * > types;
    306                 Type::Qualifiers qualifiers( Type::Const | Type::Volatile | Type::Restrict | Type::Atomic | Type::Mutex );
    307                 for ( Expression * expr : exprs ) {
    308                         assert( expr->get_result() );
    309                         if ( expr->get_result()->isVoid() ) {
    310                                 // if the type of any expr is void, the type of the entire tuple is void
    311                                 return new VoidType( Type::Qualifiers() );
    312                         }
    313                         Type * type = expr->get_result()->clone();
    314                         types.push_back( type );
    315                         // the qualifiers on the tuple type are the qualifiers that exist on all component types
    316                         qualifiers &= type->get_qualifiers();
    317                 } // for
    318                 if ( exprs.empty() ) qualifiers = Type::Qualifiers();
    319                 return new TupleType( qualifiers, types );
    320         }
    32132        const ast::Type * makeTupleType( const std::vector<ast::ptr<ast::Expr>> & exprs ) {
    32233                // produce the TupleType which aggregates the types of the exprs
     
    34152        }
    34253
    343         TypeInstType * isTtype( Type * type ) {
    344                 if ( TypeInstType * inst = dynamic_cast< TypeInstType * >( type ) ) {
    345                         if ( inst->get_baseType() && inst->get_baseType()->get_kind() == TypeDecl::Ttype ) {
    346                                 return inst;
    347                         }
    348                 }
    349                 return nullptr;
    350         }
    351 
    352         const TypeInstType * isTtype( const Type * type ) {
    353                 if ( const TypeInstType * inst = dynamic_cast< const TypeInstType * >( type ) ) {
    354                         if ( inst->baseType && inst->baseType->kind == TypeDecl::Ttype ) {
    355                                 return inst;
    356                         }
    357                 }
    358                 return nullptr;
    359         }
    360 
    36154        const ast::TypeInstType * isTtype( const ast::Type * type ) {
    36255                if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( type ) ) {
  • src/Tuples/Tuples.cc

    r790d835 rc6b4432  
    1919#include "AST/Inspect.hpp"
    2020#include "AST/LinkageSpec.hpp"
    21 #include "Common/PassVisitor.h"
    2221#include "InitTweak/InitTweak.h"
    2322
     
    2524
    2625namespace {
    27         /// Checks if impurity (read: side-effects) may exist in a piece of code.
    28         /// Currently gives a very crude approximation, wherein any function
    29         /// call expression means the code may be impure.
    30         struct ImpurityDetector_old : public WithShortCircuiting {
    31                 bool const ignoreUnique;
    32                 bool maybeImpure;
    33 
    34                 ImpurityDetector_old( bool ignoreUnique ) :
    35                         ignoreUnique( ignoreUnique ), maybeImpure( false )
    36                 {}
    37 
    38                 void previsit( const ApplicationExpr * appExpr ) {
    39                         visit_children = false;
    40                         if ( const DeclarationWithType * function =
    41                                         InitTweak::getFunction( appExpr ) ) {
    42                                 if ( function->linkage == LinkageSpec::Intrinsic ) {
    43                                         if ( function->name == "*?" || function->name == "?[?]" ) {
    44                                                 // intrinsic dereference, subscript are pure,
    45                                                 // but need to recursively look for impurity
    46                                                 visit_children = true;
    47                                                 return;
    48                                         }
    49                                 }
    50                         }
    51                         maybeImpure = true;
    52                 }
    53 
    54                 void previsit( const UntypedExpr * ) {
    55                         maybeImpure = true;
    56                         visit_children = false;
    57                 }
    58 
    59                 void previsit( const UniqueExpr * ) {
    60                         if ( ignoreUnique ) {
    61                                 // bottom out at unique expression.
    62                                 // The existence of a unique expression doesn't change the purity of an expression.
    63                                 // That is, even if the wrapped expression is impure, the wrapper protects the rest of the expression.
    64                                 visit_children = false;
    65                                 return;
    66                         }
    67                 }
    68         };
    69 
    70         bool detectImpurity( const Expression * expr, bool ignoreUnique ) {
    71                 PassVisitor<ImpurityDetector_old> detector( ignoreUnique );
    72                 expr->accept( detector );
    73                 return detector.pass.maybeImpure;
    74         }
    7526
    7627        /// Determines if impurity (read: side-effects) may exist in a piece of code. Currently gives
     
    11061}
    11162
    112 bool maybeImpure( const Expression * expr ) {
    113         return detectImpurity( expr, false );
    114 }
    115 
    116 bool maybeImpureIgnoreUnique( const Expression * expr ) {
    117         return detectImpurity( expr, true );
    118 }
    119 
    12063} // namespace Tuples
    12164
  • src/Tuples/Tuples.h

    r790d835 rc6b4432  
    2121#include "AST/Fwd.hpp"
    2222#include "AST/Node.hpp"
    23 #include "SynTree/Expression.h"
    24 #include "SynTree/Declaration.h"
    25 #include "SynTree/Type.h"
    26 
    27 #include "ResolvExpr/AlternativeFinder.h"
    2823#include "ResolvExpr/CandidateFinder.hpp"
    2924
    3025namespace Tuples {
    3126        // TupleAssignment.cc
    32         void handleTupleAssignment( ResolvExpr::AlternativeFinder & currentFinder, UntypedExpr * assign,
    33                 std::vector< ResolvExpr::AlternativeFinder >& args );
    3427        void handleTupleAssignment(
    3528                ResolvExpr::CandidateFinder & finder, const ast::UntypedExpr * assign,
     
    3831        // TupleExpansion.cc
    3932        /// expands z.[a, b.[x, y], c] into [z.a, z.b.x, z.b.y, z.c], inserting UniqueExprs as appropriate
    40         void expandMemberTuples( std::list< Declaration * > & translationUnit );
    4133        void expandMemberTuples( ast::TranslationUnit & translationUnit );
    4234
    4335        /// replaces tuple-related elements, such as TupleType, TupleExpr, TupleAssignExpr, etc.
    44         void expandTuples( std::list< Declaration * > & translationUnit );
    4536        void expandTuples( ast::TranslationUnit & translaionUnit );
    4637
    4738        /// replaces UniqueExprs with a temporary variable and one call
    48         void expandUniqueExpr( std::list< Declaration * > & translationUnit );
    4939        void expandUniqueExpr( ast::TranslationUnit & translationUnit );
    5040
    5141        /// returns VoidType if any of the expressions have Voidtype, otherwise TupleType of the Expression result types
    52         Type * makeTupleType( const std::list< Expression * > & exprs );
    5342        const ast::Type * makeTupleType( const std::vector<ast::ptr<ast::Expr>> & exprs );
    5443
    5544        /// returns a TypeInstType if `type` is a ttype, nullptr otherwise
    56         TypeInstType * isTtype( Type * type );
    57         const TypeInstType * isTtype( const Type * type );
    5845        const ast::TypeInstType * isTtype( const ast::Type * type );
    5946
    6047        /// returns true if the expression may contain side-effects.
    61         bool maybeImpure( const Expression * expr );
    6248        bool maybeImpure( const ast::Expr * expr );
    6349
    6450        /// Returns true if the expression may contain side-effect,
    6551        /// ignoring the presence of unique expressions.
    66         bool maybeImpureIgnoreUnique( const Expression * expr );
    6752        bool maybeImpureIgnoreUnique( const ast::Expr * expr );
    6853} // namespace Tuples
  • src/Validate/FindSpecialDecls.h

    r790d835 rc6b4432  
    1616#pragma once
    1717
    18 #include <list>  // for list
    19 
    20 class Declaration;
    21 class FunctionDecl;
    22 class StructDecl;
    23 class Type;
    24 
    2518namespace ast {
    2619        class TranslationUnit;
     
    2821
    2922namespace Validate {
    30         /// size_t type - set when size_t typedef is seen. Useful in a few places,
    31         /// such as in determining array dimension type
    32         extern Type * SizeType;
    33 
    34         /// intrinsic dereference operator for unqualified types - set when *? function is seen in FindSpecialDeclarations.
    35         /// Useful for creating dereference ApplicationExprs without a full resolver pass.
    36         extern FunctionDecl * dereferenceOperator;
    37 
    38         /// special built-in functions and data structures necessary for destructor generation
    39         extern StructDecl * dtorStruct;
    40         extern FunctionDecl * dtorStructDestroy;
    41 
    42         /// find and remember some of the special declarations that are useful for generating code, so that they do not have to be discovered multiple times.
    43         void findSpecialDecls( std::list< Declaration * > & translationUnit );
    4423
    4524/// Find and remember some of the special declarations that are useful for
  • src/Validate/module.mk

    r790d835 rc6b4432  
    1616
    1717SRC_VALIDATE = \
    18         Validate/FindSpecialDecls.cc \
    1918        Validate/FindSpecialDecls.h
    2019
     
    3736        Validate/GenericParameter.cpp \
    3837        Validate/GenericParameter.hpp \
    39         Validate/HandleAttributes.cc \
    40         Validate/HandleAttributes.h \
    4138        Validate/HoistStruct.cpp \
    4239        Validate/HoistStruct.hpp \
  • src/Virtual/ExpandCasts.cc

    r790d835 rc6b4432  
    2424#include "AST/Expr.hpp"
    2525#include "AST/Pass.hpp"
    26 #include "Common/PassVisitor.h"    // for PassVisitor
    2726#include "Common/ScopedMap.h"      // for ScopedMap
    2827#include "Common/SemanticError.h"  // for SemanticError
    2928#include "SymTab/Mangler.h"        // for mangleType
    30 #include "SynTree/Declaration.h"   // for ObjectDecl, StructDecl, FunctionDecl
    31 #include "SynTree/Expression.h"    // for VirtualCastExpr, CastExpr, Address...
    32 #include "SynTree/Mutator.h"       // for mutateAll
    33 #include "SynTree/Type.h"          // for Type, PointerType, StructInstType
    34 #include "SynTree/Visitor.h"       // for acceptAll
    3529
    3630namespace Virtual {
     
    4337}
    4438
    45 bool is_type_id_object( const ObjectDecl * objectDecl ) {
    46         const std::string & objectName = objectDecl->name;
    47         return is_prefix( "__cfatid_", objectName );
    48 }
    49 
    5039bool is_type_id_object( const ast::ObjectDecl * decl ) {
    5140        return is_prefix( "__cfatid_", decl->name );
     
    5544
    5645        /// Maps virtual table types the instance for that type.
    57         class VirtualTableMap final {
    58                 ScopedMap<std::string, ObjectDecl *> vtable_instances;
    59         public:
    60                 void enterScope() {
    61                         vtable_instances.beginScope();
    62                 }
    63                 void leaveScope() {
    64                         vtable_instances.endScope();
    65                 }
    66 
    67                 ObjectDecl * insert( ObjectDecl * vtableDecl ) {
    68                         std::string const & mangledName = SymTab::Mangler::mangleType( vtableDecl->type );
    69                         ObjectDecl *& value = vtable_instances[ mangledName ];
    70                         if ( value ) {
    71                                 if ( vtableDecl->storageClasses.is_extern ) {
    72                                         return nullptr;
    73                                 } else if ( ! value->storageClasses.is_extern ) {
    74                                         return value;
    75                                 }
    76                         }
    77                         value = vtableDecl;
    78                         return nullptr;
    79                 }
    80 
    81                 ObjectDecl * lookup( const Type * vtableType ) {
    82                         std::string const & mangledName = SymTab::Mangler::mangleType( vtableType );
    83                         const auto it = vtable_instances.find( mangledName );
    84                         return ( vtable_instances.end() == it ) ? nullptr : it->second;
    85                 }
    86         };
    87 
    88         class VirtualCastCore {
    89                 CastExpr * cast_to_type_id( Expression * expr, int level_of_indirection ) {
    90                         Type * type = new StructInstType(
    91                                 Type::Qualifiers( Type::Const ), pvt_decl );
    92                         for (int i = 0 ; i < level_of_indirection ; ++i) {
    93                                 type = new PointerType( noQualifiers, type );
    94                         }
    95                         return new CastExpr( expr, type );
    96                 }
    97 
    98         public:
    99                 VirtualCastCore() :
    100                         indexer(), vcast_decl( nullptr ), pvt_decl( nullptr )
    101                 {}
    102 
    103                 void premutate( FunctionDecl * functionDecl );
    104                 void premutate( StructDecl * structDecl );
    105                 void premutate( ObjectDecl * objectDecl );
    106 
    107                 Expression * postmutate( VirtualCastExpr * castExpr );
    108 
    109                 VirtualTableMap indexer;
    110         private:
    111                 FunctionDecl *vcast_decl;
    112                 StructDecl *pvt_decl;
    113         };
    114 
    115         void VirtualCastCore::premutate( FunctionDecl * functionDecl ) {
    116                 if ( (! vcast_decl) &&
    117                      functionDecl->get_name() == "__cfavir_virtual_cast" ) {
    118                         vcast_decl = functionDecl;
    119                 }
    120         }
    121 
    122         void VirtualCastCore::premutate( StructDecl * structDecl ) {
    123                 if ( pvt_decl || ! structDecl->has_body() ) {
    124                         return;
    125                 } else if ( structDecl->get_name() == "__cfavir_type_info" ) {
    126                         pvt_decl = structDecl;
    127                 }
    128         }
    129 
    130         void VirtualCastCore::premutate( ObjectDecl * objectDecl ) {
    131                 if ( is_type_id_object( objectDecl ) ) {
    132                         // Multiple definitions should be fine because of linkonce.
    133                         indexer.insert( objectDecl );
    134                 }
    135         }
    136 
    137         /// Better error locations for generated casts.
    138         CodeLocation castLocation( const VirtualCastExpr * castExpr ) {
    139                 if ( castExpr->location.isSet() ) {
    140                         return castExpr->location;
    141                 } else if ( castExpr->arg->location.isSet() ) {
    142                         return castExpr->arg->location;
    143                 } else if ( castExpr->result->location.isSet() ) {
    144                         return castExpr->result->location;
    145                 } else {
    146                         return CodeLocation();
    147                 }
    148         }
    149 
    150         [[noreturn]] void castError( const VirtualCastExpr * castExpr, std::string const & message ) {
    151                 SemanticError( castLocation( castExpr ), message );
    152         }
    153 
    154         /// Get the base type from a pointer or reference.
    155         const Type * getBaseType( const Type * type ) {
    156                 if ( auto target = dynamic_cast<const PointerType *>( type ) ) {
    157                         return target->base;
    158                 } else if ( auto target = dynamic_cast<const ReferenceType *>( type ) ) {
    159                         return target->base;
    160                 } else {
    161                         return nullptr;
    162                 }
    163         }
    164 
    165         /* Attempt to follow the "head" field of the structure to get the...
    166          * Returns nullptr on error, otherwise owner must free returned node.
    167          */
    168         StructInstType * followHeadPointerType(
    169                         const StructInstType * oldType,
    170                         const std::string& fieldName,
    171                         const CodeLocation& errorLocation ) {
    172 
    173                 // First section of the function is all about trying to fill this variable in.
    174                 StructInstType * newType = nullptr;
    175                 {
    176                         const StructDecl * oldDecl = oldType->baseStruct;
    177                         assert( oldDecl );
    178 
    179                         // Helper function for throwing semantic errors.
    180                         auto throwError = [&fieldName, &errorLocation, &oldDecl](const std::string& message) {
    181                                 const std::string& context = "While following head pointer of " +
    182                                         oldDecl->name + " named '" + fieldName + "': ";
    183                                 SemanticError( errorLocation, context + message );
    184                         };
    185 
    186                         if ( oldDecl->members.empty() ) {
    187                                 throwError( "Type has no fields." );
    188                         }
    189                         const Declaration * memberDecl = oldDecl->members.front();
    190                         assert( memberDecl );
    191                         const ObjectDecl * fieldDecl = dynamic_cast<const ObjectDecl *>( memberDecl );
    192                         assert( fieldDecl );
    193                         if ( fieldName != fieldDecl->name ) {
    194                                 throwError( "Head field did not have expected name." );
    195                         }
    196 
    197                         const Type * fieldType = fieldDecl->type;
    198                         if ( nullptr == fieldType ) {
    199                                 throwError( "Could not get head field." );
    200                         }
    201                         const PointerType * ptrType = dynamic_cast<const PointerType *>( fieldType );
    202                         if ( nullptr == ptrType ) {
    203                                 throwError( "First field is not a pointer type." );
    204                         }
    205                         assert( ptrType->base );
    206                         newType = dynamic_cast<StructInstType *>( ptrType->base );
    207                         if ( nullptr == newType ) {
    208                                 throwError( "First field does not point to a structure type." );
    209                         }
    210                 }
    211 
    212                 // Now we can look into copying it.
    213                 newType = newType->clone();
    214                 if ( ! oldType->parameters.empty() ) {
    215                         deleteAll( newType->parameters );
    216                         newType->parameters.clear();
    217                         cloneAll( oldType->parameters, newType->parameters );
    218                 }
    219                 return newType;
    220         }
    221 
    222         /// Get the type-id type from a virtual type.
    223         StructInstType * getTypeIdType( const Type * type, const CodeLocation& errorLocation ) {
    224                 const StructInstType * typeInst = dynamic_cast<const StructInstType *>( type );
    225                 if ( nullptr == typeInst ) {
    226                         return nullptr;
    227                 }
    228                 StructInstType * tableInst =
    229                         followHeadPointerType( typeInst, "virtual_table", errorLocation );
    230                 if ( nullptr == tableInst ) {
    231                         return nullptr;
    232                 }
    233                 StructInstType * typeIdInst =
    234                         followHeadPointerType( tableInst, "__cfavir_typeid", errorLocation );
    235                 delete tableInst;
    236                 return typeIdInst;
    237         }
    238 
    239         Expression * VirtualCastCore::postmutate( VirtualCastExpr * castExpr ) {
    240                 assertf( castExpr->result, "Virtual Cast target not found before expansion." );
    241 
    242                 assert( vcast_decl );
    243                 assert( pvt_decl );
    244 
    245                 const Type * base_type = getBaseType( castExpr->result );
    246                 if ( nullptr == base_type ) {
    247                         castError( castExpr, "Virtual cast target must be a pointer or reference type." );
    248                 }
    249                 const Type * type_id_type = getTypeIdType( base_type, castLocation( castExpr ) );
    250                 if ( nullptr == type_id_type ) {
    251                         castError( castExpr, "Ill formed virtual cast target type." );
    252                 }
    253                 ObjectDecl * type_id = indexer.lookup( type_id_type );
    254                 delete type_id_type;
    255                 if ( nullptr == type_id ) {
    256                         castError( castExpr, "Virtual cast does not target a virtual type." );
    257                 }
    258 
    259                 Expression * result = new CastExpr(
    260                         new ApplicationExpr( VariableExpr::functionPointer( vcast_decl ), {
    261                                 cast_to_type_id( new AddressExpr( new VariableExpr( type_id ) ), 1 ),
    262                                 cast_to_type_id( castExpr->get_arg(), 2 ),
    263                         } ),
    264                         castExpr->get_result()->clone()
    265                 );
    266 
    267                 castExpr->set_arg( nullptr );
    268                 castExpr->set_result( nullptr );
    269                 delete castExpr;
    270                 return result;
    271         }
    27246
    27347/// Better error locations for generated casts.
     
    494268} // namespace
    495269
    496 void expandCasts( std::list< Declaration * > & translationUnit ) {
    497         PassVisitor<VirtualCastCore> translator;
    498         mutateAll( translationUnit, translator );
    499 }
    500 
    501270void expandCasts( ast::TranslationUnit & translationUnit ) {
    502271        ast::Pass<ExpandCastsCore>::run( translationUnit );
  • src/Virtual/Tables.cc

    r790d835 rc6b4432  
    2121#include "AST/Stmt.hpp"
    2222#include "AST/Type.hpp"
    23 #include <SynTree/Attribute.h>
    24 #include <SynTree/Declaration.h>
    25 #include <SynTree/Expression.h>
    26 #include <SynTree/Statement.h>
    27 #include <SynTree/Type.h>
    2823
    2924namespace Virtual {
     
    6560        return 17 < name.size() && '_' == name[0] &&
    6661                std::string("_vtable_instance") == name.substr(1, name.size() - 17);
    67 }
    68 
    69 static ObjectDecl * makeVtableDeclaration(
    70                 std::string const & name,
    71                 StructInstType * type, Initializer * init ) {
    72         Type::StorageClasses storage = noStorageClasses;
    73         if ( nullptr == init ) {
    74                 storage.is_extern = true;
    75         }
    76         return new ObjectDecl(
    77                 name,
    78                 storage,
    79                 LinkageSpec::Cforall,
    80                 nullptr,
    81                 type,
    82                 init
    83         );
    8462}
    8563
     
    10179}
    10280
    103 ObjectDecl * makeVtableForward( std::string const & name, StructInstType * type ) {
    104         assert( type );
    105         return makeVtableDeclaration( name, type, nullptr );
    106 }
    107 
    10881ast::ObjectDecl * makeVtableForward(
    10982                CodeLocation const & location, std::string const & name,
     
    11184        assert( vtableType );
    11285        return makeVtableDeclaration( location, name, vtableType, nullptr );
    113 }
    114 
    115 ObjectDecl * makeVtableInstance(
    116                 std::string const & name, StructInstType * vtableType,
    117                 Type * objectType, Initializer * init ) {
    118         assert( vtableType );
    119         assert( objectType );
    120         StructDecl * vtableStruct = vtableType->baseStruct;
    121         // Build the initialization
    122         if ( nullptr == init ) {
    123                 std::list< Initializer * > inits;
    124 
    125                 // This is going to have to be run before the resolver to connect expressions.
    126                 for ( auto field : vtableStruct->members ) {
    127                         if ( std::string( "parent" ) == field->name ) {
    128                                 // This will not work with polymorphic state.
    129                                 auto oField = strict_dynamic_cast< ObjectDecl * >( field );
    130                                 auto fieldType = strict_dynamic_cast< PointerType * >( oField->type );
    131                                 auto parentType = strict_dynamic_cast< StructInstType * >( fieldType->base );
    132                                 std::string const & parentInstance = instanceName( parentType->name );
    133                                 inits.push_back(
    134                                                 new SingleInit( new AddressExpr( new NameExpr( parentInstance ) ) ) );
    135                         } else if ( std::string( "__cfavir_typeid" ) == field->name ) {
    136                                 std::string const & baseType = baseTypeName( vtableType->name );
    137                                 std::string const & typeId = typeIdName( baseType );
    138                                 inits.push_back( new SingleInit( new AddressExpr( new NameExpr( typeId ) ) ) );
    139                         } else if ( std::string( "size" ) == field->name ) {
    140                                 inits.push_back( new SingleInit( new SizeofExpr( objectType->clone() ) ) );
    141                         } else if ( std::string( "align" ) == field->name ) {
    142                                 inits.push_back( new SingleInit( new AlignofExpr( objectType->clone() ) ) );
    143                         } else {
    144                                 inits.push_back( new SingleInit( new NameExpr( field->name ) ) );
    145                         }
    146                 }
    147                 init = new ListInit( inits );
    148         // This should initialize everything except the parent pointer, the
    149         // size-of and align-of fields. These should be inserted.
    150         } else {
    151                 assert(false);
    152         }
    153         return makeVtableDeclaration( name, vtableType, init );
    15486}
    15587
     
    224156}
    225157
    226 FunctionDecl * makeGetExceptionForward(
    227                 Type * vtableType, Type * exceptType ) {
    228         assert( vtableType );
    229         assert( exceptType );
    230         FunctionType * type = new FunctionType( noQualifiers, false );
    231         vtableType->tq.is_const = true;
    232         type->returnVals.push_back( new ObjectDecl(
    233                 "_retvalue",
    234                 noStorageClasses,
    235                 LinkageSpec::Cforall,
    236                 nullptr,
    237                 new ReferenceType( noQualifiers, vtableType ),
    238                 nullptr,
    239                 { new Attribute("unused") }
    240         ) );
    241         type->parameters.push_back( new ObjectDecl(
    242                 "__unused",
    243                 noStorageClasses,
    244                 LinkageSpec::Cforall,
    245                 nullptr,
    246                 new PointerType( noQualifiers, exceptType ),
    247                 nullptr,
    248                 { new Attribute("unused") }
    249         ) );
    250         return new FunctionDecl(
    251                 functionName,
    252                 noStorageClasses,
    253                 LinkageSpec::Cforall,
    254                 type,
    255                 nullptr
    256         );
    257 }
    258 
    259158ast::FunctionDecl * makeGetExceptionForward(
    260159                CodeLocation const & location,
     
    284183}
    285184
    286 FunctionDecl * makeGetExceptionFunction(
    287                 ObjectDecl * vtableInstance, Type * exceptType ) {
    288         assert( vtableInstance );
    289         assert( exceptType );
    290         FunctionDecl * func = makeGetExceptionForward(
    291                 vtableInstance->type->clone(), exceptType );
    292         func->statements = new CompoundStmt( {
    293                 new ReturnStmt( new VariableExpr( vtableInstance ) ),
    294         } );
    295         return func;
    296 }
    297 
    298185ast::FunctionDecl * makeGetExceptionFunction(
    299186                CodeLocation const & location,
     
    307194        } );
    308195        return func;
    309 }
    310 
    311 ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType ) {
    312         assert( typeIdType );
    313         StructInstType * type = typeIdType->clone();
    314         type->tq.is_const = true;
    315         std::string const & typeid_name = typeIdTypeToInstance( typeIdType->name );
    316         return new ObjectDecl(
    317                 typeid_name,
    318                 noStorageClasses,
    319                 LinkageSpec::Cforall,
    320                 /* bitfieldWidth */ nullptr,
    321                 type,
    322                 new ListInit( { new SingleInit(
    323                         new AddressExpr( new NameExpr( "__cfatid_exception_t" ) )
    324                         ) } ),
    325                 { new Attribute( "cfa_linkonce", {} ) },
    326                 noFuncSpecifiers
    327         );
    328196}
    329197
  • src/Virtual/Tables.h

    r790d835 rc6b4432  
    1818#include <string>
    1919#include "AST/Fwd.hpp"
    20 class Declaration;
    21 class Expression;
    22 class FunctionDecl;
    23 class Initializer;
    24 class ObjectDecl;
    25 class StructDecl;
    26 class StructInstType;
    27 class Type;
    2820
    2921namespace Virtual {
     
    3729bool isVTableInstanceName( std::string const & name );
    3830
    39 ObjectDecl * makeVtableForward(
    40         std::string const & name, StructInstType * vtableType );
    4131/* Create a forward declaration of a vtable of the given type.
    4232 * vtableType node is consumed.
     
    4636        ast::StructInstType const * vtableType );
    4737
    48 ObjectDecl * makeVtableInstance(
    49         std::string const & name,
    50         StructInstType * vtableType, Type * objectType,
    51         Initializer * init = nullptr );
    5238/* Create an initialized definition of a vtable.
    5339 * vtableType and init (if provided) nodes are consumed.
     
    6147
    6248// Some special code for how exceptions interact with virtual tables.
    63 FunctionDecl * makeGetExceptionForward( Type * vtableType, Type * exceptType );
     49
    6450/* Create a forward declaration of the exception virtual function
    6551 * linking the vtableType to the exceptType. Both nodes are consumed.
     
    7056        ast::Type const * exceptType );
    7157
    72 FunctionDecl * makeGetExceptionFunction(
    73         ObjectDecl * vtableInstance, Type * exceptType );
    7458/* Create the definition of the exception virtual function.
    7559 * exceptType node is consumed.
     
    7963        ast::ObjectDecl const * vtableInstance, ast::Type const * exceptType );
    8064
    81 ObjectDecl * makeTypeIdInstance( StructInstType const * typeIdType );
    8265/* Build an instance of the type-id from the type of the type-id.
    8366 * TODO: Should take the parent type. Currently locked to the exception_t.
  • src/main.cc

    r790d835 rc6b4432  
    2929#include <string>                           // for char_traits, operator<<
    3030
    31 #include "AST/Convert.hpp"
    3231#include "AST/Pass.hpp"                     // for pass_visitor_stats
    3332#include "AST/Print.hpp"                    // for printAll
     
    4039#include "CodeGen/Generate.h"               // for generate
    4140#include "CodeGen/LinkOnce.h"               // for translateLinkOnce
    42 #include "CodeTools/TrackLoc.h"             // for fillLocations
    4341#include "Common/CodeLocationTools.hpp"     // for forceFillCodeLocations
    4442#include "Common/DeclStats.hpp"             // for printDeclStats
     
    6664#include "ResolvExpr/EraseWith.hpp"         // for eraseWith
    6765#include "ResolvExpr/Resolver.h"            // for resolve
    68 #include "SynTree/LinkageSpec.h"            // for Spec, Cforall, Intrinsic
    69 #include "SynTree/Declaration.h"            // for Declaration
    7066#include "Tuples/Tuples.h"                  // for expandMemberTuples, expan...
    7167#include "Validate/Autogen.hpp"             // for autogenerateRoutines
     
    10096                ast::pass_visitor_stats.avg = build<AverageCounter<double>>( "Average Depth", pass );
    10197                ast::pass_visitor_stats.max = build<MaxCounter<double>>( "Max Depth", pass );
    102         }
    103         {
    104                 static auto group = build<CounterGroup>( "Syntax Node" );
    105                 auto pass = build<CounterGroup>( name, group );
    106                 BaseSyntaxNode::new_nodes = build<SimpleCounter>( "Allocs", pass );
    10798        }
    10899}
Note: See TracChangeset for help on using the changeset viewer.