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
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>
这实际是指令选择部分的内容:
因为在cminus中并没有bool变量,这些IR指令用到的i1类型都是临时的:只为分支指令服务,所以直接将这些指令集成到分支跳转的判断中。
一个例外是隐式的类型转化,将比较的结果
`i1`
隐式转换为
`i32`
,此时是
`zext`
指令与
`cmp`
捆绑,特殊为
`zext`
指令分配寄存器。
-
`call`
指令:使用栈传参,caller保存自己用到的寄存器,被保存的寄存器的活跃区间覆盖
`call`
指令的程序点。
...
...
include/codegen/codegen.hpp
View file @
e23c2e2e
...
...
@@ -11,10 +11,12 @@
#include "liverange.hpp"
#include "regalloc.hpp"
#include <functional>
#include <string>
#define __PRINT_ORI__
#define __RO_PART__
#define __PRINT_COMMENT__
// #a = 8, #t = 9, reserve $t0, $t1 for temporary
#define R_USABLE 17 - 2
#define ARG_R 8
...
...
@@ -27,6 +29,11 @@
// #define STACK_ALIGN(x) (((x / 16) + (x % 16 ? 1 : 0)) * 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
::
string
;
using
std
::
vector
;
...
...
@@ -38,6 +45,10 @@ class CodeGen {
string
print
()
{
string
result
;
for
(
auto
line
:
output
)
{
#ifndef __PRINT_COMMENT__
if
(
line
.
find
(
"#"
)
!=
string
::
npos
)
continue
;
#endif
if
(
line
.
find
(
":"
)
==
string
::
npos
and
line
!=
""
)
result
+=
"
\t
"
;
// 添加缩进
result
+=
line
+
"
\n
"
;
...
...
@@ -58,6 +69,7 @@ class CodeGen {
std
::
map
<
BasicBlock
*
,
std
::
vector
<
std
::
pair
<
Value
*
,
Value
*>>>
phi_map
;
std
::
map
<
Constant
*
,
std
::
string
>
ROdata
;
unsigned
int
stackN
;
// function local vars and so on
uint
cmp_zext_cnt
;
Function
*
cur_func
;
...
...
@@ -79,11 +91,16 @@ class CodeGen {
// In the case of register allocation, this function will return the
// 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 "")
__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.
void
ptrContent2reg
(
Value
*
,
string
);
void
pass_arguments
(
CallInst
*
);
void
compute_arg_info
(
Function
*
);
string
bool2branch
(
Instruction
*
);
void
getPhiMap
();
void
copystmt
(
BasicBlock
*
bb
)
{
// all the phi instruction is transformed to copy-stmt
...
...
@@ -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
// or is stack-allocation, set last_reg for back2stack()
bool
gencopy
(
Value
*
lhs
,
string
rhs_reg
)
{
...
...
@@ -122,7 +159,7 @@ class CodeGen {
string
label_in_assem
(
BasicBlock
*
bb
)
const
{
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
())
return
4
;
else
if
(
type
->
is_integer_type
())
{
...
...
@@ -149,11 +186,16 @@ class CodeGen {
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
.
at
(
instr
));
output
.
push_back
(
instr_ir
+
suff
+
" "
+
last_reg
+
", "
+
addr
);
makeSureInRange
(
instr_ir
+
suff
,
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
);
switch
(
len
)
{
case
1
:
...
...
@@ -198,6 +240,20 @@ class CodeGen {
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
;
void
IR2assem
(
Instruction
&
,
BasicBlock
&
);
...
...
@@ -211,12 +267,12 @@ class CodeGen {
void
IR2assem
(
FpToSiInst
*
);
void
IR2assem
(
SiToFpInst
*
);
void
IR2assem
(
PhiInst
*
)
{}
void
IR2assem
(
ZextInst
*
);
// The Instructions below will do nothing
void
IR2assem
(
AllocaInst
*
)
{}
// integration with BranchInst
// integration with BranchInst
and ZextInst
void
IR2assem
(
CmpInst
*
)
{}
void
IR2assem
(
FCmpInst
*
)
{}
void
IR2assem
(
ZextInst
*
)
{}
};
#endif
include/codegen/liverange.hpp
View file @
e23c2e2e
...
...
@@ -20,7 +20,7 @@ using std::vector;
namespace
LRA
{
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
j
;
};
...
...
src/cminusfc/cminusfc.cpp
View file @
e23c2e2e
...
...
@@ -34,13 +34,15 @@ main(int argc, char **argv) {
bool
gvn
=
false
;
bool
dump_json
=
false
;
bool
emit
=
false
;
bool
assembly
=
tru
e
;
bool
assembly
=
fals
e
;
for
(
int
i
=
1
;
i
<
argc
;
++
i
)
{
if
(
argv
[
i
]
==
"-h"
s
||
argv
[
i
]
==
"--help"
s
)
{
print_help
(
argv
[
0
]);
return
0
;
}
else
if
(
argv
[
i
]
==
"-o"
s
||
argv
[
i
]
==
"-S"
s
)
{
if
(
argv
[
i
]
==
"-S"
s
)
assembly
=
true
;
if
(
target_path
.
empty
()
&&
i
+
1
<
argc
)
{
target_path
=
argv
[
i
+
1
];
if
(
target_path
.
rfind
(
"."
)
!=
std
::
string
::
npos
)
...
...
@@ -54,8 +56,6 @@ main(int argc, char **argv) {
emit
=
true
;
}
else
if
(
argv
[
i
]
==
"-mem2reg"
s
)
{
mem2reg
=
true
;
}
else
if
(
argv
[
i
]
==
"-S"
s
)
{
assembly
=
true
;
}
else
if
(
argv
[
i
]
==
"-gvn"
s
)
{
gvn
=
true
;
}
else
if
(
argv
[
i
]
==
"-dump-json"
s
)
{
...
...
@@ -123,6 +123,7 @@ main(int argc, char **argv) {
auto
IR
=
m
->
print
();
if
(
assembly
)
{
CodeGen
codegen
(
m
.
get
());
codegen
.
run
();
std
::
ofstream
target_file
(
target_path
+
".s"
);
...
...
src/codegen/codegen.cpp
View file @
e23c2e2e
...
...
@@ -12,16 +12,16 @@
#include <algorithm>
#include <cstdint>
#include <cstring>
#include <deque>
#include <ostream>
#include <sstream>
#include <string>
#include <sys/types.h>
#include <tuple>
#include <type_traits>
#include <utility>
#include <vector>
#define CONST_0 ConstantInt::get(0, m)
// $r0 $zero constant 0
// $r1 $ra return address
// $r2 $tp thread pointer
...
...
@@ -33,6 +33,7 @@
// $r22 $fp frame pointer
// $r23 - $r31 $s0 - $s8 static
using
std
::
deque
;
using
std
::
to_string
;
using
std
::
operator
""
s
;
...
...
@@ -145,38 +146,39 @@ CodeGen::run() {
}
void
CodeGen
::
ptrContent2reg
(
Value
*
ptr
,
string
reg_name
)
{
CodeGen
::
ptrContent2reg
(
Value
*
ptr
,
string
dest_reg
)
{
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
suff
=
suffix
(
ele_tp
);
auto
[
addr_reg
,
find
]
=
getRegName
(
ptr
,
1
);
/* if (not find)
* addr_reg = "$t1"; */
auto
[
addr_reg
,
find
]
=
getRegName
(
ptr
,
0
);
if
(
dynamic_cast
<
GlobalVariable
*>
(
ptr
))
{
output
.
push_back
(
"la.local "
+
addr_reg
+
", "
+
ptr
->
get_name
());
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg_name
+
", "
+
addr_reg
+
output
.
push_back
(
instr_ir
+
suff
+
" "
+
dest_reg
+
", "
+
addr_reg
+
", 0"
);
}
else
if
(
dynamic_cast
<
AllocaInst
*>
(
ptr
))
{
/* auto alloc_instr = static_cast<AllocaInst *>(ptr);
* string suff = suffix(alloc_instr->get_alloca_type()); */
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg_name
+
", $fp, -"
+
to_string
(
off
.
at
(
ptr
)));
makeSureInRange
(
instr_ir
+
suff
,
dest_reg
,
FP
,
-
off
.
at
(
ptr
),
instr_ir
+
"x"
+
suff
);
/*
output.push_back(instr_ir + suff + " " + reg_name + ", $fp, -" +
* to_string(off.at(ptr))); */
}
else
if
(
dynamic_cast
<
GetElementPtrInst
*>
(
ptr
))
{
// auto GEP_instr = static_cast<GetElementPtrInst *>(ptr);
if
(
not
find
)
{
output
.
push_back
(
"ld.d "
+
addr_reg
+
", $fp, -"
+
to_string
(
off
.
at
(
ptr
)));
makeSureInRange
(
"ld.d"
,
addr_reg
,
FP
,
-
off
.
at
(
ptr
),
"ldx.d"
);
/* output.push_back("ld.d " + addr_reg + ", $fp, -" +
* to_string(off.at(ptr))); */
}
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg_name
+
", "
+
addr_reg
+
output
.
push_back
(
instr_ir
+
suff
+
" "
+
dest_reg
+
", "
+
addr_reg
+
", 0"
);
}
else
assert
(
false
&&
"unknown type"
);
}
void
IR2assem
(
ZextInst
*
);
string
CodeGen
::
value2reg
(
Value
*
v
,
int
i
,
string
recommend
)
{
bool
is_float
=
v
->
get_type
()
->
is_float_type
();
...
...
@@ -237,8 +239,10 @@ CodeGen::value2reg(Value *v, int i, string recommend) {
}
else
if
(
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
.
at
(
v
)));
makeSureInRange
(
"addi.d"
,
reg_name
,
FP
,
-
off
.
at
(
v
),
"add.d"
,
12
,
reg_name
);
/* output.push_back("addi.d " + reg_name + ", $fp, -" +
* to_string(off.at(v))); */
}
else
if
(
dynamic_cast
<
Argument
*>
(
v
))
{
auto
args
=
cur_func
->
get_args
();
int
id
=
1
;
...
...
@@ -249,14 +253,29 @@ CodeGen::value2reg(Value *v, int i, string recommend) {
return
regname
(
ARG_R
);
else
{
string
instr_ir
=
is_float
?
"fld"
:
"ld"
;
output
.
push_back
(
instr_ir
+
suffix
(
v
->
get_type
())
+
" "
+
reg_name
+
", $fp, "
+
to_string
(
func_arg_off
.
at
(
cur_func
).
at
(
id
)));
auto
suff
=
suffix
(
v
->
get_type
());
makeSureInRange
(
instr_ir
+
suff
,
reg_name
,
FP
,
func_arg_off
.
at
(
cur_func
).
at
(
id
),
instr_ir
+
"x"
+
suff
,
12
,
reg_name
);
/* output.push_back(instr_ir + suff + " " + reg_name + ", $fp, " +
* to_string(func_arg_off.at(cur_func).at(id))); */
}
}
else
{
string
instr_ir
=
is_float
?
"fld"
:
"ld"
;
output
.
push_back
(
instr_ir
+
suffix
(
v
->
get_type
())
+
" "
+
reg_name
+
", $fp, -"
+
to_string
(
off
.
at
(
v
)));
auto
suff
=
suffix
(
v
->
get_type
());
makeSureInRange
(
instr_ir
+
suff
,
reg_name
,
FP
,
off
.
at
(
v
),
instr_ir
+
"x"
+
suff
,
12
,
reg_name
);
/* output.push_back(instr_ir + suff + " " + reg_name +
* ", $fp, -" + to_string(off.at(v))); */
}
return
reg_name
;
}
...
...
@@ -307,10 +326,14 @@ CodeGen::stackMemAlloc() {
}
stackN
=
STACK_ALIGN
(
stackN
);
output
.
push_back
(
"# prolog"
);
output
.
push_back
(
"addi.d $sp, $sp, -"
+
to_string
(
stackN
));
output
.
push_back
(
"st.d $ra, $sp,"
+
to_string
(
stackN
-
8
));
output
.
push_back
(
"st.d $fp, $sp, "
+
to_string
(
stackN
-
16
));
output
.
push_back
(
"addi.d $fp, $sp, "
+
to_string
(
stackN
));
makeSureInRange
(
"addi.d"
,
SP
,
SP
,
-
stackN
,
"add.d"
);
makeSureInRange
(
"st.d"
,
RA_reg
,
SP
,
stackN
-
8
,
"stx.d"
);
makeSureInRange
(
"st.d"
,
FP
,
SP
,
stackN
-
16
,
"stx.d"
);
makeSureInRange
(
"addi.d"
,
FP
,
SP
,
stackN
,
"add.d"
);
/* output.push_back("addi.d $sp, $sp, -" + to_string(stackN));
* output.push_back("st.d $ra, $sp," + to_string(stackN - 8));
* output.push_back("st.d $fp, $sp, " + to_string(stackN - 16));
* output.push_back("addi.d $fp, $sp, " + to_string(stackN)); */
}
void
...
...
@@ -318,11 +341,13 @@ CodeGen::stackMemDealloc() {
// 7: return value should be determined already!
output
.
push_back
(
cur_func
->
get_name
()
+
"_end:"
);
output
.
push_back
(
"# epilog"
);
output
.
push_back
(
"ld.d $ra, $sp, "
+
to_string
(
stackN
-
8
));
output
.
push_back
(
"ld.d $fp, $sp, "
+
to_string
(
stackN
-
16
));
/* output.push_back("ld.d $ra, $fp, -8");
* output.push_back("ld.d $fp, $fp, -16"); */
output
.
push_back
(
"addi.d $sp, $sp, "
+
to_string
(
stackN
));
makeSureInRange
(
"ld.d"
,
RA_reg
,
SP
,
stackN
-
8
,
"ldx.d"
);
makeSureInRange
(
"ld.d"
,
FP
,
SP
,
stackN
-
16
,
"ldx.d"
);
makeSureInRange
(
"addi.d"
,
SP
,
SP
,
stackN
,
"add.d"
);
/* output.push_back("ld.d $ra, $sp, " + to_string(stackN - 8));
* output.push_back("ld.d $fp, $sp, " + to_string(stackN - 16));
* output.push_back("addi.d $sp, $sp, " + to_string(stackN)); */
output
.
push_back
(
"jr $ra"
);
}
...
...
@@ -364,6 +389,7 @@ CodeGen::bool2branch(Instruction *instr) {
case
CmpInst
::
NE
:
{
instr_ir
=
"bne"
;
if
(
instr
->
get_operand
(
1
)
==
CONST_0
and
dynamic_cast
<
Instruction
*>
(
instr
->
get_operand
(
0
))
and
dynamic_cast
<
Instruction
*>
(
instr
->
get_operand
(
0
))
->
is_zext
())
{
// something like:
...
...
@@ -397,7 +423,6 @@ CodeGen::bool2branch(Instruction *instr) {
return
instr_ir
+
" "
+
(
reverse
?
(
reg2
+
", "
+
reg1
)
:
(
reg1
+
", "
+
reg2
))
+
","
;
}
else
{
assert
(
false
&&
"not implemented"
);
switch
(
fcmp_instr
->
get_cmp_op
())
{
case
FCmpInst
::
EQ
:
instr_ir
=
"fcmp.ceq.s $fcc0"
;
...
...
@@ -443,6 +468,117 @@ CodeGen::IR2assem(BranchInst *instr) {
}
}
void
CodeGen
::
pass_arguments
(
CallInst
*
instr
)
{
/* cannot use the arg order simply, example leading to error:
* a0<-..., a1<-a0
* so we need an suitable order and use at most 1 tmp reg to pass arguments
*/
// ASSERT: use index start from 1
const
int
N
=
8
;
auto
func
=
static_cast
<
Function
*>
(
instr
->
get_operand
(
0
));
string
v_reg
,
instr_ir
,
suff
;
// 1. get rely graph for $a regs
// for example, $a1 is need by needby[1], which is a set
vector
<
int
>
needby
[
N
+
1
];
for
(
int
arg_id
=
1
;
arg_id
<
instr
->
get_num_operand
();
arg_id
++
)
{
auto
arg_value
=
instr
->
get_operand
(
arg_id
);
v_reg
=
getRegName
(
arg_value
).
first
;
if
(
v_reg
.
substr
(
0
,
2
)
!=
"$a"
)
continue
;
else
{
int
v_id
=
std
::
stoi
(
to_string
(
v_reg
[
2
]))
-
47
;
if
(
v_id
!=
arg_id
)
needby
[
v_id
].
push_back
(
arg_id
);
}
}
// 2. get traverse order: an enhanced topological order
// key: if there is a cycle, should give out an order rather than endless
// loop, and the order should statisfy:
vector
<
int
>
order
;
deque
<
int
>
queue
;
bool
vis
[
N
+
1
]{
false
};
map
<
int
,
bool
>
backup
;
for
(
int
arg_id
=
1
;
arg_id
<
instr
->
get_num_operand
();
arg_id
++
)
queue
.
push_back
(
arg_id
);
// initialize
while
(
not
queue
.
empty
())
{
int
i
=
queue
.
front
();
queue
.
pop_front
();
if
(
find
(
order
.
begin
(),
order
.
end
(),
i
)
!=
order
.
end
())
continue
;
// already has order
bool
assign
;
if
(
needby
[
i
].
size
()
==
0
)
{
// there is no argument relying on $a_i or is self rely
assign
=
true
;
}
else
if
(
vis
[
i
])
{
// cycle detected
backup
[
i
]
=
true
;
assign
=
true
;
}
else
assign
=
false
;
if
(
assign
)
{
order
.
push_back
(
i
);
for
(
int
j
=
1
;
j
<=
N
;
++
j
)
{
// remove $a_i 's rely
auto
&
need_vec
=
needby
[
j
];
auto
iter
=
find
(
need_vec
.
begin
(),
need_vec
.
end
(),
i
);
if
(
iter
!=
need_vec
.
end
())
{
// $a_i has at most one rely on $a_
need_vec
.
erase
(
iter
);
if
(
needby
[
j
].
size
()
==
0
)
{
queue
.
push_front
(
j
);
}
break
;
}
}
}
else
queue
.
push_back
(
i
);
vis
[
i
]
=
true
;
}
order
.
clear
();
for
(
int
arg_id
=
1
;
arg_id
<
instr
->
get_num_operand
();
arg_id
++
)
order
.
push_back
(
arg_id
);
// initialize
// 3. pass arguments' value
assert
(
order
.
size
()
==
func
->
get_num_of_args
());
map
<
string
,
bool
>
wroten
;
// bool assigned[8] = {false};
string
t0_contained
;
for
(
auto
arg_id
:
order
)
{
auto
arg_value
=
instr
->
get_operand
(
arg_id
);
auto
t_reg
=
arg_value
->
get_type
()
->
is_float_type
()
?
"$ft0"
:
"$t0"
;
v_reg
=
value2reg
(
arg_value
,
1
);
if
(
backup
[
arg_id
])
{
// still relied by some argument due to cycle
auto
a_id
=
regname
(
arg_id
);
assert
(
not
wroten
[
a_id
]);
gencopy
(
t_reg
,
a_id
);
t0_contained
=
a_id
;
}
// in case that the src register has been wroten
if
(
wroten
[
v_reg
])
{
assert
(
t0_contained
==
v_reg
);
v_reg
=
arg_value
->
get_type
()
->
is_float_type
()
?
"$ft0"
:
"$t0"
;
}
if
(
arg_id
<=
ARG_R
)
{
// pass by register
gencopy
(
regname
(
arg_id
),
v_reg
);
}
else
{
// pass by stack
instr_ir
=
(
arg_value
->
get_type
()
->
is_float_type
()
?
"fst"
:
"st"
);
suff
=
suffix
(
arg_value
->
get_type
());
makeSureInRange
(
instr_ir
+
suff
,
v_reg
,
SP
,
func_arg_off
.
at
(
func
).
at
(
arg_id
),
instr_ir
+
"x"
+
suff
);
/* output.push_back(instr_ir + suff + " " + v_reg + ",
* $sp, " + to_string(func_arg_off.at(func).at(arg_id)));
*/
}
wroten
[
regname
(
arg_id
)]
=
true
;
}
}
void
CodeGen
::
IR2assem
(
CallInst
*
instr
)
{
auto
func
=
static_cast
<
Function
*>
(
instr
->
get_operand
(
0
));
...
...
@@ -454,9 +590,16 @@ CodeGen::IR2assem(CallInst *instr) {
int
storeN
=
0
;
vector
<
std
::
tuple
<
Value
*
,
string
,
int
>>
store_record
;
for
(
auto
[
op
,
interval
]
:
LRA
.
get_interval_map
())
{
if
(
RA
.
no_reg_alloca
(
op
)
or
regmap
.
at
(
op
)
==
1
)
if
(
RA
.
no_reg_alloca
(
op
))
continue
;
if
(
not
instr
->
get_function_type
()
->
get_return_type
()
->
is_void_type
()
and
regmap
.
find
(
instr
)
!=
regmap
.
end
()
and
regmap
.
at
(
instr
)
==
1
)
continue
;
if
(
interval
.
i
<=
cur_i
and
cur_i
<=
interval
.
j
)
{
if
(
interval
.
i
<
cur_i
and
cur_i
<=
interval
.
j
)
{
cout
<<
"At point "
<<
cur_i
<<
", restore for "
<<
op
->
get_name
()
<<
", interval "
<<
LRA
.
print_interval
(
interval
)
<<
endl
;
int
tplen
=
typeLen
(
op
->
get_type
());
storeN
=
ALIGN
(
storeN
,
tplen
)
+
tplen
;
auto
name
=
regname
(
regmap
.
at
(
op
),
op
->
get_type
()
->
is_float_type
());
...
...
@@ -464,31 +607,23 @@ CodeGen::IR2assem(CallInst *instr) {
}
}
int
totalN
=
STACK_ALIGN
(
ALIGN
(
storeN
,
8
)
+
func_argN
);
// cout << "debug: " << STACK_ALIGN(12) << endl;
// stack space allocation
if
(
totalN
)
output
.
push_back
(
"addi.d $sp, $sp, -"
+
to_string
(
totalN
));
if
(
totalN
)
{
makeSureInRange
(
"addi.d"
,
SP
,
SP
,
-
totalN
,
"add.d"
);
// output.push_back("addi.d $sp, $sp, -" + to_string(totalN));
}
string
instr_ir
,
suff
,
v_reg
;
// place the reserved regs
for
(
auto
[
op
,
reg
,
off
]
:
store_record
)
{
instr_ir
=
(
op
->
get_type
()
->
is_float_type
()
?
"fst"
:
"st"
);
suff
=
suffix
(
op
->
get_type
());
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg
+
", $sp, "
+
to_string
(
totalN
-
off
));
makeSureInRange
(
instr_ir
+
suff
,
reg
,
SP
,
totalN
-
off
,
instr_ir
+
"x"
+
suff
);
/* output.push_back(instr_ir + suff + " " + reg + ", $sp, " +
* to_string(totalN - off)); */
}
// pass arguments
for
(
int
arg_i
=
1
;
arg_i
<
instr
->
get_num_operand
();
arg_i
++
)
{
auto
arg_value
=
instr
->
get_operand
(
arg_i
);
v_reg
=
value2reg
(
arg_value
);
if
(
arg_i
<=
ARG_R
)
{
// pass by register
gencopy
(
regname
(
arg_i
),
v_reg
);
}
else
{
// pass by stack
instr_ir
=
(
arg_value
->
get_type
()
->
is_float_type
()
?
"fst"
:
"st"
);
suff
=
suffix
(
arg_value
->
get_type
());
output
.
push_back
(
instr_ir
+
suff
+
" "
+
v_reg
+
", $sp, "
+
to_string
(
func_arg_off
.
at
(
func
).
at
(
arg_i
)));
}
}
pass_arguments
(
instr
);
output
.
push_back
(
"bl "
+
func
->
get_name
());
// bug here: maybe
gencopy
(
instr
,
instr
->
get_type
()
->
is_float_type
()
?
"$fa0"
:
"$a0"
);
...
...
@@ -496,11 +631,15 @@ CodeGen::IR2assem(CallInst *instr) {
for
(
auto
[
op
,
reg
,
off
]
:
store_record
)
{
instr_ir
=
(
op
->
get_type
()
->
is_float_type
()
?
"fld"
:
"ld"
);
suff
=
suffix
(
op
->
get_type
());
output
.
push_back
(
instr_ir
+
suff
+
" "
+
reg
+
", $sp, "
+
to_string
(
totalN
-
off
));
makeSureInRange
(
instr_ir
+
suff
,
reg
,
SP
,
totalN
-
off
,
instr_ir
+
"x"
+
suff
);
/* output.push_back(instr_ir + suff + " " + reg + ", $sp, " +
* to_string(totalN - off)); */
}
if
(
totalN
)
{
makeSureInRange
(
"addi.d"
,
SP
,
SP
,
totalN
,
"add.d"
);
// output.push_back("addi.d $sp, $sp, " + to_string(totalN));
}
if
(
totalN
)
output
.
push_back
(
"addi.d $sp, $sp, "
+
to_string
(
totalN
));
}
void
...
...
@@ -529,7 +668,8 @@ CodeGen::IR2assem(GetElementPtrInst *instr) {
return
;
}
if
(
instr
->
get_num_operand
()
==
3
)
{
// %op54 = getelementptr [66 x i32], [66 x i32]* @dp, i32 0, i32 %op41
// %op54 = getelementptr [66 x i32], [66 x i32]* @dp, i32 0, i32
// %op41
assert
(
instr
->
get_operand
(
1
)
==
CONST_0
);
}
else
{
// %op38 = getelementptr i32, i32* %arg1, i32 %op34
}
...
...
@@ -547,8 +687,7 @@ void
CodeGen
::
IR2assem
(
LoadInst
*
instr
)
{
auto
[
reg
,
find
]
=
getRegName
(
instr
);
ptrContent2reg
(
instr
->
get_lval
(),
reg
);
if
(
not
find
)
// this if is just for logically clear
last_reg
=
reg
;
gencopy
(
instr
,
reg
);
}
void
...
...
@@ -576,6 +715,95 @@ CodeGen::IR2assem(ReturnInst *instr) {
output
.
push_back
(
"b "
+
cur_func
->
get_name
()
+
"_end"
);
}
void
CodeGen
::
IR2assem
(
ZextInst
*
instr
)
{
if
(
RA
.
no_reg_alloca
(
instr
))
return
;
assert
(
instr
->
get_num_operand
()
==
1
);
auto
cmp_instr
=
instr
->
get_operand
(
0
);
auto
icmp_instr
=
dynamic_cast
<
CmpInst
*>
(
cmp_instr
);
auto
fcmp_instr
=
dynamic_cast
<
FCmpInst
*>
(
cmp_instr
);
assert
(
icmp_instr
or
fcmp_instr
);
auto
[
dest_reg
,
_
]
=
getRegName
(
instr
);
auto
reg1
=
value2reg
(
icmp_instr
->
get_operand
(
0
),
0
);
auto
reg2
=
value2reg
(
icmp_instr
->
get_operand
(
1
),
1
);
string
instr_ir
;
bool
reverse
=
false
,
flip
=
false
,
check
=
false
;
if
(
icmp_instr
)
{
switch
(
icmp_instr
->
get_cmp_op
())
{
case
CmpInst
::
EQ
:
instr_ir
=
"xor"
;
check
=
flip
=
true
;
break
;
case
CmpInst
::
NE
:
instr_ir
=
"xor"
;
check
=
true
;
break
;
case
CmpInst
::
GT
:
instr_ir
=
"slt"
;
reverse
=
true
;
break
;
case
CmpInst
::
GE
:
instr_ir
=
"slt"
;
flip
=
true
;
break
;
case
CmpInst
::
LT
:
instr_ir
=
"slt"
;
break
;
case
CmpInst
::
LE
:
instr_ir
=
"slt"
;
reverse
=
true
;
flip
=
true
;
break
;
}
output
.
push_back
(
instr_ir
+
" "
+
dest_reg
+
", "
+
(
reverse
?
(
reg2
+
", "
+
reg1
)
:
(
reg1
+
", "
+
reg2
)));
if
(
check
)
{
if
(
flip
)
output
.
push_back
(
"sltui "
+
dest_reg
+
", "
+
dest_reg
+
", 1"
);
else
output
.
push_back
(
"sltu "
+
dest_reg
+
", $zero, "
+
dest_reg
);
}
else
if
(
flip
)
// check && flip can be solved in a single
// instruction
output
.
push_back
(
"sltui "
+
dest_reg
+
", "
+
dest_reg
+
", 1"
);
}
else
{
switch
(
fcmp_instr
->
get_cmp_op
())
{
case
FCmpInst
::
EQ
:
instr_ir
=
"fcmp.ceq.s"
;
break
;
case
FCmpInst
::
NE
:
instr_ir
=
"fcmp.cun.s"
;
break
;
case
FCmpInst
::
GT
:
instr_ir
=
"fcmp.cle.s"
;
reverse
=
true
;
break
;
case
FCmpInst
::
GE
:
instr_ir
=
"fcmp.clt.s"
;
reverse
=
true
;
break
;
case
FCmpInst
::
LT
:
instr_ir
=
"fcmp.clt.s"
;
break
;
case
FCmpInst
::
LE
:
instr_ir
=
"fcmp.cle.s"
;
break
;
}
string
cmp_reg
=
"$fcc0"
;
auto
label
=
"cmp_zext_"
+
to_string
(
++
cmp_zext_cnt
)
+
":"
;
output
.
push_back
(
instr_ir
+
" "
+
cmp_reg
+
", "
+
reg1
+
", "
+
reg2
);
output
.
push_back
(
"or "
+
dest_reg
+
", $zero, $zero"
);
output
.
push_back
(
"bceqz "
+
cmp_reg
+
", "
+
label
);
output
.
push_back
(
"addi.w "
+
dest_reg
+
", $zero, 1"
);
output
.
push_back
(
label
+
":"
);
}
gencopy
(
instr
,
dest_reg
);
}
void
CodeGen
::
IR2assem
(
Instruction
&
instr
,
BasicBlock
&
bb
)
{
if
(
instr
.
is_br
()
or
instr
.
is_ret
())
...
...
src/codegen/liverange.cpp
View file @
e23c2e2e
...
...
@@ -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
);
#ifdef __LRA_PRINT__
print
(
func
,
fals
e
,
true
);
print
(
func
,
tru
e
,
true
);
#endif
}
...
...
@@ -136,20 +139,20 @@ LiveRangeAnalyzer::make_interval(Function *) {
for
(
int
time
=
1
;
time
<=
ir_cnt
;
++
time
)
{
for
(
auto
op
:
IN
.
at
(
time
))
{
auto
&
interval
=
intervalmap
[
op
];
if
(
interval
.
i
==
0
)
// uninitialized
if
(
interval
.
i
==
-
1
)
// uninitialized
interval
.
i
=
time
-
1
;
else
interval
.
j
=
time
-
1
;
}
for
(
auto
op
:
OUT
.
at
(
time
))
{
auto
&
interval
=
intervalmap
[
op
];
if
(
interval
.
i
==
0
)
// uninitialized
if
(
interval
.
i
==
-
1
)
// uninitialized
interval
.
i
=
time
;
else
interval
.
j
=
time
;
}
}
for
(
auto
[
op
,
interval
]
:
intervalmap
)
for
(
auto
&
[
op
,
interval
]
:
intervalmap
)
liveIntervals
.
insert
({
interval
,
op
});
}
...
...
src/codegen/regalloc.cpp
View file @
e23c2e2e
...
...
@@ -26,10 +26,30 @@ bool
RegAllocator
::
no_reg_alloca
(
Value
*
v
)
const
{
auto
instr
=
dynamic_cast
<
Instruction
*>
(
v
);
auto
arg
=
dynamic_cast
<
Argument
*>
(
v
);
if
(
instr
)
return
instr
->
is_alloca
()
or
instr
->
is_cmp
()
or
instr
->
is_fcmp
()
or
instr
->
is_zext
();
if
(
arg
)
{
if
(
instr
)
{
// never allocate register
if
(
instr
->
is_alloca
()
or
instr
->
is_cmp
()
or
instr
->
is_fcmp
())
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
;
}
else
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