Commit 763cc656 authored by Kevin Modzelewski's avatar Kevin Modzelewski

CFG changes

parent 5e76425d
...@@ -425,7 +425,6 @@ ARGS ?= ...@@ -425,7 +425,6 @@ ARGS ?=
ifneq ($(BR),) ifneq ($(BR),)
override GDB_CMDS := --ex "break $(BR)" $(GDB_CMDS) override GDB_CMDS := --ex "break $(BR)" $(GDB_CMDS)
endif endif
$(call add_unittest,gc)
$(call add_unittest,analysis) $(call add_unittest,analysis)
......
...@@ -73,6 +73,13 @@ bool containsYield(AST* ast) { ...@@ -73,6 +73,13 @@ bool containsYield(AST* ast) {
return visitor.contains_yield; return visitor.contains_yield;
} }
bool containsYield(llvm::ArrayRef<AST_stmt*> body) {
for (auto e : body)
if (containsYield(e))
return true;
return false;
}
// TODO // TODO
// Combine this with the below? Basically the same logic with different string types... // Combine this with the below? Basically the same logic with different string types...
// Also should this go in this file? // Also should this go in this file?
......
...@@ -159,7 +159,9 @@ public: ...@@ -159,7 +159,9 @@ public:
bool areGlobalsFromModule() { return globals_from_module; } bool areGlobalsFromModule() { return globals_from_module; }
}; };
class AST_stmt;
bool containsYield(AST* ast); bool containsYield(AST* ast);
bool containsYield(llvm::ArrayRef<AST_stmt*> ast);
class BoxedString; class BoxedString;
BoxedString* mangleNameBoxedString(BoxedString* id, BoxedString* private_name); BoxedString* mangleNameBoxedString(BoxedString* id, BoxedString* private_name);
......
...@@ -58,24 +58,14 @@ void BoxedCode::addVersion(CompiledFunction* compiled) { ...@@ -58,24 +58,14 @@ void BoxedCode::addVersion(CompiledFunction* compiled) {
} }
} }
SourceInfo::SourceInfo(BoxedModule* m, ScopingResults scoping, FutureFlags future_flags, AST* ast) SourceInfo::SourceInfo(BoxedModule* m, ScopingResults scoping, FutureFlags future_flags, int ast_type,
: parent_module(m), scoping(std::move(scoping)), cfg(NULL), future_flags(future_flags), ast_type(ast->type) { bool is_generator)
: parent_module(m),
switch (ast_type) { scoping(std::move(scoping)),
case AST_TYPE::ClassDef: cfg(NULL),
case AST_TYPE::Module: future_flags(future_flags),
case AST_TYPE::Expression: is_generator(is_generator),
case AST_TYPE::Suite: ast_type(ast_type) {
is_generator = false;
break;
case AST_TYPE::FunctionDef:
case AST_TYPE::Lambda:
is_generator = containsYield(ast);
break;
default:
RELEASE_ASSERT(0, "Unknown type: %d", ast_type);
break;
}
} }
SourceInfo::~SourceInfo() { SourceInfo::~SourceInfo() {
......
...@@ -21,12 +21,12 @@ ...@@ -21,12 +21,12 @@
#include "llvm/IR/Module.h" #include "llvm/IR/Module.h"
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
#include "core/bst.h"
#include "codegen/codegen.h" #include "codegen/codegen.h"
#include "codegen/gcbuilder.h" #include "codegen/gcbuilder.h"
#include "codegen/irgen.h" #include "codegen/irgen.h"
#include "codegen/irgen/util.h" #include "codegen/irgen/util.h"
#include "codegen/patchpoints.h" #include "codegen/patchpoints.h"
#include "core/bst.h"
#include "core/options.h" #include "core/options.h"
#include "core/types.h" #include "core/types.h"
#include "runtime/float.h" #include "runtime/float.h"
......
...@@ -724,6 +724,7 @@ public: ...@@ -724,6 +724,7 @@ public:
switch (mod->kind) { switch (mod->kind) {
case Module_kind: { case Module_kind: {
AST_Module* rtn = new AST_Module(llvm::make_unique<InternedStringPool>()); AST_Module* rtn = new AST_Module(llvm::make_unique<InternedStringPool>());
rtn->lineno = 1;
assert(!this->pool); assert(!this->pool);
this->pool = rtn->interned_strings.get(); this->pool = rtn->interned_strings.get();
convertAll<stmt_ty>(mod->v.Module.body, rtn->body); convertAll<stmt_ty>(mod->v.Module.body, rtn->body);
...@@ -732,6 +733,7 @@ public: ...@@ -732,6 +733,7 @@ public:
case Interactive_kind: { case Interactive_kind: {
this->interactive = 1; this->interactive = 1;
AST_Module* rtn = new AST_Module(llvm::make_unique<InternedStringPool>()); AST_Module* rtn = new AST_Module(llvm::make_unique<InternedStringPool>());
rtn->lineno = 1;
assert(!this->pool); assert(!this->pool);
this->pool = rtn->interned_strings.get(); this->pool = rtn->interned_strings.get();
convertAll<stmt_ty>(mod->v.Interactive.body, rtn->body); convertAll<stmt_ty>(mod->v.Interactive.body, rtn->body);
...@@ -739,6 +741,7 @@ public: ...@@ -739,6 +741,7 @@ public:
} }
case Expression_kind: { case Expression_kind: {
AST_Expression* rtn = new AST_Expression(llvm::make_unique<InternedStringPool>()); AST_Expression* rtn = new AST_Expression(llvm::make_unique<InternedStringPool>());
rtn->lineno = 1;
this->pool = rtn->interned_strings.get(); this->pool = rtn->interned_strings.get();
// instead of storing the expression inside the AST node we convert it directly to a return statement // instead of storing the expression inside the AST node we convert it directly to a return statement
......
...@@ -231,10 +231,8 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) { ...@@ -231,10 +231,8 @@ void compileAndRunModule(AST_Module* m, BoxedModule* bm) {
RELEASE_ASSERT(fn, ""); RELEASE_ASSERT(fn, "");
FutureFlags future_flags = getFutureFlags(m->body, fn); FutureFlags future_flags = getFutureFlags(m->body, fn);
computeAllCFGs(m, /* globals_from_module */ true, future_flags, autoDecref(boxString(fn)), bm); BoxedCode* code = computeAllCFGs(m, /* globals_from_module */ true, future_flags, autoDecref(boxString(fn)), bm);
AUTO_DECREF(code);
BoxedCode* code = m->getCode();
assert(code);
static BoxedString* doc_str = getStaticString("__doc__"); static BoxedString* doc_str = getStaticString("__doc__");
bm->setattr(doc_str, code->_doc, NULL); bm->setattr(doc_str, code->_doc, NULL);
...@@ -279,8 +277,7 @@ static BoxedCode* compileForEvalOrExec(AST* source, llvm::ArrayRef<AST_stmt*> bo ...@@ -279,8 +277,7 @@ static BoxedCode* compileForEvalOrExec(AST* source, llvm::ArrayRef<AST_stmt*> bo
flags->cf_flags = future_flags; flags->cf_flags = future_flags;
} }
computeAllCFGs(source, /* globals_from_module */ false, future_flags, fn, getCurrentModule()); return computeAllCFGs(source, /* globals_from_module */ false, future_flags, fn, getCurrentModule());
return source->getCode();
} }
static BoxedCode* compileExec(AST_Module* parsedModule, BoxedString* fn, PyCompilerFlags* flags) { static BoxedCode* compileExec(AST_Module* parsedModule, BoxedString* fn, PyCompilerFlags* flags) {
...@@ -319,7 +316,7 @@ extern "C" PyCodeObject* PyAST_Compile(struct _mod* _mod, const char* filename, ...@@ -319,7 +316,7 @@ extern "C" PyCodeObject* PyAST_Compile(struct _mod* _mod, const char* filename,
return NULL; return NULL;
} }
return (PyCodeObject*)incref(code); return (PyCodeObject*)code;
} catch (ExcInfo e) { } catch (ExcInfo e) {
setCAPIException(e); setCAPIException(e);
return NULL; return NULL;
......
...@@ -2138,22 +2138,6 @@ void flatten(AST_expr* root, std::vector<AST*>& output, bool expand_scopes) { ...@@ -2138,22 +2138,6 @@ void flatten(AST_expr* root, std::vector<AST*>& output, bool expand_scopes) {
root->accept(&visitor); root->accept(&visitor);
} }
BoxedCode*& AST::getCode() {
switch (this->type) {
case AST_TYPE::Expression:
return ast_cast<AST_Expression>(this)->code;
case AST_TYPE::FunctionDef:
return ast_cast<AST_FunctionDef>(this)->code;
case AST_TYPE::ClassDef:
return ast_cast<AST_ClassDef>(this)->code;
case AST_TYPE::Module:
return ast_cast<AST_Module>(this)->code;
default:
break;
}
RELEASE_ASSERT(0, "%d", this->type);
}
InternedStringPool& AST::getStringpool() { InternedStringPool& AST::getStringpool() {
switch (this->type) { switch (this->type) {
case AST_TYPE::Expression: case AST_TYPE::Expression:
...@@ -2181,11 +2165,12 @@ llvm::ArrayRef<AST_stmt*> AST::getBody() { ...@@ -2181,11 +2165,12 @@ llvm::ArrayRef<AST_stmt*> AST::getBody() {
}; };
} }
Box* AST::getDocString() { Box* getDocString(llvm::ArrayRef<AST_stmt*> body) {
auto body = this->getBody();
if (body.size() > 0 && body[0]->type == AST_TYPE::Expr if (body.size() > 0 && body[0]->type == AST_TYPE::Expr
&& static_cast<AST_Expr*>(body[0])->value->type == AST_TYPE::Str) { && static_cast<AST_Expr*>(body[0])->value->type == AST_TYPE::Str) {
return boxString(static_cast<AST_Str*>(static_cast<AST_Expr*>(body[0])->value)->str_data); auto expr = static_cast<AST_Expr*>(body[0]);
auto str = static_cast<AST_Str*>(expr->value);
return boxString(str->str_data);
} }
return incref(Py_None); return incref(Py_None);
......
...@@ -190,12 +190,11 @@ public: ...@@ -190,12 +190,11 @@ public:
// These could be virtual methods, but since we already keep track of the type use a switch statement // These could be virtual methods, but since we already keep track of the type use a switch statement
// like everywhere else. // like everywhere else.
BoxedCode*& getCode();
InternedStringPool& getStringpool(); InternedStringPool& getStringpool();
llvm::ArrayRef<AST_stmt*> getBody(); llvm::ArrayRef<AST_stmt*> getBody();
Box* getDocString();
BORROWED(BoxedString*) getName() noexcept; BORROWED(BoxedString*) getName() noexcept;
}; };
Box* getDocString(llvm::ArrayRef<AST_stmt*> body);
class AST_expr : public AST { class AST_expr : public AST {
public: public:
...@@ -398,8 +397,6 @@ public: ...@@ -398,8 +397,6 @@ public:
std::vector<AST_stmt*> body; std::vector<AST_stmt*> body;
InternedString name; InternedString name;
BoxedCode* code;
AST_ClassDef() : AST_stmt(AST_TYPE::ClassDef) {} AST_ClassDef() : AST_stmt(AST_TYPE::ClassDef) {}
static const AST_TYPE::AST_TYPE TYPE = AST_TYPE::ClassDef; static const AST_TYPE::AST_TYPE TYPE = AST_TYPE::ClassDef;
...@@ -506,8 +503,6 @@ public: ...@@ -506,8 +503,6 @@ public:
// this should be an expr but we convert it into a AST_Return(AST_expr) to make the code simpler // this should be an expr but we convert it into a AST_Return(AST_expr) to make the code simpler
AST_stmt* body; AST_stmt* body;
BoxedCode* code;
virtual void accept(ASTVisitor* v); virtual void accept(ASTVisitor* v);
AST_Expression(std::unique_ptr<InternedStringPool> interned_strings) AST_Expression(std::unique_ptr<InternedStringPool> interned_strings)
...@@ -547,8 +542,6 @@ public: ...@@ -547,8 +542,6 @@ public:
InternedString name; // if the name is not set this is a lambda InternedString name; // if the name is not set this is a lambda
AST_arguments* args; AST_arguments* args;
BoxedCode* code;
virtual void accept(ASTVisitor* v); virtual void accept(ASTVisitor* v);
virtual void accept_stmt(ASTStmtVisitor* v); virtual void accept_stmt(ASTStmtVisitor* v);
...@@ -698,8 +691,6 @@ public: ...@@ -698,8 +691,6 @@ public:
// no lineno, col_offset attributes // no lineno, col_offset attributes
std::vector<AST_stmt*> body; std::vector<AST_stmt*> body;
BoxedCode* code;
virtual void accept(ASTVisitor* v); virtual void accept(ASTVisitor* v);
AST_Module(std::unique_ptr<InternedStringPool> interned_strings) AST_Module(std::unique_ptr<InternedStringPool> interned_strings)
......
...@@ -43,6 +43,12 @@ template <class T> static void visitVector(const std::vector<T*>& vec, BSTVisito ...@@ -43,6 +43,12 @@ template <class T> static void visitVector(const std::vector<T*>& vec, BSTVisito
} }
} }
static void visitCFG(CFG* cfg, BSTVisitor* v) {
for (auto bb : cfg->blocks)
for (auto e : bb->body)
e->accept(v);
}
void BST_alias::accept(BSTVisitor* v) { void BST_alias::accept(BSTVisitor* v) {
bool skip = v->visit_alias(this); bool skip = v->visit_alias(this);
if (skip) if (skip)
...@@ -218,7 +224,7 @@ void BST_ClassDef::accept(BSTVisitor* v) { ...@@ -218,7 +224,7 @@ void BST_ClassDef::accept(BSTVisitor* v) {
visitVector(this->bases, v); visitVector(this->bases, v);
visitVector(this->decorator_list, v); visitVector(this->decorator_list, v);
visitVector(this->body, v); visitCFG(this->code->source->cfg, v);
} }
void BST_ClassDef::accept_stmt(StmtVisitor* v) { void BST_ClassDef::accept_stmt(StmtVisitor* v) {
...@@ -364,7 +370,7 @@ void BST_FunctionDef::accept(BSTVisitor* v) { ...@@ -364,7 +370,7 @@ void BST_FunctionDef::accept(BSTVisitor* v) {
visitVector(decorator_list, v); visitVector(decorator_list, v);
args->accept(v); args->accept(v);
visitVector(body, v); visitCFG(code->source->cfg, v);
} }
void BST_FunctionDef::accept_stmt(StmtVisitor* v) { void BST_FunctionDef::accept_stmt(StmtVisitor* v) {
...@@ -1084,11 +1090,16 @@ bool PrintVisitor::visit_classdef(BST_ClassDef* node) { ...@@ -1084,11 +1090,16 @@ bool PrintVisitor::visit_classdef(BST_ClassDef* node) {
stream << ")"; stream << ")";
indent += 4; indent += 4;
stream << '\n';
printIndent();
stream << "...";
#if 0
for (int i = 0, n = node->body.size(); i < n; i++) { for (int i = 0, n = node->body.size(); i < n; i++) {
stream << "\n"; stream << "\n";
printIndent(); printIndent();
node->body[i]->accept(this); node->body[i]->accept(this);
} }
#endif
indent -= 4; indent -= 4;
return true; return true;
...@@ -1215,11 +1226,16 @@ bool PrintVisitor::visit_functiondef(BST_FunctionDef* node) { ...@@ -1215,11 +1226,16 @@ bool PrintVisitor::visit_functiondef(BST_FunctionDef* node) {
stream << ")"; stream << ")";
indent += 4; indent += 4;
stream << '\n';
printIndent();
stream << "...";
#if 0
for (int i = 0; i < node->body.size(); i++) { for (int i = 0; i < node->body.size(); i++) {
stream << "\n"; stream << "\n";
printIndent(); printIndent();
node->body[i]->accept(this); node->body[i]->accept(this);
} }
#endif
indent -= 4; indent -= 4;
return true; return true;
} }
......
...@@ -398,7 +398,6 @@ public: ...@@ -398,7 +398,6 @@ public:
virtual void accept_stmt(StmtVisitor* v); virtual void accept_stmt(StmtVisitor* v);
std::vector<BST_expr*> bases, decorator_list; std::vector<BST_expr*> bases, decorator_list;
std::vector<BST_stmt*> body;
InternedString name; InternedString name;
BoxedCode* code; BoxedCode* code;
...@@ -512,8 +511,6 @@ public: ...@@ -512,8 +511,6 @@ public:
// this should be an expr but we convert it into a BST_Return(BST_expr) to make the code simpler // this should be an expr but we convert it into a BST_Return(BST_expr) to make the code simpler
BST_stmt* body; BST_stmt* body;
BoxedCode* code;
virtual void accept(BSTVisitor* v); virtual void accept(BSTVisitor* v);
BST_Expression(std::unique_ptr<InternedStringPool> interned_strings) BST_Expression(std::unique_ptr<InternedStringPool> interned_strings)
...@@ -549,7 +546,6 @@ public: ...@@ -549,7 +546,6 @@ public:
class BST_FunctionDef : public BST_stmt { class BST_FunctionDef : public BST_stmt {
public: public:
std::vector<BST_stmt*> body;
std::vector<BST_expr*> decorator_list; std::vector<BST_expr*> decorator_list;
InternedString name; // if the name is not set this is a lambda InternedString name; // if the name is not set this is a lambda
BST_arguments* args; BST_arguments* args;
...@@ -711,8 +707,6 @@ public: ...@@ -711,8 +707,6 @@ public:
// no lineno, col_offset attributes // no lineno, col_offset attributes
std::vector<BST_stmt*> body; std::vector<BST_stmt*> body;
BoxedCode* code;
virtual void accept(BSTVisitor* v); virtual void accept(BSTVisitor* v);
BST_Module(std::unique_ptr<InternedStringPool> interned_strings) BST_Module(std::unique_ptr<InternedStringPool> interned_strings)
......
...@@ -34,39 +34,50 @@ ...@@ -34,39 +34,50 @@
namespace pyston { namespace pyston {
ParamNames::ParamNames(AST* ast, InternedStringPool& pool) void fillScopingInfo(BST_Name* node, ScopeInfo* scope_info) {
node->lookup_type = scope_info->getScopeTypeOfName(node->id);
if (node->lookup_type == ScopeInfo::VarScopeType::CLOSURE)
node->closure_offset = scope_info->getClosureOffset(node->id);
else if (node->lookup_type == ScopeInfo::VarScopeType::DEREF)
node->deref_info = scope_info->getDerefInfo(node->id);
assert(node->lookup_type != ScopeInfo::VarScopeType::UNKNOWN);
}
ParamNames::ParamNames(AST_arguments* arguments, InternedStringPool& pool)
: all_args_contains_names(1), takes_param_names(1), has_vararg_name(0), has_kwarg_name(0) { : all_args_contains_names(1), takes_param_names(1), has_vararg_name(0), has_kwarg_name(0) {
if (ast->type == AST_TYPE::Module || ast->type == AST_TYPE::ClassDef || ast->type == AST_TYPE::Expression if (!arguments)
|| ast->type == AST_TYPE::Suite) { return;
} else if (ast->type == AST_TYPE::FunctionDef || ast->type == AST_TYPE::Lambda) {
AST_arguments* arguments = ast->type == AST_TYPE::FunctionDef ? ast_cast<AST_FunctionDef>(ast)->args for (int i = 0; i < arguments->args.size(); i++) {
: ast_cast<AST_Lambda>(ast)->args; AST_expr* arg = arguments->args[i];
for (int i = 0; i < arguments->args.size(); i++) { if (arg->type == AST_TYPE::Name) {
AST_expr* arg = arguments->args[i]; AST_Name* name = ast_cast<AST_Name>(arg);
if (arg->type == AST_TYPE::Name) { BST_Name* new_name = new BST_Name(name->id, name->ctx_type, name->lineno, name->col_offset);
AST_Name* name = ast_cast<AST_Name>(arg); all_args.emplace_back(new_name);
all_args.emplace_back(name); } else {
} else { InternedString dot_arg_name = pool.get("." + std::to_string(i));
InternedString dot_arg_name = pool.get("." + std::to_string(i)); auto new_name = new BST_Name(dot_arg_name, AST_TYPE::Param, arg->lineno, arg->col_offset);
auto new_name = new AST_Name(dot_arg_name, AST_TYPE::Param, arg->lineno, arg->col_offset); new_name->lookup_type = ScopeInfo::VarScopeType::FAST;
new_name->lookup_type = ScopeInfo::VarScopeType::FAST; all_args.emplace_back(new_name);
all_args.emplace_back(new_name);
}
} }
}
auto vararg_name = arguments->vararg; auto vararg_name = arguments->vararg;
if (vararg_name) { if (vararg_name) {
has_vararg_name = 1; has_vararg_name = 1;
all_args.emplace_back(vararg_name); BST_Name* new_name
} = new BST_Name(vararg_name->id, vararg_name->ctx_type, vararg_name->lineno, vararg_name->col_offset);
all_args.emplace_back(new_name);
}
auto kwarg_name = arguments->kwarg; auto kwarg_name = arguments->kwarg;
if (kwarg_name) { if (kwarg_name) {
has_kwarg_name = 1; has_kwarg_name = 1;
all_args.emplace_back(kwarg_name); BST_Name* new_name
} = new BST_Name(kwarg_name->id, kwarg_name->ctx_type, kwarg_name->lineno, kwarg_name->col_offset);
} else { all_args.emplace_back(new_name);
RELEASE_ASSERT(0, "%d", ast->type);
} }
} }
...@@ -104,7 +115,7 @@ std::vector<const char*> ParamNames::allArgsAsStr() const { ...@@ -104,7 +115,7 @@ std::vector<const char*> ParamNames::allArgsAsStr() const {
// getLastLineno takes the block itself, and getLastLinenoSub takes an entry // getLastLineno takes the block itself, and getLastLinenoSub takes an entry
// inside the block. This is important because if there is a functiondef as the last // inside the block. This is important because if there is a functiondef as the last
// statement in a block, we should not look inside it. // statement in a block, we should not look inside it.
int getLastLinenoSub(AST* ast) { static int getLastLinenoSub(AST* ast) {
if (ast->type == AST_TYPE::TryExcept) { if (ast->type == AST_TYPE::TryExcept) {
auto te = ast_cast<AST_TryExcept>(ast); auto te = ast_cast<AST_TryExcept>(ast);
if (!te->orelse.empty()) if (!te->orelse.empty())
...@@ -134,6 +145,12 @@ int getLastLinenoSub(AST* ast) { ...@@ -134,6 +145,12 @@ int getLastLinenoSub(AST* ast) {
return ast->lineno; return ast->lineno;
} }
static int getLastLineno(llvm::ArrayRef<AST_stmt*> body, int default_lineno) {
if (body.size() == 0)
return default_lineno;
return getLastLinenoSub(body.back());
}
#if 0
int getLastLineno(AST* ast) { int getLastLineno(AST* ast) {
switch (ast->type) { switch (ast->type) {
case AST_TYPE::Lambda: { case AST_TYPE::Lambda: {
...@@ -168,6 +185,7 @@ int getLastLineno(AST* ast) { ...@@ -168,6 +185,7 @@ int getLastLineno(AST* ast) {
RELEASE_ASSERT(0, "%d", ast->type); RELEASE_ASSERT(0, "%d", ast->type);
} }
} }
#endif
void CFGBlock::connectTo(CFGBlock* successor, bool allow_backedge) { void CFGBlock::connectTo(CFGBlock* successor, bool allow_backedge) {
assert(successors.size() <= 1); assert(successors.size() <= 1);
...@@ -215,17 +233,6 @@ void CFGBlock::print(llvm::raw_ostream& stream) { ...@@ -215,17 +233,6 @@ void CFGBlock::print(llvm::raw_ostream& stream) {
} }
} }
void fillScopingInfo(AST_Name* node, ScopeInfo* scope_info) {
node->lookup_type = scope_info->getScopeTypeOfName(node->id);
if (node->lookup_type == ScopeInfo::VarScopeType::CLOSURE)
node->closure_offset = scope_info->getClosureOffset(node->id);
else if (node->lookup_type == ScopeInfo::VarScopeType::DEREF)
node->deref_info = scope_info->getDerefInfo(node->id);
assert(node->lookup_type != ScopeInfo::VarScopeType::UNKNOWN);
}
static const std::string RETURN_NAME("#rtnval"); static const std::string RETURN_NAME("#rtnval");
// The various reasons why a `finally' block (or similar, eg. a `with' exit block) might get entered. // The various reasons why a `finally' block (or similar, eg. a `with' exit block) might get entered.
...@@ -260,10 +267,12 @@ public: ...@@ -260,10 +267,12 @@ public:
// For example if we convert a generator expression into a function, the new function // For example if we convert a generator expression into a function, the new function
// should get passed as 'ast', but the original generator expression should get // should get passed as 'ast', but the original generator expression should get
// passed as 'orig_node' so that the scoping analysis can know what we're talking about. // passed as 'orig_node' so that the scoping analysis can know what we're talking about.
void runRecursively(AST* ast, AST_arguments* args, AST* orig_node); BoxedCode* runRecursively(llvm::ArrayRef<AST_stmt*> body, BoxedString* name, int lineno, AST_arguments* args,
AST* orig_node);
}; };
static CFG* computeCFG(AST* ast, BoxedString* fn, SourceInfo* source, const ParamNames& param_names, ScopeInfo* scoping, static CFG* computeCFG(llvm::ArrayRef<AST_stmt*> body, AST_TYPE::AST_TYPE ast_type, int lineno, AST_arguments* args,
BoxedString* filename, SourceInfo* source, const ParamNames& param_names, ScopeInfo* scoping,
ModuleCFGProcessor* cfgizer); ModuleCFGProcessor* cfgizer);
// A class that crawls the AST of a single function and computes the CFG // A class that crawls the AST of a single function and computes the CFG
...@@ -361,8 +370,9 @@ private: ...@@ -361,8 +370,9 @@ private:
unsigned int next_var_index = 0; unsigned int next_var_index = 0;
friend CFG* computeCFG(AST* ast, BoxedString* fn, SourceInfo* source, const ParamNames& param_names, ScopeInfo*, friend CFG* computeCFG(llvm::ArrayRef<AST_stmt*> body, AST_TYPE::AST_TYPE ast_type, int lineno, AST_arguments* args,
ModuleCFGProcessor*); BoxedString* filename, SourceInfo* source, const ParamNames& param_names, ScopeInfo* scoping,
ModuleCFGProcessor* cfgizer);
public: public:
CFGVisitor(BoxedString* filename, SourceInfo* source, InternedStringPool& stringpool, ScopeInfo* scoping, CFGVisitor(BoxedString* filename, SourceInfo* source, InternedStringPool& stringpool, ScopeInfo* scoping,
...@@ -395,19 +405,28 @@ private: ...@@ -395,19 +405,28 @@ private:
return stringpool.get(std::move(name)); return stringpool.get(std::move(name));
} }
AST_Name* makeName(InternedString id, AST_TYPE::AST_TYPE ctx_type, int lineno, int col_offset = 0, AST_Name* makeASTName(InternedString id, AST_TYPE::AST_TYPE ctx_type, int lineno, int col_offset = 0) {
bool is_kill = false) {
AST_Name* name = new AST_Name(id, ctx_type, lineno, col_offset); AST_Name* name = new AST_Name(id, ctx_type, lineno, col_offset);
return name;
}
BST_Name* makeName(InternedString id, AST_TYPE::AST_TYPE ctx_type, int lineno, int col_offset = 0,
bool is_kill = false) {
BST_Name* name = new BST_Name(id, ctx_type, lineno, col_offset);
fillScopingInfo(name, scoping); fillScopingInfo(name, scoping);
name->is_kill = is_kill; name->is_kill = is_kill;
return name; return name;
} }
AST_Name* makeLoad(InternedString id, AST* node, bool is_kill = false) { BST_Name* makeLoad(InternedString id, AST* node, bool is_kill = false) {
return makeName(id, AST_TYPE::Load, node->lineno, 0, is_kill); return makeName(id, AST_TYPE::Load, node->lineno, 0, is_kill);
} }
AST_Name* makeLoad(InternedString id, int lineno, bool is_kill = false) { BST_Name* makeLoad(InternedString id, BST* node, bool is_kill = false) {
return makeName(id, AST_TYPE::Load, node->lineno, 0, is_kill);
}
BST_Name* makeLoad(InternedString id, int lineno, bool is_kill = false) {
return makeName(id, AST_TYPE::Load, lineno, 0, is_kill); return makeName(id, AST_TYPE::Load, lineno, 0, is_kill);
} }
...@@ -423,7 +442,7 @@ private: ...@@ -423,7 +442,7 @@ private:
void popContinuation() { continuations.pop_back(); } void popContinuation() { continuations.pop_back(); }
void doReturn(AST_expr* value) { void doReturn(BST_expr* value) {
assert(value); assert(value);
assert(curblock); assert(curblock);
...@@ -440,7 +459,7 @@ private: ...@@ -440,7 +459,7 @@ private:
} }
} }
AST_Return* node = new AST_Return(); BST_Return* node = new BST_Return();
node->value = value; node->value = value;
node->col_offset = value->col_offset; node->col_offset = value->col_offset;
node->lineno = value->lineno; node->lineno = value->lineno;
...@@ -482,8 +501,8 @@ private: ...@@ -482,8 +501,8 @@ private:
raiseSyntaxError("'break' outside loop", value->lineno, value->col_offset, filename->s(), "", true); raiseSyntaxError("'break' outside loop", value->lineno, value->col_offset, filename->s(), "", true);
} }
AST_expr* callNonzero(AST_expr* e) { BST_expr* callNonzero(BST_expr* e) {
AST_LangPrimitive* call = new AST_LangPrimitive(AST_LangPrimitive::NONZERO); BST_LangPrimitive* call = new BST_LangPrimitive(BST_LangPrimitive::NONZERO);
call->args.push_back(e); call->args.push_back(e);
call->lineno = e->lineno; call->lineno = e->lineno;
call->col_offset = e->col_offset; call->col_offset = e->col_offset;
...@@ -498,17 +517,49 @@ private: ...@@ -498,17 +517,49 @@ private:
return makeLoad(name, e, true); return makeLoad(name, e, true);
} }
AST_Name* remapName(AST_Name* name) { BST_Name* remapName(AST_Name* name) {
fillScopingInfo(name, scoping); if (!name)
return name; return NULL;
BST_Name* rtn = new BST_Name(name->id, name->ctx_type, name->lineno, name->col_offset);
fillScopingInfo(rtn, scoping);
return rtn;
}
BST_Num* remapNum(AST_Num* num) {
auto r = new BST_Num();
r->lineno = num->lineno;
r->col_offset = num->col_offset;
r->num_type = num->num_type;
switch (r->num_type) {
case AST_Num::INT:
r->n_int = num->n_int;
break;
case AST_Num::FLOAT:
case AST_Num::COMPLEX:
r->n_float = num->n_float;
break;
case AST_Num::LONG:
r->n_long = num->n_long;
break;
}
return r;
} }
AST_expr* applyComprehensionCall(AST_ListComp* node, AST_Name* name) { BST_Str* remapStr(AST_Str* str) {
AST_expr* elt = remapExpr(node->elt); auto r = new BST_Str();
r->str_data = str->str_data;
r->str_type = str->str_type;
r->lineno = str->lineno;
r->col_offset = str->col_offset;
return r;
}
BST_expr* applyComprehensionCall(AST_ListComp* node, BST_Name* name) {
BST_expr* elt = remapExpr(node->elt);
return makeCall(makeLoadAttribute(name, internString("append"), true), elt); return makeCall(makeLoadAttribute(name, internString("append"), true), elt);
} }
template <typename ResultASTType, typename CompType> AST_expr* remapComprehension(CompType* node) { template <typename ResultASTType, typename CompType> BST_expr* remapComprehension(CompType* node) {
assert(curblock); assert(curblock);
InternedString rtn_name = nodeName(); InternedString rtn_name = nodeName();
...@@ -525,14 +576,14 @@ private: ...@@ -525,14 +576,14 @@ private:
AST_comprehension* c = node->generators[i]; AST_comprehension* c = node->generators[i];
bool is_innermost = (i == n - 1); bool is_innermost = (i == n - 1);
AST_expr* remapped_iter = remapExpr(c->iter); BST_expr* remapped_iter = remapExpr(c->iter);
AST_LangPrimitive* iter_call = new AST_LangPrimitive(AST_LangPrimitive::GET_ITER); BST_LangPrimitive* iter_call = new BST_LangPrimitive(BST_LangPrimitive::GET_ITER);
iter_call->args.push_back(remapped_iter); iter_call->args.push_back(remapped_iter);
iter_call->lineno = c->target->lineno; // Not sure if this should be c->target or c->iter iter_call->lineno = c->target->lineno; // Not sure if this should be c->target or c->iter
InternedString iter_name = nodeName("lc_iter", i); InternedString iter_name = nodeName("lc_iter", i);
pushAssign(iter_name, iter_call); pushAssign(iter_name, iter_call);
AST_expr* next_attr = makeLoadAttribute(makeLoad(iter_name, node), internString("next"), true); BST_expr* next_attr = makeLoadAttribute(makeLoad(iter_name, node), internString("next"), true);
CFGBlock* test_block = cfg->addBlock(); CFGBlock* test_block = cfg->addBlock();
test_block->info = "comprehension_test"; test_block->info = "comprehension_test";
...@@ -540,10 +591,10 @@ private: ...@@ -540,10 +591,10 @@ private:
pushJump(test_block); pushJump(test_block);
curblock = test_block; curblock = test_block;
AST_LangPrimitive* test_call = new AST_LangPrimitive(AST_LangPrimitive::HASNEXT); BST_LangPrimitive* test_call = new BST_LangPrimitive(BST_LangPrimitive::HASNEXT);
test_call->args.push_back(makeName(iter_name, AST_TYPE::Load, node->lineno)); test_call->args.push_back(makeName(iter_name, AST_TYPE::Load, node->lineno));
test_call->lineno = c->target->lineno; test_call->lineno = c->target->lineno;
AST_expr* test = remapExpr(test_call); BST_expr* test = wrap(test_call);
CFGBlock* body_block = cfg->addBlock(); CFGBlock* body_block = cfg->addBlock();
body_block->info = "comprehension_body"; body_block->info = "comprehension_body";
...@@ -552,7 +603,7 @@ private: ...@@ -552,7 +603,7 @@ private:
exit_blocks.push_back(exit_block); exit_blocks.push_back(exit_block);
// printf("Body block for comp %d is %d\n", i, body_block->idx); // printf("Body block for comp %d is %d\n", i, body_block->idx);
AST_Branch* br = new AST_Branch(); BST_Branch* br = new BST_Branch();
br->col_offset = node->col_offset; br->col_offset = node->col_offset;
br->lineno = node->lineno; br->lineno = node->lineno;
br->test = test; br->test = test;
...@@ -568,8 +619,8 @@ private: ...@@ -568,8 +619,8 @@ private:
pushAssign(c->target, makeLoad(next_name, node, true)); pushAssign(c->target, makeLoad(next_name, node, true));
for (AST_expr* if_condition : c->ifs) { for (AST_expr* if_condition : c->ifs) {
AST_expr* remapped = callNonzero(remapExpr(if_condition)); BST_expr* remapped = callNonzero(remapExpr(if_condition));
AST_Branch* br = new AST_Branch(); BST_Branch* br = new BST_Branch();
br->test = remapped; br->test = remapped;
push_back(br); push_back(br);
...@@ -626,15 +677,15 @@ private: ...@@ -626,15 +677,15 @@ private:
return makeLoad(rtn_name, node, /* is_kill */ true); return makeLoad(rtn_name, node, /* is_kill */ true);
} }
AST_expr* makeNum(int n) { BST_expr* makeNum(int n) {
AST_Num* node = new AST_Num(); BST_Num* node = new BST_Num();
node->num_type = AST_Num::INT; node->num_type = AST_Num::INT;
node->n_int = n; node->n_int = n;
return node; return node;
} }
void pushJump(CFGBlock* target, bool allow_backedge = false, int lineno = 0) { void pushJump(CFGBlock* target, bool allow_backedge = false, int lineno = 0) {
AST_Jump* rtn = new AST_Jump(); BST_Jump* rtn = new BST_Jump();
rtn->target = target; rtn->target = target;
rtn->lineno = lineno; rtn->lineno = lineno;
...@@ -644,8 +695,8 @@ private: ...@@ -644,8 +695,8 @@ private:
} }
// NB. can generate blocks, because callNonzero can // NB. can generate blocks, because callNonzero can
AST_Branch* makeBranch(AST_expr* test) { BST_Branch* makeBranch(BST_expr* test) {
AST_Branch* rtn = new AST_Branch(); BST_Branch* rtn = new BST_Branch();
rtn->test = callNonzero(test); rtn->test = callNonzero(test);
rtn->col_offset = test->col_offset; rtn->col_offset = test->col_offset;
rtn->lineno = test->lineno; rtn->lineno = test->lineno;
...@@ -655,9 +706,9 @@ private: ...@@ -655,9 +706,9 @@ private:
// NB. this can (but usually doesn't) generate new blocks, which is why we require `iftrue' and `iffalse' to be // NB. this can (but usually doesn't) generate new blocks, which is why we require `iftrue' and `iffalse' to be
// deferred, to avoid heisenbugs. of course, this doesn't allow these branches to be backedges, but that hasn't yet // deferred, to avoid heisenbugs. of course, this doesn't allow these branches to be backedges, but that hasn't yet
// been necessary. // been necessary.
void pushBranch(AST_expr* test, CFGBlock* iftrue, CFGBlock* iffalse) { void pushBranch(BST_expr* test, CFGBlock* iftrue, CFGBlock* iffalse) {
assert(iftrue->idx == -1 && iffalse->idx == -1); assert(iftrue->idx == -1 && iffalse->idx == -1);
AST_Branch* branch = makeBranch(test); BST_Branch* branch = makeBranch(test);
branch->iftrue = iftrue; branch->iftrue = iftrue;
branch->iffalse = iffalse; branch->iffalse = iffalse;
curblock->connectTo(iftrue); curblock->connectTo(iftrue);
...@@ -668,7 +719,7 @@ private: ...@@ -668,7 +719,7 @@ private:
void pushReraise(int lineno, InternedString exc_type_name, InternedString exc_value_name, void pushReraise(int lineno, InternedString exc_type_name, InternedString exc_value_name,
InternedString exc_traceback_name) { InternedString exc_traceback_name) {
auto raise = new AST_Raise(); auto raise = new BST_Raise();
raise->lineno = lineno; raise->lineno = lineno;
raise->arg0 = makeLoad(exc_type_name, lineno, true); raise->arg0 = makeLoad(exc_type_name, lineno, true);
raise->arg1 = makeLoad(exc_value_name, lineno, true); raise->arg1 = makeLoad(exc_value_name, lineno, true);
...@@ -677,7 +728,7 @@ private: ...@@ -677,7 +728,7 @@ private:
curblock = nullptr; curblock = nullptr;
} }
AST_expr* makeLoadAttribute(AST_expr* base, InternedString name, bool clsonly) { AST_expr* makeASTLoadAttribute(AST_expr* base, InternedString name, bool clsonly) {
AST_expr* rtn; AST_expr* rtn;
if (clsonly) { if (clsonly) {
AST_ClsAttribute* attr = new AST_ClsAttribute(); AST_ClsAttribute* attr = new AST_ClsAttribute();
...@@ -696,7 +747,26 @@ private: ...@@ -696,7 +747,26 @@ private:
return rtn; return rtn;
} }
AST_Call* makeCall(AST_expr* func) { BST_expr* makeLoadAttribute(BST_expr* base, InternedString name, bool clsonly) {
BST_expr* rtn;
if (clsonly) {
BST_ClsAttribute* attr = new BST_ClsAttribute();
attr->value = base;
attr->attr = name;
rtn = attr;
} else {
BST_Attribute* attr = new BST_Attribute();
attr->ctx_type = AST_TYPE::Load;
attr->value = base;
attr->attr = name;
rtn = attr;
}
rtn->col_offset = base->col_offset;
rtn->lineno = base->lineno;
return rtn;
}
AST_Call* makeASTCall(AST_expr* func) {
AST_Call* call = new AST_Call(); AST_Call* call = new AST_Call();
call->starargs = NULL; call->starargs = NULL;
call->kwargs = NULL; call->kwargs = NULL;
...@@ -706,20 +776,43 @@ private: ...@@ -706,20 +776,43 @@ private:
return call; return call;
} }
AST_Call* makeCall(AST_expr* func, AST_expr* arg0) { AST_Call* makeASTCall(AST_expr* func, AST_expr* arg0) {
auto call = makeASTCall(func);
call->args.push_back(arg0);
return call;
}
AST_Call* makeASTCall(AST_expr* func, AST_expr* arg0, AST_expr* arg1) {
auto call = makeASTCall(func);
call->args.push_back(arg0);
call->args.push_back(arg1);
return call;
}
BST_Call* makeCall(BST_expr* func) {
BST_Call* call = new BST_Call();
call->starargs = NULL;
call->kwargs = NULL;
call->func = func;
call->col_offset = func->col_offset;
call->lineno = func->lineno;
return call;
}
BST_Call* makeCall(BST_expr* func, BST_expr* arg0) {
auto call = makeCall(func); auto call = makeCall(func);
call->args.push_back(arg0); call->args.push_back(arg0);
return call; return call;
} }
AST_Call* makeCall(AST_expr* func, AST_expr* arg0, AST_expr* arg1) { BST_Call* makeCall(BST_expr* func, BST_expr* arg0, BST_expr* arg1) {
auto call = makeCall(func); auto call = makeCall(func);
call->args.push_back(arg0); call->args.push_back(arg0);
call->args.push_back(arg1); call->args.push_back(arg1);
return call; return call;
} }
AST_Call* makeCall(AST_expr* func, AST_expr* arg0, AST_expr* arg1, AST_expr* arg2) { BST_Call* makeCall(BST_expr* func, BST_expr* arg0, BST_expr* arg1, BST_expr* arg2) {
auto call = makeCall(func); auto call = makeCall(func);
call->args.push_back(arg0); call->args.push_back(arg0);
call->args.push_back(arg1); call->args.push_back(arg1);
...@@ -727,24 +820,24 @@ private: ...@@ -727,24 +820,24 @@ private:
return call; return call;
} }
AST_Compare* makeCompare(AST_TYPE::AST_TYPE oper, AST_expr* left, AST_expr* right) { BST_Compare* makeCompare(AST_TYPE::AST_TYPE oper, BST_expr* left, BST_expr* right) {
auto compare = new AST_Compare(); auto compare = new BST_Compare();
compare->ops.push_back(AST_TYPE::Eq); compare->ops.push_back(oper);
compare->left = left; compare->left = left;
compare->comparators.push_back(right); compare->comparators.push_back(right);
return compare; return compare;
} }
AST_Index* makeIndex(AST_expr* value) { BST_Index* makeIndex(BST_expr* value) {
auto index = new AST_Index(); auto index = new BST_Index();
index->value = value; index->value = value;
index->lineno = value->lineno; index->lineno = value->lineno;
index->col_offset = value->col_offset; index->col_offset = value->col_offset;
return index; return index;
} }
AST_Subscript* makeSubscript(AST_TYPE::AST_TYPE ctx_type, AST_expr* value, AST_slice* slice) { BST_Subscript* makeSubscript(AST_TYPE::AST_TYPE ctx_type, BST_expr* value, BST_slice* slice) {
auto subscript = new AST_Subscript(); auto subscript = new BST_Subscript();
subscript->ctx_type = ctx_type; subscript->ctx_type = ctx_type;
subscript->value = value; subscript->value = value;
subscript->slice = slice; subscript->slice = slice;
...@@ -753,20 +846,33 @@ private: ...@@ -753,20 +846,33 @@ private:
return subscript; return subscript;
} }
void pushAssign(AST_expr* target, AST_expr* val) { // void pushAssign(BST_expr* target, BST_expr* val);
AST_Assign* assign = new AST_Assign(); // We need this both on asts (ex assigning to the element name in a for loop), and
// for bsts (desugaring an augassign)
// TODO: we should get rid of this bst one, or at least not call it the same thing?
void pushAssign(BST_expr* target, BST_expr* val) {
BST_Assign* assign = new BST_Assign();
assign->value = val;
assign->col_offset = val->col_offset;
assign->lineno = val->lineno;
assign->targets.push_back(target);
push_back(assign);
}
void pushAssign(AST_expr* target, BST_expr* val) {
BST_Assign* assign = new BST_Assign();
assign->value = val; assign->value = val;
assign->col_offset = val->col_offset; assign->col_offset = val->col_offset;
assign->lineno = val->lineno; assign->lineno = val->lineno;
if (target->type == AST_TYPE::Name) { if (target->type == AST_TYPE::Name) {
assign->targets.push_back(remapName(ast_cast<AST_Name>(target))); assign->targets.push_back(makeName(ast_cast<AST_Name>(target)->id, AST_TYPE::Store, val->lineno, 0));
push_back(assign); push_back(assign);
} else if (target->type == AST_TYPE::Subscript) { } else if (target->type == AST_TYPE::Subscript) {
AST_Subscript* s = ast_cast<AST_Subscript>(target); AST_Subscript* s = ast_cast<AST_Subscript>(target);
assert(s->ctx_type == AST_TYPE::Store); assert(s->ctx_type == AST_TYPE::Store);
AST_Subscript* s_target = new AST_Subscript(); BST_Subscript* s_target = new BST_Subscript();
s_target->value = remapExpr(s->value); s_target->value = remapExpr(s->value);
s_target->slice = remapSlice(s->slice); s_target->slice = remapSlice(s->slice);
s_target->ctx_type = AST_TYPE::Store; s_target->ctx_type = AST_TYPE::Store;
...@@ -779,7 +885,7 @@ private: ...@@ -779,7 +885,7 @@ private:
AST_Attribute* a = ast_cast<AST_Attribute>(target); AST_Attribute* a = ast_cast<AST_Attribute>(target);
assert(a->ctx_type == AST_TYPE::Store); assert(a->ctx_type == AST_TYPE::Store);
AST_Attribute* a_target = new AST_Attribute(); BST_Attribute* a_target = new BST_Attribute();
a_target->value = remapExpr(a->value); a_target->value = remapExpr(a->value);
a_target->attr = scoping->mangleName(a->attr); a_target->attr = scoping->mangleName(a->attr);
a_target->ctx_type = AST_TYPE::Store; a_target->ctx_type = AST_TYPE::Store;
...@@ -800,7 +906,7 @@ private: ...@@ -800,7 +906,7 @@ private:
elts = &_t->elts; elts = &_t->elts;
} }
AST_Tuple* new_target = new AST_Tuple(); BST_Tuple* new_target = new BST_Tuple();
new_target->ctx_type = AST_TYPE::Store; new_target->ctx_type = AST_TYPE::Store;
new_target->lineno = target->lineno; new_target->lineno = target->lineno;
new_target->col_offset = target->col_offset; new_target->col_offset = target->col_offset;
...@@ -821,13 +927,16 @@ private: ...@@ -821,13 +927,16 @@ private:
} }
} }
void pushAssign(InternedString id, AST_expr* val) { void pushAssign(InternedString id, BST_expr* val) {
assert(val); BST_Assign* assign = new BST_Assign();
AST_expr* name = makeName(id, AST_TYPE::Store, val->lineno, 0); assign->value = val;
pushAssign(name, val); assign->col_offset = val->col_offset;
assign->lineno = val->lineno;
assign->targets.push_back(makeName(id, AST_TYPE::Store, val->lineno, 0));
push_back(assign);
} }
AST_stmt* makeExpr(AST_expr* expr) { AST_stmt* makeASTExpr(AST_expr* expr) {
AST_Expr* stmt = new AST_Expr(); AST_Expr* stmt = new AST_Expr();
stmt->value = expr; stmt->value = expr;
stmt->lineno = expr->lineno; stmt->lineno = expr->lineno;
...@@ -835,6 +944,14 @@ private: ...@@ -835,6 +944,14 @@ private:
return stmt; return stmt;
} }
BST_stmt* makeExpr(BST_expr* expr) {
BST_Expr* stmt = new BST_Expr();
stmt->value = expr;
stmt->lineno = expr->lineno;
stmt->col_offset = expr->col_offset;
return stmt;
}
InternedString nodeName() { return createUniqueName("#"); } InternedString nodeName() { return createUniqueName("#"); }
InternedString nodeName(llvm::StringRef suffix) { return createUniqueName(llvm::Twine("#") + suffix + "_"); } InternedString nodeName(llvm::StringRef suffix) { return createUniqueName(llvm::Twine("#") + suffix + "_"); }
...@@ -843,8 +960,8 @@ private: ...@@ -843,8 +960,8 @@ private:
return createUniqueName(llvm::Twine("#") + suffix + "_" + llvm::Twine(idx) + "_"); return createUniqueName(llvm::Twine("#") + suffix + "_" + llvm::Twine(idx) + "_");
} }
AST_expr* remapAttribute(AST_Attribute* node) { BST_expr* remapAttribute(AST_Attribute* node) {
AST_Attribute* rtn = new AST_Attribute(); BST_Attribute* rtn = new BST_Attribute();
rtn->col_offset = node->col_offset; rtn->col_offset = node->col_offset;
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
...@@ -854,8 +971,8 @@ private: ...@@ -854,8 +971,8 @@ private:
return rtn; return rtn;
} }
AST_expr* remapBinOp(AST_BinOp* node) { BST_expr* remapBinOp(AST_BinOp* node) {
AST_BinOp* rtn = new AST_BinOp(); BST_BinOp* rtn = new BST_BinOp();
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
rtn->col_offset = node->col_offset; rtn->col_offset = node->col_offset;
rtn->op_type = remapBinOpType(node->op_type); rtn->op_type = remapBinOpType(node->op_type);
...@@ -864,35 +981,35 @@ private: ...@@ -864,35 +981,35 @@ private:
return rtn; return rtn;
} }
AST_slice* _dup(AST_slice* val) { BST_slice* _dup(BST_slice* val) {
if (val == nullptr) { if (val == nullptr) {
return nullptr; return nullptr;
} else if (val->type == AST_TYPE::Ellipsis) { } else if (val->type == BST_TYPE::Ellipsis) {
AST_Ellipsis* orig = ast_cast<AST_Ellipsis>(val); BST_Ellipsis* orig = bst_cast<BST_Ellipsis>(val);
AST_Ellipsis* made = new AST_Ellipsis(); BST_Ellipsis* made = new BST_Ellipsis();
made->col_offset = orig->col_offset; made->col_offset = orig->col_offset;
made->lineno = orig->lineno; made->lineno = orig->lineno;
return made; return made;
} else if (val->type == AST_TYPE::ExtSlice) { } else if (val->type == BST_TYPE::ExtSlice) {
AST_ExtSlice* orig = ast_cast<AST_ExtSlice>(val); BST_ExtSlice* orig = bst_cast<BST_ExtSlice>(val);
AST_ExtSlice* made = new AST_ExtSlice(); BST_ExtSlice* made = new BST_ExtSlice();
made->col_offset = orig->col_offset; made->col_offset = orig->col_offset;
made->lineno = orig->lineno; made->lineno = orig->lineno;
made->dims.reserve(orig->dims.size()); made->dims.reserve(orig->dims.size());
for (AST_slice* item : orig->dims) { for (BST_slice* item : orig->dims) {
made->dims.push_back(_dup(item)); made->dims.push_back(_dup(item));
} }
return made; return made;
} else if (val->type == AST_TYPE::Index) { } else if (val->type == BST_TYPE::Index) {
AST_Index* orig = ast_cast<AST_Index>(val); BST_Index* orig = bst_cast<BST_Index>(val);
AST_Index* made = new AST_Index(); BST_Index* made = new BST_Index();
made->value = _dup(orig->value); made->value = _dup(orig->value);
made->col_offset = orig->col_offset; made->col_offset = orig->col_offset;
made->lineno = orig->lineno; made->lineno = orig->lineno;
return made; return made;
} else if (val->type == AST_TYPE::Slice) { } else if (val->type == BST_TYPE::Slice) {
AST_Slice* orig = ast_cast<AST_Slice>(val); BST_Slice* orig = bst_cast<BST_Slice>(val);
AST_Slice* made = new AST_Slice(); BST_Slice* made = new BST_Slice();
made->col_offset = orig->col_offset; made->col_offset = orig->col_offset;
made->lineno = orig->lineno; made->lineno = orig->lineno;
made->lower = _dup(orig->lower); made->lower = _dup(orig->lower);
...@@ -910,26 +1027,26 @@ private: ...@@ -910,26 +1027,26 @@ private:
// So instead, just create a copy of it. // So instead, just create a copy of it.
// This is only intended to be used with the primitev types, // This is only intended to be used with the primitev types,
// ie those that can be used as operands (temp names and constants). // ie those that can be used as operands (temp names and constants).
AST_expr* _dup(AST_expr* val) { BST_expr* _dup(BST_expr* val) {
if (val == nullptr) if (val == nullptr)
return val; return val;
if (val->type == AST_TYPE::Name) { if (val->type == BST_TYPE::Name) {
AST_Name* orig = ast_cast<AST_Name>(val); BST_Name* orig = bst_cast<BST_Name>(val);
AST_Name* made = makeName(orig->id, orig->ctx_type, orig->lineno, orig->col_offset); BST_Name* made = makeName(orig->id, orig->ctx_type, orig->lineno, orig->col_offset);
return made; return made;
} else if (val->type == AST_TYPE::Num) { } else if (val->type == BST_TYPE::Num) {
AST_Num* orig = ast_cast<AST_Num>(val); BST_Num* orig = bst_cast<BST_Num>(val);
AST_Num* made = new AST_Num(); BST_Num* made = new BST_Num();
made->num_type = orig->num_type; made->num_type = orig->num_type;
made->n_int = orig->n_int; made->n_int = orig->n_int;
made->n_long = orig->n_long; made->n_long = orig->n_long;
made->col_offset = orig->col_offset; made->col_offset = orig->col_offset;
made->lineno = orig->lineno; made->lineno = orig->lineno;
return made; return made;
} else if (val->type == AST_TYPE::Str) { } else if (val->type == BST_TYPE::Str) {
AST_Str* orig = ast_cast<AST_Str>(val); BST_Str* orig = bst_cast<BST_Str>(val);
AST_Str* made = new AST_Str(); BST_Str* made = new BST_Str();
made->str_type = orig->str_type; made->str_type = orig->str_type;
made->str_data = orig->str_data; made->str_data = orig->str_data;
made->col_offset = orig->col_offset; made->col_offset = orig->col_offset;
...@@ -940,7 +1057,7 @@ private: ...@@ -940,7 +1057,7 @@ private:
} }
} }
AST_expr* remapBoolOp(AST_BoolOp* node) { BST_expr* remapBoolOp(AST_BoolOp* node) {
assert(curblock); assert(curblock);
InternedString name = nodeName(); InternedString name = nodeName();
...@@ -949,10 +1066,10 @@ private: ...@@ -949,10 +1066,10 @@ private:
CFGBlock* exit_block = cfg->addDeferredBlock(); CFGBlock* exit_block = cfg->addDeferredBlock();
for (int i = 0; i < node->values.size() - 1; i++) { for (int i = 0; i < node->values.size() - 1; i++) {
AST_expr* val = remapExpr(node->values[i]); BST_expr* val = remapExpr(node->values[i]);
pushAssign(name, _dup(val)); pushAssign(name, _dup(val));
AST_Branch* br = new AST_Branch(); BST_Branch* br = new BST_Branch();
br->test = callNonzero(val); br->test = callNonzero(val);
br->lineno = val->lineno; br->lineno = val->lineno;
push_back(br); push_back(br);
...@@ -979,7 +1096,7 @@ private: ...@@ -979,7 +1096,7 @@ private:
curblock = next_block; curblock = next_block;
} }
AST_expr* final_val = remapExpr(node->values[node->values.size() - 1]); BST_expr* final_val = remapExpr(node->values[node->values.size() - 1]);
pushAssign(name, final_val); pushAssign(name, final_val);
pushJump(exit_block); pushJump(exit_block);
...@@ -989,8 +1106,8 @@ private: ...@@ -989,8 +1106,8 @@ private:
return makeLoad(name, node, true); return makeLoad(name, node, true);
} }
AST_expr* remapCall(AST_Call* node) { BST_expr* remapCall(AST_Call* node) {
AST_Call* rtn = new AST_Call(); BST_Call* rtn = new BST_Call();
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
rtn->col_offset = node->col_offset; rtn->col_offset = node->col_offset;
...@@ -1012,7 +1129,7 @@ private: ...@@ -1012,7 +1129,7 @@ private:
rtn->args.push_back(remapExpr(e)); rtn->args.push_back(remapExpr(e));
} }
for (auto e : node->keywords) { for (auto e : node->keywords) {
AST_keyword* kw = new AST_keyword(); BST_keyword* kw = new BST_keyword();
kw->value = remapExpr(e->value); kw->value = remapExpr(e->value);
kw->arg = e->arg; kw->arg = e->arg;
rtn->keywords.push_back(kw); rtn->keywords.push_back(kw);
...@@ -1023,8 +1140,8 @@ private: ...@@ -1023,8 +1140,8 @@ private:
return rtn; return rtn;
} }
AST_expr* remapClsAttribute(AST_ClsAttribute* node) { BST_expr* remapClsAttribute(AST_ClsAttribute* node) {
AST_ClsAttribute* rtn = new AST_ClsAttribute(); BST_ClsAttribute* rtn = new BST_ClsAttribute();
rtn->col_offset = node->col_offset; rtn->col_offset = node->col_offset;
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
...@@ -1033,12 +1150,12 @@ private: ...@@ -1033,12 +1150,12 @@ private:
return rtn; return rtn;
} }
AST_expr* remapCompare(AST_Compare* node) { BST_expr* remapCompare(AST_Compare* node) {
assert(curblock); assert(curblock);
// special case unchained comparisons to avoid generating a unnecessary complex cfg. // special case unchained comparisons to avoid generating a unnecessary complex cfg.
if (node->ops.size() == 1) { if (node->ops.size() == 1) {
AST_Compare* rtn = new AST_Compare(); BST_Compare* rtn = new BST_Compare();
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
rtn->col_offset = node->col_offset; rtn->col_offset = node->col_offset;
...@@ -1053,15 +1170,15 @@ private: ...@@ -1053,15 +1170,15 @@ private:
InternedString name = nodeName(); InternedString name = nodeName();
CFGBlock* exit_block = cfg->addDeferredBlock(); CFGBlock* exit_block = cfg->addDeferredBlock();
AST_expr* left = remapExpr(node->left); BST_expr* left = remapExpr(node->left);
for (int i = 0; i < node->ops.size(); i++) { for (int i = 0; i < node->ops.size(); i++) {
if (i > 0) if (i > 0)
push_back(makeKill(name)); push_back(makeKill(name));
AST_expr* right = remapExpr(node->comparators[i]); BST_expr* right = remapExpr(node->comparators[i]);
AST_Compare* val = new AST_Compare; BST_Compare* val = new BST_Compare;
val->col_offset = node->col_offset; val->col_offset = node->col_offset;
val->lineno = node->lineno; val->lineno = node->lineno;
val->left = left; val->left = left;
...@@ -1077,7 +1194,7 @@ private: ...@@ -1077,7 +1194,7 @@ private:
continue; continue;
} }
AST_Branch* br = new AST_Branch(); BST_Branch* br = new BST_Branch();
br->test = callNonzero(makeLoad(name, node)); br->test = callNonzero(makeLoad(name, node));
push_back(br); push_back(br);
...@@ -1106,8 +1223,8 @@ private: ...@@ -1106,8 +1223,8 @@ private:
} }
} }
AST_expr* remapDict(AST_Dict* node) { BST_expr* remapDict(AST_Dict* node) {
AST_Dict* rtn = new AST_Dict(); BST_Dict* rtn = new BST_Dict();
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
rtn->col_offset = node->col_offset; rtn->col_offset = node->col_offset;
...@@ -1116,19 +1233,24 @@ private: ...@@ -1116,19 +1233,24 @@ private:
pushAssign(dict_name, rtn); pushAssign(dict_name, rtn);
for (int i = 0; i < node->keys.size(); i++) { for (int i = 0; i < node->keys.size(); i++) {
AST_expr* value = remapExpr(node->values[i]); BST_expr* value = remapExpr(node->values[i]);
AST_Index* index = makeIndex(node->keys[i]); BST_Index* index = makeIndex(remapExpr(node->keys[i]));
AST_Subscript* subscript = makeSubscript(AST_TYPE::Store, makeLoad(dict_name, node, false), index); BST_Subscript* subscript = makeSubscript(AST_TYPE::Store, makeLoad(dict_name, node, false), index);
pushAssign(remapSubscript(subscript), value); pushAssign(subscript, value);
} }
return makeLoad(dict_name, node, true); return makeLoad(dict_name, node, true);
} }
AST_slice* remapEllipsis(AST_Ellipsis* node) { return node; } BST_slice* remapEllipsis(AST_Ellipsis* node) {
auto r = new BST_Ellipsis();
r->lineno = node->lineno;
r->col_offset = node->col_offset;
return r;
}
AST_slice* remapExtSlice(AST_ExtSlice* node) { BST_slice* remapExtSlice(AST_ExtSlice* node) {
AST_ExtSlice* rtn = new AST_ExtSlice(); BST_ExtSlice* rtn = new BST_ExtSlice();
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
rtn->col_offset = node->col_offset; rtn->col_offset = node->col_offset;
...@@ -1152,6 +1274,7 @@ private: ...@@ -1152,6 +1274,7 @@ private:
func->args = new AST_arguments(); func->args = new AST_arguments();
func->args->vararg = NULL; func->args->vararg = NULL;
func->args->kwarg = NULL; func->args->kwarg = NULL;
RELEASE_ASSERT(0, "should this just be the bare functiondef?");
return new AST_MakeFunction(func); return new AST_MakeFunction(func);
} }
...@@ -1185,84 +1308,108 @@ private: ...@@ -1185,84 +1308,108 @@ private:
} }
do_yield(insert_point); do_yield(insert_point);
// RELEASE_ASSERT(0, "have to delete these new ast nodes");
} }
AST_expr* remapGeneratorExp(AST_GeneratorExp* node) { BST_expr* remapGeneratorExp(AST_GeneratorExp* node) {
assert(node->generators.size()); assert(node->generators.size());
// We need to evaluate the first for-expression immediately, as the PEP dictates; so we pass it in as an // We need to evaluate the first for-expression immediately, as the PEP dictates; so we pass it in as an
// argument to the function we create. See // argument to the function we create. See
// https://www.python.org/dev/peps/pep-0289/#early-binding-versus-late-binding // https://www.python.org/dev/peps/pep-0289/#early-binding-versus-late-binding
AST_expr* first = remapExpr(node->generators[0]->iter); BST_expr* first = remapExpr(node->generators[0]->iter);
InternedString arg_name = internString("#arg"); InternedString arg_name = internString("#arg");
AST_MakeFunction* func = makeFunctionForScope(node); AST_arguments* genexp_args = new AST_arguments();
func->function_def->args->args.push_back(makeName(arg_name, AST_TYPE::Param, node->lineno)); genexp_args->args.push_back(makeASTName(arg_name, AST_TYPE::Param, node->lineno));
emitComprehensionLoops(node->lineno, &func->function_def->body, node->generators, std::vector<AST_stmt*> new_body;
makeName(arg_name, AST_TYPE::Load, node->lineno, /* col_offset */ 0, /* is_kill */ true), emitComprehensionLoops(node->lineno, &new_body, node->generators,
makeASTName(arg_name, AST_TYPE::Load, node->lineno, /* col_offset */ 0),
[this, node](std::vector<AST_stmt*>* insert_point) { [this, node](std::vector<AST_stmt*>* insert_point) {
auto y = new AST_Yield(); auto y = new AST_Yield();
y->value = node->elt; y->value = node->elt;
y->lineno = node->lineno; y->lineno = node->lineno;
insert_point->push_back(makeExpr(y)); insert_point->push_back(makeASTExpr(y));
}); });
cfgizer->runRecursively(func->function_def, func->function_def->args, node);
// I'm not sure this actually gets used
static BoxedString* gen_name = getStaticString("<generator>");
BoxedCode* code = cfgizer->runRecursively(new_body, gen_name, node->lineno, genexp_args, node);
// XXX bad! this should be tracked ex through co_consts
// cur_code->co_consts.push_back(def->code)
constants.push_back(code);
BST_FunctionDef* func = new BST_FunctionDef();
func->args = new BST_arguments(); // hacky, but we don't have to fill this in except for the defaults
func->code = code;
BST_MakeFunction* mkfunc = new BST_MakeFunction(func);
InternedString func_var_name = nodeName(); InternedString func_var_name = nodeName();
pushAssign(func_var_name, func); pushAssign(func_var_name, mkfunc);
return makeCall(makeLoad(func_var_name, node, true), first); return makeCall(makeLoad(func_var_name, node, true), first);
} }
void emitComprehensionYield(AST_DictComp* node, InternedString dict_name, std::vector<AST_stmt*>* insert_point) { void emitComprehensionYield(AST_DictComp* node, InternedString dict_name, std::vector<AST_stmt*>* insert_point) {
// add entry to the dictionary // add entry to the dictionary
AST_expr* setitem AST_expr* setitem = makeASTLoadAttribute(makeASTName(dict_name, AST_TYPE::Load, node->lineno),
= makeLoadAttribute(makeName(dict_name, AST_TYPE::Load, node->lineno), internString("__setitem__"), true); internString("__setitem__"), true);
insert_point->push_back(makeExpr(makeCall(setitem, node->key, node->value))); insert_point->push_back(makeASTExpr(makeASTCall(setitem, node->key, node->value)));
} }
void emitComprehensionYield(AST_SetComp* node, InternedString set_name, std::vector<AST_stmt*>* insert_point) { void emitComprehensionYield(AST_SetComp* node, InternedString set_name, std::vector<AST_stmt*>* insert_point) {
// add entry to the dictionary // add entry to the dictionary
AST_expr* add = makeLoadAttribute(makeName(set_name, AST_TYPE::Load, node->lineno), internString("add"), true); AST_expr* add
insert_point->push_back(makeExpr(makeCall(add, node->elt))); = makeASTLoadAttribute(makeASTName(set_name, AST_TYPE::Load, node->lineno), internString("add"), true);
insert_point->push_back(makeASTExpr(makeASTCall(add, node->elt)));
} }
template <typename ResultType, typename CompType> AST_expr* remapScopedComprehension(CompType* node) { template <typename ResultType, typename CompType> BST_expr* remapScopedComprehension(CompType* node) {
// See comment in remapGeneratorExp re early vs. late binding. // See comment in remapGeneratorExp re early vs. late binding.
AST_expr* first = remapExpr(node->generators[0]->iter); BST_expr* first = remapExpr(node->generators[0]->iter);
InternedString arg_name = internString("#arg"); InternedString arg_name = internString("#arg");
AST_MakeFunction* func = makeFunctionForScope(node); AST_arguments* args = new AST_arguments();
func->function_def->args->args.push_back(makeName(arg_name, AST_TYPE::Param, node->lineno)); args->args.push_back(makeASTName(arg_name, AST_TYPE::Param, node->lineno));
std::vector<AST_stmt*> new_body;
InternedString rtn_name = internString("#comp_rtn"); InternedString rtn_name = internString("#comp_rtn");
auto asgn = new AST_Assign(); auto asgn = new AST_Assign();
asgn->targets.push_back(makeName(rtn_name, AST_TYPE::Store, node->lineno)); asgn->targets.push_back(makeASTName(rtn_name, AST_TYPE::Store, node->lineno));
asgn->value = new ResultType(); asgn->value = new ResultType();
asgn->lineno = node->lineno; asgn->lineno = node->lineno;
func->function_def->body.push_back(asgn); new_body.push_back(asgn);
auto lambda = auto lambda =
[&](std::vector<AST_stmt*>* insert_point) { emitComprehensionYield(node, rtn_name, insert_point); }; [&](std::vector<AST_stmt*>* insert_point) { emitComprehensionYield(node, rtn_name, insert_point); };
AST_Name* first_name AST_Name* first_name = makeASTName(internString("#arg"), AST_TYPE::Load, node->lineno, /* col_offset */ 0);
= makeName(internString("#arg"), AST_TYPE::Load, node->lineno, /* col_offset */ 0, /* is_kill */ true); emitComprehensionLoops(node->lineno, &new_body, node->generators, first_name, lambda);
emitComprehensionLoops(node->lineno, &func->function_def->body, node->generators, first_name, lambda);
auto rtn = new AST_Return(); auto rtn = new AST_Return();
rtn->value = makeName(rtn_name, AST_TYPE::Load, node->lineno, /* col_offset */ 0, /* is_kill */ true); rtn->value = makeASTName(rtn_name, AST_TYPE::Load, node->lineno, /* col_offset */ 0);
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
func->function_def->body.push_back(rtn); new_body.push_back(rtn);
// I'm not sure this actually gets used
static BoxedString* comp_name = getStaticString("<comperehension>");
cfgizer->runRecursively(func->function_def, func->function_def->args, node); BoxedCode* code = cfgizer->runRecursively(new_body, comp_name, node->lineno, args, node);
// XXX bad! this should be tracked ex through co_consts
// cur_code->co_consts.push_back(def->code)
constants.push_back(code);
BST_FunctionDef* func = new BST_FunctionDef();
func->args = new BST_arguments(); // hacky, but we don't have to fill this in except for the defaults
func->code = code;
BST_MakeFunction* mkfunc = new BST_MakeFunction(func);
InternedString func_var_name = nodeName(); InternedString func_var_name = nodeName();
pushAssign(func_var_name, func); pushAssign(func_var_name, mkfunc);
return makeCall(makeName(func_var_name, AST_TYPE::Load, node->lineno, /* col_offset */ 0, /* is_kill */ true), return makeCall(makeLoad(func_var_name, node, true), first);
first);
} }
AST_expr* remapIfExp(AST_IfExp* node) { BST_expr* remapIfExp(AST_IfExp* node) {
assert(curblock); assert(curblock);
InternedString rtn_name = nodeName(); InternedString rtn_name = nodeName();
...@@ -1293,50 +1440,53 @@ private: ...@@ -1293,50 +1440,53 @@ private:
return makeLoad(rtn_name, node, true); return makeLoad(rtn_name, node, true);
} }
AST_slice* remapIndex(AST_Index* node) { BST_slice* remapIndex(AST_Index* node) {
AST_Index* rtn = new AST_Index(); BST_Index* rtn = new BST_Index();
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
rtn->col_offset = node->col_offset; rtn->col_offset = node->col_offset;
rtn->value = remapExpr(node->value); rtn->value = remapExpr(node->value);
return rtn; return rtn;
} }
AST_arguments* remapArguments(AST_arguments* args) { BST_arguments* remapArguments(AST_arguments* args) {
auto rtn = new AST_arguments(); // TODO: once in BST we don't need the arguments struct except for evaluating defaults.
rtn = new AST_arguments(); auto rtn = new BST_arguments();
// don't remap args, they're not evaluated. NB. expensive vector copy. // for (auto a : args->args)
rtn->args = args->args; // rtn->args.push_back(remapExpr(a));
rtn->kwarg = args->kwarg; // rtn->kwarg = remapName(args->kwarg);
rtn->vararg = args->vararg; // rtn->vararg = remapName(args->vararg);
for (auto expr : args->defaults) for (auto expr : args->defaults)
rtn->defaults.push_back(remapExpr(expr)); rtn->defaults.push_back(remapExpr(expr));
return rtn; return rtn;
} }
AST_expr* remapLambda(AST_Lambda* node) { BST_expr* remapLambda(AST_Lambda* node) {
// we convert lambdas into normal functions (but don't give it a name)
auto def = new AST_FunctionDef();
def->lineno = node->lineno;
def->col_offset = node->col_offset;
auto stmt = new AST_Return; auto stmt = new AST_Return;
stmt->lineno = node->lineno; stmt->lineno = node->lineno;
stmt->col_offset = node->col_offset; stmt->col_offset = node->col_offset;
stmt->value = node->body; // don't remap now; will be CFG'ed later stmt->value = node->body; // don't remap now; will be CFG'ed later
def->body = { stmt }; auto bdef = new BST_FunctionDef();
def->args = remapArguments(node->args); bdef->lineno = node->lineno;
bdef->col_offset = node->col_offset;
// bdef->name = name;
cfgizer->runRecursively(def, def->args, node); bdef->args = remapArguments(node->args);
auto tmp = nodeName(); auto name = getStaticString("<lambda>");
pushAssign(tmp, new AST_MakeFunction(def)); bdef->code = cfgizer->runRecursively({ stmt }, name, node->lineno, node->args, node);
// XXX bad! this should be tracked ex through co_consts
// cur_code->co_consts.push_back(def->code)
constants.push_back(bdef->code);
return makeLoad(tmp, def, /* is_kill */ false); return new BST_MakeFunction(bdef);
} }
AST_expr* remapLangPrimitive(AST_LangPrimitive* node) { BST_expr* remapLangPrimitive(AST_LangPrimitive* node) {
AST_LangPrimitive* rtn = new AST_LangPrimitive(node->opcode); // AST_LangPrimitive can be PRINT_EXPR
assert(node->opcode == AST_LangPrimitive::PRINT_EXPR);
BST_LangPrimitive* rtn = new BST_LangPrimitive(BST_LangPrimitive::PRINT_EXPR);
rtn->col_offset = node->col_offset; rtn->col_offset = node->col_offset;
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
...@@ -1346,10 +1496,10 @@ private: ...@@ -1346,10 +1496,10 @@ private:
return rtn; return rtn;
} }
AST_expr* remapList(AST_List* node) { BST_expr* remapList(AST_List* node) {
assert(node->ctx_type == AST_TYPE::Load); assert(node->ctx_type == AST_TYPE::Load);
AST_List* rtn = new AST_List(); BST_List* rtn = new BST_List();
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
rtn->col_offset = node->col_offset; rtn->col_offset = node->col_offset;
rtn->ctx_type = node->ctx_type; rtn->ctx_type = node->ctx_type;
...@@ -1360,16 +1510,16 @@ private: ...@@ -1360,16 +1510,16 @@ private:
return rtn; return rtn;
} }
AST_expr* remapRepr(AST_Repr* node) { BST_expr* remapRepr(AST_Repr* node) {
AST_Repr* rtn = new AST_Repr(); BST_Repr* rtn = new BST_Repr();
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
rtn->col_offset = node->col_offset; rtn->col_offset = node->col_offset;
rtn->value = remapExpr(node->value); rtn->value = remapExpr(node->value);
return rtn; return rtn;
} }
AST_expr* remapSet(AST_Set* node) { BST_expr* remapSet(AST_Set* node) {
AST_Set* rtn = new AST_Set(); BST_Set* rtn = new BST_Set();
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
rtn->col_offset = node->col_offset; rtn->col_offset = node->col_offset;
...@@ -1380,8 +1530,8 @@ private: ...@@ -1380,8 +1530,8 @@ private:
return rtn; return rtn;
} }
AST_slice* remapSlice(AST_Slice* node) { BST_slice* remapSlice(AST_Slice* node) {
AST_Slice* rtn = new AST_Slice(); BST_Slice* rtn = new BST_Slice();
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
rtn->col_offset = node->col_offset; rtn->col_offset = node->col_offset;
...@@ -1392,10 +1542,10 @@ private: ...@@ -1392,10 +1542,10 @@ private:
return rtn; return rtn;
} }
AST_expr* remapTuple(AST_Tuple* node) { BST_expr* remapTuple(AST_Tuple* node) {
assert(node->ctx_type == AST_TYPE::Load); assert(node->ctx_type == AST_TYPE::Load);
AST_Tuple* rtn = new AST_Tuple(); BST_Tuple* rtn = new BST_Tuple();
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
rtn->col_offset = node->col_offset; rtn->col_offset = node->col_offset;
rtn->ctx_type = node->ctx_type; rtn->ctx_type = node->ctx_type;
...@@ -1406,8 +1556,8 @@ private: ...@@ -1406,8 +1556,8 @@ private:
return rtn; return rtn;
} }
AST_expr* remapSubscript(AST_Subscript* node) { BST_expr* remapSubscript(AST_Subscript* node) {
AST_Subscript* rtn = new AST_Subscript(); BST_Subscript* rtn = new BST_Subscript();
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
rtn->col_offset = node->col_offset; rtn->col_offset = node->col_offset;
rtn->ctx_type = node->ctx_type; rtn->ctx_type = node->ctx_type;
...@@ -1416,8 +1566,8 @@ private: ...@@ -1416,8 +1566,8 @@ private:
return rtn; return rtn;
} }
AST_expr* remapUnaryOp(AST_UnaryOp* node) { BST_expr* remapUnaryOp(AST_UnaryOp* node) {
AST_UnaryOp* rtn = new AST_UnaryOp(); BST_UnaryOp* rtn = new BST_UnaryOp();
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
rtn->col_offset = node->col_offset; rtn->col_offset = node->col_offset;
rtn->op_type = node->op_type; rtn->op_type = node->op_type;
...@@ -1425,8 +1575,8 @@ private: ...@@ -1425,8 +1575,8 @@ private:
return rtn; return rtn;
} }
AST_expr* remapYield(AST_Yield* node) { BST_expr* remapYield(AST_Yield* node) {
AST_Yield* rtn = new AST_Yield(); BST_Yield* rtn = new BST_Yield();
rtn->lineno = node->lineno; rtn->lineno = node->lineno;
rtn->col_offset = node->col_offset; rtn->col_offset = node->col_offset;
rtn->value = remapExpr(node->value); rtn->value = remapExpr(node->value);
...@@ -1434,7 +1584,7 @@ private: ...@@ -1434,7 +1584,7 @@ private:
InternedString node_name(nodeName()); InternedString node_name(nodeName());
pushAssign(node_name, rtn); pushAssign(node_name, rtn);
push_back(makeExpr(new AST_LangPrimitive(AST_LangPrimitive::UNCACHE_EXC_INFO))); push_back(makeExpr(new BST_LangPrimitive(BST_LangPrimitive::UNCACHE_EXC_INFO)));
if (root_type != AST_TYPE::FunctionDef && root_type != AST_TYPE::Lambda) if (root_type != AST_TYPE::FunctionDef && root_type != AST_TYPE::Lambda)
raiseExcHelper(SyntaxError, "'yield' outside function"); raiseExcHelper(SyntaxError, "'yield' outside function");
...@@ -1442,11 +1592,11 @@ private: ...@@ -1442,11 +1592,11 @@ private:
return makeLoad(node_name, node, /* is_kill */ true); return makeLoad(node_name, node, /* is_kill */ true);
} }
AST_slice* remapSlice(AST_slice* node) { BST_slice* remapSlice(AST_slice* node) {
if (node == nullptr) if (node == nullptr)
return nullptr; return nullptr;
AST_slice* rtn = nullptr; BST_slice* rtn = nullptr;
switch (node->type) { switch (node->type) {
case AST_TYPE::Ellipsis: case AST_TYPE::Ellipsis:
rtn = remapEllipsis(ast_cast<AST_Ellipsis>(node)); rtn = remapEllipsis(ast_cast<AST_Ellipsis>(node));
...@@ -1455,8 +1605,8 @@ private: ...@@ -1455,8 +1605,8 @@ private:
rtn = remapExtSlice(ast_cast<AST_ExtSlice>(node)); rtn = remapExtSlice(ast_cast<AST_ExtSlice>(node));
break; break;
case AST_TYPE::Index: case AST_TYPE::Index:
if (ast_cast<AST_Index>(node)->value->type == AST_TYPE::Num) // if (ast_cast<AST_Index>(node)->value->type == AST_TYPE::Num)
return node; // return node;
rtn = remapIndex(ast_cast<AST_Index>(node)); rtn = remapIndex(ast_cast<AST_Index>(node));
break; break;
case AST_TYPE::Slice: case AST_TYPE::Slice:
...@@ -1468,16 +1618,27 @@ private: ...@@ -1468,16 +1618,27 @@ private:
return rtn; return rtn;
} }
BST_expr* wrap(BST_expr* node) {
// this is the part that actually generates temporaries & assigns to them.
// TODO: could skip num, str, etc.
if (node->type != BST_TYPE::Name || bst_cast<BST_Name>(node)->id.s()[0] != '#') {
InternedString name = nodeName();
pushAssign(name, node);
return makeLoad(name, node, true);
}
return node;
}
// Flattens a nested expression into a flat one, emitting instructions & // Flattens a nested expression into a flat one, emitting instructions &
// generating temporary variables as needed. // generating temporary variables as needed.
// //
// If `wrap_with_assign` is true, it will always return a temporary // If `wrap_with_assign` is true, it will always return a temporary
// variable. // variable.
AST_expr* remapExpr(AST_expr* node, bool wrap_with_assign = true) { BST_expr* remapExpr(AST_expr* node, bool wrap_with_assign = true) {
if (node == NULL) if (node == NULL)
return NULL; return NULL;
AST_expr* rtn; BST_expr* rtn;
switch (node->type) { switch (node->type) {
case AST_TYPE::Attribute: case AST_TYPE::Attribute:
rtn = remapAttribute(ast_cast<AST_Attribute>(node)); rtn = remapAttribute(ast_cast<AST_Attribute>(node));
...@@ -1519,13 +1680,15 @@ private: ...@@ -1519,13 +1680,15 @@ private:
rtn = remapList(ast_cast<AST_List>(node)); rtn = remapList(ast_cast<AST_List>(node));
break; break;
case AST_TYPE::ListComp: case AST_TYPE::ListComp:
rtn = remapComprehension<AST_List>(ast_cast<AST_ListComp>(node)); rtn = remapComprehension<BST_List>(ast_cast<AST_ListComp>(node));
break; break;
case AST_TYPE::Name: case AST_TYPE::Name:
rtn = remapName(ast_cast<AST_Name>(node)); rtn = remapName(ast_cast<AST_Name>(node));
break; break;
case AST_TYPE::Num: case AST_TYPE::Num:
return node; rtn = remapNum(ast_cast<AST_Num>(node));
// TODO: might want to start wrapping literals with assigns too
return rtn;
case AST_TYPE::Repr: case AST_TYPE::Repr:
rtn = remapRepr(ast_cast<AST_Repr>(node)); rtn = remapRepr(ast_cast<AST_Repr>(node));
break; break;
...@@ -1536,7 +1699,9 @@ private: ...@@ -1536,7 +1699,9 @@ private:
rtn = remapScopedComprehension<AST_Set>(ast_cast<AST_SetComp>(node)); rtn = remapScopedComprehension<AST_Set>(ast_cast<AST_SetComp>(node));
break; break;
case AST_TYPE::Str: case AST_TYPE::Str:
return node; rtn = remapStr(ast_cast<AST_Str>(node));
// TODO: might want to start wrapping literals with assigns too
return rtn;
case AST_TYPE::Subscript: case AST_TYPE::Subscript:
rtn = remapSubscript(ast_cast<AST_Subscript>(node)); rtn = remapSubscript(ast_cast<AST_Subscript>(node));
break; break;
...@@ -1553,18 +1718,14 @@ private: ...@@ -1553,18 +1718,14 @@ private:
RELEASE_ASSERT(0, "%d", node->type); RELEASE_ASSERT(0, "%d", node->type);
} }
// this is the part that actually generates temporaries & assigns to them. if (wrap_with_assign)
if (wrap_with_assign && (rtn->type != AST_TYPE::Name || ast_cast<AST_Name>(rtn)->id.s()[0] != '#')) { return wrap(rtn);
InternedString name = nodeName(); else
pushAssign(name, rtn);
return makeLoad(name, node, true);
} else {
return rtn; return rtn;
}
} }
// helper for visit_{tryfinally,with} // helper for visit_{tryfinally,with}
CFGBlock* makeFinallyCont(Why reason, AST_expr* whyexpr, CFGBlock* then_block) { CFGBlock* makeFinallyCont(Why reason, BST_expr* whyexpr, CFGBlock* then_block) {
CFGBlock* otherwise = cfg->addDeferredBlock(); CFGBlock* otherwise = cfg->addDeferredBlock();
otherwise->info = "finally_otherwise"; otherwise->info = "finally_otherwise";
pushBranch(makeCompare(AST_TYPE::Eq, whyexpr, makeNum(reason)), then_block, otherwise); pushBranch(makeCompare(AST_TYPE::Eq, whyexpr, makeNum(reason)), then_block, otherwise);
...@@ -1631,7 +1792,7 @@ public: ...@@ -1631,7 +1792,7 @@ public:
} }
if (type == BST_TYPE::Branch) { if (type == BST_TYPE::Branch) {
BST_TYPE::BST_TYPE test_type = ast_cast<BST_Branch>(node)->test->type; BST_TYPE::BST_TYPE test_type = bst_cast<BST_Branch>(node)->test->type;
ASSERT(test_type == BST_TYPE::Name || test_type == BST_TYPE::Num, "%d", test_type); ASSERT(test_type == BST_TYPE::Name || test_type == BST_TYPE::Num, "%d", test_type);
curblock->push_back(node); curblock->push_back(node);
return; return;
...@@ -1643,9 +1804,9 @@ public: ...@@ -1643,9 +1804,9 @@ public:
} }
if (type == BST_TYPE::Expr) { if (type == BST_TYPE::Expr) {
auto expr = ast_cast<BST_Expr>(node)->value; auto expr = bst_cast<BST_Expr>(node)->value;
if (expr->type == BST_TYPE::LangPrimitive) { if (expr->type == BST_TYPE::LangPrimitive) {
auto lp = ast_cast<BST_LangPrimitive>(expr); auto lp = bst_cast<BST_LangPrimitive>(expr);
if (lp->opcode == BST_LangPrimitive::UNCACHE_EXC_INFO if (lp->opcode == BST_LangPrimitive::UNCACHE_EXC_INFO
|| lp->opcode == BST_LangPrimitive::SET_EXC_INFO) { || lp->opcode == BST_LangPrimitive::SET_EXC_INFO) {
curblock->push_back(node); curblock->push_back(node);
...@@ -1656,30 +1817,30 @@ public: ...@@ -1656,30 +1817,30 @@ public:
} }
if (node->type == BST_TYPE::Assign) { if (node->type == BST_TYPE::Assign) {
BST_Assign* asgn = ast_cast<BST_Assign>(node); BST_Assign* asgn = bst_cast<BST_Assign>(node);
assert(asgn->targets.size() == 1); assert(asgn->targets.size() == 1);
if (asgn->targets[0]->type == BST_TYPE::Name) { if (asgn->targets[0]->type == BST_TYPE::Name) {
BST_Name* target = ast_cast<BST_Name>(asgn->targets[0]); BST_Name* target = bst_cast<BST_Name>(asgn->targets[0]);
if (target->id.s()[0] != '#') { if (target->id.s()[0] != '#') {
// assigning to a non-temporary // assigning to a non-temporary
#ifndef NDEBUG #ifndef NDEBUG
if (!(asgn->value->type == BST_TYPE::Name && ast_cast<BST_Name>(asgn->value)->id.s()[0] == '#') if (!(asgn->value->type == BST_TYPE::Name && bst_cast<BST_Name>(asgn->value)->id.s()[0] == '#')
&& asgn->value->type != BST_TYPE::Str && asgn->value->type != BST_TYPE::Num) { && asgn->value->type != BST_TYPE::Str && asgn->value->type != BST_TYPE::Num) {
fprintf(stdout, "\nError: doing a non-trivial assignment in an invoke is not allowed:\n"); fprintf(stdout, "\nError: doing a non-trivial assignment in an invoke is not allowed:\n");
print_ast(node); print_bst(node);
printf("\n"); printf("\n");
abort(); abort();
} }
#endif #endif
curblock->push_back(node); curblock->push_back(node);
return; return;
} else if (asgn->value->type == BST_TYPE::Name && ast_cast<BST_Name>(asgn->value)->id.s()[0] == '#') { } else if (asgn->value->type == BST_TYPE::Name && bst_cast<BST_Name>(asgn->value)->id.s()[0] == '#') {
// Assigning from one temporary name to another: // Assigning from one temporary name to another:
curblock->push_back(node); curblock->push_back(node);
return; return;
} else if (asgn->value->type == BST_TYPE::Num || asgn->value->type == BST_TYPE::Str } else if (asgn->value->type == BST_TYPE::Num || asgn->value->type == BST_TYPE::Str
|| (asgn->value->type == BST_TYPE::Name || (asgn->value->type == BST_TYPE::Name
&& ast_cast<BST_Name>(asgn->value)->id.s() == "None")) { && bst_cast<BST_Name>(asgn->value)->id.s() == "None")) {
// Assigning to a temporary name from an expression that can't throw: // Assigning to a temporary name from an expression that can't throw:
// NB. `None' can't throw in Python, because it's hardcoded // NB. `None' can't throw in Python, because it's hardcoded
// (seriously, try reassigning "None" in CPython). // (seriously, try reassigning "None" in CPython).
...@@ -1691,10 +1852,10 @@ public: ...@@ -1691,10 +1852,10 @@ public:
// Deleting temporary names is safe, since we only use it to represent kills. // Deleting temporary names is safe, since we only use it to represent kills.
if (node->type == BST_TYPE::Delete) { if (node->type == BST_TYPE::Delete) {
BST_Delete* del = ast_cast<BST_Delete>(node); BST_Delete* del = bst_cast<BST_Delete>(node);
assert(del->targets.size() == 1); assert(del->targets.size() == 1);
if (del->targets[0]->type == BST_TYPE::Name) { if (del->targets[0]->type == BST_TYPE::Name) {
BST_Name* target = ast_cast<BST_Name>(del->targets[0]); BST_Name* target = bst_cast<BST_Name>(del->targets[0]);
if (target->id.s()[0] == '#') { if (target->id.s()[0] == '#') {
curblock->push_back(node); curblock->push_back(node);
return; return;
...@@ -1736,9 +1897,9 @@ public: ...@@ -1736,9 +1897,9 @@ public:
// TODO: need to clear some temporaries here // TODO: need to clear some temporaries here
BST_Assign* exc_asgn = new BST_Assign(); BST_Assign* exc_asgn = new BST_Assign();
BST_Tuple* target = new BST_Tuple(); BST_Tuple* target = new BST_Tuple();
target->elts.push_back(makeName(exc_info.exc_type_name, BST_TYPE::Store, node->lineno)); target->elts.push_back(makeName(exc_info.exc_type_name, AST_TYPE::Store, node->lineno));
target->elts.push_back(makeName(exc_info.exc_value_name, BST_TYPE::Store, node->lineno)); target->elts.push_back(makeName(exc_info.exc_value_name, AST_TYPE::Store, node->lineno));
target->elts.push_back(makeName(exc_info.exc_traceback_name, BST_TYPE::Store, node->lineno)); target->elts.push_back(makeName(exc_info.exc_traceback_name, AST_TYPE::Store, node->lineno));
exc_asgn->targets.push_back(target); exc_asgn->targets.push_back(target);
exc_asgn->value = new BST_LangPrimitive(BST_LangPrimitive::LANDINGPAD); exc_asgn->value = new BST_LangPrimitive(BST_LangPrimitive::LANDINGPAD);
...@@ -1753,12 +1914,10 @@ public: ...@@ -1753,12 +1914,10 @@ public:
} }
bool visit_classdef(AST_ClassDef* node) override { bool visit_classdef(AST_ClassDef* node) override {
// waitaminute, who deallocates `node'? auto def = new BST_ClassDef();
auto def = new AST_ClassDef();
def->lineno = node->lineno; def->lineno = node->lineno;
def->col_offset = node->col_offset; def->col_offset = node->col_offset;
def->name = node->name; def->name = node->name;
def->body = node->body; // expensive vector copy
// Decorators are evaluated before bases: // Decorators are evaluated before bases:
for (auto expr : node->decorator_list) for (auto expr : node->decorator_list)
...@@ -1766,38 +1925,46 @@ public: ...@@ -1766,38 +1925,46 @@ public:
for (auto expr : node->bases) for (auto expr : node->bases)
def->bases.push_back(remapExpr(expr)); def->bases.push_back(remapExpr(expr));
cfgizer->runRecursively(def, nullptr, node); def->code = cfgizer->runRecursively(node->body, node->name.getBox(), node->lineno, NULL, node);
// XXX bad! this should be tracked ex through co_consts
// cur_code->co_consts.push_back(def->code)
constants.push_back(def->code);
auto tmp = nodeName(); auto tmp = nodeName();
pushAssign(tmp, new AST_MakeClass(def)); pushAssign(tmp, new BST_MakeClass(def));
pushAssign(scoping->mangleName(def->name), makeName(tmp, AST_TYPE::Load, node->lineno, 0, true)); pushAssign(scoping->mangleName(def->name), makeName(tmp, AST_TYPE::Load, node->lineno, 0, true));
return true; return true;
} }
bool visit_functiondef(AST_FunctionDef* node) override { bool visit_functiondef(AST_FunctionDef* node) override {
auto def = new AST_FunctionDef(); auto def = new BST_FunctionDef();
def->lineno = node->lineno; def->lineno = node->lineno;
def->col_offset = node->col_offset; def->col_offset = node->col_offset;
def->name = node->name; def->name = node->name;
def->body = node->body; // expensive vector copy
// Decorators are evaluated before the defaults, so this *must* go before remapArguments(). // Decorators are evaluated before the defaults, so this *must* go before remapArguments().
// TODO(rntz): do we have a test for this // TODO(rntz): do we have a test for this
for (auto expr : node->decorator_list) for (auto expr : node->decorator_list)
def->decorator_list.push_back(remapExpr(expr)); def->decorator_list.push_back(remapExpr(expr));
def->args = remapArguments(node->args); def->args = remapArguments(node->args);
cfgizer->runRecursively(def, node->args, node); def->code = cfgizer->runRecursively(node->body, node->name.getBox(), node->lineno, node->args, node);
// XXX bad! this should be tracked ex through co_consts
// cur_code->co_consts.push_back(def->code)
constants.push_back(def->code);
auto tmp = nodeName(); auto tmp = nodeName();
pushAssign(tmp, new AST_MakeFunction(def)); pushAssign(tmp, new BST_MakeFunction(def));
pushAssign(scoping->mangleName(def->name), makeName(tmp, AST_TYPE::Load, node->lineno, node->col_offset, true)); pushAssign(scoping->mangleName(def->name), makeName(tmp, AST_TYPE::Load, node->lineno, node->col_offset, true));
return true; return true;
} }
bool visit_global(AST_Global* node) override { bool visit_global(AST_Global* node) override {
push_back(node); BST_Global* newnode = new BST_Global();
newnode->names = std::move(node->names);
push_back(newnode);
return true; return true;
} }
...@@ -1812,12 +1979,12 @@ public: ...@@ -1812,12 +1979,12 @@ public:
bool visit_import(AST_Import* node) override { bool visit_import(AST_Import* node) override {
for (AST_alias* a : node->names) { for (AST_alias* a : node->names) {
AST_LangPrimitive* import = new AST_LangPrimitive(AST_LangPrimitive::IMPORT_NAME); BST_LangPrimitive* import = new BST_LangPrimitive(BST_LangPrimitive::IMPORT_NAME);
import->lineno = node->lineno; import->lineno = node->lineno;
import->col_offset = node->col_offset; import->col_offset = node->col_offset;
import->args.push_back(new AST_Num()); import->args.push_back(new BST_Num());
static_cast<AST_Num*>(import->args[0])->num_type = AST_Num::INT; static_cast<BST_Num*>(import->args[0])->num_type = AST_Num::INT;
// level == 0 means only check sys path for imports, nothing package-relative, // level == 0 means only check sys path for imports, nothing package-relative,
// level == -1 means check both sys path and relative for imports. // level == -1 means check both sys path and relative for imports.
...@@ -1827,9 +1994,9 @@ public: ...@@ -1827,9 +1994,9 @@ public:
level = -1; level = -1;
else else
level = 0; level = 0;
static_cast<AST_Num*>(import->args[0])->n_int = level; static_cast<BST_Num*>(import->args[0])->n_int = level;
import->args.push_back(new AST_LangPrimitive(AST_LangPrimitive::NONE)); import->args.push_back(new BST_LangPrimitive(BST_LangPrimitive::NONE));
import->args.push_back(new AST_Str(a->name.s())); import->args.push_back(new BST_Str(a->name.s()));
InternedString tmpname = nodeName(); InternedString tmpname = nodeName();
pushAssign(tmpname, import); pushAssign(tmpname, import);
...@@ -1851,7 +2018,7 @@ public: ...@@ -1851,7 +2018,7 @@ public:
l = r + 1; l = r + 1;
continue; continue;
} }
auto attr = new AST_Attribute(makeLoad(tmpname, node, true), AST_TYPE::Load, auto attr = new BST_Attribute(makeLoad(tmpname, node, true), AST_TYPE::Load,
internString(a->name.s().substr(l, r - l))); internString(a->name.s().substr(l, r - l)));
attr->lineno = import->lineno; attr->lineno = import->lineno;
pushAssign(tmpname, attr); pushAssign(tmpname, attr);
...@@ -1865,12 +2032,12 @@ public: ...@@ -1865,12 +2032,12 @@ public:
} }
bool visit_importfrom(AST_ImportFrom* node) override { bool visit_importfrom(AST_ImportFrom* node) override {
AST_LangPrimitive* import = new AST_LangPrimitive(AST_LangPrimitive::IMPORT_NAME); BST_LangPrimitive* import = new BST_LangPrimitive(BST_LangPrimitive::IMPORT_NAME);
import->lineno = node->lineno; import->lineno = node->lineno;
import->col_offset = node->col_offset; import->col_offset = node->col_offset;
import->args.push_back(new AST_Num()); import->args.push_back(new BST_Num());
static_cast<AST_Num*>(import->args[0])->num_type = AST_Num::INT; static_cast<BST_Num*>(import->args[0])->num_type = AST_Num::INT;
// level == 0 means only check sys path for imports, nothing package-relative, // level == 0 means only check sys path for imports, nothing package-relative,
// level == -1 means check both sys path and relative for imports. // level == -1 means check both sys path and relative for imports.
...@@ -1880,14 +2047,14 @@ public: ...@@ -1880,14 +2047,14 @@ public:
level = -1; level = -1;
else else
level = node->level; level = node->level;
static_cast<AST_Num*>(import->args[0])->n_int = level; static_cast<BST_Num*>(import->args[0])->n_int = level;
import->args.push_back(new AST_Tuple()); import->args.push_back(new BST_Tuple());
static_cast<AST_Tuple*>(import->args[1])->ctx_type = AST_TYPE::Load; static_cast<BST_Tuple*>(import->args[1])->ctx_type = AST_TYPE::Load;
for (int i = 0; i < node->names.size(); i++) { for (int i = 0; i < node->names.size(); i++) {
static_cast<AST_Tuple*>(import->args[1])->elts.push_back(new AST_Str(node->names[i]->name.s())); static_cast<BST_Tuple*>(import->args[1])->elts.push_back(new BST_Str(node->names[i]->name.s()));
} }
import->args.push_back(new AST_Str(node->module.s())); import->args.push_back(new BST_Str(node->module.s()));
InternedString tmp_module_name = nodeName(); InternedString tmp_module_name = nodeName();
pushAssign(tmp_module_name, import); pushAssign(tmp_module_name, import);
...@@ -1898,23 +2065,23 @@ public: ...@@ -1898,23 +2065,23 @@ public:
bool is_kill = (i == node->names.size()); bool is_kill = (i == node->names.size());
if (a->name.s() == "*") { if (a->name.s() == "*") {
AST_LangPrimitive* import_star = new AST_LangPrimitive(AST_LangPrimitive::IMPORT_STAR); BST_LangPrimitive* import_star = new BST_LangPrimitive(BST_LangPrimitive::IMPORT_STAR);
import_star->lineno = node->lineno; import_star->lineno = node->lineno;
import_star->col_offset = node->col_offset; import_star->col_offset = node->col_offset;
import_star->args.push_back(makeLoad(tmp_module_name, node, is_kill)); import_star->args.push_back(makeLoad(tmp_module_name, node, is_kill));
AST_Expr* import_star_expr = new AST_Expr(); BST_Expr* import_star_expr = new BST_Expr();
import_star_expr->value = import_star; import_star_expr->value = import_star;
import_star_expr->lineno = node->lineno; import_star_expr->lineno = node->lineno;
import_star_expr->col_offset = node->col_offset; import_star_expr->col_offset = node->col_offset;
push_back(import_star_expr); push_back(import_star_expr);
} else { } else {
AST_LangPrimitive* import_from = new AST_LangPrimitive(AST_LangPrimitive::IMPORT_FROM); BST_LangPrimitive* import_from = new BST_LangPrimitive(BST_LangPrimitive::IMPORT_FROM);
import_from->lineno = node->lineno; import_from->lineno = node->lineno;
import_from->col_offset = node->col_offset; import_from->col_offset = node->col_offset;
import_from->args.push_back(makeLoad(tmp_module_name, node, is_kill)); import_from->args.push_back(makeLoad(tmp_module_name, node, is_kill));
import_from->args.push_back(new AST_Str(a->name.s())); import_from->args.push_back(new BST_Str(a->name.s()));
InternedString tmp_import_name = nodeName(); InternedString tmp_import_name = nodeName();
pushAssign(tmp_import_name, import_from); pushAssign(tmp_import_name, import_from);
...@@ -1930,7 +2097,7 @@ public: ...@@ -1930,7 +2097,7 @@ public:
bool visit_assert(AST_Assert* node) override { bool visit_assert(AST_Assert* node) override {
assert(curblock); assert(curblock);
AST_Branch* br = new AST_Branch(); BST_Branch* br = new BST_Branch();
br->test = callNonzero(remapExpr(node->test)); br->test = callNonzero(remapExpr(node->test));
push_back(br); push_back(br);
...@@ -1945,12 +2112,12 @@ public: ...@@ -1945,12 +2112,12 @@ public:
curblock = iffalse; curblock = iffalse;
AST_Assert* remapped = new AST_Assert(); BST_Assert* remapped = new BST_Assert();
if (node->msg) if (node->msg)
remapped->msg = remapExpr(node->msg); remapped->msg = remapExpr(node->msg);
else else
remapped->msg = NULL; remapped->msg = NULL;
AST_Num* fake_test = new AST_Num(); BST_Num* fake_test = new BST_Num();
fake_test->num_type = AST_Num::INT; fake_test->num_type = AST_Num::INT;
fake_test->n_int = 0; fake_test->n_int = 0;
remapped->test = fake_test; remapped->test = fake_test;
...@@ -1964,10 +2131,10 @@ public: ...@@ -1964,10 +2131,10 @@ public:
} }
bool visit_assign(AST_Assign* node) override { bool visit_assign(AST_Assign* node) override {
AST_expr* remapped_value = remapExpr(node->value); BST_expr* remapped_value = remapExpr(node->value);
for (int i = 0; i < node->targets.size(); i++) { for (int i = 0; i < node->targets.size(); i++) {
AST_expr* val; BST_expr* val;
if (i == node->targets.size() - 1) if (i == node->targets.size() - 1)
val = remapped_value; val = remapped_value;
else else
...@@ -1995,8 +2162,8 @@ public: ...@@ -1995,8 +2162,8 @@ public:
// Finally, due to possibility of exceptions, we don't want to assign directly // Finally, due to possibility of exceptions, we don't want to assign directly
// to the final target at the same time as evaluating the augbinop // to the final target at the same time as evaluating the augbinop
AST_expr* remapped_target; BST_expr* remapped_target;
AST_expr* remapped_lhs; BST_expr* remapped_lhs;
// TODO bad that it's reusing the AST nodes? // TODO bad that it's reusing the AST nodes?
switch (node->target->type) { switch (node->target->type) {
...@@ -2005,7 +2172,7 @@ public: ...@@ -2005,7 +2172,7 @@ public:
assert(n->ctx_type == AST_TYPE::Store); assert(n->ctx_type == AST_TYPE::Store);
InternedString n_name(nodeName()); InternedString n_name(nodeName());
pushAssign(n_name, makeLoad(n->id, node)); pushAssign(n_name, makeLoad(n->id, node));
remapped_target = n; remapped_target = remapName(n);
remapped_lhs = makeLoad(n_name, node, /* is_kill */ true); remapped_lhs = makeLoad(n_name, node, /* is_kill */ true);
break; break;
} }
...@@ -2013,7 +2180,7 @@ public: ...@@ -2013,7 +2180,7 @@ public:
AST_Subscript* s = ast_cast<AST_Subscript>(node->target); AST_Subscript* s = ast_cast<AST_Subscript>(node->target);
assert(s->ctx_type == AST_TYPE::Store); assert(s->ctx_type == AST_TYPE::Store);
AST_Subscript* s_target = new AST_Subscript(); BST_Subscript* s_target = new BST_Subscript();
s_target->value = remapExpr(s->value); s_target->value = remapExpr(s->value);
s_target->slice = remapSlice(s->slice); s_target->slice = remapSlice(s->slice);
s_target->ctx_type = AST_TYPE::Store; s_target->ctx_type = AST_TYPE::Store;
...@@ -2021,13 +2188,13 @@ public: ...@@ -2021,13 +2188,13 @@ public:
s_target->lineno = s->lineno; s_target->lineno = s->lineno;
remapped_target = s_target; remapped_target = s_target;
AST_Subscript* s_lhs = new AST_Subscript(); BST_Subscript* s_lhs = new BST_Subscript();
s_lhs->value = _dup(s_target->value); s_lhs->value = _dup(s_target->value);
s_lhs->slice = _dup(s_target->slice); s_lhs->slice = _dup(s_target->slice);
s_lhs->col_offset = s->col_offset; s_lhs->col_offset = s->col_offset;
s_lhs->lineno = s->lineno; s_lhs->lineno = s->lineno;
s_lhs->ctx_type = AST_TYPE::Load; s_lhs->ctx_type = AST_TYPE::Load;
remapped_lhs = remapExpr(s_lhs); remapped_lhs = wrap(s_lhs);
break; break;
} }
...@@ -2035,21 +2202,21 @@ public: ...@@ -2035,21 +2202,21 @@ public:
AST_Attribute* a = ast_cast<AST_Attribute>(node->target); AST_Attribute* a = ast_cast<AST_Attribute>(node->target);
assert(a->ctx_type == AST_TYPE::Store); assert(a->ctx_type == AST_TYPE::Store);
AST_Attribute* a_target = new AST_Attribute(); BST_Attribute* a_target = new BST_Attribute();
a_target->value = remapExpr(a->value); a_target->value = remapExpr(a->value);
a_target->attr = a->attr; a_target->attr = scoping->mangleName(a->attr);
a_target->ctx_type = AST_TYPE::Store; a_target->ctx_type = AST_TYPE::Store;
a_target->col_offset = a->col_offset; a_target->col_offset = a->col_offset;
a_target->lineno = a->lineno; a_target->lineno = a->lineno;
remapped_target = a_target; remapped_target = a_target;
AST_Attribute* a_lhs = new AST_Attribute(); BST_Attribute* a_lhs = new BST_Attribute();
a_lhs->value = _dup(a_target->value); a_lhs->value = _dup(a_target->value);
a_lhs->attr = a->attr; a_lhs->attr = a_target->attr;
a_lhs->ctx_type = AST_TYPE::Load; a_lhs->ctx_type = AST_TYPE::Load;
a_lhs->col_offset = a->col_offset; a_lhs->col_offset = a->col_offset;
a_lhs->lineno = a->lineno; a_lhs->lineno = a->lineno;
remapped_lhs = remapExpr(a_lhs); remapped_lhs = wrap(a_lhs);
break; break;
} }
...@@ -2057,7 +2224,7 @@ public: ...@@ -2057,7 +2224,7 @@ public:
RELEASE_ASSERT(0, "%d", node->target->type); RELEASE_ASSERT(0, "%d", node->target->type);
} }
AST_AugBinOp* binop = new AST_AugBinOp(); BST_AugBinOp* binop = new BST_AugBinOp();
binop->op_type = remapBinOpType(node->op_type); binop->op_type = remapBinOpType(node->op_type);
binop->left = remapped_lhs; binop->left = remapped_lhs;
binop->right = remapExpr(node->value); binop->right = remapExpr(node->value);
...@@ -2080,14 +2247,14 @@ public: ...@@ -2080,14 +2247,14 @@ public:
bool visit_delete(AST_Delete* node) override { bool visit_delete(AST_Delete* node) override {
for (auto t : node->targets) { for (auto t : node->targets) {
AST_Delete* astdel = new AST_Delete(); BST_Delete* astdel = new BST_Delete();
astdel->lineno = node->lineno; astdel->lineno = node->lineno;
astdel->col_offset = node->col_offset; astdel->col_offset = node->col_offset;
AST_expr* target = NULL; BST_expr* target = NULL;
switch (t->type) { switch (t->type) {
case AST_TYPE::Subscript: { case AST_TYPE::Subscript: {
AST_Subscript* s = static_cast<AST_Subscript*>(t); AST_Subscript* s = static_cast<AST_Subscript*>(t);
AST_Subscript* astsubs = new AST_Subscript(); BST_Subscript* astsubs = new BST_Subscript();
astsubs->value = remapExpr(s->value); astsubs->value = remapExpr(s->value);
astsubs->slice = remapSlice(s->slice); astsubs->slice = remapSlice(s->slice);
astsubs->ctx_type = AST_TYPE::Del; astsubs->ctx_type = AST_TYPE::Del;
...@@ -2095,7 +2262,7 @@ public: ...@@ -2095,7 +2262,7 @@ public:
break; break;
} }
case AST_TYPE::Attribute: { case AST_TYPE::Attribute: {
AST_Attribute* astattr = static_cast<AST_Attribute*>(remapExpr(t, false)); BST_Attribute* astattr = static_cast<BST_Attribute*>(remapExpr(t, false));
astattr->ctx_type = AST_TYPE::Del; astattr->ctx_type = AST_TYPE::Del;
target = astattr; target = astattr;
break; break;
...@@ -2143,7 +2310,7 @@ public: ...@@ -2143,7 +2310,7 @@ public:
} }
bool visit_expr(AST_Expr* node) override { bool visit_expr(AST_Expr* node) override {
AST_Expr* remapped = new AST_Expr(); BST_Expr* remapped = new BST_Expr();
remapped->lineno = node->lineno; remapped->lineno = node->lineno;
remapped->col_offset = node->col_offset; remapped->col_offset = node->col_offset;
remapped->value = remapExpr(node->value, false); remapped->value = remapExpr(node->value, false);
...@@ -2152,11 +2319,11 @@ public: ...@@ -2152,11 +2319,11 @@ public:
} }
bool visit_print(AST_Print* node) override { bool visit_print(AST_Print* node) override {
AST_expr* dest = remapExpr(node->dest); BST_expr* dest = remapExpr(node->dest);
int i = 0; int i = 0;
for (auto v : node->values) { for (auto v : node->values) {
AST_Print* remapped = new AST_Print(); BST_Print* remapped = new BST_Print();
remapped->col_offset = node->col_offset; remapped->col_offset = node->col_offset;
remapped->lineno = node->lineno; remapped->lineno = node->lineno;
...@@ -2177,7 +2344,7 @@ public: ...@@ -2177,7 +2344,7 @@ public:
if (node->values.size() == 0) { if (node->values.size() == 0) {
assert(node->nl); assert(node->nl);
AST_Print* final = new AST_Print(); BST_Print* final = new BST_Print();
final->col_offset = node->col_offset; final->col_offset = node->col_offset;
final->lineno = node->lineno; final->lineno = node->lineno;
// TODO not good to reuse 'dest' like this // TODO not good to reuse 'dest' like this
...@@ -2208,7 +2375,7 @@ public: ...@@ -2208,7 +2375,7 @@ public:
bool visit_if(AST_If* node) override { bool visit_if(AST_If* node) override {
assert(curblock); assert(curblock);
AST_Branch* br = new AST_Branch(); BST_Branch* br = new BST_Branch();
br->col_offset = node->col_offset; br->col_offset = node->col_offset;
br->lineno = node->lineno; br->lineno = node->lineno;
br->test = callNonzero(remapExpr(node->test)); br->test = callNonzero(remapExpr(node->test));
...@@ -2274,7 +2441,7 @@ public: ...@@ -2274,7 +2441,7 @@ public:
} }
bool visit_exec(AST_Exec* node) override { bool visit_exec(AST_Exec* node) override {
AST_Exec* astexec = new AST_Exec(); BST_Exec* astexec = new BST_Exec();
astexec->lineno = node->lineno; astexec->lineno = node->lineno;
astexec->col_offset = node->col_offset; astexec->col_offset = node->col_offset;
astexec->body = remapExpr(node->body); astexec->body = remapExpr(node->body);
...@@ -2292,7 +2459,7 @@ public: ...@@ -2292,7 +2459,7 @@ public:
pushJump(test_block); pushJump(test_block);
curblock = test_block; curblock = test_block;
AST_Branch* br = makeBranch(remapExpr(node->test)); BST_Branch* br = makeBranch(remapExpr(node->test));
CFGBlock* test_block_end = curblock; CFGBlock* test_block_end = curblock;
push_back(br); push_back(br);
...@@ -2341,9 +2508,9 @@ public: ...@@ -2341,9 +2508,9 @@ public:
return true; return true;
} }
AST_stmt* makeKill(InternedString name) { BST_stmt* makeKill(InternedString name) {
// There might be a better way to represent this, maybe with a dedicated AST_Kill bytecode? // There might be a better way to represent this, maybe with a dedicated AST_Kill bytecode?
auto del = new AST_Delete(); auto del = new BST_Delete();
del->targets.push_back(makeName(name, AST_TYPE::Del, 0, 0, false)); del->targets.push_back(makeName(name, AST_TYPE::Del, 0, 0, false));
return del; return del;
} }
...@@ -2355,24 +2522,24 @@ public: ...@@ -2355,24 +2522,24 @@ public:
// is it really worth it? It got so bad because all the edges became // is it really worth it? It got so bad because all the edges became
// critical edges and needed to be broken, otherwise it's not too different. // critical edges and needed to be broken, otherwise it's not too different.
AST_expr* remapped_iter = remapExpr(node->iter); BST_expr* remapped_iter = remapExpr(node->iter);
AST_LangPrimitive* iter_call = new AST_LangPrimitive(AST_LangPrimitive::GET_ITER); BST_LangPrimitive* iter_call = new BST_LangPrimitive(BST_LangPrimitive::GET_ITER);
iter_call->args.push_back(remapped_iter); iter_call->args.push_back(remapped_iter);
iter_call->lineno = node->lineno; iter_call->lineno = node->lineno;
InternedString itername = createUniqueName("#iter_"); InternedString itername = createUniqueName("#iter_");
pushAssign(itername, iter_call); pushAssign(itername, iter_call);
AST_expr* next_attr = makeLoadAttribute(makeLoad(itername, node), internString("next"), true); BST_expr* next_attr = makeLoadAttribute(makeLoad(itername, node), internString("next"), true);
CFGBlock* test_block = cfg->addBlock(); CFGBlock* test_block = cfg->addBlock();
pushJump(test_block); pushJump(test_block);
curblock = test_block; curblock = test_block;
AST_LangPrimitive* test_call = new AST_LangPrimitive(AST_LangPrimitive::HASNEXT); BST_LangPrimitive* test_call = new BST_LangPrimitive(BST_LangPrimitive::HASNEXT);
test_call->lineno = node->lineno; test_call->lineno = node->lineno;
test_call->args.push_back(makeName(itername, AST_TYPE::Load, node->lineno)); test_call->args.push_back(makeName(itername, AST_TYPE::Load, node->lineno));
AST_Branch* test_br = makeBranch(remapExpr(test_call)); BST_Branch* test_br = makeBranch(test_call);
push_back(test_br); push_back(test_br);
CFGBlock* test_true = cfg->addBlock(); CFGBlock* test_true = cfg->addBlock();
...@@ -2409,10 +2576,10 @@ public: ...@@ -2409,10 +2576,10 @@ public:
popContinuation(); popContinuation();
if (curblock) { if (curblock) {
AST_LangPrimitive* end_call = new AST_LangPrimitive(AST_LangPrimitive::HASNEXT); BST_LangPrimitive* end_call = new BST_LangPrimitive(BST_LangPrimitive::HASNEXT);
end_call->args.push_back(makeName(itername, AST_TYPE::Load, node->lineno)); end_call->args.push_back(makeName(itername, AST_TYPE::Load, node->lineno));
end_call->lineno = node->lineno; end_call->lineno = node->lineno;
AST_Branch* end_br = makeBranch(remapExpr(end_call)); BST_Branch* end_br = makeBranch(end_call);
push_back(end_br); push_back(end_br);
CFGBlock* end_true = cfg->addBlock(); CFGBlock* end_true = cfg->addBlock();
...@@ -2455,7 +2622,7 @@ public: ...@@ -2455,7 +2622,7 @@ public:
bool visit_raise(AST_Raise* node) override { bool visit_raise(AST_Raise* node) override {
assert(curblock); assert(curblock);
AST_Raise* remapped = new AST_Raise(); BST_Raise* remapped = new BST_Raise();
remapped->col_offset = node->col_offset; remapped->col_offset = node->col_offset;
remapped->lineno = node->lineno; remapped->lineno = node->lineno;
...@@ -2517,16 +2684,16 @@ public: ...@@ -2517,16 +2684,16 @@ public:
CFGBlock* exc_next = nullptr; CFGBlock* exc_next = nullptr;
if (exc_handler->type) { if (exc_handler->type) {
AST_expr* handled_type = remapExpr(exc_handler->type); BST_expr* handled_type = remapExpr(exc_handler->type);
AST_LangPrimitive* is_caught_here = new AST_LangPrimitive(AST_LangPrimitive::CHECK_EXC_MATCH); BST_LangPrimitive* is_caught_here = new BST_LangPrimitive(BST_LangPrimitive::CHECK_EXC_MATCH);
// TODO This is supposed to be exc_type_name (value doesn't matter for checking matches) // TODO This is supposed to be exc_type_name (value doesn't matter for checking matches)
is_caught_here->args.push_back(makeLoad(exc_value_name, exc_handler)); is_caught_here->args.push_back(makeLoad(exc_value_name, exc_handler));
is_caught_here->args.push_back(handled_type); is_caught_here->args.push_back(handled_type);
is_caught_here->lineno = exc_handler->lineno; is_caught_here->lineno = exc_handler->lineno;
AST_Branch* br = new AST_Branch(); BST_Branch* br = new BST_Branch();
br->test = callNonzero(remapExpr(is_caught_here)); br->test = callNonzero(is_caught_here);
br->lineno = exc_handler->lineno; br->lineno = exc_handler->lineno;
CFGBlock* exc_handle = cfg->addBlock(); CFGBlock* exc_handle = cfg->addBlock();
...@@ -2546,7 +2713,7 @@ public: ...@@ -2546,7 +2713,7 @@ public:
pushAssign(exc_handler->name, makeLoad(exc_value_name, exc_handler)); pushAssign(exc_handler->name, makeLoad(exc_value_name, exc_handler));
} }
AST_LangPrimitive* set_exc_info = new AST_LangPrimitive(AST_LangPrimitive::SET_EXC_INFO); BST_LangPrimitive* set_exc_info = new BST_LangPrimitive(BST_LangPrimitive::SET_EXC_INFO);
set_exc_info->args.push_back(makeLoad(exc_type_name, node, true)); set_exc_info->args.push_back(makeLoad(exc_type_name, node, true));
set_exc_info->args.push_back(makeLoad(exc_value_name, node, true)); set_exc_info->args.push_back(makeLoad(exc_value_name, node, true));
set_exc_info->args.push_back(makeLoad(exc_traceback_name, node, true)); set_exc_info->args.push_back(makeLoad(exc_traceback_name, node, true));
...@@ -2571,7 +2738,7 @@ public: ...@@ -2571,7 +2738,7 @@ public:
} }
if (!caught_all) { if (!caught_all) {
AST_Raise* raise = new AST_Raise(); BST_Raise* raise = new BST_Raise();
raise->arg0 = makeLoad(exc_type_name, node, true); raise->arg0 = makeLoad(exc_type_name, node, true);
raise->arg1 = makeLoad(exc_value_name, node, true); raise->arg1 = makeLoad(exc_value_name, node, true);
raise->arg2 = makeLoad(exc_traceback_name, node, true); raise->arg2 = makeLoad(exc_traceback_name, node, true);
...@@ -2711,13 +2878,13 @@ public: ...@@ -2711,13 +2878,13 @@ public:
// TODO(rntz): for some reason, in the interpreter (but not the JIT), this is looking up __exit__ on the // TODO(rntz): for some reason, in the interpreter (but not the JIT), this is looking up __exit__ on the
// instance rather than the class. See test/tests/with_ctxclass_instance_attrs.py. // instance rather than the class. See test/tests/with_ctxclass_instance_attrs.py.
AST_expr* exit = makeLoadAttribute(makeLoad(ctxmgrname, node), internString("__exit__"), true); BST_expr* exit = makeLoadAttribute(makeLoad(ctxmgrname, node), internString("__exit__"), true);
pushAssign(exitname, exit); pushAssign(exitname, exit);
// Oddly, this acces to __enter__ doesn't suffer from the same bug. Perhaps it has something to do with // Oddly, this acces to __enter__ doesn't suffer from the same bug. Perhaps it has something to do with
// __enter__ being called immediately? // __enter__ being called immediately?
AST_expr* enter = makeLoadAttribute(makeLoad(ctxmgrname, node, true), internString("__enter__"), true); BST_expr* enter = makeLoadAttribute(makeLoad(ctxmgrname, node, true), internString("__enter__"), true);
enter = remapExpr(makeCall(enter)); enter = wrap(makeCall(enter));
if (node->optional_vars) if (node->optional_vars)
pushAssign(node->optional_vars, enter); pushAssign(node->optional_vars, enter);
else else
...@@ -2819,7 +2986,7 @@ void CFG::print(llvm::raw_ostream& stream) { ...@@ -2819,7 +2986,7 @@ void CFG::print(llvm::raw_ostream& stream) {
blocks[i]->print(stream); blocks[i]->print(stream);
} }
class AssignVRegsVisitor : public NoopASTVisitor { class AssignVRegsVisitor : public NoopBSTVisitor {
public: public:
CFGBlock* current_block; CFGBlock* current_block;
int next_vreg; int next_vreg;
...@@ -2831,15 +2998,15 @@ public: ...@@ -2831,15 +2998,15 @@ public:
AssignVRegsVisitor() : current_block(0), next_vreg(0) {} AssignVRegsVisitor() : current_block(0), next_vreg(0) {}
bool visit_alias(AST_alias* node) override { RELEASE_ASSERT(0, "these should be removed by the cfg"); } bool visit_alias(BST_alias* node) override { RELEASE_ASSERT(0, "these should be removed by the cfg"); }
bool visit_arguments(AST_arguments* node) override { bool visit_arguments(BST_arguments* node) override {
for (AST_expr* d : node->defaults) for (BST_expr* d : node->defaults)
d->accept(this); d->accept(this);
return true; return true;
} }
bool visit_classdef(AST_ClassDef* node) override { bool visit_classdef(BST_ClassDef* node) override {
for (auto e : node->bases) for (auto e : node->bases)
e->accept(this); e->accept(this);
for (auto e : node->decorator_list) for (auto e : node->decorator_list)
...@@ -2847,14 +3014,14 @@ public: ...@@ -2847,14 +3014,14 @@ public:
return true; return true;
} }
bool visit_functiondef(AST_FunctionDef* node) override { bool visit_functiondef(BST_FunctionDef* node) override {
for (auto* d : node->decorator_list) for (auto* d : node->decorator_list)
d->accept(this); d->accept(this);
node->args->accept(this); node->args->accept(this);
return true; return true;
} }
bool visit_lambda(AST_Lambda* node) override { bool visit_lambda(BST_Lambda* node) override {
node->args->accept(this); node->args->accept(this);
return true; return true;
} }
...@@ -2866,7 +3033,7 @@ public: ...@@ -2866,7 +3033,7 @@ public:
return sym_blocks_map[id].size() == 1; return sym_blocks_map[id].size() == 1;
} }
bool visit_name(AST_Name* node) override { bool visit_name(BST_Name* node) override {
if (node->vreg != -1) if (node->vreg != -1)
return true; return true;
...@@ -2932,7 +3099,7 @@ void VRegInfo::assignVRegs(CFG* cfg, const ParamNames& param_names) { ...@@ -2932,7 +3099,7 @@ void VRegInfo::assignVRegs(CFG* cfg, const ParamNames& param_names) {
} }
} }
for (AST_stmt* stmt : b->body) { for (BST_stmt* stmt : b->body) {
stmt->accept(&visitor); stmt->accept(&visitor);
} }
...@@ -2961,51 +3128,55 @@ void VRegInfo::assignVRegs(CFG* cfg, const ParamNames& param_names) { ...@@ -2961,51 +3128,55 @@ void VRegInfo::assignVRegs(CFG* cfg, const ParamNames& param_names) {
} }
static CFG* computeCFG(AST* ast, BoxedString* filename, SourceInfo* source, const ParamNames& param_names, static CFG* computeCFG(llvm::ArrayRef<AST_stmt*> body, AST_TYPE::AST_TYPE ast_type, int lineno, AST_arguments* args,
ScopeInfo* scoping, ModuleCFGProcessor* cfgizer) { BoxedString* filename, SourceInfo* source, const ParamNames& param_names, ScopeInfo* scoping,
ModuleCFGProcessor* cfgizer) {
STAT_TIMER(t0, "us_timer_computecfg", 0); STAT_TIMER(t0, "us_timer_computecfg", 0);
auto body = ast->getBody();
CFG* rtn = new CFG(); CFG* rtn = new CFG();
assert((bool)args == (ast_type == AST_TYPE::FunctionDef || ast_type == AST_TYPE::Lambda));
auto&& stringpool = cfgizer->stringpool; auto&& stringpool = cfgizer->stringpool;
CFGVisitor visitor(filename, source, stringpool, scoping, ast->type, source->future_flags, rtn, cfgizer); CFGVisitor visitor(filename, source, stringpool, scoping, ast_type, source->future_flags, rtn, cfgizer);
bool skip_first = false; bool skip_first = false;
if (ast->type == AST_TYPE::ClassDef) { if (ast_type == AST_TYPE::ClassDef) {
// A classdef always starts with "__module__ = __name__" // A classdef always starts with "__module__ = __name__"
AST_Assign* module_assign = new AST_Assign(); BST_Assign* module_assign = new BST_Assign();
auto module_name_target = new AST_Name(stringpool.get("__module__"), AST_TYPE::Store, ast->lineno); auto module_name_target = new BST_Name(stringpool.get("__module__"), AST_TYPE::Store, lineno);
fillScopingInfo(module_name_target, scoping); fillScopingInfo(module_name_target, scoping);
auto module_name_value = new AST_Name(stringpool.get("__name__"), AST_TYPE::Load, ast->lineno); auto module_name_value = new BST_Name(stringpool.get("__name__"), AST_TYPE::Load, lineno);
fillScopingInfo(module_name_value, scoping); fillScopingInfo(module_name_value, scoping);
module_assign->targets.push_back(module_name_target); module_assign->targets.push_back(module_name_target);
module_assign->value = module_name_value; module_assign->value = module_name_value;
module_assign->lineno = ast->lineno; module_assign->lineno = lineno;
visitor.push_back(module_assign); visitor.push_back(module_assign);
// If the first statement is just a single string, transform it to an assignment to __doc__ // If the first statement is just a single string, transform it to an assignment to __doc__
if (body.size() && body[0]->type == AST_TYPE::Expr) { if (body.size() && body[0]->type == AST_TYPE::Expr) {
AST_Expr* first_expr = ast_cast<AST_Expr>(body[0]); AST_Expr* first_expr = ast_cast<AST_Expr>(body[0]);
if (first_expr->value->type == AST_TYPE::Str) { if (first_expr->value->type == AST_TYPE::Str) {
AST_Assign* doc_assign = new AST_Assign(); BST_Assign* doc_assign = new BST_Assign();
auto doc_target_name = new AST_Name(stringpool.get("__doc__"), AST_TYPE::Store, ast->lineno); auto doc_target_name = new BST_Name(stringpool.get("__doc__"), AST_TYPE::Store, lineno);
fillScopingInfo(doc_target_name, scoping); fillScopingInfo(doc_target_name, scoping);
doc_assign->targets.push_back(doc_target_name); doc_assign->targets.push_back(doc_target_name);
doc_assign->value = first_expr->value; auto doc_val = new BST_Str();
doc_assign->lineno = ast->lineno; doc_val->str_data = ast_cast<AST_Str>(first_expr->value)->str_data;
doc_val->str_type = ast_cast<AST_Str>(first_expr->value)->str_type;
doc_assign->value = doc_val;
doc_assign->lineno = lineno;
visitor.push_back(doc_assign); visitor.push_back(doc_assign);
skip_first = true; skip_first = true;
} }
} }
} }
if (ast->type == AST_TYPE::FunctionDef || ast->type == AST_TYPE::Lambda) { if (ast_type == AST_TYPE::FunctionDef || ast_type == AST_TYPE::Lambda) {
// Unpack tuple arguments // Unpack tuple arguments
// Tuple arguments get assigned names ".0", ".1" etc. So this // Tuple arguments get assigned names ".0", ".1" etc. So this
// def f(a, (b,c), (d,e)): // def f(a, (b,c), (d,e)):
...@@ -3013,18 +3184,12 @@ static CFG* computeCFG(AST* ast, BoxedString* filename, SourceInfo* source, cons ...@@ -3013,18 +3184,12 @@ static CFG* computeCFG(AST* ast, BoxedString* filename, SourceInfo* source, cons
// def f(a, .1, .2): // def f(a, .1, .2):
// (b, c) = .1 // (b, c) = .1
// (d, e) = .2 // (d, e) = .2
AST_arguments* args;
if (ast->type == AST_TYPE::FunctionDef) {
args = ast_cast<AST_FunctionDef>(ast)->args;
} else {
args = ast_cast<AST_Lambda>(ast)->args;
}
int counter = 0; int counter = 0;
for (AST_expr* arg_expr : args->args) { for (AST_expr* arg_expr : args->args) {
if (arg_expr->type == AST_TYPE::Tuple) { if (arg_expr->type == AST_TYPE::Tuple) {
InternedString arg_name = stringpool.get("." + std::to_string(counter)); InternedString arg_name = stringpool.get("." + std::to_string(counter));
AST_Name* arg_name_expr BST_Name* arg_name_expr
= new AST_Name(arg_name, AST_TYPE::Load, arg_expr->lineno, arg_expr->col_offset); = new BST_Name(arg_name, AST_TYPE::Load, arg_expr->lineno, arg_expr->col_offset);
assert(scoping->getScopeTypeOfName(arg_name) == ScopeInfo::VarScopeType::FAST); assert(scoping->getScopeTypeOfName(arg_name) == ScopeInfo::VarScopeType::FAST);
arg_name_expr->lookup_type = ScopeInfo::VarScopeType::FAST; arg_name_expr->lookup_type = ScopeInfo::VarScopeType::FAST;
visitor.pushAssign(arg_expr, arg_name_expr); visitor.pushAssign(arg_expr, arg_name_expr);
...@@ -3044,19 +3209,19 @@ static CFG* computeCFG(AST* ast, BoxedString* filename, SourceInfo* source, cons ...@@ -3044,19 +3209,19 @@ static CFG* computeCFG(AST* ast, BoxedString* filename, SourceInfo* source, cons
// The functions we create for classdefs are supposed to return a dictionary of their locals. // The functions we create for classdefs are supposed to return a dictionary of their locals.
// This is the place that we add all of that: // This is the place that we add all of that:
if (ast->type == AST_TYPE::ClassDef) { if (ast_type == AST_TYPE::ClassDef) {
AST_LangPrimitive* locals = new AST_LangPrimitive(AST_LangPrimitive::LOCALS); BST_LangPrimitive* locals = new BST_LangPrimitive(BST_LangPrimitive::LOCALS);
AST_Return* rtn = new AST_Return(); BST_Return* rtn = new BST_Return();
rtn->lineno = getLastLineno(ast); rtn->lineno = getLastLineno(body, lineno);
rtn->value = locals; rtn->value = locals;
visitor.push_back(rtn); visitor.push_back(rtn);
} else { } else {
// Put a fake "return" statement at the end of every function just to make sure they all have one; // Put a fake "return" statement at the end of every function just to make sure they all have one;
// we already have to support multiple return statements in a function, but this way we can avoid // we already have to support multiple return statements in a function, but this way we can avoid
// having to support not having a return statement: // having to support not having a return statement:
AST_Return* return_stmt = new AST_Return(); BST_Return* return_stmt = new BST_Return();
return_stmt->lineno = getLastLineno(ast); return_stmt->lineno = getLastLineno(body, lineno);
return_stmt->col_offset = 0; return_stmt->col_offset = 0;
return_stmt->value = NULL; return_stmt->value = NULL;
visitor.push_back(return_stmt); visitor.push_back(return_stmt);
...@@ -3085,9 +3250,9 @@ static CFG* computeCFG(AST* ast, BoxedString* filename, SourceInfo* source, cons ...@@ -3085,9 +3250,9 @@ static CFG* computeCFG(AST* ast, BoxedString* filename, SourceInfo* source, cons
ASSERT(b->body.size(), "%d", b->idx); ASSERT(b->body.size(), "%d", b->idx);
ASSERT(b->successors.size() <= 2, "%d has too many successors!", b->idx); ASSERT(b->successors.size() <= 2, "%d has too many successors!", b->idx);
if (b->successors.size() == 0) { if (b->successors.size() == 0) {
AST_stmt* terminator = b->body.back(); BST_stmt* terminator = b->body.back();
assert(terminator->type == AST_TYPE::Return || terminator->type == AST_TYPE::Raise assert(terminator->type == BST_TYPE::Return || terminator->type == BST_TYPE::Raise
|| terminator->type == AST_TYPE::Raise || terminator->type == AST_TYPE::Assert); || terminator->type == BST_TYPE::Raise || terminator->type == BST_TYPE::Assert);
} }
if (b->predecessors.size() == 0) { if (b->predecessors.size() == 0) {
...@@ -3137,17 +3302,17 @@ static CFG* computeCFG(AST* ast, BoxedString* filename, SourceInfo* source, cons ...@@ -3137,17 +3302,17 @@ static CFG* computeCFG(AST* ast, BoxedString* filename, SourceInfo* source, cons
assert(rtn->getStartingBlock()->idx == 0); assert(rtn->getStartingBlock()->idx == 0);
std::vector<AST*> flattened; std::vector<BST*> flattened;
for (auto b : rtn->blocks) for (auto b : rtn->blocks)
flatten(b->body, flattened, true); flatten(b->body, flattened, true);
std::unordered_map<AST*, int> deduped; std::unordered_map<BST*, int> deduped;
bool no_dups = true; bool no_dups = true;
for (auto e : flattened) { for (auto e : flattened) {
deduped[e]++; deduped[e]++;
if (deduped[e] == 2) { if (deduped[e] == 2) {
printf("Duplicated: "); printf("Duplicated: ");
print_ast(e); print_bst(e);
printf("\n"); printf("\n");
no_dups = false; no_dups = false;
} }
...@@ -3223,11 +3388,11 @@ static CFG* computeCFG(AST* ast, BoxedString* filename, SourceInfo* source, cons ...@@ -3223,11 +3388,11 @@ static CFG* computeCFG(AST* ast, BoxedString* filename, SourceInfo* source, cons
if (b2->predecessors.size() != 1) if (b2->predecessors.size() != 1)
break; break;
AST_TYPE::AST_TYPE end_ast_type = b->body[b->body.size() - 1]->type; BST_TYPE::BST_TYPE end_ast_type = b->body[b->body.size() - 1]->type;
assert(end_ast_type == AST_TYPE::Jump || end_ast_type == AST_TYPE::Invoke); assert(end_ast_type == BST_TYPE::Jump || end_ast_type == BST_TYPE::Invoke);
if (end_ast_type == AST_TYPE::Invoke) { if (end_ast_type == BST_TYPE::Invoke) {
// TODO probably shouldn't be generating these anyway: // TODO probably shouldn't be generating these anyway:
auto invoke = ast_cast<AST_Invoke>(b->body.back()); auto invoke = bst_cast<BST_Invoke>(b->body.back());
assert(invoke->normal_dest == invoke->exc_dest); assert(invoke->normal_dest == invoke->exc_dest);
break; break;
} }
...@@ -3262,33 +3427,66 @@ static CFG* computeCFG(AST* ast, BoxedString* filename, SourceInfo* source, cons ...@@ -3262,33 +3427,66 @@ static CFG* computeCFG(AST* ast, BoxedString* filename, SourceInfo* source, cons
} }
void ModuleCFGProcessor::runRecursively(AST* ast, AST_arguments* args, AST* orig_node) { BoxedCode* ModuleCFGProcessor::runRecursively(llvm::ArrayRef<AST_stmt*> body, BoxedString* name, int lineno,
AST_arguments* args, AST* orig_node) {
ScopeInfo* scope_info = scoping.getScopeInfoForNode(orig_node); ScopeInfo* scope_info = scoping.getScopeInfoForNode(orig_node);
std::unique_ptr<SourceInfo> si(
new SourceInfo(bm, ScopingResults(scope_info, scoping.areGlobalsFromModule()), future_flags, ast)); AST_TYPE::AST_TYPE ast_type = orig_node->type;
ParamNames param_names(ast, stringpool); bool is_generator;
switch (ast_type) {
case AST_TYPE::ClassDef:
case AST_TYPE::Module:
case AST_TYPE::Expression:
case AST_TYPE::Suite:
is_generator = false;
break;
case AST_TYPE::GeneratorExp:
case AST_TYPE::DictComp:
case AST_TYPE::SetComp:
is_generator = ast_type == AST_TYPE::GeneratorExp;
assert(containsYield(body) == is_generator);
// Hack: our old system represented this as ast_type == FuntionDef, so
// keep doing that for now
ast_type = AST_TYPE::FunctionDef;
break;
case AST_TYPE::FunctionDef:
case AST_TYPE::Lambda:
is_generator = containsYield(orig_node);
break;
default:
RELEASE_ASSERT(0, "Unknown type: %d", ast_type);
break;
}
std::unique_ptr<SourceInfo> si(new SourceInfo(bm, ScopingResults(scope_info, scoping.areGlobalsFromModule()),
future_flags, ast_type, is_generator));
assert((bool)args == (ast_type == AST_TYPE::FunctionDef || ast_type == AST_TYPE::Lambda));
ParamNames param_names(args, stringpool);
for (auto e : param_names.allArgsAsName()) for (auto e : param_names.allArgsAsName())
fillScopingInfo(e, scope_info); fillScopingInfo(e, scope_info);
si->cfg = computeCFG(ast, fn, si.get(), param_names, scope_info, this); si->cfg = computeCFG(body, ast_type, lineno, args, fn, si.get(), param_names, scope_info, this);
BoxedCode* code; BoxedCode* code;
if (args) if (args)
code = new BoxedCode(args->args.size(), args->vararg, args->kwarg, ast->lineno, std::move(si), code = new BoxedCode(args->args.size(), args->vararg, args->kwarg, lineno, std::move(si),
std::move(param_names), fn, ast->getName(), autoDecref(ast->getDocString())); std::move(param_names), fn, name, autoDecref(getDocString(body)));
else else
code = new BoxedCode(0, false, false, ast->lineno, std::move(si), std::move(param_names), fn, ast->getName(), code = new BoxedCode(0, false, false, lineno, std::move(si), std::move(param_names), fn, name,
autoDecref(ast->getDocString())); autoDecref(getDocString(body)));
// XXX very bad! Should properly track this:
constants.push_back(code);
ast->getCode() = code; return code;
} }
void computeAllCFGs(AST* ast, bool globals_from_module, FutureFlags future_flags, BoxedString* fn, BoxedModule* bm) { BoxedCode* computeAllCFGs(AST* ast, bool globals_from_module, FutureFlags future_flags, BoxedString* fn,
ModuleCFGProcessor(ast, globals_from_module, future_flags, fn, bm).runRecursively(ast, nullptr, ast); BoxedModule* bm) {
return ModuleCFGProcessor(ast, globals_from_module, future_flags, fn, bm)
.runRecursively(ast->getBody(), ast->getName(), ast->lineno, nullptr, ast);
} }
void printCFG(CFG* cfg) { void printCFG(CFG* cfg) {
......
...@@ -330,7 +330,8 @@ public: ...@@ -330,7 +330,8 @@ public:
iterator end() const { return iterator(*this, this->v.size()); } iterator end() const { return iterator(*this, this->v.size()); }
}; };
void computeAllCFGs(AST* ast, bool globals_from_module, FutureFlags future_flags, BoxedString* fn, BoxedModule* bm); BoxedCode* computeAllCFGs(AST* ast, bool globals_from_module, FutureFlags future_flags, BoxedString* fn,
BoxedModule* bm);
void printCFG(CFG* cfg); void printCFG(CFG* cfg);
} }
......
...@@ -156,7 +156,7 @@ class CFG; ...@@ -156,7 +156,7 @@ class CFG;
class AST; class AST;
class BST; class BST;
class BST_FunctionDef; class BST_FunctionDef;
class BST_arguments; class AST_arguments;
class BST_expr; class BST_expr;
class BST_Name; class BST_Name;
class BST_stmt; class BST_stmt;
...@@ -234,7 +234,7 @@ struct ParamNames { ...@@ -234,7 +234,7 @@ struct ParamNames {
unsigned char has_vararg_name : 1; unsigned char has_vararg_name : 1;
unsigned char has_kwarg_name : 1; unsigned char has_kwarg_name : 1;
explicit ParamNames(AST* ast, InternedStringPool& pool); explicit ParamNames(AST_arguments* ast, InternedStringPool& pool);
ParamNames(const std::vector<const char*>& args, const char* vararg, const char* kwarg); ParamNames(const std::vector<const char*>& args, const char* vararg, const char* kwarg);
static ParamNames empty() { return ParamNames(); } static ParamNames empty() { return ParamNames(); }
...@@ -502,7 +502,7 @@ public: ...@@ -502,7 +502,7 @@ public:
LivenessAnalysis* getLiveness(); LivenessAnalysis* getLiveness();
SourceInfo(BoxedModule* m, ScopingResults scoping, FutureFlags future_flags, AST* ast); SourceInfo(BoxedModule* m, ScopingResults scoping, FutureFlags future_flags, int ast_type, bool is_generator);
~SourceInfo(); ~SourceInfo();
}; };
......
...@@ -16,8 +16,8 @@ ...@@ -16,8 +16,8 @@
#include <cstdarg> #include <cstdarg>
#include <dlfcn.h> #include <dlfcn.h>
#include "core/ast.h"
#include "codegen/unwinding.h" #include "codegen/unwinding.h"
#include "core/ast.h"
#include "core/options.h" #include "core/options.h"
#include "runtime/objmodel.h" #include "runtime/objmodel.h"
#include "runtime/types.h" #include "runtime/types.h"
......
...@@ -118,3 +118,11 @@ try: ...@@ -118,3 +118,11 @@ try:
f10() f10()
except UnboundLocalError, e: except UnboundLocalError, e:
print e print e
def f11():
class C(object):
def __init__(self):
self.__x = 1
self.__x += 2
print C()._C__x
f11()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-undef -D_PYSTON_API") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-undef -D_PYSTON_API")
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
add_definitions(-DGTEST_HAS_RTTI=0 ${LLVM_DEFINITIONS}) add_definitions(-DGTEST_HAS_RTTI=0 ${LLVM_DEFINITIONS})
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "codegen/osrentry.h" #include "codegen/osrentry.h"
#include "codegen/parser.h" #include "codegen/parser.h"
#include "core/ast.h" #include "core/ast.h"
#include "core/bst.h"
#include "core/cfg.h" #include "core/cfg.h"
#include "runtime/types.h" #include "runtime/types.h"
#include "unittests.h" #include "unittests.h"
...@@ -34,7 +35,7 @@ TEST_F(AnalysisTest, augassign) { ...@@ -34,7 +35,7 @@ TEST_F(AnalysisTest, augassign) {
FutureFlags future_flags = getFutureFlags(module->body, fn.c_str()); FutureFlags future_flags = getFutureFlags(module->body, fn.c_str());
auto scoping = std::make_shared<ScopingAnalysis>(module, true); auto scoping = std::make_shared<ScopingAnalysis>(module, true);
computeAllCFGs(module, true, future_flags, boxString(fn), NULL); auto module_code = computeAllCFGs(module, true, future_flags, boxString(fn), NULL);
assert(module->body[0]->type == AST_TYPE::FunctionDef); assert(module->body[0]->type == AST_TYPE::FunctionDef);
AST_FunctionDef* func = static_cast<AST_FunctionDef*>(module->body[0]); AST_FunctionDef* func = static_cast<AST_FunctionDef*>(module->body[0]);
...@@ -44,11 +45,12 @@ TEST_F(AnalysisTest, augassign) { ...@@ -44,11 +45,12 @@ TEST_F(AnalysisTest, augassign) {
ASSERT_NE(scope_info->getScopeTypeOfName(module->interned_strings->get("a")), ScopeInfo::VarScopeType::GLOBAL); ASSERT_NE(scope_info->getScopeTypeOfName(module->interned_strings->get("a")), ScopeInfo::VarScopeType::GLOBAL);
ASSERT_FALSE(scope_info->getScopeTypeOfName(module->interned_strings->get("b")) == ScopeInfo::VarScopeType::GLOBAL); ASSERT_FALSE(scope_info->getScopeTypeOfName(module->interned_strings->get("b")) == ScopeInfo::VarScopeType::GLOBAL);
ParamNames param_names(func, *module->interned_strings.get()); AST_arguments* args = new AST_arguments();
ParamNames param_names(args, *module->interned_strings.get());
// Hack to get at the cfg: // Hack to get at the cfg:
auto node = module->code->source->cfg->blocks[0]->body[0]; auto node = module_code->source->cfg->blocks[0]->body[0];
CFG* cfg = ast_cast<AST_MakeFunction>(ast_cast<AST_Assign>(node)->value)->function_def->code->source->cfg; CFG* cfg = bst_cast<BST_MakeFunction>(bst_cast<BST_Assign>(node)->value)->function_def->code->source->cfg;
std::unique_ptr<LivenessAnalysis> liveness = computeLivenessInfo(cfg); std::unique_ptr<LivenessAnalysis> liveness = computeLivenessInfo(cfg);
auto&& vregs = cfg->getVRegInfo(); auto&& vregs = cfg->getVRegInfo();
...@@ -57,11 +59,11 @@ TEST_F(AnalysisTest, augassign) { ...@@ -57,11 +59,11 @@ TEST_F(AnalysisTest, augassign) {
for (CFGBlock* block : cfg->blocks) { for (CFGBlock* block : cfg->blocks) {
//printf("%d\n", block->idx); //printf("%d\n", block->idx);
if (block->body.back()->type != AST_TYPE::Return) if (block->body.back()->type != BST_TYPE::Return)
ASSERT_TRUE(liveness->isLiveAtEnd(vregs.getVReg(module->interned_strings->get("a")), block)); ASSERT_TRUE(liveness->isLiveAtEnd(vregs.getVReg(module->interned_strings->get("a")), block));
} }
std::unique_ptr<PhiAnalysis> phis = computeRequiredPhis(ParamNames(func, *module->interned_strings.get()), cfg, liveness.get()); std::unique_ptr<PhiAnalysis> phis = computeRequiredPhis(ParamNames(args, *module->interned_strings.get()), cfg, liveness.get());
} }
void doOsrTest(bool is_osr, bool i_maybe_undefined) { void doOsrTest(bool is_osr, bool i_maybe_undefined) {
...@@ -69,7 +71,7 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) { ...@@ -69,7 +71,7 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) {
AST_Module* module = caching_parse_file(fn.c_str(), 0); AST_Module* module = caching_parse_file(fn.c_str(), 0);
assert(module); assert(module);
ParamNames param_names(module, *module->interned_strings.get()); ParamNames param_names(NULL, *module->interned_strings.get());
assert(module->body[0]->type == AST_TYPE::FunctionDef); assert(module->body[0]->type == AST_TYPE::FunctionDef);
AST_FunctionDef* func = static_cast<AST_FunctionDef*>(module->body[0]); AST_FunctionDef* func = static_cast<AST_FunctionDef*>(module->body[0]);
...@@ -79,11 +81,11 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) { ...@@ -79,11 +81,11 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) {
FutureFlags future_flags = getFutureFlags(module->body, fn.c_str()); FutureFlags future_flags = getFutureFlags(module->body, fn.c_str());
computeAllCFGs(module, true, future_flags, boxString(fn), NULL); auto module_code = computeAllCFGs(module, true, future_flags, boxString(fn), NULL);
// Hack to get at the cfg: // Hack to get at the cfg:
auto node = module->code->source->cfg->blocks[0]->body[0]; auto node = module_code->source->cfg->blocks[0]->body[0];
auto code = ast_cast<AST_MakeFunction>(ast_cast<AST_Assign>(node)->value)->function_def->code; auto code = bst_cast<BST_MakeFunction>(bst_cast<BST_Assign>(node)->value)->function_def->code;
CFG* cfg = code->source->cfg; CFG* cfg = code->source->cfg;
std::unique_ptr<LivenessAnalysis> liveness = computeLivenessInfo(cfg); std::unique_ptr<LivenessAnalysis> liveness = computeLivenessInfo(cfg);
...@@ -99,8 +101,8 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) { ...@@ -99,8 +101,8 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) {
ASSERT_EQ(6, loop_backedge->idx); ASSERT_EQ(6, loop_backedge->idx);
ASSERT_EQ(1, loop_backedge->body.size()); ASSERT_EQ(1, loop_backedge->body.size());
ASSERT_EQ(AST_TYPE::Jump, loop_backedge->body[0]->type); ASSERT_EQ(BST_TYPE::Jump, loop_backedge->body[0]->type);
AST_Jump* backedge = ast_cast<AST_Jump>(loop_backedge->body[0]); BST_Jump* backedge = bst_cast<BST_Jump>(loop_backedge->body[0]);
ASSERT_LE(backedge->target->idx, loop_backedge->idx); ASSERT_LE(backedge->target->idx, loop_backedge->idx);
std::unique_ptr<PhiAnalysis> phis; std::unique_ptr<PhiAnalysis> phis;
...@@ -116,7 +118,7 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) { ...@@ -116,7 +118,7 @@ void doOsrTest(bool is_osr, bool i_maybe_undefined) {
entry_descriptor->args[vregs.getVReg(iter_str)] = fake_type; entry_descriptor->args[vregs.getVReg(iter_str)] = fake_type;
phis = computeRequiredPhis(entry_descriptor, liveness.get()); phis = computeRequiredPhis(entry_descriptor, liveness.get());
} else { } else {
phis = computeRequiredPhis(ParamNames(func, *module->interned_strings), cfg, liveness.get()); phis = computeRequiredPhis(ParamNames(func->args, *module->interned_strings), cfg, liveness.get());
} }
// First, verify that we require phi nodes for the block we enter into. // First, verify that we require phi nodes for the block we enter into.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment