source: src/ResolvExpr/ConversionCost.cc @ 8220e50

ADTarm-ehast-experimentalenumforall-pointer-decayjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-exprpthread-emulationqualifiedEnum
Last change on this file since 8220e50 was 1c9568f, checked in by Peter A. Buhr <pabuhr@…>, 5 years ago

choose integral zero over nullptr for any integral context

  • Property mode set to 100644
File size: 31.1 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 : Mon May  6 14:18:22 2019
13// Update Count     : 25
14//
15
16#include "ConversionCost.h"
17
18#include <cassert>                       // for assert
19#include <list>                          // for list, list<>::const_iterator
20#include <string>                        // for operator==, string
21
22#include "ResolvExpr/Cost.h"             // for Cost
23#include "ResolvExpr/TypeEnvironment.h"  // for EqvClass, TypeEnvironment
24#include "SymTab/Indexer.h"              // for Indexer
25#include "SynTree/Declaration.h"         // for TypeDecl, NamedTypeDecl
26#include "SynTree/Type.h"                // for Type, BasicType, TypeInstType
27#include "typeops.h"                     // for typesCompatibleIgnoreQualifiers
28
29namespace ResolvExpr {
30#if 0
31        const Cost Cost::zero =      Cost{  0,  0,  0,  0,  0,  0,  0 };
32        const Cost Cost::infinity =  Cost{ -1, -1, -1, -1, -1,  1, -1 };
33        const Cost Cost::unsafe =    Cost{  1,  0,  0,  0,  0,  0,  0 };
34        const Cost Cost::poly =      Cost{  0,  1,  0,  0,  0,  0,  0 };
35        const Cost Cost::safe =      Cost{  0,  0,  1,  0,  0,  0,  0 };
36        const Cost Cost::sign =      Cost{  0,  0,  0,  1,  0,  0,  0 };
37        const Cost Cost::var =       Cost{  0,  0,  0,  0,  1,  0,  0 };
38        const Cost Cost::spec =      Cost{  0,  0,  0,  0,  0, -1,  0 };
39        const Cost Cost::reference = Cost{  0,  0,  0,  0,  0,  0,  1 };
40#endif
41
42#if 0
43#define PRINT(x) x
44#else
45#define PRINT(x)
46#endif
47
48        Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
49                if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
50                        PRINT( std::cerr << "type inst " << destAsTypeInst->name; )
51                        if ( const EqvClass* eqvClass = env.lookup( destAsTypeInst->name ) ) {
52                                if ( eqvClass->type ) {
53                                        return conversionCost( src, eqvClass->type, indexer, env );
54                                } else {
55                                        return Cost::infinity;
56                                }
57                        } else if ( NamedTypeDecl *namedType = indexer.lookupType( destAsTypeInst->name ) ) {
58                                PRINT( std::cerr << " found" << std::endl; )
59                                TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
60                                // all typedefs should be gone by this point
61                                assert( type );
62                                if ( type->base ) {
63                                        return conversionCost( src, type->base, indexer, env ) + Cost::safe;
64                                } // if
65                        } // if
66                        PRINT( std::cerr << " not found" << std::endl; )
67                } // if
68                PRINT(
69                        std::cerr << "src is ";
70                        src->print( std::cerr );
71                        std::cerr << std::endl << "dest is ";
72                        dest->print( std::cerr );
73                        std::cerr << std::endl << "env is" << std::endl;
74                        env.print( std::cerr, 8 );
75                )
76                if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
77                        PRINT( std::cerr << "compatible!" << std::endl; )
78                        return Cost::zero;
79                } else if ( dynamic_cast< VoidType* >( dest ) ) {
80                        return Cost::safe;
81                } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
82                        PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
83                        return convertToReferenceCost( src, refType, indexer, env, [](Type * t1, Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){
84                                return ptrsAssignable( t1, t2, env );
85                        });
86                } else {
87                        PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost );
88                        src->accept( converter );
89                        if ( converter.pass.get_cost() == Cost::infinity ) {
90                                return Cost::infinity;
91                        } else {
92                                return converter.pass.get_cost() + Cost::zero;
93                        } // if
94                } // if
95        }
96
97        Cost convertToReferenceCost( Type * src, Type * dest, int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
98                PRINT( std::cerr << "convert to reference cost... diff " << diff << " " << src << " / " << dest << std::endl; )
99                if ( diff > 0 ) {
100                        // TODO: document this
101                        Cost cost = convertToReferenceCost( strict_dynamic_cast< ReferenceType * >( src )->base, dest, diff-1, indexer, env, func );
102                        cost.incReference();
103                        return cost;
104                } else if ( diff < -1 ) {
105                        // TODO: document this
106                        Cost cost = convertToReferenceCost( src, strict_dynamic_cast< ReferenceType * >( dest )->base, diff+1, indexer, env, func );
107                        cost.incReference();
108                        return cost;
109                } else if ( diff == 0 ) {
110                        ReferenceType * srcAsRef = dynamic_cast< ReferenceType * >( src );
111                        ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
112                        if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
113                                PRINT( std::cerr << "converting between references" << std::endl; )
114                                Type::Qualifiers tq1 = srcAsRef->base->get_qualifiers();
115                                Type::Qualifiers tq2 = destAsRef->base->get_qualifiers();
116                                if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->base, destAsRef->base, indexer, env ) ) {
117                                        PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
118                                        if ( tq1 == tq2 ) {
119                                                // types are the same
120                                                return Cost::zero;
121                                        } else {
122                                                // types are the same, except otherPointer has more qualifiers
123                                                return Cost::safe;
124                                        }
125                                } else {  // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
126                                        int assignResult = func( srcAsRef->base, destAsRef->base, indexer, env );
127                                        PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; )
128                                        if ( assignResult > 0 ) {
129                                                return Cost::safe;
130                                        } else if ( assignResult < 0 ) {
131                                                return Cost::unsafe;
132                                        } // if
133                                } // if
134                        } else {
135                                PRINT( std::cerr << "reference to rvalue conversion" << std::endl; )
136                                PassVisitor<ConversionCost> converter( dest, indexer, env, conversionCost );
137                                src->accept( converter );
138                                return converter.pass.get_cost();
139                        } // if
140                } else {
141                        ReferenceType * destAsRef = dynamic_cast< ReferenceType * >( dest );
142                        assert( diff == -1 && destAsRef );
143                        PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; )
144                        if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) {
145                                PRINT( std::cerr << "converting compatible base type" << std::endl; )
146                                if ( src->get_lvalue() ) {
147                                        PRINT(
148                                                std::cerr << "lvalue to reference conversion" << std::endl;
149                                                std::cerr << src << " => " << destAsRef << std::endl;
150                                        )
151                                        // lvalue-to-reference conversion:  cv lvalue T => cv T &
152                                        if ( src->get_qualifiers() == destAsRef->base->get_qualifiers() ) {
153                                                return Cost::reference; // cost needs to be non-zero to add cast
154                                        } if ( src->get_qualifiers() < destAsRef->base->get_qualifiers() ) {
155                                                return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
156                                        } else {
157                                                return Cost::unsafe;
158                                        } // if
159                                } else if ( destAsRef->base->get_const() ) {
160                                        PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; )
161                                        // rvalue-to-const-reference conversion: T => const T &
162                                        return Cost::safe;
163                                } else {
164                                        PRINT( std::cerr << "rvalue to non-const reference conversion" << std::endl; )
165                                        // rvalue-to-reference conversion: T => T &
166                                        return Cost::unsafe;
167                                } // if
168                        } // if
169                        PRINT( std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl; )
170                }
171                return Cost::infinity;
172        }
173
174        Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
175                int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
176                Cost cost = convertToReferenceCost( src, dest, sdepth-ddepth, indexer, env, func );
177                PRINT( std::cerr << "convertToReferenceCost result: " << cost << std::endl; )
178                return cost;
179        }
180
181        ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
182                : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) {
183        }
184
185        // GENERATED START, DO NOT EDIT
186        // GENERATED BY BasicTypes-gen.cc
187        /* EXTENDED INTEGRAL RANK HIERARCHY (root to leaves)
188                                 _Bool
189        char                signed char         unsigned char       
190                  signed short int         unsigned short int       
191                  signed int               unsigned int             
192                  signed long int          unsigned long int       
193                  signed long long int     unsigned long long int   
194                  __int128                 unsigned __int128       
195                  _Float16                 _Float16 _Complex       
196                  _Float32                 _Float32 _Complex       
197                  float                    float _Complex           
198                  _Float32x                _Float32x _Complex       
199                  _Float64                 _Float64 _Complex       
200                  double                   double _Complex         
201                  _Float64x                _Float64x _Complex       
202                             __float80
203                  _Float128                _Float128 _Complex       
204                            __float128
205                  long double              long double _Complex     
206                  _Float128x               _Float128x _Complex     
207        */
208        // GENERATED END
209
210        // GENERATED START, DO NOT EDIT
211        // GENERATED BY BasicTypes-gen.cc
212        static const int costMatrix[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // path length from root to node
213                /*             B    C   SC   UC   SI  SUI    I   UI   LI  LUI  LLI LLUI   IB  UIB  _FH  _FH   _F  _FC    F   FC  _FX _FXC   FD _FDC    D   DC F80X_FDXC  F80  _FB_FLDC   FB   LD  LDC _FBX_FLDXC */
214                /*     B*/ {   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  14,  15,  15,  16,  17,  16,  18,  17, },
215                /*     C*/ {  -1,   0,   1,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  14,  15,  16,  15,  17,  16, },
216                /*    SC*/ {  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  14,  15,  16,  15,  17,  16, },
217                /*    UC*/ {  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  14,  15,  16,  15,  17,  16, },
218                /*    SI*/ {  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  15,  14,  16,  15, },
219                /*   SUI*/ {  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  13,  14,  15,  14,  16,  15, },
220                /*     I*/ {  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  14,  13,  15,  14, },
221                /*    UI*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  12,  13,  14,  13,  15,  14, },
222                /*    LI*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  13,  12,  14,  13, },
223                /*   LUI*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  11,  12,  13,  12,  14,  13, },
224                /*   LLI*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  12,  11,  13,  12, },
225                /*  LLUI*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  10,  11,  12,  11,  13,  12, },
226                /*    IB*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  11,  10,  12,  11, },
227                /*   UIB*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,   9,  10,  11,  10,  12,  11, },
228                /*   _FH*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   8,   9,  10,   9,  11,  10, },
229                /*   _FH*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1,  -1,   2,  -1,   3,  -1,   4,  -1,   5,  -1,   6,  -1,  -1,   7,  -1,  -1,   8,  -1,   9, },
230                /*    _F*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   7,   8,   9,   8,  10,   9, },
231                /*   _FC*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1,  -1,   2,  -1,   3,  -1,   4,  -1,   5,  -1,  -1,   6,  -1,  -1,   7,  -1,   8, },
232                /*     F*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   6,   7,   8,   7,   9,   8, },
233                /*    FC*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1,  -1,   2,  -1,   3,  -1,   4,  -1,  -1,   5,  -1,  -1,   6,  -1,   7, },
234                /*   _FX*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   5,   6,   7,   6,   8,   7, },
235                /*  _FXC*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1,  -1,   2,  -1,   3,  -1,  -1,   4,  -1,  -1,   5,  -1,   6, },
236                /*    FD*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   4,   5,   6,   5,   7,   6, },
237                /*  _FDC*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1,  -1,   2,  -1,  -1,   3,  -1,  -1,   4,  -1,   5, },
238                /*     D*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3,   4,   5,   4,   6,   5, },
239                /*    DC*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1,  -1,  -1,   2,  -1,  -1,   3,  -1,   4, },
240                /*  F80X*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   4,   3,   5,   4, },
241                /* _FDXC*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,  -1,   1,  -1,  -1,   2,  -1,   3, },
242                /*   F80*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   1,   0,   1,   2,   2,   3,   3,   4,   4, },
243                /*   _FB*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2,   2,   3,   3, },
244                /* _FLDC*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,  -1,   1,  -1,   2, },
245                /*    FB*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   1,   0,   1,   2,   2,   3, },
246                /*    LD*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   1,   2, },
247                /*   LDC*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   1, },
248                /*  _FBX*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1, },
249                /*_FLDXC*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0, },
250        }; // costMatrix
251        static const int maxIntCost = 15;
252        // GENERATED END
253        static_assert(
254                sizeof(costMatrix)/sizeof(costMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES*BasicType::NUMBER_OF_BASIC_TYPES,
255                "Missing row in the cost matrix"
256        );
257
258        // GENERATED START, DO NOT EDIT
259        // GENERATED BY BasicTypes-gen.cc
260        static const int signMatrix[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // number of sign changes in safe conversion
261                /*             B    C   SC   UC   SI  SUI    I   UI   LI  LUI  LLI LLUI   IB  UIB  _FH  _FH   _F  _FC    F   FC  _FX _FXC   FD _FDC    D   DC F80X_FDXC  F80  _FB_FLDC   FB   LD  LDC _FBX_FLDXC */
262                /*     B*/ {   0,   0,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
263                /*     C*/ {  -1,   0,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
264                /*    SC*/ {  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
265                /*    UC*/ {  -1,  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
266                /*    SI*/ {  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
267                /*   SUI*/ {  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
268                /*     I*/ {  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
269                /*    UI*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
270                /*    LI*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
271                /*   LUI*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
272                /*   LLI*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
273                /*  LLUI*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
274                /*    IB*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
275                /*   UIB*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
276                /*   _FH*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
277                /*   _FH*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
278                /*    _F*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
279                /*   _FC*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
280                /*     F*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
281                /*    FC*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
282                /*   _FX*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
283                /*  _FXC*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0,  -1,   0,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
284                /*    FD*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
285                /*  _FDC*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
286                /*     D*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
287                /*    DC*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
288                /*  F80X*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
289                /* _FDXC*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
290                /*   F80*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0,   0,   0, },
291                /*   _FB*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0,   0, },
292                /* _FLDC*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,  -1,   0,  -1,   0, },
293                /*    FB*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0,   0,   0, },
294                /*    LD*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0,   0,   0, },
295                /*   LDC*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,  -1,   0, },
296                /*  _FBX*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0,   0, },
297                /*_FLDXC*/ {  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,  -1,   0, },
298        }; // signMatrix
299        // GENERATED END
300        static_assert(
301                sizeof(signMatrix)/sizeof(signMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES*BasicType::NUMBER_OF_BASIC_TYPES,
302                "Missing row in the sign matrix"
303        );
304
305        void ConversionCost::postvisit( VoidType * ) {
306                cost = Cost::infinity;
307        }
308
309        void ConversionCost::postvisit(BasicType *basicType) {
310                if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
311                        int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ];
312                        if ( tableResult == -1 ) {
313                                cost = Cost::unsafe;
314                        } else {
315                                cost = Cost::zero;
316                                cost.incSafe( tableResult );
317                                cost.incSign( signMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ] );
318                        } // if
319                } else if ( dynamic_cast< EnumInstType *>( dest ) ) {
320                        // xxx - not positive this is correct, but appears to allow casting int => enum
321                        cost = Cost::unsafe;
322                } // if
323                // no cases for zero_t/one_t because it should not be possible to convert int, etc. to zero_t/one_t.
324        }
325
326        void ConversionCost::postvisit( PointerType * pointerType ) {
327                if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
328                        PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; )
329                        Type::Qualifiers tq1 = pointerType->base->get_qualifiers();
330                        Type::Qualifiers tq2 = destAsPtr->base->get_qualifiers();
331                        if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
332                                PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
333                                if ( tq1 == tq2 ) {
334                                        // types are the same
335                                        cost = Cost::zero;
336                                } else {
337                                        // types are the same, except otherPointer has more qualifiers
338                                        cost = Cost::safe;
339                                } // if
340                        } else {
341                                int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env );
342                                PRINT( std::cerr << " :: " << assignResult << std::endl; )
343                                if ( assignResult > 0 && tq1 <= tq2 ) {
344                                        // 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?
345                                        if ( tq1 == tq2 ) {
346                                                cost = Cost::safe;
347                                        } else if ( tq1 < tq2 ) {
348                                                cost = Cost::safe+Cost::safe;
349                                        }
350                                } else if ( assignResult < 0 ) {
351                                        cost = Cost::unsafe;
352                                } // if
353                                // assignResult == 0 means Cost::Infinity
354                        } // if
355                        // case case for zero_t because it should not be possible to convert pointers to zero_t.
356                } // if
357        }
358
359        void ConversionCost::postvisit( ArrayType * ) {}
360
361        void ConversionCost::postvisit( ReferenceType * refType ) {
362                // Note: dest can never be a reference, since it would have been caught in an earlier check
363                assert( ! dynamic_cast< ReferenceType * >( dest ) );
364                // convert reference to rvalue: cv T1 & => T2
365                // recursively compute conversion cost from T1 to T2.
366                // cv can be safely dropped because of 'implicit dereference' behavior.
367                cost = costFunc( refType->base, dest, indexer, env );
368                if ( refType->base->get_qualifiers() == dest->get_qualifiers() ) {
369                        cost.incReference();  // prefer exact qualifiers
370                } else if ( refType->base->get_qualifiers() < dest->get_qualifiers() ) {
371                        cost.incSafe(); // then gaining qualifiers
372                } else {
373                        cost.incUnsafe(); // lose qualifiers as last resort
374                }
375                PRINT( std::cerr << refType << " ==> " << dest << " " << cost << std::endl; )
376        }
377
378        void ConversionCost::postvisit( FunctionType * ) {}
379
380        void ConversionCost::postvisit( StructInstType * inst ) {
381                if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) {
382                        if ( inst->name == destAsInst->name ) {
383                                cost = Cost::zero;
384                        } // if
385                } // if
386        }
387
388        void ConversionCost::postvisit( UnionInstType * inst ) {
389                if ( UnionInstType *destAsInst = dynamic_cast< UnionInstType* >( dest ) ) {
390                        if ( inst->name == destAsInst->name ) {
391                                cost = Cost::zero;
392                        } // if
393                } // if
394        }
395
396        void ConversionCost::postvisit( EnumInstType * ) {
397                static Type::Qualifiers q;
398                static BasicType integer( q, BasicType::SignedInt );
399                cost = costFunc( &integer, dest, indexer, env );  // safe if dest >= int
400                if ( cost < Cost::unsafe ) {
401                        cost.incSafe();
402                } // if
403        }
404
405        void ConversionCost::postvisit( TraitInstType * ) {}
406
407        void ConversionCost::postvisit( TypeInstType *inst ) {
408                if ( const EqvClass *eqvClass = env.lookup( inst->name ) ) {
409                        cost = costFunc( eqvClass->type, dest, indexer, env );
410                } else if ( TypeInstType *destAsInst = dynamic_cast< TypeInstType* >( dest ) ) {
411                        if ( inst->name == destAsInst->name ) {
412                                cost = Cost::zero;
413                        }
414                } else if ( NamedTypeDecl *namedType = indexer.lookupType( inst->name ) ) {
415                        TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
416                        // all typedefs should be gone by this point
417                        assert( type );
418                        if ( type->base ) {
419                                cost = costFunc( type->base, dest, indexer, env ) + Cost::safe;
420                        } // if
421                } // if
422        }
423
424        void ConversionCost::postvisit( TupleType * tupleType ) {
425                Cost c = Cost::zero;
426                if ( TupleType * destAsTuple = dynamic_cast< TupleType * >( dest ) ) {
427                        std::list< Type * >::const_iterator srcIt = tupleType->types.begin();
428                        std::list< Type * >::const_iterator destIt = destAsTuple->types.begin();
429                        while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) {
430                                Cost newCost = costFunc( *srcIt++, *destIt++, indexer, env );
431                                if ( newCost == Cost::infinity ) {
432                                        return;
433                                } // if
434                                c += newCost;
435                        } // while
436                        if ( destIt != destAsTuple->types.end() ) {
437                                cost = Cost::infinity;
438                        } else {
439                                cost = c;
440                        } // if
441                } // if
442        }
443
444        void ConversionCost::postvisit( VarArgsType * ) {
445                if ( dynamic_cast< VarArgsType* >( dest ) ) {
446                        cost = Cost::zero;
447                }
448        }
449
450        void ConversionCost::postvisit( ZeroType * ) {
451                if ( dynamic_cast< ZeroType * >( dest ) ) {
452                        cost = Cost::zero;
453                } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
454                        // copied from visit(BasicType*) for signed int, but +1 for safe conversions
455                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
456                        if ( tableResult == -1 ) {
457                                cost = Cost::unsafe;
458                        } else {
459                                cost = Cost::zero;
460                                cost.incSafe( tableResult + 1 );
461                                cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ] );
462                        } // if
463                } else if ( dynamic_cast< PointerType* >( dest ) ) {
464                        cost = Cost::zero;
465                        cost.incSafe( maxIntCost + 2 ); // +1 for zero_t -> int, +1 for disambiguation
466                } // if
467        }
468
469        void ConversionCost::postvisit( OneType * ) {
470                if ( dynamic_cast< OneType * >( dest ) ) {
471                        cost = Cost::zero;
472                } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
473                        // copied from visit(BasicType*) for signed int, but +1 for safe conversions
474                        int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
475                        if ( tableResult == -1 ) {
476                                cost = Cost::unsafe;
477                        } else {
478                                cost = Cost::zero;
479                                cost.incSafe( tableResult + 1 );
480                                cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ] );
481                        } // if
482                } // if
483        }
484} // namespace ResolvExpr
485
486// Local Variables: //
487// tab-width: 4 //
488// mode: c++ //
489// compile-command: "make install" //
490// End: //
Note: See TracBrowser for help on using the repository browser.