virtual bool Traverse( AstInterface &fa, const AstNodePtr& s, AstInterface::TraversalVisitType t) { HasValueMapReplace valrepl( fa, valmap, false); if (ValueAnnotation::get_inst()->is_value_restrict_op( fa, s, &append, &valrepl, &astcodegen)) return true; AstNodePtr lhs, rhs; AstInterface::AstNodeList vars, args; HasValueDescriptor desc; if (fa.IsAssignment(s, &lhs, &rhs)) { if (append.has_value( rhs, &desc) ) { append( lhs, desc); } } else if (fa.IsVariableDecl( s, &vars, &args)) { AstInterface::AstNodeList::iterator pv = vars.begin(); AstInterface::AstNodeList::iterator pa = args.begin(); while (pv != vars.end()) { lhs = *pv; rhs = *pa; if (append.has_value( rhs, &desc) ) { append( lhs, desc ); } ++pv; ++pa; } } return true; }
bool SymbolicValGenerator:: IsFortranLoop(AstInterface& fa, const AstNodePtr& s, SymbolicVar* ivar , SymbolicVal* lb , SymbolicVal* ub, SymbolicVal* step, AstNodePtr* body) { AstNodePtr ivarast, lbast, ubast, stepast, ivarscope; if (!fa.IsFortranLoop(s, &ivarast, &lbast, &ubast, &stepast, body)) return false; std::string varname; if (! fa.IsVarRef(ivarast, 0, &varname, &ivarscope)) { return false; } if (ivar != 0) *ivar = SymbolicVar(varname, ivarscope); if (lb != 0) *lb = SymbolicValGenerator::GetSymbolicVal(fa,lbast); if (ub != 0) *ub = SymbolicValGenerator::GetSymbolicVal(fa,ubast); if (step != 0) { if (stepast != AST_NULL) *step = SymbolicValGenerator::GetSymbolicVal(fa,stepast); else *step = SymbolicVal(1); } return true; }
AstNodePtr SymbolicConst :: CodeGen(AstInterface &fa) const { if (type == "int") return fa.CreateConstInt(intval); else return fa.CreateConstant( type, val); }
AstNodePtr SymbolicFunction :: CodeGen( AstInterface &_fa) const { AstInterface::AstNodeList l; for (const_iterator i = args.begin(); i != args.end(); ++i) { SymbolicVal cur = *i; AstNodePtr curast = cur.CodeGen(_fa); l.push_back(curast); } if (t == AstInterface::OP_NONE) { return _fa.CreateFunctionCall( op, l); } else if (t == AstInterface::OP_ARRAY_ACCESS) { AstNodePtr arr = l.front(); l.pop_front(); return _fa.CreateArrayAccess(arr, l); } else if (t == AstInterface::OP_ASSIGN && l.size() == 2) { return _fa.CreateAssignment(l.front(), l.back()); } else if (l.size() == 2) return _fa.CreateBinaryOP( t, l.front(), l.back()); else { assert(l.size() == 1); return _fa.CreateUnaryOP( t, l.front()); } }
void PtrAnal:: ProcessMod(AstInterface& fa, const std::string& readname, std::list<std::string>& fields, const AstNodePtr& mod) { std::string modname; AstNodePtr p = mod; if (fa.IsVarRef(mod) || fa.IsArrayAccess(mod, &p)) { modname = Get_VarName(fa,p); Stmt stmt_last = fields.size()? field_x_eq_y(modname, fields, readname) : x_eq_y(modname, readname); stmts_pushback(stmts,stmt_last); namemap[mod.get_ptr()] = VarRef(stmt_last,modname); } else { AstInterface::OperatorEnum op; AstNodePtr p2; if (fa.IsUnaryOp(mod,&op, &p) && op == AstInterface::UOP_DEREF) { std::string lhs = Get_VarName(fa,p); Stmt stmt_last = deref_x_eq_y(lhs, fields, readname); stmts_pushback(stmts,stmt_last); namemap[p.get_ptr()] = VarRef(stmt_last,lhs); namemap[mod.get_ptr()] = VarRef(stmt_last, readname); } else if (fa.IsBinaryOp(mod,&op,&p,&p2)) { if (op==AstInterface::BOP_DOT_ACCESS) { std::string field = Local_GetFieldName(fa, p2); fields.push_front(field); ProcessMod(fa, readname, fields, p); Stmt stmt_last = stmts_back(stmts); namemap[mod.get_ptr()] = VarRef(stmt_last, readname); } else if (op==AstInterface::BOP_ARROW_ACCESS) { std::string lhs = Get_VarName(fa, p), field = Local_GetFieldName(fa, p2); fields.push_front(field); Stmt stmt_last = deref_x_eq_y(lhs,fields,readname); stmts_pushback(stmts,stmt_last); namemap[p.get_ptr()] = VarRef(stmt_last,lhs); namemap[mod.get_ptr()] = VarRef(stmt_last, readname); } else { std::cerr << "can't handle " << AstToString(mod) << "\n"; assert(false); // other operations? to be handled later } } else if (fa.IsFunctionCall(mod)) { std::string lhs = Get_VarName(fa, mod); Stmt stmt_last = deref_x_eq_y(lhs, fields, readname); stmts_pushback(stmts,stmt_last); namemap[mod.get_ptr()] = VarRef(stmt_last,lhs); } else { std::cerr << "cannot process " << AstToString(mod) << "\n"; assert(false); // other operations? to be handled later } } }
AstNodePtr SymbolicMultiply:: CodeGenOP( AstInterface &fa, const AstNodePtr& a1, const AstNodePtr& a2) const { int val = 0; if (fa.IsConstInt(a1, &val) && val == -1) return fa.CreateUnaryOP(AstInterface::UOP_MINUS, a2); else if (fa.IsConstInt(a2, &val) && val == -1) return fa.CreateUnaryOP(AstInterface::UOP_MINUS, a1); return fa.CreateBinaryOP(AstInterface::BOP_TIMES, a1, a2); }
bool operator()( AstInterface& fa, const AstNodePtr& head, AstNodePtr& result) { #ifdef DEBUG std::cerr << "LoopTransformationWrap:operator()\n"; #endif if (!fa.IsStatement(head)) return false; fa.SetRoot( head); return LoopTransformation(head, result); }
bool ArrayUseAccessFunction::get_modify(AstInterface& fa, const AstNodePtr& fc, CollectObject<AstNodePtr>* collect) { AstInterface::AstNodeList args; if (prev1 != 0 && prev1->get_modify(fa, fc, collect)) return true; std::string sig; AstNodePtr f; if (fa.IsFunctionCall(fc, &f,&args) && fa.IsVarRef(f,0,&sig) && sig == funcname) { return true; } return false; }
AstNodePtr ArrayUseAccessFunction:: CreateArrayAccess( AstInterface& fa, const AstNodePtr& arr, AstInterface::AstNodeList& index) { if (prev != 0) return prev->CreateArrayAccess(fa, arr, index); if (index.size() > 1) { AstInterface::AstNodeList tmp = index; tmp.push_front(arr); return fa.CreateFunctionCall(funcname, tmp); } else return fa.CreateArrayAccess(arr, index); }
AstNodePtr SymbolicAstWrap::CodeGen( AstInterface &fa) const { if (codegen == 0) return fa.CopyAstTree(ast); else return (*codegen)(&fa, ast); }
bool BuildAstTreeDepGraph:: ProcessLoop( AstInterface &fa, const AstNodePtr& l, const AstNodePtr& body, AstInterface::TraversalVisitType t) { if (t == AstInterface::PreVisit) { GraphAccessInterface::Node *n = graph->CreateNodeImpl(l, GetStmtDomain(l)); AstNodePtr init,cond,incr; if (!fa.IsLoop(l, &init, &cond, &incr)) assert(false); for (StmtStackType::Iterator p(stmtNodes); !p.ReachEnd(); ++p) { if (init != AST_NULL) ComputeDataDep(*p, StmtNodeInfo(n,init), DEPTYPE_DATA ); if (cond != AST_NULL) ComputeDataDep(*p, StmtNodeInfo(n,cond), DEPTYPE_DATA ); if (incr != AST_NULL) ComputeDataDep(*p, StmtNodeInfo(n,incr), DEPTYPE_DATA ); } for (StmtStackType::Iterator ps(gotoNodes); !ps.ReachEnd(); ++ps) { StmtNodeInfo info(n,l); ComputeCtrlDep((*ps), info); } ctrlNodes.PushFirst(StmtNodeInfo(n,l) ); } else { ctrlNodes.PopFirst(); } return ProcessAstTree::ProcessLoop(fa, l, body, t); }
static bool AliasAnnotAnal(AstInterface& fa, OperatorAnnotCollection <OperatorAliasDescriptor>& aliasInfo, const AstNodePtr& fc, const AstNodePtr& result, CollectObject< pair<AstNodePtr, int> >& collectalias) { AstInterface::AstNodeList args; OperatorAliasDescriptor desc; if (!aliasInfo.known_operator( fa, fc, &args, &desc, false) ) return false; ReplaceParams paramMap( desc.get_param_decl().get_params(), args); paramMap.add("result", result); int index = 0; for (OperatorAliasDescriptor::const_iterator p1 = desc.begin(); p1 != desc.end(); ++p1, ++index) { const NameGroup& cur = *p1; for (NameGroup::const_iterator p2 = cur.begin(); p2 != cur.end(); ++p2) { string varname = *p2; AstNodePtr arg = paramMap.find(varname).get_ast(); if (arg != AST_NULL) { collectalias( pair<AstNodePtr, int>(arg, index)); } else { AstNodePtr var = fa.CreateVarRef(varname); collectalias( pair<AstNodePtr, int>(var, index)); } } } return true; }
bool ArrayUseAccessFunction:: GetArrayBound( AstInterface& fa, const AstNodePtr& array, int dim, int &lb, int &ub) { if (prev != 0) return prev->GetArrayBound(fa, array, dim, lb, ub); return fa.GetArrayBound(array, dim, lb, ub); }
bool PtrAnal:: may_alias(AstInterface& fa, const AstNodePtr& _r1, const AstNodePtr& _r2) { AstNodePtr r1 = fa.IsExpression(_r1); AstNodePtr r2 = fa.IsExpression(_r2); if (r1 == AST_NULL || r2 == AST_NULL) assert(false); std::string varname1 = Get_VarName(fa, r1), varname2 = Get_VarName(fa, r2); return may_alias(varname1, varname2); }
bool ArrayUseAccessFunction::get_read(AstInterface& fa, const AstNodePtr& fc, CollectObject<AstNodePtr>* collect) { AstInterface::AstNodeList args; if (prev1 != 0 && prev1->get_read(fa, fc, collect)) return true; std::string sig; AstNodePtr f; if (fa.IsFunctionCall(fc, &f,&args) && fa.IsVarRef(f,0,&sig) && sig == funcname) { if (collect != 0) { AstInterface::AstNodeList::const_iterator argp = args.begin(); for ( ++argp; argp != args.end(); ++argp) { (*collect)(*argp); } } return true; } return false; }
bool ArrayUseAccessFunction:: IsUniqueArray( AstInterface& fa, const AstNodePtr& array) { if (prev != 0 && prev->IsUniqueArray(fa, array)) return true; AstNodeType t; if (!fa.IsVarRef(array, &t)) assert(0); return false; }
static std::string Local_GetFieldName(AstInterface& fa, const AstNodePtr& field) { std::string name; if (fa.IsVarRef(field, 0, &name)) { assert(name != ""); return "d:" + name; } std::cerr << "Not field name: " << AstToString(field) << "\n"; assert(false); }
virtual bool Traverse( AstInterface &fa, const AstNodePtr& _n, AstInterface::TraversalVisitType t) { AstNodePtr n = fa.IsExpression(_n); if (n != AST_NULL) { PtrAnal::VarRef p = m.translate_exp(n); if (p.name != "") { std::cout << AstInterface::AstToString(n) << ":" << ((long) p.stmt) << p.name << "\n"; } } else if (fa.IsStatement(_n)) { PtrAnal::StmtRef p = m.translate_stmt(_n); if (p.size()) { std::cout << AstInterface::AstToString(_n) << ":" << ((long) p.front()) << "->" << ((long)p.back()) << "\n"; } } return true; }
bool ArrayUseAccessFunction:: IsArrayAccess( AstInterface& fa, const AstNodePtr& s, AstNodePtr* array, AstInterface::AstNodeList* index) { AstInterface::AstNodeList args; if (prev != 0 && prev->IsArrayAccess(fa, s, array, index)) return true; std::string sig; AstNodePtr f; if (fa.IsFunctionCall(s, &f,&args) && fa.IsVarRef(f,0,&sig) && sig == funcname) { AstInterface::AstNodeList::const_iterator p = args.begin(); if (array != 0) *array = *p; if (index != 0) { for (++p; p != args.end(); ++p) { index->push_back(*p); } } return true; } return false; }
AstNodePtr SymbolicSelect:: CodeGen( AstInterface &fa ) const { int size = 0; AstInterface::AstNodeList list; for (OpdIterator iter = GetOpdIterator(); !iter.ReachEnd(); iter.Advance()) { AstNodePtr p = Term2Val(iter.Current()).CodeGen(fa); list.push_back(p); ++size; } assert( size > 1); std::string func = (opt< 0)? "min" : "max"; return fa.CreateFunctionCall(func, list); }
AstNodePtr SymbolicPlus:: CodeGenOP( AstInterface &fa, const AstNodePtr& a1, const AstNodePtr& a2) const { AstNodePtr opd; AstInterface::OperatorEnum opr; if (fa.IsUnaryOp(a2, &opr, &opd) && opr == AstInterface::UOP_MINUS) { return fa.CreateBinaryOP(AstInterface::BOP_MINUS,a1, fa.CopyAstTree(opd)); } else if (fa.IsUnaryOp(a1, &opr, &opd) && opr == AstInterface::UOP_MINUS) { return fa.CreateBinaryOP(AstInterface::BOP_MINUS,a2, fa.CopyAstTree(opd)); } return fa.CreateBinaryOP(AstInterface::BOP_PLUS, a1, a2); }
//! Get a unique string name for a type, similar to qualified names in C++ string OperatorDeclaration:: get_signiture( AstInterface& fa, const std::string& fname, const AstInterface::AstTypeList& plist) { std::string r = fname; if (!unique) for ( AstInterface::AstTypeList::const_iterator p = plist.begin(); p != plist.end(); ++p) { AstNodeType t = *p; string name; fa.GetTypeInfo( t, &name); r = r + "_" + name; } return r; }
AstNodePtr ArrayUseAccessFunction:: CreateArrayAccess( AstInterface& fa, const AstNodePtr& arr, const AstNodeList& index) { AstNodePtr r; if (prev != 0) r = prev->CreateArrayAccess(fa, arr, index); if (r == AST_NULL) { AstNodeList nindex; nindex.push_back(arr.get_ptr()); for (AstNodeList::const_iterator p = index.begin(); p != index.end(); ++p) nindex.push_back(*p); r = fa.CreateFunctionCall(funcname,nindex.begin(), nindex.end()) ; } return r; }
void DefUseChain<Node>:: build( AstInterface& fa, AstNodePtr root, AliasAnalysisInterface* alias, FunctionSideEffectInterface *f) { StmtVarAliasCollect defaultAlias; ReachingDefinitionAnalysis reachingDef; reachingDef(fa, root); if (alias == 0) { alias = &defaultAlias; AstNodePtr defn = fa.GetFunctionDefinition(root); assert(defn != AST_NULL); defaultAlias(fa, defn); } build(fa, reachingDef,*alias, f); }
void OperatorSideEffectDescriptor:: get_side_effect( AstInterface& fa, AstInterface::AstNodeList& args, CollectObject< AstNodePtr >& collect) { ReplaceParams paramMap( get_param_decl().get_params(), args); for (OperatorSideEffectDescriptor::const_iterator p = begin(); p != end(); ++p) { string varname = *p; AstNodePtr arg = paramMap.find(varname).get_ast(); if (arg != AST_NULL) { collect( arg); } else { AstNodePtr var = fa.CreateVarRef(varname); collect( var); } } }
void ReachingDefinitionBase:: collect_refs ( AstInterface& fa, const AstNodePtr& h, FunctionSideEffectInterface* a, AstInterface::AstNodeList* in) { for (AstInterface::AstNodeList::iterator p = in->begin(); p != in->end(); ++p) { AstNodePtr cur = *p; std::string varname; AstNodePtr scope; if (fa.IsVarRef( cur, 0, &varname, &scope)) add_ref(varname, scope, std::pair<AstNodePtr, AstNodePtr>(cur, AST_NULL) ); } ConstructReachingDefinitionBase collect(fa, *this); StmtSideEffectCollect op(a); op(fa, h, &collect); }
void ReachingDefinitionAnalysis:: FinalizeCFG( AstInterface& fa) { ReachingDefinitions in = g->get_empty_set(); for (AstInterface::AstNodeList::iterator p = pars.begin(); p != pars.end(); ++p) { AstNodePtr cur = *p; std::string name; AstNodePtr scope; if (fa.IsVarRef(cur, 0, &name, &scope)) g->add_def( in, name, scope, std::pair<AstNodePtr,AstNodePtr>(cur,AST_NULL)); } NodeIterator p = GetNodeIterator(); (*p)->finalize( fa, *g, a, &in); for ( ++p;!p.ReachEnd(); ++p) { (*p)->finalize(fa, *g, a); } }
std::string PtrAnal:: Get_VarName(AstInterface& fa, const AstNodePtr& rhs) { NameMap::const_iterator p = namemap.find(rhs.get_ptr()); if (p != namemap.end()) { VarRef cur = (*p).second; return cur.name; } std::string readname, res; AstNodePtr readscope; AstNodePtr lhs1, rhs1; bool readlhs; if (fa.IsVarRef(rhs, 0, &readname, &readscope)) { assert(readname != ""); res = Local_GetVarName(fa, readscope, readname); } else if (fa.IsConstant(rhs,&res,&readname)) { if (res == "string") { readname = Local_GetVarName(fa, rhs); Stmt stmt = allocate_x(readname); stmts_pushback(stmts,stmt); res= readname; } else res = Local_GetConstName(fa, readname); } else if (fa.IsUnaryOp(rhs) || fa.IsBinaryOp(rhs) || fa.IsFunctionCall(rhs)) { readname = Local_GetVarName(fa, rhs); ProcessExpression(fa, readname, rhs); res = readname; } else if (fa.IsAssignment(rhs,&lhs1,&rhs1,&readlhs)) { ProcessAssign(fa, lhs1, rhs1, readlhs); VarRef cur = namemap[lhs1.get_ptr()]; if (cur.name == "") { std::cerr << "does not have map for " << AstToString(lhs1) << " in " << AstToString(rhs) << "\n"; assert(0); } namemap[rhs.get_ptr()] = cur; res = cur.name; } else { std::cerr << "No name found for " << AstToString(rhs) << "\n"; assert(false); } if (res == "") { std::cerr << "No name found for " << AstToString(rhs) << "\n"; assert(false); } return res; }
void ReachingDefinitionAnalysis:: operator()( AstInterface& fa, const AstNodePtr& h, FunctionSideEffectInterface* anal) { assert( g == 0 && pars.size() == 0); AstNodePtr body = h; if (!fa.IsFunctionDefinition( h, 0, &pars, 0, &body)) ;//assert(false); ReachingDefinitionBase base; base.collect_refs( fa, body, anal, &pars); base.finalize(); g = new ReachingDefinitionGenerator( base); a = anal; if (DebugReachingDef()) std::cerr << "start building reaching definitions \n"; DataFlowAnalysis<ReachingDefNode, ReachingDefinitions>::operator()( fa, h); if (DebugReachingDef()) std::cerr << "finished building reaching definitions \n" << GraphToString(*this); }
void PtrAnal:: operator()( AstInterface& fa, const AstNodePtr& funcdef) { AstNodePtr body; AstInterface::AstNodeList params, outpars; std::string fname; if (!fa.IsFunctionDefinition(funcdef, &fname, ¶ms, &outpars, &body)) { std::cerr << "Error: analysis requires function definition as input instead of " << AstToString(funcdef) << std::endl; assert(false); } typedef std::pair<AstNodePtr,std::string> RefRec; std::list<RefRec> refs; fname = Local_GetVarName(fa, AST_NULL, fname); fdefined.push_back(fname); std::list<std::string> pnames, pres; for (AstInterface::AstNodeList::const_iterator p = params.begin(); p != params.end(); ++p) { std::string curname = Get_VarName(fa, *p); pnames.push_back(curname); refs.push_back(RefRec(*p, curname)); } pres.push_back( func_return_name(fname)); for (AstInterface::AstNodeList::const_iterator p2 = outpars.begin(); p2 != outpars.end(); ++p2) { std::string curname = Get_VarName(fa, *p2); pres.push_back(curname); refs.push_back(RefRec(*p2, curname)); } Stmt stmt_last = funcdef_x(fname, pnames, pres); stmts_pushback(stmts,stmt_last); for (std::list<RefRec>::const_iterator p3 = refs.begin(); p3 != refs.end(); ++p3) { RefRec cur = *p3; namemap[cur.first.get_ptr()] = PtrAnal::VarRef(stmt_last,cur.second); } ProcessAstTreeBase::operator()(fa, body); ControlFlowAnalysis(fa, body, stmt_last); }