source: src/ResolvExpr/CastCost.cc@ 1379c96e

Last change on this file since 1379c96e was eb7586e, checked in by JiadaL <j82liang@…>, 18 months ago
  1. Change return value of typed Enum in null context: they now return the position. Therefore, printf with enumeration value will no longer be supported. 2. sout now will return the enumeration value. So sout | enumValue will print what we expect. 3. Provide enum.hfa, which contains traits that related to enum. 4. Implement functions declare in enum.hfa for enum types, so enum type fulfill the traits. Known defeat: error if we use the enum traits on enum types. They work but c compiler gives an warning
  • Property mode set to 100644
File size: 5.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// 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 "CastCost.hpp"
17
18#include <cassert> // for assert
19
20#include "AST/Print.hpp"
21#include "AST/SymbolTable.hpp"
22#include "AST/Type.hpp"
23#include "AST/TypeEnvironment.hpp"
24#include "ConversionCost.h" // for ConversionCost
25#include "Cost.h" // for Cost, Cost::infinity
26#include "ResolvExpr/ConversionCost.h" // for conversionCost
27#include "ResolvExpr/PtrsCastable.hpp" // for ptrsCastable
28#include "ResolvExpr/Unify.h" // for typesCompatibleIgnoreQualifiers
29
30#if 0
31#define PRINT(x) x
32#else
33#define PRINT(x)
34#endif
35
36namespace ResolvExpr {
37
38namespace {
39 struct CastCost : public ConversionCost {
40 using ConversionCost::previsit;
41 using ConversionCost::postvisit;
42
43 CastCost(
44 const ast::Type * dst, bool srcIsLvalue, const ast::SymbolTable & symtab,
45 const ast::TypeEnvironment & env, CostCalculation costFunc )
46 : ConversionCost( dst, srcIsLvalue, symtab, env, costFunc ) {}
47
48 void postvisit( const ast::BasicType * basicType ) {
49 auto ptr = dynamic_cast< const ast::PointerType * >( dst );
50 if ( ptr && basicType->isInteger() ) {
51 // needed for, e.g. unsigned long => void *
52 cost = Cost::unsafe;
53 } else {
54 cost = conversionCost( basicType, dst, srcIsLvalue, symtab, env );
55 if ( Cost::unsafe < cost ) {
56 if (auto enumInst = dynamic_cast<const ast::EnumInstType *>(dst)) {
57 assert(enumInst->base->base);
58 cost = Cost::unsafe;
59 }
60 }
61 }
62 }
63
64 void postvisit( const ast::ZeroType * zero ) {
65 // auto ptr = dynamic_cast< const ast::PointerType * >( dst );
66 // if ( ptr && basicType->isInteger() ) {
67 // // needed for, e.g. unsigned long => void *
68 // cost = Cost::unsafe;
69 // } else {
70 cost = conversionCost( zero, dst, srcIsLvalue, symtab, env );
71 if ( Cost::unsafe < cost ) {
72 if (auto enumInst = dynamic_cast<const ast::EnumInstType *>(dst)) {
73 assert(enumInst->base->base);
74 cost = Cost::unsafe;
75 }
76 }
77 // }
78 }
79
80 void postvisit( const ast::OneType * one ) {
81 // auto ptr = dynamic_cast< const ast::PointerType * >( dst );
82 // if ( ptr && basicType->isInteger() ) {
83 // // needed for, e.g. unsigned long => void *
84 // cost = Cost::unsafe;
85 // } else {
86 cost = conversionCost( one, dst, srcIsLvalue, symtab, env );
87 if ( Cost::unsafe < cost ) {
88 if (auto enumInst = dynamic_cast<const ast::EnumInstType *>(dst)) {
89 assert(enumInst->base->base);
90 cost = Cost::unsafe;
91 }
92 }
93 // }
94 }
95
96 void postvisit( const ast::PointerType * pointerType ) {
97 if ( auto ptr = dynamic_cast< const ast::PointerType * >( dst ) ) {
98 if (
99 pointerType->qualifiers <= ptr->qualifiers
100 && typesCompatibleIgnoreQualifiers( pointerType->base, ptr->base, env )
101 ) {
102 cost = Cost::safe;
103 } else {
104 ast::TypeEnvironment newEnv{ env };
105 if ( auto wParams = pointerType->base.as< ast::FunctionType >() ) {
106 newEnv.add( wParams->forall );
107 }
108 int castResult = ptrsCastable( pointerType->base, ptr->base, symtab, newEnv );
109 if ( castResult > 0 ) {
110 cost = Cost::safe;
111 } else if ( castResult < 0 ) {
112 cost = Cost::infinity;
113 }
114 }
115 } else if ( auto basic = dynamic_cast< const ast::BasicType * >( dst ) ) {
116 if ( basic->isInteger() ) {
117 // necessary for, e.g. void * => unsigned long
118 cost = Cost::unsafe;
119 }
120 }
121 }
122
123 void postvist( const ast::EnumInstType * ) {
124 if ( auto basic = dynamic_cast< const ast::BasicType * >(dst) ) {
125 if ( basic->isInteger() ) cost = Cost::unsafe;
126 }
127 }
128 };
129
130} // anonymous namespace
131
132Cost castCost(
133 const ast::Type * src, const ast::Type * dst, bool srcIsLvalue,
134 const ast::SymbolTable & symtab, const ast::TypeEnvironment & env
135) {
136 if ( auto typeInst = dynamic_cast< const ast::TypeInstType * >( dst ) ) {
137 if ( const ast::EqvClass * eqvClass = env.lookup( *typeInst ) ) {
138 // check cast cost against bound type, if present
139 if ( eqvClass->bound ) {
140 return castCost( src, eqvClass->bound, srcIsLvalue, symtab, env );
141 } else {
142 return Cost::infinity;
143 }
144 } else if ( const ast::NamedTypeDecl * named = symtab.lookupType( typeInst->name ) ) {
145 // all typedefs should be gone by now
146 auto type = strict_dynamic_cast< const ast::TypeDecl * >( named );
147 if ( type->base ) {
148 return castCost( src, type->base, srcIsLvalue, symtab, env ) + Cost::safe;
149 }
150 }
151 }
152
153 PRINT(
154 std::cerr << "castCost ::: src is ";
155 ast::print( std::cerr, src );
156 std::cerr << std::endl << "dest is ";
157 ast::print( std::cerr, dst );
158 std::cerr << std::endl << "env is" << std::endl;
159 ast::print( std::cerr, env, 2 );
160 )
161
162 if ( typesCompatibleIgnoreQualifiers( src, dst, env ) ) {
163 PRINT( std::cerr << "compatible!" << std::endl; )
164 if (dynamic_cast<const ast::ZeroType *>(dst) || dynamic_cast<const ast::OneType *>(dst)) {
165 return Cost::spec;
166 }
167 return Cost::zero;
168 } else if ( dynamic_cast< const ast::VoidType * >( dst ) ) {
169 return Cost::safe;
170 } else if ( auto refType = dynamic_cast< const ast::ReferenceType * >( dst ) ) {
171 PRINT( std::cerr << "conversionCost: dest is reference" << std::endl; )
172 return convertToReferenceCost(
173 src, refType, srcIsLvalue, symtab, env, ptrsCastable );
174 } else {
175 ast::Pass< CastCost > converter(
176 dst, srcIsLvalue, symtab, env, castCost );
177 src->accept( converter );
178 return converter.core.cost;
179 }
180}
181
182} // namespace ResolvExpr
183
184// Local Variables: //
185// tab-width: 4 //
186// mode: c++ //
187// compile-command: "make install" //
188// End: //
Note: See TracBrowser for help on using the repository browser.