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
Show 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) {
...
@@ -62,8 +62,25 @@ void Compiler::compileFunction(const FunctionInfoPtr& f) {
regGen
.
allocate
();
regGen
.
allocate
();
for
(
const
auto
&
b
:
quadEnv
.
blocks
)
{
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
)
{
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() {
...
@@ -14,9 +14,9 @@ void BasicBlock::finishQuads() {
afterInit
.
clear
();
afterInit
.
clear
();
auto
self
=
shared_from_this
();
auto
self
=
this
->
shared_from_this
();
for
(
const
auto
&
q
:
quads
)
{
for
(
const
auto
&
q
:
quads
)
{
q
->
useVariables
();
q
->
block
=
self
;
q
->
block
=
self
;
q
->
useVariables
();
}
}
}
}
src/codeGen/BasicBlock.h
View file @
a83f92b3
...
@@ -6,6 +6,8 @@
...
@@ -6,6 +6,8 @@
#include <map>
#include <map>
#include <cassert>
#include <cassert>
#include "Variable.h"
#include "Variable.h"
#include "Quadruple.h"
#include "setOverloads.h"
using
namespace
std
;
using
namespace
std
;
...
@@ -13,30 +15,56 @@ class BasicBlock : public std::enable_shared_from_this<BasicBlock> {
...
@@ -13,30 +15,56 @@ class BasicBlock : public std::enable_shared_from_this<BasicBlock> {
public:
public:
struct
FlowAnalysisData
{
struct
FlowAnalysisData
{
set
<
VariablePtr
>
in
,
out
,
def
,
use
;
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
>
quads
;
vector
<
QuadruplePtr
>
afterInit
;
vector
<
QuadruplePtr
>
afterInit
;
vector
<
BasicBlockPtr
>
in
,
out
;
vector
<
BasicBlockPtr
>
in
,
out
;
vector
<
map
<
VariablePtr
,
VariablePtr
>
>
phi
;
shared_ptr
<
QPhi
>
phi
;
FlowAnalysisData
flow
;
FlowAnalysisData
flow
;
void
append
(
const
BasicBlockPtr
&
after
)
{
void
append
(
const
BasicBlockPtr
&
after
)
{
out
.
push_back
(
after
);
out
.
push_back
(
after
);
after
->
in
.
push_back
(
shared_from_this
());
after
->
in
.
push_back
(
shared_from_this
());
after
->
phi
.
emplace_back
();
after
->
phi
->
phi
.
emplace_back
();
}
}
void
addJumpInitQuad
(
const
QuadruplePtr
&
q
)
{
void
addJumpInitQuad
(
const
QuadruplePtr
&
q
)
{
afterInit
.
push_back
(
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
)
{
void
addPhi
(
const
BasicBlockPtr
&
blk
,
const
VariablePtr
&
local
,
VariablePtr
remote
)
{
assert
(
blk
&&
local
&&
remote
);
assert
(
blk
&&
local
&&
remote
);
assert
(
local
->
info
&&
!
local
->
info
->
isInstanceVariable
());
assert
(
local
->
info
&&
!
local
->
info
->
isInstanceVariable
());
auto
it
=
find
(
in
.
begin
(),
in
.
end
(),
blk
);
auto
&
phiMap
=
findPhi
(
blk
);
if
(
it
==
in
.
end
())
throw
runtime_error
(
"blk not found in incoming blocks"
);
phiMap
[
local
]
=
std
::
move
(
remote
);
auto
mit
=
phi
.
begin
()
+
(
it
-
in
.
begin
());
(
*
mit
)[
local
]
=
std
::
move
(
remote
);
}
}
void
finishQuads
();
void
finishQuads
();
...
...
src/codeGen/Quadruple.h
View file @
a83f92b3
...
@@ -154,10 +154,14 @@ public:
...
@@ -154,10 +154,14 @@ public:
vector
<
VariablePtr
>
vars
()
const
override
{
vector
<
VariablePtr
>
vars
()
const
override
{
auto
ret
=
Quadruple
::
vars
();
auto
ret
=
Quadruple
::
vars
();
if
(
param
)
ret
.
emplace_back
(
param
);
if
(
param
&&
num
>=
0
)
ret
.
emplace_back
(
param
);
return
ret
;
return
ret
;
}
}
};
void
useVariables
()
override
{
Quadruple
::
useVariables
();
if
(
param
&&
num
<
0
)
param
->
writes
.
emplace_back
(
shared_from_this
());
}};
class
QCall
:
public
QWriteVar
{
class
QCall
:
public
QWriteVar
{
public:
public:
...
@@ -267,5 +271,54 @@ 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
#endif //ZAD2_QUAD_H
src/codeGen/QuadrupleGenerator.cpp
View file @
a83f92b3
...
@@ -9,7 +9,15 @@ QuadrupleGenerator::Result QuadrupleGenerator::compileFunction(FunctionInfoPtr f
...
@@ -9,7 +9,15 @@ QuadrupleGenerator::Result QuadrupleGenerator::compileFunction(FunctionInfoPtr f
if
(
!
f
->
block
)
return
{};
if
(
!
f
->
block
)
return
{};
scope
->
currentFunction
=
f
;
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
);
f
->
block
->
accept
(
this
);
int
id
=
1
;
int
id
=
1
;
...
@@ -49,11 +57,12 @@ QuadrupleGenerator::Result QuadrupleGenerator::compileFunction(FunctionInfoPtr f
...
@@ -49,11 +57,12 @@ QuadrupleGenerator::Result QuadrupleGenerator::compileFunction(FunctionInfoPtr f
for
(
const
auto
&
v
:
vars
)
{
for
(
const
auto
&
v
:
vars
)
{
if
(
v
->
info
)
if
(
v
->
info
)
v
->
info
->
loc
=
nullptr
;
v
->
info
->
loc
=
nullptr
;
cout
<<
"
\n
var "
<<
v
->
name
<<
endl
;
// TODO: wypisywanie zmiennych
/*cout << "\nvar " << v->name << endl;
for (const auto& q : v->writes)
for (const auto& q : v->writes)
cout << q->toString() << endl;
cout << q->toString() << endl;
for (const auto& q : v->uses)
for (const auto& q : v->uses)
cout
<<
q
->
toString
()
<<
endl
;
cout << q->toString() << endl;
*/
}
}
QuadrupleGenerator
::
Result
ret
;
QuadrupleGenerator
::
Result
ret
;
vars
.
swap
(
ret
.
vars
);
vars
.
swap
(
ret
.
vars
);
...
@@ -70,7 +79,7 @@ BasicBlockPtr QuadrupleGenerator::flushBasicBlock() {
...
@@ -70,7 +79,7 @@ BasicBlockPtr QuadrupleGenerator::flushBasicBlock() {
flushLastQuad
();
flushLastQuad
();
}
}
block
=
make_shared
<
BasicBlock
>
();
newBlock
();
return
ret
;
return
ret
;
}
}
...
@@ -431,6 +440,7 @@ void QuadrupleGenerator::visitWhile(While *expr) {
...
@@ -431,6 +440,7 @@ void QuadrupleGenerator::visitWhile(While *expr) {
// produce all variables hooks
// produce all variables hooks
for
(
const
auto
&
change
:
env1
.
changes
)
{
for
(
const
auto
&
change
:
env1
.
changes
)
{
if
(
!
change
.
second
.
first
)
continue
;
auto
info
=
change
.
first
;
auto
info
=
change
.
first
;
info
->
loc
=
nullptr
;
info
->
loc
=
nullptr
;
alloc
(
info
);
alloc
(
info
);
...
@@ -445,6 +455,7 @@ void QuadrupleGenerator::visitWhile(While *expr) {
...
@@ -445,6 +455,7 @@ void QuadrupleGenerator::visitWhile(While *expr) {
expr
->
stmt_
->
accept
(
this
);
expr
->
stmt_
->
accept
(
this
);
auto
loopBlock
=
flushBasicBlock
();
// jump <- cond
auto
loopBlock
=
flushBasicBlock
();
// jump <- cond
auto
condBlock
=
block
;
addQuad
(
cond
);
addQuad
(
cond
);
// env2 contains changed hooks
// env2 contains changed hooks
...
@@ -452,26 +463,30 @@ void QuadrupleGenerator::visitWhile(While *expr) {
...
@@ -452,26 +463,30 @@ void QuadrupleGenerator::visitWhile(While *expr) {
// restore env1 pre-hook variables
// restore env1 pre-hook variables
env1
.
revert
();
env1
.
revert
();
beforeBlock
->
append
(
block
);
beforeBlock
->
append
(
condBlock
);
block
->
append
(
loopBlock
);
condBlock
->
append
(
loopBlock
);
loopBlock
->
append
(
condBlock
);
for
(
const
auto
&
p
:
env2
.
changes
)
{
for
(
const
auto
&
p
:
env2
.
changes
)
{
auto
info
=
p
.
first
;
auto
info
=
p
.
first
;
auto
x1
=
p
.
second
.
first
;
auto
hooked
=
p
.
second
.
first
;
auto
x2
=
p
.
second
.
second
;
auto
looped
=
p
.
second
.
second
;
if
(
!
hooked
||
hooked
==
looped
)
continue
;
// save hooks if used
// save hooks if used
info
->
loc
=
x1
;
info
->
loc
=
hooked
;
// transition from pre-hook to hooked var [before -> cond]
// transition from pre-hook to hooked var [before -> cond]
block
->
addPhi
(
beforeBlock
,
x1
,
env1
.
changes
[
info
].
first
);
auto
orig
=
env1
.
changes
[
info
].
first
;
// transition from loop var to hooked var [loop -> cond]
condBlock
->
addPhi
(
beforeBlock
,
hooked
,
orig
);
loopBlock
->
addPhi
(
block
,
x1
,
x2
);
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
// expr uses pre-hook variables iff unused in loop
auto
var
=
evalExpr
(
expr
->
expr_
);
auto
var
=
evalExpr
(
expr
->
expr_
);
addQuad
<
QJumpCond
>
(
loop
,
Op
::
Copy
,
var
);
addQuad
<
QJumpCond
>
(
loop
,
Op
::
Copy
,
var
);
auto
condBlock
=
flushBasicBlock
();
// jump -> loop
flushBasicBlock
();
// jump -> loop
// next block is ready to use updated variables
// next block is ready to use updated variables
...
...
src/codeGen/QuadrupleGenerator.h
View file @
a83f92b3
...
@@ -86,6 +86,10 @@ private:
...
@@ -86,6 +86,10 @@ private:
QuadruplePtr
lastQuad
;
QuadruplePtr
lastQuad
;
BasicBlockPtr
newBlock
()
{
return
block
=
make_shared
<
BasicBlock
>
();
}
void
flushLastQuad
()
{
void
flushLastQuad
()
{
if
(
lastQuad
)
{
if
(
lastQuad
)
{
block
->
quads
.
emplace_back
(
lastQuad
);
block
->
quads
.
emplace_back
(
lastQuad
);
...
...
src/codeGen/RegisterAllocator.cpp
View file @
a83f92b3
...
@@ -4,19 +4,19 @@
...
@@ -4,19 +4,19 @@
void
RegisterAllocator
::
analyseLive
()
{
void
RegisterAllocator
::
analyseLive
()
{
for
(
const
auto
&
v
:
vars
)
{
for
(
const
auto
&
v
:
vars
)
{
for
(
const
auto
&
q
:
v
->
uses
)
{
if
(
!
v
->
info
)
continue
;
q
->
block
->
flow
.
use
.
emplace
(
v
);
}
for
(
const
auto
&
q
:
v
->
writes
)
{
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
&
b
:
blocks
)
{
for
(
const
auto
&
phiMap
:
b
->
phi
)
{
for
(
const
auto
&
phiMap
:
b
->
phi
->
phi
)
{
for
(
const
auto
&
phiRow
:
phiMap
)
{
for
(
const
auto
&
phiRow
:
phiMap
)
{
b
->
flow
.
def
.
emplace
(
phiRow
.
first
);
b
->
flow
.
def
.
emplace
(
phiRow
.
first
);
b
->
flow
.
use
.
emplace
(
phiRow
.
second
);
}
}
}
}
}
}
...
@@ -30,12 +30,14 @@ void RegisterAllocator::analyseLive() {
...
@@ -30,12 +30,14 @@ void RegisterAllocator::analyseLive() {
pOut
.
swap
(
f
.
out
);
pOut
.
swap
(
f
.
out
);
f
.
in
=
f
.
use
+
(
pOut
-
f
.
def
);
f
.
in
=
f
.
use
+
(
pOut
-
f
.
def
);
for
(
const
auto
&
succ
:
b
->
out
)
{
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
(
f
.
in
!=
pIn
||
f
.
out
!=
pOut
)
changed
=
true
;
}
}
if
(
!
changed
)
break
;
if
(
!
changed
)
break
;
}
}
assert
(
blocks
.
empty
()
||
blocks
[
0
]
->
flow
.
in
.
empty
());
}
}
void
RegisterAllocator
::
allocate
()
{
void
RegisterAllocator
::
allocate
()
{
...
...
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