Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
C
C Compiler
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
gyuri
C Compiler
Commits
b58eb1e8
Commit
b58eb1e8
authored
Nov 20, 2020
by
gyuri
Browse files
Options
Downloads
Patches
Plain Diff
Make code generator handle translation units
parent
37f8ce09
No related branches found
No related tags found
No related merge requests found
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
meson.build
+21
-20
21 additions, 20 deletions
meson.build
src/c.y
+2
-2
2 additions, 2 deletions
src/c.y
src/cg.c
+112
-61
112 additions, 61 deletions
src/cg.c
test/compiler_test.c
+6
-0
6 additions, 0 deletions
test/compiler_test.c
with
141 additions
and
83 deletions
meson.build
+
21
−
20
View file @
b58eb1e8
...
...
@@ -27,31 +27,32 @@ pfiles = pgen.process('src/c.y')
c_compiler
=
executable
(
'c_compiler'
,
'src/ast.c'
,
'src/cg.c'
,
lfiles
,
pfiles
,
dependencies
:
[
ds_vec_dep
,
ds_hashmap_dep
],
include_directories
:
incdir
)
#
comp_asm = generator(c_compiler,
#
output : [ '@BASENAME@.s' ],
#
arguments : [ 'asm', '@INPUT@' ],
#
capture : true
#
)
#
#
test_s = comp_asm.process('compiler_test.c')
#
test_o = custom_target(
#
'test_o',
#
input : test_s,
#
output : [ '@BASENAME@.o' ],
#
command : [ nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@' ]
#
)
#
test_e = custom_target(
#
'test_e',
#
input : test_o,
#
output : [ '@BASENAME@' ],
#
command : [ gcc, '-static', '@INPUT@', '-o', '@OUTPUT@' ],
#
build_by_default : true
#
)
comp_asm
=
generator
(
c_compiler
,
output
:
[
'@BASENAME@.s'
],
arguments
:
[
'asm'
,
'@INPUT@'
],
capture
:
true
)
test_s
=
comp_asm
.
process
(
'
test/
compiler_test.c'
)
test_o
=
custom_target
(
'test_o'
,
input
:
test_s
,
output
:
[
'@BASENAME@.o'
],
command
:
[
nasm
,
'-f'
,
'elf64'
,
'-o'
,
'@OUTPUT@'
,
'@INPUT@'
]
)
test_e
=
custom_target
(
'test_e'
,
input
:
test_o
,
output
:
[
'@BASENAME@'
],
command
:
[
gcc
,
'-static'
,
'@INPUT@'
,
'-o'
,
'@OUTPUT@'
],
build_by_default
:
true
)
# a bit ugly because LaTeX needs to be compiled twice, but does the job...
prog_pdflatex
=
find_program
(
'pdflatex'
,
required
:
false
)
...
...
This diff is collapsed.
Click to expand it.
src/c.y
+
2
−
2
View file @
b58eb1e8
...
...
@@ -34,8 +34,8 @@ int main(int argc, char *argv[])
if (strcmp(argv[1], "ast") == 0) {
ast_fprint(stdout, n, 0);
//
} else if (strcmp(argv[1], "asm") == 0) {
//
cg_gen(n);
} else if (strcmp(argv[1], "asm") == 0) {
cg_gen(n);
} else {
return EXIT_FAILURE;
}
...
...
This diff is collapsed.
Click to expand it.
src/cg.c
+
112
−
61
View file @
b58eb1e8
...
...
@@ -3,6 +3,11 @@
#include
<stdio.h>
#include
<c_compiler/cg.h>
#define GETI(x, i) *(struct ast_node * const *)vec_get_c(&(x), i)
#define FOR_EACH_NODE(x) \
const struct ast_node *ni = GETI(x, 0); \
for (int i = 0; ni; ni = ((++i < (x).len) ? GETI(x, i): NULL))
struct
state
{
struct
hashmap
vars
;
/* hashmap<int> */
int
sp
;
/* stack pointer */
...
...
@@ -234,66 +239,112 @@ static val cg_gen_expr(struct state *s, const struct ast_node *n) {
case
AST_MEMBER_DEREF
:
// TODO
break
;
case
AST_UNARY
:
return
cg_gen_unary
(
s
,
n
);
case
AST_BIN
:
return
cg_gen_bin
(
s
,
n
);
case
AST_UNARY
:
return
cg_gen_unary
(
s
,
n
);
case
AST_COMPOUND_LITERAL
:
// TODO;
break
;
case
AST_SIZEOF_EXPR
:
// TODO
break
;
case
AST_ALIGNOF_EXPR
:
// TODO
break
;
case
AST_CAST
:
// TODO
break
;
case
AST_BIN
:
return
cg_gen_bin
(
s
,
n
);
// TODO
break
;
case
AST_CONDITIONAL
:
// TODO
break
;
default:
// TODO: we shouldn't be here
break
;
}
return
(
val
){
.
s
=
3
};
}
static
void
cg_gen_stmt_comp
(
struct
state
*
s
,
const
struct
ast_node
*
n
)
{
for
(
int
i
=
0
;
i
<
n
->
stmt_comp
.
len
;
++
i
)
{
const
struct
ast_node
*
ni
=
*
(
struct
ast_node
*
const
*
)
vec_get_c
(
&
n
->
stmt_comp
,
i
);
// fprintf(s->f, "; ");
// ast_fprint(s->f, ni, 0);
switch
(
ni
->
kind
)
{
case
AST_DECL
:
;
struct
ast_node
*
name
=
ni
->
decl
.
t
.
ident
;
struct
ast_type
t
=
ni
->
decl
.
t
;
if
(
name
->
kind
==
AST_IDENT
)
{
static
void
cg_gen_declaration
(
struct
state
*
s
,
const
struct
ast_node
*
n
)
{
FOR_EACH_NODE
(
n
->
declaration
.
init_declarator_list
)
{
const
struct
ast_node
*
d
=
ni
->
init_declarator
.
declarator
,
*
dd
=
d
->
declarator
.
direct_declarator
;
if
(
dd
->
kind
==
AST_IDENT
)
{
// TODO: type. now we assume literally EVERY type is 64 bit...
int
size
=
8
,
array
;
if
(
t
.
array
&&
(
const_eval
(
t
.
array
,
&
array
)
==
0
))
{
size
*=
array
;
}
int
size
=
8
;
s
->
sp
-=
size
;
hashmap_put
(
&
s
->
vars
,
name
->
ident
,
&
s
->
sp
);
}
else
{
// TODO: we shouldn't be here
hashmap_put
(
&
s
->
vars
,
dd
->
ident
,
&
s
->
sp
);
}
break
;
}
}
static
void
cg_gen_stmt_comp
(
struct
state
*
s
,
const
struct
ast_node
*
n
);
static
void
cg_gen_stmt
(
struct
state
*
s
,
const
struct
ast_node
*
n
)
{
switch
(
n
->
kind
)
{
case
AST_STMT_EXPR
:
cg_gen_expr
(
s
,
n
i
->
stmt_expr
.
a
);
cg_gen_expr
(
s
,
n
->
stmt_expr
.
a
);
break
;
case
AST_STMT_WHILE
:
;
int
label_start
=
get_label
(
s
),
label_end
=
get_label
(
s
);
put_label
(
s
,
label_start
);
val
val_
a
=
cg_gen_expr
(
s
,
n
i
->
stmt_while
.
a
);
val_read
(
s
,
&
val_
a
,
"rax"
);
val
val_
cond
=
cg_gen_expr
(
s
,
n
->
stmt_while
.
cond
);
val_read
(
s
,
&
val_
cond
,
"rax"
);
fprintf
(
s
->
f
,
"cmp rax, 0
\n
"
);
fprintf
(
s
->
f
,
"je label_%d
\n
"
,
label_end
);
if
(
ni
->
stmt_while
.
b
->
kind
==
AST_STMT_COMP
)
cg_gen_stmt_comp
(
s
,
ni
->
stmt_while
.
b
);
cg_gen_stmt
(
s
,
n
->
stmt_while
.
stmt
);
fprintf
(
s
->
f
,
"jmp label_%d
\n
"
,
label_start
);
put_label
(
s
,
label_end
);
break
;
case
AST_STMT_IF
:
{
int
label_end
=
get_label
(
s
);
val
val_
a
=
cg_gen_expr
(
s
,
n
i
->
stmt_if
.
a
);
val_read
(
s
,
&
val_
a
,
"rax"
);
val
val_
cond
=
cg_gen_expr
(
s
,
n
->
stmt_if
.
cond
);
val_read
(
s
,
&
val_
cond
,
"rax"
);
fprintf
(
s
->
f
,
"cmp rax, 0
\n
"
);
fprintf
(
s
->
f
,
"je label_%d
\n
"
,
label_end
);
if
(
ni
->
stmt_if
.
b
->
kind
==
AST_STMT_COMP
)
cg_gen_stmt_comp
(
s
,
ni
->
stmt_if
.
b
);
cg_gen_stmt
(
s
,
n
->
stmt_if
.
stmt
);
// TODO: else
put_label
(
s
,
label_end
);
break
;
case
AST_STMT_COMP
:
cg_gen_stmt_comp
(
s
,
n
);
break
;
}
default:
;
// TODO: we shouldn't be here
}
}
static
void
cg_gen_stmt_comp
(
struct
state
*
s
,
const
struct
ast_node
*
n
)
{
FOR_EACH_NODE
(
n
->
stmt_comp
)
{
if
(
ni
->
kind
==
AST_DECLARATION
)
{
cg_gen_declaration
(
s
,
ni
);
}
else
{
cg_gen_stmt
(
s
,
ni
);
}
}
}
static
void
cg_gen_function_definition
(
struct
state
*
s
,
const
struct
ast_node
*
n
)
{
const
struct
ast_node
*
d
=
n
->
function_definition
.
declarator
,
*
dd
=
d
->
declarator
.
direct_declarator
;
if
(
dd
->
kind
!=
AST_FUNCTION_DECLARATOR
)
return
;
const
struct
ast_node
*
i
=
dd
->
function_declarator
.
direct_declarator
;
if
(
i
->
kind
!=
AST_IDENT
)
return
;
fprintf
(
s
->
f
,
"%s:
\n
"
,
i
->
ident
);
fprintf
(
s
->
f
,
"push rbp
\n
"
);
fprintf
(
s
->
f
,
"mov rbp, rsp
\n
"
);
cg_gen_stmt_comp
(
s
,
n
->
function_definition
.
compound_statement
);
fprintf
(
s
->
f
,
"mov rsp, rbp
\n
"
);
fprintf
(
s
->
f
,
"pop rbp
\n
"
);
fprintf
(
s
->
f
,
"mov rax, 0
\n
"
);
fprintf
(
s
->
f
,
"ret
\n
"
);
fprintf
(
s
->
f
,
"
\n
"
);
}
void
cg_gen
(
const
struct
ast_node
*
n
)
{
...
...
@@ -308,18 +359,18 @@ void cg_gen(const struct ast_node *n) {
fprintf
(
s
->
f
,
"extern malloc
\n
"
);
fprintf
(
s
->
f
,
"extern free
\n
"
);
fprintf
(
s
->
f
,
"extern getchar
\n
"
);
fprintf
(
s
->
f
,
"main:
\n
"
);
fprintf
(
s
->
f
,
"push rbp
\n
"
);
fprintf
(
s
->
f
,
"mov rbp, rsp
\n
"
);
if
(
n
->
kind
==
AST_STMT_COMP
)
{
cg_gen_stmt_comp
(
s
,
n
);
if
(
n
->
kind
==
AST_TRANSLATION_UNIT
)
{
for
(
int
i
=
0
;
i
<
n
->
translation_unit
.
len
;
++
i
)
{
const
struct
ast_node
*
ni
=
*
(
struct
ast_node
*
const
*
)
vec_get_c
(
&
n
->
translation_unit
,
i
);
if
(
ni
->
kind
==
AST_DECLARATION
)
{
// TODO
}
else
if
(
ni
->
kind
==
AST_FUNCTION_DEFINITION
)
{
cg_gen_function_definition
(
s
,
ni
);
}
}
}
fprintf
(
s
->
f
,
"mov rsp, rbp
\n
"
);
fprintf
(
s
->
f
,
"pop rbp
\n
"
);
fprintf
(
s
->
f
,
"mov rax, 0
\n
"
);
fprintf
(
s
->
f
,
"ret
\n
"
);
fprintf
(
s
->
f
,
"section .rodata
\n
"
);
for
(
int
i
=
0
;
i
<
s
->
strings
.
len
;
++
i
)
{
...
...
This diff is collapsed.
Click to expand it.
test/compiler_test.c
0 → 100644
+
6
−
0
View file @
b58eb1e8
int
main
()
{
int
i
;
i
=
5
;
while
(
i
)
printf
(
"Hello world; i=%d%c"
,
--
i
,
10
);
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment