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
9234e433
Commit
9234e433
authored
Jan 04, 2021
by
zygzagZ
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WIP basic block graph (CFG)
parent
9b245472
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
177 additions
and
41 deletions
+177
-41
Compiler.cpp
src/Compiler.cpp
+115
-27
Compiler.h
src/Compiler.h
+26
-13
TypeDefs.h
src/TypeDefs.h
+1
-0
BasicBlock.h
src/codeGen/BasicBlock.h
+8
-1
Variable.h
src/codeGen/Variable.h
+27
-0
No files found.
src/Compiler.cpp
View file @
9234e433
...
...
@@ -54,6 +54,7 @@ void Compiler::compileFunction(FunctionInfoPtr f) {
buf
<<
"
\"
"
<<
name
<<
"
\"
:
\n
"
;
scope
->
currentFunction
=
f
;
block
=
make_shared
<
BasicBlock
>
();
f
->
block
->
accept
(
this
);
int
id
=
1
;
...
...
@@ -69,17 +70,25 @@ void Compiler::compileFunction(FunctionInfoPtr f) {
id
++
;
}
flushBasicBlock
();
block
=
nullptr
;
int
label
=
1
;
for
(
auto
q
:
quads
)
{
if
(
auto
l
=
dynamic_pointer_cast
<
QLabel
>
(
q
))
{
if
(
!
l
->
label
.
empty
())
l
->
label
=
to_string
(
label
++
)
+
"_"
+
l
->
label
;
else
l
->
label
=
to_string
(
label
++
);
for
(
auto
b
:
blocks
)
{
for
(
auto
q
:
b
->
quads
)
{
if
(
auto
l
=
dynamic_pointer_cast
<
QLabel
>
(
q
))
{
if
(
!
l
->
label
.
empty
())
l
->
label
=
to_string
(
label
++
)
+
"_"
+
l
->
label
;
else
l
->
label
=
to_string
(
label
++
);
}
}
}
for
(
auto
q
:
quads
)
{
buf
<<
q
->
toString
()
<<
endl
;
for
(
auto
b
:
blocks
)
{
for
(
auto
q
:
b
->
quads
)
{
buf
<<
q
->
toString
()
<<
endl
;
}
}
for
(
auto
v
:
vars
)
{
...
...
@@ -87,17 +96,74 @@ void Compiler::compileFunction(FunctionInfoPtr f) {
v
->
info
->
loc
=
nullptr
;
}
quads
.
clear
();
scope
->
currentFunction
=
nullptr
;
}
void
Compiler
::
endBasicBlock
()
{
for
(
auto
v
:
vars
)
{
/*
- kiedy przechodzę między blokami:
- pierwsze wejście w while/fora: ustawienie używanych wartości w pętli w zależności od ostatnich wartości przed pętlą
- dump przed wejściem w stmt fora, dump po sparsowaniu fora
- różnice ustawić w bloku przed i tak samo za nim
- if: przed ifem dump, za ifem dorobić else i ustawić diff
- ifelse: przed ifem dump, w środku dump, po elsie dump
- wszystkie poza zmienionymi w bloku ustawiamy na koniec bloku
wskazówki do implementacji:
- w momencie przypisywania do zmiennej lokalnej chcemy powiadomić najświeższy detektor zmian lokalnych
- po zakończeniu bloku detektor zmian odpowiednio poprzypisuje w pożądanych miejcach odpowiednie definicje
- po zakończeniu bloku detektor powiadomi kolejny z rzędu detektor o najnowszych instancjach zmienionych zmiennych
- detektor powinien działać ponad blokami prostymi
funkcje detektora:
- dodanie zmiennej VarInfoPtr do zbioru, przyporządkowanie jej najnowszej definicji (i zapamiętanie oryginalnej)
- umiejętność porównania dwóch zbiorów poprzez iterację
- każdy element który występuje tylko w jednym
- para jeśli el. występuje w obu zbiorach
implementacja detektora:
- map<VarInfoPtr, pair<orig, new>>
dalej: << i >> dla BB
porobić graf BB
złapać blocki i podumpować envy dookoła flow
dopisać sumę dumpów
*/
BasicBlockPtr
Compiler
::
flushBasicBlock
()
{
for
(
const
auto
&
v
:
vars
)
{
if
(
v
->
info
)
v
->
info
->
loc
=
nullptr
;
}
auto
ret
=
block
;
if
(
block
)
{
blocks
.
emplace_back
(
block
);
flushLastQuad
();
}
block
=
make_shared
<
BasicBlock
>
();
return
ret
;
}
VariableLayout
Compiler
::
captureEnv
()
{
VariableLayout
ret
;
BindingPtr
b
=
scope
->
currentBinding
;
while
(
b
)
{
for
(
const
auto
&
info
:
b
->
variables
)
{
if
(
info
->
isInstanceVariable
())
continue
;
if
(
info
->
loc
)
{
ret
.
add
(
info
);
}
}
b
=
b
->
getParent
();
}
return
ret
;
}
/// expressions
void
Compiler
::
visitEVar
(
EVar
*
p
)
{
...
...
@@ -180,7 +246,7 @@ void Compiler::visitEAnd(EAnd *p) {
addQuad
<
QAssign
>
(
lastVar
,
Op
::
Copy
,
r
);
addQuad
<
QJump
>
(
labelAfter
);
addQuad
(
labelLeft
);
addQuad
<
QAssign
>
(
lastVar
,
Op
::
Copy
,
l
);
addQuad
<
QAssign
>
(
lastVar
,
Op
::
Copy
,
alloc
(
0
)
);
addQuad
(
labelAfter
);
}
...
...
@@ -197,7 +263,7 @@ void Compiler::visitEOr(EOr *p) {
addQuad
<
QAssign
>
(
lastVar
,
Op
::
Copy
,
r
);
addQuad
<
QJump
>
(
labelAfter
);
addQuad
(
labelLeft
);
addQuad
<
QAssign
>
(
lastVar
,
Op
::
Copy
,
l
);
addQuad
<
QAssign
>
(
lastVar
,
Op
::
Copy
,
alloc
(
1
)
);
addQuad
(
labelAfter
);
}
...
...
@@ -238,7 +304,7 @@ void Compiler::visitEClsMmbr(EClsMmbr *p) {
size_t
offset
=
var
->
offset
;
if
(
dynamic_cast
<
EIndexAcc
*>
(
p
->
expr_
))
{
// opt if EIndexAcc is used inside visitEClsMmbr
auto
access
=
dynamic_pointer_cast
<
QAccess
>
(
quads
.
back
());
auto
access
=
dynamic_pointer_cast
<
QAccess
>
(
block
->
quads
.
back
());
access
->
access
.
offset
+=
offset
;
l
->
info
=
var
;
lastVar
=
l
;
...
...
@@ -328,12 +394,11 @@ void Compiler::assign(Expr* lval, VariablePtr val) {
auto
dest
=
evalLVal
(
lval
);
if
(
dest
->
info
&&
dest
->
info
->
isInstanceVariable
())
{
// instance variable, need to write it to memory
auto
quad
=
dynamic_pointer_cast
<
QAccess
>
(
quads
.
empty
()
?
nullptr
:
quads
.
back
()
);
auto
quad
=
dynamic_pointer_cast
<
QAccess
>
(
lastQuad
);
assert
(
quad
);
auto
loc
=
quad
->
access
;
quads
.
pop_back
();
block
->
quads
.
pop_back
();
addQuad
<
QWrite
>
(
loc
,
val
);
return
;
}
else
{
// local variable - only assign
addQuad
<
QAssign
>
(
dest
,
Op
::
Copy
,
val
);
...
...
@@ -359,27 +424,33 @@ void Compiler::visitDecr(Decr *p) {
assign
(
p
->
expr_
,
tmp
);
}
// flow control
void
Compiler
::
visitRet
(
Ret
*
p
)
{
auto
var
=
evalExpr
(
p
->
expr_
);
endBasicBlock
();
addQuad
<
QReturn
>
(
var
);
flushBasicBlock
();
}
void
Compiler
::
visitVRet
(
VRet
*
p
)
{
endBasicBlock
();
addQuad
<
QReturn
>
(
nullptr
);
flushBasicBlock
();
}
void
Compiler
::
visitCond
(
Cond
*
p
)
{
auto
var
=
evalExpr
(
p
->
expr_
);
auto
after
=
make_shared
<
QLabel
>
(
"end_if"
);
endBasicBlock
();
// possible jump -> after
addQuad
<
QJumpCond
>
(
after
,
Op
::
Not
,
var
);
auto
beforeBlock
=
flushBasicBlock
();
// possible jump -> after
p
->
stmt_
->
accept
(
this
);
end
BasicBlock
();
// possible jump <- cond
auto
innerBlock
=
flush
BasicBlock
();
// possible jump <- cond
addQuad
(
after
);
beforeBlock
->
append
(
innerBlock
);
beforeBlock
->
append
(
block
);
innerBlock
->
append
(
block
);
}
void
Compiler
::
visitCondElse
(
CondElse
*
p
)
{
...
...
@@ -388,37 +459,46 @@ void Compiler::visitCondElse(CondElse *p) {
auto
var
=
evalExpr
(
p
->
expr_
);
endBasicBlock
();
// possible jump -> else
addQuad
<
QJumpCond
>
(
elseBranch
,
Op
::
Not
,
var
);
auto
beforeBlock
=
flushBasicBlock
();
// possible jump -> else
p
->
stmt_1
->
accept
(
this
);
endBasicBlock
();
// jump -> after
addQuad
<
QJump
>
(
after
);
auto
stmt1Block
=
flushBasicBlock
();
// jump -> after
addQuad
(
elseBranch
);
p
->
stmt_2
->
accept
(
this
);
end
BasicBlock
();
// jump <- cond
auto
stmt2Block
=
flush
BasicBlock
();
// jump <- cond
addQuad
(
after
);
beforeBlock
->
append
(
stmt1Block
);
beforeBlock
->
append
(
stmt2Block
);
stmt1Block
->
append
(
block
);
stmt2Block
->
append
(
block
);
}
void
Compiler
::
visitWhile
(
While
*
p
)
{
auto
cond
=
make_shared
<
QLabel
>
(
"cond"
);
endBasicBlock
();
// jump <- loop -> cond
addQuad
<
QJump
>
(
cond
);
auto
beforeBlock
=
flushBasicBlock
();
// jump <- loop -> cond
// jump <- loop
auto
loop
=
make_shared
<
QLabel
>
(
"loop"
);
addQuad
(
loop
);
p
->
stmt_
->
accept
(
this
);
end
BasicBlock
();
// jump <- cond
auto
stmtsBlock
=
flush
BasicBlock
();
// jump <- cond
addQuad
(
cond
);
auto
var
=
evalExpr
(
p
->
expr_
);
endBasicBlock
();
// jump -> loop
addQuad
<
QJumpCond
>
(
loop
,
Op
::
Copy
,
var
);
auto
condBlock
=
flushBasicBlock
();
// jump -> loop
beforeBlock
->
append
(
condBlock
);
condBlock
->
append
(
stmtsBlock
);
condBlock
->
append
(
block
);
}
void
Compiler
::
visitSExp
(
SExp
*
p
)
{
...
...
@@ -431,3 +511,11 @@ void Compiler::visitForEach(ForEach *p) {
// TODO: implement
}
void
Compiler
::
visitBlk
(
Blk
*
blk
)
{
scope
->
currentBinding
=
blk
->
getBinding
();
Skeleton
::
visitBlk
(
blk
);
scope
->
currentBinding
=
scope
->
currentBinding
->
getParent
();
}
src/Compiler.h
View file @
9234e433
...
...
@@ -11,7 +11,6 @@
#include "Info.h"
#include "codeGen/Quadruple.h"
#include "codeGen/BasicBlock.h"
using
Op
=
Quadruple
::
Op
;
class
Compiler
:
public
Skeleton
{
...
...
@@ -27,8 +26,9 @@ private:
std
::
stringstream
buf
;
shared_ptr
<
Scope
>
scope
;
vector
<
VariablePtr
>
vars
;
vector
<
QuadruplePtr
>
quad
s
;
vector
<
BasicBlockPtr
>
block
s
;
Quadruple
::
Op
op
;
BasicBlockPtr
block
;
VariablePtr
lastVar
;
int
lineno
;
...
...
@@ -59,26 +59,29 @@ private:
return
ret
;
};
st
d
::
string
mangleFunctionName
(
FunctionInfoPtr
f
)
const
{
st
atic
std
::
string
mangleFunctionName
(
const
FunctionInfoPtr
&
f
)
{
if
(
auto
c
=
f
->
klass
.
lock
())
{
return
c
->
name
+
"::"
+
f
->
name
;
}
return
f
->
name
;
};
st
d
::
string
getVirtName
(
ClassInfoPtr
c
)
const
{
st
atic
std
::
string
getVirtName
(
const
ClassInfoPtr
&
c
)
{
return
c
->
name
+
":virt_table"
;
};
VariablePtr
alloc
(
VarInfoPtr
info
)
{
if
(
info
->
loc
&&
!
info
->
isInstanceVariable
()
)
{
VariablePtr
alloc
(
const
VarInfoPtr
&
info
)
{
if
(
info
->
loc
)
{
return
info
->
loc
;
}
auto
v
=
make_shared
<
Variable
>
(
info
);
vars
.
emplace_back
(
v
);
info
->
loc
=
v
;
if
(
!
info
->
isInstanceVariable
())
{
info
->
loc
=
v
;
}
return
v
;
}
template
<
typename
...
Args
>
VariablePtr
alloc
(
Args
...
args
)
{
auto
v
=
make_shared
<
Variable
>
(
args
...);
vars
.
emplace_back
(
v
);
...
...
@@ -86,22 +89,31 @@ private:
}
template
<
typename
T
,
typename
...
Args
>
QuadruplePtr
addQuad
(
Args
...
args
)
{
auto
quad
=
make_shared
<
T
>
(
args
...);
quad
->
lineno
=
lineno
;
quads
.
emplace_back
(
quad
);
return
quad
;
return
addQuad
(
make_shared
<
T
>
(
args
...));
}
QuadruplePtr
addQuad
(
QuadruplePtr
quad
)
{
quad
->
lineno
=
lineno
;
quads
.
emplace_back
(
quad
);
flushLastQuad
();
lastQuad
=
quad
;
return
quad
;
}
void
endBasicBlock
();
QuadruplePtr
lastQuad
;
void
flushLastQuad
()
{
if
(
lastQuad
)
{
block
->
quads
.
emplace_back
(
lastQuad
);
lastQuad
=
nullptr
;
}
}
BasicBlockPtr
flushBasicBlock
();
void
assign
(
Expr
*
lval
,
VariablePtr
val
);
VariableLayout
captureEnv
();
void
visitEVar
(
EVar
*
p
)
override
;
void
visitEIndexAcc
(
EIndexAcc
*
p
)
override
;
void
visitEClsMmbr
(
EClsMmbr
*
p
)
override
;
...
...
@@ -123,6 +135,7 @@ private:
void
visitBlk
(
Blk
*
p
)
override
;
void
visitInit
(
Init
*
p
)
override
;
void
visitAss
(
Ass
*
p
)
override
;
void
visitIncr
(
Incr
*
p
)
override
;
...
...
src/TypeDefs.h
View file @
9234e433
...
...
@@ -21,6 +21,7 @@ class Quadruple;
using
QuadruplePtr
=
shared_ptr
<
Quadruple
>
;
class
BasicBlock
;
using
BasicBlockPtr
=
shared_ptr
<
BasicBlock
>
;
class
VariableLayout
;
class
Visitable
;
class
Program
;
...
...
src/codeGen/BasicBlock.h
View file @
9234e433
...
...
@@ -6,12 +6,19 @@
#define ZAD2_BASICBLOCK_H
#include "../TypeDefs.h"
#include <vector>
#include <set>
using
namespace
std
;
class
BasicBlock
{
class
BasicBlock
:
public
std
::
enable_shared_from_this
<
BasicBlock
>
{
public:
vector
<
QuadruplePtr
>
quads
;
vector
<
BasicBlockPtr
>
in
,
out
;
set
<
VarInfoPtr
>
modifications
;
void
append
(
const
BasicBlockPtr
&
after
)
{
out
.
push_back
(
after
);
after
->
in
.
push_back
(
shared_from_this
());
}
};
...
...
src/codeGen/Variable.h
View file @
9234e433
...
...
@@ -6,8 +6,10 @@
#define ZAD2_VARIABLE_H
#include <utility>
#include <map>
#include "../TypeDefs.h"
#include "../Info.h"
class
Variable
:
std
::
enable_shared_from_this
<
Variable
>
{
public:
...
...
@@ -46,4 +48,29 @@ public:
}
};
class
VariableLayout
{
map
<
VarInfoPtr
,
pair
<
VariablePtr
,
VariablePtr
>>
changes
;
public:
void
add
(
const
VarInfoPtr
&
info
)
{
if
(
!
changes
.
count
(
info
))
{
changes
[
info
]
=
{
info
->
loc
,
nullptr
};
}
}
void
update
()
{
for
(
auto
p
:
changes
)
{
p
.
second
.
second
=
p
.
first
->
loc
;
}
}
void
revert
()
{
for
(
auto
p
:
changes
)
{
VarInfoPtr
info
=
p
.
first
;
info
->
loc
=
p
.
second
.
first
;
}
}
};
#endif //ZAD2_VARIABLE_H
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