source: src/ResolvExpr/ConversionCost.cc @ 9d5089e

arm-ehjacob/cs343-translationjenkins-sandboxnew-astnew-ast-unique-expr
Last change on this file since 9d5089e was 9d5089e, checked in by Aaron Moss <a3moss@…>, 3 years ago

Port CandidateFinder::makeFunctionCandidates() and deps

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