//unlike NodeBinaryOp, NodeBinaryOpCompare has a node type that's different from // its nodes, where left and right nodes are casted to be the same. bool NodeBinaryOpCompare::doBinaryOperationArray(s32 lslot, s32 rslot, u32 slots) { assert(0); //not implemented yet..TODO return bool. UlamValue rtnUV; UTI nuti = getNodeType(); //Bool, same array size as lhs/rhs UTI luti = m_nodeLeft->getNodeType(); UTI ruti = m_nodeRight->getNodeType(); s32 arraysize = m_state.getArraySize(luti); assert(arraysize = m_state.getArraySize(nuti)); //node is same array size as lhs/rhs s32 bitsize = m_state.getBitSize(luti); UTI scalartypidx = m_state.getUlamTypeAsScalar(luti); PACKFIT packRtn = m_state.determinePackable(nuti); if(WritePacked(packRtn)) { // pack result too. (slot size known ahead of time) rtnUV = UlamValue::makeAtom(nuti); //accumulate result here } // point to base array slots, packedness determines its 'pos' UlamValue lArrayPtr = UlamValue::makePtr(lslot, EVALRETURN, luti, packRtn, m_state); UlamValue rArrayPtr = UlamValue::makePtr(rslot, EVALRETURN, ruti, packRtn, m_state); // to use incrementPtr(), 'pos' depends on packedness UlamValue lp = UlamValue::makeScalarPtr(lArrayPtr, m_state); UlamValue rp = UlamValue::makeScalarPtr(rArrayPtr, m_state); //make immediate result for each element inside loop for(s32 i = 0; i < arraysize; i++) { UlamValue luv = m_state.getPtrTarget(lp); UlamValue ruv = m_state.getPtrTarget(rp); u32 ldata = luv.getData(lp.getPtrPos(), bitsize); //'pos' doesn't vary for unpacked u32 rdata = ruv.getData(rp.getPtrPos(), bitsize); //'pos' doesn't vary for unpacked if(WritePacked(packRtn)) //use calc position where base [0] is furthest from the end. appendBinaryOp(rtnUV, ldata, rdata, (BITSPERATOM-(bitsize * (arraysize - i))), bitsize); else { rtnUV = makeImmediateBinaryOp(scalartypidx, ldata, rdata, bitsize); //cp result UV to stack, -1 (first array element deepest) relative to current frame pointer m_state.m_nodeEvalStack.storeUlamValueInSlot(rtnUV, -slots + i); } assert(lp.incrementPtr(m_state)); assert(rp.incrementPtr(m_state)); } //forloop if(WritePacked(packRtn)) m_state.m_nodeEvalStack.storeUlamValueInSlot(rtnUV, -1); //store accumulated packed result return false; } //end dobinaryoparray
void NodeBinaryOpEqualBitwise::genCode(File * fp, UlamValue& uvpass) { assert(m_nodeLeft && m_nodeRight); assert(m_state.m_currentObjSymbolsForCodeGen.empty()); #ifdef TMPVARBRACES m_state.indent(fp); fp->write("{\n"); m_state.m_currentIndentLevel++; #endif // generate rhs first; may update current object globals (e.g. function call) UlamValue ruvpass; m_nodeRight->genCode(fp, ruvpass); // restore current object globals assert(m_state.m_currentObjSymbolsForCodeGen.empty()); // lhs should be the new current object: node member select updates them, // but a plain NodeIdent does not!!! because genCodeToStoreInto has been repurposed // to mean "don't read into a TmpVar" (e.g. by NodeCast). UlamValue luvpass; m_nodeLeft->genCodeToStoreInto(fp, luvpass); //may update m_currentObjSymbol //wiped out by left read; need to write back into left std::vector<Symbol *> saveCOSVector = m_state.m_currentObjSymbolsForCodeGen; uvpass = luvpass; //keep luvpass slot untouched Node::genCodeReadIntoATmpVar(fp, uvpass); m_state.m_currentObjSymbolsForCodeGen = saveCOSVector; //restore vector after lhs read************* UTI nuti = getNodeType(); UlamType * nut = m_state.getUlamTypeByIndex(nuti); s32 tmpVarNum = m_state.getNextTmpVarNumber(); m_state.indent(fp); fp->write("const "); fp->write(nut->getTmpStorageTypeAsString().c_str()); //e.g. u32, s32, u64.. fp->write(" "); fp->write(m_state.getTmpVarAsString(nuti,tmpVarNum).c_str()); fp->write(" = "); fp->write(methodNameForCodeGen().c_str()); fp->write("("); UTI uti = uvpass.getUlamValueTypeIdx(); assert(uti == Ptr); fp->write(m_state.getTmpVarAsString(uvpass.getPtrTargetType(), uvpass.getPtrSlotIndex()).c_str()); fp->write(", "); UTI ruti = ruvpass.getUlamValueTypeIdx(); assert(ruti == Ptr); fp->write(m_state.getTmpVarAsString(ruvpass.getPtrTargetType(), ruvpass.getPtrSlotIndex()).c_str()); fp->write(", "); fp->write_decimal(nut->getBitSize()); fp->write(");\n"); uvpass = UlamValue::makePtr(tmpVarNum, TMPREGISTER, nuti, m_state.determinePackable(nuti), m_state, uvpass.getPtrPos(), uvpass.getPtrNameId()); //P // current object globals should pertain to lhs for the write genCodeWriteFromATmpVar(fp, luvpass, uvpass); //uses rhs' tmpvar; orig lhs #ifdef TMPVARBRACES m_state.m_currentIndentLevel--; m_state.indent(fp); fp->write("}\n"); //close for tmpVar #endif assert(m_state.m_currentObjSymbolsForCodeGen.empty()); } //genCode
EvalStatus NodeSquareBracket::evalToStoreInto() { assert(m_nodeLeft && m_nodeRight); UTI nuti = getNodeType(); if(nuti == Nav) return ERROR; evalNodeProlog(0); //new current frame pointer makeRoomForSlots(1); //always 1 slot for ptr EvalStatus evs = m_nodeLeft->evalToStoreInto(); if(evs != NORMAL) { evalNodeEpilog(); return evs; } UlamValue pluv = m_state.m_nodeEvalStack.popArg(); makeRoomForNodeType(m_nodeRight->getNodeType()); //offset a constant expression evs = m_nodeRight->eval(); if(evs != NORMAL) { evalNodeEpilog(); return evs; } UlamValue offset = m_state.m_nodeEvalStack.popArg(); // constant expression only required for array declaration u32 offsetdata = offset.getImmediateData(m_state); s32 offsetInt = m_state.getUlamTypeByIndex(offset.getUlamValueTypeIdx())->getDataAsCs32(offsetdata); UTI auti = pluv.getPtrTargetType(); UlamType * aut = m_state.getUlamTypeByIndex(auti); if(aut->isCustomArray()) { UTI caType = ((UlamTypeClass *) aut)->getCustomArrayType(); UlamType * caut = m_state.getUlamTypeByIndex(caType); u32 pos = pluv.getPtrPos(); if(caut->getBitSize() > MAXBITSPERINT) pos = 0; // itemUV = UlamValue::makeAtom(caType); //else // itemUV = UlamValue::makeImmediate(caType, 0, m_state); //quietly skip for now XXX //use CA type, not the left ident's type UlamValue scalarPtr = UlamValue::makePtr(pluv.getPtrSlotIndex(), pluv.getPtrStorage(), caType, m_state.determinePackable(caType), //PACKEDLOADABLE m_state, pos /* base pos of array */ ); //copy result UV to stack, -1 relative to current frame pointer assignReturnValuePtrToStack(scalarPtr); } else { //adjust pos by offset * len, according to its scalar type UlamValue scalarPtr = UlamValue::makeScalarPtr(pluv, m_state); if(scalarPtr.incrementPtr(m_state, offsetInt)) //copy result UV to stack, -1 relative to current frame pointer assignReturnValuePtrToStack(scalarPtr); else { s32 arraysize = m_state.getArraySize(pluv.getPtrTargetType()); Symbol * lsymptr; u32 lid = 0; if(getSymbolPtr(lsymptr)) lid = lsymptr->getId(); std::ostringstream msg; msg << "Array subscript [" << offsetInt << "] exceeds the size (" << arraysize; msg << ") of array '" << m_state.m_pool.getDataAsString(lid).c_str() << "'"; MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); evs = ERROR; } } evalNodeEpilog(); return evs; } //evalToStoreInto