Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
TASTE
uPython-mirror
Commits
415eb6f8
Commit
415eb6f8
authored
Oct 05, 2013
by
Damien
Browse files
Restructure emit so it goes through a method table.
parent
492d0824
Changes
11
Expand all
Hide whitespace changes
Inline
Side-by-side
py/.gitignore
View file @
415eb6f8
*.o
py
*.py
py/Makefile
View file @
415eb6f8
CC
=
gcc
CFLAGS
=
-Wall
-ansi
-std
=
gnu99
-Os
#-DNDEBUG
CFLAGS
=
-Wall
-ansi
-std
=
gnu99
-Os
-DEMIT_ENABLE_CPY
-DEMIT_ENABLE_X64
#-DNDEBUG
LDFLAGS
=
SRC
=
\
...
...
py/asmx64.c
View file @
415eb6f8
...
...
@@ -113,7 +113,8 @@ asm_x64_t* asm_x64_new() {
void
asm_x64_free
(
asm_x64_t
*
as
,
bool
free_code
)
{
if
(
free_code
)
{
m_free
(
as
->
code_base
);
// need to un-mmap
//m_free(as->code_base);
}
/*
if (as->label != NULL) {
...
...
@@ -154,6 +155,8 @@ void asm_x64_end_pass(asm_x64_t *as) {
// calculate size of code in bytes
as
->
code_size
=
as
->
code_offset
;
as
->
code_base
=
m_new
(
byte
,
as
->
code_size
);
//uint actual_alloc;
//as->code_base = alloc_mem(as->code_size, &actual_alloc, true);
printf
(
"code_size: %u
\n
"
,
as
->
code_size
);
}
...
...
@@ -611,11 +614,12 @@ void asm_x64_call_i1(asm_x64_t* as, void* func, int i1)
*/
void
asm_x64_call_ind
(
asm_x64_t
*
as
,
void
*
ptr
,
int
temp_r64
)
{
/*
asm_x64_mov_i64_to_r64_optimised
(
as
,
(
int64_t
)
ptr
,
temp_r64
);
asm_x64_write_byte_2
(
as
,
OPCODE_CALL_RM32
,
MODRM_R64
(
2
)
|
MODRM_RM_REG
|
MODRM_RM_R64
(
temp_r64
));
*/
// this reduces code size by 2 bytes per call, but doesn't seem to speed it up at all
// doesn't work anymore because calls are 64 bits away
/*
asm_x64_write_byte_1(as, OPCODE_CALL_REL32);
asm_x64_write_word32(as, ptr - (void*)(as->code_base + as->code_offset + 4));
*/
}
py/compile.c
View file @
415eb6f8
...
...
@@ -15,6 +15,7 @@
#include
"emit.h"
// TODO need to mangle __attr names
// TODO add #define to enable/disable CPython compatibility
typedef
enum
{
PN_none
=
0
,
...
...
@@ -24,8 +25,8 @@ typedef enum {
PN_maximum_number_of
,
}
pn_kind_t
;
#define EMIT(fun, arg...) (
emit_##
fun(comp->emit, ##arg))
#define EMIT_COMMON(fun, arg...) (emit_common_##fun(comp->pass, comp->scope_cur, ##arg))
#define EMIT(fun, arg...) (
comp->emit_method_table->
fun(comp->emit, ##arg))
#define EMIT_COMMON(fun, arg...) (emit_common_##fun(comp->pass, comp->scope_cur,
comp->emit, comp->emit_method_table,
##arg))
typedef
struct
_compiler_t
{
qstr
qstr___class__
;
...
...
@@ -53,7 +54,8 @@ typedef struct _compiler_t {
scope_t
*
scope_head
;
scope_t
*
scope_cur
;
emitter_t
*
emit
;
emit_t
*
emit
;
const
emit_method_table_t
*
emit_method_table
;
}
compiler_t
;
py_parse_node_t
fold_constants
(
py_parse_node_t
pn
)
{
...
...
@@ -495,10 +497,10 @@ void c_assign(compiler_t *comp, py_parse_node_t pn, assign_kind_t assign_kind) {
switch
(
assign_kind
)
{
case
ASSIGN_STORE
:
case
ASSIGN_AUG_STORE
:
EMIT_COMMON
(
store_id
,
comp
->
emit
,
arg
);
EMIT_COMMON
(
store_id
,
arg
);
break
;
case
ASSIGN_AUG_LOAD
:
EMIT_COMMON
(
load_id
,
comp
->
qstr___class__
,
comp
->
emit
,
arg
);
EMIT_COMMON
(
load_id
,
comp
->
qstr___class__
,
arg
);
break
;
}
}
else
{
...
...
@@ -770,18 +772,18 @@ void compile_decorated(compiler_t *comp, py_parse_node_struct_t *pns) {
}
// store func/class object into name
EMIT_COMMON
(
store_id
,
comp
->
emit
,
body_name
);
EMIT_COMMON
(
store_id
,
body_name
);
}
void
compile_funcdef
(
compiler_t
*
comp
,
py_parse_node_struct_t
*
pns
)
{
qstr
fname
=
compile_funcdef_helper
(
comp
,
pns
);
// store function object into function name
EMIT_COMMON
(
store_id
,
comp
->
emit
,
fname
);
EMIT_COMMON
(
store_id
,
fname
);
}
void
c_del_stmt
(
compiler_t
*
comp
,
py_parse_node_t
pn
)
{
if
(
PY_PARSE_NODE_IS_ID
(
pn
))
{
EMIT_COMMON
(
delete_id
,
comp
->
emit
,
PY_PARSE_NODE_LEAF_ARG
(
pn
));
EMIT_COMMON
(
delete_id
,
PY_PARSE_NODE_LEAF_ARG
(
pn
));
}
else
if
(
PY_PARSE_NODE_IS_STRUCT_KIND
(
pn
,
PN_power
))
{
py_parse_node_struct_t
*
pns
=
(
py_parse_node_struct_t
*
)
pn
;
...
...
@@ -986,7 +988,7 @@ void compile_dotted_as_name(compiler_t *comp, py_parse_node_t pn) {
EMIT
(
load_const_tok
,
PY_TOKEN_KW_NONE
);
qstr
q1
,
q2
;
do_import_name
(
comp
,
pn
,
&
q1
,
&
q2
);
EMIT_COMMON
(
store_id
,
comp
->
emit
,
q1
);
EMIT_COMMON
(
store_id
,
q1
);
}
void
compile_import_name
(
compiler_t
*
comp
,
py_parse_node_struct_t
*
pns
)
{
...
...
@@ -1033,9 +1035,9 @@ void compile_import_from(compiler_t *comp, py_parse_node_struct_t *pns) {
qstr
id2
=
PY_PARSE_NODE_LEAF_ARG
(
pns3
->
nodes
[
0
]);
// should be id
EMIT
(
import_from
,
id2
);
if
(
PY_PARSE_NODE_IS_NULL
(
pns3
->
nodes
[
1
]))
{
EMIT_COMMON
(
store_id
,
comp
->
emit
,
id2
);
EMIT_COMMON
(
store_id
,
id2
);
}
else
{
EMIT_COMMON
(
store_id
,
comp
->
emit
,
PY_PARSE_NODE_LEAF_ARG
(
pns3
->
nodes
[
1
]));
EMIT_COMMON
(
store_id
,
PY_PARSE_NODE_LEAF_ARG
(
pns3
->
nodes
[
1
]));
}
}
EMIT
(
pop_top
);
...
...
@@ -1043,25 +1045,29 @@ void compile_import_from(compiler_t *comp, py_parse_node_struct_t *pns) {
}
void
compile_global_stmt
(
compiler_t
*
comp
,
py_parse_node_struct_t
*
pns
)
{
if
(
PY_PARSE_NODE_IS_LEAF
(
pns
->
nodes
[
0
]))
{
EMIT_COMMON
(
declare_global
,
PY_PARSE_NODE_LEAF_ARG
(
pns
->
nodes
[
0
]));
}
else
{
pns
=
(
py_parse_node_struct_t
*
)
pns
->
nodes
[
0
];
int
num_nodes
=
PY_PARSE_NODE_STRUCT_NUM_NODES
(
pns
);
for
(
int
i
=
0
;
i
<
num_nodes
;
i
++
)
{
EMIT_COMMON
(
declare_global
,
PY_PARSE_NODE_LEAF_ARG
(
pns
->
nodes
[
i
]));
if
(
comp
->
pass
==
PASS_1
)
{
if
(
PY_PARSE_NODE_IS_LEAF
(
pns
->
nodes
[
0
]))
{
scope_declare_global
(
comp
->
scope_cur
,
PY_PARSE_NODE_LEAF_ARG
(
pns
->
nodes
[
0
]));
}
else
{
pns
=
(
py_parse_node_struct_t
*
)
pns
->
nodes
[
0
];
int
num_nodes
=
PY_PARSE_NODE_STRUCT_NUM_NODES
(
pns
);
for
(
int
i
=
0
;
i
<
num_nodes
;
i
++
)
{
scope_declare_global
(
comp
->
scope_cur
,
PY_PARSE_NODE_LEAF_ARG
(
pns
->
nodes
[
i
]));
}
}
}
}
void
compile_nonlocal_stmt
(
compiler_t
*
comp
,
py_parse_node_struct_t
*
pns
)
{
if
(
PY_PARSE_NODE_IS_LEAF
(
pns
->
nodes
[
0
]))
{
EMIT_COMMON
(
declare_nonlocal
,
PY_PARSE_NODE_LEAF_ARG
(
pns
->
nodes
[
0
]));
}
else
{
pns
=
(
py_parse_node_struct_t
*
)
pns
->
nodes
[
0
];
int
num_nodes
=
PY_PARSE_NODE_STRUCT_NUM_NODES
(
pns
);
for
(
int
i
=
0
;
i
<
num_nodes
;
i
++
)
{
EMIT_COMMON
(
declare_nonlocal
,
PY_PARSE_NODE_LEAF_ARG
(
pns
->
nodes
[
i
]));
if
(
comp
->
pass
==
PASS_1
)
{
if
(
PY_PARSE_NODE_IS_LEAF
(
pns
->
nodes
[
0
]))
{
scope_declare_nonlocal
(
comp
->
scope_cur
,
PY_PARSE_NODE_LEAF_ARG
(
pns
->
nodes
[
0
]));
}
else
{
pns
=
(
py_parse_node_struct_t
*
)
pns
->
nodes
[
0
];
int
num_nodes
=
PY_PARSE_NODE_STRUCT_NUM_NODES
(
pns
);
for
(
int
i
=
0
;
i
<
num_nodes
;
i
++
)
{
scope_declare_nonlocal
(
comp
->
scope_cur
,
PY_PARSE_NODE_LEAF_ARG
(
pns
->
nodes
[
i
]));
}
}
}
}
...
...
@@ -1069,7 +1075,7 @@ void compile_nonlocal_stmt(compiler_t *comp, py_parse_node_struct_t *pns) {
void
compile_assert_stmt
(
compiler_t
*
comp
,
py_parse_node_struct_t
*
pns
)
{
int
l_end
=
EMIT
(
label_new
);
c_if_cond
(
comp
,
pns
->
nodes
[
0
],
true
,
l_end
);
EMIT_COMMON
(
load_id
,
comp
->
qstr___class__
,
comp
->
emit
,
comp
->
qstr_assertion_error
);
EMIT_COMMON
(
load_id
,
comp
->
qstr___class__
,
comp
->
qstr_assertion_error
);
if
(
!
PY_PARSE_NODE_IS_NULL
(
pns
->
nodes
[
1
]))
{
// assertion message
compile_node
(
comp
,
pns
->
nodes
[
1
]);
...
...
@@ -1090,7 +1096,7 @@ void compile_if_stmt(compiler_t *comp, py_parse_node_struct_t *pns) {
compile_node
(
comp
,
pns
->
nodes
[
1
]);
// if block
//if (!(PY_PARSE_NODE_IS_NULL(pns->nodes[2]) && PY_PARSE_NODE_IS_NULL(pns->nodes[3]))) { // optimisation; doesn't align with CPython
// jump over elif/else blocks if they exist
if
(
!
emit_
last_emit_was_return_value
(
comp
->
emit
))
{
// simple optimisation to align with CPython
if
(
!
EMIT
(
last_emit_was_return_value
))
{
// simple optimisation to align with CPython
EMIT
(
jump
,
l_end
);
}
//}
...
...
@@ -1111,7 +1117,7 @@ void compile_if_stmt(compiler_t *comp, py_parse_node_struct_t *pns) {
c_if_cond
(
comp
,
pns_elif2
->
nodes
[
0
],
false
,
l_fail
);
// elif condition
compile_node
(
comp
,
pns_elif2
->
nodes
[
1
]);
// elif block
if
(
!
emit_
last_emit_was_return_value
(
comp
->
emit
))
{
// simple optimisation to align with CPython
if
(
!
EMIT
(
last_emit_was_return_value
))
{
// simple optimisation to align with CPython
EMIT
(
jump
,
l_end
);
}
EMIT
(
label_assign
,
l_fail
);
...
...
@@ -1124,7 +1130,7 @@ void compile_if_stmt(compiler_t *comp, py_parse_node_struct_t *pns) {
c_if_cond
(
comp
,
pns_elif
->
nodes
[
0
],
false
,
l_fail
);
// elif condition
compile_node
(
comp
,
pns_elif
->
nodes
[
1
]);
// elif block
if
(
!
emit_
last_emit_was_return_value
(
comp
->
emit
))
{
// simple optimisation to align with CPython
if
(
!
EMIT
(
last_emit_was_return_value
))
{
// simple optimisation to align with CPython
EMIT
(
jump
,
l_end
);
}
EMIT
(
label_assign
,
l_fail
);
...
...
@@ -1153,7 +1159,7 @@ void compile_while_stmt(compiler_t *comp, py_parse_node_struct_t *pns) {
EMIT
(
label_assign
,
continue_label
);
c_if_cond
(
comp
,
pns
->
nodes
[
0
],
false
,
done_label
);
// condition
compile_node
(
comp
,
pns
->
nodes
[
1
]);
// body
if
(
!
emit_
last_emit_was_return_value
(
comp
->
emit
))
{
if
(
!
EMIT
(
last_emit_was_return_value
))
{
EMIT
(
jump
,
continue_label
);
}
EMIT
(
label_assign
,
done_label
);
...
...
@@ -1194,7 +1200,7 @@ void compile_for_stmt(compiler_t *comp, py_parse_node_struct_t *pns) {
EMIT
(
for_iter
,
pop_label
);
c_assign
(
comp
,
pns
->
nodes
[
0
],
ASSIGN_STORE
);
// variable
compile_node
(
comp
,
pns
->
nodes
[
2
]);
// body
if
(
!
emit_
last_emit_was_return_value
(
comp
->
emit
))
{
if
(
!
EMIT
(
last_emit_was_return_value
))
{
EMIT
(
jump
,
for_label
);
}
EMIT
(
label_assign
,
pop_label
);
...
...
@@ -1263,7 +1269,7 @@ void compile_try_except(compiler_t *comp, py_parse_node_t pn_body, int n_except,
if
(
qstr_exception_local
==
0
)
{
EMIT
(
pop_top
);
}
else
{
EMIT_COMMON
(
store_id
,
comp
->
emit
,
qstr_exception_local
);
EMIT_COMMON
(
store_id
,
qstr_exception_local
);
}
EMIT
(
pop_top
);
...
...
@@ -1282,8 +1288,8 @@ void compile_try_except(compiler_t *comp, py_parse_node_t pn_body, int n_except,
EMIT
(
load_const_tok
,
PY_TOKEN_KW_NONE
);
EMIT
(
label_assign
,
l3
);
EMIT
(
load_const_tok
,
PY_TOKEN_KW_NONE
);
EMIT_COMMON
(
store_id
,
comp
->
emit
,
qstr_exception_local
);
EMIT_COMMON
(
delete_id
,
comp
->
emit
,
qstr_exception_local
);
EMIT_COMMON
(
store_id
,
qstr_exception_local
);
EMIT_COMMON
(
delete_id
,
qstr_exception_local
);
EMIT
(
end_finally
);
}
EMIT
(
jump
,
l2
);
...
...
@@ -2038,7 +2044,7 @@ void compile_dictorsetmaker_item(compiler_t *comp, py_parse_node_struct_t *pns)
void
compile_classdef
(
compiler_t
*
comp
,
py_parse_node_struct_t
*
pns
)
{
qstr
cname
=
compile_classdef_helper
(
comp
,
pns
);
// store class object into class name
EMIT_COMMON
(
store_id
,
comp
->
emit
,
cname
);
EMIT_COMMON
(
store_id
,
cname
);
}
void
compile_arglist_star
(
compiler_t
*
comp
,
py_parse_node_struct_t
*
pns
)
{
...
...
@@ -2116,7 +2122,7 @@ void compile_node(compiler_t *comp, py_parse_node_t pn) {
}
else
if
(
PY_PARSE_NODE_IS_LEAF
(
pn
))
{
int
arg
=
PY_PARSE_NODE_LEAF_ARG
(
pn
);
switch
(
PY_PARSE_NODE_LEAF_KIND
(
pn
))
{
case
PY_PARSE_NODE_ID
:
EMIT_COMMON
(
load_id
,
comp
->
qstr___class__
,
comp
->
emit
,
arg
);
break
;
case
PY_PARSE_NODE_ID
:
EMIT_COMMON
(
load_id
,
comp
->
qstr___class__
,
arg
);
break
;
case
PY_PARSE_NODE_SMALL_INT
:
EMIT
(
load_const_small_int
,
arg
);
break
;
case
PY_PARSE_NODE_INTEGER
:
EMIT
(
load_const_int
,
arg
);
break
;
case
PY_PARSE_NODE_DECIMAL
:
EMIT
(
load_const_dec
,
arg
);
break
;
...
...
@@ -2287,7 +2293,7 @@ void check_for_doc_string(compiler_t *comp, py_parse_node_t pn) {
if
(
kind
==
PY_PARSE_NODE_STRING
)
{
compile_node
(
comp
,
pns
->
nodes
[
0
]);
// a doc string
// store doc string
EMIT_COMMON
(
store_id
,
comp
->
emit
,
comp
->
qstr___doc__
);
EMIT_COMMON
(
store_id
,
comp
->
qstr___doc__
);
}
}
}
...
...
@@ -2296,7 +2302,7 @@ void check_for_doc_string(compiler_t *comp, py_parse_node_t pn) {
void
compile_scope
(
compiler_t
*
comp
,
scope_t
*
scope
,
pass_kind_t
pass
)
{
comp
->
pass
=
pass
;
comp
->
scope_cur
=
scope
;
emit_
start_pass
(
comp
->
emit
,
pass
,
scope
);
EMIT
(
start_pass
,
pass
,
scope
);
if
(
comp
->
pass
==
PASS_1
)
{
scope
->
stack_size
=
0
;
...
...
@@ -2328,7 +2334,7 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
compile_node
(
comp
,
pns
->
nodes
[
3
]);
// 3 is function body
// emit return if it wasn't the last opcode
if
(
!
emit_
last_emit_was_return_value
(
comp
->
emit
))
{
if
(
!
EMIT
(
last_emit_was_return_value
))
{
EMIT
(
load_const_tok
,
PY_TOKEN_KW_NONE
);
EMIT
(
return_value
);
}
...
...
@@ -2373,7 +2379,7 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
int
l_end
=
EMIT
(
label_new
);
int
l_top
=
EMIT
(
label_new
);
EMIT_COMMON
(
load_id
,
comp
->
qstr___class__
,
comp
->
emit
,
qstr_arg
);
EMIT_COMMON
(
load_id
,
comp
->
qstr___class__
,
qstr_arg
);
EMIT
(
label_assign
,
l_top
);
EMIT
(
for_iter
,
l_end
);
c_assign
(
comp
,
pns_comp_for
->
nodes
[
0
],
ASSIGN_STORE
);
...
...
@@ -2404,12 +2410,12 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
scope
->
num_params
=
1
;
// __locals__ is the parameter
}
EMIT_COMMON
(
load_id
,
comp
->
qstr___class__
,
comp
->
emit
,
comp
->
qstr___locals__
);
EMIT_COMMON
(
load_id
,
comp
->
qstr___class__
,
comp
->
qstr___locals__
);
EMIT
(
store_locals
);
EMIT_COMMON
(
load_id
,
comp
->
qstr___class__
,
comp
->
emit
,
comp
->
qstr___name__
);
EMIT_COMMON
(
store_id
,
comp
->
emit
,
comp
->
qstr___module__
);
EMIT_COMMON
(
load_id
,
comp
->
qstr___class__
,
comp
->
qstr___name__
);
EMIT_COMMON
(
store_id
,
comp
->
qstr___module__
);
EMIT
(
load_const_id
,
PY_PARSE_NODE_LEAF_ARG
(
pns
->
nodes
[
0
]));
// 0 is class name
EMIT_COMMON
(
store_id
,
comp
->
emit
,
comp
->
qstr___qualname__
);
EMIT_COMMON
(
store_id
,
comp
->
qstr___qualname__
);
check_for_doc_string
(
comp
,
pns
->
nodes
[
2
]);
compile_node
(
comp
,
pns
->
nodes
[
2
]);
// 2 is class body
...
...
@@ -2424,7 +2430,7 @@ void compile_scope(compiler_t *comp, scope_t *scope, pass_kind_t pass) {
EMIT
(
return_value
);
}
emit_
end_pass
(
comp
->
emit
);
EMIT
(
end_pass
);
}
void
compile_scope_compute_things
(
compiler_t
*
comp
,
scope_t
*
scope
)
{
...
...
@@ -2489,7 +2495,9 @@ void py_compile(py_parse_node_t pn) {
comp
->
scope_head
=
NULL
;
comp
->
scope_cur
=
NULL
;
comp
->
emit
=
emit_new
(
comp
->
qstr___class__
);
emit_new_cpython
(
&
comp
->
emit
,
&
comp
->
emit_method_table
);
//emit_new_bc(&comp->emit, &comp->emit_method_table);
//emit_new_x64(&comp->emit, &comp->emit_method_table);
pn
=
fold_constants
(
pn
);
scope_new_and_link
(
comp
,
SCOPE_MODULE
,
pn
);
...
...
py/emit.h
View file @
415eb6f8
//#define EMIT_DO_CPY
#define EMIT_DO_BC
//#define EMIT_DO_X64
//#define EMIT_DO_THUMB
/* Notes on passes:
* We don't know exactly the opcodes in pass 1 because they depend on the
* closing over of variables (LOAD_CLOSURE, BUILD_TUPLE, MAKE_CLOSURE), which
...
...
@@ -19,15 +14,111 @@ typedef enum {
PASS_3
=
3
,
// emit code
}
pass_kind_t
;
typedef
struct
_emitter_t
emitter_t
;
typedef
struct
_emit_t
emit_t
;
typedef
struct
_emit_method_table_t
{
void
(
*
set_native_types
)(
emit_t
*
emit
,
bool
do_native_types
);
void
(
*
start_pass
)(
emit_t
*
emit
,
pass_kind_t
pass
,
scope_t
*
scope
);
void
(
*
end_pass
)(
emit_t
*
emit
);
bool
(
*
last_emit_was_return_value
)(
emit_t
*
emit
);
int
(
*
get_stack_size
)(
emit_t
*
emit
);
void
(
*
set_stack_size
)(
emit_t
*
emit
,
int
size
);
int
(
*
label_new
)(
emit_t
*
emit
);
void
(
*
label_assign
)(
emit_t
*
emit
,
int
l
);
void
(
*
import_name
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
import_from
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
import_star
)(
emit_t
*
emit
);
void
(
*
load_const_tok
)(
emit_t
*
emit
,
py_token_kind_t
tok
);
void
(
*
load_const_small_int
)(
emit_t
*
emit
,
int
arg
);
void
(
*
load_const_int
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
load_const_dec
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
load_const_id
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
load_const_str
)(
emit_t
*
emit
,
qstr
qstr
,
bool
bytes
);
void
(
*
load_const_verbatim_start
)(
emit_t
*
emit
);
void
(
*
load_const_verbatim_int
)(
emit_t
*
emit
,
int
val
);
void
(
*
load_const_verbatim_str
)(
emit_t
*
emit
,
const
char
*
str
);
void
(
*
load_const_verbatim_strn
)(
emit_t
*
emit
,
const
char
*
str
,
int
len
);
void
(
*
load_const_verbatim_quoted_str
)(
emit_t
*
emit
,
qstr
qstr
,
bool
bytes
);
void
(
*
load_const_verbatim_end
)(
emit_t
*
emit
);
void
(
*
load_fast
)(
emit_t
*
emit
,
qstr
qstr
,
int
local_num
);
void
(
*
load_name
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
load_global
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
load_deref
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
load_closure
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
load_attr
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
load_method
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
load_build_class
)(
emit_t
*
emit
);
void
(
*
store_fast
)(
emit_t
*
emit
,
qstr
qstr
,
int
local_num
);
void
(
*
store_name
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
store_global
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
store_deref
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
store_attr
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
store_locals
)(
emit_t
*
emit
);
void
(
*
store_subscr
)(
emit_t
*
emit
);
void
(
*
delete_fast
)(
emit_t
*
emit
,
qstr
qstr
,
int
local_num
);
void
(
*
delete_name
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
delete_global
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
delete_deref
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
delete_attr
)(
emit_t
*
emit
,
qstr
qstr
);
void
(
*
delete_subscr
)(
emit_t
*
emit
);
void
(
*
dup_top
)(
emit_t
*
emit
);
void
(
*
dup_top_two
)(
emit_t
*
emit
);
void
(
*
pop_top
)(
emit_t
*
emit
);
void
(
*
rot_two
)(
emit_t
*
emit
);
void
(
*
rot_three
)(
emit_t
*
emit
);
void
(
*
jump
)(
emit_t
*
emit
,
int
label
);
void
(
*
pop_jump_if_true
)(
emit_t
*
emit
,
int
label
);
void
(
*
pop_jump_if_false
)(
emit_t
*
emit
,
int
label
);
void
(
*
jump_if_true_or_pop
)(
emit_t
*
emit
,
int
label
);
void
(
*
jump_if_false_or_pop
)(
emit_t
*
emit
,
int
label
);
void
(
*
setup_loop
)(
emit_t
*
emit
,
int
label
);
void
(
*
break_loop
)(
emit_t
*
emit
,
int
label
);
void
(
*
continue_loop
)(
emit_t
*
emit
,
int
label
);
void
(
*
setup_with
)(
emit_t
*
emit
,
int
label
);
void
(
*
with_cleanup
)(
emit_t
*
emit
);
void
(
*
setup_except
)(
emit_t
*
emit
,
int
label
);
void
(
*
setup_finally
)(
emit_t
*
emit
,
int
label
);
void
(
*
end_finally
)(
emit_t
*
emit
);
void
(
*
get_iter
)(
emit_t
*
emit
);
// tos = getiter(tos)
void
(
*
for_iter
)(
emit_t
*
emit
,
int
label
);
void
(
*
for_iter_end
)(
emit_t
*
emit
);
void
(
*
pop_block
)(
emit_t
*
emit
);
void
(
*
pop_except
)(
emit_t
*
emit
);
void
(
*
unary_op
)(
emit_t
*
emit
,
rt_unary_op_t
op
);
void
(
*
binary_op
)(
emit_t
*
emit
,
rt_binary_op_t
op
);
void
(
*
compare_op
)(
emit_t
*
emit
,
rt_compare_op_t
op
);
void
(
*
build_tuple
)(
emit_t
*
emit
,
int
n_args
);
void
(
*
build_list
)(
emit_t
*
emit
,
int
n_args
);
void
(
*
list_append
)(
emit_t
*
emit
,
int
list_stack_index
);
void
(
*
build_map
)(
emit_t
*
emit
,
int
n_args
);
void
(
*
store_map
)(
emit_t
*
emit
);
void
(
*
map_add
)(
emit_t
*
emit
,
int
map_stack_index
);
void
(
*
build_set
)(
emit_t
*
emit
,
int
n_args
);
void
(
*
set_add
)(
emit_t
*
emit
,
int
set_stack_index
);
void
(
*
build_slice
)(
emit_t
*
emit
,
int
n_args
);
void
(
*
unpack_sequence
)(
emit_t
*
emit
,
int
n_args
);
void
(
*
unpack_ex
)(
emit_t
*
emit
,
int
n_left
,
int
n_right
);
void
(
*
make_function
)(
emit_t
*
emit
,
scope_t
*
scope
,
int
n_dict_params
,
int
n_default_params
);
void
(
*
make_closure
)(
emit_t
*
emit
,
scope_t
*
scope
,
int
n_dict_params
,
int
n_default_params
);
void
(
*
call_function
)(
emit_t
*
emit
,
int
n_positional
,
int
n_keyword
,
bool
have_star_arg
,
bool
have_dbl_star_arg
);
void
(
*
call_method
)(
emit_t
*
emit
,
int
n_positional
,
int
n_keyword
,
bool
have_star_arg
,
bool
have_dbl_star_arg
);
void
(
*
return_value
)(
emit_t
*
emit
);
void
(
*
raise_varargs
)(
emit_t
*
emit
,
int
n_args
);
void
(
*
yield_value
)(
emit_t
*
emit
);
void
(
*
yield_from
)(
emit_t
*
emit
);
}
emit_method_table_t
;
void
emit_common_load_id
(
pass_kind_t
pass
,
scope_t
*
scope
,
emit_t
*
emit
,
const
emit_method_table_t
*
emit_method_table
,
qstr
qstr___class__
,
qstr
qstr
);
void
emit_common_store_id
(
pass_kind_t
pass
,
scope_t
*
scope
,
emit_t
*
emit
,
const
emit_method_table_t
*
emit_method_table
,
qstr
qstr
);
void
emit_common_delete_id
(
pass_kind_t
pass
,
scope_t
*
scope
,
emit_t
*
emit
,
const
emit_method_table_t
*
emit_method_table
,
qstr
qstr
);
void
emit_common_declare_global
(
pass_kind_t
pass
,
scope_t
*
scope
,
qstr
qstr
);
void
emit_common_declare_nonlocal
(
pass_kind_t
pass
,
scope_t
*
scope
,
qstr
qstr
);
void
emit_common_load_id
(
pass_kind_t
pass
,
scope_t
*
scope
,
qstr
qstr___class__
,
emitter_t
*
emit
,
qstr
qstr
);
void
emit_common_store_id
(
pass_kind_t
pass
,
scope_t
*
scope
,
emitter_t
*
emit
,
qstr
qstr
);
void
emit_common_delete_id
(
pass_kind_t
pass
,
scope_t
*
scope
,
emitter_t
*
emit
,
qstr
qstr
);
void
emit_new_cpython
(
emit_t
**
emit
,
const
emit_method_table_t
**
emit_method_table
);
void
emit_new_bc
(
emit_t
**
emit
,
const
emit_method_table_t
**
emit_method_table
);
void
emit_new_x64
(
emit_t
**
emit
,
const
emit_method_table_t
**
emit_method_table
);
void
emit_new_thumb
(
emit_t
**
emit
,
const
emit_method_table_t
**
emit_method_table
);
emitter_t
*
emit_new
();
/*
void emit_set_native_types(emitter_t *emit, bool do_native_types);
void emit_start_pass(emitter_t *emit, pass_kind_t pass, scope_t *scope);
void emit_end_pass(emitter_t *emit);
...
...
@@ -118,3 +209,4 @@ void emit_return_value(emitter_t *emit);
void emit_raise_varargs(emitter_t *emit, int n_args);
void emit_yield_value(emitter_t *emit);
void emit_yield_from(emitter_t *emit);
*/
py/emitbc.c
View file @
415eb6f8
This diff is collapsed.
Click to expand it.
py/emitcommon.c
View file @
415eb6f8
...
...
@@ -12,53 +12,9 @@
#include
"runtime.h"
#include
"emit.h"
#define EMIT(fun, arg...) (emit_
##
fun(emit, ##arg))
#define EMIT(fun, arg...) (emit_
method_table->
fun(emit, ##arg))
void
emit_common_declare_global
(
pass_kind_t
pass
,
scope_t
*
scope
,
qstr
qstr
)
{
if
(
pass
==
PASS_1
)
{
if
(
scope
->
kind
==
SCOPE_MODULE
)
{
printf
(
"SyntaxError?: can't declare global in outer code
\n
"
);
return
;
}
bool
added
;
id_info_t
*
id_info
=
scope_find_or_add_id
(
scope
,
qstr
,
&
added
);
if
(
!
added
)
{
printf
(
"SyntaxError?: identifier already declared something
\n
"
);
return
;
}
id_info
->
kind
=
ID_INFO_KIND_GLOBAL_EXPLICIT
;
// if the id exists in the global scope, set its kind to EXPLICIT_GLOBAL
id_info
=
scope_find_global
(
scope
,
qstr
);
if
(
id_info
!=
NULL
)
{
id_info
->
kind
=
ID_INFO_KIND_GLOBAL_EXPLICIT
;
}
}
}
void
emit_common_declare_nonlocal
(
pass_kind_t
pass
,
scope_t
*
scope
,
qstr
qstr
)
{
if
(
pass
==
PASS_1
)
{
if
(
scope
->
kind
==
SCOPE_MODULE
)
{
printf
(
"SyntaxError?: can't declare nonlocal in outer code
\n
"
);
return
;
}
bool
added
;
id_info_t
*
id_info
=
scope_find_or_add_id
(
scope
,
qstr
,
&
added
);
if
(
!
added
)
{
printf
(
"SyntaxError?: identifier already declared something
\n
"
);
return
;
}
id_info_t
*
id_info2
=
scope_find_local_in_parent
(
scope
,
qstr
);
if
(
id_info2
==
NULL
||
!
(
id_info2
->
kind
==
ID_INFO_KIND_LOCAL
||
id_info2
->
kind
==
ID_INFO_KIND_CELL
||
id_info2
->
kind
==
ID_INFO_KIND_FREE
))
{
printf
(
"SyntaxError: no binding for nonlocal '%s' found
\n
"
,
qstr_str
(
qstr
));
return
;
}
id_info
->
kind
=
ID_INFO_KIND_FREE
;
scope_close_over_in_parents
(
scope
,
qstr
);
}
}
void
emit_common_load_id
(
pass_kind_t
pass
,
scope_t
*
scope
,
qstr
qstr___class__
,
emitter_t
*
emit
,
qstr
qstr
)
{
void
emit_common_load_id
(
pass_kind_t
pass
,
scope_t
*
scope
,
emit_t
*
emit
,
const
emit_method_table_t
*
emit_method_table
,
qstr
qstr___class__
,
qstr
qstr
)
{
id_info_t
*
id_info
=
NULL
;
if
(
pass
==
PASS_1
)
{
// name adding/lookup
...
...
@@ -109,7 +65,7 @@ void emit_common_load_id(pass_kind_t pass, scope_t *scope, qstr qstr___class__,
}
}
static
id_info_t
*
get_id_for_modification
(
pass_kind_t
pass
,
scope_t
*
scope
,
emitter_t
*
emit
,
qstr
qstr
)
{
static
id_info_t
*
get_id_for_modification
(
pass_kind_t
pass
,
scope_t
*
scope
,
qstr
qstr
)
{
id_info_t
*
id_info
=
NULL
;
if
(
pass
==
PASS_1
)
{
// name adding/lookup
...
...
@@ -134,9 +90,9 @@ static id_info_t *get_id_for_modification(pass_kind_t pass, scope_t *scope, emit
return
id_info
;
}
void
emit_common_store_id
(
pass_kind_t
pass
,
scope_t
*
scope
,
emit
ter
_t
*
emit
,
qstr
qstr
)
{
void
emit_common_store_id
(
pass_kind_t
pass
,
scope_t
*
scope
,
emit_t
*
emit
,
const
emit_method_table_t
*
emit_method_table
,
qstr
qstr
)
{
// create/get the id info
id_info_t
*
id
=
get_id_for_modification
(
pass
,
scope
,
emit
,
qstr
);
id_info_t
*
id
=
get_id_for_modification
(
pass
,
scope
,
qstr
);
// call the emit backend with the correct code
if
(
id
==
NULL
||
id
->
kind
==
ID_INFO_KIND_GLOBAL_IMPLICIT
)
{
...
...
@@ -152,9 +108,9 @@ void emit_common_store_id(pass_kind_t pass, scope_t *scope, emitter_t *emit, qst
}
}
void
emit_common_delete_id
(
pass_kind_t
pass
,
scope_t
*
scope
,
emit
ter
_t
*
emit
,
qstr
qstr
)
{
void
emit_common_delete_id
(
pass_kind_t
pass
,
scope_t
*
scope
,
emit_t
*
emit
,
const
emit_method_table_t
*
emit_method_table
,
qstr
qstr
)
{
// create/get the id info
id_info_t
*
id
=
get_id_for_modification
(
pass
,
scope
,
emit
,
qstr
);
id_info_t
*
id
=
get_id_for_modification
(
pass
,
scope
,
qstr
);
// call the emit backend with the correct code
if
(
id
==
NULL
||
id
->
kind
==
ID_INFO_KIND_GLOBAL_IMPLICIT
)
{
...
...
py/emitcpy.c
View file @
415eb6f8
This diff is collapsed.
Click to expand it.
py/emitx64.c
View file @
415eb6f8
This diff is collapsed.
Click to expand it.
py/scope.c
View file @
415eb6f8
...
...
@@ -165,6 +165,46 @@ void scope_close_over_in_parents(scope_t *scope, qstr qstr) {
assert
(
0
);
// we should have found the variable in one of the parents
}
void
scope_declare_global
(
scope_t
*
scope
,
qstr
qstr
)
{
if
(
scope
->
kind
==
SCOPE_MODULE
)
{
printf
(
"SyntaxError?: can't declare global in outer code
\n
"
);
return
;
}
bool
added
;
id_info_t
*
id_info
=
scope_find_or_add_id
(
scope
,
qstr
,
&
added
);
if
(
!
added
)
{
printf
(
"SyntaxError?: identifier already declared something
\n
"
);
return
;
}
id_info
->
kind
=
ID_INFO_KIND_GLOBAL_EXPLICIT
;
// if the id exists in the global scope, set its kind to EXPLICIT_GLOBAL
id_info
=
scope_find_global
(
scope
,
qstr
);
if
(
id_info
!=
NULL
)
{
id_info
->
kind
=
ID_INFO_KIND_GLOBAL_EXPLICIT
;
}
}
void
scope_declare_nonlocal
(
scope_t
*
scope
,
qstr
qstr
)
{
if
(
scope
->
kind
==
SCOPE_MODULE
)
{
printf
(
"SyntaxError?: can't declare nonlocal in outer code
\n
"
);
return
;
}
bool
added
;
id_info_t
*
id_info
=
scope_find_or_add_id
(
scope
,
qstr
,
&
added
);
if
(
!
added
)
{
printf
(
"SyntaxError?: identifier already declared something
\n
"
);
return
;
}
id_info_t
*
id_info2
=
scope_find_local_in_parent
(
scope
,
qstr
);
if
(
id_info2
==
NULL
||
!
(
id_info2
->
kind
==
ID_INFO_KIND_LOCAL
||
id_info2
->
kind
==
ID_INFO_KIND_CELL
||
id_info2
->
kind
==
ID_INFO_KIND_FREE
))
{
printf
(
"SyntaxError: no binding for nonlocal '%s' found
\n
"
,
qstr_str
(
qstr
));
return
;
}
id_info
->
kind
=
ID_INFO_KIND_FREE
;
scope_close_over_in_parents
(
scope
,
qstr
);
}
void
scope_print_info
(
scope_t
*
s
)
{
if
(
s
->
kind
==
SCOPE_MODULE
)
{
printf
(
"code <module>
\n
"
);
...
...
py/scope.h
View file @
415eb6f8