| [51587aa] | 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 | //
 | 
|---|
| [906e24d] | 7 | // Lvalue.cc --
 | 
|---|
| [51587aa] | 8 | //
 | 
|---|
 | 9 | // Author           : Richard C. Bilson
 | 
|---|
 | 10 | // Created On       : Mon May 18 07:44:20 2015
 | 
|---|
| [01aeade] | 11 | // Last Modified By : Peter A. Buhr
 | 
|---|
| [615a096] | 12 | // Last Modified On : Fri Mar 17 09:11:18 2017
 | 
|---|
 | 13 | // Update Count     : 5
 | 
|---|
| [51587aa] | 14 | //
 | 
|---|
| [51b73452] | 15 | 
 | 
|---|
| [e3e16bc] | 16 | #include <cassert>                       // for strict_dynamic_cast
 | 
|---|
| [08fc48f] | 17 | #include <string>                        // for string
 | 
|---|
| [51b73452] | 18 | 
 | 
|---|
| [8135d4c] | 19 | #include "Common/PassVisitor.h"
 | 
|---|
| [08fc48f] | 20 | #include "Common/SemanticError.h"        // for SemanticError
 | 
|---|
 | 21 | #include "GenPoly.h"                     // for isPolyType
 | 
|---|
| [51b73452] | 22 | #include "Lvalue.h"
 | 
|---|
 | 23 | 
 | 
|---|
| [08fc48f] | 24 | #include "Parser/LinkageSpec.h"          // for Spec, isBuiltin, Intrinsic
 | 
|---|
 | 25 | #include "ResolvExpr/TypeEnvironment.h"  // for AssertionSet, OpenVarSet
 | 
|---|
 | 26 | #include "ResolvExpr/Unify.h"            // for unify
 | 
|---|
| [51b73452] | 27 | #include "ResolvExpr/typeops.h"
 | 
|---|
| [8135d4c] | 28 | #include "SymTab/Autogen.h"
 | 
|---|
| [08fc48f] | 29 | #include "SymTab/Indexer.h"              // for Indexer
 | 
|---|
 | 30 | #include "SynTree/Declaration.h"         // for Declaration, FunctionDecl
 | 
|---|
 | 31 | #include "SynTree/Expression.h"          // for Expression, ConditionalExpr
 | 
|---|
 | 32 | #include "SynTree/Mutator.h"             // for mutateAll, Mutator
 | 
|---|
 | 33 | #include "SynTree/Statement.h"           // for ReturnStmt, Statement (ptr o...
 | 
|---|
 | 34 | #include "SynTree/Type.h"                // for PointerType, Type, FunctionType
 | 
|---|
 | 35 | #include "SynTree/Visitor.h"             // for Visitor, acceptAll
 | 
|---|
| [1d776fd] | 36 | 
 | 
|---|
| [cb43451] | 37 | #if 0
 | 
|---|
 | 38 | #define PRINT(x) x
 | 
|---|
 | 39 | #else
 | 
|---|
 | 40 | #define PRINT(x)
 | 
|---|
 | 41 | #endif
 | 
|---|
 | 42 | 
 | 
