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) {
...
@@ -73,6 +73,10 @@ void Compiler::compileFunction(FunctionInfoPtr f) {
flushBasicBlock
();
flushBasicBlock
();
block
=
nullptr
;
block
=
nullptr
;
for
(
auto
b
:
blocks
)
{
b
->
finishQuads
();
}
int
label
=
1
;
int
label
=
1
;
for
(
auto
b
:
blocks
)
{
for
(
auto
b
:
blocks
)
{
for
(
auto
q
:
b
->
quads
)
{
for
(
auto
q
:
b
->
quads
)
{
...
@@ -96,6 +100,9 @@ void Compiler::compileFunction(FunctionInfoPtr f) {
...
@@ -96,6 +100,9 @@ void Compiler::compileFunction(FunctionInfoPtr f) {
v
->
info
->
loc
=
nullptr
;
v
->
info
->
loc
=
nullptr
;
}
}
vars
.
clear
();
blocks
.
clear
();
scope
->
currentFunction
=
nullptr
;
scope
->
currentFunction
=
nullptr
;
}
}
...
@@ -132,10 +139,6 @@ implementacja detektora:
...
@@ -132,10 +139,6 @@ implementacja detektora:
*/
*/
BasicBlockPtr
Compiler
::
flushBasicBlock
()
{
BasicBlockPtr
Compiler
::
flushBasicBlock
()
{
for
(
const
auto
&
v
:
vars
)
{
if
(
v
->
info
)
v
->
info
->
loc
=
nullptr
;
}
auto
ret
=
block
;
auto
ret
=
block
;
if
(
block
)
{
if
(
block
)
{
blocks
.
emplace_back
(
block
);
blocks
.
emplace_back
(
block
);
...
@@ -397,7 +400,7 @@ void Compiler::assign(Expr* lval, VariablePtr val) {
...
@@ -397,7 +400,7 @@ void Compiler::assign(Expr* lval, VariablePtr val) {
auto
quad
=
dynamic_pointer_cast
<
QAccess
>
(
lastQuad
);
auto
quad
=
dynamic_pointer_cast
<
QAccess
>
(
lastQuad
);
assert
(
quad
);
assert
(
quad
);
auto
loc
=
quad
->
access
;
auto
loc
=
quad
->
access
;
block
->
quads
.
pop_back
()
;
lastQuad
=
nullptr
;
addQuad
<
QWrite
>
(
loc
,
val
);
addQuad
<
QWrite
>
(
loc
,
val
);
}
else
{
}
else
{
// local variable - only assign
// local variable - only assign
...
@@ -438,44 +441,70 @@ void Compiler::visitVRet(VRet *p) {
...
@@ -438,44 +441,70 @@ void Compiler::visitVRet(VRet *p) {
}
}
void
Compiler
::
visitCond
(
Cond
*
p
)
{
void
Compiler
::
visitCond
(
Cond
*
p
)
{
auto
var
=
evalExpr
(
p
->
expr_
);
compileCond
(
p
->
expr_
,
p
->
stmt_
,
nullptr
);
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
);
}
}
void
Compiler
::
visitCondElse
(
CondElse
*
p
)
{
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
elseBranch
=
make_shared
<
QLabel
>
(
"else"
);
auto
after
=
make_shared
<
QLabel
>
(
"end_else"
);
auto
after
=
make_shared
<
QLabel
>
(
"end_else"
);
auto
var
=
evalExpr
(
p
->
expr_
);
auto
var
=
evalExpr
(
expr_
);
addQuad
<
QJumpCond
>
(
elseBranch
,
Op
::
Not
,
var
);
addQuad
<
QJumpCond
>
(
elseBranch
,
Op
::
Not
,
var
);
auto
beforeBlock
=
flushBasicBlock
();
// possible jump -> else
auto
beforeBlock
=
flushBasicBlock
();
// possible jump -> else
auto
env1
=
captureEnv
(),
env2
=
env1
;
p
->
stmt_1
->
accept
(
this
);
stmt_1
->
accept
(
this
);
addQuad
<
QJump
>
(
after
);
addQuad
<
QJump
>
(
after
);
auto
stmt1Block
=
flushBasicBlock
();
// jump -> after
auto
stmt1Block
=
flushBasicBlock
();
// jump -> after
env1
.
capture
();
env1
.
revert
();
addQuad
(
elseBranch
);
addQuad
(
elseBranch
);
p
->
stmt_2
->
accept
(
this
);
if
(
stmt_2
)
{
stmt_2
->
accept
(
this
);
}
auto
stmt2Block
=
flushBasicBlock
();
// jump <- cond
auto
stmt2Block
=
flushBasicBlock
();
// jump <- cond
env2
.
capture
();
addQuad
(
after
);
addQuad
(
after
);
beforeBlock
->
append
(
stmt1Block
);
beforeBlock
->
append
(
stmt1Block
);
beforeBlock
->
append
(
stmt2Block
);
beforeBlock
->
append
(
stmt2Block
);
stmt1Block
->
append
(
block
);
stmt1Block
->
append
(
block
);
stmt2Block
->
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
)
{
void
Compiler
::
visitWhile
(
While
*
p
)
{
...
@@ -483,21 +512,56 @@ void Compiler::visitWhile(While *p) {
...
@@ -483,21 +512,56 @@ void Compiler::visitWhile(While *p) {
addQuad
<
QJump
>
(
cond
);
addQuad
<
QJump
>
(
cond
);
auto
beforeBlock
=
flushBasicBlock
();
// jump <- loop -> cond
auto
beforeBlock
=
flushBasicBlock
();
// jump <- loop -> cond
// jump <- loop
auto
loop
=
make_shared
<
QLabel
>
(
"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
);
p
->
stmt_
->
accept
(
this
);
auto
stmts
Block
=
flushBasicBlock
();
// jump <- cond
auto
loop
Block
=
flushBasicBlock
();
// jump <- cond
addQuad
(
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_
);
auto
var
=
evalExpr
(
p
->
expr_
);
addQuad
<
QJumpCond
>
(
loop
,
Op
::
Copy
,
var
);
addQuad
<
QJumpCond
>
(
loop
,
Op
::
Copy
,
var
);
auto
condBlock
=
flushBasicBlock
();
// jump -> loop
auto
condBlock
=
flushBasicBlock
();
// jump -> loop
// next block is ready to use updated variables
beforeBlock
->
append
(
condBlock
);
beforeBlock
->
append
(
condBlock
);
condBlock
->
append
(
stmts
Block
);
condBlock
->
append
(
loop
Block
);
condBlock
->
append
(
block
);
condBlock
->
append
(
block
);
}
}
...
...
src/Compiler.h
View file @
5b9b463e
...
@@ -113,6 +113,8 @@ private:
...
@@ -113,6 +113,8 @@ private:
VariableLayout
captureEnv
();
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
visitEVar
(
EVar
*
p
)
override
;
void
visitEIndexAcc
(
EIndexAcc
*
p
)
override
;
void
visitEIndexAcc
(
EIndexAcc
*
p
)
override
;
...
...
src/TypeCheck.cpp
View file @
5b9b463e
...
@@ -239,7 +239,7 @@ void TypeCheck::visitForEach(ForEach *for_each)
...
@@ -239,7 +239,7 @@ void TypeCheck::visitForEach(ForEach *for_each)
{
{
BindingPtr
binding
=
make_shared
<
Binding
>
(
scope
->
currentBinding
);
BindingPtr
binding
=
make_shared
<
Binding
>
(
scope
->
currentBinding
);
for_each
->
type_
->
accept
(
this
);
for_each
->
type_
->
accept
(
this
);
Array
expect
(
for_each
->
type_
);
Array
expect
(
for_each
->
type_
->
clone
()
);
auto
arrType
=
evalExpr
<
Array
>
(
for_each
->
expr_
);
auto
arrType
=
evalExpr
<
Array
>
(
for_each
->
expr_
);
if
(
!
expect
.
isEqual
(
&*
arrType
,
true
))
{
if
(
!
expect
.
isEqual
(
&*
arrType
,
true
))
{
throw
InvalidTypeError
(
expect
,
{
arrType
},
for_each
->
expr_
);
throw
InvalidTypeError
(
expect
,
{
arrType
},
for_each
->
expr_
);
...
...
src/codeGen/BasicBlock.cpp
View file @
5b9b463e
...
@@ -3,3 +3,18 @@
...
@@ -3,3 +3,18 @@
//
//
#include "BasicBlock.h"
#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;
...
@@ -12,13 +12,21 @@ using namespace std;
class
BasicBlock
:
public
std
::
enable_shared_from_this
<
BasicBlock
>
{
class
BasicBlock
:
public
std
::
enable_shared_from_this
<
BasicBlock
>
{
public:
public:
BasicBlock
()
=
default
;;
vector
<
QuadruplePtr
>
quads
;
vector
<
QuadruplePtr
>
quads
;
vector
<
QuadruplePtr
>
afterInit
;
vector
<
BasicBlockPtr
>
in
,
out
;
vector
<
BasicBlockPtr
>
in
,
out
;
set
<
VarInfoPtr
>
modifications
;
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
());
}
}
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",
...
@@ -11,7 +11,7 @@ static const std::string opNames[] = { "_U", "-", "!", "", "_UE",
"_B"
,
"+"
,
"-"
,
"*"
,
"/"
,
"%"
,
"&"
,
"|"
,
"^"
,
"_BE"
,
"_B"
,
"+"
,
"-"
,
"*"
,
"/"
,
"%"
,
"&"
,
"|"
,
"^"
,
"_BE"
,
"_C"
,
"<"
,
"<="
,
"=="
,
"!="
,
">="
,
">"
,
"_CE"
};
"_C"
,
"<"
,
"<="
,
"=="
,
"!="
,
">="
,
">"
,
"_CE"
};
class
Quadruple
:
std
::
enable_shared_from_this
<
Quadruple
>
{
class
Quadruple
{
public:
public:
class
Op
{
class
Op
{
public:
public:
...
@@ -42,6 +42,7 @@ public:
...
@@ -42,6 +42,7 @@ public:
virtual
~
Quadruple
()
{};
virtual
~
Quadruple
()
{};
virtual
std
::
string
toString
()
const
{
return
to_string
(
lineno
)
+
"
\t
"
;
};
virtual
std
::
string
toString
()
const
{
return
to_string
(
lineno
)
+
"
\t
"
;
};
virtual
bool
isFinal
()
const
{
return
false
;
}
};
};
class
QWriteVar
:
public
Quadruple
{
class
QWriteVar
:
public
Quadruple
{
...
@@ -84,6 +85,8 @@ public:
...
@@ -84,6 +85,8 @@ public:
std
::
string
toString
()
const
override
{
std
::
string
toString
()
const
override
{
return
Quadruple
::
toString
()
+
"jump "
+
target
->
label
;
return
Quadruple
::
toString
()
+
"jump "
+
target
->
label
;
}
}
virtual
bool
isFinal
()
const
{
return
true
;
}
};
};
class
QJumpCond
:
public
QJump
{
class
QJumpCond
:
public
QJump
{
...
@@ -103,6 +106,8 @@ public:
...
@@ -103,6 +106,8 @@ public:
else
else
return
Quadruple
::
toString
()
+
"jump
\"
"
+
target
->
label
+
"
\"
if "
+
left
->
name
+
" "
+
Op
::
name
(
op
)
+
" "
+
right
->
name
;
return
Quadruple
::
toString
()
+
"jump
\"
"
+
target
->
label
+
"
\"
if "
+
left
->
name
+
" "
+
Op
::
name
(
op
)
+
" "
+
right
->
name
;
}
}
virtual
bool
isFinal
()
const
{
return
true
;
}
};
};
class
QParam
:
public
Quadruple
{
class
QParam
:
public
Quadruple
{
...
@@ -150,6 +155,8 @@ public:
...
@@ -150,6 +155,8 @@ public:
return
Quadruple
::
toString
()
+
"
\t
return"
;
return
Quadruple
::
toString
()
+
"
\t
return"
;
}
}
}
}
virtual
bool
isFinal
()
const
{
return
true
;
}
};
};
class
QAccess
:
public
QWriteVar
{
class
QAccess
:
public
QWriteVar
{
...
...
src/codeGen/Variable.h
View file @
5b9b463e
...
@@ -50,23 +50,28 @@ public:
...
@@ -50,23 +50,28 @@ public:
class
VariableLayout
{
class
VariableLayout
{
map
<
VarInfoPtr
,
pair
<
VariablePtr
,
VariablePtr
>>
changes
;
public:
public:
map
<
VarInfoPtr
,
pair
<
VariablePtr
,
VariablePtr
>>
changes
;
void
add
(
const
VarInfoPtr
&
info
)
{
void
add
(
const
VarInfoPtr
&
info
)
{
if
(
!
changes
.
count
(
info
))
{
if
(
!
changes
.
count
(
info
)
&&
info
->
loc
)
{
changes
[
info
]
=
{
info
->
loc
,
nullptr
};
changes
[
info
]
=
{
info
->
loc
,
nullptr
};
}
}
}
}
void
updat
e
()
{
void
captur
e
()
{
for
(
auto
p
:
changes
)
{
for
(
auto
&
p
:
changes
)
{
p
.
second
.
second
=
p
.
first
->
loc
;
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
()
{
void
revert
()
{
for
(
auto
p
:
changes
)
{
for
(
const
auto
&
p
:
changes
)
{
VarInfoPtr
info
=
p
.
first
;
VarInfoPtr
info
=
p
.
first
;
info
->
loc
=
p
.
second
.
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