Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
latte
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
zygzagZ
latte
Commits
ec3a8925
Commit
ec3a8925
authored
Jan 08, 2021
by
zygzagZ
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fixed quad BB generation, start implementation of optimal graph-coloring
register allocation
parent
bc58b2c2
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
243 additions
and
50 deletions
+243
-50
Makefile
Makefile
+3
-3
Compiler.cpp
src/Compiler.cpp
+18
-6
Compiler.h
src/Compiler.h
+1
-0
BasicBlock.cpp
src/codeGen/BasicBlock.cpp
+10
-9
Graph.h
src/codeGen/Graph.h
+152
-0
Quadruple.h
src/codeGen/Quadruple.h
+4
-9
QuadrupleGenerator.cpp
src/codeGen/QuadrupleGenerator.cpp
+19
-16
RegisterAllocator.cpp
src/codeGen/RegisterAllocator.cpp
+32
-5
RegisterAllocator.h
src/codeGen/RegisterAllocator.h
+4
-2
No files found.
Makefile
View file @
ec3a8925
...
...
@@ -30,7 +30,7 @@ Skeleton.o : src/Skeleton.cpp src/Skeleton.h src/Absyn.h
TypeCheck.o
:
src/TypeCheck.cpp src/TypeCheck.h src/Info.h src/InfoList.h src/Absyn.h src/ParseError.h
${
CC
}
${
CCFLAGS
}
-c
src/TypeCheck.cpp
Compiler.o
:
src/Compiler.cpp src/Compiler.h src/TypeCheck.h src/Info.h src/InfoList.h src/Absyn.h src/ParseError.h src/codeGen/Quadruple.h src/codeGen/Variable.h src/codeGen/QuadrupleGenerator.h
Compiler.o
:
src/Compiler.cpp src/Compiler.h src/TypeCheck.h src/Info.h src/InfoList.h src/Absyn.h src/ParseError.h src/codeGen/Quadruple.h src/codeGen/Variable.h src/codeGen/QuadrupleGenerator.h
src/codeGen/RegisterAllocator.h src/codeGen/Graph.h
${
CC
}
${
CCFLAGS
}
-c
src/Compiler.cpp
Info.o
:
src/Info.cpp src/Info.h src/InfoList.h src/Absyn.h
...
...
@@ -51,10 +51,10 @@ BasicBlock.o : src/codeGen/BasicBlock.cpp src/codeGen/Quadruple.h src/codeGen/Ba
QuadrupleGenerator.o
:
src/codeGen/QuadrupleGenerator.cpp src/codeGen/Quadruple.h src/codeGen/BasicBlock.h src/Info.h src/InfoList.h src/Absyn.h src/codeGen/Variable.h src/Compiler.h src/codeGen/QuadrupleGenerator.h
${
CC
}
${
CCFLAGS
}
-c
src/codeGen/QuadrupleGenerator.cpp
RegisterAllocator.o
:
src/codeGen/RegisterAllocator.cpp src/codeGen/Quadruple.h src/codeGen/BasicBlock.h src/Info.h src/InfoList.h src/Absyn.h src/codeGen/Variable.h src/codeGen/RegisterAllocator.h
RegisterAllocator.o
:
src/codeGen/RegisterAllocator.cpp src/codeGen/Quadruple.h src/codeGen/BasicBlock.h src/Info.h src/InfoList.h src/Absyn.h src/codeGen/Variable.h src/codeGen/RegisterAllocator.h
src/codeGen/Graph.h
${
CC
}
${
CCFLAGS
}
-c
src/codeGen/RegisterAllocator.cpp
Latte.o
:
src/Latte.cpp src/Parser.h src/Printer.h src/Absyn.h src/ParseError.h src/TypeCheck.h src/Compiler.h src/Info.h src/InfoList.h src/codeGen/QuadrupleGenerator.h
Latte.o
:
src/Latte.cpp src/Parser.h src/Printer.h src/Absyn.h src/ParseError.h src/TypeCheck.h src/Compiler.h src/Info.h src/InfoList.h src/codeGen/QuadrupleGenerator.h
src/codeGen/RegisterAllocator.h src/codeGen/Graph.h
${
CC
}
${
CCFLAGS
}
-c
src/Latte.cpp
lib/runtime.o
:
lib/runtime.c Makefile
...
...
src/Compiler.cpp
View file @
ec3a8925
...
...
@@ -54,16 +54,22 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) {
// c++ thiscall ecx, stack right-to-left (push c, push b, push a)
buf
<<
"
\"
"
<<
name
<<
"
\"
:
\n
"
;
QuadrupleGenerator
::
Result
quadEnv
=
quadGen
.
compileFunction
(
f
);
try
{
RegisterAllocator
regGen
((
quadEnv
));
regGen
.
allocate
();
}
catch
(
const
ParseError
&
e
)
{
printFunction
(
quadEnv
);
throw
ParseError
(
buf
.
str
()
+
e
.
what
());
}
auto
quadEnv
=
quadGen
.
compileFunction
(
f
);
RegisterAllocator
regGen
=
RegisterAllocator
(
quadEnv
);
regGen
.
allocate
();
printFunction
(
quadEnv
);
}
void
Compiler
::
printFunction
(
QuadrupleGenerator
::
Result
quadEnv
)
{
int
blkNo
=
0
;
for
(
const
auto
&
b
:
quadEnv
.
blocks
)
{
buf
<<
"------------------------------
\n
"
;
buf
<<
"------------------------------
----------------------------------------------
\n
"
;
buf
<<
"blok "
<<
blkNo
<<
" "
<<
b
->
getName
()
<<
endl
;
/*buf << "in: ";
for (auto in : b->in) {
...
...
@@ -91,6 +97,12 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) {
for
(
const
auto
&
q
:
b
->
quads
)
{
auto
ret
=
q
->
toString
();
if
(
!
ret
.
empty
())
{
auto
len
=
0
;
for
(
const
auto
&
c
:
ret
)
{
len
++
;
if
(
c
==
'\t'
)
len
+=
8
-
(
len
%
8
);
}
for
(;
len
<
70
;
len
++
)
ret
+=
' '
;
buf
<<
ret
<<
" alive: "
;
for
(
auto
var
:
q
->
aliveAfter
)
buf
<<
var
->
name
<<
" "
;
...
...
src/Compiler.h
View file @
ec3a8925
...
...
@@ -33,6 +33,7 @@ private:
QuadrupleGenerator
quadGen
;
void
compileFunction
(
const
FunctionInfoPtr
&
f
);
void
printFunction
(
QuadrupleGenerator
::
Result
quadEnv
);
static
std
::
string
mangleFunctionName
(
const
FunctionInfoPtr
&
f
)
{
if
(
auto
c
=
f
->
klass
.
lock
())
{
...
...
src/codeGen/BasicBlock.cpp
View file @
ec3a8925
...
...
@@ -2,18 +2,19 @@
#include "Quadruple.h"
void
BasicBlock
::
finishQuads
()
{
while
(
!
quads
.
empty
()
&&
quads
.
back
()
->
isFinal
())
{
auto
final
=
quads
.
back
();
quads
.
pop_back
();
afterInit
.
emplace_back
(
final
);
}
if
(
!
afterInit
.
empty
())
{
while
(
!
quads
.
empty
()
&&
quads
.
back
()
->
isFinal
())
{
auto
final
=
quads
.
back
();
quads
.
pop_back
();
afterInit
.
emplace_back
(
final
);
}
for
(
const
auto
&
q
:
afterInit
)
{
quads
.
push_back
(
q
);
for
(
const
auto
&
q
:
afterInit
)
{
quads
.
push_back
(
q
);
}
afterInit
.
clear
();
}
afterInit
.
clear
();
auto
self
=
this
->
shared_from_this
();
for
(
const
auto
&
q
:
quads
)
{
q
->
block
=
self
;
...
...
src/codeGen/Graph.h
0 → 100644
View file @
ec3a8925
#ifndef ZAD2_GRAPH_H
#define ZAD2_GRAPH_H
#include <unordered_set>
template
<
typename
T
>
class
Graph
{
public:
Graph
()
{
};
void
add
(
T
&
i
,
T
&
j
)
{
vertices
[
i
];
vertices
[
j
];
edgesSet
.
emplace
(
i
,
j
);
edgesSet
.
emplace
(
j
,
i
);
}
set
<
pair
<
T
,
T
>>
edgesSet
;
map
<
T
,
int
>
vertices
;
vector
<
T
>
reverseVertices
;
vector
<
unordered_set
<
int
>>
edges
;
vector
<
int
>
order
;
vector
<
int
>
color
;
bool
chordal
=
false
;
auto
getEdges
()
const
{
return
edgesSet
;
}
vector
<
T
>
getOrder
()
const
{
vector
<
T
>
ret
;
for
(
auto
i
:
order
)
ret
.
emplace_back
(
reverseVertices
[
i
]);
return
ret
;
}
void
buildGraph
()
{
int
n
=
0
;
reverseVertices
.
reserve
(
vertices
.
size
());
for
(
auto
&
i
:
vertices
)
{
i
.
second
=
n
++
;
reverseVertices
.
emplace_back
(
i
.
first
);
}
edges
.
resize
(
vertices
.
size
());
for
(
auto
e
:
edgesSet
)
{
auto
a
=
vertices
[
e
.
first
],
b
=
vertices
[
e
.
second
];
edges
[
a
].
emplace
(
b
);
}
}
void
initOrder
()
{
if
(
vertices
.
empty
())
return
;
vector
<
int
>
card
;
vector
<
unordered_set
<
int
>>
lambda
;
int
n
=
vertices
.
size
();
card
.
resize
(
n
);
lambda
.
resize
(
n
);
for
(
int
i
=
0
;
i
<
n
;
i
++
)
{
lambda
[
0
].
emplace
(
i
);
}
while
(
!
lambda
.
empty
())
{
if
(
lambda
.
back
().
empty
())
{
lambda
.
pop_back
();
continue
;
}
auto
v
=
*
lambda
.
back
().
begin
();
order
.
push_back
(
v
);
for
(
auto
x
:
edges
[
v
])
{
auto
&
c
=
card
[
x
];
if
(
c
>=
0
)
{
lambda
[
c
].
erase
(
x
);
c
++
;
if
(
lambda
.
size
()
<=
c
)
lambda
.
emplace_back
();
lambda
[
c
].
emplace
(
x
);
}
}
lambda
[
card
[
v
]].
erase
(
v
);
card
[
v
]
=
-
1
;
}
}
void
initChordal
()
{
unordered_set
<
int
>
visited
;
for
(
auto
i
:
order
)
{
unordered_set
<
int
>
neighbors
;
for
(
auto
x
:
edges
[
i
])
{
if
(
visited
.
count
(
x
))
{
neighbors
.
emplace
(
x
);
}
}
for
(
auto
x
:
neighbors
)
{
for
(
auto
y
:
neighbors
)
{
if
(
x
==
y
)
continue
;
if
(
!
edges
[
x
].
count
(
y
)
||
!
edges
[
y
].
count
(
x
))
{
chordal
=
false
;
return
;
}
}
}
visited
.
emplace
(
i
);
}
chordal
=
true
;
}
vector
<
int
>
spilledVertices
;
int
highestColor
;
map
<
int
,
int
>
colorUses
;
vector
<
int
>
colorCount
;
void
initColoring
(
int
maxC
)
{
highestColor
=
-
1
;
color
.
resize
(
vertices
.
size
());
for
(
auto
&
i
:
color
)
i
=
-
1
;
for
(
auto
c
:
order
)
{
bool
used
[
maxC
];
for
(
auto
x
:
edges
[
c
])
{
if
(
color
[
x
]
==
-
1
)
continue
;
used
[
color
[
x
]]
=
true
;
}
for
(
int
col
=
0
;
col
<
maxC
;
col
++
)
{
if
(
!
used
[
col
])
{
color
[
c
]
=
col
;
break
;
}
}
if
(
color
[
c
]
==
-
1
)
{
disconnectNode
(
c
);
spilledVertices
.
emplace_back
(
c
);
}
else
{
highestColor
=
max
(
highestColor
,
color
[
c
]);
}
}
chordal
=
true
;
}
void
disconnectNode
(
int
node
)
{
for
(
auto
x
:
edges
[
node
])
{
edges
[
x
].
erase
(
node
);
}
}
void
setup
()
{
if
(
vertices
.
empty
())
{
throw
std
::
runtime_error
(
"ayy lmao empty vertices"
);
}
buildGraph
();
initOrder
();
initChordal
();
}
};
#endif //ZAD2_GRAPH_H
src/codeGen/Quadruple.h
View file @
ec3a8925
...
...
@@ -5,6 +5,7 @@
#include "../Info.h"
#include "Variable.h"
#include "setOverloads.h"
using
namespace
std
;
static
const
std
::
string
opNames
[]
=
{
"_U"
,
"-"
,
"!"
,
""
,
"_UE"
,
...
...
@@ -52,6 +53,9 @@ public:
for
(
const
auto
&
v
:
vars
())
{
if
(
v
)
v
->
uses
.
emplace_back
(
self
);
}
for
(
const
auto
&
v
:
definitions
())
{
if
(
v
)
v
->
writes
.
emplace_back
(
self
);
}
};
virtual
vector
<
VariablePtr
>
vars
()
const
{
return
{};
};
virtual
vector
<
VariablePtr
>
definitions
()
const
{
return
{};
};
...
...
@@ -63,10 +67,6 @@ public:
explicit
QWriteVar
(
VariablePtr
loc
)
:
Quadruple
(),
loc
(
std
::
move
(
loc
))
{};
std
::
string
toString
()
const
override
{
return
Quadruple
::
toString
()
+
"
\t
"
+
(
loc
?
(
loc
->
name
+
" := "
)
:
""
);
}
void
useVariables
()
override
{
Quadruple
::
useVariables
();
if
(
loc
)
loc
->
writes
.
emplace_back
(
shared_from_this
());
}
vector
<
VariablePtr
>
definitions
()
const
override
{
auto
ret
=
Quadruple
::
definitions
();
if
(
loc
)
ret
.
emplace_back
(
loc
);
...
...
@@ -165,11 +165,6 @@ public:
return
ret
;
}
void
useVariables
()
override
{
Quadruple
::
useVariables
();
if
(
param
&&
num
<
0
)
param
->
writes
.
emplace_back
(
shared_from_this
());
}
vector
<
VariablePtr
>
definitions
()
const
override
{
auto
ret
=
Quadruple
::
definitions
();
if
(
param
&&
num
<
0
)
ret
.
emplace_back
(
param
);
...
...
src/codeGen/QuadrupleGenerator.cpp
View file @
ec3a8925
...
...
@@ -382,36 +382,38 @@ void QuadrupleGenerator::visitCondElse(CondElse *p) {
void
QuadrupleGenerator
::
compileCond
(
Expr
*
expr_
,
Stmt
*
stmt_1
,
Stmt
*
stmt_2
)
{
// TODO: stmty nie składają się z jednego bloku tylko z wielu
auto
elseBranch
=
make_shared
<
QLabel
>
(
"else"
);
auto
elseBranch
=
make_shared
<
QLabel
>
(
"
if_
else"
);
auto
after
=
make_shared
<
QLabel
>
(
"end_else"
);
auto
var
=
evalExpr
(
expr_
);
addQuad
<
QJumpCond
>
(
elseBranch
,
Op
::
Not
,
var
);
auto
beforeBlock
=
flushBasicBlock
();
// possible jump -> else
auto
env1
=
captureEnv
(),
env2
=
env1
;
auto
envIf
=
captureEnv
(),
envElse
=
envIf
;
auto
stmtIfFirstBlock
=
block
;
addQuad
<
QLabel
>
(
"if_true"
);
stmt_1
->
accept
(
this
);
addQuad
<
QJump
>
(
after
);
auto
stmt
1
Block
=
flushBasicBlock
();
// jump -> after
env
1
.
capture
();
env
1
.
revert
();
auto
stmt
IfLast
Block
=
flushBasicBlock
();
// jump -> after
env
If
.
capture
();
env
If
.
revert
();
addQuad
(
elseBranch
);
auto
stmtElseFirstBlock
=
block
;
if
(
stmt_2
)
{
stmt_2
->
accept
(
this
);
}
auto
stmt
2
Block
=
flushBasicBlock
();
// jump <- cond
env
2
.
capture
();
auto
stmt
ElseLast
Block
=
flushBasicBlock
();
// jump <- cond
env
Else
.
capture
();
addQuad
(
after
);
beforeBlock
->
append
(
stmt
1
Block
);
beforeBlock
->
append
(
stmt
2
Block
);
stmt
1
Block
->
append
(
block
);
stmt
2
Block
->
append
(
block
);
beforeBlock
->
append
(
stmt
IfFirst
Block
);
beforeBlock
->
append
(
stmt
ElseFirst
Block
);
stmt
IfLast
Block
->
append
(
block
);
stmt
ElseLast
Block
->
append
(
block
);
merge2Envs
(
&
env
1
,
stmt1Block
,
&
env2
,
stmt2
Block
);
merge2Envs
(
&
env
If
,
stmtIfLastBlock
,
&
envElse
,
stmtElseLast
Block
);
}
void
QuadrupleGenerator
::
merge2Envs
(
VariableLayout
*
env1
,
const
BasicBlockPtr
&
b1
,
VariableLayout
*
env2
,
const
BasicBlockPtr
&
b2
)
{
...
...
@@ -473,12 +475,13 @@ void QuadrupleGenerator::visitWhile(While *expr) {
auto
info
=
p
.
first
;
auto
hooked
=
p
.
second
.
first
;
auto
looped
=
p
.
second
.
second
;
if
(
!
hooked
||
hooked
==
looped
)
continue
;
if
(
!
hooked
)
continue
;
auto
orig
=
env1
.
changes
[
info
].
first
;
// save hooks if used
info
->
loc
=
hooked
;
// transition from pre-hook to hooked var [before -> cond]
auto
orig
=
env1
.
changes
[
info
].
first
;
condBlock
->
addPhi
(
beforeBlock
,
hooked
,
orig
);
// transition from hooked var
condBlock
->
addPhi
(
loopLastBlock
,
hooked
,
looped
);
// loopLastBlock doesn't need phi, it has only one incoming block
...
...
@@ -501,6 +504,6 @@ void QuadrupleGenerator::visitSExp(SExp *p) {
void
QuadrupleGenerator
::
visitForEach
(
ForEach
*
p
)
{
auto
tab
=
evalExpr
(
p
->
expr_
);
throw
ParseError
(
"ForEach is yet unimplemented!"
,
p
);
//
throw ParseError("ForEach is yet unimplemented!", p);
// TODO: implement
}
\ No newline at end of file
src/codeGen/RegisterAllocator.cpp
View file @
ec3a8925
#include "RegisterAllocator.h"
#include "BasicBlock.h"
#include "setOverloads.h"
#include <fstream>
void
RegisterAllocator
::
analyseLive
()
{
for
(
const
auto
&
v
:
vars
)
{
...
...
@@ -37,7 +38,8 @@ void RegisterAllocator::analyseLive() {
if
(
!
changed
)
break
;
}
assert
(
blocks
.
empty
()
||
blocks
[
0
]
->
flow
.
in
.
empty
());
if
(
!
blocks
.
empty
()
&&
!
blocks
[
0
]
->
flow
.
in
.
empty
())
throw
ParseError
(
"Variable definition not found - first block expects input"
);
}
void
RegisterAllocator
::
allocate
()
{
...
...
@@ -45,7 +47,24 @@ void RegisterAllocator::allocate() {
buildGraph
();
}
void
printGraph
(
const
Graph
<
VariablePtr
>
&
graph
,
const
std
::
string
&
filename
)
{
ofstream
f
(
filename
);
for
(
const
auto
&
v
:
graph
.
getEdges
())
{
f
<<
v
.
first
->
name
<<
" "
<<
v
.
second
->
name
<<
endl
;
}
f
.
close
();
}
void
printGraph
(
const
Graph
<
std
::
string
>
&
graph
,
const
std
::
string
&
filename
)
{
ofstream
f
(
filename
);
for
(
const
auto
&
v
:
graph
.
getEdges
())
{
f
<<
v
.
first
<<
" "
<<
v
.
second
<<
endl
;
}
f
.
close
();
}
void
RegisterAllocator
::
buildGraph
()
{
bool
anyAlive
=
false
;
for
(
const
auto
&
b
:
blocks
)
{
set
<
VariablePtr
>
alive
=
b
->
flow
.
in
;
for
(
const
auto
&
q
:
b
->
quads
)
{
...
...
@@ -59,18 +78,26 @@ void RegisterAllocator::buildGraph() {
}
alive
-=
to_set
(
dead
);
q
->
aliveAfter
=
alive
;
anyAlive
|=
alive
.
size
()
>=
2
;
for
(
auto
i
:
alive
)
{
for
(
auto
j
:
alive
)
{
if
(
i
!=
j
)
{
if
(
i
.
get
()
>
j
.
get
())
{
swap
(
i
,
j
);
}
graphEdges
.
insert
(
make_pair
(
i
,
j
));
graph
.
add
(
i
,
j
);
g2
.
add
(
i
->
name
,
j
->
name
);
}
}
}
}
}
if
(
!
anyAlive
)
return
;
graph
.
setup
();
g2
.
setup
();
assert
(
graph
.
chordal
==
g2
.
chordal
);
if
(
!
g2
.
chordal
)
{
printGraph
(
graph
,
"./mygraph"
);
printGraph
(
g2
,
"./myg2"
);
throw
ParseError
(
"graph not chordal!"
);
}
}
src/codeGen/RegisterAllocator.h
View file @
ec3a8925
...
...
@@ -5,6 +5,7 @@
#include "Quadruple.h"
#include "QuadrupleGenerator.h"
#include "Graph.h"
class
Register
:
public
std
::
enable_shared_from_this
<
Register
>
{
bool
available
;
...
...
@@ -14,7 +15,7 @@ class Register : public std::enable_shared_from_this<Register> {
class
RegisterAllocator
{
public:
explicit
RegisterAllocator
(
const
QuadrupleGenerator
::
Result
&
r
)
:
blocks
(
r
.
blocks
),
vars
(
r
.
vars
)
{}
RegisterAllocator
(
const
QuadrupleGenerator
::
Result
&
r
)
:
blocks
(
r
.
blocks
),
vars
(
r
.
vars
)
{}
void
processQJump
(
shared_ptr
<
QJump
>
q
);
void
processQJumpCond
(
shared_ptr
<
QJumpCond
>
q
);
void
processQLabel
(
shared_ptr
<
QLabel
>
q
);
...
...
@@ -29,10 +30,11 @@ public:
void
allocate
();
void
buildGraph
();
private:
Graph
<
VariablePtr
>
graph
;
Graph
<
std
::
string
>
g2
;
void
analyseLive
();
vector
<
BasicBlockPtr
>
blocks
;
vector
<
VariablePtr
>
vars
;
set
<
pair
<
VariablePtr
,
VariablePtr
>>
graphEdges
;
};
...
...
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