|---|
| [51b73452] | 43 | namespace GenPoly {
 | 
|---|
| [01aeade] | 44 |         namespace {
 | 
|---|
| [9a34b5a] | 45 |                 // TODO: fold this into the general createDeref function??
 | 
|---|
 | 46 |                 Expression * mkDeref( Expression * arg ) {
 | 
|---|
 | 47 |                         if ( SymTab::dereferenceOperator ) {
 | 
|---|
 | 48 |                                 VariableExpr * deref = new VariableExpr( SymTab::dereferenceOperator );
 | 
|---|
 | 49 |                                 deref->set_result( new PointerType( Type::Qualifiers(), deref->get_result() ) );
 | 
|---|
 | 50 |                                 Type * base = InitTweak::getPointerBase( arg->get_result() );
 | 
|---|
 | 51 |                                 assertf( base, "expected pointer type in dereference (type was %s)", toString( arg->get_result() ).c_str() );
 | 
|---|
 | 52 |                                 ApplicationExpr * ret = new ApplicationExpr( deref, { arg } );
 | 
|---|
 | 53 |                                 delete ret->get_result();
 | 
|---|
| [8499c707] | 54 |                                 ret->set_result( base->clone() );
 | 
|---|
 | 55 |                                 ret->get_result()->set_lvalue( true );
 | 
|---|
| [9a34b5a] | 56 |                                 return ret;
 | 
|---|
 | 57 |                         } else {
 | 
|---|
 | 58 |                                 return UntypedExpr::createDeref( arg );
 | 
|---|
 | 59 |                         }
 | 
|---|
 | 60 |                 }
 | 
|---|
 | 61 | 
 | 
|---|
| [1d776fd] | 62 |                 struct ReferenceConversions final {
 | 
|---|
 | 63 |                         Expression * postmutate( CastExpr * castExpr );
 | 
|---|
| [8a6cf7e] | 64 |                         Expression * postmutate( AddressExpr * addrExpr );
 | 
|---|
| [01aeade] | 65 |                 };
 | 
|---|
 | 66 | 
 | 
|---|
| [1d776fd] | 67 |                 /// Intrinsic functions that take reference parameters don't REALLY take reference parameters -- their reference arguments must always be implicitly dereferenced.
 | 
|---|
 | 68 |                 struct FixIntrinsicArgs final {
 | 
|---|
| [8499c707] | 69 |                         Expression * postmutate( ApplicationExpr * appExpr );
 | 
|---|
| [1d776fd] | 70 |                 };
 | 
|---|
 | 71 | 
 | 
|---|
| [9aaac6e9] | 72 |                 struct FixIntrinsicResult final : public WithGuards {
 | 
|---|
| [8499c707] | 73 |                         Expression * postmutate( ApplicationExpr * appExpr );
 | 
|---|
| [9aaac6e9] | 74 |                         void premutate( FunctionDecl * funcDecl );
 | 
|---|
 | 75 |                         bool inIntrinsic = false;
 | 
|---|
| [8499c707] | 76 |                 };
 | 
|---|
| [1d776fd] | 77 | 
 | 
|---|
 | 78 |                 /// Replace reference types with pointer types
 | 
|---|
 | 79 |                 struct ReferenceTypeElimination final {
 | 
|---|
 | 80 |                         Type * postmutate( ReferenceType * refType );
 | 
|---|
| [01aeade] | 81 |                 };
 | 
|---|
| [b6fd751] | 82 | 
 | 
|---|
 | 83 |                 /// GCC-like Generalized Lvalues (which have since been removed from GCC)
 | 
|---|
 | 84 |                 /// https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Lvalues.html#Lvalues
 | 
|---|
 | 85 |                 /// Replaces &(a,b) with (a, &b), &(a ? b : c) with (a ? &b : &c)
 | 
|---|
| [d335627] | 86 |                 struct GeneralizedLvalue final : public WithVisitorRef<GeneralizedLvalue> {
 | 
|---|
| [1d776fd] | 87 |                         Expression * postmutate( AddressExpr * addressExpr );
 | 
|---|
| [9236060] | 88 |                         Expression * postmutate( MemberExpr * memExpr );
 | 
|---|
| [acd7c5dd] | 89 | 
 | 
|---|
 | 90 |                         template<typename Func>
 | 
|---|
 | 91 |                         Expression * applyTransformation( Expression * expr, Expression * arg, Func mkExpr );
 | 
|---|
| [b6fd751] | 92 |                 };
 | 
|---|
| [cb43451] | 93 | 
 | 
|---|
 | 94 |                 /// Removes redundant &*/*& pattern that this pass can generate
 | 
|---|
 | 95 |                 struct CollapseAddrDeref final {
 | 
|---|
 | 96 |                         Expression * postmutate( AddressExpr * addressExpr );
 | 
|---|
 | 97 |                         Expression * postmutate( ApplicationExpr * appExpr );
 | 
|---|
 | 98 |                 };
 | 
|---|
| [8499c707] | 99 | 
 | 
|---|
 | 100 |                 struct AddrRef final : public WithGuards {
 | 
|---|
 | 101 |                         void premutate( AddressExpr * addrExpr );
 | 
|---|
 | 102 |                         Expression * postmutate( AddressExpr * addrExpr );
 | 
|---|
 | 103 |                         void premutate( Expression * expr );
 | 
|---|
 | 104 | 
 | 
|---|
 | 105 |                         bool first = true;
 | 
|---|
 | 106 |                         bool current = false;
 | 
|---|
 | 107 |                         int refDepth = 0;
 | 
|---|
 | 108 |                 };
 | 
|---|
| [01aeade] | 109 |         } // namespace
 | 
|---|
 | 110 | 
 | 
|---|
| [b0440b7] | 111 |         static bool referencesEliminated = false;
 | 
|---|
 | 112 |         // used by UntypedExpr::createDeref to determine whether result type of dereference should be ReferenceType or value type.
 | 
|---|
 | 113 |         bool referencesPermissable() {
 | 
|---|
 | 114 |                 return ! referencesEliminated;
 | 
|---|
 | 115 |         }
 | 
|---|
 | 116 | 
 | 
|---|
| [01aeade] | 117 |         void convertLvalue( std::list< Declaration* >& translationUnit ) {
 | 
|---|
| [1d776fd] | 118 |                 PassVisitor<ReferenceConversions> refCvt;
 | 
|---|
 | 119 |                 PassVisitor<ReferenceTypeElimination> elim;
 | 
|---|
 | 120 |                 PassVisitor<GeneralizedLvalue> genLval;
 | 
|---|
 | 121 |                 PassVisitor<FixIntrinsicArgs> fixer;
 | 
|---|
| [cb43451] | 122 |                 PassVisitor<CollapseAddrDeref> collapser;
 | 
|---|
| [8499c707] | 123 |                 PassVisitor<AddrRef> addrRef;
 | 
|---|
 | 124 |                 PassVisitor<FixIntrinsicResult> intrinsicResults;
 | 
|---|
 | 125 |                 mutateAll( translationUnit, intrinsicResults );
 | 
|---|
 | 126 |                 mutateAll( translationUnit, addrRef );
 | 
|---|
| [1d776fd] | 127 |                 mutateAll( translationUnit, refCvt );
 | 
|---|
 | 128 |                 mutateAll( translationUnit, fixer );
 | 
|---|
| [cb43451] | 129 |                 mutateAll( translationUnit, collapser );
 | 
|---|
| [8499c707] | 130 |                 mutateAll( translationUnit, genLval );
 | 
|---|
| [8a6cf7e] | 131 |                 mutateAll( translationUnit, elim );  // last because other passes need reference types to work
 | 
|---|
| [b0440b7] | 132 | 
 | 
|---|
 | 133 |                 // from this point forward, no other pass should create reference types.
 | 
|---|
 | 134 |                 referencesEliminated = true;
 | 
|---|
| [01aeade] | 135 |         }
 | 
|---|
 | 136 | 
 | 
|---|
| [acd7c5dd] | 137 |         Expression * generalizedLvalue( Expression * expr ) {
 | 
|---|
| [9236060] | 138 |                 PassVisitor<GeneralizedLvalue> genLval;
 | 
|---|
| [acd7c5dd] | 139 |                 return expr->acceptMutator( genLval );
 | 
|---|
 | 140 |         }
 | 
|---|
 | 141 | 
 | 
|---|
| [01aeade] | 142 |         namespace {
 | 
|---|
| [8a6cf7e] | 143 |                 // true for intrinsic function calls that return a reference
 | 
|---|
| [1d776fd] | 144 |                 bool isIntrinsicReference( Expression * expr ) {
 | 
|---|
| [8a6cf7e] | 145 |                         if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) {
 | 
|---|
 | 146 |                                 std::string fname = InitTweak::getFunctionName( untyped );
 | 
|---|
 | 147 |                                 // known intrinsic-reference prelude functions
 | 
|---|
 | 148 |                                 return fname == "*?" || fname == "?[?]";
 | 
|---|
| [1d776fd] | 149 |                         } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) {
 | 
|---|
 | 150 |                                 if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) {
 | 
|---|
| [8a6cf7e] | 151 |                                         // use type of return variable rather than expr result type, since it may have been changed to a pointer type
 | 
|---|
 | 152 |                                         FunctionType * ftype = GenPoly::getFunctionType( func->get_type() );
 | 
|---|
 | 153 |                                         Type * ret = ftype->get_returnVals().empty() ? nullptr : ftype->get_returnVals().front()->get_type();
 | 
|---|
 | 154 |                                         return func->get_linkage() == LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret );
 | 
|---|
| [1d776fd] | 155 |                                 }
 | 
