Ignore:
Timestamp:
Oct 29, 2019, 4:01:24 PM (6 years ago)
Author:
Thierry Delisle <tdelisle@…>
Branches:
ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
Children:
773db65, 9421f3d8
Parents:
7951100 (diff), 8364209 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

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

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CastCost.cc

    r7951100 rb067d9b  
    99// Author           : Richard C. Bilson
    1010// Created On       : Sun May 17 06:57:43 2015
    11 // Last Modified By : Peter A. Buhr
    12 // Last Modified On : Tue Feb  2 15:34:36 2016
    13 // Update Count     : 7
     11// Last Modified By : Andrew Beach
     12// Last Modified On : Thu Aug  8 16:12:00 2019
     13// Update Count     : 8
    1414//
    1515
    1616#include <cassert>                       // for assert
    1717
     18#include "AST/Print.hpp"
     19#include "AST/SymbolTable.hpp"
     20#include "AST/Type.hpp"
     21#include "AST/TypeEnvironment.hpp"
    1822#include "ConversionCost.h"              // for ConversionCost
    1923#include "Cost.h"                        // for Cost, Cost::infinity
     
    3135
    3236namespace ResolvExpr {
    33         struct CastCost : public ConversionCost {
     37        struct CastCost_old : public ConversionCost {
    3438          public:
    35                 CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
     39                CastCost_old( const Type * dest, bool srcIsLvalue,
     40                        const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
    3641
    3742                using ConversionCost::previsit;
    3843                using ConversionCost::postvisit;
    39                 void postvisit( BasicType * basicType );
    40                 void postvisit( PointerType * pointerType );
     44                void postvisit( const BasicType * basicType );
     45                void postvisit( const PointerType * pointerType );
    4146        };
    4247
    43         Cost castCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
    44                 if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
    45                         if ( const EqvClass* eqvClass = env.lookup( destAsTypeInst->get_name() ) ) {
     48        Cost castCost( const Type * src, const Type * dest, bool srcIsLvalue,
     49                        const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
     50                if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType * >( dest ) ) {
     51                        if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->name ) ) {
    4652                                if ( eqvClass->type ) {
    47                                         return castCost( src, eqvClass->type, indexer, env );
     53                                        return castCost( src, eqvClass->type, srcIsLvalue, indexer, env );
    4854                                } else {
    4955                                        return Cost::infinity;
    5056                                }
    51                         } else if ( NamedTypeDecl *namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) {
     57                        } else if ( const NamedTypeDecl * namedType = indexer.lookupType( destAsTypeInst->name ) ) {
    5258                                // all typedefs should be gone by this point
    53                                 TypeDecl *type = strict_dynamic_cast< TypeDecl* >( namedType );
     59                                const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( namedType );
    5460                                if ( type->base ) {
    55                                         return castCost( src, type->base, indexer, env ) + Cost::safe;
     61                                        return castCost( src, type->base, srcIsLvalue, indexer, env ) + Cost::safe;
    5662                                } // if
    5763                        } // if
     
    7076                        PRINT( std::cerr << "compatible!" << std::endl; )
    7177                        return Cost::zero;
    72                 } else if ( dynamic_cast< VoidType* >( dest ) ) {
     78                } else if ( dynamic_cast< const VoidType * >( dest ) ) {
    7379                        return Cost::safe;
    74                 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
     80                } else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) {
    7581                        PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
    76                         return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
     82                        return convertToReferenceCost( src, refType, srcIsLvalue, indexer, env, [](const Type * t1, const Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
    7783                                return ptrsCastable( t1, t2, env, indexer );
    7884                        });
    7985                } else {
    80                         PassVisitor<CastCost> converter( dest, indexer, env, castCost );
     86                        PassVisitor<CastCost_old> converter(
     87                                dest, srcIsLvalue, indexer, env,
     88                                (Cost (*)( const Type *, const Type *, bool, const SymTab::Indexer &, const TypeEnvironment & ))
     89                                        castCost );
    8190                        src->accept( converter );
    8291                        if ( converter.pass.get_cost() == Cost::infinity ) {
     
    8998        }
    9099
    91         CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
    92                 : ConversionCost( dest, indexer, env, costFunc ) {
    93         }
    94 
    95         void CastCost::postvisit( BasicType *basicType ) {
    96                 PointerType *destAsPointer = dynamic_cast< PointerType* >( dest );
     100        CastCost_old::CastCost_old( const Type * dest, bool srcIsLvalue,
     101                        const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
     102                : ConversionCost( dest, srcIsLvalue, indexer, env, costFunc ) {
     103        }
     104
     105        void CastCost_old::postvisit( const BasicType * basicType ) {
     106                const PointerType * destAsPointer = dynamic_cast< const PointerType * >( dest );
    97107                if ( destAsPointer && basicType->isInteger() ) {
    98                         // necessary for, e.g. unsigned long => void*
     108                        // necessary for, e.g. unsigned long => void *
    99109                        cost = Cost::unsafe;
    100110                } else {
    101                         cost = conversionCost( basicType, dest, indexer, env );
     111                        cost = conversionCost( basicType, dest, srcIsLvalue, indexer, env );
    102112                } // if
    103113        }
    104114
    105         void CastCost::postvisit( PointerType *pointerType ) {
    106                 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
    107                         if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
     115        void CastCost_old::postvisit( const PointerType * pointerType ) {
     116                if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) {
     117                        if ( pointerType->tq <= destAsPtr->tq && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
    108118                                cost = Cost::safe;
    109119                        } else {
     
    118128                                } // if
    119129                        } // if
    120                 } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
     130                } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
    121131                        if ( destAsBasic->isInteger() ) {
    122                                 // necessary for, e.g. void* => unsigned long
     132                                // necessary for, e.g. void * => unsigned long
    123133                                cost = Cost::unsafe;
    124134                        } // if
    125135                }
    126136        }
     137
     138namespace {
     139        struct CastCost_new : public ConversionCost_new {
     140                using ConversionCost_new::previsit;
     141                using ConversionCost_new::postvisit;
     142
     143                CastCost_new(
     144                        const ast::Type * dst, const ast::SymbolTable & symtab,
     145                        const ast::TypeEnvironment & env, CostCalculation costFunc )
     146                : ConversionCost_new( dst, symtab, env, costFunc ) {}
     147
     148                void postvisit( const ast::BasicType * basicType ) {
     149                        auto ptr = dynamic_cast< const ast::PointerType * >( dst );
     150                        if ( ptr && basicType->isInteger() ) {
     151                                // needed for, e.g. unsigned long => void *
     152                                cost = Cost::unsafe;
     153                        } else {
     154                                cost = conversionCost( basicType, dst, symtab, env );
     155                        }
     156                }
     157
     158                void postvisit( const ast::PointerType * pointerType ) {
     159                        if ( auto ptr = dynamic_cast< const ast::PointerType * >( dst ) ) {
     160                                if (
     161                                        pointerType->qualifiers <= ptr->qualifiers
     162                                        && typesCompatibleIgnoreQualifiers( pointerType->base, ptr->base, symtab, env )
     163                                ) {
     164                                        cost = Cost::safe;
     165                                } else {
     166                                        ast::TypeEnvironment newEnv{ env };
     167                                        if ( auto wParams = pointerType->base.as< ast::ParameterizedType >() ) {
     168                                                newEnv.add( wParams->forall );
     169                                        }
     170                                        int castResult = ptrsCastable( pointerType->base, ptr->base, symtab, newEnv );
     171                                        if ( castResult > 0 ) {
     172                                                cost = Cost::safe;
     173                                        } else if ( castResult < 0 ) {
     174                                                cost = Cost::infinity;
     175                                        }
     176                                }
     177                        } else if ( auto basic = dynamic_cast< const ast::BasicType * >( dst ) ) {
     178                                if ( basic->isInteger() ) {
     179                                        // necessary for, e.g. void * => unsigned long
     180                                        cost = Cost::unsafe;
     181                                }
     182                        }
     183                }
     184        };
     185} // anonymous namespace
     186
     187Cost castCost(
     188        const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
     189        const ast::TypeEnvironment & env
     190) {
     191        if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
     192                if ( const ast::EqvClass * eqvClass = env.lookup( typeInst->name ) ) {
     193                        // check cast cost against bound type, if present
     194                        if ( eqvClass->bound ) {
     195                                return castCost( src, eqvClass->bound, symtab, env );
     196                        } else {
     197                                return Cost::infinity;
     198                        }
     199                } else if ( const ast::NamedTypeDecl * named = symtab.lookupType( typeInst->name ) ) {
     200                        // all typedefs should be gone by now
     201                        auto type = strict_dynamic_cast< const ast::TypeDecl * >( named );
     202                        if ( type->base ) {
     203                                return castCost( src, type->base, symtab, env ) + Cost::safe;
     204                        }
     205                }
     206        }
     207
     208        PRINT(
     209                std::cerr << "castCost ::: src is ";
     210                ast::print( std::cerr, src );
     211                std::cerr << std::endl << "dest is ";
     212                ast::print( std::cerr, dst );
     213                std::cerr << std::endl << "env is" << std::endl;
     214                ast::print( std::cerr, env, 2 );
     215        )
     216
     217        if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
     218                PRINT( std::cerr << "compatible!" << std::endl; )
     219                return Cost::zero;
     220        } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
     221                return Cost::safe;
     222        } else if ( auto refType = dynamic_cast< const ast::ReferenceType * >( dst ) ) {
     223                PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
     224                #warning cast on ptrsCastable artifact of having two functions, remove when port done
     225                return convertToReferenceCost(
     226                        src, refType, symtab, env,
     227                        ( int (*)(
     228                                const ast::Type *, const ast::Type *, const ast::SymbolTable &,
     229                                const ast::TypeEnvironment & )
     230                        ) ptrsCastable );
     231        } else {
     232                #warning cast on castCost artifact of having two functions, remove when port done
     233                ast::Pass< CastCost_new > converter{
     234                        dst, symtab, env,
     235                        ( Cost (*)(
     236                                const ast::Type *, const ast::Type *, const ast::SymbolTable &,
     237                                const ast::TypeEnvironment & )
     238                        ) castCost };
     239                src->accept( converter );
     240                return converter.pass.cost;
     241        }
     242}
     243
    127244} // namespace ResolvExpr
    128245
Note: See TracChangeset for help on using the changeset viewer.