| 851 | } |
| 852 | |
| 853 | vector<SimNode *> SimulateVisitor::simulateExprMakeStruct(const ExprMakeStruct *mks) { |
| 854 | gc_guard gc_scope; |
| 855 | vector<SimNode *> simlist; |
| 856 | // init with 0 |
| 857 | int total = int(mks->structs.size()); |
| 858 | int stride = mks->makeType->getStride(); |
| 859 | // note: if its an empty tuple init, like [[tuple<int;float>]] and its embedded - we need to zero it out |
| 860 | bool emptyEmbeddedTuple = ( mks->makeType->baseType==Type::tTuple && total==0); |
| 861 | bool partialyInitStruct = !mks->doesNotNeedInit && !mks->initAllFields; |
| 862 | if ( (emptyEmbeddedTuple || partialyInitStruct) && stride ) { |
| 863 | int bytes = das::max(total,1) * stride; |
| 864 | SimNode * init0; |
| 865 | if ( mks->useCMRES ) { |
| 866 | if ( bytes==0 ) { |
| 867 | init0 = nullptr; |
| 868 | } else if ( bytes <= 32 ) { |
| 869 | init0 = context.code->makeNodeUnrollNZ<SimNode_InitLocalCMResN>(bytes, mks->at, mks->extraOffset); |
| 870 | } else { |
| 871 | init0 = context.code->makeNode<SimNode_InitLocalCMRes>(mks->at, mks->extraOffset, bytes); |
| 872 | } |
| 873 | } else if ( mks->useStackRef ) { |
| 874 | init0 = context.code->makeNode<SimNode_InitLocalRef>(mks->at, mks->stackTop, mks->extraOffset, bytes); |
| 875 | } else { |
| 876 | init0 = context.code->makeNode<SimNode_InitLocal>(mks->at, mks->stackTop + mks->extraOffset, bytes); |
| 877 | } |
| 878 | if (init0) simlist.push_back(init0); |
| 879 | } |
| 880 | if ( mks->makeType->baseType == Type::tStructure ) { |
| 881 | for ( int index=0; index != total; ++index ) { |
| 882 | if ( mks->constructor ) { |
| 883 | uint32_t offset = mks->extraOffset + index*stride; |
| 884 | SimNode_CallBase * pCall = (SimNode_CallBase *) context.code->makeNodeUnrollAny<SimNode_CallAndCopyOrMove>(0, mks->at); |
| 885 | DAS_ASSERT(mks->constructor->index!=-1 && "should have failed in type infer otherwise"); |
| 886 | pCall->fnPtr = context.getFunction(mks->constructor->index); |
| 887 | if ( mks->useCMRES ) { |
| 888 | pCall->cmresEval = context.code->makeNode<SimNode_GetCMResOfs>(mks->at, offset); |
| 889 | } else if ( mks->useStackRef ) { |
| 890 | pCall->cmresEval = context.code->makeNode<SimNode_GetLocalRefOff>(mks->at, mks->stackTop, offset); |
| 891 | } else { |
| 892 | pCall->cmresEval = context.code->makeNode<SimNode_GetLocal>(mks->at, mks->stackTop + offset); |
| 893 | } |
| 894 | simlist.push_back(pCall); |
| 895 | } |
| 896 | auto & fields = mks->structs[index]; |
| 897 | for ( const auto & decl : *fields ) { |
| 898 | auto field = mks->makeType->structType->findField(decl->name); |
| 899 | DAS_ASSERT(field && "should have failed in type infer otherwise"); |
| 900 | uint32_t offset = mks->extraOffset + index*stride + field->offset; |
| 901 | SimNode * cpy; |
| 902 | if ( decl->value->rtti_isMakeLocal() ) { |
| 903 | // so what happens here, is we ask it for the generated commands and append it to this list only |
| 904 | auto mkl = static_cast<ExprMakeLocal*>(decl->value); |
| 905 | auto lsim = sv_simulateLocal(mkl); |
| 906 | simlist.insert(simlist.end(), lsim.begin(), lsim.end()); |
| 907 | continue; |
| 908 | } else if ( mks->useCMRES ) { |
| 909 | if ( decl->moveSemantics ){ |
| 910 | cpy = sv_makeLocalCMResMove(mks->at, offset, decl->value); |
nothing calls this directly
no test coverage detected