|---|
| [ce8c12f] | 156 |                         }
 | 
|---|
| [1d776fd] | 157 |                         return false;
 | 
|---|
| [ce8c12f] | 158 |                 }
 | 
|---|
 | 159 | 
 | 
|---|
| [8499c707] | 160 |                 Expression * FixIntrinsicResult::postmutate( ApplicationExpr * appExpr ) {
 | 
|---|
 | 161 |                         if ( isIntrinsicReference( appExpr ) ) {
 | 
|---|
 | 162 |                                 // eliminate reference types from intrinsic applications - now they return lvalues
 | 
|---|
 | 163 |                                 Type * result = appExpr->get_result();
 | 
|---|
 | 164 |                                 appExpr->set_result( result->stripReferences()->clone() );
 | 
|---|
 | 165 |                                 appExpr->get_result()->set_lvalue( true );
 | 
|---|
| [9aaac6e9] | 166 |                                 if ( ! inIntrinsic ) {
 | 
|---|
 | 167 |                                         // when not in an intrinsic function, add a cast to
 | 
|---|
 | 168 |                                         // don't add cast when in an intrinsic function, since they already have the cast
 | 
|---|
 | 169 |                                         Expression * ret = new CastExpr( appExpr, result );
 | 
|---|
 | 170 |                                         ret->set_env( appExpr->get_env() );
 | 
|---|
 | 171 |                                         appExpr->set_env( nullptr );
 | 
|---|
 | 172 |                                         return ret;
 | 
|---|
 | 173 |                                 }
 | 
|---|
 | 174 |                                 delete result;
 | 
|---|
| [8499c707] | 175 |                         }
 | 
|---|
 | 176 |                         return appExpr;
 | 
|---|
 | 177 |                 }
 | 
|---|
 | 178 | 
 | 
|---|
| [9aaac6e9] | 179 |                 void FixIntrinsicResult::premutate( FunctionDecl * funcDecl ) {
 | 
|---|
 | 180 |                         GuardValue( inIntrinsic );
 | 
|---|
 | 181 |                         inIntrinsic =  funcDecl->linkage == LinkageSpec::Intrinsic;
 | 
|---|
 | 182 |                 }
 | 
|---|
 | 183 | 
 | 
