Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Franck Pommereau
/
cct
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Graphs
Issues
0
Wiki
Network
Create a new issue
Commits
Authored by
Franck Pommereau
2018-04-28 16:16:59 +0200
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
d9bfca1ddbd1964dffb049189a9de10a4050b366
d9bfca1d
1 parent
e12242fa
added source filename:lineno in output
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
132 additions
and
52 deletions
TODO
cctlib/cast.py
cctlib/clex.py
cctlib/cparse.py
cctlib/cttc.py
cctlib/cx86.py
cctlib/main.py
TODO
View file @
d9bfca1
* cparse.py: add lineno to nodes
* cttc.py & cx86.py: output lineno as comments
General:
* make a cleaner parser
* use preprocessor
TTC:
* make stdlib
* load extern symbols from stdlib (declared in .h)
x86:
...
...
cctlib/cast.py
View file @
d9bfca1
...
...
@@ -20,9 +20,16 @@ class Node:
self
.
colno
=
colno
self
.
filename
=
filename
def
loc
(
self
)
:
return
"
%
s:
%
s:
%
s"
%
(
self
.
filename
,
self
.
lineno
,
self
.
colno
)
def
loc
(
self
,
col
=
False
)
:
if
col
:
return
"
%
s:
%
s:
%
s"
%
(
self
.
filename
,
self
.
lineno
,
self
.
colno
)
else
:
return
"
%
s:
%
s"
%
(
self
.
filename
,
self
.
lineno
)
def
getpos
(
self
)
:
return
{
"lineno"
:
self
.
lineno
,
"colno"
:
self
.
colno
,
"filename"
:
self
.
filename
}
def
is_null
(
self
):
"""Returns whether the node represents a null node."""
...
...
cctlib/clex.py
View file @
d9bfca1
...
...
@@ -250,11 +250,11 @@ def t_WHITESPACE(t):
def
t_NEWLINE
(
t
):
r'\n+'
t
.
lineno
+=
len
(
t
.
value
)
t
.
l
exer
.
l
ineno
+=
len
(
t
.
value
)
def
t_COMMENT
(
t
):
r'/\*[\w\W]*?\*/'
t
.
lineno
+=
t
.
value
.
count
(
'
\n
'
)
t
.
l
exer
.
l
ineno
+=
t
.
value
.
count
(
'
\n
'
)
pass
# ---------------------------------------------------------------
...
...
cctlib/cparse.py
View file @
d9bfca1
...
...
@@ -8,6 +8,7 @@
# $Id: cparse.py,v 1.2 2004/05/27 16:25:08 varmaa Exp $
# ---------------------------------------------------------------
import
ply.lex
import
ply.yacc
as
yacc
from
.clex
import
tokens
# needed by yacc.yacc()
...
...
@@ -26,6 +27,21 @@ def _get_calculated(node):
else
:
return
node
inputfile
=
None
def
_get_pos
(
prod
)
:
for
p
in
prod
.
slice
[
1
:]
:
if
isinstance
(
p
,
Node
)
and
p
.
lineno
:
return
p
.
getpos
()
elif
isinstance
(
p
,
yacc
.
YaccSymbol
)
:
for
child
in
[
p
.
type
,
p
.
value
]
:
if
isinstance
(
child
,
Node
)
and
child
.
lineno
:
return
child
.
getpos
()
line_start
=
prod
.
lexer
.
lexdata
.
rfind
(
'
\n
'
,
0
,
prod
.
lexpos
(
1
))
+
1
return
{
"lineno"
:
prod
.
lineno
(
1
),
"colno"
:
prod
.
lexpos
(
1
)
-
line_start
+
1
,
"filename"
:
inputfile
}
# ---------------------------------------------------------------
# PARSER GRAMMAR / AST CONSTRUCTION
#
...
...
@@ -46,7 +62,7 @@ class ParseError(Exception):
def
p_translation_unit_01
(
t
):
'''translation_unit : external_declaration'''
t
[
0
]
=
TranslationUnit
(
t
[
1
])
t
[
0
]
=
TranslationUnit
(
t
[
1
]
,
**
_get_pos
(
t
)
)
def
p_translation_unit_02
(
t
):
'''translation_unit : translation_unit external_declaration'''
...
...
@@ -61,13 +77,13 @@ def p_external_declaration(t):
def
p_function_definition_01
(
t
):
'''function_definition : type_specifier declarator compound_statement'''
t
[
2
]
.
set_base_type
(
t
[
1
])
t
[
0
]
=
FunctionDefn
(
t
[
2
],
t
[
3
])
t
[
0
]
=
FunctionDefn
(
t
[
2
],
t
[
3
]
,
**
_get_pos
(
t
)
)
def
p_function_definition_02
(
t
):
'''function_definition : STATIC type_specifier declarator compound_statement'''
t
[
3
]
.
static
=
1
t
[
3
]
.
set_base_type
(
t
[
2
])
t
[
0
]
=
FunctionDefn
(
t
[
3
],
t
[
4
])
t
[
0
]
=
FunctionDefn
(
t
[
3
],
t
[
4
]
,
**
_get_pos
(
t
)
)
def
p_declaration_01
(
t
):
'''declaration : type_specifier declarator SEMICOLON'''
...
...
@@ -84,7 +100,7 @@ def p_declaration_02(t):
def
p_declaration_list_opt_01
(
t
):
'''declaration_list_opt : empty'''
t
[
0
]
=
NullNode
()
t
[
0
]
=
NullNode
(
**
_get_pos
(
t
)
)
def
p_declaration_list_opt_02
(
t
):
'''declaration_list_opt : declaration_list'''
...
...
@@ -92,7 +108,7 @@ def p_declaration_list_opt_02(t):
def
p_declaration_list_02
(
t
):
'''declaration_list : declaration'''
t
[
0
]
=
DeclarationList
(
t
[
1
])
t
[
0
]
=
DeclarationList
(
t
[
1
]
,
**
_get_pos
(
t
)
)
def
p_declaration_list_03
(
t
):
'''declaration_list : declaration_list declaration'''
...
...
@@ -102,7 +118,7 @@ def p_declaration_list_03(t):
def
p_type_specifier
(
t
):
'''type_specifier : INT
| CHAR'''
t
[
0
]
=
BaseType
(
t
[
1
])
t
[
0
]
=
BaseType
(
t
[
1
]
,
**
_get_pos
(
t
)
)
def
p_declarator_01
(
t
):
'''declarator : direct_declarator'''
...
...
@@ -115,16 +131,16 @@ def p_declarator_02(t):
def
p_direct_declarator_01
(
t
):
'''direct_declarator : ID'''
t
[
0
]
=
Declaration
(
t
[
1
])
t
[
0
]
=
Declaration
(
t
[
1
]
,
**
_get_pos
(
t
)
)
def
p_direct_declarator_02
(
t
):
'''direct_declarator : direct_declarator LPAREN parameter_type_list RPAREN'''
t
[
1
]
.
add_type
(
FunctionType
(
t
[
3
]))
t
[
1
]
.
add_type
(
FunctionType
(
t
[
3
]
,
**
_get_pos
(
t
)
))
t
[
0
]
=
t
[
1
]
def
p_direct_declarator_03
(
t
):
'''direct_declarator : direct_declarator LPAREN RPAREN'''
t
[
1
]
.
add_type
(
FunctionType
(
ParamList
()))
t
[
1
]
.
add_type
(
FunctionType
(
ParamList
(
**
_get_pos
(
t
)),
**
_get_pos
(
t
)))
t
[
0
]
=
t
[
1
]
def
p_parameter_type_list_01
(
t
):
...
...
@@ -138,7 +154,7 @@ def p_parameter_type_list_02(t):
def
p_parameter_list_01
(
t
):
'''parameter_list : parameter_declaration'''
t
[
0
]
=
ParamList
(
t
[
1
])
t
[
0
]
=
ParamList
(
t
[
1
]
,
**
_get_pos
(
t
)
)
def
p_parameter_list_02
(
t
):
'''parameter_list : parameter_list COMMA parameter_declaration'''
...
...
@@ -152,11 +168,11 @@ def p_parameter_declaration(t):
def
p_compound_statement_01
(
t
):
'''compound_statement : LBRACE declaration_list_opt statement_list RBRACE'''
t
[
0
]
=
CompoundStatement
(
t
[
2
],
t
[
3
])
t
[
0
]
=
CompoundStatement
(
t
[
2
],
t
[
3
]
,
**
_get_pos
(
t
)
)
def
p_compound_statement_02
(
t
):
'''compound_statement : LBRACE declaration_list_opt RBRACE'''
t
[
0
]
=
CompoundStatement
(
t
[
2
],
NullNode
())
t
[
0
]
=
CompoundStatement
(
t
[
2
],
NullNode
(
**
_get_pos
(
t
)),
**
_get_pos
(
t
))
def
p_expression_statement
(
t
):
'''expression_statement : expression SEMICOLON'''
...
...
@@ -170,7 +186,7 @@ def p_expression_02(t):
'''expression : equality_expression ASSIGN expression
| equality_expression EQ_PLUS expression
| equality_expression EQ_MINUS expression'''
t
[
0
]
=
Binop
(
t
[
1
],
t
[
3
],
t
[
2
])
t
[
0
]
=
Binop
(
t
[
1
],
t
[
3
],
t
[
2
]
,
**
_get_pos
(
t
)
)
def
p_equality_expression_01
(
t
):
'''equality_expression : relational_expression'''
...
...
@@ -179,7 +195,7 @@ def p_equality_expression_01(t):
def
p_equality_expression_02
(
t
):
'''equality_expression : equality_expression EQ relational_expression
| equality_expression NOT_EQ relational_expression'''
t
[
0
]
=
_get_calculated
(
Binop
(
t
[
1
],
t
[
3
],
t
[
2
]))
t
[
0
]
=
_get_calculated
(
Binop
(
t
[
1
],
t
[
3
],
t
[
2
]
,
**
_get_pos
(
t
)
))
def
p_relational_expression_01
(
t
):
'''relational_expression : additive_expression'''
...
...
@@ -190,7 +206,7 @@ def p_relational_expression_02(t):
| relational_expression GREATER additive_expression
| relational_expression LESS_EQ additive_expression
| relational_expression GREATER_EQ additive_expression'''
t
[
0
]
=
_get_calculated
(
Binop
(
t
[
1
],
t
[
3
],
t
[
2
]))
t
[
0
]
=
_get_calculated
(
Binop
(
t
[
1
],
t
[
3
],
t
[
2
]
,
**
_get_pos
(
t
)
))
def
p_postfix_expression_01
(
t
):
'''postfix_expression : primary_expression'''
...
...
@@ -198,20 +214,20 @@ def p_postfix_expression_01(t):
def
p_postfix_expression_02
(
t
):
'''postfix_expression : postfix_expression LPAREN argument_expression_list RPAREN'''
t
[
0
]
=
FunctionExpression
(
t
[
1
],
t
[
3
])
t
[
0
]
=
FunctionExpression
(
t
[
1
],
t
[
3
]
,
**
_get_pos
(
t
)
)
pass
def
p_postfix_expression_03
(
t
):
'''postfix_expression : postfix_expression LPAREN RPAREN'''
t
[
0
]
=
FunctionExpression
(
t
[
1
],
ArgumentList
())
t
[
0
]
=
FunctionExpression
(
t
[
1
],
ArgumentList
(
**
_get_pos
(
t
)),
**
_get_pos
(
t
))
def
p_postfix_expression_04
(
t
):
'''postfix_expression : postfix_expression LBRACKET expression RBRACKET'''
t
[
0
]
=
ArrayExpression
(
t
[
1
],
t
[
3
])
t
[
0
]
=
ArrayExpression
(
t
[
1
],
t
[
3
]
,
**
_get_pos
(
t
)
)
def
p_argument_expression_list_01
(
t
):
'''argument_expression_list : expression'''
t
[
0
]
=
ArgumentList
(
t
[
1
])
t
[
0
]
=
ArgumentList
(
t
[
1
]
,
**
_get_pos
(
t
)
)
def
p_argument_expression_list_02
(
t
):
'''argument_expression_list : argument_expression_list COMMA expression'''
...
...
@@ -224,7 +240,7 @@ def p_unary_expression_01(t):
def
p_unary_expression_02
(
t
):
'''unary_expression : MINUS unary_expression'''
t
[
0
]
=
_get_calculated
(
Negative
(
t
[
2
]))
t
[
0
]
=
_get_calculated
(
Negative
(
t
[
2
]
,
**
_get_pos
(
t
)
))
def
p_unary_expression_03
(
t
):
'''unary_expression : PLUS unary_expression'''
...
...
@@ -234,15 +250,15 @@ def p_unary_expression_03(t):
'''unary_expression : EXCLAMATION unary_expression'''
# horrible hack for the '!' operator... Just insert an
# (expr == 0) into the AST.
t
[
0
]
=
_get_calculated
(
Binop
(
t
[
2
],
Const
(
0
,
BaseType
(
'int'
)),
'=='
))
t
[
0
]
=
_get_calculated
(
Binop
(
t
[
2
],
Const
(
0
,
BaseType
(
'int'
)),
'=='
,
**
_get_pos
(
t
)
))
def
p_unary_expression_04
(
t
):
'''unary_expression : ASTERISK unary_expression'''
t
[
0
]
=
Pointer
(
t
[
2
])
t
[
0
]
=
Pointer
(
t
[
2
]
,
**
_get_pos
(
t
)
)
def
p_unary_expression_05
(
t
):
'''unary_expression : AMPERSAND unary_expression'''
t
[
0
]
=
AddrOf
(
t
[
2
])
t
[
0
]
=
AddrOf
(
t
[
2
]
,
**
_get_pos
(
t
)
)
def
p_mult_expression_01
(
t
):
'''mult_expression : unary_expression'''
...
...
@@ -252,7 +268,7 @@ def p_mult_expression_02(t):
'''mult_expression : mult_expression ASTERISK unary_expression
| mult_expression DIV unary_expression
| mult_expression MODULO unary_expression'''
t
[
0
]
=
_get_calculated
(
Binop
(
t
[
1
],
t
[
3
],
t
[
2
]))
t
[
0
]
=
_get_calculated
(
Binop
(
t
[
1
],
t
[
3
],
t
[
2
]
,
**
_get_pos
(
t
)
))
def
p_additive_expression_01
(
t
):
'''additive_expression : mult_expression'''
...
...
@@ -261,23 +277,23 @@ def p_additive_expression_01(t):
def
p_additive_expression_02
(
t
):
'''additive_expression : additive_expression PLUS mult_expression
| additive_expression MINUS mult_expression'''
t
[
0
]
=
_get_calculated
(
Binop
(
t
[
1
],
t
[
3
],
t
[
2
]))
t
[
0
]
=
_get_calculated
(
Binop
(
t
[
1
],
t
[
3
],
t
[
2
]
,
**
_get_pos
(
t
)
))
def
p_primary_expression_01
(
t
):
'''primary_expression : ID'''
t
[
0
]
=
Id
(
t
[
1
],
t
.
lineno
(
1
))
t
[
0
]
=
Id
(
t
[
1
],
**
_get_pos
(
t
))
def
p_primary_expression_02
(
t
):
'''primary_expression : INUMBER'''
t
[
0
]
=
Const
(
int
(
t
[
1
]),
BaseType
(
'int'
))
t
[
0
]
=
Const
(
int
(
t
[
1
]),
BaseType
(
'int'
,
**
_get_pos
(
t
)),
**
_get_pos
(
t
))
def
p_primary_expression_03
(
t
):
'''primary_expression : FNUMBER'''
t
[
0
]
=
Const
(
float
(
t
[
1
]),
BaseType
(
'double'
))
t
[
0
]
=
Const
(
float
(
t
[
1
]),
BaseType
(
'double'
,
**
_get_pos
(
t
)),
**
_get_pos
(
t
))
def
p_primary_expression_04
(
t
):
'''primary_expression : CHARACTER'''
t
[
0
]
=
Const
(
ord
(
eval
(
t
[
1
])),
BaseType
(
'char'
))
t
[
0
]
=
Const
(
ord
(
eval
(
t
[
1
])),
BaseType
(
'char'
,
**
_get_pos
(
t
)),
**
_get_pos
(
t
))
def
p_primary_expression_05
(
t
):
'''primary_expression : string_literal'''
...
...
@@ -289,7 +305,7 @@ def p_primary_expression_06(t):
def
p_string_literal_01
(
t
):
'''string_literal : STRING'''
t
[
0
]
=
StringLiteral
(
eval
(
t
[
1
]))
t
[
0
]
=
StringLiteral
(
eval
(
t
[
1
])
,
**
_get_pos
(
t
)
)
def
p_string_literal_02
(
t
):
'''string_literal : string_literal STRING'''
...
...
@@ -306,11 +322,11 @@ def p_statement(t):
def
p_jump_statement_01
(
t
):
'''jump_statement : RETURN SEMICOLON'''
t
[
0
]
=
ReturnStatement
(
NullNode
())
t
[
0
]
=
ReturnStatement
(
NullNode
(
**
_get_pos
(
t
)),
**
_get_pos
(
t
))
def
p_jump_statement_02
(
t
):
'''jump_statement : RETURN expression SEMICOLON'''
t
[
0
]
=
ReturnStatement
(
t
[
2
])
t
[
0
]
=
ReturnStatement
(
t
[
2
]
,
**
_get_pos
(
t
)
)
def
p_jump_statement_03
(
t
):
'''jump_statement : BREAK SEMICOLON'''
...
...
@@ -322,23 +338,23 @@ def p_jump_statement_04(t):
def
p_iteration_statement_01
(
t
):
'''iteration_statement : WHILE LPAREN expression RPAREN statement'''
t
[
0
]
=
WhileLoop
(
t
[
3
],
t
[
5
])
t
[
0
]
=
WhileLoop
(
t
[
3
],
t
[
5
]
,
**
_get_pos
(
t
)
)
def
p_iteration_statement_02
(
t
):
'''iteration_statement : FOR LPAREN expression_statement expression_statement expression RPAREN statement'''
t
[
0
]
=
ForLoop
(
t
[
3
],
t
[
4
],
t
[
5
],
t
[
7
])
t
[
0
]
=
ForLoop
(
t
[
3
],
t
[
4
],
t
[
5
],
t
[
7
]
,
**
_get_pos
(
t
)
)
def
p_selection_statement_01
(
t
):
'''selection_statement : IF LPAREN expression RPAREN statement'''
t
[
0
]
=
IfStatement
(
t
[
3
],
t
[
5
],
NullNode
())
t
[
0
]
=
IfStatement
(
t
[
3
],
t
[
5
],
NullNode
(
**
_get_pos
(
t
)),
**
_get_pos
(
t
))
def
p_selection_statement_02
(
t
):
'''selection_statement : IF LPAREN expression RPAREN statement ELSE statement'''
t
[
0
]
=
IfStatement
(
t
[
3
],
t
[
5
],
t
[
7
])
t
[
0
]
=
IfStatement
(
t
[
3
],
t
[
5
],
t
[
7
]
,
**
_get_pos
(
t
)
)
def
p_statement_list_02
(
t
):
'''statement_list : statement'''
t
[
0
]
=
StatementList
(
t
[
1
])
t
[
0
]
=
StatementList
(
t
[
1
]
,
**
_get_pos
(
t
)
)
def
p_statement_list_03
(
t
):
'''statement_list : statement_list statement'''
...
...
@@ -350,7 +366,7 @@ def p_empty(t):
pass
def
p_error
(
t
):
print
(
"[
%
s] syntax error:"
%
t
.
lineno
)
print
(
"[
%
(filename)
:
%(lineno)
s:
%(colno)
s] syntax error:"
%
_get_pos
(
t
)
)
start
=
t
.
lexer
.
lexdata
.
rfind
(
"
\n
"
,
0
,
t
.
lexpos
)
if
start
==
-
1
:
start
=
0
...
...
cctlib/cttc.py
View file @
d9bfca1
...
...
@@ -142,6 +142,11 @@ class CodeGenVisitor (Visitor) :
def
c
(
self
,
str
,
indent_amt
=
2
):
self
.
curr_str
.
write
(
"
\n
#
%
s
\n\n
"
%
str
)
def
_loc
(
self
,
node
,
comment
=
""
)
:
if
node
.
lineno
!=
self
.
_last_lineno
or
comment
:
self
.
_last_lineno
=
node
.
lineno
self
.
curr_str
.
write
(
"#
%
s
%
s
\n
"
%
(
node
.
loc
(),
comment
))
def
vNodeList
(
self
,
node
):
self
.
_visitList
(
node
.
nodes
)
...
...
@@ -158,6 +163,7 @@ class CodeGenVisitor (Visitor) :
def
vStatementList
(
self
,
node
):
for
n
in
node
.
nodes
:
self
.
_loc
(
n
)
self
.
_accept_and_empty_stack
(
n
)
def
_generate_global_variable_definitions
(
self
,
node
):
...
...
@@ -169,6 +175,7 @@ class CodeGenVisitor (Visitor) :
return
globals_str
def
vTranslationUnit
(
self
,
node
):
self
.
_last_lineno
=
None
self
.
curr_str
=
io
.
StringIO
()
self
.
globals_str
=
self
.
_generate_global_variable_definitions
(
node
)
self
.
_visitList
(
node
.
nodes
)
...
...
@@ -239,6 +246,7 @@ class CodeGenVisitor (Visitor) :
stack_frame_size
=
self
.
_calc_function_var_addrs
(
node
.
symtab
,
0
)
line
=
self
.
_fill_line
(
"BEGIN FUNCTION:
%
s()"
%
node
.
name
)
self
.
c
(
"
%
s
\n
#
\n
# Function type:
%
s"
%
(
line
,
node
.
type
.
get_string
()),
0
)
self
.
_loc
(
node
,
"(enter function)"
)
self
.
o
(
"
%
s:"
%
node
.
compile_loc
)
self
.
o
(
" push BP"
,
"Save old frame pointer"
)
self
.
o
(
" mov SP BP"
,
"Set new frame pointer"
)
...
...
@@ -255,6 +263,7 @@ class CodeGenVisitor (Visitor) :
self
.
o
(
" sub R9 SP SP"
,
"... shift SP"
)
self
.
stack
.
save_callee_saves
()
self
.
curr_str
.
write
(
function_str
.
getvalue
())
self
.
_loc
(
node
,
"(exit function)"
)
self
.
o
(
"
%
s:"
%
self
.
curr_func_end_label
)
self
.
stack
.
load_callee_saves
()
self
.
o
(
" mov BP SP"
,
"Deallocate local+temp vars"
)
...
...
@@ -264,9 +273,11 @@ class CodeGenVisitor (Visitor) :
self
.
c
(
line
,
0
)
def
vCompoundStatement
(
self
,
node
):
self
.
_loc
(
node
)
node
.
statement_list
.
accept
(
self
)
def
vIfStatement
(
self
,
node
):
self
.
_loc
(
node
)
done_label
=
self
.
new_label
()
+
"_done"
if
not
node
.
else_stmt
.
is_null
():
else_label
=
self
.
new_label
()
+
"_else"
...
...
@@ -300,6 +311,7 @@ class CodeGenVisitor (Visitor) :
self
.
continue_labels
.
pop
()
def
vWhileLoop
(
self
,
node
):
self
.
_loc
(
node
)
test_label
=
self
.
new_label
()
+
"_test"
done_label
=
self
.
new_label
()
+
"_done"
self
.
_push_loop_labels
(
break_label
=
done_label
,
...
...
@@ -319,6 +331,7 @@ class CodeGenVisitor (Visitor) :
self
.
_pop_loop_labels
()
def
vForLoop
(
self
,
node
):
self
.
_loc
(
node
)
test_label
=
self
.
new_label
()
+
"_test"
done_label
=
self
.
new_label
()
+
"_done"
self
.
_push_loop_labels
(
break_label
=
done_label
,
...
...
@@ -340,10 +353,12 @@ class CodeGenVisitor (Visitor) :
self
.
_pop_loop_labels
()
def
vBreakStatement
(
self
,
node
):
self
.
_loc
(
node
)
self
.
o
(
" set R9 @
%
s"
%
self
.
break_labels
[
-
1
],
"Loop: break statement"
)
self
.
o
(
" jmp R9"
,
"... jump to loop exit"
)
def
vContinueStatement
(
self
,
node
):
self
.
_loc
(
node
)
self
.
o
(
" set R9 @
%
s"
%
self
.
continue_labels
[
-
1
],
"Loop: continue statement"
)
self
.
o
(
" jmp R9"
,
"... jump to loop start"
)
...
...
@@ -359,6 +374,7 @@ class CodeGenVisitor (Visitor) :
return
label_str
def
vStringLiteral
(
self
,
node
):
self
.
_loc
(
node
)
label_str
=
self
.
_get_new_str_literal_label
(
node
.
get_str
())
COMMENT_CHARS
=
7
comment_label
=
node
.
get_sanitized_str
()
...
...
@@ -368,10 +384,12 @@ class CodeGenVisitor (Visitor) :
"Get addr of string literal '
%
s'"
%
comment_label
)
def
vConst
(
self
,
node
):
self
.
_loc
(
node
)
self
.
o
(
" set
%
s
%
X"
%
(
self
.
stack
.
push
(),
node
.
value
),
"Load numeric constant
%
d"
%
node
.
value
)
def
vId
(
self
,
node
):
self
.
_loc
(
node
)
if
node
.
output_addr
:
if
isinstance
(
node
.
symbol
.
compile_loc
,
int
)
:
self
.
o
(
" set R9
%
X"
%
node
.
symbol
.
compile_loc
,
...
...
@@ -392,6 +410,7 @@ class CodeGenVisitor (Visitor) :
self
.
o
(
" ld
%
s
%
s"
%
(
reg
,
reg
),
"Get value of
%
s"
%
node
.
symbol
.
name
)
def
vArrayExpression
(
self
,
node
):
self
.
_loc
(
node
)
node
.
expr
.
accept
(
self
)
node
.
index
.
accept
(
self
)
reg_index
=
self
.
stack
.
pop
()
...
...
@@ -404,6 +423,7 @@ class CodeGenVisitor (Visitor) :
self
.
o
(
" ld
%
s
%
s"
%
(
reg_to
,
reg_to
),
"Load array value"
)
def
vFunctionExpression
(
self
,
node
):
self
.
_loc
(
node
)
if
self
.
test
and
node
.
function
.
symbol
.
name
==
"TTCTEST"
:
call
=
node
.
arglist
.
nodes
[
0
]
.
get_str
()
expect
=
self
.
test
[
call
]
...
...
@@ -433,6 +453,7 @@ class CodeGenVisitor (Visitor) :
self
.
c
(
"FUNCTION CALL to
%
s() - end"
%
node
.
function
.
symbol
.
name
)
def
vReturnStatement
(
self
,
node
):
self
.
_loc
(
node
)
return_reg
=
self
.
_accept_and_pop
(
node
.
expr
)
self
.
o
(
" mov
%
s R0"
%
return_reg
,
"Set return value"
)
self
.
o
(
" set R9 @
%
s"
%
self
.
curr_func_end_label
,
...
...
@@ -526,6 +547,7 @@ class CodeGenVisitor (Visitor) :
raise
Exception
(
"unsupported comparison
%
r"
%
node
.
op
)
def
vBinop
(
self
,
node
):
self
.
_loc
(
node
)
if
node
.
op
in
cparse
.
Binop
.
ASSIGN_OPS
:
self
.
_binop_assign
(
node
)
elif
node
.
op
in
[
'+'
,
'-'
,
'*'
]:
...
...
@@ -534,11 +556,13 @@ class CodeGenVisitor (Visitor) :
self
.
_binop_compare
(
node
)
def
vNegative
(
self
,
node
):
self
.
_loc
(
node
)
node
.
expr
.
accept
(
self
)
reg
=
self
.
stack
.
peek
()
self
.
o
(
" neg
%
s
%
s"
%
(
reg
,
reg
),
"Perform unary negation"
)
def
vPointer
(
self
,
node
):
self
.
_loc
(
node
)
node
.
expr
.
accept
(
self
)
if
node
.
output_addr
:
self
.
o
(
""
,
"(Getting pointer target addr via '*')"
)
...
...
@@ -549,6 +573,7 @@ class CodeGenVisitor (Visitor) :
self
.
stack
.
done
()
def
vAddrOf
(
self
,
node
):
self
.
_loc
(
node
)
node
.
expr
.
accept
(
self
)
self
.
o
(
""
,
"(Address-of operator '&' used here)"
)
...
...
@@ -558,6 +583,6 @@ def compile (path) :
def
cpp
(
args
,
path
)
:
if
args
.
test
:
return
[
"cpp"
,
"-
P"
,
"-
D"
,
"TTC"
,
path
]
return
[
"cpp"
,
"-D"
,
"TTC"
,
path
]
else
:
return
[
"cpp"
,
"-P"
,
path
]
return
[
"cpp"
,
path
]
...
...
cctlib/cx86.py
View file @
d9bfca1
...
...
@@ -478,7 +478,13 @@ class CodeGenVisitor(Visitor):
self
.
o
(
"
\n
%
s#
%
s
\n
"
%
(
indent
,
str
))
def
_loc
(
self
,
node
,
comment
=
""
)
:
if
node
.
lineno
!=
self
.
_last_lineno
or
comment
:
self
.
_last_lineno
=
node
.
lineno
self
.
curr_str
.
write
(
"#
%
s
%
s
\n
"
%
(
node
.
loc
(),
comment
))
def
vNodeList
(
self
,
node
):
self
.
_loc
(
node
)
self
.
_visitList
(
node
.
nodes
)
def
_empty_stack
(
self
,
node
):
...
...
@@ -506,6 +512,7 @@ class CodeGenVisitor(Visitor):
def
vStatementList
(
self
,
node
):
for
n
in
node
.
nodes
:
self
.
_loc
(
n
)
self
.
_accept_and_empty_stack
(
n
)
def
_generate_global_variable_definitions
(
self
,
node
):
...
...
@@ -524,6 +531,7 @@ class CodeGenVisitor(Visitor):
def
vTranslationUnit
(
self
,
node
):
"""Outputs the entire assembly source file."""
self
.
_last_lineno
=
None
self
.
curr_str
=
io
.
StringIO
()
self
.
globals_str
=
self
.
_generate_global_variable_definitions
(
node
)
...
...
@@ -665,6 +673,7 @@ class CodeGenVisitor(Visitor):
"# Function type:
%
s"
%
(
line
,
node
.
type
.
get_string
()),
0
)
self
.
_loc
(
node
,
"(enter function)"
)
if
not
node
.
static
:
self
.
o
(
" .global
%
s"
%
node
.
compile_loc
)
self
.
o
(
"
%
s:"
%
node
.
compile_loc
)
...
...
@@ -700,6 +709,7 @@ class CodeGenVisitor(Visitor):
# Add the previously-generated assembly code for the function.
self
.
curr_str
.
write
(
function_str
.
getvalue
())
self
.
_loc
(
node
,
"(exit function)"
)
self
.
o
(
"
%
s:"
%
self
.
curr_func_end_label
)
# Restore any callee-save registers that may have been used.
...
...
@@ -712,9 +722,11 @@ class CodeGenVisitor(Visitor):
self
.
c
(
line
,
0
)
def
vCompoundStatement
(
self
,
node
):
self
.
_loc
(
node
)
node
.
statement_list
.
accept
(
self
)
def
vIfStatement
(
self
,
node
):
self
.
_loc
(
node
)
done_label
=
self
.
new_label
()
+
"_done"
if
not
node
.
else_stmt
.
is_null
():
else_label
=
self
.
new_label
()
+
"_else"
...
...
@@ -757,6 +769,7 @@ class CodeGenVisitor(Visitor):
self
.
continue_labels
.
pop
()
def
vWhileLoop
(
self
,
node
):
self
.
_loc
(
node
)
test_label
=
self
.
new_label
()
+
"_test"
done_label
=
self
.
new_label
()
+
"_done"
...
...
@@ -782,6 +795,7 @@ class CodeGenVisitor(Visitor):
self
.
_pop_loop_labels
()
def
vForLoop
(
self
,
node
):
self
.
_loc
(
node
)
test_label
=
self
.
new_label
()
+
"_test"
done_label
=
self
.
new_label
()
+
"_done"
...
...
@@ -810,10 +824,12 @@ class CodeGenVisitor(Visitor):
self
.
_pop_loop_labels
()
def
vBreakStatement
(
self
,
node
):
self
.
_loc
(
node
)
self
.
o
(
" jmp
%
s"
%
self
.
break_labels
[
-
1
],
"Loop: break statement"
)
def
vContinueStatement
(
self
,
node
):
self
.
_loc
(
node
)
self
.
o
(
" jmp
%
s"
%
self
.
continue_labels
[
-
1
],
"Loop: continue statement"
)
...
...
@@ -833,6 +849,7 @@ class CodeGenVisitor(Visitor):
return
label_str
def
vStringLiteral
(
self
,
node
):
self
.
_loc
(
node
)
label_str
=
self
.
_get_new_str_literal_label
(
node
.
get_str
())
# Make a little preview of the literal in the annotated
...
...
@@ -847,11 +864,13 @@ class CodeGenVisitor(Visitor):
"Get addr of string literal '
%
s'"
%
comment_label
)
def
vConst
(
self
,
node
):
self
.
_loc
(
node
)
self
.
o
(
" movl $
%
d,
%
s"
%
(
node
.
value
,
self
.
stack
.
push
(
node
.
type
)),
"Load numeric constant
%
d"
%
node
.
value
)
def
vId
(
self
,
node
):
self
.
_loc
(
node
)
# If we're only supposed to push our address on the stack, not
# our actual value, then do that and exit.
if
node
.
output_addr
:
...
...
@@ -869,6 +888,7 @@ class CodeGenVisitor(Visitor):
"Get value of
%
s"
%
node
.
symbol
.
name
)
def
vArrayExpression
(
self
,
node
):
self
.
_loc
(
node
)
node
.
expr
.
accept
(
self
)
node
.
index
.
accept
(
self
)
reg_index
=
self
.
stack
.
pop
(
node
.
index
.
type
)
...
...
@@ -891,6 +911,7 @@ class CodeGenVisitor(Visitor):
def
vFunctionExpression
(
self
,
node
):
"""Generates assembly for calling a function."""
self
.
_loc
(
node
)
self
.
c
(
"FUNCTION CALL to
%
s() - begin"
%
node
.
function
.
symbol
.
name
)
...
...
@@ -936,6 +957,7 @@ class CodeGenVisitor(Visitor):
node
.
function
.
symbol
.
name
)
def
vReturnStatement
(
self
,
node
):
self
.
_loc
(
node
)
return_reg
=
self
.
_accept_and_pop
(
node
.
expr
)
self
.
o
(
" movl
%
s,
%%
eax"
%
return_reg
,
"Set return value"
)
self
.
o
(
" jmp
%
s"
%
self
.
curr_func_end_label
,
"Exit function"
)
...
...
@@ -1051,6 +1073,7 @@ class CodeGenVisitor(Visitor):
"Zero-extend the boolean result"
)
def
vBinop
(
self
,
node
):
self
.
_loc
(
node
)
if
node
.
op
in
cparse
.
Binop
.
ASSIGN_OPS
:
self
.
_binop_assign
(
node
)
elif
node
.
op
in
[
'+'
,
'-'
,
'*'
]:
...
...
@@ -1059,11 +1082,13 @@ class CodeGenVisitor(Visitor):
self
.
_binop_compare
(
node
)
def
vNegative
(
self
,
node
):
self
.
_loc
(
node
)
node
.
expr
.
accept
(
self
)
self
.
o
(
" negl
%
s"
%
self
.
stack
.
peek
(),
"Perform unary negation"
)
def
vPointer
(
self
,
node
):
self
.
_loc
(
node
)
node
.
expr
.
accept
(
self
)
if
node
.
output_addr
:
self
.
o
(
""
,
"(Getting pointer target addr via '*')"
)
...
...
@@ -1080,6 +1105,7 @@ class CodeGenVisitor(Visitor):
self
.
stack
.
done
()
def
vAddrOf
(
self
,
node
):
self
.
_loc
(
node
)
node
.
expr
.
accept
(
self
)
self
.
stack
.
force_type_change
(
node
.
type
)
self
.
o
(
""
,
"(Address-of operator '&' used here)"
)
...
...
@@ -1094,6 +1120,6 @@ def compile (path) :
def
cpp
(
args
,
path
)
:
if
args
.
test
:
return
[
"cpp"
,
"-
P"
,
"-
D"
,
"CC"
,
path
]
return
[
"cpp"
,
"-D"
,
"CC"
,
path
]
else
:
return
[
"cpp"
,
"-P"
,
path
]
return
[
"cpp"
,
path
]
...
...
cctlib/main.py
View file @
d9bfca1
...
...
@@ -27,6 +27,7 @@ class Compiler (object) :
self
.
total_warnings
=
0
def
_parse
(
self
)
:
"Parses the source code."
cparse
.
inputfile
=
self
.
path
self
.
ast
=
yacc
.
parse
(
self
.
code
)
def
_compile_phase
(
self
,
visitor
)
:
"Applies a visitor to the abstract syntax tree."
...
...
@@ -109,8 +110,10 @@ def main (args=None) :
print
(
"Preprocessing
%
r"
%
src
)
cpp
=
ARCH
[
args
.
arch
]
.
cpp
(
args
,
src
)
print
(
"..$
%
s"
%
" "
.
join
(
cpp
))
code
=
subprocess
.
check_output
(
cpp
)
.
decode
()
print
(
"Compiling preprocessed
%
r (line numbers may have changed)"
%
src
)
code
=
"
\n
"
.
join
(
l
.
rstrip
()
for
l
in
subprocess
.
check_output
(
cpp
)
.
decode
()
.
splitlines
()
if
not
l
.
startswith
(
"#"
))
print
(
"Compiling preprocessed
%
r"
%
src
)
else
:
code
=
"
\n
"
.
join
(
l
.
rstrip
()
for
l
in
open
(
src
)
.
readlines
())
print
(
"Compiling
%
r"
%
src
)
...
...
Please
register
or
login
to post a comment