Changeset 8a6cf7e
- Timestamp:
- Jul 26, 2017, 4:26:08 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:
- 2afec66
- Parents:
- d335627
- Location:
- src
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
src/CodeGen/CodeGenerator.cc
rd335627 r8a6cf7e 661 661 extension( commaExpr ); 662 662 output << "("; 663 if ( genC ) { 664 // arg1 of a CommaExpr is never used, so it can be safely cast to void to reduce gcc warnings. 665 commaExpr->set_arg1( new CastExpr( commaExpr->get_arg1() ) ); 666 } 663 667 commaExpr->get_arg1()->accept( *this ); 664 668 output << " , "; … … 724 728 for ( Statement * stmt : stmts ) { 725 729 output << lineDirective( stmt ) << indent; 726 730 output << printLabels( stmt->get_labels() ); 727 731 if ( i+1 == numStmts ) { 728 732 // last statement in a statement expression needs to be handled specially - … … 769 773 void CodeGenerator::visit( ExprStmt * exprStmt ) { 770 774 assert( exprStmt ); 771 Expression * expr = exprStmt->get_expr();772 775 if ( genC ) { 773 776 // cast the top-level expression to void to reduce gcc warnings. 774 expr = new CastExpr( expr);775 } 776 expr ->accept( *this );777 exprStmt->set_expr( new CastExpr( exprStmt->get_expr() ) ); 778 } 779 exprStmt->get_expr()->accept( *this ); 777 780 output << ";"; 778 781 } -
src/GenPoly/Lvalue.cc
rd335627 r8a6cf7e 66 66 struct ReferenceConversions final { 67 67 Expression * postmutate( CastExpr * castExpr ); 68 Expression * postmutate( AddressExpr * addrExpr ); 68 69 }; 69 70 … … 102 103 mutateAll( translationUnit, refCvt ); 103 104 mutateAll( translationUnit, fixer ); 104 mutateAll( translationUnit, elim );105 105 mutateAll( translationUnit, genLval ); 106 106 mutateAll( translationUnit, collapser ); 107 mutateAll( translationUnit, elim ); // last because other passes need reference types to work 107 108 } 108 109 109 110 namespace { 110 Type* isLvalueRet( FunctionType *function ) { 111 if ( function->get_returnVals().empty() ) return 0; 112 Type *ty = function->get_returnVals().front()->get_type(); 113 return dynamic_cast< ReferenceType * >( ty ) ; 114 } 115 116 bool isIntrinsicApp( ApplicationExpr *appExpr ) { 117 if ( VariableExpr *varExpr = dynamic_cast< VariableExpr* >( appExpr->get_function() ) ) { 118 return varExpr->get_var()->get_linkage() == LinkageSpec::Intrinsic; 119 } else { 120 return false; 121 } // if 122 } 123 124 bool isDeref( Expression * expr ) { 111 // true for intrinsic function calls that return a reference 112 bool isIntrinsicReference( Expression * expr ) { 125 113 if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) { 126 return InitTweak::getFunctionName( untyped ) == "*?"; 114 std::string fname = InitTweak::getFunctionName( untyped ); 115 // known intrinsic-reference prelude functions 116 return fname == "*?" || fname == "?[?]"; 127 117 } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) { 128 118 if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) { 129 return func->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getFunctionName( appExpr ) == "*?"; 130 } 131 } 132 return false; 133 } 134 135 bool isIntrinsicReference( Expression * expr ) { 136 if ( isDeref( expr ) ) return true; 137 else if ( UntypedExpr * untyped = dynamic_cast< UntypedExpr * >( expr ) ) { 138 return InitTweak::getFunctionName( untyped ) == "?[?]"; 139 } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) { 140 if ( DeclarationWithType * func = InitTweak::getFunction( appExpr ) ) { 141 return func->get_linkage() == LinkageSpec::Intrinsic && InitTweak::getFunctionName( appExpr ) == "?[?]"; 119 // use type of return variable rather than expr result type, since it may have been changed to a pointer type 120 FunctionType * ftype = GenPoly::getFunctionType( func->get_type() ); 121 Type * ret = ftype->get_returnVals().empty() ? nullptr : ftype->get_returnVals().front()->get_type(); 122 return func->get_linkage() == LinkageSpec::Intrinsic && dynamic_cast<ReferenceType *>( ret ); 142 123 } 143 124 } … … 186 167 } 187 168 169 Expression * ReferenceConversions::postmutate( AddressExpr * addrExpr ) { 170 // Inner expression may have been lvalue to reference conversion, which becomes an address expression. 171 // In this case, remove the outer address expression and return the argument. 172 // TODO: It's possible that this might catch too much and require a more sophisticated check. 173 if ( dynamic_cast<AddressExpr*>( addrExpr->get_arg() ) ) { 174 Expression * arg = addrExpr->get_arg(); 175 arg->set_env( addrExpr->get_env() ); 176 addrExpr->set_arg( nullptr ); 177 addrExpr->set_env( nullptr ); 178 delete addrExpr; 179 return arg; 180 } 181 return addrExpr; 182 } 183 188 184 Expression * ReferenceConversions::postmutate( CastExpr * castExpr ) { 189 185 // xxx - is it possible to convert directly between reference types with a different base? E.g., … … 244 240 (void)refType; 245 241 // conversion from reference to rvalue 246 PRINT( std::cerr << "convert reference to rvalue -- *" << std::endl; ) 247 PRINT( std::cerr << "was = " << castExpr << std::endl; ) 242 PRINT( 243 std::cerr << "convert reference to rvalue -- *" << std::endl; 244 std::cerr << "was = " << castExpr << std::endl; 245 ) 248 246 Expression * ret = castExpr->get_arg(); 247 TypeSubstitution * env = castExpr->get_env(); 248 castExpr->set_env( nullptr ); 249 249 if ( ! isIntrinsicReference( ret ) ) { 250 250 // dereference if not already dereferenced 251 251 ret = mkDeref( ret ); 252 252 } 253 ret->set_env( castExpr->get_env() ); 254 castExpr->set_arg( nullptr ); 255 castExpr->set_env( nullptr ); 256 delete castExpr; 253 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( castExpr->get_result(), castExpr->get_arg()->get_result()->stripReferences(), SymTab::Indexer() ) ) { 254 // can remove cast if types are compatible 255 castExpr->set_arg( nullptr ); 256 delete castExpr; 257 } else { 258 // must keep cast if types are different 259 castExpr->set_arg( ret ); 260 ret = castExpr; 261 } 262 ret->set_env( env ); 257 263 PRINT( std::cerr << "now: " << ret << std::endl; ) 258 264 return ret; … … 263 269 Type * ReferenceTypeElimination::postmutate( ReferenceType * refType ) { 264 270 Type * base = refType->get_base(); 271 Type::Qualifiers qualifiers = refType->get_qualifiers(); 265 272 refType->set_base( nullptr ); 266 273 delete refType; 267 return new PointerType( Type::Qualifiers(), base );274 return new PointerType( qualifiers, base ); 268 275 } 269 276 -
src/InitTweak/FixInit.cc
rd335627 r8a6cf7e 1182 1182 ctorExpr->set_callExpr( nullptr ); 1183 1183 ctorExpr->set_env( nullptr ); 1184 delete ctorExpr; 1184 1185 1185 1186 Expression *& firstArg = callExpr->get_args().front(); 1186 UntypedExpr * assign = new UntypedExpr( new NameExpr( "?=?" ) ); 1187 assign->get_args().push_back( new VariableExpr( tmp ) ); 1188 assign->get_args().push_back( firstArg ); 1189 assign->set_result( ctorExpr->get_result()->clone() ); 1190 firstArg = assign; 1191 1192 CommaExpr * commaExpr = new CommaExpr( callExpr, new VariableExpr( tmp ) ); 1187 1188 // xxx - hack in 'fake' assignment operator until resolver can easily be called in this pass. Once the resolver can be used in PassVisitor, this hack goes away. 1189 1190 // generate the type of assignment operator using the type of tmp minus any reference types 1191 Type * type = tmp->get_type()->stripReferences(); 1192 FunctionType * ftype = SymTab::genAssignType( type ); 1193 1194 // generate fake assignment decl and call it using &tmp and &firstArg 1195 // since tmp is guaranteed to be a reference and we want to assign pointers 1196 FunctionDecl * assignDecl = new FunctionDecl( "?=?", Type::StorageClasses(), LinkageSpec::Intrinsic, ftype, nullptr ); 1197 ApplicationExpr * assign = new ApplicationExpr( VariableExpr::functionPointer( assignDecl ) ); 1198 assign->get_args().push_back( new AddressExpr( new VariableExpr( tmp ) ) ); 1199 Expression * addrArg = new AddressExpr( firstArg ); 1200 // if firstArg has type T&&, then &firstArg has type T*&. 1201 // Cast away the reference to a value type so that the argument 1202 // matches the assignment's parameter types 1203 if ( dynamic_cast<ReferenceType *>( addrArg->get_result() ) ) { 1204 addrArg = new CastExpr( addrArg, addrArg->get_result()->stripReferences()->clone() ); 1205 } 1206 assign->get_args().push_back( addrArg ); 1207 firstArg = new VariableExpr( tmp ); 1208 1209 // for constructor expr: 1210 // T x; 1211 // x{}; 1212 // results in: 1213 // T x; 1214 // T & tmp; 1215 // &tmp = &x, ?{}(tmp), tmp 1216 CommaExpr * commaExpr = new CommaExpr( assign, new CommaExpr( callExpr, new VariableExpr( tmp ) ) ); 1193 1217 commaExpr->set_env( env ); 1194 delete ctorExpr;1195 1218 return commaExpr; 1196 1219 } -
src/SymTab/Autogen.h
rd335627 r8a6cf7e 38 38 /// Useful for creating dereference ApplicationExprs without a full resolver pass. 39 39 extern FunctionDecl * dereferenceOperator; 40 41 // temporary 42 FunctionType * genAssignType( Type * paramType ); 40 43 41 44 /// inserts into out a generated call expression to function fname with arguments dstParam and srcParam. Intended to be used with generated ?=?, ?{}, and ^?{} calls. -
src/SynTree/Expression.cc
rd335627 r8a6cf7e 92 92 } 93 93 94 VariableExpr * VariableExpr::functionPointer( FunctionDecl * func ) { 95 VariableExpr * funcExpr = new VariableExpr( func ); 96 funcExpr->set_result( new PointerType( Type::Qualifiers(), funcExpr->get_result() ) ); 97 return funcExpr; 98 } 99 94 100 void VariableExpr::print( std::ostream &os, int indent ) const { 95 101 os << "Variable Expression: "; -
src/SynTree/Expression.h
rd335627 r8a6cf7e 259 259 void set_var( DeclarationWithType * newValue ) { var = newValue; } 260 260 261 static VariableExpr * functionPointer( FunctionDecl * decl ); 262 261 263 virtual VariableExpr * clone() const { return new VariableExpr( * this ); } 262 264 virtual void accept( Visitor & v ) { v.visit( this ); }
Note: See TracChangeset
for help on using the changeset viewer.