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
5b9b463e
Commit
5b9b463e
authored
Jan 05, 2021
by
zygzagZ
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
SSA+CFG, quadruple code working
parent
9234e433
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
136 additions
and
35 deletions
+136
-35
Compiler.cpp
src/Compiler.cpp
+90
-26
Compiler.h
src/Compiler.h
+2
-0
TypeCheck.cpp
src/TypeCheck.cpp
+1
-1
BasicBlock.cpp
src/codeGen/BasicBlock.cpp
+15
-0
BasicBlock.h
src/codeGen/BasicBlock.h
+9
-1
Quadruple.h
src/codeGen/Quadruple.h
+8
-1
Variable.h
src/codeGen/Variable.h
+11
-6
No files found.
src/Compiler.cpp
View file @
5b9b463e
...
...
@@ -73,6 +73,10 @@ void Compiler::compileFunction(FunctionInfoPtr f) {
flushBasicBlock
();
block
=
nullptr
;
for
(
auto
b
:
blocks
)
{
b
->
finishQuads
();
}
int
label
=
1
;
for
(
auto
b
:
blocks
)
{
for
(
auto
q
:
b
->
quads
)
{
...
...
@@ -96,6 +100,9 @@ void Compiler::compileFunction(FunctionInfoPtr f) {
v
->
info
->
loc
=
nullptr
;
}
vars
.
clear
();
blocks
.
clear
();
scope
->
currentFunction
=
nullptr
;
}
...
...
@@ -132,10 +139,6 @@ implementacja detektora:
*/
BasicBlockPtr
Compiler
::
flushBasicBlock
()
{
for
(
const
auto
&
v
:
vars
)
{
if
(
v
->
info
)
v
->
info
->
loc
=
nullptr
;
}
auto
ret
=
block
;
if
(
block
)
{
blocks
.
emplace_back
(
block
);
...
...
@@ -397,7 +400,7 @@ void Compiler::assign(Expr* lval, VariablePtr val) {
auto
quad
=
dynamic_pointer_cast
<
QAccess
>
(
lastQuad
);
assert
(
quad
);
auto
loc
=
quad
->
access
;
block
->
quads
.
pop_back
()
;
lastQuad
=
nullptr
;
addQuad
<
QWrite
>
(
loc
,
val
);
}
else
{
// local variable - only assign
...
...
@@ -438,44 +441,70 @@ void Compiler::visitVRet(VRet *p) {
}
void
Compiler
::
visitCond
(
Cond
*
p
)
{
auto
var
=
evalExpr
(
p
->
expr_
);
auto
after
=
make_shared
<
QLabel
>
(
"end_if"
);
addQuad
<
QJumpCond
>
(
after
,
Op
::
Not
,
var
);
auto
beforeBlock
=
flushBasicBlock
();
// possible jump -> after
p
->
stmt_
->
accept
(
this
);
auto
innerBlock
=
flushBasicBlock
();
// possible jump <- cond
addQuad
(
after
);
beforeBlock
->
append
(
innerBlock
);
beforeBlock
->
append
(
block
);
innerBlock
->
append
(
block
);
compileCond
(
p
->
expr_
,
p
->
stmt_
,
nullptr
);
}
void
Compiler
::
visitCondElse
(
CondElse
*
p
)
{
compileCond
(
p
->
expr_
,
p
->
stmt_1
,
p
->
stmt_2
);
}
void
Compiler
::
compileCond
(
Expr
*
expr_
,
Stmt
*
stmt_1
,
Stmt
*
stmt_2
)
{
auto
elseBranch
=
make_shared
<
QLabel
>
(
"else"
);
auto
after
=
make_shared
<
QLabel
>
(
"end_else"
);
auto
var
=
evalExpr
(
p
->
expr_
);
auto
var
=
evalExpr
(
expr_
);
addQuad
<
QJumpCond
>
(
elseBranch
,
Op
::
Not
,
var
);
auto
beforeBlock
=
flushBasicBlock
();
// possible jump -> else
auto
env1
=
captureEnv
(),
env2
=
env1
;
p
->
stmt_1
->
accept
(
this
);
stmt_1
->
accept
(
this
);
addQuad
<
QJump
>
(
after
);
auto
stmt1Block
=
flushBasicBlock
();
// jump -> after
env1
.
capture
();
env1
.
revert
();
addQuad
(
elseBranch
);
p
->
stmt_2
->
accept
(
this
);
if
(
stmt_2
)
{
stmt_2
->
accept
(
this
);
}
auto
stmt2Block
=
flushBasicBlock
();
// jump <- cond
env2
.
capture
();
addQuad
(
after
);
beforeBlock
->
append
(
stmt1Block
);
beforeBlock
->
append
(
stmt2Block
);
stmt1Block
->
append
(
block
);
stmt2Block
->
append
(
block
);
merge2Envs
(
&
env1
,
stmt1Block
,
&
env2
,
stmt2Block
);
}
void
Compiler
::
merge2Envs
(
VariableLayout
*
env1
,
BasicBlockPtr
b1
,
VariableLayout
*
env2
,
BasicBlockPtr
b2
)
{
for
(
int
i
=
0
;
i
<
2
;
i
++
)
{
for
(
const
auto
&
p1
:
env1
->
changes
)
{
if
(
p1
.
second
.
first
==
p1
.
second
.
second
)
continue
;
auto
info
=
p1
.
first
;
auto
it
=
env2
->
changes
.
find
(
info
);
if
(
it
!=
env2
->
changes
.
end
())
{
auto
p2
=
*
it
;
// variables have been already merged
if
(
p1
.
second
.
first
==
p2
.
second
.
second
)
continue
;
info
->
loc
=
nullptr
;
auto
merged
=
alloc
(
info
);
// assign both versions to merged variable location
b1
->
addJumpInitQuad
(
make_shared
<
QAssign
>
(
merged
,
Op
::
Copy
,
p1
.
second
.
second
));
b2
->
addJumpInitQuad
(
make_shared
<
QAssign
>
(
merged
,
Op
::
Copy
,
p2
.
second
.
second
));
}
else
{
// copy changes to another block that did not touch var
b2
->
addJumpInitQuad
(
make_shared
<
QAssign
>
(
p1
.
second
.
second
,
Op
::
Copy
,
p1
.
second
.
first
));
}
}
swap
(
env1
,
env2
);
swap
(
b1
,
b2
);
}
}
void
Compiler
::
visitWhile
(
While
*
p
)
{
...
...
@@ -483,21 +512,56 @@ void Compiler::visitWhile(While *p) {
addQuad
<
QJump
>
(
cond
);
auto
beforeBlock
=
flushBasicBlock
();
// jump <- loop -> cond
// jump <- loop
auto
loop
=
make_shared
<
QLabel
>
(
"loop"
);
addQuad
(
loop
);
addQuad
(
loop
);
// jump <- loop
// hook env
auto
env1
=
captureEnv
();
// produce all variables hooks
for
(
const
auto
&
change
:
env1
.
changes
)
{
auto
info
=
change
.
first
;
info
->
loc
=
nullptr
;
alloc
(
info
);
}
// save hooks for later
env1
.
capture
();
// env2 starts with hooked variables
auto
env2
=
captureEnv
();
p
->
stmt_
->
accept
(
this
);
auto
stmts
Block
=
flushBasicBlock
();
// jump <- cond
auto
loop
Block
=
flushBasicBlock
();
// jump <- cond
addQuad
(
cond
);
// env2 contains changed hooks
env2
.
capture
();
// restore env1 pre-hook variables
env1
.
revert
();
for
(
auto
p
:
env2
.
changes
)
{
auto
info
=
p
.
first
;
auto
x1
=
p
.
second
.
first
;
auto
x2
=
p
.
second
.
second
;
// save hooks if used
info
->
loc
=
x1
;
// transition from pre-hook to hooked var [before -> cond]
beforeBlock
->
addJumpInitQuad
(
make_shared
<
QAssign
>
(
x1
,
Op
::
Copy
,
env1
.
changes
[
info
].
first
));
// transition from loop var to hooked var [loop -> cond]
loopBlock
->
addJumpInitQuad
(
make_shared
<
QAssign
>
(
x1
,
Op
::
Copy
,
x2
));
}
// expr uses pre-hook variables iff unused in loop
auto
var
=
evalExpr
(
p
->
expr_
);
addQuad
<
QJumpCond
>
(
loop
,
Op
::
Copy
,
var
);
auto
condBlock
=
flushBasicBlock
();
// jump -> loop
// next block is ready to use updated variables
beforeBlock
->
append
(
condBlock
);
condBlock
->
append
(
stmts
Block
);
condBlock
->
append
(
loop
Block
);
condBlock
->
append
(
block
);
}
...
...
src/Compiler.h
View file @
5b9b463e
...
...
@@ -113,6 +113,8 @@ private:
VariableLayout
captureEnv
();
void
merge2Envs
(
VariableLayout
*
env1
,
BasicBlockPtr
b1
,
VariableLayout
*
env2
,
BasicBlockPtr
b2
);
void
compileCond
(
Expr
*
cond
,
Stmt
*
stmt1
,
Stmt
*
stmt2
);
void
visitEVar
(
EVar
*
p
)
override
;
void
visitEIndexAcc
(
EIndexAcc
*
p
)
override
;
...
...
src/TypeCheck.cpp
View file @
5b9b463e
...
...
@@ -239,7 +239,7 @@ void TypeCheck::visitForEach(ForEach *for_each)
{
BindingPtr
binding
=
make_shared
<
Binding
>
(
scope
->
currentBinding
);
for_each
->
type_
->
accept
(
this
);
Array
expect
(
for_each
->
type_
);
Array
expect
(
for_each
->
type_
->
clone
()
);
auto
arrType
=
evalExpr
<
Array
>
(
for_each
->
expr_
);
if
(
!
expect
.
isEqual
(
&*
arrType
,
true
))
{
throw
InvalidTypeError
(
expect
,
{
arrType
},
for_each
->
expr_
);
...
...
src/codeGen/BasicBlock.cpp
View file @
5b9b463e
...
...
@@ -3,3 +3,18 @@
//
#include "BasicBlock.h"
#include "Quadruple.h"
void
BasicBlock
::
finishQuads
()
{
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
);
}
afterInit
.
clear
();
}
src/codeGen/BasicBlock.h
View file @
5b9b463e
...
...
@@ -12,13 +12,21 @@ using namespace std;
class
BasicBlock
:
public
std
::
enable_shared_from_this
<
BasicBlock
>
{
public:
BasicBlock
()
=
default
;;
vector
<
QuadruplePtr
>
quads
;
vector
<
QuadruplePtr
>
afterInit
;
vector
<
BasicBlockPtr
>
in
,
out
;
set
<
VarInfoPtr
>
modifications
;
void
append
(
const
BasicBlockPtr
&
after
)
{
out
.
push_back
(
after
);
after
->
in
.
push_back
(
shared_from_this
());
}
void
addJumpInitQuad
(
const
QuadruplePtr
&
q
)
{
afterInit
.
push_back
(
q
);
}
void
finishQuads
();
};
...
...
src/codeGen/Quadruple.h
View file @
5b9b463e
...
...
@@ -11,7 +11,7 @@ static const std::string opNames[] = { "_U", "-", "!", "", "_UE",
"_B"
,
"+"
,
"-"
,
"*"
,
"/"
,
"%"
,
"&"
,
"|"
,
"^"
,
"_BE"
,
"_C"
,
"<"
,
"<="
,
"=="
,
"!="
,
">="
,
">"
,
"_CE"
};
class
Quadruple
:
std
::
enable_shared_from_this
<
Quadruple
>
{
class
Quadruple
{
public:
class
Op
{
public:
...
...
@@ -42,6 +42,7 @@ public:
virtual
~
Quadruple
()
{};
virtual
std
::
string
toString
()
const
{
return
to_string
(
lineno
)
+
"
\t
"
;
};
virtual
bool
isFinal
()
const
{
return
false
;
}
};
class
QWriteVar
:
public
Quadruple
{
...
...
@@ -84,6 +85,8 @@ public:
std
::
string
toString
()
const
override
{
return
Quadruple
::
toString
()
+
"jump "
+
target
->
label
;
}
virtual
bool
isFinal
()
const
{
return
true
;
}
};
class
QJumpCond
:
public
QJump
{
...
...
@@ -103,6 +106,8 @@ public:
else
return
Quadruple
::
toString
()
+
"jump
\"
"
+
target
->
label
+
"
\"
if "
+
left
->
name
+
" "
+
Op
::
name
(
op
)
+
" "
+
right
->
name
;
}
virtual
bool
isFinal
()
const
{
return
true
;
}
};
class
QParam
:
public
Quadruple
{
...
...
@@ -150,6 +155,8 @@ public:
return
Quadruple
::
toString
()
+
"
\t
return"
;
}
}
virtual
bool
isFinal
()
const
{
return
true
;
}
};
class
QAccess
:
public
QWriteVar
{
...
...
src/codeGen/Variable.h
View file @
5b9b463e
...
...
@@ -50,23 +50,28 @@ public:
class
VariableLayout
{
map
<
VarInfoPtr
,
pair
<
VariablePtr
,
VariablePtr
>>
changes
;
public:
map
<
VarInfoPtr
,
pair
<
VariablePtr
,
VariablePtr
>>
changes
;
void
add
(
const
VarInfoPtr
&
info
)
{
if
(
!
changes
.
count
(
info
))
{
if
(
!
changes
.
count
(
info
)
&&
info
->
loc
)
{
changes
[
info
]
=
{
info
->
loc
,
nullptr
};
}
}
void
updat
e
()
{
for
(
auto
p
:
changes
)
{
void
captur
e
()
{
for
(
auto
&
p
:
changes
)
{
p
.
second
.
second
=
p
.
first
->
loc
;
}
for
(
auto
it
=
changes
.
begin
();
it
!=
changes
.
end
();
)
{
auto
pit
=
it
;
it
++
;
if
(
pit
->
second
.
first
==
pit
->
second
.
second
)
changes
.
erase
(
pit
);
}
}
void
revert
()
{
for
(
auto
p
:
changes
)
{
for
(
const
auto
&
p
:
changes
)
{
VarInfoPtr
info
=
p
.
first
;
info
->
loc
=
p
.
second
.
first
;
}
...
...
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