void NodeUnaryOp::genCode(File * fp, UVPass& uvpass) { assert(m_node); m_node->genCode(fp, uvpass); UTI nuti = getNodeType(); UlamType * nut = m_state.getUlamTypeByIndex(nuti); s32 tmpVarNum = m_state.getNextTmpVarNumber(); m_state.indentUlamCode(fp); fp->write("const "); fp->write(nut->getTmpStorageTypeAsString().c_str()); //e.g. u32, s32, u64.. fp->write(" "); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum, TMPREGISTER).c_str()); fp->write(" = "); fp->write(methodNameForCodeGen().c_str()); fp->write("("); fp->write(uvpass.getTmpVarAsString(m_state).c_str()); fp->write(", "); fp->write_decimal(nut->getBitSize()); fp->write(");"); GCNL; uvpass = UVPass::makePass(tmpVarNum, TMPREGISTER, nuti, m_state.determinePackable(nuti), m_state, 0, 0); //POS 0 rightjustified. } //genCode
void NodeBinaryOpEqualShift::genCode(File * fp, UVPass& uvpass) { assert(m_nodeLeft && m_nodeRight); assert(m_state.m_currentObjSymbolsForCodeGen.empty()); // generate rhs first; may update current object globals (e.g. function call) UVPass 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). UVPass 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.indentUlamCode(fp); fp->write("const "); fp->write(nut->getTmpStorageTypeAsString().c_str()); //e.g. u32, s32, u64.. fp->write(" "); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum, TMPREGISTER).c_str()); fp->write(" = "); fp->write(methodNameForCodeGen().c_str()); fp->write("("); fp->write(uvpass.getTmpVarAsString(m_state).c_str()); fp->write(", "); fp->write(ruvpass.getTmpVarAsString(m_state).c_str()); fp->write(", "); fp->write_decimal(nut->getBitSize()); fp->write(");"); GCNL; uvpass = UVPass::makePass(tmpVarNum, TMPREGISTER, nuti, m_state.determinePackable(nuti), m_state, uvpass.getPassPos(), uvpass.getPassNameId()); //P // current object globals should pertain to lhs for the write genCodeWriteFromATmpVar(fp, luvpass, uvpass); //uses rhs' tmpvar; orig lhs assert(m_state.m_currentObjSymbolsForCodeGen.empty()); } //genCode
void NodeBinaryOpCompare::genCode(File * fp, UVPass& uvpass) { assert(m_nodeLeft && m_nodeRight); assert(m_state.m_currentObjSymbolsForCodeGen.empty()); //************* // generate rhs first; may update current object globals (e.g. function call) UVPass ruvpass; m_nodeRight->genCode(fp, ruvpass); // restore current object globals assert(m_state.m_currentObjSymbolsForCodeGen.empty()); //************* UVPass 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.indentUlamCode(fp); fp->write("const "); fp->write(nut->getTmpStorageTypeAsString().c_str()); //e.g. u32, s32, u64.. fp->write(" "); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum, TMPREGISTER).c_str()); fp->write(" = "); fp->write(methodNameForCodeGen().c_str()); fp->write("("); UTI luti = luvpass.getPassTargetType(); //reset fp->write(luvpass.getTmpVarAsString(m_state).c_str()); fp->write(", "); fp->write(ruvpass.getTmpVarAsString(m_state).c_str()); fp->write(", "); //compare needs size of left/right nodes (only difference!) fp->write_decimal(m_state.getUlamTypeByIndex(luti)->getTotalBitSize()); fp->write(");"); GCNL; uvpass = UVPass::makePass(tmpVarNum, TMPREGISTER, nuti, m_state.determinePackable(nuti), m_state, 0, 0); //P assert(m_state.m_currentObjSymbolsForCodeGen.empty()); //************* } //genCode
//short-circuit when lhs is true void NodeBinaryOpLogicalOr::genCode(File * fp, UVPass& uvpass) { assert(m_nodeLeft && m_nodeRight); assert(m_state.m_currentObjSymbolsForCodeGen.empty()); //************* //initialize node result to false UTI nuti = getNodeType(); UlamType * nut = m_state.getUlamTypeByIndex(nuti); s32 tmpVarNum = m_state.getNextTmpVarNumber(); m_state.indentUlamCode(fp); //fp->write("const "); fp->write(nut->getTmpStorageTypeAsString().c_str()); //e.g. u32, s32, u64.. fp->write(" "); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum, TMPREGISTER).c_str()); fp->write(" = false;"); GCNL; //process lhs first UVPass luvpass; m_nodeLeft->genCode(fp, luvpass); //updates m_currentObjSymbol UTI luti = luvpass.getPassTargetType(); UlamType * lut = m_state.getUlamTypeByIndex(luti); assert(lut->getUlamTypeEnum() == Bool); //fp->write("\n"); m_state.indentUlamCode(fp); fp->write("if(!"); //lhs is false fp->write(((UlamTypePrimitiveBool *) lut)->getConvertToCboolMethod().c_str()); fp->write("("); fp->write(luvpass.getTmpVarAsString(m_state).c_str()); fp->write(", "); fp->write_decimal(lut->getBitSize()); fp->write(")"); fp->write(")"); GCNL; m_state.indentUlamCode(fp); fp->write("{\n"); m_state.m_currentIndentLevel++; UVPass ruvpass; m_nodeRight->genCode(fp, ruvpass); //set node's tmp var to whatever rhs value m_state.indentUlamCode(fp); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum, TMPREGISTER).c_str()); fp->write(" = "); fp->write(ruvpass.getTmpVarAsString(m_state).c_str()); fp->write(";"); GCNL; m_state.m_currentIndentLevel--; m_state.indentUlamCode(fp); fp->write("}\n"); m_state.indentUlamCode(fp); fp->write("else\n"); m_state.indentUlamCode(fp); fp->write("{\n"); m_state.m_currentIndentLevel++; //set node's tmp var to lhs value (true) m_state.indentUlamCode(fp); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum, TMPREGISTER).c_str()); fp->write(" = "); fp->write(luvpass.getTmpVarAsString(m_state).c_str()); fp->write(";"); GCNL; m_state.m_currentIndentLevel--; m_state.indentUlamCode(fp); fp->write("}\n"); uvpass = UVPass::makePass(tmpVarNum, TMPREGISTER, nuti, m_state.determinePackable(nuti), m_state, 0, 0); //P assert(m_state.m_currentObjSymbolsForCodeGen.empty()); //************* } //genCode
void NodeAtomof::genCode(File * fp, UVPass& uvpass) { //lhs, no longer allowed with packed elements assert(getStoreIntoAble() == TBOOL_TRUE); UTI nuti = getNodeType(); //UAtomRef if(m_nodeOf->hasASymbolReference() && (m_state.getUlamTypeByIndex(getOfType())->getUlamClassType() == UC_QUARK)) { Symbol * stgcos = NULL; AssertBool gotstg = m_nodeOf->getStorageSymbolPtr(stgcos); assert(gotstg); m_state.indentUlamCode(fp); fp->write("if("); fp->write(stgcos->getMangledName().c_str()); fp->write(".GetType() == T::ATOM_UNDEFINED_TYPE)"); GCNL; m_state.m_currentIndentLevel++; m_state.indentUlamCode(fp); fp->write("FAIL(NOT_AN_ELEMENT);"); GCNL; m_state.m_currentIndentLevel--; UlamType * nut = m_state.getUlamTypeByIndex(nuti); s32 tmpVarNum = m_state.getNextTmpVarNumber(); //tmp for atomref m_state.indentUlamCode(fp); //non-const fp->write(nut->getLocalStorageTypeAsString().c_str()); //for C++ local vars fp->write(" "); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum, TMPBITVAL).c_str()); fp->write("("); fp->write(stgcos->getMangledName().c_str()); //ur for self fp->write(", "); //is storage! can't be const (error/t3659) fp->write(" - T::ATOM_FIRST_STATE_BIT"); //must be an effective element ref (e.g.t3684, t3663) fp->write("); //atomof"); GCNL; //read into a T s32 tmpVarNum2 = m_state.getNextTmpVarNumber(); //tmp for atomref m_state.indentUlamCode(fp); fp->write("const "); fp->write(nut->getTmpStorageTypeAsString().c_str()); //for C++ local vars fp->write(" "); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum2, TMPTATOM).c_str()); fp->write(" = "); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum, TMPBITVAL).c_str()); fp->write(".read();"); GCNL; uvpass = UVPass::makePass(tmpVarNum2, TMPTATOM, nuti, UNPACKED, m_state, 0, uvpass.getPassNameId()); } else { //get the element in a tmpvar; necessary for array item members selected (at runtime). m_nodeOf->genCode(fp, uvpass); assert(m_state.m_currentObjSymbolsForCodeGen.empty()); //e.g. 'return self.atomof;' (e.g. t3408, t3410, t3585, t3631, t3663) uvpass = UVPass::makePass(uvpass.getPassVarNum(), TMPTATOM, nuti, UNPACKED, m_state, uvpass.getPassPos(), uvpass.getPassNameId()); } } //genCode
void NodeInstanceof::genCode(File * fp, UVPass& uvpass) { //generates a new instance of.. UTI nuti = getNodeType(); UlamType * nut = m_state.getUlamTypeByIndex(nuti); s32 tmpVarNum = m_state.getNextTmpVarNumber(); //tmp for atomref Symbol * cos = NULL; Symbol * stgcos = NULL; //starts out as its default type; references (UAtom) are updated: m_state.indentUlamCode(fp); //non-const fp->write(nut->getLocalStorageTypeAsString().c_str()); //for C++ local vars fp->write(" "); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum, TMPBITVAL).c_str()); fp->write(";"); GCNL; // a reference (including 'self'), returns a UAtom of effective type; // SINCE effective self type is known only at runtime. if(m_nodeOf) { m_nodeOf->genCodeToStoreInto(fp, uvpass); assert(!m_state.m_currentObjSymbolsForCodeGen.empty()); cos = m_state.m_currentObjSymbolsForCodeGen.back(); UTI cosuti = cos->getUlamTypeIdx(); stgcos = m_state.m_currentObjSymbolsForCodeGen[0]; bool isself = stgcos->isSelf(); bool issuper = stgcos->isSuper(); bool isaref = m_state.isAltRefType(cosuti) || isself || issuper; if(isaref) { u32 tmpuclass = m_state.getNextTmpVarNumber(); //only for this case m_state.indentUlamCode(fp); fp->write("const UlamClass<EC> * "); fp->write(m_state.getUlamClassTmpVarAsString(tmpuclass).c_str()); fp->write(" = "); fp->write(cos->getMangledName().c_str()); fp->write(".GetEffectiveSelf();"); GCNL; //primitive FAILS m_state.indentUlamCode(fp); fp->write("if("); fp->write(m_state.getUlamClassTmpVarAsString(tmpuclass).c_str()); fp->write(" == NULL) FAIL(ILLEGAL_ARGUMENT); //non-class"); GCNL; //an immediate default quark FAILS m_state.indentUlamCode(fp); fp->write("if("); fp->write(m_state.getUlamClassTmpVarAsString(tmpuclass).c_str()); fp->write("->AsUlamQuark() != NULL) "); fp->write("FAIL(NOT_AN_ELEMENT); //quark"); GCNL; m_state.indentUlamCode(fp); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum, TMPBITVAL).c_str()); fp->write(".WriteAtom("); fp->write("((UlamElement<EC> *) "); fp->write(m_state.getUlamClassTmpVarAsString(tmpuclass).c_str()); fp->write(")->GetDefaultAtom()); //instanceof default element"); GCNL; } else if(m_state.isAtom(nuti)) { u32 tmpuclass = m_state.getNextTmpVarNumber(); //only for this case m_state.indentUlamCode(fp); fp->write("const UlamClass<EC> * "); fp->write(m_state.getUlamClassTmpVarAsString(tmpuclass).c_str()); fp->write(" = "); fp->write("uc.LookupUlamElementTypeFromContext("); fp->write(cos->getMangledName().c_str()); fp->write(".GetType()"); fp->write(");"); GCNL; m_state.indentUlamCode(fp); fp->write("if("); fp->write(m_state.getUlamClassTmpVarAsString(tmpuclass).c_str()); fp->write(" == NULL) FAIL(ILLEGAL_ARGUMENT); //non-class"); GCNL; m_state.indentUlamCode(fp); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum, TMPBITVAL).c_str()); fp->write(".WriteAtom("); fp->write("((UlamElement<EC> *) "); fp->write(m_state.getUlamClassTmpVarAsString(tmpuclass).c_str()); fp->write(")->GetDefaultAtom()); //instanceof default element"); GCNL; } } if(m_state.isAtom(nuti)) { // THE READ: s32 tmpVarNum2 = m_state.getNextTmpVarNumber(); //tmp to read into TMPSTORAGE rstor = nut->getTmpStorageTypeForTmpVar(); m_state.indentUlamCode(fp); fp->write("const "); fp->write(nut->getTmpStorageTypeAsString().c_str()); //for C++ local vars fp->write(" "); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum2, rstor).c_str()); fp->write(" = "); fp->write(m_state.getTmpVarAsString(nuti, tmpVarNum, TMPBITVAL).c_str()); fp->write("."); fp->write("read();"); GCNL; uvpass = UVPass::makePass(tmpVarNum2, rstor, nuti, nut->getPackable(), m_state, 0, cos ? cos->getId() : 0); } else //element and uvpass stays the same (a default immediate element). uvpass = UVPass::makePass(tmpVarNum, TMPBITVAL, nuti, nut->getPackable(), m_state, 0, cos ? cos->getId() : 0); //t3657 m_state.clearCurrentObjSymbolsForCodeGen(); //clear remnant of rhs ? } //genCode
void NodeCast::genCodeCastAtomAndQuark(File * fp, UlamValue & uvpass) { UTI nuti = getNodeType(); //quark tobe UlamType * nut = m_state.getUlamTypeByIndex(nuti); UTI vuti = uvpass.getUlamValueTypeIdx(); if(vuti == Ptr) vuti = uvpass.getPtrTargetType(); //replace m_node->genCodeToStoreInto(fp, uvpass); //No need to load lhs into tmp (T); symbol's in COS vector assert(!m_state.m_currentObjSymbolsForCodeGen.empty()); Symbol * stgcos = NULL; stgcos = m_state.m_currentObjSymbolsForCodeGen[0]; s32 tmpVarPos = m_state.getNextTmpVarNumber(); // "downcast" might not be true; compare to be sure the atom has a quark "Foo" // get signed pos if(vuti == UAtom) { m_state.indent(fp); fp->write("const s32 "); fp->write(m_state.getTmpVarAsString(Int, tmpVarPos).c_str());; fp->write(" = "); //internal method, takes uc, u32 and const char*, returns s32 position fp->write(m_state.getHasMangledFunctionName(vuti)); fp->write("("); fp->write("uc, "); Node::genLocalMemberNameOfMethod(fp); //assume atom is a local var (neither dm nor ep) if(stgcos->isSelf()) fp->write("GetType(), "); //no read for self else fp->write("read().GetType(), "); fp->write("\""); fp->write(nut->getUlamTypeMangledName().c_str()); fp->write("\");\n"); //keeping pos in tmp } else { UlamType* vut = m_state.getUlamTypeByIndex(vuti); if(vut->getUlamClass() == UC_ELEMENT) { m_state.indent(fp); fp->write("const s32 "); fp->write(m_state.getTmpVarAsString(Int, tmpVarPos).c_str());; fp->write(" = "); //internal method, takes uc, u32 and const char*, returns s32 position fp->write(vut->getUlamTypeMangledName().c_str()); fp->write("<EC>::"); fp->write(m_state.getHasMangledFunctionName(vuti)); fp->write("(\""); fp->write(nut->getUlamTypeMangledName().c_str()); fp->write("\");\n"); //keeping pos in tmp } else { //e.g. a quark here would be wrong std::ostringstream msg; msg << "Casting 'incomplete' types "; msg << m_state.getUlamTypeNameBriefByIndex(nuti).c_str(); msg << " to be "; msg << m_state.getUlamTypeNameBriefByIndex(vuti).c_str(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); assert(0);//return; } } m_state.indent(fp); fp->write("if("); fp->write(m_state.getTmpVarAsString(Int, tmpVarPos).c_str()); fp->write(" < 0)\n"); m_state.m_currentIndentLevel++; m_state.indent(fp); fp->write("FAIL(BAD_CAST);\n\n"); m_state.m_currentIndentLevel--; //informed by genCodedAutoLocal() in NodeVarDecl used for conditional-as // uses stgcos since there's no m_varSymbol in this situation. s32 tmpVarStg = m_state.getNextTmpVarNumber(); UTI stguti = stgcos->getUlamTypeIdx(); UlamType * stgut = m_state.getUlamTypeByIndex(stguti); assert(stguti == UAtom || stgut->getUlamClass() == UC_ELEMENT); // can't let Node::genCodeReadIntoTmpVar do this for us (we need a ref!): assert(m_state.m_currentObjSymbolsForCodeGen.size() == 1); m_state.indent(fp); // no const here fp->write(stgut->getTmpStorageTypeAsString().c_str()); fp->write("& "); fp->write(m_state.getTmpVarAsString(stguti, tmpVarStg, TMPBITVAL).c_str()); fp->write(" = "); fp->write(stgcos->getMangledName().c_str()); if(!stgcos->isSelf()) fp->write(".getRef()"); fp->write("; //ref needed\n"); // now we have our pos in tmpVarPos, and our T in tmpVarStg // time to (like a) "shadow 'self'" with auto local variable: m_state.indent(fp); fp->write(nut->getUlamTypeImmediateAutoMangledName().c_str()); //for C++ local vars, ie non-data members fp->write("<EC> "); s32 tmpIQ = m_state.getNextTmpVarNumber(); //tmp since no variable name fp->write(m_state.getTmpVarAsString(nuti, tmpIQ).c_str()); fp->write("("); fp->write(m_state.getTmpVarAsString(stguti, tmpVarStg, TMPBITVAL).c_str()); //for known quark: fp->write(", "); fp->write(m_state.getTmpVarAsString(Int, tmpVarPos).c_str()); fp->write(");\n"); //like, shadow lhs of as //update the uvpass to have the casted immediate quark uvpass = UlamValue::makePtr(tmpIQ, uvpass.getPtrStorage(), nuti, m_state.determinePackable(nuti), m_state, 0); //POS 0 rightjustified; m_state.m_currentObjSymbolsForCodeGen.clear(); //clear remnant of lhs } //genCodeCastAtomAndQuark
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 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