|---|
| [1d776fd] | 184 |                 Expression * FixIntrinsicArgs::postmutate( ApplicationExpr * appExpr ) {
 | 
|---|
| [9a34b5a] | 185 |                         // intrinsic functions don't really take reference-typed parameters, so they require an implicit dereference on their arguments.
 | 
|---|
| [1d776fd] | 186 |                         if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) {
 | 
|---|
| [d335627] | 187 |                                 FunctionType * ftype = GenPoly::getFunctionType( function->get_type() );
 | 
|---|
 | 188 |                                 assertf( ftype, "Function declaration does not have function type." );
 | 
|---|
 | 189 |                                 // can be of differing lengths only when function is variadic
 | 
|---|
 | 190 |                                 assertf( ftype->get_parameters().size() == appExpr->get_args().size() || ftype->get_isVarArgs(), "ApplicationExpr args do not match formal parameter type." );
 | 
|---|
| [b0440b7] | 191 | 
 | 
|---|
 | 192 | 
 | 
|---|
| [d335627] | 193 |                                 unsigned int i = 0;
 | 
|---|
 | 194 |                                 const unsigned int end = ftype->get_parameters().size();
 | 
|---|
 | 195 |                                 for ( auto p : unsafe_group_iterate( appExpr->get_args(), ftype->get_parameters() ) ) {
 | 
|---|
 | 196 |                                         if (i == end) break;
 | 
|---|
 | 197 |                                         Expression *& arg = std::get<0>( p );
 | 
|---|
 | 198 |                                         Type * formal = std::get<1>( p )->get_type();
 | 
|---|
 | 199 |                                         PRINT(
 | 
|---|
 | 200 |                                                 std::cerr << "pair<0>: " << arg << std::endl;
 | 
|---|
 | 201 |                                                 std::cerr << "pair<1>: " << formal << std::endl;
 | 
|---|
 | 202 |                                         )
 | 
|---|
 | 203 |                                         if ( dynamic_cast<ReferenceType*>( formal ) ) {
 | 
|---|
| [8499c707] | 204 |                                                 if ( isIntrinsicReference( arg ) ) { // do not combine conditions, because that changes the meaning of the else if
 | 
|---|
| [d335627] | 205 |                                                         if ( function->get_linkage() != LinkageSpec::Intrinsic ) { // intrinsic functions that turn pointers into references
 | 
|---|
 | 206 |                                                                 // if argument is dereference or array subscript, the result isn't REALLY a reference, so it's not necessary to fix the argument
 | 
|---|
| [8499c707] | 207 |                                                                 PRINT(
 | 
|---|
 | 208 |                                                                         std::cerr << "===is intrinsic arg in non-intrinsic call - adding address" << std::endl;
 | 
|---|
 | 209 |                                                                 )
 | 
|---|
| [d335627] | 210 |                                                                 arg = new AddressExpr( arg );
 | 
|---|
 | 211 |                                                         }
 | 
|---|
 | 212 |                                                 } else if ( function->get_linkage() == LinkageSpec::Intrinsic ) {
 | 
|---|
| [8499c707] | 213 |                                                         // std::cerr << "===adding deref to arg" << std::endl;
 | 
|---|
| [d335627] | 214 |                                                         // if the parameter is a reference, add a dereference to the reference-typed argument.
 | 
|---|
 | 215 |                                                         Type * baseType = InitTweak::getPointerBase( arg->get_result() );
 | 
|---|
| [8499c707] | 216 |                                                         assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ).c_str() );
 | 
|---|
| [d335627] | 217 |                                                         PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() );
 | 
|---|
 | 218 |                                                         delete arg->get_result();
 | 
|---|
 | 219 |                                                         arg->set_result( ptrType );
 | 
|---|
 | 220 |                                                         arg = mkDeref( arg );
 | 
|---|
| [1d776fd] | 221 |                                                 }
 | 
|---|
 | 222 |                                         }
 | 
|---|
| [d335627] | 223 |                                         ++i;
 | 
|---|
| [baba5d8] | 224 |                                 }
 | 
|---|
| [1d776fd] | 225 |                         }
 | 
|---|
 | 226 |                         return appExpr;
 | 
|---|
| [01aeade] | 227 |                 }
 | 
|---|
 | 228 | 
 | 
|---|
| [8499c707] | 229 |                 // idea: &&&E: get outer &, inner &
 | 
|---|
 | 230 |                 // at inner &, record depth D of reference type
 | 
|---|
 | 231 |                 // at outer &, add D derefs.
 | 
|---|
| [8135d4c] | 232 |                 void AddrRef::premutate( Expression * ) {
 | 
|---|
| [8499c707] | 233 |                         GuardValue( current );
 | 
|---|
 | 234 |                         GuardValue( first );
 | 
|---|
 | 235 |                         current = false;
 | 
|---|
 | 236 |                         first = true;
 | 
|---|
 | 237 |                 }
 | 
|---|
 | 238 | 
 | 
|---|
| [8135d4c] | 239 |                 void AddrRef::premutate( AddressExpr * ) {
 | 
|---|
| [8499c707] | 240 |                         GuardValue( current );
 | 
|---|
 | 241 |                         GuardValue( first );
 | 
|---|
 | 242 |                         current = first;
 | 
|---|
 | 243 |                         first = false;
 | 
|---|
 | 244 |                         if ( current ) {
 | 
|---|
 | 245 |                                 GuardValue( refDepth );
 | 
|---|
 | 246 |                                 refDepth = 0;
 | 
|---|
 | 247 |                         }
 | 
|---|
 | 248 |                 }
 | 
|---|
 | 249 | 
 | 
