source: src/ResolvExpr/ConversionCost.cc@ 0019d77

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since 0019d77 was eb1be63, checked in by Fangren Yu <f37yu@…>, 5 years ago

conversion cost pass should not consider structs again after types compatible check

  • Property mode set to 100644
File size: 42.0 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 : Andrew Beach
12// Last Modified On : Fri Oct 4 14:45:00 2019
13// Update Count : 28
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( const Type * src, const Type * dest, bool srcIsLvalue,
49 const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
50 if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType * >( dest ) ) {
51 PRINT( std::cerr << "type inst " << destAsTypeInst->name; )
52 if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->name ) ) {
53 if ( eqvClass->type ) {
54 return conversionCost( src, eqvClass->type, srcIsLvalue, indexer, env );
55 } else {
56 return Cost::infinity;
57 }
58 } else if ( const NamedTypeDecl * namedType = indexer.lookupType( destAsTypeInst->name ) ) {
59 PRINT( std::cerr << " found" << std::endl; )
60 const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
61 // all typedefs should be gone by this point
62 assert( type );
63 if ( type->base ) {
64 return conversionCost( src, type->base, srcIsLvalue, indexer, env )
65 + Cost::safe;
66 } // if
67 } // if
68 PRINT( std::cerr << " not found" << std::endl; )
69 } // if
70 PRINT(
71 std::cerr << "src is ";
72 src->print( std::cerr );
73 std::cerr << std::endl << "dest is ";
74 dest->print( std::cerr );
75 std::cerr << std::endl << "env is" << std::endl;
76 env.print( std::cerr, 8 );
77 )
78 if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
79 PRINT( std::cerr << "compatible!" << std::endl; )
80 return Cost::zero;
81 } else if ( dynamic_cast< const VoidType * >( dest ) ) {
82 return Cost::safe;
83 } else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) {
84 PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
85 return convertToReferenceCost( src, refType, srcIsLvalue, indexer, env, [](const Type * const t1, const Type * t2, const SymTab::Indexer &, const TypeEnvironment & env ){
86 return ptrsAssignable( t1, t2, env );
87 });
88 } else {
89 PassVisitor<ConversionCost> converter(
90 dest, srcIsLvalue, indexer, env,
91 (Cost (*)(const Type *, const Type *, bool, const SymTab::Indexer&, const TypeEnvironment&))
92 conversionCost );
93 src->accept( converter );
94 if ( converter.pass.get_cost() == Cost::infinity ) {
95 return Cost::infinity;
96 } else {
97 return converter.pass.get_cost() + Cost::zero;
98 } // if
99 } // if
100 }
101
102 static Cost convertToReferenceCost( const Type * src, const Type * dest, bool srcIsLvalue,
103 int diff, const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
104 PRINT( std::cerr << "convert to reference cost... diff " << diff << " " << src << " / " << dest << std::endl; )
105 if ( diff > 0 ) {
106 // TODO: document this
107 Cost cost = convertToReferenceCost(
108 strict_dynamic_cast< const ReferenceType * >( src )->base, dest, srcIsLvalue,
109 diff-1, indexer, env, func );
110 cost.incReference();
111 return cost;
112 } else if ( diff < -1 ) {
113 // TODO: document this
114 Cost cost = convertToReferenceCost(
115 src, strict_dynamic_cast< const ReferenceType * >( dest )->base, srcIsLvalue,
116 diff+1, indexer, env, func );
117 cost.incReference();
118 return cost;
119 } else if ( diff == 0 ) {
120 const ReferenceType * srcAsRef = dynamic_cast< const ReferenceType * >( src );
121 const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest );
122 if ( srcAsRef && destAsRef ) { // pointer-like conversions between references
123 PRINT( std::cerr << "converting between references" << std::endl; )
124 Type::Qualifiers tq1 = srcAsRef->base->tq;
125 Type::Qualifiers tq2 = destAsRef->base->tq;
126 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( srcAsRef->base, destAsRef->base, indexer, env ) ) {
127 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
128 if ( tq1 == tq2 ) {
129 // types are the same
130 return Cost::zero;
131 } else {
132 // types are the same, except otherPointer has more qualifiers
133 return Cost::safe;
134 }
135 } else { // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
136 int assignResult = func( srcAsRef->base, destAsRef->base, indexer, env );
137 PRINT( std::cerr << "comparing references: " << assignResult << " " << srcAsRef << " " << destAsRef << std::endl; )
138 if ( assignResult > 0 ) {
139 return Cost::safe;
140 } else if ( assignResult < 0 ) {
141 return Cost::unsafe;
142 } // if
143 } // if
144 } else {
145 PRINT( std::cerr << "reference to rvalue conversion" << std::endl; )
146 PassVisitor<ConversionCost> converter(
147 dest, srcIsLvalue, indexer, env,
148 (Cost (*)(const Type *, const Type *, bool, const SymTab::Indexer&, const TypeEnvironment&))
149 conversionCost );
150 src->accept( converter );
151 return converter.pass.get_cost();
152 } // if
153 } else {
154 const ReferenceType * destAsRef = dynamic_cast< const ReferenceType * >( dest );
155 assert( diff == -1 && destAsRef );
156 PRINT( std::cerr << "dest is: " << dest << " / src is: " << src << std::endl; )
157 if ( typesCompatibleIgnoreQualifiers( src, destAsRef->base, indexer, env ) ) {
158 PRINT( std::cerr << "converting compatible base type" << std::endl; )
159 if ( srcIsLvalue ) {
160 PRINT(
161 std::cerr << "lvalue to reference conversion" << std::endl;
162 std::cerr << src << " => " << destAsRef << std::endl;
163 )
164 // lvalue-to-reference conversion: cv lvalue T => cv T &
165 if ( src->tq == destAsRef->base->tq ) {
166 return Cost::reference; // cost needs to be non-zero to add cast
167 } if ( src->tq < destAsRef->base->tq ) {
168 return Cost::safe; // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
169 } else {
170 return Cost::unsafe;
171 } // if
172 } else if ( destAsRef->base->get_const() ) {
173 PRINT( std::cerr << "rvalue to const ref conversion" << std::endl; )
174 // rvalue-to-const-reference conversion: T => const T &
175 return Cost::safe;
176 } else {
177 PRINT( std::cerr << "rvalue to non-const reference conversion" << std::endl; )
178 // rvalue-to-reference conversion: T => T &
179 return Cost::unsafe;
180 } // if
181 } // if
182 PRINT( std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl; )
183 }
184 return Cost::infinity;
185 }
186
187 Cost convertToReferenceCost( const Type * src, const ReferenceType * dest, bool srcIsLvalue,
188 const SymTab::Indexer & indexer, const TypeEnvironment & env, PtrsFunction func ) {
189 int sdepth = src->referenceDepth(), ddepth = dest->referenceDepth();
190 Cost cost = convertToReferenceCost( src, dest, srcIsLvalue, sdepth-ddepth, indexer, env, func );
191 PRINT( std::cerr << "convertToReferenceCost result: " << cost << std::endl; )
192 return cost;
193 }
194
195 ConversionCost::ConversionCost( const Type * dest, bool srcIsLvalue, const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
196 : dest( dest ), srcIsLvalue( srcIsLvalue ), indexer( indexer ), cost( Cost::infinity ), env( env ), costFunc( costFunc ) {
197 }
198
199 // GENERATED START, DO NOT EDIT
200 // GENERATED BY BasicTypes-gen.cc
201 /* EXTENDED INTEGRAL RANK HIERARCHY (root to leaves)
202 _Bool
203 char signed char unsigned char
204 signed short int unsigned short int
205 signed int unsigned int
206 signed long int unsigned long int
207 signed long long int unsigned long long int
208 __int128 unsigned __int128
209 _Float16 _Float16 _Complex
210 _Float32 _Float32 _Complex
211 float float _Complex
212 _Float32x _Float32x _Complex
213 _Float64 _Float64 _Complex
214 double double _Complex
215 _Float64x _Float64x _Complex
216 __float80
217 _Float128 _Float128 _Complex
218 __float128
219 long double long double _Complex
220 _Float128x _Float128x _Complex
221 */
222 // GENERATED END
223
224 // GENERATED START, DO NOT EDIT
225 // GENERATED BY BasicTypes-gen.cc
226 static const int costMatrix[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // path length from root to node
227 /* 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 */
228 /* 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, },
229 /* 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, },
230 /* 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, },
231 /* 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, },
232 /* 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, },
233 /* 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, },
234 /* 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, },
235 /* 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, },
236 /* 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, },
237 /* 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, },
238 /* 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, },
239 /* 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, },
240 /* 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, },
241 /* 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, },
242 /* _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, },
243 /* _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, },
244 /* _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, },
245 /* _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, },
246 /* 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, },
247 /* 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, },
248 /* _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, },
249 /* _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, },
250 /* 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, },
251 /* _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, },
252 /* 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, },
253 /* 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, },
254 /* 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, },
255 /* _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, },
256 /* 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, },
257 /* _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, },
258 /* _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, },
259 /* 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, },
260 /* 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, },
261 /* 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, },
262 /* _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, },
263 /* _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, },
264 }; // costMatrix
265 static const int maxIntCost = 15;
266 // GENERATED END
267 static_assert(
268 sizeof(costMatrix)/sizeof(costMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES * BasicType::NUMBER_OF_BASIC_TYPES,
269 "Missing row in the cost matrix"
270 );
271
272 // GENERATED START, DO NOT EDIT
273 // GENERATED BY BasicTypes-gen.cc
274 static const int signMatrix[BasicType::NUMBER_OF_BASIC_TYPES][BasicType::NUMBER_OF_BASIC_TYPES] = { // number of sign changes in safe conversion
275 /* 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 */
276 /* 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, },
277 /* 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, },
278 /* 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, },
279 /* 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, },
280 /* 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, },
281 /* 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, },
282 /* 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, },
283 /* 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, },
284 /* 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, },
285 /* 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, },
286 /* 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, },
287 /* 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, },
288 /* 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, },
289 /* 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, },
290 /* _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, },
291 /* _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, },
292 /* _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, },
293 /* _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, },
294 /* 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, },
295 /* 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, },
296 /* _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, },
297 /* _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, },
298 /* 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, },
299 /* _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, },
300 /* 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, },
301 /* 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, },
302 /* 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, },
303 /* _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, },
304 /* 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, },
305 /* _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, },
306 /* _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, },
307 /* 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, },
308 /* 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, },
309 /* 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, },
310 /* _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, },
311 /* _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, },
312 }; // signMatrix
313 // GENERATED END
314 static_assert(
315 sizeof(signMatrix)/sizeof(signMatrix[0][0]) == BasicType::NUMBER_OF_BASIC_TYPES * BasicType::NUMBER_OF_BASIC_TYPES,
316 "Missing row in the sign matrix"
317 );
318
319 void ConversionCost::postvisit( const VoidType * ) {
320 cost = Cost::infinity;
321 }
322
323 void ConversionCost::postvisit(const BasicType * basicType) {
324 if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
325 int tableResult = costMatrix[ basicType->kind ][ destAsBasic->kind ];
326 if ( tableResult == -1 ) {
327 cost = Cost::unsafe;
328 } else {
329 cost = Cost::zero;
330 cost.incSafe( tableResult );
331 cost.incSign( signMatrix[ basicType->kind ][ destAsBasic->kind ] );
332 } // if
333 } else if ( dynamic_cast< const EnumInstType * >( dest ) ) {
334 // xxx - not positive this is correct, but appears to allow casting int => enum
335 cost = Cost::unsafe;
336 } // if
337 // no cases for zero_t/one_t because it should not be possible to convert int, etc. to zero_t/one_t.
338 }
339
340 void ConversionCost::postvisit( const PointerType * pointerType ) {
341 if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) {
342 PRINT( std::cerr << pointerType << " ===> " << destAsPtr << std::endl; )
343 Type::Qualifiers tq1 = pointerType->base->tq;
344 Type::Qualifiers tq2 = destAsPtr->base->tq;
345 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
346 PRINT( std::cerr << " :: compatible and good qualifiers" << std::endl; )
347 if ( tq1 == tq2 ) {
348 // types are the same
349 cost = Cost::zero;
350 } else {
351 // types are the same, except otherPointer has more qualifiers
352 cost = Cost::safe;
353 } // if
354 } else {
355 int assignResult = ptrsAssignable( pointerType->base, destAsPtr->base, env );
356 PRINT( std::cerr << " :: " << assignResult << std::endl; )
357 if ( assignResult > 0 && tq1 <= tq2 ) {
358 // 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?
359 if ( tq1 == tq2 ) {
360 cost = Cost::safe;
361 } else if ( tq1 < tq2 ) {
362 cost = Cost::safe+Cost::safe;
363 }
364 } else if ( assignResult < 0 ) {
365 cost = Cost::unsafe;
366 } // if
367 // assignResult == 0 means Cost::Infinity
368 } // if
369 // case case for zero_t because it should not be possible to convert pointers to zero_t.
370 } // if
371 }
372
373 void ConversionCost::postvisit( const ArrayType * ) {}
374
375 void ConversionCost::postvisit( const ReferenceType * refType ) {
376 // Note: dest can never be a reference, since it would have been caught in an earlier check
377 assert( ! dynamic_cast< const ReferenceType * >( dest ) );
378 // convert reference to rvalue: cv T1 & => T2
379 // recursively compute conversion cost from T1 to T2.
380 // cv can be safely dropped because of 'implicit dereference' behavior.
381 cost = costFunc( refType->base, dest, srcIsLvalue, indexer, env );
382 if ( refType->base->tq == dest->tq ) {
383 cost.incReference(); // prefer exact qualifiers
384 } else if ( refType->base->tq < dest->tq ) {
385 cost.incSafe(); // then gaining qualifiers
386 } else {
387 cost.incUnsafe(); // lose qualifiers as last resort
388 }
389 PRINT( std::cerr << refType << " ==> " << dest << " " << cost << std::endl; )
390 }
391
392 void ConversionCost::postvisit( const FunctionType * ) {}
393
394 void ConversionCost::postvisit( const StructInstType * inst ) {
395 /*
396 if ( const StructInstType * destAsInst = dynamic_cast< const StructInstType * >( dest ) ) {
397 if ( inst->name == destAsInst->name ) {
398 cost = Cost::zero;
399 } // if
400 } // if
401 */
402 }
403
404 void ConversionCost::postvisit( const UnionInstType * inst ) {
405 /*
406 if ( const UnionInstType * destAsInst = dynamic_cast< const UnionInstType * >( dest ) ) {
407 if ( inst->name == destAsInst->name ) {
408 cost = Cost::zero;
409 } // if
410 } // if
411 */
412 }
413
414 void ConversionCost::postvisit( const EnumInstType * ) {
415 static Type::Qualifiers q;
416 static BasicType integer( q, BasicType::SignedInt );
417 cost = costFunc( &integer, dest, srcIsLvalue, indexer, env ); // safe if dest >= int
418 if ( cost < Cost::unsafe ) {
419 cost.incSafe();
420 } // if
421 }
422
423 void ConversionCost::postvisit( const TraitInstType * ) {}
424
425 void ConversionCost::postvisit( const TypeInstType * inst ) {
426 if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
427 cost = costFunc( eqvClass->type, dest, srcIsLvalue, indexer, env );
428 } else if ( const TypeInstType * destAsInst = dynamic_cast< const TypeInstType * >( dest ) ) {
429 if ( inst->name == destAsInst->name ) {
430 cost = Cost::zero;
431 }
432 } else if ( const NamedTypeDecl * namedType = indexer.lookupType( inst->name ) ) {
433 const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
434 // all typedefs should be gone by this point
435 assert( type );
436 if ( type->base ) {
437 cost = costFunc( type->base, dest, srcIsLvalue, indexer, env ) + Cost::safe;
438 } // if
439 } // if
440 }
441
442 void ConversionCost::postvisit( const TupleType * tupleType ) {
443 Cost c = Cost::zero;
444 if ( const TupleType * destAsTuple = dynamic_cast< const TupleType * >( dest ) ) {
445 std::list< Type * >::const_iterator srcIt = tupleType->types.begin();
446 std::list< Type * >::const_iterator destIt = destAsTuple->types.begin();
447 while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) {
448 Cost newCost = costFunc( * srcIt++, * destIt++, srcIsLvalue, indexer, env );
449 if ( newCost == Cost::infinity ) {
450 return;
451 } // if
452 c += newCost;
453 } // while
454 if ( destIt != destAsTuple->types.end() ) {
455 cost = Cost::infinity;
456 } else {
457 cost = c;
458 } // if
459 } // if
460 }
461
462 void ConversionCost::postvisit( const VarArgsType * ) {
463 if ( dynamic_cast< const VarArgsType * >( dest ) ) {
464 cost = Cost::zero;
465 }
466 }
467
468 void ConversionCost::postvisit( const ZeroType * ) {
469 if ( dynamic_cast< const ZeroType * >( dest ) ) {
470 cost = Cost::zero;
471 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
472 // copied from visit(BasicType *) for signed int, but +1 for safe conversions
473 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
474 if ( tableResult == -1 ) {
475 cost = Cost::unsafe;
476 } else {
477 cost = Cost::zero;
478 cost.incSafe( tableResult + 1 );
479 cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
480 } // if
481 } else if ( dynamic_cast< const PointerType * >( dest ) ) {
482 cost = Cost::zero;
483 cost.incSafe( maxIntCost + 2 ); // +1 for zero_t -> int, +1 for disambiguation
484 } // if
485 }
486
487 void ConversionCost::postvisit( const OneType * ) {
488 if ( dynamic_cast< const OneType * >( dest ) ) {
489 cost = Cost::zero;
490 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
491 // copied from visit(BasicType *) for signed int, but +1 for safe conversions
492 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
493 if ( tableResult == -1 ) {
494 cost = Cost::unsafe;
495 } else {
496 cost = Cost::zero;
497 cost.incSafe( tableResult + 1 );
498 cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
499 } // if
500 } // if
501 }
502
503namespace {
504 # warning For overload resolution between the two versions.
505 int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,
506 const ast::SymbolTable &, const ast::TypeEnvironment & env ) {
507 return ptrsAssignable( t1, t2, env );
508 }
509 Cost localConversionCost(
510 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
511 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
512 ) { return conversionCost( src, dst, srcIsLvalue, symtab, env ); }
513}
514
515Cost conversionCost(
516 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
517 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
518) {
519 if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
520 if ( const ast::EqvClass * eqv = env.lookup( inst->name ) ) {
521 if ( eqv->bound ) {
522 return conversionCost(src, eqv->bound, srcIsLvalue, symtab, env );
523 } else {
524 return Cost::infinity;
525 }
526 } else if ( const ast::NamedTypeDecl * named = symtab.lookupType( inst->name ) ) {
527 const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( named );
528 assertf( type, "Unexpected typedef." );
529 if ( type->base ) {
530 return conversionCost( src, type->base, srcIsLvalue, symtab, env ) + Cost::safe;
531 }
532 }
533 }
534 if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
535 return Cost::zero;
536 } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
537 return Cost::safe;
538 } else if ( const ast::ReferenceType * refType =
539 dynamic_cast< const ast::ReferenceType * >( dst ) ) {
540 return convertToReferenceCost( src, refType, srcIsLvalue, symtab, env, localPtrsAssignable );
541 } else {
542 ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost );
543 src->accept( converter );
544 return converter.pass.cost;
545 }
546}
547
548static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
549 int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
550 PtrsCalculation func ) {
551 if ( 0 < diff ) {
552 Cost cost = convertToReferenceCost(
553 strict_dynamic_cast< const ast::ReferenceType * >( src )->base, dst,
554 srcIsLvalue, (diff - 1), symtab, env, func );
555 cost.incReference();
556 return cost;
557 } else if ( diff < -1 ) {
558 Cost cost = convertToReferenceCost(
559 src, strict_dynamic_cast< const ast::ReferenceType * >( dst )->base,
560 srcIsLvalue, (diff + 1), symtab, env, func );
561 cost.incReference();
562 return cost;
563 } else if ( 0 == diff ) {
564 const ast::ReferenceType * srcAsRef = dynamic_cast< const ast::ReferenceType * >( src );
565 const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
566 if ( srcAsRef && dstAsRef ) {
567 ast::CV::Qualifiers tq1 = srcAsRef->base->qualifiers;
568 ast::CV::Qualifiers tq2 = dstAsRef->base->qualifiers;
569 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
570 srcAsRef->base, dstAsRef->base, symtab, env ) ) {
571 if ( tq1 == tq2 ) {
572 return Cost::zero;
573 } else {
574 return Cost::safe;
575 }
576 } else {
577 int assignResult = func( srcAsRef->base, dstAsRef->base, symtab, env );
578 if ( 0 < assignResult ) {
579 return Cost::safe;
580 } else if ( assignResult < 0 ) {
581 return Cost::unsafe;
582 }
583 }
584 } else {
585 ast::Pass<ConversionCost_new> converter( dst, srcIsLvalue, symtab, env, localConversionCost );
586 src->accept( converter );
587 return converter.pass.cost;
588 }
589 } else {
590 assert( -1 == diff );
591 const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
592 assert( dstAsRef );
593 if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) {
594 if ( srcIsLvalue ) {
595 if ( src->qualifiers == dstAsRef->base->qualifiers ) {
596 return Cost::reference;
597 } else if ( src->qualifiers < dstAsRef->base->qualifiers ) {
598 return Cost::safe;
599 } else {
600 return Cost::unsafe;
601 }
602 } else if ( dstAsRef->base->is_const() ) {
603 return Cost::safe;
604 } else {
605 return Cost::unsafe;
606 }
607 }
608 }
609 return Cost::infinity;
610}
611
612Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst,
613 bool srcIsLvalue, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
614 PtrsCalculation func ) {
615 int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth();
616 return convertToReferenceCost( src, dst, srcIsLvalue, sdepth - ddepth, symtab, env, func );
617}
618
619void ConversionCost_new::postvisit( const ast::VoidType * voidType ) {
620 (void)voidType;
621 cost = Cost::infinity;
622}
623
624void ConversionCost_new::postvisit( const ast::BasicType * basicType ) {
625 if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) {
626 int tableResult = costMatrix[ basicType->kind ][ dstAsBasic->kind ];
627 if ( tableResult == -1 ) {
628 cost = Cost::unsafe;
629 } else {
630 cost = Cost::zero;
631 cost.incSafe( tableResult );
632 cost.incSign( signMatrix[ basicType->kind ][ dstAsBasic->kind ] );
633 }
634 } else if ( dynamic_cast< const ast::EnumInstType * >( dst ) ) {
635 // xxx - not positive this is correct, but appears to allow casting int => enum
636 cost = Cost::unsafe;
637 }
638}
639
640void ConversionCost_new::postvisit( const ast::PointerType * pointerType ) {
641 if ( const ast::PointerType * dstAsPtr = dynamic_cast< const ast::PointerType * >( dst ) ) {
642 ast::CV::Qualifiers tq1 = pointerType->base->qualifiers;
643 ast::CV::Qualifiers tq2 = dstAsPtr->base->qualifiers;
644 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
645 pointerType->base, dstAsPtr->base, symtab, env ) ) {
646 if ( tq1 == tq2 ) {
647 cost = Cost::zero;
648 } else {
649 cost = Cost::safe;
650 }
651 } else {
652 int assignResult = ptrsAssignable( pointerType->base, dstAsPtr->base, env );
653 if ( 0 < assignResult && tq1 <= tq2 ) {
654 if ( tq1 == tq2 ) {
655 cost = Cost::safe;
656 } else {
657 cost = Cost::safe + Cost::safe;
658 }
659 } else if ( assignResult < 0 ) {
660 cost = Cost::unsafe;
661 } // else Cost::infinity
662 }
663 }
664}
665
666void ConversionCost_new::postvisit( const ast::ArrayType * arrayType ) {
667 (void)arrayType;
668}
669
670void ConversionCost_new::postvisit( const ast::ReferenceType * refType ) {
671 assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) );
672
673 cost = costCalc( refType->base, dst, srcIsLvalue, symtab, env );
674 if ( refType->base->qualifiers == dst->qualifiers ) {
675 cost.incReference();
676 } else if ( refType->base->qualifiers < dst->qualifiers ) {
677 cost.incSafe();
678 } else {
679 cost.incUnsafe();
680 }
681}
682
683void ConversionCost_new::postvisit( const ast::FunctionType * functionType ) {
684 (void)functionType;
685}
686
687void ConversionCost_new::postvisit( const ast::StructInstType * structInstType ) {
688 /*
689 if ( const ast::StructInstType * dstAsInst =
690 dynamic_cast< const ast::StructInstType * >( dst ) ) {
691 if ( structInstType->name == dstAsInst->name ) {
692 cost = Cost::zero;
693 }
694 }
695 */
696}
697
698void ConversionCost_new::postvisit( const ast::UnionInstType * unionInstType ) {
699 /*
700 if ( const ast::UnionInstType * dstAsInst =
701 dynamic_cast< const ast::UnionInstType * >( dst ) ) {
702 if ( unionInstType->name == dstAsInst->name ) {
703 cost = Cost::zero;
704 }
705 }
706 */
707}
708
709void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) {
710 (void)enumInstType;
711 static ast::ptr<ast::BasicType> integer = { new ast::BasicType( ast::BasicType::SignedInt ) };
712 cost = costCalc( integer, dst, srcIsLvalue, symtab, env );
713 if ( cost < Cost::unsafe ) {
714 cost.incSafe();
715 }
716}
717
718void ConversionCost_new::postvisit( const ast::TraitInstType * traitInstType ) {
719 (void)traitInstType;
720}
721
722void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) {
723 if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) {
724 cost = costCalc( eqv->bound, dst, srcIsLvalue, symtab, env );
725 } else if ( const ast::TypeInstType * dstAsInst =
726 dynamic_cast< const ast::TypeInstType * >( dst ) ) {
727 if ( typeInstType->name == dstAsInst->name ) {
728 cost = Cost::zero;
729 }
730 } else if ( const ast::NamedTypeDecl * namedType = symtab.lookupType( typeInstType->name ) ) {
731 const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( namedType );
732 assertf( type, "Unexpected typedef.");
733 if ( type->base ) {
734 cost = costCalc( type->base, dst, srcIsLvalue, symtab, env ) + Cost::safe;
735 }
736 }
737}
738
739void ConversionCost_new::postvisit( const ast::TupleType * tupleType ) {
740 Cost c = Cost::zero;
741 if ( const ast::TupleType * dstAsTuple = dynamic_cast< const ast::TupleType * >( dst ) ) {
742 auto srcIt = tupleType->types.begin();
743 auto dstIt = dstAsTuple->types.begin();
744 auto srcEnd = tupleType->types.end();
745 auto dstEnd = dstAsTuple->types.end();
746 while ( srcIt != srcEnd && dstIt != dstEnd ) {
747 Cost newCost = costCalc( * srcIt++, * dstIt++, srcIsLvalue, symtab, env );
748 if ( newCost == Cost::infinity ) {
749 return;
750 }
751 c += newCost;
752 }
753 if ( dstIt != dstEnd ) {
754 cost = Cost::infinity;
755 } else {
756 cost = c;
757 }
758 }
759}
760
761void ConversionCost_new::postvisit( const ast::VarArgsType * varArgsType ) {
762 (void)varArgsType;
763 if ( dynamic_cast< const ast::VarArgsType * >( dst ) ) {
764 cost = Cost::zero;
765 }
766}
767
768void ConversionCost_new::postvisit( const ast::ZeroType * zeroType ) {
769 (void)zeroType;
770 if ( dynamic_cast< const ast::ZeroType * >( dst ) ) {
771 cost = Cost::zero;
772 } else if ( const ast::BasicType * dstAsBasic =
773 dynamic_cast< const ast::BasicType * >( dst ) ) {
774 int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
775 if ( -1 == tableResult ) {
776 cost = Cost::unsafe;
777 } else {
778 cost = Cost::zero;
779 cost.incSafe( tableResult + 1 );
780 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
781 }
782 } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
783 cost = Cost::zero;
784 // +1 for zero_t ->, +1 for disambiguation
785 cost.incSafe( maxIntCost + 2 );
786 }
787}
788
789void ConversionCost_new::postvisit( const ast::OneType * oneType ) {
790 (void)oneType;
791 if ( dynamic_cast< const ast::OneType * >( dst ) ) {
792 cost = Cost::zero;
793 } else if ( const ast::BasicType * dstAsBasic =
794 dynamic_cast< const ast::BasicType * >( dst ) ) {
795 int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
796 if ( -1 == tableResult ) {
797 cost = Cost::unsafe;
798 } else {
799 cost = Cost::zero;
800 cost.incSafe( tableResult + 1 );
801 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
802 }
803 }
804}
805size_t ConversionCost_new::traceId = Stats::Heap::new_stacktrace_id("ConversionCost");
806
807} // namespace ResolvExpr
808
809// Local Variables: //
810// tab-width: 4 //
811// mode: c++ //
812// compile-command: "make install" //
813// End: //
Note: See TracBrowser for help on using the repository browser.