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