/*************************************************************************/ /* DUCTAPE Version 2.0 */ /* Copyright (C) 2001 */ /* Forschungszentrum Juelich, Zentralinstitut fuer Angewandte Mathematik */ /*************************************************************************/ #include "pdbType.h" #include "pdbCRoutine.h" #include "pdbFRoutine.h" #include "pdbClass.h" #include #ifdef NO_INLINE # define inline # include "pdbRoutine.inl" #endif extern void pdb_ERROR(const char *msg, const char *val); const char *pdbStmt::toName(stmt_t v) { switch (v) { case ST_SWITCH: return "switch"; case ST_CASE : return "case"; case ST_INIT : return "init"; case ST_RETURN: return "return"; case ST_IF : return "if"; case ST_EMPTY : return "empty"; case ST_FOR : return "for"; case ST_GOTO : return "goto"; case ST_BREAK : return "break"; case ST_LABEL : return "label"; case ST_BLOCK : return "block"; case ST_ASM : return "asm"; case ST_EXPR : return "expr"; case ST_ASSIGN: return "assign"; case ST_THROW : return "throw"; case ST_WHILE : return "while"; case ST_DO : return "do"; case ST_TRY : return "try"; case ST_CATCH : return "catch"; case ST_DECL : return "decl"; case ST_CONTINUE : return "continue"; case ST_SET_VLA_SIZE: return "set_vla_size"; case ST_VLA_DECL : return "vla_decl"; case ST_VLA_DEALLOC : return "vla_dealloc"; case ST_FALLOCATE : return "fallocate"; case ST_FASSIGN : return "fassign"; case ST_FIO : return "fio"; case ST_FDO : return "fdo"; case ST_FDEALLOCATE : return "fdeallocate"; case ST_FRETURN : return "freturn"; case ST_FIF : return "fif"; case ST_FCONTINUE : return "fcontinue"; case ST_FSINGLE_IF : return "fsingle_if"; case ST_FGOTO : return "fgoto"; case ST_FSTOP : return "fstop"; case ST_FLABEL : return "flabel"; case ST_FEXIT: return "fexit"; case ST_FCYCLE : return "fcycle"; case ST_FARITHIF : return "farithif"; case ST_FENTRY : return "fentry"; case ST_FPAUSE : return "fpause"; case ST_FLABELASSIGN : return "flabelassign"; case ST_FPOINTERASSIGN : return "fpointerassign"; case ST_FSELECT : return "fselect"; case ST_FCASE : return "fcase"; case ST_FWHERE : return "fwhere"; case ST_FFORALL : return "fforall"; case ST_FCALL : return "fcall"; case ST_NA : default : return "NA"; } } pdbStmt::stmt_t pdbStmt::toStmt(const char *v) { if ( strcmp ("switch", v) == 0 ) return ST_SWITCH; if ( strcmp ("case", v) == 0 ) return ST_CASE; if ( strcmp ("init", v) == 0 ) return ST_INIT; if ( strcmp ("return", v) == 0 ) return ST_RETURN; if ( strcmp ("if", v) == 0 ) return ST_IF; if ( strcmp ("empty", v) == 0 ) return ST_EMPTY; if ( strcmp ("for", v) == 0 ) return ST_FOR; if ( strcmp ("goto", v) == 0 ) return ST_GOTO; if ( strcmp ("break", v) == 0 ) return ST_BREAK; if ( strcmp ("label", v) == 0 ) return ST_LABEL; if ( strcmp ("block", v) == 0 ) return ST_BLOCK; if ( strcmp ("asm", v) == 0 ) return ST_ASM; if ( strcmp ("expr", v) == 0 ) return ST_EXPR; if ( strcmp ("assign", v) == 0 ) return ST_ASSIGN; if ( strcmp ("throw", v) == 0 ) return ST_THROW; if ( strcmp ("while", v) == 0 ) return ST_WHILE; if ( strcmp ("do", v) == 0 ) return ST_DO; if ( strcmp ("try", v) == 0 ) return ST_TRY; if ( strcmp ("catch", v) == 0 ) return ST_CATCH; if ( strcmp ("decl", v) == 0 ) return ST_DECL; if ( strcmp ("continue", v) == 0 ) return ST_CONTINUE; if ( strcmp ("set_vla_size", v) == 0 ) return ST_SET_VLA_SIZE; if ( strcmp ("vla_decl", v) == 0 ) return ST_VLA_DECL; if ( strcmp ("vla_dealloc", v) == 0 ) return ST_VLA_DEALLOC; if ( strcmp ("fallocate", v) == 0 ) return ST_FALLOCATE; if ( strcmp ("fassign", v) == 0 ) return ST_FASSIGN; if ( strcmp ("fio", v) == 0 ) return ST_FIO; if ( strcmp ("fdo", v) == 0 ) return ST_FDO; if ( strcmp ("fdeallocate", v) == 0 ) return ST_FDEALLOCATE; if ( strcmp ("freturn", v) == 0 ) return ST_FRETURN; if ( strcmp ("fif", v) == 0 ) return ST_FIF; if ( strcmp ("fsingle_if", v) == 0 ) return ST_FSINGLE_IF; if ( strcmp ("fgoto", v) == 0 ) return ST_FGOTO; if ( strcmp ("fstop", v) == 0 ) return ST_FSTOP; if ( strcmp ("flabel", v) == 0 ) return ST_FLABEL; if ( strcmp ("fexit", v) == 0 ) return ST_FEXIT; if ( strcmp ("fcycle", v) == 0 ) return ST_FCYCLE; if ( strcmp ("farithif", v) == 0 ) return ST_FARITHIF; if ( strcmp ("fentry", v) == 0 ) return ST_FENTRY; if ( strcmp ("fpause", v) == 0 ) return ST_FPAUSE; if ( strcmp ("flabelassign", v) == 0 ) return ST_FLABELASSIGN; if ( strcmp ("fpointerassign", v) == 0 ) return ST_FPOINTERASSIGN; if ( strcmp ("fselect", v) == 0 ) return ST_FSELECT; if ( strcmp ("fcase", v) == 0 ) return ST_FCASE; if ( strcmp ("fwhere", v) == 0 ) return ST_FWHERE; if ( strcmp ("fforall", v) == 0 ) return ST_FFORALL; if ( strcmp ("fcall", v) == 0 ) return ST_FCALL; if ( strcmp ("fcontinue", v) == 0 ) return ST_FCONTINUE; pdb_ERROR("Unknown statement kind ", v); return ST_NA; } ostream& operator<<(ostream& ostr, const pdbStmt& s) { const pdbStmt* s1; ostr << "st#" << s.id() << " " << pdbStmt::toName(s.kind()) << " " << s.stmtBegin() << " " << s.stmtEnd(); if ((s1 = s.nextStmt()) != NULL) ostr << " st#" << s1->id(); else ostr << " NA"; if ((s1 = s.downStmt()) != NULL) ostr << " st#" << s1->id(); else ostr << " NA"; if ((s1 = s.extraStmt()) != NULL) ostr << " st#" << s1->id(); else if ( s.kind() == pdbStmt::ST_DECL || s.kind() == pdbStmt::ST_IF || s.kind() == pdbStmt::ST_CASE || s.kind() == pdbStmt::ST_FOR ) ostr << " NA"; return ostr; } ostream& operator<<(ostream& ostr, const pdbCallee& c) { ostr << "ro#" << c.call()->id() << " " << pdbItem::toName(c.virtuality()) << " "; return c.printLoc(ostr); } pdbRoutine::~pdbRoutine() { for (callvec::const_iterator ct=calls.begin(); ct!=calls.end(); ++ct) delete *ct; for (locvec::const_iterator rt=retrns.begin(); rt!=retrns.end(); ++rt) delete *rt; for (stmtvec::const_iterator st=stmts.begin(); st!=stmts.end(); ++st) delete *st; } void pdbRoutine::incrCalled() const { pdbRoutine *self = const_cast(this); self->numc++; } pdbStmt* pdbRoutine::addStmt(int id) { if ( id < 0 ) return 0; if ( id >= stmts.size() ) stmts.resize(id+1, 0); if ( ! stmts[id] ) stmts[id] = new pdbStmt(id); return stmts[id]; } void pdbRoutine::process(PDB *p) { // if routine wasn't called, add it to the toplevel functions if ( numCalled() == 0 ) { p->callTree()->addCallee(this, pdbItem::VI_NO, 0, 0, 0); } int lastid=-1; // recreate PDB 2.0 return location information from statement info for (stmtvec::const_iterator st=statements().begin(); st!=statements().end(); ++st) { if (*st == NULL) { fprintf (stderr, "Error: invalid PDB file, last was st#%d\n",lastid); } else { lastid = (*st)->id(); if ( (*st)->kind() == pdbStmt::ST_RETURN || (*st)->kind() == pdbStmt::ST_FRETURN ) { const pdbLoc& loc = (*st)->stmtBegin(); if ( loc.file() ) addReturnLocation(loc.file(), loc.line(), loc.col()); } if ( (*st)->kind() == pdbStmt::ST_FSTOP ) { const pdbLoc& loc = (*st)->stmtBegin(); if ( loc.file() ) { pdbFRoutine *f = dynamic_cast (this); f->addStopLocation(const_cast(loc.file()), loc.line(), loc.col()); } } } } pdbItem::process(p); } ostream& pdbRoutine::print(ostream& ostr) const { rspec_t k; link_t l; const pdbStmt* s; pdbItem::print(ostr); if ( signature() ) ostr << "rsig ty#" << signature()->id() << "\n"; if ( (l = linkage()) != LK_NA ) ostr << "rlink " << toName(l) << "\n"; ostr << "rkind " << toName(kind()) << "\n"; if ( (k = specialKind()) != RS_NA ) ostr << "rskind " << toName(k) << "\n"; pdbTemplateItem::print(ostr); const pdbRoutine::callvec c = callees(); for (pdbRoutine::callvec::const_iterator ct=c.begin(); ct!=c.end(); ++ct) ostr << "rcall " << **ct << "\n"; pdbFatItem::print(ostr); if ( (s = body()) ) { ostr << "rbody st#" << s->id() << "\n"; for (int i=0; ikind() != pdbStmt::ST_NA ) ostr << "rstmt " << *(stmts[i]) << "\n"; } else { if ( firstExecStmtLocation().file() ) ostr << "rstart " << firstExecStmtLocation() << "\n"; const pdbRoutine::locvec lr = returnLocations(); for (pdbRoutine::locvec::const_iterator lt=lr.begin(); lt!=lr.end(); ++lt) ostr << "rret " << **lt << "\n"; } return ostr; } void pdbRoutine::adjustPtrs(PDB* p) { const pdbRoutine* r; const pdbFile* fi; pdbTemplateItem::adjustPtrs(p); if ( sig->newId() > UNIQUE ) sig = p->getTypeMap()[sig->newId()]; for( callvec::iterator it = calls.begin(); it!=calls.end(); ++it) { r = (*it)->call(); if ( r->newId() > UNIQUE ) if ( p->language() & PDB::LA_C_or_CXX ) { (*it)->call(p->getCRoutineMap()[r->newId()]); } else if ( p->language() & PDB::LA_FORTRAN ) { (*it)->call(p->getFRoutineMap()[r->newId()]); } if ( (fi=(*it)->file()) && (fi->newId() > UNIQUE) ) (*it)->file(p->getFileMap()[fi->newId()]); } if ( (fi=firstExecStmtLocation().file()) && (fi->newId() > UNIQUE) ) festmt.file(p->getFileMap()[fi->newId()]); for( locvec::iterator rt = retrns.begin(); rt!=retrns.end(); ++rt) { if ( (fi=(*rt)->file()) && (fi->newId() > UNIQUE) ) (*rt)->file(p->getFileMap()[fi->newId()]); } for( stmtvec::iterator st = stmts.begin(); st!=stmts.end(); ++st) { if ( *st ) { if ( (fi=(*st)->bg.file()) && (fi->newId() > UNIQUE) ) (*st)->bg.file(p->getFileMap()[fi->newId()]); if ( (fi=(*st)->ed.file()) && (fi->newId() > UNIQUE) ) (*st)->ed.file(p->getFileMap()[fi->newId()]); } } } pdbSimpleItem::dupl_t pdbRoutine::findDuplicate(pdbSimpleItem* r) { pdbRoutine* rhs = dynamic_cast (r); if ( fullName() == rhs->fullName() ) { if ( kind() == RO_EXT && rhs->kind() != RO_EXT ) return OLDDUPL; else return NEWDUPL; } else { return NODUPL; } }