Changeset 1d776fd
- Timestamp:
- Jul 13, 2017, 3:51:19 PM (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:
- 9a1e509
- Parents:
- 6b9b047
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/GenPoly/Lvalue.cc
r6b9b047 r1d776fd 34 34 #include "InitTweak/InitTweak.h" 35 35 36 #include "Common/PassVisitor.h" 37 38 // need to be careful about polymorphic references... e.g. in *? (___operator_deref__A0_1_0_0__Fd0_Pd0_intrinsic___1) 39 // the variable is automatically dereferenced and this causes errors dereferencing void*. 40 36 41 namespace GenPoly { 37 42 namespace { 38 /// Replace uses of lvalue returns with appropriate pointers 39 class Pass1 : public Mutator { 40 public: 41 typedef Mutator Parent; 42 Pass1(); 43 44 // xxx - should this happen to every expression with reference result type? probably just appexpr and varexpr? 45 virtual Type *mutate( ReferenceType * refType ); 46 virtual Expression *mutate( VariableExpr *varExpr ); 47 virtual Expression *mutate( ApplicationExpr *appExpr ); 48 virtual Statement *mutate( ReturnStmt *appExpr ); 49 virtual DeclarationWithType *mutate( FunctionDecl *funDecl ); 50 private: 51 DeclarationWithType* retval; 52 }; 53 54 /// Replace declarations of lvalue returns with appropriate pointers 55 class Pass2 : public Visitor { 56 public: 57 virtual void visit( FunctionType *funType ); 58 private: 43 struct ReferenceConversions final { 44 Expression * postmutate( CastExpr * castExpr ); 45 }; 46 47 /// Intrinsic functions that take reference parameters don't REALLY take reference parameters -- their reference arguments must always be implicitly dereferenced. 48 struct FixIntrinsicArgs final { 49 Expression * postmutate( ApplicationExpr *appExpr ); 50 }; 51 52 53 /// Replace reference types with pointer types 54 struct ReferenceTypeElimination final { 55 Type * postmutate( ReferenceType * refType ); 59 56 }; 60 57 … … 62 59 /// https://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/Lvalues.html#Lvalues 63 60 /// Replaces &(a,b) with (a, &b), &(a ? b : c) with (a ? &b : &c) 64 class GeneralizedLvalue : public Mutator { 65 typedef Mutator Parent; 66 67 virtual Expression * mutate( AddressExpr * addressExpr ); 61 struct GeneralizedLvalue final { 62 Expression * postmutate( AddressExpr * addressExpr ); 68 63 }; 69 64 } // namespace 70 65 71 66 void convertLvalue( std::list< Declaration* >& translationUnit ) { 72 Pass1 p1; 73 Pass2 p2; 74 GeneralizedLvalue genLval; 75 mutateAll( translationUnit, p1 ); 76 acceptAll( translationUnit, p2 ); 67 std::cerr << "convertLvalue" << std::endl; 68 PassVisitor<ReferenceConversions> refCvt; 69 PassVisitor<ReferenceTypeElimination> elim; 70 PassVisitor<GeneralizedLvalue> genLval; 71 PassVisitor<FixIntrinsicArgs> fixer; 72 mutateAll( translationUnit, refCvt ); 73 mutateAll( translationUnit, fixer ); 74 mutateAll( translationUnit, elim ); 77 75 mutateAll( translationUnit, genLval ); 78 76 } … … 82 80 if ( function->get_returnVals().empty() ) return 0; 83 81 Type *ty = function->get_returnVals().front()->get_type(); 84 return ty->get_lvalue() ? ty : 0;82 return dynamic_cast< ReferenceType * >( ty ) ; 85 83 } 86 84 … … 93 91 } 94 92 95 Pass1::Pass1() { 96 } 97 98 DeclarationWithType * Pass1::mutate( FunctionDecl *funcDecl ) { 99 if ( funcDecl->get_statements() ) { 100 DeclarationWithType* oldRetval = retval; 101 retval = 0; 102 if ( ! LinkageSpec::isBuiltin( funcDecl->get_linkage() ) && isLvalueRet( funcDecl->get_functionType() ) ) { 103 retval = funcDecl->get_functionType()->get_returnVals().front(); 104 } 105 // fix expressions and return statements in this function 106 funcDecl->set_statements( funcDecl->get_statements()->acceptMutator( *this ) ); 107 retval = oldRetval; 108 } // if 109 return funcDecl; 110 } 111 112 Type * Pass1::mutate( ReferenceType * refType ) { 93 bool isDeref( Expression * expr ) { 94 if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) { 95 return InitTweak::getFunctionName( untyped ) == "*?"; 96 } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) { 97 if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) { 98 return func->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getFunctionName( appExpr ) == "*?"; 99 } 100 } 101 return false; 102 } 103 104 bool isIntrinsicReference( Expression * expr ) { 105 if ( isDeref( expr ) ) return true; 106 else if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) { 107 return InitTweak::getFunctionName( untyped ) == "?[?]"; 108 } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) { 109 if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) { 110 return func->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getFunctionName( appExpr ) == "?[?]"; 111 } 112 } 113 return false; 114 } 115 116 void fixArg( Expression *& arg, Type * formal ) { 117 // if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( arg ) ) { 118 if ( dynamic_cast<ReferenceType*>( formal ) ) { // xxx - but might be deref, in which case result isn't REALLY a reference, at least not in the sense that we need to add another deref... 119 // doesn't work, for some reason left arg is skipped in assign 120 ReferenceType * refType = safe_dynamic_cast< ReferenceType * >( arg->get_result() ) ; 121 std::cerr << "appexpr arg is non-deref/index intrinsic call" << std::endl; 122 std::cerr << arg << std::endl; 123 PointerType * ptrType = new PointerType( Type::Qualifiers(), refType->get_base()->clone() ); 124 delete refType; 125 arg->set_result( ptrType ); 126 arg = UntypedExpr::createDeref( arg ); 127 } 128 129 // } 130 } 131 132 Expression * FixIntrinsicArgs::postmutate( ApplicationExpr * appExpr ) { 133 if ( DeclarationWithType * function = InitTweak::getFunction( appExpr ) ) { 134 if ( function->get_linkage() == LinkageSpec::Intrinsic ) { // intrinsic functions that turn pointers into references 135 FunctionType * ftype = GenPoly::getFunctionType( function->get_type() ); 136 assertf( ftype, "Function declaration does not have function type." ); 137 for ( auto p : group_iterate( appExpr->get_args(), ftype->get_parameters() ) ) { 138 Expression *& arg = std::get<0>( p ); 139 DeclarationWithType * formal = std::get<1>( p ); 140 std::cerr << "pair<0>: " << arg << std::endl; 141 std::cerr << "pair<1>: " << formal->get_type() << std::endl; 142 if ( isIntrinsicReference( arg ) ) { 143 std::cerr << "skipping intrinsic reference" << std::endl; 144 continue; 145 } else { 146 fixArg( arg, formal->get_type() ); 147 } 148 } 149 } 150 } 151 return appExpr; 152 } 153 154 Expression * ReferenceConversions::postmutate( CastExpr * castExpr ) { 155 // conversion to reference type 156 if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_result() ) ) { 157 (void)refType; 158 if ( ReferenceType * otherRef = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) { 159 // nothing to do if casting from reference to reference. 160 (void)otherRef; 161 std::cerr << "convert reference to reference -- nop" << std::endl; 162 if ( isIntrinsicReference( castExpr->get_arg() ) ) { 163 Expression * callExpr = castExpr->get_arg(); 164 Expression ** arg = nullptr; 165 Expression *& arg0 = InitTweak::getCallArg( callExpr, 0 ); 166 if ( dynamic_cast<PointerType *>( arg0->get_result() ) ) { 167 arg = &arg0; 168 } else { 169 arg = &InitTweak::getCallArg( callExpr, 1 ); 170 } 171 172 castExpr->set_arg( *arg ); 173 *arg = castExpr; 174 std::cerr << "but arg is deref -- &" << std::endl; 175 std::cerr << callExpr << std::endl; 176 // castExpr->set_arg( new AddressExpr( castExpr->get_arg() ) ); 177 178 // move environment out to new top-level 179 callExpr->set_env( castExpr->get_env() ); 180 castExpr->set_env( nullptr ); 181 return callExpr; 182 } 183 std::cerr << castExpr << std::endl; 184 return castExpr; 185 } else if ( castExpr->get_arg()->get_result()->get_lvalue() ) { 186 // conversion from lvalue to reference 187 // xxx - keep cast, but turn into pointer cast?? 188 // xxx - memory 189 std::cerr << "convert lvalue to reference -- &" << std::endl; 190 std::cerr << castExpr->get_arg() << std::endl; 191 castExpr->set_arg( new AddressExpr( castExpr->get_arg() ) ); 192 // return new AddressExpr( castExpr->get_arg() ); 193 return castExpr; 194 } else { 195 // rvalue to reference conversion -- introduce temporary 196 } 197 assertf( false, "Only conversions to reference from lvalue are currently supported: %s", toString( castExpr ).c_str() ); 198 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( castExpr->get_arg()->get_result() ) ) { 199 // should be easy, just need to move deref code up here? 200 std::cerr << "convert reference to rvalue -- *" << std::endl; 201 if ( isIntrinsicReference( castExpr->get_arg() ) ) { 202 std::cerr << "but arg is intrinsic reference -- nop" << std::endl; 203 return castExpr; 204 } 205 std::cerr << castExpr << std::endl; 206 207 PointerType * ptrType = new PointerType( refType->get_qualifiers(), refType->get_base()->clone() ); 208 delete castExpr->get_result(); 209 castExpr->set_result( ptrType ); 210 Expression * deref = UntypedExpr::createDeref( castExpr ); 211 deref->set_env( castExpr->get_env() ); 212 castExpr->set_env( nullptr ); 213 return deref; 214 // assertf( false, "Conversions from reference types are not currently supported." ); 215 } 216 return castExpr; 217 } 218 219 Type * ReferenceTypeElimination::postmutate( ReferenceType * refType ) { 113 220 Type * base = refType->get_base(); 114 221 refType->set_base( nullptr ); … … 117 224 } 118 225 119 Expression * Pass1::mutate( VariableExpr *varExpr ) { 120 if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( varExpr->get_result() ) ) { 121 varExpr->set_result( refType->acceptMutator( *this ) ); 122 return UntypedExpr::createDeref( varExpr ); 123 } 124 return Parent::mutate( varExpr ); 125 } 126 127 Expression * Pass1::mutate( ApplicationExpr *appExpr ) { 128 appExpr->get_function()->acceptMutator( *this ); 129 mutateAll( appExpr->get_args(), *this ); 130 131 PointerType *pointer = safe_dynamic_cast< PointerType* >( appExpr->get_function()->get_result() ); 132 FunctionType *function = safe_dynamic_cast< FunctionType* >( pointer->get_base() ); 133 134 Type *funType = isLvalueRet( function ); 135 if ( funType && ! isIntrinsicApp( appExpr ) ) { 136 Expression *expr = appExpr; 137 Type *appType = appExpr->get_result(); 138 if ( isPolyType( funType ) && ! isPolyType( appType ) ) { 139 // make sure cast for polymorphic type is inside dereference 140 expr = new CastExpr( appExpr, new PointerType( Type::Qualifiers(), appType->clone() ) ); 141 } 142 UntypedExpr *deref = new UntypedExpr( new NameExpr( "*?" ) ); 143 deref->set_result( appType->clone() ); 144 appExpr->set_result( new PointerType( Type::Qualifiers(), appType ) ); 145 deref->get_args().push_back( expr ); 146 return deref; 147 } else { 148 return appExpr; 149 } // if 150 } 151 152 Statement * Pass1::mutate(ReturnStmt *retStmt) { 153 if ( retval && retStmt->get_expr() ) { 154 if ( retStmt->get_expr()->get_result()->get_lvalue() ) { 155 // ***** Code Removal ***** because casts may be stripped already 156 157 // strip casts because not allowed to take address of cast 158 // while ( CastExpr *castExpr = dynamic_cast< CastExpr* >( retStmt->get_expr() ) ) { 159 // retStmt->set_expr( castExpr->get_arg() ); 160 // retStmt->get_expr()->set_env( castExpr->get_env() ); 161 // castExpr->set_env( 0 ); 162 // castExpr->set_arg( 0 ); 163 // delete castExpr; 164 // } // while 165 retStmt->set_expr( new AddressExpr( retStmt->get_expr()->acceptMutator( *this ) ) ); 166 } else { 167 throw SemanticError( "Attempt to return non-lvalue from an lvalue-qualified function" ); 168 } // if 169 } // if 170 return retStmt; 171 } 172 173 void Pass2::visit( FunctionType *funType ) { 174 std::string typeName; 175 if ( isLvalueRet( funType ) ) { 176 DeclarationWithType *retParm = funType->get_returnVals().front(); 177 178 // make a new parameter that is a pointer to the type of the old return value 179 retParm->set_type( new PointerType( Type::Qualifiers(), retParm->get_type() ) ); 180 } // if 181 182 Visitor::visit( funType ); 183 } 184 185 bool isDeref( Expression * expr ) { 186 if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) { 187 return InitTweak::getFunctionName( untyped ) == "*?"; 188 } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) { 189 return InitTweak::getFunctionName( appExpr ) == "*?"; 190 } else { 191 return false; 192 } 193 } 194 195 Expression * GeneralizedLvalue::mutate( AddressExpr * addrExpr ) { 196 addrExpr = safe_dynamic_cast< AddressExpr * >( Parent::mutate( addrExpr ) ); 226 Expression * GeneralizedLvalue::postmutate( AddressExpr * addrExpr ) { 197 227 if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( addrExpr->get_arg() ) ) { 198 228 Expression * arg1 = commaExpr->get_arg1()->clone(); … … 206 236 delete addrExpr; 207 237 return new ConditionalExpr( arg1, new AddressExpr( arg2 ), new AddressExpr( arg3 ) ); 208 } else if ( isDeref( addrExpr->get_arg() ) ) {209 // xxx - this doesn't belong here -- move it somewhere else210 Expression *& arg = InitTweak::getCallArg( addrExpr->get_arg(), 0 );211 Expression * inner = arg;212 arg = nullptr;213 delete addrExpr;214 return inner;215 238 } 216 239 return addrExpr;
Note: See TracChangeset
for help on using the changeset viewer.