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
e4d71bee
Commit
e4d71bee
authored
Jan 14, 2021
by
zygzagZ
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WIP better memory access
parent
aafb3bcc
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
187 additions
and
63 deletions
+187
-63
runtime.c
lib/runtime.c
+5
-2
Compiler.cpp
src/Compiler.cpp
+54
-5
Compiler.h
src/Compiler.h
+110
-46
QuadrupleGenerator.cpp
src/codeGen/QuadrupleGenerator.cpp
+7
-6
QuadrupleGenerator.h
src/codeGen/QuadrupleGenerator.h
+9
-3
test.sh
test.sh
+2
-1
No files found.
lib/runtime.c
View file @
e4d71bee
...
...
@@ -4,6 +4,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
int
printInt
(
int
a
)
{
printf
(
"%d
\n
"
,
a
);
...
...
@@ -59,11 +60,13 @@ char* __latte_mem_init(size_t size, void* virtTab) {
}
char
*
__latte_mem_init_array
(
int
len
,
size_t
size
,
void
*
virtTab
)
{
if
(
len
<
0
)
error
();
char
*
buf
=
calloc
(
len
,
size
);
if
(
len
>
(
SIZE_MAX
-
4
)
/
size
)
error
();
char
*
buf
=
calloc
(
1
,
4
+
len
*
size
);
if
(
!
buf
)
error
();
*
((
int
*
)
buf
)
=
len
;
// store length
if
(
virtTab
)
{
for
(
size_t
i
=
0
;
i
<
len
;
i
++
)
{
*
((
void
**
)(
buf
+
i
*
size
))
=
virtTab
;
*
((
void
**
)(
buf
+
4
+
i
*
size
))
=
virtTab
;
}
}
return
buf
;
...
...
src/Compiler.cpp
View file @
e4d71bee
...
...
@@ -137,6 +137,7 @@ void Compiler::printFunction(const QuadrupleGenerator::Result& quadEnv, const Fu
buf
<<
"
\n
"
COMMENT
"----------
\n
"
;
}
for
(
const
auto
&
q
:
b
->
quads
)
{
currentQuad
=
q
;
auto
ret
=
q
->
toString
();
if
(
!
ret
.
empty
())
{
auto
len
=
0
;
...
...
@@ -162,6 +163,7 @@ void Compiler::printFunction(const QuadrupleGenerator::Result& quadEnv, const Fu
}
}
}
currentQuad
=
nullptr
;
if
(
!
b
->
flow
.
use
.
empty
())
{
buf
<<
COMMENT
"----------
\n
"
COMMENT
"use: "
;
for
(
const
auto
&
v
:
b
->
flow
.
use
)
{
...
...
@@ -209,7 +211,7 @@ const char* const Register::names[9] = {"eax", "ebx", "ecx", "edx", "edi", "esi"
const
vector
<
Register
>
Register
::
all
=
{
0
,
1
,
2
,
3
,
4
,
5
,
6
,
7
,
8
};
const
vector
<
Register
>
Register
::
callerSaved
=
{
2
,
3
};
const
vector
<
Register
>
Register
::
calleeSaved
=
{
1
,
4
,
5
};
const
vector
<
Register
>
Register
::
assignable
=
{
1
,
4
,
5
,
2
,
3
};
// ecx and edx least used
const
vector
<
Register
>
Register
::
assignable
=
{
1
,
5
,
4
,
2
,
3
};
// ecx and edx least used
string
Compiler
::
getRef
(
const
VariablePtr
&
v
)
{
if
(
v
->
constExpr
)
{
...
...
@@ -274,13 +276,28 @@ void Compiler::generateQAlloc(QAlloc &q) {
}
void
Compiler
::
generateQWrite
(
QWrite
&
q
)
{
// memory = extension
append
(
"MOVL"
,
getRef
(
q
.
val
),
getRef
(
q
.
loc
));
Register
rl
=
lock
(
q
.
val
,
true
);
// out of all registers
// now i want to choose some that are free
// or temporarily push some not used in calculation of q.access nor q.loc
append
(
"MOVL"
,
rl
,
loadLoc
(
q
.
loc
));
// and, if pushed, pop them back later
regMap
.
unlock
();
}
void
Compiler
::
generateQAccess
(
QAccess
&
q
)
{
// memory = extension
append
(
"MOVL"
,
getRef
(
q
.
access
),
getRef
(
q
.
loc
));
// get register for q.loc, spilling one if necessary
Register
rl
=
lock
(
q
.
loc
,
false
);
// out of all registers
// now i want to choose some that are free
// or temporarily push some not used in calculation of q.access nor q.loc
append
(
"MOVL"
,
loadLoc
(
q
.
access
),
rl
);
if
(
Register
(
q
.
loc
)
==
0
)
{
append
(
"MOVL"
,
rl
,
getRef
(
q
.
loc
));
}
// and, if pushed, pop them back later
regMap
.
unlock
();
}
void
Compiler
::
generateQReturn
(
QReturn
&
q
)
{
...
...
@@ -568,3 +585,35 @@ void Compiler::generateQBlockEnd(QBlockEnd &q) {
const
auto
&
map
=
tgBlock
->
getPhiMapping
(
thisBlock
);
generatePhiXCHG
(
map
);
}
string
Compiler
::
loadLoc
(
const
VariableLocation
&
loc
)
{
int
offset
=
loc
.
offset
;
Register
rb
=
lock
(
loc
.
base
,
true
);
if
(
loc
.
index
)
{
if
(
loc
.
index
->
constExpr
)
{
offset
+=
loc
.
index
->
val
*
loc
.
multiplier
;
}
else
{
Register
ri
=
lock
(
loc
.
index
,
true
);
auto
ret
=
to_string
(
offset
)
+
"("
+
(
string
)
rb
+
","
+
(
string
)
ri
;
if
(
loc
.
multiplier
!=
1
)
ret
+=
","
+
to_string
(
loc
.
multiplier
);
return
ret
+
")"
;
}
}
return
to_string
(
offset
)
+
"("
+
(
string
)
rb
+
")"
;
}
void
RegisterMap
::
backup
(
Register
i
)
{
chk
(
i
);
backups
.
emplace_back
(
i
);
c
->
append
(
"MOVL"
,
i
,
"-"
+
to_string
(
backups
.
size
()
*
4
)
+
"(%esp)"
);
lock
(
i
);
}
void
RegisterMap
::
unlock
()
{
locks
.
clear
();
for
(
size_t
i
=
0
;
i
<
backups
.
size
();
i
++
)
{
c
->
append
(
"MOVL"
,
"-"
+
to_string
(
i
*
4
+
4
)
+
"(%esp)"
,
backups
[
i
]);
}
backups
.
clear
();
}
src/Compiler.h
View file @
e4d71bee
...
...
@@ -42,10 +42,85 @@ public:
static
const
vector
<
Register
>
assignable
;
};
namespace
{
vector
<
Register
>
aliveAfter
(
const
Quadruple
&
q
,
const
vector
<
Register
>
&
vec
)
{
const
uint
noRegs
=
vec
.
size
();
bool
used
[
noRegs
];
int
notUsed
=
noRegs
;
for
(
auto
&
i
:
used
)
i
=
false
;
for
(
auto
&
live
:
q
.
aliveAfter
)
{
for
(
uint
i
=
0
;
i
<
noRegs
;
i
++
)
{
const
Register
&
r
=
vec
[
i
];
if
(
!
used
[
i
]
&&
Register
(
live
)
==
r
)
{
used
[
i
]
=
true
;
--
notUsed
;
}
}
if
(
notUsed
==
0
)
break
;
}
vector
<
Register
>
ret
;
for
(
uint
i
=
0
;
i
<
noRegs
;
i
++
)
{
if
(
used
[
i
])
ret
.
emplace_back
(
vec
[
i
]);
}
return
ret
;
}
vector
<
Register
>
aliveAfter
(
const
QuadruplePtr
&
q
,
const
vector
<
Register
>
&
vec
)
{
return
aliveAfter
(
*
q
,
vec
);
}
}
class
RegisterMap
{
public:
RegisterMap
(
Compiler
*
c
)
:
c
(
c
)
{};
Compiler
*
c
;
set
<
Register
>
locks
;
vector
<
Register
>
backups
;
set
<
Register
>
available
()
const
{
auto
ret
=
to_set
(
Register
::
assignable
);
ret
.
emplace
(
0
);
ret
-=
to_set
(
locks
);
return
ret
;
}
auto
unused
(
const
QuadruplePtr
&
q
)
const
{
auto
ret
=
to_set
(
::
aliveAfter
(
q
,
Register
::
assignable
));
ret
.
emplace
(
0
);
ret
-=
to_set
(
locks
);
return
ret
;
}
void
lock
(
Register
i
)
{
if
(
!
locks
.
count
(
i
))
locks
.
emplace
(
i
);
}
Register
borrow
(
const
QuadruplePtr
&
q
)
{
for
(
auto
i
:
unused
(
q
))
{
lock
(
i
);
return
i
;
}
for
(
auto
i
:
available
())
{
backup
(
i
);
return
i
;
}
throw
runtime_error
(
"Unable to borrow register!"
);
}
void
backup
(
Register
i
);
void
unlock
();
private:
void
chk
(
Register
i
)
const
{
if
(
locks
.
count
(
i
))
throw
runtime_error
(
"Register already locked!"
);
}
};
using
Op
=
Quadruple
::
Op
;
class
Compiler
{
public:
Compiler
(
const
std
::
string
&
f
,
shared_ptr
<
Scope
>
s
)
:
file
(
f
),
buf
(),
scope
(
s
),
quadGen
(
std
::
move
(
s
))
{};
Compiler
(
const
std
::
string
&
f
,
shared_ptr
<
Scope
>
s
)
:
file
(
f
),
buf
(),
scope
(
s
),
quadGen
(
std
::
move
(
s
))
,
regMap
(
this
)
{};
static
const
std
::
string
extension
;
static
void
externalCommand
(
std
::
filesystem
::
path
file
);
...
...
@@ -82,6 +157,8 @@ private:
std
::
stringstream
buf
;
shared_ptr
<
Scope
>
scope
;
QuadrupleGenerator
quadGen
;
RegisterMap
regMap
;
QuadruplePtr
currentQuad
;
unordered_set
<
VariablePtr
>
temps
;
unordered_set
<
VarInfoPtr
>
localInfos
;
...
...
@@ -91,21 +168,38 @@ private:
void
genVirtTables
();
string
getRef
(
const
VariablePtr
&
v
);
string
getRef
(
const
VariableLocation
&
loc
)
{
int
offset
=
loc
.
offset
;
if
(
loc
.
index
)
{
if
(
loc
.
index
->
constExpr
)
{
offset
+=
loc
.
index
->
val
*
loc
.
multiplier
;
}
else
{
auto
ret
=
to_string
(
offset
)
+
"("
+
getRef
(
loc
.
base
)
+
","
+
getRef
(
loc
.
index
);
if
(
loc
.
multiplier
!=
1
)
ret
+=
","
+
to_string
(
loc
.
multiplier
);
return
ret
+
")"
;
string
loadLoc
(
const
VariableLocation
&
loc
);
void
generatePhiXCHG
(
const
map
<
VariablePtr
,
VariablePtr
>
&
varMap
);
string
getBlockLabelText
(
const
QuadruplePtr
&
q
)
{
return
getBlockLabelText
(
q
->
block
);
}
string
getBlockLabelText
(
BasicBlockPtr
&
b
)
{
auto
n
=
b
->
getName
();
if
(
n
.
empty
())
throw
runtime_error
(
"Attempt to get label text of unlabeled block"
);
return
quote
(
n
);
}
shared_ptr
<
QLabel
>
exitLabel
;
void
generateStandardReturn
()
{
append
(
"JMP"
,
quote
(
exitLabel
->
label
));
}
Register
lock
(
const
VariablePtr
&
v
,
bool
move
=
false
)
{
auto
reg
=
Register
(
v
);
if
(
reg
==
0
)
{
reg
=
regMap
.
borrow
(
currentQuad
);
if
(
move
)
{
append
(
"MOVL"
,
getRef
(
v
),
reg
);
}
}
else
{
regMap
.
lock
(
reg
);
}
return
to_string
(
offset
)
+
"("
+
getRef
(
loc
.
base
)
+
")"
;
return
reg
;
}
void
generatePhiXCHG
(
const
map
<
VariablePtr
,
VariablePtr
>
&
varMap
);
protected:
static
string
getOpName
(
Quadruple
::
Op
op
)
{
switch
(
op
.
op
)
{
case
Op
:
:
Plus
:
return
"ADDL"
;
...
...
@@ -172,46 +266,16 @@ private:
buf
<<
endl
;
}
st
ring
getBlockLabelText
(
const
QuadruplePtr
&
q
)
{
return
getBlockLabelText
(
q
->
block
);
public:
st
atic
vector
<
Register
>
aliveAfter
(
Quadruple
&
q
,
const
vector
<
Register
>
&
vec
)
{
return
::
aliveAfter
(
q
,
vec
);
}
string
getBlockLabelText
(
BasicBlockPtr
&
b
)
{
auto
n
=
b
->
getName
();
if
(
n
.
empty
())
throw
runtime_error
(
"Attempt to get label text of unlabeled block"
);
return
quote
(
n
);
}
shared_ptr
<
QLabel
>
exitLabel
;
void
generateStandardReturn
()
{
append
(
"JMP"
,
quote
(
exitLabel
->
label
));
}
static
vector
<
Register
>
aliveAfter
(
Quadruple
&
q
,
const
vector
<
Register
>
&
vec
)
{
const
uint
noRegs
=
vec
.
size
();
bool
used
[
noRegs
];
int
notUsed
=
noRegs
;
for
(
auto
&
i
:
used
)
i
=
false
;
for
(
auto
&
live
:
q
.
aliveAfter
)
{
for
(
uint
i
=
0
;
i
<
noRegs
;
i
++
)
{
const
Register
&
r
=
vec
[
i
];
if
(
!
used
[
i
]
&&
Register
(
live
)
==
r
)
{
used
[
i
]
=
true
;
--
notUsed
;
}
}
if
(
notUsed
==
0
)
break
;
}
vector
<
Register
>
ret
;
for
(
uint
i
=
0
;
i
<
noRegs
;
i
++
)
{
if
(
used
[
i
])
ret
.
emplace_back
(
vec
[
i
]);
}
return
ret
;
}
static
vector
<
Register
>
registersToSave
(
Quadruple
&
q
)
{
return
aliveAfter
(
q
,
Register
::
callerSaved
);
}
friend
class
RegisterMap
;
};
#endif
src/codeGen/QuadrupleGenerator.cpp
View file @
e4d71bee
...
...
@@ -12,14 +12,15 @@ QuadrupleGenerator::Result QuadrupleGenerator::compileFunction(FunctionInfoPtr f
newBlock
();
{
int
param
=
1
;
for
(
const
auto
&
arg
:
f
->
arguments
)
{
auto
var
=
alloc
(
arg
);
if
(
VarInfoPtr
self
=
f
->
self
)
{
auto
var
=
alloc
(
self
);
addQuad
(
make_shared
<
QParam
>
(
var
,
-
param
));
param
++
;
}
if
(
VarInfoPtr
self
=
f
->
self
)
{
auto
var
=
alloc
(
self
);
for
(
const
auto
&
arg
:
f
->
arguments
)
{
auto
var
=
alloc
(
arg
);
addQuad
(
make_shared
<
QParam
>
(
var
,
-
param
));
param
++
;
}
}
f
->
block
->
accept
(
this
);
...
...
@@ -327,9 +328,9 @@ void QuadrupleGenerator::visitEIndexAcc(EIndexAcc *p) {
auto
newIndex
=
alloc
();
// calculate var = index * quantifier
addQuad
<
QAssign
>
(
newIndex
,
index
,
Op
::
Mul
,
q
);
addQuad
<
QAccess
>
(
lastVar
,
lhs
,
newIndex
,
1
,
0
);
addQuad
<
QAccess
>
(
lastVar
,
lhs
,
newIndex
,
1
,
4
);
// 4 accounts for table length entry
}
else
{
addQuad
<
QAccess
>
(
lastVar
,
lhs
,
index
,
type
->
type_
->
size
(),
0
);
addQuad
<
QAccess
>
(
lastVar
,
lhs
,
index
,
type
->
type_
->
size
(),
4
);
// 4 accounts for table length entry
}
Bool
b
;
if
(
type
->
type_
->
isEqual
(
&
b
))
{
...
...
src/codeGen/QuadrupleGenerator.h
View file @
e4d71bee
...
...
@@ -38,11 +38,17 @@ private:
shared_ptr
<
QLabel
>
labelTrue
,
labelFalse
;
VariablePtr
evalLVal
(
Visitable
*
expr
)
{
auto
info
=
evalExpr
(
expr
)
->
info
;
auto
ret
=
evalExpr
(
expr
);
auto
info
=
ret
->
info
;
if
(
!
info
)
{
throw
ParseError
(
"LValue expected"
,
expr
);
if
(
!
lastQuad
||
!
dynamic_pointer_cast
<
QAccess
>
(
lastQuad
))
throw
ParseError
(
"LValue expected"
,
expr
);
else
return
ret
;
}
else
{
info
->
loc
=
nullptr
;
}
info
->
loc
=
nullptr
;
return
alloc
(
info
);
}
...
...
test.sh
View file @
e4d71bee
...
...
@@ -85,7 +85,8 @@ done && green "OK: $t bad+ tests passed!" && for ext in `ls lat/lattests/extensi
if
!
diff <
(
$VALGRIND
timeout
2
${
i
%.*
}
<
"
$inp
"
)
"
${
i
%.*
}
.output"
;
then
red
"ERROR
$i
"
exit
1
ok
=
0
break
fi
done
if
[
$ok
-eq
1
]
;
then
...
...
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