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
7efd8225
Commit
7efd8225
authored
May 16, 2014
by
Kevin Modzelewski
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Exceptions part #2: AST and CFG support
parent
a4b0c853
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
391 additions
and
63 deletions
+391
-63
src/Makefile
src/Makefile
+1
-1
src/analysis/function_analysis.cpp
src/analysis/function_analysis.cpp
+2
-0
src/analysis/scoping_analysis.cpp
src/analysis/scoping_analysis.cpp
+5
-0
src/analysis/type_analysis.cpp
src/analysis/type_analysis.cpp
+24
-0
src/codegen/dis.cpp
src/codegen/dis.cpp
+6
-1
src/codegen/opt/dead_allocs.cpp
src/codegen/opt/dead_allocs.cpp
+2
-2
src/codegen/opt/escape_analysis.cpp
src/codegen/opt/escape_analysis.cpp
+3
-3
src/codegen/parser.cpp
src/codegen/parser.cpp
+16
-12
src/core/ast.cpp
src/core/ast.cpp
+76
-0
src/core/ast.h
src/core/ast.h
+48
-1
src/core/cfg.cpp
src/core/cfg.cpp
+208
-42
src/core/types.h
src/core/types.h
+0
-1
No files found.
src/Makefile
View file @
7efd8225
...
...
@@ -283,7 +283,7 @@ $(UNITTEST_DIR)/$1: $(GTEST_DIR)/src/gtest-all.o $(NON_ENTRY_OBJS) $(BUILD_SYSTE
$(ECHO)
Linking
$$
@
$(VERB)
$(CXX)
$(NON_ENTRY_OBJS)
$(GTEST_DIR)
/src/gtest-all.o
$(GTEST_DIR)
/src/gtest_main.o
$(UNITTEST_DIR)
/
$1
.o
$(LDFLAGS)
-o
$$
@
dbg_$1_unittests
:
$(UNITTEST_DIR)/$1
zsh
-c
'ulimit -v
$(MAX_MEM_KB)
; ulimit -d
$(MAX_MEM_KB)
; time
gdb
$(GDB_CMDS)
--args ./
$(UNITTEST_DIR)
/$1 --gtest_break_on_failure
$(ARGS)
'
zsh
-c
'ulimit -v
$(MAX_MEM_KB)
; ulimit -d
$(MAX_MEM_KB)
; time
$(GDB)
$(GDB_CMDS)
--args ./
$(UNITTEST_DIR)
/$1 --gtest_break_on_failure
$(ARGS)
'
run_$1_unittests
:
$(UNITTEST_DIR)/$1
zsh
-c
'ulimit -v
$(MAX_MEM_KB)
; ulimit -d
$(MAX_MEM_KB)
; time ./
$(UNITTEST_DIR)
/$1
$(ARGS)
'
run_unittests
::
run_$1_unittests
...
...
src/analysis/function_analysis.cpp
View file @
7efd8225
...
...
@@ -177,9 +177,11 @@ public:
virtual
bool
visit_branch
(
AST_Branch
*
node
)
{
return
true
;
}
virtual
bool
visit_expr
(
AST_Expr
*
node
)
{
return
true
;
}
virtual
bool
visit_global
(
AST_Global
*
node
)
{
return
true
;
}
virtual
bool
visit_invoke
(
AST_Invoke
*
node
)
{
return
false
;
}
virtual
bool
visit_jump
(
AST_Jump
*
node
)
{
return
true
;
}
virtual
bool
visit_pass
(
AST_Pass
*
node
)
{
return
true
;
}
virtual
bool
visit_print
(
AST_Print
*
node
)
{
return
true
;
}
virtual
bool
visit_raise
(
AST_Raise
*
node
)
{
return
true
;
}
virtual
bool
visit_return
(
AST_Return
*
node
)
{
return
true
;
}
virtual
bool
visit_classdef
(
AST_ClassDef
*
node
)
{
...
...
src/analysis/scoping_analysis.cpp
View file @
7efd8225
...
...
@@ -145,6 +145,7 @@ public:
}
virtual
bool
visit_arguments
(
AST_arguments
*
node
)
{
return
false
;
}
virtual
bool
visit_assert
(
AST_Assert
*
node
)
{
return
false
;
}
virtual
bool
visit_assign
(
AST_Assign
*
node
)
{
return
false
;
}
virtual
bool
visit_augassign
(
AST_AugAssign
*
node
)
{
return
false
;
}
virtual
bool
visit_attribute
(
AST_Attribute
*
node
)
{
return
false
;
}
...
...
@@ -157,6 +158,7 @@ public:
// virtual bool visit_classdef(AST_ClassDef *node) { return false; }
virtual
bool
visit_continue
(
AST_Continue
*
node
)
{
return
false
;
}
virtual
bool
visit_dict
(
AST_Dict
*
node
)
{
return
false
;
}
virtual
bool
visit_excepthandler
(
AST_ExceptHandler
*
node
)
{
return
false
;
}
virtual
bool
visit_expr
(
AST_Expr
*
node
)
{
return
false
;
}
virtual
bool
visit_for
(
AST_For
*
node
)
{
return
false
;
}
// virtual bool visit_functiondef(AST_FunctionDef *node) { return false; }
...
...
@@ -172,11 +174,14 @@ public:
virtual
bool
visit_num
(
AST_Num
*
node
)
{
return
false
;
}
virtual
bool
visit_pass
(
AST_Pass
*
node
)
{
return
false
;
}
virtual
bool
visit_print
(
AST_Print
*
node
)
{
return
false
;
}
virtual
bool
visit_raise
(
AST_Raise
*
node
)
{
return
false
;
}
virtual
bool
visit_repr
(
AST_Repr
*
node
)
{
return
false
;
}
virtual
bool
visit_return
(
AST_Return
*
node
)
{
return
false
;
}
virtual
bool
visit_slice
(
AST_Slice
*
node
)
{
return
false
;
}
virtual
bool
visit_str
(
AST_Str
*
node
)
{
return
false
;
}
virtual
bool
visit_subscript
(
AST_Subscript
*
node
)
{
return
false
;
}
virtual
bool
visit_tryexcept
(
AST_TryExcept
*
node
)
{
return
false
;
}
virtual
bool
visit_tryfinally
(
AST_TryFinally
*
node
)
{
return
false
;
}
virtual
bool
visit_tuple
(
AST_Tuple
*
node
)
{
return
false
;
}
virtual
bool
visit_unaryop
(
AST_UnaryOp
*
node
)
{
return
false
;
}
virtual
bool
visit_while
(
AST_While
*
node
)
{
return
false
;
}
...
...
src/analysis/type_analysis.cpp
View file @
7efd8225
...
...
@@ -329,6 +329,17 @@ private:
virtual
void
*
visit_index
(
AST_Index
*
node
)
{
return
getType
(
node
->
value
);
}
virtual
void
*
visit_langprimitive
(
AST_LangPrimitive
*
node
)
{
switch
(
node
->
opcode
)
{
case
AST_LangPrimitive
:
:
ISINSTANCE
:
return
BOOL
;
case
AST_LangPrimitive
:
:
LANDINGPAD
:
return
UNKNOWN
;
default:
RELEASE_ASSERT
(
0
,
"%d"
,
node
->
opcode
);
}
}
virtual
void
*
visit_list
(
AST_List
*
node
)
{
// Get all the sub-types, even though they're not necessary to
// determine the expression type, so that things like speculations
...
...
@@ -459,6 +470,8 @@ private:
visit_alias
(
alias
);
}
virtual
void
visit_invoke
(
AST_Invoke
*
node
)
{
node
->
stmt
->
accept_stmt
(
this
);
}
virtual
void
visit_jump
(
AST_Jump
*
node
)
{}
virtual
void
visit_pass
(
AST_Pass
*
node
)
{}
...
...
@@ -473,6 +486,17 @@ private:
}
}
virtual
void
visit_raise
(
AST_Raise
*
node
)
{
if
(
EXPAND_UNNEEDED
)
{
if
(
node
->
arg0
)
getType
(
node
->
arg0
);
if
(
node
->
arg1
)
getType
(
node
->
arg1
);
if
(
node
->
arg2
)
getType
(
node
->
arg2
);
}
}
virtual
void
visit_return
(
AST_Return
*
node
)
{
if
(
EXPAND_UNNEEDED
)
{
if
(
node
->
value
!=
NULL
)
...
...
src/codegen/dis.cpp
View file @
7efd8225
...
...
@@ -144,6 +144,7 @@ void PystonJITEventListener::NotifyObjectEmitted(const llvm::ObjectImage& Obj) {
code
=
I
->
getName
(
name
);
assert
(
!
code
);
uint64_t
address
,
size
;
const
char
*
type
=
"unknown"
;
bool
b
;
code
=
I
->
isText
(
b
);
...
...
@@ -162,7 +163,11 @@ void PystonJITEventListener::NotifyObjectEmitted(const llvm::ObjectImage& Obj) {
assert
(
!
code
);
if
(
b
)
type
=
"rodata"
;
printf
(
"Section: %s %s
\n
"
,
name
.
data
(),
type
);
code
=
I
->
getAddress
(
address
);
assert
(
!
code
);
code
=
I
->
getSize
(
size
);
assert
(
!
code
);
printf
(
"Section: %s %s (%lx %lx)
\n
"
,
name
.
data
(),
type
,
address
,
size
);
#if LLVMREV < 200442
I
=
I
.
increment
(
code
);
...
...
src/codegen/opt/dead_allocs.cpp
View file @
7efd8225
...
...
@@ -104,9 +104,9 @@ private:
continue
;
}
if
(
CallInst
*
si
=
dyn_cast
<
Call
Inst
>
(
user
))
{
if
(
llvm
::
isa
<
CallInst
>
(
user
)
||
llvm
::
isa
<
Invoke
Inst
>
(
user
))
{
if
(
VERBOSITY
()
>=
2
)
errs
()
<<
"Not dead; used here: "
<<
*
si
<<
'\n'
;
errs
()
<<
"Not dead; used here: "
<<
*
user
<<
'\n'
;
return
true
;
}
...
...
src/codegen/opt/escape_analysis.cpp
View file @
7efd8225
...
...
@@ -132,10 +132,10 @@ bool EscapeAnalysis::runOnFunction(Function& F) {
continue
;
}
if
(
CallInst
*
si
=
dyn_cast
<
Call
Inst
>
(
user
))
{
if
(
llvm
::
isa
<
CallInst
>
(
user
)
||
llvm
::
isa
<
Invoke
Inst
>
(
user
))
{
if
(
VERBOSITY
()
>=
2
)
errs
()
<<
"Escapes here: "
<<
*
si
<<
'\n'
;
chain
->
escape_points
.
insert
(
si
);
errs
()
<<
"Escapes here: "
<<
*
user
<<
'\n'
;
chain
->
escape_points
.
insert
(
dyn_cast
<
Instruction
>
(
user
)
);
continue
;
}
...
...
src/codegen/parser.cpp
View file @
7efd8225
...
...
@@ -790,12 +790,24 @@ AST* readASTMisc(BufferedReader* reader) {
}
}
static
std
::
string
getParserCommandLine
(
const
char
*
fn
)
{
llvm
::
SmallString
<
128
>
parse_ast_fn
;
// TODO supposed to pass argv0, main_addr to this function:
parse_ast_fn
=
llvm
::
sys
::
fs
::
getMainExecutable
(
NULL
,
NULL
);
assert
(
parse_ast_fn
.
size
()
&&
"could not find the path to the pyston src dir"
);
while
(
llvm
::
sys
::
path
::
filename
(
parse_ast_fn
)
!=
"pyston"
)
{
llvm
::
sys
::
path
::
remove_filename
(
parse_ast_fn
);
}
llvm
::
sys
::
path
::
append
(
parse_ast_fn
,
"src/codegen/parse_ast.py"
);
return
std
::
string
(
"python -S "
)
+
parse_ast_fn
.
str
().
str
()
+
" "
+
fn
;
}
AST_Module
*
parse
(
const
char
*
fn
)
{
Timer
_t
(
"parsing"
);
std
::
string
cmdline
=
"python codegen/parse_ast.py "
;
cmdline
+=
fn
;
FILE
*
fp
=
popen
(
cmdline
.
c_str
(),
"r"
);
FILE
*
fp
=
popen
(
getParserCommandLine
(
fn
).
c_str
(),
"r"
);
BufferedReader
*
reader
=
new
BufferedReader
(
fp
);
AST
*
rtn
=
readASTMisc
(
reader
);
...
...
@@ -820,15 +832,7 @@ AST_Module* parse(const char* fn) {
#define LENGTH_SUFFIX_LENGTH 4
static
void
_reparse
(
const
char
*
fn
,
const
std
::
string
&
cache_fn
)
{
llvm
::
SmallString
<
128
>
parse_ast_fn
;
// TODO supposed to pass argv0, main_addr to this function:
parse_ast_fn
=
llvm
::
sys
::
fs
::
getMainExecutable
(
NULL
,
NULL
);
assert
(
parse_ast_fn
.
size
()
&&
"could not find the path to the pyston src dir"
);
llvm
::
sys
::
path
::
remove_filename
(
parse_ast_fn
);
llvm
::
sys
::
path
::
append
(
parse_ast_fn
,
"codegen/parse_ast.py"
);
std
::
string
cmdline
=
std
::
string
(
"python -S "
)
+
parse_ast_fn
.
str
().
str
()
+
" "
+
fn
;
FILE
*
parser
=
popen
(
cmdline
.
c_str
(),
"r"
);
FILE
*
parser
=
popen
(
getParserCommandLine
(
fn
).
c_str
(),
"r"
);
FILE
*
cache_fp
=
fopen
(
cache_fn
.
c_str
(),
"w"
);
assert
(
cache_fp
);
...
...
src/core/ast.cpp
View file @
7efd8225
...
...
@@ -513,6 +513,18 @@ void* AST_Index::accept_expr(ExprVisitor* v) {
return
v
->
visit_index
(
this
);
}
void
AST_Invoke
::
accept
(
ASTVisitor
*
v
)
{
bool
skip
=
v
->
visit_invoke
(
this
);
if
(
skip
)
return
;
this
->
stmt
->
accept
(
v
);
}
void
AST_Invoke
::
accept_stmt
(
StmtVisitor
*
v
)
{
return
v
->
visit_invoke
(
this
);
}
void
AST_keyword
::
accept
(
ASTVisitor
*
v
)
{
bool
skip
=
v
->
visit_keyword
(
this
);
if
(
skip
)
...
...
@@ -521,6 +533,18 @@ void AST_keyword::accept(ASTVisitor* v) {
value
->
accept
(
v
);
}
void
AST_LangPrimitive
::
accept
(
ASTVisitor
*
v
)
{
bool
skip
=
v
->
visit_langprimitive
(
this
);
if
(
skip
)
return
;
visitVector
(
args
,
v
);
}
void
*
AST_LangPrimitive
::
accept_expr
(
ExprVisitor
*
v
)
{
return
v
->
visit_langprimitive
(
this
);
}
void
AST_List
::
accept
(
ASTVisitor
*
v
)
{
bool
skip
=
v
->
visit_list
(
this
);
if
(
skip
)
...
...
@@ -1175,6 +1199,38 @@ bool PrintVisitor::visit_index(AST_Index* node) {
return
false
;
}
bool
PrintVisitor
::
visit_invoke
(
AST_Invoke
*
node
)
{
// printf("invoke: ");
// node->value->accept(this);
// printf("; on success goto %d; on error goto %d", node->normal_dest->idx, node->exc_dest->idx);
printf
(
"invoke %d %d: "
,
node
->
normal_dest
->
idx
,
node
->
exc_dest
->
idx
);
node
->
stmt
->
accept
(
this
);
return
true
;
}
bool
PrintVisitor
::
visit_langprimitive
(
AST_LangPrimitive
*
node
)
{
printf
(
":"
);
switch
(
node
->
opcode
)
{
case
AST_LangPrimitive
:
:
ISINSTANCE
:
printf
(
"isinstance"
);
break
;
case
AST_LangPrimitive
:
:
LANDINGPAD
:
printf
(
"landingpad"
);
break
;
default:
RELEASE_ASSERT
(
0
,
"%d"
,
node
->
opcode
);
}
printf
(
"("
);
for
(
int
i
=
0
,
n
=
node
->
args
.
size
();
i
<
n
;
++
i
)
{
if
(
i
>
0
)
printf
(
", "
);
node
->
args
[
i
]
->
accept
(
this
);
}
printf
(
")"
);
return
true
;
}
bool
PrintVisitor
::
visit_list
(
AST_List
*
node
)
{
printf
(
"["
);
for
(
int
i
=
0
,
n
=
node
->
elts
.
size
();
i
<
n
;
++
i
)
{
...
...
@@ -1548,6 +1604,10 @@ public:
output
->
push_back
(
node
);
return
false
;
}
virtual
bool
visit_excepthandler
(
AST_ExceptHandler
*
node
)
{
output
->
push_back
(
node
);
return
false
;
}
virtual
bool
visit_expr
(
AST_Expr
*
node
)
{
output
->
push_back
(
node
);
return
false
;
...
...
@@ -1588,6 +1648,10 @@ public:
output
->
push_back
(
node
);
return
false
;
}
virtual
bool
visit_langprimitive
(
AST_LangPrimitive
*
node
)
{
output
->
push_back
(
node
);
return
false
;
}
virtual
bool
visit_list
(
AST_List
*
node
)
{
output
->
push_back
(
node
);
return
false
;
...
...
@@ -1616,6 +1680,10 @@ public:
output
->
push_back
(
node
);
return
false
;
}
virtual
bool
visit_raise
(
AST_Raise
*
node
)
{
output
->
push_back
(
node
);
return
false
;
}
virtual
bool
visit_repr
(
AST_Repr
*
node
)
{
output
->
push_back
(
node
);
return
false
;
...
...
@@ -1636,6 +1704,14 @@ public:
output
->
push_back
(
node
);
return
false
;
}
virtual
bool
visit_tryexcept
(
AST_TryExcept
*
node
)
{
output
->
push_back
(
node
);
return
false
;
}
virtual
bool
visit_tryfinally
(
AST_TryFinally
*
node
)
{
output
->
push_back
(
node
);
return
false
;
}
virtual
bool
visit_tuple
(
AST_Tuple
*
node
)
{
output
->
push_back
(
node
);
return
false
;
...
...
src/core/ast.h
View file @
7efd8225
...
...
@@ -120,6 +120,8 @@ enum AST_TYPE {
Jump
=
201
,
ClsAttribute
=
202
,
AugBinOp
=
203
,
Invoke
=
204
,
LangPrimitive
=
205
,
};
};
...
...
@@ -620,7 +622,7 @@ public:
virtual
void
accept
(
ASTVisitor
*
v
);
virtual
void
accept_stmt
(
StmtVisitor
*
v
);
AST_Raise
()
:
AST_stmt
(
AST_TYPE
::
Raise
)
{}
AST_Raise
()
:
AST_stmt
(
AST_TYPE
::
Raise
)
,
arg0
(
NULL
),
arg1
(
NULL
),
arg2
(
NULL
)
{}
static
const
AST_TYPE
::
AST_TYPE
TYPE
=
AST_TYPE
::
Raise
;
};
...
...
@@ -795,6 +797,41 @@ public:
static
const
AST_TYPE
::
AST_TYPE
TYPE
=
AST_TYPE
::
ClsAttribute
;
};
class
AST_Invoke
:
public
AST_stmt
{
public:
AST_stmt
*
stmt
;
CFGBlock
*
normal_dest
,
*
exc_dest
;
virtual
void
accept
(
ASTVisitor
*
v
);
virtual
void
accept_stmt
(
StmtVisitor
*
v
);
AST_Invoke
(
AST_stmt
*
stmt
)
:
AST_stmt
(
AST_TYPE
::
Invoke
),
stmt
(
stmt
)
{}
static
const
AST_TYPE
::
AST_TYPE
TYPE
=
AST_TYPE
::
Invoke
;
};
// "LangPrimitive" represents operations that "primitive" to the language,
// but aren't directly *exactly* representable as normal Python.
// ClsAttribute would fall into this category, as would isinstance (which
// is not the same as the "isinstance" name since that could get redefined).
class
AST_LangPrimitive
:
public
AST_expr
{
public:
enum
Opcodes
{
ISINSTANCE
,
LANDINGPAD
,
}
opcode
;
std
::
vector
<
AST_expr
*>
args
;
virtual
void
accept
(
ASTVisitor
*
v
);
virtual
void
*
accept_expr
(
ExprVisitor
*
v
);
AST_LangPrimitive
(
Opcodes
opcode
)
:
AST_expr
(
AST_TYPE
::
LangPrimitive
),
opcode
(
opcode
)
{}
static
const
AST_TYPE
::
AST_TYPE
TYPE
=
AST_TYPE
::
LangPrimitive
;
};
template
<
typename
T
>
T
*
ast_cast
(
AST
*
node
)
{
assert
(
node
->
type
==
T
::
TYPE
);
return
static_cast
<
T
*>
(
node
);
...
...
@@ -834,7 +871,9 @@ public:
virtual
bool
visit_import
(
AST_Import
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
bool
visit_importfrom
(
AST_ImportFrom
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
bool
visit_index
(
AST_Index
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
bool
visit_invoke
(
AST_Invoke
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
bool
visit_keyword
(
AST_keyword
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
bool
visit_langprimitive
(
AST_LangPrimitive
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
bool
visit_list
(
AST_List
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
bool
visit_listcomp
(
AST_ListComp
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
bool
visit_module
(
AST_Module
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
...
...
@@ -891,7 +930,9 @@ public:
virtual
bool
visit_import
(
AST_Import
*
node
)
{
return
false
;
}
virtual
bool
visit_importfrom
(
AST_ImportFrom
*
node
)
{
return
false
;
}
virtual
bool
visit_index
(
AST_Index
*
node
)
{
return
false
;
}
virtual
bool
visit_invoke
(
AST_Invoke
*
node
)
{
return
false
;
}
virtual
bool
visit_keyword
(
AST_keyword
*
node
)
{
return
false
;
}
virtual
bool
visit_langprimitive
(
AST_LangPrimitive
*
node
)
{
return
false
;
}
virtual
bool
visit_list
(
AST_List
*
node
)
{
return
false
;
}
virtual
bool
visit_listcomp
(
AST_ListComp
*
node
)
{
return
false
;
}
virtual
bool
visit_module
(
AST_Module
*
node
)
{
return
false
;
}
...
...
@@ -931,6 +972,7 @@ public:
virtual
void
*
visit_dict
(
AST_Dict
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
void
*
visit_ifexp
(
AST_IfExp
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
void
*
visit_index
(
AST_Index
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
void
*
visit_langprimitive
(
AST_LangPrimitive
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
void
*
visit_list
(
AST_List
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
void
*
visit_listcomp
(
AST_ListComp
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
void
*
visit_name
(
AST_Name
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
...
...
@@ -961,6 +1003,7 @@ public:
virtual
void
visit_if
(
AST_If
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
void
visit_import
(
AST_Import
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
void
visit_importfrom
(
AST_ImportFrom
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
void
visit_invoke
(
AST_Invoke
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
void
visit_pass
(
AST_Pass
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
void
visit_print
(
AST_Print
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
virtual
void
visit_raise
(
AST_Raise
*
node
)
{
RELEASE_ASSERT
(
0
,
""
);
}
...
...
@@ -1011,7 +1054,9 @@ public:
virtual
bool
visit_import
(
AST_Import
*
node
);
virtual
bool
visit_importfrom
(
AST_ImportFrom
*
node
);
virtual
bool
visit_index
(
AST_Index
*
node
);
virtual
bool
visit_invoke
(
AST_Invoke
*
node
);
virtual
bool
visit_keyword
(
AST_keyword
*
node
);
virtual
bool
visit_langprimitive
(
AST_LangPrimitive
*
node
);
virtual
bool
visit_list
(
AST_List
*
node
);
virtual
bool
visit_listcomp
(
AST_ListComp
*
node
);
virtual
bool
visit_module
(
AST_Module
*
node
);
...
...
@@ -1050,6 +1095,8 @@ template <class T, class R> void findNodes(const R& roots, std::vector<T*>& outp
output
.
push_back
(
reinterpret_cast
<
T
*>
(
n
));
}
}
std
::
string
getOpSymbol
(
int
op_type
);
};
#endif
src/core/cfg.cpp
View file @
7efd8225
...
...
@@ -56,6 +56,12 @@ private:
std
::
vector
<
LoopInfo
>
loops
;
std
::
vector
<
CFGBlock
*>
returns
;
struct
ExcBlockInfo
{
CFGBlock
*
exc_dest
;
std
::
string
exc_obj_name
;
};
std
::
vector
<
ExcBlockInfo
>
exc_handlers
;
void
pushLoop
(
CFGBlock
*
continue_dest
,
CFGBlock
*
break_dest
)
{
LoopInfo
loop
;
loop
.
continue_dest
=
continue_dest
;
...
...
@@ -394,6 +400,14 @@ private:
return
rtn
;
}
AST_expr
*
remapLangPrimitive
(
AST_LangPrimitive
*
node
)
{
AST_LangPrimitive
*
rtn
=
new
AST_LangPrimitive
(
node
->
opcode
);
for
(
AST_expr
*
arg
:
node
->
args
)
{
rtn
->
args
.
push_back
(
remapExpr
(
arg
));
}
return
rtn
;
}
AST_expr
*
remapList
(
AST_List
*
node
)
{
assert
(
node
->
ctx_type
==
AST_TYPE
::
Load
);
...
...
@@ -621,6 +635,9 @@ private:
case
AST_TYPE
:
:
Index
:
rtn
=
remapIndex
(
ast_cast
<
AST_Index
>
(
node
));
break
;
case
AST_TYPE
:
:
LangPrimitive
:
rtn
=
remapLangPrimitive
(
ast_cast
<
AST_LangPrimitive
>
(
node
));
break
;
case
AST_TYPE
:
:
List
:
rtn
=
remapList
(
ast_cast
<
AST_List
>
(
node
));
break
;
...
...
@@ -670,33 +687,88 @@ public:
~
CFGVisitor
()
{
assert
(
loops
.
size
()
==
0
);
assert
(
returns
.
size
()
==
0
);
assert
(
exc_handlers
.
size
()
==
0
);
}
void
push_back
(
AST_stmt
*
node
)
{
if
(
curblock
)
assert
(
node
->
type
!=
AST_TYPE
::
Invoke
);
if
(
!
curblock
)
return
;
if
(
exc_handlers
.
size
()
==
0
)
{
curblock
->
push_back
(
node
);
return
;
}
AST_TYPE
::
AST_TYPE
type
=
node
->
type
;
if
(
type
==
AST_TYPE
::
Jump
)
{
curblock
->
push_back
(
node
);
return
;
}
if
(
type
==
AST_TYPE
::
Branch
)
{
AST_TYPE
::
AST_TYPE
test_type
=
ast_cast
<
AST_Branch
>
(
node
)
->
test
->
type
;
assert
(
test_type
==
AST_TYPE
::
Name
||
test_type
==
AST_TYPE
::
Num
);
curblock
->
push_back
(
node
);
return
;
}
if
(
type
==
AST_TYPE
::
Return
)
{
curblock
->
push_back
(
node
);
return
;
}
CFGBlock
*
normal_dest
=
cfg
->
addBlock
();
// Add an extra exc_dest trampoline to prevent critical edges:
CFGBlock
*
exc_dest
=
cfg
->
addBlock
();
AST_Invoke
*
invoke
=
new
AST_Invoke
(
node
);
invoke
->
normal_dest
=
normal_dest
;
invoke
->
exc_dest
=
exc_dest
;
curblock
->
push_back
(
invoke
);
curblock
->
connectTo
(
normal_dest
);
curblock
->
connectTo
(
exc_dest
);
ExcBlockInfo
&
exc_info
=
exc_handlers
.
back
();
curblock
=
exc_dest
;
curblock
->
push_back
(
makeAssign
(
exc_info
.
exc_obj_name
,
new
AST_LangPrimitive
(
AST_LangPrimitive
::
LANDINGPAD
)));
AST_Jump
*
j
=
new
AST_Jump
();
j
->
target
=
exc_info
.
exc_dest
;
curblock
->
push_back
(
j
);
curblock
->
connectTo
(
exc_info
.
exc_dest
);
curblock
=
normal_dest
;
}
virtual
bool
visit_classdef
(
AST_ClassDef
*
node
)
{
push_back
(
node
);
return
true
;
}
virtual
bool
visit_functiondef
(
AST_FunctionDef
*
node
)
{
push_back
(
node
);
return
true
;
}
virtual
bool
visit_global
(
AST_Global
*
node
)
{
push_back
(
node
);
return
true
;
}
virtual
bool
visit_import
(
AST_Import
*
node
)
{
push_back
(
node
);
return
true
;
}
virtual
bool
visit_importfrom
(
AST_ImportFrom
*
node
)
{
push_back
(
node
);
return
true
;
}
virtual
bool
visit_pass
(
AST_Pass
*
node
)
{
return
true
;
}
bool
visit_assert
(
AST_Assert
*
node
)
override
{
...
...
@@ -749,13 +821,16 @@ public:
}
virtual
bool
visit_assign
(
AST_Assign
*
node
)
{
AST_Assign
*
remapped
=
new
AST_Assign
();
remapped
->
lineno
=
node
->
lineno
;
remapped
->
col_offset
=
node
->
col_offset
;
remapped
->
value
=
remapExpr
(
node
->
value
,
false
);
// TODO bad that it's reusing the AST nodes?
remapped
->
targets
=
node
->
targets
;
push_back
(
remapped
);
AST_expr
*
remapped_value
=
remapExpr
(
node
->
value
);
for
(
AST_expr
*
target
:
node
->
targets
)
{
AST_Assign
*
remapped
=
new
AST_Assign
();
remapped
->
lineno
=
node
->
lineno
;
remapped
->
col_offset
=
node
->
col_offset
;
remapped
->
value
=
remapped_value
;
remapped
->
targets
.
push_back
(
target
);
push_back
(
remapped
);
}
return
true
;
}
...
...
@@ -958,7 +1033,7 @@ public:
AST_Jump
*
j
=
makeJump
();
push_back
(
j
);
assert
(
loops
.
size
());
j
->
target
=
loops
[
loops
.
size
()
-
1
].
break_dest
;
j
->
target
=
getBreak
()
;
curblock
->
connectTo
(
j
->
target
,
true
);
curblock
=
NULL
;
...
...
@@ -978,10 +1053,9 @@ public:
AST_Jump
*
j
=
makeJump
();
push_back
(
j
);
assert
(
loops
.
size
());
j
->
target
=
loops
[
loops
.
size
()
-
1
].
continue_dest
;
j
->
target
=
getContinue
()
;
curblock
->
connectTo
(
j
->
target
,
true
);
// See visit_break for explanation:
curblock
=
NULL
;
return
true
;
}
...
...
@@ -1155,6 +1229,111 @@ public:
return
true
;
}
bool
visit_raise
(
AST_Raise
*
node
)
override
{
AST_Raise
*
remapped
=
new
AST_Raise
();
if
(
node
->
arg0
)
remapped
->
arg0
=
remapExpr
(
node
->
arg0
);
if
(
node
->
arg1
)
remapped
->
arg1
=
remapExpr
(
node
->
arg1
);
if
(
node
->
arg2
)
remapped
->
arg2
=
remapExpr
(
node
->
arg2
);
push_back
(
remapped
);
return
true
;
}
bool
visit_tryexcept
(
AST_TryExcept
*
node
)
override
{
assert
(
node
->
handlers
.
size
()
>
0
);
CFGBlock
*
exc_handler_block
=
cfg
->
addDeferredBlock
();
std
::
string
exc_obj_name
=
nodeName
(
node
);
exc_handlers
.
push_back
({
exc_handler_block
,
exc_obj_name
});
for
(
AST_stmt
*
subnode
:
node
->
body
)
{
subnode
->
accept
(
this
);
}
exc_handlers
.
pop_back
();
for
(
AST_stmt
*
subnode
:
node
->
orelse
)
{
subnode
->
accept
(
this
);
}
CFGBlock
*
join_block
=
cfg
->
addDeferredBlock
();
AST_Jump
*
j
=
new
AST_Jump
();
j
->
target
=
join_block
;
push_back
(
j
);
curblock
->
connectTo
(
join_block
);
if
(
exc_handler_block
->
predecessors
.
size
()
==
0
)
{
delete
exc_handler_block
;
}
else
{
cfg
->
placeBlock
(
exc_handler_block
);
curblock
=
exc_handler_block
;
AST_expr
*
exc_obj
=
makeName
(
exc_obj_name
,
AST_TYPE
::
Load
);
bool
caught_all
=
false
;
for
(
AST_ExceptHandler
*
exc_handler
:
node
->
handlers
)
{
assert
(
!
caught_all
&&
"bare except clause not the last one in the list?"
);
CFGBlock
*
exc_next
=
nullptr
;
if
(
exc_handler
->
type
)
{
AST_expr
*
handled_type
=
remapExpr
(
exc_handler
->
type
);
AST_LangPrimitive
*
is_caught_here
=
new
AST_LangPrimitive
(
AST_LangPrimitive
::
ISINSTANCE
);
is_caught_here
->
args
.
push_back
(
exc_obj
);
is_caught_here
->
args
.
push_back
(
handled_type
);
is_caught_here
->
args
.
push_back
(
makeNum
(
1
));
// flag: false_on_noncls
CFGBlock
*
exc_handle
=
cfg
->
addBlock
();
exc_next
=
cfg
->
addDeferredBlock
();
AST_Branch
*
br
=
new
AST_Branch
();
br
->
test
=
remapExpr
(
is_caught_here
);
br
->
iftrue
=
exc_handle
;
br
->
iffalse
=
exc_next
;
curblock
->
connectTo
(
exc_handle
);
curblock
->
connectTo
(
exc_next
);
push_back
(
br
);
curblock
=
exc_handle
;
}
else
{
caught_all
=
true
;
}
if
(
exc_handler
->
name
)
{
push_back
(
makeAssign
(
exc_handler
->
name
,
exc_obj
));
}
for
(
AST_stmt
*
subnode
:
exc_handler
->
body
)
{
subnode
->
accept
(
this
);
}
AST_Jump
*
j
=
new
AST_Jump
();
j
->
target
=
join_block
;
push_back
(
j
);
curblock
->
connectTo
(
join_block
);
if
(
exc_next
)
{
cfg
->
placeBlock
(
exc_next
);
}
else
{
assert
(
caught_all
);
}
curblock
=
exc_next
;
}
if
(
!
caught_all
)
{
AST_Raise
*
raise
=
new
AST_Raise
();
raise
->
arg0
=
exc_obj
;
push_back
(
raise
);
curblock
=
NULL
;
}
}
cfg
->
placeBlock
(
join_block
);
curblock
=
join_block
;
return
true
;
}
virtual
bool
visit_with
(
AST_With
*
node
)
{
char
ctxmgrname_buf
[
80
];
snprintf
(
ctxmgrname_buf
,
80
,
"#ctxmgr_%p"
,
node
);
...
...
@@ -1182,13 +1361,12 @@ public:
break_dest
=
cfg
->
addDeferredBlock
();
break_dest
->
info
=
"with_break"
;
orig_continue_dest
=
loops
[
loops
.
size
()
-
1
].
continue_dest
;
orig_break_dest
=
loops
[
loops
.
size
()
-
1
].
break_dest
;
orig_continue_dest
=
getContinue
()
;
orig_break_dest
=
getBreak
()
;
pushLoop
(
continue_dest
,
break_dest
);
}
CFGBlock
*
orig_return_dest
=
getReturn
();
CFGBlock
*
return_dest
=
cfg
->
addDeferredBlock
();
return_dest
->
info
=
"with_return"
;
pushReturn
(
return_dest
);
...
...
@@ -1309,14 +1487,22 @@ CFG* computeCFG(AST_TYPE::AST_TYPE root_type, std::vector<AST_stmt*> body) {
return_stmt
->
value
=
NULL
;
visitor
.
push_back
(
return_stmt
);
// rtn->print();
#ifndef NDEBUG
////
// Check some properties expected by later stages:
assert
(
rtn
->
getStartingBlock
()
->
predecessors
.
size
()
==
0
);
for
(
CFGBlock
*
b
:
rtn
->
blocks
)
{
ASSERT
(
b
->
idx
!=
-
1
,
"Forgot to place a block!"
);
for
(
CFGBlock
*
b2
:
b
->
predecessors
)
{
ASSERT
(
b2
->
idx
!=
-
1
,
"Forgot to place a block!"
);
}
for
(
CFGBlock
*
b2
:
b
->
successors
)
{
ASSERT
(
b2
->
idx
!=
-
1
,
"Forgot to place a block!"
);
}
}
// We need to generate the CFG in a way that doesn't have any critical edges,
// since the ir generation requires that.
// We could do this with a separate critical-edge-breaking pass, but for now
...
...
@@ -1354,6 +1540,11 @@ CFG* computeCFG(AST_TYPE::AST_TYPE root_type, std::vector<AST_stmt*> body) {
assert
(
rtn
->
blocks
[
i
]
->
predecessors
[
0
]
->
idx
<
i
);
}
assert
(
rtn
->
getStartingBlock
()
->
idx
==
0
);
// TODO make sure the result of Invoke nodes are not used on the exceptional path
#endif
// Prune unnecessary blocks from the CFG.
// Not strictly necessary, but makes the output easier to look at,
// and can make the analyses more efficient.
...
...
@@ -1386,34 +1577,9 @@ CFG* computeCFG(AST_TYPE::AST_TYPE root_type, std::vector<AST_stmt*> body) {
}
}
assert
(
rtn
->
getStartingBlock
()
->
idx
==
0
);
/*
// I keep on going back and forth about whether or not it's ok to reuse AST nodes.
// On the one hand, it's nice to say that an AST* pointer uniquely identifies a spot
// in the computation, but then again the sharing can actually be nice because
// it indicates that there are certain similarities between the points, and things such
// as type recorders will end up being shared.
std::vector<AST*> all_ast_nodes;
for (CFGBlock* block : rtn->blocks) {
flatten(block->body, all_ast_nodes, false);
}
std::unordered_set<AST*> seen_ast_nodes;
for (AST* n : all_ast_nodes) {
if (seen_ast_nodes.count(n)) {
if
(
VERBOSITY
())
rtn
->
print
();
printf("This node appears multiple times in the tree:\n");
print_ast(n);
printf("\n");
assert(0);
}
seen_ast_nodes.insert(n);
}
*/
#endif
return
rtn
;
}
}
src/core/types.h
View file @
7efd8225
...
...
@@ -228,7 +228,6 @@ extern "C" Box* callCompiledFunc(CompiledFunction* cf, int64_t nargs, Box* arg1,
std
::
string
getOpName
(
int
op_type
);
std
::
string
getReverseOpName
(
int
op_type
);
std
::
string
getInplaceOpName
(
int
op_type
);
std
::
string
getOpSymbol
(
int
op_type
);
std
::
string
getInplaceOpSymbol
(
int
op_type
);
typedef
bool
i1
;
...
...
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