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 NodeAtomof::genCodeToStoreInto(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; uvpass = UVPass::makePass(tmpVarNum, TMPBITVAL, nuti, UNPACKED, m_state, uvpass.getPassPos(), uvpass.getPassNameId()); } else { //lhs assert(getStoreIntoAble() == TBOOL_TRUE); assert(m_nodeOf); m_nodeOf->genCodeToStoreInto(fp, uvpass); //does it handle array item members selected? assert(!m_state.m_currentObjSymbolsForCodeGen.empty()); uvpass = UVPass::makePass(uvpass.getPassVarNum(), TMPTATOM, getNodeType(), UNPACKED, m_state, uvpass.getPassPos(), uvpass.getPassNameId()); } } //genCodeToStoreInto
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 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
// presumably called by e.g. a binary op equal (lhs); caller saves // currentObjPass/Symbol, unlike genCode (rhs) void NodeMemberSelect::genCodeToStoreInto(File * fp, UVPass& uvpass) { assert(m_nodeLeft && m_nodeRight); UVPass luvpass; if(passalongUVPass()) { luvpass = uvpass; //t3584 Node::adjustUVPassForElements(luvpass); //t3803 ? } // if parent is another MS, we might need to adjust pos first // elements can be data members of transients, etc. m_nodeLeft->genCodeToStoreInto(fp, luvpass); //NodeIdent can't do it, because it doesn't know it's not a stand-alone element. // here, we know there's rhs of member select, which needs to adjust to state bits. //process multiple member selections (e.g. t3817) UVPass ruvpass; if(passalongUVPass()) { ruvpass = luvpass; //t3615 ? Node::adjustUVPassForElements(ruvpass); //t3803 } m_nodeRight->genCodeToStoreInto(fp, ruvpass); //uvpass contains the member selected, or cos obj symbol? uvpass = ruvpass; //tmp variable needed for any function call not returning a ref (t41006), including 'aref'(t41005); func calls returning a ref already made tmpvar. // uvpass not necessarily returning a reference type (t3913,4,5,7); // t41035 returns a primitive ref; t3946, t3948 if(m_nodeRight->isFunctionCall() && !m_state.isReference(uvpass.getPassTargetType())) { m_tmpvarSymbol = Node::makeTmpVarSymbolForCodeGen(uvpass, NULL); //dm to avoid leaks m_state.m_currentObjSymbolsForCodeGen.push_back(m_tmpvarSymbol); } } //genCodeToStoreInto
//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 NodeControl::genCode(File * fp, UVPass& uvpass) { assert(m_nodeCondition && m_nodeBody); //bracket for overall tmpvars (e.g. condition and body) is // generated by the specific control; e.g. final bracket depends // on presence of 'else'. m_nodeCondition->genCode(fp, uvpass); bool isTerminal = (uvpass.getPassStorage() == TERMINAL); UTI cuti = uvpass.getPassTargetType(); UlamType * cut = m_state.getUlamTypeByIndex(cuti); m_state.indentUlamCode(fp); fp->write(getName()); //if, while fp->write("("); if(isTerminal) { fp->write(m_state.m_pool.getDataAsString(uvpass.getPassNameId()).c_str()); } else { if(m_state.m_genCodingConditionalHas) { assert(cut->getUlamTypeEnum() == Bool); fp->write(((UlamTypePrimitiveBool *) cut)->getConvertToCboolMethod().c_str()); fp->write("(("); fp->write(uvpass.getTmpVarAsString(m_state).c_str()); fp->write(" >= 0 ? 1 : 0), "); //test for 'has' pos fp->write_decimal(cut->getBitSize()); fp->write(")"); } else { //regular condition assert(cut->getUlamTypeEnum() == Bool); fp->write(((UlamTypePrimitiveBool *) cut)->getConvertToCboolMethod().c_str()); fp->write("("); fp->write(uvpass.getTmpVarAsString(m_state).c_str()); fp->write(", "); fp->write_decimal(cut->getBitSize()); fp->write(")"); } } fp->write(")"); GCNL; m_state.indentUlamCode(fp); fp->write("{\n"); m_state.m_currentIndentLevel++; //note: in case of has-conditional, uvpass still has the tmpvariable containing the pos! m_nodeBody->genCode(fp, uvpass); //probably should have been done within the body, to avoid any //subsequent if/whiles from misinterpretting it as theirs; if so, again, moot. assert(!m_state.m_genCodingConditionalHas); m_state.m_currentIndentLevel--; m_state.indentUlamCode(fp); fp->write("} // end "); fp->write(getName()); //end fp->write("\n"); } //genCode