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
a83f92b3
Commit
a83f92b3
authored
Jan 06, 2021
by
zygzagZ
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Works: Using function parameters, strict-SSA, analysis: liveness, flow
parent
726a943e
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
152 additions
and
33 deletions
+152
-33
Compiler.cpp
src/Compiler.cpp
+18
-1
BasicBlock.cpp
src/codeGen/BasicBlock.cpp
+2
-2
BasicBlock.h
src/codeGen/BasicBlock.h
+35
-7
Quadruple.h
src/codeGen/Quadruple.h
+55
-2
QuadrupleGenerator.cpp
src/codeGen/QuadrupleGenerator.cpp
+28
-13
QuadrupleGenerator.h
src/codeGen/QuadrupleGenerator.h
+4
-0
RegisterAllocator.cpp
src/codeGen/RegisterAllocator.cpp
+10
-8
No files found.
src/Compiler.cpp
View file @
a83f92b3
...
...
@@ -62,8 +62,25 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) {
regGen
.
allocate
();
for
(
const
auto
&
b
:
quadEnv
.
blocks
)
{
buf
<<
"------------------------------
\n
"
;
if
(
!
b
->
flow
.
in
.
empty
())
{
buf
<<
"in: "
;
for
(
const
auto
&
v
:
b
->
flow
.
in
)
{
buf
<<
v
->
name
<<
", "
;
}
buf
<<
"
\n
----------
\n
"
;
}
for
(
const
auto
&
q
:
b
->
quads
)
{
buf
<<
q
->
toString
()
<<
endl
;
auto
ret
=
q
->
toString
();
if
(
!
ret
.
empty
())
buf
<<
ret
<<
endl
;
}
if
(
!
b
->
flow
.
out
.
empty
())
{
buf
<<
"----------
\n
out: "
;
for
(
const
auto
&
v
:
b
->
flow
.
out
)
{
buf
<<
v
->
name
<<
", "
;
}
buf
<<
"
\n
"
;
}
}
}
src/codeGen/BasicBlock.cpp
View file @
a83f92b3
...
...
@@ -14,9 +14,9 @@ void BasicBlock::finishQuads() {
afterInit
.
clear
();
auto
self
=
shared_from_this
();
auto
self
=
this
->
shared_from_this
();
for
(
const
auto
&
q
:
quads
)
{
q
->
useVariables
();
q
->
block
=
self
;
q
->
useVariables
();
}
}
src/codeGen/BasicBlock.h
View file @
a83f92b3
...
...
@@ -6,6 +6,8 @@
#include <map>
#include <cassert>
#include "Variable.h"
#include "Quadruple.h"
#include "setOverloads.h"
using
namespace
std
;
...
...
@@ -13,30 +15,56 @@ class BasicBlock : public std::enable_shared_from_this<BasicBlock> {
public:
struct
FlowAnalysisData
{
set
<
VariablePtr
>
in
,
out
,
def
,
use
;
BasicBlock
*
b
{};
void
addUse
(
const
VariablePtr
&
v
)
{
if
(
!
def
.
contains
(
v
))
use
.
emplace
(
v
);
}
void
addDef
(
const
VariablePtr
&
v
)
{
def
.
emplace
(
v
);
use
.
erase
(
v
);
}
[[
nodiscard
]]
set
<
VariablePtr
>
inForBlock
(
const
BasicBlockPtr
&
q
)
const
{
set
<
VariablePtr
>
ret
;
for
(
const
auto
&
var
:
b
->
findPhi
(
q
))
{
ret
.
emplace
(
var
.
second
);
}
return
in
+
ret
;
}
};
BasicBlock
()
{
phi
=
make_shared
<
QPhi
>
();
flow
.
b
=
this
;
quads
.
emplace_back
(
phi
);
};
BasicBlock
()
=
default
;
vector
<
QuadruplePtr
>
quads
;
vector
<
QuadruplePtr
>
afterInit
;
vector
<
BasicBlockPtr
>
in
,
out
;
vector
<
map
<
VariablePtr
,
VariablePtr
>
>
phi
;
shared_ptr
<
QPhi
>
phi
;
FlowAnalysisData
flow
;
void
append
(
const
BasicBlockPtr
&
after
)
{
out
.
push_back
(
after
);
after
->
in
.
push_back
(
shared_from_this
());
after
->
phi
.
emplace_back
();
after
->
phi
->
phi
.
emplace_back
();
}
void
addJumpInitQuad
(
const
QuadruplePtr
&
q
)
{
afterInit
.
push_back
(
q
);
}
map
<
VariablePtr
,
VariablePtr
>
&
findPhi
(
const
BasicBlockPtr
&
blk
)
{
auto
it
=
find
(
in
.
begin
(),
in
.
end
(),
blk
);
if
(
it
==
in
.
end
())
throw
runtime_error
(
"blk not found in incoming blocks"
);
auto
mit
=
phi
->
phi
.
begin
()
+
(
it
-
in
.
begin
());
return
*
mit
;
}
void
addPhi
(
const
BasicBlockPtr
&
blk
,
const
VariablePtr
&
local
,
VariablePtr
remote
)
{
assert
(
blk
&&
local
&&
remote
);
assert
(
local
->
info
&&
!
local
->
info
->
isInstanceVariable
());
auto
it
=
find
(
in
.
begin
(),
in
.
end
(),
blk
);
if
(
it
==
in
.
end
())
throw
runtime_error
(
"blk not found in incoming blocks"
);
auto
mit
=
phi
.
begin
()
+
(
it
-
in
.
begin
());
(
*
mit
)[
local
]
=
std
::
move
(
remote
);
auto
&
phiMap
=
findPhi
(
blk
);
phiMap
[
local
]
=
std
::
move
(
remote
);
}
void
finishQuads
();
...
...
src/codeGen/Quadruple.h
View file @
a83f92b3
...
...
@@ -154,10 +154,14 @@ public:
vector
<
VariablePtr
>
vars
()
const
override
{
auto
ret
=
Quadruple
::
vars
();
if
(
param
)
ret
.
emplace_back
(
param
);
if
(
param
&&
num
>=
0
)
ret
.
emplace_back
(
param
);
return
ret
;
}
};
void
useVariables
()
override
{
Quadruple
::
useVariables
();
if
(
param
&&
num
<
0
)
param
->
writes
.
emplace_back
(
shared_from_this
());
}};
class
QCall
:
public
QWriteVar
{
public:
...
...
@@ -267,5 +271,54 @@ public:
}
};
class
QPhi
:
public
Quadruple
{
public:
vector
<
map
<
VariablePtr
,
VariablePtr
>>
phi
;
vector
<
VariablePtr
>
vars
()
const
override
{
auto
ret
=
Quadruple
::
vars
();
for
(
const
auto
&
b
:
phi
)
{
for
(
const
auto
&
v
:
b
)
{
ret
.
emplace_back
(
v
.
second
);
}
}
return
ret
;
}
void
useVariables
()
override
{
set
<
VariablePtr
>
written
;
auto
self
=
shared_from_this
();
for
(
const
auto
&
b
:
phi
)
{
for
(
const
auto
&
v
:
b
)
{
if
(
!
written
.
contains
(
v
.
first
))
{
v
.
first
->
writes
.
emplace_back
(
self
);
written
.
emplace
(
v
.
first
);
}
// QPhi does not place uses here, it is handled in RegisterAllocator
}
}
}
std
::
string
toString
()
const
override
{
if
(
phi
.
size
()
<
2
)
return
""
;
std
::
string
ret
=
Quadruple
::
toString
()
+
"phi "
;
for
(
const
auto
&
left
:
*
phi
.
begin
())
{
auto
&
tg
=
left
.
first
;
ret
+=
tg
->
name
+
" = ["
;
bool
f
=
true
;
for
(
auto
b
:
phi
)
{
if
(
!
b
.
count
(
tg
))
continue
;
if
(
f
)
f
=
false
;
else
ret
+=
", "
;
ret
+=
b
[
tg
]
->
name
;
}
ret
+=
"] "
;
}
return
ret
;
}
};
#endif //ZAD2_QUAD_H
src/codeGen/QuadrupleGenerator.cpp
View file @
a83f92b3
...
...
@@ -9,7 +9,15 @@ QuadrupleGenerator::Result QuadrupleGenerator::compileFunction(FunctionInfoPtr f
if
(
!
f
->
block
)
return
{};
scope
->
currentFunction
=
f
;
block
=
make_shared
<
BasicBlock
>
();
newBlock
();
{
int
param
=
1
;
for
(
const
auto
&
arg
:
f
->
arguments
)
{
auto
var
=
alloc
(
arg
);
addQuad
(
make_shared
<
QParam
>
(
var
,
-
param
));
param
++
;
}
}
f
->
block
->
accept
(
this
);
int
id
=
1
;
...
...
@@ -49,11 +57,12 @@ QuadrupleGenerator::Result QuadrupleGenerator::compileFunction(FunctionInfoPtr f
for
(
const
auto
&
v
:
vars
)
{
if
(
v
->
info
)
v
->
info
->
loc
=
nullptr
;
cout
<<
"
\n
var "
<<
v
->
name
<<
endl
;
// TODO: wypisywanie zmiennych
/*cout << "\nvar " << v->name << endl;
for (const auto& q : v->writes)
cout << q->toString() << endl;
for (const auto& q : v->uses)
cout
<<
q
->
toString
()
<<
endl
;
cout << q->toString() << endl;
*/
}
QuadrupleGenerator
::
Result
ret
;
vars
.
swap
(
ret
.
vars
);
...
...
@@ -70,7 +79,7 @@ BasicBlockPtr QuadrupleGenerator::flushBasicBlock() {
flushLastQuad
();
}
block
=
make_shared
<
BasicBlock
>
();
newBlock
();
return
ret
;
}
...
...
@@ -431,6 +440,7 @@ void QuadrupleGenerator::visitWhile(While *expr) {
// produce all variables hooks
for
(
const
auto
&
change
:
env1
.
changes
)
{
if
(
!
change
.
second
.
first
)
continue
;
auto
info
=
change
.
first
;
info
->
loc
=
nullptr
;
alloc
(
info
);
...
...
@@ -445,6 +455,7 @@ void QuadrupleGenerator::visitWhile(While *expr) {
expr
->
stmt_
->
accept
(
this
);
auto
loopBlock
=
flushBasicBlock
();
// jump <- cond
auto
condBlock
=
block
;
addQuad
(
cond
);
// env2 contains changed hooks
...
...
@@ -452,26 +463,30 @@ void QuadrupleGenerator::visitWhile(While *expr) {
// restore env1 pre-hook variables
env1
.
revert
();
beforeBlock
->
append
(
block
);
block
->
append
(
loopBlock
);
beforeBlock
->
append
(
condBlock
);
condBlock
->
append
(
loopBlock
);
loopBlock
->
append
(
condBlock
);
for
(
const
auto
&
p
:
env2
.
changes
)
{
auto
info
=
p
.
first
;
auto
x1
=
p
.
second
.
first
;
auto
x2
=
p
.
second
.
second
;
auto
hooked
=
p
.
second
.
first
;
auto
looped
=
p
.
second
.
second
;
if
(
!
hooked
||
hooked
==
looped
)
continue
;
// save hooks if used
info
->
loc
=
x1
;
info
->
loc
=
hooked
;
// transition from pre-hook to hooked var [before -> cond]
block
->
addPhi
(
beforeBlock
,
x1
,
env1
.
changes
[
info
].
first
);
// transition from loop var to hooked var [loop -> cond]
loopBlock
->
addPhi
(
block
,
x1
,
x2
);
auto
orig
=
env1
.
changes
[
info
].
first
;
condBlock
->
addPhi
(
beforeBlock
,
hooked
,
orig
);
condBlock
->
addPhi
(
loopBlock
,
hooked
,
looped
);
// loopBlock doesn't need phi, it has only one incoming block
}
// expr uses pre-hook variables iff unused in loop
auto
var
=
evalExpr
(
expr
->
expr_
);
addQuad
<
QJumpCond
>
(
loop
,
Op
::
Copy
,
var
);
auto
condBlock
=
flushBasicBlock
();
// jump -> loop
flushBasicBlock
();
// jump -> loop
// next block is ready to use updated variables
...
...
src/codeGen/QuadrupleGenerator.h
View file @
a83f92b3
...
...
@@ -86,6 +86,10 @@ private:
QuadruplePtr
lastQuad
;
BasicBlockPtr
newBlock
()
{
return
block
=
make_shared
<
BasicBlock
>
();
}
void
flushLastQuad
()
{
if
(
lastQuad
)
{
block
->
quads
.
emplace_back
(
lastQuad
);
...
...
src/codeGen/RegisterAllocator.cpp
View file @
a83f92b3
...
...
@@ -4,19 +4,19 @@
void
RegisterAllocator
::
analyseLive
()
{
for
(
const
auto
&
v
:
vars
)
{
for
(
const
auto
&
q
:
v
->
uses
)
{
q
->
block
->
flow
.
use
.
emplace
(
v
);
}
if
(
!
v
->
info
)
continue
;
for
(
const
auto
&
q
:
v
->
writes
)
{
q
->
block
->
flow
.
def
.
emplace
(
v
);
q
->
block
->
flow
.
addDef
(
v
);
}
for
(
const
auto
&
q
:
v
->
uses
)
{
q
->
block
->
flow
.
addUse
(
v
);
}
}
for
(
const
auto
&
b
:
blocks
)
{
for
(
const
auto
&
phiMap
:
b
->
phi
)
{
for
(
const
auto
&
phiMap
:
b
->
phi
->
phi
)
{
for
(
const
auto
&
phiRow
:
phiMap
)
{
b
->
flow
.
def
.
emplace
(
phiRow
.
first
);
b
->
flow
.
use
.
emplace
(
phiRow
.
second
);
}
}
}
...
...
@@ -30,14 +30,16 @@ void RegisterAllocator::analyseLive() {
pOut
.
swap
(
f
.
out
);
f
.
in
=
f
.
use
+
(
pOut
-
f
.
def
);
for
(
const
auto
&
succ
:
b
->
out
)
{
f
.
out
+=
succ
->
flow
.
in
;
f
.
out
+=
succ
->
flow
.
in
ForBlock
(
b
)
;
}
if
(
f
.
in
!=
pIn
||
f
.
out
!=
pOut
)
changed
=
true
;
}
if
(
!
changed
)
break
;
}
assert
(
blocks
.
empty
()
||
blocks
[
0
]
->
flow
.
in
.
empty
());
}
void
RegisterAllocator
::
allocate
()
{
analyseLive
();
}
\ No newline at end of file
}
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