source: src/ResolvExpr/CastCost.cc @ 123e8b9

Last change on this file since 123e8b9 was eb7586e, checked in by JiadaL <j82liang@…>, 2 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.