Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
P
Pyston
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Boxiang Sun
Pyston
Commits
763cc656
Commit
763cc656
authored
Sep 02, 2016
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
CFG changes
parent
5e76425d
Changes
18
Show whitespace changes
Inline
Side-by-side
Showing
18 changed files
with
666 additions
and
472 deletions
+666
-472
Makefile
Makefile
+0
-1
src/analysis/scoping_analysis.cpp
src/analysis/scoping_analysis.cpp
+7
-0
src/analysis/scoping_analysis.h
src/analysis/scoping_analysis.h
+2
-0
src/codegen/codegen.cpp
src/codegen/codegen.cpp
+8
-18
src/codegen/compvars.cpp
src/codegen/compvars.cpp
+1
-1
src/codegen/cpython_ast.cpp
src/codegen/cpython_ast.cpp
+3
-0
src/codegen/irgen/hooks.cpp
src/codegen/irgen/hooks.cpp
+4
-7
src/core/ast.cpp
src/core/ast.cpp
+4
-19
src/core/ast.h
src/core/ast.h
+1
-10
src/core/bst.cpp
src/core/bst.cpp
+18
-2
src/core/bst.h
src/core/bst.h
+0
-6
src/core/cfg.cpp
src/core/cfg.cpp
+588
-390
src/core/cfg.h
src/core/cfg.h
+2
-1
src/core/types.h
src/core/types.h
+3
-3
src/runtime/exceptions.cpp
src/runtime/exceptions.cpp
+1
-1
test/tests/augassign_analysis.py
test/tests/augassign_analysis.py
+8
-0
test/unittests/CMakeLists.txt
test/unittests/CMakeLists.txt
+1
-0
test/unittests/analysis.cpp
test/unittests/analysis.cpp
+15
-13
No files found.
Makefile
View file @
763cc656
...
@@ -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)
...
...
src/analysis/scoping_analysis.cpp
View file @
763cc656
...
@@ -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?
...
...
src/analysis/scoping_analysis.h
View file @
763cc656
...
@@ -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
);
...
...
src/codegen/codegen.cpp
View file @
763cc656
...
@@ -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
()
{
...
...
src/codegen/compvars.cpp
View file @
763cc656
...
@@ -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"
...
...
src/codegen/cpython_ast.cpp
View file @
763cc656
...
@@ -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
...
...
src/codegen/irgen/hooks.cpp
View file @
763cc656
...
@@ -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
;
...
...
src/core/ast.cpp
View file @
763cc656
...
@@ -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
);
...
...
src/core/ast.h
View file @
763cc656
...
@@ -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
)
...
...
src/core/bst.cpp
View file @
763cc656
...
@@ -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
);
visit
Vector
(
this
->
body
,
v
);
visit
CFG
(
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
);
visit
Vector
(
body
,
v
);
visit
CFG
(
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
;
}
}
...
...
src/core/bst.h
View file @
763cc656
...
@@ -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
)
...
...
src/core/cfg.cpp
View file @
763cc656
...
@@ -34,21 +34,31 @@
...
@@ -34,21 +34,31 @@
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
:
ast_cast
<
AST_Lambda
>
(
ast
)
->
args
;
for
(
int
i
=
0
;
i
<
arguments
->
args
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
arguments
->
args
.
size
();
i
++
)
{
AST_expr
*
arg
=
arguments
->
args
[
i
];
AST_expr
*
arg
=
arguments
->
args
[
i
];
if
(
arg
->
type
==
AST_TYPE
::
Name
)
{
if
(
arg
->
type
==
AST_TYPE
::
Name
)
{
AST_Name
*
name
=
ast_cast
<
AST_Name
>
(
arg
);
AST_Name
*
name
=
ast_cast
<
AST_Name
>
(
arg
);
all_args
.
emplace_back
(
name
);
BST_Name
*
new_name
=
new
BST_Name
(
name
->
id
,
name
->
ctx_type
,
name
->
lineno
,
name
->
col_offset
);
all_args
.
emplace_back
(
new_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
A
ST_Name
(
dot_arg_name
,
AST_TYPE
::
Param
,
arg
->
lineno
,
arg
->
col_offset
);
auto
new_name
=
new
B
ST_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
);
}
}
...
@@ -57,16 +67,17 @@ ParamNames::ParamNames(AST* ast, InternedStringPool& pool)
...
@@ -57,16 +67,17 @@ ParamNames::ParamNames(AST* ast, InternedStringPool& pool)
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
;
}
}
A
ST_Name
*
makeLoad
(
InternedString
id
,
AST
*
node
,
bool
is_kill
=
false
)
{
B
ST_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
(
A
ST_expr
*
value
)
{
void
doReturn
(
B
ST_expr
*
value
)
{
assert
(
value
);
assert
(
value
);
assert
(
curblock
);
assert
(
curblock
);
...
@@ -440,7 +459,7 @@ private:
...
@@ -440,7 +459,7 @@ private:
}
}
}
}
AST_Return
*
node
=
new
A
ST_Return
();
BST_Return
*
node
=
new
B
ST_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
(
A
ST_expr
*
e
)
{
BST_expr
*
callNonzero
(
B
ST_expr
*
e
)
{
AST_LangPrimitive
*
call
=
new
AST_LangPrimitive
(
A
ST_LangPrimitive
::
NONZERO
);
BST_LangPrimitive
*
call
=
new
BST_LangPrimitive
(
B
ST_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
;
}
BST_Str
*
remapStr
(
AST_Str
*
str
)
{
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
;
}
}
AST_expr
*
applyComprehensionCall
(
AST_ListComp
*
node
,
A
ST_Name
*
name
)
{
BST_expr
*
applyComprehensionCall
(
AST_ListComp
*
node
,
B
ST_Name
*
name
)
{
A
ST_expr
*
elt
=
remapExpr
(
node
->
elt
);
B
ST_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
>
A
ST_expr
*
remapComprehension
(
CompType
*
node
)
{
template
<
typename
ResultASTType
,
typename
CompType
>
B
ST_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
);
A
ST_expr
*
remapped_iter
=
remapExpr
(
c
->
iter
);
B
ST_expr
*
remapped_iter
=
remapExpr
(
c
->
iter
);
AST_LangPrimitive
*
iter_call
=
new
AST_LangPrimitive
(
A
ST_LangPrimitive
::
GET_ITER
);
BST_LangPrimitive
*
iter_call
=
new
BST_LangPrimitive
(
B
ST_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
);
A
ST_expr
*
next_attr
=
makeLoadAttribute
(
makeLoad
(
iter_name
,
node
),
internString
(
"next"
),
true
);
B
ST_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
(
A
ST_LangPrimitive
::
HASNEXT
);
BST_LangPrimitive
*
test_call
=
new
BST_LangPrimitive
(
B
ST_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
A
ST_Branch
();
BST_Branch
*
br
=
new
B
ST_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
)
{
A
ST_expr
*
remapped
=
callNonzero
(
remapExpr
(
if_condition
));
B
ST_expr
*
remapped
=
callNonzero
(
remapExpr
(
if_condition
));
AST_Branch
*
br
=
new
A
ST_Branch
();
BST_Branch
*
br
=
new
B
ST_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
);
}
}
A
ST_expr
*
makeNum
(
int
n
)
{
B
ST_expr
*
makeNum
(
int
n
)
{
AST_Num
*
node
=
new
A
ST_Num
();
BST_Num
*
node
=
new
B
ST_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
A
ST_Jump
();
BST_Jump
*
rtn
=
new
B
ST_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
(
A
ST_expr
*
test
)
{
BST_Branch
*
makeBranch
(
B
ST_expr
*
test
)
{
AST_Branch
*
rtn
=
new
A
ST_Branch
();
BST_Branch
*
rtn
=
new
B
ST_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
(
A
ST_expr
*
test
,
CFGBlock
*
iftrue
,
CFGBlock
*
iffalse
)
{
void
pushBranch
(
B
ST_expr
*
test
,
CFGBlock
*
iftrue
,
CFGBlock
*
iffalse
)
{
assert
(
iftrue
->
idx
==
-
1
&&
iffalse
->
idx
==
-
1
);
assert
(
iftrue
->
idx
==
-
1
&&
iffalse
->
idx
==
-
1
);
A
ST_Branch
*
branch
=
makeBranch
(
test
);
B
ST_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
A
ST_Raise
();
auto
raise
=
new
B
ST_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
*
make
AST
LoadAttribute
(
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
,
A
ST_expr
*
arg1
)
{
BST_Call
*
makeCall
(
BST_expr
*
func
,
BST_expr
*
arg0
,
B
ST_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
,
A
ST_expr
*
arg2
)
{
BST_Call
*
makeCall
(
BST_expr
*
func
,
BST_expr
*
arg0
,
BST_expr
*
arg1
,
B
ST_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
,
A
ST_expr
*
right
)
{
BST_Compare
*
makeCompare
(
AST_TYPE
::
AST_TYPE
oper
,
BST_expr
*
left
,
B
ST_expr
*
right
)
{
auto
compare
=
new
A
ST_Compare
();
auto
compare
=
new
B
ST_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
(
A
ST_expr
*
value
)
{
BST_Index
*
makeIndex
(
B
ST_expr
*
value
)
{
auto
index
=
new
A
ST_Index
();
auto
index
=
new
B
ST_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
,
A
ST_slice
*
slice
)
{
BST_Subscript
*
makeSubscript
(
AST_TYPE
::
AST_TYPE
ctx_type
,
BST_expr
*
value
,
B
ST_slice
*
slice
)
{
auto
subscript
=
new
A
ST_Subscript
();
auto
subscript
=
new
B
ST_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
A
ST_Subscript
();
BST_Subscript
*
s_target
=
new
B
ST_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
A
ST_Attribute
();
BST_Attribute
*
a_target
=
new
B
ST_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
A
ST_Tuple
();
BST_Tuple
*
new_target
=
new
B
ST_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
*
make
AST
Expr
(
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
)
+
"_"
);
}
}
A
ST_expr
*
remapAttribute
(
AST_Attribute
*
node
)
{
B
ST_expr
*
remapAttribute
(
AST_Attribute
*
node
)
{
AST_Attribute
*
rtn
=
new
A
ST_Attribute
();
BST_Attribute
*
rtn
=
new
B
ST_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
;
}
}
A
ST_expr
*
remapBinOp
(
AST_BinOp
*
node
)
{
B
ST_expr
*
remapBinOp
(
AST_BinOp
*
node
)
{
AST_BinOp
*
rtn
=
new
A
ST_BinOp
();
BST_BinOp
*
rtn
=
new
B
ST_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
(
A
ST_slice
*
val
)
{
BST_slice
*
_dup
(
B
ST_slice
*
val
)
{
if
(
val
==
nullptr
)
{
if
(
val
==
nullptr
)
{
return
nullptr
;
return
nullptr
;
}
else
if
(
val
->
type
==
A
ST_TYPE
::
Ellipsis
)
{
}
else
if
(
val
->
type
==
B
ST_TYPE
::
Ellipsis
)
{
AST_Ellipsis
*
orig
=
ast_cast
<
A
ST_Ellipsis
>
(
val
);
BST_Ellipsis
*
orig
=
bst_cast
<
B
ST_Ellipsis
>
(
val
);
AST_Ellipsis
*
made
=
new
A
ST_Ellipsis
();
BST_Ellipsis
*
made
=
new
B
ST_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
==
A
ST_TYPE
::
ExtSlice
)
{
}
else
if
(
val
->
type
==
B
ST_TYPE
::
ExtSlice
)
{
AST_ExtSlice
*
orig
=
ast_cast
<
A
ST_ExtSlice
>
(
val
);
BST_ExtSlice
*
orig
=
bst_cast
<
B
ST_ExtSlice
>
(
val
);
AST_ExtSlice
*
made
=
new
A
ST_ExtSlice
();
BST_ExtSlice
*
made
=
new
B
ST_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
(
A
ST_slice
*
item
:
orig
->
dims
)
{
for
(
B
ST_slice
*
item
:
orig
->
dims
)
{
made
->
dims
.
push_back
(
_dup
(
item
));
made
->
dims
.
push_back
(
_dup
(
item
));
}
}
return
made
;
return
made
;
}
else
if
(
val
->
type
==
A
ST_TYPE
::
Index
)
{
}
else
if
(
val
->
type
==
B
ST_TYPE
::
Index
)
{
AST_Index
*
orig
=
ast_cast
<
A
ST_Index
>
(
val
);
BST_Index
*
orig
=
bst_cast
<
B
ST_Index
>
(
val
);
AST_Index
*
made
=
new
A
ST_Index
();
BST_Index
*
made
=
new
B
ST_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
==
A
ST_TYPE
::
Slice
)
{
}
else
if
(
val
->
type
==
B
ST_TYPE
::
Slice
)
{
AST_Slice
*
orig
=
ast_cast
<
A
ST_Slice
>
(
val
);
BST_Slice
*
orig
=
bst_cast
<
B
ST_Slice
>
(
val
);
AST_Slice
*
made
=
new
A
ST_Slice
();
BST_Slice
*
made
=
new
B
ST_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
(
A
ST_expr
*
val
)
{
BST_expr
*
_dup
(
B
ST_expr
*
val
)
{
if
(
val
==
nullptr
)
if
(
val
==
nullptr
)
return
val
;
return
val
;
if
(
val
->
type
==
A
ST_TYPE
::
Name
)
{
if
(
val
->
type
==
B
ST_TYPE
::
Name
)
{
AST_Name
*
orig
=
ast_cast
<
A
ST_Name
>
(
val
);
BST_Name
*
orig
=
bst_cast
<
B
ST_Name
>
(
val
);
A
ST_Name
*
made
=
makeName
(
orig
->
id
,
orig
->
ctx_type
,
orig
->
lineno
,
orig
->
col_offset
);
B
ST_Name
*
made
=
makeName
(
orig
->
id
,
orig
->
ctx_type
,
orig
->
lineno
,
orig
->
col_offset
);
return
made
;
return
made
;
}
else
if
(
val
->
type
==
A
ST_TYPE
::
Num
)
{
}
else
if
(
val
->
type
==
B
ST_TYPE
::
Num
)
{
AST_Num
*
orig
=
ast_cast
<
A
ST_Num
>
(
val
);
BST_Num
*
orig
=
bst_cast
<
B
ST_Num
>
(
val
);
AST_Num
*
made
=
new
A
ST_Num
();
BST_Num
*
made
=
new
B
ST_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
==
A
ST_TYPE
::
Str
)
{
}
else
if
(
val
->
type
==
B
ST_TYPE
::
Str
)
{
AST_Str
*
orig
=
ast_cast
<
A
ST_Str
>
(
val
);
BST_Str
*
orig
=
bst_cast
<
B
ST_Str
>
(
val
);
AST_Str
*
made
=
new
A
ST_Str
();
BST_Str
*
made
=
new
B
ST_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:
}
}
}
}
A
ST_expr
*
remapBoolOp
(
AST_BoolOp
*
node
)
{
B
ST_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
++
)
{
A
ST_expr
*
val
=
remapExpr
(
node
->
values
[
i
]);
B
ST_expr
*
val
=
remapExpr
(
node
->
values
[
i
]);
pushAssign
(
name
,
_dup
(
val
));
pushAssign
(
name
,
_dup
(
val
));
AST_Branch
*
br
=
new
A
ST_Branch
();
BST_Branch
*
br
=
new
B
ST_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
;
}
}
A
ST_expr
*
final_val
=
remapExpr
(
node
->
values
[
node
->
values
.
size
()
-
1
]);
B
ST_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
);
}
}
A
ST_expr
*
remapCall
(
AST_Call
*
node
)
{
B
ST_expr
*
remapCall
(
AST_Call
*
node
)
{
AST_Call
*
rtn
=
new
A
ST_Call
();
BST_Call
*
rtn
=
new
B
ST_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
A
ST_keyword
();
BST_keyword
*
kw
=
new
B
ST_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
;
}
}
A
ST_expr
*
remapClsAttribute
(
AST_ClsAttribute
*
node
)
{
B
ST_expr
*
remapClsAttribute
(
AST_ClsAttribute
*
node
)
{
AST_ClsAttribute
*
rtn
=
new
A
ST_ClsAttribute
();
BST_ClsAttribute
*
rtn
=
new
B
ST_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
;
}
}
A
ST_expr
*
remapCompare
(
AST_Compare
*
node
)
{
B
ST_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
A
ST_Compare
();
BST_Compare
*
rtn
=
new
B
ST_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
();
A
ST_expr
*
left
=
remapExpr
(
node
->
left
);
B
ST_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
));
A
ST_expr
*
right
=
remapExpr
(
node
->
comparators
[
i
]);
B
ST_expr
*
right
=
remapExpr
(
node
->
comparators
[
i
]);
AST_Compare
*
val
=
new
A
ST_Compare
;
BST_Compare
*
val
=
new
B
ST_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
A
ST_Branch
();
BST_Branch
*
br
=
new
B
ST_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:
}
}
}
}
A
ST_expr
*
remapDict
(
AST_Dict
*
node
)
{
B
ST_expr
*
remapDict
(
AST_Dict
*
node
)
{
AST_Dict
*
rtn
=
new
A
ST_Dict
();
BST_Dict
*
rtn
=
new
B
ST_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
++
)
{
A
ST_expr
*
value
=
remapExpr
(
node
->
values
[
i
]);
B
ST_expr
*
value
=
remapExpr
(
node
->
values
[
i
]);
AST_Index
*
index
=
makeIndex
(
node
->
keys
[
i
]
);
BST_Index
*
index
=
makeIndex
(
remapExpr
(
node
->
keys
[
i
])
);
A
ST_Subscript
*
subscript
=
makeSubscript
(
AST_TYPE
::
Store
,
makeLoad
(
dict_name
,
node
,
false
),
index
);
B
ST_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
;
}
A
ST_slice
*
remapExtSlice
(
AST_ExtSlice
*
node
)
{
B
ST_slice
*
remapExtSlice
(
AST_ExtSlice
*
node
)
{
AST_ExtSlice
*
rtn
=
new
A
ST_ExtSlice
();
BST_ExtSlice
*
rtn
=
new
B
ST_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");
}
}
A
ST_expr
*
remapGeneratorExp
(
AST_GeneratorExp
*
node
)
{
B
ST_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
A
ST_expr
*
first
=
remapExpr
(
node
->
generators
[
0
]
->
iter
);
B
ST_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
(
make
AST
Expr
(
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
,
mk
func
);
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
(
make
Expr
(
make
Call
(
setitem
,
node
->
key
,
node
->
value
)));
insert_point
->
push_back
(
make
ASTExpr
(
makeAST
Call
(
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
>
A
ST_expr
*
remapScopedComprehension
(
CompType
*
node
)
{
template
<
typename
ResultType
,
typename
CompType
>
B
ST_expr
*
remapScopedComprehension
(
CompType
*
node
)
{
// See comment in remapGeneratorExp re early vs. late binding.
// See comment in remapGeneratorExp re early vs. late binding.
A
ST_expr
*
first
=
remapExpr
(
node
->
generators
[
0
]
->
iter
);
B
ST_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
(
make
AST
Name
(
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
=
make
Name
(
rtn_name
,
AST_TYPE
::
Load
,
node
->
lineno
,
/* col_offset */
0
,
/* is_kill */
true
);
rtn
->
value
=
make
ASTName
(
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
);
cfgizer
->
runRecursively
(
func
->
function_def
,
func
->
function_def
->
args
,
node
);
// I'm not sure this actually gets used
static
BoxedString
*
comp_name
=
getStaticString
(
"<comperehension>"
);
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
,
mk
func
);
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
);
}
}
A
ST_expr
*
remapIfExp
(
AST_IfExp
*
node
)
{
B
ST_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
);
}
}
A
ST_slice
*
remapIndex
(
AST_Index
*
node
)
{
B
ST_slice
*
remapIndex
(
AST_Index
*
node
)
{
AST_Index
*
rtn
=
new
A
ST_Index
();
BST_Index
*
rtn
=
new
B
ST_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
;
}
}
A
ST_arguments
*
remapArguments
(
AST_arguments
*
args
)
{
B
ST_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
A
ST_arguments
();
auto
rtn
=
new
B
ST_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
;
}
}
A
ST_expr
*
remapList
(
AST_List
*
node
)
{
B
ST_expr
*
remapList
(
AST_List
*
node
)
{
assert
(
node
->
ctx_type
==
AST_TYPE
::
Load
);
assert
(
node
->
ctx_type
==
AST_TYPE
::
Load
);
AST_List
*
rtn
=
new
A
ST_List
();
BST_List
*
rtn
=
new
B
ST_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
;
}
}
A
ST_expr
*
remapRepr
(
AST_Repr
*
node
)
{
B
ST_expr
*
remapRepr
(
AST_Repr
*
node
)
{
AST_Repr
*
rtn
=
new
A
ST_Repr
();
BST_Repr
*
rtn
=
new
B
ST_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
;
}
}
A
ST_expr
*
remapSet
(
AST_Set
*
node
)
{
B
ST_expr
*
remapSet
(
AST_Set
*
node
)
{
AST_Set
*
rtn
=
new
A
ST_Set
();
BST_Set
*
rtn
=
new
B
ST_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
;
}
}
A
ST_slice
*
remapSlice
(
AST_Slice
*
node
)
{
B
ST_slice
*
remapSlice
(
AST_Slice
*
node
)
{
AST_Slice
*
rtn
=
new
A
ST_Slice
();
BST_Slice
*
rtn
=
new
B
ST_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
;
}
}
A
ST_expr
*
remapTuple
(
AST_Tuple
*
node
)
{
B
ST_expr
*
remapTuple
(
AST_Tuple
*
node
)
{
assert
(
node
->
ctx_type
==
AST_TYPE
::
Load
);
assert
(
node
->
ctx_type
==
AST_TYPE
::
Load
);
AST_Tuple
*
rtn
=
new
A
ST_Tuple
();
BST_Tuple
*
rtn
=
new
B
ST_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
;
}
}
A
ST_expr
*
remapSubscript
(
AST_Subscript
*
node
)
{
B
ST_expr
*
remapSubscript
(
AST_Subscript
*
node
)
{
AST_Subscript
*
rtn
=
new
A
ST_Subscript
();
BST_Subscript
*
rtn
=
new
B
ST_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
;
}
}
A
ST_expr
*
remapUnaryOp
(
AST_UnaryOp
*
node
)
{
B
ST_expr
*
remapUnaryOp
(
AST_UnaryOp
*
node
)
{
AST_UnaryOp
*
rtn
=
new
A
ST_UnaryOp
();
BST_UnaryOp
*
rtn
=
new
B
ST_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
;
}
}
A
ST_expr
*
remapYield
(
AST_Yield
*
node
)
{
B
ST_expr
*
remapYield
(
AST_Yield
*
node
)
{
AST_Yield
*
rtn
=
new
A
ST_Yield
();
BST_Yield
*
rtn
=
new
B
ST_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
(
A
ST_LangPrimitive
::
UNCACHE_EXC_INFO
)));
push_back
(
makeExpr
(
new
BST_LangPrimitive
(
B
ST_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
);
}
}
A
ST_slice
*
remapSlice
(
AST_slice
*
node
)
{
B
ST_slice
*
remapSlice
(
AST_slice
*
node
)
{
if
(
node
==
nullptr
)
if
(
node
==
nullptr
)
return
nullptr
;
return
nullptr
;
A
ST_slice
*
rtn
=
nullptr
;
B
ST_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.
A
ST_expr
*
remapExpr
(
AST_expr
*
node
,
bool
wrap_with_assign
=
true
)
{
B
ST_expr
*
remapExpr
(
AST_expr
*
node
,
bool
wrap_with_assign
=
true
)
{
if
(
node
==
NULL
)
if
(
node
==
NULL
)
return
NULL
;
return
NULL
;
A
ST_expr
*
rtn
;
B
ST_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
<
A
ST_List
>
(
ast_cast
<
AST_ListComp
>
(
node
));
rtn
=
remapComprehension
<
B
ST_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
,
A
ST_expr
*
whyexpr
,
CFGBlock
*
then_block
)
{
CFGBlock
*
makeFinallyCont
(
Why
reason
,
B
ST_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
=
a
st_cast
<
BST_Branch
>
(
node
)
->
test
->
type
;
BST_TYPE
::
BST_TYPE
test_type
=
b
st_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
=
a
st_cast
<
BST_Expr
>
(
node
)
->
value
;
auto
expr
=
b
st_cast
<
BST_Expr
>
(
node
)
->
value
;
if
(
expr
->
type
==
BST_TYPE
::
LangPrimitive
)
{
if
(
expr
->
type
==
BST_TYPE
::
LangPrimitive
)
{
auto
lp
=
a
st_cast
<
BST_LangPrimitive
>
(
expr
);
auto
lp
=
b
st_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
=
a
st_cast
<
BST_Assign
>
(
node
);
BST_Assign
*
asgn
=
b
st_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
=
a
st_cast
<
BST_Name
>
(
asgn
->
targets
[
0
]);
BST_Name
*
target
=
b
st_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
&&
a
st_cast
<
BST_Name
>
(
asgn
->
value
)
->
id
.
s
()[
0
]
==
'#'
)
if
(
!
(
asgn
->
value
->
type
==
BST_TYPE
::
Name
&&
b
st_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
,
"
\n
Error: doing a non-trivial assignment in an invoke is not allowed:
\n
"
);
fprintf
(
stdout
,
"
\n
Error: doing a non-trivial assignment in an invoke is not allowed:
\n
"
);
print_
a
st
(
node
);
print_
b
st
(
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
&&
a
st_cast
<
BST_Name
>
(
asgn
->
value
)
->
id
.
s
()[
0
]
==
'#'
)
{
}
else
if
(
asgn
->
value
->
type
==
BST_TYPE
::
Name
&&
b
st_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
&&
a
st_cast
<
BST_Name
>
(
asgn
->
value
)
->
id
.
s
()
==
"None"
))
{
&&
b
st_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
=
a
st_cast
<
BST_Delete
>
(
node
);
BST_Delete
*
del
=
b
st_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
=
a
st_cast
<
BST_Name
>
(
del
->
targets
[
0
]);
BST_Name
*
target
=
b
st_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
,
B
ST_TYPE
::
Store
,
node
->
lineno
));
target
->
elts
.
push_back
(
makeName
(
exc_info
.
exc_type_name
,
A
ST_TYPE
::
Store
,
node
->
lineno
));
target
->
elts
.
push_back
(
makeName
(
exc_info
.
exc_value_name
,
B
ST_TYPE
::
Store
,
node
->
lineno
));
target
->
elts
.
push_back
(
makeName
(
exc_info
.
exc_value_name
,
A
ST_TYPE
::
Store
,
node
->
lineno
));
target
->
elts
.
push_back
(
makeName
(
exc_info
.
exc_traceback_name
,
B
ST_TYPE
::
Store
,
node
->
lineno
));
target
->
elts
.
push_back
(
makeName
(
exc_info
.
exc_traceback_name
,
A
ST_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
A
ST_MakeClass
(
def
));
pushAssign
(
tmp
,
new
B
ST_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
A
ST_FunctionDef
();
auto
def
=
new
B
ST_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
A
ST_MakeFunction
(
def
));
pushAssign
(
tmp
,
new
B
ST_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
(
A
ST_LangPrimitive
::
IMPORT_NAME
);
BST_LangPrimitive
*
import
=
new
BST_LangPrimitive
(
B
ST_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
A
ST_Num
());
import
->
args
.
push_back
(
new
B
ST_Num
());
static_cast
<
A
ST_Num
*>
(
import
->
args
[
0
])
->
num_type
=
AST_Num
::
INT
;
static_cast
<
B
ST_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
<
A
ST_Num
*>
(
import
->
args
[
0
])
->
n_int
=
level
;
static_cast
<
B
ST_Num
*>
(
import
->
args
[
0
])
->
n_int
=
level
;
import
->
args
.
push_back
(
new
AST_LangPrimitive
(
A
ST_LangPrimitive
::
NONE
));
import
->
args
.
push_back
(
new
BST_LangPrimitive
(
B
ST_LangPrimitive
::
NONE
));
import
->
args
.
push_back
(
new
A
ST_Str
(
a
->
name
.
s
()));
import
->
args
.
push_back
(
new
B
ST_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
A
ST_Attribute
(
makeLoad
(
tmpname
,
node
,
true
),
AST_TYPE
::
Load
,
auto
attr
=
new
B
ST_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
(
A
ST_LangPrimitive
::
IMPORT_NAME
);
BST_LangPrimitive
*
import
=
new
BST_LangPrimitive
(
B
ST_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
A
ST_Num
());
import
->
args
.
push_back
(
new
B
ST_Num
());
static_cast
<
A
ST_Num
*>
(
import
->
args
[
0
])
->
num_type
=
AST_Num
::
INT
;
static_cast
<
B
ST_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
<
A
ST_Num
*>
(
import
->
args
[
0
])
->
n_int
=
level
;
static_cast
<
B
ST_Num
*>
(
import
->
args
[
0
])
->
n_int
=
level
;
import
->
args
.
push_back
(
new
A
ST_Tuple
());
import
->
args
.
push_back
(
new
B
ST_Tuple
());
static_cast
<
A
ST_Tuple
*>
(
import
->
args
[
1
])
->
ctx_type
=
AST_TYPE
::
Load
;
static_cast
<
B
ST_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
A
ST_Str
(
node
->
names
[
i
]
->
name
.
s
()));
static_cast
<
BST_Tuple
*>
(
import
->
args
[
1
])
->
elts
.
push_back
(
new
B
ST_Str
(
node
->
names
[
i
]
->
name
.
s
()));
}
}
import
->
args
.
push_back
(
new
A
ST_Str
(
node
->
module
.
s
()));
import
->
args
.
push_back
(
new
B
ST_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
(
A
ST_LangPrimitive
::
IMPORT_STAR
);
BST_LangPrimitive
*
import_star
=
new
BST_LangPrimitive
(
B
ST_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
A
ST_Expr
();
BST_Expr
*
import_star_expr
=
new
B
ST_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
(
A
ST_LangPrimitive
::
IMPORT_FROM
);
BST_LangPrimitive
*
import_from
=
new
BST_LangPrimitive
(
B
ST_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
A
ST_Str
(
a
->
name
.
s
()));
import_from
->
args
.
push_back
(
new
B
ST_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
A
ST_Branch
();
BST_Branch
*
br
=
new
B
ST_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
A
ST_Assert
();
BST_Assert
*
remapped
=
new
B
ST_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
A
ST_Num
();
BST_Num
*
fake_test
=
new
B
ST_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
{
A
ST_expr
*
remapped_value
=
remapExpr
(
node
->
value
);
B
ST_expr
*
remapped_value
=
remapExpr
(
node
->
value
);
for
(
int
i
=
0
;
i
<
node
->
targets
.
size
();
i
++
)
{
for
(
int
i
=
0
;
i
<
node
->
targets
.
size
();
i
++
)
{
A
ST_expr
*
val
;
B
ST_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
A
ST_expr
*
remapped_target
;
B
ST_expr
*
remapped_target
;
A
ST_expr
*
remapped_lhs
;
B
ST_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
A
ST_Subscript
();
BST_Subscript
*
s_target
=
new
B
ST_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
A
ST_Subscript
();
BST_Subscript
*
s_lhs
=
new
B
ST_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
A
ST_Attribute
();
BST_Attribute
*
a_target
=
new
B
ST_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
A
ST_Attribute
();
BST_Attribute
*
a_lhs
=
new
B
ST_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
A
ST_AugBinOp
();
BST_AugBinOp
*
binop
=
new
B
ST_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
A
ST_Delete
();
BST_Delete
*
astdel
=
new
B
ST_Delete
();
astdel
->
lineno
=
node
->
lineno
;
astdel
->
lineno
=
node
->
lineno
;
astdel
->
col_offset
=
node
->
col_offset
;
astdel
->
col_offset
=
node
->
col_offset
;
A
ST_expr
*
target
=
NULL
;
B
ST_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
A
ST_Subscript
();
BST_Subscript
*
astsubs
=
new
B
ST_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
<
A
ST_Attribute
*>
(
remapExpr
(
t
,
false
));
BST_Attribute
*
astattr
=
static_cast
<
B
ST_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
A
ST_Expr
();
BST_Expr
*
remapped
=
new
B
ST_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
{
A
ST_expr
*
dest
=
remapExpr
(
node
->
dest
);
B
ST_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
A
ST_Print
();
BST_Print
*
remapped
=
new
B
ST_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
A
ST_Print
();
BST_Print
*
final
=
new
B
ST_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
A
ST_Branch
();
BST_Branch
*
br
=
new
B
ST_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
A
ST_Exec
();
BST_Exec
*
astexec
=
new
B
ST_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
;
A
ST_Branch
*
br
=
makeBranch
(
remapExpr
(
node
->
test
));
B
ST_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
;
}
}
A
ST_stmt
*
makeKill
(
InternedString
name
)
{
B
ST_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
A
ST_Delete
();
auto
del
=
new
B
ST_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.
A
ST_expr
*
remapped_iter
=
remapExpr
(
node
->
iter
);
B
ST_expr
*
remapped_iter
=
remapExpr
(
node
->
iter
);
AST_LangPrimitive
*
iter_call
=
new
AST_LangPrimitive
(
A
ST_LangPrimitive
::
GET_ITER
);
BST_LangPrimitive
*
iter_call
=
new
BST_LangPrimitive
(
B
ST_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
);
A
ST_expr
*
next_attr
=
makeLoadAttribute
(
makeLoad
(
itername
,
node
),
internString
(
"next"
),
true
);
B
ST_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
(
A
ST_LangPrimitive
::
HASNEXT
);
BST_LangPrimitive
*
test_call
=
new
BST_LangPrimitive
(
B
ST_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
(
A
ST_LangPrimitive
::
HASNEXT
);
BST_LangPrimitive
*
end_call
=
new
BST_LangPrimitive
(
B
ST_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
A
ST_Raise
();
BST_Raise
*
remapped
=
new
B
ST_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
)
{
A
ST_expr
*
handled_type
=
remapExpr
(
exc_handler
->
type
);
B
ST_expr
*
handled_type
=
remapExpr
(
exc_handler
->
type
);
AST_LangPrimitive
*
is_caught_here
=
new
AST_LangPrimitive
(
A
ST_LangPrimitive
::
CHECK_EXC_MATCH
);
BST_LangPrimitive
*
is_caught_here
=
new
BST_LangPrimitive
(
B
ST_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
A
ST_Branch
();
BST_Branch
*
br
=
new
B
ST_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
(
A
ST_LangPrimitive
::
SET_EXC_INFO
);
BST_LangPrimitive
*
set_exc_info
=
new
BST_LangPrimitive
(
B
ST_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
A
ST_Raise
();
BST_Raise
*
raise
=
new
B
ST_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.
A
ST_expr
*
exit
=
makeLoadAttribute
(
makeLoad
(
ctxmgrname
,
node
),
internString
(
"__exit__"
),
true
);
B
ST_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?
A
ST_expr
*
enter
=
makeLoadAttribute
(
makeLoad
(
ctxmgrname
,
node
,
true
),
internString
(
"__enter__"
),
true
);
B
ST_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
Noop
A
STVisitor
{
class
AssignVRegsVisitor
:
public
Noop
B
STVisitor
{
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
(
A
ST_alias
*
node
)
override
{
RELEASE_ASSERT
(
0
,
"these should be removed by the cfg"
);
}
bool
visit_alias
(
B
ST_alias
*
node
)
override
{
RELEASE_ASSERT
(
0
,
"these should be removed by the cfg"
);
}
bool
visit_arguments
(
A
ST_arguments
*
node
)
override
{
bool
visit_arguments
(
B
ST_arguments
*
node
)
override
{
for
(
A
ST_expr
*
d
:
node
->
defaults
)
for
(
B
ST_expr
*
d
:
node
->
defaults
)
d
->
accept
(
this
);
d
->
accept
(
this
);
return
true
;
return
true
;
}
}
bool
visit_classdef
(
A
ST_ClassDef
*
node
)
override
{
bool
visit_classdef
(
B
ST_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
(
A
ST_FunctionDef
*
node
)
override
{
bool
visit_functiondef
(
B
ST_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
(
A
ST_Lambda
*
node
)
override
{
bool
visit_lambda
(
B
ST_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
(
A
ST_Name
*
node
)
override
{
bool
visit_name
(
B
ST_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
(
A
ST_stmt
*
stmt
:
b
->
body
)
{
for
(
B
ST_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
A
ST_Assign
();
BST_Assign
*
module_assign
=
new
B
ST_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
A
ST_Assign
();
BST_Assign
*
doc_assign
=
new
B
ST_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
));
A
ST_Name
*
arg_name_expr
B
ST_Name
*
arg_name_expr
=
new
A
ST_Name
(
arg_name
,
AST_TYPE
::
Load
,
arg_expr
->
lineno
,
arg_expr
->
col_offset
);
=
new
B
ST_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
(
A
ST_LangPrimitive
::
LOCALS
);
BST_LangPrimitive
*
locals
=
new
BST_LangPrimitive
(
B
ST_LangPrimitive
::
LOCALS
);
AST_Return
*
rtn
=
new
A
ST_Return
();
BST_Return
*
rtn
=
new
B
ST_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
A
ST_Return
();
BST_Return
*
return_stmt
=
new
B
ST_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
)
{
A
ST_stmt
*
terminator
=
b
->
body
.
back
();
B
ST_stmt
*
terminator
=
b
->
body
.
back
();
assert
(
terminator
->
type
==
AST_TYPE
::
Return
||
terminator
->
type
==
A
ST_TYPE
::
Raise
assert
(
terminator
->
type
==
BST_TYPE
::
Return
||
terminator
->
type
==
B
ST_TYPE
::
Raise
||
terminator
->
type
==
AST_TYPE
::
Raise
||
terminator
->
type
==
A
ST_TYPE
::
Assert
);
||
terminator
->
type
==
BST_TYPE
::
Raise
||
terminator
->
type
==
B
ST_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
<
A
ST
*>
flattened
;
std
::
vector
<
B
ST
*>
flattened
;
for
(
auto
b
:
rtn
->
blocks
)
for
(
auto
b
:
rtn
->
blocks
)
flatten
(
b
->
body
,
flattened
,
true
);
flatten
(
b
->
body
,
flattened
,
true
);
std
::
unordered_map
<
A
ST
*
,
int
>
deduped
;
std
::
unordered_map
<
B
ST
*
,
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_
a
st
(
e
);
print_
b
st
(
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
::
A
ST_TYPE
end_ast_type
=
b
->
body
[
b
->
body
.
size
()
-
1
]
->
type
;
BST_TYPE
::
B
ST_TYPE
end_ast_type
=
b
->
body
[
b
->
body
.
size
()
-
1
]
->
type
;
assert
(
end_ast_type
==
AST_TYPE
::
Jump
||
end_ast_type
==
A
ST_TYPE
::
Invoke
);
assert
(
end_ast_type
==
BST_TYPE
::
Jump
||
end_ast_type
==
B
ST_TYPE
::
Invoke
);
if
(
end_ast_type
==
A
ST_TYPE
::
Invoke
)
{
if
(
end_ast_type
==
B
ST_TYPE
::
Invoke
)
{
// TODO probably shouldn't be generating these anyway:
// TODO probably shouldn't be generating these anyway:
auto
invoke
=
ast_cast
<
A
ST_Invoke
>
(
b
->
body
.
back
());
auto
invoke
=
bst_cast
<
B
ST_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
)
{
...
...
src/core/cfg.h
View file @
763cc656
...
@@ -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
);
}
}
...
...
src/core/types.h
View file @
763cc656
...
@@ -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
B
ST_arguments
;
class
A
ST_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
();
};
};
...
...
src/runtime/exceptions.cpp
View file @
763cc656
...
@@ -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"
...
...
test/tests/augassign_analysis.py
View file @
763cc656
...
@@ -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
()
test/unittests/CMakeLists.txt
View file @
763cc656
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
}
)
...
...
test/unittests/analysis.cpp
View file @
763cc656
...
@@ -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
<
A
ST_Assign
>
(
node
)
->
value
)
->
function_def
->
code
->
source
->
cfg
;
CFG
*
cfg
=
bst_cast
<
BST_MakeFunction
>
(
bst_cast
<
B
ST_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
!=
A
ST_TYPE
::
Return
)
if
(
block
->
body
.
back
()
->
type
!=
B
ST_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
<
A
ST_Assign
>
(
node
)
->
value
)
->
function_def
->
code
;
auto
code
=
bst_cast
<
BST_MakeFunction
>
(
bst_cast
<
B
ST_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
(
A
ST_TYPE
::
Jump
,
loop_backedge
->
body
[
0
]
->
type
);
ASSERT_EQ
(
B
ST_TYPE
::
Jump
,
loop_backedge
->
body
[
0
]
->
type
);
AST_Jump
*
backedge
=
ast_cast
<
A
ST_Jump
>
(
loop_backedge
->
body
[
0
]);
BST_Jump
*
backedge
=
bst_cast
<
B
ST_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.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment