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
46d82364
Commit
46d82364
authored
Jan 12, 2021
by
zygzagZ
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Tests 1-17 work
parent
22f00483
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
93 additions
and
59 deletions
+93
-59
Compiler.cpp
src/Compiler.cpp
+36
-27
Compiler.h
src/Compiler.h
+2
-0
Info.h
src/Info.h
+3
-3
Quadruple.h
src/codeGen/Quadruple.h
+7
-2
QuadrupleGenerator.cpp
src/codeGen/QuadrupleGenerator.cpp
+17
-15
QuadrupleGenerator.h
src/codeGen/QuadrupleGenerator.h
+6
-2
RegisterAllocator.cpp
src/codeGen/RegisterAllocator.cpp
+7
-3
Variable.h
src/codeGen/Variable.h
+3
-0
test.sh
test.sh
+12
-7
No files found.
src/Compiler.cpp
View file @
46d82364
...
...
@@ -274,7 +274,7 @@ void Compiler::generatePhiXCHG(const map<VariablePtr, VariablePtr> &varMap) {
const
auto
&
loc
=
phiVars
.
first
,
&
val
=
phiVars
.
second
;
auto
ri
=
Register
(
loc
),
rj
=
Register
(
val
);
if
(
loc
->
constExpr
)
continue
;
if
(
ri
==
0
||
val
->
constExpr
)
{
// we need to do do memory stores now
if
(
ri
==
0
)
{
// we need to do do memory stores now
if
(
ri
==
0
&&
rj
==
0
&&
!
val
->
constExpr
)
{
assert
(
loc
->
info
==
val
->
info
);
}
else
{
...
...
@@ -311,7 +311,7 @@ void Compiler::generatePhiXCHG(const map<VariablePtr, VariablePtr> &varMap) {
for
(
const
auto
&
phiVars
:
varMap
)
{
const
auto
&
i
=
phiVars
.
first
,
&
j
=
phiVars
.
second
;
auto
ri
=
Register
(
i
),
rj
=
Register
(
j
);
if
(
ri
!=
0
&&
rj
==
0
)
{
if
(
ri
!=
0
&&
(
rj
==
0
||
j
->
constExpr
)
)
{
append
(
"MOVL"
,
getRef
(
j
),
ri
);
}
}
...
...
@@ -326,32 +326,39 @@ void Compiler::generateQJump(QJump &q) {
append
(
"JMP"
,
getBlockLabelText
(
q
.
target
));
}
Op
Compiler
::
generateCmp
(
const
VariablePtr
&
l
,
Op
op
,
const
VariablePtr
&
r
)
{
auto
regL
=
Register
(
l
),
regR
=
Register
(
r
);
auto
locL
=
getRef
(
l
);
auto
locR
=
getRef
(
r
);
if
(
regL
==
0
&&
regR
==
0
)
{
append
(
"MOVL"
,
locR
,
regR
);
locR
=
regR
;
}
else
if
(
regL
!=
0
&&
regR
==
0
)
{
// left is in register but right is not - swap operands
// as right needs to be a register
swap
(
locL
,
locR
);
assert
(
op
.
kind
()
==
Op
::
CMP
);
op
=
op
.
rot
();
// we swapped operands
}
append
(
"CMP"
,
locL
,
locR
);
if
(
op
.
kind
()
==
Op
::
CMP
)
op
=
op
.
rot
();
// compare has different syntax in AT&T
return
op
;
}
void
Compiler
::
generateQJumpCond
(
QJumpCond
&
q
)
{
auto
thisBlock
=
q
.
block
;
auto
tgBlock
=
q
.
target
->
block
;
const
auto
&
map
=
tgBlock
->
getPhiMapping
(
thisBlock
);
for
(
const
auto
&
phiVars
:
map
)
{
// if (Register(phiVars.first) != Register(phiVars.second)) {
throw
runtime_error
(
"Unimplemented phi CondJump register XCHG
"
);
buf
<<
(
"// Unimplemented phi CondJump register XCHG
\n
"
);
// }
}
auto
op
=
q
.
op
;
if
(
q
.
left
)
{
// 2 args
assert
(
!
q
.
left
->
constExpr
||
!
q
.
right
->
constExpr
);
auto
regL
=
Register
(
q
.
left
),
regR
=
Register
(
q
.
right
);
auto
locL
=
getRef
(
q
.
left
);
auto
locR
=
getRef
(
q
.
right
);
if
(
regL
==
0
&&
regR
==
0
)
{
append
(
"MOVL"
,
locR
,
regR
);
locR
=
regR
;
}
else
if
(
regL
!=
0
&&
regR
==
0
)
{
// left is in register but right is not - swap operands
// as right needs to be a register
swap
(
locL
,
locR
);
assert
(
op
.
kind
()
==
Op
::
CMP
);
op
=
op
.
rot
();
// we swapped operands
}
append
(
"CMP"
,
locL
,
locR
);
op
=
generateCmp
(
q
.
left
,
op
,
q
.
right
);
}
else
{
// 1 arg
if
(
q
.
right
->
constExpr
)
{
if
((
op
==
Op
::
Not
)
^
q
.
right
->
val
)
{
...
...
@@ -360,11 +367,10 @@ void Compiler::generateQJumpCond(QJumpCond &q) {
return
;
}
auto
tg
=
moveToAnyRegister
(
q
.
right
);
append
(
"CMP"
,
tg
,
tg
);
append
(
"TEST"
,
tg
,
tg
);
op
=
op
.
neg
();
}
if
(
op
.
kind
()
!=
Op
::
CMP
&&
op
.
kind
()
!=
Op
::
UNARY
)
throw
runtime_error
(
"Unexpected operator in compare"
);
if
(
op
.
kind
()
==
Op
::
CMP
)
op
=
op
.
rot
();
// compare has different syntax in AT&T
string
operand
=
getOpName
(
op
);
// getOpName returns SETZ, SETNE, SET*, replace it to JMP
operand
.
replace
(
0
,
3
,
"J"
);
...
...
@@ -441,14 +447,17 @@ void Compiler::generateQAssign(QAssign &q) {
if
(
backupEdx
&&
edxAlive
)
append
(
"MOVL"
,
"-4(%esp)"
,
edx
);
return
;
}
else
if
(
q
.
op
.
kind
()
==
Op
::
CMP
)
{
auto
loc
=
getRef
(
i
);
if
(
Register
(
i
)
==
0
&&
Register
(
j
)
==
0
)
{
moveTo
(
i
,
0
);
loc
=
"%eax"
;
auto
op
=
generateCmp
(
i
,
q
.
op
,
j
);
if
((
int
)
tg
<
4
)
{
// eax - edx
append
(
"MOVL"
,
"$0"
,
tg
);
string
s
=
"%AL"
;
s
[
1
]
=
((
string
)
tg
)[
2
];
append
(
op
,
s
);
}
else
{
append
(
"MOVL"
,
"$0"
,
"%EAX"
);
append
(
op
,
"%AL"
);
append
(
"MOVL"
,
"%EAX"
,
tg
);
}
append
(
"CMPL"
,
loc
,
getRef
(
j
));
append
(
q
.
op
,
tg
);
}
else
{
assert
(
q
.
op
.
kind
()
==
Op
::
BINARY
);
bool
swapped
=
false
;
...
...
src/Compiler.h
View file @
46d82364
...
...
@@ -69,6 +69,8 @@ public:
void
generateQPhi
(
QPhi
&
q
);
void
generateQBlockEnd
(
QBlockEnd
&
q
);
Op
generateCmp
(
const
VariablePtr
&
l
,
Op
op
,
const
VariablePtr
&
r
);
static
std
::
string
mangleFunctionName
(
const
FunctionInfoPtr
&
f
)
{
if
(
auto
c
=
f
->
klass
.
lock
())
{
return
c
->
name
+
"::"
+
f
->
name
;
...
...
src/Info.h
View file @
46d82364
...
...
@@ -58,11 +58,11 @@ public:
InfoList
<
ClassInfo
>
classes
;
InfoList
<
FunctionInfo
>
functions
;
weak
_ptr
<
Binding
>
parent
;
shared
_ptr
<
Binding
>
parent
;
Binding
(
BindingPtr
parent
=
nullptr
);
virtual
~
Binding
()
{};
BindingPtr
getParent
()
{
return
parent
.
lock
()
;
};
BindingPtr
getParent
()
{
return
parent
;
};
};
class
ClassInfo
:
public
VarInfo
,
public
Binding
...
...
@@ -72,7 +72,7 @@ public:
ClassInfo
(
PIdent
*
ident
,
BindingPtr
parent
=
nullptr
);
virtual
string
kind
()
const
{
return
"class"
;
}
ClassInfoPtr
getClassParent
()
{
return
dynamic_pointer_cast
<
ClassInfo
>
(
parent
.
lock
()
);
};
ClassInfoPtr
getClassParent
()
{
return
dynamic_pointer_cast
<
ClassInfo
>
(
parent
);
};
size_t
calculateSize
();
size_t
size
,
functionCount
;
};
...
...
src/codeGen/Quadruple.h
View file @
46d82364
...
...
@@ -2,6 +2,7 @@
#define ZAD2_QUAD_H
#include <string>
#include <utility>
#include <cassert>
#include "../Info.h"
#include "Variable.h"
...
...
@@ -112,8 +113,12 @@ public:
Op
op
;
vector
<
VariablePtr
>
args
;
QAssign
(
VariablePtr
loc
,
Op
op
,
vector
<
VariablePtr
>
list
)
:
QWriteVar
(
std
::
move
(
loc
)),
op
(
op
),
args
(
std
::
move
(
list
))
{};
QAssign
(
VariablePtr
loc
,
VariablePtr
l
,
Op
op
,
VariablePtr
r
)
:
QWriteVar
(
std
::
move
(
loc
)),
op
(
op
),
args
({
std
::
move
(
l
),
std
::
move
(
r
)})
{};
QAssign
(
VariablePtr
loc
,
Op
op
,
const
vector
<
VariablePtr
>&
list
)
:
QWriteVar
(
std
::
move
(
loc
)),
op
(
op
)
{
for
(
const
auto
&
i
:
list
)
if
(
i
)
args
.
emplace_back
(
i
);
};
QAssign
(
VariablePtr
loc
,
VariablePtr
l
,
Op
op
,
VariablePtr
r
)
:
QAssign
(
std
::
move
(
loc
),
op
,
{
std
::
move
(
l
),
std
::
move
(
r
)})
{
};
QAssign
(
VariablePtr
loc
,
Op
op
,
VariablePtr
x
)
:
QWriteVar
(
std
::
move
(
loc
)),
op
(
op
),
args
({
std
::
move
(
x
)})
{};
std
::
string
toString
()
const
override
{
...
...
src/codeGen/QuadrupleGenerator.cpp
View file @
46d82364
...
...
@@ -102,7 +102,12 @@ VariableLayout QuadrupleGenerator::captureEnv() {
/// expressions
void
QuadrupleGenerator
::
visitEVar
(
EVar
*
p
)
{
lastVar
=
alloc
(
p
->
pident_
->
var
.
lock
());
auto
var
=
p
->
pident_
->
var
.
lock
();
lastVar
=
alloc
(
var
);
Bool
b
;
if
(
var
->
type
->
isEqual
(
&
b
))
{
addLastVarCondJump
(
nullptr
,
Op
::
Copy
,
lastVar
);
}
}
void
QuadrupleGenerator
::
visitELitInt
(
ELitInt
*
p
)
{
...
...
@@ -111,12 +116,12 @@ void QuadrupleGenerator::visitELitInt(ELitInt *p) {
void
QuadrupleGenerator
::
visitELitTrue
(
ELitTrue
*
p
)
{
lastVar
=
alloc
(
1
);
if
(
labelTrue
)
addQuad
<
QJump
>
(
labelTrue
);
//
if (labelTrue) addQuad<QJump>(labelTrue);
}
void
QuadrupleGenerator
::
visitELitFalse
(
ELitFalse
*
p
)
{
lastVar
=
alloc
(
0
);
if
(
labelFalse
)
addQuad
<
QJump
>
(
labelFalse
);
//
if (labelFalse) addQuad<QJump>(labelFalse);
}
void
QuadrupleGenerator
::
visitEString
(
EString
*
p
)
{
...
...
@@ -131,26 +136,22 @@ void QuadrupleGenerator::visitNullCast(NullCast *p) {
void
QuadrupleGenerator
::
visitNeg
(
Neg
*
p
)
{
auto
var
=
evalExpr
(
p
->
expr_
);
lastVar
=
alloc
();
lastVar
=
alloc
(
var
);
addQuad
<
QAssign
>
(
lastVar
,
Op
::
Neg
,
var
);
if
((
lastVar
->
constExpr
=
var
->
constExpr
))
{
lastVar
->
val
=
-
var
->
val
;
}
lastVar
->
val
=
-
var
->
val
;
}
void
QuadrupleGenerator
::
visitNot
(
Not
*
p
)
{
auto
var
=
evalJump
(
p
->
expr_
,
labelFalse
,
labelTrue
);
lastVar
=
alloc
();
lastVar
=
alloc
(
var
);
addQuad
<
QAssign
>
(
lastVar
,
Op
::
Not
,
var
);
if
((
lastVar
->
constExpr
=
var
->
constExpr
))
{
lastVar
->
val
=
!
var
->
val
;
}
lastVar
->
val
=
!
var
->
val
;
}
void
QuadrupleGenerator
::
visitEMul
(
EMul
*
p
)
{
auto
l
=
evalExpr
(
p
->
expr_1
);
auto
r
=
evalExpr
(
p
->
expr_2
);
lastVar
=
alloc
();
lastVar
=
alloc
(
l
);
p
->
mulop_
->
accept
(
this
);
addQuad
<
QAssign
>
(
lastVar
,
l
,
op
,
r
);
if
((
lastVar
->
constExpr
=
l
->
constExpr
&&
r
->
constExpr
))
{
...
...
@@ -168,7 +169,7 @@ void QuadrupleGenerator::visitEMul(EMul *p) {
void
QuadrupleGenerator
::
visitEAdd
(
EAdd
*
p
)
{
auto
l
=
evalExpr
(
p
->
expr_1
);
auto
r
=
evalExpr
(
p
->
expr_2
);
lastVar
=
alloc
();
lastVar
=
alloc
(
l
);
p
->
addop_
->
accept
(
this
);
Str
s
;
if
(
p
->
type
->
isEqual
(
&
s
))
{
...
...
@@ -176,6 +177,7 @@ void QuadrupleGenerator::visitEAdd(EAdd *p) {
addQuad
<
QParam
>
(
r
,
1
,
call
);
addQuad
<
QParam
>
(
l
,
2
,
call
);
addQuad
(
call
);
lastVar
->
constExpr
=
false
;
return
;
}
...
...
@@ -191,7 +193,7 @@ void QuadrupleGenerator::visitEAdd(EAdd *p) {
void
QuadrupleGenerator
::
visitERel
(
ERel
*
p
)
{
auto
l
=
evalExpr
(
p
->
expr_1
);
auto
r
=
evalExpr
(
p
->
expr_2
);
lastVar
=
alloc
();
lastVar
=
alloc
(
l
);
p
->
relop_
->
accept
(
this
);
if
((
lastVar
->
constExpr
=
l
->
constExpr
&&
r
->
constExpr
))
{
if
(
op
==
Op
::
LT
)
...
...
@@ -381,7 +383,7 @@ void QuadrupleGenerator::visitEApp(EApp *p) {
throw
ParseError
(
"Unimplemented EApp instantiation (neither EClsMmbr nor EVar"
,
p
);
}
auto
ret
=
alloc
();
auto
ret
=
alloc
(
funType
->
type_
->
clone
()
);
auto
call
=
make_shared
<
QCall
>
(
ret
,
info
,
p
->
listexpr_
->
size
(),
self
);
int
i
=
0
;
for
(
auto
param
=
p
->
listexpr_
->
rbegin
();
param
!=
p
->
listexpr_
->
rend
();
param
++
)
{
...
...
src/codeGen/QuadrupleGenerator.h
View file @
46d82364
...
...
@@ -101,7 +101,8 @@ private:
void
addLastVarCondJump
(
const
VariablePtr
&
l
,
Quadruple
::
Op
op
,
const
VariablePtr
&
r
)
{
if
(
labelTrue
&&
labelFalse
)
{
addQuad
<
QJumpCond
>
(
labelTrue
,
l
,
op
,
r
);
addQuad
<
QAssign
>
(
lastVar
,
l
,
op
,
r
);
// testy jump assign
// addQuad<QAssign>(lastVar, l, op, r);
addQuad
<
QJump
>
(
labelFalse
);
return
;
}
else
if
(
labelTrue
)
{
...
...
@@ -110,7 +111,10 @@ private:
}
else
if
(
labelFalse
)
{
addQuad
<
QJumpCond
>
(
labelFalse
,
l
,
op
.
neg
(),
r
);
lastVar
=
alloc
(
1
);
}
else
return
;
}
else
{
// testy jump assign
// return;
}
addQuad
<
QAssign
>
(
lastVar
,
l
,
op
,
r
);
}
...
...
src/codeGen/RegisterAllocator.cpp
View file @
46d82364
...
...
@@ -6,11 +6,10 @@
void
RegisterAllocator
::
analyseLive
()
{
for
(
const
auto
&
v
:
vars
)
{
if
(
!
v
->
info
)
continue
;
for
(
const
auto
&
q
:
v
->
writes
)
{
q
->
block
->
flow
.
addDef
(
v
);
}
if
(
v
->
constExpr
)
continue
;
if
(
/*!v->info ||*/
v
->
constExpr
)
continue
;
for
(
const
auto
&
q
:
v
->
uses
)
{
q
->
block
->
flow
.
addUse
(
v
);
}
...
...
@@ -70,11 +69,12 @@ void RegisterAllocator::buildGraph() {
set
<
VariablePtr
>
alive
=
b
->
flow
.
in
;
for
(
const
auto
&
q
:
b
->
quads
)
{
alive
+=
to_set
(
q
->
definitions
());
for
(
const
auto
&
al
:
alive
)
assert
(
al
);
vector
<
VariablePtr
>
dead
;
for
(
const
auto
&
var
:
alive
)
{
// this quad is the last quad that uses var
auto
noMoreUses
=
var
->
uses
.
empty
()
||
var
->
uses
.
back
()
==
q
;
if
((
noMoreUses
&&
!
b
->
flow
.
out
.
count
(
var
)))
{
if
((
noMoreUses
&&
!
b
->
flow
.
out
.
count
(
var
))
||
var
->
constExpr
)
{
dead
.
emplace_back
(
var
);
}
}
...
...
@@ -89,12 +89,16 @@ void RegisterAllocator::buildGraph() {
}
if
(
auto
assign
=
dynamic_pointer_cast
<
QAssign
>
(
q
))
{
if
(
assign
->
op
==
Quadruple
::
Op
::
Copy
&&
!
assign
->
loc
->
constExpr
&&
alive
.
count
(
assign
->
loc
))
{
assert
(
assign
->
loc
);
assert
(
assign
->
args
[
0
]);
graph
.
addAssign
(
assign
->
loc
,
assign
->
args
[
0
]);
}
}
else
if
(
auto
phi
=
dynamic_pointer_cast
<
QPhi
>
(
q
))
{
for
(
const
auto
&
phiBlock
:
phi
->
phi
)
{
for
(
const
auto
&
phiVars
:
phiBlock
)
{
if
(
alive
.
count
(
phiVars
.
first
))
{
assert
(
phiVars
.
first
);
assert
(
phiVars
.
second
);
graph
.
addAssign
(
phiVars
.
first
,
phiVars
.
second
);
}
}
...
...
src/codeGen/Variable.h
View file @
46d82364
...
...
@@ -10,6 +10,9 @@
class
Variable
:
std
::
enable_shared_from_this
<
Variable
>
{
public:
Variable
()
=
default
;
explicit
Variable
(
const
VariablePtr
&
v
)
:
info
(
v
->
info
),
type
(
v
->
type
),
constExpr
(
v
->
constExpr
),
val
(
v
->
val
)
{};
explicit
Variable
(
TypePtr
t
)
:
type
(
std
::
move
(
t
))
{};
explicit
Variable
(
Type
*
t
)
:
type
(
t
)
{};
explicit
Variable
(
VarInfoPtr
i
)
:
info
(
std
::
move
(
i
)),
type
(
info
->
type
)
{};
explicit
Variable
(
int
constVal
)
:
type
(
new
Int
),
constExpr
(
true
),
val
(
constVal
)
{};
explicit
Variable
(
std
::
string
symbolName
)
:
name
(
std
::
move
(
symbolName
))
{};
...
...
test.sh
View file @
46d82364
...
...
@@ -3,7 +3,7 @@ t=0
RED
=
'\033[0;31m'
GREEN
=
'\033[0;32m'
NONE
=
'\033[0m'
BIN
=
"./latc_x86"
function
red
{
echo
-e
"
${
RED
}
$@
${
NONE
}
"
}
...
...
@@ -13,27 +13,32 @@ function green {
make
-j8
&&
for
i
in
lat/lattests/good/
*
.lat
;
do
t
=
$((
t+1
))
(
./latc
"
$i
"
&>/dev/null
)
;
(
$BIN
"
$i
"
&>/dev/null
)
;
if
!
[
$?
-eq
0
]
;
then
red
"FAIL
$i
"
;
./latc
"
$i
"
$BIN
"
$i
"
exit
1
;
fi
if
!
diff <
(
${
i
%.*
}
)
"
${
i
%.*
}
.output"
;
then
red
"ERROR
$i
"
exit
1
fi
done
&&
green good OK
&&
for
i
in
lat/lattests/bad/
*
.lat
;
do
t
=
$((
t+1
))
(
./latc
"
$i
"
&>/dev/null
)
;
(
$BIN
"
$i
"
&>/dev/null
)
;
if
[
$?
-eq
0
]
;
then
red
"FAIL
$i
"
;
./latc
"
$i
"
$BIN
"
$i
"
exit
1
;
fi
done
&&
green
"OK:
$t
tests passed!"
&&
for
ext
in
`
ls
lat/lattests/extensions
`
;
do
ok
=
1
for
i
in
lat/lattests/extensions/
$ext
/
*
.lat
;
do
(
./latc
"
$i
"
&>/dev/null
)
;
(
$BIN
"
$i
"
&>/dev/null
)
;
if
!
[
$?
-eq
0
]
;
then
red
"
$ext
fails on
$i
"
;
./latc
"
$i
"
$BIN
"
$i
"
ok
=
0
;
break
;
fi
...
...
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