|---|
 | 250 |                 Expression * AddrRef::postmutate( AddressExpr * addrExpr ) {
 | 
|---|
 | 251 |                         if ( refDepth == 0 ) {
 | 
|---|
 | 252 |                                 if ( ! isIntrinsicReference( addrExpr->get_arg() ) ) {
 | 
|---|
 | 253 |                                         // try to avoid ?[?]
 | 
|---|
 | 254 |                                         refDepth = addrExpr->get_arg()->get_result()->referenceDepth();
 | 
|---|
 | 255 |                                 }
 | 
|---|
 | 256 |                         }
 | 
|---|
 | 257 |                         if ( current ) {
 | 
|---|
 | 258 |                                 Expression * ret = addrExpr;
 | 
|---|
 | 259 |                                 while ( refDepth ) {
 | 
|---|
 | 260 |                                         ret = mkDeref( ret );
 | 
|---|
 | 261 |                                         refDepth--;
 | 
|---|
 | 262 |                                 }
 | 
|---|
 | 263 |                                 return ret;
 | 
|---|
 | 264 |                         }
 | 
|---|
 | 265 |                         return addrExpr;
 | 
|---|
 | 266 |                 }
 | 
|---|
 | 267 | 
 | 
|---|
| [8a6cf7e] | 268 |                 Expression * ReferenceConversions::postmutate( AddressExpr * addrExpr ) {
 | 
|---|
 | 269 |                         // Inner expression may have been lvalue to reference conversion, which becomes an address expression.
 | 
|---|
 | 270 |                         // In this case, remove the outer address expression and return the argument.
 | 
|---|
 | 271 |                         // TODO: It's possible that this might catch too much and require a more sophisticated check.
 | 
|---|
 | 272 |                         return addrExpr;
 | 
|---|
 | 273 |                 }
 | 
|---|
 | 274 | 
 | 
|---|
| [1d776fd] | 275 |                 Expression * ReferenceConversions::postmutate( CastExpr * castExpr ) {
 | 
|---|
| [9a34b5a] | 276 |                         // xxx - is it possible to convert directly between reference types with a different base? E.g.,
 | 
|---|
 | 277 |                         //   int x;
 | 
|---|
 | 278 |                         //   (double&)x;
 | 
|---|
 | 279 |                         // At the moment, I am working off of the assumption that this is illegal, thus the cast becomes redundant
 | 
|---|
 | 280 |                         // after this pass, so trash the cast altogether. If that changes, care must be taken to insert the correct
 | 
|---|
 | 281 |                         // pointer casts in the right places.
 | 
|---|
 | 282 | 
 | 
|---|
| [1d776fd] | 283 |                         // conversion to reference type
 | 
|---|
 | 284 |                         if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_result() ) ) {
 | 
|---|
 | 285 |                                 (void)refType;
 | 
|---|
 | 286 |                                 if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) {
 | 
|---|
 | 287 |                                         // nothing to do if casting from reference to reference.
 | 
|---|
 | 288 |                                         (void)otherRef;
 | 
|---|
| [cb43451] | 289 |                                         PRINT( std::cerr << "convert reference to reference -- nop" << std::endl; )
 | 
|---|
| [1d776fd] | 290 |                                         if ( isIntrinsicReference( castExpr->get_arg() ) ) {
 | 
|---|
 | 291 |                                                 Expression * callExpr = castExpr->get_arg();
 | 
|---|
| [cb43451] | 292 |                                                 PRINT(
 | 
|---|
 | 293 |                                                         std::cerr << "but arg is deref -- &" << std::endl;
 | 
|---|
 | 294 |                                                         std::cerr << callExpr << std::endl;
 | 
|---|
 | 295 |                                                 )
 | 
|---|
| [8499c707] | 296 |                                                 callExpr = new AddressExpr( callExpr ); // this doesn't work properly for multiple casts
 | 
|---|
 | 297 |                                                 delete callExpr->get_result();
 | 
|---|
 | 298 |                                                 callExpr->set_result( refType->clone() );
 | 
|---|
| [1d776fd] | 299 |                                                 // move environment out to new top-level
 | 
|---|
 | 300 |                                                 callExpr->set_env( castExpr->get_env() );
 | 
|---|
| [9a34b5a] | 301 |                                                 castExpr->set_arg( nullptr );
 | 
|---|
| [1d776fd] | 302 |                                                 castExpr->set_env( nullptr );
 | 
|---|
| [9a34b5a] | 303 |                                                 delete castExpr;
 | 
|---|
| [1d776fd] | 304 |                                                 return callExpr;
 | 
|---|
 | 305 |                                         }
 | 
|---|
| [8499c707] | 306 |                                         int depth1 = refType->referenceDepth();
 | 
|---|
 | 307 |                                         int depth2 = otherRef->referenceDepth();
 | 
|---|
| [fc56cdbf] | 308 |                                         int diff = depth1-depth2;
 | 
|---|
 | 309 |                                         if ( diff == 0 ) {
 | 
|---|
 | 310 |                                                 assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() );
 | 
|---|
 | 311 |                                                 PRINT( std::cerr << castExpr << std::endl; )
 | 
|---|
 | 312 |                                                 return castExpr;
 | 
|---|
 | 313 |                                         } else if ( diff < 0 ) {
 | 
|---|
 | 314 |                                                 Expression * ret = castExpr->get_arg();
 | 
|---|
 | 315 |                                                 for ( int i = 0; i < diff; ++i ) {
 | 
|---|
 | 316 |                                                         ret = mkDeref( ret );
 | 
|---|
 | 317 |                                                 }
 | 
|---|
 | 318 |                                                 ret->set_env( castExpr->get_env() );
 | 
|---|
 | 319 |                                                 delete ret->get_result();
 | 
|---|
 | 320 |                                                 ret->set_result( castExpr->get_result() );
 | 
|---|
 | 321 |                                                 castExpr->set_env( nullptr );
 | 
|---|
 | 322 |                                                 castExpr->set_arg( nullptr );
 | 
|---|
 | 323 |                                                 castExpr->set_result( nullptr );
 | 
|---|
 | 324 |                                                 delete castExpr;
 | 
|---|
 | 325 |                                                 return ret;
 | 
|---|
 | 326 |                                         } else if ( diff > 0 ) {
 | 
|---|
 | 327 |                                                 Expression * ret = castExpr->get_arg();
 | 
|---|
 | 328 |                                                 for ( int i = 0; i < diff; ++i ) {
 | 
|---|
 | 329 |                                                         ret = new AddressExpr( ret );
 | 
|---|
 | 330 |                                                 }
 | 
|---|
 | 331 |                                                 ret->set_env( castExpr->get_env() );
 | 
|---|
 | 332 |                                                 delete ret->get_result();
 | 
|---|
 | 333 |                                                 ret->set_result( castExpr->get_result() );
 | 
|---|
 | 334 |                                                 castExpr->set_env( nullptr );
 | 
|---|
 | 335 |                                                 castExpr->set_arg( nullptr );
 | 
|---|
 | 336 |                                                 castExpr->set_result( nullptr );
 | 
|---|
 | 337 |                                                 delete castExpr;
 | 
|---|
 | 338 |                                                 return ret;
 | 
|---|
 | 339 |                                         }
 | 
