source: src/ResolvExpr/CastCost.cc@ fed6a0f

ADT ast-experimental
Last change on this file since fed6a0f was e563edf, checked in by Andrew Beach <ajbeach@…>, 3 years ago

Header Clean-up: Clearing out typeops, moving things to Unify because that header already exist.

  • Property mode set to 100644
File size: 9.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// CastCost.cc --
8//
9// Author : Richard C. Bilson
10// Created On : Sun May 17 06:57:43 2015
11// Last Modified By : Andrew Beach
12// Last Modified On : Tue Oct 4 15:00:00 2019
13// Update Count : 9
14//
15
16#include <cassert> // for assert
17
18#include "AST/Print.hpp"
19#include "AST/SymbolTable.hpp"
20#include "AST/Type.hpp"
21#include "AST/TypeEnvironment.hpp"
22#include "ConversionCost.h" // for ConversionCost
23#include "Cost.h" // for Cost, Cost::infinity
24#include "ResolvExpr/TypeEnvironment.h" // for TypeEnvironment, EqvClass
25#include "ResolvExpr/typeops.h" // for ptrsCastable
26#include "ResolvExpr/Unify.h" // for typesCompatibleIgnoreQualifiers
27#include "SymTab/Indexer.h" // for Indexer
28#include "SynTree/Declaration.h" // for TypeDecl, NamedTypeDecl
29#include "SynTree/Type.h" // for PointerType, Type, TypeInstType
30
31#if 0
32#define PRINT(x) x
33#else
34#define PRINT(x)
35#endif
36
37namespace ResolvExpr {
38 struct CastCost_old : public ConversionCost {
39 public:
40 CastCost_old( const Type * dest, bool srcIsLvalue,
41 const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc );
42
43 using ConversionCost::previsit;
44 using ConversionCost::postvisit;
45 void postvisit( const BasicType * basicType );
46 void postvisit( const PointerType * pointerType );
47 };
48
49 Cost castCost( const Type * src, const Type * dest, bool srcIsLvalue,
50 const SymTab::Indexer &indexer, const TypeEnvironment &env ) {
51 if ( const TypeInstType * destAsTypeInst = dynamic_cast< const TypeInstType * >( dest ) ) {
52 if ( const EqvClass * eqvClass = env.lookup( destAsTypeInst->name ) ) {
53 if ( eqvClass->type ) {
54 return castCost( src, eqvClass->type, srcIsLvalue, indexer, env );
55 } else {
56 return Cost::infinity;
57 }
58 } else if ( const NamedTypeDecl * namedType = indexer.lookupType( destAsTypeInst->name ) ) {
59 // all typedefs should be gone by this point
60 const TypeDecl * type = strict_dynamic_cast< const TypeDecl * >( namedType );
61 if ( type->base ) {
62 return castCost( src, type->base, srcIsLvalue, indexer, env ) + Cost::safe;
63 } // if
64 } // if
65 } // if
66
67 PRINT(
68 std::cerr << "castCost ::: src is ";
69 src->print( std::cerr );
70 std::cerr << std::endl << "dest is ";
71 dest->print( std::cerr );
72 std::cerr << std::endl << "env is" << std::endl;
73 env.print( std::cerr, 8 );
74 )
75
76 if ( typesCompatibleIgnoreQualifiers( src, dest, indexer, env ) ) {
77 PRINT( std::cerr << "compatible!" << std::endl; )
78 return Cost::zero;
79 } else if ( dynamic_cast< const VoidType * >( dest ) ) {
80 return Cost::safe;
81 } else if ( const ReferenceType * refType = dynamic_cast< const ReferenceType * > ( dest ) ) {
82 PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
83 return convertToReferenceCost( src, refType, srcIsLvalue, indexer, env, [](const Type * t1, const Type * t2, const SymTab::Indexer & indexer, const TypeEnvironment & env ) {
84 return ptrsCastable( t1, t2, env, indexer );
85 });
86 } else {
87 PassVisitor<CastCost_old> converter(
88 dest, srcIsLvalue, indexer, env,
89 (Cost (*)( const Type *, const Type *, bool, const SymTab::Indexer &, const TypeEnvironment & ))
90 castCost );
91 src->accept( converter );
92 if ( converter.pass.get_cost() == Cost::infinity ) {
93 return Cost::infinity;
94 } else {
95 // xxx - why are we adding cost 0 here?
96 return converter.pass.get_cost() + Cost::zero;
97 } // if
98 } // if
99 }
100
101 CastCost_old::CastCost_old( const Type * dest, bool srcIsLvalue,
102 const SymTab::Indexer &indexer, const TypeEnvironment &env, CostFunction costFunc )
103 : ConversionCost( dest, srcIsLvalue, indexer, env, costFunc ) {
104 }
105
106 void CastCost_old::postvisit( const BasicType * basicType ) {
107 const PointerType * destAsPointer = dynamic_cast< const PointerType * >( dest );
108 if ( destAsPointer && basicType->isInteger() ) {
109 // necessary for, e.g. unsigned long => void *
110 cost = Cost::unsafe;
111 } else {
112 cost = conversionCost( basicType, dest, srcIsLvalue, indexer, env );
113 } // if
114 }
115
116 void CastCost_old::postvisit( const PointerType * pointerType ) {
117 if ( const PointerType * destAsPtr = dynamic_cast< const PointerType * >( dest ) ) {
118 if ( pointerType->tq <= destAsPtr->tq && typesCompatibleIgnoreQualifiers( pointerType->base, destAsPtr->base, indexer, env ) ) {
119 cost = Cost::safe;
120 } else {
121 TypeEnvironment newEnv( env );
122 newEnv.add( pointerType->forall );
123 newEnv.add( pointerType->base->forall );
124 int castResult = ptrsCastable( pointerType->base, destAsPtr->base, newEnv, indexer );
125 if ( castResult > 0 ) {
126 cost = Cost::safe;
127 } else if ( castResult < 0 ) {
128 cost = Cost::infinity;
129 } // if
130 } // if
131 } else if ( const BasicType * destAsBasic = dynamic_cast< const BasicType * >( dest ) ) {
132 if ( destAsBasic->isInteger() ) {
133 // necessary for, e.g. void * => unsigned long
134 cost = Cost::unsafe;
135 } // if
136 }
137 }
138
139namespace {
140 struct CastCost_new : public ConversionCost_new {
141 using ConversionCost_new::previsit;
142 using ConversionCost_new::postvisit;
143
144 CastCost_new(
145 const ast::Type * dst, bool srcIsLvalue, const ast::SymbolTable & symtab,
146 const ast::TypeEnvironment & env, CostCalculation costFunc )
147 : ConversionCost_new( dst, srcIsLvalue, symtab, env, costFunc ) {}
148
149 void postvisit( const ast::BasicType * basicType ) {
150 auto ptr = dynamic_cast< const ast::PointerType * >( dst );
151 if ( ptr && basicType->isInteger() ) {
152 // needed for, e.g. unsigned long => void *
153 cost = Cost::unsafe;
154 } else {
155 cost = conversionCost( basicType, dst, srcIsLvalue, symtab, env );
156 }
157 }
158
159 void postvisit( const ast::PointerType * pointerType ) {
160 if ( auto ptr = dynamic_cast< const ast::PointerType * >( dst ) ) {
161 if (
162 pointerType->qualifiers <= ptr->qualifiers
163 && typesCompatibleIgnoreQualifiers( pointerType->base, ptr->base, symtab, env )
164 ) {
165 cost = Cost::safe;
166 } else {
167 ast::TypeEnvironment newEnv{ env };
168 if ( auto wParams = pointerType->base.as< ast::FunctionType >() ) {
169 newEnv.add( wParams->forall );
170 }
171 int castResult = ptrsCastable( pointerType->base, ptr->base, symtab, newEnv );
172 if ( castResult > 0 ) {
173 cost = Cost::safe;
174 } else if ( castResult < 0 ) {
175 cost = Cost::infinity;
176 }
177 }
178 } else if ( auto basic = dynamic_cast< const ast::BasicType * >( dst ) ) {
179 if ( basic->isInteger() ) {
180 // necessary for, e.g. void * => unsigned long
181 cost = Cost::unsafe;
182 }
183 }
184 }
185 };
186
187 #warning For overload resolution between the two versions.
188 int localPtrsCastable(const ast::Type * t1, const ast::Type * t2,
189 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env ) {
190 return ptrsCastable( t1, t2, symtab, env );
191 }
192 Cost localCastCost(
193 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
194 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
195 ) { return castCost( src, dst, srcIsLvalue, symtab, env ); }
196} // anonymous namespace
197
198
199
200Cost castCost(
201 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
202 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
203) {
204 if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
205 if ( const ast::EqvClass * eqvClass = env.lookup( *typeInst ) ) {
206 // check cast cost against bound type, if present
207 if ( eqvClass->bound ) {
208 return castCost( src, eqvClass->bound, srcIsLvalue, symtab, env );
209 } else {
210 return Cost::infinity;
211 }
212 } else if ( const ast::NamedTypeDecl * named = symtab.lookupType( typeInst->name ) ) {
213 // all typedefs should be gone by now
214 auto type = strict_dynamic_cast< const ast::TypeDecl * >( named );
215 if ( type->base ) {
216 return castCost( src, type->base, srcIsLvalue, symtab, env ) + Cost::safe;
217 }
218 }
219 }
220
221 PRINT(
222 std::cerr << "castCost ::: src is ";
223 ast::print( std::cerr, src );
224 std::cerr << std::endl << "dest is ";
225 ast::print( std::cerr, dst );
226 std::cerr << std::endl << "env is" << std::endl;
227 ast::print( std::cerr, env, 2 );
228 )
229
230 if ( typesCompatibleIgnoreQualifiers( src, dst, symtab, env ) ) {
231 PRINT( std::cerr << "compatible!" << std::endl; )
232 return Cost::zero;
233 } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
234 return Cost::safe;
235 } else if ( auto refType = dynamic_cast< const ast::ReferenceType * >( dst ) ) {
236 PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
237 #warning cast on ptrsCastable artifact of having two functions, remove when port done
238 return convertToReferenceCost(
239 src, refType, srcIsLvalue, symtab, env, localPtrsCastable );
240 } else {
241 #warning cast on castCost artifact of having two functions, remove when port done
242 ast::Pass< CastCost_new > converter(
243 dst, srcIsLvalue, symtab, env, localCastCost );
244 src->accept( converter );
245 return converter.core.cost;
246 }
247}
248
249} // namespace ResolvExpr
250
251// Local Variables: //
252// tab-width: 4 //
253// mode: c++ //
254// compile-command: "make install" //
255// End: //
Note: See TracBrowser for help on using the repository browser.