source: src/ResolvExpr/ConversionCost.cc@ 3e93c00

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

lvalue is now read through the expression.

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