//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::doBinaryOperationImmediate(s32 lslot, s32 rslot, u32 slots) { assert(slots == 1); UTI luti = m_nodeLeft->getNodeType(); u32 len = m_state.getTotalBitSize(luti); UlamValue luv = m_state.m_nodeEvalStack.loadUlamValueFromSlot(lslot); //immediate value UlamValue ruv = m_state.m_nodeEvalStack.loadUlamValueFromSlot(rslot); //immediate value if((luv.getUlamValueTypeIdx() == Nav) || (ruv.getUlamValueTypeIdx() == Nav)) return false; UlamValue rtnUV; u32 wordsize = m_state.getTotalWordSize(luti); if(wordsize == MAXBITSPERINT) { u32 ldata = luv.getImmediateData(len); u32 rdata = ruv.getImmediateData(len); rtnUV = makeImmediateBinaryOp(luti, ldata, rdata, len); } else if(wordsize == MAXBITSPERLONG) { u64 ldata = luv.getImmediateDataLong(len); u64 rdata = ruv.getImmediateDataLong(len); rtnUV = makeImmediateLongBinaryOp(luti, ldata, rdata, len); } //else //assert(0); if(rtnUV.getUlamValueTypeIdx() == Nav) return false; m_state.m_nodeEvalStack.storeUlamValueInSlot(rtnUV, -1); return true; } //dobinaryopImmediate
//for eval, want the value of the rhs bool NodeMemberSelect::doBinaryOperation(s32 lslot, s32 rslot, u32 slots) { assert(slots); //the return value of a function call, or value of a data member UlamValue ruv = m_state.m_nodeEvalStack.loadUlamValueFromSlot(rslot); UlamValue rtnUV; UTI ruti = getNodeType(); PACKFIT packFit = m_state.determinePackable(ruti); if(m_state.isScalar(ruti) || WritePacked(packFit)) { rtnUV = ruv; } else { //make a ptr to an unpacked array, base[0] ? [pls test] rtnUV = UlamValue::makePtr(rslot, EVALRETURN, ruti, UNPACKED, m_state); } if((rtnUV.getUlamValueTypeIdx() == Nav) || (ruti == Nav)) return false; if((rtnUV.getUlamValueTypeIdx() == Hzy) || (ruti == Hzy)) return false; //copy result UV to stack, -1 relative to current frame pointer Node::assignReturnValueToStack(rtnUV); return true; } //doBinaryOperation
bool NodeUnaryOp::doUnaryOperationImmediate(s32 slot, u32 nslots) { assert(nslots == 1); UTI nuti = getNodeType(); u32 len = m_state.getTotalBitSize(nuti); UlamValue uv = m_state.m_nodeEvalStack.loadUlamValueFromSlot(slot); //immediate valueg if((uv.getUlamValueTypeIdx() == Nav) || (nuti == Nav)) return false; if((uv.getUlamValueTypeIdx() == Hzy) || (nuti == Hzy)) return false; UlamValue rtnUV; u32 wordsize = m_state.getUlamTypeByIndex(nuti)->getTotalWordSize(); if(wordsize <= MAXBITSPERINT) { u32 data = uv.getImmediateData(len, m_state); rtnUV = makeImmediateUnaryOp(nuti, data, len); } else if(wordsize <= MAXBITSPERLONG) { u64 data = uv.getImmediateDataLong(len, m_state); //t3849 rtnUV = makeImmediateLongUnaryOp(nuti, data, len); } else m_state.abortGreaterThanMaxBitsPerLong(); m_state.m_nodeEvalStack.storeUlamValueInSlot(rtnUV, -1); return true; } //dounaryopImmediate
void NodeBinaryOpArithDivide::appendBinaryOp(UlamValue& refUV, u32 ldata, u32 rdata, u32 pos, u32 len) { if(rdata == 0) { MSG(getNodeLocationAsString().c_str(), "Possible Divide By Zero Attempt", ERR); refUV.setUlamValueTypeIdx(Nav); setNodeType(Nav); //compiler counts return; } UTI type = refUV.getUlamValueTypeIdx(); ULAMTYPE typEnum = m_state.getUlamTypeByIndex(type)->getUlamTypeEnum(); switch(typEnum) { case Int: refUV.putData(pos, len, _BinOpDivideInt32(ldata, rdata, len)); break; case Unsigned: refUV.putData(pos, len, _BinOpDivideUnsigned32(ldata, rdata, len)); break; case Bool: refUV.putData(pos, len, _BinOpDivideBool32(ldata, rdata, len)); break; case Unary: refUV.putData(pos, len, _BinOpDivideUnary32(ldata, rdata, len)); break; case Bits: default: m_state.abortUndefinedUlamPrimitiveType(); break; }; return; } //appendBinaryOp
EvalStatus NodeVarRef::eval() { assert(m_varSymbol); assert(m_varSymbol->getAutoLocalType() != ALT_AS); //NodeVarRefAuto UTI nuti = getNodeType(); if(nuti == Nav) return evalErrorReturn(); assert(m_varSymbol->getUlamTypeIdx() == nuti); assert(m_nodeInitExpr); evalNodeProlog(0); //new current frame pointer makeRoomForSlots(1); //always 1 slot for ptr EvalStatus evs = m_nodeInitExpr->evalToStoreInto(); if(evs != NORMAL) return evalStatusReturn(evs); UlamValue pluv = m_state.m_nodeEvalStack.popArg(); assert(m_state.isPtr(pluv.getUlamValueTypeIdx())); ((SymbolVariableStack *) m_varSymbol)->setAutoPtrForEval(pluv); //for future ident eval uses ((SymbolVariableStack *) m_varSymbol)->setAutoStorageTypeForEval(m_nodeInitExpr->getNodeType()); //for future virtual function call eval uses m_state.m_funcCallStack.storeUlamValueInSlot(pluv, ((SymbolVariableStack *) m_varSymbol)->getStackFrameSlotIndex()); //doesn't seem to matter.. evalNodeEpilog(); return NORMAL; } //eval
void NodeBinaryOpEqualArithRemainder::appendBinaryOp(UlamValue& refUV, u32 ldata, u32 rdata, u32 pos, u32 len) { UTI type = refUV.getUlamValueTypeIdx(); ULAMTYPE typEnum = m_state.getUlamTypeByIndex(type)->getUlamTypeEnum(); switch(typEnum) { case Int: refUV.putData(pos, len, _BinOpModInt32(ldata, rdata, len)); break; case Unsigned: refUV.putData(pos, len, _BinOpModUnsigned32(ldata, rdata, len)); break; case Bool: refUV.putData(pos, len, _BinOpModBool32(ldata, rdata, len)); break; case Unary: refUV.putData(pos, len, _BinOpModUnary32(ldata, rdata, len)); break; case Bits: default: m_state.abortUndefinedUlamPrimitiveType(); break; }; return; } //appendBinaryOp
void NodeBinaryOpArithRemainder::appendBinaryOp(UlamValue& refUV, u32 ldata, u32 rdata, u32 pos, u32 len) { if(rdata == 0) { MSG(getNodeLocationAsString().c_str(), "Possible Remainder By Zero Attempt", ERR); return; } UTI type = refUV.getUlamValueTypeIdx(); ULAMTYPE typEnum = m_state.getUlamTypeByIndex(type)->getUlamTypeEnum(); switch(typEnum) { case Int: refUV.putData(pos, len, _BinOpModInt32(ldata, rdata, len)); break; case Unsigned: refUV.putData(pos, len, _BinOpModUnsigned32(ldata, rdata, len)); break; case Bool: refUV.putData(pos, len, _BinOpModBool32(ldata, rdata, len)); break; case Unary: refUV.putData(pos, len, _BinOpModUnary32(ldata, rdata, len)); break; case Bits: default: assert(0); break; }; return; } //appendBinaryOp
void NodeBinaryOpArithSubtract::appendBinaryOp(UlamValue& refUV, u32 ldata, u32 rdata, u32 pos, u32 len) { UTI type = refUV.getUlamValueTypeIdx(); ULAMTYPE typEnum = m_state.getUlamTypeByIndex(type)->getUlamTypeEnum(); switch(typEnum) { case Int: refUV.putData(pos, len, _BinOpSubtractInt32(ldata, rdata, len)); break; case Unsigned: refUV.putData(pos, len, _BinOpSubtractUnsigned32(ldata, rdata, len)); break; case Bool: refUV.putData(pos, len, _BinOpSubtractBool32(ldata, rdata, len)); break; case Unary: refUV.putData(pos, len, _BinOpSubtractUnary32(ldata, rdata, len)); break; case Bits: default: assert(0); break; }; return; } //appendBinaryOp
bool UlamTypePrimitiveUnary::cast(UlamValue & val, UTI typidx) { bool brtn = true; assert(m_state.getUlamTypeByIndex(typidx) == this); UTI valtypidx = val.getUlamValueTypeIdx(); if(UlamType::safeCast(valtypidx) != CAST_CLEAR) //bad|hazy return false; u32 wordsize = getTotalWordSize(); u32 valwordsize = m_state.getTotalWordSize(valtypidx); if(wordsize <= MAXBITSPERINT) { if(valwordsize <= MAXBITSPERINT) brtn = castTo32(val, typidx); else if(valwordsize <= MAXBITSPERLONG) brtn = castTo64(val, typidx); //downcast else m_state.abortGreaterThanMaxBitsPerLong(); } else if(wordsize <= MAXBITSPERLONG) brtn = castTo64(val, typidx); else { std::ostringstream msg; msg << "Casting to an unsupported word size: " << wordsize; msg << ", Value Type and bit size was: "; msg << valtypidx << "," << m_state.getBitSize(valtypidx); msg << " TO: "; msg << typidx << "," << getBitSize(); MSG(m_state.getFullLocationAsString(m_state.m_locOfNextLineText).c_str(), msg.str().c_str(), DEBUG); brtn = false; } return brtn; } //cast
void NodeBinaryOpShiftLeft::appendBinaryOp(UlamValue& refUV, u32 ldata, u32 rdata, u32 pos, u32 len) { assert(0); //not implemented yet! #if 0 UTI type = refUV.getUlamValueTypeIdx(); ULAMTYPE typEnum = m_state.getUlamTypeByIndex(type)->getUlamTypeEnum(); switch(typEnum) { case Int: refUV.putData(pos, len, _ShiftOpLeftInt32(ldata, rdata, len)); break; case Unsigned: refUV.putData(pos, len, _ShiftOpLeftUnsigned32(ldata, rdata, len)); break; case Bool: refUV.putData(pos, len, _ShiftOpLeftBool32(ldata, rdata, len)); break; case Unary: refUV.putData(pos, len, _ShiftOpLeftUnary32(ldata, rdata, len)); break; case Bits: case Unary: refUV.putData(pos, len, _ShiftOpLeftBits32(ldata, rdata, len)); break; default: assert(0); break; }; #endif return; } //appendBinaryOp
bool UlamTypeInt::castTo64(UlamValue & val, UTI typidx) { bool brtn = true; UTI valtypidx = val.getUlamValueTypeIdx(); u32 valwordsize = m_state.getTotalWordSize(valtypidx); u64 data; if(valwordsize == MAXBITSPERINT) data = (u64) val.getImmediateData(m_state); else if(valwordsize == MAXBITSPERLONG) data = val.getImmediateDataLong(m_state); else assert(0); u64 sdata = 0; s32 bitsize = getBitSize(); s32 valbitsize = m_state.getBitSize(valtypidx); ULAMTYPE valtypEnum = m_state.getUlamTypeByIndex(valtypidx)->getUlamTypeEnum(); switch(valtypEnum) { case Int: // casting Int to Int to change bits size sdata = _Int64ToInt64(data, valbitsize, bitsize); break; case Unsigned: // casting Unsigned to Int to change type sdata = _Unsigned64ToInt64(data, valbitsize, bitsize); break; case Bits: // casting Bits to Int to change type sdata = _Bits64ToInt64(data, valbitsize, bitsize); break; case Unary: sdata = _Unary64ToInt64(data, valbitsize, bitsize); break; case Bool: sdata = _Bool64ToInt64(data, valbitsize, bitsize); break; case Void: default: //std::cerr << "UlamTypeInt (cast) error! Value Type was: " << valtypidx << std::endl; brtn = false; }; if(brtn) { u32 wordsize = getTotalWordSize(); //tobe if(wordsize == MAXBITSPERINT) //downcast val = UlamValue::makeImmediate(typidx, (u32) sdata, m_state); //overwrite val else if(wordsize == MAXBITSPERLONG) val = UlamValue::makeImmediateLong(typidx, sdata, m_state); //overwrite val else assert(0); } return brtn; } //castTo64
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); } }
bool UlamTypePrimitiveUnary::castTo64(UlamValue & val, UTI typidx) { bool brtn = true; UTI valtypidx = val.getUlamValueTypeIdx(); u32 valwordsize = m_state.getTotalWordSize(valtypidx); u64 data; if(valwordsize <= MAXBITSPERINT) data = (u64) val.getImmediateData(m_state); else if(valwordsize <= MAXBITSPERLONG) data = val.getImmediateDataLong(m_state); else m_state.abortGreaterThanMaxBitsPerLong(); s32 bitsize = getBitSize(); s32 valbitsize = m_state.getBitSize(valtypidx); //base types e.g. Int, Bool, Unary, Foo, Bar.. ULAMTYPE valtypEnum = m_state.getUlamTypeByIndex(valtypidx)->getUlamTypeEnum(); switch(valtypEnum) { case Int: // cast from Int->Unary, OR Bool->Unary (same as Bool->Int) data = _Int64ToUnary64(data, valbitsize, bitsize); break; case Unsigned: data = _Unsigned64ToUnary64(data, valbitsize, bitsize); break; case Bool: // Bool -> Unary is the same as Bool -> Int data = _Bool64ToUnary64(data, valbitsize, bitsize); break; case Unary: data = _Unary64ToUnary64(data, valbitsize, bitsize); break; case Bits: break; case Void: default: //std::cerr << "UlamTypePrimitiveUnary (cast) error! Value Type was: " << valtypidx << std::endl; brtn = false; }; if(brtn) { u32 wordsize = getTotalWordSize(); //tobe if(wordsize <= MAXBITSPERINT) //downcast val = UlamValue::makeImmediate(typidx, data, m_state); //overwrite val else if(wordsize <= MAXBITSPERLONG) val = UlamValue::makeImmediateLong(typidx, data, m_state); //overwrite val else m_state.abortGreaterThanMaxBitsPerLong(); } return brtn; } //castTo64
bool UlamTypeInt::castTo32(UlamValue & val, UTI typidx) { bool brtn = true; UTI valtypidx = val.getUlamValueTypeIdx(); s32 bitsize = getBitSize(); s32 valbitsize = m_state.getBitSize(valtypidx); u32 data = val.getImmediateData(m_state); u32 sdata = 0; ULAMTYPE valtypEnum = m_state.getUlamTypeByIndex(valtypidx)->getUlamTypeEnum(); switch(valtypEnum) { case Int: // casting Int to Int to change bits size sdata = _Int32ToInt32(data, valbitsize, bitsize); break; case Unsigned: // casting Unsigned to Int to change type sdata = _Unsigned32ToInt32(data, valbitsize, bitsize); break; case Bits: // casting Bits to Int to change type sdata = _Bits32ToInt32(data, valbitsize, bitsize); break; case Unary: sdata = _Unary32ToInt32(data, valbitsize, bitsize); break; case Bool: sdata = _Bool32ToInt32(data, valbitsize, bitsize); break; case Void: default: //std::cerr << "UlamTypeInt (cast) error! Value Type was: " << valtypidx << std::endl; brtn = false; }; if(brtn) val = UlamValue::makeImmediate(typidx, sdata, m_state); //overwrite val return brtn; } //castTo32
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
bool UlamTypePrimitiveUnary::castTo32(UlamValue & val, UTI typidx) { bool brtn = true; UTI valtypidx = val.getUlamValueTypeIdx(); u32 data = val.getImmediateData(m_state); s32 bitsize = getBitSize(); s32 valbitsize = m_state.getBitSize(valtypidx); //base types e.g. Int, Bool, Unary, Foo, Bar.. ULAMTYPE valtypEnum = m_state.getUlamTypeByIndex(valtypidx)->getUlamTypeEnum(); switch(valtypEnum) { case Int: // cast from Int->Unary, OR Bool->Unary (same as Bool->Int) data = _Int32ToUnary32(data, valbitsize, bitsize); break; case Unsigned: data = _Unsigned32ToUnary32(data, valbitsize, bitsize); break; case Bool: // Bool -> Unary is the same as Bool -> Int data = _Bool32ToUnary32(data, valbitsize, bitsize); break; case Unary: data = _Unary32ToUnary32(data, valbitsize, bitsize); break; case Bits: break; case Void: default: //std::cerr << "UlamTypePrimitiveUnary (cast) error! Value Type was: " << valtypidx << std::endl; brtn = false; }; if(brtn) val = UlamValue::makeImmediate(typidx, data, m_state); //overwrite val, same data return brtn; } //castTo32
EvalStatus NodeMemberSelect::evalToStoreInto() { UTI nuti = getNodeType(); if(nuti == Nav) return ERROR; if(nuti == Hzy) return NOTREADY; evalNodeProlog(0); UlamValue saveCurrentObjectPtr = m_state.m_currentObjPtr; //************* makeRoomForSlots(1); //always 1 slot for ptr EvalStatus evs = m_nodeLeft->evalToStoreInto(); if(evs != NORMAL) { evalNodeEpilog(); return evs; } //UPDATE selected member (i.e. element or quark) before eval of rhs // (i.e. data member or func call) UlamValue newCurrentObjectPtr = m_state.m_nodeEvalStack.loadUlamValuePtrFromSlot(1); //e.g. Ptr to atom UTI newobjtype = newCurrentObjectPtr.getUlamValueTypeIdx(); if(!m_state.isPtr(newobjtype)) { assert(m_nodeLeft->isFunctionCall());// must be the result of a function call; // copy anonymous class to "uc" hidden slot in STACK, then replace with a pointer to it. assert(m_state.isAClass(newobjtype)); newCurrentObjectPtr = assignAnonymousClassReturnValueToStack(newCurrentObjectPtr); //t3913 } m_state.m_currentObjPtr = newCurrentObjectPtr; makeRoomForSlots(1); //always 1 slot for ptr evs = m_nodeRight->evalToStoreInto(); if(evs != NORMAL) { evalNodeEpilog(); return evs; } UlamValue ruvPtr = m_state.m_nodeEvalStack.loadUlamValuePtrFromSlot(2); UTI robjtype = ruvPtr.getUlamValueTypeIdx(); //t3913 if(!m_state.isPtr(robjtype)) { // must be the result of a function call; // copy anonymous class to "uc" hidden slot in STACK, then replace with a pointer to it. assert(m_state.isAClass(robjtype)); ruvPtr = assignAnonymousClassReturnValueToStack(ruvPtr); } Node::assignReturnValuePtrToStack(ruvPtr); m_state.m_currentObjPtr = saveCurrentObjectPtr; //restore current object ptr ********** evalNodeEpilog(); return NORMAL; } //evalToStoreInto
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
EvalStatus NodeSquareBracket::eval() { 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(); UTI ltype = pluv.getPtrTargetType(); //could be a custom array which is a scalar quark. already checked. UlamType * lut = m_state.getUlamTypeByIndex(ltype); bool isCustomArray = lut->isCustomArray(); assert(!m_state.isScalar(ltype) || isCustomArray); //already checked, must be array 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(); UlamType * offut = m_state.getUlamTypeByIndex(offset.getUlamValueTypeIdx()); s32 offsetInt = 0; if(offut->isNumericType()) { // constant expression only required for array declaration s32 arraysize = m_state.getArraySize(ltype); u32 offsetdata = offset.getImmediateData(m_state); offsetInt = offut->getDataAsCs32(offsetdata); if((offsetInt >= arraysize) && !isCustomArray) { 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); evalNodeEpilog(); return ERROR; } } else if(!isCustomArray) { Symbol * lsymptr; u32 lid = 0; if(getSymbolPtr(lsymptr)) lid = lsymptr->getId(); std::ostringstream msg; msg << "Array subscript of array '"; msg << m_state.m_pool.getDataAsString(lid).c_str(); msg << "' requires a numeric type"; MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); evalNodeEpilog(); return ERROR; } assignReturnValueToStack(pluv.getValAt(offsetInt, m_state)); evalNodeEpilog(); return NORMAL; } //eval
EvalStatus NodeCast::eval() { assert(m_node); //has to be UTI tobeType = getNodeType(); UTI nodeType = m_node->getNodeType(); //uv.getUlamValueType() if(tobeType == Nav) return ERROR; evalNodeProlog(0); //new current frame pointer makeRoomForNodeType(nodeType); EvalStatus evs = m_node->eval(); if(evs != NORMAL) { evalNodeEpilog(); return evs; } //do we believe these to be scalars, only? //possibly an array that needs to be casted, per elenemt if(m_state.isScalar(tobeType)) { if(!m_state.isScalar(nodeType)) { std::ostringstream msg; msg << "Cannot cast an array "; msg << m_state.getUlamTypeNameBriefByIndex(nodeType).c_str(); msg << " to a scalar type " ; msg << m_state.getUlamTypeNameBriefByIndex(tobeType).c_str(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); } } else { //both arrays the same dimensions if(m_state.getArraySize(tobeType) != m_state.getArraySize(nodeType)) { MSG(getNodeLocationAsString().c_str(), "Considering implementing array casts!!!", ERR); } } UlamValue uv = m_state.m_nodeEvalStack.loadUlamValueFromSlot(1); if(nodeType != tobeType) { if(!(m_state.getUlamTypeByIndex(tobeType)->cast(uv, tobeType))) { std::ostringstream msg; msg << "Cast problem during eval! Value type "; msg << m_state.getUlamTypeNameBriefByIndex(uv.getUlamValueTypeIdx()).c_str(); msg << " failed to be cast as "; msg << m_state.getUlamTypeNameBriefByIndex(tobeType).c_str(); MSG(getNodeLocationAsString().c_str(), msg.str().c_str(), ERR); evalNodeEpilog(); return ERROR; } } //also copy result UV to stack, -1 relative to current frame pointer assignReturnValueToStack(uv); evalNodeEpilog(); return NORMAL; } //eval
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
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 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
EvalStatus NodeMemberSelect::eval() { assert(m_nodeLeft && m_nodeRight); UTI nuti = getNodeType(); if(nuti == Nav) return ERROR; if(nuti == Hzy) return NOTREADY; evalNodeProlog(0); //new current frame pointer on node eval stack UlamValue saveCurrentObjectPtr = m_state.m_currentObjPtr; //************* UlamValue saveCurrentSelfPtr = m_state.m_currentSelfPtr; //************* makeRoomForSlots(1); //always 1 slot for ptr EvalStatus evs = m_nodeLeft->evalToStoreInto(); if(evs != NORMAL) { evalNodeEpilog(); return evs; } //UPDATE selected member (i.e. element or quark) before eval of rhs //(i.e. data member or func call); e.g. Ptr to atom UlamValue newCurrentObjectPtr = m_state.m_nodeEvalStack.loadUlamValuePtrFromSlot(1); UTI newobjtype = newCurrentObjectPtr.getUlamValueTypeIdx(); if(!m_state.isPtr(newobjtype)) { assert(m_nodeLeft->isFunctionCall()); //must be the result of a function call // copy anonymous class to "uc" hidden slot in STACK, then replace with a pointer to it. assert(m_state.isAClass(newobjtype)); newCurrentObjectPtr = assignAnonymousClassReturnValueToStack(newCurrentObjectPtr); //t3912 } u32 superid = m_state.m_pool.getIndexForDataString("super"); if(newCurrentObjectPtr.getPtrNameId() == superid) { if(!m_nodeRight->isFunctionCall()) newCurrentObjectPtr = m_state.m_currentSelfPtr; //(t3749) else m_state.m_currentSelfPtr = newCurrentObjectPtr; //changes self ********* (t3743, t3745) } m_state.m_currentObjPtr = newCurrentObjectPtr; //UTI ruti = m_nodeRight->getNodeType(); //u32 slot = makeRoomForNodeType(ruti); u32 slot = makeRoomForNodeType(nuti); evs = m_nodeRight->eval(); //a Node Function Call here, or data member eval if(evs != NORMAL) { evalNodeEpilog(); return evs; } //assigns rhs to lhs UV pointer (handles arrays); //also copy result UV to stack, -1 relative to current frame pointer if(slot) //avoid Void's if(!doBinaryOperation(1, 1+slot, slot)) evs = ERROR; m_state.m_currentObjPtr = saveCurrentObjectPtr; //restore current object ptr m_state.m_currentSelfPtr = saveCurrentSelfPtr; //restore current self ptr evalNodeEpilog(); return evs; } //eval
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
//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) { m_state.abortNotImplementedYet(); //not implemented yet..TODO return bool. #if 0 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); u32 navCount = 0; u32 hzyCount = 0; //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); if(rtnUV.getUlamValueTypeIdx() == Nav) navCount++; else if(rtnUV.getUlamValueTypeIdx() == Hzy) hzyCount++; //cp result UV to stack, -1 (first array element deepest) relative to current frame pointer m_state.m_nodeEvalStack.storeUlamValueInSlot(rtnUV, -slots + i); } AssertBool isNextLeft = lp.incrementPtr(m_state); assert(isNextLeft); AssertBool isNextRight = rp.incrementPtr(m_state); assert(isNextRight); } //forloop if(navCount > 0) return false; if(hzyCount > 0) return false; if(WritePacked(packRtn)) m_state.m_nodeEvalStack.storeUlamValueInSlot(rtnUV, -1); //store accumulated packed result #endif return false; //NOT IMPLEMENTED YET! } //end dobinaryOperaationarray