Changes in src/InitTweak/InitTweak.cc [c6b4432:14c0f7b]
- File:
-
- 1 edited
-
src/InitTweak/InitTweak.cc (modified) (19 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/InitTweak/InitTweak.cc
rc6b4432 r14c0f7b 29 29 #include "AST/Type.hpp" 30 30 #include "CodeGen/OperatorTable.h" // for isConstructor, isDestructor, isCto... 31 #include "Common/PassVisitor.h" 31 32 #include "Common/SemanticError.h" // for SemanticError 32 33 #include "Common/UniqueName.h" // for UniqueName … … 35 36 #include "InitTweak.h" 36 37 #include "ResolvExpr/Unify.h" // for typesCompatibleIgnoreQualifiers 38 #include "SymTab/Autogen.h" 39 #include "SymTab/Indexer.h" // for Indexer 40 #include "SynTree/LinkageSpec.h" // for Spec, isBuiltin, Intrinsic 41 #include "SynTree/Attribute.h" // for Attribute 42 #include "SynTree/Constant.h" // for Constant 43 #include "SynTree/Declaration.h" // for ObjectDecl, DeclarationWithType 44 #include "SynTree/Expression.h" // for Expression, UntypedExpr, Applicati... 45 #include "SynTree/Initializer.h" // for Initializer, ListInit, Designation 46 #include "SynTree/Label.h" // for Label 47 #include "SynTree/Statement.h" // for CompoundStmt, ExprStmt, BranchStmt 48 #include "SynTree/Type.h" // for FunctionType, ArrayType, PointerType 49 #include "SynTree/Visitor.h" // for Visitor, maybeAccept 37 50 #include "Tuples/Tuples.h" // for Tuples::isTtype 38 51 39 52 namespace InitTweak { 40 53 namespace { 54 struct HasDesignations : public WithShortCircuiting { 55 bool hasDesignations = false; 56 57 void previsit( BaseSyntaxNode * ) { 58 // short circuit if we already know there are designations 59 if ( hasDesignations ) visit_children = false; 60 } 61 62 void previsit( Designation * des ) { 63 // short circuit if we already know there are designations 64 if ( hasDesignations ) visit_children = false; 65 else if ( ! des->get_designators().empty() ) { 66 hasDesignations = true; 67 visit_children = false; 68 } 69 } 70 }; 71 72 struct InitDepthChecker : public WithGuards { 73 bool depthOkay = true; 74 Type * type; 75 int curDepth = 0, maxDepth = 0; 76 InitDepthChecker( Type * type ) : type( type ) { 77 Type * t = type; 78 while ( ArrayType * at = dynamic_cast< ArrayType * >( t ) ) { 79 maxDepth++; 80 t = at->get_base(); 81 } 82 maxDepth++; 83 } 84 void previsit( ListInit * ) { 85 curDepth++; 86 GuardAction( [this]() { curDepth--; } ); 87 if ( curDepth > maxDepth ) depthOkay = false; 88 } 89 }; 90 41 91 struct HasDesignations_new : public ast::WithShortCircuiting { 42 92 bool result = false; … … 57 107 }; 58 108 59 struct InitDepthChecker_new {109 struct InitDepthChecker_new : public ast::WithGuards { 60 110 bool result = true; 61 111 const ast::Type * type; … … 69 119 maxDepth++; 70 120 } 71 void previsit( ast::ListInit const * ) {121 void previsit( ListInit * ) { 72 122 curDepth++; 123 GuardAction( [this]() { curDepth--; } ); 73 124 if ( curDepth > maxDepth ) result = false; 74 125 } 75 void postvisit( ast::ListInit const * ) { 76 curDepth--; 77 } 126 }; 127 128 struct InitFlattener_old : public WithShortCircuiting { 129 void previsit( SingleInit * singleInit ) { 130 visit_children = false; 131 argList.push_back( singleInit->value->clone() ); 132 } 133 std::list< Expression * > argList; 78 134 }; 79 135 … … 88 144 89 145 } // anonymous namespace 146 147 std::list< Expression * > makeInitList( Initializer * init ) { 148 PassVisitor<InitFlattener_old> flattener; 149 maybeAccept( init, flattener ); 150 return flattener.pass.argList; 151 } 152 153 bool isDesignated( Initializer * init ) { 154 PassVisitor<HasDesignations> finder; 155 maybeAccept( init, finder ); 156 return finder.pass.hasDesignations; 157 } 158 159 bool checkInitDepth( ObjectDecl * objDecl ) { 160 PassVisitor<InitDepthChecker> checker( objDecl->type ); 161 maybeAccept( objDecl->init, checker ); 162 return checker.pass.depthOkay; 163 } 90 164 91 165 bool isDesignated( const ast::Init * init ) { … … 106 180 return std::move( flattener.core.argList ); 107 181 } 182 183 class InitExpander_old::ExpanderImpl { 184 public: 185 virtual ~ExpanderImpl() = default; 186 virtual std::list< Expression * > next( std::list< Expression * > & indices ) = 0; 187 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ) = 0; 188 }; 189 190 class InitImpl_old : public InitExpander_old::ExpanderImpl { 191 public: 192 InitImpl_old( Initializer * init ) : init( init ) {} 193 virtual ~InitImpl_old() = default; 194 195 virtual std::list< Expression * > next( __attribute((unused)) std::list< Expression * > & indices ) { 196 // this is wrong, but just a placeholder for now 197 // if ( ! flattened ) flatten( indices ); 198 // return ! inits.empty() ? makeInitList( inits.front() ) : std::list< Expression * >(); 199 return makeInitList( init ); 200 } 201 202 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ); 203 private: 204 Initializer * init; 205 }; 206 207 class ExprImpl_old : public InitExpander_old::ExpanderImpl { 208 public: 209 ExprImpl_old( Expression * expr ) : arg( expr ) {} 210 virtual ~ExprImpl_old() { delete arg; } 211 212 virtual std::list< Expression * > next( std::list< Expression * > & indices ) { 213 std::list< Expression * > ret; 214 Expression * expr = maybeClone( arg ); 215 if ( expr ) { 216 for ( std::list< Expression * >::reverse_iterator it = indices.rbegin(); it != indices.rend(); ++it ) { 217 // go through indices and layer on subscript exprs ?[?] 218 ++it; 219 UntypedExpr * subscriptExpr = new UntypedExpr( new NameExpr( "?[?]") ); 220 subscriptExpr->get_args().push_back( expr ); 221 subscriptExpr->get_args().push_back( (*it)->clone() ); 222 expr = subscriptExpr; 223 } 224 ret.push_back( expr ); 225 } 226 return ret; 227 } 228 229 virtual Statement * buildListInit( UntypedExpr * callExpr, std::list< Expression * > & indices ); 230 private: 231 Expression * arg; 232 }; 233 234 InitExpander_old::InitExpander_old( Initializer * init ) : expander( new InitImpl_old( init ) ) {} 235 236 InitExpander_old::InitExpander_old( Expression * expr ) : expander( new ExprImpl_old( expr ) ) {} 237 238 std::list< Expression * > InitExpander_old::operator*() { 239 return cur; 240 } 241 242 InitExpander_old & InitExpander_old::operator++() { 243 cur = expander->next( indices ); 244 return *this; 245 } 246 247 // use array indices list to build switch statement 248 void InitExpander_old::addArrayIndex( Expression * index, Expression * dimension ) { 249 indices.push_back( index ); 250 indices.push_back( dimension ); 251 } 252 253 void InitExpander_old::clearArrayIndices() { 254 deleteAll( indices ); 255 indices.clear(); 256 } 257 258 bool InitExpander_old::addReference() { 259 bool added = false; 260 for ( Expression *& expr : cur ) { 261 expr = new AddressExpr( expr ); 262 added = true; 263 } 264 return added; 265 } 266 267 namespace { 268 /// given index i, dimension d, initializer init, and callExpr f, generates 269 /// if (i < d) f(..., init) 270 /// ++i; 271 /// so that only elements within the range of the array are constructed 272 template< typename OutIterator > 273 void buildCallExpr( UntypedExpr * callExpr, Expression * index, Expression * dimension, Initializer * init, OutIterator out ) { 274 UntypedExpr * cond = new UntypedExpr( new NameExpr( "?<?") ); 275 cond->get_args().push_back( index->clone() ); 276 cond->get_args().push_back( dimension->clone() ); 277 278 std::list< Expression * > args = makeInitList( init ); 279 callExpr->get_args().splice( callExpr->get_args().end(), args ); 280 281 *out++ = new IfStmt( cond, new ExprStmt( callExpr ), nullptr ); 282 283 UntypedExpr * increment = new UntypedExpr( new NameExpr( "++?" ) ); 284 increment->get_args().push_back( index->clone() ); 285 *out++ = new ExprStmt( increment ); 286 } 287 288 template< typename OutIterator > 289 void build( UntypedExpr * callExpr, InitExpander_old::IndexList::iterator idx, InitExpander_old::IndexList::iterator idxEnd, Initializer * init, OutIterator out ) { 290 if ( idx == idxEnd ) return; 291 Expression * index = *idx++; 292 assert( idx != idxEnd ); 293 Expression * dimension = *idx++; 294 295 // xxx - may want to eventually issue a warning here if we can detect 296 // that the number of elements exceeds to dimension of the array 297 if ( idx == idxEnd ) { 298 if ( ListInit * listInit = dynamic_cast< ListInit * >( init ) ) { 299 for ( Initializer * init : *listInit ) { 300 buildCallExpr( callExpr->clone(), index, dimension, init, out ); 301 } 302 } else { 303 buildCallExpr( callExpr->clone(), index, dimension, init, out ); 304 } 305 } else { 306 std::list< Statement * > branches; 307 308 unsigned long cond = 0; 309 ListInit * listInit = dynamic_cast< ListInit * >( init ); 310 if ( ! listInit ) { 311 // xxx - this shouldn't be an error, but need a way to 312 // terminate without creating output, so should catch this error 313 SemanticError( init->location, "unbalanced list initializers" ); 314 } 315 316 static UniqueName targetLabel( "L__autogen__" ); 317 Label switchLabel( targetLabel.newName(), 0, std::list< Attribute * >{ new Attribute("unused") } ); 318 for ( Initializer * init : *listInit ) { 319 Expression * condition; 320 // check for designations 321 // if ( init-> ) { 322 condition = new ConstantExpr( Constant::from_ulong( cond ) ); 323 ++cond; 324 // } else { 325 // condition = // ... take designation 326 // cond = // ... take designation+1 327 // } 328 std::list< Statement * > stmts; 329 build( callExpr, idx, idxEnd, init, back_inserter( stmts ) ); 330 stmts.push_back( new BranchStmt( switchLabel, BranchStmt::Break ) ); 331 CaseStmt * caseStmt = new CaseStmt( condition, stmts ); 332 branches.push_back( caseStmt ); 333 } 334 *out++ = new SwitchStmt( index->clone(), branches ); 335 *out++ = new NullStmt( { switchLabel } ); 336 } 337 } 338 } 339 340 // if array came with an initializer list: initialize each element 341 // may have more initializers than elements in the array - need to check at each index that 342 // we haven't exceeded size. 343 // may have fewer initializers than elements in the array - need to default construct 344 // remaining elements. 345 // To accomplish this, generate switch statement, consuming all of expander's elements 346 Statement * InitImpl_old::buildListInit( UntypedExpr * dst, std::list< Expression * > & indices ) { 347 if ( ! init ) return nullptr; 348 CompoundStmt * block = new CompoundStmt(); 349 build( dst, indices.begin(), indices.end(), init, back_inserter( block->get_kids() ) ); 350 if ( block->get_kids().empty() ) { 351 delete block; 352 return nullptr; 353 } else { 354 init = nullptr; // init was consumed in creating the list init 355 return block; 356 } 357 } 358 359 Statement * ExprImpl_old::buildListInit( UntypedExpr *, std::list< Expression * > & ) { 360 return nullptr; 361 } 362 363 Statement * InitExpander_old::buildListInit( UntypedExpr * dst ) { 364 return expander->buildListInit( dst, indices ); 365 } 108 366 109 367 class InitExpander_new::ExpanderImpl { … … 277 535 } 278 536 537 Type * getTypeofThis( FunctionType * ftype ) { 538 assertf( ftype, "getTypeofThis: nullptr ftype" ); 539 ObjectDecl * thisParam = getParamThis( ftype ); 540 ReferenceType * refType = strict_dynamic_cast< ReferenceType * >( thisParam->type ); 541 return refType->base; 542 } 543 279 544 const ast::Type * getTypeofThis( const ast::FunctionType * ftype ) { 280 545 assertf( ftype, "getTypeofThis: nullptr ftype" ); … … 287 552 } 288 553 554 ObjectDecl * getParamThis( FunctionType * ftype ) { 555 assertf( ftype, "getParamThis: nullptr ftype" ); 556 auto & params = ftype->parameters; 557 assertf( ! params.empty(), "getParamThis: ftype with 0 parameters: %s", toString( ftype ).c_str() ); 558 return strict_dynamic_cast< ObjectDecl * >( params.front() ); 559 } 560 289 561 const ast::ObjectDecl * getParamThis(const ast::FunctionDecl * func) { 290 562 assertf( func, "getParamThis: nullptr ftype" ); … … 292 564 assertf( ! params.empty(), "getParamThis: ftype with 0 parameters: %s", toString( func ).c_str()); 293 565 return params.front().strict_as<ast::ObjectDecl>(); 566 } 567 568 bool tryConstruct( DeclarationWithType * dwt ) { 569 ObjectDecl * objDecl = dynamic_cast< ObjectDecl * >( dwt ); 570 if ( ! objDecl ) return false; 571 return (objDecl->get_init() == nullptr || 572 ( objDecl->get_init() != nullptr && objDecl->get_init()->get_maybeConstructed() )) 573 && ! objDecl->get_storageClasses().is_extern 574 && isConstructable( objDecl->type ); 575 } 576 577 bool isConstructable( Type * type ) { 578 return ! dynamic_cast< VarArgsType * >( type ) && ! dynamic_cast< ReferenceType * >( type ) && ! dynamic_cast< FunctionType * >( type ) && ! Tuples::isTtype( type ); 294 579 } 295 580 … … 308 593 } 309 594 595 struct CallFinder_old { 596 CallFinder_old( const std::list< std::string > & names ) : names( names ) {} 597 598 void postvisit( ApplicationExpr * appExpr ) { 599 handleCallExpr( appExpr ); 600 } 601 602 void postvisit( UntypedExpr * untypedExpr ) { 603 handleCallExpr( untypedExpr ); 604 } 605 606 std::list< Expression * > * matches; 607 private: 608 const std::list< std::string > names; 609 610 template< typename CallExpr > 611 void handleCallExpr( CallExpr * expr ) { 612 std::string fname = getFunctionName( expr ); 613 if ( std::find( names.begin(), names.end(), fname ) != names.end() ) { 614 matches->push_back( expr ); 615 } 616 } 617 }; 618 310 619 struct CallFinder_new final { 311 620 std::vector< const ast::Expr * > matches; … … 325 634 }; 326 635 636 void collectCtorDtorCalls( Statement * stmt, std::list< Expression * > & matches ) { 637 static PassVisitor<CallFinder_old> finder( std::list< std::string >{ "?{}", "^?{}" } ); 638 finder.pass.matches = &matches; 639 maybeAccept( stmt, finder ); 640 } 641 327 642 std::vector< const ast::Expr * > collectCtorDtorCalls( const ast::Stmt * stmt ) { 328 643 ast::Pass< CallFinder_new > finder{ std::vector< std::string >{ "?{}", "^?{}" } }; … … 331 646 } 332 647 648 Expression * getCtorDtorCall( Statement * stmt ) { 649 std::list< Expression * > matches; 650 collectCtorDtorCalls( stmt, matches ); 651 assertf( matches.size() <= 1, "%zd constructor/destructors found in %s", matches.size(), toString( stmt ).c_str() ); 652 return matches.size() == 1 ? matches.front() : nullptr; 653 } 654 333 655 namespace { 656 DeclarationWithType * getCalledFunction( Expression * expr ); 657 658 template<typename CallExpr> 659 DeclarationWithType * handleDerefCalledFunction( CallExpr * expr ) { 660 // (*f)(x) => should get "f" 661 std::string name = getFunctionName( expr ); 662 assertf( name == "*?", "Unexpected untyped expression: %s", name.c_str() ); 663 assertf( ! expr->get_args().empty(), "Cannot get called function from dereference with no arguments" ); 664 return getCalledFunction( expr->get_args().front() ); 665 } 666 667 DeclarationWithType * getCalledFunction( Expression * expr ) { 668 assert( expr ); 669 if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( expr ) ) { 670 return varExpr->var; 671 } else if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( expr ) ) { 672 return memberExpr->member; 673 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( expr ) ) { 674 return getCalledFunction( castExpr->arg ); 675 } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( expr ) ) { 676 return handleDerefCalledFunction( untypedExpr ); 677 } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * > ( expr ) ) { 678 return handleDerefCalledFunction( appExpr ); 679 } else if ( AddressExpr * addrExpr = dynamic_cast< AddressExpr * >( expr ) ) { 680 return getCalledFunction( addrExpr->arg ); 681 } else if ( CommaExpr * commaExpr = dynamic_cast< CommaExpr * >( expr ) ) { 682 return getCalledFunction( commaExpr->arg2 ); 683 } 684 return nullptr; 685 } 686 687 DeclarationWithType * getFunctionCore( const Expression * expr ) { 688 if ( const auto * appExpr = dynamic_cast< const ApplicationExpr * >( expr ) ) { 689 return getCalledFunction( appExpr->function ); 690 } else if ( const auto * untyped = dynamic_cast< const UntypedExpr * >( expr ) ) { 691 return getCalledFunction( untyped->function ); 692 } 693 assertf( false, "getFunction with unknown expression: %s", toString( expr ).c_str() ); 694 } 695 } 696 697 DeclarationWithType * getFunction( Expression * expr ) { 698 return getFunctionCore( expr ); 699 } 700 701 const DeclarationWithType * getFunction( const Expression * expr ) { 702 return getFunctionCore( expr ); 703 } 704 705 ApplicationExpr * isIntrinsicCallExpr( Expression * expr ) { 706 ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr ); 707 if ( ! appExpr ) return nullptr; 708 DeclarationWithType * function = getCalledFunction( appExpr->get_function() ); 709 assertf( function, "getCalledFunction returned nullptr: %s", toString( appExpr->get_function() ).c_str() ); 710 // check for Intrinsic only - don't want to remove all overridable ctor/dtors because autogenerated ctor/dtor 711 // will call all member dtors, and some members may have a user defined dtor. 712 return function->get_linkage() == LinkageSpec::Intrinsic ? appExpr : nullptr; 713 } 714 715 namespace { 716 template <typename Predicate> 717 bool allofCtorDtor( Statement * stmt, const Predicate & pred ) { 718 std::list< Expression * > callExprs; 719 collectCtorDtorCalls( stmt, callExprs ); 720 return std::all_of( callExprs.begin(), callExprs.end(), pred); 721 } 722 334 723 template <typename Predicate> 335 724 bool allofCtorDtor( const ast::Stmt * stmt, const Predicate & pred ) { … … 337 726 return std::all_of( callExprs.begin(), callExprs.end(), pred ); 338 727 } 728 } 729 730 bool isIntrinsicSingleArgCallStmt( Statement * stmt ) { 731 return allofCtorDtor( stmt, []( Expression * callExpr ){ 732 if ( ApplicationExpr * appExpr = isIntrinsicCallExpr( callExpr ) ) { 733 FunctionType *funcType = GenPoly::getFunctionType( appExpr->function->result ); 734 assert( funcType ); 735 return funcType->get_parameters().size() == 1; 736 } 737 return false; 738 }); 339 739 } 340 740 … … 349 749 return false; 350 750 }); 751 } 752 753 bool isIntrinsicCallStmt( Statement * stmt ) { 754 return allofCtorDtor( stmt, []( Expression * callExpr ) { 755 return isIntrinsicCallExpr( callExpr ); 756 }); 757 } 758 759 namespace { 760 template<typename CallExpr> 761 Expression *& callArg( CallExpr * callExpr, unsigned int pos ) { 762 if ( pos >= callExpr->get_args().size() ) assertf( false, "getCallArg for argument that doesn't exist: (%u); %s.", pos, toString( callExpr ).c_str() ); 763 for ( Expression *& arg : callExpr->get_args() ) { 764 if ( pos == 0 ) return arg; 765 pos--; 766 } 767 assert( false ); 768 } 769 } 770 771 Expression *& getCallArg( Expression * callExpr, unsigned int pos ) { 772 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( callExpr ) ) { 773 return callArg( appExpr, pos ); 774 } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( callExpr ) ) { 775 return callArg( untypedExpr, pos ); 776 } else if ( TupleAssignExpr * tupleExpr = dynamic_cast< TupleAssignExpr * > ( callExpr ) ) { 777 std::list< Statement * > & stmts = tupleExpr->get_stmtExpr()->get_statements()->get_kids(); 778 assertf( ! stmts.empty(), "TupleAssignExpr somehow has no statements." ); 779 ExprStmt * stmt = strict_dynamic_cast< ExprStmt * >( stmts.back() ); 780 TupleExpr * tuple = strict_dynamic_cast< TupleExpr * >( stmt->get_expr() ); 781 assertf( ! tuple->get_exprs().empty(), "TupleAssignExpr somehow has empty tuple expr." ); 782 return getCallArg( tuple->get_exprs().front(), pos ); 783 } else if ( ImplicitCopyCtorExpr * copyCtor = dynamic_cast< ImplicitCopyCtorExpr * >( callExpr ) ) { 784 return getCallArg( copyCtor->callExpr, pos ); 785 } else { 786 assertf( false, "Unexpected expression type passed to getCallArg: %s", toString( callExpr ).c_str() ); 787 } 788 } 789 790 namespace { 791 std::string funcName( Expression * func ); 792 793 template<typename CallExpr> 794 std::string handleDerefName( CallExpr * expr ) { 795 // (*f)(x) => should get name "f" 796 std::string name = getFunctionName( expr ); 797 assertf( name == "*?", "Unexpected untyped expression: %s", name.c_str() ); 798 assertf( ! expr->get_args().empty(), "Cannot get function name from dereference with no arguments" ); 799 return funcName( expr->get_args().front() ); 800 } 801 802 std::string funcName( Expression * func ) { 803 if ( NameExpr * nameExpr = dynamic_cast< NameExpr * >( func ) ) { 804 return nameExpr->get_name(); 805 } else if ( VariableExpr * varExpr = dynamic_cast< VariableExpr * >( func ) ) { 806 return varExpr->get_var()->get_name(); 807 } else if ( CastExpr * castExpr = dynamic_cast< CastExpr * >( func ) ) { 808 return funcName( castExpr->get_arg() ); 809 } else if ( MemberExpr * memberExpr = dynamic_cast< MemberExpr * >( func ) ) { 810 return memberExpr->get_member()->get_name(); 811 } else if ( UntypedMemberExpr * memberExpr = dynamic_cast< UntypedMemberExpr * > ( func ) ) { 812 return funcName( memberExpr->get_member() ); 813 } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * >( func ) ) { 814 return handleDerefName( untypedExpr ); 815 } else if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( func ) ) { 816 return handleDerefName( appExpr ); 817 } else if ( ConstructorExpr * ctorExpr = dynamic_cast< ConstructorExpr * >( func ) ) { 818 return funcName( getCallArg( ctorExpr->get_callExpr(), 0 ) ); 819 } else { 820 assertf( false, "Unexpected expression type being called as a function in call expression: %s", toString( func ).c_str() ); 821 } 822 } 823 } 824 825 std::string getFunctionName( Expression * expr ) { 826 // there's some unforunate overlap here with getCalledFunction. Ideally this would be able to use getCalledFunction and 827 // return the name of the DeclarationWithType, but this needs to work for NameExpr and UntypedMemberExpr, where getCalledFunction 828 // can't possibly do anything reasonable. 829 if ( ApplicationExpr * appExpr = dynamic_cast< ApplicationExpr * >( expr ) ) { 830 return funcName( appExpr->get_function() ); 831 } else if ( UntypedExpr * untypedExpr = dynamic_cast< UntypedExpr * > ( expr ) ) { 832 return funcName( untypedExpr->get_function() ); 833 } else { 834 std::cerr << expr << std::endl; 835 assertf( false, "Unexpected expression type passed to getFunctionName" ); 836 } 837 } 838 839 Type * getPointerBase( Type * type ) { 840 if ( PointerType * ptrType = dynamic_cast< PointerType * >( type ) ) { 841 return ptrType->get_base(); 842 } else if ( ArrayType * arrayType = dynamic_cast< ArrayType * >( type ) ) { 843 return arrayType->get_base(); 844 } else if ( ReferenceType * refType = dynamic_cast< ReferenceType * >( type ) ) { 845 return refType->get_base(); 846 } else { 847 return nullptr; 848 } 849 } 850 851 Type * isPointerType( Type * type ) { 852 return getPointerBase( type ) ? type : nullptr; 853 } 854 855 ApplicationExpr * createBitwiseAssignment( Expression * dst, Expression * src ) { 856 static FunctionDecl * assign = nullptr; 857 if ( ! assign ) { 858 // temporary? Generate a fake assignment operator to represent bitwise assignments. 859 // This operator could easily exist as a real function, but it's tricky because nothing should resolve to this function. 860 TypeDecl * td = new TypeDecl( "T", noStorageClasses, nullptr, TypeDecl::Dtype, true ); 861 assign = new FunctionDecl( "?=?", noStorageClasses, LinkageSpec::Intrinsic, SymTab::genAssignType( new TypeInstType( noQualifiers, td->name, td ) ), nullptr ); 862 } 863 if ( dynamic_cast< ReferenceType * >( dst->result ) ) { 864 for (int depth = dst->result->referenceDepth(); depth > 0; depth--) { 865 dst = new AddressExpr( dst ); 866 } 867 } else { 868 dst = new CastExpr( dst, new ReferenceType( noQualifiers, dst->result->clone() ) ); 869 } 870 if ( dynamic_cast< ReferenceType * >( src->result ) ) { 871 for (int depth = src->result->referenceDepth(); depth > 0; depth--) { 872 src = new AddressExpr( src ); 873 } 874 } 875 return new ApplicationExpr( VariableExpr::functionPointer( assign ), { dst, src } ); 351 876 } 352 877 … … 380 905 return app; 381 906 } 907 908 struct ConstExprChecker : public WithShortCircuiting { 909 // most expressions are not const expr 910 void previsit( Expression * ) { isConstExpr = false; visit_children = false; } 911 912 void previsit( AddressExpr *addressExpr ) { 913 visit_children = false; 914 915 // address of a variable or member expression is constexpr 916 Expression * arg = addressExpr->get_arg(); 917 if ( ! dynamic_cast< NameExpr * >( arg) && ! dynamic_cast< VariableExpr * >( arg ) && ! dynamic_cast< MemberExpr * >( arg ) && ! dynamic_cast< UntypedMemberExpr * >( arg ) ) isConstExpr = false; 918 } 919 920 // these expressions may be const expr, depending on their children 921 void previsit( SizeofExpr * ) {} 922 void previsit( AlignofExpr * ) {} 923 void previsit( UntypedOffsetofExpr * ) {} 924 void previsit( OffsetofExpr * ) {} 925 void previsit( OffsetPackExpr * ) {} 926 void previsit( CommaExpr * ) {} 927 void previsit( LogicalExpr * ) {} 928 void previsit( ConditionalExpr * ) {} 929 void previsit( CastExpr * ) {} 930 void previsit( ConstantExpr * ) {} 931 932 void previsit( VariableExpr * varExpr ) { 933 visit_children = false; 934 935 if ( EnumInstType * inst = dynamic_cast< EnumInstType * >( varExpr->result ) ) { 936 long long int value; 937 if ( inst->baseEnum->valueOf( varExpr->var, value ) ) { 938 // enumerators are const expr 939 return; 940 } 941 } 942 isConstExpr = false; 943 } 944 945 bool isConstExpr = true; 946 }; 382 947 383 948 struct ConstExprChecker_new : public ast::WithShortCircuiting { … … 424 989 }; 425 990 991 bool isConstExpr( Expression * expr ) { 992 if ( expr ) { 993 PassVisitor<ConstExprChecker> checker; 994 expr->accept( checker ); 995 return checker.pass.isConstExpr; 996 } 997 return true; 998 } 999 1000 bool isConstExpr( Initializer * init ) { 1001 if ( init ) { 1002 PassVisitor<ConstExprChecker> checker; 1003 init->accept( checker ); 1004 return checker.pass.isConstExpr; 1005 } // if 1006 // for all intents and purposes, no initializer means const expr 1007 return true; 1008 } 1009 426 1010 bool isConstExpr( const ast::Expr * expr ) { 427 1011 if ( expr ) { … … 443 1027 } 444 1028 1029 const FunctionDecl * isCopyFunction( const Declaration * decl, const std::string & fname ) { 1030 const FunctionDecl * function = dynamic_cast< const FunctionDecl * >( decl ); 1031 if ( ! function ) return nullptr; 1032 if ( function->name != fname ) return nullptr; 1033 FunctionType * ftype = function->type; 1034 if ( ftype->parameters.size() != 2 ) return nullptr; 1035 1036 Type * t1 = getPointerBase( ftype->get_parameters().front()->get_type() ); 1037 Type * t2 = ftype->parameters.back()->get_type(); 1038 assert( t1 ); 1039 1040 if ( ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2, SymTab::Indexer() ) ) { 1041 return function; 1042 } else { 1043 return nullptr; 1044 } 1045 } 1046 445 1047 bool isAssignment( const ast::FunctionDecl * decl ) { 446 1048 return CodeGen::isAssignment( decl->name ) && isCopyFunction( decl ); … … 469 1071 return ResolvExpr::typesCompatibleIgnoreQualifiers( t1, t2 ); 470 1072 } 1073 1074 1075 const FunctionDecl * isAssignment( const Declaration * decl ) { 1076 return isCopyFunction( decl, "?=?" ); 1077 } 1078 const FunctionDecl * isDestructor( const Declaration * decl ) { 1079 if ( CodeGen::isDestructor( decl->name ) ) { 1080 return dynamic_cast< const FunctionDecl * >( decl ); 1081 } 1082 return nullptr; 1083 } 1084 const FunctionDecl * isDefaultConstructor( const Declaration * decl ) { 1085 if ( CodeGen::isConstructor( decl->name ) ) { 1086 if ( const FunctionDecl * func = dynamic_cast< const FunctionDecl * >( decl ) ) { 1087 if ( func->type->parameters.size() == 1 ) { 1088 return func; 1089 } 1090 } 1091 } 1092 return nullptr; 1093 } 1094 const FunctionDecl * isCopyConstructor( const Declaration * decl ) { 1095 return isCopyFunction( decl, "?{}" ); 1096 } 471 1097 472 1098 #if defined( __x86_64 ) || defined( __i386 ) // assembler comment to prevent assembler warning message … … 477 1103 static const char * const data_section = ".data" ASM_COMMENT; 478 1104 static const char * const tlsd_section = ".tdata" ASM_COMMENT; 1105 void addDataSectionAttribute( ObjectDecl * objDecl ) { 1106 const bool is_tls = objDecl->get_storageClasses().is_threadlocal_any(); 1107 const char * section = is_tls ? tlsd_section : data_section; 1108 objDecl->attributes.push_back(new Attribute("section", { 1109 new ConstantExpr( Constant::from_string( section ) ) 1110 })); 1111 } 479 1112 480 1113 void addDataSectionAttribute( ast::ObjectDecl * objDecl ) {
Note:
See TracChangeset
for help on using the changeset viewer.