source: src/ResolvExpr/ConversionCost.cc@ aca6a54c

ADT arm-eh ast-experimental enum forall-pointer-decay jacob/cs343-translation new-ast-unique-expr pthread-emulation qualifiedEnum
Last change on this file since aca6a54c was 849720f, checked in by Andrew Beach <ajbeach@…>, 6 years ago

lvalue should now always come directly from the expression.

  • Property mode set to 100644
File size: 41.6 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 : Mon Aug 12 10:21:00 2019
13// Update Count : 27
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 if ( const StructInstType * destAsInst = dynamic_cast< const StructInstType * >( dest ) ) {
396 if ( inst->name == destAsInst->name ) {
397 cost = Cost::zero;
398 } // if
399 } // if
400 }
401
402 void ConversionCost::postvisit( const UnionInstType * inst ) {
403 if ( const UnionInstType * destAsInst = dynamic_cast< const UnionInstType * >( dest ) ) {
404 if ( inst->name == destAsInst->name ) {
405 cost = Cost::zero;
406 } // if
407 } // if
408 }
409
410 void ConversionCost::postvisit( const EnumInstType * ) {
411 static Type::Qualifiers q;
412 static BasicType integer( q, BasicType::SignedInt );
413 cost = costFunc( &integer, dest, srcIsLvalue, indexer, env ); // safe if dest >= int
414 if ( cost < Cost::unsafe ) {
415 cost.incSafe();
416 } // if
417 }
418
419 void ConversionCost::postvisit( const TraitInstType * ) {}
420
421 void ConversionCost::postvisit( const TypeInstType * inst ) {
422 if ( const EqvClass * eqvClass = env.lookup( inst->name ) ) {
423 cost = costFunc( eqvClass->type, dest, srcIsLvalue, indexer, env );
424 } else if ( const TypeInstType * destAsInst = dynamic_cast< const TypeInstType * >( dest ) ) {
425 if ( inst->name == destAsInst->name ) {
426 cost = Cost::zero;
427 }
428 } else if ( const NamedTypeDecl * namedType = indexer.lookupType( inst->name ) ) {
429 const TypeDecl * type = dynamic_cast< const TypeDecl * >( namedType );
430 // all typedefs should be gone by this point
431 assert( type );
432 if ( type->base ) {
433 cost = costFunc( type->base, dest, srcIsLvalue, indexer, env ) + Cost::safe;
434 } // if
435 } // if
436 }
437
438 void ConversionCost::postvisit( const TupleType * tupleType ) {
439 Cost c = Cost::zero;
440 if ( const TupleType * destAsTuple = dynamic_cast< const TupleType * >( dest ) ) {
441 std::list< Type * >::const_iterator srcIt = tupleType->types.begin();
442 std::list< Type * >::const_iterator destIt = destAsTuple->types.begin();
443 while ( srcIt != tupleType->types.end() && destIt != destAsTuple->types.end() ) {
444 Cost newCost = costFunc( * srcIt++, * destIt++, srcIsLvalue, indexer, env );
445 if ( newCost == Cost::infinity ) {
446 return;
447 } // if
448 c += newCost;
449 } // while
450 if ( destIt != destAsTuple->types.end() ) {
451 cost = Cost::infinity;
452 } else {
453 cost = c;
454 } // if
455 } // if
456 }
457
458 void ConversionCost::postvisit( const VarArgsType * ) {
459 if ( dynamic_cast< const VarArgsType * >( dest ) ) {
460 cost = Cost::zero;
461 }
462 }
463
464 void ConversionCost::postvisit( const ZeroType * ) {
465 if ( dynamic_cast< const ZeroType * >( dest ) ) {
466 cost = Cost::zero;
467 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
468 // copied from visit(BasicType *) for signed int, but +1 for safe conversions
469 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
470 if ( tableResult == -1 ) {
471 cost = Cost::unsafe;
472 } else {
473 cost = Cost::zero;
474 cost.incSafe( tableResult + 1 );
475 cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
476 } // if
477 } else if ( dynamic_cast< const PointerType * >( dest ) ) {
478 cost = Cost::zero;
479 cost.incSafe( maxIntCost + 2 ); // +1 for zero_t -> int, +1 for disambiguation
480 } // if
481 }
482
483 void ConversionCost::postvisit( const OneType * ) {
484 if ( dynamic_cast< const OneType * >( dest ) ) {
485 cost = Cost::zero;
486 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
487 // copied from visit(BasicType *) for signed int, but +1 for safe conversions
488 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->kind ];
489 if ( tableResult == -1 ) {
490 cost = Cost::unsafe;
491 } else {
492 cost = Cost::zero;
493 cost.incSafe( tableResult + 1 );
494 cost.incSign( signMatrix[ BasicType::SignedInt ][ destAsBasic->kind ] );
495 } // if
496 } // if
497 }
498
499static int localPtrsAssignable(const ast::Type * t1, const ast::Type * t2,
500 const ast::SymbolTable &, const ast::TypeEnvironment & env ) {
501 return ptrsAssignable( t1, t2, env );
502}
503
504// TODO: This is used for overload resolution. It might be able to be dropped once the old system
505// is removed.
506static Cost localConversionCost(
507 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
508 const ast::TypeEnvironment & env
509) { return conversionCost( src, dst, symtab, env ); }
510
511Cost conversionCost(
512 const ast::Type * src, const ast::Type * dst, const ast::SymbolTable & symtab,
513 const ast::TypeEnvironment & env
514) {
515 if ( const ast::TypeInstType * inst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
516 if ( const ast::EqvClass * eqv = env.lookup( inst->name ) ) {
517 if ( eqv->bound ) {
518 return conversionCost(src, eqv->bound, symtab, env );
519 } else {
520 return Cost::infinity;
521 }
522 } else if ( const ast::NamedTypeDecl * named = symtab.lookupType( inst->name ) ) {
523 const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( named );
524 assertf( type, "Unexpected typedef." );
525 if ( type->base ) {
526 return conversionCost( src, type->base, symtab, env ) + Cost::safe;
527 }
528 }
529 }
530 if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
531 return Cost::zero;
532 } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
533 return Cost::safe;
534 } else if ( const ast::ReferenceType * refType =
535 dynamic_cast< const ast::ReferenceType * >( dst ) ) {
536 return convertToReferenceCost( src, refType, symtab, env, localPtrsAssignable );
537 } else {
538 ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost );
539 src->accept( converter );
540 return converter.pass.cost;
541 }
542}
543
544static Cost convertToReferenceCost( const ast::Type * src, const ast::Type * dst,
545 int diff, const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
546 NumCostCalculation func ) {
547 if ( 0 < diff ) {
548 Cost cost = convertToReferenceCost(
549 strict_dynamic_cast< const ast::ReferenceType * >( src )->base,
550 dst, (diff - 1), symtab, env, func );
551 cost.incReference();
552 return cost;
553 } else if ( diff < -1 ) {
554 Cost cost = convertToReferenceCost(
555 src, strict_dynamic_cast< const ast::ReferenceType * >( dst )->base,
556 (diff + 1), symtab, env, func );
557 cost.incReference();
558 return cost;
559 } else if ( 0 == diff ) {
560 const ast::ReferenceType * srcAsRef = dynamic_cast< const ast::ReferenceType * >( src );
561 const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
562 if ( srcAsRef && dstAsRef ) {
563 ast::CV::Qualifiers tq1 = srcAsRef->base->qualifiers;
564 ast::CV::Qualifiers tq2 = dstAsRef->base->qualifiers;
565 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
566 srcAsRef->base, dstAsRef->base, symtab, env ) ) {
567 if ( tq1 == tq2 ) {
568 return Cost::zero;
569 } else {
570 return Cost::safe;
571 }
572 } else {
573 int assignResult = func( srcAsRef->base, dstAsRef->base, symtab, env );
574 if ( 0 < assignResult ) {
575 return Cost::safe;
576 } else if ( assignResult < 0 ) {
577 return Cost::unsafe;
578 }
579 }
580 } else {
581 ast::Pass<ConversionCost_new> converter( dst, symtab, env, localConversionCost );
582 src->accept( converter );
583 return converter.pass.cost;
584 }
585 } else {
586 assert( -1 == diff );
587 const ast::ReferenceType * dstAsRef = dynamic_cast< const ast::ReferenceType * >( dst );
588 assert( dstAsRef );
589 if ( typesCompatibleIgnoreQualifiers( src, dstAsRef->base, symtab, env ) ) {
590 if ( src->is_lvalue() ) {
591 if ( src->qualifiers == dstAsRef->base->qualifiers ) {
592 return Cost::reference;
593 } else if ( src->qualifiers < dstAsRef->base->qualifiers ) {
594 return Cost::safe;
595 } else {
596 return Cost::unsafe;
597 }
598 } else if ( dstAsRef->base->is_const() ) {
599 return Cost::safe;
600 } else {
601 return Cost::unsafe;
602 }
603 }
604 }
605 return Cost::infinity;
606}
607
608Cost convertToReferenceCost( const ast::Type * src, const ast::ReferenceType * dst,
609 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env,
610 NumCostCalculation func ) {
611 int sdepth = src->referenceDepth(), ddepth = dst->referenceDepth();
612 return convertToReferenceCost( src, dst, sdepth - ddepth, symtab, env, func );
613}
614
615void ConversionCost_new::postvisit( const ast::VoidType * voidType ) {
616 (void)voidType;
617 cost = Cost::infinity;
618}
619
620void ConversionCost_new::postvisit( const ast::BasicType * basicType ) {
621 if ( const ast::BasicType * dstAsBasic = dynamic_cast< const ast::BasicType * >( dst ) ) {
622 int tableResult = costMatrix[ basicType->kind ][ dstAsBasic->kind ];
623 if ( tableResult == -1 ) {
624 cost = Cost::unsafe;
625 } else {
626 cost = Cost::zero;
627 cost.incSafe( tableResult );
628 cost.incSign( signMatrix[ basicType->kind ][ dstAsBasic->kind ] );
629 }
630 } else if ( dynamic_cast< const ast::EnumInstType * >( dst ) ) {
631 // xxx - not positive this is correct, but appears to allow casting int => enum
632 cost = Cost::unsafe;
633 }
634}
635
636void ConversionCost_new::postvisit( const ast::PointerType * pointerType ) {
637 if ( const ast::PointerType * dstAsPtr = dynamic_cast< const ast::PointerType * >( dst ) ) {
638 ast::CV::Qualifiers tq1 = pointerType->base->qualifiers;
639 ast::CV::Qualifiers tq2 = dstAsPtr->base->qualifiers;
640 if ( tq1 <= tq2 && typesCompatibleIgnoreQualifiers(
641 pointerType->base, dstAsPtr->base, symtab, env ) ) {
642 if ( tq1 == tq2 ) {
643 cost = Cost::zero;
644 } else {
645 cost = Cost::safe;
646 }
647 } else {
648 int assignResult = ptrsAssignable( pointerType->base, dstAsPtr->base, env );
649 if ( 0 < assignResult && tq1 <= tq2 ) {
650 if ( tq1 == tq2 ) {
651 cost = Cost::safe;
652 } else {
653 cost = Cost::safe + Cost::safe;
654 }
655 } else if ( assignResult < 0 ) {
656 cost = Cost::unsafe;
657 } // else Cost::infinity
658 }
659 }
660}
661
662void ConversionCost_new::postvisit( const ast::ArrayType * arrayType ) {
663 (void)arrayType;
664}
665
666void ConversionCost_new::postvisit( const ast::ReferenceType * refType ) {
667 assert( nullptr == dynamic_cast< const ast::ReferenceType * >( dst ) );
668
669 cost = costCalc( refType->base, dst, symtab, env );
670 if ( refType->base->qualifiers == dst->qualifiers ) {
671 cost.incReference();
672 } else if ( refType->base->qualifiers < dst->qualifiers ) {
673 cost.incSafe();
674 } else {
675 cost.incUnsafe();
676 }
677}
678
679void ConversionCost_new::postvisit( const ast::FunctionType * functionType ) {
680 (void)functionType;
681}
682
683void ConversionCost_new::postvisit( const ast::StructInstType * structInstType ) {
684 if ( const ast::StructInstType * dstAsInst =
685 dynamic_cast< const ast::StructInstType * >( dst ) ) {
686 if ( structInstType->name == dstAsInst->name ) {
687 cost = Cost::zero;
688 }
689 }
690}
691
692void ConversionCost_new::postvisit( const ast::UnionInstType * unionInstType ) {
693 if ( const ast::UnionInstType * dstAsInst =
694 dynamic_cast< const ast::UnionInstType * >( dst ) ) {
695 if ( unionInstType->name == dstAsInst->name ) {
696 cost = Cost::zero;
697 }
698 }
699}
700
701void ConversionCost_new::postvisit( const ast::EnumInstType * enumInstType ) {
702 (void)enumInstType;
703 static const ast::BasicType integer( ast::BasicType::SignedInt );
704 cost = costCalc( &integer, dst, symtab, env );
705 if ( cost < Cost::unsafe ) {
706 cost.incSafe();
707 }
708}
709
710void ConversionCost_new::postvisit( const ast::TraitInstType * traitInstType ) {
711 (void)traitInstType;
712}
713
714void ConversionCost_new::postvisit( const ast::TypeInstType * typeInstType ) {
715 if ( const ast::EqvClass * eqv = env.lookup( typeInstType->name ) ) {
716 cost = costCalc( eqv->bound, dst, symtab, env );
717 } else if ( const ast::TypeInstType * dstAsInst =
718 dynamic_cast< const ast::TypeInstType * >( dst ) ) {
719 if ( typeInstType->name == dstAsInst->name ) {
720 cost = Cost::zero;
721 }
722 } else if ( const ast::NamedTypeDecl * namedType = symtab.lookupType( typeInstType->name ) ) {
723 const ast::TypeDecl * type = dynamic_cast< const ast::TypeDecl * >( namedType );
724 assertf( type, "Unexpected typedef.");
725 if ( type->base ) {
726 cost = costCalc( type->base, dst, symtab, env ) + Cost::safe;
727 }
728 }
729}
730
731void ConversionCost_new::postvisit( const ast::TupleType * tupleType ) {
732 Cost c = Cost::zero;
733 if ( const ast::TupleType * dstAsTuple = dynamic_cast< const ast::TupleType * >( dst ) ) {
734 auto srcIt = tupleType->types.begin();
735 auto dstIt = dstAsTuple->types.begin();
736 auto srcEnd = tupleType->types.end();
737 auto dstEnd = dstAsTuple->types.end();
738 while ( srcIt != srcEnd && dstIt != dstEnd ) {
739 Cost newCost = costCalc( * srcIt++, * dstIt++, symtab, env );
740 if ( newCost == Cost::infinity ) {
741 return;
742 }
743 c += newCost;
744 }
745 if ( dstIt != dstEnd ) {
746 cost = Cost::infinity;
747 } else {
748 cost = c;
749 }
750 }
751}
752
753void ConversionCost_new::postvisit( const ast::VarArgsType * varArgsType ) {
754 (void)varArgsType;
755 if ( dynamic_cast< const ast::VarArgsType * >( dst ) ) {
756 cost = Cost::zero;
757 }
758}
759
760void ConversionCost_new::postvisit( const ast::ZeroType * zeroType ) {
761 (void)zeroType;
762 if ( dynamic_cast< const ast::ZeroType * >( dst ) ) {
763 cost = Cost::zero;
764 } else if ( const ast::BasicType * dstAsBasic =
765 dynamic_cast< const ast::BasicType * >( dst ) ) {
766 int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
767 if ( -1 == tableResult ) {
768 cost = Cost::unsafe;
769 } else {
770 cost = Cost::zero;
771 cost.incSafe( tableResult + 1 );
772 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
773 }
774 }
775}
776
777void ConversionCost_new::postvisit( const ast::OneType * oneType ) {
778 (void)oneType;
779 if ( dynamic_cast< const ast::OneType * >( dst ) ) {
780 cost = Cost::zero;
781 } else if ( const ast::BasicType * dstAsBasic =
782 dynamic_cast< const ast::BasicType * >( dst ) ) {
783 int tableResult = costMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ];
784 if ( -1 == tableResult ) {
785 cost = Cost::unsafe;
786 } else {
787 cost = Cost::zero;
788 cost.incSafe( tableResult + 1 );
789 cost.incSign( signMatrix[ ast::BasicType::SignedInt ][ dstAsBasic->kind ] );
790 }
791 } else if ( dynamic_cast< const ast::PointerType * >( dst ) ) {
792 cost = Cost::zero;
793 cost.incSafe( maxIntCost + 2 );
794 }
795}
796
797
798} // namespace ResolvExpr
799
800// Local Variables: //
801// tab-width: 4 //
802// mode: c++ //
803// compile-command: "make install" //
804// End: //
Note: See TracBrowser for help on using the repository browser.