source: src/ResolvExpr/ConversionCost.cc @ db67b11

ADTaaron-thesisarm-ehast-experimentalcleanup-dtorsdeferred_resndemanglerenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprnew-envno_listpersistent-indexerpthread-emulationqualifiedEnumresolv-newwith_gc
Last change on this file since db67b11 was 74b007ba, checked in by Rob Schluntz <rschlunt@…>, 7 years ago

Remove unused isDynamicLayout parameter from autogen, add some more debug information

  • Property mode set to 100644
File size: 16.4 KB
RevLine 
[a32b204]1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
[a436947]7// ConversionCost.cc --
[a32b204]8//
9// Author           : Richard C. Bilson
10// Created On       : Sun May 17 07:06:19 2015
11// Last Modified By : Peter A. Buhr
[4040425]12// Last Modified On : Wed Mar  2 17:35:46 2016
13// Update Count     : 6
[a32b204]14//
[51b7345]15
16#include "ConversionCost.h"
17#include "typeops.h"
18#include "SynTree/Type.h"
19#include "SynTree/Visitor.h"
20#include "SymTab/Indexer.h"
21
22namespace ResolvExpr {
[7ebaa56]23        const Cost Cost::zero = Cost( 0, 0, 0, 0 );
24        const Cost Cost::infinity = Cost( -1, -1, -1, -1 );
25        const Cost Cost::unsafe = Cost( 1, 0, 0, 0 );
26        const Cost Cost::poly = Cost( 0, 1, 0, 0 );
27        const Cost Cost::safe = Cost( 0, 0, 1, 0 );
28        const Cost Cost::reference = Cost( 0, 0, 0, 1 );
[b46e3bd]29
[51b7345]30
[a32b204]31        Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
32                if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
33                        EqvClass eqvClass;
34                        NamedTypeDecl *namedType;
[51b7345]35///     std::cout << "type inst " << destAsTypeInst->get_name();
[a32b204]36                        if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) {
[0b150ec]37                                if ( eqvClass.type ) {
38                                        return conversionCost( src, eqvClass.type, indexer, env );
39                                } else {
40                                        return Cost::infinity;
41                                }
[a32b204]42                        } else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) ) {
[51b7345]43///       std::cout << " found" << std::endl;
[a32b204]44                                TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
45                                // all typedefs should be gone by this point
46                                assert( type );
47                                if ( type->get_base() ) {
[89be1c68]48                                        return conversionCost( src, type->get_base(), indexer, env ) + Cost::safe;
[a32b204]49                                } // if
50                        } // if
[51b7345]51///     std::cout << " not found" << std::endl;
[a32b204]52                } // if
[51b7345]53///   std::cout << "src is ";
54///   src->print( std::cout );
55///   std::cout << std::endl << "dest is ";
56///   dest->print( std::cout );
57///   std::cout << std::endl << "env is" << std::endl;
58///   env.print( std::cout, 8 );
[a32b204]59                if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
[51b7345]60///     std::cout << "compatible!" << std::endl;
[89be1c68]61                        return Cost::zero;
[a32b204]62                } else if ( dynamic_cast< VoidType* >( dest ) ) {
[89be1c68]63                        return Cost::safe;
[2463d0e]64                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
65                        // std::cerr << "conversionCost: dest is reference" << std::endl;
66                        return convertToReferenceCost( src, refType, indexer, env );
[a32b204]67                } else {
68                        ConversionCost converter( dest, indexer, env );
69                        src->accept( converter );
70                        if ( converter.get_cost() == Cost::infinity ) {
71                                return Cost::infinity;
72                        } else {
[89be1c68]73                                return converter.get_cost() + Cost::zero;
[a32b204]74                        } // if
75                } // if
76        }
77
[89be1c68]78        Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
[74b007ba]79                // std::cerr << "convert to reference cost..." << std::endl;
[89be1c68]80                if ( diff > 0 ) {
81                        // TODO: document this
82                        Cost cost = convertToReferenceCost( safe_dynamic_cast< ReferenceType * >( src )->get_base(), dest, diff-1, indexer, env );
[7ebaa56]83                        cost.incReference();
[89be1c68]84                        return cost;
85                } else if ( diff < -1 ) {
86                        // TODO: document this
87                        Cost cost = convertToReferenceCost( src, safe_dynamic_cast< ReferenceType * >( dest )->get_base(), diff+1, indexer, env );
[7ebaa56]88                        cost.incReference();
[89be1c68]89                        return cost;
90                } else if ( diff == 0 ) {
91                        ReferenceType * srcAsRef = dynamic_cast< ReferenceType * >( src );
92                        ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
93                        if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
[74b007ba]94                                // std::cerr << "converting between references" << std::endl;
[89be1c68]95                                if ( srcAsRef->get_base()->get_qualifiers() <= destAsRef->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), destAsRef->get_base(), indexer, env ) ) {
96                                        return Cost::safe;
97                                } else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
98                                        int assignResult = ptrsAssignable( srcAsRef->get_base(), destAsRef->get_base(), env );
99                                        if ( assignResult < 0 ) {
100                                                return Cost::safe;
101                                        } else if ( assignResult > 0 ) {
102                                                return Cost::unsafe;
103                                        } // if
[2463d0e]104                                } // if
105                        } else {
[74b007ba]106                                // std::cerr << "reference to rvalue conversion" << std::endl;
[89be1c68]107                                ConversionCost converter( dest, indexer, env );
108                                src->accept( converter );
109                                return converter.get_cost();
110                        } // if
[2463d0e]111                } else {
[89be1c68]112                        ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
113                        assert( diff == -1 && destAsRef );
114                        if ( typesCompatibleIgnoreQualifiers( src, destAsRef->get_base(), indexer, env ) ) {
[74b007ba]115                                // std::cerr << "converting compatible base type" << std::endl;
[89be1c68]116                                if ( src->get_lvalue() ) {
[74b007ba]117                                        // std::cerr << "lvalue to reference conversion" << std::endl;
[89be1c68]118                                        // lvalue-to-reference conversion:  cv lvalue T => cv T &
119                                        if ( src->get_qualifiers() == destAsRef->get_base()->get_qualifiers() ) {
[7ebaa56]120                                                return Cost::reference; // cost needs to be non-zero to add cast
[89be1c68]121                                        } if ( src->get_qualifiers() < destAsRef->get_base()->get_qualifiers() ) {
[7ebaa56]122                                                return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
[89be1c68]123                                        } else {
124                                                return Cost::unsafe;
125                                        } // if
126                                } else if ( destAsRef->get_base()->get_const() ) {
[74b007ba]127                                        // std::cerr << "rvalue to const ref conversion" << std::endl;
[89be1c68]128                                        // rvalue-to-const-reference conversion: T => const T &
129                                        return Cost::safe;
130                                } else {
131                                        // std::cerr << "rvalue to non-const reference conversion" << std::endl;
132                                        // rvalue-to-reference conversion: T => T &
133                                        return Cost::unsafe;
134                                } // if
135                        } // if
[74b007ba]136                        // std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl;
[2463d0e]137                }
138                return Cost::infinity;
139        }
140
[89be1c68]141        Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
142                int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
143                return convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env );
144        }
145
[a32b204]146        ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env )
147                : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ) {
148        }
[51b7345]149
150/*
[a32b204]151            Old
152            ===
153           Double
154             |
155           Float
156             |
157           ULong
158           /   \
159        UInt    Long
160           \   /
161            Int
162             |
163           Ushort
164             |
165           Short
166             |
167           Uchar
168           /   \
169        Schar   Char
170
171                                New
172                                ===
173                       +-----LongDoubleComplex--+
174           LongDouble--+          |             +-LongDoubleImag
175             |         +---DoubleComplex---+         |
176           Double------+        |          +----DoubleImag
177             |           +-FloatComplex-+            |
178           Float---------+              +-------FloatImag
179             |
180          ULongLong
181             |
182          LongLong
183             |
184           ULong
185           /   \
186        UInt    Long
187           \   /
188            Int
189             |
190           Ushort
191             |
192           Short
193             |
194           Uchar
195           /   \
196        Schar   Char
197           \   /
198            Bool
[51b7345]199*/
200
[a32b204]201        static const int costMatrix[ BasicType::NUMBER_OF_BASIC_TYPES ][ BasicType::NUMBER_OF_BASIC_TYPES ] =
202        {
203        /* Src \ Dest:  Bool    Char    SChar   UChar   Short   UShort  Int     UInt    Long    ULong   LLong   ULLong  Float   Double  LDbl    FCplex  DCplex  LDCplex FImag   DImag   LDImag */
204                /* Bool */      { 0,    1,              1,              2,              3,              4,              5,              6,              6,              7,              8,              9,              10,             11,             12,             11,             12,             13,             -1,             -1,             -1 },
205                /* Char */      { -1,   0,              -1,             1,              2,              3,              4,              5,              5,              6,              7,              8,              9,              10,             11,             10,             11,             12,             -1,             -1,             -1 },
206                /* SChar */ { -1,       -1,             0,              1,              2,              3,              4,              5,              5,              6,              7,              8,              9,              10,             11,             10,             11,             12,             -1,             -1,             -1 },
207                /* UChar */ { -1,       -1,             -1,             0,              1,              2,              3,              4,              4,              5,              6,              7,              8,              9,              10,             9,              10,             11,             -1,             -1,             -1 },
208                /* Short */ { -1,       -1,             -1,             -1,             0,              1,              2,              3,              3,              4,              5,              6,              7,              8,              9,              8,              9,              10,             -1,             -1,             -1 },
209                /* UShort */{ -1,       -1,             -1,             -1,             -1,             0,              1,              2,              2,              3,              4,              5,              6,              7,              8,              7,              8,              9,              -1,             -1,             -1 },
210                /* Int */       { -1,   -1,             -1,             -1,             -1,             -1,             0,              1,              1,              2,              3,              4,              5,              6,              7,              6,              7,              8,              -1,             -1,             -1 },
211                /* UInt */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             1,              2,              3,              4,              5,              6,              5,              6,              7,              -1,             -1,             -1 },
212                /* Long */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              3,              4,              5,              6,              5,              6,              7,              -1,             -1,             -1 },
213                /* ULong */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              3,              4,              5,              4,              5,              6,              -1,             -1,             -1 },
214                /* LLong */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              3,              4,              3,              4,              5,              -1,             -1,             -1 },
215                /* ULLong */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              3,              2,              3,              4,              -1,             -1,             -1 },
216                /* Float */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              1,              2,              3,              -1,             -1,             -1 },
217                /* Double */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              -1,             1,              2,              -1,             -1,             -1 },
218                /* LDbl */      { -1,   -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             -1,             1,              -1,             -1,             -1 },
219                /* FCplex */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              2,              -1,             -1,             -1 },
220                /* DCplex */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              1,              -1,             -1,             -1 },
221                /* LDCplex */{ -1,      -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             0,              -1,             -1,             -1 },
222                /* FImag */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              3,              0,              1,              2 },
223                /* DImag */ { -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              2,              -1,             0,              1 },
224                /* LDImag */{ -1,       -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             -1,             1,              -1,             -1,             0 }
225        };
226
[7e003011]227        void ConversionCost::visit( __attribute((unused)) VoidType *voidType ) {
[a32b204]228                cost = Cost::infinity;
229        }
230
231        void ConversionCost::visit(BasicType *basicType) {
232                if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
233                        int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ];
234                        if ( tableResult == -1 ) {
[89be1c68]235                                cost = Cost::unsafe;
[a32b204]236                        } else {
[89be1c68]237                                cost = Cost::zero;
238                                cost.incSafe( tableResult );
[a32b204]239                        } // if
[a436947]240                } else if ( dynamic_cast< EnumInstType *>( dest ) ) {
241                        // xxx - not positive this is correct, but appears to allow casting int => enum
[89be1c68]242                        cost = Cost::unsafe;
[89e6ffc]243                } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) {
[89be1c68]244                        cost = Cost::unsafe;
[89e6ffc]245                } // if
[a32b204]246        }
247
248        void ConversionCost::visit(PointerType *pointerType) {
249                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
[cb43451]250                        // std::cerr << pointerType << " ===> " << destAsPtr;
251                        Type::Qualifiers tq1 = pointerType->get_base()->get_qualifiers();
252                        Type::Qualifiers tq2 = destAsPtr->get_base()->get_qualifiers();
253                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
254                                if ( tq1 == tq2 ) {
255                                        // types are the same
256                                        cost = Cost::zero;
257                                } else {
258                                        // types are the same, except otherPointer has more qualifiers
259                                        // std::cerr << " :: compatible and good qualifiers" << std::endl;
260                                        cost = Cost::safe;
261                                }
262                        } else {  // xxx - this discards qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
[a32b204]263                                int assignResult = ptrsAssignable( pointerType->get_base(), destAsPtr->get_base(), env );
[cb43451]264                                // std::cerr << " :: " << assignResult << std::endl;
265                                if ( assignResult < 0 && pointerType->get_base()->get_qualifiers() <= destAsPtr->get_qualifiers() ) {
[89be1c68]266                                        cost = Cost::safe;
[a32b204]267                                } else if ( assignResult > 0 ) {
[89be1c68]268                                        cost = Cost::unsafe;
[a32b204]269                                } // if
[cb43451]270                                // assignResult == 0 means Cost::Infinity
[a32b204]271                        } // if
[89e6ffc]272                } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) {
[89be1c68]273                        cost = Cost::unsafe;
[a32b204]274                } // if
275        }
276
[7e003011]277        void ConversionCost::visit(__attribute((unused)) ArrayType *arrayType) {}
[2463d0e]278
279        void ConversionCost::visit(ReferenceType *refType) {
280                // Note: dest can never be a reference, since it would have been caught in an earlier check
281                assert( ! dynamic_cast< ReferenceType * >( dest ) );
282                // convert reference to rvalue: cv T1 & => T2
283                // recursively compute conversion cost from T1 to T2.
284                // cv can be safely dropped because of 'implicit dereference' behavior.
285                refType->get_base()->accept( *this );
[cb43451]286                if ( refType->get_base()->get_qualifiers() == dest->get_qualifiers() ) {
287                        cost.incReference();  // prefer exact qualifiers
288                } else if ( refType->get_base()->get_qualifiers() < dest->get_qualifiers() ) {
289                        cost.incSafe(); // then gaining qualifiers
290                } else {
291                        cost.incUnsafe(); // lose qualifiers as last resort
292                }
293                // std::cerr << refType << " ==> " << dest << " " << cost << std::endl;
[2463d0e]294        }
295
[7e003011]296        void ConversionCost::visit(__attribute((unused)) FunctionType *functionType) {}
[a32b204]297
298        void ConversionCost::visit(StructInstType *inst) {
299                if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) {
300                        if ( inst->get_name() == destAsInst->get_name() ) {
301                                cost = Cost::zero;
302                        } // if
303                } // if
304        }
305
306        void ConversionCost::visit(UnionInstType *inst) {
307                if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) {
308                        if ( inst->get_name() == destAsInst->get_name() ) {
309                                cost = Cost::zero;
310                        } // if
311                } // if
312        }
313
[7e003011]314        void ConversionCost::visit( __attribute((unused)) EnumInstType *inst ) {
[a32b204]315                static Type::Qualifiers q;
316                static BasicType integer( q, BasicType::SignedInt );
[2463d0e]317                integer.accept( *this );  // safe if dest >= int
[89be1c68]318                if ( cost < Cost::unsafe ) {
[a32b204]319                        cost.incSafe();
320                } // if
321        }
322
[7e003011]323        void ConversionCost::visit( __attribute((unused)) TraitInstType *inst) {
[a32b204]324        }
325
326        void ConversionCost::visit(TypeInstType *inst) {
327                EqvClass eqvClass;
328                NamedTypeDecl *namedType;
329                if ( env.lookup( inst->get_name(), eqvClass ) ) {
330                        cost = conversionCost( eqvClass.type, dest, indexer, env );
331                } else if ( TypeInstType *destAsInst = dynamic_cast< TypeInstType* >( dest ) ) {
332                        if ( inst->get_name() == destAsInst->get_name() ) {
333                                cost = Cost::zero;
334                        }
335                } else if ( ( namedType = indexer.lookupType( inst->get_name() ) ) ) {
336                        TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
337                        // all typedefs should be gone by this point
338                        assert( type );
339                        if ( type->get_base() ) {
[89be1c68]340                                cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost::safe;
[a32b204]341                        } // if
342                } // if
343        }
344
[7e003011]345        void ConversionCost::visit( __attribute((unused)) TupleType *tupleType) {
[89be1c68]346                Cost c = Cost::zero;
[a32b204]347                if ( TupleType *destAsTuple = dynamic_cast< TupleType* >( dest ) ) {
348                        std::list< Type* >::const_iterator srcIt = tupleType->get_types().begin();
349                        std::list< Type* >::const_iterator destIt = destAsTuple->get_types().begin();
[4ab9536]350                        while ( srcIt != tupleType->get_types().end() && destIt != destAsTuple->get_types().end() ) {
[a32b204]351                                Cost newCost = conversionCost( *srcIt++, *destIt++, indexer, env );
352                                if ( newCost == Cost::infinity ) {
353                                        return;
354                                } // if
355                                c += newCost;
356                        } // while
357                        if ( destIt != destAsTuple->get_types().end() ) {
358                                cost = Cost::infinity;
359                        } else {
360                                cost = c;
361                        } // if
362                } // if
363        }
[44b7088]364
[7e003011]365        void ConversionCost::visit( __attribute((unused)) VarArgsType *varArgsType) {
[90c3b1c]366                if ( dynamic_cast< VarArgsType* >( dest ) ) {
[44b7088]367                        cost = Cost::zero;
368                }
369        }
[89e6ffc]370
[7e003011]371        void ConversionCost::visit( __attribute((unused)) ZeroType *zeroType) {
[89e6ffc]372                if ( dynamic_cast< ZeroType* >( dest ) ) {
373                        cost = Cost::zero;
374                } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
375                        // copied from visit(BasicType*) for signed int, but +1 for safe conversions
376                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
377                        if ( tableResult == -1 ) {
[89be1c68]378                                cost = Cost::unsafe;
[89e6ffc]379                        } else {
[89be1c68]380                                cost = Cost::zero;
381                                cost.incSafe( tableResult + 1 );
[89e6ffc]382                        }
383                } else if ( dynamic_cast< PointerType* >( dest ) ) {
[89be1c68]384                        cost = Cost::safe;
[89e6ffc]385                }
386        }
387
[7e003011]388        void ConversionCost::visit( __attribute((unused)) OneType *oneType) {
[89e6ffc]389                if ( dynamic_cast< OneType* >( dest ) ) {
390                        cost = Cost::zero;
391                } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
392                        // copied from visit(BasicType*) for signed int, but +1 for safe conversions
393                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
394                        if ( tableResult == -1 ) {
[89be1c68]395                                cost = Cost::unsafe;
[89e6ffc]396                        } else {
[89be1c68]397                                cost = Cost::zero;
398                                cost.incSafe( tableResult + 1 );
[89e6ffc]399                        }
400                }
401        }
[51b7345]402} // namespace ResolvExpr
[a32b204]403
404// Local Variables: //
405// tab-width: 4 //
406// mode: c++ //
407// compile-command: "make install" //
408// End: //
Note: See TracBrowser for help on using the repository browser.