|---|
 | 340 | 
 | 
|---|
| [8499c707] | 341 |                                         assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() );
 | 
|---|
| [cb43451] | 342 |                                         PRINT( std::cerr << castExpr << std::endl; )
 | 
|---|
| [1d776fd] | 343 |                                         return castExpr;
 | 
|---|
 | 344 |                                 } else if ( castExpr->get_arg()->get_result()->get_lvalue() ) {
 | 
|---|
 | 345 |                                         // conversion from lvalue to reference
 | 
|---|
 | 346 |                                         // xxx - keep cast, but turn into pointer cast??
 | 
|---|
 | 347 |                                         // xxx - memory
 | 
|---|
| [cb43451] | 348 |                                         PRINT(
 | 
|---|
 | 349 |                                                 std::cerr << "convert lvalue to reference -- &" << std::endl;
 | 
|---|
 | 350 |                                                 std::cerr << castExpr->get_arg() << std::endl;
 | 
|---|
 | 351 |                                         )
 | 
|---|
 | 352 |                                         AddressExpr * ret = new AddressExpr( castExpr->get_arg() );
 | 
|---|
 | 353 |                                         if ( refType->get_base()->get_qualifiers() != castExpr->get_arg()->get_result()->get_qualifiers() ) {
 | 
|---|
 | 354 |                                                 // must keep cast if cast-to type is different from the actual type
 | 
|---|
 | 355 |                                                 castExpr->set_arg( ret );
 | 
|---|
 | 356 |                                                 return castExpr;
 | 
|---|
 | 357 |                                         }
 | 
|---|
| [9a34b5a] | 358 |                                         ret->set_env( castExpr->get_env() );
 | 
|---|
| [8499c707] | 359 |                                         delete ret->get_result();
 | 
|---|
 | 360 |                                         ret->set_result( castExpr->get_result() );
 | 
|---|
| [9a34b5a] | 361 |                                         castExpr->set_env( nullptr );
 | 
|---|
 | 362 |                                         castExpr->set_arg( nullptr );
 | 
|---|
| [8499c707] | 363 |                                         castExpr->set_result( nullptr );
 | 
|---|
| [9a34b5a] | 364 |                                         delete castExpr;
 | 
|---|
 | 365 |                                         return ret;
 | 
|---|
| [01aeade] | 366 |                                 } else {
 | 
|---|
| [1d776fd] | 367 |                                         // rvalue to reference conversion -- introduce temporary
 | 
|---|
 | 368 |                                 }
 | 
|---|
 | 369 |                                 assertf( false, "Only conversions to reference from lvalue are currently supported: %s", toString( castExpr ).c_str() );
 | 
