Ignore:
Timestamp:
Jun 24, 2019, 3:42:36 PM (5 years ago)
Author:
Aaron Moss <a3moss@…>
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:
1335e6f
Parents:
093a5d7
Message:

Port castCost, ptrsCastable

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/ResolvExpr/CastCost.cc

    r093a5d7 r3c89751  
    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( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
    3640
    3741                using ConversionCost::previsit;
     
    7882                        });
    7983                } else {
    80                         #warning cast on castCost artifact of having two functions, remove when port done
    81                         PassVisitor<CastCost> converter(
     84                        PassVisitor<CastCost_old> converter(
    8285                                dest, indexer, env,
    8386                                (Cost (*)( Type *, Type *, const SymTab::Indexer &, const TypeEnvironment & ))
     
    9396        }
    9497
    95         CastCost::CastCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
     98        CastCost_old::CastCost_old( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
    9699                : ConversionCost( dest, indexer, env, costFunc ) {
    97100        }
    98101
    99         void CastCost::postvisit( BasicType *basicType ) {
     102        void CastCost_old::postvisit( BasicType *basicType ) {
    100103                PointerType *destAsPointer = dynamic_cast< PointerType* >( dest );
    101104                if ( destAsPointer && basicType->isInteger() ) {
     
    107110        }
    108111
    109         void CastCost::postvisit( PointerType *pointerType ) {
     112        void CastCost_old::postvisit( PointerType *pointerType ) {
    110113                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
    111114                        if ( pointerType->get_qualifiers() <= destAsPtr->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
     
    130133        }
    131134
    132         Cost castCost(
    133                 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
    134                 const ast::TypeEnvironment & env
    135         ) {
    136                 #warning unimplmented
    137                 (void)src; (void)dst; (void)symtab; (void)env;
    138                 assert(false);
     135namespace {
     136        struct CastCost_new : public ConversionCost_new {
     137                using ConversionCost_new::previsit;
     138                using ConversionCost_new::postvisit;
     139
     140                CastCost_new(
     141                        const ast::Type * dst, const ast::SymbolTable & symtab,
     142                        const ast::TypeEnvironment & env, CostCalculation costFunc )
     143                : ConversionCost_new( dst, symtab, env, costFunc ) {}
     144
     145                void postvisit( const ast::BasicType * basicType ) {
     146                        auto ptr = dynamic_cast< const ast::PointerType * >( dst );
     147                        if ( ptr && basicType->isInteger() ) {
     148                                // needed for, e.g. unsigned long => void *
     149                                cost = Cost::unsafe;
     150                        } else {
     151                                cost = conversionCost( basicType, dst, symtab, env );
     152                        }
     153                }
     154
     155                void postvisit( const ast::PointerType * pointerType ) {
     156                        if ( auto ptr = dynamic_cast< const ast::PointerType * >( dst ) ) {
     157                                if (
     158                                        pointerType->qualifiers <= ptr->qualifiers
     159                                        && typesCompatibleIgnoreQualifiers( pointerType->base, ptr->base, symtab, env )
     160                                ) {
     161                                        cost = Cost::safe;
     162                                } else {
     163                                        ast::TypeEnvironment newEnv{ env };
     164                                        if ( auto wParams = pointerType->base.as< ast::ParameterizedType >() ) {
     165                                                newEnv.add( wParams->forall );
     166                                        }
     167                                        int castResult = ptrsCastable( pointerType->base, ptr->base, symtab, newEnv );
     168                                        if ( castResult > 0 ) {
     169                                                cost = Cost::safe;
     170                                        } else if ( castResult < 0 ) {
     171                                                cost = Cost::infinity;
     172                                        }
     173                                }
     174                        } else if ( auto basic = dynamic_cast< const ast::BasicType * >( dst ) ) {
     175                                if ( basic->isInteger() ) {
     176                                        // necessary for, e.g. void * => unsigned long
     177                                        cost = Cost::unsafe;
     178                                }
     179                        }
     180                }
     181        };
     182} // anonymous namespace
     183
     184Cost castCost(
     185        const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
     186        const ast::TypeEnvironment & env
     187) {
     188        if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
     189                if ( const ast::EqvClass * eqvClass = env.lookup( typeInst->name ) ) {
     190                        // check cast cost against bound type, if present
     191                        if ( eqvClass->bound ) {
     192                                return castCost( src, eqvClass->bound, symtab, env );
     193                        } else {
     194                                return Cost::infinity;
     195                        }
     196                } else if ( const ast::NamedTypeDecl * named = symtab.lookupType( typeInst->name ) ) {
     197                        // all typedefs should be gone by now
     198                        auto type = strict_dynamic_cast< const ast::TypeDecl * >( named );
     199                        if ( type->base ) {
     200                                return castCost( src, type->base, symtab, env ) + Cost::safe;
     201                        }
     202                }
     203        }
     204
     205        PRINT(
     206                std::cerr << "castCost ::: src is ";
     207                ast::print( std::cerr, src );
     208                std::cerr << std::endl << "dest is ";
     209                ast::print( std::cerr, dst );
     210                std::cerr << std::endl << "env is" << std::endl;
     211                ast::print( std::cerr, env, 2 );
     212        )
     213
     214        if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
     215                PRINT( std::cerr << "compatible!" << std::endl; )
    139216                return Cost::zero;
    140         }
     217        } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
     218                return Cost::safe;
     219        } else if ( auto refType = dynamic_cast< const ast::ReferenceType * >( dst ) ) {
     220                PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
     221                #warning cast on ptrsCastable artifact of having two functions, remove when port done
     222                return convertToReferenceCost(
     223                        src, refType, symtab, env,
     224                        ( int (*)(
     225                                const ast::Type *, const ast::Type *, const ast::SymbolTable &,
     226                                const ast::TypeEnvironment & )
     227                        ) ptrsCastable );
     228        } else {
     229                #warning cast on castCost artifact of having two functions, remove when port done
     230                ast::Pass< CastCost_new > converter{
     231                        dst, symtab, env,
     232                        ( Cost (*)(
     233                                const ast::Type *, const ast::Type *, const ast::SymbolTable &,
     234                                const ast::TypeEnvironment & )
     235                        ) castCost };
     236                src->accept( converter );
     237                return converter.pass.cost;
     238        }
     239}
     240
    141241} // namespace ResolvExpr
    142242
Note: See TracChangeset for help on using the changeset viewer.