Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
2
2022fall-Compiler_CMinus
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
李晓奇
2022fall-Compiler_CMinus
Commits
83f09476
Commit
83f09476
authored
Jan 28, 2023
by
lxq
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
should pass the functional test
parent
33502fa9
Changes
4
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
224 additions
and
188 deletions
+224
-188
include/codegen.hpp
include/codegen.hpp
+20
-15
src/cminusfc/cminusfc.cpp
src/cminusfc/cminusfc.cpp
+19
-10
src/codegen/codegen.cpp
src/codegen/codegen.cpp
+163
-152
tests/5-bonus/test_time.py
tests/5-bonus/test_time.py
+22
-11
No files found.
include/codegen.hpp
View file @
83f09476
...
...
@@ -43,18 +43,17 @@ class CodeGen {
void
IR2assem
(
GetElementPtrInst
*
);
void
IR2assem
(
CallInst
*
);
void
IR2assem
(
BranchInst
*
);
void
IR2assem
(
BinaryInst
*
);
void
IR2assem
(
FpToSiInst
*
);
void
IR2assem
(
SiToFpInst
*
);
// The Instructions below will do nothing
void
IR2assem
(
AllocaInst
*
)
{}
// integration with BranchInst
void
IR2assem
(
CmpInst
*
)
{}
void
IR2assem
(
FCmpInst
*
)
{}
void
IR2assem
(
ZextInst
*
)
{}
void
IR2assem
(
BinaryInst
*
);
void
IR2assem
(
PhiInst
*
)
{}
void
IR2assem
(
FCmpInst
*
)
{}
void
IR2assem
(
FpToSiInst
*
)
{}
void
IR2assem
(
SiToFpInst
*
)
{}
void
stackMemAlloc
();
void
stackMemDealloc
();
...
...
@@ -63,7 +62,7 @@ class CodeGen {
// - for global variables and pointers from alloca and GEP, read through
// address
// only use register a_id and t_
void
value2reg
(
Value
*
,
int
id
=
0
,
bool
is_float
=
false
);
void
value2reg
(
Value
*
,
int
id
=
0
);
// load the content in ptr to specified register.
// only use register a_id and t_
void
ptrContent2reg
(
Value
*
,
int
id
=
0
);
...
...
@@ -92,21 +91,27 @@ class CodeGen {
}
}
void
back2stack
(
Instruction
*
instr
,
string
reg
=
"$a0"
)
{
// assert the value needed to store back is in $a0 or $f0, according to the
// value type
void
back2stack
(
Instruction
*
instr
)
{
// std::cerr << instr->print() << std::endl;
string
suff
=
suffix
(
typeLen
(
instr
->
get_type
()));
auto
type
=
instr
->
get_type
();
string
instr_ir
=
type
->
is_float_type
()
?
"fst"
:
"st"
;
string
suff
=
suffix
(
type
);
string
reg
=
type
->
is_float_type
()
?
"$fa0"
:
"$a0"
;
string
addr
=
"$fp, -"
+
std
::
to_string
(
off
[
instr
]);
output
.
push_back
(
"st"
+
suff
+
" "
+
reg
+
"
"
+
addr
);
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg
+
",
"
+
addr
);
}
string
suffix
(
int
len
)
{
string
suffix
(
Type
*
type
)
{
int
len
=
typeLen
(
type
);
switch
(
len
)
{
case
1
:
return
".b"
;
case
2
:
return
".h"
;
case
4
:
return
".w"
;
return
type
->
is_float_type
()
?
".s"
:
".w"
;
case
8
:
return
".d"
;
}
...
...
@@ -116,16 +121,16 @@ class CodeGen {
bool
no_stack_alloca
(
Instruction
*
instr
)
{
if
(
instr
->
is_void
())
return
true
;
if
(
instr
->
is_cmp
()
or
instr
->
is_zext
())
if
(
instr
->
is_
fcmp
()
or
instr
->
is_
cmp
()
or
instr
->
is_zext
())
return
true
;
return
false
;
}
std
::
map
<
Value
*
,
unsigned
int
>
off
;
//
to $fp
std
::
map
<
Value
*
,
unsigned
int
>
off
;
// stack offset
to $fp
std
::
map
<
Function
*
,
std
::
map
<
int
,
int
>>
func_arg_off
;
// to $sp
std
::
map
<
Function
*
,
int
>
func_arg_N
;
unsigned
int
stackN
;
std
::
map
<
Function
*
,
int
>
func_arg_N
;
// total space for args
unsigned
int
stackN
;
// function local vars and so on
Function
*
cur_func
;
...
...
src/cminusfc/cminusfc.cpp
View file @
83f09476
...
...
@@ -17,13 +17,16 @@
using
namespace
std
::
literals
::
string_literals
;
void
print_help
(
std
::
string
exe_name
)
{
void
print_help
(
std
::
string
exe_name
)
{
std
::
cout
<<
"Usage: "
<<
exe_name
<<
" [ -h | --help ] [ -o <target-file> ] [ -emit-llvm ] [-mem2reg] [-gvn] [-dump-json] <input-file>"
<<
" [ -h | --help ] [ -o <target-file> ] [ -emit-llvm ] "
"[-mem2reg] [-gvn] [-dump-json] <input-file>"
<<
std
::
endl
;
}
int
main
(
int
argc
,
char
**
argv
)
{
int
main
(
int
argc
,
char
**
argv
)
{
std
::
string
target_path
;
std
::
string
input_path
;
...
...
@@ -36,9 +39,11 @@ int main(int argc, char **argv) {
if
(
argv
[
i
]
==
"-h"
s
||
argv
[
i
]
==
"--help"
s
)
{
print_help
(
argv
[
0
]);
return
0
;
}
else
if
(
argv
[
i
]
==
"-o"
s
)
{
}
else
if
(
argv
[
i
]
==
"-o"
s
||
argv
[
i
]
==
"-S"
s
)
{
if
(
target_path
.
empty
()
&&
i
+
1
<
argc
)
{
target_path
=
argv
[
i
+
1
];
if
(
target_path
.
rfind
(
"."
)
!=
std
::
string
::
npos
)
target_path
=
target_path
.
substr
(
0
,
target_path
.
rfind
(
"."
));
i
+=
1
;
}
else
{
print_help
(
argv
[
0
]);
...
...
@@ -71,12 +76,13 @@ int main(int argc, char **argv) {
if
(
target_path
.
empty
())
{
auto
pos
=
input_path
.
rfind
(
'.'
);
if
(
pos
==
std
::
string
::
npos
)
{
std
::
cerr
<<
argv
[
0
]
<<
": input file "
<<
input_path
<<
" has unknown filetype!"
<<
std
::
endl
;
std
::
cerr
<<
argv
[
0
]
<<
": input file "
<<
input_path
<<
" has unknown filetype!"
<<
std
::
endl
;
return
-
1
;
}
else
{
// if (input_path.substr(pos) != ".cminus") {
// std::cerr << argv[0] << ": input file " << input_path << "
has unknown filetype!" << std::endl;
// return -1;
// std::cerr << argv[0] << ": input file " << input_path << "
//
has unknown filetype!" << std::endl;
return -1;
// }
target_path
=
input_path
.
substr
(
0
,
pos
);
}
...
...
@@ -89,7 +95,8 @@ int main(int argc, char **argv) {
a
.
run_visitor
(
builder
);
}
catch
(
std
::
exception
e
)
{
std
::
cout
<<
"Exception catched:
\n\t
"
<<
e
.
what
()
<<
std
::
endl
;
std
::
cout
<<
"Already generated IR code:
\n
"
<<
builder
.
getModule
()
->
print
();
std
::
cout
<<
"Already generated IR code:
\n
"
<<
builder
.
getModule
()
->
print
();
return
-
1
;
}
...
...
@@ -104,7 +111,8 @@ int main(int argc, char **argv) {
if
(
gvn
)
{
PM
.
add_pass
<
DeadCode
>
(
false
);
// remove some undef
PM
.
add_pass
<
GVN
>
(
emit
,
dump_json
);
PM
.
add_pass
<
DeadCode
>
(
false
);
// delete unused instructions created by GVN
PM
.
add_pass
<
DeadCode
>
(
false
);
// delete unused instructions created by GVN
}
PM
.
run
();
...
...
@@ -132,7 +140,8 @@ int main(int argc, char **argv) {
lib_path
.
erase
(
lib_path
.
rfind
(
'/'
));
else
lib_path
.
clear
();
auto
cmd_str
=
"clang -O0 -w -no-pie "
s
+
target_path
+
".ll -o "
+
target_path
+
lib_path
+
" -lcminus_io"
;
auto
cmd_str
=
"clang -O0 -w -no-pie "
s
+
target_path
+
".ll -o "
+
target_path
+
lib_path
+
" -lcminus_io"
;
int
re_code0
=
std
::
system
(
cmd_str
.
c_str
());
cmd_str
=
"rm "
s
+
target_path
+
".ll"
;
int
re_code1
=
std
::
system
(
cmd_str
.
c_str
());
...
...
src/codegen/codegen.cpp
View file @
83f09476
This diff is collapsed.
Click to expand it.
tests/5-bonus/test_time.py
View file @
83f09476
...
...
@@ -6,7 +6,7 @@ import argparse
import
subprocess
test_dir
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
))
# 当前文件夹路径 tests/5-bonus
cminus
=
os
.
path
.
join
(
test_dir
,
'../../build/cminus'
)
# ===可修改===
cminus
=
os
.
path
.
join
(
test_dir
,
'../../build/cminus
fc
'
)
# ===可修改===
testfile_dir
=
os
.
path
.
join
(
test_dir
,
'./testcases'
)
output_file_name
=
os
.
path
.
join
(
test_dir
,
'./test_result'
)
io
=
os
.
path
.
join
(
test_dir
,
'../../src/io/io.c'
)
...
...
@@ -56,7 +56,8 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
# 超时,跳过
if
start_time
-
total_start
>
30
*
60
or
start_time
-
single_begin
>
30
*
60
:
output_file
.
write
(
f"[
{
count
+
1
}
/
{
test_count
}
] "
+
file_name
+
': skipped due to exceeded total time limit
\n
'
)
output_file
.
write
(
f"[
{
count
+
1
}
/
{
test_count
}
] "
+
file_name
+
': skipped due to exceeded total time limit
\n
'
)
continue
# 未超时
output_file
.
write
(
f"[
{
count
+
1
}
/
{
test_count
}
] "
+
file_name
+
': '
)
...
...
@@ -75,8 +76,9 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
output_file
.
write
(
'compile-1 timeout
\n
'
)
failed_count
+=
1
continue
except
Exception
:
except
Exception
as
e
:
output_file
.
write
(
"compile-1 failed with an unexcept error
\n
"
)
output_file
.
write
(
str
(
e
))
failed_count
+=
1
continue
...
...
@@ -107,8 +109,9 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
output_file
.
write
(
'compile timeout
\n
'
)
failed_count
+=
1
continue
except
Exception
:
except
Exception
as
e
:
output_file
.
write
(
"compile failed with an unexcept error
\n
"
)
output_file
.
write
(
e
)
failed_count
+=
1
continue
...
...
@@ -135,8 +138,9 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
output_file
.
write
(
"executable time limit exceeded
\n
"
)
failed_count
+=
1
continue
except
Exception
as
_
:
except
Exception
as
e
:
output_file
.
write
(
'executable runtime error
\n
'
)
output_file
.
write
(
str
(
e
))
failed_count
+=
1
continue
...
...
@@ -159,8 +163,11 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
succ_count
+=
1
testtime
[
count
]
=
time
else
:
output_file
.
write
(
'output is different from standard answer, this may be caused by wrong return code
\n
'
)
# 因为退出码也会作为输出的一部分,因此输出和答案不同可能是程序崩溃造成的
# 因为退出码也会作为输出的一部分,因此输出和答案不同可能是程序崩溃造成的
output_file
.
write
(
'output is different from standard answer, this may be caused by wrong return code
\n
'
)
output_file
.
write
(
f"
\t
{
ref
=
}
"
)
output_file
.
write
(
f"
\t
{
actual
=
}
"
)
failed_count
+=
1
output_file
.
write
(
f"
{
failed_count
}
tests failed
\n
"
)
...
...
@@ -172,9 +179,11 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
output_file
.
write
(
'
\t\t\t
your_cminus'
)
for
count
,
file_name
in
enumerate
(
testfiles
):
output_file
.
write
(
'{:<20}'
.
format
(
file_name
))
output_file
.
write
(
'
\t\t
%.6f'
%
testtime
[
count
]
if
testtime
[
count
]
!=
-
1
else
'
\t\t
None '
)
output_file
.
write
(
'
\t\t
%.6f'
%
testtime
[
count
]
if
testtime
[
count
]
!=
-
1
else
'
\t\t
None '
)
output_file
.
write
(
"===================================================================
\n
"
)
output_file
.
write
(
"===================================================================
\n
"
)
if
__name__
==
"__main__"
:
...
...
@@ -182,8 +191,10 @@ if __name__ == "__main__":
parser
=
argparse
.
ArgumentParser
(
description
=
"functional test"
)
parser
.
add_argument
(
"--console"
,
action
=
"store_true"
,
help
=
"specify whether to output the result to console"
)
parser
.
add_argument
(
"--clang"
,
action
=
"store_true"
,
help
=
"estimate runtime when compile with clang"
)
parser
.
add_argument
(
"--console"
,
action
=
"store_true"
,
help
=
"specify whether to output the result to console"
)
parser
.
add_argument
(
"--clang"
,
action
=
"store_true"
,
help
=
"estimate runtime when compile with clang"
)
args
=
parser
.
parse_args
()
eval
(
args
.
console
,
testfile_dir
,
use_clang
=
args
.
clang
)
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