| 618 | } |
| 619 | |
| 620 | SimNode * Function::simulate (Context & context) const { |
| 621 | if ( builtIn ) { |
| 622 | DAS_ASSERTF(0, "can only simulate non built-in function"); |
| 623 | return nullptr; |
| 624 | } |
| 625 | for ( auto & ann : annotations ) { |
| 626 | if ( ann->annotation->rtti_isFunctionAnnotation() ) { |
| 627 | auto fann = (FunctionAnnotation *)(ann->annotation); |
| 628 | string err; |
| 629 | auto node = fann->simulate(&context, (Function*)this, ann->arguments, err); |
| 630 | if ( !node ) { |
| 631 | if ( !err.empty() ) { |
| 632 | context.thisProgram->error("integration error, function failed to simulate", err, "", |
| 633 | at, CompilationError::internal_function_annotation ); |
| 634 | return nullptr; |
| 635 | } |
| 636 | } else { |
| 637 | return node; |
| 638 | } |
| 639 | } |
| 640 | } |
| 641 | SimulateVisitor sv(context); |
| 642 | sv.simulateExpression(body); |
| 643 | if ( fastCall ) { |
| 644 | DAS_ASSERT(totalStackSize == sizeof(Prologue) && "function can't allocate stack"); |
| 645 | DAS_ASSERT((result->isWorkhorseType() || result->isVoid()) && "fastcall can only return a workhorse type"); |
| 646 | DAS_ASSERT(body->rtti_isBlock() && "function must contain a block"); |
| 647 | auto block = static_cast<ExprBlock*>(body); |
| 648 | if ( block->list.size()==0 ) { |
| 649 | DAS_ASSERT(block->inFunction && block->inFunction->result->isVoid() && "only void function produces fastcall NOP"); |
| 650 | return context.code->makeNode<SimNode_NOP>(block->at); |
| 651 | } |
| 652 | if ( block->list.back()->rtti_isReturn() ) { |
| 653 | DAS_ASSERT(block->list.back()->rtti_isReturn() && "fastcall body expr is return"); |
| 654 | auto retE = static_cast<ExprReturn*>(block->list.back()); |
| 655 | if ( retE->subexpr ) { |
| 656 | return sv.getE(retE->subexpr); |
| 657 | } else { |
| 658 | return context.code->makeNode<SimNode_NOP>(retE->at); |
| 659 | } |
| 660 | } else { |
| 661 | return sv.getE(block->list.back()); |
| 662 | } |
| 663 | } else { |
| 664 | #if DAS_DEBUGGER |
| 665 | if ( context.debugger ) { |
| 666 | auto sbody = sv.getE(body); |
| 667 | if ( !sbody->rtti_node_isBlock() ) { |
| 668 | auto block = context.code->makeNode<SimNodeDebug_BlockNF>(sbody->debugInfo); |
| 669 | block->total = 1; |
| 670 | block->list = (SimNode **) context.code->allocate(sizeof(SimNode *)*1); |
| 671 | block->list[0] = sbody; |
| 672 | return block; |
| 673 | } else { |
| 674 | return sbody; |
| 675 | } |
| 676 | } else { |
| 677 | return sv.getE(body); |
no test coverage detected