source: src/ResolvExpr/ConversionCost.cc@ 65cec25

ADT aaron-thesis arm-eh ast-experimental cleanup-dtors deferred_resn demangler enum forall-pointer-decay jacob/cs343-translation jenkins-sandbox new-ast new-ast-unique-expr new-env no_list persistent-indexer pthread-emulation qualifiedEnum resolv-new with_gc
Last change on this file since 65cec25 was 2463d0e, checked in by Rob Schluntz <rschlunt@…>, 8 years ago

Add conversion & cast cost for reference conversions

  • Property mode set to 100644
File size: 14.1 KB
Line 
1//
2// Cforall Version 1.0.0 Copyright (C) 2015 University of Waterloo
3//
4// The contents of this file are covered under the licence agreement in the
5// file "LICENCE" distributed with Cforall.
6//
7// ConversionCost.cc --
8//
9// Author : Richard C. Bilson
10// Created On : Sun May 17 07:06:19 2015
11// Last Modified By : Peter A. Buhr
12// Last Modified On : Wed Mar 2 17:35:46 2016
13// Update Count : 6
14//
15
16#include "ConversionCost.h"
17#include "typeops.h"
18#include "SynTree/Type.h"
19#include "SynTree/Visitor.h"
20#include "SymTab/Indexer.h"
21
22namespace ResolvExpr {
23 const Cost Cost::zero = Cost( 0, 0, 0 );
24 const Cost Cost::infinity = Cost( -1, -1, -1 );
25
26 Cost conversionCost( Type *src, Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
27 if ( TypeInstType *destAsTypeInst = dynamic_cast< TypeInstType* >( dest ) ) {
28 EqvClass eqvClass;
29 NamedTypeDecl *namedType;
30/// std::cout << "type inst " << destAsTypeInst->get_name();
31 if ( env.lookup( destAsTypeInst->get_name(), eqvClass ) ) {
32 if ( eqvClass.type ) {
33 return conversionCost( src, eqvClass.type, indexer, env );
34 } else {
35 return Cost::infinity;
36 }
37 } else if ( ( namedType = indexer.lookupType( destAsTypeInst->get_name() ) ) ) {
38/// std::cout << " found" << std::endl;
39 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
40 // all typedefs should be gone by this point
41 assert( type );
42 if ( type->get_base() ) {
43 return conversionCost( src, type->get_base(), indexer, env ) + Cost( 0, 0, 1 );
44 } // if
45 } // if
46/// std::cout << " not found" << std::endl;
47 } // if
48/// std::cout << "src is ";
49/// src->print( std::cout );
50/// std::cout << std::endl << "dest is ";
51/// dest->print( std::cout );
52/// std::cout << std::endl << "env is" << std::endl;
53/// env.print( std::cout, 8 );
54 if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
55/// std::cout << "compatible!" << std::endl;
56 return Cost( 0, 0, 0 );
57 } else if ( dynamic_cast< VoidType* >( dest ) ) {
58 return Cost( 0, 0, 1 );
59 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * > ( dest ) ) {
60 // std::cerr << "conversionCost: dest is reference" << std::endl;
61 return convertToReferenceCost( src, refType, indexer, env );
62 } else {
63 ConversionCost converter( dest, indexer, env );
64 src->accept( converter );
65 if ( converter.get_cost() == Cost::infinity ) {
66 return Cost::infinity;
67 } else {
68 return converter.get_cost() + Cost( 0, 0, 0 );
69 } // if
70 } // if
71 }
72
73 Cost convertToReferenceCost( Type * src, ReferenceType * dest, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
74 // std::cerr << "convert to reference cost..." << std::endl;
75 if ( ReferenceType *srcAsRef = dynamic_cast< ReferenceType * >( src ) ) { // pointer-like conversions between references
76 // std::cerr << "converting between references" << std::endl;
77 if ( srcAsRef->get_base()->get_qualifiers() <= dest->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( srcAsRef->get_base(), dest->get_base(), indexer, env ) ) {
78 return Cost( 0, 0, 1 );
79 } else { // xxx - this discards reference qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
80 int assignResult = ptrsAssignable( srcAsRef->get_base(), dest->get_base(), env );
81 if ( assignResult < 0 ) {
82 return Cost( 0, 0, 1 );
83 } else if ( assignResult > 0 ) {
84 return Cost( 1, 0, 0 );
85 } // if
86 } // if
87 } else if ( typesCompatibleIgnoreQualifiers( src, dest->get_base(), indexer, env ) ) {
88 // std::cerr << "converting compatible base type" << std::endl;
89 if ( src->get_lvalue() ) {
90 // std::cerr << "lvalue to reference conversion" << std::endl;
91 // lvalue-to-reference conversion: cv lvalue T => cv T &
92 if ( src->get_qualifiers() == dest->get_base()->get_qualifiers() ) {
93 return Cost( 0, 0, 1 ); // cost needs to be non-zero to add cast
94 } if ( src->get_qualifiers() < dest->get_base()->get_qualifiers() ) {
95 return Cost( 0, 0, 2 ); // cost needs to be higher than previous cast to differentiate adding qualifiers vs. keeping same
96 } else {
97 return Cost( 1, 0, 0 );
98 }
99 } else if ( dest->get_base()->get_const() ) {
100 // std::cerr << "rvalue to const ref conversion" << std::endl;
101 // rvalue-to-const-reference conversion: T => const T &
102 return Cost( 0, 0, 1 );
103 } else {
104 // std::cerr << "rvalue to non-const reference conversion" << std::endl;
105 // rvalue-to-reference conversion: T => T &
106 return Cost( 1, 0, 0 );
107 }
108 } else {
109 // std::cerr << "attempting to convert from incompatible base type -- fail" << std::endl;
110 }
111 return Cost::infinity;
112 }
113
114 ConversionCost::ConversionCost( Type *dest, const SymTab::Indexer &indexer, const TypeEnvironment &env )
115 : dest( dest ), indexer( indexer ), cost( Cost::infinity ), env( env ) {
116 }
117
118/*
119 Old
120 ===
121 Double
122 |
123 Float
124 |
125 ULong
126 / \
127 UInt Long
128 \ /
129 Int
130 |
131 Ushort
132 |
133 Short
134 |
135 Uchar
136 / \
137 Schar Char
138
139 New
140 ===
141 +-----LongDoubleComplex--+
142 LongDouble--+ | +-LongDoubleImag
143 | +---DoubleComplex---+ |
144 Double------+ | +----DoubleImag
145 | +-FloatComplex-+ |
146 Float---------+ +-------FloatImag
147 |
148 ULongLong
149 |
150 LongLong
151 |
152 ULong
153 / \
154 UInt Long
155 \ /
156 Int
157 |
158 Ushort
159 |
160 Short
161 |
162 Uchar
163 / \
164 Schar Char
165 \ /
166 Bool
167*/
168
169 static const int costMatrix[ BasicType::NUMBER_OF_BASIC_TYPES ][ BasicType::NUMBER_OF_BASIC_TYPES ] =
170 {
171 /* Src \ Dest: Bool Char SChar UChar Short UShort Int UInt Long ULong LLong ULLong Float Double LDbl FCplex DCplex LDCplex FImag DImag LDImag */
172 /* Bool */ { 0, 1, 1, 2, 3, 4, 5, 6, 6, 7, 8, 9, 10, 11, 12, 11, 12, 13, -1, -1, -1 },
173 /* Char */ { -1, 0, -1, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10, 11, 10, 11, 12, -1, -1, -1 },
174 /* SChar */ { -1, -1, 0, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10, 11, 10, 11, 12, -1, -1, -1 },
175 /* UChar */ { -1, -1, -1, 0, 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10, 9, 10, 11, -1, -1, -1 },
176 /* Short */ { -1, -1, -1, -1, 0, 1, 2, 3, 3, 4, 5, 6, 7, 8, 9, 8, 9, 10, -1, -1, -1 },
177 /* UShort */{ -1, -1, -1, -1, -1, 0, 1, 2, 2, 3, 4, 5, 6, 7, 8, 7, 8, 9, -1, -1, -1 },
178 /* Int */ { -1, -1, -1, -1, -1, -1, 0, 1, 1, 2, 3, 4, 5, 6, 7, 6, 7, 8, -1, -1, -1 },
179 /* UInt */ { -1, -1, -1, -1, -1, -1, -1, 0, -1, 1, 2, 3, 4, 5, 6, 5, 6, 7, -1, -1, -1 },
180 /* Long */ { -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 5, 6, 7, -1, -1, -1 },
181 /* ULong */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 4, 5, 6, -1, -1, -1 },
182 /* LLong */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 3, 4, 5, -1, -1, -1 },
183 /* ULLong */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 2, 3, 4, -1, -1, -1 },
184 /* Float */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 1, 2, 3, -1, -1, -1 },
185 /* Double */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, 1, 2, -1, -1, -1 },
186 /* LDbl */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, 1, -1, -1, -1 },
187 /* FCplex */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, -1, -1, -1 },
188 /* DCplex */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, -1, -1, -1 },
189 /* LDCplex */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, -1, -1, -1 },
190 /* FImag */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, 3, 0, 1, 2 },
191 /* DImag */ { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 2, -1, 0, 1 },
192 /* LDImag */{ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, -1, 0 }
193 };
194
195 void ConversionCost::visit( __attribute((unused)) VoidType *voidType ) {
196 cost = Cost::infinity;
197 }
198
199 void ConversionCost::visit(BasicType *basicType) {
200 if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
201 int tableResult = costMatrix[ basicType->get_kind() ][ destAsBasic->get_kind() ];
202 if ( tableResult == -1 ) {
203 cost = Cost( 1, 0, 0 );
204 } else {
205 cost = Cost( 0, 0, tableResult );
206 } // if
207 } else if ( dynamic_cast< EnumInstType *>( dest ) ) {
208 // xxx - not positive this is correct, but appears to allow casting int => enum
209 cost = Cost( 1, 0, 0 );
210 } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) {
211 cost = Cost( 1, 0, 0 );
212 } // if
213 }
214
215 void ConversionCost::visit(PointerType *pointerType) {
216 if ( PointerType *destAsPtr = dynamic_cast< PointerType* >( dest ) ) {
217 if ( pointerType->get_base()->get_qualifiers() <= destAsPtr->get_base()->get_qualifiers() && typesCompatibleIgnoreQualifiers( pointerType->get_base(), destAsPtr->get_base(), indexer, env ) ) {
218 cost = Cost( 0, 0, 1 );
219 } else { // xxx - this discards pointer qualifiers from consideration -- reducing qualifiers is a safe conversion; is this right?
220 int assignResult = ptrsAssignable( pointerType->get_base(), destAsPtr->get_base(), env );
221 if ( assignResult < 0 ) {
222 cost = Cost( 0, 0, 1 );
223 } else if ( assignResult > 0 ) {
224 cost = Cost( 1, 0, 0 );
225 } // if
226 } // if
227 } else if ( dynamic_cast< ZeroType* >( dest ) != nullptr || dynamic_cast< OneType* >( dest ) != nullptr ) {
228 cost = Cost( 1, 0, 0 );
229 } // if
230 }
231
232 void ConversionCost::visit(__attribute((unused)) ArrayType *arrayType) {}
233
234 void ConversionCost::visit(ReferenceType *refType) {
235 // Note: dest can never be a reference, since it would have been caught in an earlier check
236 assert( ! dynamic_cast< ReferenceType * >( dest ) );
237 // convert reference to rvalue: cv T1 & => T2
238 // recursively compute conversion cost from T1 to T2.
239 // cv can be safely dropped because of 'implicit dereference' behavior.
240 refType->get_base()->accept( *this );
241 }
242
243 void ConversionCost::visit(__attribute((unused)) FunctionType *functionType) {}
244
245 void ConversionCost::visit(StructInstType *inst) {
246 if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) {
247 if ( inst->get_name() == destAsInst->get_name() ) {
248 cost = Cost::zero;
249 } // if
250 } // if
251 }
252
253 void ConversionCost::visit(UnionInstType *inst) {
254 if ( StructInstType *destAsInst = dynamic_cast< StructInstType* >( dest ) ) {
255 if ( inst->get_name() == destAsInst->get_name() ) {
256 cost = Cost::zero;
257 } // if
258 } // if
259 }
260
261 void ConversionCost::visit( __attribute((unused)) EnumInstType *inst ) {
262 static Type::Qualifiers q;
263 static BasicType integer( q, BasicType::SignedInt );
264 integer.accept( *this ); // safe if dest >= int
265 if ( cost < Cost( 1, 0, 0 ) ) {
266 cost.incSafe();
267 } // if
268 }
269
270 void ConversionCost::visit( __attribute((unused)) TraitInstType *inst) {
271 }
272
273 void ConversionCost::visit(TypeInstType *inst) {
274 EqvClass eqvClass;
275 NamedTypeDecl *namedType;
276 if ( env.lookup( inst->get_name(), eqvClass ) ) {
277 cost = conversionCost( eqvClass.type, dest, indexer, env );
278 } else if ( TypeInstType *destAsInst = dynamic_cast< TypeInstType* >( dest ) ) {
279 if ( inst->get_name() == destAsInst->get_name() ) {
280 cost = Cost::zero;
281 }
282 } else if ( ( namedType = indexer.lookupType( inst->get_name() ) ) ) {
283 TypeDecl *type = dynamic_cast< TypeDecl* >( namedType );
284 // all typedefs should be gone by this point
285 assert( type );
286 if ( type->get_base() ) {
287 cost = conversionCost( type->get_base(), dest, indexer, env ) + Cost( 0, 0, 1 );
288 } // if
289 } // if
290 }
291
292 void ConversionCost::visit( __attribute((unused)) TupleType *tupleType) {
293 Cost c;
294 if ( TupleType *destAsTuple = dynamic_cast< TupleType* >( dest ) ) {
295 std::list< Type* >::const_iterator srcIt = tupleType->get_types().begin();
296 std::list< Type* >::const_iterator destIt = destAsTuple->get_types().begin();
297 while ( srcIt != tupleType->get_types().end() && destIt != destAsTuple->get_types().end() ) {
298 Cost newCost = conversionCost( *srcIt++, *destIt++, indexer, env );
299 if ( newCost == Cost::infinity ) {
300 return;
301 } // if
302 c += newCost;
303 } // while
304 if ( destIt != destAsTuple->get_types().end() ) {
305 cost = Cost::infinity;
306 } else {
307 cost = c;
308 } // if
309 } // if
310 }
311
312 void ConversionCost::visit( __attribute((unused)) VarArgsType *varArgsType) {
313 if ( dynamic_cast< VarArgsType* >( dest ) ) {
314 cost = Cost::zero;
315 }
316 }
317
318 void ConversionCost::visit( __attribute((unused)) ZeroType *zeroType) {
319 if ( dynamic_cast< ZeroType* >( dest ) ) {
320 cost = Cost::zero;
321 } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
322 // copied from visit(BasicType*) for signed int, but +1 for safe conversions
323 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
324 if ( tableResult == -1 ) {
325 cost = Cost( 1, 0, 0 );
326 } else {
327 cost = Cost( 0, 0, tableResult + 1 );
328 }
329 } else if ( dynamic_cast< PointerType* >( dest ) ) {
330 cost = Cost( 0, 0, 1 );
331 }
332 }
333
334 void ConversionCost::visit( __attribute((unused)) OneType *oneType) {
335 if ( dynamic_cast< OneType* >( dest ) ) {
336 cost = Cost::zero;
337 } else if ( BasicType *destAsBasic = dynamic_cast< BasicType* >( dest ) ) {
338 // copied from visit(BasicType*) for signed int, but +1 for safe conversions
339 int tableResult = costMatrix[ BasicType::SignedInt ][ destAsBasic->get_kind() ];
340 if ( tableResult == -1 ) {
341 cost = Cost( 1, 0, 0 );
342 } else {
343 cost = Cost( 0, 0, tableResult + 1 );
344 }
345 }
346 }
347} // namespace ResolvExpr
348
349// Local Variables: //
350// tab-width: 4 //
351// mode: c++ //
352// compile-command: "make install" //
353// End: //
Note: See TracBrowser for help on using the repository browser.