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
e23c2e2e
Commit
e23c2e2e
authored
Feb 07, 2023
by
lxq
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
finish argument pass, need to do float part
parent
b4870a73
Changes
7
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
386 additions
and
76 deletions
+386
-76
Reports/5-bonus/report.md
Reports/5-bonus/report.md
+2
-0
include/codegen/codegen.hpp
include/codegen/codegen.hpp
+63
-7
include/codegen/liverange.hpp
include/codegen/liverange.hpp
+1
-1
src/cminusfc/cminusfc.cpp
src/cminusfc/cminusfc.cpp
+4
-3
src/codegen/codegen.cpp
src/codegen/codegen.cpp
+285
-57
src/codegen/liverange.cpp
src/codegen/liverange.cpp
+7
-4
src/codegen/regalloc.cpp
src/codegen/regalloc.cpp
+24
-4
No files found.
Reports/5-bonus/report.md
View file @
e23c2e2e
...
@@ -132,6 +132,8 @@ op6: <8, 8>
...
@@ -132,6 +132,8 @@ op6: <8, 8>
这实际是指令选择部分的内容:
这实际是指令选择部分的内容:
因为在cminus中并没有bool变量,这些IR指令用到的i1类型都是临时的:只为分支指令服务,所以直接将这些指令集成到分支跳转的判断中。
因为在cminus中并没有bool变量,这些IR指令用到的i1类型都是临时的:只为分支指令服务,所以直接将这些指令集成到分支跳转的判断中。
一个例外是隐式的类型转化,将比较的结果
`i1`
隐式转换为
`i32`
,此时是
`zext`
指令与
`cmp`
捆绑,特殊为
`zext`
指令分配寄存器。
-
`call`
指令:使用栈传参,caller保存自己用到的寄存器,被保存的寄存器的活跃区间覆盖
`call`
指令的程序点。
-
`call`
指令:使用栈传参,caller保存自己用到的寄存器,被保存的寄存器的活跃区间覆盖
`call`
指令的程序点。
...
...
include/codegen/codegen.hpp
View file @
e23c2e2e
...
@@ -11,10 +11,12 @@
...
@@ -11,10 +11,12 @@
#include "liverange.hpp"
#include "liverange.hpp"
#include "regalloc.hpp"
#include "regalloc.hpp"
#include <functional>
#include <string>
#include <string>
#define __PRINT_ORI__
#define __PRINT_ORI__
#define __RO_PART__
#define __RO_PART__
#define __PRINT_COMMENT__
// #a = 8, #t = 9, reserve $t0, $t1 for temporary
// #a = 8, #t = 9, reserve $t0, $t1 for temporary
#define R_USABLE 17 - 2
#define R_USABLE 17 - 2
#define ARG_R 8
#define ARG_R 8
...
@@ -27,6 +29,11 @@
...
@@ -27,6 +29,11 @@
// #define STACK_ALIGN(x) (((x / 16) + (x % 16 ? 1 : 0)) * 16)
// #define STACK_ALIGN(x) (((x / 16) + (x % 16 ? 1 : 0)) * 16)
#define STACK_ALIGN(x) ALIGN(x, 16)
#define STACK_ALIGN(x) ALIGN(x, 16)
#define CONST_0 ConstantInt::get(0, m)
#define FP "$fp"
#define SP "$sp"
#define RA_reg "$ra"
using
std
::
map
;
using
std
::
map
;
using
std
::
string
;
using
std
::
string
;
using
std
::
vector
;
using
std
::
vector
;
...
@@ -38,6 +45,10 @@ class CodeGen {
...
@@ -38,6 +45,10 @@ class CodeGen {
string
print
()
{
string
print
()
{
string
result
;
string
result
;
for
(
auto
line
:
output
)
{
for
(
auto
line
:
output
)
{
#ifndef __PRINT_COMMENT__
if
(
line
.
find
(
"#"
)
!=
string
::
npos
)
continue
;
#endif
if
(
line
.
find
(
":"
)
==
string
::
npos
and
line
!=
""
)
if
(
line
.
find
(
":"
)
==
string
::
npos
and
line
!=
""
)
result
+=
"
\t
"
;
// 添加缩进
result
+=
"
\t
"
;
// 添加缩进
result
+=
line
+
"
\n
"
;
result
+=
line
+
"
\n
"
;
...
@@ -58,6 +69,7 @@ class CodeGen {
...
@@ -58,6 +69,7 @@ class CodeGen {
std
::
map
<
BasicBlock
*
,
std
::
vector
<
std
::
pair
<
Value
*
,
Value
*>>>
phi_map
;
std
::
map
<
BasicBlock
*
,
std
::
vector
<
std
::
pair
<
Value
*
,
Value
*>>>
phi_map
;
std
::
map
<
Constant
*
,
std
::
string
>
ROdata
;
std
::
map
<
Constant
*
,
std
::
string
>
ROdata
;
unsigned
int
stackN
;
// function local vars and so on
unsigned
int
stackN
;
// function local vars and so on
uint
cmp_zext_cnt
;
Function
*
cur_func
;
Function
*
cur_func
;
...
@@ -79,11 +91,16 @@ class CodeGen {
...
@@ -79,11 +91,16 @@ class CodeGen {
// In the case of register allocation, this function will return the
// In the case of register allocation, this function will return the
// allocated register for that value, if the value possesses no register,
// allocated register for that value, if the value possesses no register,
// choose from from $t0 or $t1 based on id, or the input string(not "")
// choose from from $t0 or $t1 based on id, or the input string(not "")
__attribute__
((
warn_unused_result
))
string
value2reg
(
Value
*
,
int
i
=
0
,
string
=
""
);
__attribute__
((
warn_unused_result
))
string
value2reg
(
Value
*
,
int
i
=
0
,
string
=
""
);
// load the content in ptr to specified register.
// load the content in ptr to specified register.
void
ptrContent2reg
(
Value
*
,
string
);
void
ptrContent2reg
(
Value
*
,
string
);
void
pass_arguments
(
CallInst
*
);
void
compute_arg_info
(
Function
*
);
void
compute_arg_info
(
Function
*
);
string
bool2branch
(
Instruction
*
);
string
bool2branch
(
Instruction
*
);
void
getPhiMap
();
void
getPhiMap
();
void
copystmt
(
BasicBlock
*
bb
)
{
void
copystmt
(
BasicBlock
*
bb
)
{
// all the phi instruction is transformed to copy-stmt
// all the phi instruction is transformed to copy-stmt
...
@@ -97,6 +114,26 @@ class CodeGen {
...
@@ -97,6 +114,26 @@ class CodeGen {
}
}
}
}
// this is a decorated version of push_back, it checks intermediat number in
// the instruction, make sure imm will not overflow
void
makeSureInRange
(
string
instr_ir
,
string
reg1
,
string
reg2
,
int
imm
,
string
tinstr
,
int
bits
=
12
,
string
treg
=
"$t0"
,
bool
u
=
false
)
{
auto
[
l
,
h
]
=
immRange
(
bits
,
u
);
if
(
l
<=
imm
and
imm
<=
h
)
output
.
push_back
(
instr_ir
+
" "
+
reg1
+
", "
+
reg2
+
", "
+
to_string
(
imm
));
else
{
assert
(
value2reg
(
ConstantInt
::
get
(
imm
,
m
),
0
,
treg
)
==
treg
);
output
.
push_back
(
tinstr
+
" "
+
reg1
+
", "
+
reg2
+
", "
+
treg
);
}
}
// if reg-allocation, store to the specific register
// if reg-allocation, store to the specific register
// or is stack-allocation, set last_reg for back2stack()
// or is stack-allocation, set last_reg for back2stack()
bool
gencopy
(
Value
*
lhs
,
string
rhs_reg
)
{
bool
gencopy
(
Value
*
lhs
,
string
rhs_reg
)
{
...
@@ -122,7 +159,7 @@ class CodeGen {
...
@@ -122,7 +159,7 @@ class CodeGen {
string
label_in_assem
(
BasicBlock
*
bb
)
const
{
string
label_in_assem
(
BasicBlock
*
bb
)
const
{
return
cur_func
->
get_name
()
+
bb
->
get_name
().
substr
(
5
);
return
cur_func
->
get_name
()
+
bb
->
get_name
().
substr
(
5
);
}
}
int
typeLen
(
Type
*
type
)
const
{
static
int
typeLen
(
Type
*
type
)
{
if
(
type
->
is_float_type
())
if
(
type
->
is_float_type
())
return
4
;
return
4
;
else
if
(
type
->
is_integer_type
())
{
else
if
(
type
->
is_integer_type
())
{
...
@@ -149,11 +186,16 @@ class CodeGen {
...
@@ -149,11 +186,16 @@ class CodeGen {
string
instr_ir
=
type
->
is_float_type
()
?
"fst"
:
"st"
;
string
instr_ir
=
type
->
is_float_type
()
?
"fst"
:
"st"
;
string
suff
=
suffix
(
type
);
string
suff
=
suffix
(
type
);
// string reg = type->is_float_type() ? "$fa0" : "$a0";
// string reg = type->is_float_type() ? "$fa0" : "$a0";
string
addr
=
"$fp, -"
+
std
::
to_string
(
off
.
at
(
instr
));
makeSureInRange
(
instr_ir
+
suff
,
output
.
push_back
(
instr_ir
+
suff
+
" "
+
last_reg
+
", "
+
addr
);
last_reg
,
FP
,
-
off
.
at
(
instr
),
instr_ir
+
"x"
+
suff
);
// string addr = "$fp, -" + std::to_string(off.at(instr));
// output.push_back(instr_ir + suff + " " + last_reg + ", " + addr);
}
}
st
ring
suffix
(
Type
*
type
)
const
{
st
atic
string
suffix
(
Type
*
type
)
{
int
len
=
typeLen
(
type
);
int
len
=
typeLen
(
type
);
switch
(
len
)
{
switch
(
len
)
{
case
1
:
case
1
:
...
@@ -198,6 +240,20 @@ class CodeGen {
...
@@ -198,6 +240,20 @@ class CodeGen {
return
name
;
return
name
;
}
}
static
pair
<
int
,
int
>
immRange
(
int
bit
,
bool
u
)
{
pair
<
int
,
int
>
res
;
if
(
u
)
{
res
.
first
=
0
;
res
.
second
=
(
1
<<
bit
)
-
1
;
}
else
{
bit
--
;
res
.
first
=
-
(
1
<<
bit
);
res
.
second
=
(
1
<<
bit
)
-
1
;
}
return
res
;
};
pair
<
string
,
bool
>
getRegName
(
Value
*
,
int
=
0
)
const
;
pair
<
string
,
bool
>
getRegName
(
Value
*
,
int
=
0
)
const
;
void
IR2assem
(
Instruction
&
,
BasicBlock
&
);
void
IR2assem
(
Instruction
&
,
BasicBlock
&
);
...
@@ -211,12 +267,12 @@ class CodeGen {
...
@@ -211,12 +267,12 @@ class CodeGen {
void
IR2assem
(
FpToSiInst
*
);
void
IR2assem
(
FpToSiInst
*
);
void
IR2assem
(
SiToFpInst
*
);
void
IR2assem
(
SiToFpInst
*
);
void
IR2assem
(
PhiInst
*
)
{}
void
IR2assem
(
PhiInst
*
)
{}
void
IR2assem
(
ZextInst
*
);
// The Instructions below will do nothing
// The Instructions below will do nothing
void
IR2assem
(
AllocaInst
*
)
{}
void
IR2assem
(
AllocaInst
*
)
{}
// integration with BranchInst
// integration with BranchInst
and ZextInst
void
IR2assem
(
CmpInst
*
)
{}
void
IR2assem
(
CmpInst
*
)
{}
void
IR2assem
(
FCmpInst
*
)
{}
void
IR2assem
(
FCmpInst
*
)
{}
void
IR2assem
(
ZextInst
*
)
{}
};
};
#endif
#endif
include/codegen/liverange.hpp
View file @
e23c2e2e
...
@@ -20,7 +20,7 @@ using std::vector;
...
@@ -20,7 +20,7 @@ using std::vector;
namespace
LRA
{
namespace
LRA
{
struct
Interval
{
struct
Interval
{
Interval
(
int
a
=
0
,
int
b
=
0
)
:
i
(
a
),
j
(
b
)
{}
Interval
(
int
a
=
-
1
,
int
b
=
-
1
)
:
i
(
a
),
j
(
b
)
{}
int
i
;
// 0 means uninitialized
int
i
;
// 0 means uninitialized
int
j
;
int
j
;
};
};
...
...
src/cminusfc/cminusfc.cpp
View file @
e23c2e2e
...
@@ -34,13 +34,15 @@ main(int argc, char **argv) {
...
@@ -34,13 +34,15 @@ main(int argc, char **argv) {
bool
gvn
=
false
;
bool
gvn
=
false
;
bool
dump_json
=
false
;
bool
dump_json
=
false
;
bool
emit
=
false
;
bool
emit
=
false
;
bool
assembly
=
tru
e
;
bool
assembly
=
fals
e
;
for
(
int
i
=
1
;
i
<
argc
;
++
i
)
{
for
(
int
i
=
1
;
i
<
argc
;
++
i
)
{
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
||
argv
[
i
]
==
"-S"
s
)
{
}
else
if
(
argv
[
i
]
==
"-o"
s
||
argv
[
i
]
==
"-S"
s
)
{
if
(
argv
[
i
]
==
"-S"
s
)
assembly
=
true
;
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
)
if
(
target_path
.
rfind
(
"."
)
!=
std
::
string
::
npos
)
...
@@ -54,8 +56,6 @@ main(int argc, char **argv) {
...
@@ -54,8 +56,6 @@ main(int argc, char **argv) {
emit
=
true
;
emit
=
true
;
}
else
if
(
argv
[
i
]
==
"-mem2reg"
s
)
{
}
else
if
(
argv
[
i
]
==
"-mem2reg"
s
)
{
mem2reg
=
true
;
mem2reg
=
true
;
}
else
if
(
argv
[
i
]
==
"-S"
s
)
{
assembly
=
true
;
}
else
if
(
argv
[
i
]
==
"-gvn"
s
)
{
}
else
if
(
argv
[
i
]
==
"-gvn"
s
)
{
gvn
=
true
;
gvn
=
true
;
}
else
if
(
argv
[
i
]
==
"-dump-json"
s
)
{
}
else
if
(
argv
[
i
]
==
"-dump-json"
s
)
{
...
@@ -123,6 +123,7 @@ main(int argc, char **argv) {
...
@@ -123,6 +123,7 @@ main(int argc, char **argv) {
auto
IR
=
m
->
print
();
auto
IR
=
m
->
print
();
if
(
assembly
)
{
if
(
assembly
)
{
CodeGen
codegen
(
m
.
get
());
CodeGen
codegen
(
m
.
get
());
codegen
.
run
();
codegen
.
run
();
std
::
ofstream
target_file
(
target_path
+
".s"
);
std
::
ofstream
target_file
(
target_path
+
".s"
);
...
...
src/codegen/codegen.cpp
View file @
e23c2e2e
This diff is collapsed.
Click to expand it.
src/codegen/liverange.cpp
View file @
e23c2e2e
...
@@ -124,10 +124,13 @@ LiveRangeAnalyzer::run(Function *func) {
...
@@ -124,10 +124,13 @@ LiveRangeAnalyzer::run(Function *func) {
}
}
}
}
}
}
// argument should be in the IN-set of Entry
for
(
auto
arg
:
func
->
get_args
())
IN
[
1
].
insert
(
arg
);
make_interval
(
func
);
make_interval
(
func
);
#ifdef __LRA_PRINT__
#ifdef __LRA_PRINT__
print
(
func
,
fals
e
,
true
);
print
(
func
,
tru
e
,
true
);
#endif
#endif
}
}
...
@@ -136,20 +139,20 @@ LiveRangeAnalyzer::make_interval(Function *) {
...
@@ -136,20 +139,20 @@ LiveRangeAnalyzer::make_interval(Function *) {
for
(
int
time
=
1
;
time
<=
ir_cnt
;
++
time
)
{
for
(
int
time
=
1
;
time
<=
ir_cnt
;
++
time
)
{
for
(
auto
op
:
IN
.
at
(
time
))
{
for
(
auto
op
:
IN
.
at
(
time
))
{
auto
&
interval
=
intervalmap
[
op
];
auto
&
interval
=
intervalmap
[
op
];
if
(
interval
.
i
==
0
)
// uninitialized
if
(
interval
.
i
==
-
1
)
// uninitialized
interval
.
i
=
time
-
1
;
interval
.
i
=
time
-
1
;
else
else
interval
.
j
=
time
-
1
;
interval
.
j
=
time
-
1
;
}
}
for
(
auto
op
:
OUT
.
at
(
time
))
{
for
(
auto
op
:
OUT
.
at
(
time
))
{
auto
&
interval
=
intervalmap
[
op
];
auto
&
interval
=
intervalmap
[
op
];
if
(
interval
.
i
==
0
)
// uninitialized
if
(
interval
.
i
==
-
1
)
// uninitialized
interval
.
i
=
time
;
interval
.
i
=
time
;
else
else
interval
.
j
=
time
;
interval
.
j
=
time
;
}
}
}
}
for
(
auto
[
op
,
interval
]
:
intervalmap
)
for
(
auto
&
[
op
,
interval
]
:
intervalmap
)
liveIntervals
.
insert
({
interval
,
op
});
liveIntervals
.
insert
({
interval
,
op
});
}
}
...
...
src/codegen/regalloc.cpp
View file @
e23c2e2e
...
@@ -26,10 +26,30 @@ bool
...
@@ -26,10 +26,30 @@ bool
RegAllocator
::
no_reg_alloca
(
Value
*
v
)
const
{
RegAllocator
::
no_reg_alloca
(
Value
*
v
)
const
{
auto
instr
=
dynamic_cast
<
Instruction
*>
(
v
);
auto
instr
=
dynamic_cast
<
Instruction
*>
(
v
);
auto
arg
=
dynamic_cast
<
Argument
*>
(
v
);
auto
arg
=
dynamic_cast
<
Argument
*>
(
v
);
if
(
instr
)
if
(
instr
)
{
return
instr
->
is_alloca
()
or
instr
->
is_cmp
()
or
instr
->
is_fcmp
()
or
// never allocate register
instr
->
is_zext
();
if
(
instr
->
is_alloca
()
or
instr
->
is_cmp
()
or
instr
->
is_fcmp
())
if
(
arg
)
{
return
true
;
else
if
(
instr
->
is_zext
())
{
// only alloca for true use
for
(
auto
use
:
instr
->
get_use_list
())
if
(
not
dynamic_cast
<
Instruction
*>
(
use
.
val_
)
->
is_br
())
{
auto
instr
=
static_cast
<
Instruction
*>
(
use
.
val_
);
if
(
instr
->
is_cmp
())
{
// special case for cmp again
auto
cmp
=
static_cast
<
CmpInst
*>
(
instr
);
assert
(
cmp
->
get_cmp_op
()
==
CmpInst
::
NE
);
auto
uses
=
instr
->
get_use_list
();
assert
(
uses
.
size
()
==
1
and
dynamic_cast
<
Instruction
*>
(
uses
.
begin
()
->
val_
)
->
is_br
());
}
else
return
false
;
}
return
true
;
}
else
// then always allocate
return
false
;
}
if
(
arg
)
{
// only allocate for the first 8 args
return
get_arg_id
(
arg
)
>
ARG_MAX_R
;
return
get_arg_id
(
arg
)
>
ARG_MAX_R
;
}
else
}
else
assert
(
false
&&
"only instruction and argument's LiveInterval exits"
);
assert
(
false
&&
"only instruction and argument's LiveInterval exits"
);
...
...
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