// Copyright (c) 2014-2016 Dropbox, Inc. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "core/bst.h" #include #include #include #include #include #include "Python.h" #include "core/cfg.h" #include "runtime/types.h" namespace pyston { #ifdef DEBUG_LINE_NUMBERS int BST_stmt::next_lineno = 100000; BST_stmt::BST_stmt(BST_TYPE::BST_TYPE type) : type(type), lineno(++next_lineno) { // if (lineno == 100644) // raise(SIGTRAP); } #endif template static void visitVector(const std::vector& vec, BSTVisitor* v) { for (int i = 0; i < vec.size(); i++) { vec[i]->accept(v); } } static void visitCFG(CFG* cfg, BSTVisitor* v) { for (auto bb : cfg->blocks) for (auto e : bb->body) e->accept(v); } void BST_Assert::accept(BSTVisitor* v) { bool skip = v->visit_assert(this); if (skip) return; v->visit_vreg(&vreg_msg); } void BST_Assert::accept_stmt(StmtVisitor* v) { v->visit_assert(this); } void BST_CopyVReg::accept(BSTVisitor* v) { bool skip = v->visit_copyvreg(this); if (skip) return; v->visit_vreg(&vreg_src); v->visit_vreg(&vreg_dst, true); } void BST_CopyVReg::accept_stmt(StmtVisitor* v) { v->visit_copyvreg(this); } void BST_AugBinOp::accept(BSTVisitor* v) { bool skip = v->visit_augbinop(this); if (skip) return; v->visit_vreg(&vreg_left); v->visit_vreg(&vreg_right); v->visit_vreg(&vreg_dst, true); } void BST_AugBinOp::accept_stmt(StmtVisitor* v) { return v->visit_augbinop(this); } void BST_BinOp::accept(BSTVisitor* v) { bool skip = v->visit_binop(this); if (skip) return; v->visit_vreg(&vreg_left); v->visit_vreg(&vreg_right); v->visit_vreg(&vreg_dst, true); } void BST_BinOp::accept_stmt(StmtVisitor* v) { return v->visit_binop(this); } void BST_CallFunc::accept(BSTVisitor* v) { bool skip = v->visit_callfunc(this); if (skip) return; v->visit_vreg(&vreg_func); for (int i = 0; i < num_args + num_keywords; ++i) { v->visit_vreg(&elts[i]); } v->visit_vreg(&vreg_starargs); v->visit_vreg(&vreg_kwargs); v->visit_vreg(&vreg_dst, true); } void BST_CallFunc::accept_stmt(StmtVisitor* v) { return v->visit_callfunc(this); } void BST_CallAttr::accept(BSTVisitor* v) { bool skip = v->visit_callattr(this); if (skip) return; v->visit_vreg(&vreg_value); for (int i = 0; i < num_args + num_keywords; ++i) { v->visit_vreg(&elts[i]); } v->visit_vreg(&vreg_starargs); v->visit_vreg(&vreg_kwargs); v->visit_vreg(&vreg_dst, true); } void BST_CallAttr::accept_stmt(StmtVisitor* v) { return v->visit_callattr(this); } void BST_CallClsAttr::accept(BSTVisitor* v) { bool skip = v->visit_callclsattr(this); if (skip) return; v->visit_vreg(&vreg_value); for (int i = 0; i < num_args + num_keywords; ++i) { v->visit_vreg(&elts[i]); } v->visit_vreg(&vreg_starargs); v->visit_vreg(&vreg_kwargs); v->visit_vreg(&vreg_dst, true); } void BST_CallClsAttr::accept_stmt(StmtVisitor* v) { return v->visit_callclsattr(this); } void BST_Compare::accept(BSTVisitor* v) { bool skip = v->visit_compare(this); if (skip) return; v->visit_vreg(&vreg_left); v->visit_vreg(&vreg_comparator); v->visit_vreg(&vreg_dst, true); } void BST_Compare::accept_stmt(StmtVisitor* v) { return v->visit_compare(this); } void BST_ClassDef::accept(BSTVisitor* v) { bool skip = v->visit_classdef(this); if (skip) return; v->visit_vreg(&vreg_bases_tuple); for (int i = 0; i < num_decorator; ++i) { v->visit_vreg(&decorator[i]); } if (!v->skip_visit_child_cfg) visitCFG(this->code->source->cfg, v); } void BST_ClassDef::accept_stmt(StmtVisitor* v) { v->visit_classdef(this); } void BST_DeleteAttr::accept(BSTVisitor* v) { bool skip = v->visit_deleteattr(this); if (skip) return; v->visit_vreg(&vreg_value); } void BST_DeleteAttr::accept_stmt(StmtVisitor* v) { v->visit_deleteattr(this); } void BST_DeleteSub::accept(BSTVisitor* v) { bool skip = v->visit_deletesub(this); if (skip) return; v->visit_vreg(&vreg_value); v->visit_vreg(&vreg_slice); } void BST_DeleteSub::accept_stmt(StmtVisitor* v) { v->visit_deletesub(this); } void BST_DeleteSubSlice::accept(BSTVisitor* v) { bool skip = v->visit_deletesubslice(this); if (skip) return; v->visit_vreg(&vreg_value); v->visit_vreg(&vreg_lower); v->visit_vreg(&vreg_upper); } void BST_DeleteSubSlice::accept_stmt(StmtVisitor* v) { v->visit_deletesubslice(this); } void BST_DeleteName::accept(BSTVisitor* v) { bool skip = v->visit_deletename(this); if (skip) return; v->visit_vreg(&vreg); } void BST_DeleteName::accept_stmt(StmtVisitor* v) { v->visit_deletename(this); } void BST_Dict::accept(BSTVisitor* v) { bool skip = v->visit_dict(this); if (skip) return; v->visit_vreg(&vreg_dst, true); } void BST_Dict::accept_stmt(StmtVisitor* v) { return v->visit_dict(this); } void BST_Exec::accept(BSTVisitor* v) { bool skip = v->visit_exec(this); if (skip) return; v->visit_vreg(&vreg_body); v->visit_vreg(&vreg_globals); v->visit_vreg(&vreg_locals); } void BST_Exec::accept_stmt(StmtVisitor* v) { v->visit_exec(this); } void BST_FunctionDef::accept(BSTVisitor* v) { bool skip = v->visit_functiondef(this); if (skip) return; for (int i = 0; i < num_decorator + num_defaults; ++i) { v->visit_vreg(&elts[i]); } if (!v->skip_visit_child_cfg) visitCFG(code->source->cfg, v); } void BST_FunctionDef::accept_stmt(StmtVisitor* v) { v->visit_functiondef(this); } void BST_Invoke::accept(BSTVisitor* v) { bool skip = v->visit_invoke(this); if (skip) return; this->stmt->accept(v); } void BST_Invoke::accept_stmt(StmtVisitor* v) { return v->visit_invoke(this); } void BST_Landingpad::accept(BSTVisitor* v) { bool skip = v->visit_landingpad(this); if (skip) return; v->visit_vreg(&vreg_dst, true); } void BST_Landingpad::accept_stmt(StmtVisitor* v) { return v->visit_landingpad(this); } void BST_Locals::accept(BSTVisitor* v) { bool skip = v->visit_locals(this); if (skip) return; v->visit_vreg(&vreg_dst, true); } void BST_Locals::accept_stmt(StmtVisitor* v) { return v->visit_locals(this); } void BST_GetIter::accept(BSTVisitor* v) { bool skip = v->visit_getiter(this); if (skip) return; v->visit_vreg(&vreg_value); v->visit_vreg(&vreg_dst, true); } void BST_GetIter::accept_stmt(StmtVisitor* v) { return v->visit_getiter(this); } void BST_ImportFrom::accept(BSTVisitor* v) { bool skip = v->visit_importfrom(this); if (skip) return; v->visit_vreg(&vreg_module); v->visit_vreg(&vreg_name); v->visit_vreg(&vreg_dst, true); } void BST_ImportFrom::accept_stmt(StmtVisitor* v) { return v->visit_importfrom(this); } void BST_ImportName::accept(BSTVisitor* v) { bool skip = v->visit_importname(this); if (skip) return; v->visit_vreg(&vreg_from); v->visit_vreg(&vreg_name); v->visit_vreg(&vreg_dst, true); } void BST_ImportName::accept_stmt(StmtVisitor* v) { return v->visit_importname(this); } void BST_ImportStar::accept(BSTVisitor* v) { bool skip = v->visit_importstar(this); if (skip) return; v->visit_vreg(&vreg_name); v->visit_vreg(&vreg_dst, true); } void BST_ImportStar::accept_stmt(StmtVisitor* v) { return v->visit_importstar(this); } void BST_Nonzero::accept(BSTVisitor* v) { bool skip = v->visit_nonzero(this); if (skip) return; v->visit_vreg(&vreg_value); v->visit_vreg(&vreg_dst, true); } void BST_Nonzero::accept_stmt(StmtVisitor* v) { return v->visit_nonzero(this); } void BST_CheckExcMatch::accept(BSTVisitor* v) { bool skip = v->visit_checkexcmatch(this); if (skip) return; v->visit_vreg(&vreg_value); v->visit_vreg(&vreg_cls); v->visit_vreg(&vreg_dst, true); } void BST_CheckExcMatch::accept_stmt(StmtVisitor* v) { return v->visit_checkexcmatch(this); } void BST_SetExcInfo::accept(BSTVisitor* v) { bool skip = v->visit_setexcinfo(this); if (skip) return; v->visit_vreg(&vreg_type); v->visit_vreg(&vreg_value); v->visit_vreg(&vreg_traceback); } void BST_SetExcInfo::accept_stmt(StmtVisitor* v) { return v->visit_setexcinfo(this); } void BST_UncacheExcInfo::accept(BSTVisitor* v) { bool skip = v->visit_uncacheexcinfo(this); if (skip) return; } void BST_UncacheExcInfo::accept_stmt(StmtVisitor* v) { return v->visit_uncacheexcinfo(this); } void BST_HasNext::accept(BSTVisitor* v) { bool skip = v->visit_hasnext(this); if (skip) return; v->visit_vreg(&vreg_value); v->visit_vreg(&vreg_dst, true); } void BST_HasNext::accept_stmt(StmtVisitor* v) { return v->visit_hasnext(this); } void BST_PrintExpr::accept(BSTVisitor* v) { bool skip = v->visit_printexpr(this); if (skip) return; v->visit_vreg(&vreg_value); } void BST_PrintExpr::accept_stmt(StmtVisitor* v) { return v->visit_printexpr(this); } void BST_List::accept(BSTVisitor* v) { bool skip = v->visit_list(this); if (skip) return; for (int i = 0; i < num_elts; ++i) v->visit_vreg(&elts[i]); v->visit_vreg(&vreg_dst, true); } void BST_List::accept_stmt(StmtVisitor* v) { return v->visit_list(this); } void BST_LoadName::accept(BSTVisitor* v) { bool skip = v->visit_loadname(this); if (skip) return; if (lookup_type == ScopeInfo::VarScopeType::FAST || lookup_type == ScopeInfo::VarScopeType::CLOSURE) v->visit_vreg(&vreg); v->visit_vreg(&vreg_dst, true); } void BST_LoadName::accept_stmt(StmtVisitor* v) { v->visit_loadname(this); } void BST_LoadAttr::accept(BSTVisitor* v) { bool skip = v->visit_loadattr(this); if (skip) return; v->visit_vreg(&vreg_value); v->visit_vreg(&vreg_dst, true); } void BST_LoadAttr::accept_stmt(StmtVisitor* v) { v->visit_loadattr(this); } void BST_LoadSub::accept(BSTVisitor* v) { bool skip = v->visit_loadsub(this); if (skip) return; v->visit_vreg(&vreg_value); v->visit_vreg(&vreg_slice); v->visit_vreg(&vreg_dst, true); } void BST_LoadSub::accept_stmt(StmtVisitor* v) { v->visit_loadsub(this); } void BST_LoadSubSlice::accept(BSTVisitor* v) { bool skip = v->visit_loadsubslice(this); if (skip) return; v->visit_vreg(&vreg_value); v->visit_vreg(&vreg_lower); v->visit_vreg(&vreg_upper); v->visit_vreg(&vreg_dst, true); } void BST_LoadSubSlice::accept_stmt(StmtVisitor* v) { v->visit_loadsubslice(this); } void BST_StoreName::accept(BSTVisitor* v) { bool skip = v->visit_storename(this); if (skip) return; if (lookup_type == ScopeInfo::VarScopeType::FAST || lookup_type == ScopeInfo::VarScopeType::CLOSURE) v->visit_vreg(&vreg, true); v->visit_vreg(&vreg_value); } void BST_StoreName::accept_stmt(StmtVisitor* v) { v->visit_storename(this); } void BST_StoreAttr::accept(BSTVisitor* v) { bool skip = v->visit_storeattr(this); if (skip) return; v->visit_vreg(&vreg_value); v->visit_vreg(&vreg_target); } void BST_StoreAttr::accept_stmt(StmtVisitor* v) { v->visit_storeattr(this); } void BST_StoreSub::accept(BSTVisitor* v) { bool skip = v->visit_storesub(this); if (skip) return; v->visit_vreg(&vreg_target); v->visit_vreg(&vreg_slice); v->visit_vreg(&vreg_value); } void BST_StoreSub::accept_stmt(StmtVisitor* v) { v->visit_storesub(this); } void BST_StoreSubSlice::accept(BSTVisitor* v) { bool skip = v->visit_storesubslice(this); if (skip) return; v->visit_vreg(&vreg_target); v->visit_vreg(&vreg_lower); v->visit_vreg(&vreg_upper); v->visit_vreg(&vreg_value); } void BST_StoreSubSlice::accept_stmt(StmtVisitor* v) { v->visit_storesubslice(this); } void BST_Print::accept(BSTVisitor* v) { bool skip = v->visit_print(this); if (skip) return; v->visit_vreg(&vreg_dest); v->visit_vreg(&vreg_value); } void BST_Print::accept_stmt(StmtVisitor* v) { v->visit_print(this); } void BST_Raise::accept(BSTVisitor* v) { bool skip = v->visit_raise(this); if (skip) return; v->visit_vreg(&vreg_arg0); v->visit_vreg(&vreg_arg1); v->visit_vreg(&vreg_arg2); } void BST_Raise::accept_stmt(StmtVisitor* v) { v->visit_raise(this); } void BST_Repr::accept(BSTVisitor* v) { bool skip = v->visit_repr(this); if (skip) return; v->visit_vreg(&vreg_value); v->visit_vreg(&vreg_dst, true); } void BST_Repr::accept_stmt(StmtVisitor* v) { return v->visit_repr(this); } void BST_Return::accept(BSTVisitor* v) { bool skip = v->visit_return(this); if (skip) return; v->visit_vreg(&vreg_value); } void BST_Return::accept_stmt(StmtVisitor* v) { v->visit_return(this); } void BST_Set::accept(BSTVisitor* v) { bool skip = v->visit_set(this); if (skip) return; for (int i = 0; i < num_elts; ++i) { v->visit_vreg(&elts[i]); } v->visit_vreg(&vreg_dst, true); } void BST_Set::accept_stmt(StmtVisitor* v) { return v->visit_set(this); } void BST_Tuple::accept(BSTVisitor* v) { bool skip = v->visit_tuple(this); if (skip) return; for (int i = 0; i < num_elts; ++i) { v->visit_vreg(&elts[i]); } v->visit_vreg(&vreg_dst, true); } void BST_Tuple::accept_stmt(StmtVisitor* v) { return v->visit_tuple(this); } void BST_UnaryOp::accept(BSTVisitor* v) { bool skip = v->visit_unaryop(this); if (skip) return; v->visit_vreg(&vreg_operand); v->visit_vreg(&vreg_dst, true); } void BST_UnaryOp::accept_stmt(StmtVisitor* v) { return v->visit_unaryop(this); } void BST_UnpackIntoArray::accept(BSTVisitor* v) { bool skip = v->visit_unpackintoarray(this); if (skip) return; v->visit_vreg(&vreg_src); for (int i = 0; i < num_elts; ++i) { v->visit_vreg(&vreg_dst[i], true); } } void BST_UnpackIntoArray::accept_stmt(StmtVisitor* v) { return v->visit_unpackintoarray(this); } void BST_Yield::accept(BSTVisitor* v) { bool skip = v->visit_yield(this); if (skip) return; v->visit_vreg(&vreg_value); v->visit_vreg(&vreg_dst, true); } void BST_Yield::accept_stmt(StmtVisitor* v) { return v->visit_yield(this); } void BST_Branch::accept(BSTVisitor* v) { bool skip = v->visit_branch(this); if (skip) return; v->visit_vreg(&vreg_test); } void BST_Branch::accept_stmt(StmtVisitor* v) { v->visit_branch(this); } void BST_Jump::accept(BSTVisitor* v) { bool skip = v->visit_jump(this); if (skip) return; } void BST_Jump::accept_stmt(StmtVisitor* v) { v->visit_jump(this); } void BST_MakeFunction::accept(BSTVisitor* v) { bool skip = v->visit_makefunction(this); if (skip) return; function_def->accept(v); v->visit_vreg(&vreg_dst, true); } void BST_MakeFunction::accept_stmt(StmtVisitor* v) { return v->visit_makefunction(this); } void BST_MakeClass::accept(BSTVisitor* v) { bool skip = v->visit_makeclass(this); if (skip) return; class_def->accept(v); v->visit_vreg(&vreg_dst, true); } void BST_MakeClass::accept_stmt(StmtVisitor* v) { return v->visit_makeclass(this); } void BST_MakeSlice::accept(BSTVisitor* v) { bool skip = v->visit_makeslice(this); if (skip) return; v->visit_vreg(&vreg_lower); v->visit_vreg(&vreg_upper); v->visit_vreg(&vreg_step); v->visit_vreg(&vreg_dst, true); } void BST_MakeSlice::accept_stmt(StmtVisitor* v) { return v->visit_makeslice(this); } void print_bst(BST_stmt* bst, const CodeConstants& code_constants) { PrintVisitor v(code_constants, 0, llvm::outs()); bst->accept(&v); v.flush(); } void PrintVisitor::printIndent() { for (int i = 0; i < indent; i++) { stream << ' '; } } extern "C" BoxedString* repr(Box* obj); bool PrintVisitor::visit_vreg(int* vreg, bool is_dst) { if (*vreg != VREG_UNDEFINED) { stream << "%" << *vreg; if (*vreg < 0) stream << "|" << autoDecref(repr(code_constants.getConstant(*vreg)))->s() << "|"; } else stream << "%undef"; if (is_dst) stream << " = "; return true; } bool PrintVisitor::visit_assert(BST_Assert* node) { stream << "assert 0"; if (node->vreg_msg != VREG_UNDEFINED) { stream << ", "; visit_vreg(&node->vreg_msg); } return true; } bool PrintVisitor::visit_copyvreg(BST_CopyVReg* node) { visit_vreg(&node->vreg_dst, true); stream << "nokill "; visit_vreg(&node->vreg_src); return true; } bool PrintVisitor::visit_augbinop(BST_AugBinOp* node) { visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_left); stream << " =" << getOpSymbol(node->op_type) << " "; visit_vreg(&node->vreg_right); return true; } bool PrintVisitor::visit_binop(BST_BinOp* node) { visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_left); stream << " " << getOpSymbol(node->op_type) << " "; visit_vreg(&node->vreg_right); return true; } bool PrintVisitor::visit_callfunc(BST_CallFunc* node) { visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_func); stream << "("; bool prevarg = false; for (int i = 0; i < node->num_args + node->num_keywords; ++i) { if (prevarg) stream << ", "; visit_vreg(&node->elts[i]); prevarg = true; } if (node->vreg_starargs != VREG_UNDEFINED) { if (prevarg) stream << ", "; visit_vreg(&node->vreg_starargs); prevarg = true; } if (node->vreg_kwargs != VREG_UNDEFINED) { if (prevarg) stream << ", "; visit_vreg(&node->vreg_kwargs); prevarg = true; } stream << ")"; return true; } bool PrintVisitor::visit_callattr(BST_CallAttr* node) { visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_value); stream << "."; stream << node->attr.s(); stream << "("; bool prevarg = false; for (int i = 0; i < node->num_args + node->num_keywords; ++i) { if (prevarg) stream << ", "; visit_vreg(&node->elts[i]); prevarg = true; } if (node->vreg_starargs != VREG_UNDEFINED) { if (prevarg) stream << ", "; visit_vreg(&node->vreg_starargs); prevarg = true; } if (node->vreg_kwargs != VREG_UNDEFINED) { if (prevarg) stream << ", "; visit_vreg(&node->vreg_kwargs); prevarg = true; } stream << ")"; return true; } bool PrintVisitor::visit_callclsattr(BST_CallClsAttr* node) { visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_value); stream << ":"; stream << node->attr.s(); stream << "("; bool prevarg = false; for (int i = 0; i < node->num_args + node->num_keywords; ++i) { if (prevarg) stream << ", "; visit_vreg(&node->elts[i]); prevarg = true; } if (node->vreg_starargs != VREG_UNDEFINED) { if (prevarg) stream << ", "; visit_vreg(&node->vreg_starargs); prevarg = true; } if (node->vreg_kwargs != VREG_UNDEFINED) { if (prevarg) stream << ", "; visit_vreg(&node->vreg_kwargs); prevarg = true; } stream << ")"; return true; } bool PrintVisitor::visit_compare(BST_Compare* node) { visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_left); stream << " " << getOpSymbol(node->op) << " "; visit_vreg(&node->vreg_comparator); return true; } bool PrintVisitor::visit_classdef(BST_ClassDef* node) { for (int i = 0, n = node->num_decorator; i < n; i++) { stream << "@"; visit_vreg(&node->decorator[i]); stream << "\n"; printIndent(); } stream << "class " << node->name.s() << "("; visit_vreg(&node->vreg_bases_tuple); stream << ")"; indent += 4; stream << '\n'; printIndent(); stream << "..."; #if 0 for (int i = 0, n = node->body.size(); i < n; i++) { stream << "\n"; printIndent(); node->body[i]->accept(this); } #endif indent -= 4; return true; } bool PrintVisitor::visit_deletesub(BST_DeleteSub* node) { stream << "del "; visit_vreg(&node->vreg_value); stream << "["; visit_vreg(&node->vreg_slice); stream << "]"; return true; } bool PrintVisitor::visit_deletesubslice(BST_DeleteSubSlice* node) { stream << "del "; visit_vreg(&node->vreg_value); stream << "["; if (node->vreg_lower != VREG_UNDEFINED) visit_vreg(&node->vreg_lower); if (node->vreg_upper != VREG_UNDEFINED) { stream << ":"; visit_vreg(&node->vreg_upper); } stream << "]"; return true; } bool PrintVisitor::visit_deleteattr(BST_DeleteAttr* node) { stream << "del "; visit_vreg(&node->vreg_value); stream << '.'; stream << node->attr.s(); return true; } bool PrintVisitor::visit_deletename(BST_DeleteName* node) { stream << "del "; if (node->lookup_type == ScopeInfo::VarScopeType::FAST || node->lookup_type == ScopeInfo::VarScopeType::CLOSURE) { visit_vreg(&node->vreg); stream << " "; } stream << node->id.s(); return true; } bool PrintVisitor::visit_dict(BST_Dict* node) { visit_vreg(&node->vreg_dst, true); stream << "{}"; return true; } bool PrintVisitor::visit_exec(BST_Exec* node) { stream << "exec "; visit_vreg(&node->vreg_body); if (node->vreg_globals != VREG_UNDEFINED) { stream << " in "; visit_vreg(&node->vreg_globals); if (node->vreg_locals != VREG_UNDEFINED) { stream << ", "; visit_vreg(&node->vreg_locals); } } stream << "\n"; return true; } bool PrintVisitor::visit_functiondef(BST_FunctionDef* node) { for (int i = 0; i < node->num_decorator; ++i) { stream << "@"; visit_vreg(&node->elts[i]); stream << "\n"; printIndent(); } stream << "def "; if (node->name != InternedString()) stream << node->name.s(); else stream << ""; stream << "("; for (int i = 0; i < node->num_defaults; ++i) { if (i > 0) stream << ", "; stream << "="; visit_vreg(&node->elts[node->num_decorator + i]); } stream << ")"; indent += 4; stream << '\n'; printIndent(); stream << "..."; #if 0 for (int i = 0; i < node->body.size(); i++) { stream << "\n"; printIndent(); node->body[i]->accept(this); } #endif indent -= 4; return true; } bool PrintVisitor::visit_invoke(BST_Invoke* node) { stream << "invoke " << node->normal_dest->idx << " " << node->exc_dest->idx << ": "; node->stmt->accept(this); return true; } bool PrintVisitor::visit_landingpad(BST_Landingpad* node) { visit_vreg(&node->vreg_dst, true); stream << ":LANDINGPAD()"; return true; } bool PrintVisitor::visit_locals(BST_Locals* node) { visit_vreg(&node->vreg_dst, true); stream << ":LOCALS()"; return true; } bool PrintVisitor::visit_getiter(BST_GetIter* node) { visit_vreg(&node->vreg_dst, true); stream << ":GET_ITER("; visit_vreg(&node->vreg_value); stream << ")"; return true; } bool PrintVisitor::visit_importfrom(BST_ImportFrom* node) { visit_vreg(&node->vreg_dst, true); stream << ":IMPORT_FROM("; visit_vreg(&node->vreg_module); stream << ", "; visit_vreg(&node->vreg_name); stream << ")"; return true; } bool PrintVisitor::visit_importname(BST_ImportName* node) { visit_vreg(&node->vreg_dst, true); stream << ":IMPORT_NAME("; visit_vreg(&node->vreg_from); stream << ", "; visit_vreg(&node->vreg_name); stream << ", " << node->level << ")"; return true; } bool PrintVisitor::visit_importstar(BST_ImportStar* node) { visit_vreg(&node->vreg_dst, true); stream << ":IMPORT_STAR("; visit_vreg(&node->vreg_name); stream << ")"; return true; } bool PrintVisitor::visit_nonzero(BST_Nonzero* node) { visit_vreg(&node->vreg_dst, true); stream << ":NONZERO("; visit_vreg(&node->vreg_value); stream << ")"; return true; } bool PrintVisitor::visit_checkexcmatch(BST_CheckExcMatch* node) { visit_vreg(&node->vreg_dst, true); stream << ":CHECK_EXC_MATCH("; visit_vreg(&node->vreg_value); stream << ", "; visit_vreg(&node->vreg_cls); stream << ")"; return true; } bool PrintVisitor::visit_setexcinfo(BST_SetExcInfo* node) { stream << ":SET_EXC_INFO("; visit_vreg(&node->vreg_value); stream << ", "; visit_vreg(&node->vreg_type); stream << ", "; visit_vreg(&node->vreg_traceback); stream << ")"; return true; } bool PrintVisitor::visit_uncacheexcinfo(BST_UncacheExcInfo* node) { stream << ":UNCACHE_EXC_INFO()"; return true; } bool PrintVisitor::visit_hasnext(BST_HasNext* node) { visit_vreg(&node->vreg_dst, true); stream << ":HAS_NEXT("; visit_vreg(&node->vreg_value); stream << ")"; return true; } bool PrintVisitor::visit_printexpr(BST_PrintExpr* node) { stream << ":PRINT_EXPR("; visit_vreg(&node->vreg_value); stream << ")"; return true; } bool PrintVisitor::visit_list(BST_List* node) { visit_vreg(&node->vreg_dst, true); stream << "["; for (int i = 0, n = node->num_elts; i < n; ++i) { if (i > 0) stream << ", "; visit_vreg(&node->elts[i]); } stream << "]"; return true; } bool PrintVisitor::visit_print(BST_Print* node) { stream << "print "; if (node->vreg_dest != VREG_UNDEFINED) { stream << ">>"; visit_vreg(&node->vreg_dest); stream << ", "; } if (node->vreg_value != VREG_UNDEFINED) visit_vreg(&node->vreg_value); if (!node->nl) stream << ","; return true; } bool PrintVisitor::visit_raise(BST_Raise* node) { stream << "raise"; if (node->vreg_arg0 != VREG_UNDEFINED) { stream << " "; visit_vreg(&node->vreg_arg0); } if (node->vreg_arg1 != VREG_UNDEFINED) { stream << ", "; visit_vreg(&node->vreg_arg1); } if (node->vreg_arg2 != VREG_UNDEFINED) { stream << ", "; visit_vreg(&node->vreg_arg2); } return true; } bool PrintVisitor::visit_repr(BST_Repr* node) { visit_vreg(&node->vreg_dst, true); stream << "`"; visit_vreg(&node->vreg_value); stream << "`"; return true; } bool PrintVisitor::visit_return(BST_Return* node) { stream << "return "; if (node->vreg_value != VREG_UNDEFINED) visit_vreg(&node->vreg_value); return true; } bool PrintVisitor::visit_set(BST_Set* node) { visit_vreg(&node->vreg_dst, true); // An empty set literal is not writeable in Python (it's a dictionary), // but we sometimes generate it (ex in set comprehension lowering). // Just to make it clear when printing, print empty set literals as "SET{}". if (!node->num_elts) stream << "SET"; stream << "{"; bool first = true; for (int i = 0; i < node->num_elts; ++i) { if (!first) stream << ", "; first = false; visit_vreg(&node->num_elts[&i]); } stream << "}"; return true; } bool PrintVisitor::visit_makeslice(BST_MakeSlice* node) { visit_vreg(&node->vreg_dst, true); stream << "("; if (node->vreg_lower != VREG_UNDEFINED) visit_vreg(&node->vreg_lower); if (node->vreg_upper != VREG_UNDEFINED || node->vreg_step != VREG_UNDEFINED) stream << ':'; if (node->vreg_upper != VREG_UNDEFINED) visit_vreg(&node->vreg_upper); if (node->vreg_step != VREG_UNDEFINED) { stream << ':'; visit_vreg(&node->vreg_step); } stream << ")"; return true; } bool PrintVisitor::visit_loadname(BST_LoadName* node) { visit_vreg(&node->vreg_dst, true); if (node->lookup_type == ScopeInfo::VarScopeType::FAST || node->lookup_type == ScopeInfo::VarScopeType::CLOSURE) { visit_vreg(&node->vreg); stream << " "; } stream << node->id.s(); return true; } bool PrintVisitor::visit_loadattr(BST_LoadAttr* node) { visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_value); stream << (node->clsonly ? ':' : '.') << node->attr.s(); return true; } bool PrintVisitor::visit_loadsub(BST_LoadSub* node) { visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_value); stream << "["; visit_vreg(&node->vreg_slice); stream << "]"; return true; } bool PrintVisitor::visit_loadsubslice(BST_LoadSubSlice* node) { visit_vreg(&node->vreg_dst, true); visit_vreg(&node->vreg_value); stream << "["; if (node->vreg_lower != VREG_UNDEFINED) visit_vreg(&node->vreg_lower); if (node->vreg_upper != VREG_UNDEFINED) { stream << ":"; visit_vreg(&node->vreg_upper); } stream << "]"; return true; } bool PrintVisitor::visit_storename(BST_StoreName* node) { if (node->lookup_type == ScopeInfo::VarScopeType::FAST || node->lookup_type == ScopeInfo::VarScopeType::CLOSURE) { visit_vreg(&node->vreg); stream << " "; } stream << node->id.s(); stream << " = "; visit_vreg(&node->vreg_value); return true; } bool PrintVisitor::visit_storeattr(BST_StoreAttr* node) { visit_vreg(&node->vreg_target); stream << "." << node->attr.s() << " = "; visit_vreg(&node->vreg_value); return true; } bool PrintVisitor::visit_storesub(BST_StoreSub* node) { visit_vreg(&node->vreg_target); stream << "["; visit_vreg(&node->vreg_slice); stream << "] = "; visit_vreg(&node->vreg_value); return true; } bool PrintVisitor::visit_storesubslice(BST_StoreSubSlice* node) { visit_vreg(&node->vreg_target); stream << "["; if (node->vreg_lower != VREG_UNDEFINED) visit_vreg(&node->vreg_lower); if (node->vreg_upper != VREG_UNDEFINED) { stream << ":"; visit_vreg(&node->vreg_upper); } stream << "] = "; visit_vreg(&node->vreg_value); return true; } bool PrintVisitor::visit_tuple(BST_Tuple* node) { visit_vreg(&node->vreg_dst, true); stream << "("; int n = node->num_elts; for (int i = 0; i < n; i++) { if (i) stream << ", "; visit_vreg(&node->elts[i]); } if (n == 1) stream << ","; stream << ")"; return true; } bool PrintVisitor::visit_unaryop(BST_UnaryOp* node) { visit_vreg(&node->vreg_dst, true); switch (node->op_type) { case AST_TYPE::Invert: stream << "~"; break; case AST_TYPE::Not: stream << "not "; break; case AST_TYPE::UAdd: stream << "+"; break; case AST_TYPE::USub: stream << "-"; break; default: RELEASE_ASSERT(0, "%s", getOpName(node->op_type)->c_str()); break; } stream << "("; // node->operand->accept(this); visit_vreg(&node->vreg_operand); stream << ")"; return true; } bool PrintVisitor::visit_unpackintoarray(BST_UnpackIntoArray* node) { stream << "("; for (int i = 0; i < node->num_elts; ++i) { visit_vreg(&node->vreg_dst[i]); if (i + 1 < node->num_elts || i == 0) stream << ", "; } stream << ") = "; visit_vreg(&node->vreg_src); return true; } bool PrintVisitor::visit_yield(BST_Yield* node) { visit_vreg(&node->vreg_dst, true); stream << "yield "; if (node->vreg_value != VREG_UNDEFINED) visit_vreg(&node->vreg_value); return true; } bool PrintVisitor::visit_branch(BST_Branch* node) { stream << "if "; visit_vreg(&node->vreg_test); stream << " goto " << node->iftrue->idx << " else goto " << node->iffalse->idx; return true; } bool PrintVisitor::visit_jump(BST_Jump* node) { stream << "goto " << node->target->idx; return true; } bool PrintVisitor::visit_makefunction(BST_MakeFunction* node) { visit_vreg(&node->vreg_dst, true); stream << "make_"; return false; } bool PrintVisitor::visit_makeclass(BST_MakeClass* node) { visit_vreg(&node->vreg_dst, true); stream << "make_"; return false; } namespace { class FlattenVisitor : public BSTVisitor { private: std::vector* output; bool expand_scopes; public: FlattenVisitor(std::vector* output, bool expand_scopes) : BSTVisitor(false /* visit child CFG */), output(output), expand_scopes(expand_scopes) { assert(expand_scopes && "not sure if this works properly"); } virtual bool visit_vreg(int* vreg, bool is_dst = false) { return false; } virtual bool visit_assert(BST_Assert* node) { output->push_back(node); return false; } virtual bool visit_copyvreg(BST_CopyVReg* node) { output->push_back(node); return false; } virtual bool visit_augbinop(BST_AugBinOp* node) { output->push_back(node); return false; } virtual bool visit_binop(BST_BinOp* node) { output->push_back(node); return false; } virtual bool visit_callfunc(BST_CallFunc* node) { output->push_back(node); return false; } virtual bool visit_callattr(BST_CallAttr* node) { output->push_back(node); return false; } virtual bool visit_callclsattr(BST_CallClsAttr* node) { output->push_back(node); return false; } virtual bool visit_classdef(BST_ClassDef* node) { output->push_back(node); return !expand_scopes; } virtual bool visit_compare(BST_Compare* node) { output->push_back(node); return false; } virtual bool visit_deletesub(BST_DeleteSub* node) { output->push_back(node); return false; } virtual bool visit_deletesubslice(BST_DeleteSubSlice* node) { output->push_back(node); return false; } virtual bool visit_deleteattr(BST_DeleteAttr* node) { output->push_back(node); return false; } virtual bool visit_deletename(BST_DeleteName* node) { output->push_back(node); return false; } virtual bool visit_dict(BST_Dict* node) { output->push_back(node); return false; } virtual bool visit_exec(BST_Exec* node) { output->push_back(node); return false; } virtual bool visit_functiondef(BST_FunctionDef* node) { output->push_back(node); return !expand_scopes; } virtual bool visit_invoke(BST_Invoke* node) { output->push_back(node); return false; } virtual bool visit_list(BST_List* node) { output->push_back(node); return false; } virtual bool visit_print(BST_Print* node) { output->push_back(node); return false; } virtual bool visit_raise(BST_Raise* node) { output->push_back(node); return false; } virtual bool visit_repr(BST_Repr* node) { output->push_back(node); return false; } virtual bool visit_return(BST_Return* node) { output->push_back(node); return false; } virtual bool visit_set(BST_Set* node) { output->push_back(node); return false; } virtual bool visit_tuple(BST_Tuple* node) { output->push_back(node); return false; } virtual bool visit_unaryop(BST_UnaryOp* node) { output->push_back(node); return false; } virtual bool visit_unpackintoarray(BST_UnpackIntoArray* node) { output->push_back(node); return false; } virtual bool visit_yield(BST_Yield* node) { output->push_back(node); return false; } virtual bool visit_branch(BST_Branch* node) { output->push_back(node); return false; } virtual bool visit_jump(BST_Jump* node) { output->push_back(node); return false; } virtual bool visit_makeclass(BST_MakeClass* node) { output->push_back(node); return false; } virtual bool visit_makefunction(BST_MakeFunction* node) { output->push_back(node); return false; } virtual bool visit_makeslice(BST_MakeSlice* node) { output->push_back(node); return false; } virtual bool visit_landingpad(BST_Landingpad* node) { output->push_back(node); return false; } virtual bool visit_locals(BST_Locals* node) { output->push_back(node); return false; } virtual bool visit_getiter(BST_GetIter* node) { output->push_back(node); return false; } virtual bool visit_importfrom(BST_ImportFrom* node) { output->push_back(node); return false; } virtual bool visit_importname(BST_ImportName* node) { output->push_back(node); return false; } virtual bool visit_importstar(BST_ImportStar* node) { output->push_back(node); return false; } virtual bool visit_nonzero(BST_Nonzero* node) { output->push_back(node); return false; } virtual bool visit_checkexcmatch(BST_CheckExcMatch* node) { output->push_back(node); return false; } virtual bool visit_setexcinfo(BST_SetExcInfo* node) { output->push_back(node); return false; } virtual bool visit_uncacheexcinfo(BST_UncacheExcInfo* node) { output->push_back(node); return false; } virtual bool visit_hasnext(BST_HasNext* node) { output->push_back(node); return false; } virtual bool visit_printexpr(BST_PrintExpr* node) { output->push_back(node); return false; } virtual bool visit_loadname(BST_LoadName* node) { output->push_back(node); return false; } virtual bool visit_loadattr(BST_LoadAttr* node) { output->push_back(node); return false; } virtual bool visit_loadsub(BST_LoadSub* node) { output->push_back(node); return false; } virtual bool visit_loadsubslice(BST_LoadSubSlice* node) { output->push_back(node); return false; } virtual bool visit_storename(BST_StoreName* node) { output->push_back(node); return false; } virtual bool visit_storesub(BST_StoreSub* node) { output->push_back(node); return false; } virtual bool visit_storesubslice(BST_StoreSubSlice* node) { output->push_back(node); return false; } virtual bool visit_storeattr(BST_StoreAttr* node) { output->push_back(node); return false; } }; } void flatten(llvm::ArrayRef roots, std::vector& output, bool expand_scopes) { FlattenVisitor visitor(&output, expand_scopes); for (int i = 0; i < roots.size(); i++) { roots[i]->accept(&visitor); } } }