ExprLet
| 549 | } |
| 550 | // ExprLet |
| 551 | virtual void preVisitLet ( ExprLet * expr, const VariablePtr & var, bool last ) override { |
| 552 | Visitor::preVisitLet(expr,var,last); |
| 553 | if ( inStruct ) return; |
| 554 | uint32_t sz = var->type->ref ? sizeof(void *) : var->type->getSizeOf(); |
| 555 | if ( var->aliasCMRES ) { |
| 556 | if ( log ) { |
| 557 | logs << "\tCR\t" << sz |
| 558 | << "\tlet " << var->name << ", line " << var->at.line << "\n"; |
| 559 | } |
| 560 | } else { |
| 561 | var->stackTop = allocateStack(sz); |
| 562 | if ( log ) { |
| 563 | logs << "\t" << var->stackTop << "\t" << sz |
| 564 | << "\tlet " << var->name << ", line " << var->at.line << "\n"; |
| 565 | if ( log_var_scope ) { |
| 566 | logs <<"\t\t\t\t" << expr->visibility.describe(true) << "\n"; |
| 567 | } |
| 568 | } |
| 569 | } |
| 570 | for ( auto blk=scopes.rbegin(), blks=scopes.rend(); blk!=blks; ++blk ) { |
| 571 | auto pblock = *blk; |
| 572 | pblock->stackCleanVars.push_back(make_pair(var->stackTop, var->type->ref ? int(sizeof(void *)) : var->type->getSizeOf())); |
| 573 | if ( pblock->isClosure ) break; |
| 574 | } |
| 575 | if ( var->init ) { |
| 576 | if ( var->init->rtti_isMakeLocal() ) { |
| 577 | auto mkl = static_cast<ExprMakeLocal*>(var->init); |
| 578 | mkl->setRefSp(false, var->aliasCMRES, var->stackTop, 0); |
| 579 | mkl->doesNotNeedInit = false; |
| 580 | } else if ( var->init->rtti_isCall() ) { |
| 581 | auto cll = static_cast<ExprCall*>(var->init); |
| 582 | if ( (cll->func->copyOnReturn || cll->func->moveOnReturn) && !cll->func->aliasCMRES ) { // note: let never aliases!!! |
| 583 | cll->doesNotNeedSp = true; |
| 584 | } else { |
| 585 | cll->doesNotNeedSp = false; |
| 586 | } |
| 587 | } else if ( var->init->rtti_isInvoke() ) { |
| 588 | auto cll = static_cast<ExprInvoke*>(var->init); |
| 589 | if ( cll->isCopyOrMove() ) { |
| 590 | cll->doesNotNeedSp = true; |
| 591 | } else { |
| 592 | cll->doesNotNeedSp = false; |
| 593 | } |
| 594 | } |
| 595 | } |
| 596 | if (!var->type->ref && var->type->baseType != Type::tBlock) { |
| 597 | pushSp(); // Free everything allocated to init let (not let itself) |
| 598 | } |
| 599 | } |
| 600 | virtual VariablePtr visitLet ( ExprLet * /*expr*/, const VariablePtr & var, bool /*last*/ ) override { |
| 601 | if (!inStruct && !var->type->ref && var->type->baseType != Type::tBlock) { |
| 602 | popSp(); |
nothing calls this directly
no test coverage detected