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
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
78 additions
and
14 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
This diff is collapsed. Click to expand it.
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