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
b90933be
Commit
b90933be
authored
Feb 04, 2023
by
lxq
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
live variable analysis with copy-stmt
parent
4a232c57
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
260 additions
and
2 deletions
+260
-2
src/codegen/codegen.cpp
src/codegen/codegen.cpp
+42
-2
src/codegen/liverange.cpp
src/codegen/liverange.cpp
+218
-0
No files found.
src/codegen/codegen.cpp
View file @
b90933be
...
...
@@ -13,11 +13,16 @@
#include "Instruction.h"
#include "Type.h"
#include "Value.h"
#include "ast.hpp"
#include <algorithm>
#include <cstdint>
#include <cstring>
#include <sstream>
#include <string>
#include <sys/types.h>
#include <utility>
#include <vector>
// $r0 $zero constant 0
// $r1 $ra return address
...
...
@@ -95,6 +100,7 @@ CodeGen::run() {
// funtions
for
(
auto
&
func
:
m
->
get_functions
())
{
if
(
not
func
.
is_declaration
())
{
LRA
.
run
(
&
func
);
cur_func
=
&
func
;
output
.
push_back
(
""
);
output
.
push_back
(
".globl "
+
func
.
get_name
());
...
...
@@ -113,6 +119,24 @@ CodeGen::run() {
stackMemDealloc
();
}
}
// read only data
output
.
push_back
(
".section .rodata"
);
for
(
auto
[
constant
,
name
]
:
ROdata
)
{
auto
int_
=
dynamic_cast
<
ConstantInt
*>
(
constant
);
auto
float_
=
dynamic_cast
<
ConstantFP
*>
(
constant
);
string
value
;
assert
((
int_
||
float_
)
&&
"wrong type"
);
if
(
int_
)
{
value
=
to_string
(
int_
->
get_value
());
}
else
{
std
::
stringstream
ss
;
float
v
=
(
float_
->
get_value
());
ss
<<
std
::
hex
<<
*
(
uint32_t
*
)
&
v
;
value
=
"0x"
+
ss
.
str
();
}
output
.
push_back
(
name
+
": "
);
output
.
push_back
(
".word "
+
value
);
}
}
void
...
...
@@ -145,8 +169,23 @@ void
CodeGen
::
value2reg
(
Value
*
v
,
int
id
)
{
bool
is_float
=
v
->
get_type
()
->
is_float_type
();
auto
reg_name
=
(
is_float
?
"$fa"
:
"$a"
)
+
to_string
(
id
);
string
tmp_ireg
=
"$t0"
;
if
(
dynamic_cast
<
Constant
*>
(
v
))
{
auto
constant
=
static_cast
<
Constant
*>
(
v
);
#ifdef __RO_PART__
if
(
ROdata
.
find
(
constant
)
==
ROdata
.
end
())
ROdata
[
constant
]
=
".LC"
+
to_string
(
ROdata
.
size
());
string
instr_ir
,
addr
=
ROdata
[
constant
];
if
(
dynamic_cast
<
ConstantInt
*>
(
constant
))
instr_ir
=
"ld.w"
;
else
if
(
dynamic_cast
<
ConstantFP
*>
(
constant
))
instr_ir
=
"fld.s"
;
else
assert
(
false
&&
"wait for completion"
);
output
.
push_back
(
"la.local "
+
tmp_ireg
+
", "
+
addr
);
output
.
push_back
(
instr_ir
+
" "
+
reg_name
+
", "
+
tmp_ireg
+
", 0"
);
#else
if
(
dynamic_cast
<
ConstantInt
*>
(
constant
))
{
int
k
=
static_cast
<
ConstantInt
*>
(
constant
)
->
get_value
();
if
((
k
&
0xfff
)
!=
k
)
{
...
...
@@ -159,7 +198,6 @@ CodeGen::value2reg(Value *v, int id) {
}
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
)
...
...
@@ -173,6 +211,7 @@ CodeGen::value2reg(Value *v, int id) {
}
else
assert
(
false
&&
"wait for completion"
);
#endif
}
else
if
(
dynamic_cast
<
GlobalVariable
*>
(
v
))
{
output
.
push_back
(
"la.local "
+
reg_name
+
", "
+
v
->
get_name
());
}
else
if
(
dynamic_cast
<
AllocaInst
*>
(
v
))
{
...
...
@@ -218,7 +257,6 @@ void
CodeGen
::
stackMemDealloc
()
{
output
.
push_back
(
"# epilog"
);
// 7: return value should be determined already!
// output.push_back("addi.w $a0, $zero, 0");
output
.
push_back
(
cur_func
->
get_name
()
+
"_end:"
);
output
.
push_back
(
"ld.d $ra, $fp, -8"
);
output
.
push_back
(
"addi.d $sp, $sp, "
+
to_string
(
stackN
));
...
...
@@ -391,6 +429,8 @@ CodeGen::IR2assem(BinaryInst *instr) {
value2reg
(
instr
->
get_operand
(
1
),
1
);
string
instr_ir
=
instr
->
get_instr_op_name
();
if
(
instr_ir
==
"sdiv"
)
instr_ir
=
"div"
;
string
suff
=
suffix
(
instr
->
get_type
());
output
.
push_back
(
instr_ir
+
suff
+
(
is_float
?
" $fa0, $fa0, $fa1"
:
" $a0, $a0, $a1"
));
...
...
src/codegen/liverange.cpp
0 → 100644
View file @
b90933be
#include "liverange.hpp"
#include "Function.h"
#include "Instruction.h"
#include <algorithm>
#include <iterator>
void
LiveRangeAnalyzer
::
clear
()
{
IN
.
clear
();
OUT
.
clear
();
liverange
.
clear
();
instr_id
.
clear
();
}
LiveRangeAnalyzer
::
LiveSet
LiveRangeAnalyzer
::
joinFor
(
BasicBlock
*
bb
)
{
LiveSet
out
;
for
(
auto
succ
:
bb
->
get_succ_basic_blocks
())
{
auto
&
irs
=
succ
->
get_instructions
();
auto
it
=
irs
.
begin
();
while
(
it
!=
irs
.
end
()
and
it
->
is_phi
())
++
it
;
assert
(
it
!=
irs
.
end
()
&&
"need to find first_ir from copy-stmt"
);
union_ip
(
out
,
IN
[
instr_id
.
at
(
&
(
*
it
))]);
// std::cout << "# " + it->print() << std::endl;
}
// std::cout << "\tget out: " << print_liveSet(out) << std::endl;
return
out
;
}
void
LiveRangeAnalyzer
::
make_id
(
Function
*
func
)
{
// instruction numbering
// this is also the structure of the IR logically:
// ignore phi, add copy-statement
int
ir_cnt
=
0
;
for
(
auto
&
bb
:
func
->
get_basic_blocks
())
{
for
(
auto
&
instr
:
bb
.
get_instructions
())
{
if
(
instr
.
is_phi
())
continue
;
if
(
instr
.
is_br
()
or
instr
.
is_ret
())
{
// insert copy-stmt in front of the jump ir
auto
it
=
phi_map
.
find
(
&
bb
);
if
(
it
!=
phi_map
.
end
())
{
for
(
auto
pr
:
it
->
second
)
{
cpstmt_id
[
pr
]
=
++
ir_cnt
;
}
}
}
instr_id
[
&
instr
]
=
++
ir_cnt
;
}
}
}
void
LiveRangeAnalyzer
::
run
(
Function
*
func
)
{
clear
();
make_id
(
func
);
#ifdef __LRA_PRINT__
print
(
func
,
false
);
#endif
bool
cont
=
true
;
while
(
cont
)
{
cont
=
false
;
// reverse traverse BasicBlocks
for
(
auto
rit_bb
=
func
->
get_basic_blocks
().
rbegin
();
rit_bb
!=
func
->
get_basic_blocks
().
rend
();
++
rit_bb
)
{
auto
bb
=
&
(
*
rit_bb
);
LiveSet
bef_in
,
out
;
bool
last_ir
=
true
;
// reverse traverse instructions
for
(
auto
rit_ir
=
rit_bb
->
get_instructions
().
rbegin
();
rit_ir
!=
rit_bb
->
get_instructions
().
rend
();
++
rit_ir
)
{
auto
instr
=
&
(
*
rit_ir
);
if
(
instr
->
is_phi
())
{
assert
(
not
last_ir
&&
"If phi is the last ir, then data "
"flow fails due to ignorance of phi"
);
continue
;
}
//
// get out-set for this instruction
if
(
last_ir
)
{
last_ir
=
false
;
out
=
joinFor
(
bb
);
}
else
{
out
=
bef_in
;
}
OUT
[
instr_id
.
at
(
instr
)]
=
out
;
//
// get in-set
bef_in
=
transferFunction
(
instr
);
cont
|=
bef_in
!=
IN
[
instr_id
.
at
(
instr
)];
IN
[
instr_id
.
at
(
instr
)]
=
bef_in
;
if
(
instr
->
is_ret
()
or
instr
->
is_br
())
{
// deal with copy-stmt
auto
it
=
phi_map
.
find
(
bb
);
if
(
it
!=
phi_map
.
end
())
{
for
(
auto
rit
=
it
->
second
.
rbegin
();
rit
!=
it
->
second
.
rend
();
++
rit
)
{
auto
[
lv
,
rv
]
=
*
rit
;
if
(
last_ir
)
{
last_ir
=
false
;
out
=
joinFor
(
bb
);
}
else
out
=
bef_in
;
OUT
[
cpstmt_id
.
at
(
*
rit
)]
=
out
;
// transfer manually
out
.
erase
(
lv
);
if
(
dynamic_cast
<
Instruction
*>
(
rv
))
out
.
insert
(
rv
);
cont
|=
out
!=
IN
[
cpstmt_id
.
at
(
*
rit
)];
bef_in
=
IN
[
cpstmt_id
.
at
(
*
rit
)]
=
out
;
}
}
}
}
}
}
#ifdef __LRA_PRINT__
print
(
func
);
#endif
}
LiveRangeAnalyzer
::
LiveSet
LiveRangeAnalyzer
::
transferFunction
(
Instruction
*
instr
)
{
LiveSet
in
,
out
=
OUT
[
instr_id
.
at
(
instr
)];
LiveSet
use
;
// calculate use for this instruction
for
(
auto
op
:
instr
->
get_operands
())
{
// op type:
// - global
// - function
// - Constant
// - instruction
// - argument
// - BasicBlock
auto
ins
=
dynamic_cast
<
Instruction
*>
(
op
);
if
(
ins
)
{
assert
(
not
ins
->
is_void
()
&&
"instr as op should not be void"
);
use
.
insert
(
op
);
}
}
// in = use + (out - def)
auto
iter
=
out
.
find
(
instr
);
if
(
iter
!=
out
.
end
())
out
.
erase
(
iter
);
std
::
set_union
(
out
.
begin
(),
out
.
end
(),
use
.
begin
(),
use
.
end
(),
std
::
inserter
(
in
,
in
.
begin
()));
return
in
;
}
void
LiveRangeAnalyzer
::
print
(
Function
*
func
,
bool
printSet
)
{
// for debug
for
(
auto
&
bb
:
func
->
get_basic_blocks
())
{
for
(
auto
&
instr
:
bb
.
get_instructions
())
{
if
(
instr
.
is_phi
())
// ignore phi
continue
;
// insert copy-stmt
if
((
instr
.
is_br
()
or
instr
.
is_ret
())
and
phi_map
.
find
(
&
bb
)
!=
phi_map
.
end
())
{
for
(
auto
pr
:
phi_map
.
find
(
&
bb
)
->
second
)
{
auto
[
lv
,
rv
]
=
pr
;
auto
idx
=
cpstmt_id
.
at
(
pr
);
std
::
cout
<<
cpstmt_id
[
pr
]
<<
". "
<<
lv
->
get_name
()
<<
" = "
<<
(
rv
->
get_name
()
==
""
?
rv
->
print
()
:
rv
->
get_name
())
<<
std
::
endl
;
if
(
not
printSet
)
continue
;
auto
&
in
=
IN
.
at
(
idx
);
auto
&
out
=
OUT
.
at
(
idx
);
std
::
cout
<<
"
\t
in-set: "
+
print_liveSet
(
in
)
<<
"
\n
"
;
std
::
cout
<<
"
\t
out-set: "
+
print_liveSet
(
out
)
<<
"
\n
"
;
}
}
// normal ir
std
::
cout
<<
instr_id
[
&
instr
]
<<
". "
<<
instr
.
print
()
<<
" # "
<<
&
instr
<<
std
::
endl
;
if
(
not
printSet
)
continue
;
auto
idx
=
instr_id
.
at
(
&
instr
);
auto
&
in
=
IN
.
at
(
idx
);
auto
&
out
=
OUT
.
at
(
idx
);
std
::
cout
<<
"
\t
in-set: "
+
print_liveSet
(
in
)
<<
"
\n
"
;
std
::
cout
<<
"
\t
out-set: "
+
print_liveSet
(
out
)
<<
"
\n
"
;
}
/* if (phi_map.find(&bb) != phi_map.end()) {
* for (auto pr : phi_map.find(&bb)->second) {
* auto [lv, rv] = pr;
* auto idx = cpstmt_id.at(pr);
* std::cout << cpstmt_id[pr] << ". " << lv->get_name() << " = "
* << (rv->get_name() == "" ? rv->print()
* : rv->get_name())
* << std::endl;
* if (not printSet)
* continue;
* auto &in = IN.at(idx);
* auto &out = OUT.at(idx);
* std::cout << "\tin-set: " + print_liveSet(in) << "\n";
* std::cout << "\tout-set: " + print_liveSet(out) << "\n";
* }
* } */
}
}
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