- Timestamp:
- Aug 11, 2017, 10:04:23 AM (7 years ago)
- Branches:
- ADT, aaron-thesis, arm-eh, ast-experimental, cleanup-dtors, deferred_resn, demangler, enum, forall-pointer-decay, jacob/cs343-translation, jenkins-sandbox, master, new-ast, new-ast-unique-expr, new-env, no_list, persistent-indexer, pthread-emulation, qualifiedEnum, resolv-new, with_gc
- Children:
- 83a071f9
- Parents:
- b1bead1
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Lvalue.cc
rb1bead1 r8499c707 28 28 #include "SymTab/Indexer.h" 29 29 #include "SymTab/Autogen.h" 30 30 31 #include "ResolvExpr/Resolver.h" 31 32 #include "ResolvExpr/typeops.h" … … 33 34 #include "Common/UniqueName.h" 34 35 #include "Common/utility.h" 36 #include "Common/PassVisitor.h" 37 35 38 #include "InitTweak/InitTweak.h" 36 37 #include "Common/PassVisitor.h"38 39 // need to be careful about polymorphic references... e.g. in *? (___operator_deref__A0_1_0_0__Fd0_Pd0_intrinsic___1)40 // the variable is automatically dereferenced and this causes errors dereferencing void*.41 39 42 40 #if 0 … … 57 55 ApplicationExpr * ret = new ApplicationExpr( deref, { arg } ); 58 56 delete ret->get_result(); 59 ret->set_result( new ReferenceType( Type::Qualifiers(), base->clone() ) ); 57 ret->set_result( base->clone() ); 58 ret->get_result()->set_lvalue( true ); 60 59 return ret; 61 60 } else { … … 65 64 66 65 struct ReferenceConversions final { 66 void premutate( AddressExpr * addrExpr ); 67 67 68 Expression * postmutate( CastExpr * castExpr ); 68 69 Expression * postmutate( AddressExpr * addrExpr ); … … 71 72 /// Intrinsic functions that take reference parameters don't REALLY take reference parameters -- their reference arguments must always be implicitly dereferenced. 72 73 struct FixIntrinsicArgs final { 73 Expression * postmutate( ApplicationExpr *appExpr ); 74 }; 75 74 Expression * postmutate( ApplicationExpr * appExpr ); 75 }; 76 77 struct FixIntrinsicResult final { 78 Expression * postmutate( ApplicationExpr * appExpr ); 79 }; 76 80 77 81 /// Replace reference types with pointer types … … 91 95 Expression * postmutate( AddressExpr * addressExpr ); 92 96 Expression * postmutate( ApplicationExpr * appExpr ); 97 }; 98 99 struct AddrRef final : public WithGuards { 100 void premutate( AddressExpr * addrExpr ); 101 Expression * postmutate( AddressExpr * addrExpr ); 102 void premutate( Expression * expr ); 103 104 bool first = true; 105 bool current = false; 106 int refDepth = 0; 93 107 }; 94 108 } // namespace … … 107 121 PassVisitor<FixIntrinsicArgs> fixer; 108 122 PassVisitor<CollapseAddrDeref> collapser; 123 PassVisitor<AddrRef> addrRef; 124 PassVisitor<FixIntrinsicResult> intrinsicResults; 125 mutateAll( translationUnit, intrinsicResults ); 126 mutateAll( translationUnit, addrRef ); 109 127 mutateAll( translationUnit, refCvt ); 110 128 mutateAll( translationUnit, fixer ); 129 mutateAll( translationUnit, collapser ); 111 130 mutateAll( translationUnit, genLval ); 112 mutateAll( translationUnit, collapser );113 131 mutateAll( translationUnit, elim ); // last because other passes need reference types to work 114 132 … … 135 153 } 136 154 137 // xxx - might need to & every * (or every * that is an arg to non-intrinsic function??) 155 Expression * FixIntrinsicResult::postmutate( ApplicationExpr * appExpr ) { 156 if ( isIntrinsicReference( appExpr ) ) { 157 // eliminate reference types from intrinsic applications - now they return lvalues 158 Type * result = appExpr->get_result(); 159 appExpr->set_result( result->stripReferences()->clone() ); 160 appExpr->get_result()->set_lvalue( true ); 161 Expression * ret = new CastExpr( appExpr, result ); 162 ret->set_env( appExpr->get_env() ); 163 appExpr->set_env( nullptr ); 164 return ret; 165 } 166 return appExpr; 167 } 168 138 169 Expression * FixIntrinsicArgs::postmutate( ApplicationExpr * appExpr ) { 139 170 // intrinsic functions don't really take reference-typed parameters, so they require an implicit dereference on their arguments. … … 144 175 assertf( ftype->get_parameters().size() == appExpr->get_args().size() || ftype->get_isVarArgs(), "ApplicationExpr args do not match formal parameter type." ); 145 176 146 if ( isIntrinsicReference( appExpr ) ) {147 // eliminate reference types from intrinsic applications - now they return lvalues148 appExpr->set_result( appExpr->get_result()->stripReferences() );149 appExpr->get_result()->set_lvalue( true );150 }151 177 152 178 unsigned int i = 0; … … 161 187 ) 162 188 if ( dynamic_cast<ReferenceType*>( formal ) ) { 163 if ( isIntrinsicReference( arg ) ) { 189 if ( isIntrinsicReference( arg ) ) { // do not combine conditions, because that changes the meaning of the else if 164 190 if ( function->get_linkage() != LinkageSpec::Intrinsic ) { // intrinsic functions that turn pointers into references 165 191 // if argument is dereference or array subscript, the result isn't REALLY a reference, so it's not necessary to fix the argument 166 PRINT( std::cerr << "is intrinsic arg in non-intrinsic call - adding address" << std::endl; ) 192 PRINT( 193 std::cerr << "===is intrinsic arg in non-intrinsic call - adding address" << std::endl; 194 ) 167 195 arg = new AddressExpr( arg ); 168 196 } 169 197 } else if ( function->get_linkage() == LinkageSpec::Intrinsic ) { 198 // std::cerr << "===adding deref to arg" << std::endl; 170 199 // if the parameter is a reference, add a dereference to the reference-typed argument. 171 200 Type * baseType = InitTweak::getPointerBase( arg->get_result() ); 172 assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ) );201 assertf( baseType, "parameter is reference, arg must be pointer or reference: %s", toString( arg->get_result() ).c_str() ); 173 202 PointerType * ptrType = new PointerType( Type::Qualifiers(), baseType->clone() ); 174 203 delete arg->get_result(); … … 183 212 } 184 213 214 // idea: &&&E: get outer &, inner & 215 // at inner &, record depth D of reference type 216 // at outer &, add D derefs. 217 void AddrRef::premutate( Expression * expr ) { 218 GuardValue( current ); 219 GuardValue( first ); 220 current = false; 221 first = true; 222 } 223 224 void AddrRef::premutate( AddressExpr * addrExpr ) { 225 GuardValue( current ); 226 GuardValue( first ); 227 current = first; 228 first = false; 229 if ( current ) { 230 GuardValue( refDepth ); 231 refDepth = 0; 232 } 233 } 234 235 Expression * AddrRef::postmutate( AddressExpr * addrExpr ) { 236 if ( refDepth == 0 ) { 237 if ( ! isIntrinsicReference( addrExpr->get_arg() ) ) { 238 // try to avoid ?[?] 239 refDepth = addrExpr->get_arg()->get_result()->referenceDepth(); 240 } 241 } 242 if ( current ) { 243 Expression * ret = addrExpr; 244 while ( refDepth ) { 245 ret = mkDeref( ret ); 246 refDepth--; 247 } 248 return ret; 249 } 250 return addrExpr; 251 } 252 185 253 Expression * ReferenceConversions::postmutate( AddressExpr * addrExpr ) { 186 254 // Inner expression may have been lvalue to reference conversion, which becomes an address expression. 187 255 // In this case, remove the outer address expression and return the argument. 188 256 // TODO: It's possible that this might catch too much and require a more sophisticated check. 189 if ( dynamic_cast<AddressExpr*>( addrExpr->get_arg() ) ) {190 Expression * arg = addrExpr->get_arg();191 arg->set_env( addrExpr->get_env() );192 addrExpr->set_arg( nullptr );193 addrExpr->set_env( nullptr );194 delete addrExpr;195 return arg;196 }197 257 return addrExpr; 198 258 } … … 219 279 std::cerr << callExpr << std::endl; 220 280 ) 281 callExpr = new AddressExpr( callExpr ); // this doesn't work properly for multiple casts 282 delete callExpr->get_result(); 283 callExpr->set_result( refType->clone() ); 221 284 // move environment out to new top-level 222 285 callExpr->set_env( castExpr->get_env() ); … … 226 289 return callExpr; 227 290 } 228 assertf( false, "non-intrinsic reference with cast of reference to reference not yet supported: ", toString( castExpr ) ); 291 int depth1 = refType->referenceDepth(); 292 int depth2 = otherRef->referenceDepth(); 293 assertf( depth1 == depth2, "non-intrinsic reference with cast of reference to reference not yet supported: %d %d %s", depth1, depth2, toString( castExpr ).c_str() ); 229 294 PRINT( std::cerr << castExpr << std::endl; ) 230 295 return castExpr; … … 241 306 // must keep cast if cast-to type is different from the actual type 242 307 castExpr->set_arg( ret ); 243 244 308 return castExpr; 245 309 } 246 310 ret->set_env( castExpr->get_env() ); 311 delete ret->get_result(); 312 ret->set_result( castExpr->get_result() ); 247 313 castExpr->set_env( nullptr ); 248 314 castExpr->set_arg( nullptr ); 315 castExpr->set_result( nullptr ); 249 316 delete castExpr; 250 317 return ret; … … 296 363 Expression * arg1 = commaExpr->get_arg1()->clone(); 297 364 Expression * arg2 = commaExpr->get_arg2()->clone(); 365 Expression * ret = new CommaExpr( arg1, (new AddressExpr( arg2 ))->acceptMutator( *visitor ) ); 366 ret->set_env( addrExpr->get_env() ); 367 addrExpr->set_env( nullptr ); 298 368 delete addrExpr; 299 return new CommaExpr( arg1, (new AddressExpr( arg2 ))->acceptMutator( *visitor ) );369 return ret; 300 370 } else if ( ConditionalExpr * condExpr = dynamic_cast< ConditionalExpr * >( addrExpr->get_arg() ) ) { 301 371 Expression * arg1 = condExpr->get_arg1()->clone(); 302 372 Expression * arg2 = condExpr->get_arg2()->clone(); 303 373 Expression * arg3 = condExpr->get_arg3()->clone(); 374 Expression * ret = new ConditionalExpr( arg1, (new AddressExpr( arg2 ))->acceptMutator( *visitor ), (new AddressExpr( arg3 ))->acceptMutator( *visitor ) ); 375 ret->set_env( addrExpr->get_env() ); 376 addrExpr->set_env( nullptr ); 304 377 delete addrExpr; 305 return new ConditionalExpr( arg1, (new AddressExpr( arg2 ))->acceptMutator( *visitor ), (new AddressExpr( arg3 ))->acceptMutator( *visitor ) );378 return ret; 306 379 } 307 380 return addrExpr; 308 381 } 309 382 310 Expression * CollapseAddrDeref::postmutate( AddressExpr * addr essExpr ) {311 Expression * arg = addr essExpr->get_arg();383 Expression * CollapseAddrDeref::postmutate( AddressExpr * addrExpr ) { 384 Expression * arg = addrExpr->get_arg(); 312 385 if ( isIntrinsicReference( arg ) ) { 313 386 std::string fname = InitTweak::getFunctionName( arg ); … … 315 388 Expression *& arg0 = InitTweak::getCallArg( arg, 0 ); 316 389 Expression * ret = arg0; 317 ret->set_env( addr essExpr->get_env() );390 ret->set_env( addrExpr->get_env() ); 318 391 arg0 = nullptr; 319 addr essExpr->set_env( nullptr );320 delete addr essExpr;392 addrExpr->set_env( nullptr ); 393 delete addrExpr; 321 394 return ret; 322 395 } 323 396 } 324 return addr essExpr;397 return addrExpr; 325 398 } 326 399
Note: See TracChangeset
for help on using the changeset viewer.