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
Show 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 {
...
@@ -43,18 +43,17 @@ class CodeGen {
void
IR2assem
(
GetElementPtrInst
*
);
void
IR2assem
(
GetElementPtrInst
*
);
void
IR2assem
(
CallInst
*
);
void
IR2assem
(
CallInst
*
);
void
IR2assem
(
BranchInst
*
);
void
IR2assem
(
BranchInst
*
);
void
IR2assem
(
BinaryInst
*
);
void
IR2assem
(
FpToSiInst
*
);
void
IR2assem
(
SiToFpInst
*
);
// The Instructions below will do nothing
// The Instructions below will do nothing
void
IR2assem
(
AllocaInst
*
)
{}
void
IR2assem
(
AllocaInst
*
)
{}
// integration with BranchInst
// integration with BranchInst
void
IR2assem
(
CmpInst
*
)
{}
void
IR2assem
(
CmpInst
*
)
{}
void
IR2assem
(
FCmpInst
*
)
{}
void
IR2assem
(
ZextInst
*
)
{}
void
IR2assem
(
ZextInst
*
)
{}
void
IR2assem
(
BinaryInst
*
);
void
IR2assem
(
PhiInst
*
)
{}
void
IR2assem
(
PhiInst
*
)
{}
void
IR2assem
(
FCmpInst
*
)
{}
void
IR2assem
(
FpToSiInst
*
)
{}
void
IR2assem
(
SiToFpInst
*
)
{}
void
stackMemAlloc
();
void
stackMemAlloc
();
void
stackMemDealloc
();
void
stackMemDealloc
();
...
@@ -63,7 +62,7 @@ class CodeGen {
...
@@ -63,7 +62,7 @@ class CodeGen {
// - for global variables and pointers from alloca and GEP, read through
// - for global variables and pointers from alloca and GEP, read through
// address
// address
// only use register a_id and t_
// 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.
// load the content in ptr to specified register.
// only use register a_id and t_
// only use register a_id and t_
void
ptrContent2reg
(
Value
*
,
int
id
=
0
);
void
ptrContent2reg
(
Value
*
,
int
id
=
0
);
...
@@ -92,21 +91,27 @@ class CodeGen {
...
@@ -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;
// 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
]);
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
)
{
switch
(
len
)
{
case
1
:
case
1
:
return
".b"
;
return
".b"
;
case
2
:
case
2
:
return
".h"
;
return
".h"
;
case
4
:
case
4
:
return
".w"
;
return
type
->
is_float_type
()
?
".s"
:
".w"
;
case
8
:
case
8
:
return
".d"
;
return
".d"
;
}
}
...
@@ -116,16 +121,16 @@ class CodeGen {
...
@@ -116,16 +121,16 @@ class CodeGen {
bool
no_stack_alloca
(
Instruction
*
instr
)
{
bool
no_stack_alloca
(
Instruction
*
instr
)
{
if
(
instr
->
is_void
())
if
(
instr
->
is_void
())
return
true
;
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
true
;
return
false
;
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
*
,
std
::
map
<
int
,
int
>>
func_arg_off
;
// to $sp
std
::
map
<
Function
*
,
int
>
func_arg_N
;
std
::
map
<
Function
*
,
int
>
func_arg_N
;
// total space for args
unsigned
int
stackN
;
unsigned
int
stackN
;
// function local vars and so on
Function
*
cur_func
;
Function
*
cur_func
;
...
...
src/cminusfc/cminusfc.cpp
View file @
83f09476
...
@@ -17,13 +17,16 @@
...
@@ -17,13 +17,16 @@
using
namespace
std
::
literals
::
string_literals
;
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
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
;
<<
std
::
endl
;
}
}
int
main
(
int
argc
,
char
**
argv
)
{
int
main
(
int
argc
,
char
**
argv
)
{
std
::
string
target_path
;
std
::
string
target_path
;
std
::
string
input_path
;
std
::
string
input_path
;
...
@@ -36,9 +39,11 @@ int main(int argc, char **argv) {
...
@@ -36,9 +39,11 @@ int main(int argc, char **argv) {
if
(
argv
[
i
]
==
"-h"
s
||
argv
[
i
]
==
"--help"
s
)
{
if
(
argv
[
i
]
==
"-h"
s
||
argv
[
i
]
==
"--help"
s
)
{
print_help
(
argv
[
0
]);
print_help
(
argv
[
0
]);
return
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
)
{
if
(
target_path
.
empty
()
&&
i
+
1
<
argc
)
{
target_path
=
argv
[
i
+
1
];
target_path
=
argv
[
i
+
1
];
if
(
target_path
.
rfind
(
"."
)
!=
std
::
string
::
npos
)
target_path
=
target_path
.
substr
(
0
,
target_path
.
rfind
(
"."
));
i
+=
1
;
i
+=
1
;
}
else
{
}
else
{
print_help
(
argv
[
0
]);
print_help
(
argv
[
0
]);
...
@@ -71,12 +76,13 @@ int main(int argc, char **argv) {
...
@@ -71,12 +76,13 @@ int main(int argc, char **argv) {
if
(
target_path
.
empty
())
{
if
(
target_path
.
empty
())
{
auto
pos
=
input_path
.
rfind
(
'.'
);
auto
pos
=
input_path
.
rfind
(
'.'
);
if
(
pos
==
std
::
string
::
npos
)
{
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
;
return
-
1
;
}
else
{
}
else
{
// if (input_path.substr(pos) != ".cminus") {
// if (input_path.substr(pos) != ".cminus") {
// std::cerr << argv[0] << ": input file " << input_path << "
has unknown filetype!" << std::endl;
// std::cerr << argv[0] << ": input file " << input_path << "
// return -1;
//
has unknown filetype!" << std::endl;
return -1;
// }
// }
target_path
=
input_path
.
substr
(
0
,
pos
);
target_path
=
input_path
.
substr
(
0
,
pos
);
}
}
...
@@ -89,7 +95,8 @@ int main(int argc, char **argv) {
...
@@ -89,7 +95,8 @@ int main(int argc, char **argv) {
a
.
run_visitor
(
builder
);
a
.
run_visitor
(
builder
);
}
catch
(
std
::
exception
e
)
{
}
catch
(
std
::
exception
e
)
{
std
::
cout
<<
"Exception catched:
\n\t
"
<<
e
.
what
()
<<
std
::
endl
;
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
;
return
-
1
;
}
}
...
@@ -104,7 +111,8 @@ int main(int argc, char **argv) {
...
@@ -104,7 +111,8 @@ int main(int argc, char **argv) {
if
(
gvn
)
{
if
(
gvn
)
{
PM
.
add_pass
<
DeadCode
>
(
false
);
// remove some undef
PM
.
add_pass
<
DeadCode
>
(
false
);
// remove some undef
PM
.
add_pass
<
GVN
>
(
emit
,
dump_json
);
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
();
PM
.
run
();
...
@@ -132,7 +140,8 @@ int main(int argc, char **argv) {
...
@@ -132,7 +140,8 @@ int main(int argc, char **argv) {
lib_path
.
erase
(
lib_path
.
rfind
(
'/'
));
lib_path
.
erase
(
lib_path
.
rfind
(
'/'
));
else
else
lib_path
.
clear
();
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
());
int
re_code0
=
std
::
system
(
cmd_str
.
c_str
());
cmd_str
=
"rm "
s
+
target_path
+
".ll"
;
cmd_str
=
"rm "
s
+
target_path
+
".ll"
;
int
re_code1
=
std
::
system
(
cmd_str
.
c_str
());
int
re_code1
=
std
::
system
(
cmd_str
.
c_str
());
...
...
src/codegen/codegen.cpp
View file @
83f09476
...
@@ -13,6 +13,8 @@
...
@@ -13,6 +13,8 @@
#include "Type.h"
#include "Type.h"
#include "Value.h"
#include "Value.h"
#include <cstdint>
#include <cstring>
#include <string>
#include <string>
// $r0 $zero constant 0
// $r0 $zero constant 0
...
@@ -98,50 +100,67 @@ CodeGen::run() {
...
@@ -98,50 +100,67 @@ CodeGen::run() {
void
void
CodeGen
::
ptrContent2reg
(
Value
*
ptr
,
int
id
)
{
CodeGen
::
ptrContent2reg
(
Value
*
ptr
,
int
id
)
{
auto
reg_name
=
"$a"
+
to_string
(
id
);
auto
ele_tp
=
ptr
->
get_type
()
->
get_pointer_element_type
();
assert
(
ele_tp
);
bool
is_float
=
ele_tp
->
is_float_type
();
string
instr_ir
=
(
is_float
?
"fld"
:
"ld"
);
string
reg_name
=
(
is_float
?
"$fa"
:
"$a"
)
+
to_string
(
id
);
string
suff
=
suffix
(
ele_tp
);
if
(
dynamic_cast
<
GlobalVariable
*>
(
ptr
))
{
if
(
dynamic_cast
<
GlobalVariable
*>
(
ptr
))
{
auto
type
=
static_cast
<
GlobalVariable
*>
(
ptr
)
->
get_type
()
->
get_pointer_element_type
();
auto
suff
=
suffix
(
typeLen
(
type
));
output
.
push_back
(
"la.local "
+
reg_name
+
", "
+
ptr
->
get_name
());
output
.
push_back
(
"la.local "
+
reg_name
+
", "
+
ptr
->
get_name
());
output
.
push_back
(
"ldx"
+
suff
+
" "
+
reg_name
+
", "
+
reg_name
+
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg_name
+
", "
+
reg_name
+
",
$r
0"
);
", 0"
);
}
else
if
(
dynamic_cast
<
AllocaInst
*>
(
ptr
))
{
}
else
if
(
dynamic_cast
<
AllocaInst
*>
(
ptr
))
{
auto
alloc_instr
=
static_cast
<
AllocaInst
*>
(
ptr
);
/*
auto alloc_instr = static_cast<AllocaInst *>(ptr);
string
suff
=
suffix
(
typeLen
(
alloc_instr
->
get_alloca_type
()));
* string suff = suffix(alloc_instr->get_alloca_type()); */
output
.
push_back
(
"ld"
+
suff
+
" "
+
reg_name
+
", $fp, -"
+
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg_name
+
", $fp, -"
+
to_string
(
off
[
ptr
]));
to_string
(
off
[
ptr
]));
}
else
if
(
dynamic_cast
<
GetElementPtrInst
*>
(
ptr
))
{
}
else
if
(
dynamic_cast
<
GetElementPtrInst
*>
(
ptr
))
{
auto
GEP_instr
=
static_cast
<
GetElementPtrInst
*>
(
ptr
);
// auto GEP_instr = static_cast<GetElementPtrInst *>(ptr);
auto
suff
=
suffix
(
typeLen
(
GEP_instr
->
get_element_type
()));
output
.
push_back
(
"ld.d "
+
reg_name
+
", $fp, -"
+
to_string
(
off
[
ptr
]));
output
.
push_back
(
"ld.d "
+
reg_name
+
", $fp, -"
+
to_string
(
off
[
ptr
]));
output
.
push_back
(
"ldx"
+
suff
+
" "
+
reg_name
+
", "
+
reg_name
+
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg_name
+
", "
+
reg_name
+
",
$r
0"
);
", 0"
);
}
else
}
else
assert
(
false
&&
"unknown type"
);
assert
(
false
&&
"unknown type"
);
}
}
void
void
CodeGen
::
value2reg
(
Value
*
v
,
int
id
,
bool
is_float
)
{
CodeGen
::
value2reg
(
Value
*
v
,
int
id
)
{
auto
reg_name
=
(
is_float
?
"$f"
:
"$a"
)
+
to_string
(
id
);
bool
is_float
=
v
->
get_type
()
->
is_float_type
();
auto
reg_name
=
(
is_float
?
"$fa"
:
"$a"
)
+
to_string
(
id
);
if
(
dynamic_cast
<
Constant
*>
(
v
))
{
if
(
dynamic_cast
<
Constant
*>
(
v
))
{
auto
constant
=
static_cast
<
Constant
*>
(
v
);
auto
constant
=
static_cast
<
Constant
*>
(
v
);
if
(
dynamic_cast
<
ConstantInt
*>
(
constant
))
{
if
(
dynamic_cast
<
ConstantInt
*>
(
constant
))
{
int
k
=
static_cast
<
ConstantInt
*>
(
constant
)
->
get_value
();
int
k
=
static_cast
<
ConstantInt
*>
(
constant
)
->
get_value
();
if
((
k
&
0xfff
)
!=
k
)
{
if
((
k
&
0xfff
)
!=
k
)
{
output
.
push_back
(
"lui.w "
+
reg_name
+
", "
+
output
.
push_back
(
"lu
12
i.w "
+
reg_name
+
", "
+
to_string
(
k
>>
12
));
to_string
(
k
>>
12
));
output
.
push_back
(
"ori "
+
reg_name
+
", "
+
reg_name
+
", "
+
output
.
push_back
(
"ori "
+
reg_name
+
", "
+
reg_name
+
", "
+
to_string
(
k
&
0xfff
));
to_string
(
k
&
0xfff
));
}
else
}
else
output
.
push_back
(
"ori "
+
reg_name
+
", $r0, "
+
to_string
(
k
));
output
.
push_back
(
"ori "
+
reg_name
+
", $r0, "
+
to_string
(
k
));
}
else
if
(
dynamic_cast
<
ConstantFP
*>
(
constant
))
{
// move the binary code to int-reg, then use movgr2fr to move the
// value to float-reg
string
tmp_ireg
=
"$t0"
;
float
k
=
static_cast
<
ConstantFP
*>
(
constant
)
->
get_value
();
int
hex_int
=
*
(
uint32_t
*
)
&
k
;
if
((
hex_int
&
0xfff
)
!=
hex_int
)
output
.
push_back
(
"lu12i.w "
+
tmp_ireg
+
", "
+
to_string
(
hex_int
>>
12
));
if
(
hex_int
&
0xfff
)
output
.
push_back
(
"ori "
+
tmp_ireg
+
", "
+
tmp_ireg
+
", "
+
to_string
(
hex_int
&
0xfff
));
output
.
push_back
(
"movgr2fr.w "
+
reg_name
+
", "
+
tmp_ireg
);
// output.push_back("ffint.s.w " + reg_name + ", " + reg_name);
}
else
}
else
assert
(
false
&&
"wait for completion"
);
assert
(
false
&&
"wait for completion"
);
}
else
if
(
dynamic_cast
<
GlobalVariable
*>
(
v
))
{
}
else
if
(
dynamic_cast
<
GlobalVariable
*>
(
v
))
{
output
.
push_back
(
"la.local "
+
reg_name
+
", "
+
v
->
get_name
());
output
.
push_back
(
"la.local "
+
reg_name
+
", "
+
v
->
get_name
());
}
else
if
(
dynamic_cast
<
AllocaInst
*>
(
v
))
{
}
else
if
(
dynamic_cast
<
AllocaInst
*>
(
v
))
{
// auto alloc_instr = dynamic_cast<AllocaInst *>(v);
// auto alloc_instr = dynamic_cast<AllocaInst *>(v);
// give the stack address
output
.
push_back
(
"addi.d "
+
reg_name
+
", $fp, -"
+
to_string
(
off
[
v
]));
output
.
push_back
(
"addi.d "
+
reg_name
+
", $fp, -"
+
to_string
(
off
[
v
]));
}
else
if
(
dynamic_cast
<
Argument
*>
(
v
))
{
}
else
if
(
dynamic_cast
<
Argument
*>
(
v
))
{
auto
args
=
cur_func
->
get_args
();
auto
args
=
cur_func
->
get_args
();
...
@@ -149,12 +168,13 @@ CodeGen::value2reg(Value *v, int id, bool is_float) {
...
@@ -149,12 +168,13 @@ CodeGen::value2reg(Value *v, int id, bool is_float) {
for
(
auto
iter
=
args
.
begin
();
id
<=
args
.
size
();
++
iter
,
++
id
)
for
(
auto
iter
=
args
.
begin
();
id
<=
args
.
size
();
++
iter
,
++
id
)
if
(
*
iter
==
v
)
if
(
*
iter
==
v
)
break
;
break
;
output
.
push_back
(
"ld"
+
suffix
(
typeLen
(
v
->
get_type
()))
+
" "
+
string
instr_ir
=
is_float
?
"fld"
:
"ld"
;
reg_name
+
", $fp, "
+
output
.
push_back
(
instr_ir
+
suffix
(
v
->
get_type
())
+
" "
+
reg_name
+
to_string
(
func_arg_off
[
cur_func
][
id
]));
", $fp, "
+
to_string
(
func_arg_off
[
cur_func
][
id
]));
}
else
{
}
else
{
output
.
push_back
(
"ld"
+
suffix
(
typeLen
(
v
->
get_type
()))
+
" "
+
string
instr_ir
=
is_float
?
"fld"
:
"ld"
;
reg_name
+
", $fp, -"
+
to_string
(
off
[
v
]));
output
.
push_back
(
instr_ir
+
suffix
(
v
->
get_type
())
+
" "
+
reg_name
+
", $fp, -"
+
to_string
(
off
[
v
]));
}
}
}
}
...
@@ -215,23 +235,41 @@ CodeGen::stackMemAlloc() {
...
@@ -215,23 +235,41 @@ CodeGen::stackMemAlloc() {
output
.
push_back
(
"addi.d $fp, $sp, "
+
to_string
(
stackN
));
output
.
push_back
(
"addi.d $fp, $sp, "
+
to_string
(
stackN
));
output
.
push_back
(
"st.d $ra, $fp, -8"
);
output
.
push_back
(
"st.d $ra, $fp, -8"
);
}
}
void
CodeGen
::
IR2assem
(
FpToSiInst
*
instr
)
{
assert
(
instr
->
get_operand
(
0
)
->
get_type
()
==
m
->
get_float_type
());
assert
(
instr
->
get_dest_type
()
==
m
->
get_int32_type
());
value2reg
(
instr
->
get_operand
(
0
));
output
.
push_back
(
"ftint.w.s $fa0, $fa0"
);
output
.
push_back
(
"movfr2gr.s $a0, $fa0"
);
}
void
CodeGen
::
IR2assem
(
SiToFpInst
*
instr
)
{
assert
(
instr
->
get_operand
(
0
)
->
get_type
()
==
m
->
get_int32_type
());
assert
(
instr
->
get_dest_type
()
==
m
->
get_float_type
());
output
.
push_back
(
"movgr2fr.w $fa0, $a0"
);
output
.
push_back
(
"ffint.s.w $fa0, $fa0"
);
}
string
string
CodeGen
::
bool2branch
(
Instruction
*
instr
)
{
CodeGen
::
bool2branch
(
Instruction
*
instr
)
{
assert
(
instr
->
get_type
()
==
instr
->
get_module
()
->
get_int1_type
());
assert
(
instr
->
get_type
()
==
m
->
get_int1_type
());
auto
cmp_instr
=
dynamic_cast
<
CmpInst
*>
(
instr
);
auto
icmp_instr
=
dynamic_cast
<
CmpInst
*>
(
instr
);
assert
(
cmp_instr
);
auto
fcmp_instr
=
dynamic_cast
<
FCmpInst
*>
(
instr
);
assert
(
icmp_instr
or
fcmp_instr
);
string
instr_ir
;
string
instr_ir
;
bool
reverse
=
false
;
bool
reverse
=
false
;
switch
(
cmp_instr
->
get_cmp_op
())
{
if
(
icmp_instr
)
{
switch
(
icmp_instr
->
get_cmp_op
())
{
case
CmpInst
::
EQ
:
case
CmpInst
::
EQ
:
instr_ir
=
"beq"
;
instr_ir
=
"beq"
;
break
;
break
;
case
CmpInst
::
NE
:
{
case
CmpInst
::
NE
:
{
instr_ir
=
"bne"
;
instr_ir
=
"bne"
;
if
(
instr
->
get_operand
(
1
)
==
if
(
instr
->
get_operand
(
1
)
==
ConstantInt
::
get
(
0
,
m
)
and
ConstantInt
::
get
(
0
,
instr
->
get_module
())
and
dynamic_cast
<
Instruction
*>
(
instr
->
get_operand
(
0
))
dynamic_cast
<
Instruction
*>
(
instr
->
get_operand
(
0
))
->
is_zext
())
{
->
is_zext
())
{
// something like:
// something like:
// %op0 = icmp slt i32 1, 2 # deepest
// %op0 = icmp slt i32 1, 2 # deepest
// %op1 = zext i1 %op0 to i32
// %op1 = zext i1 %op0 to i32
...
@@ -242,9 +280,7 @@ CodeGen::bool2branch(Instruction *instr) {
...
@@ -242,9 +280,7 @@ CodeGen::bool2branch(Instruction *instr) {
->
get_operand
(
0
));
->
get_operand
(
0
));
return
bool2branch
(
deepest
);
return
bool2branch
(
deepest
);
}
}
}
}
break
;
break
;
case
CmpInst
::
GT
:
case
CmpInst
::
GT
:
instr_ir
=
"blt"
;
instr_ir
=
"blt"
;
reverse
=
true
;
reverse
=
true
;
...
@@ -262,8 +298,35 @@ CodeGen::bool2branch(Instruction *instr) {
...
@@ -262,8 +298,35 @@ CodeGen::bool2branch(Instruction *instr) {
}
}
value2reg
(
instr
->
get_operand
(
0
),
0
);
value2reg
(
instr
->
get_operand
(
0
),
0
);
value2reg
(
instr
->
get_operand
(
1
),
1
);
value2reg
(
instr
->
get_operand
(
1
),
1
);
return
instr_ir
+
(
reverse
?
" $a1, $a0,"
:
" $a0, $a1,"
);
return
instr_ir
+
(
reverse
?
" $a1, $a0 "
:
" $a0, $a1 "
);
}
else
{
switch
(
fcmp_instr
->
get_cmp_op
())
{
case
FCmpInst
::
EQ
:
instr_ir
=
"fcmp.ceq.s $fcc0"
;
break
;
case
FCmpInst
::
NE
:
instr_ir
=
"fcmp.cun.s $fcc0"
;
break
;
case
FCmpInst
::
GT
:
instr_ir
=
"fcmp.cle.s $fcc0"
;
reverse
=
true
;
break
;
case
FCmpInst
::
GE
:
instr_ir
=
"fcmp.clt.s $fcc0"
;
reverse
=
true
;
break
;
case
FCmpInst
::
LT
:
instr_ir
=
"fcmp.clt.s $fcc0"
;
break
;
case
FCmpInst
::
LE
:
instr_ir
=
"fcmp.cle.s $fcc0"
;
break
;
}
value2reg
(
instr
->
get_operand
(
0
),
0
);
value2reg
(
instr
->
get_operand
(
1
),
1
);
output
.
push_back
(
instr_ir
+
", "
+
"$fa0, $fa1"
);
return
(
reverse
?
"bceqz $fcc0,"
:
"bcnez $fcc0,"
);
}
}
}
void
void
...
@@ -287,85 +350,33 @@ CodeGen::IR2assem(CallInst *instr) {
...
@@ -287,85 +350,33 @@ CodeGen::IR2assem(CallInst *instr) {
auto
func
=
static_cast
<
Function
*>
(
instr
->
get_operand
(
0
));
auto
func
=
static_cast
<
Function
*>
(
instr
->
get_operand
(
0
));
// stack space allocation
// stack space allocation
output
.
push_back
(
"addi.d $sp, $sp, -"
+
to_string
(
func_arg_N
[
func
]));
output
.
push_back
(
"addi.d $sp, $sp, -"
+
to_string
(
func_arg_N
[
func
]));
string
instr_ir
,
suff
,
reg
;
// place the arguments
// place the arguments
for
(
int
i
=
1
;
i
<
instr
->
get_num_operand
();
i
++
)
{
for
(
int
i
=
1
;
i
<
instr
->
get_num_operand
();
i
++
)
{
auto
arg
=
instr
->
get_operand
(
i
);
auto
arg
=
instr
->
get_operand
(
i
);
auto
tplen
=
typeLen
(
arg
->
get_type
());
// auto tplen = typeLen(arg->get_type());
string
suff
=
suffix
(
tplen
);
instr_ir
=
(
arg
->
get_type
()
->
is_float_type
()
?
"fst"
:
"st"
);
suff
=
suffix
(
arg
->
get_type
());
reg
=
(
arg
->
get_type
()
->
is_float_type
()
?
"$fa0"
:
"$a0"
);
value2reg
(
arg
);
value2reg
(
arg
);
output
.
push_back
(
"st"
+
suff
+
" $a0
, $sp, "
+
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg
+
"
, $sp, "
+
to_string
(
func_arg_off
[
func
][
i
]));
to_string
(
func_arg_off
[
func
][
i
]));
}
}
output
.
push_back
(
"bl "
+
func
->
get_name
());
output
.
push_back
(
"bl "
+
func
->
get_name
());
output
.
push_back
(
"addi.d $sp, $sp, "
+
to_string
(
func_arg_N
[
func
]));
output
.
push_back
(
"addi.d $sp, $sp, "
+
to_string
(
func_arg_N
[
func
]));
output
.
push_back
(
"addi.d $fp, $sp, "
+
to_string
(
stackN
));
output
.
push_back
(
"addi.d $fp, $sp, "
+
to_string
(
stackN
));
if
(
not
instr
->
is_void
())
back2stack
(
instr
);
}
}
/* void
* CodeGen::IR2assem(CmpInst *instr) {
* value2reg(instr->get_operand(0), 0);
* value2reg(instr->get_operand(1), 1);
* string instr_ir;
* switch (instr->get_cmp_op()) {
* case CmpInst::EQ:
* break;
* case CmpInst::NE:
* // output.push_back("xor $a0, $a0, $a1");
* break;
* case CmpInst::GT:
* output.push_back("slt $a0, $a1, $a0");
* break;
* case CmpInst::GE:
* break;
* case CmpInst::LT:
* output.push_back("slt $a0, $a0, $a1");
* break;
* case CmpInst::LE:
* break;
* }
* output.push_back(instr_ir + " $a0, $a0, $a1");
* back2stack(instr);
* } */
void
void
CodeGen
::
IR2assem
(
BinaryInst
*
instr
)
{
CodeGen
::
IR2assem
(
BinaryInst
*
instr
)
{
auto
is_float
=
instr
->
get_type
()
->
is_float_type
();
value2reg
(
instr
->
get_operand
(
0
),
0
);
value2reg
(
instr
->
get_operand
(
0
),
0
);
value2reg
(
instr
->
get_operand
(
1
),
1
);
value2reg
(
instr
->
get_operand
(
1
),
1
);
string
suff
=
suffix
(
typeLen
(
instr
->
get_type
()));
string
instr_ir
=
instr
->
get_instr_op_name
();
string
instr_ir
;
string
suff
=
suffix
(
instr
->
get_type
());
switch
(
instr
->
get_instr_type
())
{
output
.
push_back
(
instr_ir
+
suff
+
case
Instruction
::
add
:
(
is_float
?
" $fa0, $fa0, $fa1"
:
" $a0, $a0, $a1"
));
instr_ir
=
"add"
;
break
;
case
Instruction
::
sub
:
instr_ir
=
"sub"
;
break
;
case
Instruction
::
mul
:
instr_ir
=
"mulw.d.w"
;
suff
=
""
;
break
;
case
Instruction
::
sdiv
:
instr_ir
=
"div"
;
break
;
/* case Instruction::fadd:
* instr_ir = "fadd";
* break;
* case Instruction::fsub:
* instr_ir = "fsub";
* break;
* case Instruction::fmul:
* instr_ir = "fmul";
* break;
* case Instruction::fdiv:
* instr_ir = "fdiv";
* break; */
default:
assert
(
false
&&
"instruction type"
);
}
output
.
push_back
(
instr_ir
+
suff
+
" $a0, $a0, $a1"
);
back2stack
(
instr
);
}
}
void
void
...
@@ -383,10 +394,10 @@ CodeGen::IR2assem(GetElementPtrInst *instr) {
...
@@ -383,10 +394,10 @@ CodeGen::IR2assem(GetElementPtrInst *instr) {
}
else
}
else
assert
(
false
&&
"GEP translation error"
);
assert
(
false
&&
"GEP translation error"
);
value2reg
(
instr
->
get_operand
(
i
),
1
);
value2reg
(
instr
->
get_operand
(
i
),
1
);
output
.
push_back
(
"mul.w $a1, $a1, "
+
to_string
(
size
));
value2reg
(
ConstantInt
::
get
(
size
,
m
),
2
);
output
.
push_back
(
"mul.w $a1, $a1, $a2"
);
output
.
push_back
(
"add.d $a0, $a0, $a1"
);
output
.
push_back
(
"add.d $a0, $a0, $a1"
);
}
}
back2stack
(
instr
);
}
}
void
void
...
@@ -395,18 +406,17 @@ CodeGen::IR2assem(LoadInst *instr) {
...
@@ -395,18 +406,17 @@ CodeGen::IR2assem(LoadInst *instr) {
ptrContent2reg
(
instr
->
get_lval
());
ptrContent2reg
(
instr
->
get_lval
());
assert
(
instr
->
get_type
()
==
instr
->
get_load_type
());
assert
(
instr
->
get_type
()
==
instr
->
get_load_type
());
back2stack
(
instr
);
/* string suff = suffix(typeLen(instr->get_load_type()));
* string addr = "$fp, -" + to_string(off[instr]);
* output.push_back("st" + suff + " $a0, " + addr); */
}
}
void
void
CodeGen
::
IR2assem
(
StoreInst
*
instr
)
{
CodeGen
::
IR2assem
(
StoreInst
*
instr
)
{
value2reg
(
instr
->
get_rval
());
value2reg
(
instr
->
get_rval
()
,
0
);
value2reg
(
instr
->
get_lval
(),
1
);
value2reg
(
instr
->
get_lval
(),
1
);
string
suff
=
suffix
(
typeLen
(
instr
->
get_rval
()
->
get_type
()));
bool
is_float
=
instr
->
get_rval
()
->
get_type
()
->
is_float_type
();
output
.
push_back
(
"st"
+
suff
+
" $a0, $a1, 0"
);
string
instr_ir
=
(
is_float
?
"fst"
:
"st"
);
string
suff
=
suffix
(
instr
->
get_rval
()
->
get_type
());
string
reg
=
(
is_float
?
"$fa0"
:
"$a0"
);
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg
+
", $a1, 0"
);
}
}
void
void
...
@@ -424,59 +434,60 @@ CodeGen::IR2assem(Instruction &instr) {
...
@@ -424,59 +434,60 @@ CodeGen::IR2assem(Instruction &instr) {
switch
(
instr
.
get_instr_type
())
{
switch
(
instr
.
get_instr_type
())
{
case
Instruction
::
ret
:
case
Instruction
::
ret
:
IR2assem
(
static_cast
<
ReturnInst
*>
(
&
instr
));
IR2assem
(
static_cast
<
ReturnInst
*>
(
&
instr
));
return
;
break
;
case
Instruction
::
br
:
case
Instruction
::
br
:
IR2assem
(
static_cast
<
BranchInst
*>
(
&
instr
));
IR2assem
(
static_cast
<
BranchInst
*>
(
&
instr
));
return
;
break
;
// Standard binary operators
// Standard binary operators
case
Instruction
::
add
:
case
Instruction
::
add
:
case
Instruction
::
sub
:
case
Instruction
::
sub
:
case
Instruction
::
mul
:
case
Instruction
::
mul
:
case
Instruction
::
sdiv
:
case
Instruction
::
sdiv
:
IR2assem
(
static_cast
<
BinaryInst
*>
(
&
instr
));
return
;
// float binary operators
// float binary operators
case
Instruction
::
fadd
:
case
Instruction
::
fadd
:
break
;
case
Instruction
::
fsub
:
case
Instruction
::
fsub
:
break
;
case
Instruction
::
fmul
:
case
Instruction
::
fmul
:
break
;
case
Instruction
::
fdiv
:
case
Instruction
::
fdiv
:
IR2assem
(
static_cast
<
BinaryInst
*>
(
&
instr
));
break
;
break
;
// Memory operators
// Memory operators
case
Instruction
::
alloca
:
case
Instruction
::
alloca
:
IR2assem
(
static_cast
<
AllocaInst
*>
(
&
instr
));
IR2assem
(
static_cast
<
AllocaInst
*>
(
&
instr
));
return
;
break
;
case
Instruction
::
load
:
case
Instruction
::
load
:
IR2assem
(
static_cast
<
LoadInst
*>
(
&
instr
));
IR2assem
(
static_cast
<
LoadInst
*>
(
&
instr
));
return
;
break
;
case
Instruction
::
store
:
case
Instruction
::
store
:
IR2assem
(
static_cast
<
StoreInst
*>
(
&
instr
));
IR2assem
(
static_cast
<
StoreInst
*>
(
&
instr
));
return
;
break
;
// Other operators
// Other operators
case
Instruction
::
cmp
:
case
Instruction
::
cmp
:
IR2assem
(
static_cast
<
CmpInst
*>
(
&
instr
));
break
;
break
;
case
Instruction
::
fcmp
:
case
Instruction
::
fcmp
:
IR2assem
(
static_cast
<
FCmpInst
*>
(
&
instr
));
break
;
break
;
case
Instruction
::
phi
:
case
Instruction
::
phi
:
IR2assem
(
static_cast
<
PhiInst
*>
(
&
instr
));
IR2assem
(
static_cast
<
PhiInst
*>
(
&
instr
));
return
;
break
;
case
Instruction
::
call
:
case
Instruction
::
call
:
IR2assem
(
static_cast
<
CallInst
*>
(
&
instr
));
IR2assem
(
static_cast
<
CallInst
*>
(
&
instr
));
return
;
break
;
case
Instruction
::
getelementptr
:
case
Instruction
::
getelementptr
:
IR2assem
(
static_cast
<
GetElementPtrInst
*>
(
&
instr
));
IR2assem
(
static_cast
<
GetElementPtrInst
*>
(
&
instr
));
return
;
break
;
case
Instruction
::
zext
:
case
Instruction
::
zext
:
IR2assem
(
static_cast
<
ZextInst
*>
(
&
instr
));
IR2assem
(
static_cast
<
ZextInst
*>
(
&
instr
));
return
;
break
;
case
Instruction
::
fptosi
:
case
Instruction
::
fptosi
:
IR2assem
(
static_cast
<
FpToSiInst
*>
(
&
instr
));
IR2assem
(
static_cast
<
FpToSiInst
*>
(
&
instr
));
return
;
break
;
case
Instruction
::
sitofp
:
case
Instruction
::
sitofp
:
IR2assem
(
static_cast
<
SiToFpInst
*>
(
&
instr
));
IR2assem
(
static_cast
<
SiToFpInst
*>
(
&
instr
));
return
;
break
;
}
}
// assert(false && "This ")
// assert(false && "This ")
if
(
not
instr
.
is_void
()
and
not
no_stack_alloca
(
&
instr
)
and
not
instr
.
is_alloca
())
back2stack
(
&
instr
);
}
}
tests/5-bonus/test_time.py
View file @
83f09476
...
@@ -6,7 +6,7 @@ import argparse
...
@@ -6,7 +6,7 @@ import argparse
import
subprocess
import
subprocess
test_dir
=
os
.
path
.
dirname
(
os
.
path
.
abspath
(
__file__
))
# 当前文件夹路径 tests/5-bonus
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'
)
testfile_dir
=
os
.
path
.
join
(
test_dir
,
'./testcases'
)
output_file_name
=
os
.
path
.
join
(
test_dir
,
'./test_result'
)
output_file_name
=
os
.
path
.
join
(
test_dir
,
'./test_result'
)
io
=
os
.
path
.
join
(
test_dir
,
'../../src/io/io.c'
)
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):
...
@@ -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
:
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
continue
# 未超时
# 未超时
output_file
.
write
(
f"[
{
count
+
1
}
/
{
test_count
}
] "
+
file_name
+
': '
)
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):
...
@@ -75,8 +76,9 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
output_file
.
write
(
'compile-1 timeout
\n
'
)
output_file
.
write
(
'compile-1 timeout
\n
'
)
failed_count
+=
1
failed_count
+=
1
continue
continue
except
Exception
:
except
Exception
as
e
:
output_file
.
write
(
"compile-1 failed with an unexcept error
\n
"
)
output_file
.
write
(
"compile-1 failed with an unexcept error
\n
"
)
output_file
.
write
(
str
(
e
))
failed_count
+=
1
failed_count
+=
1
continue
continue
...
@@ -107,8 +109,9 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
...
@@ -107,8 +109,9 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
output_file
.
write
(
'compile timeout
\n
'
)
output_file
.
write
(
'compile timeout
\n
'
)
failed_count
+=
1
failed_count
+=
1
continue
continue
except
Exception
:
except
Exception
as
e
:
output_file
.
write
(
"compile failed with an unexcept error
\n
"
)
output_file
.
write
(
"compile failed with an unexcept error
\n
"
)
output_file
.
write
(
e
)
failed_count
+=
1
failed_count
+=
1
continue
continue
...
@@ -135,8 +138,9 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
...
@@ -135,8 +138,9 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
output_file
.
write
(
"executable time limit exceeded
\n
"
)
output_file
.
write
(
"executable time limit exceeded
\n
"
)
failed_count
+=
1
failed_count
+=
1
continue
continue
except
Exception
as
_
:
except
Exception
as
e
:
output_file
.
write
(
'executable runtime error
\n
'
)
output_file
.
write
(
'executable runtime error
\n
'
)
output_file
.
write
(
str
(
e
))
failed_count
+=
1
failed_count
+=
1
continue
continue
...
@@ -159,8 +163,11 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
...
@@ -159,8 +163,11 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
succ_count
+=
1
succ_count
+=
1
testtime
[
count
]
=
time
testtime
[
count
]
=
time
else
:
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
failed_count
+=
1
output_file
.
write
(
f"
{
failed_count
}
tests failed
\n
"
)
output_file
.
write
(
f"
{
failed_count
}
tests failed
\n
"
)
...
@@ -172,9 +179,11 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
...
@@ -172,9 +179,11 @@ def eval(console=False, test_dir=testfile_dir, use_clang=False):
output_file
.
write
(
'
\t\t\t
your_cminus'
)
output_file
.
write
(
'
\t\t\t
your_cminus'
)
for
count
,
file_name
in
enumerate
(
testfiles
):
for
count
,
file_name
in
enumerate
(
testfiles
):
output_file
.
write
(
'{:<20}'
.
format
(
file_name
))
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__"
:
if
__name__
==
"__main__"
:
...
@@ -182,8 +191,10 @@ if __name__ == "__main__":
...
@@ -182,8 +191,10 @@ if __name__ == "__main__":
parser
=
argparse
.
ArgumentParser
(
description
=
"functional test"
)
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
(
"--console"
,
action
=
"store_true"
,
parser
.
add_argument
(
"--clang"
,
action
=
"store_true"
,
help
=
"estimate runtime when compile with clang"
)
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
()
args
=
parser
.
parse_args
()
eval
(
args
.
console
,
testfile_dir
,
use_clang
=
args
.
clang
)
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