void UnpackedStorage::assignUlamValuePtr(UlamValue pluv, UlamValue puv) { assert(pluv.getPtrTargetType() == puv.getPtrTargetType()); s32 leftbaseslot = pluv.getPtrSlotIndex(); //even for scalars m_values[leftbaseslot] = puv; }
void UnpackedStorage::assignUlamValue(UlamValue pluv, UlamValue ruv) { assert(pluv.getUlamValueTypeIdx() == Ptr); assert(ruv.getUlamValueTypeIdx() != Ptr); s32 leftbaseslot = pluv.getPtrSlotIndex(); //even for scalars if(pluv.isTargetPacked() == UNPACKED) { m_values[leftbaseslot] = ruv; //must be immediate } else { //target is packed or packedloadable, use pos & len in ptr UlamValue lvalAtIdx = loadDataMemberAt(leftbaseslot); assert(lvalAtIdx.getUlamValueTypeIdx() == UAtom); //? lvalAtIdx.putDataIntoAtom(pluv, ruv, m_state); storeDataMemberAt(lvalAtIdx, leftbaseslot); } }
void NodeCast::genCodeCastAtomAndElement(File * fp, UlamValue & uvpass) { UTI nuti = getNodeType(); UlamType * nut = m_state.getUlamTypeByIndex(nuti); UTI vuti = uvpass.getUlamValueTypeIdx(); s32 tmpVarNum = 0; if(vuti == Ptr) { tmpVarNum = uvpass.getPtrSlotIndex(); vuti = uvpass.getPtrTargetType(); //replace } // "downcast" might not be true; compare to be sure the atom is an element "Foo" if(vuti == UAtom) { m_state.indent(fp); fp->write("if(!"); fp->write(nut->getUlamTypeMangledName().c_str()); fp->write("<EC>::THE_INSTANCE."); fp->write(m_state.getIsMangledFunctionName()); fp->write("("); fp->write(m_state.getTmpVarAsString(vuti, tmpVarNum).c_str()); fp->write("))\n"); m_state.m_currentIndentLevel++; m_state.indent(fp); fp->write("FAIL(BAD_CAST);\n"); m_state.m_currentIndentLevel--; } //update the uvpass to have the casted type uvpass = UlamValue::makePtr(tmpVarNum, uvpass.getPtrStorage(), nuti, m_state.determinePackable(nuti), m_state, 0, uvpass.getPtrNameId()); //POS 0 rightjustified; pass along name id return; } //genCodeCastAtomAndElement
void NodeCast::genCodeReadIntoATmpVar(File * fp, UlamValue& uvpass) { // e.g. called by NodeFunctionCall on a NodeTerminal.. if(!needsACast()) { return m_node->genCodeReadIntoATmpVar(fp, uvpass); } UTI nuti = getNodeType(); UlamType * nut = m_state.getUlamTypeByIndex(nuti); UTI vuti = uvpass.getUlamValueTypeIdx(); bool isTerminal = false; s32 tmpVarNum = 0; if(vuti == Ptr) { tmpVarNum = uvpass.getPtrSlotIndex(); vuti = uvpass.getPtrTargetType(); //replace } else { // an immediate terminal value isTerminal = true; } if(nuti == vuti) return; //nothing to do! UlamType * vut = m_state.getUlamTypeByIndex(vuti); //after vuti replacement ULAMCLASSTYPE nclasstype = nut->getUlamClass(); ULAMCLASSTYPE vclasstype = vut->getUlamClass(); //handle element-atom and atom-element casting differently: // handle element->quark, atom->quark, not quark->element or quark->atom if(nuti == UAtom || vuti == UAtom || vclasstype == UC_ELEMENT || vclasstype == UC_QUARK) { //only to be nclasstype quark makes sense!!! check first, one might be element if(nclasstype == UC_QUARK || vclasstype == UC_QUARK) return genCodeCastAtomAndQuark(fp, uvpass); if(nclasstype == UC_ELEMENT || vclasstype == UC_ELEMENT) return genCodeCastAtomAndElement(fp, uvpass); { std::ostringstream msg; msg << "Casting 'incomplete' types: "; msg << m_state.getUlamTypeNameByIndex(nuti).c_str(); msg << "(UTI" << nuti << ") to be " << m_state.getUlamTypeNameByIndex(vuti).c_str(); msg << "(UTI" << vuti << ")"; MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), DEBUG); return; } } s32 tmpVarCastNum = m_state.getNextTmpVarNumber(); m_state.indent(fp); fp->write("const "); fp->write(nut->getTmpStorageTypeAsString().c_str()); //e.g. u32, s32, u64, etc. fp->write(" "); fp->write(m_state.getTmpVarAsString(nuti, tmpVarCastNum).c_str()); fp->write(" = "); // write the cast method (e.g. _Unsigned32ToInt32, _Int32ToUnary32, etc..) fp->write(nut->castMethodForCodeGen(vuti).c_str()); fp->write("("); if(isTerminal) { s32 len = m_state.getBitSize(vuti); assert(len != UNKNOWNSIZE); if(len <= MAXBITSPERINT) { u32 data = uvpass.getImmediateData(m_state); char dstr[40]; vut->getDataAsString(data, dstr, 'z'); fp->write(dstr); } else if(len <= MAXBITSPERLONG) { u64 data = uvpass.getImmediateDataLong(m_state); char dstr[70]; vut->getDataLongAsString(data, dstr, 'z'); fp->write(dstr); } else assert(0); } else { fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum).c_str()); } fp->write(", "); assert(!(nuti == UAtom || vuti == UAtom)); //LENGTH of node being casted (Uh_AP_mi::LENGTH ?) //fp->write(m_state.getBitVectorLengthAsStringForCodeGen(nodetype).c_str()); fp->write_decimal(m_state.getTotalBitSize(vuti)); //src length fp->write(", "); fp->write_decimal(m_state.getTotalBitSize(nuti)); //tobe length fp->write(")"); fp->write(";\n"); //PROBLEM is that funccall checks for 0 nameid to use the tmp var! // but then if we don't pass it along Node::genMemberNameForMethod fails.. if(isTerminal) uvpass = UlamValue::makePtr(tmpVarCastNum, TMPREGISTER, nuti, m_state.determinePackable(nuti), m_state, 0); //POS 0 rightjustified. else uvpass = UlamValue::makePtr(tmpVarCastNum, TMPREGISTER, nuti, m_state.determinePackable(nuti), m_state, 0, uvpass.getPtrNameId()); //POS 0 rightjustified; pass along name id } //genCodeReadIntoTmp
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
void NodeBinaryOpCompare::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()); //************* UlamValue luvpass; m_nodeLeft->genCode(fp, luvpass); //updates m_currentObjSymbol 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 luti = luvpass.getUlamValueTypeIdx(); assert(luti == Ptr); luti = luvpass.getPtrTargetType(); //reset fp->write(m_state.getTmpVarAsString(luti, luvpass.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(", "); //compare needs size of left/right nodes (only difference!) fp->write_decimal(m_state.getUlamTypeByIndex(luti)->getTotalBitSize()); fp->write(");\n"); uvpass = UlamValue::makePtr(tmpVarNum, TMPREGISTER, nuti, m_state.determinePackable(nuti), m_state, 0); //P #ifdef TMPVARBRACES m_state.m_currentIndentLevel--; m_state.indent(fp); fp->write("}\n"); //close for tmpVar #endif assert(m_state.m_currentObjSymbolsForCodeGen.empty()); //************* } //genCode