|---|
 | 370 |                         } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) {
 | 
|---|
| [d335627] | 371 |                                 (void)refType;
 | 
|---|
| [9a34b5a] | 372 |                                 // conversion from reference to rvalue
 | 
|---|
| [8a6cf7e] | 373 |                                 PRINT(
 | 
|---|
 | 374 |                                         std::cerr << "convert reference to rvalue -- *" << std::endl;
 | 
|---|
 | 375 |                                         std::cerr << "was = " << castExpr << std::endl;
 | 
|---|
 | 376 |                                 )
 | 
|---|
| [9191a8e] | 377 |                                 Expression * ret = castExpr->get_arg();
 | 
|---|
| [8a6cf7e] | 378 |                                 TypeSubstitution * env = castExpr->get_env();
 | 
|---|
 | 379 |                                 castExpr->set_env( nullptr );
 | 
|---|
| [9191a8e] | 380 |                                 if ( ! isIntrinsicReference( ret ) ) {
 | 
|---|
 | 381 |                                         // dereference if not already dereferenced
 | 
|---|
 | 382 |                                         ret = mkDeref( ret );
 | 
|---|
 | 383 |                                 }
 | 
|---|
| [8a6cf7e] | 384 |                                 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( castExpr->get_result(), castExpr->get_arg()->get_result()->stripReferences(), SymTab::Indexer() ) ) {
 | 
|---|
| [b0440b7] | 385 |                                         // can remove cast if types are compatible, changing expression type to value type
 | 
|---|
 | 386 |                                         ret->set_result( castExpr->get_result()->clone() );
 | 
|---|
| [8a6cf7e] | 387 |                                         castExpr->set_arg( nullptr );
 | 
|---|
 | 388 |                                         delete castExpr;
 | 
|---|
 | 389 |                                 } else {
 | 
|---|
 | 390 |                                         // must keep cast if types are different
 | 
|---|
 | 391 |                                         castExpr->set_arg( ret );
 | 
|---|
 | 392 |                                         ret = castExpr;
 | 
|---|
 | 393 |                                 }
 | 
|---|
 | 394 |                                 ret->set_env( env );
 | 
|---|
| [9191a8e] | 395 |                                 PRINT( std::cerr << "now: " << ret << std::endl; )
 | 
|---|
 | 396 |                                 return ret;
 | 
|---|
| [1d776fd] | 397 |                         }
 | 
|---|
 | 398 |                         return castExpr;
 | 
|---|
| [01aeade] | 399 |                 }
 | 
|---|
| [b6fd751] | 400 | 
 | 
|---|
| [1d776fd] | 401 |                 Type * ReferenceTypeElimination::postmutate( ReferenceType * refType ) {
 | 
|---|
 | 402 |                         Type * base = refType->get_base();
 | 
|---|
| [8a6cf7e] | 403 |                         Type::Qualifiers qualifiers = refType->get_qualifiers();
 | 
|---|
| [1d776fd] | 404 |                         refType->set_base( nullptr );
 | 
|---|
 | 405 |                         delete refType;
 | 
|---|
| [8a6cf7e] | 406 |                         return new PointerType( qualifiers, base );
 | 
|---|
| [ce8c12f] | 407 |                 }
 | 
|---|
 | 408 | 
 | 
|---|
| [acd7c5dd] | 409 |                 template<typename Func>
 | 
|---|
 | 410 |                 Expression * GeneralizedLvalue::applyTransformation( Expression * expr, Expression * arg, Func mkExpr ) {
 | 
|---|
 | 411 |                         if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( arg ) ) {
 | 
|---|
| [b6fd751] | 412 |                                 Expression * arg1 = commaExpr->get_arg1()->clone();
 | 
|---|
 | 413 |                                 Expression * arg2 = commaExpr->get_arg2()->clone();
 | 
|---|
| [9236060] | 414 |                                 Expression * ret = new CommaExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ) );
 | 
|---|
| [acd7c5dd] | 415 |                                 ret->set_env( expr->get_env() );
 | 
|---|
 | 416 |                                 expr->set_env( nullptr );
 | 
|---|
 | 417 |                                 delete expr;
 | 
|---|
| [8499c707] | 418 |                                 return ret;
 | 
|---|
| [acd7c5dd] | 419 |                         } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( arg ) ) {
 | 
|---|
| [b6fd751] | 420 |                                 Expression * arg1 = condExpr->get_arg1()->clone();
 | 
|---|
 | 421 |                                 Expression * arg2 = condExpr->get_arg2()->clone();
 | 
|---|
 | 422 |                                 Expression * arg3 = condExpr->get_arg3()->clone();
 | 
|---|
| [9236060] | 423 |                                 ConditionalExpr * ret = new ConditionalExpr( arg1, mkExpr( arg2 )->acceptMutator( *visitor ), mkExpr( arg3 )->acceptMutator( *visitor ) );
 | 
|---|
| [acd7c5dd] | 424 |                                 ret->set_env( expr->get_env() );
 | 
|---|
 | 425 |                                 expr->set_env( nullptr );
 | 
|---|
 | 426 |                                 delete expr;
 | 
|---|
 | 427 | 
 | 
|---|
 | 428 |                                 // conditional expr type may not be either of the argument types, need to unify
 | 
|---|
 | 429 |                                 using namespace ResolvExpr;
 | 
|---|
 | 430 |                                 Type* commonType = nullptr;
 | 
|---|
 | 431 |                                 TypeEnvironment newEnv;
 | 
|---|
 | 432 |                                 AssertionSet needAssertions, haveAssertions;
 | 
|---|
 | 433 |                                 OpenVarSet openVars;
 | 
|---|
 | 434 |                                 unify( ret->get_arg2()->get_result(), ret->get_arg3()->get_result(), newEnv, needAssertions, haveAssertions, openVars, SymTab::Indexer(), commonType );
 | 
|---|
 | 435 |                                 ret->set_result( commonType ? commonType : ret->get_arg2()->get_result()->clone() );
 | 
|---|
| [8499c707] | 436 |                                 return ret;
 | 
|---|
| [b6fd751] | 437 |                         }
 | 
