source: src/ResolvExpr/ConversionCost.cc@ b2e0df3

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 b2e0df3 was e6b42e7, checked in by Andrew Beach <ajbeach@…>, 5 years ago

Added the ast::Pass::read utility. Converted two passes to use its two different uses.

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