source: src/ResolvExpr/ConversionCost.cc @ b46e3bd

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 b46e3bd was b46e3bd, checked in by Rob Schluntz <rschlunt@…>, 7 years ago

Update Cost structure to include static unsafe, poly, safe members

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