/** * Q: how can this be optimized? * @brief test if there exists a return transition with the given from state, * predecessor state, and symbol in this collection of transitions * * @param - from: the desired from state for the return transition * @param - pred: the desired predecessor state for the return transition * @param - sym: the desired symbol for the return transition * @return true if there exists a return transition with the given from state and * symbol in this collection of transitions * */ bool TransitionStorage::returnExists( State from, State pred, Symbol sym ) const { Returns const & outgoing = T_info.exitTrans(from); for( ReturnIterator rit = outgoing.begin(); rit != outgoing.end(); rit++ ) { if( (getCallSite(*rit) == pred) && (getReturnSym(*rit) == sym) ) return true; } return false; }
/** * Q: how can this be optimized? * @brief provides access to all return transitions with the given from * state and symbol in this collection of transitions * * @param - from: the desired from state for the return transitions * @param - sym: the desired symbol for the return transitions * @return the set of return transitions with the given from state and symbol * */ const TransitionStorage::Returns TransitionStorage::getReturns( State from, Symbol sym ) const { Returns result; Returns const & outgoing = T_info.exitTrans(from); for( ReturnIterator rit = outgoing.begin(); rit != outgoing.end(); rit++ ) { if( (getExit(*rit) == from) && (getReturnSym(*rit) == sym) ) result.insert(*rit); } return result; }
/** * * @brief creates transitions for 'dup' mirroring 'orig' outgoing transitions * * @param - orig: the state that is being duplicated * @param - dup: the state that is duplicating 'orig' * */ void TransitionStorage::dupTransOutgoing( State orig, State dup ) { // Duplicate outgoing internal transitions. const Info::Internals & from = T_info.fromTrans(orig); for( Info::InternalIterator it = from.begin(); it != from.end(); it++ ) { Internal iTrans(dup,getInternalSym(*it),getTarget(*it)); addInternal(iTrans); } // Duplicate call site call transitions. const Info::Calls & call = T_info.callTrans(orig); for( Info::CallIterator it = call.begin(); it != call.end(); it++ ) { Call cTrans(dup,getCallSym(*it),getEntry(*it)); addCall(cTrans); } // Duplicate exit point return transitions. const Info::Returns & exit = T_info.exitTrans(orig); for( Info::ReturnIterator it = exit.begin(); it != exit.end(); it++ ) { Return rTrans(dup,getCallSite(*it),getReturnSym(*it),getReturnSite(*it)); addReturn(rTrans); } // Q: Do we want to do these? Seems inconsistent. -Evan // A: Aditya says 'yes', and thinks we need it. So we definitely don't // want to change it without looking at uses and compensating. // Duplicate call predecessor return transitions. const Info::Returns & pred = T_info.predTrans(orig); for( Info::ReturnIterator it = pred.begin(); it != pred.end(); it++ ) { Return rTrans(getExit(*it),dup,getReturnSym(*it),getReturnSite(*it)); addReturn(rTrans); } }
/** * * @brief finds the symbol on any transition whose source is 'from' and * whose target is 'to' * * @param - from: the source of the transition * @param - to: the target of the transition * @return true if there exists some transition with the given source and * target, false otherwise * */ bool TransitionStorage::getSymbol( State fromSt, State toSt, Symbol & sym ) const { //Check internal transitions. const Info::Internals & from = T_info.fromTrans(fromSt); for(Info::InternalIterator it = from.begin(); it != from.end(); it++ ) { if( toSt == getTarget(*it) ) { sym = getInternalSym(*it); return true; } } //Check call transitions. const Info::Calls & call = T_info.callTrans(fromSt); for(Info::CallIterator it = call.begin(); it != call.end(); it++ ) { if( toSt == getEntry(*it) ) { sym = getCallSym(*it); return true; } } //Check return transitions. const Info::Returns & exit = T_info.exitTrans(fromSt); for(Info::ReturnIterator it = exit.begin(); it != exit.end(); it++ ) { if( toSt == getReturnSite(*it) ) { sym = getReturnSym(*it); return true; } } //Q: does this count as a symbol we would like to have? /*const Info::Returns pred = T_info.predTrans(fromSt); for( Info::ReturnIterator it = pred.begin(); it != pred.end(); it++ ) { if( toSt == getReturnSite(*it) ) { sym = getReturnSym(*it); return true; } }*/ return false; }
/** * * @brief removes all return transitions with the given symbol * * @param - sym: the symbol whose transitions to remove * @return false if no transitions were removed, true otherwise * */ bool TransitionStorage::removeReturnTransSym( Symbol sym ) { Returns removeTrans; //Find transitions to remove. for( ReturnIterator rit = returnTrans.begin(); rit != returnTrans.end(); rit++ ) { if( getReturnSym(*rit) == sym ) removeTrans.insert(*rit); } //Remove transitions. for( ReturnIterator rit = removeTrans.begin(); rit != removeTrans.end(); rit++ ) { removeReturn(*rit); } return removeTrans.size() > 0; }
PTREE AnalyseReturnClassVal // RETURN CLASS VALUE ( PTREE expr ) // - expression for return { TYPE retn_type; // - return type TYPE retn_class; // - class for return PTREE tgt; // - target expression CNV_DIAG* diag; // - diagnosis retn_type = expr->u.subtree[0]->type; retn_class = StructType( retn_type ); DbgVerify( retn_class != NULL, "AnalyseReturnClassVal -- not class" ); if( ClassCorrupted( retn_class ) ) { PTreeErrorNode( expr ); } else if( TypeAbstract( retn_class ) ) { PTreeErrorExprType( expr, ERR_CONVERT_TO_ABSTRACT_TYPE, retn_class ); ScopeNotePureFunctions( retn_class ); } else { diag = DefargBeingCompiled() ? &diagDefarg : &diagReturn; tgt = NodeFetchReference( getReturnSym() ); expr = removeReturnNode( expr ); expr = CopyClassRetnVal( expr, tgt, retn_type, diag ); if( expr->op != PT_ERROR ) { if( NodeIsBinaryOp( expr, CO_DTOR ) ) { PTREE node = expr->u.subtree[0]; if( SymFunctionReturn() == node->u.symcg.symbol ) { PTreeFree( node ); node = expr; expr = expr->u.subtree[1]; PTreeFree( node ); } } } #if 0 // this is just so we can do some checking expr = CastImplicit( expr , retn_type , CNV_EXPR , DefargBeingCompiled() ? &diagDefarg : &diagReturn ); } #endif }
/** * * @brief print the collection of transitions * * @param - o: the output stream to print to * @return the output stream that was printed to * */ std::ostream & TransitionStorage::print( std::ostream & o ) const { //Print call transitions. o << "Delta_c: {\n "; bool first = true; for( CallIterator cit = callTrans.begin(); cit != callTrans.end(); cit++, first=false ) { if( !first ) o << ", \n "; o << "("; printKey(o,getCallSite(*cit)); o << " (=" << getCallSite(*cit) << ") "; o << ", "; printKey(o,getCallSym(*cit)); o << ", "; printKey(o,getEntry(*cit)); o << " (=" << getEntry(*cit) << ") "; o << ")"; } o << "\n}\n"; //Print internal transitions. o << "Delta_i: {\n "; first = true; for(InternalIterator iit = internalTrans.begin(); iit != internalTrans.end(); iit++, first=false ) { if( !first ) o << ",\n "; o << "("; printKey(o,getSource(*iit)); o << " (=" << getSource(*iit) << ") "; o << ", "; printKey(o,getInternalSym(*iit)); o << ", "; printKey(o,getTarget(*iit)); o << " (=" << getTarget(*iit) << ") "; o << ")"; } o << "\n}\n"; //Print return transitions. o << "Delta_r: {\n "; first = true; for(ReturnIterator rit = returnTrans.begin(); rit != returnTrans.end(); rit++, first = false ) { if( !first ) o << ",\n "; o << "("; printKey(o,getExit(*rit)); o << " (=" << getExit(*rit) << ") "; o << ", "; printKey(o,getCallSite(*rit)); o << " (=" << getCallSite(*rit) << ") "; o << ", "; printKey(o,getReturnSym(*rit)); o << ", "; printKey(o,getReturnSite(*rit)); o << " (=" << getReturnSite(*rit) << ") "; o << ")"; } o << "\n}\n"; return o; }
/** * * @brief creates transitions for 'dup' mirroring 'orig' transitions * * @param - orig: the state that is being duplicated * @param - dup: the state that is duplicating 'orig' * */ void TransitionStorage::dupTrans( State orig, State dup ) { //Duplicate outgoing internal transitions. const Info::Internals & from = T_info.fromTrans(orig); for( Info::InternalIterator it = from.begin(); it != from.end(); it++ ) { Internal iTrans(dup,getInternalSym(*it),getTarget(*it)); addInternal(iTrans); // Q: This is also inconsistent with dupTransOutgoing, which didn't do // anything special with self loops. -Evan // A: Aditya says yes, but this is again what McVeto(?) needs. // dupTrans is used in 'duplicateState', but dupTransOutgoing is // different. if( orig == getTarget(*it) ) //Handle self-loops. { Internal loop(dup,getInternalSym(*it),dup); addInternal(loop); } } //Duplicate incoming internal transitions. const Info::Internals & to = T_info.toTrans(orig); for( Info::InternalIterator it = to.begin(); it != to.end(); it++ ) { Internal iTrans(getSource(*it),getInternalSym(*it),dup); addInternal(iTrans); } //Duplicate call site call transitions. const Info::Calls & call = T_info.callTrans(orig); for( Info::CallIterator it = call.begin(); it != call.end(); it++ ) { Call cTrans(dup,getCallSym(*it),getEntry(*it)); addCall(cTrans); if( orig == getEntry(*it) ) //Handle self-loops. { Call loop(dup,getCallSym(*it),dup); addCall(loop); } } //Duplicate entry point call transitions. const Info::Calls & entry = T_info.entryTrans(orig); for( Info::CallIterator it = entry.begin(); it != entry.end(); it++ ) { Call cTrans(getCallSite(*it),getCallSym(*it),dup); addCall(cTrans); } //Duplicate exit point return transitions. const Info::Returns & exit = T_info.exitTrans(orig); for( Info::ReturnIterator it = exit.begin(); it != exit.end(); it++ ) { Return rTrans(dup,getCallSite(*it),getReturnSym(*it),getReturnSite(*it)); addReturn(rTrans); if( orig == getCallSite(*it) ) //Handle self-loops. { Return loop(dup,dup,getReturnSym(*it),getReturnSite(*it)); addReturn(loop); } if( orig == getReturnSite(*it) ) //Handle self-loops. { Return loop(dup,getCallSite(*it),getReturnSym(*it),dup); addReturn(loop); } if( orig == getCallSite(*it) && orig == getReturnSite(*it) ) //Handle self-loops. { Return loop(dup,dup,getReturnSym(*it),dup); addReturn(loop); } } //Duplicate call predecessor return transitions. const Info::Returns & pred = T_info.predTrans(orig); for( Info::ReturnIterator it = pred.begin(); it != pred.end(); it++ ) { Return rTrans(getExit(*it),dup,getReturnSym(*it),getReturnSite(*it)); addReturn(rTrans); if( orig == getReturnSite(*it) ) //Handle self-loops. { Return loop(getExit(*it),dup,getReturnSym(*it),dup); addReturn(loop); } } //Duplicate return site return transitions. const Info::Returns & ret = T_info.retTrans(orig); for( Info::ReturnIterator it = ret.begin(); it != ret.end(); it++ ) { Return rTrans(getExit(*it),getCallSite(*it),getReturnSym(*it),dup); addReturn(rTrans); } }