|---|
| [acd7c5dd] | 438 |                         return expr;
 | 
|---|
 | 439 |                 }
 | 
|---|
 | 440 | 
 | 
|---|
| [9236060] | 441 |                 Expression * GeneralizedLvalue::postmutate( MemberExpr * memExpr ) {
 | 
|---|
| [acd7c5dd] | 442 |                         return applyTransformation( memExpr, memExpr->get_aggregate(), [=]( Expression * aggr ) { return new MemberExpr( memExpr->get_member(), aggr ); } );
 | 
|---|
 | 443 |                 }
 | 
|---|
 | 444 | 
 | 
|---|
| [9236060] | 445 |                 Expression * GeneralizedLvalue::postmutate( AddressExpr * addrExpr ) {
 | 
|---|
| [acd7c5dd] | 446 |                         return applyTransformation( addrExpr, addrExpr->get_arg(), []( Expression * arg ) { return new AddressExpr( arg ); } );
 | 
|---|
| [b6fd751] | 447 |                 }
 | 
|---|
| [cb43451] | 448 | 
 | 
|---|
| [8499c707] | 449 |                 Expression * CollapseAddrDeref::postmutate( AddressExpr * addrExpr ) {
 | 
|---|
 | 450 |                         Expression * arg = addrExpr->get_arg();
 | 
|---|
| [cb43451] | 451 |                         if ( isIntrinsicReference( arg ) ) {
 | 
|---|
 | 452 |                                 std::string fname = InitTweak::getFunctionName( arg );
 | 
|---|
 | 453 |                                 if ( fname == "*?" ) {
 | 
|---|
 | 454 |                                         Expression *& arg0 = InitTweak::getCallArg( arg, 0 );
 | 
|---|
 | 455 |                                         Expression * ret = arg0;
 | 
|---|
| [8499c707] | 456 |                                         ret->set_env( addrExpr->get_env() );
 | 
|---|
| [cb43451] | 457 |                                         arg0 = nullptr;
 | 
|---|
| [8499c707] | 458 |                                         addrExpr->set_env( nullptr );
 | 
|---|
 | 459 |                                         delete addrExpr;
 | 
|---|
| [cb43451] | 460 |                                         return ret;
 | 
|---|
 | 461 |                                 }
 | 
|---|
 | 462 |                         }
 | 
|---|
| [8499c707] | 463 |                         return addrExpr;
 | 
|---|
| [cb43451] | 464 |                 }
 | 
|---|
 | 465 | 
 | 
|---|
 | 466 |                 Expression * CollapseAddrDeref::postmutate( ApplicationExpr * appExpr ) {
 | 
|---|
 | 467 |                         if ( isIntrinsicReference( appExpr ) ) {
 | 
|---|
 | 468 |                                 std::string fname = InitTweak::getFunctionName( appExpr );
 | 
|---|
 | 469 |                                 if ( fname == "*?" ) {
 | 
|---|
 | 470 |                                         Expression * arg = InitTweak::getCallArg( appExpr, 0 );
 | 
|---|
 | 471 |                                         // xxx - this isn't right, because it can remove casts that should be there...
 | 
|---|
 | 472 |                                         // while ( CastExpr * castExpr = dynamic_cast< CastExpr * >( arg ) ) {
 | 
|---|
 | 473 |                                         //      arg = castExpr->get_arg();
 | 
|---|
 | 474 |                                         // }
 | 
|---|
 | 475 |                                         if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( arg ) ) {
 | 
|---|
 | 476 |                                                 Expression * ret = addrExpr->get_arg();
 | 
|---|
 | 477 |                                                 ret->set_env( appExpr->get_env() );
 | 
|---|
 | 478 |                                                 addrExpr->set_arg( nullptr );
 | 
|---|
 | 479 |                                                 appExpr->set_env( nullptr );
 | 
|---|
 | 480 |                                                 delete appExpr;
 | 
|---|
 | 481 |                                                 return ret;
 | 
|---|
 | 482 |                                         }
 | 
|---|
 | 483 |                                 }
 | 
|---|
 | 484 |                         }
 | 
|---|
 | 485 |                         return appExpr;
 | 
|---|
 | 486 |                 }
 | 
|---|
| [01aeade] | 487 |         } // namespace
 | 
|---|
| [51b73452] | 488 | } // namespace GenPoly
 | 
|---|
| [01aeade] | 489 | 
 | 
|---|
| [51587aa] | 490 | // Local Variables: //
 | 
|---|
 | 491 | // tab-width: 4 //
 | 
|---|
 | 492 | // mode: c++ //
 | 
|---|
 | 493 | // compile-command: "make install" //
 | 
|---|
 | 494 | // End: //
 | 
|---|