void readVarInfo(const AstVar* var, uint16_t& localId, uint16_t& localContext, Context* ctx) { VarInfo* info = getInfo<VarInfo>(var); uint16_t varFunctionId = info->functionId(); uint16_t curFunctionId = ctx->currentFunctionId(); localId = info->localId(); localContext = 0; if (varFunctionId != curFunctionId) { InterpreterFunction* varFunction = ctx->functionById(varFunctionId); InterpreterFunction* curFunction = ctx->functionById(curFunctionId); int32_t varFunctionDeep = varFunction->deepness(); int32_t curFunctionDeep = curFunction->deepness(); // var function deepness always >= current function deepness localContext = static_cast<uint16_t>(curFunctionDeep - varFunctionDeep); } }
void MMO_ToMicroModelica_::transform() { /* Aca comienza todo el ciclo */ checkStatement(_c->getStatements()); checkStatement(_c->getIniStatements()); initialFrame.push(_c->getIniStatements()); transformEqList(_c->getIniEquations() , _c->getIniStatements(), NULL ); transformEqList(_c->getEquations() , _c->getStatements() , NULL ); /* Cambiamos los tipos y constantes Booleanas */ for(int i = 0; i < _c->getVarSymbolTable()->count();i++) { VarInfo v = _c->getVarSymbolTable()->varInfo(i); string n = _c->getVarSymbolTable()->varName(i); //v->setComment(NULL); v->setModification( ChangeModifications(v->modification())); if (_pre->find(n) != _pre->end()) v->setDiscrete(); if ( ( !v->isConstant() ) || v->type()->getType() == TYBOOLEAN) v->setType(ChangeToReal(v->type())); } ChangePre(_c->getIniEquations()); ChangePre(_c->getEquations()); }
MMO_Expression_::MMO_Expression_ (AST_Expression exp, MMO_ModelData data) : _exp (NULL), _data (data), _str (), _equationIndex (0), _expressionOrder (2) { _ri = newMMO_ReplaceInterval (_data->symbols ()); if (_data->hasAnnotation ()) { _expressionOrder = _data->annotation ()->polyCoeffs (); } AST_Expression e = _ri->foldTraverse (exp); _exp = e; _gen = newGenerateDeps (_data); _deps = _gen->foldTraverse (exp); for (VariableInterval vi = _ri->first (); !_ri->end (); vi = _ri->next ()) { VarInfo v = _data->symbols ()->lookup (vi.name ()); if (v->isState ()) { _deps->insert (vi.index (), DEP_STATE_VECTOR); } else if (v->isAlgebraic ()) { _deps->insert (vi.index (), DEP_ALGEBRAIC_VECTOR_DEF); } else if (v->isDiscrete ()) { _deps->insert (vi.index (), DEP_DISCRETE_VECTOR); } } if (_data->calculateAlgebraics ()) { map<Index, Index> states, discretes; _traverseAlgebraics (_deps, _data->lhs (), _deps, &states, &discretes, Index (), DEP_ALGEBRAIC_DEF, -1); _traverseAlgebraics (_deps, _data->lhs (), _deps, &states, &discretes, Index (), DEP_ALGEBRAIC_VECTOR_DEF, -1); } _printer = newMMO_PrintExp (_data->symbols (), _ri, data->packages ()); }
void MMO_Generator_::_variablesInitCode () { stringstream buffer; VarSymbolTable vt = _model->varTable (); vt->setPrintEnvironment (VST_INIT); if (_model->annotation ()->solver () == ANT_DASSL || _model->annotation ()->solver () == ANT_DOPRI) { vt->setPrintEnvironment (VST_CLASSIC_INIT); } string indent = _writer->indent (1); for (VarInfo vi = vt->begin (); !vt->end (); vi = vt->next ()) { Index idx = vi->index (); if (!vi->isConstant () && !vi->isParameter () && (vi->hasAssignment () || vi->hasStartModifier () || vi->hasEachModifier ())) { buffer << _model->printInitialAssignment (vi, indent); _writer->write (&buffer, WR_START_CODE); } } }
bool FastQuery::getData(const std::string &varNameStr, void *data, const std::string &varPathStr, const bool collective, const bool bcast) { if (! isValid("FastQuery::getData")) return false; std::vector<VarInfo> varInfoList; std::vector<VarSpace> varSpaceList; unsigned int numVar = metadataMgr->getAllVariables (varInfoList, varSpaceList, varPathStr, varNameStr); if (numVar == 0) { LOGGER(ibis::gVerbose > 0) << "Warning -- FastQuery::getData(" << varPathStr.c_str() << ", " << varNameStr.c_str() << ") failed to find the named variable"; return false; } int idx=0; if (numVar > 1) { // pick the best fit variable with the shortest length std::string varName = varInfoList[0].getPath(); int len = varName.size(); for (unsigned int i=1; i<numVar; i++) { if (len > varInfoList[i].getPath().size()) { idx = i; len = varInfoList[i].getPath().size(); } } LOGGER(ibis::gVerbose > 2) << "Warning -- FastQuery::getData(" << varPathStr.c_str() << ", " << varNameStr.c_str() << ") found multiple variables with the name, use \"" << varInfoList[idx].getPath() << "\""; } VarInfo varInfo = varInfoList[idx]; VarSpace varSpace = varSpaceList[idx]; bool berr; #ifndef FQ_NOMPI if (collective == false) { #endif if (varInfo.getSize() == varSpace.getSize()) { berr = dataFile->getData(varInfo.getPath(), data); } else { berr = dataFile->getArrayData(varInfo.getPath(), varSpace.getOffsets(), varSpace.getCounts(), varSpace.getStrides(), data); } #ifndef FQ_NOMPI } else { int mpi_dim = 0; // split data by the first dimension std::vector<uint64_t> offsets = varSpace.getOffsets(); std::vector<uint64_t> counts = varSpace.getCounts(); std::vector<uint64_t> strides = varSpace.getStrides(); int nElements = varSpace.getSize(); unsigned int totalCount = counts[mpi_dim]; if (totalCount < mpi_size) { LOGGER(ibis::gVerbose > 0) << "Warning -- IndexBuilder::setData(" << varPathStr.c_str() << ", " << varNameStr.c_str() << "): number of MPI tasks cannot be less than" << " the dimension length " << totalCount; return false; } int mpi_len = std::ceil((double)totalCount/(double)mpi_size); if (mpi_rank >= totalCount%mpi_len && totalCount%mpi_len != 0) { counts[mpi_dim] = mpi_len - 1; offsets[mpi_dim] += (mpi_len*mpi_rank - (mpi_rank-totalCount%mpi_len)) * strides[mpi_dim]; } else { counts[mpi_dim] = mpi_len; offsets[mpi_dim] += (mpi_len*mpi_rank)*strides[mpi_dim]; } bool mpi_berr = false; FQ::DataType fqType = varInfo.getType(); void* mpi_data; int data_len = counts[mpi_dim]*(nElements/totalCount); switch(fqType){ case FQ::FQT_FLOAT: { mpi_data = new float[data_len]; mpi_berr = dataFile->getArrayData(varInfo.getPath(), offsets, counts, strides, mpi_data); break;} case FQ::FQT_DOUBLE: { mpi_data = new double[data_len]; mpi_berr = dataFile->getArrayData(varInfo.getPath(), offsets, counts, strides, mpi_data); break;} case FQ::FQT_BYTE: { mpi_data = new signed char[data_len]; mpi_berr = dataFile->getArrayData(varInfo.getPath(), offsets, counts, strides, mpi_data); break;} case FQ::FQT_UBYTE: { mpi_data = new unsigned char[data_len]; mpi_berr = dataFile->getArrayData(varInfo.getPath(), offsets, counts, strides, mpi_data); break;} case FQ::FQT_SHORT: { mpi_data = new int16_t[data_len]; mpi_berr = dataFile->getArrayData(varInfo.getPath(), offsets, counts, strides, mpi_data); break;} case FQ::FQT_USHORT: { mpi_data = new uint16_t[data_len]; mpi_berr = dataFile->getArrayData(varInfo.getPath(), offsets, counts, strides, mpi_data); break;} case FQ::FQT_INT: { mpi_data = new int32_t[data_len]; mpi_berr = dataFile->getArrayData(varInfo.getPath(), offsets, counts, strides, mpi_data); break;} case FQ::FQT_UINT: { mpi_data = new uint32_t[data_len]; mpi_berr = dataFile->getArrayData(varInfo.getPath(), offsets, counts, strides, mpi_data); break;} case FQ::FQT_LONG: { mpi_data = new int64_t[data_len]; mpi_berr = dataFile->getArrayData(varInfo.getPath(), offsets, counts, strides, mpi_data); break;} case FQ::FQT_ULONG: { mpi_data = new uint64_t[data_len]; mpi_berr = dataFile->getArrayData(varInfo.getPath(), offsets, counts, strides, mpi_data); break;} default: LOGGER(ibis::gVerbose > 0) << "Warning -- FastQuery::setData(" << varPathStr.c_str() << ", " << varNameStr.c_str() << ") can not handle FQ data type " << fqType; mpi_berr = false; } MPI_Allreduce(&mpi_berr, &berr, 1, MPI_BYTE, MPI_BAND, mpi_comm); if (berr) { int recvcounts[mpi_size]; int displs[mpi_size]; recvcounts[0] = mpi_len*(nElements/totalCount); displs[0] = 0; for(int i=1; i<mpi_size; i++) { if (i >= totalCount%mpi_len && totalCount%mpi_len != 0) recvcounts[i] = (mpi_len - 1)*(nElements/totalCount); else recvcounts[i] = mpi_len*(nElements/totalCount); displs[i] = displs[i-1] + recvcounts[i-1]; } switch(fqType){ case FQ::FQT_FLOAT: { MPI_Allgatherv(mpi_data, data_len, MPI_FLOAT, data, recvcounts, displs, MPI_FLOAT, mpi_comm); break;} case FQ::FQT_DOUBLE: { MPI_Allgatherv(mpi_data, data_len, MPI_DOUBLE, data, recvcounts, displs, MPI_DOUBLE, mpi_comm); break;} case FQ::FQT_BYTE: { MPI_Allgatherv(mpi_data, data_len, MPI_CHAR, data, recvcounts, displs, MPI_CHAR, mpi_comm); break;} case FQ::FQT_UBYTE: { MPI_Allgatherv(mpi_data, data_len, MPI_UNSIGNED_CHAR, data, recvcounts, displs, MPI_UNSIGNED_CHAR, mpi_comm); break;} case FQ::FQT_SHORT: { MPI_Allgatherv(mpi_data, data_len, MPI_SHORT, data, recvcounts, displs, MPI_SHORT, mpi_comm); break;} case FQ::FQT_USHORT: { MPI_Allgatherv(mpi_data, data_len, MPI_UNSIGNED_SHORT, data, recvcounts, displs, MPI_UNSIGNED_SHORT, mpi_comm); break;} case FQ::FQT_INT: { MPI_Allgatherv(mpi_data, data_len, MPI_INT, data, recvcounts, displs, MPI_INT, mpi_comm); break;} case FQ::FQT_UINT: { MPI_Allgatherv(mpi_data, data_len, MPI_UNSIGNED, data, recvcounts, displs, MPI_UNSIGNED, mpi_comm); break;} case FQ::FQT_LONG: { MPI_Allgatherv(mpi_data, data_len, MPI_LONG_LONG, data, recvcounts, displs, MPI_LONG_LONG, mpi_comm); break;} case FQ::FQT_ULONG: { MPI_Allgatherv(mpi_data, data_len, MPI_UNSIGNED_LONG_LONG, data, recvcounts, displs, MPI_UNSIGNED_LONG_LONG, mpi_comm); break;} default: berr = false; break; } } } #endif if (! berr) { LOGGER(ibis::gVerbose > 0) << "Warning -- FastQuery::getData(" << varPathStr.c_str() << ", " << varNameStr.c_str() << ") failed to get data from dataset \"" << varInfo.getPath().c_str() << "\""; return false; } else { LOGGER(ibis::gVerbose > 6) << "FastQuery::getData(" << varPathStr.c_str() << ", " << varNameStr.c_str() << ") successfully retrieved data from dataset \"" << varInfo.getPath().c_str() << "\""; return true; } } // FastQuery::getData
void CheckLeakAutoVar::checkScope(const Token * const startToken, VarInfo *varInfo, std::set<unsigned int> notzero) { std::map<unsigned int, std::string> &alloctype = varInfo->alloctype; std::map<unsigned int, std::string> &possibleUsage = varInfo->possibleUsage; const std::set<unsigned int> conditionalAlloc(varInfo->conditionalAlloc); // Allocation functions. key = function name, value = allocation type std::map<std::string, std::string> allocFunctions(cfgalloc); allocFunctions["malloc"] = "malloc"; allocFunctions["strdup"] = "malloc"; allocFunctions["fopen"] = "fopen"; // Deallocation functions. key = function name, value = allocation type std::map<std::string, std::string> deallocFunctions(cfgdealloc); deallocFunctions["free"] = "malloc"; deallocFunctions["fclose"] = "fopen"; // Parse all tokens const Token * const endToken = startToken->link(); for (const Token *tok = startToken; tok && tok != endToken; tok = tok->next()) { // Deallocation and then dereferencing pointer.. if (tok->varId() > 0) { const std::map<unsigned int, std::string>::iterator var = alloctype.find(tok->varId()); if (var != alloctype.end()) { if (var->second == "dealloc" && !Token::Match(tok->previous(), "[;{},=] %var% =")) { deallocUseError(tok, tok->str()); } else if (Token::simpleMatch(tok->tokAt(-2), "= &")) { varInfo->erase(tok->varId()); } else if (Token::simpleMatch(tok->previous(), "=")) { varInfo->erase(tok->varId()); } } } if (tok->str() == "(" && tok->previous()->isName()) { functionCall(tok->previous(), varInfo, ""); tok = tok->link(); continue; } // look for end of statement if (!Token::Match(tok, "[;{}]") || Token::Match(tok->next(), "[;{}]")) continue; tok = tok->next(); if (tok == endToken) break; // parse statement // assignment.. if (tok && tok->varId() && Token::Match(tok, "%var% =")) { // taking address of another variable.. if (Token::Match(tok->next(), "= %var% [+;]")) { if (tok->tokAt(2)->varId() != tok->varId()) { // If variable points at allocated memory => error leakIfAllocated(tok, *varInfo); // no multivariable checking currently => bail out for rhs variables for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) { if (tok2->str() == ";") { break; } if (tok2->varId()) { varInfo->erase(tok2->varId()); } } } } // is variable used in rhs? bool used_in_rhs = false; for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next()) { if (tok2->str() == ";") { break; } if (tok->varId() == tok2->varId()) { used_in_rhs = true; break; } } // TODO: Better checking how the pointer is used in rhs? if (used_in_rhs) continue; // Variable has already been allocated => error if (conditionalAlloc.find(tok->varId()) == conditionalAlloc.end()) leakIfAllocated(tok, *varInfo); varInfo->erase(tok->varId()); // not a local variable nor argument? const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok->varId()); if (var && !var->isArgument() && !var->isLocal()) { continue; } // Don't check reference variables if (var && var->isReference()) continue; // allocation? if (Token::Match(tok->tokAt(2), "%type% (")) { const std::map<std::string, std::string>::const_iterator it = allocFunctions.find(tok->strAt(2)); if (it != allocFunctions.end()) { alloctype[tok->varId()] = it->second; } } // Assigning non-zero value variable. It might be used to // track the execution for a later if condition. if (Token::Match(tok->tokAt(2), "%num% ;") && MathLib::toLongNumber(tok->strAt(2)) != 0) notzero.insert(tok->varId()); else if (Token::Match(tok->tokAt(2), "- %type% ;") && tok->tokAt(3)->isUpperCaseName()) notzero.insert(tok->varId()); else notzero.erase(tok->varId()); } // if/else else if (Token::simpleMatch(tok, "if (")) { // Parse function calls inside the condition for (const Token *innerTok = tok->tokAt(2); innerTok; innerTok = innerTok->next()) { if (innerTok->str() == ")") break; if (innerTok->str() == "(" && innerTok->previous()->isName()) { std::string dealloc; { const std::map<std::string, std::string>::iterator func = deallocFunctions.find(tok->str()); if (func != deallocFunctions.end()) { dealloc = func->second; } } functionCall(innerTok->previous(), varInfo, dealloc); innerTok = innerTok->link(); } } const Token *tok2 = tok->linkAt(1); if (Token::simpleMatch(tok2, ") {")) { VarInfo varInfo1(*varInfo); VarInfo varInfo2(*varInfo); if (Token::Match(tok->next(), "( %var% )")) { varInfo2.erase(tok->tokAt(2)->varId()); if (notzero.find(tok->tokAt(2)->varId()) != notzero.end()) varInfo2.clear(); } else if (Token::Match(tok->next(), "( ! %var% )|&&")) { varInfo1.erase(tok->tokAt(3)->varId()); } else if (Token::Match(tok->next(), "( %var% ( ! %var% ) )|&&")) { varInfo1.erase(tok->tokAt(5)->varId()); } checkScope(tok2->next(), &varInfo1, notzero); tok2 = tok2->linkAt(1); if (Token::simpleMatch(tok2, "} else {")) { checkScope(tok2->tokAt(2), &varInfo2, notzero); tok = tok2->linkAt(2)->previous(); } else { tok = tok2->previous(); } VarInfo old; old.swap(*varInfo); // Conditional allocation in varInfo1 std::map<unsigned int, std::string>::const_iterator it; for (it = varInfo1.alloctype.begin(); it != varInfo1.alloctype.end(); ++it) { if (varInfo2.alloctype.find(it->first) == varInfo2.alloctype.end() && old.alloctype.find(it->first) == old.alloctype.end()) { varInfo->conditionalAlloc.insert(it->first); } } // Conditional allocation in varInfo2 for (it = varInfo2.alloctype.begin(); it != varInfo2.alloctype.end(); ++it) { if (varInfo1.alloctype.find(it->first) == varInfo1.alloctype.end() && old.alloctype.find(it->first) == old.alloctype.end()) { varInfo->conditionalAlloc.insert(it->first); } } // Conditional allocation/deallocation for (it = varInfo1.alloctype.begin(); it != varInfo1.alloctype.end(); ++it) { if (it->second == "dealloc" && conditionalAlloc.find(it->first) != conditionalAlloc.end()) { varInfo->conditionalAlloc.erase(it->first); varInfo2.erase(it->first); } } for (it = varInfo2.alloctype.begin(); it != varInfo2.alloctype.end(); ++it) { if (it->second == "dealloc" && conditionalAlloc.find(it->first) != conditionalAlloc.end()) { varInfo->conditionalAlloc.erase(it->first); varInfo1.erase(it->first); } } alloctype.insert(varInfo1.alloctype.begin(), varInfo1.alloctype.end()); alloctype.insert(varInfo2.alloctype.begin(), varInfo2.alloctype.end()); possibleUsage.insert(varInfo1.possibleUsage.begin(), varInfo1.possibleUsage.end()); possibleUsage.insert(varInfo2.possibleUsage.begin(), varInfo2.possibleUsage.end()); } } // unknown control.. else if (Token::Match(tok, "%type% (") && Token::simpleMatch(tok->linkAt(1), ") {")) { varInfo->clear(); break; } // Function call.. else if (Token::Match(tok, "%type% (") && tok->str() != "return") { std::string dealloc; { const std::map<std::string, std::string>::iterator func = deallocFunctions.find(tok->str()); if (func != deallocFunctions.end()) { dealloc = func->second; } } functionCall(tok, varInfo, dealloc); tok = tok->next()->link(); // Handle scopes that might be noreturn if (dealloc.empty() && Token::simpleMatch(tok, ") ; }")) { const std::string &functionName(tok->link()->previous()->str()); bool unknown = false; if (cfgignore.find(functionName) == cfgignore.end() && cfguse.find(functionName) == cfguse.end() && _tokenizer->IsScopeNoReturn(tok->tokAt(2), &unknown)) { if (unknown) { //const std::string &functionName(tok->link()->previous()->str()); varInfo->possibleUsageAll(functionName); } else { varInfo->clear(); } } } continue; } // return else if (tok->str() == "return" || tok->str() == "throw") { ret(tok, *varInfo); varInfo->clear(); } } }
void CheckLeakAutoVar::checkScope(const Token * const startToken, VarInfo *varInfo, std::set<unsigned int> notzero) { std::map<unsigned int, int> &alloctype = varInfo->alloctype; std::map<unsigned int, std::string> &possibleUsage = varInfo->possibleUsage; const std::set<unsigned int> conditionalAlloc(varInfo->conditionalAlloc); // Parse all tokens const Token * const endToken = startToken->link(); for (const Token *tok = startToken; tok && tok != endToken; tok = tok->next()) { // Deallocation and then dereferencing pointer.. if (tok->varId() > 0) { const std::map<unsigned int, int>::iterator var = alloctype.find(tok->varId()); if (var != alloctype.end()) { if (var->second == DEALLOC && !Token::Match(tok->previous(), "[;{},=] %var% =")) { deallocUseError(tok, tok->str()); } else if (Token::simpleMatch(tok->tokAt(-2), "= &")) { varInfo->erase(tok->varId()); } else if (tok->strAt(-1) == "=") { varInfo->erase(tok->varId()); } } else if (Token::Match(tok->previous(), "& %var% = %var% ;")) { varInfo->referenced.insert(tok->tokAt(2)->varId()); } } if (tok->str() == "(" && tok->previous()->isName()) { functionCall(tok->previous(), varInfo, NOALLOC); tok = tok->link(); continue; } // look for end of statement if (!Token::Match(tok, "[;{}]") || Token::Match(tok->next(), "[;{}]")) continue; tok = tok->next(); if (!tok || tok == endToken) break; // parse statement // assignment.. if (tok->varId() && Token::Match(tok, "%var% =")) { // taking address of another variable.. if (Token::Match(tok->next(), "= %var% [+;]")) { if (tok->tokAt(2)->varId() != tok->varId()) { // If variable points at allocated memory => error leakIfAllocated(tok, *varInfo); // no multivariable checking currently => bail out for rhs variables for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) { if (tok2->str() == ";") { break; } if (tok2->varId()) { varInfo->erase(tok2->varId()); } } } } // is variable used in rhs? bool used_in_rhs = false; for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next()) { if (tok2->str() == ";") { break; } if (tok->varId() == tok2->varId()) { used_in_rhs = true; break; } } // TODO: Better checking how the pointer is used in rhs? if (used_in_rhs) continue; // Variable has already been allocated => error if (conditionalAlloc.find(tok->varId()) == conditionalAlloc.end()) leakIfAllocated(tok, *varInfo); varInfo->erase(tok->varId()); // not a local variable nor argument? const Variable *var = tok->variable(); if (var && !var->isArgument() && !var->isLocal()) { continue; } // Don't check reference variables if (var && var->isReference()) continue; // allocation? if (Token::Match(tok->tokAt(2), "%type% (")) { int i = _settings->library.alloc(tok->tokAt(2)); if (i > 0) { alloctype[tok->varId()] = i; } } // Assigning non-zero value variable. It might be used to // track the execution for a later if condition. if (Token::Match(tok->tokAt(2), "%num% ;") && MathLib::toLongNumber(tok->strAt(2)) != 0) notzero.insert(tok->varId()); else if (Token::Match(tok->tokAt(2), "- %type% ;") && tok->tokAt(3)->isUpperCaseName()) notzero.insert(tok->varId()); else notzero.erase(tok->varId()); } // if/else else if (Token::simpleMatch(tok, "if (")) { // Parse function calls inside the condition for (const Token *innerTok = tok->tokAt(2); innerTok; innerTok = innerTok->next()) { if (innerTok->str() == ")") break; if (innerTok->str() == "(" && innerTok->previous()->isName()) { const int deallocId = _settings->library.dealloc(tok); functionCall(innerTok->previous(), varInfo, deallocId); innerTok = innerTok->link(); } } const Token *tok2 = tok->linkAt(1); if (Token::simpleMatch(tok2, ") {")) { VarInfo varInfo1(*varInfo); // VarInfo for if code VarInfo varInfo2(*varInfo); // VarInfo for else code if (Token::Match(tok->next(), "( %var% )")) { varInfo2.erase(tok->tokAt(2)->varId()); if (notzero.find(tok->tokAt(2)->varId()) != notzero.end()) varInfo2.clear(); } else if (Token::Match(tok->next(), "( ! %var% )|&&")) { varInfo1.erase(tok->tokAt(3)->varId()); } else if (Token::Match(tok->next(), "( %var% ( ! %var% ) )|&&")) { varInfo1.erase(tok->tokAt(5)->varId()); } else if (Token::Match(tok->next(), "( %var% < 0 )|&&")) { varInfo1.erase(tok->tokAt(2)->varId()); } else if (Token::Match(tok->next(), "( 0 > %var% )|&&")) { varInfo1.erase(tok->tokAt(4)->varId()); } else if (Token::Match(tok->next(), "( %var% > 0 )|&&")) { varInfo2.erase(tok->tokAt(2)->varId()); } else if (Token::Match(tok->next(), "( 0 < %var% )|&&")) { varInfo2.erase(tok->tokAt(4)->varId()); } checkScope(tok2->next(), &varInfo1, notzero); tok2 = tok2->linkAt(1); if (Token::simpleMatch(tok2, "} else {")) { checkScope(tok2->tokAt(2), &varInfo2, notzero); tok = tok2->linkAt(2)->previous(); } else { tok = tok2->previous(); } VarInfo old; old.swap(*varInfo); // Conditional allocation in varInfo1 std::map<unsigned int, int>::const_iterator it; for (it = varInfo1.alloctype.begin(); it != varInfo1.alloctype.end(); ++it) { if (varInfo2.alloctype.find(it->first) == varInfo2.alloctype.end() && old.alloctype.find(it->first) == old.alloctype.end()) { varInfo->conditionalAlloc.insert(it->first); } } // Conditional allocation in varInfo2 for (it = varInfo2.alloctype.begin(); it != varInfo2.alloctype.end(); ++it) { if (varInfo1.alloctype.find(it->first) == varInfo1.alloctype.end() && old.alloctype.find(it->first) == old.alloctype.end()) { varInfo->conditionalAlloc.insert(it->first); } } // Conditional allocation/deallocation for (it = varInfo1.alloctype.begin(); it != varInfo1.alloctype.end(); ++it) { if (it->second == DEALLOC && conditionalAlloc.find(it->first) != conditionalAlloc.end()) { varInfo->conditionalAlloc.erase(it->first); varInfo2.erase(it->first); } } for (it = varInfo2.alloctype.begin(); it != varInfo2.alloctype.end(); ++it) { if (it->second == DEALLOC && conditionalAlloc.find(it->first) != conditionalAlloc.end()) { varInfo->conditionalAlloc.erase(it->first); varInfo1.erase(it->first); } } alloctype.insert(varInfo1.alloctype.begin(), varInfo1.alloctype.end()); alloctype.insert(varInfo2.alloctype.begin(), varInfo2.alloctype.end()); possibleUsage.insert(varInfo1.possibleUsage.begin(), varInfo1.possibleUsage.end()); possibleUsage.insert(varInfo2.possibleUsage.begin(), varInfo2.possibleUsage.end()); } } // unknown control.. else if (Token::Match(tok, "%type% (") && Token::simpleMatch(tok->linkAt(1), ") {")) { varInfo->clear(); break; } // Function call.. else if (Token::Match(tok, "%type% (") && tok->str() != "return") { const int dealloc = _settings->library.dealloc(tok); functionCall(tok, varInfo, dealloc); tok = tok->next()->link(); // Handle scopes that might be noreturn if (dealloc == NOALLOC && Token::simpleMatch(tok, ") ; }")) { const std::string &functionName(tok->link()->previous()->str()); bool unknown = false; if (_tokenizer->IsScopeNoReturn(tok->tokAt(2), &unknown)) { if (!unknown) varInfo->clear(); else if (_settings->library.leakignore.find(functionName) == _settings->library.leakignore.end() && _settings->library.use.find(functionName) == _settings->library.use.end()) varInfo->possibleUsageAll(functionName); } } continue; } // return else if (tok->str() == "return") { ret(tok, *varInfo); varInfo->clear(); } // goto => weird execution path else if (tok->str() == "goto") { varInfo->clear(); } // continue/break else if (Token::Match(tok, "continue|break ;")) { varInfo->clear(); } // throw // TODO: if the execution leave the function then treat it as return else if (tok->str() == "throw") { varInfo->clear(); } } }
Type TypeCheck_::check_expression(AST_Expression e) { Type ct,t1,t2,t; switch (e->expressionType()) { case EXPBINOP: { AST_Expression_BinOp b = e->getAsBinOp(); return check_binop(b->left() , b->right() , b->binopType()); } case EXPUMINUS: { AST_Expression_UMinus b = e->getAsUMinus(); t = check_expression(b->exp()); if ( check_equal(t , T("Integer")) or check_equal(t , T("Real")) ) return t; throw "Type Error (3)"; } case EXPOUTPUT : { AST_Expression_Output b = e->getAsOutput(); return check_expression(b->expressionList()->front() ); } case EXPIF: { AST_Expression_If b = e->getAsIf(); ct = check_expression(b->condition() ); t1 = check_expression(b->then() ); t2 = check_expression(b->else_exp()); // Falta el elseIF if ( !check_equal(ct, T("Boolean")) ) throw "Type Error (4)"; if ( !check_equal(t1,t2) ) throw "Type Error (5)"; return t1; } case EXPCALL: { // Añadir las funciones en la listaaaa de variables AST_Expression_Call c = e->getAsCall(); if ( toStr(c->name()) == "sample" ) return T("Boolean"); if ( toStr(c->name()) == "pre" ) return check_expression(c->arguments()->front()); return T("Real"); } case EXPCOMPREF: { AST_Expression_ComponentReference b = e->getAsComponentReference(); VarInfo tt = varEnv->lookup( toStr(b->names()->front()) ); if (tt == NULL) { cerr << "Var:" << b->names()->front() << ":"; throw "Variable no existe (8)"; } if (b->indexes()->front()->size() == 0) return tt->type(); else { Type t = tt->type(); AST_ExpressionListIterator exit; foreach(exit , b->indexes()->front() ) if (t->getType() == TYARRAY) t = t->getAsArray()->arrayOf(); else throw "Type Error (7)"; return t; } break; } case EXPDERIVATIVE: return T("Real"); case EXPBOOLEAN: return T("Boolean"); case EXPSTRING: return T("String"); case EXPREAL: return T("Real"); case EXPINTEGER: return T("Integer"); case EXPBOOLEANNOT: { AST_Expression_BooleanNot b = e->getAsBooleanNot(); t = check_expression(b->exp()); if ( !check_equal(t, T("Boolean")) ) throw "Type Error (6)"; return t; } default: throw "No implrementado aun! (check_expression)"; } }
int MMO_EvalInitExp_::foldTraverseElement (AST_Expression exp) { int ret = 0; switch (exp->expressionType ()) { case EXPCOMPREF: { AST_Expression_ComponentReference cr = exp->getAsComponentReference (); VarInfo vi = _vt->lookup (cr->name ()); if (vi == NULL) { Error::getInstance ()->add (exp->lineNum (), EM_IR | EM_VARIABLE_NOT_FOUND, ER_Error, "%s", cr->name ().c_str ()); return (ret); } if (!vi->isConstant ()) { Error::getInstance ()->add ( exp->lineNum (), EM_IR | EM_INIT_EXP, ER_Error, "Only constants allowed inside initial expressions. %s", cr->name ().c_str ()); return (ret); } return (vi->value ()); } case EXPBOOLEAN: { AST_Expression_Boolean eb = exp->getAsBoolean (); if (eb->value ()) { return (1); } else { return (0); } } case EXPBOOLEANNOT: { AST_Expression_BooleanNot ebn = exp->getAsBooleanNot (); int res = foldTraverse (ebn->exp ()); if (res == 0) { return (1); } else { return (0); } } case EXPREAL: Error::getInstance ()->add ( 0, EM_IR | EM_INIT_EXP, ER_Warning, "Implicit conversion from Real to Integer, in initial expression."); return (exp->getAsReal ()->val ()); case EXPINTEGER: return (exp->getAsInteger ()->val ()); default: Error::getInstance ()->add ( 0, EM_IR | EM_INIT_EXP, ER_Warning, "Initial expression not recognized, returning zero as default value."); break; } return (ret); }
void CheckLeakAutoVar::checkScope(const Token * const startToken, VarInfo *varInfo, std::set<unsigned int> notzero) { std::map<unsigned int, VarInfo::AllocInfo> &alloctype = varInfo->alloctype; std::map<unsigned int, std::string> &possibleUsage = varInfo->possibleUsage; const std::set<unsigned int> conditionalAlloc(varInfo->conditionalAlloc); // Parse all tokens const Token * const endToken = startToken->link(); for (const Token *tok = startToken; tok && tok != endToken; tok = tok->next()) { if (!tok->scope()->isExecutable()) { tok = tok->scope()->classEnd; if (!tok) // Ticket #6666 (crash upon invalid code) break; } // Deallocation and then dereferencing pointer.. if (tok->varId() > 0) { const std::map<unsigned int, VarInfo::AllocInfo>::const_iterator var = alloctype.find(tok->varId()); if (var != alloctype.end()) { if (var->second.status == VarInfo::DEALLOC && tok->strAt(-1) != "&" && (!Token::Match(tok, "%name% =") || tok->strAt(-1) == "*")) { deallocUseError(tok, tok->str()); } else if (Token::simpleMatch(tok->tokAt(-2), "= &")) { varInfo->erase(tok->varId()); } else if (tok->strAt(-1) == "=") { varInfo->erase(tok->varId()); } } else if (Token::Match(tok->previous(), "& %name% = %var% ;")) { varInfo->referenced.insert(tok->tokAt(2)->varId()); } } if (tok->str() == "(" && tok->previous()->isName()) { VarInfo::AllocInfo allocation(0, VarInfo::NOALLOC); functionCall(tok->previous(), varInfo, allocation); tok = tok->link(); continue; } // look for end of statement if (!Token::Match(tok, "[;{}]") || Token::Match(tok->next(), "[;{}]")) continue; tok = tok->next(); if (!tok || tok == endToken) break; // parse statement, skip to last member while (Token::Match(tok, "%name% ::|. %name% !!(")) tok = tok->tokAt(2); // assignment.. if (Token::Match(tok, "%var% =")) { // taking address of another variable.. if (Token::Match(tok->next(), "= %var% [+;]")) { if (tok->tokAt(2)->varId() != tok->varId()) { // If variable points at allocated memory => error leakIfAllocated(tok, *varInfo); // no multivariable checking currently => bail out for rhs variables for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) { if (tok2->str() == ";") { break; } if (tok2->varId()) { varInfo->erase(tok2->varId()); } } } } // is variable used in rhs? bool used_in_rhs = false; for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next()) { if (tok2->str() == ";") { break; } if (tok->varId() == tok2->varId()) { used_in_rhs = true; break; } } // TODO: Better checking how the pointer is used in rhs? if (used_in_rhs) continue; // Variable has already been allocated => error if (conditionalAlloc.find(tok->varId()) == conditionalAlloc.end()) leakIfAllocated(tok, *varInfo); varInfo->erase(tok->varId()); // not a local variable nor argument? const Variable *var = tok->variable(); if (var && !var->isArgument() && (!var->isLocal() || var->isStatic())) continue; // Don't check reference variables if (var && var->isReference()) continue; // non-pod variable if (_tokenizer->isCPP()) { if (!var) continue; // Possibly automatically deallocated memory if (!var->typeStartToken()->isStandardType() && Token::Match(tok, "%var% = new")) continue; } // allocation? if (tok->next()->astOperand2() && Token::Match(tok->next()->astOperand2()->previous(), "%type% (")) { int i = _settings->library.alloc(tok->next()->astOperand2()->previous()); if (i > 0) { alloctype[tok->varId()].type = i; alloctype[tok->varId()].status = VarInfo::ALLOC; } } else if (_tokenizer->isCPP() && tok->strAt(2) == "new") { alloctype[tok->varId()].type = -1; alloctype[tok->varId()].status = VarInfo::ALLOC; } // Assigning non-zero value variable. It might be used to // track the execution for a later if condition. if (Token::Match(tok->tokAt(2), "%num% ;") && MathLib::toLongNumber(tok->strAt(2)) != 0) notzero.insert(tok->varId()); else if (Token::Match(tok->tokAt(2), "- %type% ;") && tok->tokAt(3)->isUpperCaseName()) notzero.insert(tok->varId()); else notzero.erase(tok->varId()); } // if/else else if (Token::simpleMatch(tok, "if (")) { // Parse function calls inside the condition for (const Token *innerTok = tok->tokAt(2); innerTok; innerTok = innerTok->next()) { if (innerTok->str() == ")") break; if (innerTok->str() == "(" && innerTok->previous()->isName()) { VarInfo::AllocInfo allocation(_settings->library.dealloc(tok), VarInfo::DEALLOC); if (allocation.type == 0) allocation.status = VarInfo::NOALLOC; functionCall(innerTok->previous(), varInfo, allocation); innerTok = innerTok->link(); } } const Token *tok2 = tok->linkAt(1); if (Token::simpleMatch(tok2, ") {")) { VarInfo varInfo1(*varInfo); // VarInfo for if code VarInfo varInfo2(*varInfo); // VarInfo for else code // Recursively scan variable comparisons in condition std::stack<const Token *> tokens; tokens.push(tok->next()->astOperand2()); while (!tokens.empty()) { const Token *tok3 = tokens.top(); tokens.pop(); if (!tok3) continue; if (tok3->str() == "&&") { tokens.push(tok3->astOperand1()); tokens.push(tok3->astOperand2()); continue; } if (tok3->str() == "(" && Token::Match(tok3->astOperand1(), "UNLIKELY|LIKELY")) { tokens.push(tok3->astOperand2()); continue; } const Token *vartok = nullptr; if (astIsVariableComparison(tok3, "!=", "0", &vartok)) { varInfo2.erase(vartok->varId()); if (notzero.find(vartok->varId()) != notzero.end()) varInfo2.clear(); } else if (astIsVariableComparison(tok3, "==", "0", &vartok)) { varInfo1.erase(vartok->varId()); } else if (astIsVariableComparison(tok3, "<", "0", &vartok)) { varInfo1.erase(vartok->varId()); } else if (astIsVariableComparison(tok3, ">", "0", &vartok)) { varInfo2.erase(vartok->varId()); } else if (astIsVariableComparison(tok3, "==", "-1", &vartok)) { varInfo1.erase(vartok->varId()); } } checkScope(tok2->next(), &varInfo1, notzero); tok2 = tok2->linkAt(1); if (Token::simpleMatch(tok2, "} else {")) { checkScope(tok2->tokAt(2), &varInfo2, notzero); tok = tok2->linkAt(2)->previous(); } else { tok = tok2->previous(); } VarInfo old; old.swap(*varInfo); // Conditional allocation in varInfo1 std::map<unsigned int, VarInfo::AllocInfo>::const_iterator it; for (it = varInfo1.alloctype.begin(); it != varInfo1.alloctype.end(); ++it) { if (varInfo2.alloctype.find(it->first) == varInfo2.alloctype.end() && old.alloctype.find(it->first) == old.alloctype.end()) { varInfo->conditionalAlloc.insert(it->first); } } // Conditional allocation in varInfo2 for (it = varInfo2.alloctype.begin(); it != varInfo2.alloctype.end(); ++it) { if (varInfo1.alloctype.find(it->first) == varInfo1.alloctype.end() && old.alloctype.find(it->first) == old.alloctype.end()) { varInfo->conditionalAlloc.insert(it->first); } } // Conditional allocation/deallocation for (it = varInfo1.alloctype.begin(); it != varInfo1.alloctype.end(); ++it) { if (it->second.status == VarInfo::DEALLOC && conditionalAlloc.find(it->first) != conditionalAlloc.end()) { varInfo->conditionalAlloc.erase(it->first); varInfo2.erase(it->first); } } for (it = varInfo2.alloctype.begin(); it != varInfo2.alloctype.end(); ++it) { if (it->second.status == VarInfo::DEALLOC && conditionalAlloc.find(it->first) != conditionalAlloc.end()) { varInfo->conditionalAlloc.erase(it->first); varInfo1.erase(it->first); } } alloctype.insert(varInfo1.alloctype.begin(), varInfo1.alloctype.end()); alloctype.insert(varInfo2.alloctype.begin(), varInfo2.alloctype.end()); possibleUsage.insert(varInfo1.possibleUsage.begin(), varInfo1.possibleUsage.end()); possibleUsage.insert(varInfo2.possibleUsage.begin(), varInfo2.possibleUsage.end()); } } // unknown control.. (TODO: handle loops) else if ((Token::Match(tok, "%type% (") && Token::simpleMatch(tok->linkAt(1), ") {")) || Token::simpleMatch(tok, "do {")) { varInfo->clear(); break; } // return else if (tok->str() == "return") { ret(tok, *varInfo); varInfo->clear(); } // throw else if (_tokenizer->isCPP() && tok->str() == "throw") { bool tryFound = false; const Scope* scope = tok->scope(); while (scope && scope->isExecutable()) { if (scope->type == Scope::eTry) tryFound = true; scope = scope->nestedIn; } // If the execution leaves the function then treat it as return if (!tryFound) ret(tok, *varInfo); varInfo->clear(); } // Function call.. else if (Token::Match(tok, "%type% (")) { VarInfo::AllocInfo allocation(_settings->library.dealloc(tok), VarInfo::DEALLOC); if (allocation.type == 0) allocation.status = VarInfo::NOALLOC; functionCall(tok, varInfo, allocation); tok = tok->next()->link(); // Handle scopes that might be noreturn if (allocation.status == VarInfo::NOALLOC && Token::simpleMatch(tok, ") ; }")) { const std::string &functionName(tok->link()->previous()->str()); bool unknown = false; if (_tokenizer->IsScopeNoReturn(tok->tokAt(2), &unknown)) { if (!unknown) varInfo->clear(); else if (_settings->library.leakignore.find(functionName) == _settings->library.leakignore.end() && _settings->library.use.find(functionName) == _settings->library.use.end()) varInfo->possibleUsageAll(functionName); } } continue; } // delete else if (_tokenizer->isCPP() && tok->str() == "delete") { if (tok->strAt(1) == "[") tok = tok->tokAt(3); else tok = tok->next(); while (Token::Match(tok, "%name% ::|.")) tok = tok->tokAt(2); if (tok->varId() && tok->strAt(1) != "[") { VarInfo::AllocInfo allocation(-1, VarInfo::DEALLOC); changeAllocStatus(varInfo, allocation, tok, tok); } } // goto => weird execution path else if (tok->str() == "goto") { varInfo->clear(); } // continue/break else if (Token::Match(tok, "continue|break ;")) { varInfo->clear(); } } }
VOID Image(IMG img, VOID *v) { cerr << "Loading image " << IMG_Name(img) << endl; /* Find main. We won't do anything before main starts. */ RTN rtn = RTN_FindByName(img, "main"); if(RTN_Valid(rtn)) { RTN_Open(rtn); RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)callBeforeMain, IARG_END); RTN_Close(rtn); } /* Go over all the allocation routines we are instrumenting and insert the * instrumentation. */ bool varInfoAllocated = false; VarInfo *vi = NULL; for(FuncProto *fp: funcProto) { RTN rtn = RTN_FindByName(img, fp->name.c_str()); if (RTN_Valid(rtn)) { /* If we found a routine we care about, allocate the * VarInfo structure for that image. Init it if we can. * If not, make it NULL. */ if(!varInfoAllocated) { varInfoAllocated = true; vi = new VarInfo(); if (!vi->init(IMG_Name(img))) { cerr<<"Failed to initialize VarInfo for image " << IMG_Name(img) << endl; delete vi; vi = NULL; } } FuncRecord *fr; cout << "Procedure " << fp->name << " located." << endl; PIN_GetLock(&lock, PIN_ThreadId() + 1); if((fr = findFuncRecord(&funcRecords, fp->name)) == NULL) { fr = allocateAndAdd(&funcRecords, fp, vi); } assert(fr != NULL); PIN_ReleaseLock(&lock); RTN_Open(rtn); // Instrument if(fp->number >= 0 && fp->size >= 0 && fp->retaddr >= 0) { RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)callBeforeAlloc, IARG_PTR, fr, IARG_THREAD_ID, IARG_RETURN_IP, IARG_FUNCARG_ENTRYPOINT_VALUE, fp->number, IARG_FUNCARG_ENTRYPOINT_VALUE, fp->size, IARG_FUNCARG_ENTRYPOINT_VALUE, fp->retaddr, IARG_END); } else if(fp->number == -1 && fp->size >= 0 && fp->retaddr >= 0) { RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)callBeforeAlloc, IARG_PTR, fr, IARG_THREAD_ID, IARG_RETURN_IP, IARG_ADDRINT, 1, IARG_FUNCARG_ENTRYPOINT_VALUE, fp->size, IARG_FUNCARG_ENTRYPOINT_VALUE, fp->retaddr, IARG_END); } else if(fp->number == -1 && fp->size >= 0 && fp->retaddr == -1) { RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)callBeforeAlloc, IARG_PTR, fr, IARG_THREAD_ID, IARG_RETURN_IP, IARG_ADDRINT, 1, IARG_FUNCARG_ENTRYPOINT_VALUE, fp->size, IARG_UINT32, 0, IARG_END); } else if(fp->number >= 0 && fp->size >= 0 && fp->retaddr == -1) { RTN_InsertCall(rtn, IPOINT_BEFORE, (AFUNPTR)callBeforeAlloc, IARG_PTR, fr, IARG_THREAD_ID, IARG_RETURN_IP, IARG_FUNCARG_ENTRYPOINT_VALUE, fp->number, IARG_FUNCARG_ENTRYPOINT_VALUE, fp->size, IARG_UINT32, 0, IARG_END); } else { cerr << "I did not understand this function prototype: " << endl << fp->name << ": number " << fp->number << ", size " << fp->size << ", retaddr " << fp->retaddr << endl; Usage(); exit(-1); } RTN_InsertCall(rtn, IPOINT_AFTER, (AFUNPTR)callAfterAlloc, IARG_PTR, fr, IARG_THREAD_ID, IARG_FUNCRET_EXITPOINT_VALUE, IARG_END); RTN_Close(rtn); } } }
void MMO_Generator_::_variables () { stringstream buffer; VarSymbolTable vt = _model->varTable (); vt->setPrintEnvironment (VST_INIT); if (_model->annotation ()->solver () == ANT_DASSL || _model->annotation ()->solver () == ANT_DOPRI) { vt->setPrintEnvironment (VST_CLASSIC_INIT); } string indent = _writer->indent (1); list<VarInfo>::iterator it; list<VarInfo> parameters = vt->parameters (); for (it = parameters.begin (); it != parameters.end (); it++) { VarInfo vi = *it; Index idx = vi->index (); stringstream reverse; if (vi->type ()->getType () == TYREAL) { buffer << "double " << vt->print (vi); } else if (vi->type ()->getType () == TYINTEGER) { buffer << "int " << vt->print (vi); reverse << "int __reverse" << vt->print (vi); } if (vi->isArray ()) { buffer << "[" << vi->size () << "]"; reverse << "[" << vi->size () << "]"; } else { buffer << " = 0"; reverse << " = 0"; } buffer << ";"; if (vi->type ()->getType () == TYINTEGER) { reverse << ";"; _writer->write (&reverse, WR_GLOBAL_VARS); } _writer->write (&buffer, WR_GLOBAL_VARS); if (vi->hasAssignment () || vi->hasStartModifier () || vi->hasEachModifier ()) { buffer << _model->printInitialAssignment (vi, indent); _writer->write (&buffer, WR_START_CODE); } } _writer->newLine (WR_GLOBAL_VARS); }